Skip to content
This repository was archived by the owner on Aug 6, 2026. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 25 additions & 3 deletions packages/ui/src/features/permissions/PlanApprovalSelector.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,27 +53,49 @@ function renderSelector(options: PermissionOption[]) {
describe("PlanApprovalSelector", () => {
beforeEach(() => {
// Reset the remembered choice so tests don't leak through persistence.
useSettingsStore.setState({ lastPlanApprovalMode: null });
useSettingsStore.setState({
lastPlanApprovalMode: null,
defaultPlanApprovalMode: "last_used",
});
});

it.each([
{
label: "there is no prior or remembered mode",
lastMode: null,
defaultMode: "last_used",
options: [AUTO, ACCEPT_EDITS, DEFAULT_MODE, REJECT],
expected: "auto",
},
{
label: "a last choice is remembered",
lastMode: "acceptEdits",
defaultMode: "last_used",
options: [AUTO, ACCEPT_EDITS, DEFAULT_MODE],
expected: "acceptEdits",
},
{
label: "a pinned default mode overrides the remembered choice",
lastMode: "acceptEdits",
defaultMode: "auto",
options: [AUTO, ACCEPT_EDITS, DEFAULT_MODE],
expected: "auto",
},
{
label: "the pinned default mode isn't offered",
lastMode: "acceptEdits",
defaultMode: "bypassPermissions",
options: [AUTO, ACCEPT_EDITS, DEFAULT_MODE],
expected: "acceptEdits",
},
] as const)(
"defaults to $expected when $label",
async ({ lastMode, options, expected }) => {
async ({ lastMode, defaultMode, options, expected }) => {
const user = userEvent.setup();
useSettingsStore.setState({ lastPlanApprovalMode: lastMode });
useSettingsStore.setState({
lastPlanApprovalMode: lastMode,
defaultPlanApprovalMode: defaultMode,
});
const { onSelect } = renderSelector([...options]);

await user.click(screen.getByText("Approve and proceed"));
Expand Down
57 changes: 42 additions & 15 deletions packages/ui/src/features/permissions/PlanApprovalSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ import type {
import type { ExecutionMode } from "@posthog/shared";
import { ModeSelector } from "@posthog/ui/features/message-editor/components/ModeSelector";
import { MODE_LABELS } from "@posthog/ui/features/sessions/modeStyles";
import { useSettingsStore } from "@posthog/ui/features/settings/settingsStore";
import {
type DefaultPlanApprovalMode,
useSettingsStore,
} from "@posthog/ui/features/settings/settingsStore";
import {
ActionSelector,
InlineEditableText,
Expand All @@ -32,6 +35,32 @@ function hasCustomInput(option: PermissionOption): boolean {
);
}

// Resolution order: a pinned default mode (if configured and offered), else
// the mode last approved with (remembered preference), then "auto", then
// manual-approve, then any single-use mode, then the first.
function resolveInitialPlanApprovalMode(
approveOptions: PermissionOption[],
defaultApprovalMode: DefaultPlanApprovalMode,
lastApprovalMode: ExecutionMode | null,
): string | undefined {
const has = (id: string) => approveOptions.some((o) => o.optionId === id);

if (defaultApprovalMode !== "last_used" && has(defaultApprovalMode)) {
return defaultApprovalMode;
}
if (lastApprovalMode && has(lastApprovalMode)) {
return lastApprovalMode;
}
if (has("auto")) {
return "auto";
}
return (
approveOptions.find((o) => o.optionId === "default")?.optionId ??
approveOptions.find((o) => o.kind === "allow_once")?.optionId ??
approveOptions[0]?.optionId
);
}

// Don't steal focus from an interactive element in a different grid cell
// (multi-task view). Mirrors the guard in useActionSelectorState.
function isInteractiveElementInDifferentCell(
Expand Down Expand Up @@ -77,21 +106,19 @@ export function PlanApprovalSelector({
const setLastApprovalMode = useSettingsStore(
(s) => s.setLastPlanApprovalMode,
);
const defaultApprovalMode = useSettingsStore(
(s) => s.defaultPlanApprovalMode,
);

// Resolution order: the mode last approved with (remembered preference),
// then "auto", then manual-approve, then any single-use mode, then the first.
const initialMode = useMemo(() => {
const has = (id: string) => approveOptions.some((o) => o.optionId === id);
return (
(lastApprovalMode && has(lastApprovalMode)
? lastApprovalMode
: undefined) ??
(has("auto") ? "auto" : undefined) ??
approveOptions.find((o) => o.optionId === "default")?.optionId ??
approveOptions.find((o) => o.kind === "allow_once")?.optionId ??
approveOptions[0]?.optionId
);
}, [approveOptions, lastApprovalMode]);
const initialMode = useMemo(
() =>
resolveInitialPlanApprovalMode(
approveOptions,
defaultApprovalMode,
lastApprovalMode,
),
[approveOptions, lastApprovalMode, defaultApprovalMode],
);
Comment on lines +113 to +121

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Resolved Mode Leaves State Stale

When persisted settings hydrate after mount, or the mounted selector receives a new approval with different options, initialMode recomputes but the following useState(initialMode) retains the old selection. Approving can therefore submit the pre-hydration mode or a mode that is not offered by the current approval request.

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/ui/src/features/permissions/PlanApprovalSelector.tsx
Line: 113-121

Comment:
**Resolved Mode Leaves State Stale**

When persisted settings hydrate after mount, or the mounted selector receives a new approval with different options, `initialMode` recomputes but the following `useState(initialMode)` retains the old selection. Approving can therefore submit the pre-hydration mode or a mode that is not offered by the current approval request.

How can I resolve this? If you propose a fix, please make it concise.


const [selectedMode, setSelectedMode] = useState(initialMode);
const [selectedIndex, setSelectedIndex] = useState(0);
Expand Down
12 changes: 12 additions & 0 deletions packages/ui/src/features/sessions/modeStyles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
Robot,
ShieldCheck,
} from "@phosphor-icons/react";
import type { ExecutionMode } from "@posthog/shared";

export interface ModeStyle {
icon: React.ReactNode;
Expand Down Expand Up @@ -66,3 +67,14 @@ export const MODE_LABELS: Record<string, string> = {
"read-only": "Read-only",
"full-access": "Full access",
};

// Concrete modes `buildExitPlanModePermissionOptions` (packages/agent) can
// offer when a plan is approved, excluding "plan" itself. Kept here, next to
// the label map settings/approval UI already share, so both pick modes from
// one list.
export const PLAN_APPROVAL_MODES: readonly ExecutionMode[] = [
"auto",
"default",
"acceptEdits",
"bypassPermissions",
];
Comment on lines +70 to +80

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PLAN_APPROVAL_MODES hardcodes Claude-only mode ids, breaking the pinned setting for the Codex adapter

should_fix bug

Why we think it's a valid issue
  • Checked: PR-head PLAN_APPROVAL_MODES (modeStyles.tsx:75-80) and its MODE_LABELS/MODE_STYLES entries for full-access (lines 42-43, 68); the pinned branch if (defaultApprovalMode !== "last_used" && has(defaultApprovalMode)) in resolveInitialPlanApprovalMode (PlanApprovalSelector.tsx:48-50); Claude's buildExitPlanModePermissionOptions (permission-options.ts:107-136); and Codex's requestPlanImplementation (codex-app-server-agent.ts:1063-1099).
  • Found: Codex offers exactly auto plus (ALLOW_BYPASS-gated) full-access (codex-app-server-agent.ts:1078-1092) — never default/acceptEdits/bypassPermissions. So for a Codex session has() is false for three of the four picklist entries, and the pinned branch falls through to the last-used/auto chain — the pin silently no-ops. full-access is a valid ExecutionMode with existing label/style entries but is absent from PLAN_APPROVAL_MODES, so Codex's one meaningful elevated mode is unpinnable. The picker is rendered globally in General settings (unconditional PLAN_APPROVAL_MODES.map), not adapter-scoped, so Codex-only users see dead options.
  • Impact: A real, reproducible defect directly from this PR: concrete trigger (Codex session + pin any of three Claude-only modes → no-op; or want to pin full-access → impossible) and concrete consequence (explicit user preference silently ignored; relevant mode unreachable). Contradicts the PR's stated Codex coverage. Clears the keep bar — not speculative, not style, premise verified.
  • Priority: Lowering must_fix → should_fix. It fails safe: the no-op degrades to the exact prior last-used/auto behavior (no dangerous or data-losing action), the default last_used is backward compatible so untouched users are unaffected, and only Codex users who actively select a Claude-only mode are hit. A completeness gap in a new convenience feature, not a regression, crash, security, or data-loss bug — meaningful to fix but not release-blocking.
Issue description

PLAN_APPROVAL_MODES is ["auto", "default", "acceptEdits", "bypassPermissions"], and GeneralSettings.tsx uses exactly this list to populate the new "Mode after plan approval" picker. But the two adapters that route through PlanApprovalSelector offer completely different approve-option sets: Claude's buildExitPlanModePermissionOptions (packages/agent/src/adapters/claude/permissions/permission-options.ts) offers bypassPermissions/auto/acceptEdits/default, while Codex's requestPlanImplementation (packages/agent/src/adapters/codex-app-server/codex-app-server-agent.ts:1063-1099) only ever offers auto and full-access (gated by ALLOW_BYPASS) — never default, acceptEdits, or bypassPermissions. In resolveInitialPlanApprovalMode (PlanApprovalSelector.tsx), the pinned-mode branch is if (defaultApprovalMode !== "last_used" && has(defaultApprovalMode)). For a Codex session, has() will be false for default/acceptEdits/bypassPermissions (they're never in approveOptions), so pinning to any of those three Settings choices silently falls through to the old last-used/auto fallback chain — a no-op that contradicts what the user configured. Worse, Codex's actual bypass-equivalent mode, "full-access", isn't in PLAN_APPROVAL_MODES at all, so a Codex user can never pin the one mode that would be meaningful for them, even though "full-access" is a valid ExecutionMode (packages/shared/src/exec-types.ts) and already has an entry in this same file's MODE_LABELS/MODE_STYLES maps. This directly contradicts the PR's stated claim that "both the Claude and Codex adapters route their plan-approval prompt through this same shared UI component, [so] the change covers both." In practice, for Codex users the setting only works for the "auto" choice; the other three choices are dead options and the relevant elevated-trust mode is unreachable.

Suggested fix

Make the offered pin choices adapter-agnostic and derived from what can actually be offered, e.g. include "full-access" alongside the Claude modes (PLAN_APPROVAL_MODES = ["auto", "default", "acceptEdits", "bypassPermissions", "full-access"]), or better, have GeneralSettings.tsx/resolveInitialPlanApprovalMode only surface/select from modes that are relevant per-adapter. At minimum, add "full-access" to the list so Codex users have a working pinned option, and document (or filter) that default/acceptEdits/bypassPermissions are Claude-only and will silently no-op under Codex.

Prompt to fix with AI (copy-paste)
## Context
@packages/ui/src/features/sessions/modeStyles.tsx#L70-80

<issue_description>
`PLAN_APPROVAL_MODES` is `["auto", "default", "acceptEdits", "bypassPermissions"]`, and `GeneralSettings.tsx` uses exactly this list to populate the new "Mode after plan approval" picker. But the two adapters that route through `PlanApprovalSelector` offer completely different approve-option sets: Claude's `buildExitPlanModePermissionOptions` (packages/agent/src/adapters/claude/permissions/permission-options.ts) offers `bypassPermissions`/`auto`/`acceptEdits`/`default`, while Codex's `requestPlanImplementation` (packages/agent/src/adapters/codex-app-server/codex-app-server-agent.ts:1063-1099) only ever offers `auto` and `full-access` (gated by `ALLOW_BYPASS`) — never `default`, `acceptEdits`, or `bypassPermissions`. In `resolveInitialPlanApprovalMode` (PlanApprovalSelector.tsx), the pinned-mode branch is `if (defaultApprovalMode !== "last_used" && has(defaultApprovalMode))`. For a Codex session, `has()` will be false for `default`/`acceptEdits`/`bypassPermissions` (they're never in `approveOptions`), so pinning to any of those three Settings choices silently falls through to the old last-used/auto fallback chain — a no-op that contradicts what the user configured. Worse, Codex's actual bypass-equivalent mode, `"full-access"`, isn't in `PLAN_APPROVAL_MODES` at all, so a Codex user can never pin the one mode that would be meaningful for them, even though `"full-access"` is a valid `ExecutionMode` (packages/shared/src/exec-types.ts) and already has an entry in this same file's `MODE_LABELS`/`MODE_STYLES` maps. This directly contradicts the PR's stated claim that "both the Claude and Codex adapters route their plan-approval prompt through this same shared UI component, [so] the change covers both." In practice, for Codex users the setting only works for the "auto" choice; the other three choices are dead options and the relevant elevated-trust mode is unreachable.
</issue_description>

<issue_validation>
- **Checked:** PR-head `PLAN_APPROVAL_MODES` (modeStyles.tsx:75-80) and its `MODE_LABELS`/`MODE_STYLES` entries for `full-access` (lines 42-43, 68); the pinned branch `if (defaultApprovalMode !== "last_used" && has(defaultApprovalMode))` in `resolveInitialPlanApprovalMode` (PlanApprovalSelector.tsx:48-50); Claude's `buildExitPlanModePermissionOptions` (permission-options.ts:107-136); and Codex's `requestPlanImplementation` (codex-app-server-agent.ts:1063-1099).
- **Found:** Codex offers exactly `auto` plus (ALLOW_BYPASS-gated) `full-access` (codex-app-server-agent.ts:1078-1092) — never `default`/`acceptEdits`/`bypassPermissions`. So for a Codex session `has()` is false for three of the four picklist entries, and the pinned branch falls through to the last-used/auto chain — the pin silently no-ops. `full-access` is a valid `ExecutionMode` with existing label/style entries but is absent from `PLAN_APPROVAL_MODES`, so Codex's one meaningful elevated mode is unpinnable. The picker is rendered globally in General settings (unconditional `PLAN_APPROVAL_MODES.map`), not adapter-scoped, so Codex-only users see dead options.
- **Impact:** A real, reproducible defect directly from this PR: concrete trigger (Codex session + pin any of three Claude-only modes → no-op; or want to pin `full-access` → impossible) and concrete consequence (explicit user preference silently ignored; relevant mode unreachable). Contradicts the PR's stated Codex coverage. Clears the keep bar — not speculative, not style, premise verified.
- **Priority:** Lowering must_fix → should_fix. It fails safe: the no-op degrades to the exact prior last-used/auto behavior (no dangerous or data-losing action), the default `last_used` is backward compatible so untouched users are unaffected, and only Codex users who actively select a Claude-only mode are hit. A completeness gap in a new convenience feature, not a regression, crash, security, or data-loss bug — meaningful to fix but not release-blocking.
</issue_validation>

## Task
Investigate the issue and solve it

<potential_solution>
Make the offered pin choices adapter-agnostic and derived from what can actually be offered, e.g. include `"full-access"` alongside the Claude modes (`PLAN_APPROVAL_MODES = ["auto", "default", "acceptEdits", "bypassPermissions", "full-access"]`), or better, have `GeneralSettings.tsx`/`resolveInitialPlanApprovalMode` only surface/select from modes that are relevant per-adapter. At minimum, add `"full-access"` to the list so Codex users have a working pinned option, and document (or filter) that `default`/`acceptEdits`/`bypassPermissions` are Claude-only and will silently no-op under Codex.
</potential_solution>

Comment on lines +75 to +80

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Codex Full Access Is Missing

Codex offers full-access after plan approval when bypass is allowed, but this list controls the new settings menu and omits that mode. Codex users can select Full access during approval but cannot pin it as their default.

Suggested change
export const PLAN_APPROVAL_MODES: readonly ExecutionMode[] = [
"auto",
"default",
"acceptEdits",
"bypassPermissions",
];
export const PLAN_APPROVAL_MODES: readonly ExecutionMode[] = [
"auto",
"default",
"acceptEdits",
"bypassPermissions",
"full-access",
];

Rule Used: When implementing new features, ensure that the UI... (source)

Learned From
PostHog/posthog#32595
PostHog/posthog#32677

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/ui/src/features/sessions/modeStyles.tsx
Line: 75-80

Comment:
**Codex Full Access Is Missing**

Codex offers `full-access` after plan approval when bypass is allowed, but this list controls the new settings menu and omits that mode. Codex users can select Full access during approval but cannot pin it as their default.

```suggestion
export const PLAN_APPROVAL_MODES: readonly ExecutionMode[] = [
  "auto",
  "default",
  "acceptEdits",
  "bypassPermissions",
  "full-access",
];
```

**Rule Used:** When implementing new features, ensure that the UI... ([source](https://app.greptile.com/posthog-org-19734/-/custom-context?memory=5d57f0af-0be1-44de-8885-055f27e2885f))

**Learned From**
[PostHog/posthog#32595](https://github.com/PostHog/posthog/pull/32595)
[PostHog/posthog#32677](https://github.com/PostHog/posthog/pull/32677)

How can I resolve this? If you propose a fix, please make it concise.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

44 changes: 44 additions & 0 deletions packages/ui/src/features/settings/sections/GeneralSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,16 @@ import {
COLLAPSE_MODE_OPTIONS,
type CollapseMode,
} from "@posthog/ui/features/sessions/components/new-thread/conversationThreadConfig";
import {
MODE_LABELS,
PLAN_APPROVAL_MODES,
} from "@posthog/ui/features/sessions/modeStyles";
import { SettingRow } from "@posthog/ui/features/settings/SettingRow";
import {
type AutoConvertLongText,
type DefaultInitialTaskMode,
type DefaultMessagingMode,
type DefaultPlanApprovalMode,
type DefaultReasoningEffort,
type DiffOpenMode,
type SendMessagesWith,
Expand Down Expand Up @@ -77,6 +82,7 @@ export function GeneralSettings() {
autoConvertLongText,
defaultInitialTaskMode,
defaultMessagingMode,
defaultPlanApprovalMode,
defaultReasoningEffort,
diffOpenMode,
sendMessagesWith,
Expand All @@ -87,6 +93,7 @@ export function GeneralSettings() {
setAutoConvertLongText,
setDefaultInitialTaskMode,
setDefaultMessagingMode,
setDefaultPlanApprovalMode,
setDefaultReasoningEffort,
setDiffOpenMode,
setSendMessagesWith,
Expand Down Expand Up @@ -146,6 +153,18 @@ export function GeneralSettings() {
[defaultInitialTaskMode, setDefaultInitialTaskMode],
);

const handleDefaultPlanApprovalModeChange = useCallback(
(value: DefaultPlanApprovalMode) => {
track(ANALYTICS_EVENTS.SETTING_CHANGED, {
setting_name: "default_plan_approval_mode",
new_value: value,
old_value: defaultPlanApprovalMode,
});
setDefaultPlanApprovalMode(value);
},
[defaultPlanApprovalMode, setDefaultPlanApprovalMode],
);

const handleDefaultMessagingModeChange = useCallback(
(value: DefaultMessagingMode) => {
track(ANALYTICS_EVENTS.SETTING_CHANGED, {
Expand Down Expand Up @@ -298,6 +317,31 @@ export function GeneralSettings() {
</Select.Root>
</SettingRow>

<SettingRow
label="Mode after plan approval"
description="Choose whether approving a plan always resumes in a specific mode, or remembers your last choice"
>
<Select.Root
value={defaultPlanApprovalMode}
onValueChange={(value) =>
handleDefaultPlanApprovalModeChange(
value as DefaultPlanApprovalMode,
)
}
size="1"
>
<Select.Trigger className="min-w-[100px]" />
<Select.Content>
<Select.Item value="last_used">Last used</Select.Item>
{PLAN_APPROVAL_MODES.map((mode) => (
<Select.Item key={mode} value={mode}>
{MODE_LABELS[mode]}
</Select.Item>
))}
</Select.Content>
</Select.Root>
</SettingRow>

<SettingRow
label="Default messaging mode"
description="Mode new sessions start in. Steer applies messages mid-turn. Queue holds them until the turn ends."
Expand Down
1 change: 1 addition & 0 deletions packages/ui/src/features/settings/settingsStore.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ describe("feature settingsStore cloud selections", () => {
["slotMachineMode", false, true],
["dismissibleUpdateBanners", false, true],
["showSidebarWorktrees", false, true],
["defaultPlanApprovalMode", "last_used", "auto"],
] as const)("rehydrates %s", async (field, initial, persisted) => {
getItem.mockResolvedValue(
JSON.stringify({ state: { [field]: persisted }, version: 0 }),
Expand Down
9 changes: 9 additions & 0 deletions packages/ui/src/features/settings/settingsStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export type LocalWorkspaceMode = "worktree" | "local";
export const DEFAULT_WORKSPACE_MODE: WorkspaceMode = "cloud";
export type AgentAdapter = Adapter;
export type DefaultInitialTaskMode = "plan" | "last_used";
export type DefaultPlanApprovalMode = ExecutionMode | "last_used";
export type DefaultMessagingMode = "queue" | "steer";
export type DefaultReasoningEffort =
| "low"
Expand Down Expand Up @@ -117,6 +118,9 @@ interface SettingsStore {
lastUsedInitialTaskMode: ExecutionMode;
// Mode last chosen when approving a plan; pre-selected on the next approval.
lastPlanApprovalMode: ExecutionMode | null;
// Pins plan approval to always pre-select a specific mode, overriding
// lastPlanApprovalMode; "last_used" preserves the old sticky behavior.
defaultPlanApprovalMode: DefaultPlanApprovalMode;
defaultReasoningEffort: DefaultReasoningEffort;
defaultMessagingMode: DefaultMessagingMode;
setDefaultMessagingMode: (mode: DefaultMessagingMode) => void;
Expand All @@ -140,6 +144,7 @@ interface SettingsStore {
setDefaultInitialTaskMode: (mode: DefaultInitialTaskMode) => void;
setLastUsedInitialTaskMode: (mode: ExecutionMode) => void;
setLastPlanApprovalMode: (mode: ExecutionMode) => void;
setDefaultPlanApprovalMode: (mode: DefaultPlanApprovalMode) => void;
setDefaultReasoningEffort: (effort: DefaultReasoningEffort) => void;

// Notifications
Expand Down Expand Up @@ -306,6 +311,7 @@ export const useSettingsStore = create<SettingsStore>()(
defaultInitialTaskMode: "plan",
lastUsedInitialTaskMode: "plan",
lastPlanApprovalMode: null,
defaultPlanApprovalMode: "last_used",
defaultReasoningEffort: "last_used",
defaultMessagingMode: "queue",
setDefaultRunMode: (mode) => set({ defaultRunMode: mode }),
Expand Down Expand Up @@ -348,6 +354,8 @@ export const useSettingsStore = create<SettingsStore>()(
setLastUsedInitialTaskMode: (mode) =>
set({ lastUsedInitialTaskMode: mode }),
setLastPlanApprovalMode: (mode) => set({ lastPlanApprovalMode: mode }),
setDefaultPlanApprovalMode: (mode) =>
set({ defaultPlanApprovalMode: mode }),
setDefaultReasoningEffort: (effort) =>
set({ defaultReasoningEffort: effort }),
setDefaultMessagingMode: (mode) => set({ defaultMessagingMode: mode }),
Expand Down Expand Up @@ -531,6 +539,7 @@ export const useSettingsStore = create<SettingsStore>()(
defaultInitialTaskMode: state.defaultInitialTaskMode,
lastUsedInitialTaskMode: state.lastUsedInitialTaskMode,
lastPlanApprovalMode: state.lastPlanApprovalMode,
defaultPlanApprovalMode: state.defaultPlanApprovalMode,
defaultReasoningEffort: state.defaultReasoningEffort,
defaultMessagingMode: state.defaultMessagingMode,

Expand Down
Loading