Order agent configuration runtime first

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-07-22 15:25:46 +00:00
1 parent 85d48eb699
commit ad69cf63e2
5 files changed
+103 -102

No files matched your search

@@ -398,6 +398,7 @@ describe("AgentConfigForm environment selector", () => {
expect(result.container.textContent).toContain("Advanced runtime");
expect(result.container.textContent).toContain("runtime adapter fields");
expect(runtime?.compareDocumentPosition(environment as Node) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy();
expect(runtime?.textContent).not.toContain("Environment variables");
expect(runtime?.textContent).not.toContain("Working directory (deprecated)");
expect(environment?.parentElement?.textContent).toContain("Environment variables");
+98 -98
View File
@@ -1091,104 +1091,6 @@ export function AgentConfigForm(props: AgentConfigFormProps) {
</div>
)}
{/* ---- Execution ---- */}
{configurationShell && sectionVisible("environment") ? (
<div id="config-environment" className="scroll-mt-24" />
) : null}
{sectionVisible("environment") && (forcedKubernetes ? (
// Instance execution policy forces the managed Kubernetes sandbox
// (executionMode=kubernetes): never offer local / non-Kubernetes targets.
// Render the environment read-only instead of the selectable picker.
<div className={cn(!cards && (isCreate ? "border-t border-border" : "border-b border-border"))}>
{cards
? <h3 className="text-sm font-medium mb-3">Environment</h3>
: <div className="px-4 py-2 text-xs font-medium text-muted-foreground">Environment</div>
}
<div className={cn(cards ? "border border-border rounded-lg p-4 space-y-3" : "px-4 pb-3 space-y-3")}>
<Field
label="Default environment"
hint="This instance runs all agents in the Kubernetes sandbox. Local execution is disabled."
>
{kubernetesEnvironment ? (
<div className={cn(inputClass, "flex items-center text-muted-foreground")}>
{kubernetesEnvironment.name} · Kubernetes sandbox
</div>
) : (
<div className="rounded-md border border-amber-500/25 bg-amber-500/10 px-3 py-2 text-xs text-amber-800 dark:text-amber-200">
This instance requires the Kubernetes sandbox, but no managed Kubernetes
environment is available for this company yet. Configure one before creating
agents; execution will not fall back to local.
</div>
)}
</Field>
</div>
</div>
) : showEnvironmentOverrideControl ? (
<div className={cn(!cards && (isCreate ? "border-t border-border" : "border-b border-border"))}>
{cards
? <h3 className="text-sm font-medium mb-3">Environment</h3>
: <div className="px-4 py-2 text-xs font-medium text-muted-foreground">Environment</div>
}
<div className={cn(cards ? "border border-border rounded-lg p-4 space-y-3" : "px-4 pb-3 space-y-3")}>
<Field label="Environment override">
<div className="space-y-2">
<select
className={inputClass}
value={currentDefaultEnvironmentId}
onChange={(event) => {
const nextValue = event.target.value;
if (isCreate) {
set!({ defaultEnvironmentId: nextValue });
return;
}
mark("identity", "defaultEnvironmentId", nextValue || null);
}}
>
<option value="">Default: {inheritedEnvironmentLabel}</option>
{environmentOptions.map((environment) => (
<option key={environment.id} value={environment.id}>
{environment.name} · {environment.driver}
</option>
))}
</select>
</div>
</Field>
</div>
</div>
) : null)}
{configurationShell && sectionVisible("environment") && isLocal && (
<div className={cn(cards ? "border border-border rounded-lg p-4 space-y-3" : "px-4 pb-3 space-y-3")}>
<Field label="Environment variables" hint={help.envVars}>
<EnvironmentVariablesEditor
ref={environmentVariablesEditorRef}
value={
isCreate
? ((val!.envBindings ?? EMPTY_ENV) as Record<string, EnvBinding>)
: eff("adapterConfig", "env", (config.env ?? EMPTY_ENV) as Record<string, EnvBinding>)
}
secrets={availableSecrets}
userSecretDefinitions={userSecretDefinitions}
onCreateSecret={async (name, value) => createSecret.mutateAsync({ name, value })}
onChange={(env) =>
isCreate
? set!({ envBindings: env ?? {}, envVars: "" })
: mark("adapterConfig", "env", env)
}
/>
</Field>
{!isCreate && (
<Field label="Secret access" hint={help.secretAccess}>
<AgentSecretAccessEditor
config={{ ...config, ...overlay.adapterConfig }}
secrets={availableSecrets}
onChange={applyAccessGrants}
/>
</Field>
)}
</div>
)}
{/* ---- Adapter ---- */}
{sectionVisible("runtime") && <div id={configurationShell ? "config-runtime" : undefined} className={cn(!cards && (isCreate ? "border-t border-border" : "border-b border-border"), configurationShell && "scroll-mt-24")}>
<div className={cn(cards ? "flex items-center justify-between mb-3" : "px-4 py-2 flex items-center justify-between gap-2")}>
@@ -1563,6 +1465,104 @@ export function AgentConfigForm(props: AgentConfigFormProps) {
</div>
)}
{/* ---- Execution ---- */}
{configurationShell && sectionVisible("environment") ? (
<div id="config-environment" className="scroll-mt-24" />
) : null}
{sectionVisible("environment") && (forcedKubernetes ? (
// Instance execution policy forces the managed Kubernetes sandbox
// (executionMode=kubernetes): never offer local / non-Kubernetes targets.
// Render the environment read-only instead of the selectable picker.
<div className={cn(!cards && (isCreate ? "border-t border-border" : "border-b border-border"))}>
{cards
? <h3 className="text-sm font-medium mb-3">Environment</h3>
: <div className="px-4 py-2 text-xs font-medium text-muted-foreground">Environment</div>
}
<div className={cn(cards ? "border border-border rounded-lg p-4 space-y-3" : "px-4 pb-3 space-y-3")}>
<Field
label="Default environment"
hint="This instance runs all agents in the Kubernetes sandbox. Local execution is disabled."
>
{kubernetesEnvironment ? (
<div className={cn(inputClass, "flex items-center text-muted-foreground")}>
{kubernetesEnvironment.name} · Kubernetes sandbox
</div>
) : (
<div className="rounded-md border border-amber-500/25 bg-amber-500/10 px-3 py-2 text-xs text-amber-800 dark:text-amber-200">
This instance requires the Kubernetes sandbox, but no managed Kubernetes
environment is available for this company yet. Configure one before creating
agents; execution will not fall back to local.
</div>
)}
</Field>
</div>
</div>
) : showEnvironmentOverrideControl ? (
<div className={cn(!cards && (isCreate ? "border-t border-border" : "border-b border-border"))}>
{cards
? <h3 className="text-sm font-medium mb-3">Environment</h3>
: <div className="px-4 py-2 text-xs font-medium text-muted-foreground">Environment</div>
}
<div className={cn(cards ? "border border-border rounded-lg p-4 space-y-3" : "px-4 pb-3 space-y-3")}>
<Field label="Environment override">
<div className="space-y-2">
<select
className={inputClass}
value={currentDefaultEnvironmentId}
onChange={(event) => {
const nextValue = event.target.value;
if (isCreate) {
set!({ defaultEnvironmentId: nextValue });
return;
}
mark("identity", "defaultEnvironmentId", nextValue || null);
}}
>
<option value="">Default: {inheritedEnvironmentLabel}</option>
{environmentOptions.map((environment) => (
<option key={environment.id} value={environment.id}>
{environment.name} · {environment.driver}
</option>
))}
</select>
</div>
</Field>
</div>
</div>
) : null)}
{configurationShell && sectionVisible("environment") && isLocal && (
<div className={cn(cards ? "border border-border rounded-lg p-4 space-y-3" : "px-4 pb-3 space-y-3")}>
<Field label="Environment variables" hint={help.envVars}>
<EnvironmentVariablesEditor
ref={environmentVariablesEditorRef}
value={
isCreate
? ((val!.envBindings ?? EMPTY_ENV) as Record<string, EnvBinding>)
: eff("adapterConfig", "env", (config.env ?? EMPTY_ENV) as Record<string, EnvBinding>)
}
secrets={availableSecrets}
userSecretDefinitions={userSecretDefinitions}
onCreateSecret={async (name, value) => createSecret.mutateAsync({ name, value })}
onChange={(env) =>
isCreate
? set!({ envBindings: env ?? {}, envVars: "" })
: mark("adapterConfig", "env", env)
}
/>
</Field>
{!isCreate && (
<Field label="Secret access" hint={help.secretAccess}>
<AgentSecretAccessEditor
config={{ ...config, ...overlay.adapterConfig }}
secrets={availableSecrets}
onChange={applyAccessGrants}
/>
</Field>
)}
</div>
)}
{/* ---- Run Policy ---- */}
{sectionVisible("schedule") && (isCreate && showCreateRunPolicySection ? (
<div id={configurationShell ? "config-schedule" : undefined} className={cn(!cards && "border-b border-border", configurationShell && "scroll-mt-24")}>
@@ -8,7 +8,7 @@ import {
describe("agent configuration shell", () => {
it("matches both section names and field labels", () => {
expect([...filterAgentConfigurationSections("")].slice(0, 2)).toEqual(["environment", "runtime"]);
expect([...filterAgentConfigurationSections("")].slice(0, 2)).toEqual(["runtime", "environment"]);
expect([...filterAgentConfigurationSections("heartbeat")]).toEqual(["schedule"]);
expect([...filterAgentConfigurationSections("API Keys")]).toEqual(["keys"]);
expect([...filterAgentConfigurationSections("sandbox")]).toEqual(["danger"]);
@@ -20,8 +20,8 @@ export const agentConfigurationSections: ReadonlyArray<{
instant?: boolean;
fields: string[];
}> = [
{ id: "environment", label: "Environment", fields: ["execution environment", "environment override", "variables", "secrets"] },
{ id: "runtime", label: "Runtime", fields: ["adapter", "model", "effort", "turns", "command", "arguments", "engine", "timeout", "chrome"] },
{ id: "environment", label: "Environment", fields: ["execution environment", "environment override", "variables", "secrets"] },
{ id: "schedule", label: "Schedule & Runs", fields: ["heartbeat", "wake on demand", "cooldown", "concurrent runs", "continuation"] },
{ id: "access", label: "Access & Governance", instant: true, fields: ["trust preset", "boundary", "create agents", "create skills", "assign tasks"] },
{ id: "keys", label: "API Keys", instant: true, fields: ["credentials", "create key", "revoke key"] },
+2 -2
View File
@@ -1779,11 +1779,11 @@ function AgentConfigurePage({
});
const effectiveChips: Array<{ label: string; value: string; section: AgentConfigurationSectionId; inherited?: boolean }> = [
{ label: "Environment", value: effectiveConfig.environment, section: "environment", inherited: effectiveConfig.environmentInherited },
{ label: "Variables", value: String(effectiveConfig.environmentVariableCount), section: "environment" },
{ label: "Adapter", value: effectiveConfig.adapter, section: "runtime" },
{ label: "Model", value: effectiveConfig.model, section: "runtime", inherited: effectiveConfig.modelInherited },
{ label: "Cost saver", value: effectiveConfig.cheapModel, section: "runtime", inherited: effectiveConfig.cheapInherited },
{ label: "Environment", value: effectiveConfig.environment, section: "environment", inherited: effectiveConfig.environmentInherited },
{ label: "Variables", value: String(effectiveConfig.environmentVariableCount), section: "environment" },
{ label: "Heartbeat", value: effectiveConfig.cadence, section: "schedule" },
{ label: "Trust", value: effectiveConfig.trust, section: "access" },
{ label: "API keys", value: String(effectiveConfig.apiKeyCount), section: "keys" },