@inkeep/agents-run-api 0.22.0 → 0.22.2

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.
@@ -1,12 +1,60 @@
1
+ import { getLogger as getLogger$1 } from './chunk-A2S7GSHL.js';
1
2
  import { __publicField } from './chunk-PKBMQBKP.js';
2
- import { getLogger } from '@inkeep/agents-core';
3
3
  import { spawn } from 'child_process';
4
4
  import { createHash } from 'crypto';
5
5
  import { mkdirSync, existsSync, rmSync, writeFileSync } from 'fs';
6
6
  import { tmpdir } from 'os';
7
7
  import { join } from 'path';
8
+ import { getLogger } from '@inkeep/agents-core';
9
+ import { Sandbox } from '@vercel/sandbox';
10
+
11
+ // src/tools/sandbox-utils.ts
12
+ function createExecutionWrapper(executeCode, args) {
13
+ return `
14
+ // Function tool execution wrapper
15
+ const args = ${JSON.stringify(args, null, 2)};
8
16
 
9
- var logger = getLogger("local-sandbox-executor");
17
+ // User's function code
18
+ const execute = ${executeCode}
19
+
20
+ // Execute the function and output the result
21
+ (async () => {
22
+ try {
23
+ const result = await execute(args);
24
+ // Output result as JSON on the last line
25
+ console.log(JSON.stringify({ success: true, result }));
26
+ } catch (error) {
27
+ console.error(JSON.stringify({
28
+ success: false,
29
+ error: error instanceof Error ? error.message : String(error)
30
+ }));
31
+ process.exit(1);
32
+ }
33
+ })();
34
+ `;
35
+ }
36
+ function parseExecutionResult(stdout, functionId, logger4) {
37
+ try {
38
+ const outputLines = stdout.split("\n").filter((line) => line.trim());
39
+ const resultLine = outputLines[outputLines.length - 1];
40
+ return JSON.parse(resultLine);
41
+ } catch (parseError) {
42
+ if (logger4) {
43
+ logger4.warn(
44
+ {
45
+ functionId,
46
+ stdout,
47
+ parseError
48
+ },
49
+ "Failed to parse execution result"
50
+ );
51
+ }
52
+ return stdout;
53
+ }
54
+ }
55
+
56
+ // src/tools/NativeSandboxExecutor.ts
57
+ var logger = getLogger("native-sandbox-executor");
10
58
  var ExecutionSemaphore = class {
11
59
  constructor(permits, maxWaitTimeMs = 3e4) {
12
60
  __publicField(this, "permits");
@@ -59,7 +107,7 @@ var ExecutionSemaphore = class {
59
107
  return this.waitQueue.length;
60
108
  }
61
109
  };
62
- var _LocalSandboxExecutor = class _LocalSandboxExecutor {
110
+ var _NativeSandboxExecutor = class _NativeSandboxExecutor {
63
111
  constructor() {
64
112
  __publicField(this, "tempDir");
65
113
  __publicField(this, "sandboxPool", {});
@@ -72,10 +120,10 @@ var _LocalSandboxExecutor = class _LocalSandboxExecutor {
72
120
  this.startPoolCleanup();
73
121
  }
74
122
  static getInstance() {
75
- if (!_LocalSandboxExecutor.instance) {
76
- _LocalSandboxExecutor.instance = new _LocalSandboxExecutor();
123
+ if (!_NativeSandboxExecutor.instance) {
124
+ _NativeSandboxExecutor.instance = new _NativeSandboxExecutor();
77
125
  }
78
- return _LocalSandboxExecutor.instance;
126
+ return _NativeSandboxExecutor.instance;
79
127
  }
80
128
  getSemaphore(vcpus) {
81
129
  const effectiveVcpus = Math.max(1, vcpus || 1);
@@ -276,7 +324,7 @@ var _LocalSandboxExecutor = class _LocalSandboxExecutor {
276
324
  }
277
325
  try {
278
326
  const moduleType = this.detectModuleType(config.executeCode, config.sandboxConfig?.runtime);
279
- const executionCode = this.wrapFunctionCode(config.executeCode, args);
327
+ const executionCode = createExecutionWrapper(config.executeCode, args);
280
328
  const fileExtension = moduleType === "esm" ? "mjs" : "js";
281
329
  writeFileSync(join(sandboxDir, `index.${fileExtension}`), executionCode, "utf8");
282
330
  const result = await this.executeInSandbox(
@@ -383,11 +431,16 @@ var _LocalSandboxExecutor = class _LocalSandboxExecutor {
383
431
  clearTimeout(timeoutId);
384
432
  if (code === 0) {
385
433
  try {
386
- const result = JSON.parse(stdout);
387
- if (result.success) {
388
- resolve(result.result);
434
+ const result = parseExecutionResult(stdout, "function", logger);
435
+ if (typeof result === "object" && result !== null && "success" in result) {
436
+ const parsed = result;
437
+ if (parsed.success) {
438
+ resolve(parsed.result);
439
+ } else {
440
+ reject(new Error(parsed.error || "Function execution failed"));
441
+ }
389
442
  } else {
390
- reject(new Error(result.error || "Function execution failed"));
443
+ resolve(result);
391
444
  }
392
445
  } catch (parseError) {
393
446
  logger.error({ stdout, stderr, parseError }, "Failed to parse function result");
@@ -406,36 +459,276 @@ var _LocalSandboxExecutor = class _LocalSandboxExecutor {
406
459
  });
407
460
  });
408
461
  }
409
- wrapFunctionCode(executeCode, args) {
410
- return `
411
- // Wrapped function execution (ESM)
412
- const execute = ${executeCode};
413
- const args = ${JSON.stringify(args)};
414
-
415
- try {
416
- const result = execute(args);
417
-
418
- // Handle both sync and async functions
419
- if (result && typeof result.then === 'function') {
420
- // Async function - result is a Promise
421
- result
422
- .then(result => {
423
- console.log(JSON.stringify({ success: true, result }));
424
- })
425
- .catch(error => {
426
- console.log(JSON.stringify({ success: false, error: error.message }));
462
+ };
463
+ __publicField(_NativeSandboxExecutor, "instance", null);
464
+ var NativeSandboxExecutor = _NativeSandboxExecutor;
465
+ var logger2 = getLogger$1("VercelSandboxExecutor");
466
+ var _VercelSandboxExecutor = class _VercelSandboxExecutor {
467
+ constructor(config) {
468
+ __publicField(this, "config");
469
+ this.config = config;
470
+ logger2.info(
471
+ {
472
+ teamId: config.teamId,
473
+ projectId: config.projectId,
474
+ runtime: config.runtime,
475
+ timeout: config.timeout,
476
+ vcpus: config.vcpus
477
+ },
478
+ "VercelSandboxExecutor initialized"
479
+ );
480
+ }
481
+ /**
482
+ * Get singleton instance of VercelSandboxExecutor
483
+ */
484
+ static getInstance(config) {
485
+ if (!_VercelSandboxExecutor.instance) {
486
+ _VercelSandboxExecutor.instance = new _VercelSandboxExecutor(config);
487
+ }
488
+ return _VercelSandboxExecutor.instance;
489
+ }
490
+ /**
491
+ * Execute a function tool in Vercel Sandbox
492
+ */
493
+ async executeFunctionTool(functionId, args, toolConfig) {
494
+ const startTime = Date.now();
495
+ const logs = [];
496
+ try {
497
+ logger2.info(
498
+ {
499
+ functionId,
500
+ functionName: toolConfig.name
501
+ },
502
+ "Executing function in Vercel Sandbox"
503
+ );
504
+ const sandbox = await Sandbox.create({
505
+ token: this.config.token,
506
+ teamId: this.config.teamId,
507
+ projectId: this.config.projectId,
508
+ timeout: this.config.timeout,
509
+ resources: {
510
+ vcpus: this.config.vcpus || 1
511
+ },
512
+ runtime: this.config.runtime
427
513
  });
428
- } else {
429
- // Sync function - result is immediate
430
- console.log(JSON.stringify({ success: true, result }));
514
+ logger2.info(
515
+ {
516
+ functionId,
517
+ sandboxId: sandbox.sandboxId
518
+ },
519
+ `Sandbox created for function ${functionId}`
520
+ );
521
+ try {
522
+ if (toolConfig.dependencies && Object.keys(toolConfig.dependencies).length > 0) {
523
+ logger2.debug(
524
+ {
525
+ functionId,
526
+ functionName: toolConfig.name,
527
+ dependencies: toolConfig.dependencies
528
+ },
529
+ "Installing dependencies"
530
+ );
531
+ const packageJson = {
532
+ dependencies: toolConfig.dependencies
533
+ };
534
+ const packageJsonContent = JSON.stringify(packageJson, null, 2);
535
+ await sandbox.writeFiles([
536
+ {
537
+ path: "package.json",
538
+ content: Buffer.from(packageJsonContent, "utf-8")
539
+ }
540
+ ]);
541
+ const installCmd = await sandbox.runCommand({
542
+ cmd: "npm",
543
+ args: ["install", "--omit=dev"]
544
+ });
545
+ const installStdout = await installCmd.stdout();
546
+ const installStderr = await installCmd.stderr();
547
+ if (installStdout) {
548
+ logs.push(installStdout);
549
+ }
550
+ if (installStderr) {
551
+ logs.push(installStderr);
552
+ }
553
+ if (installCmd.exitCode !== 0) {
554
+ throw new Error(`Failed to install dependencies: ${installStderr}`);
555
+ }
556
+ }
557
+ const executionCode = createExecutionWrapper(toolConfig.executeCode, args);
558
+ const filename = this.config.runtime === "typescript" ? "execute.ts" : "execute.js";
559
+ await sandbox.writeFiles([
560
+ {
561
+ path: filename,
562
+ content: Buffer.from(executionCode, "utf-8")
563
+ }
564
+ ]);
565
+ logger2.info(
566
+ {
567
+ functionId,
568
+ runtime: this.config.runtime === "typescript" ? "tsx" : "node"
569
+ },
570
+ `Execution code written to file for runtime ${this.config.runtime}`
571
+ );
572
+ const runtime = this.config.runtime === "typescript" ? "tsx" : "node";
573
+ const executeCmd = await sandbox.runCommand({
574
+ cmd: runtime,
575
+ args: [filename]
576
+ });
577
+ const executeStdout = await executeCmd.stdout();
578
+ const executeStderr = await executeCmd.stderr();
579
+ if (executeStdout) {
580
+ logs.push(executeStdout);
581
+ }
582
+ if (executeStderr) {
583
+ logs.push(executeStderr);
584
+ }
585
+ const executionTime = Date.now() - startTime;
586
+ if (executeCmd.exitCode !== 0) {
587
+ logger2.error(
588
+ {
589
+ functionId,
590
+ exitCode: executeCmd.exitCode,
591
+ stderr: executeStderr
592
+ },
593
+ "Function execution failed"
594
+ );
595
+ return {
596
+ success: false,
597
+ error: executeStderr || "Function execution failed with non-zero exit code",
598
+ logs,
599
+ executionTime
600
+ };
601
+ }
602
+ const result = parseExecutionResult(executeStdout, functionId, logger2);
603
+ logger2.info(
604
+ {
605
+ functionId,
606
+ executionTime
607
+ },
608
+ "Function executed successfully in Vercel Sandbox"
609
+ );
610
+ return {
611
+ success: true,
612
+ result,
613
+ logs,
614
+ executionTime
615
+ };
616
+ } finally {
617
+ await sandbox.stop();
618
+ }
619
+ } catch (error) {
620
+ const executionTime = Date.now() - startTime;
621
+ const errorMessage = error instanceof Error ? error.message : String(error);
622
+ logger2.error(
623
+ {
624
+ functionId,
625
+ error: errorMessage,
626
+ executionTime
627
+ },
628
+ "Vercel Sandbox execution error"
629
+ );
630
+ return {
631
+ success: false,
632
+ error: errorMessage,
633
+ logs,
634
+ executionTime
635
+ };
636
+ }
431
637
  }
432
- } catch (error) {
433
- console.log(JSON.stringify({ success: false, error: error.message }));
434
- }
435
- `;
638
+ /**
639
+ * Clean up resources
640
+ */
641
+ async cleanup() {
642
+ logger2.info({}, "VercelSandboxExecutor cleanup completed");
643
+ }
644
+ };
645
+ __publicField(_VercelSandboxExecutor, "instance");
646
+ var VercelSandboxExecutor = _VercelSandboxExecutor;
647
+
648
+ // src/tools/SandboxExecutorFactory.ts
649
+ var logger3 = getLogger$1("SandboxExecutorFactory");
650
+ var _SandboxExecutorFactory = class _SandboxExecutorFactory {
651
+ constructor() {
652
+ __publicField(this, "nativeExecutor", null);
653
+ __publicField(this, "vercelExecutors", /* @__PURE__ */ new Map());
654
+ logger3.info({}, "SandboxExecutorFactory initialized");
655
+ }
656
+ /**
657
+ * Get singleton instance of SandboxExecutorFactory
658
+ */
659
+ static getInstance() {
660
+ if (!_SandboxExecutorFactory.instance) {
661
+ _SandboxExecutorFactory.instance = new _SandboxExecutorFactory();
662
+ }
663
+ return _SandboxExecutorFactory.instance;
664
+ }
665
+ /**
666
+ * Execute a function tool using the appropriate sandbox provider
667
+ */
668
+ async executeFunctionTool(functionId, args, config) {
669
+ const sandboxConfig = config.sandboxConfig;
670
+ if (!sandboxConfig) {
671
+ throw new Error("Sandbox configuration is required for function tool execution");
672
+ }
673
+ if (sandboxConfig.provider === "native") {
674
+ return this.executeInNativeSandbox(functionId, args, config);
675
+ }
676
+ if (sandboxConfig.provider === "vercel") {
677
+ return this.executeInVercelSandbox(functionId, args, config);
678
+ }
679
+ throw new Error(`Unknown sandbox provider: ${sandboxConfig.provider}`);
680
+ }
681
+ /**
682
+ * Execute in native sandbox
683
+ */
684
+ async executeInNativeSandbox(functionId, args, config) {
685
+ if (!this.nativeExecutor) {
686
+ this.nativeExecutor = NativeSandboxExecutor.getInstance();
687
+ logger3.info({}, "Native sandbox executor created");
688
+ }
689
+ return this.nativeExecutor.executeFunctionTool(functionId, args, config);
690
+ }
691
+ /**
692
+ * Execute in Vercel sandbox
693
+ */
694
+ async executeInVercelSandbox(functionId, args, config) {
695
+ const vercelConfig = config.sandboxConfig;
696
+ const configKey = `${vercelConfig.teamId}:${vercelConfig.projectId}`;
697
+ if (!this.vercelExecutors.has(configKey)) {
698
+ const executor2 = VercelSandboxExecutor.getInstance(vercelConfig);
699
+ this.vercelExecutors.set(configKey, executor2);
700
+ logger3.info(
701
+ {
702
+ teamId: vercelConfig.teamId,
703
+ projectId: vercelConfig.projectId
704
+ },
705
+ "Vercel sandbox executor created"
706
+ );
707
+ }
708
+ const executor = this.vercelExecutors.get(configKey);
709
+ if (!executor) {
710
+ throw new Error(`Failed to get Vercel executor for config: ${configKey}`);
711
+ }
712
+ const result = await executor.executeFunctionTool(functionId, args, config);
713
+ if (!result.success) {
714
+ throw new Error(result.error || "Vercel sandbox execution failed");
715
+ }
716
+ return result.result;
717
+ }
718
+ /**
719
+ * Clean up all sandbox executors
720
+ */
721
+ async cleanup() {
722
+ logger3.info({}, "Cleaning up sandbox executors");
723
+ this.nativeExecutor = null;
724
+ for (const [key, executor] of this.vercelExecutors.entries()) {
725
+ await executor.cleanup();
726
+ this.vercelExecutors.delete(key);
727
+ }
728
+ logger3.info({}, "Sandbox executor cleanup completed");
436
729
  }
437
730
  };
438
- __publicField(_LocalSandboxExecutor, "instance", null);
439
- var LocalSandboxExecutor = _LocalSandboxExecutor;
731
+ __publicField(_SandboxExecutorFactory, "instance");
732
+ var SandboxExecutorFactory = _SandboxExecutorFactory;
440
733
 
441
- export { LocalSandboxExecutor };
734
+ export { SandboxExecutorFactory };