@inkeep/agents-run-api 0.21.1 → 0.22.1
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/{LocalSandboxExecutor-TSOIXW7O.js → SandboxExecutorFactory-FMNUKYDI.js} +332 -39
- package/dist/index.cjs +592 -268
- package/dist/index.d.cts +19 -2
- package/dist/index.d.ts +19 -2
- package/dist/index.js +219 -204
- package/dist/instrumentation.js +1 -1
- package/package.json +3 -2
- package/dist/{chunk-RZXPMRBA.js → chunk-TVLDBLRZ.js} +1 -1
|
@@ -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
|
-
|
|
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
|
|
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 (!
|
|
76
|
-
|
|
123
|
+
if (!_NativeSandboxExecutor.instance) {
|
|
124
|
+
_NativeSandboxExecutor.instance = new _NativeSandboxExecutor();
|
|
77
125
|
}
|
|
78
|
-
return
|
|
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 =
|
|
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 =
|
|
387
|
-
if (result
|
|
388
|
-
|
|
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
|
-
|
|
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
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
|
|
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
|
-
|
|
429
|
-
|
|
430
|
-
|
|
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
|
-
|
|
433
|
-
|
|
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(
|
|
439
|
-
var
|
|
731
|
+
__publicField(_SandboxExecutorFactory, "instance");
|
|
732
|
+
var SandboxExecutorFactory = _SandboxExecutorFactory;
|
|
440
733
|
|
|
441
|
-
export {
|
|
734
|
+
export { SandboxExecutorFactory };
|