UNPKG

@mastra/core

Version:
255 lines (249 loc) 9.49 kB
import { MASTRA_RESOURCE_ID_KEY } from '../chunk-W4DLMY73.js'; // src/tool-provider/types.ts var SHARED_BUCKET_ID = "shared"; // src/tool-provider/base.ts var BaseToolProvider = class { allowedToolkits; allowedTools; constructor(options = {}) { this.allowedToolkits = options.allowedToolkits ?? []; this.allowedTools = options.allowedTools ?? {}; } // ── VNext catalog (filtered) ────────────────────────────────────────── async listToolkitsVNext() { const all = await this.listAllToolkits(); const data = this.allowedToolkits.length === 0 ? all : all.filter((toolkit) => matchesAny(toolkit.slug, this.allowedToolkits)); return { data }; } async listToolsVNext(opts = {}) { if (opts.toolkit !== void 0 && this.allowedToolkits.length > 0 && !matchesAny(opts.toolkit, this.allowedToolkits)) { return { data: [], pagination: { page: opts.page ?? 1, perPage: opts.perPage, hasMore: false } }; } const result = await this.listAllTools(opts); if (Object.keys(this.allowedTools).length === 0) return result; return { ...result, data: result.data.filter((tool) => { const toolkit = tool.toolkit; if (!toolkit) return true; const patterns = this.allowedTools[toolkit]; if (patterns === void 0) return true; return matchesAny(tool.slug, patterns); }) }; } // ── legacy surface (default forwards to VNext) ─────────────────────── async listToolkits() { const result = await this.listToolkitsVNext(); return { data: result.data }; } async listTools(options = {}) { const result = await this.listToolsVNext(options); return { data: result.data, pagination: result.pagination }; } /** * Legacy `resolveTools` shim — subclasses that opt into the VNext surface * normally implement `resolveToolsVNext` instead; the legacy signature * delegates so existing callers keep working. */ async resolveTools(toolSlugs, toolConfigs, options) { return this.resolveToolsVNext({ toolSlugs, toolMeta: Object.fromEntries( Object.entries(toolConfigs ?? {}).map(([slug, cfg]) => [slug, { description: cfg?.description }]) ), connectionId: "", authorId: options?.userId, requestContext: options?.requestContext }); } /** * Default connection-fields implementation — returns `[]`. Subclasses * whose underlying provider requires user-supplied custom fields at * authorize time (e.g. Confluence subdomain) should override. */ async listConnectionFields(_opts) { return []; } /** * Default health implementation — returns `{ ok: true }`. Subclasses that * need to probe SDK reachability or configuration should override. */ async getHealth() { return { ok: true }; } }; function matchesAny(slug, patterns) { for (const pattern of patterns) { if (pattern === slug) return true; if (pattern.endsWith("*")) { const prefix = pattern.slice(0, -1); if (slug.startsWith(prefix)) return true; } } return false; } // src/tool-provider/runtime.ts function buildConnectionSuffix(label, usedSuffixes) { const raw = (label ?? "").toUpperCase(); let base = ""; let prevWasUnderscore = true; for (let i = 0; i < raw.length; i++) { const c = raw.charCodeAt(i); const isAllowed = c >= 65 && c <= 90 || // A-Z c >= 48 && c <= 57; if (isAllowed) { base += raw[i]; prevWasUnderscore = false; } else if (!prevWasUnderscore) { base += "_"; prevWasUnderscore = true; } } if (base.endsWith("_")) base = base.slice(0, -1); if (!base) base = "CONN"; let candidate = base; let n = 2; while (usedSuffixes.has(candidate)) { candidate = `${base}_${n}`; n += 1; } usedSuffixes.add(candidate); return candidate; } async function resolveStoredToolProviders(toolProviders, lookup, opts = {}) { const { requestContext, authorId, logger } = opts; const out = {}; logger?.debug(`[resolveStoredToolProviders] called`, { providerIds: Object.keys(toolProviders ?? {}), authorId }); if (!toolProviders || Object.keys(toolProviders).length === 0) { logger?.debug(`[resolveStoredToolProviders] no toolProviders on agent \u2014 returning {}`); return out; } for (const [providerId, cfg] of Object.entries(toolProviders)) { let provider; try { provider = lookup(providerId); } catch (error) { logger?.warn(`[resolveStoredToolProviders] Unknown provider "${providerId}"`, { error }); continue; } if (!provider.resolveToolsVNext) { logger?.warn(`[resolveStoredToolProviders] Provider "${providerId}" does not implement resolveToolsVNext`); continue; } const tools = cfg.tools ?? {}; const connectionsByToolkit = cfg.connections ?? {}; for (const [toolkit, connections] of Object.entries(connectionsByToolkit)) { if (!connections || connections.length === 0) { logger?.debug( `[resolveStoredToolProviders] toolkit "${toolkit}" on provider "${providerId}" has no pinned connections \u2014 skipping` ); continue; } if (connections.length > 1 && !provider.capabilities?.multipleConnectionsPerToolkit) { logger?.warn( `[resolveStoredToolProviders] provider "${providerId}" does not support multiple connections per toolkit but received ${connections.length} for "${toolkit}" \u2014 skipping` ); continue; } const slugsForToolkit = Object.entries(tools).filter(([slug, meta]) => meta?.toolkit ? meta.toolkit === toolkit : slug.startsWith(`${toolkit}.`)).map(([slug]) => slug); if (slugsForToolkit.length === 0) { logger?.debug( `[resolveStoredToolProviders] toolkit "${toolkit}" on provider "${providerId}" has connections but no matching tool slugs \u2014 skipping`, { availableSlugs: Object.keys(tools) } ); continue; } logger?.debug(`[resolveStoredToolProviders] resolving tools for ${providerId}/${toolkit}`, { slugs: slugsForToolkit, connectionCount: connections.length }); const skipSuffix = connections.length === 1; const usedSuffixes = /* @__PURE__ */ new Set(); for (const connection of connections) { const suffix = skipSuffix ? "" : `__${buildConnectionSuffix(connection.label, usedSuffixes)}`; const resolvedAuthorId = resolveConnectionAuthorId(connection, authorId, requestContext, logger); let resolved; try { resolved = await provider.resolveToolsVNext({ toolSlugs: slugsForToolkit, toolMeta: cfg.tools ?? {}, connectionId: connection.connectionId, authorId: resolvedAuthorId, requestContext }); } catch (error) { logger?.warn( `[resolveStoredToolProviders] Failed to resolve tools for ${providerId}/${toolkit} connection ${connection.connectionId}`, { error } ); continue; } for (const [slug, tool] of Object.entries(resolved)) { const renamedSlug = `${slug}${suffix}`; const baseDescription = tool.description ?? ""; const description = skipSuffix ? baseDescription : appendRoutingHint(baseDescription, connection); out[renamedSlug] = { ...tool, id: renamedSlug, description }; } } } } return out; } var defaultBucketWarned = false; function warnDefaultBucketFallback(logger) { if (defaultBucketWarned) return; defaultBucketWarned = true; logger?.warn( '[resolveStoredToolProviders] caller-supplied scope falling back to shared "default" bucket \u2014 wire authConfig.mapUserToResourceId to avoid cross-tenant OAuth sharing' ); } function resolveConnectionAuthorId(connection, callerAuthorId, requestContext, logger) { if (connection.kind !== "author") return void 0; if (connection.scope === "shared") return SHARED_BUCKET_ID; if (connection.scope === "caller-supplied") { const resourceId = requestContext?.[MASTRA_RESOURCE_ID_KEY]; if (typeof resourceId === "string" && resourceId.length > 0) return resourceId; warnDefaultBucketFallback(logger); return "default"; } return callerAuthorId; } function appendRoutingHint(description, connection) { const hint = `Routes through connection: ${connection.label ?? connection.connectionId}`; if (!description) return hint; return `${description} ${hint}`; } // src/tool-provider/errors.ts var DuplicateToolProviderError = class extends Error { ids; constructor(ids) { super(`Duplicate tool provider ids: ${ids.join(", ")}`); this.name = "DuplicateToolProviderError"; this.ids = ids; } }; var UnknownToolProviderError = class extends Error { id; knownIds; constructor(id, knownIds) { super(`Unknown tool provider "${id}". Known ids: ${knownIds.length ? knownIds.join(", ") : "(none)"}`); this.name = "UnknownToolProviderError"; this.id = id; this.knownIds = knownIds; } }; export { BaseToolProvider, DuplicateToolProviderError, SHARED_BUCKET_ID, UnknownToolProviderError, buildConnectionSuffix, resolveStoredToolProviders }; //# sourceMappingURL=index.js.map //# sourceMappingURL=index.js.map