integrate-sdk 0.9.2-dev.0 → 0.9.4-dev.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/dist/adapters/auto-routes.d.ts.map +1 -1
  2. package/dist/adapters/auto-routes.js +727 -17
  3. package/dist/adapters/base-handler.d.ts.map +1 -1
  4. package/dist/adapters/index.js +722 -16
  5. package/dist/adapters/nextjs.d.ts.map +1 -1
  6. package/dist/adapters/nextjs.js +722 -16
  7. package/dist/adapters/node.js +722 -16
  8. package/dist/adapters/svelte-kit.js +722 -16
  9. package/dist/adapters/tanstack-start.js +722 -16
  10. package/dist/ai/anthropic.d.ts +11 -0
  11. package/dist/ai/anthropic.d.ts.map +1 -1
  12. package/dist/ai/anthropic.js +552 -2
  13. package/dist/ai/google.d.ts +11 -0
  14. package/dist/ai/google.d.ts.map +1 -1
  15. package/dist/ai/google.js +561 -2
  16. package/dist/ai/index.js +648 -8
  17. package/dist/ai/openai.d.ts +11 -0
  18. package/dist/ai/openai.d.ts.map +1 -1
  19. package/dist/ai/openai.js +550 -2
  20. package/dist/ai/vercel-ai.d.ts +13 -0
  21. package/dist/ai/vercel-ai.d.ts.map +1 -1
  22. package/dist/ai/vercel-ai.js +536 -2
  23. package/dist/code-mode/executor.d.ts +99 -0
  24. package/dist/code-mode/executor.d.ts.map +1 -0
  25. package/dist/code-mode/executor.js +207 -0
  26. package/dist/code-mode/index.d.ts +12 -0
  27. package/dist/code-mode/index.d.ts.map +1 -0
  28. package/dist/code-mode/index.js +527 -0
  29. package/dist/code-mode/runtime-stub.d.ts +16 -0
  30. package/dist/code-mode/runtime-stub.d.ts.map +1 -0
  31. package/dist/code-mode/runtime-stub.js +72 -0
  32. package/dist/code-mode/tool-builder.d.ts +83 -0
  33. package/dist/code-mode/tool-builder.d.ts.map +1 -0
  34. package/dist/code-mode/tool-builder.js +524 -0
  35. package/dist/code-mode/type-generator.d.ts +22 -0
  36. package/dist/code-mode/type-generator.d.ts.map +1 -0
  37. package/dist/code-mode/type-generator.js +217 -0
  38. package/dist/index.js +722 -16
  39. package/dist/oauth.js +727 -17
  40. package/dist/server.d.ts +1 -0
  41. package/dist/server.d.ts.map +1 -1
  42. package/dist/server.js +733 -17
  43. package/dist/src/adapters/auto-routes.d.ts.map +1 -1
  44. package/dist/src/adapters/base-handler.d.ts.map +1 -1
  45. package/dist/src/adapters/nextjs.d.ts.map +1 -1
  46. package/dist/src/ai/anthropic.d.ts +11 -0
  47. package/dist/src/ai/anthropic.d.ts.map +1 -1
  48. package/dist/src/ai/google.d.ts +11 -0
  49. package/dist/src/ai/google.d.ts.map +1 -1
  50. package/dist/src/ai/openai.d.ts +11 -0
  51. package/dist/src/ai/openai.d.ts.map +1 -1
  52. package/dist/src/ai/vercel-ai.d.ts +13 -0
  53. package/dist/src/ai/vercel-ai.d.ts.map +1 -1
  54. package/dist/src/code-mode/executor.d.ts +99 -0
  55. package/dist/src/code-mode/executor.d.ts.map +1 -0
  56. package/dist/src/code-mode/index.d.ts +12 -0
  57. package/dist/src/code-mode/index.d.ts.map +1 -0
  58. package/dist/src/code-mode/runtime-stub.d.ts +16 -0
  59. package/dist/src/code-mode/runtime-stub.d.ts.map +1 -0
  60. package/dist/src/code-mode/tool-builder.d.ts +83 -0
  61. package/dist/src/code-mode/tool-builder.d.ts.map +1 -0
  62. package/dist/src/code-mode/type-generator.d.ts +22 -0
  63. package/dist/src/code-mode/type-generator.d.ts.map +1 -0
  64. package/dist/src/config/types.d.ts +55 -0
  65. package/dist/src/config/types.d.ts.map +1 -1
  66. package/dist/src/server.d.ts.map +1 -1
  67. package/package.json +15 -6
  68. package/server.ts +9 -0
package/dist/oauth.js CHANGED
@@ -507,10 +507,17 @@ var init_errors = __esm(() => {
507
507
  function camelToSnake(str) {
508
508
  return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
509
509
  }
510
+ function snakeToCamel(str) {
511
+ return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
512
+ }
510
513
  function methodToToolName(methodName, integrationId) {
511
514
  const snakeCaseMethod = camelToSnake(methodName);
512
515
  return `${integrationId}_${snakeCaseMethod}`;
513
516
  }
517
+ function toolNameToMethod(toolName) {
518
+ const withoutPrefix = toolName.replace(/^[^_]+_/, "");
519
+ return snakeToCamel(withoutPrefix);
520
+ }
514
521
 
515
522
  // src/triggers/client.ts
516
523
  class TriggerClient {
@@ -2648,7 +2655,11 @@ function createNextOAuthHandler(config) {
2648
2655
  }
2649
2656
  return response;
2650
2657
  } catch (error) {
2651
- logger6.error("[OAuth Refresh] Error:", error);
2658
+ if (error.message?.toLowerCase().includes("not supported")) {
2659
+ logger6.info("[OAuth Refresh] Not supported for this provider:", error.message);
2660
+ } else {
2661
+ logger6.error("[OAuth Refresh] Error:", error);
2662
+ }
2652
2663
  return Response.json({ error: error.message || "Failed to refresh token" }, { status: 500 });
2653
2664
  }
2654
2665
  },
@@ -8553,6 +8564,508 @@ var init_trigger_tools = __esm(() => {
8553
8564
  init_utils2();
8554
8565
  });
8555
8566
 
8567
+ // src/code-mode/type-generator.ts
8568
+ function safeIdent(name) {
8569
+ if (!/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name) || RESERVED_TS.has(name)) {
8570
+ return JSON.stringify(name);
8571
+ }
8572
+ return name;
8573
+ }
8574
+ function integrationFromToolName(toolName) {
8575
+ const idx = toolName.indexOf("_");
8576
+ return idx === -1 ? toolName : toolName.slice(0, idx);
8577
+ }
8578
+ function jsonSchemaToTs(schema, indent) {
8579
+ if (!schema || typeof schema !== "object")
8580
+ return "unknown";
8581
+ const s = schema;
8582
+ if (Array.isArray(s.enum) && s.enum.length > 0) {
8583
+ return s.enum.map((v) => typeof v === "string" ? JSON.stringify(v) : typeof v === "number" || typeof v === "boolean" ? String(v) : "unknown").join(" | ");
8584
+ }
8585
+ if (Array.isArray(s.type)) {
8586
+ return s.type.map((t2) => jsonSchemaToTs({ ...s, type: t2 }, indent)).join(" | ");
8587
+ }
8588
+ const t = s.type;
8589
+ switch (t) {
8590
+ case "string":
8591
+ return "string";
8592
+ case "number":
8593
+ case "integer":
8594
+ return "number";
8595
+ case "boolean":
8596
+ return "boolean";
8597
+ case "null":
8598
+ return "null";
8599
+ case "array": {
8600
+ const items = s.items;
8601
+ if (Array.isArray(items))
8602
+ return "unknown[]";
8603
+ const inner = jsonSchemaToTs(items, indent);
8604
+ return /[|&]/.test(inner) ? `Array<${inner}>` : `${inner}[]`;
8605
+ }
8606
+ case "object":
8607
+ return objectShape(s, indent);
8608
+ default:
8609
+ if (s.properties && typeof s.properties === "object")
8610
+ return objectShape(s, indent);
8611
+ return "unknown";
8612
+ }
8613
+ }
8614
+ function objectShape(schema, indent) {
8615
+ const props = schema.properties && typeof schema.properties === "object" ? schema.properties : {};
8616
+ const keys = Object.keys(props);
8617
+ if (keys.length === 0) {
8618
+ return schema.additionalProperties === false ? "Record<string, never>" : "Record<string, unknown>";
8619
+ }
8620
+ const required = new Set(Array.isArray(schema.required) ? schema.required : []);
8621
+ const inner = indent + " ";
8622
+ const lines = ["{"];
8623
+ for (const key of keys) {
8624
+ const prop = props[key];
8625
+ const desc = prop && typeof prop.description === "string" ? prop.description : undefined;
8626
+ if (desc)
8627
+ lines.push(`${inner}/** ${desc.replace(/\*\//g, "*\\/")} */`);
8628
+ const optional = required.has(key) ? "" : "?";
8629
+ const type = jsonSchemaToTs(prop, inner);
8630
+ lines.push(`${inner}${safeIdent(key)}${optional}: ${type};`);
8631
+ }
8632
+ lines.push(`${indent}}`);
8633
+ return lines.join(`
8634
+ `);
8635
+ }
8636
+ function argsType(schema) {
8637
+ if (!schema)
8638
+ return "Record<string, unknown>";
8639
+ const hasProps = schema.properties && Object.keys(schema.properties).length > 0;
8640
+ if (!hasProps)
8641
+ return "Record<string, unknown>";
8642
+ return objectShape(schema, " ");
8643
+ }
8644
+ function methodHasRequiredArgs(schema) {
8645
+ if (!schema || !schema.properties)
8646
+ return false;
8647
+ const req = Array.isArray(schema.required) ? schema.required : [];
8648
+ return req.length > 0;
8649
+ }
8650
+ function formatDescription(desc, indent) {
8651
+ if (!desc)
8652
+ return "";
8653
+ const cleaned = desc.replace(/\*\//g, "*\\/").trim();
8654
+ if (!cleaned.includes(`
8655
+ `))
8656
+ return `${indent}/** ${cleaned} */
8657
+ `;
8658
+ const lines = cleaned.split(`
8659
+ `).map((l) => `${indent} * ${l}`).join(`
8660
+ `);
8661
+ return `${indent}/**
8662
+ ${lines}
8663
+ ${indent} */
8664
+ `;
8665
+ }
8666
+ function generateCodeModeTypes(tools) {
8667
+ const byIntegration = {};
8668
+ for (const tool of tools) {
8669
+ const integration = integrationFromToolName(tool.name);
8670
+ (byIntegration[integration] ??= []).push(tool);
8671
+ }
8672
+ const methodMap = {};
8673
+ const integrationCounts = {};
8674
+ const sections = [];
8675
+ const integrationIds = Object.keys(byIntegration).sort();
8676
+ sections.push("/**");
8677
+ sections.push(" * Integrate SDK — available APIs inside `execute_code`.");
8678
+ sections.push(" * Every method is async and returns the MCP tool-call response.");
8679
+ sections.push(" * Call them via the exported `client` object, e.g.");
8680
+ sections.push(" * const repos = await client.github.listRepos();");
8681
+ sections.push(" */");
8682
+ sections.push("");
8683
+ for (const integrationId of integrationIds) {
8684
+ const integrationTools = byIntegration[integrationId].slice().sort((a, b) => a.name.localeCompare(b.name));
8685
+ integrationCounts[integrationId] = integrationTools.length;
8686
+ const interfaceName = pascalCase(integrationId) + "Client";
8687
+ sections.push(`export interface ${interfaceName} {`);
8688
+ for (const tool of integrationTools) {
8689
+ const methodName = toolNameToMethod(tool.name);
8690
+ methodMap[`${integrationId}.${methodName}`] = tool.name;
8691
+ sections.push(formatDescription(tool.description, " "));
8692
+ const argType = argsType(tool.inputSchema);
8693
+ const argIsOptional = !methodHasRequiredArgs(tool.inputSchema);
8694
+ const paramName = argIsOptional ? "args?" : "args";
8695
+ sections.push(` ${safeIdent(methodName)}(${paramName}: ${argType}): Promise<ToolResult>;`);
8696
+ }
8697
+ sections.push("}");
8698
+ sections.push("");
8699
+ }
8700
+ sections.push("export interface ToolResult {");
8701
+ sections.push(" content: Array<{ type: 'text' | 'image' | 'resource'; text?: string; data?: string; mimeType?: string; [key: string]: unknown }>;");
8702
+ sections.push(" isError?: boolean;");
8703
+ sections.push(" structuredContent?: Record<string, unknown>;");
8704
+ sections.push("}");
8705
+ sections.push("");
8706
+ sections.push("export interface Client {");
8707
+ for (const integrationId of integrationIds) {
8708
+ const interfaceName = pascalCase(integrationId) + "Client";
8709
+ sections.push(` ${safeIdent(integrationId)}: ${interfaceName};`);
8710
+ }
8711
+ sections.push("}");
8712
+ sections.push("");
8713
+ sections.push("export declare const client: Client;");
8714
+ return {
8715
+ source: sections.filter((line, idx, arr) => !(line === "" && arr[idx - 1] === "")).join(`
8716
+ `),
8717
+ methodMap,
8718
+ integrationCounts
8719
+ };
8720
+ }
8721
+ function pascalCase(id) {
8722
+ return id.split(/[^A-Za-z0-9]/).filter(Boolean).map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join("") || "Unknown";
8723
+ }
8724
+ var RESERVED_TS;
8725
+ var init_type_generator = __esm(() => {
8726
+ RESERVED_TS = new Set([
8727
+ "break",
8728
+ "case",
8729
+ "catch",
8730
+ "class",
8731
+ "const",
8732
+ "continue",
8733
+ "debugger",
8734
+ "default",
8735
+ "delete",
8736
+ "do",
8737
+ "else",
8738
+ "enum",
8739
+ "export",
8740
+ "extends",
8741
+ "false",
8742
+ "finally",
8743
+ "for",
8744
+ "function",
8745
+ "if",
8746
+ "import",
8747
+ "in",
8748
+ "instanceof",
8749
+ "new",
8750
+ "null",
8751
+ "return",
8752
+ "super",
8753
+ "switch",
8754
+ "this",
8755
+ "throw",
8756
+ "true",
8757
+ "try",
8758
+ "typeof",
8759
+ "var",
8760
+ "void",
8761
+ "while",
8762
+ "with",
8763
+ "as",
8764
+ "implements",
8765
+ "interface",
8766
+ "let",
8767
+ "package",
8768
+ "private",
8769
+ "protected",
8770
+ "public",
8771
+ "static",
8772
+ "yield"
8773
+ ]);
8774
+ });
8775
+
8776
+ // src/code-mode/runtime-stub.ts
8777
+ var RUNTIME_STUB_SOURCE = `// runtime.mjs — generated by integrate-sdk code mode
8778
+ const MCP_URL = process.env.INTEGRATE_MCP_URL;
8779
+ const SESSION_TOKEN = process.env.INTEGRATE_SESSION_TOKEN;
8780
+ const PROVIDER_TOKENS = process.env.INTEGRATE_PROVIDER_TOKENS || '';
8781
+ const INTEGRATIONS_HEADER = process.env.INTEGRATE_INTEGRATIONS || '';
8782
+ const CONTEXT_JSON = process.env.INTEGRATE_CONTEXT || '';
8783
+
8784
+ if (!MCP_URL) {
8785
+ throw new Error('INTEGRATE_MCP_URL is not set — the sandbox cannot reach the MCP route.');
8786
+ }
8787
+
8788
+ function camelToSnake(str) {
8789
+ return str.replace(/[A-Z]/g, (letter) => '_' + letter.toLowerCase());
8790
+ }
8791
+
8792
+ async function callTool(toolName, args) {
8793
+ const headers = {
8794
+ 'Content-Type': 'application/json',
8795
+ 'x-integrate-code-mode': '1',
8796
+ };
8797
+ if (SESSION_TOKEN) headers['Authorization'] = 'Bearer ' + SESSION_TOKEN;
8798
+ if (PROVIDER_TOKENS) headers['x-integrate-tokens'] = PROVIDER_TOKENS;
8799
+ if (INTEGRATIONS_HEADER) headers['x-integrations'] = INTEGRATIONS_HEADER;
8800
+ if (CONTEXT_JSON) headers['x-integrate-context'] = CONTEXT_JSON;
8801
+
8802
+ const res = await fetch(MCP_URL, {
8803
+ method: 'POST',
8804
+ headers,
8805
+ body: JSON.stringify({ name: toolName, arguments: args || {} }),
8806
+ });
8807
+
8808
+ const text = await res.text();
8809
+ let payload;
8810
+ try {
8811
+ payload = text ? JSON.parse(text) : null;
8812
+ } catch {
8813
+ payload = { content: [{ type: 'text', text }] };
8814
+ }
8815
+
8816
+ if (!res.ok) {
8817
+ const message = (payload && (payload.error || payload.message)) || 'Tool call failed: HTTP ' + res.status;
8818
+ const err = new Error(message);
8819
+ err.status = res.status;
8820
+ err.toolName = toolName;
8821
+ throw err;
8822
+ }
8823
+
8824
+ return payload;
8825
+ }
8826
+
8827
+ function createIntegrationProxy(integrationId) {
8828
+ return new Proxy({}, {
8829
+ get(_target, methodName) {
8830
+ if (typeof methodName !== 'string') return undefined;
8831
+ return (args) => callTool(integrationId + '_' + camelToSnake(methodName), args);
8832
+ },
8833
+ });
8834
+ }
8835
+
8836
+ export const client = new Proxy({}, {
8837
+ get(_target, integrationId) {
8838
+ if (typeof integrationId !== 'string') return undefined;
8839
+ return createIntegrationProxy(integrationId);
8840
+ },
8841
+ });
8842
+
8843
+ export { callTool };
8844
+ `;
8845
+
8846
+ // src/code-mode/executor.ts
8847
+ var exports_executor = {};
8848
+ __export(exports_executor, {
8849
+ executeSandboxCode: () => executeSandboxCode,
8850
+ __setSandboxFactoryForTests: () => __setSandboxFactoryForTests
8851
+ });
8852
+ function __setSandboxFactoryForTests(factory) {
8853
+ sandboxFactoryOverride = factory;
8854
+ }
8855
+ async function loadSandboxFactory() {
8856
+ if (sandboxFactoryOverride)
8857
+ return sandboxFactoryOverride;
8858
+ try {
8859
+ const dynamicImport = new Function("specifier", "return import(specifier)");
8860
+ const pkg = "@" + "vercel/sandbox";
8861
+ const mod = await dynamicImport(pkg);
8862
+ return mod.Sandbox ?? mod.default?.Sandbox ?? mod;
8863
+ } catch (err) {
8864
+ throw new Error("Code Mode requires the optional peer dependency `@vercel/sandbox`. " + "Install it with `npm install @vercel/sandbox` (or `bun add @vercel/sandbox`).");
8865
+ }
8866
+ }
8867
+ function wrapUserCode(code) {
8868
+ return `// user.mjs — wrapped by integrate-sdk code mode
8869
+ import { client, callTool } from './runtime.mjs';
8870
+
8871
+ (async () => {
8872
+ try {
8873
+ const __result = await (async () => {
8874
+ ${code}
8875
+ })();
8876
+ if (typeof __result !== 'undefined') {
8877
+ process.stdout.write('\\n' + ${JSON.stringify(RESULT_SENTINEL)} + JSON.stringify(__result) + '\\n');
8878
+ }
8879
+ } catch (err) {
8880
+ const payload = {
8881
+ message: err && err.message ? err.message : String(err),
8882
+ name: err && err.name,
8883
+ stack: err && err.stack,
8884
+ toolName: err && err.toolName,
8885
+ status: err && err.status,
8886
+ };
8887
+ process.stderr.write('\\n' + ${JSON.stringify(RESULT_SENTINEL)} + JSON.stringify({ error: payload }) + '\\n');
8888
+ process.exit(1);
8889
+ }
8890
+ })();
8891
+ `;
8892
+ }
8893
+ function defaultNetworkPolicy(mcpUrl) {
8894
+ try {
8895
+ const host = new URL(mcpUrl).hostname;
8896
+ return { allow: [host] };
8897
+ } catch {
8898
+ return { allow: [] };
8899
+ }
8900
+ }
8901
+ function extractResult(stream) {
8902
+ const idx = stream.lastIndexOf(RESULT_SENTINEL);
8903
+ if (idx === -1)
8904
+ return { cleaned: stream };
8905
+ const before = stream.slice(0, idx).replace(/\n$/, "");
8906
+ const rest = stream.slice(idx + RESULT_SENTINEL.length);
8907
+ const newlineIdx = rest.indexOf(`
8908
+ `);
8909
+ const payload = newlineIdx === -1 ? rest : rest.slice(0, newlineIdx);
8910
+ const after = newlineIdx === -1 ? "" : rest.slice(newlineIdx + 1);
8911
+ try {
8912
+ return { cleaned: (before + after).trimEnd(), result: JSON.parse(payload) };
8913
+ } catch {
8914
+ return { cleaned: stream };
8915
+ }
8916
+ }
8917
+ async function executeSandboxCode(options) {
8918
+ const startedAt = Date.now();
8919
+ const runtime = options.runtime ?? "node22";
8920
+ const timeoutMs = options.timeoutMs ?? 60000;
8921
+ const networkPolicy = options.networkPolicy ?? defaultNetworkPolicy(options.mcpUrl);
8922
+ let sandbox = null;
8923
+ try {
8924
+ const Sandbox = await loadSandboxFactory();
8925
+ sandbox = await Sandbox.create({
8926
+ runtime,
8927
+ timeout: timeoutMs,
8928
+ resources: options.vcpus ? { vcpus: options.vcpus } : undefined,
8929
+ networkPolicy
8930
+ });
8931
+ const runtimeContent = Buffer.from(RUNTIME_STUB_SOURCE, "utf-8");
8932
+ const userContent = Buffer.from(wrapUserCode(options.code), "utf-8");
8933
+ await sandbox.writeFiles([
8934
+ { path: "runtime.mjs", content: runtimeContent },
8935
+ { path: "user.mjs", content: userContent }
8936
+ ]);
8937
+ const env = {
8938
+ INTEGRATE_MCP_URL: options.mcpUrl
8939
+ };
8940
+ if (options.sessionToken)
8941
+ env.INTEGRATE_SESSION_TOKEN = options.sessionToken;
8942
+ if (options.providerTokens && Object.keys(options.providerTokens).length > 0) {
8943
+ env.INTEGRATE_PROVIDER_TOKENS = JSON.stringify(options.providerTokens);
8944
+ }
8945
+ if (options.integrationsHeader)
8946
+ env.INTEGRATE_INTEGRATIONS = options.integrationsHeader;
8947
+ if (options.context)
8948
+ env.INTEGRATE_CONTEXT = JSON.stringify(options.context);
8949
+ const cmd = await sandbox.runCommand({
8950
+ cmd: "node",
8951
+ args: ["user.mjs"],
8952
+ env
8953
+ });
8954
+ const [stdoutRaw, stderrRaw] = await Promise.all([cmd.stdout(), cmd.stderr()]);
8955
+ const stdoutExtract = extractResult(stdoutRaw);
8956
+ const stderrExtract = extractResult(stderrRaw);
8957
+ return {
8958
+ success: cmd.exitCode === 0,
8959
+ exitCode: cmd.exitCode,
8960
+ result: stdoutExtract.result ?? stderrExtract.result,
8961
+ stdout: stdoutExtract.cleaned,
8962
+ stderr: stderrExtract.cleaned,
8963
+ durationMs: Date.now() - startedAt
8964
+ };
8965
+ } catch (err) {
8966
+ return {
8967
+ success: false,
8968
+ exitCode: -1,
8969
+ stdout: "",
8970
+ stderr: "",
8971
+ durationMs: Date.now() - startedAt,
8972
+ error: err instanceof Error ? err.message : String(err)
8973
+ };
8974
+ } finally {
8975
+ if (sandbox) {
8976
+ try {
8977
+ await sandbox.stop();
8978
+ } catch {}
8979
+ }
8980
+ }
8981
+ }
8982
+ var sandboxFactoryOverride = null, RESULT_SENTINEL = "__INTEGRATE_RESULT__";
8983
+ var init_executor = () => {};
8984
+
8985
+ // src/code-mode/tool-builder.ts
8986
+ function resolveCodeModeClientConfig(client) {
8987
+ const oauthConfig = client.__oauthConfig;
8988
+ return oauthConfig?.codeMode ?? {};
8989
+ }
8990
+ function buildCodeModeTool(client, options) {
8991
+ const { tools, providerTokens, context, integrationIds } = options;
8992
+ const generated = generateCodeModeTypes(tools);
8993
+ const serverCodeModeConfig = resolveCodeModeClientConfig(client);
8994
+ const sandboxOverrides = options.sandbox ?? {};
8995
+ const description = `${DEFAULT_INSTRUCTIONS}
8996
+
8997
+ \`\`\`typescript
8998
+ ${generated.source}
8999
+ \`\`\``;
9000
+ const execute = async ({ code }) => {
9001
+ const publicUrl = sandboxOverrides.publicUrl ?? serverCodeModeConfig.publicUrl ?? getEnv("INTEGRATE_PUBLIC_URL");
9002
+ if (!publicUrl) {
9003
+ return {
9004
+ success: false,
9005
+ exitCode: -1,
9006
+ stdout: "",
9007
+ stderr: "",
9008
+ durationMs: 0,
9009
+ error: "Code Mode requires `codeMode.publicUrl` in createMCPServer config (or the INTEGRATE_PUBLIC_URL env var). " + "The sandbox uses it to call back into /api/integrate/mcp."
9010
+ };
9011
+ }
9012
+ const mcpUrl = publicUrl.replace(/\/$/, "") + "/api/integrate/mcp";
9013
+ return executeSandboxCode({
9014
+ code,
9015
+ mcpUrl,
9016
+ providerTokens,
9017
+ context,
9018
+ integrationsHeader: integrationIds && integrationIds.length > 0 ? integrationIds.join(",") : undefined,
9019
+ runtime: sandboxOverrides.runtime ?? serverCodeModeConfig.runtime,
9020
+ timeoutMs: sandboxOverrides.timeoutMs ?? serverCodeModeConfig.timeoutMs,
9021
+ vcpus: sandboxOverrides.vcpus ?? serverCodeModeConfig.vcpus,
9022
+ networkPolicy: sandboxOverrides.networkPolicy ?? serverCodeModeConfig.networkPolicy
9023
+ });
9024
+ };
9025
+ return {
9026
+ name: CODE_MODE_TOOL_NAME,
9027
+ description,
9028
+ parameters: {
9029
+ type: "object",
9030
+ properties: {
9031
+ code: {
9032
+ type: "string",
9033
+ description: "The TypeScript/JavaScript snippet to execute. It is wrapped in an async IIFE, so you may use top-level await and return a final value."
9034
+ }
9035
+ },
9036
+ required: ["code"],
9037
+ additionalProperties: false
9038
+ },
9039
+ execute
9040
+ };
9041
+ }
9042
+ var CODE_MODE_TOOL_NAME = "execute_code", DEFAULT_INSTRUCTIONS;
9043
+ var init_tool_builder = __esm(() => {
9044
+ init_type_generator();
9045
+ init_executor();
9046
+ DEFAULT_INSTRUCTIONS = [
9047
+ "You are given a single tool: `execute_code`. Instead of calling individual MCP tools,",
9048
+ "you write a short async TypeScript/JavaScript snippet that uses the typed `client`",
9049
+ "object below, and the snippet runs in an isolated sandbox which dispatches the actual",
9050
+ "tool calls. Chain multiple operations together in one snippet whenever possible —",
9051
+ "that is the whole point of this tool.",
9052
+ "",
9053
+ "Rules:",
9054
+ "- The snippet is the body of an `async` function. Use `await` freely.",
9055
+ "- Use `return <value>` at the end to hand a structured result back to the caller;",
9056
+ " the caller receives it as JSON.",
9057
+ "- Use `console.log(...)` for intermediate observations you want to read later.",
9058
+ "- Throw / let errors propagate; the runtime will surface them with a non-zero exit.",
9059
+ "- Each method call returns an object of shape `ToolResult` (see types below).",
9060
+ " The payload usually lives in `result.content[0].text` as JSON — parse it if needed.",
9061
+ "- You cannot import npm packages. Only the pre-imported `client` and standard",
9062
+ " globals (`fetch`, `console`, `JSON`, ...) are available.",
9063
+ "",
9064
+ "API surface:"
9065
+ ].join(`
9066
+ `);
9067
+ });
9068
+
8556
9069
  // src/ai/vercel-ai.ts
8557
9070
  function convertMCPToolToVercelAI(mcpTool, client, options) {
8558
9071
  return {
@@ -8577,8 +9090,25 @@ async function getVercelAITools(client, options) {
8577
9090
  await ensureClientConnected(client);
8578
9091
  const mcpTools = await client.getEnabledToolsAsync();
8579
9092
  const vercelTools = {};
8580
- for (const mcpTool of mcpTools) {
8581
- vercelTools[mcpTool.name] = convertMCPToolToVercelAI(mcpTool, client, finalOptions);
9093
+ const mode = options?.mode ?? "code";
9094
+ if (mode === "code") {
9095
+ const codeTool = buildCodeModeTool(client, {
9096
+ tools: mcpTools,
9097
+ providerTokens,
9098
+ context: options?.context,
9099
+ integrationIds: client.__oauthConfig?.integrations?.map((i) => i.id) ?? client.integrations?.map?.((i) => i.id)
9100
+ });
9101
+ vercelTools[CODE_MODE_TOOL_NAME] = {
9102
+ description: codeTool.description,
9103
+ inputSchema: exports_external.object({
9104
+ code: exports_external.string().describe(codeTool.parameters.properties.code.description)
9105
+ }),
9106
+ execute: async (args) => codeTool.execute(args)
9107
+ };
9108
+ } else {
9109
+ for (const mcpTool of mcpTools) {
9110
+ vercelTools[mcpTool.name] = convertMCPToolToVercelAI(mcpTool, client, finalOptions);
9111
+ }
8582
9112
  }
8583
9113
  const triggerConfig = client.__triggerConfig;
8584
9114
  if (triggerConfig) {
@@ -8588,8 +9118,10 @@ async function getVercelAITools(client, options) {
8588
9118
  return vercelTools;
8589
9119
  }
8590
9120
  var init_vercel_ai = __esm(() => {
9121
+ init_zod();
8591
9122
  init_utils();
8592
9123
  init_trigger_tools();
9124
+ init_tool_builder();
8593
9125
  });
8594
9126
 
8595
9127
  // node_modules/zod-to-json-schema/dist/esm/Options.js
@@ -10017,7 +10549,22 @@ async function getOpenAITools(client, options) {
10017
10549
  const finalOptions = providerTokens ? { ...options, providerTokens } : options;
10018
10550
  await ensureClientConnected(client);
10019
10551
  const mcpTools = await client.getEnabledToolsAsync();
10020
- const openaiTools = mcpTools.map((mcpTool) => convertMCPToolToOpenAI(mcpTool, client, finalOptions));
10552
+ const mode = options?.mode ?? "code";
10553
+ const openaiTools = mode === "code" ? (() => {
10554
+ const codeTool = buildCodeModeTool(client, {
10555
+ tools: mcpTools,
10556
+ providerTokens,
10557
+ context: options?.context,
10558
+ integrationIds: client.__oauthConfig?.integrations?.map((i) => i.id)
10559
+ });
10560
+ return [{
10561
+ type: "function",
10562
+ name: CODE_MODE_TOOL_NAME,
10563
+ description: codeTool.description,
10564
+ parameters: codeTool.parameters,
10565
+ strict: options?.strict ?? null
10566
+ }];
10567
+ })() : mcpTools.map((mcpTool) => convertMCPToolToOpenAI(mcpTool, client, finalOptions));
10021
10568
  const triggerConfig = client.__triggerConfig;
10022
10569
  if (triggerConfig) {
10023
10570
  const triggerTools = createTriggerTools(triggerConfig, options?.context);
@@ -10042,6 +10589,19 @@ async function handleOpenAIToolCalls(client, toolCalls, options) {
10042
10589
  const toolOutputs = [];
10043
10590
  const triggerConfig = client.__triggerConfig;
10044
10591
  const triggerTools = triggerConfig ? createTriggerTools(triggerConfig, options?.context) : null;
10592
+ let cachedCodeModeTool = null;
10593
+ const getCodeModeTool = async () => {
10594
+ if (cachedCodeModeTool)
10595
+ return cachedCodeModeTool;
10596
+ const mcpTools = await client.getEnabledToolsAsync();
10597
+ cachedCodeModeTool = buildCodeModeTool(client, {
10598
+ tools: mcpTools,
10599
+ providerTokens: options?.providerTokens,
10600
+ context: options?.context,
10601
+ integrationIds: client.__oauthConfig?.integrations?.map((i) => i.id)
10602
+ });
10603
+ return cachedCodeModeTool;
10604
+ };
10045
10605
  for (const output of toolCalls) {
10046
10606
  if (output.type === "function_call") {
10047
10607
  const toolCall = {
@@ -10052,7 +10612,10 @@ async function handleOpenAIToolCalls(client, toolCalls, options) {
10052
10612
  try {
10053
10613
  const args = JSON.parse(toolCall.arguments);
10054
10614
  let result;
10055
- if (triggerTools && triggerTools[toolCall.name]) {
10615
+ if (toolCall.name === CODE_MODE_TOOL_NAME) {
10616
+ const codeTool = await getCodeModeTool();
10617
+ result = await codeTool.execute(args);
10618
+ } else if (triggerTools && triggerTools[toolCall.name]) {
10056
10619
  result = await triggerTools[toolCall.name].execute(args);
10057
10620
  } else {
10058
10621
  result = await executeToolWithToken(client, toolCall.name, args, options);
@@ -10093,6 +10656,7 @@ async function handleOpenAIResponse(client, response, options) {
10093
10656
  var init_openai = __esm(() => {
10094
10657
  init_utils();
10095
10658
  init_trigger_tools();
10659
+ init_tool_builder();
10096
10660
  init_esm();
10097
10661
  });
10098
10662
 
@@ -10112,11 +10676,27 @@ async function handleAnthropicToolCalls(client, messageContent, options) {
10112
10676
  const toolResults = [];
10113
10677
  const triggerConfig = client.__triggerConfig;
10114
10678
  const triggerTools = triggerConfig ? createTriggerTools(triggerConfig, options?.context) : null;
10679
+ let cachedCodeModeTool = null;
10680
+ const getCodeModeTool = async () => {
10681
+ if (cachedCodeModeTool)
10682
+ return cachedCodeModeTool;
10683
+ const mcpTools = await client.getEnabledToolsAsync();
10684
+ cachedCodeModeTool = buildCodeModeTool(client, {
10685
+ tools: mcpTools,
10686
+ providerTokens: options?.providerTokens,
10687
+ context: options?.context,
10688
+ integrationIds: client.__oauthConfig?.integrations?.map((i) => i.id)
10689
+ });
10690
+ return cachedCodeModeTool;
10691
+ };
10115
10692
  const toolUseBlocks = messageContent.filter((block) => block.type === "tool_use" && ("id" in block) && ("name" in block) && ("input" in block));
10116
10693
  for (const toolUse of toolUseBlocks) {
10117
10694
  try {
10118
10695
  let result;
10119
- if (triggerTools && triggerTools[toolUse.name]) {
10696
+ if (toolUse.name === CODE_MODE_TOOL_NAME) {
10697
+ const codeTool = await getCodeModeTool();
10698
+ result = await codeTool.execute(toolUse.input);
10699
+ } else if (triggerTools && triggerTools[toolUse.name]) {
10120
10700
  result = await triggerTools[toolUse.name].execute(toolUse.input);
10121
10701
  } else {
10122
10702
  result = await executeToolWithToken(client, toolUse.name, toolUse.input, options);
@@ -10149,7 +10729,24 @@ async function getAnthropicTools(client, options) {
10149
10729
  const finalOptions = providerTokens ? { ...options, providerTokens } : options;
10150
10730
  await ensureClientConnected(client);
10151
10731
  const mcpTools = await client.getEnabledToolsAsync();
10152
- const anthropicTools = mcpTools.map((mcpTool) => convertMCPToolToAnthropic(mcpTool, client, finalOptions));
10732
+ const mode = options?.mode ?? "code";
10733
+ const anthropicTools = mode === "code" ? (() => {
10734
+ const codeTool = buildCodeModeTool(client, {
10735
+ tools: mcpTools,
10736
+ providerTokens,
10737
+ context: options?.context,
10738
+ integrationIds: client.__oauthConfig?.integrations?.map((i) => i.id)
10739
+ });
10740
+ return [{
10741
+ name: CODE_MODE_TOOL_NAME,
10742
+ description: codeTool.description,
10743
+ input_schema: {
10744
+ type: "object",
10745
+ properties: codeTool.parameters.properties,
10746
+ required: [...codeTool.parameters.required]
10747
+ }
10748
+ }];
10749
+ })() : mcpTools.map((mcpTool) => convertMCPToolToAnthropic(mcpTool, client, finalOptions));
10153
10750
  const triggerConfig = client.__triggerConfig;
10154
10751
  if (triggerConfig) {
10155
10752
  const triggerTools = createTriggerTools(triggerConfig, options?.context);
@@ -10194,6 +10791,7 @@ async function handleAnthropicMessage(client, message, options) {
10194
10791
  var init_anthropic = __esm(() => {
10195
10792
  init_utils();
10196
10793
  init_trigger_tools();
10794
+ init_tool_builder();
10197
10795
  init_esm();
10198
10796
  });
10199
10797
 
@@ -10279,13 +10877,29 @@ async function executeGoogleFunctionCalls(client, functionCalls, options) {
10279
10877
  const finalOptions = providerTokens ? { ...options, providerTokens } : options;
10280
10878
  const triggerConfig = client.__triggerConfig;
10281
10879
  const triggerTools = triggerConfig ? createTriggerTools(triggerConfig, options?.context) : null;
10880
+ let cachedCodeModeTool = null;
10881
+ const getCodeModeTool = async () => {
10882
+ if (cachedCodeModeTool)
10883
+ return cachedCodeModeTool;
10884
+ const mcpTools = await client.getEnabledToolsAsync();
10885
+ cachedCodeModeTool = buildCodeModeTool(client, {
10886
+ tools: mcpTools,
10887
+ providerTokens: finalOptions?.providerTokens,
10888
+ context: options?.context,
10889
+ integrationIds: client.__oauthConfig?.integrations?.map((i) => i.id)
10890
+ });
10891
+ return cachedCodeModeTool;
10892
+ };
10282
10893
  const results = await Promise.all(functionCalls.map(async (call) => {
10283
10894
  if (!call?.name) {
10284
10895
  throw new Error("Function call must have a name");
10285
10896
  }
10286
10897
  const args = call.args || {};
10287
10898
  let result;
10288
- if (triggerTools && triggerTools[call.name]) {
10899
+ if (call.name === CODE_MODE_TOOL_NAME) {
10900
+ const codeTool = await getCodeModeTool();
10901
+ result = await codeTool.execute(args);
10902
+ } else if (triggerTools && triggerTools[call.name]) {
10289
10903
  result = await triggerTools[call.name].execute(args);
10290
10904
  } else {
10291
10905
  result = await executeToolWithToken(client, call.name, args, finalOptions);
@@ -10304,7 +10918,33 @@ async function getGoogleTools(client, options) {
10304
10918
  const finalOptions = providerTokens ? { ...options, providerTokens } : options;
10305
10919
  await ensureClientConnected(client);
10306
10920
  const mcpTools = await client.getEnabledToolsAsync();
10307
- const googleTools = await Promise.all(mcpTools.map((mcpTool) => convertMCPToolToGoogle(mcpTool, client, finalOptions)));
10921
+ const mode = options?.mode ?? "code";
10922
+ let googleTools;
10923
+ if (mode === "code") {
10924
+ const TypeEnum = await getGoogleType();
10925
+ const codeTool = buildCodeModeTool(client, {
10926
+ tools: mcpTools,
10927
+ providerTokens,
10928
+ context: options?.context,
10929
+ integrationIds: client.__oauthConfig?.integrations?.map((i) => i.id)
10930
+ });
10931
+ googleTools = [{
10932
+ name: CODE_MODE_TOOL_NAME,
10933
+ description: codeTool.description,
10934
+ parameters: {
10935
+ type: TypeEnum.OBJECT,
10936
+ properties: {
10937
+ code: {
10938
+ type: TypeEnum.STRING,
10939
+ description: codeTool.parameters.properties.code.description
10940
+ }
10941
+ },
10942
+ required: ["code"]
10943
+ }
10944
+ }];
10945
+ } else {
10946
+ googleTools = await Promise.all(mcpTools.map((mcpTool) => convertMCPToolToGoogle(mcpTool, client, finalOptions)));
10947
+ }
10308
10948
  const triggerConfig = client.__triggerConfig;
10309
10949
  if (triggerConfig) {
10310
10950
  const triggerTools = createTriggerTools(triggerConfig, options?.context);
@@ -10382,6 +11022,7 @@ function convertJsonSchemaToGoogleSchema(jsonSchema, TypeEnum) {
10382
11022
  var init_google = __esm(() => {
10383
11023
  init_utils();
10384
11024
  init_trigger_tools();
11025
+ init_tool_builder();
10385
11026
  init_esm();
10386
11027
  });
10387
11028
 
@@ -10447,8 +11088,8 @@ var init_webhooks = __esm(() => {
10447
11088
  var MAX_TRIGGER_STEPS = 20, WEBHOOK_DELIVERY_TIMEOUT_MS = 1e4;
10448
11089
 
10449
11090
  // src/triggers/executor.ts
10450
- var exports_executor = {};
10451
- __export(exports_executor, {
11091
+ var exports_executor2 = {};
11092
+ __export(exports_executor2, {
10452
11093
  executeTrigger: () => executeTrigger
10453
11094
  });
10454
11095
  async function executeTrigger(trigger, config, context) {
@@ -10595,7 +11236,7 @@ async function executeTrigger(trigger, config, context) {
10595
11236
  return { success: false, steps, error: limitError };
10596
11237
  }
10597
11238
  var logger31;
10598
- var init_executor = __esm(() => {
11239
+ var init_executor2 = __esm(() => {
10599
11240
  init_logger();
10600
11241
  init_utils2();
10601
11242
  init_webhooks();
@@ -10740,7 +11381,8 @@ function createMCPServer(config) {
10740
11381
  integrations: updatedIntegrations,
10741
11382
  getSessionContext: config.getSessionContext,
10742
11383
  setProviderToken: config.setProviderToken,
10743
- removeProviderToken: config.removeProviderToken
11384
+ removeProviderToken: config.removeProviderToken,
11385
+ codeMode: config.codeMode
10744
11386
  };
10745
11387
  client.__triggerConfig = config.triggers ? {
10746
11388
  callbacks: config.triggers,
@@ -10810,8 +11452,21 @@ function createMCPServer(config) {
10810
11452
  if (action === "mcp" && method === "POST") {
10811
11453
  try {
10812
11454
  const body = await webRequest.json();
10813
- const authHeader = webRequest.headers.get("authorization");
11455
+ let authHeader = webRequest.headers.get("authorization");
10814
11456
  const integrationsHeader = webRequest.headers.get("x-integrations");
11457
+ if (!authHeader) {
11458
+ const tokensHeader = webRequest.headers.get("x-integrate-tokens");
11459
+ const toolName = typeof body?.name === "string" ? body.name : "";
11460
+ if (tokensHeader && toolName) {
11461
+ try {
11462
+ const tokens = JSON.parse(tokensHeader);
11463
+ const provider = toolName.split("_")[0];
11464
+ if (provider && tokens[provider]) {
11465
+ authHeader = `Bearer ${tokens[provider]}`;
11466
+ }
11467
+ } catch {}
11468
+ }
11469
+ }
10815
11470
  const { OAuthHandler: OAuthHandler2 } = await Promise.resolve().then(() => (init_base_handler(), exports_base_handler));
10816
11471
  const oauthHandler = new OAuthHandler2({
10817
11472
  providers,
@@ -10832,6 +11487,53 @@ function createMCPServer(config) {
10832
11487
  return Response.json({ error: error.message || "Failed to execute tool call" }, { status: error.statusCode || 500 });
10833
11488
  }
10834
11489
  }
11490
+ if (action === "code" && method === "POST") {
11491
+ try {
11492
+ const body = await webRequest.json();
11493
+ if (typeof body?.code !== "string" || body.code.length === 0) {
11494
+ return Response.json({ error: "`code` is required and must be a non-empty string." }, { status: 400 });
11495
+ }
11496
+ const { executeSandboxCode: executeSandboxCode2 } = await Promise.resolve().then(() => (init_executor(), exports_executor));
11497
+ const codeModeConfig = config.codeMode ?? {};
11498
+ const publicUrl = codeModeConfig.publicUrl ?? getEnv("INTEGRATE_PUBLIC_URL");
11499
+ if (!publicUrl) {
11500
+ return Response.json({
11501
+ error: "Code Mode requires `codeMode.publicUrl` in createMCPServer config (or the INTEGRATE_PUBLIC_URL env var). Set it to the public origin where /api/integrate/mcp is reachable."
11502
+ }, { status: 500 });
11503
+ }
11504
+ let contextOverride = body.context;
11505
+ if (!contextOverride && config.getSessionContext) {
11506
+ try {
11507
+ contextOverride = await config.getSessionContext(webRequest);
11508
+ } catch {}
11509
+ }
11510
+ let providerTokens = body.providerTokens;
11511
+ if (!providerTokens) {
11512
+ const headerTokens = webRequest.headers.get("x-integrate-tokens");
11513
+ if (headerTokens) {
11514
+ try {
11515
+ providerTokens = JSON.parse(headerTokens);
11516
+ } catch {}
11517
+ }
11518
+ }
11519
+ const integrationIds = updatedIntegrations.map((i) => i.id);
11520
+ const result = await executeSandboxCode2({
11521
+ code: body.code,
11522
+ mcpUrl: publicUrl.replace(/\/$/, "") + "/api/integrate/mcp",
11523
+ providerTokens,
11524
+ context: contextOverride,
11525
+ integrationsHeader: integrationIds.join(","),
11526
+ runtime: codeModeConfig.runtime,
11527
+ timeoutMs: codeModeConfig.timeoutMs,
11528
+ vcpus: codeModeConfig.vcpus,
11529
+ networkPolicy: codeModeConfig.networkPolicy
11530
+ });
11531
+ return Response.json(result, { status: result.success ? 200 : 500 });
11532
+ } catch (error) {
11533
+ logger32.error("[Code Mode] Error:", error);
11534
+ return Response.json({ error: error?.message || "Failed to execute code" }, { status: 500 });
11535
+ }
11536
+ }
10835
11537
  if (action === "integrations" && method === "GET") {
10836
11538
  const integrations = updatedIntegrations.map((integration) => ({
10837
11539
  id: integration.id,
@@ -10867,7 +11569,7 @@ function createMCPServer(config) {
10867
11569
  return Response.json({ error: "Trigger has no provider configured" }, { status: 400 });
10868
11570
  }
10869
11571
  const triggerContext = trigger.userId ? { userId: trigger.userId } : undefined;
10870
- const { executeTrigger: executeTrigger2 } = await Promise.resolve().then(() => (init_executor(), exports_executor));
11572
+ const { executeTrigger: executeTrigger2 } = await Promise.resolve().then(() => (init_executor2(), exports_executor2));
10871
11573
  const { OAuthHandler: OAuthHandler2 } = await Promise.resolve().then(() => (init_base_handler(), exports_base_handler));
10872
11574
  const oauthHandler = new OAuthHandler2({
10873
11575
  providers,
@@ -11030,7 +11732,7 @@ function createMCPServer(config) {
11030
11732
  if (!trigger.provider) {
11031
11733
  return Response.json({ error: "Trigger has no provider configured" }, { status: 400 });
11032
11734
  }
11033
- const { executeTrigger: executeTrigger2 } = await Promise.resolve().then(() => (init_executor(), exports_executor));
11735
+ const { executeTrigger: executeTrigger2 } = await Promise.resolve().then(() => (init_executor2(), exports_executor2));
11034
11736
  const { OAuthHandler: OAuthHandler2 } = await Promise.resolve().then(() => (init_base_handler(), exports_base_handler));
11035
11737
  const oauthHandler = new OAuthHandler2({
11036
11738
  providers,
@@ -12106,6 +12808,10 @@ class OAuthHandler {
12106
12808
  });
12107
12809
  if (!response.ok) {
12108
12810
  const error = await response.text();
12811
+ const lowerError = error.toLowerCase();
12812
+ if (lowerError.includes("not supported") || lowerError.includes("unsupported")) {
12813
+ throw new Error(`Token refresh not supported: ${error}`);
12814
+ }
12109
12815
  throw new Error(`Token refresh failed: ${error}`);
12110
12816
  }
12111
12817
  const data = await response.json();
@@ -12228,7 +12934,11 @@ async function POST2(req, context) {
12228
12934
  }
12229
12935
  return createErrorResponse(`Unknown action: ${action}`, 404);
12230
12936
  } catch (error) {
12231
- logger34.error(`[OAuth ${action}] Error:`, error);
12937
+ if (action === "refresh" && error.message?.toLowerCase().includes("not supported")) {
12938
+ logger34.info(`[OAuth ${action}] Not supported for this provider:`, error.message);
12939
+ } else {
12940
+ logger34.error(`[OAuth ${action}] Error:`, error);
12941
+ }
12232
12942
  return createErrorResponse(error.message, 500);
12233
12943
  }
12234
12944
  }