{"version":3,"file":"index.cjs","names":["MASTRA_RESOURCE_ID_KEY"],"sources":["../../src/tool-provider/types.ts","../../src/tool-provider/base.ts","../../src/tool-provider/runtime.ts","../../src/tool-provider/errors.ts"],"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  /**\n   * Identity bucketing for this connection. Providers may use it to decide\n   * whether to pin a specific account or let the backend auto-resolve within\n   * the user bucket. Absent = treat as `'per-author'` (back-compat).\n   */\n  scope?: ToolProviderConnectionScope;\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  /**\n   * Default identity-bucketing scope for connections authorized against this\n   * provider. Set by the app author at construction time — this is a tenancy\n   * architecture decision, not an end-user choice. The authorize flow uses it\n   * when the request does not specify a `scope`, so a provider configured with\n   * `defaultScope: 'caller-supplied'` produces per-tenant connections without\n   * any UI control. Falls back to `'per-author'` when absent.\n   */\n  readonly defaultScope?: ToolProviderConnectionScope;\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  ToolProviderConnectionScope,\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   * Default identity-bucketing scope for connections authorized against this\n   * provider. This is the app author's tenancy decision (e.g.\n   * `'caller-supplied'` for per-tenant OAuth). The authorize flow applies it\n   * whenever a request doesn't override `scope`. Defaults to `'per-author'`.\n   */\n  defaultScope?: ToolProviderConnectionScope;\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  readonly defaultScope?: ToolProviderConnectionScope;\n\n  constructor(options: BaseToolProviderOptions = {}) {\n    this.allowedToolkits = options.allowedToolkits ?? [];\n    this.allowedTools = options.allowedTools ?? {};\n    this.defaultScope = options.defaultScope;\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. A provider\n * whose default scope is `caller-supplied` is also called once for each\n * selected toolkit without a pinned connection, using the request resource id\n * as its dynamic connection bucket. This lets connection-management and other\n * connectionless tools bootstrap a caller's first OAuth connection.\n *\n * Tools resolved through multiple pinned connections are renamed with a\n * `__<LABEL>` suffix. Single-connection and unpinned caller-supplied toolkits\n * keep 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    // `caller-supplied` providers resolve within the current request's user\n    // bucket, so they do not need a persisted account pin to materialise a\n    // selected toolkit. This is required for bootstrap tools such as\n    // COMPOSIO_MANAGE_CONNECTIONS, whose own toolkit intentionally has no\n    // OAuth connection.\n    if (provider.defaultScope === 'caller-supplied') {\n      const unpinnedSlugsByToolkit = new Map<string, string[]>();\n      for (const [slug, meta] of Object.entries(tools)) {\n        const separatorIndex = slug.indexOf('.');\n        const toolkit = meta?.toolkit ?? (separatorIndex > 0 ? slug.slice(0, separatorIndex) : undefined);\n        if (!toolkit || connectionsByToolkit[toolkit]?.length) continue;\n        const slugs = unpinnedSlugsByToolkit.get(toolkit) ?? [];\n        slugs.push(slug);\n        unpinnedSlugsByToolkit.set(toolkit, slugs);\n      }\n\n      if (unpinnedSlugsByToolkit.size > 0) {\n        const resolvedAuthorId = resolveCallerSuppliedAuthorId(requestContext, logger);\n        for (const [toolkit, toolSlugs] of unpinnedSlugsByToolkit) {\n          logger?.debug(\n            `[resolveStoredToolProviders] resolving unpinned caller-supplied tools for ${providerId}/${toolkit}`,\n            { slugs: toolSlugs },\n          );\n\n          try {\n            const resolved = await provider.resolveToolsVNext({\n              toolSlugs,\n              toolMeta: tools,\n              connectionId: resolvedAuthorId,\n              authorId: resolvedAuthorId,\n              scope: 'caller-supplied',\n              requestContext,\n            });\n\n            for (const [slug, tool] of Object.entries(resolved)) {\n              out[slug] = { ...tool, id: slug } as ToolAction<any, any, any>;\n            }\n          } catch (error) {\n            logger?.warn(\n              `[resolveStoredToolProviders] Failed to resolve unpinned caller-supplied tools for ${providerId}/${toolkit}`,\n              { error },\n            );\n          }\n        }\n      }\n    }\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            scope: connection.scope,\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    return resolveCallerSuppliedAuthorId(requestContext, logger);\n  }\n  return callerAuthorId;\n}\n\nfunction resolveCallerSuppliedAuthorId(\n  requestContext: Record<string, unknown> | undefined,\n  logger: IMastraLogger | undefined,\n): string {\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\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"],"mappings":"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"}