@inkeep/agents-run-api 0.18.0 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{LocalSandboxExecutor-PQIRECLQ.js → LocalSandboxExecutor-2UQ32ZZH.js} +111 -6
- package/dist/{chunk-DQQRVSJS.js → chunk-QRT6EIUX.js} +6 -6
- package/dist/{conversations-JSORLLWS.js → conversations-OFIM2WLJ.js} +1 -1
- package/dist/index.cjs +705 -556
- package/dist/index.js +590 -543
- package/package.json +4 -3
- package/templates/v1/phase1/system-prompt.xml +1 -1
- package/templates/v1/shared/artifact-retrieval-guidance.xml +1 -1
|
@@ -7,6 +7,58 @@ import { tmpdir } from 'os';
|
|
|
7
7
|
import { join } from 'path';
|
|
8
8
|
|
|
9
9
|
var logger = getLogger("local-sandbox-executor");
|
|
10
|
+
var ExecutionSemaphore = class {
|
|
11
|
+
constructor(permits, maxWaitTimeMs = 3e4) {
|
|
12
|
+
__publicField(this, "permits");
|
|
13
|
+
__publicField(this, "waitQueue", []);
|
|
14
|
+
__publicField(this, "maxWaitTime");
|
|
15
|
+
this.permits = Math.max(1, permits);
|
|
16
|
+
this.maxWaitTime = maxWaitTimeMs;
|
|
17
|
+
}
|
|
18
|
+
async acquire(fn) {
|
|
19
|
+
await new Promise((resolve, reject) => {
|
|
20
|
+
if (this.permits > 0) {
|
|
21
|
+
this.permits--;
|
|
22
|
+
resolve();
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const timeoutId = setTimeout(() => {
|
|
26
|
+
const index = this.waitQueue.findIndex((item) => item.resolve === resolve);
|
|
27
|
+
if (index !== -1) {
|
|
28
|
+
this.waitQueue.splice(index, 1);
|
|
29
|
+
reject(
|
|
30
|
+
new Error(
|
|
31
|
+
`Function execution queue timeout after ${this.maxWaitTime}ms. Too many concurrent executions.`
|
|
32
|
+
)
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
}, this.maxWaitTime);
|
|
36
|
+
this.waitQueue.push({
|
|
37
|
+
resolve: () => {
|
|
38
|
+
clearTimeout(timeoutId);
|
|
39
|
+
this.permits--;
|
|
40
|
+
resolve();
|
|
41
|
+
},
|
|
42
|
+
reject
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
try {
|
|
46
|
+
return await fn();
|
|
47
|
+
} finally {
|
|
48
|
+
this.permits++;
|
|
49
|
+
const next = this.waitQueue.shift();
|
|
50
|
+
if (next) {
|
|
51
|
+
next.resolve();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
getAvailablePermits() {
|
|
56
|
+
return this.permits;
|
|
57
|
+
}
|
|
58
|
+
getQueueLength() {
|
|
59
|
+
return this.waitQueue.length;
|
|
60
|
+
}
|
|
61
|
+
};
|
|
10
62
|
var _LocalSandboxExecutor = class _LocalSandboxExecutor {
|
|
11
63
|
constructor() {
|
|
12
64
|
__publicField(this, "tempDir");
|
|
@@ -14,6 +66,7 @@ var _LocalSandboxExecutor = class _LocalSandboxExecutor {
|
|
|
14
66
|
__publicField(this, "POOL_TTL", 5 * 60 * 1e3);
|
|
15
67
|
// 5 minutes
|
|
16
68
|
__publicField(this, "MAX_USE_COUNT", 50);
|
|
69
|
+
__publicField(this, "executionSemaphores", /* @__PURE__ */ new Map());
|
|
17
70
|
this.tempDir = join(tmpdir(), "inkeep-sandboxes");
|
|
18
71
|
this.ensureTempDir();
|
|
19
72
|
this.startPoolCleanup();
|
|
@@ -24,6 +77,34 @@ var _LocalSandboxExecutor = class _LocalSandboxExecutor {
|
|
|
24
77
|
}
|
|
25
78
|
return _LocalSandboxExecutor.instance;
|
|
26
79
|
}
|
|
80
|
+
/**
|
|
81
|
+
* Get or create a semaphore for the specified vCPU limit
|
|
82
|
+
*/
|
|
83
|
+
getSemaphore(vcpus) {
|
|
84
|
+
const effectiveVcpus = Math.max(1, vcpus || 1);
|
|
85
|
+
if (!this.executionSemaphores.has(effectiveVcpus)) {
|
|
86
|
+
logger.debug({ vcpus: effectiveVcpus }, "Creating new execution semaphore");
|
|
87
|
+
this.executionSemaphores.set(effectiveVcpus, new ExecutionSemaphore(effectiveVcpus));
|
|
88
|
+
}
|
|
89
|
+
const semaphore = this.executionSemaphores.get(effectiveVcpus);
|
|
90
|
+
if (!semaphore) {
|
|
91
|
+
throw new Error(`Failed to create semaphore for ${effectiveVcpus} vCPUs`);
|
|
92
|
+
}
|
|
93
|
+
return semaphore;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Get execution statistics for monitoring and debugging
|
|
97
|
+
*/
|
|
98
|
+
getExecutionStats() {
|
|
99
|
+
const stats = {};
|
|
100
|
+
for (const [vcpus, semaphore] of this.executionSemaphores.entries()) {
|
|
101
|
+
stats[`vcpu_${vcpus}`] = {
|
|
102
|
+
availablePermits: semaphore.getAvailablePermits(),
|
|
103
|
+
queueLength: semaphore.getQueueLength()
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
return stats;
|
|
107
|
+
}
|
|
27
108
|
ensureTempDir() {
|
|
28
109
|
try {
|
|
29
110
|
mkdirSync(this.tempDir, { recursive: true });
|
|
@@ -98,7 +179,7 @@ var _LocalSandboxExecutor = class _LocalSandboxExecutor {
|
|
|
98
179
|
}
|
|
99
180
|
}, 6e4);
|
|
100
181
|
}
|
|
101
|
-
detectModuleType(executeCode) {
|
|
182
|
+
detectModuleType(executeCode, configuredRuntime) {
|
|
102
183
|
const esmPatterns = [
|
|
103
184
|
/import\s+.*\s+from\s+['"]/g,
|
|
104
185
|
// import ... from '...'
|
|
@@ -119,6 +200,9 @@ var _LocalSandboxExecutor = class _LocalSandboxExecutor {
|
|
|
119
200
|
];
|
|
120
201
|
const hasEsmSyntax = esmPatterns.some((pattern) => pattern.test(executeCode));
|
|
121
202
|
const hasCjsSyntax = cjsPatterns.some((pattern) => pattern.test(executeCode));
|
|
203
|
+
if (configuredRuntime === "typescript") {
|
|
204
|
+
return hasCjsSyntax ? "cjs" : "esm";
|
|
205
|
+
}
|
|
122
206
|
if (hasEsmSyntax && hasCjsSyntax) {
|
|
123
207
|
logger.warn(
|
|
124
208
|
{ executeCode: `${executeCode.substring(0, 100)}...` },
|
|
@@ -135,6 +219,24 @@ var _LocalSandboxExecutor = class _LocalSandboxExecutor {
|
|
|
135
219
|
return "cjs";
|
|
136
220
|
}
|
|
137
221
|
async executeFunctionTool(toolId, args, config) {
|
|
222
|
+
const vcpus = config.sandboxConfig?.vcpus || 1;
|
|
223
|
+
const semaphore = this.getSemaphore(vcpus);
|
|
224
|
+
logger.debug(
|
|
225
|
+
{
|
|
226
|
+
toolId,
|
|
227
|
+
vcpus,
|
|
228
|
+
availablePermits: semaphore.getAvailablePermits(),
|
|
229
|
+
queueLength: semaphore.getQueueLength(),
|
|
230
|
+
sandboxConfig: config.sandboxConfig,
|
|
231
|
+
poolSize: Object.keys(this.sandboxPool).length
|
|
232
|
+
},
|
|
233
|
+
"Acquiring execution slot for function tool"
|
|
234
|
+
);
|
|
235
|
+
return semaphore.acquire(async () => {
|
|
236
|
+
return this.executeInSandbox_Internal(toolId, args, config);
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
async executeInSandbox_Internal(toolId, args, config) {
|
|
138
240
|
const dependencies = config.dependencies || {};
|
|
139
241
|
const dependencyHash = this.generateDependencyHash(dependencies);
|
|
140
242
|
logger.debug(
|
|
@@ -142,6 +244,7 @@ var _LocalSandboxExecutor = class _LocalSandboxExecutor {
|
|
|
142
244
|
toolId,
|
|
143
245
|
dependencies,
|
|
144
246
|
dependencyHash,
|
|
247
|
+
sandboxConfig: config.sandboxConfig,
|
|
145
248
|
poolSize: Object.keys(this.sandboxPool).length
|
|
146
249
|
},
|
|
147
250
|
"Executing function tool"
|
|
@@ -161,7 +264,7 @@ var _LocalSandboxExecutor = class _LocalSandboxExecutor {
|
|
|
161
264
|
},
|
|
162
265
|
"Creating new sandbox"
|
|
163
266
|
);
|
|
164
|
-
const moduleType = this.detectModuleType(config.executeCode);
|
|
267
|
+
const moduleType = this.detectModuleType(config.executeCode, config.sandboxConfig?.runtime);
|
|
165
268
|
const packageJson = {
|
|
166
269
|
name: `function-tool-${toolId}`,
|
|
167
270
|
version: "1.0.0",
|
|
@@ -178,14 +281,15 @@ var _LocalSandboxExecutor = class _LocalSandboxExecutor {
|
|
|
178
281
|
this.addToPool(dependencyHash, sandboxDir, dependencies);
|
|
179
282
|
}
|
|
180
283
|
try {
|
|
181
|
-
const moduleType = this.detectModuleType(config.executeCode);
|
|
284
|
+
const moduleType = this.detectModuleType(config.executeCode, config.sandboxConfig?.runtime);
|
|
182
285
|
const executionCode = this.wrapFunctionCode(config.executeCode, args);
|
|
183
286
|
const fileExtension = moduleType === "esm" ? "mjs" : "js";
|
|
184
287
|
writeFileSync(join(sandboxDir, `index.${fileExtension}`), executionCode, "utf8");
|
|
185
288
|
const result = await this.executeInSandbox(
|
|
186
289
|
sandboxDir,
|
|
187
290
|
config.sandboxConfig?.timeout || 3e4,
|
|
188
|
-
moduleType
|
|
291
|
+
moduleType,
|
|
292
|
+
config.sandboxConfig
|
|
189
293
|
);
|
|
190
294
|
return result;
|
|
191
295
|
} catch (error) {
|
|
@@ -224,7 +328,7 @@ var _LocalSandboxExecutor = class _LocalSandboxExecutor {
|
|
|
224
328
|
});
|
|
225
329
|
});
|
|
226
330
|
}
|
|
227
|
-
async executeInSandbox(sandboxDir, timeout, moduleType) {
|
|
331
|
+
async executeInSandbox(sandboxDir, timeout, moduleType, _sandboxConfig) {
|
|
228
332
|
return new Promise((resolve, reject) => {
|
|
229
333
|
const fileExtension = moduleType === "esm" ? "mjs" : "js";
|
|
230
334
|
const spawnOptions = {
|
|
@@ -262,12 +366,13 @@ var _LocalSandboxExecutor = class _LocalSandboxExecutor {
|
|
|
262
366
|
const timeoutId = setTimeout(() => {
|
|
263
367
|
logger.warn({ sandboxDir, timeout }, "Function execution timed out, killing process");
|
|
264
368
|
node.kill("SIGTERM");
|
|
369
|
+
const forceKillTimeout = Math.min(Math.max(timeout / 10, 2e3), 5e3);
|
|
265
370
|
setTimeout(() => {
|
|
266
371
|
try {
|
|
267
372
|
node.kill("SIGKILL");
|
|
268
373
|
} catch {
|
|
269
374
|
}
|
|
270
|
-
},
|
|
375
|
+
}, forceKillTimeout);
|
|
271
376
|
reject(new Error(`Function execution timed out after ${timeout}ms`));
|
|
272
377
|
}, timeout);
|
|
273
378
|
node.on("close", (code, signal) => {
|
|
@@ -75,7 +75,7 @@ async function getScopedHistory({
|
|
|
75
75
|
let matchesAgent = true;
|
|
76
76
|
let matchesTask = true;
|
|
77
77
|
if (filters.subAgentId) {
|
|
78
|
-
matchesAgent = msg.role === "agent" && msg.visibility === "user-facing" || msg.
|
|
78
|
+
matchesAgent = msg.role === "agent" && msg.visibility === "user-facing" || msg.toSubAgentId === filters.subAgentId || msg.fromSubAgentId === filters.subAgentId;
|
|
79
79
|
}
|
|
80
80
|
if (filters.taskId) {
|
|
81
81
|
matchesTask = msg.taskId === filters.taskId || msg.a2aTaskId === filters.taskId;
|
|
@@ -150,12 +150,12 @@ async function getFormattedConversationHistory({
|
|
|
150
150
|
if (msg.role === "user") {
|
|
151
151
|
roleLabel = "user";
|
|
152
152
|
} else if (msg.role === "agent" && (msg.messageType === "a2a-request" || msg.messageType === "a2a-response")) {
|
|
153
|
-
const
|
|
154
|
-
const
|
|
155
|
-
roleLabel = `${
|
|
153
|
+
const fromSubAgent = msg.fromSubAgentId || msg.fromExternalAgentId || "unknown";
|
|
154
|
+
const toSubAgent = msg.toSubAgentId || msg.toExternalAgentId || "unknown";
|
|
155
|
+
roleLabel = `${fromSubAgent} to ${toSubAgent}`;
|
|
156
156
|
} else if (msg.role === "agent" && msg.messageType === "chat") {
|
|
157
|
-
const
|
|
158
|
-
roleLabel = `${
|
|
157
|
+
const fromSubAgent = msg.fromSubAgentId || "unknown";
|
|
158
|
+
roleLabel = `${fromSubAgent} to User`;
|
|
159
159
|
} else {
|
|
160
160
|
roleLabel = msg.role || "system";
|
|
161
161
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { createDefaultConversationHistoryConfig, getConversationScopedArtifacts, getFormattedConversationHistory, getFullConversationContext, getScopedHistory, getUserFacingHistory, saveA2AMessageResponse } from './chunk-
|
|
1
|
+
export { createDefaultConversationHistoryConfig, getConversationScopedArtifacts, getFormattedConversationHistory, getFullConversationContext, getScopedHistory, getUserFacingHistory, saveA2AMessageResponse } from './chunk-QRT6EIUX.js';
|