Set codex-local creation defaults for model and sandbox bypass

This commit is contained in:
Dotta
2026-03-03 12:41:50 -06:00
parent 8351f7f1bd
commit 0810101fda
5 changed files with 78 additions and 9 deletions

View File

@@ -1,8 +1,10 @@
export const type = "codex_local"; export const type = "codex_local";
export const label = "Codex (local)"; export const label = "Codex (local)";
export const DEFAULT_CODEX_LOCAL_MODEL = "gpt-5.3-codex";
export const DEFAULT_CODEX_LOCAL_BYPASS_APPROVALS_AND_SANDBOX = true;
export const models = [ export const models = [
{ id: "gpt-5.3-codex", label: "gpt-5.3-codex" }, { id: DEFAULT_CODEX_LOCAL_MODEL, label: DEFAULT_CODEX_LOCAL_MODEL },
{ id: "gpt-5.3-codex-spark", label: "gpt-5.3-codex-spark" }, { id: "gpt-5.3-codex-spark", label: "gpt-5.3-codex-spark" },
{ id: "gpt-5", label: "gpt-5" }, { id: "gpt-5", label: "gpt-5" },
{ id: "o3", label: "o3" }, { id: "o3", label: "o3" },

View File

@@ -1,4 +1,8 @@
import type { CreateConfigValues } from "@paperclipai/adapter-utils"; import type { CreateConfigValues } from "@paperclipai/adapter-utils";
import {
DEFAULT_CODEX_LOCAL_BYPASS_APPROVALS_AND_SANDBOX,
DEFAULT_CODEX_LOCAL_MODEL,
} from "../index.js";
function parseCommaArgs(value: string): string[] { function parseCommaArgs(value: string): string[] {
return value return value
@@ -55,7 +59,7 @@ export function buildCodexLocalConfig(v: CreateConfigValues): Record<string, unk
if (v.cwd) ac.cwd = v.cwd; if (v.cwd) ac.cwd = v.cwd;
if (v.instructionsFilePath) ac.instructionsFilePath = v.instructionsFilePath; if (v.instructionsFilePath) ac.instructionsFilePath = v.instructionsFilePath;
if (v.promptTemplate) ac.promptTemplate = v.promptTemplate; if (v.promptTemplate) ac.promptTemplate = v.promptTemplate;
if (v.model) ac.model = v.model; ac.model = v.model || DEFAULT_CODEX_LOCAL_MODEL;
if (v.thinkingEffort) ac.modelReasoningEffort = v.thinkingEffort; if (v.thinkingEffort) ac.modelReasoningEffort = v.thinkingEffort;
ac.timeoutSec = 0; ac.timeoutSec = 0;
ac.graceSec = 15; ac.graceSec = 15;
@@ -68,7 +72,10 @@ export function buildCodexLocalConfig(v: CreateConfigValues): Record<string, unk
} }
if (Object.keys(env).length > 0) ac.env = env; if (Object.keys(env).length > 0) ac.env = env;
ac.search = v.search; ac.search = v.search;
ac.dangerouslyBypassApprovalsAndSandbox = v.dangerouslyBypassSandbox; ac.dangerouslyBypassApprovalsAndSandbox =
typeof v.dangerouslyBypassSandbox === "boolean"
? v.dangerouslyBypassSandbox
: DEFAULT_CODEX_LOCAL_BYPASS_APPROVALS_AND_SANDBOX;
if (v.command) ac.command = v.command; if (v.command) ac.command = v.command;
if (v.extraArgs) ac.extraArgs = parseCommaArgs(v.extraArgs); if (v.extraArgs) ac.extraArgs = parseCommaArgs(v.extraArgs);
return ac; return ac;

View File

@@ -32,6 +32,10 @@ import { assertBoard, assertCompanyAccess, getActorInfo } from "./authz.js";
import { findServerAdapter, listAdapterModels } from "../adapters/index.js"; import { findServerAdapter, listAdapterModels } from "../adapters/index.js";
import { redactEventPayload } from "../redaction.js"; import { redactEventPayload } from "../redaction.js";
import { runClaudeLogin } from "@paperclipai/adapter-claude-local/server"; import { runClaudeLogin } from "@paperclipai/adapter-claude-local/server";
import {
DEFAULT_CODEX_LOCAL_BYPASS_APPROVALS_AND_SANDBOX,
DEFAULT_CODEX_LOCAL_MODEL,
} from "@paperclipai/adapter-codex-local";
export function agentRoutes(db: Db) { export function agentRoutes(db: Db) {
const DEFAULT_INSTRUCTIONS_PATH_KEYS: Record<string, string> = { const DEFAULT_INSTRUCTIONS_PATH_KEYS: Record<string, string> = {
@@ -170,6 +174,25 @@ export function agentRoutes(db: Db) {
return trimmed.length > 0 ? trimmed : null; return trimmed.length > 0 ? trimmed : null;
} }
function applyCreateDefaultsByAdapterType(
adapterType: string | null | undefined,
adapterConfig: Record<string, unknown>,
): Record<string, unknown> {
if (adapterType !== "codex_local") return adapterConfig;
const next = { ...adapterConfig };
if (!asNonEmptyString(next.model)) {
next.model = DEFAULT_CODEX_LOCAL_MODEL;
}
const hasBypassFlag =
typeof next.dangerouslyBypassApprovalsAndSandbox === "boolean" ||
typeof next.dangerouslyBypassSandbox === "boolean";
if (!hasBypassFlag) {
next.dangerouslyBypassApprovalsAndSandbox = DEFAULT_CODEX_LOCAL_BYPASS_APPROVALS_AND_SANDBOX;
}
return next;
}
function resolveInstructionsFilePath(candidatePath: string, adapterConfig: Record<string, unknown>) { function resolveInstructionsFilePath(candidatePath: string, adapterConfig: Record<string, unknown>) {
const trimmed = candidatePath.trim(); const trimmed = candidatePath.trim();
if (path.isAbsolute(trimmed)) return trimmed; if (path.isAbsolute(trimmed)) return trimmed;
@@ -546,9 +569,13 @@ export function agentRoutes(db: Db) {
await assertCanCreateAgentsForCompany(req, companyId); await assertCanCreateAgentsForCompany(req, companyId);
const sourceIssueIds = parseSourceIssueIds(req.body); const sourceIssueIds = parseSourceIssueIds(req.body);
const { sourceIssueId: _sourceIssueId, sourceIssueIds: _sourceIssueIds, ...hireInput } = req.body; const { sourceIssueId: _sourceIssueId, sourceIssueIds: _sourceIssueIds, ...hireInput } = req.body;
const requestedAdapterConfig = applyCreateDefaultsByAdapterType(
hireInput.adapterType,
((hireInput.adapterConfig ?? {}) as Record<string, unknown>),
);
const normalizedAdapterConfig = await secretsSvc.normalizeAdapterConfigForPersistence( const normalizedAdapterConfig = await secretsSvc.normalizeAdapterConfigForPersistence(
companyId, companyId,
((hireInput.adapterConfig ?? {}) as Record<string, unknown>), requestedAdapterConfig,
{ strictMode: strictSecretsMode }, { strictMode: strictSecretsMode },
); );
const normalizedHireInput = { const normalizedHireInput = {
@@ -677,9 +704,13 @@ export function agentRoutes(db: Db) {
assertBoard(req); assertBoard(req);
} }
const requestedAdapterConfig = applyCreateDefaultsByAdapterType(
req.body.adapterType,
((req.body.adapterConfig ?? {}) as Record<string, unknown>),
);
const normalizedAdapterConfig = await secretsSvc.normalizeAdapterConfigForPersistence( const normalizedAdapterConfig = await secretsSvc.normalizeAdapterConfigForPersistence(
companyId, companyId,
((req.body.adapterConfig ?? {}) as Record<string, unknown>), requestedAdapterConfig,
{ strictMode: strictSecretsMode }, { strictMode: strictSecretsMode },
); );

View File

@@ -11,6 +11,10 @@ import type { AdapterModel } from "../api/agents";
import { agentsApi } from "../api/agents"; import { agentsApi } from "../api/agents";
import { secretsApi } from "../api/secrets"; import { secretsApi } from "../api/secrets";
import { assetsApi } from "../api/assets"; import { assetsApi } from "../api/assets";
import {
DEFAULT_CODEX_LOCAL_BYPASS_APPROVALS_AND_SANDBOX,
DEFAULT_CODEX_LOCAL_MODEL,
} from "@paperclipai/adapter-codex-local";
import { import {
Popover, Popover,
PopoverContent, PopoverContent,
@@ -433,7 +437,13 @@ export function AgentConfigForm(props: AgentConfigFormProps) {
if (isCreate) { if (isCreate) {
// Reset all adapter-specific fields to defaults when switching adapter type // Reset all adapter-specific fields to defaults when switching adapter type
const { adapterType: _at, ...defaults } = defaultCreateValues; const { adapterType: _at, ...defaults } = defaultCreateValues;
set!({ ...defaults, adapterType: t }); const nextValues: CreateConfigValues = { ...defaults, adapterType: t };
if (t === "codex_local") {
nextValues.model = DEFAULT_CODEX_LOCAL_MODEL;
nextValues.dangerouslyBypassSandbox =
DEFAULT_CODEX_LOCAL_BYPASS_APPROVALS_AND_SANDBOX;
}
set!(nextValues);
} else { } else {
// Clear all adapter config and explicitly blank out model + both effort keys // Clear all adapter config and explicitly blank out model + both effort keys
// so the old adapter's values don't bleed through via eff() // so the old adapter's values don't bleed through via eff()
@@ -441,9 +451,15 @@ export function AgentConfigForm(props: AgentConfigFormProps) {
...prev, ...prev,
adapterType: t, adapterType: t,
adapterConfig: { adapterConfig: {
model: "", model: t === "codex_local" ? DEFAULT_CODEX_LOCAL_MODEL : "",
effort: "", effort: "",
modelReasoningEffort: "", modelReasoningEffort: "",
...(t === "codex_local"
? {
dangerouslyBypassApprovalsAndSandbox:
DEFAULT_CODEX_LOCAL_BYPASS_APPROVALS_AND_SANDBOX,
}
: {}),
}, },
})); }));
} }

View File

@@ -18,6 +18,10 @@ import { Button } from "@/components/ui/button";
import { cn } from "../lib/utils"; import { cn } from "../lib/utils";
import { getUIAdapter } from "../adapters"; import { getUIAdapter } from "../adapters";
import { defaultCreateValues } from "./agent-config-defaults"; import { defaultCreateValues } from "./agent-config-defaults";
import {
DEFAULT_CODEX_LOCAL_BYPASS_APPROVALS_AND_SANDBOX,
DEFAULT_CODEX_LOCAL_MODEL,
} from "@paperclipai/adapter-codex-local";
import { AsciiArtAnimation } from "./AsciiArtAnimation"; import { AsciiArtAnimation } from "./AsciiArtAnimation";
import { ChoosePathButton } from "./PathInstructionsModal"; import { ChoosePathButton } from "./PathInstructionsModal";
import { HintIcon } from "./agent-config-primitives"; import { HintIcon } from "./agent-config-primitives";
@@ -156,11 +160,15 @@ export function OnboardingWizard() {
...defaultCreateValues, ...defaultCreateValues,
adapterType, adapterType,
cwd, cwd,
model, model: adapterType === "codex_local" ? model || DEFAULT_CODEX_LOCAL_MODEL : model,
command, command,
args, args,
url, url,
dangerouslySkipPermissions: adapterType === "claude_local", dangerouslySkipPermissions: adapterType === "claude_local",
dangerouslyBypassSandbox:
adapterType === "codex_local"
? DEFAULT_CODEX_LOCAL_BYPASS_APPROVALS_AND_SANDBOX
: defaultCreateValues.dangerouslyBypassSandbox,
}); });
} }
@@ -456,7 +464,12 @@ export function OnboardingWizard() {
: "border-border hover:bg-accent/50" : "border-border hover:bg-accent/50"
)} )}
onClick={() => { onClick={() => {
if (!opt.comingSoon) setAdapterType(opt.value as AdapterType); if (opt.comingSoon) return;
const nextType = opt.value as AdapterType;
setAdapterType(nextType);
if (nextType === "codex_local" && !model) {
setModel(DEFAULT_CODEX_LOCAL_MODEL);
}
}} }}
> >
<opt.icon className="h-4 w-4" /> <opt.icon className="h-4 w-4" />