@inkeep/agents-api 0.0.0-dev-20260121234635 → 0.0.0-dev-20260122001454
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/.well-known/workflow/v1/manifest.debug.json +11 -11
- package/dist/createApp.d.ts +2 -2
- package/dist/domains/evals/routes/datasetTriggers.d.ts +2 -2
- package/dist/domains/evals/routes/index.d.ts +2 -2
- package/dist/domains/evals/workflow/routes.d.ts +2 -2
- package/dist/domains/manage/routes/conversations.d.ts +2 -2
- package/dist/domains/manage/routes/index.d.ts +2 -2
- package/dist/domains/manage/routes/mcp.d.ts +2 -2
- package/dist/domains/run/agents/Agent.js +1 -1
- package/dist/domains/run/agents/relationTools.d.ts +2 -2
- package/dist/domains/run/routes/webhooks.js +7 -13
- package/dist/domains/run/services/AgentSession.js +9 -0
- package/dist/domains/run/tools/NativeSandboxExecutor.d.ts +3 -2
- package/dist/domains/run/tools/NativeSandboxExecutor.js +76 -46
- package/dist/domains/run/tools/SandboxExecutorFactory.d.ts +11 -1
- package/dist/domains/run/tools/SandboxExecutorFactory.js +27 -3
- package/dist/domains/run/tools/VercelSandboxExecutor.d.ts +3 -11
- package/dist/domains/run/tools/VercelSandboxExecutor.js +137 -127
- package/dist/domains/run/utils/token-estimator.d.ts +2 -2
- package/dist/factory.d.ts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/middleware/manageAuth.d.ts +2 -2
- package/dist/middleware/projectAccess.d.ts +2 -2
- package/dist/middleware/requirePermission.d.ts +2 -2
- package/dist/middleware/runAuth.d.ts +4 -4
- package/dist/middleware/tenantAccess.d.ts +2 -2
- package/dist/middleware/tracing.d.ts +3 -3
- package/package.json +3 -3
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"steps": {
|
|
3
|
+
"node_modules/.pnpm/workflow@4.0.1-beta.33_@aws-sdk+client-sts@3.970.0_@opentelemetry+api@1.9.0_@types+reac_5c488396978166b4f12e99cb3aa4a769/node_modules/workflow/dist/internal/builtins.js": {
|
|
4
|
+
"__builtin_response_array_buffer": {
|
|
5
|
+
"stepId": "__builtin_response_array_buffer"
|
|
6
|
+
},
|
|
7
|
+
"__builtin_response_json": {
|
|
8
|
+
"stepId": "__builtin_response_json"
|
|
9
|
+
},
|
|
10
|
+
"__builtin_response_text": {
|
|
11
|
+
"stepId": "__builtin_response_text"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
3
14
|
"src/domains/evals/workflow/functions/evaluateConversation.ts": {
|
|
4
15
|
"executeEvaluatorStep": {
|
|
5
16
|
"stepId": "step//src/domains/evals/workflow/functions/evaluateConversation.ts//executeEvaluatorStep"
|
|
@@ -14,17 +25,6 @@
|
|
|
14
25
|
"stepId": "step//src/domains/evals/workflow/functions/evaluateConversation.ts//logStep"
|
|
15
26
|
}
|
|
16
27
|
},
|
|
17
|
-
"node_modules/.pnpm/workflow@4.0.1-beta.33_@aws-sdk+client-sts@3.970.0_@opentelemetry+api@1.9.0_@types+reac_5c488396978166b4f12e99cb3aa4a769/node_modules/workflow/dist/internal/builtins.js": {
|
|
18
|
-
"__builtin_response_array_buffer": {
|
|
19
|
-
"stepId": "__builtin_response_array_buffer"
|
|
20
|
-
},
|
|
21
|
-
"__builtin_response_json": {
|
|
22
|
-
"stepId": "__builtin_response_json"
|
|
23
|
-
},
|
|
24
|
-
"__builtin_response_text": {
|
|
25
|
-
"stepId": "__builtin_response_text"
|
|
26
|
-
}
|
|
27
|
-
},
|
|
28
28
|
"src/domains/evals/workflow/functions/runDatasetItem.ts": {
|
|
29
29
|
"callChatApiStep": {
|
|
30
30
|
"stepId": "step//src/domains/evals/workflow/functions/runDatasetItem.ts//callChatApiStep"
|
package/dist/createApp.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { AppConfig } from "./types/app.js";
|
|
2
2
|
import "./types/index.js";
|
|
3
3
|
import { Hono } from "hono";
|
|
4
|
-
import * as
|
|
4
|
+
import * as hono_types8 from "hono/types";
|
|
5
5
|
|
|
6
6
|
//#region src/createApp.d.ts
|
|
7
7
|
declare const isWebhookRoute: (path: string) => boolean;
|
|
8
|
-
declare function createAgentsHono(config: AppConfig): Hono<
|
|
8
|
+
declare function createAgentsHono(config: AppConfig): Hono<hono_types8.BlankEnv, hono_types8.BlankSchema, "/">;
|
|
9
9
|
//#endregion
|
|
10
10
|
export { createAgentsHono, isWebhookRoute };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { OpenAPIHono } from "@hono/zod-openapi";
|
|
2
|
-
import * as
|
|
2
|
+
import * as hono16 from "hono";
|
|
3
3
|
|
|
4
4
|
//#region src/domains/evals/routes/datasetTriggers.d.ts
|
|
5
|
-
declare const app: OpenAPIHono<
|
|
5
|
+
declare const app: OpenAPIHono<hono16.Env, {}, "/">;
|
|
6
6
|
//#endregion
|
|
7
7
|
export { app as default };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { OpenAPIHono } from "@hono/zod-openapi";
|
|
2
|
-
import * as
|
|
2
|
+
import * as hono17 from "hono";
|
|
3
3
|
|
|
4
4
|
//#region src/domains/evals/routes/index.d.ts
|
|
5
|
-
declare const app: OpenAPIHono<
|
|
5
|
+
declare const app: OpenAPIHono<hono17.Env, {}, "/">;
|
|
6
6
|
//#endregion
|
|
7
7
|
export { app as default };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Hono } from "hono";
|
|
2
|
-
import * as
|
|
2
|
+
import * as hono_types1 from "hono/types";
|
|
3
3
|
|
|
4
4
|
//#region src/domains/evals/workflow/routes.d.ts
|
|
5
|
-
declare const workflowRoutes: Hono<
|
|
5
|
+
declare const workflowRoutes: Hono<hono_types1.BlankEnv, hono_types1.BlankSchema, "/">;
|
|
6
6
|
//#endregion
|
|
7
7
|
export { workflowRoutes };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { OpenAPIHono } from "@hono/zod-openapi";
|
|
2
|
-
import * as
|
|
2
|
+
import * as hono14 from "hono";
|
|
3
3
|
|
|
4
4
|
//#region src/domains/manage/routes/conversations.d.ts
|
|
5
|
-
declare const app: OpenAPIHono<
|
|
5
|
+
declare const app: OpenAPIHono<hono14.Env, {}, "/">;
|
|
6
6
|
//#endregion
|
|
7
7
|
export { app as default };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { OpenAPIHono } from "@hono/zod-openapi";
|
|
2
|
-
import * as
|
|
2
|
+
import * as hono15 from "hono";
|
|
3
3
|
|
|
4
4
|
//#region src/domains/manage/routes/index.d.ts
|
|
5
|
-
declare const app: OpenAPIHono<
|
|
5
|
+
declare const app: OpenAPIHono<hono15.Env, {}, "/">;
|
|
6
6
|
//#endregion
|
|
7
7
|
export { app as default };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Hono } from "hono";
|
|
2
|
-
import * as
|
|
2
|
+
import * as hono_types3 from "hono/types";
|
|
3
3
|
|
|
4
4
|
//#region src/domains/manage/routes/mcp.d.ts
|
|
5
|
-
declare const app: Hono<
|
|
5
|
+
declare const app: Hono<hono_types3.BlankEnv, hono_types3.BlankSchema, "/">;
|
|
6
6
|
//#endregion
|
|
7
7
|
export { app as default };
|
|
@@ -728,7 +728,7 @@ var Agent = class {
|
|
|
728
728
|
})).data ?? [];
|
|
729
729
|
if (functionToolsData.length === 0) return functionTools;
|
|
730
730
|
const { SandboxExecutorFactory } = await import("../tools/SandboxExecutorFactory.js");
|
|
731
|
-
const sandboxExecutor = SandboxExecutorFactory.
|
|
731
|
+
const sandboxExecutor = sessionId ? SandboxExecutorFactory.getForSession(sessionId) : new SandboxExecutorFactory();
|
|
732
732
|
for (const functionToolDef of functionToolsData) {
|
|
733
733
|
const functionId = functionToolDef.functionId;
|
|
734
734
|
if (!functionId) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AgentConfig, DelegateRelation } from "./Agent.js";
|
|
2
2
|
import { InternalRelation } from "../utils/project.js";
|
|
3
|
-
import * as
|
|
3
|
+
import * as _inkeep_agents_core1 from "@inkeep/agents-core";
|
|
4
4
|
import { CredentialStoreRegistry, FullExecutionContext } from "@inkeep/agents-core";
|
|
5
5
|
import * as ai0 from "ai";
|
|
6
6
|
|
|
@@ -44,7 +44,7 @@ declare function createDelegateToAgentTool({
|
|
|
44
44
|
message: string;
|
|
45
45
|
}, {
|
|
46
46
|
toolCallId: any;
|
|
47
|
-
result:
|
|
47
|
+
result: _inkeep_agents_core1.Message | _inkeep_agents_core1.Task;
|
|
48
48
|
}>;
|
|
49
49
|
/**
|
|
50
50
|
* Parameters for building a transfer relation config
|
|
@@ -6,7 +6,7 @@ import { createSSEStreamHelper } from "../utils/stream-helpers.js";
|
|
|
6
6
|
import { ExecutionHandler } from "../handlers/executionHandler.js";
|
|
7
7
|
import { OpenAPIHono, createRoute, z } from "@hono/zod-openapi";
|
|
8
8
|
import { JsonTransformer, createApiError, createMessage, createOrGetConversation, createTriggerInvocation, generateId, getConversationId, getFullProjectWithRelationIds, getTriggerById, interpolateTemplate, setActiveAgentForConversation, updateTriggerInvocationStatus, verifySigningSecret, verifyTriggerAuth, withRef } from "@inkeep/agents-core";
|
|
9
|
-
import { context, propagation, trace } from "@opentelemetry/api";
|
|
9
|
+
import { ROOT_CONTEXT, context, propagation, trace } from "@opentelemetry/api";
|
|
10
10
|
import Ajv from "ajv";
|
|
11
11
|
|
|
12
12
|
//#region src/domains/run/routes/webhooks.ts
|
|
@@ -232,18 +232,12 @@ async function invokeAgentAsync(params) {
|
|
|
232
232
|
"message.content": userMessage,
|
|
233
233
|
"message.parts": JSON.stringify(messageParts),
|
|
234
234
|
"message.timestamp": (/* @__PURE__ */ new Date()).toISOString()
|
|
235
|
-
} }, async (span) => {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
currentBag = currentBag.setEntry("agent.id", { value: agentId });
|
|
242
|
-
currentBag = currentBag.setEntry("invocation.type", { value: "trigger" });
|
|
243
|
-
currentBag = currentBag.setEntry("trigger.id", { value: triggerId });
|
|
244
|
-
currentBag = currentBag.setEntry("trigger.invocation.id", { value: invocationId });
|
|
245
|
-
const ctxWithBaggage = propagation.setBaggage(context.active(), currentBag);
|
|
246
|
-
return await context.with(ctxWithBaggage, async () => {
|
|
235
|
+
} }, ROOT_CONTEXT, async (span) => {
|
|
236
|
+
const spanCtx = trace.setSpan(ROOT_CONTEXT, span);
|
|
237
|
+
let bag = propagation.getBaggage(spanCtx) ?? propagation.createBaggage();
|
|
238
|
+
bag = bag.setEntry("conversation.id", { value: conversationId }).setEntry("tenant.id", { value: tenantId }).setEntry("project.id", { value: projectId }).setEntry("agent.id", { value: agentId }).setEntry("invocation.type", { value: "trigger" }).setEntry("trigger.id", { value: triggerId }).setEntry("trigger.invocation.id", { value: invocationId });
|
|
239
|
+
const ctx = propagation.setBaggage(spanCtx, bag);
|
|
240
|
+
return await context.with(ctx, async () => {
|
|
247
241
|
try {
|
|
248
242
|
logger.info({
|
|
249
243
|
tenantId,
|
|
@@ -345,6 +345,15 @@ var AgentSession = class {
|
|
|
345
345
|
this.artifactProcessingErrors.clear();
|
|
346
346
|
this.artifactCache.clear();
|
|
347
347
|
if (this.sessionId) toolSessionManager.endSession(this.sessionId);
|
|
348
|
+
if (this.sessionId) try {
|
|
349
|
+
const { SandboxExecutorFactory } = await import("../tools/SandboxExecutorFactory.js");
|
|
350
|
+
await SandboxExecutorFactory.cleanupSession(this.sessionId);
|
|
351
|
+
} catch (error) {
|
|
352
|
+
logger.warn({
|
|
353
|
+
sessionId: this.sessionId,
|
|
354
|
+
error
|
|
355
|
+
}, "Failed to cleanup session-scoped sandbox executors");
|
|
356
|
+
}
|
|
348
357
|
if (this.scheduledTimeouts) {
|
|
349
358
|
for (const timeoutId of this.scheduledTimeouts) clearTimeout(timeoutId);
|
|
350
359
|
this.scheduledTimeouts.clear();
|
|
@@ -13,10 +13,11 @@ interface FunctionToolConfig {
|
|
|
13
13
|
declare class NativeSandboxExecutor {
|
|
14
14
|
private tempDir;
|
|
15
15
|
private sandboxPool;
|
|
16
|
-
private static instance;
|
|
17
16
|
private executionSemaphores;
|
|
17
|
+
private poolCleanupInterval;
|
|
18
|
+
private sandboxInitPromises;
|
|
18
19
|
constructor();
|
|
19
|
-
|
|
20
|
+
cleanup(): Promise<void>;
|
|
20
21
|
private getSemaphore;
|
|
21
22
|
getExecutionStats(): Record<string, {
|
|
22
23
|
availablePermits: number;
|
|
@@ -3,7 +3,7 @@ import { FUNCTION_TOOL_EXECUTION_TIMEOUT_MS_DEFAULT, FUNCTION_TOOL_SANDBOX_CLEAN
|
|
|
3
3
|
import { createExecutionWrapper, parseExecutionResult } from "./sandbox-utils.js";
|
|
4
4
|
import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
5
5
|
import { join } from "node:path";
|
|
6
|
-
import { createHash } from "node:crypto";
|
|
6
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
7
7
|
import { spawn } from "node:child_process";
|
|
8
8
|
import { tmpdir } from "node:os";
|
|
9
9
|
|
|
@@ -52,8 +52,7 @@ import { tmpdir } from "node:os";
|
|
|
52
52
|
* - Works in Docker, Kubernetes, serverless (Vercel, Lambda)
|
|
53
53
|
* - No files left in project directory (no git pollution)
|
|
54
54
|
*
|
|
55
|
-
*
|
|
56
|
-
* across all tool executions, otherwise caching doesn't work.
|
|
55
|
+
* Note: In this repo, sandbox pooling is scoped to a single message/session via SandboxExecutorFactory.
|
|
57
56
|
*/
|
|
58
57
|
const logger = getLogger("native-sandbox-executor");
|
|
59
58
|
/**
|
|
@@ -105,19 +104,25 @@ var ExecutionSemaphore = class {
|
|
|
105
104
|
return this.waitQueue.length;
|
|
106
105
|
}
|
|
107
106
|
};
|
|
108
|
-
var NativeSandboxExecutor = class
|
|
107
|
+
var NativeSandboxExecutor = class {
|
|
109
108
|
tempDir;
|
|
110
109
|
sandboxPool = {};
|
|
111
|
-
static instance = null;
|
|
112
110
|
executionSemaphores = /* @__PURE__ */ new Map();
|
|
111
|
+
poolCleanupInterval = null;
|
|
112
|
+
sandboxInitPromises = /* @__PURE__ */ new Map();
|
|
113
113
|
constructor() {
|
|
114
114
|
this.tempDir = join(tmpdir(), "inkeep-sandboxes");
|
|
115
115
|
this.ensureTempDir();
|
|
116
116
|
this.startPoolCleanup();
|
|
117
117
|
}
|
|
118
|
-
|
|
119
|
-
if (
|
|
120
|
-
|
|
118
|
+
async cleanup() {
|
|
119
|
+
if (this.poolCleanupInterval) {
|
|
120
|
+
clearInterval(this.poolCleanupInterval);
|
|
121
|
+
this.poolCleanupInterval = null;
|
|
122
|
+
}
|
|
123
|
+
this.sandboxInitPromises.clear();
|
|
124
|
+
for (const sandbox of Object.values(this.sandboxPool)) this.cleanupSandbox(sandbox.sandboxDir);
|
|
125
|
+
this.sandboxPool = {};
|
|
121
126
|
}
|
|
122
127
|
getSemaphore(vcpus) {
|
|
123
128
|
const effectiveVcpus = Math.max(1, vcpus || 1);
|
|
@@ -154,16 +159,20 @@ var NativeSandboxExecutor = class NativeSandboxExecutor {
|
|
|
154
159
|
if (now - sandbox.lastUsed < FUNCTION_TOOL_SANDBOX_POOL_TTL_MS && sandbox.useCount < FUNCTION_TOOL_SANDBOX_MAX_USE_COUNT) {
|
|
155
160
|
sandbox.lastUsed = now;
|
|
156
161
|
sandbox.useCount++;
|
|
162
|
+
sandbox.activeCount++;
|
|
157
163
|
logger.debug({
|
|
158
164
|
poolKey,
|
|
159
165
|
useCount: sandbox.useCount,
|
|
160
166
|
sandboxDir: sandbox.sandboxDir,
|
|
161
|
-
lastUsed: new Date(sandbox.lastUsed)
|
|
167
|
+
lastUsed: new Date(sandbox.lastUsed),
|
|
168
|
+
activeCount: sandbox.activeCount
|
|
162
169
|
}, "Reusing cached sandbox");
|
|
163
170
|
return sandbox.sandboxDir;
|
|
164
171
|
}
|
|
165
|
-
|
|
166
|
-
|
|
172
|
+
if (sandbox.activeCount === 0) {
|
|
173
|
+
this.cleanupSandbox(sandbox.sandboxDir);
|
|
174
|
+
delete this.sandboxPool[poolKey];
|
|
175
|
+
}
|
|
167
176
|
}
|
|
168
177
|
return null;
|
|
169
178
|
}
|
|
@@ -174,7 +183,8 @@ var NativeSandboxExecutor = class NativeSandboxExecutor {
|
|
|
174
183
|
sandboxDir,
|
|
175
184
|
lastUsed: Date.now(),
|
|
176
185
|
useCount: 1,
|
|
177
|
-
dependencies
|
|
186
|
+
dependencies,
|
|
187
|
+
activeCount: 0
|
|
178
188
|
};
|
|
179
189
|
logger.debug({
|
|
180
190
|
poolKey,
|
|
@@ -196,10 +206,10 @@ var NativeSandboxExecutor = class NativeSandboxExecutor {
|
|
|
196
206
|
}
|
|
197
207
|
}
|
|
198
208
|
startPoolCleanup() {
|
|
199
|
-
setInterval(() => {
|
|
209
|
+
this.poolCleanupInterval = setInterval(() => {
|
|
200
210
|
const now = Date.now();
|
|
201
211
|
const keysToDelete = [];
|
|
202
|
-
for (const [key, sandbox] of Object.entries(this.sandboxPool)) if (now - sandbox.lastUsed > FUNCTION_TOOL_SANDBOX_POOL_TTL_MS || sandbox.useCount >= FUNCTION_TOOL_SANDBOX_MAX_USE_COUNT) {
|
|
212
|
+
for (const [key, sandbox] of Object.entries(this.sandboxPool)) if (sandbox.activeCount === 0 && (now - sandbox.lastUsed > FUNCTION_TOOL_SANDBOX_POOL_TTL_MS || sandbox.useCount >= FUNCTION_TOOL_SANDBOX_MAX_USE_COUNT)) {
|
|
203
213
|
this.cleanupSandbox(sandbox.sandboxDir);
|
|
204
214
|
keysToDelete.push(key);
|
|
205
215
|
}
|
|
@@ -257,42 +267,62 @@ var NativeSandboxExecutor = class NativeSandboxExecutor {
|
|
|
257
267
|
sandboxConfig: config.sandboxConfig,
|
|
258
268
|
poolSize: Object.keys(this.sandboxPool).length
|
|
259
269
|
}, "Executing function tool");
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
270
|
+
const sandboxDir = await (async () => {
|
|
271
|
+
const cachedDir = this.getCachedSandbox(dependencyHash);
|
|
272
|
+
if (cachedDir) return cachedDir;
|
|
273
|
+
const existingInit = this.sandboxInitPromises.get(dependencyHash);
|
|
274
|
+
if (existingInit) {
|
|
275
|
+
const dir = await existingInit;
|
|
276
|
+
const poolEntry = this.sandboxPool[dependencyHash];
|
|
277
|
+
if (poolEntry) poolEntry.activeCount++;
|
|
278
|
+
return dir;
|
|
279
|
+
}
|
|
280
|
+
const initPromise = (async () => {
|
|
281
|
+
const dir = join(this.tempDir, `sandbox-${dependencyHash}-${Date.now()}`);
|
|
282
|
+
mkdirSync(dir, { recursive: true });
|
|
283
|
+
logger.debug({
|
|
284
|
+
toolId,
|
|
285
|
+
dependencyHash,
|
|
286
|
+
sandboxDir: dir,
|
|
287
|
+
dependencies
|
|
288
|
+
}, "Creating new sandbox");
|
|
289
|
+
const packageJson = {
|
|
290
|
+
name: `function-tool-${toolId}`,
|
|
291
|
+
version: "1.0.0",
|
|
292
|
+
dependencies
|
|
293
|
+
};
|
|
294
|
+
writeFileSync(join(dir, "package.json"), JSON.stringify(packageJson, null, 2), "utf8");
|
|
295
|
+
if (Object.keys(dependencies).length > 0) await this.installDependencies(dir);
|
|
296
|
+
this.addToPool(dependencyHash, dir, dependencies);
|
|
297
|
+
this.sandboxPool[dependencyHash].activeCount++;
|
|
298
|
+
return dir;
|
|
299
|
+
})();
|
|
300
|
+
this.sandboxInitPromises.set(dependencyHash, initPromise);
|
|
301
|
+
try {
|
|
302
|
+
return await initPromise;
|
|
303
|
+
} finally {
|
|
304
|
+
this.sandboxInitPromises.delete(dependencyHash);
|
|
305
|
+
}
|
|
306
|
+
})();
|
|
307
|
+
let runDir = null;
|
|
284
308
|
try {
|
|
285
309
|
const moduleType = this.detectModuleType(config.executeCode, config.sandboxConfig?.runtime);
|
|
286
310
|
const executionCode = createExecutionWrapper(config.executeCode, args);
|
|
287
|
-
|
|
288
|
-
|
|
311
|
+
runDir = join(sandboxDir, "runs", `${Date.now()}-${createHash("sha256").update(randomUUID()).digest("hex").substring(0, 8)}`);
|
|
312
|
+
mkdirSync(runDir, { recursive: true });
|
|
313
|
+
writeFileSync(join(runDir, `index.${moduleType === "esm" ? "mjs" : "cjs"}`), executionCode, "utf8");
|
|
314
|
+
return await this.executeInSandbox(runDir, config.sandboxConfig?.timeout || FUNCTION_TOOL_EXECUTION_TIMEOUT_MS_DEFAULT, moduleType, config.sandboxConfig);
|
|
289
315
|
} catch (error) {
|
|
290
|
-
if (isNewSandbox) {
|
|
291
|
-
this.cleanupSandbox(sandboxDir);
|
|
292
|
-
const poolKey = dependencyHash;
|
|
293
|
-
delete this.sandboxPool[poolKey];
|
|
294
|
-
}
|
|
295
316
|
throw error;
|
|
317
|
+
} finally {
|
|
318
|
+
if (runDir) try {
|
|
319
|
+
rmSync(runDir, {
|
|
320
|
+
recursive: true,
|
|
321
|
+
force: true
|
|
322
|
+
});
|
|
323
|
+
} catch {}
|
|
324
|
+
const poolEntry = this.sandboxPool[dependencyHash];
|
|
325
|
+
if (poolEntry) poolEntry.activeCount = Math.max(0, poolEntry.activeCount - 1);
|
|
296
326
|
}
|
|
297
327
|
}
|
|
298
328
|
async installDependencies(sandboxDir) {
|
|
@@ -344,7 +374,7 @@ var NativeSandboxExecutor = class NativeSandboxExecutor {
|
|
|
344
374
|
}
|
|
345
375
|
async executeInSandbox(sandboxDir, timeout, moduleType, _sandboxConfig) {
|
|
346
376
|
return new Promise((resolve$1, reject) => {
|
|
347
|
-
const fileExtension = moduleType === "esm" ? "mjs" : "
|
|
377
|
+
const fileExtension = moduleType === "esm" ? "mjs" : "cjs";
|
|
348
378
|
const spawnOptions = {
|
|
349
379
|
cwd: sandboxDir,
|
|
350
380
|
stdio: "pipe",
|
|
@@ -8,13 +8,23 @@ import { FunctionToolConfig } from "./NativeSandboxExecutor.js";
|
|
|
8
8
|
*/
|
|
9
9
|
declare class SandboxExecutorFactory {
|
|
10
10
|
private static instance;
|
|
11
|
+
private static sessionFactories;
|
|
11
12
|
private nativeExecutor;
|
|
12
13
|
private vercelExecutors;
|
|
13
|
-
|
|
14
|
+
constructor();
|
|
14
15
|
/**
|
|
15
16
|
* Get singleton instance of SandboxExecutorFactory
|
|
16
17
|
*/
|
|
17
18
|
static getInstance(): SandboxExecutorFactory;
|
|
19
|
+
/**
|
|
20
|
+
* Get a session-scoped instance of SandboxExecutorFactory.
|
|
21
|
+
* Intended to scope Vercel sandbox pooling to a single message/session.
|
|
22
|
+
*/
|
|
23
|
+
static getForSession(sessionId: string): SandboxExecutorFactory;
|
|
24
|
+
/**
|
|
25
|
+
* Cleanup and remove a session-scoped SandboxExecutorFactory.
|
|
26
|
+
*/
|
|
27
|
+
static cleanupSession(sessionId: string): Promise<void>;
|
|
18
28
|
/**
|
|
19
29
|
* Execute a function tool using the appropriate sandbox provider
|
|
20
30
|
*/
|
|
@@ -10,6 +10,7 @@ const logger = getLogger("SandboxExecutorFactory");
|
|
|
10
10
|
*/
|
|
11
11
|
var SandboxExecutorFactory = class SandboxExecutorFactory {
|
|
12
12
|
static instance;
|
|
13
|
+
static sessionFactories = /* @__PURE__ */ new Map();
|
|
13
14
|
nativeExecutor = null;
|
|
14
15
|
vercelExecutors = /* @__PURE__ */ new Map();
|
|
15
16
|
constructor() {
|
|
@@ -23,6 +24,26 @@ var SandboxExecutorFactory = class SandboxExecutorFactory {
|
|
|
23
24
|
return SandboxExecutorFactory.instance;
|
|
24
25
|
}
|
|
25
26
|
/**
|
|
27
|
+
* Get a session-scoped instance of SandboxExecutorFactory.
|
|
28
|
+
* Intended to scope Vercel sandbox pooling to a single message/session.
|
|
29
|
+
*/
|
|
30
|
+
static getForSession(sessionId) {
|
|
31
|
+
const existing = SandboxExecutorFactory.sessionFactories.get(sessionId);
|
|
32
|
+
if (existing) return existing;
|
|
33
|
+
const created = new SandboxExecutorFactory();
|
|
34
|
+
SandboxExecutorFactory.sessionFactories.set(sessionId, created);
|
|
35
|
+
return created;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Cleanup and remove a session-scoped SandboxExecutorFactory.
|
|
39
|
+
*/
|
|
40
|
+
static async cleanupSession(sessionId) {
|
|
41
|
+
const factory = SandboxExecutorFactory.sessionFactories.get(sessionId);
|
|
42
|
+
if (!factory) return;
|
|
43
|
+
await factory.cleanup();
|
|
44
|
+
SandboxExecutorFactory.sessionFactories.delete(sessionId);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
26
47
|
* Execute a function tool using the appropriate sandbox provider
|
|
27
48
|
*/
|
|
28
49
|
async executeFunctionTool(functionId, args, config) {
|
|
@@ -37,7 +58,7 @@ var SandboxExecutorFactory = class SandboxExecutorFactory {
|
|
|
37
58
|
*/
|
|
38
59
|
async executeInNativeSandbox(functionId, args, config) {
|
|
39
60
|
if (!this.nativeExecutor) {
|
|
40
|
-
this.nativeExecutor = NativeSandboxExecutor
|
|
61
|
+
this.nativeExecutor = new NativeSandboxExecutor();
|
|
41
62
|
logger.info({}, "Native sandbox executor created");
|
|
42
63
|
}
|
|
43
64
|
return this.nativeExecutor.executeFunctionTool(functionId, args, config);
|
|
@@ -49,7 +70,7 @@ var SandboxExecutorFactory = class SandboxExecutorFactory {
|
|
|
49
70
|
const vercelConfig = config.sandboxConfig;
|
|
50
71
|
const configKey = `${vercelConfig.teamId}:${vercelConfig.projectId}`;
|
|
51
72
|
if (!this.vercelExecutors.has(configKey)) {
|
|
52
|
-
const executor$1 = VercelSandboxExecutor
|
|
73
|
+
const executor$1 = new VercelSandboxExecutor(vercelConfig);
|
|
53
74
|
this.vercelExecutors.set(configKey, executor$1);
|
|
54
75
|
logger.info({
|
|
55
76
|
teamId: vercelConfig.teamId,
|
|
@@ -67,7 +88,10 @@ var SandboxExecutorFactory = class SandboxExecutorFactory {
|
|
|
67
88
|
*/
|
|
68
89
|
async cleanup() {
|
|
69
90
|
logger.info({}, "Cleaning up sandbox executors");
|
|
70
|
-
this.nativeExecutor
|
|
91
|
+
if (this.nativeExecutor) {
|
|
92
|
+
await this.nativeExecutor.cleanup();
|
|
93
|
+
this.nativeExecutor = null;
|
|
94
|
+
}
|
|
71
95
|
for (const [key, executor] of this.vercelExecutors.entries()) {
|
|
72
96
|
await executor.cleanup();
|
|
73
97
|
this.vercelExecutors.delete(key);
|
|
@@ -15,15 +15,12 @@ interface ExecutionResult {
|
|
|
15
15
|
* Caches and reuses sandboxes based on dependencies to improve performance
|
|
16
16
|
*/
|
|
17
17
|
declare class VercelSandboxExecutor {
|
|
18
|
-
private static instance;
|
|
19
18
|
private config;
|
|
20
19
|
private sandboxPool;
|
|
21
20
|
private cleanupInterval;
|
|
22
|
-
private
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
*/
|
|
26
|
-
static getInstance(config: VercelSandboxConfig): VercelSandboxExecutor;
|
|
21
|
+
private sandboxInitPromises;
|
|
22
|
+
constructor(config: VercelSandboxConfig);
|
|
23
|
+
private getOrCreateSandbox;
|
|
27
24
|
/**
|
|
28
25
|
* Generate a hash for dependencies to use as cache key
|
|
29
26
|
*/
|
|
@@ -57,11 +54,6 @@ declare class VercelSandboxExecutor {
|
|
|
57
54
|
* Matches patterns like process.env.VAR_NAME or process.env['VAR_NAME']
|
|
58
55
|
*/
|
|
59
56
|
private extractEnvVars;
|
|
60
|
-
/**
|
|
61
|
-
* Create .env file content from environment variables
|
|
62
|
-
* Note: Currently creates empty placeholders. Values will be populated in the future.
|
|
63
|
-
*/
|
|
64
|
-
private createEnvFileContent;
|
|
65
57
|
/**
|
|
66
58
|
* Execute a function tool in Vercel Sandbox with pooling
|
|
67
59
|
*/
|
|
@@ -11,11 +11,11 @@ const logger = getLogger("VercelSandboxExecutor");
|
|
|
11
11
|
* Executes function tools in isolated Vercel Sandbox MicroVMs
|
|
12
12
|
* Caches and reuses sandboxes based on dependencies to improve performance
|
|
13
13
|
*/
|
|
14
|
-
var VercelSandboxExecutor = class
|
|
15
|
-
static instance;
|
|
14
|
+
var VercelSandboxExecutor = class {
|
|
16
15
|
config;
|
|
17
16
|
sandboxPool = /* @__PURE__ */ new Map();
|
|
18
17
|
cleanupInterval = null;
|
|
18
|
+
sandboxInitPromises = /* @__PURE__ */ new Map();
|
|
19
19
|
constructor(config) {
|
|
20
20
|
this.config = config;
|
|
21
21
|
logger.info({
|
|
@@ -27,12 +27,74 @@ var VercelSandboxExecutor = class VercelSandboxExecutor {
|
|
|
27
27
|
}, "VercelSandboxExecutor initialized with pooling");
|
|
28
28
|
this.startPoolCleanup();
|
|
29
29
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if (
|
|
35
|
-
|
|
30
|
+
async getOrCreateSandbox(params) {
|
|
31
|
+
const cached = this.getCachedSandbox(params.dependencyHash);
|
|
32
|
+
if (cached) return cached;
|
|
33
|
+
const existingInit = this.sandboxInitPromises.get(params.dependencyHash);
|
|
34
|
+
if (existingInit) {
|
|
35
|
+
await existingInit;
|
|
36
|
+
const afterInit = this.getCachedSandbox(params.dependencyHash);
|
|
37
|
+
if (!afterInit) throw new Error("Sandbox initialization finished but sandbox not found in pool");
|
|
38
|
+
return afterInit;
|
|
39
|
+
}
|
|
40
|
+
const initPromise = (async () => {
|
|
41
|
+
let sandbox = null;
|
|
42
|
+
try {
|
|
43
|
+
sandbox = await Sandbox.create({
|
|
44
|
+
token: this.config.token,
|
|
45
|
+
teamId: this.config.teamId,
|
|
46
|
+
projectId: this.config.projectId,
|
|
47
|
+
timeout: this.config.timeout,
|
|
48
|
+
resources: { vcpus: this.config.vcpus || 1 },
|
|
49
|
+
runtime: this.config.runtime
|
|
50
|
+
});
|
|
51
|
+
logger.info({
|
|
52
|
+
functionId: params.functionId,
|
|
53
|
+
functionName: params.toolName,
|
|
54
|
+
sandboxId: sandbox.sandboxId,
|
|
55
|
+
dependencyHash: params.dependencyHash
|
|
56
|
+
}, "New sandbox created");
|
|
57
|
+
this.addToPool(params.dependencyHash, sandbox, params.dependencies);
|
|
58
|
+
if (Object.keys(params.dependencies).length > 0) {
|
|
59
|
+
logger.debug({
|
|
60
|
+
functionId: params.functionId,
|
|
61
|
+
functionName: params.toolName,
|
|
62
|
+
dependencyHash: params.dependencyHash,
|
|
63
|
+
dependencies: params.dependencies
|
|
64
|
+
}, "Installing dependencies in new sandbox");
|
|
65
|
+
const packageJsonContent = JSON.stringify({ dependencies: params.dependencies }, null, 2);
|
|
66
|
+
await sandbox.writeFiles([{
|
|
67
|
+
path: "package.json",
|
|
68
|
+
content: Buffer.from(packageJsonContent, "utf-8")
|
|
69
|
+
}]);
|
|
70
|
+
const installCmd = await sandbox.runCommand({
|
|
71
|
+
cmd: "npm",
|
|
72
|
+
args: ["install", "--omit=dev"],
|
|
73
|
+
cwd: "/vercel/sandbox"
|
|
74
|
+
});
|
|
75
|
+
const installStdout = await installCmd.stdout();
|
|
76
|
+
const installStderr = await installCmd.stderr();
|
|
77
|
+
if (installStdout) logger.debug({ functionId: params.functionId }, installStdout);
|
|
78
|
+
if (installStderr) logger.debug({ functionId: params.functionId }, installStderr);
|
|
79
|
+
if (installCmd.exitCode !== 0) throw new Error(`Failed to install dependencies: ${installStderr}`);
|
|
80
|
+
logger.info({
|
|
81
|
+
functionId: params.functionId,
|
|
82
|
+
dependencyHash: params.dependencyHash
|
|
83
|
+
}, "Dependencies installed successfully");
|
|
84
|
+
}
|
|
85
|
+
return sandbox;
|
|
86
|
+
} catch (error) {
|
|
87
|
+
await this.removeSandbox(params.dependencyHash);
|
|
88
|
+
if (sandbox) try {
|
|
89
|
+
await sandbox.stop();
|
|
90
|
+
} catch {}
|
|
91
|
+
throw error;
|
|
92
|
+
} finally {
|
|
93
|
+
this.sandboxInitPromises.delete(params.dependencyHash);
|
|
94
|
+
}
|
|
95
|
+
})();
|
|
96
|
+
this.sandboxInitPromises.set(params.dependencyHash, initPromise);
|
|
97
|
+
return initPromise;
|
|
36
98
|
}
|
|
37
99
|
/**
|
|
38
100
|
* Generate a hash for dependencies to use as cache key
|
|
@@ -48,13 +110,17 @@ var VercelSandboxExecutor = class VercelSandboxExecutor {
|
|
|
48
110
|
const cached = this.sandboxPool.get(dependencyHash);
|
|
49
111
|
if (!cached) return null;
|
|
50
112
|
const age = Date.now() - cached.createdAt;
|
|
51
|
-
|
|
113
|
+
const timeoutSafetyMs = 2e3;
|
|
114
|
+
const timeRemaining = cached.timeoutMs - age;
|
|
115
|
+
if (age > FUNCTION_TOOL_SANDBOX_POOL_TTL_MS || cached.useCount >= FUNCTION_TOOL_SANDBOX_MAX_USE_COUNT || timeRemaining <= timeoutSafetyMs) {
|
|
52
116
|
logger.debug({
|
|
53
117
|
dependencyHash,
|
|
54
118
|
age,
|
|
55
119
|
useCount: cached.useCount,
|
|
56
120
|
ttl: FUNCTION_TOOL_SANDBOX_POOL_TTL_MS,
|
|
57
|
-
maxUseCount: FUNCTION_TOOL_SANDBOX_MAX_USE_COUNT
|
|
121
|
+
maxUseCount: FUNCTION_TOOL_SANDBOX_MAX_USE_COUNT,
|
|
122
|
+
timeoutMs: cached.timeoutMs,
|
|
123
|
+
timeRemaining
|
|
58
124
|
}, "Sandbox expired, will create new one");
|
|
59
125
|
this.removeSandbox(dependencyHash);
|
|
60
126
|
return null;
|
|
@@ -62,7 +128,9 @@ var VercelSandboxExecutor = class VercelSandboxExecutor {
|
|
|
62
128
|
logger.debug({
|
|
63
129
|
dependencyHash,
|
|
64
130
|
useCount: cached.useCount,
|
|
65
|
-
age
|
|
131
|
+
age,
|
|
132
|
+
timeoutMs: cached.timeoutMs,
|
|
133
|
+
timeRemaining
|
|
66
134
|
}, "Reusing cached sandbox");
|
|
67
135
|
return cached.sandbox;
|
|
68
136
|
}
|
|
@@ -73,6 +141,7 @@ var VercelSandboxExecutor = class VercelSandboxExecutor {
|
|
|
73
141
|
this.sandboxPool.set(dependencyHash, {
|
|
74
142
|
sandbox,
|
|
75
143
|
createdAt: Date.now(),
|
|
144
|
+
timeoutMs: sandbox.timeout,
|
|
76
145
|
useCount: 0,
|
|
77
146
|
dependencies
|
|
78
147
|
});
|
|
@@ -94,6 +163,7 @@ var VercelSandboxExecutor = class VercelSandboxExecutor {
|
|
|
94
163
|
async removeSandbox(dependencyHash) {
|
|
95
164
|
const cached = this.sandboxPool.get(dependencyHash);
|
|
96
165
|
if (cached) {
|
|
166
|
+
this.sandboxPool.delete(dependencyHash);
|
|
97
167
|
try {
|
|
98
168
|
await cached.sandbox.stop();
|
|
99
169
|
logger.debug({ dependencyHash }, "Sandbox stopped");
|
|
@@ -103,7 +173,6 @@ var VercelSandboxExecutor = class VercelSandboxExecutor {
|
|
|
103
173
|
dependencyHash
|
|
104
174
|
}, "Error stopping sandbox");
|
|
105
175
|
}
|
|
106
|
-
this.sandboxPool.delete(dependencyHash);
|
|
107
176
|
}
|
|
108
177
|
}
|
|
109
178
|
/**
|
|
@@ -113,7 +182,12 @@ var VercelSandboxExecutor = class VercelSandboxExecutor {
|
|
|
113
182
|
this.cleanupInterval = setInterval(() => {
|
|
114
183
|
const now = Date.now();
|
|
115
184
|
const toRemove = [];
|
|
116
|
-
for (const [hash, cached] of this.sandboxPool.entries())
|
|
185
|
+
for (const [hash, cached] of this.sandboxPool.entries()) {
|
|
186
|
+
const age = now - cached.createdAt;
|
|
187
|
+
const timeoutSafetyMs = 2e3;
|
|
188
|
+
const timeRemaining = cached.timeoutMs - age;
|
|
189
|
+
if (age > FUNCTION_TOOL_SANDBOX_POOL_TTL_MS || cached.useCount >= FUNCTION_TOOL_SANDBOX_MAX_USE_COUNT || timeRemaining <= timeoutSafetyMs) toRemove.push(hash);
|
|
190
|
+
}
|
|
117
191
|
if (toRemove.length > 0) {
|
|
118
192
|
logger.info({
|
|
119
193
|
count: toRemove.length,
|
|
@@ -132,6 +206,7 @@ var VercelSandboxExecutor = class VercelSandboxExecutor {
|
|
|
132
206
|
this.cleanupInterval = null;
|
|
133
207
|
}
|
|
134
208
|
logger.info({ poolSize: this.sandboxPool.size }, "Cleaning up all sandboxes");
|
|
209
|
+
this.sandboxInitPromises.clear();
|
|
135
210
|
const promises = Array.from(this.sandboxPool.keys()).map((hash) => this.removeSandbox(hash));
|
|
136
211
|
await Promise.all(promises);
|
|
137
212
|
}
|
|
@@ -156,18 +231,6 @@ var VercelSandboxExecutor = class VercelSandboxExecutor {
|
|
|
156
231
|
return envVars;
|
|
157
232
|
}
|
|
158
233
|
/**
|
|
159
|
-
* Create .env file content from environment variables
|
|
160
|
-
* Note: Currently creates empty placeholders. Values will be populated in the future.
|
|
161
|
-
*/
|
|
162
|
-
createEnvFileContent(envVarNames) {
|
|
163
|
-
const envLines = [];
|
|
164
|
-
for (const varName of envVarNames) {
|
|
165
|
-
envLines.push(`${varName}=""`);
|
|
166
|
-
logger.debug({ varName }, "Adding environment variable placeholder to sandbox");
|
|
167
|
-
}
|
|
168
|
-
return envLines.join("\n");
|
|
169
|
-
}
|
|
170
|
-
/**
|
|
171
234
|
* Execute a function tool in Vercel Sandbox with pooling
|
|
172
235
|
*/
|
|
173
236
|
async executeFunctionTool(functionId, args, toolConfig) {
|
|
@@ -175,6 +238,9 @@ var VercelSandboxExecutor = class VercelSandboxExecutor {
|
|
|
175
238
|
const logs = [];
|
|
176
239
|
const dependencies = toolConfig.dependencies || {};
|
|
177
240
|
const dependencyHash = this.generateDependencyHash(dependencies);
|
|
241
|
+
const runRelDir = `runs/${`${Date.now()}-${crypto.randomBytes(6).toString("hex")}`}`;
|
|
242
|
+
const filename = this.config.runtime === "typescript" ? "execute.ts" : "execute.js";
|
|
243
|
+
const runFilePath = `${runRelDir}/${filename}`;
|
|
178
244
|
try {
|
|
179
245
|
logger.info({
|
|
180
246
|
functionId,
|
|
@@ -182,109 +248,44 @@ var VercelSandboxExecutor = class VercelSandboxExecutor {
|
|
|
182
248
|
dependencyHash,
|
|
183
249
|
poolSize: this.sandboxPool.size
|
|
184
250
|
}, "Executing function in Vercel Sandbox");
|
|
185
|
-
|
|
186
|
-
let isNewSandbox = false;
|
|
187
|
-
if (!sandbox) {
|
|
188
|
-
isNewSandbox = true;
|
|
189
|
-
sandbox = await Sandbox.create({
|
|
190
|
-
token: this.config.token,
|
|
191
|
-
teamId: this.config.teamId,
|
|
192
|
-
projectId: this.config.projectId,
|
|
193
|
-
timeout: this.config.timeout,
|
|
194
|
-
resources: { vcpus: this.config.vcpus || 1 },
|
|
195
|
-
runtime: this.config.runtime
|
|
196
|
-
});
|
|
197
|
-
logger.info({
|
|
198
|
-
functionId,
|
|
199
|
-
sandboxId: sandbox.sandboxId,
|
|
200
|
-
dependencyHash
|
|
201
|
-
}, `New sandbox created for function ${functionId}`);
|
|
202
|
-
this.addToPool(dependencyHash, sandbox, dependencies);
|
|
203
|
-
} else logger.info({
|
|
251
|
+
const sandbox = await this.getOrCreateSandbox({
|
|
204
252
|
functionId,
|
|
205
|
-
|
|
206
|
-
dependencyHash
|
|
207
|
-
|
|
253
|
+
toolName: toolConfig.name,
|
|
254
|
+
dependencyHash,
|
|
255
|
+
dependencies
|
|
256
|
+
});
|
|
208
257
|
this.incrementUseCount(dependencyHash);
|
|
209
258
|
try {
|
|
210
|
-
if (isNewSandbox && toolConfig.dependencies && Object.keys(toolConfig.dependencies).length > 0) {
|
|
211
|
-
logger.debug({
|
|
212
|
-
functionId,
|
|
213
|
-
functionName: toolConfig.name,
|
|
214
|
-
dependencies: toolConfig.dependencies
|
|
215
|
-
}, "Installing dependencies in new sandbox");
|
|
216
|
-
const packageJson = { dependencies: toolConfig.dependencies };
|
|
217
|
-
const packageJsonContent = JSON.stringify(packageJson, null, 2);
|
|
218
|
-
await sandbox.writeFiles([{
|
|
219
|
-
path: "package.json",
|
|
220
|
-
content: Buffer.from(packageJsonContent, "utf-8")
|
|
221
|
-
}]);
|
|
222
|
-
const installCmd = await sandbox.runCommand({
|
|
223
|
-
cmd: "npm",
|
|
224
|
-
args: ["install", "--omit=dev"]
|
|
225
|
-
});
|
|
226
|
-
const installStdout = await installCmd.stdout();
|
|
227
|
-
const installStderr = await installCmd.stderr();
|
|
228
|
-
if (installStdout) logs.push(installStdout);
|
|
229
|
-
if (installStderr) logs.push(installStderr);
|
|
230
|
-
if (installCmd.exitCode !== 0) throw new Error(`Failed to install dependencies: ${installStderr}`);
|
|
231
|
-
logger.info({
|
|
232
|
-
functionId,
|
|
233
|
-
dependencyHash
|
|
234
|
-
}, "Dependencies installed successfully");
|
|
235
|
-
}
|
|
236
259
|
const executionCode = createExecutionWrapper(toolConfig.executeCode, args);
|
|
237
260
|
const envVars = this.extractEnvVars(toolConfig.executeCode);
|
|
238
|
-
const
|
|
239
|
-
const
|
|
240
|
-
|
|
241
|
-
|
|
261
|
+
const env = envVars.size > 0 ? Object.fromEntries(Array.from(envVars).map((k) => [k, ""])) : {};
|
|
262
|
+
const mkdirCmd = await sandbox.runCommand({
|
|
263
|
+
cmd: "mkdir",
|
|
264
|
+
args: ["-p", runRelDir],
|
|
265
|
+
cwd: "/vercel/sandbox"
|
|
266
|
+
});
|
|
267
|
+
const mkdirStderr = await mkdirCmd.stderr();
|
|
268
|
+
if (mkdirCmd.exitCode !== 0) throw new Error(mkdirStderr || "Failed to create run directory");
|
|
269
|
+
await sandbox.writeFiles([{
|
|
270
|
+
path: runFilePath,
|
|
242
271
|
content: Buffer.from(executionCode, "utf-8")
|
|
272
|
+
}]);
|
|
273
|
+
const runtime = this.config.runtime === "typescript" ? "tsx" : "node";
|
|
274
|
+
const executeCmd = this.config.runtime === "typescript" ? await sandbox.runCommand({
|
|
275
|
+
cmd: "npx",
|
|
276
|
+
args: [
|
|
277
|
+
"--yes",
|
|
278
|
+
"tsx",
|
|
279
|
+
filename
|
|
280
|
+
],
|
|
281
|
+
cwd: `/vercel/sandbox/${runRelDir}`,
|
|
282
|
+
env
|
|
283
|
+
}) : await sandbox.runCommand({
|
|
284
|
+
cmd: runtime,
|
|
285
|
+
args: [filename],
|
|
286
|
+
cwd: `/vercel/sandbox/${runRelDir}`,
|
|
287
|
+
env
|
|
243
288
|
});
|
|
244
|
-
if (envVars.size > 0) {
|
|
245
|
-
const envFileContent = this.createEnvFileContent(envVars);
|
|
246
|
-
if (envFileContent) {
|
|
247
|
-
filesToWrite.push({
|
|
248
|
-
path: ".env",
|
|
249
|
-
content: Buffer.from(envFileContent, "utf-8")
|
|
250
|
-
});
|
|
251
|
-
logger.info({
|
|
252
|
-
functionId,
|
|
253
|
-
envVarCount: envVars.size,
|
|
254
|
-
envVars: Array.from(envVars)
|
|
255
|
-
}, "Creating environment variable placeholders in sandbox");
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
await sandbox.writeFiles(filesToWrite);
|
|
259
|
-
logger.info({
|
|
260
|
-
functionId,
|
|
261
|
-
runtime: this.config.runtime === "typescript" ? "tsx" : "node",
|
|
262
|
-
hasEnvVars: envVars.size > 0
|
|
263
|
-
}, `Execution code written to file for runtime ${this.config.runtime}`);
|
|
264
|
-
const executeCmd = await (async () => {
|
|
265
|
-
if (envVars.size > 0) return sandbox.runCommand({
|
|
266
|
-
cmd: "npx",
|
|
267
|
-
args: this.config.runtime === "typescript" ? [
|
|
268
|
-
"--yes",
|
|
269
|
-
"dotenv-cli",
|
|
270
|
-
"--",
|
|
271
|
-
"npx",
|
|
272
|
-
"tsx",
|
|
273
|
-
filename
|
|
274
|
-
] : [
|
|
275
|
-
"--yes",
|
|
276
|
-
"dotenv-cli",
|
|
277
|
-
"--",
|
|
278
|
-
"node",
|
|
279
|
-
filename
|
|
280
|
-
]
|
|
281
|
-
});
|
|
282
|
-
const runtime = this.config.runtime === "typescript" ? "tsx" : "node";
|
|
283
|
-
return sandbox.runCommand({
|
|
284
|
-
cmd: runtime,
|
|
285
|
-
args: [filename]
|
|
286
|
-
});
|
|
287
|
-
})();
|
|
288
289
|
const executeStdout = await executeCmd.stdout();
|
|
289
290
|
const executeStderr = await executeCmd.stderr();
|
|
290
291
|
if (executeStdout) logs.push(executeStdout);
|
|
@@ -294,7 +295,8 @@ var VercelSandboxExecutor = class VercelSandboxExecutor {
|
|
|
294
295
|
logger.error({
|
|
295
296
|
functionId,
|
|
296
297
|
exitCode: executeCmd.exitCode,
|
|
297
|
-
stderr: executeStderr
|
|
298
|
+
stderr: executeStderr,
|
|
299
|
+
logs
|
|
298
300
|
}, "Function execution failed");
|
|
299
301
|
return {
|
|
300
302
|
success: false,
|
|
@@ -306,7 +308,8 @@ var VercelSandboxExecutor = class VercelSandboxExecutor {
|
|
|
306
308
|
const result = parseExecutionResult(executeStdout, functionId, logger);
|
|
307
309
|
logger.info({
|
|
308
310
|
functionId,
|
|
309
|
-
executionTime
|
|
311
|
+
executionTime,
|
|
312
|
+
logs
|
|
310
313
|
}, "Function executed successfully in Vercel Sandbox");
|
|
311
314
|
return {
|
|
312
315
|
success: true,
|
|
@@ -314,9 +317,14 @@ var VercelSandboxExecutor = class VercelSandboxExecutor {
|
|
|
314
317
|
logs,
|
|
315
318
|
executionTime
|
|
316
319
|
};
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
|
|
320
|
+
} finally {
|
|
321
|
+
try {
|
|
322
|
+
await sandbox.runCommand({
|
|
323
|
+
cmd: "rm",
|
|
324
|
+
args: ["-rf", runRelDir],
|
|
325
|
+
cwd: "/vercel/sandbox"
|
|
326
|
+
});
|
|
327
|
+
} catch {}
|
|
320
328
|
}
|
|
321
329
|
} catch (error) {
|
|
322
330
|
const executionTime = Date.now() - startTime;
|
|
@@ -324,7 +332,9 @@ var VercelSandboxExecutor = class VercelSandboxExecutor {
|
|
|
324
332
|
logger.error({
|
|
325
333
|
functionId,
|
|
326
334
|
error: errorMessage,
|
|
327
|
-
|
|
335
|
+
stack: error,
|
|
336
|
+
executionTime,
|
|
337
|
+
logs
|
|
328
338
|
}, "Vercel Sandbox execution error");
|
|
329
339
|
return {
|
|
330
340
|
success: false,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as _inkeep_agents_core3 from "@inkeep/agents-core";
|
|
2
2
|
import { BreakdownComponentDef, ContextBreakdown, calculateBreakdownTotal, createEmptyBreakdown } from "@inkeep/agents-core";
|
|
3
3
|
|
|
4
4
|
//#region src/domains/run/utils/token-estimator.d.ts
|
|
@@ -17,7 +17,7 @@ interface AssembleResult {
|
|
|
17
17
|
/** The assembled prompt string */
|
|
18
18
|
prompt: string;
|
|
19
19
|
/** Token breakdown for each component */
|
|
20
|
-
breakdown:
|
|
20
|
+
breakdown: _inkeep_agents_core3.ContextBreakdown;
|
|
21
21
|
}
|
|
22
22
|
//#endregion
|
|
23
23
|
export { AssembleResult, type BreakdownComponentDef, type ContextBreakdown, calculateBreakdownTotal, createEmptyBreakdown, estimateTokens };
|
package/dist/factory.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ import * as hono0 from "hono";
|
|
|
7
7
|
import { CredentialStore, ServerConfig } from "@inkeep/agents-core";
|
|
8
8
|
import * as zod0 from "zod";
|
|
9
9
|
import { SSOProviderConfig, UserAuthConfig } from "@inkeep/agents-core/auth";
|
|
10
|
-
import * as
|
|
10
|
+
import * as hono_types0 from "hono/types";
|
|
11
11
|
import * as better_auth0 from "better-auth";
|
|
12
12
|
import * as better_auth_plugins0 from "better-auth/plugins";
|
|
13
13
|
import * as _better_auth_sso0 from "@better-auth/sso";
|
|
@@ -1536,6 +1536,6 @@ declare function createAgentsApp(config?: {
|
|
|
1536
1536
|
auth?: UserAuthConfig;
|
|
1537
1537
|
sandboxConfig?: SandboxConfig;
|
|
1538
1538
|
skipInitialization?: boolean;
|
|
1539
|
-
}): hono0.Hono<
|
|
1539
|
+
}): hono0.Hono<hono_types0.BlankEnv, hono_types0.BlankSchema, "/">;
|
|
1540
1540
|
//#endregion
|
|
1541
1541
|
export { type SSOProviderConfig, type UserAuthConfig, createAgentsApp, createAgentsAuth, createAgentsHono, createAuth0Provider, createOIDCProvider, initializeDefaultUser };
|
package/dist/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ import { createAuth0Provider, createOIDCProvider } from "./ssoHelpers.js";
|
|
|
8
8
|
import { SSOProviderConfig, UserAuthConfig, createAgentsApp } from "./factory.js";
|
|
9
9
|
import { Hono } from "hono";
|
|
10
10
|
import * as zod205 from "zod";
|
|
11
|
-
import * as
|
|
11
|
+
import * as hono_types5 from "hono/types";
|
|
12
12
|
import * as better_auth78 from "better-auth";
|
|
13
13
|
import * as better_auth_plugins69 from "better-auth/plugins";
|
|
14
14
|
import * as _better_auth_sso10 from "@better-auth/sso";
|
|
@@ -1531,6 +1531,6 @@ declare const auth: better_auth78.Auth<{
|
|
|
1531
1531
|
}>;
|
|
1532
1532
|
}];
|
|
1533
1533
|
}> | null;
|
|
1534
|
-
declare const app: Hono<
|
|
1534
|
+
declare const app: Hono<hono_types5.BlankEnv, hono_types5.BlankSchema, "/">;
|
|
1535
1535
|
//#endregion
|
|
1536
1536
|
export { type AppConfig, type AppVariables, Hono, type NativeSandboxConfig, type SSOProviderConfig, type SandboxConfig, type UserAuthConfig, type VercelSandboxConfig, auth, createAgentsApp, createAgentsHono, createAuth0Provider, createOIDCProvider, app as default, initializeDefaultUser };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as hono12 from "hono";
|
|
2
2
|
import { BaseExecutionContext } from "@inkeep/agents-core";
|
|
3
3
|
import { createAuth } from "@inkeep/agents-core/auth";
|
|
4
4
|
|
|
@@ -12,7 +12,7 @@ import { createAuth } from "@inkeep/agents-core/auth";
|
|
|
12
12
|
* 3. Database API key
|
|
13
13
|
* 4. Internal service token
|
|
14
14
|
*/
|
|
15
|
-
declare const manageApiKeyAuth: () =>
|
|
15
|
+
declare const manageApiKeyAuth: () => hono12.MiddlewareHandler<{
|
|
16
16
|
Variables: {
|
|
17
17
|
executionContext: BaseExecutionContext;
|
|
18
18
|
userId?: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ManageAppVariables } from "../types/app.js";
|
|
2
|
-
import * as
|
|
2
|
+
import * as hono13 from "hono";
|
|
3
3
|
|
|
4
4
|
//#region src/middleware/projectAccess.d.ts
|
|
5
5
|
|
|
@@ -26,6 +26,6 @@ declare const requireProjectPermission: <Env$1 extends {
|
|
|
26
26
|
Variables: ManageAppVariables;
|
|
27
27
|
} = {
|
|
28
28
|
Variables: ManageAppVariables;
|
|
29
|
-
}>(permission?: ProjectPermission) =>
|
|
29
|
+
}>(permission?: ProjectPermission) => hono13.MiddlewareHandler<Env$1, string, {}, Response>;
|
|
30
30
|
//#endregion
|
|
31
31
|
export { ProjectPermission, requireProjectPermission };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ManageAppVariables } from "../types/app.js";
|
|
2
|
-
import * as
|
|
2
|
+
import * as hono3 from "hono";
|
|
3
3
|
|
|
4
4
|
//#region src/middleware/requirePermission.d.ts
|
|
5
5
|
type Permission = {
|
|
@@ -9,6 +9,6 @@ declare const requirePermission: <Env$1 extends {
|
|
|
9
9
|
Variables: ManageAppVariables;
|
|
10
10
|
} = {
|
|
11
11
|
Variables: ManageAppVariables;
|
|
12
|
-
}>(permissions: Permission) =>
|
|
12
|
+
}>(permissions: Permission) => hono3.MiddlewareHandler<Env$1, string, {}, Response>;
|
|
13
13
|
//#endregion
|
|
14
14
|
export { requirePermission };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as hono4 from "hono";
|
|
2
2
|
import { BaseExecutionContext } from "@inkeep/agents-core";
|
|
3
3
|
|
|
4
4
|
//#region src/middleware/runAuth.d.ts
|
|
5
|
-
declare const runApiKeyAuth: () =>
|
|
5
|
+
declare const runApiKeyAuth: () => hono4.MiddlewareHandler<{
|
|
6
6
|
Variables: {
|
|
7
7
|
executionContext: BaseExecutionContext;
|
|
8
8
|
};
|
|
@@ -11,7 +11,7 @@ declare const runApiKeyAuth: () => hono11.MiddlewareHandler<{
|
|
|
11
11
|
* Creates a middleware that applies API key authentication except for specified route patterns
|
|
12
12
|
* @param skipRouteCheck - Function that returns true if the route should skip authentication
|
|
13
13
|
*/
|
|
14
|
-
declare const runApiKeyAuthExcept: (skipRouteCheck: (path: string) => boolean) =>
|
|
14
|
+
declare const runApiKeyAuthExcept: (skipRouteCheck: (path: string) => boolean) => hono4.MiddlewareHandler<{
|
|
15
15
|
Variables: {
|
|
16
16
|
executionContext: BaseExecutionContext;
|
|
17
17
|
};
|
|
@@ -20,7 +20,7 @@ declare const runApiKeyAuthExcept: (skipRouteCheck: (path: string) => boolean) =
|
|
|
20
20
|
* Helper middleware for endpoints that optionally support API key authentication
|
|
21
21
|
* If no auth header is present, it continues without setting the executionContext
|
|
22
22
|
*/
|
|
23
|
-
declare const runOptionalAuth: () =>
|
|
23
|
+
declare const runOptionalAuth: () => hono4.MiddlewareHandler<{
|
|
24
24
|
Variables: {
|
|
25
25
|
executionContext?: BaseExecutionContext;
|
|
26
26
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as hono9 from "hono";
|
|
2
2
|
|
|
3
3
|
//#region src/middleware/tenantAccess.d.ts
|
|
4
4
|
|
|
@@ -11,7 +11,7 @@ import * as hono6 from "hono";
|
|
|
11
11
|
* - API key user: Access only to the tenant associated with the API key
|
|
12
12
|
* - Session user: Access based on organization membership
|
|
13
13
|
*/
|
|
14
|
-
declare const requireTenantAccess: () =>
|
|
14
|
+
declare const requireTenantAccess: () => hono9.MiddlewareHandler<{
|
|
15
15
|
Variables: {
|
|
16
16
|
userId: string;
|
|
17
17
|
tenantId: string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as hono10 from "hono";
|
|
2
2
|
|
|
3
3
|
//#region src/middleware/tracing.d.ts
|
|
4
|
-
declare const otelBaggageMiddleware: () =>
|
|
5
|
-
declare const executionBaggageMiddleware: () =>
|
|
4
|
+
declare const otelBaggageMiddleware: () => hono10.MiddlewareHandler<any, string, {}, Response>;
|
|
5
|
+
declare const executionBaggageMiddleware: () => hono10.MiddlewareHandler<any, string, {}, Response>;
|
|
6
6
|
//#endregion
|
|
7
7
|
export { executionBaggageMiddleware, otelBaggageMiddleware };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inkeep/agents-api",
|
|
3
|
-
"version": "0.0.0-dev-
|
|
3
|
+
"version": "0.0.0-dev-20260122001454",
|
|
4
4
|
"description": "Unified Inkeep Agents API - combines management, runtime, and evaluation capabilities",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"exports": {
|
|
@@ -70,8 +70,8 @@
|
|
|
70
70
|
"openid-client": "^6.8.1",
|
|
71
71
|
"pg": "^8.16.3",
|
|
72
72
|
"workflow": "4.0.1-beta.33",
|
|
73
|
-
"@inkeep/agents-core": "^0.0.0-dev-
|
|
74
|
-
"@inkeep/agents-manage-mcp": "^0.0.0-dev-
|
|
73
|
+
"@inkeep/agents-core": "^0.0.0-dev-20260122001454",
|
|
74
|
+
"@inkeep/agents-manage-mcp": "^0.0.0-dev-20260122001454"
|
|
75
75
|
},
|
|
76
76
|
"peerDependencies": {
|
|
77
77
|
"@hono/zod-openapi": "^1.1.5",
|