From e25dd9861cdb343b5483830aee1cd84d0d5e9a0f Mon Sep 17 00:00:00 2001 From: Zero Liu Date: Thu, 28 May 2026 15:33:44 -0700 Subject: [PATCH] refactor(agent-mode): remove "Enable Agent Mode" toggle Agent Mode is always on now (still desktop-only, since it requires subprocess support). Drop the persisted `agentMode.enabled` flag and the master toggle from settings, make `isAgentModeEnabled()` platform-only, and clean up the now-dead toggle-reactive wiring (ribbon refresh, settings-driven command re-registration). Co-Authored-By: Claude Opus 4.8 (1M context) --- src/agentMode/index.ts | 17 +++++----- src/commands/index.ts | 13 +++----- src/constants.ts | 1 - src/main.ts | 21 +----------- src/settings/model.test.ts | 1 - src/settings/model.ts | 3 -- src/settings/v2/components/AgentSettings.tsx | 35 ++++++-------------- 7 files changed, 24 insertions(+), 67 deletions(-) diff --git a/src/agentMode/index.ts b/src/agentMode/index.ts index 4e58a7d2..5c55e9c6 100644 --- a/src/agentMode/index.ts +++ b/src/agentMode/index.ts @@ -1,7 +1,7 @@ import { type App, Platform } from "obsidian"; import type CopilotPlugin from "@/main"; import { logError } from "@/logger"; -import { type CopilotSettings, getSettings, useSettingsValue } from "@/settings/model"; +import { getSettings } from "@/settings/model"; import { backendRegistry, listBackendDescriptors } from "./backends/registry"; import { AgentChatPersistenceManager } from "./session/AgentChatPersistenceManager"; import { AgentModelPreloader } from "./session/AgentModelPreloader"; @@ -51,17 +51,16 @@ export { SkillManager, SkillsSettings, useManagedSkills } from "./skills"; export type { Skill } from "./skills"; /** - * True when Agent Mode is enabled and the platform supports it. Agent Mode - * requires subprocess support, so this is always false on mobile regardless - * of the persisted `enabled` flag (which may have been synced from desktop). + * True when the platform supports Agent Mode. Agent Mode is always on, but + * requires subprocess support, so this is always false on mobile. */ -export function isAgentModeEnabled(settings: CopilotSettings = getSettings()): boolean { - return !Platform.isMobile && !!settings.agentMode?.enabled; +export function isAgentModeEnabled(): boolean { + return !Platform.isMobile; } -/** React hook variant — re-renders when the setting or platform-derived value changes. */ +/** Hook variant for symmetry with other settings-derived hooks. */ export function useIsAgentModeEnabled(): boolean { - return isAgentModeEnabled(useSettingsValue()); + return isAgentModeEnabled(); } /** @@ -159,7 +158,7 @@ export function createAgentSessionManager(app: App, plugin: CopilotPlugin): Agen } const settings = getSettings(); - if (!isAgentModeEnabled(settings)) return manager; + if (!isAgentModeEnabled()) return manager; // Per-backend preload registration: each backend's status flips // independently. The chat UI gates on the active backend's status; the // picker reads every backend's status to render per-backend loading rows. diff --git a/src/commands/index.ts b/src/commands/index.ts index 354619f6..1ca0b84b 100644 --- a/src/commands/index.ts +++ b/src/commands/index.ts @@ -25,7 +25,6 @@ import { checkIsPlusUser } from "@/plusUtils"; import CopilotPlugin from "@/main"; import { shouldUseMiyo } from "@/miyo/miyoUtils"; import { getAllQAMarkdownContent } from "@/search/searchUtils"; -import { CopilotSettings } from "@/settings/model"; import { NoteSelectedTextContext, WebSelectedTextContext } from "@/types/message"; import { ensureFolderExists, isSourceModeOn } from "@/utils"; import { Editor, MarkdownView, Notice, TFile } from "obsidian"; @@ -88,11 +87,7 @@ function addCheckCommand( }); } -export function registerCommands( - plugin: CopilotPlugin, - prev: CopilotSettings | undefined, - next: CopilotSettings -) { +export function registerCommands(plugin: CopilotPlugin) { addEditorCommand(plugin, COMMAND_IDS.COUNT_WORD_AND_TOKENS_SELECTION, async (editor: Editor) => { const selectedText = editor.getSelection(); const wordCount = selectedText.split(" ").length; @@ -128,9 +123,9 @@ export function registerCommands( await plugin.newChat(); }); - // Re-runs from the settings subscription in main.ts so toggling the - // master switch refreshes the command palette. - if (isAgentModeEnabled(next)) { + // Agent Mode is always on, but requires subprocess support — register the + // agent commands on desktop only. + if (isAgentModeEnabled()) { addCommand(plugin, COMMAND_IDS.OPEN_AGENT_CHAT_WINDOW, () => { void plugin.activateAgentView(); }); diff --git a/src/constants.ts b/src/constants.ts index ddd89095..378977fe 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1023,7 +1023,6 @@ export const DEFAULT_SETTINGS: CopilotSettings = { autoCompactThreshold: 128000, convertedDocOutputFolder: DEFAULT_CONVERTED_DOC_OUTPUT_FOLDER, agentMode: { - enabled: true, byok: {}, mcpServers: [], activeBackend: "opencode", diff --git a/src/main.ts b/src/main.ts index 99d3821e..64570f8a 100644 --- a/src/main.ts +++ b/src/main.ts @@ -91,7 +91,6 @@ import { Notice, Platform, Plugin, - setIcon, TFile, WorkspaceLeaf, } from "obsidian"; @@ -183,10 +182,6 @@ export default class CopilotPlugin extends Plugin { logError("Failed to persist settings.", error); new Notice("Copilot failed to save settings. Check logs and try again."); } - registerCommands(this, prev, next); - if (prev && prev.agentMode?.enabled !== next.agentMode?.enabled) { - this.refreshRibbonIcon(); - } // Sign-in / sign-out (isPlusUser flip) or key rotation while signed in. if ( prev?.isPlusUser !== next.isPlusUser || @@ -289,7 +284,7 @@ export default class CopilotPlugin extends Plugin { () => (this.canUseAgentView() ? this.activateAgentView() : this.activateView()) ); - registerCommands(this, undefined, getSettings()); + registerCommands(this); // Tool initialization is now handled automatically in CopilotPlusChainRunner and AutonomousAgentChainRunner @@ -781,10 +776,6 @@ export default class CopilotPlugin extends Plugin { new Notice("Agent Chat is not available on mobile."); return null; } - if (!isAgentModeEnabled()) { - new Notice("Enable Agent Mode in Copilot settings first."); - return null; - } if (!this.agentSessionManager) { new Notice("Agent Chat is not initialized."); return null; @@ -796,16 +787,6 @@ export default class CopilotPlugin extends Plugin { return !!this.agentSessionManager && isAgentModeEnabled(); } - private refreshRibbonIcon() { - if (!this.ribbonIconEl) return; - const agentReady = this.canUseAgentView(); - const icon = agentReady ? "bot" : "message-square"; - const tooltip = agentReady ? "Open Copilot Agent Chat" : "Open Copilot Chat"; - setIcon(this.ribbonIconEl, icon); - this.ribbonIconEl.setAttribute("aria-label", tooltip); - this.ribbonIconEl.setAttribute("title", tooltip); - } - async loadSettings() { const rawData = (await this.loadData()) as unknown; const settings = await loadSettingsWithKeychain(rawData, (d) => this.saveData(d)); diff --git a/src/settings/model.test.ts b/src/settings/model.test.ts index 92f73b53..37c6b24f 100644 --- a/src/settings/model.test.ts +++ b/src/settings/model.test.ts @@ -187,7 +187,6 @@ describe("sanitizeSettings - agentMode shape migration", () => { agentMode: undefined as unknown as never, }); expect(sanitized.agentMode).toEqual({ - enabled: true, byok: {}, mcpServers: [], activeBackend: "opencode", diff --git a/src/settings/model.ts b/src/settings/model.ts index eefcd1c8..409a5d0e 100644 --- a/src/settings/model.ts +++ b/src/settings/model.ts @@ -230,7 +230,6 @@ export interface CopilotSettings { settingsVersion?: number; /** Agent Mode (ACP-backed BYOK agent harness). Desktop only. */ agentMode: { - enabled: boolean; byok: { anthropic?: string; openai?: string; google?: string }; /** * User-configured MCP servers passed to the agent on session start. @@ -844,7 +843,6 @@ function sanitizeAgentMode(raw: unknown): CopilotSettings["agentMode"] { return { ...DEFAULT_SETTINGS.agentMode }; } const r = raw as Record; - const enabled = typeof r.enabled === "boolean" ? r.enabled : DEFAULT_SETTINGS.agentMode.enabled; const byok = r.byok && typeof r.byok === "object" ? (r.byok as { anthropic?: string; openai?: string; google?: string }) @@ -904,7 +902,6 @@ function sanitizeAgentMode(raw: unknown): CopilotSettings["agentMode"] { }; return { - enabled, byok, mcpServers, activeBackend, diff --git a/src/settings/v2/components/AgentSettings.tsx b/src/settings/v2/components/AgentSettings.tsx index f451a916..c6ca9da8 100644 --- a/src/settings/v2/components/AgentSettings.tsx +++ b/src/settings/v2/components/AgentSettings.tsx @@ -50,34 +50,21 @@ export const AgentSettings: React.FC = () => {
Agents (alpha)
- setSettings((cur) => ({ agentMode: { ...cur.agentMode, enabled: checked } })) + type="select" + title="Default backend" + description="Used when you click + to start a new session and for auto-spawn on mount. Selecting a model from the model picker also updates this." + value={settings.agentMode.activeBackend} + onChange={(value) => + setSettings((cur) => ({ agentMode: { ...cur.agentMode, activeBackend: value } })) } + options={orderedDescriptors.map((d) => ({ label: d.displayName, value: d.id }))} /> - {settings.agentMode.enabled && ( - - setSettings((cur) => ({ agentMode: { ...cur.agentMode, activeBackend: value } })) - } - options={orderedDescriptors.map((d) => ({ label: d.displayName, value: d.id }))} - /> - )} + - {settings.agentMode.enabled && } - - {settings.agentMode.enabled && - orderedDescriptors.map((descriptor) => ( - - ))} + {orderedDescriptors.map((descriptor) => ( + + ))}
);