/** * Events: everything that changes on the daemon, announced on one journal. * * A client opens with REST snapshots and follows events to stay current. The * journal is a bounded window: a cursor that fell out of it cannot be replayed, * and the daemon says so rather than silently skipping what was lost. */ import { type Static } from "@sinclair/typebox"; import { type Cuid2, type EventCursor, type ResourceVersion, type Timestamp } from "./common.js"; import type { Agent, AgentDraftSnapshot, AgentProfile } from "./agents.js"; import type { Cloud } from "./cloud.js"; import type { GitState } from "./git.js"; import type { HappyIntegration } from "./integrations.js"; import type { Message, Run } from "./messages.js"; import type { BackgroundProcess } from "./processes.js"; import type { Profile } from "./profile.js"; import type { Project } from "./projects.js"; import type { Question } from "./questions.js"; import type { Terminal } from "./terminals.js"; import type { AgentContextUsage } from "./usage.js"; import type { Workspace } from "./workspaces.js"; import type { SlashCommand } from "./slashCommands.js"; import type { SkillsUpdatedPayload } from "./skills.js"; import type { WorkspaceServiceCreatedPayload, WorkspaceServiceUpdatedPayload } from "./services.js"; /** * What every `*.updated` payload carries beside the resource's own ID. * * A client whose cached `version` equals `previousVersion` merges `changes` and * adopts the new version; when they differ its copy is dirty and it refetches * that one resource. */ export interface ResourceUpdate { /** The resource's version before this change. */ previousVersion: ResourceVersion; /** Its version after. */ version: ResourceVersion; /** Only the fields that changed; `updatedAt` is always among them. */ changes: Partial; /** Echoed when the mutation behind this change supplied one. */ mutationId?: string; } /** What every mutation-caused payload may carry. */ export interface MutationEcho { mutationId?: string; } /** This daemon process entered its sticky read-only drain phase. */ export interface DaemonDrainingPayload { daemonId: Cuid2; draining: true; } export type ProjectCreatedPayload = MutationEcho & { project: Project; }; export type ProjectUpdatedPayload = ResourceUpdate & { projectId: Cuid2; }; export type WorkspaceCreatedPayload = MutationEcho & { workspace: Workspace; }; export type WorkspaceUpdatedPayload = ResourceUpdate & { workspaceId: Cuid2; }; /** A global secret entered the catalog; values are absent by construction. */ export declare const secretCreatedPayloadSchema: import("@sinclair/typebox").TObject<{ mutationId: import("@sinclair/typebox").TOptional; secret: import("@sinclair/typebox").TObject<{ availableToAgents: import("@sinclair/typebox").TBoolean; createdAt: import("@sinclair/typebox").TInteger; description: import("@sinclair/typebox").TString; environment: import("@sinclair/typebox").TOptional; environmentVariables: import("@sinclair/typebox").TArray; id: import("@sinclair/typebox").TString; managed: import("@sinclair/typebox").TBoolean; updatedAt: import("@sinclair/typebox").TInteger; values: import("@sinclair/typebox").TOptional; version: import("@sinclair/typebox").TString; }>; }>; export type SecretCreatedPayload = Static; /** The safe fields that may appear in a version-chained secret update. */ export declare const secretUpdatedChangesSchema: import("@sinclair/typebox").TObject<{ availableToAgents: import("@sinclair/typebox").TOptional; description: import("@sinclair/typebox").TOptional; environment: import("@sinclair/typebox").TOptional; environmentVariables: import("@sinclair/typebox").TOptional>; updatedAt: import("@sinclair/typebox").TInteger; values: import("@sinclair/typebox").TOptional; }>; export type SecretUpdatedChanges = Static; /** A version-chained metadata change or value-only rotation. */ export declare const secretUpdatedPayloadSchema: import("@sinclair/typebox").TObject<{ changes: import("@sinclair/typebox").TObject<{ availableToAgents: import("@sinclair/typebox").TOptional; description: import("@sinclair/typebox").TOptional; environment: import("@sinclair/typebox").TOptional; environmentVariables: import("@sinclair/typebox").TOptional>; updatedAt: import("@sinclair/typebox").TInteger; values: import("@sinclair/typebox").TOptional; }>; mutationId: import("@sinclair/typebox").TOptional; previousVersion: import("@sinclair/typebox").TString; secretId: import("@sinclair/typebox").TString; version: import("@sinclair/typebox").TString; }>; export type SecretUpdatedPayload = Static; /** One direct project, workspace, or agent grant was created. */ export declare const secretAttachedPayloadSchema: import("@sinclair/typebox").TObject<{ attachment: import("@sinclair/typebox").TObject<{ createdAt: import("@sinclair/typebox").TInteger; id: import("@sinclair/typebox").TString; secretId: import("@sinclair/typebox").TString; target: import("@sinclair/typebox").TObject<{ id: import("@sinclair/typebox").TString; type: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"project">, import("@sinclair/typebox").TLiteral<"workspace">, import("@sinclair/typebox").TLiteral<"agent">]>; }>; }>; mutationId: import("@sinclair/typebox").TOptional; }>; export type SecretAttachedPayload = Static; /** One direct grant was removed. */ export declare const secretDetachedPayloadSchema: import("@sinclair/typebox").TObject<{ attachment: import("@sinclair/typebox").TObject<{ createdAt: import("@sinclair/typebox").TInteger; id: import("@sinclair/typebox").TString; secretId: import("@sinclair/typebox").TString; target: import("@sinclair/typebox").TObject<{ id: import("@sinclair/typebox").TString; type: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"project">, import("@sinclair/typebox").TLiteral<"workspace">, import("@sinclair/typebox").TLiteral<"agent">]>; }>; }>; mutationId: import("@sinclair/typebox").TOptional; }>; export type SecretDetachedPayload = Static; /** A daemon-owned feature retired one managed secret and all its grants. */ export declare const secretRemovedPayloadSchema: import("@sinclair/typebox").TObject<{ previousVersion: import("@sinclair/typebox").TString; secretId: import("@sinclair/typebox").TString; }>; export type SecretRemovedPayload = Static; /** A bot was created together with its dedicated workspace and one agent. */ export declare const botCreatedPayloadSchema: import("@sinclair/typebox").TObject<{ bot: import("@sinclair/typebox").TObject<{ agent: import("@sinclair/typebox").TRecursive; canSendMessages: import("@sinclair/typebox").TOptional; createdAt: import("@sinclair/typebox").TInteger; id: import("@sinclair/typebox").TString; lastCursor: import("@sinclair/typebox").TString; managedByAnotherAgent: import("@sinclair/typebox").TOptional; orderKey: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TNull]>; parentAgentId: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TNull]>; pendingQuestionId: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TNull]>; processes: import("@sinclair/typebox").TObject<{ running: import("@sinclair/typebox").TInteger; }>; status: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"idle">, import("@sinclair/typebox").TLiteral<"thinking">, import("@sinclair/typebox").TLiteral<"working">, import("@sinclair/typebox").TLiteral<"generating_tools">, import("@sinclair/typebox").TLiteral<"running_tools">]>; subagents: import("@sinclair/typebox").TObject<{ running: import("@sinclair/typebox").TInteger; total: import("@sinclair/typebox").TInteger; }>; subtask: import("@sinclair/typebox").TOptional; subtasks: import("@sinclair/typebox").TOptional>; title: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TNull]>; titleStatus: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"idle">, import("@sinclair/typebox").TLiteral<"ready">]>; unread: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{ reason: import("@sinclair/typebox").TString; since: import("@sinclair/typebox").TInteger; }>, import("@sinclair/typebox").TNull]>; updatedAt: import("@sinclair/typebox").TInteger; userVisible: import("@sinclair/typebox").TOptional; version: import("@sinclair/typebox").TString; workspaceId: import("@sinclair/typebox").TString; }>>; archivedAt: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TInteger, import("@sinclair/typebox").TNull]>; avatar: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{ kind: import("@sinclair/typebox").TLiteral<"image">; source: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"user">, import("@sinclair/typebox").TLiteral<"generated">]>; thumbhash: import("@sinclair/typebox").TString; }>, import("@sinclair/typebox").TNull]>; compute: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{ path: import("@sinclair/typebox").TString; type: import("@sinclair/typebox").TLiteral<"host">; }>, import("@sinclair/typebox").TObject<{ image: import("@sinclair/typebox").TString; type: import("@sinclair/typebox").TLiteral<"docker">; }>]>; createdAt: import("@sinclair/typebox").TInteger; id: import("@sinclair/typebox").TString; isAdmin: import("@sinclair/typebox").TOptional; name: import("@sinclair/typebox").TString; orderKey: import("@sinclair/typebox").TString; status: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"active">, import("@sinclair/typebox").TLiteral<"archived">]>; systemKey: import("@sinclair/typebox").TOptional>; updatedAt: import("@sinclair/typebox").TInteger; username: import("@sinclair/typebox").TString; version: import("@sinclair/typebox").TString; workspaceId: import("@sinclair/typebox").TString; }>; mutationId: import("@sinclair/typebox").TOptional; }>; export type BotCreatedPayload = Static; /** A version-chained change to a bot's own fields. */ export declare const botUpdatedPayloadSchema: import("@sinclair/typebox").TObject<{ botId: import("@sinclair/typebox").TString; changes: import("@sinclair/typebox").TObject<{ agent: import("@sinclair/typebox").TOptional; canSendMessages: import("@sinclair/typebox").TOptional; createdAt: import("@sinclair/typebox").TInteger; id: import("@sinclair/typebox").TString; lastCursor: import("@sinclair/typebox").TString; managedByAnotherAgent: import("@sinclair/typebox").TOptional; orderKey: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TNull]>; parentAgentId: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TNull]>; pendingQuestionId: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TNull]>; processes: import("@sinclair/typebox").TObject<{ running: import("@sinclair/typebox").TInteger; }>; status: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"idle">, import("@sinclair/typebox").TLiteral<"thinking">, import("@sinclair/typebox").TLiteral<"working">, import("@sinclair/typebox").TLiteral<"generating_tools">, import("@sinclair/typebox").TLiteral<"running_tools">]>; subagents: import("@sinclair/typebox").TObject<{ running: import("@sinclair/typebox").TInteger; total: import("@sinclair/typebox").TInteger; }>; subtask: import("@sinclair/typebox").TOptional; subtasks: import("@sinclair/typebox").TOptional>; title: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TNull]>; titleStatus: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"idle">, import("@sinclair/typebox").TLiteral<"ready">]>; unread: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{ reason: import("@sinclair/typebox").TString; since: import("@sinclair/typebox").TInteger; }>, import("@sinclair/typebox").TNull]>; updatedAt: import("@sinclair/typebox").TInteger; userVisible: import("@sinclair/typebox").TOptional; version: import("@sinclair/typebox").TString; workspaceId: import("@sinclair/typebox").TString; }>>>; archivedAt: import("@sinclair/typebox").TOptional>; avatar: import("@sinclair/typebox").TOptional; source: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"user">, import("@sinclair/typebox").TLiteral<"generated">]>; thumbhash: import("@sinclair/typebox").TString; }>, import("@sinclair/typebox").TNull]>>; compute: import("@sinclair/typebox").TOptional; }>, import("@sinclair/typebox").TObject<{ image: import("@sinclair/typebox").TString; type: import("@sinclair/typebox").TLiteral<"docker">; }>]>>; createdAt: import("@sinclair/typebox").TOptional; id: import("@sinclair/typebox").TOptional; isAdmin: import("@sinclair/typebox").TOptional; name: import("@sinclair/typebox").TOptional; orderKey: import("@sinclair/typebox").TOptional; status: import("@sinclair/typebox").TOptional, import("@sinclair/typebox").TLiteral<"archived">]>>; systemKey: import("@sinclair/typebox").TOptional>; updatedAt: import("@sinclair/typebox").TOptional; username: import("@sinclair/typebox").TOptional; version: import("@sinclair/typebox").TOptional; workspaceId: import("@sinclair/typebox").TOptional; }>; mutationId: import("@sinclair/typebox").TOptional; previousVersion: import("@sinclair/typebox").TString; version: import("@sinclair/typebox").TString; }>; export type BotUpdatedPayload = Static; export type TerminalCreatedPayload = MutationEcho & { terminal: Terminal; }; export type TerminalUpdatedPayload = ResourceUpdate & { terminalId: Cuid2; }; /** Git state is computed, so it has no version chain: the payload is the whole snapshot. */ export interface GitUpdatedPayload { workspaceId: Cuid2; git: GitState; } /** File state is computed, so clients refetch the affected visible paths. */ export interface FilesUpdatedPayload { workspaceId: Cuid2; /** Relative paths, or `null` when the safe scope is every visible path in the workspace. */ paths: string[] | null; } export type AgentCreatedPayload = MutationEcho & { agent: Agent; }; export type AgentUpdatedPayload = ResourceUpdate & { agentId: Cuid2; }; /** Current context is computed state, so it carries a complete replacement and no version chain. */ export interface AgentContextUpdatedPayload { agentId: Cuid2; context: AgentContextUsage | null; } /** Draft state is a complete current-value replacement rather than part of the agent resource. */ export interface AgentDraftUpdatedPayload extends MutationEcho { agentId: Cuid2; draft: AgentDraftSnapshot; } /** The complete current request-profile catalog is a replacement, not a resource diff. */ export interface AgentProfilesUpdatedPayload extends MutationEcho { agentId: Cuid2; profiles: AgentProfile[]; } /** The complete current slash-command catalog is a replacement, not a versioned resource diff. */ export interface AgentSlashCommandsUpdatedPayload extends MutationEcho { agentId: Cuid2; slashCommands: SlashCommand[]; } export type ProcessStartedPayload = MutationEcho & { process: BackgroundProcess; }; export type ProcessUpdatedPayload = ResourceUpdate & { processId: Cuid2; }; export type QuestionCreatedPayload = MutationEcho & { question: Question; }; export type QuestionUpdatedPayload = ResourceUpdate & { questionId: Cuid2; }; /** A run began; the agent left `"idle"`. */ export interface RunStartedPayload extends MutationEcho { agentId: Cuid2; run: Run; /** Visible messages accepted into the run, oldest first. */ acceptedMessageIds: Cuid2[]; } /** Steering atomically closed one run and opened its successor. */ export interface RunBoundaryPayload extends MutationEcho { agentId: Cuid2; finishedRun: Run; startedRun: Run; /** Visible steering messages accepted into the successor, oldest first. */ acceptedMessageIds: Cuid2[]; } /** A run reached a terminal state; the agent is `"idle"` again. */ export interface RunFinishedPayload extends MutationEcho { agentId: Cuid2; run: Run; } /** A message entered history; pending user messages arrive here first. */ export interface MessageCreatedPayload extends MutationEcho { agentId: Cuid2; /** `null` for a pending user message, which belongs to no run yet. */ runId: Cuid2 | null; message: Message; } /** The whole message as of now, not a diff. */ export interface MessageUpdatedPayload extends MutationEcho { agentId: Cuid2; runId: Cuid2; message: Message; } /** * Streaming text: the one event that is not a full object. * * A client that misses deltas recovers the full message from the next * `message.updated` or from history. */ export declare const messageDeltaPayloadSchema: import("@sinclair/typebox").TObject<{ agentId: import("@sinclair/typebox").TString; runId: import("@sinclair/typebox").TString; messageId: import("@sinclair/typebox").TString; /** Which content block grows. */ blockIndex: import("@sinclair/typebox").TInteger; /** The block's prior UTF-16 code-unit length. */ offset: import("@sinclair/typebox").TInteger; /** Text to concatenate onto that block. */ append: import("@sinclair/typebox").TString; }>; /** Streaming text with an absolute prior-text offset. */ export type MessageDeltaPayload = Static; /** * The message is gone from history. * * Deletion happens only when the daemon resets a block of the transcript to * restart inference; the replacements arrive as ordinary `message.created`. */ export interface MessageDeletedPayload { agentId: Cuid2; runId: Cuid2; messageId: Cuid2; } /** Deliberately empty: a nudge to refetch the config endpoints when convenient. */ export type ConfigUpdatedPayload = Record; /** Complete public roster replacement; keep the greater version across snapshots and events. */ export declare const connectionsUpdatedPayloadSchema: import("@sinclair/typebox").TObject<{ connections: import("@sinclair/typebox").TArray; }>, import("@sinclair/typebox").TObject<{ id: import("@sinclair/typebox").TString; name: import("@sinclair/typebox").TString; orderKey: import("@sinclair/typebox").TString; authentication: import("@sinclair/typebox").TLiteral<"workos">; organizationId: import("@sinclair/typebox").TString; }>]>>; version: import("@sinclair/typebox").TString; }>; export type ConnectionsUpdatedPayload = Static; /** A standalone full-profile replacement or a team-wide identity-only invalidation. */ export type ProfileUpdatedPayload = MutationEcho & ({ profile: Profile; userId?: never; } | { profile?: never; userId: Cuid2; }); /** Cloud state is a complete replacement rather than a version-chain diff. */ export interface CloudUpdatedPayload extends MutationEcho { cloud: Cloud; } /** Happy integration state is computed, so the payload is a complete replacement. */ export interface HappyIntegrationUpdatedPayload { integration: HappyIntegration; } /** One event on the journal. */ export interface EventEnvelope { /** This event's place in the journal; never a resource identity. */ cursor: EventCursor; type: TType; occurredAt: Timestamp; payload: TPayload; } /** Every event the specification names today. */ export type HappyAgentEvent = EventEnvelope<"daemon.draining", DaemonDrainingPayload> | EventEnvelope<"project.created", ProjectCreatedPayload> | EventEnvelope<"project.updated", ProjectUpdatedPayload> | EventEnvelope<"workspace.created", WorkspaceCreatedPayload> | EventEnvelope<"workspace.updated", WorkspaceUpdatedPayload> | EventEnvelope<"secret.created", SecretCreatedPayload> | EventEnvelope<"secret.updated", SecretUpdatedPayload> | EventEnvelope<"secret.attached", SecretAttachedPayload> | EventEnvelope<"secret.detached", SecretDetachedPayload> | EventEnvelope<"secret.removed", SecretRemovedPayload> | EventEnvelope<"bot.created", BotCreatedPayload> | EventEnvelope<"bot.updated", BotUpdatedPayload> | EventEnvelope<"terminal.created", TerminalCreatedPayload> | EventEnvelope<"terminal.updated", TerminalUpdatedPayload> | EventEnvelope<"service.created", WorkspaceServiceCreatedPayload> | EventEnvelope<"service.updated", WorkspaceServiceUpdatedPayload> | EventEnvelope<"git.updated", GitUpdatedPayload> | EventEnvelope<"files.updated", FilesUpdatedPayload> | EventEnvelope<"skills.updated", SkillsUpdatedPayload> | EventEnvelope<"agent.created", AgentCreatedPayload> | EventEnvelope<"agent.updated", AgentUpdatedPayload> | EventEnvelope<"agent.context.updated", AgentContextUpdatedPayload> | EventEnvelope<"agent.draft.updated", AgentDraftUpdatedPayload> | EventEnvelope<"agent.profiles.updated", AgentProfilesUpdatedPayload> | EventEnvelope<"agent.slash_commands.updated", AgentSlashCommandsUpdatedPayload> | EventEnvelope<"process.started", ProcessStartedPayload> | EventEnvelope<"process.updated", ProcessUpdatedPayload> | EventEnvelope<"process.exited", ProcessUpdatedPayload> | EventEnvelope<"question.created", QuestionCreatedPayload> | EventEnvelope<"question.updated", QuestionUpdatedPayload> | EventEnvelope<"run.started", RunStartedPayload> | EventEnvelope<"run.boundary", RunBoundaryPayload> | EventEnvelope<"run.finished", RunFinishedPayload> | EventEnvelope<"message.created", MessageCreatedPayload> | EventEnvelope<"message.updated", MessageUpdatedPayload> | EventEnvelope<"message.delta", MessageDeltaPayload> | EventEnvelope<"message.deleted", MessageDeletedPayload> | EventEnvelope<"config.updated", ConfigUpdatedPayload> | EventEnvelope<"connections.updated", ConnectionsUpdatedPayload> | EventEnvelope<"profile.updated", ProfileUpdatedPayload> | EventEnvelope<"cloud.updated", CloudUpdatedPayload> | EventEnvelope<"happy.integration.updated", HappyIntegrationUpdatedPayload>; /** The name of an event this client build knows. */ export type HappyAgentEventType = HappyAgentEvent["type"]; /** `GET /v0/events` query parameters. */ export interface EventPageQuery { /** The cursor to read from, exclusive; omitted, reading starts at the oldest. */ after?: EventCursor; /** An inclusive upper bound, for pulling the changes between two cursors. */ until?: EventCursor; /** Default 100. */ limit?: number; } /** `GET /v0/events` */ export interface EventPageResponse { /** Oldest first. */ events: HappyAgentEvent[]; /** Where this page ended; pass it as the next `after`. */ cursor: EventCursor; /** The newest event the daemon holds, so a client knows how far behind it is. */ latestCursor: EventCursor; } /** The `hello` frame `GET /v0/events/stream` opens with. */ export interface EventStreamHello { /** The position the stream continues from. */ cursor: EventCursor; /** * The supplied cursor was lost to the journal window. The stream is live * from now, but the client must resync its snapshots. */ gap: boolean; /** The supplied cursor was honored; everything since it follows, in order. */ resumed: boolean; connectedAt: Timestamp; /** This daemon process's identity. Absent on older compatible daemons. */ daemonId?: Cuid2; /** When this daemon process started. Absent on older compatible daemons. */ daemonStartedAt?: Timestamp; /** Whether this daemon process is draining. Absent on older compatible daemons. */ draining?: boolean; } /** One frame read off `GET /v0/events/stream`. */ export type EventStreamFrame = { kind: "hello"; hello: EventStreamHello; } | { kind: "event"; event: HappyAgentEvent; cursor: EventCursor; }; /** `GET /v0/events/stream` options. */ export interface EventStreamOptions { /** The cursor to resume from, sent as the `after` query parameter. */ after?: EventCursor | undefined; /** * The cursor to resume from, sent as the standard `Last-Event-ID` header. * Equivalent to `after`; both forms exist because SSE reconnects use the * header and a first connection usually names the cursor in the query. */ lastEventId?: EventCursor | undefined; /** Closes the connection and ends the iteration. */ signal?: AbortSignal | undefined; } //# sourceMappingURL=events.d.ts.map