Hide deprecated agent working directory by default

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
dotta
2026-03-20 07:04:41 -05:00
parent 4ab3e4f7ab
commit bf5cfaaeab
5 changed files with 64 additions and 28 deletions

View File

@@ -44,6 +44,7 @@ import { ClaudeLocalAdvancedFields } from "../adapters/claude-local/config-field
import { MarkdownEditor } from "./MarkdownEditor";
import { ChoosePathButton } from "./PathInstructionsModal";
import { OpenCodeLogoIcon } from "./OpenCodeLogoIcon";
import { shouldShowLegacyWorkingDirectoryField } from "../lib/legacy-agent-config";
/* ---- Create mode values ---- */
@@ -297,6 +298,8 @@ export function AgentConfigForm(props: AgentConfigFormProps) {
adapterType === "opencode_local" ||
adapterType === "pi_local" ||
adapterType === "cursor";
const showLegacyWorkingDirectoryField =
isLocal && shouldShowLegacyWorkingDirectoryField({ isCreate, adapterConfig: config });
const uiAdapter = useMemo(() => getUIAdapter(adapterType), [adapterType]);
// Fetch adapter models for the effective adapter type
@@ -590,8 +593,8 @@ export function AgentConfigForm(props: AgentConfigFormProps) {
)}
{/* Working directory */}
{isLocal && (
<Field label="Working directory" hint={help.cwd}>
{showLegacyWorkingDirectoryField && (
<Field label="Working directory (deprecated)" hint={help.cwd}>
<div className="flex items-center gap-2 rounded-md border border-border px-2.5 py-1.5">
<FolderOpen className="h-3.5 w-3.5 text-muted-foreground shrink-0" />
<DraftInput

View File

@@ -32,8 +32,6 @@ import { DEFAULT_CURSOR_LOCAL_MODEL } from "@paperclipai/adapter-cursor-local";
import { DEFAULT_GEMINI_LOCAL_MODEL } from "@paperclipai/adapter-gemini-local";
import { resolveRouteOnboardingOptions } from "../lib/onboarding-route";
import { AsciiArtAnimation } from "./AsciiArtAnimation";
import { ChoosePathButton } from "./PathInstructionsModal";
import { HintIcon } from "./agent-config-primitives";
import { OpenCodeLogoIcon } from "./OpenCodeLogoIcon";
import {
Building2,
@@ -49,7 +47,6 @@ import {
MousePointer2,
Check,
Loader2,
FolderOpen,
ChevronDown,
X
} from "lucide-react";
@@ -113,7 +110,6 @@ export function OnboardingWizard() {
// Step 2
const [agentName, setAgentName] = useState("CEO");
const [adapterType, setAdapterType] = useState<AdapterType>("claude_local");
const [cwd, setCwd] = useState("");
const [model, setModel] = useState("");
const [command, setCommand] = useState("");
const [args, setArgs] = useState("");
@@ -217,7 +213,7 @@ export function OnboardingWizard() {
if (step !== 2) return;
setAdapterEnvResult(null);
setAdapterEnvError(null);
}, [step, adapterType, cwd, model, command, args, url]);
}, [step, adapterType, model, command, args, url]);
const selectedModel = (adapterModels ?? []).find((m) => m.id === model);
const hasAnthropicApiKeyOverrideCheck =
@@ -273,7 +269,6 @@ export function OnboardingWizard() {
setCompanyGoal("");
setAgentName("CEO");
setAdapterType("claude_local");
setCwd("");
setModel("");
setCommand("");
setArgs("");
@@ -301,7 +296,6 @@ export function OnboardingWizard() {
const config = adapter.buildAdapterConfig({
...defaultCreateValues,
adapterType,
cwd,
model:
adapterType === "codex_local"
? model || DEFAULT_CODEX_LOCAL_MODEL
@@ -874,24 +868,6 @@ export function OnboardingWizard() {
adapterType === "pi_local" ||
adapterType === "cursor") && (
<div className="space-y-3">
<div>
<div className="flex items-center gap-1.5 mb-1">
<label className="text-xs text-muted-foreground">
Working directory
</label>
<HintIcon text="Paperclip works best if you create a new folder for your agents to keep their memories and stay organized. Create a new folder and put the path here." />
</div>
<div className="flex items-center gap-2 rounded-md border border-border px-2.5 py-1.5">
<FolderOpen className="h-3.5 w-3.5 text-muted-foreground shrink-0" />
<input
className="w-full bg-transparent outline-none text-sm font-mono placeholder:text-muted-foreground/50"
placeholder="/path/to/project"
value={cwd}
onChange={(e) => setCwd(e.target.value)}
/>
<ChoosePathButton />
</div>
</div>
<div>
<label className="text-xs text-muted-foreground mb-1 block">
Model

View File

@@ -25,7 +25,7 @@ export const help: Record<string, string> = {
reportsTo: "The agent this one reports to in the org hierarchy.",
capabilities: "Describes what this agent can do. Shown in the org chart and used for task routing.",
adapterType: "How this agent runs: local CLI (Claude/Codex/OpenCode), OpenClaw Gateway, spawned process, or generic HTTP webhook.",
cwd: "Default working directory fallback for local adapters. Use an absolute path on the machine running Paperclip.",
cwd: "Deprecated legacy working directory fallback for local adapters. Existing agents may still carry this value, but new configurations should use project workspaces instead.",
promptTemplate: "Sent on every heartbeat. Keep this small and dynamic. Use it for current-task framing, not large static instructions. Supports {{ agent.id }}, {{ agent.name }}, {{ agent.role }} and other template variables.",
model: "Override the default model used by the adapter.",
thinkingEffort: "Control model reasoning depth. Supported values vary by adapter/model.",

View File

@@ -0,0 +1,40 @@
import { describe, expect, it } from "vitest";
import {
hasLegacyWorkingDirectory,
shouldShowLegacyWorkingDirectoryField,
} from "./legacy-agent-config";
describe("legacy agent config helpers", () => {
it("treats non-empty cwd values as legacy working directories", () => {
expect(hasLegacyWorkingDirectory("/tmp/workspace")).toBe(true);
expect(hasLegacyWorkingDirectory(" /tmp/workspace ")).toBe(true);
});
it("ignores nullish and blank cwd values", () => {
expect(hasLegacyWorkingDirectory("")).toBe(false);
expect(hasLegacyWorkingDirectory(" ")).toBe(false);
expect(hasLegacyWorkingDirectory(null)).toBe(false);
expect(hasLegacyWorkingDirectory(undefined)).toBe(false);
});
it("shows the deprecated field only for edit forms with an existing cwd", () => {
expect(
shouldShowLegacyWorkingDirectoryField({
isCreate: true,
adapterConfig: { cwd: "/tmp/workspace" },
}),
).toBe(false);
expect(
shouldShowLegacyWorkingDirectoryField({
isCreate: false,
adapterConfig: { cwd: "" },
}),
).toBe(false);
expect(
shouldShowLegacyWorkingDirectoryField({
isCreate: false,
adapterConfig: { cwd: "/tmp/workspace" },
}),
).toBe(true);
});
});

View File

@@ -0,0 +1,17 @@
function asNonEmptyString(value: unknown): string | null {
if (typeof value !== "string") return null;
const trimmed = value.trim();
return trimmed.length > 0 ? trimmed : null;
}
export function hasLegacyWorkingDirectory(value: unknown): boolean {
return asNonEmptyString(value) !== null;
}
export function shouldShowLegacyWorkingDirectoryField(input: {
isCreate: boolean;
adapterConfig: Record<string, unknown> | null | undefined;
}): boolean {
if (input.isCreate) return false;
return hasLegacyWorkingDirectory(input.adapterConfig?.cwd);
}