Skip to content

Commit ec4c65d

Browse files
claudesinelaw
authored andcommitted
feat(orchestrator): move Agent Command into Advanced (local); keep it inline for remote
The agent dropdown fills the command, so the raw 'Agent Command' text box is a power-user override. Fold it into the Advanced section on the local backend to declutter the common case; remote backends (no Advanced fold) keep it inline. The Auto mode / Start prompt controls still surface directly under the selector once an agent is picked. Picking the 'custom…' preset auto-expands Advanced and focuses the command field so it stays reachable. Note: does not include the floating pop-over dropdown — that's a separate host-native change (see scratchpad-host-dropdown-prompt.md).
1 parent 0341fb9 commit ec4c65d

1 file changed

Lines changed: 45 additions & 26 deletions

File tree

crates/fresh-editor/plugins/orchestrator.ts

Lines changed: 45 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5656,20 +5656,23 @@ function rebuildFormFocusCycle(): void {
56565656
if (form.backend === "local") {
56575657
const worktreeEnabled = form.projectPathIsGit !== false;
56585658
const effectiveCreateWorktree = worktreeEnabled && form.createWorktree;
5659-
cycle.push("project_path", "name", "cmd");
5660-
// Agent-specific controls sit between the command and the Advanced fold,
5659+
// The agent selector is a single stop after Session Name. The Agent Command
5660+
// field moved under the Advanced fold (a power-user override the dropdown
5661+
// fills), so it's a Tab stop there, not in the body.
5662+
cycle.push("project_path", "name", "agent_dropdown");
5663+
// Agent-specific controls sit between the selector and the Advanced fold,
56615664
// matching `agentOptionsFields`' render order (Auto mode, then Start prompt).
5662-
// "Teach Fresh CLI" moved under Advanced, so it's a Tab stop there, not here.
56635665
const agent = activeAgentEntry();
56645666
if (agent?.auto) cycle.push("auto_mode");
56655667
if (agent?.prompt) cycle.push("start_prompt");
56665668
// The "Advanced…" header is always a Tab stop; its folded fields join the
5667-
// cycle only while the section is expanded, in render order: Teach Fresh
5668-
// CLI, then worktree, then "Checkout branch" (a stop on any git path — it
5669-
// drives the in-place checkout when no worktree is created), then "New
5670-
// branch name" (only when cutting a worktree).
5669+
// cycle only while expanded, in render order: Agent Command, Teach Fresh
5670+
// CLI, worktree, "Checkout branch" (a stop on any git path — it drives the
5671+
// in-place checkout when no worktree is created), then "New branch name"
5672+
// (only when cutting a worktree).
56715673
cycle.push("advanced_toggle");
56725674
if (form.advancedExpanded) {
5675+
cycle.push("cmd");
56735676
if (agent?.systemPrompt) cycle.push("teach_fresh_cli");
56745677
if (worktreeEnabled) cycle.push("worktree");
56755678
if (worktreeEnabled) cycle.push("branch");
@@ -5686,10 +5689,10 @@ function rebuildFormFocusCycle(): void {
56865689
}
56875690
cycle.push("name", "cmd");
56885691
}
5689-
// The agent selector is a single dropdown Tab stop just before the Agent
5690-
// Command field (←/→ or ↑/↓ cycles the options), present for every backend.
5692+
// On remote backends the agent selector sits just before the (still-inline)
5693+
// Agent Command field. Local already placed `agent_dropdown` explicitly.
56915694
const cmdIdx = cycle.indexOf("cmd");
5692-
if (cmdIdx >= 0) {
5695+
if (cmdIdx >= 0 && !cycle.includes("agent_dropdown")) {
56935696
cycle.splice(cmdIdx, 0, "agent_dropdown");
56945697
}
56955698
cycle.push("create-visit", "create-bg", "cancel");
@@ -6084,7 +6087,10 @@ function activeAgentPresetKey(): string {
60846087
function applyAgentPreset(p: AgentPreset): void {
60856088
if (!form) return;
60866089
if (p.custom) {
6087-
// Hand focus to the free-text field so the user can type a command.
6090+
// Hand focus to the free-text command field so the user can type. On local
6091+
// that field lives under Advanced, so expand the fold first; otherwise the
6092+
// `cmd` key isn't in the focus cycle and the setFocusKey would be dropped.
6093+
if (form.backend === "local") form.advancedExpanded = true;
60886094
// Focus must be set *after* the re-render — re-mounting the spec resets
60896095
// host focus, which would otherwise clobber the setFocusKey.
60906096
renderForm();
@@ -6553,6 +6559,27 @@ function agentPresetRow(): WidgetSpec {
65536559
// remote backends don't route through `resolveAgentLaunch` — and adapt to the
65546560
// resolved agent: a bare terminal / unknown command shows neither, opencode
65556561
// shows only the prompt (no auto flag), etc.
6562+
// "Agent Command" text input — the raw command the workspace launches. The
6563+
// agent dropdown fills it, so it's a power-user override: folded into Advanced
6564+
// on the local backend, shown inline on remote backends (no Advanced fold).
6565+
function cmdField(): WidgetSpec {
6566+
return labeledSection({
6567+
label: editor.t("form.agent_command"),
6568+
child: text({
6569+
value: form!.cmd.value,
6570+
cursorByte: form!.cmd.cursor,
6571+
// Clearing the field falls back to the backend default: a bare local
6572+
// terminal (the host resolves `$SHELL`), or — for SSH — letting ssh
6573+
// spawn the remote login shell. The placeholder names that default.
6574+
placeholder: form!.backend === "ssh"
6575+
? editor.t("form.cmd_placeholder_ssh")
6576+
: editor.t("form.agent_terminal"),
6577+
fullWidth: true,
6578+
key: "cmd",
6579+
}),
6580+
});
6581+
}
6582+
65566583
function agentOptionsFields(): WidgetSpec[] {
65576584
if (!form || form.backend !== "local") return [];
65586585
const entry = activeAgentEntry();
@@ -6647,6 +6674,10 @@ function advancedSection(): WidgetSpec[] {
66476674
const effectiveCreateWorktree = worktreeEnabled && form.createWorktree;
66486675
const fields: WidgetSpec[] = [header];
66496676

6677+
// "Agent Command" — the raw launch command. The agent dropdown fills it, so
6678+
// it lives here as a power-user override rather than cluttering the body.
6679+
fields.push(cmdField());
6680+
66506681
// "Teach Fresh CLI" — enabled by default, but folded away here so it doesn't
66516682
// clutter the common case. Only meaningful for an agent with a systemPrompt
66526683
// injection strategy (a bare terminal / unknown command can't be "taught").
@@ -7017,21 +7048,9 @@ function buildFormSpec(): WidgetSpec {
70177048
}),
70187049
}),
70197050
agentPresetRow(),
7020-
labeledSection({
7021-
label: editor.t("form.agent_command"),
7022-
child: text({
7023-
value: form.cmd.value,
7024-
cursorByte: form.cmd.cursor,
7025-
// Clearing the field falls back to the backend default: a bare local
7026-
// terminal (the host resolves `$SHELL`), or — for SSH — letting ssh
7027-
// spawn the remote login shell. The placeholder names that default.
7028-
placeholder: form.backend === "ssh"
7029-
? editor.t("form.cmd_placeholder_ssh")
7030-
: editor.t("form.agent_terminal"),
7031-
fullWidth: true,
7032-
key: "cmd",
7033-
}),
7034-
}),
7051+
// On remote backends the command box stays inline (no Advanced fold to hold
7052+
// it); on local it moves into Advanced (appended in `advancedSection`).
7053+
...(form.backend === "local" ? [] : [cmdField()]),
70357054
// Agent-specific controls (Auto mode / Start prompt), adaptive to the
70367055
// resolved agent. Empty for a bare terminal / unknown command.
70377056
...agentOptionsFields(),

0 commit comments

Comments
 (0)