import { Tool } from 'ai'; type ConnectorName = 'gmail' | 'outlook' | 'calendar' | 'drive' | 'notion' | 'sheets'; type ActionName = 'email.send' | 'calendar.create_event' | 'sheets.values_update' | 'sheets.values_append' | 'sheets.create_spreadsheet' | 'sheets.add_sheet'; interface ProfileToolsOptions { /** Optional connector tools this hosted/product surface requested and this app supports. */ connectors?: ConnectorName[]; /** Optional action tools this hosted/product surface requested and this app supports. Execution still enforces user state and approval. */ actions?: ActionName[]; /** Advanced adapter/runtime tools. Omit unless the host runtime explicitly supports them. */ advanced?: { /** Expose the model-facing commit tool for MCP/adapter runtimes. */ commit?: boolean; /** Expose raw profile file tools for advanced runtimes. */ files?: boolean; /** Expose Configure web search and URL fetch utility tools. */ utilitySearch?: boolean; }; } interface ConfigureToolCall { name?: string; arguments?: Record | string; input?: Record; function?: { name?: string; arguments?: Record | string; }; } /** * Error codes returned by SDK methods. * Use these to programmatically handle specific failure modes. * * @example * ```typescript * import { ConfigureError, ErrorCode } from 'configure'; * * try { * await profile.read(); * } catch (e) { * if (e instanceof ConfigureError && e.code === ErrorCode.AUTH_REQUIRED) { * // Token expired — re-authenticate * } * } * ``` */ declare const ErrorCode: { /** No API key provided to Configure */ readonly API_KEY_MISSING: "API_KEY_MISSING"; /** Token is missing, invalid, or expired (HTTP 401/403) */ readonly AUTH_REQUIRED: "AUTH_REQUIRED"; /** Input failed validation before reaching the API */ readonly INVALID_INPUT: "INVALID_INPUT"; /** The requested tool is not connected for this user (HTTP 400) */ readonly TOOL_NOT_CONNECTED: "TOOL_NOT_CONNECTED"; /** Network request failed (DNS, connection refused, etc.) */ readonly NETWORK_ERROR: "NETWORK_ERROR"; /** Too many requests (HTTP 429) */ readonly RATE_LIMITED: "RATE_LIMITED"; /** Resource not found (HTTP 404) */ readonly NOT_FOUND: "NOT_FOUND"; /** Server error (HTTP 5xx) */ readonly SERVER_ERROR: "SERVER_ERROR"; /** Request timed out */ readonly TIMEOUT: "TIMEOUT"; /** Not authorized for this resource (HTTP 403, distinct from AUTH_REQUIRED) */ readonly ACCESS_DENIED: "ACCESS_DENIED"; /** Tool operation failed (provider error, misconfiguration) */ readonly TOOL_ERROR: "TOOL_ERROR"; /** Billing/quota limit reached (HTTP 402) */ readonly PAYMENT_REQUIRED: "PAYMENT_REQUIRED"; /** A prior portable profile read must be committed before another portable read. */ readonly COMMIT_REQUIRED: "COMMIT_REQUIRED"; }; type ErrorCodeValue = (typeof ErrorCode)[keyof typeof ErrorCode]; /** * Vercel AI SDK adapter. * * `profile.tools()` returns Anthropic-shaped definitions: an ARRAY of * `{ name, description, input_schema }`. The AI SDK wants the opposite shape, * an OBJECT keyed by tool name whose values carry their own `execute`. Spreading * our array next to an AI SDK tool set silently produces `{0: ..., 1: ...}`, * which the model never sees, so every integration had to hand-write this * conversion. It lives here instead. * * Imported through the `configure/ai-sdk` subpath so `ai` stays an OPTIONAL * peer: nothing in the main entry point pulls it in. * * Known limitation: the AI SDK passes `execute` an `abortSignal`, and this * adapter cannot forward it. `profile.executeTool()` takes no per-call options, * and the runtime's only AbortSignal comes from its own client timeout. So a * cancelled stream leaves the in-flight Configure request running until that * timeout. Nothing is corrupted and the result is discarded; it is wasted work, * not a wrong answer. Forwarding it needs an options parameter on executeTool. */ /** * The surface this adapter needs from a profile handle. Structural on purpose: * it accepts the real handle from `configure.profile({...})` and any stand-in * a test supplies, without importing the runtime class. */ interface AISDKProfileSource { executeTool: (toolCall: ConfigureToolCall, options?: { allow?: Iterable; }) => Promise; } /** Shape returned to the model when a Configure call is refused. */ interface ConfigureToolFailure { /** Always true, so a model can branch on it without inspecting further. */ error: true; /** Machine-readable SDK error code, e.g. `AUTH_REQUIRED`. */ code: ErrorCodeValue; message: string; /** * What to do about it, as a machine-actionable action word rather than a * link: `reauthenticate`, `connect_tool`, `reconnect`, `retry`, * `check_permissions`, `commit_profile`, and so on. Mint the actual link with * `profile.connect({ app })` when the action calls for one. */ suggestedAction?: string; /** Documentation for this failure, when the backend supplied one. */ docUrl?: string; } interface ToAISDKToolsOptions extends ProfileToolsOptions { /** * What a failing tool call hands back. Default `'value'`. * * `'value'` returns a {@link ConfigureToolFailure}. This matters because a * Configure refusal NAMES ITS OWN FIX: `TOOL_NOT_CONNECTED` arrives with * `suggestedAction: 'connect_tool'`, so the turn can recover by minting a * link with `profile.connect({ app })` instead of dying. `code` is the SDK * error code, not the backend's raw string, and `suggestedAction` is an * action word, not a URL. Measured * against ai@7: throwing does not abort the run, but the framework converts * the error into a generic `tool-error` content part, which drops * `suggestedAction` and `docUrl` and never appears in `toolResults`. The * model then knows only that something failed, not what would fix it. * * `'throw'` restores throwing for callers who handle it themselves. */ onError?: 'value' | 'throw'; } /** * Convert Configure's tools into an AI SDK tool set. * * ```ts * const result = streamText({ * model, * messages, * stopWhen: stepCountIs(5), // without a stop condition the turn ends on the tool call * tools: { ...yourTools, ...toAISDKTools(profile, { connectors: ['gmail'] }) }, * }); * ``` * * Pass the same options you would pass to `profile.tools()`. Configure's tools * win on a name collision in the spread order above; reverse the spread and * your own tool of the same name wins instead. */ declare function toAISDKTools(profile: AISDKProfileSource, options?: ToAISDKToolsOptions): Record; export { type AISDKProfileSource, type ConfigureToolFailure, type ToAISDKToolsOptions, toAISDKTools };