Pular para o conteúdo

Tipos de mídia e execução local ​

Assinaturas públicas completas do SDK de bots do Monky, geradas da entrada TypeScript de @monky/bot-sdk. Campos opcionais usam ?; campos readonly não devem ser alterados. Os links de origem incluem regras de validação e detalhes da implementação.

Visão geral do SDK de bots e eventos · Voz · Miniapps · Armazenamento · Execução local

BotDeviceStorageStatus ​

Origem e validação

ts
export type BotDeviceStorageStatus = "granted" | "unavailable" | "denied";

BotScreen ​

Origem e validação

ts
export type BotScreen = {
    title: string;
    id: string;
    channelId: string;
    botId: string;
    createdAt: number;
    revision: number;
    state: BotScreenJson;
    html: string;
    instanceId: string;
    creatorUserId?: string | undefined;
};

BotScreenActionEvent ​

Origem e validação

ts
export type BotScreenActionEvent = {
    channelId: string;
    revision: number;
    userId: string;
    userNickname: string;
    instanceId: string;
    action: string;
    payload: BotScreenJson;
    actionId: string;
    screenId: string;
};

BotScreenBeforeCloseEvent ​

Origem e validação

ts
export interface BotScreenBeforeCloseEvent {
    readonly reason: BotScreenBeforeCloseReason;
}

BotScreenBeforeCloseReason ​

Origem e validação

ts
export type BotScreenBeforeCloseReason = "leave" | "end";

BotScreenBridge ​

Origem e validação

ts
export interface BotScreenBridge {
    readonly viewer: BotScreenViewer;
    /** Delivers the current state at once and every update; returns an unsubscribe function. */
    onState(callback: (state: BotScreenJson, revision: number) => void): () => void;
    /** Whether the bridge accepted the intent, not whether the bot accepted the action. */
    sendAction(action: string, payload: BotScreenJson): boolean;
    /**
     * Runs, in registration order, before a close this person asked for; the view stays visible
     * and may ask anything. Resolving `false` keeps it open. Revocations never wait for it.
     */
    onBeforeClose(handler: (event: BotScreenBeforeCloseEvent) => boolean | void | Promise<boolean | void>): () => void;
    /**
     * Runs on every close, while the view is already hidden, muted and cut from state and actions.
     * The document is kept for at most 5 seconds so the handlers can finish, e.g. saving; `storage`
     * keeps working meanwhile.
     */
    onClose(handler: (event: BotScreenCloseEvent) => void | Promise<void>): () => void;
    /**
     * Runs at once with whether the person can see the view, then on every change. The view stays
     * open but hidden while they browse elsewhere in Monky, scroll it off the stage or minimize the
     * window. Not called once the view is closing.
     */
    onVisibilityChange(handler: (visible: boolean) => void): () => void;
    /**
     * Data kept on this computer, when the bot has `device_storage` and the person allows it.
     * Missing in clients released before bot storage.
     */
    readonly storage?: BotScreenStorage;
}

BotScreenClient ​

Origem e validação

ts
export class BotScreenClient {
    constructor(adapter: BotScreenAdapter);
    createScreen(serverId: string, input: BotScreenCreate): Promise<BotScreen>;
    updateScreen(serverId: string, ref: BotScreenRef, patch: BotScreenPatch): Promise<BotScreen>;
    closeScreen(serverId: string, ref: BotScreenRef): Promise<void>;
    listScreens(serverId: string, channelId: string): Promise<BotScreen[]>;
    handle(serverId: string, type: string, payload: unknown): boolean;
}

BotScreenCloseEvent ​

Origem e validação

ts
export interface BotScreenCloseEvent {
    readonly reason: BotScreenCloseReason;
}

BotScreenCloseReason ​

Origem e validação

ts
export type BotScreenCloseReason = "ended" | BotScreenBeforeCloseReason | "revoked";

BotScreenCreate ​

Origem e validação

ts
export type BotScreenCreate = {
    title: string;
    channelId: string;
    state: BotScreenJson;
    html: string;
    id?: string | undefined;
    invocationId?: string | undefined;
};

BotScreenJson ​

Origem e validação

ts
export type BotScreenJson = string | number | boolean | BotScreenJson[] | {
    [key: string]: BotScreenJson;
} | null;

BotScreenPatch ​

Origem e validação

ts
export type BotScreenPatch = {
    expectedRevision: number;
    state: BotScreenJson;
};

BotScreenRef ​

Origem e validação

ts
export type BotScreenRef = {
    id: string;
    instanceId: string;
};

BotScreenRemoved ​

Origem e validação

ts
export type BotScreenRemoved = {
    id: string;
    channelId: string;
    reason: "ended";
    instanceId: string;
    endedByUserId: string;
} | {
    id: string;
    channelId: string;
    reason: "closed";
    instanceId: string;
} | {
    id: string;
    channelId: string;
    reason: "access_revoked";
    instanceId: string;
} | {
    id: string;
    channelId: string;
    reason: "bot_disconnected";
    instanceId: string;
} | {
    id: string;
    channelId: string;
    reason: "view_revoked";
    instanceId: string;
};

BotScreenStorage ​

Origem e validação

ts
export interface BotScreenStorage {
    /** `unavailable` until Monky connects the document, and whenever nothing may be stored. */
    readonly status: BotDeviceStorageStatus;
    /** Calls back at once with the current status and on every change; returns an unsubscribe function. */
    onStatus(callback: (status: BotDeviceStorageStatus) => void): () => void;
    get(key: string): Promise<string | ArrayBuffer | null>;
    /** With `{ autosave: true }`, a save that cannot happen resolves `false` instead of rejecting. */
    set(key: string, value: string | ArrayBuffer | ArrayBufferView | Blob, options?: {
        autosave?: boolean;
    }): Promise<boolean>;
    /** Resolves whether the key existed. */
    delete(key: string): Promise<boolean>;
    /** In key order. */
    list(options?: {
        prefix?: string;
    }): Promise<BotScreenStorageEntry[]>;
    usage(): Promise<BotScreenStorageUsage | null>;
}

BotScreenStorageEntry ​

Origem e validação

ts
export interface BotScreenStorageEntry {
    readonly key: string;
    readonly size: number;
    /** Milliseconds since the epoch. */
    readonly updatedAt: number;
}

BotScreenStorageUsage ​

Origem e validação

ts
export interface BotScreenStorageUsage {
    readonly usedBytes: number;
    readonly maxBytes: number;
    readonly level: BotStorageLevel;
}

BotScreenViewer ​

Origem e validação

ts
export interface BotScreenViewer {
    readonly id: string;
    readonly nickname: string;
    readonly locale: BotLocale;
}

BotVoiceAudioReceiver ​

Origem e validação

ts
export interface BotVoiceAudioReceiver {
    readonly droppedPackets: number;
    return: () => Promise<IteratorResult<BotVoicePacket, undefined>>;
    throw: (error: unknown) => Promise<IteratorResult<BotVoicePacket, undefined>>;
    [Symbol.asyncIterator]: () => AsyncIterableIterator<BotVoicePacket, undefined, undefined>;
    next: (...[value]: [
    ] | [
        undefined
    ]) => Promise<IteratorResult<BotVoicePacket, undefined>>;
}

BotVoiceConnection ​

Origem e validação

ts
export class BotVoiceConnection {
    constructor(channelId: string, auth: BotVoiceAuth, callbacks: VoiceCallbacks, publishAudio?: boolean);
    readonly channelId: string;
    get humanParticipantCount(): number;
    get isClosed(): boolean;
    get isReceivingAudio(): boolean;
    get receivesAudio(): boolean;
    join(options?: BotVoiceJoinOptions): Promise<void>;
    receiveAudio(argument0?: {
        signal?: AbortSignal;
    }): BotVoiceAudioReceiver;
    setMuted(muted: boolean): Promise<void>;
    setDeafened(deafened: boolean): Promise<void>;
    handle(message: VoiceMessage): boolean;
    writeOpus(frame: Uint8Array): Promise<void>;
    stopSpeaking(): void;
    close(): Promise<void>;
    disconnect(reason: string): Promise<void>;
}

BotVoiceJoinOptions ​

Origem e validação

ts
export type BotVoiceJoinOptions = {
    invocationId?: string | undefined;
    receiveAudio?: boolean | undefined;
};

BotVoicePacket ​

Origem e validação

ts
export interface BotVoicePacket {
    channelId: string;
    userId: string;
    sessionId: string;
    codec: 'opus';
    clockRate: 48000;
    channels: 2;
    /** Raw Opus, not PCM or an Ogg container. Owned by this packet's caller. */
    opus: Uint8Array;
    sequenceNumber: number;
    timestamp: number;
    ssrc: number;
    /** Monotonic milliseconds in this process, not wall time or RTP time. */
    receivedAt: number;
}

LocalCapabilityId ​

Origem e validação

ts
export type LocalCapabilityId = "youtube-audio";

LocalExecutionClient ​

Origem e validação

ts
export interface LocalExecutionClient {
    /**
     * Whether the connected server negotiated this operation (false while disconnected).
     * The invoker's client is checked per task and rejects with FEATURE_REQUIRES_UPDATE.
     */
    supports(operation: LocalOperation): boolean;
    /** Interaction contexts capture their original lifetime; source tasks acquire a fresh bot connection. */
    executor(context: LocalRequestContext): LocalExecutor;
    /** Retained metadata outlives this invocation/signal, but never authorizes a replacement human socket. */
    retainSource(invocationId: string, url: string, options?: LocalExecutionTaskOptions): Promise<LocalSourceContext>;
    releaseSource(sourceContextId: string): Promise<void>;
    /**
     * Check the original physical executor's current voice/access without starting
     * client work. Rejects with LocalExecutionRpcError when unavailable; a later
     * stream must still pass fresh admission and consent.
     */
    checkSourceAvailability(sourceContextId: string, voiceChannelId: string, options?: LocalExecutionTaskOptions): Promise<void>;
}

LocalExecutionError ​

Origem e validação

ts
export class LocalExecutionError extends Error {
    readonly event: Readonly<LocalExecutionTerminalEvent>;
    constructor(event: LocalExecutionTerminalEvent);
}

LocalExecutionProvider ​

Origem e validação

ts
export interface LocalExecutionProvider {
    localExecution(serverId: string): LocalExecutionClient;
}

LocalExecutionRpcError ​

Origem e validação

ts
export class LocalExecutionRpcError extends Error {
    readonly reason?: LocalTaskFailureReason;
    readonly cancellationCause?: LocalTaskCancellationCause;
    constructor(code: ProtocolErrorCode, message: string);
    readonly code: ProtocolErrorCode;
}

LocalExecutionTaskOptions ​

Origem e validação

ts
export interface LocalExecutionTaskOptions {
    readonly signal?: AbortSignal;
}

LocalExecutionTerminalEvent ​

Origem e validação

ts
export type LocalExecutionTerminalEvent = {
    taskId: string;
    state: "failed";
    reason: "timeout" | "busy" | "invalid_request" | "permission_denied" | "executor_unavailable" | "unsupported_platform" | "tools_missing" | "tool_install_failed" | "integrity_failed" | "storage_failed" | "provider_unavailable" | "transport_failed" | "worker_failed";
    sourceFailure?: {
        code: "input" | "unsupported" | "tools" | "runtime" | "unavailable" | "timeout" | "busy";
    } | {
        code: "recovery_failed";
        attempts: number;
    } | undefined;
} | {
    taskId: string;
    state: "cancelled";
    cause: "requested" | "requester_left_voice" | "requester_disconnected" | "bot_left_voice" | "bot_disconnected" | "permission_revoked" | "source_released" | "voice_mode_changed" | "expired" | "server_shutdown";
};

LocalExecutor ​

Origem e validação

ts
export interface LocalExecutor {
    execute(spec: Extract<LocalTaskSpec, {
        operation: 'youtube.search';
    }>, options?: LocalExecutionTaskOptions): Promise<Extract<LocalWireTaskResult, {
        operation: 'youtube.search';
    }>>;
    execute(spec: Extract<LocalTaskSpec, {
        operation: 'youtube.resolve';
    }>, options?: LocalExecutionTaskOptions): Promise<Extract<LocalWireTaskResult, {
        operation: 'youtube.resolve';
    }>>;
    execute(spec: Extract<LocalTaskSpec, {
        operation: 'youtube.preview';
    }>, options?: LocalExecutionTaskOptions): Promise<LocalWirePreviewResult>;
    /**
     * Bounded flat metadata (`spec.limit` ≤ 500); each track still needs its own resolve/stream.
     * Rejects with FEATURE_REQUIRES_UPDATE: reason `invalid_request` when the server lacks the
     * operation, `executor_unavailable` when the invoker's client does.
     */
    execute(spec: Extract<LocalTaskSpec, {
        operation: 'youtube.playlist';
    }>, options?: LocalExecutionTaskOptions): Promise<Extract<LocalWireTaskResult, {
        operation: 'youtube.playlist';
    }>>;
    execute(spec: LocalMetadataTaskSpec, options?: LocalExecutionTaskOptions): Promise<LocalMetadataTaskResult>;
    /** Resolve only after the private peer and reliable data channel are ready. */
    stream(spec: Extract<LocalTaskSpec, {
        operation: 'youtube.stream';
    }>, options: LocalStreamOptions): Promise<LocalOpusStream>;
}

LocalMediaTrack ​

Origem e validação

ts
export type LocalMediaTrack = {
    title: string;
    url: string;
    id: string;
    duration: number;
};

LocalMetadataTaskResult ​

Origem e validação

ts
export type LocalMetadataTaskResult = {
    title: string | null;
    operation: "youtube.playlist";
    total: number | null;
    tracks: {
        title: string;
        url: string;
        id: string;
        duration: number;
    }[];
    skipped: number;
} | {
    operation: "youtube.search";
    tracks: {
        title: string;
        url: string;
        id: string;
        duration: number;
    }[];
} | {
    operation: "youtube.resolve";
    track: {
        title: string;
        url: string;
        id: string;
        duration: number;
    };
} | {
    operation: "youtube.preview";
    localPreviewId: string;
    taskId: string;
    requestId: string;
    executorSessionId: string;
};

LocalMetadataTaskSpec ​

Origem e validação

ts
export type LocalMetadataTaskSpec = {
    operation: "youtube.search";
    query: string;
} | {
    url: string;
    operation: "youtube.resolve";
} | {
    url: string;
    operation: "youtube.preview";
} | {
    url: string;
    operation: "youtube.playlist";
    limit: number;
};

LocalOperation ​

Origem e validação

ts
export type LocalOperation = "youtube.search" | "youtube.resolve" | "youtube.preview" | "youtube.stream" | "youtube.playlist";

LocalOpusStream ​

Origem e validação

ts
export interface LocalOpusStream {
    /** Server wire task ID, never the executor's Main-local task UUID. */
    readonly taskId: string;
    readonly track: LocalMediaTrack;
    readonly frames: AsyncIterable<Uint8Array>;
    /** Aborted with LocalExecutionError on failure/cancellation, not normal EOF/drain. */
    readonly signal: AbortSignal;
    /** Rejects immediately on failure/cancellation; resolves after playback drain and server completion. */
    readonly closed: Promise<void>;
    /** Advance once after playback consumes a frame, never when buffering it. */
    markFrameAdvanced(): void;
    /** Await the matching revision; opposite requests supersede/reject older ones. An 8s timeout fails the task. */
    setPaused(paused: boolean): Promise<void>;
    /**
     * Cancel active work and await teardown, or await server completion after playback
     * has drained. Cancellation remains observable through signal/closed.
     * Does not release a retained source.
     */
    close(): Promise<void>;
}

LocalPlaylistResult ​

Origem e validação

ts
export type LocalPlaylistResult = {
    title: string | null;
    operation: "youtube.playlist";
    total: number | null;
    tracks: {
        title: string;
        url: string;
        id: string;
        duration: number;
    }[];
    skipped: number;
};

LocalPreviewReference ​

Origem e validação

ts
export type LocalPreviewReference = {
    localPreviewId: string;
    taskId: string;
    requestId: string;
    executorSessionId: string;
};

LocalRequestContext ​

Origem e validação

ts
export type LocalRequestContext = {
    kind: "invocation";
    invocationId: string;
} | {
    kind: "autocomplete";
    requestId: string;
} | {
    kind: "audio-preview";
    requestId: string;
} | {
    kind: "source";
    sourceContextId: string;
};

LocalSourceContext ​

Origem e validação

ts
export type LocalSourceContext = {
    url: string;
    expiresAt: number;
    botId: string;
    sourceContextId: string;
    botPublicKey: string;
    invokerId: string;
    invokerSessionId: string;
    originChannelId: string;
    capability: "youtube-audio";
    provider: "youtube-local";
};

LocalSourceFailure ​

Origem e validação

ts
export type LocalSourceFailure = {
    code: "input" | "unsupported" | "tools" | "runtime" | "unavailable" | "timeout" | "busy";
} | {
    code: "recovery_failed";
    attempts: number;
};

LocalStreamOptions ​

Origem e validação

ts
export interface LocalStreamOptions {
    readonly voiceChannelId: string;
    readonly signal?: AbortSignal | undefined;
}

LocalTaskCancellationCause ​

Origem e validação

ts
export type LocalTaskCancellationCause = "requested" | "requester_left_voice" | "requester_disconnected" | "bot_left_voice" | "bot_disconnected" | "permission_revoked" | "source_released" | "voice_mode_changed" | "expired" | "server_shutdown";

LocalTaskEvent ​

Origem e validação

ts
export type LocalTaskEvent = {
    taskId: string;
    state: "accepted";
    result: {
        title: string | null;
        operation: "youtube.playlist";
        total: number | null;
        tracks: {
            title: string;
            url: string;
            id: string;
            duration: number;
        }[];
        skipped: number;
    } | {
        operation: "youtube.search";
        tracks: {
            title: string;
            url: string;
            id: string;
            duration: number;
        }[];
    } | {
        operation: "youtube.resolve";
        track: {
            title: string;
            url: string;
            id: string;
            duration: number;
        };
    } | {
        operation: "youtube.preview";
        localPreviewId: string;
        taskId: string;
        requestId: string;
        executorSessionId: string;
    } | {
        operation: "youtube.stream";
        track: {
            title: string;
            url: string;
            id: string;
            duration: number;
        };
    };
    media?: {
        protocol: "opus-datachannel-v1";
        generation: number;
        iceServers: {
            urls: string[];
            username?: string | undefined;
            credential?: string | undefined;
        }[];
    } | undefined;
} | {
    taskId: string;
    state: "ready";
    mediaGeneration: number;
} | {
    revision: number;
    taskId: string;
    state: "paused";
} | {
    revision: number;
    taskId: string;
    state: "resumed";
} | {
    taskId: string;
    state: "completed";
    mediaGeneration?: number | undefined;
    playedFrames?: number | undefined;
} | {
    taskId: string;
    state: "failed";
    reason: "timeout" | "busy" | "invalid_request" | "permission_denied" | "executor_unavailable" | "unsupported_platform" | "tools_missing" | "tool_install_failed" | "integrity_failed" | "storage_failed" | "provider_unavailable" | "transport_failed" | "worker_failed";
    sourceFailure?: {
        code: "input" | "unsupported" | "tools" | "runtime" | "unavailable" | "timeout" | "busy";
    } | {
        code: "recovery_failed";
        attempts: number;
    } | undefined;
} | {
    taskId: string;
    state: "cancelled";
    cause: "requested" | "requester_left_voice" | "requester_disconnected" | "bot_left_voice" | "bot_disconnected" | "permission_revoked" | "source_released" | "voice_mode_changed" | "expired" | "server_shutdown";
};

LocalTaskFailureReason ​

Origem e validação

ts
export type LocalTaskFailureReason = "timeout" | "busy" | "invalid_request" | "permission_denied" | "executor_unavailable" | "unsupported_platform" | "tools_missing" | "tool_install_failed" | "integrity_failed" | "storage_failed" | "provider_unavailable" | "transport_failed" | "worker_failed";

LocalTaskSpec ​

Origem e validação

ts
export type LocalTaskSpec = {
    operation: "youtube.search";
    query: string;
} | {
    url: string;
    operation: "youtube.resolve";
} | {
    url: string;
    operation: "youtube.preview";
} | {
    url: string;
    operation: "youtube.stream";
} | {
    url: string;
    operation: "youtube.playlist";
    limit: number;
};

LocalWirePreviewResult ​

Origem e validação

ts
export type LocalWirePreviewResult = {
    operation: "youtube.preview";
    localPreviewId: string;
    taskId: string;
    requestId: string;
    executorSessionId: string;
};

LocalWireTaskResult ​

Origem e validação

ts
export type LocalWireTaskResult = {
    title: string | null;
    operation: "youtube.playlist";
    total: number | null;
    tracks: {
        title: string;
        url: string;
        id: string;
        duration: number;
    }[];
    skipped: number;
} | {
    operation: "youtube.search";
    tracks: {
        title: string;
        url: string;
        id: string;
        duration: number;
    }[];
} | {
    operation: "youtube.resolve";
    track: {
        title: string;
        url: string;
        id: string;
        duration: number;
    };
} | {
    operation: "youtube.preview";
    localPreviewId: string;
    taskId: string;
    requestId: string;
    executorSessionId: string;
} | {
    operation: "youtube.stream";
    track: {
        title: string;
        url: string;
        id: string;
        duration: number;
    };
};