Improve E2B plugin configuration UX and fix execution timeouts

Clarify E2B API key configuration in plugin settings UI. Fix plugin
environment RPC timeout propagation with 30s overhead buffer.
Deduplicate timeout resolver into plugin-environment-driver.
This commit is contained in:
Devin Foley committed 2026-04-29 16:57:46 -07:00
1 parent a4ac6ff133
commit 518639fd5f
7 files changed
+187 -7

No files matched your search

@@ -551,7 +551,7 @@ describeEmbeddedPostgres("environmentRuntimeService", () => {
expect(executed.stdout).toBe("ok\n");
expect(released).toHaveLength(1);
expect(released[0]?.lease.status).toBe("released");
expect(workerManager.call).toHaveBeenCalledWith(pluginId, "environmentExecute", expect.anything());
expect(workerManager.call).toHaveBeenCalledWith(pluginId, "environmentExecute", expect.anything(), 31000);
expect(workerManager.call).toHaveBeenCalledWith(pluginId, "environmentReleaseLease", expect.anything());
});
@@ -676,7 +676,6 @@ describeEmbeddedPostgres("environmentRuntimeService", () => {
args: ["ok"],
cwd: "/workspace",
env: {},
timeoutMs: 1000,
});
await environmentService(db).update(environment.id, {
@@ -692,7 +691,7 @@ describeEmbeddedPostgres("environmentRuntimeService", () => {
config: expect.objectContaining({
apiKey: "resolved-provider-key",
}),
}));
}), 31234);
expect(workerManager.call).toHaveBeenCalledWith(pluginId, "environmentReleaseLease", expect.objectContaining({
config: expect.objectContaining({
apiKey: "resolved-provider-key",
@@ -1241,7 +1240,7 @@ describeEmbeddedPostgres("environmentRuntimeService", () => {
args: ["ok"],
cwd: "/workspace/project",
env: { FOO: "bar" },
}));
}), 31000);
expect(workerManager.call).toHaveBeenCalledWith(pluginId, "environmentDestroyLease", {
driverKey: "fake-plugin",
companyId,
+5 -1
View File
@@ -36,6 +36,7 @@ import {
executePluginEnvironmentCommand,
realizePluginEnvironmentWorkspace,
resolvePluginSandboxProviderDriverByKey,
resolvePluginExecuteRpcTimeoutMs,
resumePluginEnvironmentLease,
} from "./plugin-environment-driver.js";
import { collectSecretRefPaths } from "./json-schema-secret-refs.js";
@@ -654,7 +655,10 @@ function createSandboxEnvironmentDriver(
env: input.env,
stdin: input.stdin,
timeoutMs: input.timeoutMs,
});
}, resolvePluginExecuteRpcTimeoutMs({
requestedTimeoutMs: input.timeoutMs,
config: sanitizedConfig,
}));
}
}
throw new Error("Sandbox driver does not support direct command execution for built-in providers.");
@@ -313,5 +313,31 @@ export async function executePluginEnvironmentCommand(input: {
workerManager: input.workerManager,
config: input.config,
});
return await input.workerManager.call(plugin.id, "environmentExecute", input.params);
return await input.workerManager.call(
plugin.id,
"environmentExecute",
input.params,
resolvePluginExecuteRpcTimeoutMs({
requestedTimeoutMs: input.params.timeoutMs,
config: input.config.driverConfig,
}),
);
}
const RPC_OVERHEAD_BUFFER_MS = 30_000;
export function resolvePluginExecuteRpcTimeoutMs(input: {
requestedTimeoutMs?: number;
config: Record<string, unknown>;
}): number | undefined {
let baseMs: number | undefined;
if (Number.isFinite(input.requestedTimeoutMs) && (input.requestedTimeoutMs ?? 0) > 0) {
baseMs = Math.trunc(input.requestedTimeoutMs!);
} else {
const configTimeoutMs = typeof input.config.timeoutMs === "number" ? input.config.timeoutMs : null;
if (configTimeoutMs && Number.isFinite(configTimeoutMs) && configTimeoutMs > 0) {
baseMs = Math.trunc(configTimeoutMs);
}
}
return baseMs != null ? baseMs + RPC_OVERHEAD_BUFFER_MS : undefined;
}