fix: align agent exec config

This commit is contained in:
Peter Steinberger
2026-01-18 04:37:15 +00:00
parent 55aff22274
commit 1ae415e395
5 changed files with 37 additions and 35 deletions

View File

@@ -343,10 +343,7 @@ export function createExecTool(
const configuredSecurity = defaults?.security ?? "deny";
const requestedSecurity = normalizeExecSecurity(params.security);
let security = minSecurity(
configuredSecurity,
requestedSecurity ?? configuredSecurity,
);
let security = minSecurity(configuredSecurity, requestedSecurity ?? configuredSecurity);
if (elevatedRequested) {
security = "full";
}

View File

@@ -213,7 +213,6 @@ export function createClawdbotCodingTools(options?: {
messageProvider: options?.messageProvider,
backgroundMs: options?.exec?.backgroundMs ?? execConfig.backgroundMs,
timeoutSec: options?.exec?.timeoutSec ?? execConfig.timeoutSec,
cleanupMs: options?.exec?.cleanupMs ?? execConfig.cleanupMs,
notifyOnExit: options?.exec?.notifyOnExit ?? execConfig.notifyOnExit,
sandbox: sandbox
? {

View File

@@ -120,6 +120,35 @@ export type ToolPolicyConfig = {
profile?: ToolProfileId;
};
export type ExecToolConfig = {
/** Exec host routing (default: sandbox). */
host?: "sandbox" | "gateway" | "node";
/** Exec security mode (default: deny). */
security?: "deny" | "allowlist" | "full";
/** Exec ask mode (default: on-miss). */
ask?: "off" | "on-miss" | "always";
/** Default node binding for exec.host=node (node id/name). */
node?: string;
/** Default time (ms) before an exec command auto-backgrounds. */
backgroundMs?: number;
/** Default timeout (seconds) before auto-killing exec commands. */
timeoutSec?: number;
/** How long to keep finished sessions in memory (ms). */
cleanupMs?: number;
/** Emit a system event and heartbeat when a backgrounded exec exits. */
notifyOnExit?: boolean;
/** apply_patch subtool configuration (experimental). */
applyPatch?: {
/** Enable apply_patch for OpenAI models (default: false). */
enabled?: boolean;
/**
* Optional allowlist of model ids that can use apply_patch.
* Accepts either raw ids (e.g. "gpt-5.2") or full ids (e.g. "openai/gpt-5.2").
*/
allowModels?: string[];
};
};
export type AgentToolsConfig = {
/** Base tool profile applied before allow/deny lists. */
profile?: ToolProfileId;
@@ -134,6 +163,8 @@ export type AgentToolsConfig = {
/** Approved senders for /elevated (per-provider allowlists). */
allowFrom?: AgentElevatedAllowFromConfig;
};
/** Exec tool defaults for this agent. */
exec?: ExecToolConfig;
sandbox?: {
tools?: {
allow?: string[];
@@ -338,34 +369,7 @@ export type ToolsConfig = {
allowFrom?: AgentElevatedAllowFromConfig;
};
/** Exec tool defaults. */
exec?: {
/** Exec host routing (default: sandbox). */
host?: "sandbox" | "gateway" | "node";
/** Exec security mode (default: deny). */
security?: "deny" | "allowlist" | "full";
/** Exec ask mode (default: on-miss). */
ask?: "off" | "on-miss" | "always";
/** Default node binding for exec.host=node (node id/name). */
node?: string;
/** Default time (ms) before an exec command auto-backgrounds. */
backgroundMs?: number;
/** Default timeout (seconds) before auto-killing exec commands. */
timeoutSec?: number;
/** How long to keep finished sessions in memory (ms). */
cleanupMs?: number;
/** Emit a system event and heartbeat when a backgrounded exec exits. */
notifyOnExit?: boolean;
/** apply_patch subtool configuration (experimental). */
applyPatch?: {
/** Enable apply_patch for OpenAI models (default: false). */
enabled?: boolean;
/**
* Optional allowlist of model ids that can use apply_patch.
* Accepts either raw ids (e.g. "gpt-5.2") or full ids (e.g. "openai/gpt-5.2").
*/
allowModels?: string[];
};
};
exec?: ExecToolConfig;
/** Sub-agent tool policy defaults (deny wins). */
subagents?: {
/** Default model selection for spawned sub-agents (string or {primary,fallbacks}). */

View File

@@ -192,7 +192,9 @@ export const handleBridgeEvent = async (
const runId = typeof obj.runId === "string" ? obj.runId.trim() : "";
const command = typeof obj.command === "string" ? obj.command.trim() : "";
const exitCode =
typeof obj.exitCode === "number" && Number.isFinite(obj.exitCode) ? obj.exitCode : undefined;
typeof obj.exitCode === "number" && Number.isFinite(obj.exitCode)
? obj.exitCode
: undefined;
const timedOut = obj.timedOut === true;
const success = obj.success === true;
const output = typeof obj.output === "string" ? obj.output.trim() : "";

View File

@@ -185,7 +185,7 @@ function parseFirstToken(command: string): string | null {
const trimmed = command.trim();
if (!trimmed) return null;
const first = trimmed[0];
if (first === "\"" || first === "'") {
if (first === '"' || first === "'") {
const end = trimmed.indexOf(first, 1);
if (end > 1) return trimmed.slice(1, end);
return trimmed.slice(1);