@inkeep/agents-api 0.0.0-dev-20260121225854 → 0.0.0-dev-20260122001146

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/.well-known/workflow/v1/flow.cjs +44 -44
  2. package/dist/.well-known/workflow/v1/flow.cjs.debug.json +2 -2
  3. package/dist/.well-known/workflow/v1/manifest.debug.json +14 -14
  4. package/dist/.well-known/workflow/v1/step.cjs +130 -130
  5. package/dist/.well-known/workflow/v1/step.cjs.debug.json +2 -2
  6. package/dist/data/db/manageDbClient.d.ts +2 -2
  7. package/dist/data/db/runDbClient.d.ts +2 -2
  8. package/dist/domains/evals/routes/datasetTriggers.d.ts +2 -2
  9. package/dist/domains/evals/routes/index.d.ts +2 -2
  10. package/dist/domains/evals/workflow/routes.d.ts +2 -2
  11. package/dist/domains/manage/routes/conversations.d.ts +2 -2
  12. package/dist/domains/manage/routes/evals/evaluationResults.d.ts +2 -2
  13. package/dist/domains/manage/routes/index.d.ts +2 -2
  14. package/dist/domains/manage/routes/mcp.d.ts +2 -2
  15. package/dist/domains/manage/routes/signoz.d.ts +2 -2
  16. package/dist/domains/run/agents/Agent.js +1 -1
  17. package/dist/domains/run/agents/relationTools.d.ts +2 -2
  18. package/dist/domains/run/services/AgentSession.js +9 -0
  19. package/dist/domains/run/tools/NativeSandboxExecutor.d.ts +3 -2
  20. package/dist/domains/run/tools/NativeSandboxExecutor.js +76 -46
  21. package/dist/domains/run/tools/SandboxExecutorFactory.d.ts +11 -1
  22. package/dist/domains/run/tools/SandboxExecutorFactory.js +27 -3
  23. package/dist/domains/run/tools/VercelSandboxExecutor.d.ts +3 -11
  24. package/dist/domains/run/tools/VercelSandboxExecutor.js +137 -127
  25. package/dist/domains/run/utils/token-estimator.d.ts +2 -2
  26. package/dist/middleware/evalsAuth.d.ts +2 -2
  27. package/dist/middleware/manageAuth.d.ts +2 -2
  28. package/dist/middleware/projectAccess.d.ts +2 -2
  29. package/dist/middleware/projectConfig.d.ts +3 -3
  30. package/dist/middleware/requirePermission.d.ts +2 -2
  31. package/dist/middleware/runAuth.d.ts +4 -4
  32. package/dist/middleware/sessionAuth.d.ts +3 -3
  33. package/dist/middleware/tenantAccess.d.ts +2 -2
  34. package/dist/middleware/tracing.d.ts +3 -3
  35. package/package.json +3 -3
@@ -1,7 +1,7 @@
1
1
  import { Hono } from "hono";
2
- import * as hono_types8 from "hono/types";
2
+ import * as hono_types5 from "hono/types";
3
3
 
4
4
  //#region src/domains/manage/routes/mcp.d.ts
5
- declare const app: Hono<hono_types8.BlankEnv, hono_types8.BlankSchema, "/">;
5
+ declare const app: Hono<hono_types5.BlankEnv, hono_types5.BlankSchema, "/">;
6
6
  //#endregion
7
7
  export { app as default };
@@ -1,10 +1,10 @@
1
1
  import { ManageAppVariables } from "../../../types/app.js";
2
2
  import { Hono } from "hono";
3
- import * as hono_types5 from "hono/types";
3
+ import * as hono_types7 from "hono/types";
4
4
 
5
5
  //#region src/domains/manage/routes/signoz.d.ts
6
6
  declare const app: Hono<{
7
7
  Variables: ManageAppVariables;
8
- }, hono_types5.BlankSchema, "/">;
8
+ }, hono_types7.BlankSchema, "/">;
9
9
  //#endregion
10
10
  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.getInstance();
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 _inkeep_agents_core0 from "@inkeep/agents-core";
3
+ import * as _inkeep_agents_core2 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: _inkeep_agents_core0.Message | _inkeep_agents_core0.Task;
47
+ result: _inkeep_agents_core2.Message | _inkeep_agents_core2.Task;
48
48
  }>;
49
49
  /**
50
50
  * Parameters for building a transfer relation config
@@ -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
- static getInstance(): NativeSandboxExecutor;
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
- * The singleton pattern here is important - we need one shared pool
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 NativeSandboxExecutor {
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
- static getInstance() {
119
- if (!NativeSandboxExecutor.instance) NativeSandboxExecutor.instance = new NativeSandboxExecutor();
120
- return NativeSandboxExecutor.instance;
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
- this.cleanupSandbox(sandbox.sandboxDir);
166
- delete this.sandboxPool[poolKey];
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
- let sandboxDir = this.getCachedSandbox(dependencyHash);
261
- let isNewSandbox = false;
262
- if (!sandboxDir) {
263
- sandboxDir = join(this.tempDir, `sandbox-${dependencyHash}-${Date.now()}`);
264
- mkdirSync(sandboxDir, { recursive: true });
265
- isNewSandbox = true;
266
- logger.debug({
267
- toolId,
268
- dependencyHash,
269
- sandboxDir,
270
- dependencies
271
- }, "Creating new sandbox");
272
- const moduleType = this.detectModuleType(config.executeCode, config.sandboxConfig?.runtime);
273
- const packageJson = {
274
- name: `function-tool-${toolId}`,
275
- version: "1.0.0",
276
- ...moduleType === "esm" && { type: "module" },
277
- dependencies,
278
- scripts: { start: moduleType === "esm" ? "node index.mjs" : "node index.js" }
279
- };
280
- writeFileSync(join(sandboxDir, "package.json"), JSON.stringify(packageJson, null, 2), "utf8");
281
- if (Object.keys(dependencies).length > 0) await this.installDependencies(sandboxDir);
282
- this.addToPool(dependencyHash, sandboxDir, dependencies);
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
- writeFileSync(join(sandboxDir, `index.${moduleType === "esm" ? "mjs" : "js"}`), executionCode, "utf8");
288
- return await this.executeInSandbox(sandboxDir, config.sandboxConfig?.timeout || FUNCTION_TOOL_EXECUTION_TIMEOUT_MS_DEFAULT, moduleType, config.sandboxConfig);
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" : "js";
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
- private constructor();
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.getInstance();
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.getInstance(vercelConfig);
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 = null;
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 constructor();
23
- /**
24
- * Get singleton instance of VercelSandboxExecutor
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
  */