integrate-sdk 0.9.3-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 (62) hide show
  1. package/dist/adapters/auto-routes.js +713 -15
  2. package/dist/adapters/index.js +713 -15
  3. package/dist/adapters/nextjs.js +713 -15
  4. package/dist/adapters/node.js +713 -15
  5. package/dist/adapters/svelte-kit.js +713 -15
  6. package/dist/adapters/tanstack-start.js +713 -15
  7. package/dist/ai/anthropic.d.ts +11 -0
  8. package/dist/ai/anthropic.d.ts.map +1 -1
  9. package/dist/ai/anthropic.js +552 -2
  10. package/dist/ai/google.d.ts +11 -0
  11. package/dist/ai/google.d.ts.map +1 -1
  12. package/dist/ai/google.js +561 -2
  13. package/dist/ai/index.js +648 -8
  14. package/dist/ai/openai.d.ts +11 -0
  15. package/dist/ai/openai.d.ts.map +1 -1
  16. package/dist/ai/openai.js +550 -2
  17. package/dist/ai/vercel-ai.d.ts +13 -0
  18. package/dist/ai/vercel-ai.d.ts.map +1 -1
  19. package/dist/ai/vercel-ai.js +536 -2
  20. package/dist/code-mode/executor.d.ts +99 -0
  21. package/dist/code-mode/executor.d.ts.map +1 -0
  22. package/dist/code-mode/executor.js +207 -0
  23. package/dist/code-mode/index.d.ts +12 -0
  24. package/dist/code-mode/index.d.ts.map +1 -0
  25. package/dist/code-mode/index.js +527 -0
  26. package/dist/code-mode/runtime-stub.d.ts +16 -0
  27. package/dist/code-mode/runtime-stub.d.ts.map +1 -0
  28. package/dist/code-mode/runtime-stub.js +72 -0
  29. package/dist/code-mode/tool-builder.d.ts +83 -0
  30. package/dist/code-mode/tool-builder.d.ts.map +1 -0
  31. package/dist/code-mode/tool-builder.js +524 -0
  32. package/dist/code-mode/type-generator.d.ts +22 -0
  33. package/dist/code-mode/type-generator.d.ts.map +1 -0
  34. package/dist/code-mode/type-generator.js +217 -0
  35. package/dist/index.js +713 -15
  36. package/dist/oauth.js +713 -15
  37. package/dist/server.d.ts +1 -0
  38. package/dist/server.d.ts.map +1 -1
  39. package/dist/server.js +724 -16
  40. package/dist/src/ai/anthropic.d.ts +11 -0
  41. package/dist/src/ai/anthropic.d.ts.map +1 -1
  42. package/dist/src/ai/google.d.ts +11 -0
  43. package/dist/src/ai/google.d.ts.map +1 -1
  44. package/dist/src/ai/openai.d.ts +11 -0
  45. package/dist/src/ai/openai.d.ts.map +1 -1
  46. package/dist/src/ai/vercel-ai.d.ts +13 -0
  47. package/dist/src/ai/vercel-ai.d.ts.map +1 -1
  48. package/dist/src/code-mode/executor.d.ts +99 -0
  49. package/dist/src/code-mode/executor.d.ts.map +1 -0
  50. package/dist/src/code-mode/index.d.ts +12 -0
  51. package/dist/src/code-mode/index.d.ts.map +1 -0
  52. package/dist/src/code-mode/runtime-stub.d.ts +16 -0
  53. package/dist/src/code-mode/runtime-stub.d.ts.map +1 -0
  54. package/dist/src/code-mode/tool-builder.d.ts +83 -0
  55. package/dist/src/code-mode/tool-builder.d.ts.map +1 -0
  56. package/dist/src/code-mode/type-generator.d.ts +22 -0
  57. package/dist/src/code-mode/type-generator.d.ts.map +1 -0
  58. package/dist/src/config/types.d.ts +55 -0
  59. package/dist/src/config/types.d.ts.map +1 -1
  60. package/dist/src/server.d.ts.map +1 -1
  61. package/package.json +15 -6
  62. package/server.ts +9 -0
package/dist/index.js CHANGED
@@ -416,10 +416,17 @@ var init_errors = __esm(() => {
416
416
  function camelToSnake(str) {
417
417
  return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
418
418
  }
419
+ function snakeToCamel(str) {
420
+ return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
421
+ }
419
422
  function methodToToolName(methodName, integrationId) {
420
423
  const snakeCaseMethod = camelToSnake(methodName);
421
424
  return `${integrationId}_${snakeCaseMethod}`;
422
425
  }
426
+ function toolNameToMethod(toolName) {
427
+ const withoutPrefix = toolName.replace(/^[^_]+_/, "");
428
+ return snakeToCamel(withoutPrefix);
429
+ }
423
430
 
424
431
  // src/triggers/client.ts
425
432
  class TriggerClient {
@@ -8723,6 +8730,508 @@ var init_trigger_tools = __esm(() => {
8723
8730
  init_utils2();
8724
8731
  });
8725
8732
 
8733
+ // src/code-mode/type-generator.ts
8734
+ function safeIdent(name) {
8735
+ if (!/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name) || RESERVED_TS.has(name)) {
8736
+ return JSON.stringify(name);
8737
+ }
8738
+ return name;
8739
+ }
8740
+ function integrationFromToolName(toolName) {
8741
+ const idx = toolName.indexOf("_");
8742
+ return idx === -1 ? toolName : toolName.slice(0, idx);
8743
+ }
8744
+ function jsonSchemaToTs(schema, indent) {
8745
+ if (!schema || typeof schema !== "object")
8746
+ return "unknown";
8747
+ const s = schema;
8748
+ if (Array.isArray(s.enum) && s.enum.length > 0) {
8749
+ return s.enum.map((v) => typeof v === "string" ? JSON.stringify(v) : typeof v === "number" || typeof v === "boolean" ? String(v) : "unknown").join(" | ");
8750
+ }
8751
+ if (Array.isArray(s.type)) {
8752
+ return s.type.map((t2) => jsonSchemaToTs({ ...s, type: t2 }, indent)).join(" | ");
8753
+ }
8754
+ const t = s.type;
8755
+ switch (t) {
8756
+ case "string":
8757
+ return "string";
8758
+ case "number":
8759
+ case "integer":
8760
+ return "number";
8761
+ case "boolean":
8762
+ return "boolean";
8763
+ case "null":
8764
+ return "null";
8765
+ case "array": {
8766
+ const items = s.items;
8767
+ if (Array.isArray(items))
8768
+ return "unknown[]";
8769
+ const inner = jsonSchemaToTs(items, indent);
8770
+ return /[|&]/.test(inner) ? `Array<${inner}>` : `${inner}[]`;
8771
+ }
8772
+ case "object":
8773
+ return objectShape(s, indent);
8774
+ default:
8775
+ if (s.properties && typeof s.properties === "object")
8776
+ return objectShape(s, indent);
8777
+ return "unknown";
8778
+ }
8779
+ }
8780
+ function objectShape(schema, indent) {
8781
+ const props = schema.properties && typeof schema.properties === "object" ? schema.properties : {};
8782
+ const keys = Object.keys(props);
8783
+ if (keys.length === 0) {
8784
+ return schema.additionalProperties === false ? "Record<string, never>" : "Record<string, unknown>";
8785
+ }
8786
+ const required = new Set(Array.isArray(schema.required) ? schema.required : []);
8787
+ const inner = indent + " ";
8788
+ const lines = ["{"];
8789
+ for (const key of keys) {
8790
+ const prop = props[key];
8791
+ const desc = prop && typeof prop.description === "string" ? prop.description : undefined;
8792
+ if (desc)
8793
+ lines.push(`${inner}/** ${desc.replace(/\*\//g, "*\\/")} */`);
8794
+ const optional = required.has(key) ? "" : "?";
8795
+ const type = jsonSchemaToTs(prop, inner);
8796
+ lines.push(`${inner}${safeIdent(key)}${optional}: ${type};`);
8797
+ }
8798
+ lines.push(`${indent}}`);
8799
+ return lines.join(`
8800
+ `);
8801
+ }
8802
+ function argsType(schema) {
8803
+ if (!schema)
8804
+ return "Record<string, unknown>";
8805
+ const hasProps = schema.properties && Object.keys(schema.properties).length > 0;
8806
+ if (!hasProps)
8807
+ return "Record<string, unknown>";
8808
+ return objectShape(schema, " ");
8809
+ }
8810
+ function methodHasRequiredArgs(schema) {
8811
+ if (!schema || !schema.properties)
8812
+ return false;
8813
+ const req = Array.isArray(schema.required) ? schema.required : [];
8814
+ return req.length > 0;
8815
+ }
8816
+ function formatDescription(desc, indent) {
8817
+ if (!desc)
8818
+ return "";
8819
+ const cleaned = desc.replace(/\*\//g, "*\\/").trim();
8820
+ if (!cleaned.includes(`
8821
+ `))
8822
+ return `${indent}/** ${cleaned} */
8823
+ `;
8824
+ const lines = cleaned.split(`
8825
+ `).map((l) => `${indent} * ${l}`).join(`
8826
+ `);
8827
+ return `${indent}/**
8828
+ ${lines}
8829
+ ${indent} */
8830
+ `;
8831
+ }
8832
+ function generateCodeModeTypes(tools) {
8833
+ const byIntegration = {};
8834
+ for (const tool of tools) {
8835
+ const integration = integrationFromToolName(tool.name);
8836
+ (byIntegration[integration] ??= []).push(tool);
8837
+ }
8838
+ const methodMap = {};
8839
+ const integrationCounts = {};
8840
+ const sections = [];
8841
+ const integrationIds = Object.keys(byIntegration).sort();
8842
+ sections.push("/**");
8843
+ sections.push(" * Integrate SDK — available APIs inside `execute_code`.");
8844
+ sections.push(" * Every method is async and returns the MCP tool-call response.");
8845
+ sections.push(" * Call them via the exported `client` object, e.g.");
8846
+ sections.push(" * const repos = await client.github.listRepos();");
8847
+ sections.push(" */");
8848
+ sections.push("");
8849
+ for (const integrationId of integrationIds) {
8850
+ const integrationTools = byIntegration[integrationId].slice().sort((a, b) => a.name.localeCompare(b.name));
8851
+ integrationCounts[integrationId] = integrationTools.length;
8852
+ const interfaceName = pascalCase(integrationId) + "Client";
8853
+ sections.push(`export interface ${interfaceName} {`);
8854
+ for (const tool of integrationTools) {
8855
+ const methodName = toolNameToMethod(tool.name);
8856
+ methodMap[`${integrationId}.${methodName}`] = tool.name;
8857
+ sections.push(formatDescription(tool.description, " "));
8858
+ const argType = argsType(tool.inputSchema);
8859
+ const argIsOptional = !methodHasRequiredArgs(tool.inputSchema);
8860
+ const paramName = argIsOptional ? "args?" : "args";
8861
+ sections.push(` ${safeIdent(methodName)}(${paramName}: ${argType}): Promise<ToolResult>;`);
8862
+ }
8863
+ sections.push("}");
8864
+ sections.push("");
8865
+ }
8866
+ sections.push("export interface ToolResult {");
8867
+ sections.push(" content: Array<{ type: 'text' | 'image' | 'resource'; text?: string; data?: string; mimeType?: string; [key: string]: unknown }>;");
8868
+ sections.push(" isError?: boolean;");
8869
+ sections.push(" structuredContent?: Record<string, unknown>;");
8870
+ sections.push("}");
8871
+ sections.push("");
8872
+ sections.push("export interface Client {");
8873
+ for (const integrationId of integrationIds) {
8874
+ const interfaceName = pascalCase(integrationId) + "Client";
8875
+ sections.push(` ${safeIdent(integrationId)}: ${interfaceName};`);
8876
+ }
8877
+ sections.push("}");
8878
+ sections.push("");
8879
+ sections.push("export declare const client: Client;");
8880
+ return {
8881
+ source: sections.filter((line, idx, arr) => !(line === "" && arr[idx - 1] === "")).join(`
8882
+ `),
8883
+ methodMap,
8884
+ integrationCounts
8885
+ };
8886
+ }
8887
+ function pascalCase(id) {
8888
+ return id.split(/[^A-Za-z0-9]/).filter(Boolean).map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join("") || "Unknown";
8889
+ }
8890
+ var RESERVED_TS;
8891
+ var init_type_generator = __esm(() => {
8892
+ RESERVED_TS = new Set([
8893
+ "break",
8894
+ "case",
8895
+ "catch",
8896
+ "class",
8897
+ "const",
8898
+ "continue",
8899
+ "debugger",
8900
+ "default",
8901
+ "delete",
8902
+ "do",
8903
+ "else",
8904
+ "enum",
8905
+ "export",
8906
+ "extends",
8907
+ "false",
8908
+ "finally",
8909
+ "for",
8910
+ "function",
8911
+ "if",
8912
+ "import",
8913
+ "in",
8914
+ "instanceof",
8915
+ "new",
8916
+ "null",
8917
+ "return",
8918
+ "super",
8919
+ "switch",
8920
+ "this",
8921
+ "throw",
8922
+ "true",
8923
+ "try",
8924
+ "typeof",
8925
+ "var",
8926
+ "void",
8927
+ "while",
8928
+ "with",
8929
+ "as",
8930
+ "implements",
8931
+ "interface",
8932
+ "let",
8933
+ "package",
8934
+ "private",
8935
+ "protected",
8936
+ "public",
8937
+ "static",
8938
+ "yield"
8939
+ ]);
8940
+ });
8941
+
8942
+ // src/code-mode/runtime-stub.ts
8943
+ var RUNTIME_STUB_SOURCE = `// runtime.mjs — generated by integrate-sdk code mode
8944
+ const MCP_URL = process.env.INTEGRATE_MCP_URL;
8945
+ const SESSION_TOKEN = process.env.INTEGRATE_SESSION_TOKEN;
8946
+ const PROVIDER_TOKENS = process.env.INTEGRATE_PROVIDER_TOKENS || '';
8947
+ const INTEGRATIONS_HEADER = process.env.INTEGRATE_INTEGRATIONS || '';
8948
+ const CONTEXT_JSON = process.env.INTEGRATE_CONTEXT || '';
8949
+
8950
+ if (!MCP_URL) {
8951
+ throw new Error('INTEGRATE_MCP_URL is not set — the sandbox cannot reach the MCP route.');
8952
+ }
8953
+
8954
+ function camelToSnake(str) {
8955
+ return str.replace(/[A-Z]/g, (letter) => '_' + letter.toLowerCase());
8956
+ }
8957
+
8958
+ async function callTool(toolName, args) {
8959
+ const headers = {
8960
+ 'Content-Type': 'application/json',
8961
+ 'x-integrate-code-mode': '1',
8962
+ };
8963
+ if (SESSION_TOKEN) headers['Authorization'] = 'Bearer ' + SESSION_TOKEN;
8964
+ if (PROVIDER_TOKENS) headers['x-integrate-tokens'] = PROVIDER_TOKENS;
8965
+ if (INTEGRATIONS_HEADER) headers['x-integrations'] = INTEGRATIONS_HEADER;
8966
+ if (CONTEXT_JSON) headers['x-integrate-context'] = CONTEXT_JSON;
8967
+
8968
+ const res = await fetch(MCP_URL, {
8969
+ method: 'POST',
8970
+ headers,
8971
+ body: JSON.stringify({ name: toolName, arguments: args || {} }),
8972
+ });
8973
+
8974
+ const text = await res.text();
8975
+ let payload;
8976
+ try {
8977
+ payload = text ? JSON.parse(text) : null;
8978
+ } catch {
8979
+ payload = { content: [{ type: 'text', text }] };
8980
+ }
8981
+
8982
+ if (!res.ok) {
8983
+ const message = (payload && (payload.error || payload.message)) || 'Tool call failed: HTTP ' + res.status;
8984
+ const err = new Error(message);
8985
+ err.status = res.status;
8986
+ err.toolName = toolName;
8987
+ throw err;
8988
+ }
8989
+
8990
+ return payload;
8991
+ }
8992
+
8993
+ function createIntegrationProxy(integrationId) {
8994
+ return new Proxy({}, {
8995
+ get(_target, methodName) {
8996
+ if (typeof methodName !== 'string') return undefined;
8997
+ return (args) => callTool(integrationId + '_' + camelToSnake(methodName), args);
8998
+ },
8999
+ });
9000
+ }
9001
+
9002
+ export const client = new Proxy({}, {
9003
+ get(_target, integrationId) {
9004
+ if (typeof integrationId !== 'string') return undefined;
9005
+ return createIntegrationProxy(integrationId);
9006
+ },
9007
+ });
9008
+
9009
+ export { callTool };
9010
+ `;
9011
+
9012
+ // src/code-mode/executor.ts
9013
+ var exports_executor = {};
9014
+ __export(exports_executor, {
9015
+ executeSandboxCode: () => executeSandboxCode,
9016
+ __setSandboxFactoryForTests: () => __setSandboxFactoryForTests
9017
+ });
9018
+ function __setSandboxFactoryForTests(factory) {
9019
+ sandboxFactoryOverride = factory;
9020
+ }
9021
+ async function loadSandboxFactory() {
9022
+ if (sandboxFactoryOverride)
9023
+ return sandboxFactoryOverride;
9024
+ try {
9025
+ const dynamicImport = new Function("specifier", "return import(specifier)");
9026
+ const pkg = "@" + "vercel/sandbox";
9027
+ const mod = await dynamicImport(pkg);
9028
+ return mod.Sandbox ?? mod.default?.Sandbox ?? mod;
9029
+ } catch (err) {
9030
+ throw new Error("Code Mode requires the optional peer dependency `@vercel/sandbox`. " + "Install it with `npm install @vercel/sandbox` (or `bun add @vercel/sandbox`).");
9031
+ }
9032
+ }
9033
+ function wrapUserCode(code) {
9034
+ return `// user.mjs — wrapped by integrate-sdk code mode
9035
+ import { client, callTool } from './runtime.mjs';
9036
+
9037
+ (async () => {
9038
+ try {
9039
+ const __result = await (async () => {
9040
+ ${code}
9041
+ })();
9042
+ if (typeof __result !== 'undefined') {
9043
+ process.stdout.write('\\n' + ${JSON.stringify(RESULT_SENTINEL)} + JSON.stringify(__result) + '\\n');
9044
+ }
9045
+ } catch (err) {
9046
+ const payload = {
9047
+ message: err && err.message ? err.message : String(err),
9048
+ name: err && err.name,
9049
+ stack: err && err.stack,
9050
+ toolName: err && err.toolName,
9051
+ status: err && err.status,
9052
+ };
9053
+ process.stderr.write('\\n' + ${JSON.stringify(RESULT_SENTINEL)} + JSON.stringify({ error: payload }) + '\\n');
9054
+ process.exit(1);
9055
+ }
9056
+ })();
9057
+ `;
9058
+ }
9059
+ function defaultNetworkPolicy(mcpUrl) {
9060
+ try {
9061
+ const host = new URL(mcpUrl).hostname;
9062
+ return { allow: [host] };
9063
+ } catch {
9064
+ return { allow: [] };
9065
+ }
9066
+ }
9067
+ function extractResult(stream) {
9068
+ const idx = stream.lastIndexOf(RESULT_SENTINEL);
9069
+ if (idx === -1)
9070
+ return { cleaned: stream };
9071
+ const before = stream.slice(0, idx).replace(/\n$/, "");
9072
+ const rest = stream.slice(idx + RESULT_SENTINEL.length);
9073
+ const newlineIdx = rest.indexOf(`
9074
+ `);
9075
+ const payload = newlineIdx === -1 ? rest : rest.slice(0, newlineIdx);
9076
+ const after = newlineIdx === -1 ? "" : rest.slice(newlineIdx + 1);
9077
+ try {
9078
+ return { cleaned: (before + after).trimEnd(), result: JSON.parse(payload) };
9079
+ } catch {
9080
+ return { cleaned: stream };
9081
+ }
9082
+ }
9083
+ async function executeSandboxCode(options) {
9084
+ const startedAt = Date.now();
9085
+ const runtime = options.runtime ?? "node22";
9086
+ const timeoutMs = options.timeoutMs ?? 60000;
9087
+ const networkPolicy = options.networkPolicy ?? defaultNetworkPolicy(options.mcpUrl);
9088
+ let sandbox = null;
9089
+ try {
9090
+ const Sandbox = await loadSandboxFactory();
9091
+ sandbox = await Sandbox.create({
9092
+ runtime,
9093
+ timeout: timeoutMs,
9094
+ resources: options.vcpus ? { vcpus: options.vcpus } : undefined,
9095
+ networkPolicy
9096
+ });
9097
+ const runtimeContent = Buffer.from(RUNTIME_STUB_SOURCE, "utf-8");
9098
+ const userContent = Buffer.from(wrapUserCode(options.code), "utf-8");
9099
+ await sandbox.writeFiles([
9100
+ { path: "runtime.mjs", content: runtimeContent },
9101
+ { path: "user.mjs", content: userContent }
9102
+ ]);
9103
+ const env = {
9104
+ INTEGRATE_MCP_URL: options.mcpUrl
9105
+ };
9106
+ if (options.sessionToken)
9107
+ env.INTEGRATE_SESSION_TOKEN = options.sessionToken;
9108
+ if (options.providerTokens && Object.keys(options.providerTokens).length > 0) {
9109
+ env.INTEGRATE_PROVIDER_TOKENS = JSON.stringify(options.providerTokens);
9110
+ }
9111
+ if (options.integrationsHeader)
9112
+ env.INTEGRATE_INTEGRATIONS = options.integrationsHeader;
9113
+ if (options.context)
9114
+ env.INTEGRATE_CONTEXT = JSON.stringify(options.context);
9115
+ const cmd = await sandbox.runCommand({
9116
+ cmd: "node",
9117
+ args: ["user.mjs"],
9118
+ env
9119
+ });
9120
+ const [stdoutRaw, stderrRaw] = await Promise.all([cmd.stdout(), cmd.stderr()]);
9121
+ const stdoutExtract = extractResult(stdoutRaw);
9122
+ const stderrExtract = extractResult(stderrRaw);
9123
+ return {
9124
+ success: cmd.exitCode === 0,
9125
+ exitCode: cmd.exitCode,
9126
+ result: stdoutExtract.result ?? stderrExtract.result,
9127
+ stdout: stdoutExtract.cleaned,
9128
+ stderr: stderrExtract.cleaned,
9129
+ durationMs: Date.now() - startedAt
9130
+ };
9131
+ } catch (err) {
9132
+ return {
9133
+ success: false,
9134
+ exitCode: -1,
9135
+ stdout: "",
9136
+ stderr: "",
9137
+ durationMs: Date.now() - startedAt,
9138
+ error: err instanceof Error ? err.message : String(err)
9139
+ };
9140
+ } finally {
9141
+ if (sandbox) {
9142
+ try {
9143
+ await sandbox.stop();
9144
+ } catch {}
9145
+ }
9146
+ }
9147
+ }
9148
+ var sandboxFactoryOverride = null, RESULT_SENTINEL = "__INTEGRATE_RESULT__";
9149
+ var init_executor = () => {};
9150
+
9151
+ // src/code-mode/tool-builder.ts
9152
+ function resolveCodeModeClientConfig(client) {
9153
+ const oauthConfig = client.__oauthConfig;
9154
+ return oauthConfig?.codeMode ?? {};
9155
+ }
9156
+ function buildCodeModeTool(client, options) {
9157
+ const { tools, providerTokens, context, integrationIds } = options;
9158
+ const generated = generateCodeModeTypes(tools);
9159
+ const serverCodeModeConfig = resolveCodeModeClientConfig(client);
9160
+ const sandboxOverrides = options.sandbox ?? {};
9161
+ const description = `${DEFAULT_INSTRUCTIONS}
9162
+
9163
+ \`\`\`typescript
9164
+ ${generated.source}
9165
+ \`\`\``;
9166
+ const execute = async ({ code }) => {
9167
+ const publicUrl = sandboxOverrides.publicUrl ?? serverCodeModeConfig.publicUrl ?? getEnv("INTEGRATE_PUBLIC_URL");
9168
+ if (!publicUrl) {
9169
+ return {
9170
+ success: false,
9171
+ exitCode: -1,
9172
+ stdout: "",
9173
+ stderr: "",
9174
+ durationMs: 0,
9175
+ 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."
9176
+ };
9177
+ }
9178
+ const mcpUrl = publicUrl.replace(/\/$/, "") + "/api/integrate/mcp";
9179
+ return executeSandboxCode({
9180
+ code,
9181
+ mcpUrl,
9182
+ providerTokens,
9183
+ context,
9184
+ integrationsHeader: integrationIds && integrationIds.length > 0 ? integrationIds.join(",") : undefined,
9185
+ runtime: sandboxOverrides.runtime ?? serverCodeModeConfig.runtime,
9186
+ timeoutMs: sandboxOverrides.timeoutMs ?? serverCodeModeConfig.timeoutMs,
9187
+ vcpus: sandboxOverrides.vcpus ?? serverCodeModeConfig.vcpus,
9188
+ networkPolicy: sandboxOverrides.networkPolicy ?? serverCodeModeConfig.networkPolicy
9189
+ });
9190
+ };
9191
+ return {
9192
+ name: CODE_MODE_TOOL_NAME,
9193
+ description,
9194
+ parameters: {
9195
+ type: "object",
9196
+ properties: {
9197
+ code: {
9198
+ type: "string",
9199
+ 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."
9200
+ }
9201
+ },
9202
+ required: ["code"],
9203
+ additionalProperties: false
9204
+ },
9205
+ execute
9206
+ };
9207
+ }
9208
+ var CODE_MODE_TOOL_NAME = "execute_code", DEFAULT_INSTRUCTIONS;
9209
+ var init_tool_builder = __esm(() => {
9210
+ init_type_generator();
9211
+ init_executor();
9212
+ DEFAULT_INSTRUCTIONS = [
9213
+ "You are given a single tool: `execute_code`. Instead of calling individual MCP tools,",
9214
+ "you write a short async TypeScript/JavaScript snippet that uses the typed `client`",
9215
+ "object below, and the snippet runs in an isolated sandbox which dispatches the actual",
9216
+ "tool calls. Chain multiple operations together in one snippet whenever possible —",
9217
+ "that is the whole point of this tool.",
9218
+ "",
9219
+ "Rules:",
9220
+ "- The snippet is the body of an `async` function. Use `await` freely.",
9221
+ "- Use `return <value>` at the end to hand a structured result back to the caller;",
9222
+ " the caller receives it as JSON.",
9223
+ "- Use `console.log(...)` for intermediate observations you want to read later.",
9224
+ "- Throw / let errors propagate; the runtime will surface them with a non-zero exit.",
9225
+ "- Each method call returns an object of shape `ToolResult` (see types below).",
9226
+ " The payload usually lives in `result.content[0].text` as JSON — parse it if needed.",
9227
+ "- You cannot import npm packages. Only the pre-imported `client` and standard",
9228
+ " globals (`fetch`, `console`, `JSON`, ...) are available.",
9229
+ "",
9230
+ "API surface:"
9231
+ ].join(`
9232
+ `);
9233
+ });
9234
+
8726
9235
  // src/ai/vercel-ai.ts
8727
9236
  function convertMCPToolToVercelAI(mcpTool, client, options) {
8728
9237
  return {
@@ -8747,8 +9256,25 @@ async function getVercelAITools(client, options) {
8747
9256
  await ensureClientConnected(client);
8748
9257
  const mcpTools = await client.getEnabledToolsAsync();
8749
9258
  const vercelTools = {};
8750
- for (const mcpTool of mcpTools) {
8751
- vercelTools[mcpTool.name] = convertMCPToolToVercelAI(mcpTool, client, finalOptions);
9259
+ const mode = options?.mode ?? "code";
9260
+ if (mode === "code") {
9261
+ const codeTool = buildCodeModeTool(client, {
9262
+ tools: mcpTools,
9263
+ providerTokens,
9264
+ context: options?.context,
9265
+ integrationIds: client.__oauthConfig?.integrations?.map((i) => i.id) ?? client.integrations?.map?.((i) => i.id)
9266
+ });
9267
+ vercelTools[CODE_MODE_TOOL_NAME] = {
9268
+ description: codeTool.description,
9269
+ inputSchema: exports_external.object({
9270
+ code: exports_external.string().describe(codeTool.parameters.properties.code.description)
9271
+ }),
9272
+ execute: async (args) => codeTool.execute(args)
9273
+ };
9274
+ } else {
9275
+ for (const mcpTool of mcpTools) {
9276
+ vercelTools[mcpTool.name] = convertMCPToolToVercelAI(mcpTool, client, finalOptions);
9277
+ }
8752
9278
  }
8753
9279
  const triggerConfig = client.__triggerConfig;
8754
9280
  if (triggerConfig) {
@@ -8758,8 +9284,10 @@ async function getVercelAITools(client, options) {
8758
9284
  return vercelTools;
8759
9285
  }
8760
9286
  var init_vercel_ai = __esm(() => {
9287
+ init_zod();
8761
9288
  init_utils();
8762
9289
  init_trigger_tools();
9290
+ init_tool_builder();
8763
9291
  });
8764
9292
 
8765
9293
  // node_modules/zod-to-json-schema/dist/esm/Options.js
@@ -10187,7 +10715,22 @@ async function getOpenAITools(client, options) {
10187
10715
  const finalOptions = providerTokens ? { ...options, providerTokens } : options;
10188
10716
  await ensureClientConnected(client);
10189
10717
  const mcpTools = await client.getEnabledToolsAsync();
10190
- const openaiTools = mcpTools.map((mcpTool) => convertMCPToolToOpenAI(mcpTool, client, finalOptions));
10718
+ const mode = options?.mode ?? "code";
10719
+ const openaiTools = mode === "code" ? (() => {
10720
+ const codeTool = buildCodeModeTool(client, {
10721
+ tools: mcpTools,
10722
+ providerTokens,
10723
+ context: options?.context,
10724
+ integrationIds: client.__oauthConfig?.integrations?.map((i) => i.id)
10725
+ });
10726
+ return [{
10727
+ type: "function",
10728
+ name: CODE_MODE_TOOL_NAME,
10729
+ description: codeTool.description,
10730
+ parameters: codeTool.parameters,
10731
+ strict: options?.strict ?? null
10732
+ }];
10733
+ })() : mcpTools.map((mcpTool) => convertMCPToolToOpenAI(mcpTool, client, finalOptions));
10191
10734
  const triggerConfig = client.__triggerConfig;
10192
10735
  if (triggerConfig) {
10193
10736
  const triggerTools = createTriggerTools(triggerConfig, options?.context);
@@ -10212,6 +10755,19 @@ async function handleOpenAIToolCalls(client, toolCalls, options) {
10212
10755
  const toolOutputs = [];
10213
10756
  const triggerConfig = client.__triggerConfig;
10214
10757
  const triggerTools = triggerConfig ? createTriggerTools(triggerConfig, options?.context) : null;
10758
+ let cachedCodeModeTool = null;
10759
+ const getCodeModeTool = async () => {
10760
+ if (cachedCodeModeTool)
10761
+ return cachedCodeModeTool;
10762
+ const mcpTools = await client.getEnabledToolsAsync();
10763
+ cachedCodeModeTool = buildCodeModeTool(client, {
10764
+ tools: mcpTools,
10765
+ providerTokens: options?.providerTokens,
10766
+ context: options?.context,
10767
+ integrationIds: client.__oauthConfig?.integrations?.map((i) => i.id)
10768
+ });
10769
+ return cachedCodeModeTool;
10770
+ };
10215
10771
  for (const output of toolCalls) {
10216
10772
  if (output.type === "function_call") {
10217
10773
  const toolCall = {
@@ -10222,7 +10778,10 @@ async function handleOpenAIToolCalls(client, toolCalls, options) {
10222
10778
  try {
10223
10779
  const args = JSON.parse(toolCall.arguments);
10224
10780
  let result;
10225
- if (triggerTools && triggerTools[toolCall.name]) {
10781
+ if (toolCall.name === CODE_MODE_TOOL_NAME) {
10782
+ const codeTool = await getCodeModeTool();
10783
+ result = await codeTool.execute(args);
10784
+ } else if (triggerTools && triggerTools[toolCall.name]) {
10226
10785
  result = await triggerTools[toolCall.name].execute(args);
10227
10786
  } else {
10228
10787
  result = await executeToolWithToken(client, toolCall.name, args, options);
@@ -10263,6 +10822,7 @@ async function handleOpenAIResponse(client, response, options) {
10263
10822
  var init_openai = __esm(() => {
10264
10823
  init_utils();
10265
10824
  init_trigger_tools();
10825
+ init_tool_builder();
10266
10826
  init_esm();
10267
10827
  });
10268
10828
 
@@ -10282,11 +10842,27 @@ async function handleAnthropicToolCalls(client, messageContent, options) {
10282
10842
  const toolResults = [];
10283
10843
  const triggerConfig = client.__triggerConfig;
10284
10844
  const triggerTools = triggerConfig ? createTriggerTools(triggerConfig, options?.context) : null;
10845
+ let cachedCodeModeTool = null;
10846
+ const getCodeModeTool = async () => {
10847
+ if (cachedCodeModeTool)
10848
+ return cachedCodeModeTool;
10849
+ const mcpTools = await client.getEnabledToolsAsync();
10850
+ cachedCodeModeTool = buildCodeModeTool(client, {
10851
+ tools: mcpTools,
10852
+ providerTokens: options?.providerTokens,
10853
+ context: options?.context,
10854
+ integrationIds: client.__oauthConfig?.integrations?.map((i) => i.id)
10855
+ });
10856
+ return cachedCodeModeTool;
10857
+ };
10285
10858
  const toolUseBlocks = messageContent.filter((block) => block.type === "tool_use" && ("id" in block) && ("name" in block) && ("input" in block));
10286
10859
  for (const toolUse of toolUseBlocks) {
10287
10860
  try {
10288
10861
  let result;
10289
- if (triggerTools && triggerTools[toolUse.name]) {
10862
+ if (toolUse.name === CODE_MODE_TOOL_NAME) {
10863
+ const codeTool = await getCodeModeTool();
10864
+ result = await codeTool.execute(toolUse.input);
10865
+ } else if (triggerTools && triggerTools[toolUse.name]) {
10290
10866
  result = await triggerTools[toolUse.name].execute(toolUse.input);
10291
10867
  } else {
10292
10868
  result = await executeToolWithToken(client, toolUse.name, toolUse.input, options);
@@ -10319,7 +10895,24 @@ async function getAnthropicTools(client, options) {
10319
10895
  const finalOptions = providerTokens ? { ...options, providerTokens } : options;
10320
10896
  await ensureClientConnected(client);
10321
10897
  const mcpTools = await client.getEnabledToolsAsync();
10322
- const anthropicTools = mcpTools.map((mcpTool) => convertMCPToolToAnthropic(mcpTool, client, finalOptions));
10898
+ const mode = options?.mode ?? "code";
10899
+ const anthropicTools = mode === "code" ? (() => {
10900
+ const codeTool = buildCodeModeTool(client, {
10901
+ tools: mcpTools,
10902
+ providerTokens,
10903
+ context: options?.context,
10904
+ integrationIds: client.__oauthConfig?.integrations?.map((i) => i.id)
10905
+ });
10906
+ return [{
10907
+ name: CODE_MODE_TOOL_NAME,
10908
+ description: codeTool.description,
10909
+ input_schema: {
10910
+ type: "object",
10911
+ properties: codeTool.parameters.properties,
10912
+ required: [...codeTool.parameters.required]
10913
+ }
10914
+ }];
10915
+ })() : mcpTools.map((mcpTool) => convertMCPToolToAnthropic(mcpTool, client, finalOptions));
10323
10916
  const triggerConfig = client.__triggerConfig;
10324
10917
  if (triggerConfig) {
10325
10918
  const triggerTools = createTriggerTools(triggerConfig, options?.context);
@@ -10364,6 +10957,7 @@ async function handleAnthropicMessage(client, message, options) {
10364
10957
  var init_anthropic = __esm(() => {
10365
10958
  init_utils();
10366
10959
  init_trigger_tools();
10960
+ init_tool_builder();
10367
10961
  init_esm();
10368
10962
  });
10369
10963
 
@@ -10449,13 +11043,29 @@ async function executeGoogleFunctionCalls(client, functionCalls, options) {
10449
11043
  const finalOptions = providerTokens ? { ...options, providerTokens } : options;
10450
11044
  const triggerConfig = client.__triggerConfig;
10451
11045
  const triggerTools = triggerConfig ? createTriggerTools(triggerConfig, options?.context) : null;
11046
+ let cachedCodeModeTool = null;
11047
+ const getCodeModeTool = async () => {
11048
+ if (cachedCodeModeTool)
11049
+ return cachedCodeModeTool;
11050
+ const mcpTools = await client.getEnabledToolsAsync();
11051
+ cachedCodeModeTool = buildCodeModeTool(client, {
11052
+ tools: mcpTools,
11053
+ providerTokens: finalOptions?.providerTokens,
11054
+ context: options?.context,
11055
+ integrationIds: client.__oauthConfig?.integrations?.map((i) => i.id)
11056
+ });
11057
+ return cachedCodeModeTool;
11058
+ };
10452
11059
  const results = await Promise.all(functionCalls.map(async (call) => {
10453
11060
  if (!call?.name) {
10454
11061
  throw new Error("Function call must have a name");
10455
11062
  }
10456
11063
  const args = call.args || {};
10457
11064
  let result;
10458
- if (triggerTools && triggerTools[call.name]) {
11065
+ if (call.name === CODE_MODE_TOOL_NAME) {
11066
+ const codeTool = await getCodeModeTool();
11067
+ result = await codeTool.execute(args);
11068
+ } else if (triggerTools && triggerTools[call.name]) {
10459
11069
  result = await triggerTools[call.name].execute(args);
10460
11070
  } else {
10461
11071
  result = await executeToolWithToken(client, call.name, args, finalOptions);
@@ -10474,7 +11084,33 @@ async function getGoogleTools(client, options) {
10474
11084
  const finalOptions = providerTokens ? { ...options, providerTokens } : options;
10475
11085
  await ensureClientConnected(client);
10476
11086
  const mcpTools = await client.getEnabledToolsAsync();
10477
- const googleTools = await Promise.all(mcpTools.map((mcpTool) => convertMCPToolToGoogle(mcpTool, client, finalOptions)));
11087
+ const mode = options?.mode ?? "code";
11088
+ let googleTools;
11089
+ if (mode === "code") {
11090
+ const TypeEnum = await getGoogleType();
11091
+ const codeTool = buildCodeModeTool(client, {
11092
+ tools: mcpTools,
11093
+ providerTokens,
11094
+ context: options?.context,
11095
+ integrationIds: client.__oauthConfig?.integrations?.map((i) => i.id)
11096
+ });
11097
+ googleTools = [{
11098
+ name: CODE_MODE_TOOL_NAME,
11099
+ description: codeTool.description,
11100
+ parameters: {
11101
+ type: TypeEnum.OBJECT,
11102
+ properties: {
11103
+ code: {
11104
+ type: TypeEnum.STRING,
11105
+ description: codeTool.parameters.properties.code.description
11106
+ }
11107
+ },
11108
+ required: ["code"]
11109
+ }
11110
+ }];
11111
+ } else {
11112
+ googleTools = await Promise.all(mcpTools.map((mcpTool) => convertMCPToolToGoogle(mcpTool, client, finalOptions)));
11113
+ }
10478
11114
  const triggerConfig = client.__triggerConfig;
10479
11115
  if (triggerConfig) {
10480
11116
  const triggerTools = createTriggerTools(triggerConfig, options?.context);
@@ -10552,6 +11188,7 @@ function convertJsonSchemaToGoogleSchema(jsonSchema, TypeEnum) {
10552
11188
  var init_google = __esm(() => {
10553
11189
  init_utils();
10554
11190
  init_trigger_tools();
11191
+ init_tool_builder();
10555
11192
  init_esm();
10556
11193
  });
10557
11194
 
@@ -10617,8 +11254,8 @@ var init_webhooks = __esm(() => {
10617
11254
  var MAX_TRIGGER_STEPS = 20, WEBHOOK_DELIVERY_TIMEOUT_MS = 1e4;
10618
11255
 
10619
11256
  // src/triggers/executor.ts
10620
- var exports_executor = {};
10621
- __export(exports_executor, {
11257
+ var exports_executor2 = {};
11258
+ __export(exports_executor2, {
10622
11259
  executeTrigger: () => executeTrigger
10623
11260
  });
10624
11261
  async function executeTrigger(trigger, config, context) {
@@ -10765,7 +11402,7 @@ async function executeTrigger(trigger, config, context) {
10765
11402
  return { success: false, steps, error: limitError };
10766
11403
  }
10767
11404
  var logger31;
10768
- var init_executor = __esm(() => {
11405
+ var init_executor2 = __esm(() => {
10769
11406
  init_logger();
10770
11407
  init_utils2();
10771
11408
  init_webhooks();
@@ -10910,7 +11547,8 @@ function createMCPServer(config) {
10910
11547
  integrations: updatedIntegrations,
10911
11548
  getSessionContext: config.getSessionContext,
10912
11549
  setProviderToken: config.setProviderToken,
10913
- removeProviderToken: config.removeProviderToken
11550
+ removeProviderToken: config.removeProviderToken,
11551
+ codeMode: config.codeMode
10914
11552
  };
10915
11553
  client.__triggerConfig = config.triggers ? {
10916
11554
  callbacks: config.triggers,
@@ -10980,8 +11618,21 @@ function createMCPServer(config) {
10980
11618
  if (action === "mcp" && method === "POST") {
10981
11619
  try {
10982
11620
  const body = await webRequest.json();
10983
- const authHeader = webRequest.headers.get("authorization");
11621
+ let authHeader = webRequest.headers.get("authorization");
10984
11622
  const integrationsHeader = webRequest.headers.get("x-integrations");
11623
+ if (!authHeader) {
11624
+ const tokensHeader = webRequest.headers.get("x-integrate-tokens");
11625
+ const toolName = typeof body?.name === "string" ? body.name : "";
11626
+ if (tokensHeader && toolName) {
11627
+ try {
11628
+ const tokens = JSON.parse(tokensHeader);
11629
+ const provider = toolName.split("_")[0];
11630
+ if (provider && tokens[provider]) {
11631
+ authHeader = `Bearer ${tokens[provider]}`;
11632
+ }
11633
+ } catch {}
11634
+ }
11635
+ }
10985
11636
  const { OAuthHandler: OAuthHandler2 } = await Promise.resolve().then(() => (init_base_handler(), exports_base_handler));
10986
11637
  const oauthHandler = new OAuthHandler2({
10987
11638
  providers,
@@ -11002,6 +11653,53 @@ function createMCPServer(config) {
11002
11653
  return Response.json({ error: error.message || "Failed to execute tool call" }, { status: error.statusCode || 500 });
11003
11654
  }
11004
11655
  }
11656
+ if (action === "code" && method === "POST") {
11657
+ try {
11658
+ const body = await webRequest.json();
11659
+ if (typeof body?.code !== "string" || body.code.length === 0) {
11660
+ return Response.json({ error: "`code` is required and must be a non-empty string." }, { status: 400 });
11661
+ }
11662
+ const { executeSandboxCode: executeSandboxCode2 } = await Promise.resolve().then(() => (init_executor(), exports_executor));
11663
+ const codeModeConfig = config.codeMode ?? {};
11664
+ const publicUrl = codeModeConfig.publicUrl ?? getEnv("INTEGRATE_PUBLIC_URL");
11665
+ if (!publicUrl) {
11666
+ return Response.json({
11667
+ 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."
11668
+ }, { status: 500 });
11669
+ }
11670
+ let contextOverride = body.context;
11671
+ if (!contextOverride && config.getSessionContext) {
11672
+ try {
11673
+ contextOverride = await config.getSessionContext(webRequest);
11674
+ } catch {}
11675
+ }
11676
+ let providerTokens = body.providerTokens;
11677
+ if (!providerTokens) {
11678
+ const headerTokens = webRequest.headers.get("x-integrate-tokens");
11679
+ if (headerTokens) {
11680
+ try {
11681
+ providerTokens = JSON.parse(headerTokens);
11682
+ } catch {}
11683
+ }
11684
+ }
11685
+ const integrationIds = updatedIntegrations.map((i) => i.id);
11686
+ const result = await executeSandboxCode2({
11687
+ code: body.code,
11688
+ mcpUrl: publicUrl.replace(/\/$/, "") + "/api/integrate/mcp",
11689
+ providerTokens,
11690
+ context: contextOverride,
11691
+ integrationsHeader: integrationIds.join(","),
11692
+ runtime: codeModeConfig.runtime,
11693
+ timeoutMs: codeModeConfig.timeoutMs,
11694
+ vcpus: codeModeConfig.vcpus,
11695
+ networkPolicy: codeModeConfig.networkPolicy
11696
+ });
11697
+ return Response.json(result, { status: result.success ? 200 : 500 });
11698
+ } catch (error) {
11699
+ logger32.error("[Code Mode] Error:", error);
11700
+ return Response.json({ error: error?.message || "Failed to execute code" }, { status: 500 });
11701
+ }
11702
+ }
11005
11703
  if (action === "integrations" && method === "GET") {
11006
11704
  const integrations = updatedIntegrations.map((integration) => ({
11007
11705
  id: integration.id,
@@ -11037,7 +11735,7 @@ function createMCPServer(config) {
11037
11735
  return Response.json({ error: "Trigger has no provider configured" }, { status: 400 });
11038
11736
  }
11039
11737
  const triggerContext = trigger.userId ? { userId: trigger.userId } : undefined;
11040
- const { executeTrigger: executeTrigger2 } = await Promise.resolve().then(() => (init_executor(), exports_executor));
11738
+ const { executeTrigger: executeTrigger2 } = await Promise.resolve().then(() => (init_executor2(), exports_executor2));
11041
11739
  const { OAuthHandler: OAuthHandler2 } = await Promise.resolve().then(() => (init_base_handler(), exports_base_handler));
11042
11740
  const oauthHandler = new OAuthHandler2({
11043
11741
  providers,
@@ -11200,7 +11898,7 @@ function createMCPServer(config) {
11200
11898
  if (!trigger.provider) {
11201
11899
  return Response.json({ error: "Trigger has no provider configured" }, { status: 400 });
11202
11900
  }
11203
- const { executeTrigger: executeTrigger2 } = await Promise.resolve().then(() => (init_executor(), exports_executor));
11901
+ const { executeTrigger: executeTrigger2 } = await Promise.resolve().then(() => (init_executor2(), exports_executor2));
11204
11902
  const { OAuthHandler: OAuthHandler2 } = await Promise.resolve().then(() => (init_base_handler(), exports_base_handler));
11205
11903
  const oauthHandler = new OAuthHandler2({
11206
11904
  providers,