metatell Bot SDK
    Preparing search index...

    Logging, Rate Limits, and Errors

    Enable verbose SDK logs with debug: true:

    const client = createMetatellClient({
    serverUrl,
    roomId,
    debug: true,
    })

    debug: true sets the core log level to debug and also logs incoming NAF traffic.

    The SDK and core packages each keep their own logger provider registry. @metatell/bot-sdk exports DefaultLoggerProvider, registerLoggerProvider, getLogger, and getRingBuffer for SDK-level loggers such as AgentClient and for your own modules:

    import { DefaultLoggerProvider, getLogger, registerLoggerProvider } from '@metatell/bot-sdk'

    const provider = new DefaultLoggerProvider()
    provider.setLogLevel('debug')
    registerLoggerProvider(provider, { allowOverwrite: true })

    const logger = getLogger('my-bot')
    logger.debug('started', { roomId })

    MetatellClient and the core services log through the registry in @metatell/bot-core, which exports DefaultLoggerProvider, registerLoggerProvider, and getLoggerProvider. Register a provider there before creating the client to redirect or filter those logs.

    A logger provider implements getLogger(module) and may implement setMinLevel(level). DefaultLoggerProvider writes to the console and a ring buffer, and also supports enableConsole(enabled), registerSink(sink), and unregisterSink(sink).

    Use getRingBuffer() when you need to inspect recent log entries for diagnostics.

    setRateLimit() accepts the keys messages, moves, and looks:

    client.setRateLimit('messages', 2)
    client.setRateLimit('moves', 10)
    client.setRateLimit('looks', 5)

    console.log(client.getRateLimit('messages'))

    AgentClient throttles send(), move(), look(), and lookAtNearest() with these values. MetatellClient stores and returns the values but does not currently throttle calls. To throttle your own loops, use TokenBucketRateLimiter or RateLimitedQueue:

    import { RateLimitedQueue } from '@metatell/bot-sdk'

    const queue = new RateLimitedQueue()
    queue.setRate('moves', 5)

    await queue.execute('moves', () => client.avatar.moveTo(target))

    RateLimitedQueue.execute() waits for a token and rejects if none becomes available after about one second.

    The SDK exports these error classes:

    • MetatellError: abstract base class with code, timestamp, and cause.
    • AuthenticationError: authentication failure. Has an optional status.
    • TransportError: connection or transport failure. Has an optional reason.
    • ProtocolError: invalid configuration or protocol data.
    • TimeoutError: operation timed out. Has timeoutMs.
    • RateLimitedError: request was rate limited. Has an optional retryAfterMs.
    • NavigationError: scene or navmesh failure. Has a NavigationErrorCode and retryable.

    Use isMetatellError(error) and isRetryableError(error) to classify errors. isRetryableError() returns true for TransportError, TimeoutError, RateLimitedError with retryAfterMs, and NavigationError with retryable: true.

    SDK failures are reported as rejected promises. Wrap connection, chat, avatar, and voice operations in try/catch:

    import { AuthenticationError, TransportError, isRetryableError } from '@metatell/bot-sdk'

    try {
    await client.connect()
    } catch (error) {
    if (error instanceof AuthenticationError) {
    // Refresh or replace the access token.
    } else if (error instanceof TransportError) {
    // Reconnect or stop the bot cleanly.
    } else if (isRetryableError(error)) {
    // Back off and retry later.
    } else {
    throw error
    }
    }

    MetatellClient does not emit an error event.