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.
- package/dist/adapters/auto-routes.d.ts.map +1 -1
- package/dist/adapters/auto-routes.js +727 -17
- package/dist/adapters/base-handler.d.ts.map +1 -1
- package/dist/adapters/index.js +722 -16
- package/dist/adapters/nextjs.d.ts.map +1 -1
- package/dist/adapters/nextjs.js +722 -16
- package/dist/adapters/node.js +722 -16
- package/dist/adapters/svelte-kit.js +722 -16
- package/dist/adapters/tanstack-start.js +722 -16
- package/dist/ai/anthropic.d.ts +11 -0
- package/dist/ai/anthropic.d.ts.map +1 -1
- package/dist/ai/anthropic.js +552 -2
- package/dist/ai/google.d.ts +11 -0
- package/dist/ai/google.d.ts.map +1 -1
- package/dist/ai/google.js +561 -2
- package/dist/ai/index.js +648 -8
- package/dist/ai/openai.d.ts +11 -0
- package/dist/ai/openai.d.ts.map +1 -1
- package/dist/ai/openai.js +550 -2
- package/dist/ai/vercel-ai.d.ts +13 -0
- package/dist/ai/vercel-ai.d.ts.map +1 -1
- package/dist/ai/vercel-ai.js +536 -2
- package/dist/code-mode/executor.d.ts +99 -0
- package/dist/code-mode/executor.d.ts.map +1 -0
- package/dist/code-mode/executor.js +207 -0
- package/dist/code-mode/index.d.ts +12 -0
- package/dist/code-mode/index.d.ts.map +1 -0
- package/dist/code-mode/index.js +527 -0
- package/dist/code-mode/runtime-stub.d.ts +16 -0
- package/dist/code-mode/runtime-stub.d.ts.map +1 -0
- package/dist/code-mode/runtime-stub.js +72 -0
- package/dist/code-mode/tool-builder.d.ts +83 -0
- package/dist/code-mode/tool-builder.d.ts.map +1 -0
- package/dist/code-mode/tool-builder.js +524 -0
- package/dist/code-mode/type-generator.d.ts +22 -0
- package/dist/code-mode/type-generator.d.ts.map +1 -0
- package/dist/code-mode/type-generator.js +217 -0
- package/dist/index.js +722 -16
- package/dist/oauth.js +727 -17
- package/dist/server.d.ts +1 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +733 -17
- package/dist/src/adapters/auto-routes.d.ts.map +1 -1
- package/dist/src/adapters/base-handler.d.ts.map +1 -1
- package/dist/src/adapters/nextjs.d.ts.map +1 -1
- package/dist/src/ai/anthropic.d.ts +11 -0
- package/dist/src/ai/anthropic.d.ts.map +1 -1
- package/dist/src/ai/google.d.ts +11 -0
- package/dist/src/ai/google.d.ts.map +1 -1
- package/dist/src/ai/openai.d.ts +11 -0
- package/dist/src/ai/openai.d.ts.map +1 -1
- package/dist/src/ai/vercel-ai.d.ts +13 -0
- package/dist/src/ai/vercel-ai.d.ts.map +1 -1
- package/dist/src/code-mode/executor.d.ts +99 -0
- package/dist/src/code-mode/executor.d.ts.map +1 -0
- package/dist/src/code-mode/index.d.ts +12 -0
- package/dist/src/code-mode/index.d.ts.map +1 -0
- package/dist/src/code-mode/runtime-stub.d.ts +16 -0
- package/dist/src/code-mode/runtime-stub.d.ts.map +1 -0
- package/dist/src/code-mode/tool-builder.d.ts +83 -0
- package/dist/src/code-mode/tool-builder.d.ts.map +1 -0
- package/dist/src/code-mode/type-generator.d.ts +22 -0
- package/dist/src/code-mode/type-generator.d.ts.map +1 -0
- package/dist/src/config/types.d.ts +55 -0
- package/dist/src/config/types.d.ts.map +1 -1
- package/dist/src/server.d.ts.map +1 -1
- package/package.json +15 -6
- package/server.ts +9 -0
package/dist/ai/index.js
CHANGED
|
@@ -4402,6 +4402,523 @@ function createTriggerTools(config, context) {
|
|
|
4402
4402
|
};
|
|
4403
4403
|
}
|
|
4404
4404
|
|
|
4405
|
+
// ../utils/naming.ts
|
|
4406
|
+
function snakeToCamel(str) {
|
|
4407
|
+
return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
|
|
4408
|
+
}
|
|
4409
|
+
function toolNameToMethod(toolName) {
|
|
4410
|
+
const withoutPrefix = toolName.replace(/^[^_]+_/, "");
|
|
4411
|
+
return snakeToCamel(withoutPrefix);
|
|
4412
|
+
}
|
|
4413
|
+
|
|
4414
|
+
// ../code-mode/type-generator.ts
|
|
4415
|
+
var RESERVED_TS = new Set([
|
|
4416
|
+
"break",
|
|
4417
|
+
"case",
|
|
4418
|
+
"catch",
|
|
4419
|
+
"class",
|
|
4420
|
+
"const",
|
|
4421
|
+
"continue",
|
|
4422
|
+
"debugger",
|
|
4423
|
+
"default",
|
|
4424
|
+
"delete",
|
|
4425
|
+
"do",
|
|
4426
|
+
"else",
|
|
4427
|
+
"enum",
|
|
4428
|
+
"export",
|
|
4429
|
+
"extends",
|
|
4430
|
+
"false",
|
|
4431
|
+
"finally",
|
|
4432
|
+
"for",
|
|
4433
|
+
"function",
|
|
4434
|
+
"if",
|
|
4435
|
+
"import",
|
|
4436
|
+
"in",
|
|
4437
|
+
"instanceof",
|
|
4438
|
+
"new",
|
|
4439
|
+
"null",
|
|
4440
|
+
"return",
|
|
4441
|
+
"super",
|
|
4442
|
+
"switch",
|
|
4443
|
+
"this",
|
|
4444
|
+
"throw",
|
|
4445
|
+
"true",
|
|
4446
|
+
"try",
|
|
4447
|
+
"typeof",
|
|
4448
|
+
"var",
|
|
4449
|
+
"void",
|
|
4450
|
+
"while",
|
|
4451
|
+
"with",
|
|
4452
|
+
"as",
|
|
4453
|
+
"implements",
|
|
4454
|
+
"interface",
|
|
4455
|
+
"let",
|
|
4456
|
+
"package",
|
|
4457
|
+
"private",
|
|
4458
|
+
"protected",
|
|
4459
|
+
"public",
|
|
4460
|
+
"static",
|
|
4461
|
+
"yield"
|
|
4462
|
+
]);
|
|
4463
|
+
function safeIdent(name) {
|
|
4464
|
+
if (!/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name) || RESERVED_TS.has(name)) {
|
|
4465
|
+
return JSON.stringify(name);
|
|
4466
|
+
}
|
|
4467
|
+
return name;
|
|
4468
|
+
}
|
|
4469
|
+
function integrationFromToolName(toolName) {
|
|
4470
|
+
const idx = toolName.indexOf("_");
|
|
4471
|
+
return idx === -1 ? toolName : toolName.slice(0, idx);
|
|
4472
|
+
}
|
|
4473
|
+
function jsonSchemaToTs(schema, indent) {
|
|
4474
|
+
if (!schema || typeof schema !== "object")
|
|
4475
|
+
return "unknown";
|
|
4476
|
+
const s = schema;
|
|
4477
|
+
if (Array.isArray(s.enum) && s.enum.length > 0) {
|
|
4478
|
+
return s.enum.map((v) => typeof v === "string" ? JSON.stringify(v) : typeof v === "number" || typeof v === "boolean" ? String(v) : "unknown").join(" | ");
|
|
4479
|
+
}
|
|
4480
|
+
if (Array.isArray(s.type)) {
|
|
4481
|
+
return s.type.map((t2) => jsonSchemaToTs({ ...s, type: t2 }, indent)).join(" | ");
|
|
4482
|
+
}
|
|
4483
|
+
const t = s.type;
|
|
4484
|
+
switch (t) {
|
|
4485
|
+
case "string":
|
|
4486
|
+
return "string";
|
|
4487
|
+
case "number":
|
|
4488
|
+
case "integer":
|
|
4489
|
+
return "number";
|
|
4490
|
+
case "boolean":
|
|
4491
|
+
return "boolean";
|
|
4492
|
+
case "null":
|
|
4493
|
+
return "null";
|
|
4494
|
+
case "array": {
|
|
4495
|
+
const items = s.items;
|
|
4496
|
+
if (Array.isArray(items))
|
|
4497
|
+
return "unknown[]";
|
|
4498
|
+
const inner = jsonSchemaToTs(items, indent);
|
|
4499
|
+
return /[|&]/.test(inner) ? `Array<${inner}>` : `${inner}[]`;
|
|
4500
|
+
}
|
|
4501
|
+
case "object":
|
|
4502
|
+
return objectShape(s, indent);
|
|
4503
|
+
default:
|
|
4504
|
+
if (s.properties && typeof s.properties === "object")
|
|
4505
|
+
return objectShape(s, indent);
|
|
4506
|
+
return "unknown";
|
|
4507
|
+
}
|
|
4508
|
+
}
|
|
4509
|
+
function objectShape(schema, indent) {
|
|
4510
|
+
const props = schema.properties && typeof schema.properties === "object" ? schema.properties : {};
|
|
4511
|
+
const keys = Object.keys(props);
|
|
4512
|
+
if (keys.length === 0) {
|
|
4513
|
+
return schema.additionalProperties === false ? "Record<string, never>" : "Record<string, unknown>";
|
|
4514
|
+
}
|
|
4515
|
+
const required = new Set(Array.isArray(schema.required) ? schema.required : []);
|
|
4516
|
+
const inner = indent + " ";
|
|
4517
|
+
const lines = ["{"];
|
|
4518
|
+
for (const key of keys) {
|
|
4519
|
+
const prop = props[key];
|
|
4520
|
+
const desc = prop && typeof prop.description === "string" ? prop.description : undefined;
|
|
4521
|
+
if (desc)
|
|
4522
|
+
lines.push(`${inner}/** ${desc.replace(/\*\//g, "*\\/")} */`);
|
|
4523
|
+
const optional = required.has(key) ? "" : "?";
|
|
4524
|
+
const type = jsonSchemaToTs(prop, inner);
|
|
4525
|
+
lines.push(`${inner}${safeIdent(key)}${optional}: ${type};`);
|
|
4526
|
+
}
|
|
4527
|
+
lines.push(`${indent}}`);
|
|
4528
|
+
return lines.join(`
|
|
4529
|
+
`);
|
|
4530
|
+
}
|
|
4531
|
+
function argsType(schema) {
|
|
4532
|
+
if (!schema)
|
|
4533
|
+
return "Record<string, unknown>";
|
|
4534
|
+
const hasProps = schema.properties && Object.keys(schema.properties).length > 0;
|
|
4535
|
+
if (!hasProps)
|
|
4536
|
+
return "Record<string, unknown>";
|
|
4537
|
+
return objectShape(schema, " ");
|
|
4538
|
+
}
|
|
4539
|
+
function methodHasRequiredArgs(schema) {
|
|
4540
|
+
if (!schema || !schema.properties)
|
|
4541
|
+
return false;
|
|
4542
|
+
const req = Array.isArray(schema.required) ? schema.required : [];
|
|
4543
|
+
return req.length > 0;
|
|
4544
|
+
}
|
|
4545
|
+
function formatDescription(desc, indent) {
|
|
4546
|
+
if (!desc)
|
|
4547
|
+
return "";
|
|
4548
|
+
const cleaned = desc.replace(/\*\//g, "*\\/").trim();
|
|
4549
|
+
if (!cleaned.includes(`
|
|
4550
|
+
`))
|
|
4551
|
+
return `${indent}/** ${cleaned} */
|
|
4552
|
+
`;
|
|
4553
|
+
const lines = cleaned.split(`
|
|
4554
|
+
`).map((l) => `${indent} * ${l}`).join(`
|
|
4555
|
+
`);
|
|
4556
|
+
return `${indent}/**
|
|
4557
|
+
${lines}
|
|
4558
|
+
${indent} */
|
|
4559
|
+
`;
|
|
4560
|
+
}
|
|
4561
|
+
function generateCodeModeTypes(tools) {
|
|
4562
|
+
const byIntegration = {};
|
|
4563
|
+
for (const tool of tools) {
|
|
4564
|
+
const integration = integrationFromToolName(tool.name);
|
|
4565
|
+
(byIntegration[integration] ??= []).push(tool);
|
|
4566
|
+
}
|
|
4567
|
+
const methodMap = {};
|
|
4568
|
+
const integrationCounts = {};
|
|
4569
|
+
const sections = [];
|
|
4570
|
+
const integrationIds = Object.keys(byIntegration).sort();
|
|
4571
|
+
sections.push("/**");
|
|
4572
|
+
sections.push(" * Integrate SDK — available APIs inside `execute_code`.");
|
|
4573
|
+
sections.push(" * Every method is async and returns the MCP tool-call response.");
|
|
4574
|
+
sections.push(" * Call them via the exported `client` object, e.g.");
|
|
4575
|
+
sections.push(" * const repos = await client.github.listRepos();");
|
|
4576
|
+
sections.push(" */");
|
|
4577
|
+
sections.push("");
|
|
4578
|
+
for (const integrationId of integrationIds) {
|
|
4579
|
+
const integrationTools = byIntegration[integrationId].slice().sort((a, b) => a.name.localeCompare(b.name));
|
|
4580
|
+
integrationCounts[integrationId] = integrationTools.length;
|
|
4581
|
+
const interfaceName = pascalCase(integrationId) + "Client";
|
|
4582
|
+
sections.push(`export interface ${interfaceName} {`);
|
|
4583
|
+
for (const tool of integrationTools) {
|
|
4584
|
+
const methodName = toolNameToMethod(tool.name);
|
|
4585
|
+
methodMap[`${integrationId}.${methodName}`] = tool.name;
|
|
4586
|
+
sections.push(formatDescription(tool.description, " "));
|
|
4587
|
+
const argType = argsType(tool.inputSchema);
|
|
4588
|
+
const argIsOptional = !methodHasRequiredArgs(tool.inputSchema);
|
|
4589
|
+
const paramName = argIsOptional ? "args?" : "args";
|
|
4590
|
+
sections.push(` ${safeIdent(methodName)}(${paramName}: ${argType}): Promise<ToolResult>;`);
|
|
4591
|
+
}
|
|
4592
|
+
sections.push("}");
|
|
4593
|
+
sections.push("");
|
|
4594
|
+
}
|
|
4595
|
+
sections.push("export interface ToolResult {");
|
|
4596
|
+
sections.push(" content: Array<{ type: 'text' | 'image' | 'resource'; text?: string; data?: string; mimeType?: string; [key: string]: unknown }>;");
|
|
4597
|
+
sections.push(" isError?: boolean;");
|
|
4598
|
+
sections.push(" structuredContent?: Record<string, unknown>;");
|
|
4599
|
+
sections.push("}");
|
|
4600
|
+
sections.push("");
|
|
4601
|
+
sections.push("export interface Client {");
|
|
4602
|
+
for (const integrationId of integrationIds) {
|
|
4603
|
+
const interfaceName = pascalCase(integrationId) + "Client";
|
|
4604
|
+
sections.push(` ${safeIdent(integrationId)}: ${interfaceName};`);
|
|
4605
|
+
}
|
|
4606
|
+
sections.push("}");
|
|
4607
|
+
sections.push("");
|
|
4608
|
+
sections.push("export declare const client: Client;");
|
|
4609
|
+
return {
|
|
4610
|
+
source: sections.filter((line, idx, arr) => !(line === "" && arr[idx - 1] === "")).join(`
|
|
4611
|
+
`),
|
|
4612
|
+
methodMap,
|
|
4613
|
+
integrationCounts
|
|
4614
|
+
};
|
|
4615
|
+
}
|
|
4616
|
+
function pascalCase(id) {
|
|
4617
|
+
return id.split(/[^A-Za-z0-9]/).filter(Boolean).map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join("") || "Unknown";
|
|
4618
|
+
}
|
|
4619
|
+
|
|
4620
|
+
// ../code-mode/runtime-stub.ts
|
|
4621
|
+
var RUNTIME_STUB_SOURCE = `// runtime.mjs — generated by integrate-sdk code mode
|
|
4622
|
+
const MCP_URL = process.env.INTEGRATE_MCP_URL;
|
|
4623
|
+
const SESSION_TOKEN = process.env.INTEGRATE_SESSION_TOKEN;
|
|
4624
|
+
const PROVIDER_TOKENS = process.env.INTEGRATE_PROVIDER_TOKENS || '';
|
|
4625
|
+
const INTEGRATIONS_HEADER = process.env.INTEGRATE_INTEGRATIONS || '';
|
|
4626
|
+
const CONTEXT_JSON = process.env.INTEGRATE_CONTEXT || '';
|
|
4627
|
+
|
|
4628
|
+
if (!MCP_URL) {
|
|
4629
|
+
throw new Error('INTEGRATE_MCP_URL is not set — the sandbox cannot reach the MCP route.');
|
|
4630
|
+
}
|
|
4631
|
+
|
|
4632
|
+
function camelToSnake(str) {
|
|
4633
|
+
return str.replace(/[A-Z]/g, (letter) => '_' + letter.toLowerCase());
|
|
4634
|
+
}
|
|
4635
|
+
|
|
4636
|
+
async function callTool(toolName, args) {
|
|
4637
|
+
const headers = {
|
|
4638
|
+
'Content-Type': 'application/json',
|
|
4639
|
+
'x-integrate-code-mode': '1',
|
|
4640
|
+
};
|
|
4641
|
+
if (SESSION_TOKEN) headers['Authorization'] = 'Bearer ' + SESSION_TOKEN;
|
|
4642
|
+
if (PROVIDER_TOKENS) headers['x-integrate-tokens'] = PROVIDER_TOKENS;
|
|
4643
|
+
if (INTEGRATIONS_HEADER) headers['x-integrations'] = INTEGRATIONS_HEADER;
|
|
4644
|
+
if (CONTEXT_JSON) headers['x-integrate-context'] = CONTEXT_JSON;
|
|
4645
|
+
|
|
4646
|
+
const res = await fetch(MCP_URL, {
|
|
4647
|
+
method: 'POST',
|
|
4648
|
+
headers,
|
|
4649
|
+
body: JSON.stringify({ name: toolName, arguments: args || {} }),
|
|
4650
|
+
});
|
|
4651
|
+
|
|
4652
|
+
const text = await res.text();
|
|
4653
|
+
let payload;
|
|
4654
|
+
try {
|
|
4655
|
+
payload = text ? JSON.parse(text) : null;
|
|
4656
|
+
} catch {
|
|
4657
|
+
payload = { content: [{ type: 'text', text }] };
|
|
4658
|
+
}
|
|
4659
|
+
|
|
4660
|
+
if (!res.ok) {
|
|
4661
|
+
const message = (payload && (payload.error || payload.message)) || 'Tool call failed: HTTP ' + res.status;
|
|
4662
|
+
const err = new Error(message);
|
|
4663
|
+
err.status = res.status;
|
|
4664
|
+
err.toolName = toolName;
|
|
4665
|
+
throw err;
|
|
4666
|
+
}
|
|
4667
|
+
|
|
4668
|
+
return payload;
|
|
4669
|
+
}
|
|
4670
|
+
|
|
4671
|
+
function createIntegrationProxy(integrationId) {
|
|
4672
|
+
return new Proxy({}, {
|
|
4673
|
+
get(_target, methodName) {
|
|
4674
|
+
if (typeof methodName !== 'string') return undefined;
|
|
4675
|
+
return (args) => callTool(integrationId + '_' + camelToSnake(methodName), args);
|
|
4676
|
+
},
|
|
4677
|
+
});
|
|
4678
|
+
}
|
|
4679
|
+
|
|
4680
|
+
export const client = new Proxy({}, {
|
|
4681
|
+
get(_target, integrationId) {
|
|
4682
|
+
if (typeof integrationId !== 'string') return undefined;
|
|
4683
|
+
return createIntegrationProxy(integrationId);
|
|
4684
|
+
},
|
|
4685
|
+
});
|
|
4686
|
+
|
|
4687
|
+
export { callTool };
|
|
4688
|
+
`;
|
|
4689
|
+
|
|
4690
|
+
// ../code-mode/executor.ts
|
|
4691
|
+
var sandboxFactoryOverride = null;
|
|
4692
|
+
async function loadSandboxFactory() {
|
|
4693
|
+
if (sandboxFactoryOverride)
|
|
4694
|
+
return sandboxFactoryOverride;
|
|
4695
|
+
try {
|
|
4696
|
+
const dynamicImport = new Function("specifier", "return import(specifier)");
|
|
4697
|
+
const pkg = "@" + "vercel/sandbox";
|
|
4698
|
+
const mod = await dynamicImport(pkg);
|
|
4699
|
+
return mod.Sandbox ?? mod.default?.Sandbox ?? mod;
|
|
4700
|
+
} catch (err) {
|
|
4701
|
+
throw new Error("Code Mode requires the optional peer dependency `@vercel/sandbox`. " + "Install it with `npm install @vercel/sandbox` (or `bun add @vercel/sandbox`).");
|
|
4702
|
+
}
|
|
4703
|
+
}
|
|
4704
|
+
var RESULT_SENTINEL = "__INTEGRATE_RESULT__";
|
|
4705
|
+
function wrapUserCode(code) {
|
|
4706
|
+
return `// user.mjs — wrapped by integrate-sdk code mode
|
|
4707
|
+
import { client, callTool } from './runtime.mjs';
|
|
4708
|
+
|
|
4709
|
+
(async () => {
|
|
4710
|
+
try {
|
|
4711
|
+
const __result = await (async () => {
|
|
4712
|
+
${code}
|
|
4713
|
+
})();
|
|
4714
|
+
if (typeof __result !== 'undefined') {
|
|
4715
|
+
process.stdout.write('\\n' + ${JSON.stringify(RESULT_SENTINEL)} + JSON.stringify(__result) + '\\n');
|
|
4716
|
+
}
|
|
4717
|
+
} catch (err) {
|
|
4718
|
+
const payload = {
|
|
4719
|
+
message: err && err.message ? err.message : String(err),
|
|
4720
|
+
name: err && err.name,
|
|
4721
|
+
stack: err && err.stack,
|
|
4722
|
+
toolName: err && err.toolName,
|
|
4723
|
+
status: err && err.status,
|
|
4724
|
+
};
|
|
4725
|
+
process.stderr.write('\\n' + ${JSON.stringify(RESULT_SENTINEL)} + JSON.stringify({ error: payload }) + '\\n');
|
|
4726
|
+
process.exit(1);
|
|
4727
|
+
}
|
|
4728
|
+
})();
|
|
4729
|
+
`;
|
|
4730
|
+
}
|
|
4731
|
+
function defaultNetworkPolicy(mcpUrl) {
|
|
4732
|
+
try {
|
|
4733
|
+
const host = new URL(mcpUrl).hostname;
|
|
4734
|
+
return { allow: [host] };
|
|
4735
|
+
} catch {
|
|
4736
|
+
return { allow: [] };
|
|
4737
|
+
}
|
|
4738
|
+
}
|
|
4739
|
+
function extractResult(stream) {
|
|
4740
|
+
const idx = stream.lastIndexOf(RESULT_SENTINEL);
|
|
4741
|
+
if (idx === -1)
|
|
4742
|
+
return { cleaned: stream };
|
|
4743
|
+
const before = stream.slice(0, idx).replace(/\n$/, "");
|
|
4744
|
+
const rest = stream.slice(idx + RESULT_SENTINEL.length);
|
|
4745
|
+
const newlineIdx = rest.indexOf(`
|
|
4746
|
+
`);
|
|
4747
|
+
const payload = newlineIdx === -1 ? rest : rest.slice(0, newlineIdx);
|
|
4748
|
+
const after = newlineIdx === -1 ? "" : rest.slice(newlineIdx + 1);
|
|
4749
|
+
try {
|
|
4750
|
+
return { cleaned: (before + after).trimEnd(), result: JSON.parse(payload) };
|
|
4751
|
+
} catch {
|
|
4752
|
+
return { cleaned: stream };
|
|
4753
|
+
}
|
|
4754
|
+
}
|
|
4755
|
+
async function executeSandboxCode(options) {
|
|
4756
|
+
const startedAt = Date.now();
|
|
4757
|
+
const runtime = options.runtime ?? "node22";
|
|
4758
|
+
const timeoutMs = options.timeoutMs ?? 60000;
|
|
4759
|
+
const networkPolicy = options.networkPolicy ?? defaultNetworkPolicy(options.mcpUrl);
|
|
4760
|
+
let sandbox = null;
|
|
4761
|
+
try {
|
|
4762
|
+
const Sandbox = await loadSandboxFactory();
|
|
4763
|
+
sandbox = await Sandbox.create({
|
|
4764
|
+
runtime,
|
|
4765
|
+
timeout: timeoutMs,
|
|
4766
|
+
resources: options.vcpus ? { vcpus: options.vcpus } : undefined,
|
|
4767
|
+
networkPolicy
|
|
4768
|
+
});
|
|
4769
|
+
const runtimeContent = Buffer.from(RUNTIME_STUB_SOURCE, "utf-8");
|
|
4770
|
+
const userContent = Buffer.from(wrapUserCode(options.code), "utf-8");
|
|
4771
|
+
await sandbox.writeFiles([
|
|
4772
|
+
{ path: "runtime.mjs", content: runtimeContent },
|
|
4773
|
+
{ path: "user.mjs", content: userContent }
|
|
4774
|
+
]);
|
|
4775
|
+
const env = {
|
|
4776
|
+
INTEGRATE_MCP_URL: options.mcpUrl
|
|
4777
|
+
};
|
|
4778
|
+
if (options.sessionToken)
|
|
4779
|
+
env.INTEGRATE_SESSION_TOKEN = options.sessionToken;
|
|
4780
|
+
if (options.providerTokens && Object.keys(options.providerTokens).length > 0) {
|
|
4781
|
+
env.INTEGRATE_PROVIDER_TOKENS = JSON.stringify(options.providerTokens);
|
|
4782
|
+
}
|
|
4783
|
+
if (options.integrationsHeader)
|
|
4784
|
+
env.INTEGRATE_INTEGRATIONS = options.integrationsHeader;
|
|
4785
|
+
if (options.context)
|
|
4786
|
+
env.INTEGRATE_CONTEXT = JSON.stringify(options.context);
|
|
4787
|
+
const cmd = await sandbox.runCommand({
|
|
4788
|
+
cmd: "node",
|
|
4789
|
+
args: ["user.mjs"],
|
|
4790
|
+
env
|
|
4791
|
+
});
|
|
4792
|
+
const [stdoutRaw, stderrRaw] = await Promise.all([cmd.stdout(), cmd.stderr()]);
|
|
4793
|
+
const stdoutExtract = extractResult(stdoutRaw);
|
|
4794
|
+
const stderrExtract = extractResult(stderrRaw);
|
|
4795
|
+
return {
|
|
4796
|
+
success: cmd.exitCode === 0,
|
|
4797
|
+
exitCode: cmd.exitCode,
|
|
4798
|
+
result: stdoutExtract.result ?? stderrExtract.result,
|
|
4799
|
+
stdout: stdoutExtract.cleaned,
|
|
4800
|
+
stderr: stderrExtract.cleaned,
|
|
4801
|
+
durationMs: Date.now() - startedAt
|
|
4802
|
+
};
|
|
4803
|
+
} catch (err) {
|
|
4804
|
+
return {
|
|
4805
|
+
success: false,
|
|
4806
|
+
exitCode: -1,
|
|
4807
|
+
stdout: "",
|
|
4808
|
+
stderr: "",
|
|
4809
|
+
durationMs: Date.now() - startedAt,
|
|
4810
|
+
error: err instanceof Error ? err.message : String(err)
|
|
4811
|
+
};
|
|
4812
|
+
} finally {
|
|
4813
|
+
if (sandbox) {
|
|
4814
|
+
try {
|
|
4815
|
+
await sandbox.stop();
|
|
4816
|
+
} catch {}
|
|
4817
|
+
}
|
|
4818
|
+
}
|
|
4819
|
+
}
|
|
4820
|
+
|
|
4821
|
+
// ../utils/env.ts
|
|
4822
|
+
function getEnv(key) {
|
|
4823
|
+
try {
|
|
4824
|
+
const getImportMeta = new Function('return typeof import.meta !== "undefined" ? import.meta : undefined');
|
|
4825
|
+
const importMeta = getImportMeta();
|
|
4826
|
+
if (importMeta && typeof importMeta.env === "object" && importMeta.env !== null) {
|
|
4827
|
+
const value = importMeta.env[key];
|
|
4828
|
+
if (value !== undefined && value !== null && value !== "") {
|
|
4829
|
+
return String(value);
|
|
4830
|
+
}
|
|
4831
|
+
}
|
|
4832
|
+
} catch {}
|
|
4833
|
+
if (typeof process !== "undefined" && process.env) {
|
|
4834
|
+
const value = process.env[key];
|
|
4835
|
+
if (value !== undefined && value !== null && value !== "") {
|
|
4836
|
+
return value;
|
|
4837
|
+
}
|
|
4838
|
+
}
|
|
4839
|
+
return;
|
|
4840
|
+
}
|
|
4841
|
+
|
|
4842
|
+
// ../code-mode/tool-builder.ts
|
|
4843
|
+
var CODE_MODE_TOOL_NAME = "execute_code";
|
|
4844
|
+
var DEFAULT_INSTRUCTIONS = [
|
|
4845
|
+
"You are given a single tool: `execute_code`. Instead of calling individual MCP tools,",
|
|
4846
|
+
"you write a short async TypeScript/JavaScript snippet that uses the typed `client`",
|
|
4847
|
+
"object below, and the snippet runs in an isolated sandbox which dispatches the actual",
|
|
4848
|
+
"tool calls. Chain multiple operations together in one snippet whenever possible —",
|
|
4849
|
+
"that is the whole point of this tool.",
|
|
4850
|
+
"",
|
|
4851
|
+
"Rules:",
|
|
4852
|
+
"- The snippet is the body of an `async` function. Use `await` freely.",
|
|
4853
|
+
"- Use `return <value>` at the end to hand a structured result back to the caller;",
|
|
4854
|
+
" the caller receives it as JSON.",
|
|
4855
|
+
"- Use `console.log(...)` for intermediate observations you want to read later.",
|
|
4856
|
+
"- Throw / let errors propagate; the runtime will surface them with a non-zero exit.",
|
|
4857
|
+
"- Each method call returns an object of shape `ToolResult` (see types below).",
|
|
4858
|
+
" The payload usually lives in `result.content[0].text` as JSON — parse it if needed.",
|
|
4859
|
+
"- You cannot import npm packages. Only the pre-imported `client` and standard",
|
|
4860
|
+
" globals (`fetch`, `console`, `JSON`, ...) are available.",
|
|
4861
|
+
"",
|
|
4862
|
+
"API surface:"
|
|
4863
|
+
].join(`
|
|
4864
|
+
`);
|
|
4865
|
+
function resolveCodeModeClientConfig(client) {
|
|
4866
|
+
const oauthConfig = client.__oauthConfig;
|
|
4867
|
+
return oauthConfig?.codeMode ?? {};
|
|
4868
|
+
}
|
|
4869
|
+
function buildCodeModeTool(client, options) {
|
|
4870
|
+
const { tools, providerTokens, context, integrationIds } = options;
|
|
4871
|
+
const generated = generateCodeModeTypes(tools);
|
|
4872
|
+
const serverCodeModeConfig = resolveCodeModeClientConfig(client);
|
|
4873
|
+
const sandboxOverrides = options.sandbox ?? {};
|
|
4874
|
+
const description = `${DEFAULT_INSTRUCTIONS}
|
|
4875
|
+
|
|
4876
|
+
\`\`\`typescript
|
|
4877
|
+
${generated.source}
|
|
4878
|
+
\`\`\``;
|
|
4879
|
+
const execute = async ({ code }) => {
|
|
4880
|
+
const publicUrl = sandboxOverrides.publicUrl ?? serverCodeModeConfig.publicUrl ?? getEnv("INTEGRATE_PUBLIC_URL");
|
|
4881
|
+
if (!publicUrl) {
|
|
4882
|
+
return {
|
|
4883
|
+
success: false,
|
|
4884
|
+
exitCode: -1,
|
|
4885
|
+
stdout: "",
|
|
4886
|
+
stderr: "",
|
|
4887
|
+
durationMs: 0,
|
|
4888
|
+
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."
|
|
4889
|
+
};
|
|
4890
|
+
}
|
|
4891
|
+
const mcpUrl = publicUrl.replace(/\/$/, "") + "/api/integrate/mcp";
|
|
4892
|
+
return executeSandboxCode({
|
|
4893
|
+
code,
|
|
4894
|
+
mcpUrl,
|
|
4895
|
+
providerTokens,
|
|
4896
|
+
context,
|
|
4897
|
+
integrationsHeader: integrationIds && integrationIds.length > 0 ? integrationIds.join(",") : undefined,
|
|
4898
|
+
runtime: sandboxOverrides.runtime ?? serverCodeModeConfig.runtime,
|
|
4899
|
+
timeoutMs: sandboxOverrides.timeoutMs ?? serverCodeModeConfig.timeoutMs,
|
|
4900
|
+
vcpus: sandboxOverrides.vcpus ?? serverCodeModeConfig.vcpus,
|
|
4901
|
+
networkPolicy: sandboxOverrides.networkPolicy ?? serverCodeModeConfig.networkPolicy
|
|
4902
|
+
});
|
|
4903
|
+
};
|
|
4904
|
+
return {
|
|
4905
|
+
name: CODE_MODE_TOOL_NAME,
|
|
4906
|
+
description,
|
|
4907
|
+
parameters: {
|
|
4908
|
+
type: "object",
|
|
4909
|
+
properties: {
|
|
4910
|
+
code: {
|
|
4911
|
+
type: "string",
|
|
4912
|
+
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."
|
|
4913
|
+
}
|
|
4914
|
+
},
|
|
4915
|
+
required: ["code"],
|
|
4916
|
+
additionalProperties: false
|
|
4917
|
+
},
|
|
4918
|
+
execute
|
|
4919
|
+
};
|
|
4920
|
+
}
|
|
4921
|
+
|
|
4405
4922
|
// anthropic.ts
|
|
4406
4923
|
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
4407
4924
|
function convertMCPToolToAnthropic(mcpTool, _client, _options) {
|
|
@@ -4419,11 +4936,27 @@ async function handleAnthropicToolCalls(client, messageContent, options) {
|
|
|
4419
4936
|
const toolResults = [];
|
|
4420
4937
|
const triggerConfig = client.__triggerConfig;
|
|
4421
4938
|
const triggerTools = triggerConfig ? createTriggerTools(triggerConfig, options?.context) : null;
|
|
4939
|
+
let cachedCodeModeTool = null;
|
|
4940
|
+
const getCodeModeTool = async () => {
|
|
4941
|
+
if (cachedCodeModeTool)
|
|
4942
|
+
return cachedCodeModeTool;
|
|
4943
|
+
const mcpTools = await client.getEnabledToolsAsync();
|
|
4944
|
+
cachedCodeModeTool = buildCodeModeTool(client, {
|
|
4945
|
+
tools: mcpTools,
|
|
4946
|
+
providerTokens: options?.providerTokens,
|
|
4947
|
+
context: options?.context,
|
|
4948
|
+
integrationIds: client.__oauthConfig?.integrations?.map((i) => i.id)
|
|
4949
|
+
});
|
|
4950
|
+
return cachedCodeModeTool;
|
|
4951
|
+
};
|
|
4422
4952
|
const toolUseBlocks = messageContent.filter((block) => block.type === "tool_use" && ("id" in block) && ("name" in block) && ("input" in block));
|
|
4423
4953
|
for (const toolUse of toolUseBlocks) {
|
|
4424
4954
|
try {
|
|
4425
4955
|
let result;
|
|
4426
|
-
if (
|
|
4956
|
+
if (toolUse.name === CODE_MODE_TOOL_NAME) {
|
|
4957
|
+
const codeTool = await getCodeModeTool();
|
|
4958
|
+
result = await codeTool.execute(toolUse.input);
|
|
4959
|
+
} else if (triggerTools && triggerTools[toolUse.name]) {
|
|
4427
4960
|
result = await triggerTools[toolUse.name].execute(toolUse.input);
|
|
4428
4961
|
} else {
|
|
4429
4962
|
result = await executeToolWithToken(client, toolUse.name, toolUse.input, options);
|
|
@@ -4456,7 +4989,24 @@ async function getAnthropicTools(client, options) {
|
|
|
4456
4989
|
const finalOptions = providerTokens ? { ...options, providerTokens } : options;
|
|
4457
4990
|
await ensureClientConnected(client);
|
|
4458
4991
|
const mcpTools = await client.getEnabledToolsAsync();
|
|
4459
|
-
const
|
|
4992
|
+
const mode = options?.mode ?? "code";
|
|
4993
|
+
const anthropicTools = mode === "code" ? (() => {
|
|
4994
|
+
const codeTool = buildCodeModeTool(client, {
|
|
4995
|
+
tools: mcpTools,
|
|
4996
|
+
providerTokens,
|
|
4997
|
+
context: options?.context,
|
|
4998
|
+
integrationIds: client.__oauthConfig?.integrations?.map((i) => i.id)
|
|
4999
|
+
});
|
|
5000
|
+
return [{
|
|
5001
|
+
name: CODE_MODE_TOOL_NAME,
|
|
5002
|
+
description: codeTool.description,
|
|
5003
|
+
input_schema: {
|
|
5004
|
+
type: "object",
|
|
5005
|
+
properties: codeTool.parameters.properties,
|
|
5006
|
+
required: [...codeTool.parameters.required]
|
|
5007
|
+
}
|
|
5008
|
+
}];
|
|
5009
|
+
})() : mcpTools.map((mcpTool) => convertMCPToolToAnthropic(mcpTool, client, finalOptions));
|
|
4460
5010
|
const triggerConfig = client.__triggerConfig;
|
|
4461
5011
|
if (triggerConfig) {
|
|
4462
5012
|
const triggerTools = createTriggerTools(triggerConfig, options?.context);
|
|
@@ -4582,13 +5132,29 @@ async function executeGoogleFunctionCalls(client, functionCalls, options) {
|
|
|
4582
5132
|
const finalOptions = providerTokens ? { ...options, providerTokens } : options;
|
|
4583
5133
|
const triggerConfig = client.__triggerConfig;
|
|
4584
5134
|
const triggerTools = triggerConfig ? createTriggerTools(triggerConfig, options?.context) : null;
|
|
5135
|
+
let cachedCodeModeTool = null;
|
|
5136
|
+
const getCodeModeTool = async () => {
|
|
5137
|
+
if (cachedCodeModeTool)
|
|
5138
|
+
return cachedCodeModeTool;
|
|
5139
|
+
const mcpTools = await client.getEnabledToolsAsync();
|
|
5140
|
+
cachedCodeModeTool = buildCodeModeTool(client, {
|
|
5141
|
+
tools: mcpTools,
|
|
5142
|
+
providerTokens: finalOptions?.providerTokens,
|
|
5143
|
+
context: options?.context,
|
|
5144
|
+
integrationIds: client.__oauthConfig?.integrations?.map((i) => i.id)
|
|
5145
|
+
});
|
|
5146
|
+
return cachedCodeModeTool;
|
|
5147
|
+
};
|
|
4585
5148
|
const results = await Promise.all(functionCalls.map(async (call) => {
|
|
4586
5149
|
if (!call?.name) {
|
|
4587
5150
|
throw new Error("Function call must have a name");
|
|
4588
5151
|
}
|
|
4589
5152
|
const args = call.args || {};
|
|
4590
5153
|
let result;
|
|
4591
|
-
if (
|
|
5154
|
+
if (call.name === CODE_MODE_TOOL_NAME) {
|
|
5155
|
+
const codeTool = await getCodeModeTool();
|
|
5156
|
+
result = await codeTool.execute(args);
|
|
5157
|
+
} else if (triggerTools && triggerTools[call.name]) {
|
|
4592
5158
|
result = await triggerTools[call.name].execute(args);
|
|
4593
5159
|
} else {
|
|
4594
5160
|
result = await executeToolWithToken(client, call.name, args, finalOptions);
|
|
@@ -4607,7 +5173,33 @@ async function getGoogleTools(client, options) {
|
|
|
4607
5173
|
const finalOptions = providerTokens ? { ...options, providerTokens } : options;
|
|
4608
5174
|
await ensureClientConnected(client);
|
|
4609
5175
|
const mcpTools = await client.getEnabledToolsAsync();
|
|
4610
|
-
const
|
|
5176
|
+
const mode = options?.mode ?? "code";
|
|
5177
|
+
let googleTools;
|
|
5178
|
+
if (mode === "code") {
|
|
5179
|
+
const TypeEnum = await getGoogleType();
|
|
5180
|
+
const codeTool = buildCodeModeTool(client, {
|
|
5181
|
+
tools: mcpTools,
|
|
5182
|
+
providerTokens,
|
|
5183
|
+
context: options?.context,
|
|
5184
|
+
integrationIds: client.__oauthConfig?.integrations?.map((i) => i.id)
|
|
5185
|
+
});
|
|
5186
|
+
googleTools = [{
|
|
5187
|
+
name: CODE_MODE_TOOL_NAME,
|
|
5188
|
+
description: codeTool.description,
|
|
5189
|
+
parameters: {
|
|
5190
|
+
type: TypeEnum.OBJECT,
|
|
5191
|
+
properties: {
|
|
5192
|
+
code: {
|
|
5193
|
+
type: TypeEnum.STRING,
|
|
5194
|
+
description: codeTool.parameters.properties.code.description
|
|
5195
|
+
}
|
|
5196
|
+
},
|
|
5197
|
+
required: ["code"]
|
|
5198
|
+
}
|
|
5199
|
+
}];
|
|
5200
|
+
} else {
|
|
5201
|
+
googleTools = await Promise.all(mcpTools.map((mcpTool) => convertMCPToolToGoogle(mcpTool, client, finalOptions)));
|
|
5202
|
+
}
|
|
4611
5203
|
const triggerConfig = client.__triggerConfig;
|
|
4612
5204
|
if (triggerConfig) {
|
|
4613
5205
|
const triggerTools = createTriggerTools(triggerConfig, options?.context);
|
|
@@ -4707,8 +5299,25 @@ async function getVercelAITools(client, options) {
|
|
|
4707
5299
|
await ensureClientConnected(client);
|
|
4708
5300
|
const mcpTools = await client.getEnabledToolsAsync();
|
|
4709
5301
|
const vercelTools = {};
|
|
4710
|
-
|
|
4711
|
-
|
|
5302
|
+
const mode = options?.mode ?? "code";
|
|
5303
|
+
if (mode === "code") {
|
|
5304
|
+
const codeTool = buildCodeModeTool(client, {
|
|
5305
|
+
tools: mcpTools,
|
|
5306
|
+
providerTokens,
|
|
5307
|
+
context: options?.context,
|
|
5308
|
+
integrationIds: client.__oauthConfig?.integrations?.map((i) => i.id) ?? client.integrations?.map?.((i) => i.id)
|
|
5309
|
+
});
|
|
5310
|
+
vercelTools[CODE_MODE_TOOL_NAME] = {
|
|
5311
|
+
description: codeTool.description,
|
|
5312
|
+
inputSchema: exports_external.object({
|
|
5313
|
+
code: exports_external.string().describe(codeTool.parameters.properties.code.description)
|
|
5314
|
+
}),
|
|
5315
|
+
execute: async (args) => codeTool.execute(args)
|
|
5316
|
+
};
|
|
5317
|
+
} else {
|
|
5318
|
+
for (const mcpTool of mcpTools) {
|
|
5319
|
+
vercelTools[mcpTool.name] = convertMCPToolToVercelAI(mcpTool, client, finalOptions);
|
|
5320
|
+
}
|
|
4712
5321
|
}
|
|
4713
5322
|
const triggerConfig = client.__triggerConfig;
|
|
4714
5323
|
if (triggerConfig) {
|
|
@@ -4740,7 +5349,22 @@ async function getOpenAITools(client, options) {
|
|
|
4740
5349
|
const finalOptions = providerTokens ? { ...options, providerTokens } : options;
|
|
4741
5350
|
await ensureClientConnected(client);
|
|
4742
5351
|
const mcpTools = await client.getEnabledToolsAsync();
|
|
4743
|
-
const
|
|
5352
|
+
const mode = options?.mode ?? "code";
|
|
5353
|
+
const openaiTools = mode === "code" ? (() => {
|
|
5354
|
+
const codeTool = buildCodeModeTool(client, {
|
|
5355
|
+
tools: mcpTools,
|
|
5356
|
+
providerTokens,
|
|
5357
|
+
context: options?.context,
|
|
5358
|
+
integrationIds: client.__oauthConfig?.integrations?.map((i) => i.id)
|
|
5359
|
+
});
|
|
5360
|
+
return [{
|
|
5361
|
+
type: "function",
|
|
5362
|
+
name: CODE_MODE_TOOL_NAME,
|
|
5363
|
+
description: codeTool.description,
|
|
5364
|
+
parameters: codeTool.parameters,
|
|
5365
|
+
strict: options?.strict ?? null
|
|
5366
|
+
}];
|
|
5367
|
+
})() : mcpTools.map((mcpTool) => convertMCPToolToOpenAI(mcpTool, client, finalOptions));
|
|
4744
5368
|
const triggerConfig = client.__triggerConfig;
|
|
4745
5369
|
if (triggerConfig) {
|
|
4746
5370
|
const triggerTools = createTriggerTools(triggerConfig, options?.context);
|
|
@@ -4765,6 +5389,19 @@ async function handleOpenAIToolCalls(client, toolCalls, options) {
|
|
|
4765
5389
|
const toolOutputs = [];
|
|
4766
5390
|
const triggerConfig = client.__triggerConfig;
|
|
4767
5391
|
const triggerTools = triggerConfig ? createTriggerTools(triggerConfig, options?.context) : null;
|
|
5392
|
+
let cachedCodeModeTool = null;
|
|
5393
|
+
const getCodeModeTool = async () => {
|
|
5394
|
+
if (cachedCodeModeTool)
|
|
5395
|
+
return cachedCodeModeTool;
|
|
5396
|
+
const mcpTools = await client.getEnabledToolsAsync();
|
|
5397
|
+
cachedCodeModeTool = buildCodeModeTool(client, {
|
|
5398
|
+
tools: mcpTools,
|
|
5399
|
+
providerTokens: options?.providerTokens,
|
|
5400
|
+
context: options?.context,
|
|
5401
|
+
integrationIds: client.__oauthConfig?.integrations?.map((i) => i.id)
|
|
5402
|
+
});
|
|
5403
|
+
return cachedCodeModeTool;
|
|
5404
|
+
};
|
|
4768
5405
|
for (const output of toolCalls) {
|
|
4769
5406
|
if (output.type === "function_call") {
|
|
4770
5407
|
const toolCall = {
|
|
@@ -4775,7 +5412,10 @@ async function handleOpenAIToolCalls(client, toolCalls, options) {
|
|
|
4775
5412
|
try {
|
|
4776
5413
|
const args = JSON.parse(toolCall.arguments);
|
|
4777
5414
|
let result;
|
|
4778
|
-
if (
|
|
5415
|
+
if (toolCall.name === CODE_MODE_TOOL_NAME) {
|
|
5416
|
+
const codeTool = await getCodeModeTool();
|
|
5417
|
+
result = await codeTool.execute(args);
|
|
5418
|
+
} else if (triggerTools && triggerTools[toolCall.name]) {
|
|
4779
5419
|
result = await triggerTools[toolCall.name].execute(args);
|
|
4780
5420
|
} else {
|
|
4781
5421
|
result = await executeToolWithToken(client, toolCall.name, args, options);
|