{"version":3,"sources":["../../src/tool-provider/types.ts","../../src/tool-provider/base.ts","../../src/tool-provider/runtime.ts","../../src/tool-provider/errors.ts"],"names":["MASTRA_RESOURCE_ID_KEY"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { StorageToolConfig } from '../storage/types';\nimport type { ToolAction } from '../tools/types';\n\n/**\n * Metadata about a tool provider.\n */\nexport interface ToolProviderInfo {\n  /** Unique identifier for this provider (e.g., 'composio') */\n  id: string;\n  /** Human-readable name */\n  name: string;\n  /** Short description of the provider */\n  description?: string;\n}\n\n/**\n * A toolkit (group of related tools) from a tool provider.\n *\n * Composio calls this a \"toolkit\"; the neutral term keeps additional\n * providers (e.g. Arcade) from having to adopt vendor vocabulary.\n */\nexport interface ToolProviderToolkit {\n  /** Unique slug for this toolkit (e.g., 'gmail', 'slack') */\n  slug: string;\n  /** Human-readable name */\n  name: string;\n  /** Description of the toolkit */\n  description?: string;\n  /** Icon URL or identifier */\n  icon?: string;\n}\n\n/**\n * A tool listing entry from a tool provider.\n * Used for UI discovery — does not include the full executable tool.\n */\nexport interface ToolProviderToolInfo {\n  /** Fully-qualified tool slug (e.g., 'gmail.fetch_emails') */\n  slug: string;\n  /** Human-readable name */\n  name: string;\n  /** Description of what this tool does */\n  description?: string;\n  /** Toolkit (tool service) this tool belongs to */\n  toolkit?: string;\n}\n\n/**\n * Options for listing tools from a provider.\n */\nexport interface ListToolProviderToolsOptions {\n  /** Filter by toolkit slug */\n  toolkit?: string;\n  /** Search query for filtering tools */\n  search?: string;\n  /** Pagination cursor or page (1-indexed) */\n  page?: number;\n  /** Number of tools per page */\n  perPage?: number;\n}\n\n/**\n * Paginated result from tool provider list operations.\n */\nexport interface ToolProviderListResult<T> {\n  data: T[];\n  pagination?: {\n    total?: number;\n    page?: number;\n    perPage?: number;\n    hasMore: boolean;\n  };\n}\n\n/**\n * Options for resolving executable tools at agent runtime.\n */\nexport interface ResolveToolProviderToolsOptions {\n  /** User ID for user-scoped tool execution (e.g., Composio) */\n  userId?: string;\n  /** Per-request context (e.g., user-specific API keys, tenant IDs) */\n  requestContext?: Record<string, unknown>;\n  /** Additional provider-specific options */\n  [key: string]: unknown;\n}\n\n// ── Capabilities ────────────────────────────────────────────────────────\n\n/**\n * Per-provider capability flags. Lets callers branch on optional features\n * without instanceof / subclass checks.\n */\nexport interface ToolProviderCapabilities {\n  /** Provider supports multiple connections (OAuth buckets) on the same toolkit. */\n  multipleConnectionsPerToolkit: boolean;\n  /** Provider can answer `getConnectionStatus` for many items in one call. */\n  batchConnectionStatus: boolean;\n  /** Re-authorizing a connection reuses the same `connectionId` (token refresh in place). */\n  reauthorizeReusesConnectionId: boolean;\n  /**\n   * Provider supports revoking a connection at the underlying service (true) vs.\n   * only unpinning it locally (false). UI hides the \"Disconnect\" affordance\n   * when this is falsy.\n   */\n  supportsRevoke?: boolean;\n}\n\n// ── Connections + scope ─────────────────────────────────────────────────\n\n/**\n * Identity bucketing for a pinned connection.\n *\n * - `'per-author'` (default) — bucketed under the caller's resolved authorId.\n * - `'shared'` — bucketed under {@link SHARED_BUCKET_ID}, visible to every caller.\n * - `'caller-supplied'` — bucketed under the host app's `resourceId` forwarded\n *   via request context. Used for multi-tenant SaaS deployments where the\n *   host app authenticates the end-user upstream. Falls back to a shared\n *   `'default'` bucket when the resource id is missing; multi-tenant\n *   deployments should wire the resource id explicitly (e.g. via\n *   `authConfig.mapUserToResourceId`) to avoid cross-tenant bucket sharing.\n */\nexport type ToolProviderConnectionScope = 'shared' | 'per-author' | 'caller-supplied';\n\n/**\n * Constant authorId used to bucket {@link ToolProviderConnection}s with\n * `scope: 'shared'`.\n */\nexport const SHARED_BUCKET_ID = 'shared';\n\n/**\n * A single OAuth bucket bound to one toolkit on one agent.\n */\nexport interface ToolProviderConnection {\n  /**\n   * Identity binding kind.\n   *\n   * - `'author'` — uses the agent author's connection (v1 default).\n   * - `'invoker'` — uses the end-user's connection (reserved).\n   * - `'platform'` — uses a shared platform account (reserved).\n   */\n  kind: 'author' | 'invoker' | 'platform';\n  /** Parent toolkit slug. Denormalized for callsite clarity. */\n  toolkit: string;\n  /**\n   * Provider-opaque identifier for the OAuth bucket.\n   *\n   * Required for `'author'` and `'platform'`; reserved (empty) for `'invoker'`.\n   */\n  connectionId: string;\n  /**\n   * Display label and LLM disambiguator. Optional when this is the only\n   * connection for a `toolkit`; required (non-empty, ≤ 32 chars,\n   * `[A-Za-z0-9 _-]+`, case-insensitively unique) once there are ≥ 2\n   * connections sharing the same `toolkit`.\n   */\n  label?: string;\n  /**\n   * Identity bucketing. Optional for back-compat with pre-scope pins;\n   * treated as `'per-author'` when missing.\n   */\n  scope?: ToolProviderConnectionScope;\n}\n\n/**\n * Per-tool override stored alongside the selected tool slug.\n */\nexport interface ToolProviderToolMeta {\n  /**\n   * Toolkit this slug belongs to. Required for the runtime to group\n   * selected tools by toolkit when fanning out across connections.\n   * Optional only for backward-compat with pre-fix stored data; new writes\n   * must include it.\n   */\n  toolkit?: string;\n  /** Optional description override surfaced to the LLM. */\n  description?: string;\n}\n\n/**\n * Stored shape for one provider's configuration on one agent.\n */\nexport interface ToolProviderConfig {\n  /** Selected tool slugs and their per-agent overrides. Key = tool slug. */\n  tools: Record<string, ToolProviderToolMeta>;\n  /** Connections grouped by toolkit slug. */\n  connections: Record<string, ToolProviderConnection[]>;\n}\n\n/**\n * The full tool-providers shape on an agent: keyed by provider id.\n */\nexport type ToolProviders = Record<string /* providerId */, ToolProviderConfig>;\n\n// ── List / auth / health surface ─────────────────────────────────────────\n\n/**\n * Options for `ToolProvider.listToolsVNext`. All fields are optional.\n */\nexport interface ListToolsOpts {\n  /** Restrict results to one toolkit slug. */\n  toolkit?: string;\n  /** Free-text search across tool slugs / names / descriptions. */\n  search?: string;\n  /** 1-indexed page number for paginated listings. */\n  page?: number;\n  /** Page size. Adapters may clamp to a sane upper bound. */\n  perPage?: number;\n}\n\n/**\n * Wrapped pagination envelope returned by `listToolsVNext`. `hasMore` is the\n * only forward-progress signal — adapters are not required to surface a\n * total count.\n */\nexport interface ListToolsResult {\n  data: ToolProviderToolInfo[];\n  pagination: {\n    page: number;\n    perPage?: number;\n    hasMore: boolean;\n  };\n}\n\n/** Wrapped result returned by `listToolkitsVNext`. */\nexport interface ListToolkitsResult {\n  data: ToolProviderToolkit[];\n}\n\n/**\n * Options for `ToolProvider.resolveToolsVNext`.\n *\n * The runtime fan-out calls this **once per connection** — providers never\n * see fan-out logic or tool-name suffixes.\n */\nexport interface ResolveToolsOpts {\n  /** Original tool slugs to materialise. */\n  toolSlugs: string[];\n  /** Per-tool overrides (description, etc.) keyed by tool slug. */\n  toolMeta: Record<string, ToolProviderToolMeta>;\n  /** Provider-opaque OAuth bucket identifier. */\n  connectionId: string;\n  /**\n   * For `kind: 'author'` connections, the agent author's user id. The runtime\n   * uses this as the provider's user bucket so the pin works for any\n   * invoker, not just the author. Falsy = fall back to request context.\n   */\n  authorId?: string;\n  /** Per-request context (auth, tenant, currentUser, ...). */\n  requestContext?: Record<string, unknown>;\n}\n\n/**\n * Options for `ToolProvider.authorize`.\n */\nexport interface AuthorizeOpts {\n  /** Toolkit slug being authorized. */\n  toolkit: string;\n  /**\n   * Existing or newly-minted connection bucket id.\n   *\n   * Providers with `reauthorizeReusesConnectionId: true` refresh the token\n   * in place when a known id is supplied.\n   */\n  connectionId: string;\n  /** Optional tool slug — some providers scope authorize per tool. */\n  toolName?: string;\n  /**\n   * Provider-specific custom fields collected from the user before the\n   * OAuth flow starts (e.g. Confluence `{ subdomain: 'mycorp' }`).\n   */\n  config?: Record<string, unknown>;\n}\n\n/**\n * A single user-supplied field required to open a new connection on a\n * toolkit. Surfaced by {@link ToolProvider.listConnectionFields} and\n * rendered inline in the connection picker.\n */\nexport interface ConnectionField {\n  /** Programmatic name (e.g. `'subdomain'`). Sent back as a key in `AuthorizeOpts.config`. */\n  name: string;\n  /** Human-readable label (e.g. `'Your Subdomain'`). */\n  displayName: string;\n  /** Optional helper text rendered under the input. */\n  description?: string;\n  /** Storage / input type. Adapters coerce richer types into one of these. */\n  type: 'string' | 'number' | 'boolean';\n  /** Whether the user must provide a value before authorize can run. */\n  required: boolean;\n  /** Provider-suggested default (rendered as the input's initial value). */\n  default?: string | null;\n}\n\n/**\n * Health summary returned by `ToolProvider.getHealth`.\n */\nexport interface ToolProviderHealth {\n  ok: boolean;\n  /** Short, user-facing message. */\n  message?: string;\n  /** Free-form per-provider diagnostics. */\n  details?: Record<string, unknown>;\n}\n\n/**\n * Async OAuth flow status as observed by `getAuthStatus`.\n */\nexport type AuthFlowStatus = 'pending' | 'completed' | 'failed';\n\n/**\n * Options for `ToolProvider.listConnections`.\n *\n * Use `userIds[]` to list across multiple buckets in one call (admin\n * cross-author listing). `userId` is the single-bucket convenience and is\n * normalized to `[userId]` internally.\n */\nexport interface ListConnectionsOpts {\n  /** Toolkit slug. */\n  toolkit: string;\n  /** Multi-bucket lookup. Preferred when present. */\n  userIds?: string[];\n  /** Single-bucket convenience. */\n  userId?: string;\n  /** 1-indexed page number for paginated listings. */\n  page?: number;\n  /** Page size. Adapters clamp to a sane upper bound (default 50, max 200). */\n  perPage?: number;\n}\n\n/** One existing connection on the underlying provider. */\nexport interface ExistingConnection {\n  /** Provider-issued connection identifier (e.g. Composio `ca_xxx`). */\n  connectionId: string;\n  /** Connection state: `'active'` is safe to pin. */\n  status: 'active' | 'inactive' | 'failed' | 'pending';\n  /** When the connection was created, if the provider reports it. */\n  createdAt?: string;\n  /**\n   * Bucket owner this connection belongs to. Mirrors the `userId` /\n   * `authorId` the connection was created under. Surfaced for admin\n   * cross-author UI.\n   */\n  authorId?: string;\n}\n\nexport interface ListConnectionsResult {\n  items: ExistingConnection[];\n  /** Pagination envelope. Adapters are not required to surface a total count. */\n  pagination: {\n    page: number;\n    perPage?: number;\n    hasMore: boolean;\n    total?: number;\n  };\n}\n\n/**\n * Interface for tool providers (e.g., Composio) that supply tools to agents.\n *\n * Tool providers serve two purposes:\n * 1. **Discovery** — UI uses `listToolkits()` / `listToolkitsVNext()` / `listTools()` / `listToolsVNext()` to browse available tools\n * 2. **Runtime** — Agent hydration uses `resolveTools()` / `resolveToolsVNext()` to get executable tools for selected tool slugs\n *\n * The VNext surface (`listToolkitsVNext` / `listToolsVNext` / `resolveToolsVNext` and the\n * auth/health methods below) is opt-in: providers can keep using the legacy\n * `listTools()` / `resolveTools()` pair for static, code-config use cases.\n */\nexport interface ToolProvider {\n  /** Provider metadata */\n  readonly info: ToolProviderInfo;\n\n  /**\n   * Optional human-readable display name surfaced in the picker. Falls back\n   * to `info.name` when absent.\n   */\n  readonly displayName?: string;\n\n  /**\n   * Static capability flags. Required when the v2 surface is implemented;\n   * legacy providers may omit it.\n   */\n  readonly capabilities?: ToolProviderCapabilities;\n\n  // ── Legacy surface (kept for back-compat) ─────────────────────────────\n\n  /**\n   * List available toolkits from this provider.\n   * Used by UI for browsing.\n   */\n  listToolkits?(): Promise<ToolProviderListResult<ToolProviderToolkit>>;\n\n  /**\n   * List available tools, optionally filtered by toolkit or search query.\n   * Used by UI for browsing/selecting tools.\n   */\n  listTools(options?: ListToolProviderToolsOptions): Promise<ToolProviderListResult<ToolProviderToolInfo>>;\n\n  /**\n   * Get the JSON schema for a specific tool's input.\n   * Used by UI to display tool details.\n   */\n  getToolSchema?(toolSlug: string): Promise<Record<string, unknown> | null>;\n\n  /**\n   * Resolve executable tools for the given slugs (legacy signature).\n   * Called during agent hydration to resolve `integrationTools` references.\n   */\n  resolveTools(\n    toolSlugs: string[],\n    toolConfigs?: Record<string, StorageToolConfig>,\n    options?: ResolveToolProviderToolsOptions,\n  ): Promise<Record<string, ToolAction<any, any, any>>>;\n\n  // ── VNext surface (opt-in, used by Agent Builder + editor UI) ────────\n\n  /** List allowed toolkits, wrapped in a result envelope. */\n  listToolkitsVNext?(): Promise<ListToolkitsResult>;\n\n  /**\n   * List allowed tools (wrapped envelope). With no options, lists across\n   * every toolkit. Pass `toolkit` to scope; pass `search` to filter; pass\n   * `page` / `perPage` to paginate.\n   */\n  listToolsVNext?(opts?: ListToolsOpts): Promise<ListToolsResult>;\n\n  /**\n   * Materialise executable Mastra tools for one (toolSlugs × connection)\n   * call. Runtime fan-out invokes this once per connection and applies\n   * naming/suffix logic on top.\n   */\n  resolveToolsVNext?(opts: ResolveToolsOpts): Promise<Record<string, ToolAction<any, any, any>>>;\n\n  /** Start an OAuth flow; returns the redirect URL and an opaque auth handle. */\n  authorize?(opts: AuthorizeOpts): Promise<{ url: string; authId: string }>;\n\n  /**\n   * List provider-specific custom fields the user must supply when starting\n   * a fresh OAuth flow for `toolkit` (e.g. Confluence subdomain).\n   *\n   * Returning `[]` means the provider can authorize without extra input.\n   * The picker UI shows an inline form when this is non-empty.\n   */\n  listConnectionFields?(opts: { toolkit: string }): Promise<ConnectionField[]>;\n\n  /** Poll the OAuth flow status by `authId`. */\n  getAuthStatus?(authId: string): Promise<AuthFlowStatus>;\n\n  /**\n   * Batch-check whether a set of `(connectionId, toolkit)` tuples are still\n   * connected (lazy revocation detection). Result keyed by `connectionId`.\n   */\n  getConnectionStatus?(opts: {\n    items: Array<{ connectionId: string; toolkit: string }>;\n  }): Promise<Record<string, { connected: boolean }>>;\n\n  /**\n   * List the underlying provider's existing connections for a given user +\n   * toolkit. Used by the picker UI to surface already-authorized accounts\n   * so authors can pin them onto an agent without re-running OAuth.\n   */\n  listConnections?(opts: ListConnectionsOpts): Promise<ListConnectionsResult>;\n\n  /** Provider-level health (config, reachability, etc.). */\n  getHealth?(): Promise<ToolProviderHealth>;\n\n  /**\n   * Revoke an existing connection at the provider. Only meaningful when\n   * `capabilities.supportsRevoke` is true. Implementations should treat a\n   * missing connection (already revoked / never existed) as a success.\n   */\n  revokeConnection?(connectionId: string): Promise<void>;\n}\n","import type { StorageToolConfig } from '../storage/types';\nimport type { ToolAction } from '../tools/types';\nimport type {\n  AuthFlowStatus,\n  AuthorizeOpts,\n  ConnectionField,\n  ListConnectionsOpts,\n  ListConnectionsResult,\n  ListToolkitsResult,\n  ListToolsOpts,\n  ListToolsResult,\n  ResolveToolsOpts,\n  ToolProvider,\n  ToolProviderCapabilities,\n  ToolProviderHealth,\n  ToolProviderInfo,\n  ToolProviderListResult,\n  ToolProviderToolInfo,\n  ToolProviderToolkit,\n} from './types';\n\n/**\n * Constructor options shared by every {@link BaseToolProvider} subclass.\n *\n * Allowlists are matched against the **provider-opaque slugs** returned by\n * `listAllToolkits()` / `listAllTools()`. Two forms are supported:\n *\n * - exact slug match: `'gmail'`\n * - suffix wildcard:  `'gmail.*'`\n *\n * `allowedTools` is keyed by toolkit slug. If a toolkit is listed in\n * `allowedToolkits` but **not** present in `allowedTools`, all of its\n * tools are included. An explicit empty array (`allowedTools: { gmail: [] }`)\n * filters everything out for that toolkit.\n */\nexport interface BaseToolProviderOptions {\n  /** When set, `listToolkitsVNext()` keeps only toolkits whose slug matches. */\n  allowedToolkits?: readonly string[];\n  /**\n   * Per-toolkit tool allowlist. Keys are toolkit slugs; values are patterns\n   * matched against tool slugs (exact or `prefix*`). Omitting a toolkit\n   * leaves its tools unfiltered.\n   */\n  allowedTools?: Readonly<Record<string, readonly string[]>>;\n}\n\n/**\n * Shared base class for concrete {@link ToolProvider} implementations.\n *\n * Subclasses implement the SDK-specific `listAllToolkits` and\n * `listAllTools` methods (and the runtime / auth methods); the base class\n * layers admin allowlist filtering on top so every adapter behaves the\n * same way.\n */\nexport abstract class BaseToolProvider implements ToolProvider {\n  abstract readonly info: ToolProviderInfo;\n  abstract readonly capabilities: ToolProviderCapabilities;\n\n  protected readonly allowedToolkits: readonly string[];\n  protected readonly allowedTools: Readonly<Record<string, readonly string[]>>;\n\n  constructor(options: BaseToolProviderOptions = {}) {\n    this.allowedToolkits = options.allowedToolkits ?? [];\n    this.allowedTools = options.allowedTools ?? {};\n  }\n\n  // ── VNext catalog (filtered) ──────────────────────────────────────────\n\n  async listToolkitsVNext(): Promise<ListToolkitsResult> {\n    const all = await this.listAllToolkits();\n    const data =\n      this.allowedToolkits.length === 0 ? all : all.filter(toolkit => matchesAny(toolkit.slug, this.allowedToolkits));\n    return { data };\n  }\n\n  async listToolsVNext(opts: ListToolsOpts = {}): Promise<ListToolsResult> {\n    // Deny toolkits not in the allowlist before touching the SDK.\n    if (\n      opts.toolkit !== undefined &&\n      this.allowedToolkits.length > 0 &&\n      !matchesAny(opts.toolkit, this.allowedToolkits)\n    ) {\n      return {\n        data: [],\n        pagination: { page: opts.page ?? 1, perPage: opts.perPage, hasMore: false },\n      };\n    }\n    const result = await this.listAllTools(opts);\n    if (Object.keys(this.allowedTools).length === 0) return result;\n    return {\n      ...result,\n      data: result.data.filter(tool => {\n        const toolkit = tool.toolkit;\n        if (!toolkit) return true;\n        const patterns = this.allowedTools[toolkit];\n        if (patterns === undefined) return true;\n        return matchesAny(tool.slug, patterns);\n      }),\n    };\n  }\n\n  // ── legacy surface (default forwards to VNext) ───────────────────────\n\n  async listToolkits(): Promise<ToolProviderListResult<ToolProviderToolkit>> {\n    const result = await this.listToolkitsVNext();\n    return { data: result.data };\n  }\n\n  async listTools(options: ListToolsOpts = {}): Promise<ToolProviderListResult<ToolProviderToolInfo>> {\n    const result = await this.listToolsVNext(options);\n    return { data: result.data, pagination: result.pagination };\n  }\n\n  /**\n   * Legacy `resolveTools` shim — subclasses that opt into the VNext surface\n   * normally implement `resolveToolsVNext` instead; the legacy signature\n   * delegates so existing callers keep working.\n   */\n  async resolveTools(\n    toolSlugs: string[],\n    toolConfigs?: Record<string, StorageToolConfig>,\n    options?: { userId?: string; requestContext?: Record<string, unknown>; [key: string]: unknown },\n  ): Promise<Record<string, ToolAction<any, any, any>>> {\n    return this.resolveToolsVNext({\n      toolSlugs,\n      toolMeta: Object.fromEntries(\n        Object.entries(toolConfigs ?? {}).map(([slug, cfg]) => [slug, { description: cfg?.description }]),\n      ),\n      connectionId: '',\n      authorId: options?.userId,\n      requestContext: options?.requestContext,\n    });\n  }\n\n  // ── SDK hooks subclasses implement ────────────────────────────────────\n\n  protected abstract listAllToolkits(): Promise<ToolProviderToolkit[]>;\n  protected abstract listAllTools(opts: ListToolsOpts): Promise<ListToolsResult>;\n\n  abstract resolveToolsVNext(opts: ResolveToolsOpts): Promise<Record<string, ToolAction<any, any, any>>>;\n\n  abstract authorize(opts: AuthorizeOpts): Promise<{ url: string; authId: string }>;\n  abstract getAuthStatus(authId: string): Promise<AuthFlowStatus>;\n  abstract getConnectionStatus(opts: {\n    items: Array<{ connectionId: string; toolkit: string }>;\n  }): Promise<Record<string, { connected: boolean }>>;\n  abstract listConnections(opts: ListConnectionsOpts): Promise<ListConnectionsResult>;\n\n  /**\n   * Default connection-fields implementation — returns `[]`. Subclasses\n   * whose underlying provider requires user-supplied custom fields at\n   * authorize time (e.g. Confluence subdomain) should override.\n   */\n  async listConnectionFields(_opts: { toolkit: string }): Promise<ConnectionField[]> {\n    return [];\n  }\n\n  /**\n   * Default health implementation — returns `{ ok: true }`. Subclasses that\n   * need to probe SDK reachability or configuration should override.\n   */\n  async getHealth(): Promise<ToolProviderHealth> {\n    return { ok: true };\n  }\n}\n\n/**\n * Matches `slug` against an allowlist entry. Supports exact match and a\n * `prefix*` suffix wildcard.\n */\nfunction matchesAny(slug: string, patterns: readonly string[]): boolean {\n  for (const pattern of patterns) {\n    if (pattern === slug) return true;\n    if (pattern.endsWith('*')) {\n      const prefix = pattern.slice(0, -1);\n      if (slug.startsWith(prefix)) return true;\n    }\n  }\n  return false;\n}\n","import type { IMastraLogger } from '../logger';\nimport { MASTRA_RESOURCE_ID_KEY } from '../request-context';\nimport type { ToolAction } from '../tools/types';\nimport type { ToolProvider, ToolProviderConnection, ToolProviders } from './types';\nimport { SHARED_BUCKET_ID } from './types';\n\n/**\n * Lookup function the runtime uses to resolve a registered provider by id.\n */\nexport type ToolProviderLookup = (providerId: string) => ToolProvider;\n\nexport interface ResolveStoredToolProvidersOpts {\n  /** Per-request context plumbed to each `provider.resolveToolsVNext` call. */\n  requestContext?: Record<string, unknown>;\n  /**\n   * Agent author's user id. Used as the provider user bucket for\n   * `kind: 'author'` connections so pinned credentials work for any invoker.\n   */\n  authorId?: string;\n  /** Optional logger for non-fatal per-connection warnings. */\n  logger?: IMastraLogger;\n}\n\n/**\n * Sanitize a connection label into the suffix segment appended to a tool slug\n * (`__<SUFFIX>`).\n *\n * Rules:\n * - Uppercase.\n * - Non-`[A-Z0-9_]` characters become `_`.\n * - On collision with `usedSuffixes`, append `_2`, `_3`, ... until unique.\n * - The returned suffix is added to `usedSuffixes` in place.\n */\nexport function buildConnectionSuffix(label: string | undefined, usedSuffixes: Set<string>): string {\n  // Single linear pass over the input — no regex with quantifiers on\n  // user-controlled data (CodeQL js/polynomial-redos).\n  const raw = (label ?? '').toUpperCase();\n  let base = '';\n  let prevWasUnderscore = true; // start true → skips leading underscores\n  for (let i = 0; i < raw.length; i++) {\n    const c = raw.charCodeAt(i);\n    const isAllowed =\n      (c >= 0x41 && c <= 0x5a) || // A-Z\n      (c >= 0x30 && c <= 0x39); // 0-9\n    if (isAllowed) {\n      base += raw[i];\n      prevWasUnderscore = false;\n    } else if (!prevWasUnderscore) {\n      base += '_';\n      prevWasUnderscore = true;\n    }\n  }\n  if (base.endsWith('_')) base = base.slice(0, -1);\n  if (!base) base = 'CONN';\n\n  let candidate = base;\n  let n = 2;\n  while (usedSuffixes.has(candidate)) {\n    candidate = `${base}_${n}`;\n    n += 1;\n  }\n  usedSuffixes.add(candidate);\n  return candidate;\n}\n\n/**\n * Provider-agnostic runtime fan-out.\n *\n * For every stored `toolProviders[providerId].connections[toolkit]`\n * entry, calls `provider.resolveToolsVNext` once per connection, then renames\n * the resulting tools with a `__<LABEL>` suffix when more than one\n * connection is bound to the same toolkit. Single-connection toolkits keep\n * the natural slug.\n *\n * Each renamed tool also gets a routing hint appended to its description so\n * the LLM can disambiguate between connections.\n *\n * Errors from one connection do **not** poison sibling connections — they are\n * logged and skipped.\n */\nexport async function resolveStoredToolProviders(\n  toolProviders: ToolProviders | undefined,\n  lookup: ToolProviderLookup,\n  opts: ResolveStoredToolProvidersOpts = {},\n): Promise<Record<string, ToolAction<any, any, any>>> {\n  const { requestContext, authorId, logger } = opts;\n  const out: Record<string, ToolAction<any, any, any>> = {};\n  logger?.debug(`[resolveStoredToolProviders] called`, {\n    providerIds: Object.keys(toolProviders ?? {}),\n    authorId,\n  });\n  if (!toolProviders || Object.keys(toolProviders).length === 0) {\n    logger?.debug(`[resolveStoredToolProviders] no toolProviders on agent — returning {}`);\n    return out;\n  }\n\n  for (const [providerId, cfg] of Object.entries(toolProviders)) {\n    let provider: ToolProvider;\n    try {\n      provider = lookup(providerId);\n    } catch (error) {\n      logger?.warn(`[resolveStoredToolProviders] Unknown provider \"${providerId}\"`, { error });\n      continue;\n    }\n\n    if (!provider.resolveToolsVNext) {\n      logger?.warn(`[resolveStoredToolProviders] Provider \"${providerId}\" does not implement resolveToolsVNext`);\n      continue;\n    }\n\n    const tools = cfg.tools ?? {};\n    const connectionsByToolkit = cfg.connections ?? {};\n\n    for (const [toolkit, connections] of Object.entries(connectionsByToolkit)) {\n      if (!connections || connections.length === 0) {\n        logger?.debug(\n          `[resolveStoredToolProviders] toolkit \"${toolkit}\" on provider \"${providerId}\" has no pinned connections — skipping`,\n        );\n        continue;\n      }\n\n      if (connections.length > 1 && !provider.capabilities?.multipleConnectionsPerToolkit) {\n        logger?.warn(\n          `[resolveStoredToolProviders] provider \"${providerId}\" does not support multiple ` +\n            `connections per toolkit but received ${connections.length} for \"${toolkit}\" — skipping`,\n        );\n        continue;\n      }\n\n      // Group selected slugs by ToolProviderToolMeta.toolkit. Falls back to a\n      // slug-prefix match (`<toolkit>.<tool>`) for providers that follow the\n      // dot convention but didn't write toolkit on the meta entry.\n      const slugsForToolkit = Object.entries(tools)\n        .filter(([slug, meta]) => (meta?.toolkit ? meta.toolkit === toolkit : slug.startsWith(`${toolkit}.`)))\n        .map(([slug]) => slug);\n      if (slugsForToolkit.length === 0) {\n        logger?.debug(\n          `[resolveStoredToolProviders] toolkit \"${toolkit}\" on provider \"${providerId}\" has connections but no matching tool slugs — skipping`,\n          { availableSlugs: Object.keys(tools) },\n        );\n        continue;\n      }\n      logger?.debug(`[resolveStoredToolProviders] resolving tools for ${providerId}/${toolkit}`, {\n        slugs: slugsForToolkit,\n        connectionCount: connections.length,\n      });\n\n      const skipSuffix = connections.length === 1;\n      const usedSuffixes = new Set<string>();\n\n      for (const connection of connections) {\n        const suffix = skipSuffix ? '' : `__${buildConnectionSuffix(connection.label, usedSuffixes)}`;\n\n        const resolvedAuthorId = resolveConnectionAuthorId(connection, authorId, requestContext, logger);\n\n        let resolved: Record<string, ToolAction<any, any, any>>;\n        try {\n          resolved = await provider.resolveToolsVNext({\n            toolSlugs: slugsForToolkit,\n            toolMeta: cfg.tools ?? {},\n            connectionId: connection.connectionId,\n            authorId: resolvedAuthorId,\n            requestContext,\n          });\n        } catch (error) {\n          logger?.warn(\n            `[resolveStoredToolProviders] Failed to resolve tools for ${providerId}/${toolkit} ` +\n              `connection ${connection.connectionId}`,\n            { error },\n          );\n          continue;\n        }\n\n        for (const [slug, tool] of Object.entries(resolved)) {\n          const renamedSlug = `${slug}${suffix}`;\n          const baseDescription = tool.description ?? '';\n          const description = skipSuffix ? baseDescription : appendRoutingHint(baseDescription, connection);\n\n          out[renamedSlug] = {\n            ...tool,\n            id: renamedSlug,\n            description,\n          } as ToolAction<any, any, any>;\n        }\n      }\n    }\n  }\n\n  return out;\n}\n\n// Emit a single warn per process when the connection-owner fallback fires.\n// Multi-tenant deployments that forget to wire `mapUserToResourceId` silently\n// funnel every `caller-supplied` pin into one shared OAuth account — surface\n// that misconfiguration once.\nlet defaultBucketWarned = false;\nfunction warnDefaultBucketFallback(logger: IMastraLogger | undefined): void {\n  if (defaultBucketWarned) return;\n  defaultBucketWarned = true;\n  logger?.warn(\n    '[resolveStoredToolProviders] caller-supplied scope falling back to shared \"default\" bucket — ' +\n      'wire authConfig.mapUserToResourceId to avoid cross-tenant OAuth sharing',\n  );\n}\n\n/**\n * Resolve the provider user bucket for a pinned connection.\n *\n * - `kind !== 'author'` → undefined (invoker/platform are reserved for later phases).\n * - `scope === 'shared'` → {@link SHARED_BUCKET_ID}.\n * - `scope === 'caller-supplied'` → `requestContext[MASTRA_RESOURCE_ID_KEY]` when\n *   present, otherwise falls back to the shared `'default'` bucket (matching legacy\n *   `ComposioToolProvider` semantics on main). Multi-tenant deployments should wire\n *   `authConfig.mapUserToResourceId` to avoid cross-user bucket sharing.\n * - otherwise → the caller's resolved authorId.\n */\nfunction resolveConnectionAuthorId(\n  connection: ToolProviderConnection,\n  callerAuthorId: string | undefined,\n  requestContext: Record<string, unknown> | undefined,\n  logger: IMastraLogger | undefined,\n): string | undefined {\n  if (connection.kind !== 'author') return undefined;\n  if (connection.scope === 'shared') return SHARED_BUCKET_ID;\n  if (connection.scope === 'caller-supplied') {\n    const resourceId = requestContext?.[MASTRA_RESOURCE_ID_KEY];\n    if (typeof resourceId === 'string' && resourceId.length > 0) return resourceId;\n    // Match legacy ComposioToolProvider behavior: when the host app has not\n    // wired requestContext[MASTRA_RESOURCE_ID_KEY] (e.g. via\n    // authConfig.mapUserToResourceId), fall back to a shared 'default' bucket\n    // so tools still resolve. Multi-tenant deployments must wire the resource\n    // id explicitly to avoid cross-user bucket sharing.\n    warnDefaultBucketFallback(logger);\n    return 'default';\n  }\n  return callerAuthorId;\n}\n\nfunction appendRoutingHint(description: string, connection: ToolProviderConnection): string {\n  const hint = `Routes through connection: ${connection.label ?? connection.connectionId}`;\n  if (!description) return hint;\n  return `${description}\\n\\n${hint}`;\n}\n","/**\n * Thrown when two {@link ToolProvider} entries share the same `id` during\n * editor / Mastra construction.\n */\nexport class DuplicateToolProviderError extends Error {\n  readonly ids: readonly string[];\n\n  constructor(ids: readonly string[]) {\n    super(`Duplicate tool provider ids: ${ids.join(', ')}`);\n    this.name = 'DuplicateToolProviderError';\n    this.ids = ids;\n  }\n}\n\n/**\n * Thrown when no registered tool provider matches the requested id.\n */\nexport class UnknownToolProviderError extends Error {\n  readonly id: string;\n  readonly knownIds: readonly string[];\n\n  constructor(id: string, knownIds: readonly string[]) {\n    super(`Unknown tool provider \"${id}\". Known ids: ${knownIds.length ? knownIds.join(', ') : '(none)'}`);\n    this.name = 'UnknownToolProviderError';\n    this.id = id;\n    this.knownIds = knownIds;\n  }\n}\n"]}