import { type Static, type TSchema, Type } from "@sinclair/typebox"; const NonEmptyString = Type.String({ minLength: 1 }); export const PresenceEntrySchema = Type.Object( { host: Type.Optional(NonEmptyString), ip: Type.Optional(NonEmptyString), version: Type.Optional(NonEmptyString), platform: Type.Optional(NonEmptyString), deviceFamily: Type.Optional(NonEmptyString), modelIdentifier: Type.Optional(NonEmptyString), mode: Type.Optional(NonEmptyString), lastInputSeconds: Type.Optional(Type.Integer({ minimum: 0 })), reason: Type.Optional(NonEmptyString), tags: Type.Optional(Type.Array(NonEmptyString)), text: Type.Optional(Type.String()), ts: Type.Integer({ minimum: 0 }), instanceId: Type.Optional(NonEmptyString), }, { additionalProperties: false }, ); export const HealthSnapshotSchema = Type.Any(); export const StateVersionSchema = Type.Object( { presence: Type.Integer({ minimum: 0 }), health: Type.Integer({ minimum: 0 }), }, { additionalProperties: false }, ); export const SnapshotSchema = Type.Object( { presence: Type.Array(PresenceEntrySchema), health: HealthSnapshotSchema, stateVersion: StateVersionSchema, uptimeMs: Type.Integer({ minimum: 0 }), }, { additionalProperties: false }, ); export const TickEventSchema = Type.Object( { ts: Type.Integer({ minimum: 0 }), }, { additionalProperties: false }, ); export const ShutdownEventSchema = Type.Object( { reason: NonEmptyString, restartExpectedMs: Type.Optional(Type.Integer({ minimum: 0 })), }, { additionalProperties: false }, ); export const ConnectParamsSchema = Type.Object( { minProtocol: Type.Integer({ minimum: 1 }), maxProtocol: Type.Integer({ minimum: 1 }), client: Type.Object( { name: NonEmptyString, version: NonEmptyString, platform: NonEmptyString, deviceFamily: Type.Optional(NonEmptyString), modelIdentifier: Type.Optional(NonEmptyString), mode: NonEmptyString, instanceId: Type.Optional(NonEmptyString), }, { additionalProperties: false }, ), caps: Type.Optional(Type.Array(NonEmptyString, { default: [] })), auth: Type.Optional( Type.Object( { token: Type.Optional(Type.String()), username: Type.Optional(Type.String()), password: Type.Optional(Type.String()), }, { additionalProperties: false }, ), ), locale: Type.Optional(Type.String()), userAgent: Type.Optional(Type.String()), }, { additionalProperties: false }, ); export const HelloOkSchema = Type.Object( { type: Type.Literal("hello-ok"), protocol: Type.Integer({ minimum: 1 }), server: Type.Object( { version: NonEmptyString, commit: Type.Optional(NonEmptyString), host: Type.Optional(NonEmptyString), connId: NonEmptyString, }, { additionalProperties: false }, ), features: Type.Object( { methods: Type.Array(NonEmptyString), events: Type.Array(NonEmptyString), }, { additionalProperties: false }, ), snapshot: SnapshotSchema, canvasHostUrl: Type.Optional(NonEmptyString), policy: Type.Object( { maxPayload: Type.Integer({ minimum: 1 }), maxBufferedBytes: Type.Integer({ minimum: 1 }), tickIntervalMs: Type.Integer({ minimum: 1 }), }, { additionalProperties: false }, ), }, { additionalProperties: false }, ); export const ErrorShapeSchema = Type.Object( { code: NonEmptyString, message: NonEmptyString, details: Type.Optional(Type.Unknown()), retryable: Type.Optional(Type.Boolean()), retryAfterMs: Type.Optional(Type.Integer({ minimum: 0 })), }, { additionalProperties: false }, ); export const RequestFrameSchema = Type.Object( { type: Type.Literal("req"), id: NonEmptyString, method: NonEmptyString, params: Type.Optional(Type.Unknown()), }, { additionalProperties: false }, ); export const ResponseFrameSchema = Type.Object( { type: Type.Literal("res"), id: NonEmptyString, ok: Type.Boolean(), payload: Type.Optional(Type.Unknown()), error: Type.Optional(ErrorShapeSchema), }, { additionalProperties: false }, ); export const EventFrameSchema = Type.Object( { type: Type.Literal("event"), event: NonEmptyString, payload: Type.Optional(Type.Unknown()), seq: Type.Optional(Type.Integer({ minimum: 0 })), stateVersion: Type.Optional(StateVersionSchema), }, { additionalProperties: false }, ); // Discriminated union of all top-level frames. Using a discriminator makes // downstream codegen (quicktype) produce tighter types instead of all-optional // blobs. export const GatewayFrameSchema = Type.Union( [RequestFrameSchema, ResponseFrameSchema, EventFrameSchema], { discriminator: "type" }, ); export const AgentEventSchema = Type.Object( { runId: NonEmptyString, seq: Type.Integer({ minimum: 0 }), stream: NonEmptyString, ts: Type.Integer({ minimum: 0 }), data: Type.Record(Type.String(), Type.Unknown()), }, { additionalProperties: false }, ); export const SendParamsSchema = Type.Object( { to: NonEmptyString, message: NonEmptyString, mediaUrl: Type.Optional(Type.String()), provider: Type.Optional(Type.String()), idempotencyKey: NonEmptyString, }, { additionalProperties: false }, ); export const AgentParamsSchema = Type.Object( { message: NonEmptyString, to: Type.Optional(Type.String()), sessionId: Type.Optional(Type.String()), sessionKey: Type.Optional(Type.String()), thinking: Type.Optional(Type.String()), deliver: Type.Optional(Type.Boolean()), channel: Type.Optional(Type.String()), timeout: Type.Optional(Type.Integer({ minimum: 0 })), idempotencyKey: NonEmptyString, }, { additionalProperties: false }, ); export const WakeParamsSchema = Type.Object( { mode: Type.Union([Type.Literal("now"), Type.Literal("next-heartbeat")]), text: NonEmptyString, }, { additionalProperties: false }, ); export const NodePairRequestParamsSchema = Type.Object( { nodeId: NonEmptyString, displayName: Type.Optional(NonEmptyString), platform: Type.Optional(NonEmptyString), version: Type.Optional(NonEmptyString), deviceFamily: Type.Optional(NonEmptyString), modelIdentifier: Type.Optional(NonEmptyString), caps: Type.Optional(Type.Array(NonEmptyString)), commands: Type.Optional(Type.Array(NonEmptyString)), remoteIp: Type.Optional(NonEmptyString), silent: Type.Optional(Type.Boolean()), }, { additionalProperties: false }, ); export const NodePairListParamsSchema = Type.Object( {}, { additionalProperties: false }, ); export const NodePairApproveParamsSchema = Type.Object( { requestId: NonEmptyString }, { additionalProperties: false }, ); export const NodePairRejectParamsSchema = Type.Object( { requestId: NonEmptyString }, { additionalProperties: false }, ); export const NodePairVerifyParamsSchema = Type.Object( { nodeId: NonEmptyString, token: NonEmptyString }, { additionalProperties: false }, ); export const NodeListParamsSchema = Type.Object( {}, { additionalProperties: false }, ); export const NodeDescribeParamsSchema = Type.Object( { nodeId: NonEmptyString }, { additionalProperties: false }, ); export const NodeInvokeParamsSchema = Type.Object( { nodeId: NonEmptyString, command: NonEmptyString, params: Type.Optional(Type.Unknown()), timeoutMs: Type.Optional(Type.Integer({ minimum: 0 })), idempotencyKey: NonEmptyString, }, { additionalProperties: false }, ); export const SessionsListParamsSchema = Type.Object( { limit: Type.Optional(Type.Integer({ minimum: 1 })), activeMinutes: Type.Optional(Type.Integer({ minimum: 1 })), includeGlobal: Type.Optional(Type.Boolean()), includeUnknown: Type.Optional(Type.Boolean()), }, { additionalProperties: false }, ); export const SessionsPatchParamsSchema = Type.Object( { key: NonEmptyString, thinkingLevel: Type.Optional(Type.Union([NonEmptyString, Type.Null()])), verboseLevel: Type.Optional(Type.Union([NonEmptyString, Type.Null()])), groupActivation: Type.Optional( Type.Union([Type.Literal("mention"), Type.Literal("always"), Type.Null()]), ), syncing: Type.Optional( Type.Union([Type.Boolean(), NonEmptyString, Type.Null()]), ), }, { additionalProperties: false }, ); export const SessionsResetParamsSchema = Type.Object( { key: NonEmptyString }, { additionalProperties: false }, ); export const SessionsDeleteParamsSchema = Type.Object( { key: NonEmptyString, deleteTranscript: Type.Optional(Type.Boolean()), }, { additionalProperties: false }, ); export const SessionsCompactParamsSchema = Type.Object( { key: NonEmptyString, maxLines: Type.Optional(Type.Integer({ minimum: 1 })), }, { additionalProperties: false }, ); export const ConfigGetParamsSchema = Type.Object( {}, { additionalProperties: false }, ); export const ConfigSetParamsSchema = Type.Object( { raw: NonEmptyString, }, { additionalProperties: false }, ); export const ProvidersStatusParamsSchema = Type.Object( { probe: Type.Optional(Type.Boolean()), timeoutMs: Type.Optional(Type.Integer({ minimum: 0 })), }, { additionalProperties: false }, ); export const WebLoginStartParamsSchema = Type.Object( { force: Type.Optional(Type.Boolean()), timeoutMs: Type.Optional(Type.Integer({ minimum: 0 })), verbose: Type.Optional(Type.Boolean()), }, { additionalProperties: false }, ); export const WebLoginWaitParamsSchema = Type.Object( { timeoutMs: Type.Optional(Type.Integer({ minimum: 0 })), }, { additionalProperties: false }, ); export const ModelChoiceSchema = Type.Object( { id: NonEmptyString, name: NonEmptyString, provider: NonEmptyString, contextWindow: Type.Optional(Type.Integer({ minimum: 1 })), }, { additionalProperties: false }, ); export const ModelsListParamsSchema = Type.Object( {}, { additionalProperties: false }, ); export const ModelsListResultSchema = Type.Object( { models: Type.Array(ModelChoiceSchema), }, { additionalProperties: false }, ); export const SkillsStatusParamsSchema = Type.Object( {}, { additionalProperties: false }, ); export const SkillsInstallParamsSchema = Type.Object( { name: NonEmptyString, installId: NonEmptyString, timeoutMs: Type.Optional(Type.Integer({ minimum: 1000 })), }, { additionalProperties: false }, ); export const SkillsUpdateParamsSchema = Type.Object( { skillKey: NonEmptyString, enabled: Type.Optional(Type.Boolean()), apiKey: Type.Optional(Type.String()), env: Type.Optional(Type.Record(NonEmptyString, Type.String())), }, { additionalProperties: false }, ); export const CronScheduleSchema = Type.Union([ Type.Object( { kind: Type.Literal("at"), atMs: Type.Integer({ minimum: 0 }), }, { additionalProperties: false }, ), Type.Object( { kind: Type.Literal("every"), everyMs: Type.Integer({ minimum: 1 }), anchorMs: Type.Optional(Type.Integer({ minimum: 0 })), }, { additionalProperties: false }, ), Type.Object( { kind: Type.Literal("cron"), expr: NonEmptyString, tz: Type.Optional(Type.String()), }, { additionalProperties: false }, ), ]); export const CronPayloadSchema = Type.Union([ Type.Object( { kind: Type.Literal("systemEvent"), text: NonEmptyString, }, { additionalProperties: false }, ), Type.Object( { kind: Type.Literal("agentTurn"), message: NonEmptyString, thinking: Type.Optional(Type.String()), timeoutSeconds: Type.Optional(Type.Integer({ minimum: 1 })), deliver: Type.Optional(Type.Boolean()), channel: Type.Optional( Type.Union([ Type.Literal("last"), Type.Literal("whatsapp"), Type.Literal("telegram"), ]), ), to: Type.Optional(Type.String()), bestEffortDeliver: Type.Optional(Type.Boolean()), }, { additionalProperties: false }, ), ]); export const CronIsolationSchema = Type.Object( { postToMainPrefix: Type.Optional(Type.String()), }, { additionalProperties: false }, ); export const CronJobStateSchema = Type.Object( { nextRunAtMs: Type.Optional(Type.Integer({ minimum: 0 })), runningAtMs: Type.Optional(Type.Integer({ minimum: 0 })), lastRunAtMs: Type.Optional(Type.Integer({ minimum: 0 })), lastStatus: Type.Optional( Type.Union([ Type.Literal("ok"), Type.Literal("error"), Type.Literal("skipped"), ]), ), lastError: Type.Optional(Type.String()), lastDurationMs: Type.Optional(Type.Integer({ minimum: 0 })), }, { additionalProperties: false }, ); export const CronJobSchema = Type.Object( { id: NonEmptyString, name: NonEmptyString, description: Type.Optional(Type.String()), enabled: Type.Boolean(), createdAtMs: Type.Integer({ minimum: 0 }), updatedAtMs: Type.Integer({ minimum: 0 }), schedule: CronScheduleSchema, sessionTarget: Type.Union([Type.Literal("main"), Type.Literal("isolated")]), wakeMode: Type.Union([Type.Literal("next-heartbeat"), Type.Literal("now")]), payload: CronPayloadSchema, isolation: Type.Optional(CronIsolationSchema), state: CronJobStateSchema, }, { additionalProperties: false }, ); export const CronListParamsSchema = Type.Object( { includeDisabled: Type.Optional(Type.Boolean()), }, { additionalProperties: false }, ); export const CronStatusParamsSchema = Type.Object( {}, { additionalProperties: false }, ); export const CronAddParamsSchema = Type.Object( { name: NonEmptyString, description: Type.Optional(Type.String()), enabled: Type.Optional(Type.Boolean()), schedule: CronScheduleSchema, sessionTarget: Type.Union([Type.Literal("main"), Type.Literal("isolated")]), wakeMode: Type.Union([Type.Literal("next-heartbeat"), Type.Literal("now")]), payload: CronPayloadSchema, isolation: Type.Optional(CronIsolationSchema), }, { additionalProperties: false }, ); export const CronUpdateParamsSchema = Type.Object( { id: NonEmptyString, patch: Type.Partial(CronAddParamsSchema), }, { additionalProperties: false }, ); export const CronRemoveParamsSchema = Type.Object( { id: NonEmptyString, }, { additionalProperties: false }, ); export const CronRunParamsSchema = Type.Object( { id: NonEmptyString, mode: Type.Optional( Type.Union([Type.Literal("due"), Type.Literal("force")]), ), }, { additionalProperties: false }, ); export const CronRunsParamsSchema = Type.Object( { id: NonEmptyString, limit: Type.Optional(Type.Integer({ minimum: 1, maximum: 5000 })), }, { additionalProperties: false }, ); export const CronRunLogEntrySchema = Type.Object( { ts: Type.Integer({ minimum: 0 }), jobId: NonEmptyString, action: Type.Literal("finished"), status: Type.Optional( Type.Union([ Type.Literal("ok"), Type.Literal("error"), Type.Literal("skipped"), ]), ), error: Type.Optional(Type.String()), summary: Type.Optional(Type.String()), runAtMs: Type.Optional(Type.Integer({ minimum: 0 })), durationMs: Type.Optional(Type.Integer({ minimum: 0 })), nextRunAtMs: Type.Optional(Type.Integer({ minimum: 0 })), }, { additionalProperties: false }, ); // WebChat/WebSocket-native chat methods export const ChatHistoryParamsSchema = Type.Object( { sessionKey: NonEmptyString, limit: Type.Optional(Type.Integer({ minimum: 1, maximum: 1000 })), }, { additionalProperties: false }, ); export const ChatSendParamsSchema = Type.Object( { sessionKey: NonEmptyString, message: NonEmptyString, thinking: Type.Optional(Type.String()), deliver: Type.Optional(Type.Boolean()), attachments: Type.Optional(Type.Array(Type.Unknown())), timeoutMs: Type.Optional(Type.Integer({ minimum: 0 })), idempotencyKey: NonEmptyString, }, { additionalProperties: false }, ); export const ChatAbortParamsSchema = Type.Object( { sessionKey: NonEmptyString, runId: NonEmptyString, }, { additionalProperties: false }, ); export const ChatEventSchema = Type.Object( { runId: NonEmptyString, sessionKey: NonEmptyString, seq: Type.Integer({ minimum: 0 }), state: Type.Union([ Type.Literal("delta"), Type.Literal("final"), Type.Literal("aborted"), Type.Literal("error"), ]), message: Type.Optional(Type.Unknown()), errorMessage: Type.Optional(Type.String()), usage: Type.Optional(Type.Unknown()), stopReason: Type.Optional(Type.String()), }, { additionalProperties: false }, ); export const ProtocolSchemas: Record = { ConnectParams: ConnectParamsSchema, HelloOk: HelloOkSchema, RequestFrame: RequestFrameSchema, ResponseFrame: ResponseFrameSchema, EventFrame: EventFrameSchema, GatewayFrame: GatewayFrameSchema, PresenceEntry: PresenceEntrySchema, StateVersion: StateVersionSchema, Snapshot: SnapshotSchema, ErrorShape: ErrorShapeSchema, AgentEvent: AgentEventSchema, SendParams: SendParamsSchema, AgentParams: AgentParamsSchema, WakeParams: WakeParamsSchema, NodePairRequestParams: NodePairRequestParamsSchema, NodePairListParams: NodePairListParamsSchema, NodePairApproveParams: NodePairApproveParamsSchema, NodePairRejectParams: NodePairRejectParamsSchema, NodePairVerifyParams: NodePairVerifyParamsSchema, NodeListParams: NodeListParamsSchema, NodeDescribeParams: NodeDescribeParamsSchema, NodeInvokeParams: NodeInvokeParamsSchema, SessionsListParams: SessionsListParamsSchema, SessionsPatchParams: SessionsPatchParamsSchema, SessionsResetParams: SessionsResetParamsSchema, SessionsDeleteParams: SessionsDeleteParamsSchema, SessionsCompactParams: SessionsCompactParamsSchema, ConfigGetParams: ConfigGetParamsSchema, ConfigSetParams: ConfigSetParamsSchema, ProvidersStatusParams: ProvidersStatusParamsSchema, WebLoginStartParams: WebLoginStartParamsSchema, WebLoginWaitParams: WebLoginWaitParamsSchema, ModelChoice: ModelChoiceSchema, ModelsListParams: ModelsListParamsSchema, ModelsListResult: ModelsListResultSchema, SkillsStatusParams: SkillsStatusParamsSchema, SkillsInstallParams: SkillsInstallParamsSchema, SkillsUpdateParams: SkillsUpdateParamsSchema, CronJob: CronJobSchema, CronListParams: CronListParamsSchema, CronStatusParams: CronStatusParamsSchema, CronAddParams: CronAddParamsSchema, CronUpdateParams: CronUpdateParamsSchema, CronRemoveParams: CronRemoveParamsSchema, CronRunParams: CronRunParamsSchema, CronRunsParams: CronRunsParamsSchema, CronRunLogEntry: CronRunLogEntrySchema, ChatHistoryParams: ChatHistoryParamsSchema, ChatSendParams: ChatSendParamsSchema, ChatAbortParams: ChatAbortParamsSchema, ChatEvent: ChatEventSchema, TickEvent: TickEventSchema, ShutdownEvent: ShutdownEventSchema, }; export const PROTOCOL_VERSION = 2 as const; export type ConnectParams = Static; export type HelloOk = Static; export type RequestFrame = Static; export type ResponseFrame = Static; export type EventFrame = Static; export type GatewayFrame = Static; export type Snapshot = Static; export type PresenceEntry = Static; export type ErrorShape = Static; export type StateVersion = Static; export type AgentEvent = Static; export type WakeParams = Static; export type NodePairRequestParams = Static; export type NodePairListParams = Static; export type NodePairApproveParams = Static; export type NodePairRejectParams = Static; export type NodePairVerifyParams = Static; export type NodeListParams = Static; export type NodeDescribeParams = Static; export type NodeInvokeParams = Static; export type SessionsListParams = Static; export type SessionsPatchParams = Static; export type SessionsResetParams = Static; export type SessionsDeleteParams = Static; export type SessionsCompactParams = Static; export type ConfigGetParams = Static; export type ConfigSetParams = Static; export type ProvidersStatusParams = Static; export type WebLoginStartParams = Static; export type WebLoginWaitParams = Static; export type ModelChoice = Static; export type ModelsListParams = Static; export type ModelsListResult = Static; export type SkillsStatusParams = Static; export type SkillsInstallParams = Static; export type SkillsUpdateParams = Static; export type CronJob = Static; export type CronListParams = Static; export type CronStatusParams = Static; export type CronAddParams = Static; export type CronUpdateParams = Static; export type CronRemoveParams = Static; export type CronRunParams = Static; export type CronRunsParams = Static; export type CronRunLogEntry = Static; export type ChatAbortParams = Static; export type ChatEvent = Static; export type TickEvent = Static; export type ShutdownEvent = Static; export const ErrorCodes = { NOT_LINKED: "NOT_LINKED", AGENT_TIMEOUT: "AGENT_TIMEOUT", INVALID_REQUEST: "INVALID_REQUEST", UNAVAILABLE: "UNAVAILABLE", } as const; export type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes]; export function errorShape( code: ErrorCode, message: string, opts?: { details?: unknown; retryable?: boolean; retryAfterMs?: number }, ): ErrorShape { return { code, message, ...opts, }; }