{"version":3,"file":"index.cjs","names":["os","context","SpanKind","trace","ChannelWriter","ChannelReader","detectProjectName","WebSocket","SeverityNumber","isChannelRef"],"sources":["../src/errors.ts","../src/iii-constants.ts","../src/iii-types.ts","../src/iii.ts"],"sourcesContent":["/**\n * Typed error surfaced when an invocation dispatched over the SDK fails — RBAC\n * rejection (FORBIDDEN), handler-level failure, or a timeout waiting for the\n * engine to respond. Wraps the wire `ErrorBody` shape plus the `function_id`\n * that was targeted, so callers get a single error type across all failure\n * modes and can disambiguate via `err.code`.\n *\n * Before this existed, rejection values were plain `ErrorBody`-shaped objects,\n * which printed as `[object Object]` when stringified — leaving developers to\n * grep through SDK source to figure out what tripped. The class name, `code`\n * prefix in the message, and `function_id` field together make a rejection\n * self-describing.\n */\nexport type IIIInvocationErrorInit = {\n  code: string\n  message: string\n  function_id?: string\n  stacktrace?: string\n}\n\nexport class IIIInvocationError extends Error {\n  public readonly code: string\n  public readonly function_id?: string\n  public readonly stacktrace?: string\n\n  constructor(init: IIIInvocationErrorInit) {\n    super(`${init.code}: ${init.message}`)\n    this.name = 'IIIInvocationError'\n    this.code = init.code\n    this.function_id = init.function_id\n    this.stacktrace = init.stacktrace\n  }\n}\n\n/**\n * True when `value` looks like the wire `ErrorBody` the engine sends in\n * `InvocationResult.error`: `{ code: string, message: string, stacktrace?: string }`.\n * Used to distinguish an engine rejection (which we wrap in\n * {@link IIIInvocationError}) from a JS `Error` thrown elsewhere.\n */\nexport function isErrorBody(value: unknown): value is {\n  code: string\n  message: string\n  stacktrace?: string\n} {\n  if (typeof value !== 'object' || value === null) return false\n  const v = value as { code?: unknown; message?: unknown; stacktrace?: unknown }\n  return (\n    typeof v.code === 'string' &&\n    typeof v.message === 'string' &&\n    (v.stacktrace === undefined || typeof v.stacktrace === 'string')\n  )\n}\n","/**\n * Constants for the III module.\n */\n\n/**\n * Engine function paths for internal operations.\n *\n * Naming note: `LIST_TRIGGERS` / `INFO_TRIGGERS` cover trigger TYPES\n * (templates). `LIST_REGISTERED_TRIGGERS` / `INFO_REGISTERED_TRIGGERS`\n * cover trigger INSTANCES (subscriber rows). The old\n * `engine::trigger-types::list` builtin has been removed and is now\n * served by `engine::triggers::list`.\n */\nexport const EngineFunctions = {\n  LIST_FUNCTIONS: 'engine::functions::list',\n  INFO_FUNCTIONS: 'engine::functions::info',\n  LIST_WORKERS: 'engine::workers::list',\n  INFO_WORKERS: 'engine::workers::info',\n  LIST_TRIGGERS: 'engine::triggers::list',\n  INFO_TRIGGERS: 'engine::triggers::info',\n  LIST_REGISTERED_TRIGGERS: 'engine::registered-triggers::list',\n  INFO_REGISTERED_TRIGGERS: 'engine::registered-triggers::info',\n  REGISTER_WORKER: 'engine::workers::register',\n} as const\n\n/** Engine trigger types */\nexport const EngineTriggers = {\n  FUNCTIONS_AVAILABLE: 'engine::functions-available',\n  LOG: 'log',\n} as const\n\n/** Log function paths */\nexport const LogFunctions = {\n  INFO: 'engine::log::info',\n  WARN: 'engine::log::warn',\n  ERROR: 'engine::log::error',\n  DEBUG: 'engine::log::debug',\n} as const\n\n/** Connection state for the III WebSocket */\nexport type IIIConnectionState =\n  | 'disconnected'\n  | 'connecting'\n  | 'connected'\n  | 'reconnecting'\n  | 'failed'\n\n/** Configuration for WebSocket reconnection behavior */\nexport interface IIIReconnectionConfig {\n  /** Starting delay in milliseconds (default: 1000ms) */\n  initialDelayMs: number\n  /** Maximum delay cap in milliseconds (default: 30000ms) */\n  maxDelayMs: number\n  /** Exponential backoff multiplier (default: 2) */\n  backoffMultiplier: number\n  /** Random jitter factor 0-1 (default: 0.3) */\n  jitterFactor: number\n  /** Maximum retry attempts, -1 for infinite (default: -1) */\n  maxRetries: number\n}\n\n/** Default reconnection configuration */\nexport const DEFAULT_BRIDGE_RECONNECTION_CONFIG: IIIReconnectionConfig = {\n  initialDelayMs: 1000,\n  maxDelayMs: 30000,\n  backoffMultiplier: 2,\n  jitterFactor: 0.3,\n  maxRetries: -1,\n}\n\n/** Default invocation timeout in milliseconds */\nexport const DEFAULT_INVOCATION_TIMEOUT_MS = 30000\n","export enum MessageType {\n  RegisterFunction = 'registerfunction',\n  UnregisterFunction = 'unregisterfunction',\n  InvokeFunction = 'invokefunction',\n  InvocationResult = 'invocationresult',\n  RegisterTriggerType = 'registertriggertype',\n  RegisterTrigger = 'registertrigger',\n  UnregisterTrigger = 'unregistertrigger',\n  UnregisterTriggerType = 'unregistertriggertype',\n  TriggerRegistrationResult = 'triggerregistrationresult',\n  WorkerRegistered = 'workerregistered',\n}\n\nexport type RegisterTriggerTypeMessage = {\n  message_type: MessageType.RegisterTriggerType\n  id: string\n  description: string\n}\n\nexport type UnregisterTriggerTypeMessage = {\n  message_type: MessageType.UnregisterTriggerType\n  id: string\n}\n\nexport type UnregisterTriggerMessage = {\n  message_type: MessageType.UnregisterTrigger\n  id: string\n  type?: string\n}\n\nexport type ErrorBody = {\n  code: string\n  message: string\n  stacktrace?: string\n}\n\nexport type TriggerRegistrationResultMessage = {\n  message_type: MessageType.TriggerRegistrationResult\n  id: string\n  type: string\n  function_id: string\n  error?: ErrorBody\n}\n\nexport type RegisterTriggerMessage = {\n  message_type: MessageType.RegisterTrigger\n  id: string\n  type: string\n  function_id: string\n  config: unknown\n  metadata?: Record<string, unknown>\n}\n\n/**\n * Authentication configuration for HTTP-invoked functions.\n *\n * - `hmac` -- HMAC signature verification using a shared secret.\n * - `bearer` -- Bearer token authentication.\n * - `api_key` -- API key sent via a custom header.\n */\nexport type HttpAuthConfig =\n  | { type: 'hmac'; secret_key: string }\n  | { type: 'bearer'; token_key: string }\n  | { type: 'api_key'; header: string; value_key: string }\n\n/**\n * Configuration for registering an HTTP-invoked function (Lambda, Cloudflare\n * Workers, etc.) instead of a local handler.\n */\nexport type HttpInvocationConfig = {\n  /** URL to invoke. */\n  url: string\n  /** HTTP method. Defaults to `POST`. */\n  method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'\n  /** Timeout in milliseconds. */\n  timeout_ms?: number\n  /** Custom headers to send with the request. */\n  headers?: Record<string, string>\n  /** Authentication configuration. */\n  auth?: HttpAuthConfig\n}\n\nexport type RegisterFunctionFormat = {\n  /**\n   * The name of the parameter\n   */\n  name?: string\n  /**\n   * The description of the parameter\n   */\n  description?: string\n  /**\n   * The type of the parameter\n   */\n  type?: 'string' | 'number' | 'boolean' | 'object' | 'array' | 'null' | 'map' | 'integer'\n  /**\n   * The body of the parameter (for objects)\n   */\n  properties?: Record<string, unknown>\n  /**\n   * The items of the parameter (for arrays)\n   */\n  items?: unknown\n  /**\n   * Whether the parameter is required\n   */\n  required?: string[]\n  [key: string]: unknown\n}\n\nexport type RegisterFunctionMessage = {\n  message_type: MessageType.RegisterFunction\n  /**\n   * The path of the function (use :: for namespacing, e.g. external::my_lambda)\n   */\n  id: string\n  /**\n   * The description of the function\n   */\n  description?: string\n  /**\n   * The request format of the function\n   */\n  request_format?: RegisterFunctionFormat\n  /**\n   * The response format of the function\n   */\n  response_format?: RegisterFunctionFormat\n  metadata?: Record<string, unknown>\n  /**\n   * HTTP invocation config for external HTTP functions (Lambda, Cloudflare Workers, etc.)\n   */\n  invocation?: HttpInvocationConfig\n}\n\n/**\n * Routing action for {@link TriggerRequest}. Determines how the engine\n * handles the invocation.\n *\n * - `enqueue` -- Routes through a named queue for async processing.\n * - `void` -- Fire-and-forget, no response.\n */\nexport type TriggerAction = { type: 'enqueue'; queue: string } | { type: 'void' }\n\n/**\n * Input passed to the RBAC auth function during WebSocket upgrade.\n * Contains the HTTP headers, query parameters, and client IP from the\n * connecting worker's upgrade request.\n */\nexport type AuthInput = {\n  /** HTTP headers from the WebSocket upgrade request. */\n  headers: Record<string, string>\n  /** Query parameters from the upgrade URL. Each key maps to an array of values to support repeated keys. */\n  query_params: Record<string, string[]>\n  /** IP address of the connecting client. */\n  ip_address: string\n}\n\n/**\n * Return value from the RBAC auth function. Controls which functions the\n * authenticated worker can invoke and what context is forwarded to the\n * middleware.\n */\nexport type AuthResult = {\n  /** Additional function IDs to allow beyond the `expose_functions` config. */\n  allowed_functions: string[]\n  /** Function IDs to deny even if they match `expose_functions`. Takes precedence over allowed. */\n  forbidden_functions: string[]\n  /** Trigger type IDs the worker may register triggers for. When omitted, all types are allowed. */\n  allowed_trigger_types?: string[]\n  /** Whether the worker may register new trigger types. */\n  allow_trigger_type_registration: boolean\n  /** Whether the worker may register new functions. Defaults to `true` if omitted. */\n  allow_function_registration?: boolean\n  /** Arbitrary context forwarded to the middleware function on every invocation. */\n  context: Record<string, unknown>\n  /** Optional prefix applied to all function IDs registered by this worker. */\n  function_registration_prefix?: string\n}\n\n/**\n * Input passed to the RBAC middleware function on every function invocation\n * through the RBAC port. The middleware can inspect, modify, or reject the\n * call before it reaches the target function.\n */\nexport type MiddlewareFunctionInput = {\n  /** ID of the function being invoked. */\n  function_id: string\n  /** Payload sent by the caller. */\n  payload: Record<string, unknown>\n  /** Routing action, if any. */\n  action?: TriggerAction\n  /** Auth context returned by the auth function for this session. */\n  context: Record<string, unknown>\n}\n\n/**\n * Input passed to the `on_trigger_type_registration_function_id` hook\n * when a worker attempts to register a new trigger type through the RBAC port.\n * Return an {@link OnTriggerTypeRegistrationResult} with the (possibly mapped)\n * fields, or throw to deny the registration.\n */\nexport type OnTriggerTypeRegistrationInput = {\n  /** ID of the trigger type being registered. */\n  trigger_type_id: string\n  /** Human-readable description of the trigger type. */\n  description: string\n  /** Auth context from `AuthResult.context` for this session. */\n  context: Record<string, unknown>\n}\n\n/**\n * Result returned from the `on_trigger_type_registration_function_id` hook.\n * All fields are optional -- omitted fields keep the original value from the\n * registration request.\n */\nexport type OnTriggerTypeRegistrationResult = {\n  /** Mapped trigger type ID. */\n  trigger_type_id?: string\n  /** Mapped description. */\n  description?: string\n}\n\n/**\n * Input passed to the `on_trigger_registration_function_id` hook\n * when a worker attempts to register a trigger through the RBAC port.\n * Return an {@link OnTriggerRegistrationResult} with the (possibly mapped)\n * fields, or throw to deny the registration.\n */\nexport type OnTriggerRegistrationInput = {\n  /** ID of the trigger being registered. */\n  trigger_id: string\n  /** Trigger type identifier. */\n  trigger_type: string\n  /** ID of the function this trigger is bound to. */\n  function_id: string\n  /** Trigger-specific configuration. */\n  config: unknown\n  /** Arbitrary metadata attached to the trigger. */\n  metadata?: Record<string, unknown>\n  /** Auth context from `AuthResult.context` for this session. */\n  context: Record<string, unknown>\n}\n\n/**\n * Result returned from the `on_trigger_registration_function_id` hook.\n * All fields are optional -- omitted fields keep the original value from the\n * registration request.\n */\nexport type OnTriggerRegistrationResult = {\n  /** Mapped trigger ID. */\n  trigger_id?: string\n  /** Mapped trigger type. */\n  trigger_type?: string\n  /** Mapped function ID. */\n  function_id?: string\n  /** Mapped trigger configuration. */\n  config?: unknown\n}\n\n/**\n * Input passed to the `on_function_registration_function_id` hook\n * when a worker attempts to register a function through the RBAC port.\n * Return an {@link OnFunctionRegistrationResult} with the (possibly mapped)\n * fields, or throw to deny the registration.\n */\nexport type OnFunctionRegistrationInput = {\n  /** ID of the function being registered. */\n  function_id: string\n  /** Human-readable description of the function. */\n  description?: string\n  /** Arbitrary metadata attached to the function. */\n  metadata?: Record<string, unknown>\n  /** Auth context from `AuthResult.context` for this session. */\n  context: Record<string, unknown>\n}\n\n/**\n * Result returned from the `on_function_registration_function_id` hook.\n * All fields are optional -- omitted fields keep the original value from the\n * registration request.\n */\nexport type OnFunctionRegistrationResult = {\n  /** Mapped function ID. */\n  function_id?: string\n  /** Mapped description. */\n  description?: string\n  /** Mapped metadata. */\n  metadata?: Record<string, unknown>\n}\n\n/**\n * Result returned when a function is invoked with `TriggerAction.Enqueue`.\n */\nexport type EnqueueResult = {\n  /** Unique receipt ID for the enqueued message. */\n  messageReceiptId: string\n}\n\n/**\n * Request object passed to {@link ISdk.trigger}.\n *\n * @typeParam TInput - Type of the payload.\n */\nexport type TriggerRequest<TInput = unknown> = {\n  /** ID of the function to invoke. */\n  function_id: string\n  /** Payload to pass to the function. */\n  payload: TInput\n  /** Routing action. Omit for synchronous request/response. */\n  action?: TriggerAction\n  /** Override the default invocation timeout in milliseconds. */\n  timeoutMs?: number\n}\n\nexport type InvokeFunctionMessage = {\n  message_type: MessageType.InvokeFunction\n  /**\n   * This is optional for async invocations\n   */\n  invocation_id?: string\n  /**\n   * The path of the function\n   */\n  function_id: string\n  /**\n   * The data to pass to the function\n   */\n  data: unknown\n  /**\n   * W3C trace-context traceparent header for distributed tracing\n   */\n  traceparent?: string\n  /**\n   * W3C baggage header for cross-cutting context propagation\n   */\n  baggage?: string\n  /**\n   * Trigger action for queue routing or fire-and-forget\n   */\n  action?: TriggerAction\n}\n\nexport type InvocationResultMessage = {\n  message_type: MessageType.InvocationResult\n  /**\n   * The id of the invocation\n   */\n  invocation_id: string\n  /**\n   * The path of the function\n   */\n  function_id: string\n  result?: unknown\n  error?: unknown\n  /**\n   * W3C trace-context traceparent header for distributed tracing\n   */\n  traceparent?: string\n  /**\n   * W3C baggage header for cross-cutting context propagation\n   */\n  baggage?: string\n}\n\nexport type WorkerRegisteredMessage = {\n  message_type: MessageType.WorkerRegistered\n  worker_id: string\n}\n\nexport type UnregisterFunctionMessage = {\n  message_type: MessageType.UnregisterFunction\n  id: string\n}\n\n/**\n * Serializable reference to one end of a streaming channel. Can be included\n * in invocation payloads to pass channel endpoints between workers.\n */\nexport type StreamChannelRef = {\n  /** Unique channel identifier. */\n  channel_id: string\n  /** Access key for authentication. */\n  access_key: string\n  /** Whether this ref is for reading or writing. */\n  direction: 'read' | 'write'\n}\n\nexport type IIIMessage =\n  | RegisterFunctionMessage\n  | UnregisterFunctionMessage\n  | InvokeFunctionMessage\n  | InvocationResultMessage\n  | RegisterTriggerMessage\n  | RegisterTriggerTypeMessage\n  | UnregisterTriggerMessage\n  | UnregisterTriggerTypeMessage\n  | TriggerRegistrationResultMessage\n  | WorkerRegisteredMessage\n","import { context, trace } from '@opentelemetry/api'\nimport { createRequire } from 'node:module'\nimport * as os from 'node:os'\nimport { type Data, WebSocket } from 'ws'\nimport { ChannelReader, ChannelWriter } from './channels'\nimport { IIIInvocationError, isErrorBody } from './errors'\nimport {\n  DEFAULT_BRIDGE_RECONNECTION_CONFIG,\n  DEFAULT_INVOCATION_TIMEOUT_MS,\n  EngineFunctions,\n  type IIIConnectionState,\n  type IIIReconnectionConfig,\n} from './iii-constants'\nimport {\n  type HttpInvocationConfig,\n  type IIIMessage,\n  type InvocationResultMessage,\n  type InvokeFunctionMessage,\n  MessageType,\n  type RegisterFunctionMessage,\n  type RegisterTriggerMessage,\n  type RegisterTriggerTypeMessage,\n  type StreamChannelRef,\n  type TriggerAction as TriggerActionType,\n  type TriggerRegistrationResultMessage,\n  type TriggerRequest,\n  type WorkerRegisteredMessage,\n} from './iii-types'\nimport { registerWorkerGauges, stopWorkerGauges } from '@iii-dev/observability'\nimport { getMeter, getTracer } from '@iii-dev/observability/internal'\nimport { SpanKind } from '@opentelemetry/api'\nimport type { IStream } from './stream'\nimport { detectProjectName } from './utils'\nimport {\n  extractContext,\n  getLogger,\n  initOtel,\n  injectBaggage,\n  injectTraceparent,\n  type OtelConfig,\n  recordSpanEvent,\n  redactAndTruncate,\n  resolveMaxBytesFromEnv,\n  SeverityNumber,\n  shutdownOtel,\n  withSpan,\n} from '@iii-dev/observability'\nimport type { TriggerHandler } from './triggers'\nimport type {\n  FunctionRef,\n  Invocation,\n  ISdk,\n  RegisterFunctionOptions,\n  RemoteFunctionData,\n  RemoteFunctionHandler,\n  RemoteTriggerTypeData,\n  Trigger,\n  TriggerTypeRef,\n} from './types'\nimport { isChannelRef } from './utils'\n\nconst require = createRequire(import.meta.url)\nconst { version: SDK_VERSION } = require('../package.json')\n\nfunction getOsInfo(): string {\n  return `${os.platform()} ${os.release()} (${os.arch()})`\n}\n\nfunction getDefaultWorkerName(): string {\n  return `${os.hostname()}:${process.pid}`\n}\n\n/** @internal */\nexport type TelemetryOptions = {\n  language?: string\n  project_name?: string\n  framework?: string\n  amplitude_api_key?: string\n}\n\n/**\n * Configuration options passed to {@link registerWorker}.\n *\n * @example\n * ```typescript\n * const iii = registerWorker('ws://localhost:49134', {\n *   workerName: 'my-worker',\n *   invocationTimeoutMs: 10000,\n *   reconnectionConfig: { maxRetries: 5 },\n * })\n * ```\n */\nexport type InitOptions = {\n  /** Display name for this worker. Defaults to `hostname:pid`. */\n  workerName?: string\n  /** Enable worker metrics via OpenTelemetry. Defaults to `true`. */\n  enableMetricsReporting?: boolean\n  /** Default timeout for `trigger()` in milliseconds. Defaults to `30000`. */\n  invocationTimeoutMs?: number\n  /**\n   * WebSocket reconnection behavior.\n   *\n   * @see {@link IIIReconnectionConfig} for available fields and defaults.\n   */\n  reconnectionConfig?: Partial<IIIReconnectionConfig>\n  /**\n   * OpenTelemetry configuration. OTel is initialized automatically by default.\n   * Set `{ enabled: false }` or env `OTEL_ENABLED=false/0/no/off` to disable.\n   * The `engineWsUrl` is set automatically from the III address.\n   */\n  otel?: Omit<OtelConfig, 'engineWsUrl'>\n  /** Custom HTTP headers sent during the WebSocket handshake. */\n  headers?: Record<string, string>\n  /** @internal */\n  telemetry?: TelemetryOptions\n}\n\nclass Sdk implements ISdk {\n  private ws?: WebSocket\n  private functions = new Map<string, RemoteFunctionData>()\n  private invocations = new Map<string, Invocation & { timeout?: NodeJS.Timeout }>()\n  private triggers = new Map<string, RegisterTriggerMessage>()\n  private triggerTypes = new Map<string, RemoteTriggerTypeData>()\n  private messagesToSend: Record<string, unknown>[] = []\n  private workerName: string\n  private workerId?: string\n  private reconnectTimeout?: NodeJS.Timeout\n  private metricsReportingEnabled: boolean\n  private invocationTimeoutMs: number\n  private reconnectionConfig: IIIReconnectionConfig\n  private reconnectAttempt = 0\n  private connectionState: IIIConnectionState = 'disconnected'\n  private isShuttingDown = false\n\n  constructor(\n    private readonly address: string,\n    private readonly options?: InitOptions,\n  ) {\n    this.workerName = options?.workerName ?? getDefaultWorkerName()\n    this.metricsReportingEnabled = options?.enableMetricsReporting ?? true\n    this.invocationTimeoutMs = options?.invocationTimeoutMs ?? DEFAULT_INVOCATION_TIMEOUT_MS\n    this.reconnectionConfig = {\n      ...DEFAULT_BRIDGE_RECONNECTION_CONFIG,\n      ...options?.reconnectionConfig,\n    }\n\n    // Initialize OpenTelemetry (enabled by default, opt-out via config or env)\n    initOtel({ ...options?.otel, engineWsUrl: this.address })\n\n    this.connect()\n  }\n\n  /**\n   * Registers a custom trigger type with the engine. A trigger type defines\n   * how external events (HTTP, cron, queue, etc.) map to function invocations.\n   *\n   * @param triggerType - Trigger type registration input.\n   * @param triggerType.id - Unique trigger type identifier.\n   * @param triggerType.description - Human-readable description.\n   * @param handler - Handler with `registerTrigger` / `unregisterTrigger` callbacks.\n   *\n   * @example\n   * ```typescript\n   * iii.registerTriggerType(\n   *   { id: 'my-trigger', description: 'Custom trigger' },\n   *   {\n   *     async registerTrigger({ id, function_id, config }) { },\n   *     async unregisterTrigger({ id, function_id, config }) { },\n   *   },\n   * )\n   * ```\n   */\n  registerTriggerType = <TConfig>(\n    triggerType: Omit<RegisterTriggerTypeMessage, 'message_type'>,\n    handler: TriggerHandler<TConfig>,\n  ): TriggerTypeRef<TConfig> => {\n    this.sendMessage(MessageType.RegisterTriggerType, triggerType, true)\n    this.triggerTypes.set(triggerType.id, {\n      message: { ...triggerType, message_type: MessageType.RegisterTriggerType },\n      handler,\n    })\n\n    return {\n      id: triggerType.id,\n      registerTrigger: (functionId: string, config: TConfig, metadata?: Record<string, unknown>) => {\n        return this.registerTrigger({\n          type: triggerType.id,\n          function_id: functionId,\n          config,\n          metadata,\n        })\n      },\n      registerFunction: (functionId, handler, config, metadata?) => {\n        const ref = this.registerFunction(functionId, handler)\n        this.registerTrigger({\n          type: triggerType.id,\n          function_id: functionId,\n          config,\n          metadata,\n        })\n        return ref\n      },\n      unregister: () => {\n        this.unregisterTriggerType(triggerType)\n      },\n    }\n  }\n\n  /**\n   * Unregisters a previously registered trigger type.\n   *\n   * @param triggerType - The trigger type to unregister (must match the `id` used during registration).\n   */\n  unregisterTriggerType = (triggerType: Omit<RegisterTriggerTypeMessage, 'message_type'>): void => {\n    this.sendMessage(MessageType.UnregisterTriggerType, triggerType, true)\n    this.triggerTypes.delete(triggerType.id)\n  }\n\n  /**\n   * Binds a trigger configuration to a registered function. When the trigger\n   * fires, the engine invokes the target function.\n   *\n   * @param trigger - Trigger registration input.\n   * @param trigger.type - Trigger type (e.g. `http`, `durable:subscriber`, `cron`).\n   * @param trigger.function_id - ID of the function to invoke.\n   * @param trigger.config - Trigger-specific configuration.\n   * @returns A {@link Trigger} handle with an `unregister()` method.\n   *\n   * @example\n   * ```typescript\n   * const trigger = iii.registerTrigger({\n   *   type: 'http',\n   *   function_id: 'greet',\n   *   config: { api_path: '/greet', http_method: 'GET' },\n   * })\n   *\n   * // Later...\n   * trigger.unregister()\n   * ```\n   */\n  registerTrigger = (trigger: Omit<RegisterTriggerMessage, 'message_type' | 'id'>): Trigger => {\n    const id = crypto.randomUUID()\n    const fullTrigger: RegisterTriggerMessage = {\n      ...trigger,\n      id,\n      message_type: MessageType.RegisterTrigger,\n    }\n    this.sendMessage(MessageType.RegisterTrigger, fullTrigger, true)\n    this.triggers.set(id, fullTrigger)\n\n    return {\n      unregister: () => {\n        this.sendMessage(MessageType.UnregisterTrigger, {\n          id,\n          message_type: MessageType.UnregisterTrigger,\n          type: fullTrigger.type,\n        })\n        this.triggers.delete(id)\n      },\n    }\n  }\n\n  /**\n   * Registers a function with the engine. The `functionId` is the unique identifier\n   * used by triggers and invocations.\n   *\n   * Pass a handler for local execution, or an {@link HttpInvocationConfig}\n   * for HTTP-invoked functions (Lambda, Cloudflare Workers, etc.).\n   *\n   * @param functionId - Unique function identifier.\n   * @param handlerOrInvocation - Async handler or HTTP invocation config.\n   * @param options - Optional function registration options (description, request/response formats, metadata).\n   * @returns A {@link FunctionRef} with `id` and `unregister()`.\n   *\n   * @example\n   * ```typescript\n   * const fn = iii.registerFunction(\n   *   'greet',\n   *   async (input: { name: string }) => {\n   *     return { message: `Hello, ${input.name}!` }\n   *   },\n   *   { description: 'Greets a user' },\n   * )\n   * ```\n   */\n  registerFunction = (\n    functionId: string,\n    handlerOrInvocation: RemoteFunctionHandler | HttpInvocationConfig,\n    options?: RegisterFunctionOptions,\n  ): FunctionRef => {\n    if (!functionId || functionId.trim() === '') {\n      throw new Error('id is required')\n    }\n    if (this.functions.has(functionId)) {\n      throw new Error(`function id already registered: ${functionId}`)\n    }\n\n    const isHandler = typeof handlerOrInvocation === 'function'\n\n    const fullMessage: RegisterFunctionMessage = isHandler\n      ? { ...options, id: functionId, message_type: MessageType.RegisterFunction }\n      : {\n          ...options,\n          id: functionId,\n          message_type: MessageType.RegisterFunction,\n          invocation: {\n            url: handlerOrInvocation.url,\n            method: handlerOrInvocation.method ?? 'POST',\n            timeout_ms: handlerOrInvocation.timeout_ms,\n            headers: handlerOrInvocation.headers,\n            auth: handlerOrInvocation.auth,\n          },\n        }\n\n    this.sendMessage(MessageType.RegisterFunction, fullMessage, true)\n\n    if (isHandler) {\n      const handler = handlerOrInvocation as RemoteFunctionHandler\n      this.functions.set(functionId, {\n        message: fullMessage,\n        handler: async (input, traceparent?: string, baggage?: string) => {\n          const tracePayloads = !(\n            process.env.III_DISABLE_TRACE_PAYLOADS === '1' ||\n            process.env.III_DISABLE_TRACE_PAYLOADS?.toLowerCase() === 'true'\n          )\n          const payloadMaxBytes = resolveMaxBytesFromEnv()\n\n          const runHandler = async () => {\n            if (tracePayloads) {\n              const { json, truncated } = redactAndTruncate(input, payloadMaxBytes)\n              recordSpanEvent('iii.invocation.input', {\n                'iii.payload.json': json,\n                'iii.payload.truncated': truncated,\n              })\n            }\n            try {\n              const result = await handler(input)\n              if (tracePayloads) {\n                const { json, truncated } = redactAndTruncate(result, payloadMaxBytes)\n                recordSpanEvent('iii.invocation.output', {\n                  'iii.payload.json': json,\n                  'iii.payload.truncated': truncated,\n                  'iii.payload.ok': true,\n                })\n              }\n              return result\n            } catch (err) {\n              if (tracePayloads) {\n                const errMsg = err instanceof Error ? err.message : String(err)\n                const { json, truncated } = redactAndTruncate(\n                  { error: errMsg },\n                  payloadMaxBytes,\n                )\n                recordSpanEvent('iii.invocation.output', {\n                  'iii.payload.json': json,\n                  'iii.payload.truncated': truncated,\n                  'iii.payload.ok': false,\n                })\n              }\n              throw err\n            }\n          }\n\n          if (getTracer()) {\n            const parentContext = extractContext(traceparent, baggage)\n\n            return context.with(parentContext, () =>\n              withSpan(`call ${functionId}`, { kind: SpanKind.SERVER }, async () => await runHandler()),\n            )\n          }\n\n          const traceId = crypto.randomUUID().replace(/-/g, '')\n          const spanId = crypto.randomUUID().replace(/-/g, '').slice(0, 16)\n          const syntheticSpan = trace.wrapSpanContext({ traceId, spanId, traceFlags: 1 })\n\n          return context.with(trace.setSpan(context.active(), syntheticSpan), async () => await runHandler())\n        },\n      })\n    } else {\n      this.functions.set(functionId, { message: fullMessage })\n    }\n\n    return {\n      id: functionId,\n      unregister: () => {\n        this.sendMessage(MessageType.UnregisterFunction, { id: functionId }, true)\n        this.functions.delete(functionId)\n      },\n    }\n  }\n\n  /**\n   * @internal Implementation backing the `createChannel` helper in the\n   * `iii-sdk/helpers` submodule. Not part of the public `ISdk` surface.\n   *\n   * Creates a streaming channel pair for worker-to-worker data transfer.\n   * Returns a {@link Channel} with a local writer/reader and serializable refs\n   * that can be passed as fields in invocation data to other functions.\n   */\n  __helpers_create_channel = async (bufferSize?: number): Promise<import('./types').Channel> => {\n    const result = await this.trigger<{ buffer_size?: number }, { writer: StreamChannelRef; reader: StreamChannelRef }>(\n      { function_id: 'engine::channels::create', payload: { buffer_size: bufferSize } },\n    )\n\n    return {\n      writer: new ChannelWriter(this.address, result.writer),\n      reader: new ChannelReader(this.address, result.reader),\n      writerRef: result.writer,\n      readerRef: result.reader,\n    }\n  }\n\n  /**\n   * Invokes a remote function. The routing behavior and return type depend\n   * on the `action` field of the request.\n   *\n   * | `action`                      | Behavior                                           | Return type              |\n   * |-------------------------------|----------------------------------------------------|-----------------------   |\n   * | _(none)_                      | Synchronous -- waits for the function to return     | `Promise<TOutput>`       |\n   * | `TriggerAction.Enqueue(...)` | Async via named queue -- engine acknowledges enqueue | `Promise<EnqueueResult>` |\n   * | `TriggerAction.Void()`       | Fire-and-forget -- no response                      | `Promise<undefined>`     |\n   *\n   * @param request - The trigger request.\n   * @param request.function_id - ID of the function to invoke.\n   * @param request.payload - Payload to pass to the function.\n   * @param request.action - Routing action. Omit for synchronous request/response.\n   * @param request.timeoutMs - Override the default invocation timeout.\n   * @returns The result of the function invocation.\n   *\n   * @example\n   * ```typescript\n   * import { TriggerAction } from 'iii-sdk'\n   *\n   * // Synchronous\n   * const result = await iii.trigger({ function_id: 'get-order', payload: { id: '123' } })\n   *\n   * // Enqueue\n   * const { messageReceiptId } = await iii.trigger({\n   *   function_id: 'payments::charge',\n   *   payload: { orderId: '123', amount: 49.99 },\n   *   action: TriggerAction.Enqueue({ queue: 'payment' }),\n   * })\n   *\n   * // Fire-and-forget\n   * iii.trigger({\n   *   function_id: 'notifications::send',\n   *   payload: { userId: '123' },\n   *   action: TriggerAction.Void(),\n   * })\n   * ```\n   */\n  trigger = async <TInput, TOutput>(request: TriggerRequest<TInput>): Promise<TOutput> => {\n    const { function_id, payload, action, timeoutMs } = request\n    const effectiveTimeout = timeoutMs ?? this.invocationTimeoutMs\n\n    // Void is fire-and-forget — no invocation_id, no response\n    if (action?.type === 'void') {\n      const traceparent = injectTraceparent()\n      const baggage = injectBaggage()\n      this.sendMessage(MessageType.InvokeFunction, {\n        function_id,\n        data: payload,\n        traceparent,\n        baggage,\n        action,\n      })\n      return undefined as TOutput\n    }\n\n    // Enqueue and default: send invocation_id, await response\n    const invocation_id = crypto.randomUUID()\n    const traceparent = injectTraceparent()\n    const baggage = injectBaggage()\n\n    return new Promise<TOutput>((resolve, reject) => {\n      const timeout = setTimeout(() => {\n        const invocation = this.invocations.get(invocation_id)\n        if (invocation) {\n          this.invocations.delete(invocation_id)\n          reject(\n            new IIIInvocationError({\n              code: 'TIMEOUT',\n              message: `invocation timed out after ${effectiveTimeout}ms`,\n              function_id,\n            }),\n          )\n        }\n      }, effectiveTimeout)\n\n      this.invocations.set(invocation_id, {\n        resolve: (result: TOutput) => {\n          clearTimeout(timeout)\n          resolve(result)\n        },\n        reject: (error: unknown) => {\n          clearTimeout(timeout)\n          reject(error)\n        },\n        function_id,\n        timeout,\n      })\n\n      this.sendMessage(MessageType.InvokeFunction, {\n        invocation_id,\n        function_id,\n        data: payload,\n        traceparent,\n        baggage,\n        action,\n      })\n    })\n  }\n\n  private registerWorkerMetadata(): void {\n    const telemetryOpts = this.options?.telemetry\n    const language =\n      telemetryOpts?.language ?? Intl.DateTimeFormat().resolvedOptions().locale ?? process.env.LANG?.split('.')[0]\n\n    this.trigger({\n      function_id: EngineFunctions.REGISTER_WORKER,\n      payload: {\n        runtime: 'node',\n        version: SDK_VERSION,\n        name: this.workerName,\n        os: getOsInfo(),\n        pid: process.pid,\n        isolation: process.env.III_ISOLATION || null,\n        telemetry: {\n          language,\n          project_name: telemetryOpts?.project_name ?? detectProjectName(),\n          framework: telemetryOpts?.framework?.trim() || 'iii-node',\n          amplitude_api_key: telemetryOpts?.amplitude_api_key,\n        },\n      },\n      action: { type: 'void' },\n    })\n  }\n\n  /**\n   * @internal Implementation backing the `createStream` helper in the\n   * `iii-sdk/helpers` submodule. Not part of the public `ISdk` surface.\n   *\n   * Registers a custom stream implementation, overriding the engine default\n   * for the given stream name. Registers 5 of the 6 `IStream` methods\n   * (`get`, `set`, `delete`, `list`, `listGroups`). The `update` method is\n   * not registered -- atomic updates are handled by the engine's built-in\n   * stream update logic.\n   */\n  __helpers_create_stream = <TData>(streamName: string, stream: IStream<TData>): void => {\n    this.registerFunction(`stream::get(${streamName})`, stream.get.bind(stream))\n    this.registerFunction(`stream::set(${streamName})`, stream.set.bind(stream))\n    this.registerFunction(`stream::delete(${streamName})`, stream.delete.bind(stream))\n    this.registerFunction(`stream::list(${streamName})`, stream.list.bind(stream))\n    this.registerFunction(`stream::list_groups(${streamName})`, stream.listGroups.bind(stream))\n  }\n\n  /**\n   * Gracefully shutdown the iii, cleaning up all resources.\n   */\n  shutdown = async (): Promise<void> => {\n    this.isShuttingDown = true\n\n    this.stopMetricsReporting()\n\n    // Shutdown OpenTelemetry\n    await shutdownOtel()\n\n    // Clear reconnection timeout\n    this.clearReconnectTimeout()\n\n    // Reject all pending invocations\n    for (const [_id, invocation] of this.invocations) {\n      if (invocation.timeout) {\n        clearTimeout(invocation.timeout)\n      }\n      invocation.reject(new Error('iii is shutting down'))\n    }\n    this.invocations.clear()\n\n    // Close WebSocket. Swallow any close-time errors (most commonly\n    // \"WebSocket was closed before the connection was established\" —\n    // emitted when `close()` fires while still in CONNECTING state\n    // and there's no error listener). Without a catch-all listener,\n    // that event becomes an unhandled exception because we remove\n    // every listener right above the close call.\n    if (this.ws) {\n      this.ws.removeAllListeners()\n      this.ws.on('error', () => {})\n      try {\n        this.ws.close()\n      } catch {\n        // ignore — shutting down anyway\n      }\n      this.ws = undefined\n    }\n\n    this.setConnectionState('disconnected')\n  }\n\n  // private methods\n\n  private setConnectionState(state: IIIConnectionState): void {\n    if (this.connectionState !== state) {\n      this.connectionState = state\n    }\n  }\n\n  private connect(): void {\n    if (this.isShuttingDown) {\n      return\n    }\n\n    this.setConnectionState('connecting')\n    this.ws = new WebSocket(this.address, { headers: this.options?.headers })\n    this.ws.on('open', this.onSocketOpen.bind(this))\n    this.ws.on('close', this.onSocketClose.bind(this))\n    this.ws.on('error', this.onSocketError.bind(this))\n  }\n\n  private clearReconnectTimeout(): void {\n    if (this.reconnectTimeout) {\n      clearTimeout(this.reconnectTimeout)\n      this.reconnectTimeout = undefined\n    }\n  }\n\n  private scheduleReconnect(): void {\n    if (this.isShuttingDown) {\n      return\n    }\n\n    const { maxRetries, initialDelayMs, backoffMultiplier, maxDelayMs, jitterFactor } = this.reconnectionConfig\n\n    if (maxRetries !== -1 && this.reconnectAttempt >= maxRetries) {\n      this.setConnectionState('failed')\n      this.logError(`Max reconnection retries (${maxRetries}) reached, giving up`)\n      return\n    }\n\n    if (this.reconnectTimeout) {\n      return // Already scheduled\n    }\n\n    const exponentialDelay = initialDelayMs * backoffMultiplier ** this.reconnectAttempt\n    const cappedDelay = Math.min(exponentialDelay, maxDelayMs)\n    const jitter = cappedDelay * jitterFactor * (2 * Math.random() - 1)\n    const delay = Math.floor(cappedDelay + jitter)\n\n    this.setConnectionState('reconnecting')\n    console.debug(`[iii] Reconnecting in ${delay}ms (attempt ${this.reconnectAttempt + 1})...`)\n\n    this.reconnectTimeout = setTimeout(() => {\n      this.reconnectTimeout = undefined\n      this.reconnectAttempt++\n      this.connect()\n    }, delay)\n  }\n\n  private onSocketError(error: Error): void {\n    this.logError('WebSocket error', error)\n  }\n\n  private startMetricsReporting(): void {\n    if (!this.metricsReportingEnabled || !this.workerId) {\n      return\n    }\n\n    const meter = getMeter()\n    if (!meter) {\n      console.warn(\n        '[iii] Worker metrics disabled: OpenTelemetry not initialized. Call initOtel() with metricsEnabled: true before creating the iii.',\n      )\n      return\n    }\n\n    registerWorkerGauges(meter, {\n      workerId: this.workerId,\n      workerName: this.workerName,\n    })\n  }\n\n  private stopMetricsReporting(): void {\n    stopWorkerGauges()\n  }\n\n  private onSocketClose(): void {\n    this.ws?.removeAllListeners()\n    this.ws?.terminate()\n    this.ws = undefined\n\n    this.setConnectionState('disconnected')\n    this.stopMetricsReporting()\n    this.scheduleReconnect()\n  }\n\n  private onSocketOpen(): void {\n    this.clearReconnectTimeout()\n    this.reconnectAttempt = 0\n    this.setConnectionState('connected')\n\n    this.ws?.on('message', this.onMessage.bind(this))\n\n    this.triggerTypes.forEach(({ message }) => {\n      this.sendMessage(MessageType.RegisterTriggerType, message, true)\n    })\n    this.functions.forEach(({ message }) => {\n      this.sendMessage(MessageType.RegisterFunction, message, true)\n    })\n    this.triggers.forEach((trigger) => {\n      this.sendMessage(MessageType.RegisterTrigger, trigger, true)\n    })\n\n    // Optimized: swap with empty array instead of splice\n    const pending = this.messagesToSend\n    this.messagesToSend = []\n    for (const message of pending) {\n      if (\n        message.type === MessageType.InvokeFunction &&\n        typeof message.invocation_id === 'string' &&\n        !this.invocations.has(message.invocation_id)\n      ) {\n        continue\n      }\n      this.sendMessageRaw(JSON.stringify(message))\n    }\n\n    this.registerWorkerMetadata()\n  }\n\n  private isOpen(): boolean {\n    return this.ws?.readyState === WebSocket.OPEN\n  }\n\n  private sendMessageRaw(data: string): void {\n    if (this.ws && this.isOpen()) {\n      try {\n        this.ws.send(data, (err) => {\n          if (err) {\n            this.logError('Failed to send message', err)\n          }\n        })\n      } catch (error) {\n        this.logError('Exception while sending message', error)\n      }\n    }\n  }\n\n  private toWireFormat(messageType: MessageType, message: Omit<IIIMessage, 'message_type'>): Record<string, unknown> {\n    const { message_type: _, ...rest } = message as Record<string, unknown>\n    if (messageType === MessageType.RegisterTrigger && 'type' in message) {\n      const { type: triggerType, ...triggerRest } = message as RegisterTriggerMessage\n      return { type: messageType, ...triggerRest, trigger_type: triggerType }\n    }\n    if (messageType === MessageType.UnregisterTrigger && 'type' in message) {\n      const { type: triggerType, ...triggerRest } = message as RegisterTriggerMessage\n      return { type: messageType, ...triggerRest, trigger_type: triggerType }\n    }\n    if (messageType === MessageType.TriggerRegistrationResult && 'type' in message) {\n      const { type: triggerType, ...resultRest } = message as TriggerRegistrationResultMessage\n      return { type: messageType, ...resultRest, trigger_type: triggerType }\n    }\n    return { type: messageType, ...rest } as Record<string, unknown>\n  }\n\n  private sendMessage(messageType: MessageType, message: Omit<IIIMessage, 'message_type'>, skipIfClosed = false): void {\n    const wireMessage = this.toWireFormat(messageType, message)\n    if (this.isOpen()) {\n      this.sendMessageRaw(JSON.stringify(wireMessage))\n    } else if (!skipIfClosed) {\n      this.messagesToSend.push(wireMessage)\n    }\n  }\n\n  private logError(message: string, error?: unknown): void {\n    const otelLogger = getLogger()\n    const errorMessage = error instanceof Error ? error.message : String(error ?? '')\n\n    if (otelLogger) {\n      otelLogger.emit({\n        severityNumber: SeverityNumber.ERROR,\n        body: `[iii] ${message}${errorMessage ? `: ${errorMessage}` : ''}`,\n      })\n    } else {\n      console.error(`[iii] ${message}`, error ?? '')\n    }\n  }\n\n  private onInvocationResult(invocation_id: string, result: unknown, error: unknown): void {\n    const invocation = this.invocations.get(invocation_id)\n\n    if (invocation) {\n      if (invocation.timeout) {\n        clearTimeout(invocation.timeout)\n      }\n      if (error) {\n        invocation.reject(this.toInvocationError(error, invocation.function_id))\n      } else {\n        invocation.resolve(result)\n      }\n    }\n\n    this.invocations.delete(invocation_id)\n  }\n\n  /**\n   * Wrap a wire-format `ErrorBody` in {@link IIIInvocationError} so callers get\n   * a real `Error` with a readable `.message` and a typed `.code`. Pass-through\n   * for values that are already `Error` subclasses. Everything else is wrapped\n   * under an `UNKNOWN` code so `String(err) !== '[object Object]'` holds for\n   * every rejection path.\n   */\n  private toInvocationError(error: unknown, function_id?: string): Error {\n    if (error instanceof Error) {\n      return error\n    }\n    if (isErrorBody(error)) {\n      return new IIIInvocationError({\n        code: error.code,\n        message: error.message,\n        function_id,\n        stacktrace: error.stacktrace,\n      })\n    }\n    // JSON.stringify(undefined) returns undefined (not \"undefined\"), which\n    // would set message to the literal string \"undefined\" after type coercion\n    // and leak an uninformative rejection. Fall back through String(error)\n    // so every path produces a concrete, readable string.\n    const message =\n      typeof error === 'string'\n        ? error\n        : (JSON.stringify(error) ?? String(error))\n    return new IIIInvocationError({\n      code: 'UNKNOWN',\n      message,\n      function_id,\n    })\n  }\n\n  private resolveChannelValue(value: unknown): unknown {\n    if (isChannelRef(value)) {\n      return value.direction === 'read'\n        ? new ChannelReader(this.address, value)\n        : new ChannelWriter(this.address, value)\n    }\n    if (Array.isArray(value)) {\n      return value.map((item) => this.resolveChannelValue(item))\n    }\n    if (value !== null && typeof value === 'object') {\n      const out: Record<string, unknown> = {}\n      for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n        out[k] = this.resolveChannelValue(v)\n      }\n      return out\n    }\n    return value\n  }\n\n  private async onInvokeFunction<TInput>(\n    invocation_id: string | undefined,\n    function_id: string,\n    input: TInput,\n    traceparent?: string,\n    baggage?: string,\n  ): Promise<unknown> {\n    const fn = this.functions.get(function_id)\n    const getResponseTraceparent = () => injectTraceparent() ?? traceparent\n    const getResponseBaggage = () => injectBaggage() ?? baggage\n\n    const resolvedInput = this.resolveChannelValue(input) as TInput\n\n    if (fn?.handler) {\n      if (!invocation_id) {\n        try {\n          await fn.handler(resolvedInput, traceparent, baggage)\n        } catch (error) {\n          this.logError(`Error invoking function ${function_id}`, error)\n        }\n        return\n      }\n\n      try {\n        const result = await fn.handler(resolvedInput, traceparent, baggage)\n        this.sendMessage(MessageType.InvocationResult, {\n          invocation_id,\n          function_id,\n          result,\n          traceparent: getResponseTraceparent(),\n          baggage: getResponseBaggage(),\n        })\n      } catch (error) {\n        const isError = error instanceof Error\n        this.sendMessage(MessageType.InvocationResult, {\n          invocation_id,\n          function_id,\n          error: {\n            code: 'invocation_failed',\n            message: isError ? error.message : String(error),\n            stacktrace: isError ? error.stack : undefined,\n          },\n          traceparent: getResponseTraceparent(),\n          baggage: getResponseBaggage(),\n        })\n      }\n    } else {\n      const errorCode = fn ? 'function_not_invokable' : 'function_not_found'\n      const errorMessage = fn ? 'Function is HTTP-invoked and cannot be invoked locally' : 'Function not found'\n      if (invocation_id) {\n        this.sendMessage(MessageType.InvocationResult, {\n          invocation_id,\n          function_id,\n          error: { code: errorCode, message: errorMessage },\n          traceparent,\n          baggage,\n        })\n      }\n    }\n  }\n\n  private async onRegisterTrigger(message: { trigger_type: string; id: string; function_id: string; config: unknown; metadata?: Record<string, unknown> }) {\n    const { trigger_type, id, function_id, config, metadata } = message\n    const triggerTypeData = this.triggerTypes.get(trigger_type)\n\n    if (triggerTypeData) {\n      try {\n        await triggerTypeData.handler.registerTrigger({ id, function_id, config, metadata })\n        this.sendMessage(MessageType.TriggerRegistrationResult, {\n          id,\n          message_type: MessageType.TriggerRegistrationResult,\n          type: trigger_type,\n          function_id,\n        })\n      } catch (error) {\n        this.sendMessage(MessageType.TriggerRegistrationResult, {\n          id,\n          message_type: MessageType.TriggerRegistrationResult,\n          type: trigger_type,\n          function_id,\n          error: { code: 'trigger_registration_failed', message: (error as Error).message },\n        })\n      }\n    } else {\n      this.sendMessage(MessageType.TriggerRegistrationResult, {\n        id,\n        message_type: MessageType.TriggerRegistrationResult,\n        type: trigger_type,\n        function_id,\n        error: { code: 'trigger_type_not_found', message: 'Trigger type not found' },\n      })\n    }\n  }\n\n  private onTriggerRegistrationResult(\n    message: { id: string; trigger_type?: string; type?: string; function_id: string; error?: { code: string; message: string; stacktrace?: string } },\n  ): void {\n    if (!message.error) return\n    const triggerType = message.trigger_type ?? message.type ?? ''\n    console.error(\n      `[iii] Trigger registration failed for \"${message.id}\" (${triggerType}): ${message.error.message}`,\n    )\n  }\n\n  private onMessage(socketMessage: Data): void {\n    let msgType: MessageType\n    let message: Record<string, unknown>\n\n    try {\n      const parsed = JSON.parse(socketMessage.toString()) as Record<string, unknown>\n      msgType = parsed.type as MessageType\n      const { type: _, ...rest } = parsed\n      message = rest\n    } catch (error) {\n      this.logError('Failed to parse incoming message', error)\n      return\n    }\n\n    if (msgType === MessageType.InvocationResult) {\n      const { invocation_id, result, error } = message as InvocationResultMessage\n      this.onInvocationResult(invocation_id, result, error)\n    } else if (msgType === MessageType.InvokeFunction) {\n      const { invocation_id, function_id, data, traceparent, baggage } = message as InvokeFunctionMessage\n      this.onInvokeFunction(invocation_id, function_id, data, traceparent, baggage)\n    } else if (msgType === MessageType.RegisterTrigger) {\n      this.onRegisterTrigger(message as { trigger_type: string; id: string; function_id: string; config: unknown; metadata?: Record<string, unknown> })\n    } else if (msgType === MessageType.TriggerRegistrationResult) {\n      this.onTriggerRegistrationResult(\n        message as { id: string; trigger_type?: string; type?: string; function_id: string; error?: { code: string; message: string; stacktrace?: string } },\n      )\n    } else if (msgType === MessageType.WorkerRegistered) {\n      const { worker_id } = message as WorkerRegisteredMessage\n      this.workerId = worker_id\n      console.debug('[iii] Worker registered with ID:', worker_id)\n      this.startMetricsReporting()\n    }\n  }\n}\n\n/**\n * Factory object that constructs routing actions for {@link ISdk.trigger}.\n *\n * @example\n * ```typescript\n * import { TriggerAction } from 'iii-sdk'\n *\n * // Enqueue to a named queue\n * iii.trigger({\n *   function_id: 'process',\n *   payload: { data: 'hello' },\n *   action: TriggerAction.Enqueue({ queue: 'jobs' }),\n * })\n *\n * // Fire-and-forget\n * iii.trigger({\n *   function_id: 'notify',\n *   payload: {},\n *   action: TriggerAction.Void(),\n * })\n * ```\n */\nexport const TriggerAction = {\n  /**\n   * Routes the invocation through a named queue. The engine enqueues the job,\n   * acknowledges the caller with `{ messageReceiptId }`, and processes it\n   * asynchronously.\n   *\n   * @param opts - Queue routing options.\n   * @param opts.queue - Name of the target queue.\n   */\n  Enqueue: (opts: { queue: string }): TriggerActionType => ({ type: 'enqueue', ...opts }),\n  /**\n   * Fire-and-forget routing. The engine forwards the invocation without\n   * waiting for a response or queuing the job.\n   */\n  Void: (): TriggerActionType => ({ type: 'void' }),\n} as const\n\n/**\n * Creates and returns a connected SDK instance. The WebSocket connection is\n * established automatically -- there is no separate `connect()` call.\n *\n * @param address - WebSocket URL of the III engine (e.g. `ws://localhost:49134`).\n * @param options - Optional {@link InitOptions} for worker name, timeouts, reconnection, and OTel.\n * @returns A connected {@link ISdk} instance.\n *\n * @example\n * ```typescript\n * import { registerWorker } from 'iii-sdk'\n *\n * const iii = registerWorker(process.env.III_URL ?? 'ws://localhost:49134', {\n *   workerName: 'my-worker',\n * })\n * ```\n */\nexport const registerWorker = (address: string, options?: InitOptions): ISdk => new Sdk(address, options)\n"],"mappings":"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"}