mirror of
https://github.com/logancyang/obsidian-copilot.git
synced 2026-07-22 07:50:24 +00:00
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) <noreply@anthropic.com>
This commit is contained in:
parent
0a6046ff0a
commit
e25dd9861c
7 changed files with 24 additions and 67 deletions
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1023,7 +1023,6 @@ export const DEFAULT_SETTINGS: CopilotSettings = {
|
|||
autoCompactThreshold: 128000,
|
||||
convertedDocOutputFolder: DEFAULT_CONVERTED_DOC_OUTPUT_FOLDER,
|
||||
agentMode: {
|
||||
enabled: true,
|
||||
byok: {},
|
||||
mcpServers: [],
|
||||
activeBackend: "opencode",
|
||||
|
|
|
|||
21
src/main.ts
21
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));
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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<string, unknown>;
|
||||
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,
|
||||
|
|
|
|||
|
|
@ -50,34 +50,21 @@ export const AgentSettings: React.FC = () => {
|
|||
<div className="tw-mb-3 tw-text-xl tw-font-bold">Agents (alpha)</div>
|
||||
<div className="tw-space-y-4">
|
||||
<SettingItem
|
||||
type="switch"
|
||||
title="Enable Agent Mode"
|
||||
description="BYOK agent harness backed by a local ACP subprocess. Desktop only."
|
||||
checked={settings.agentMode.enabled}
|
||||
onCheckedChange={(checked) =>
|
||||
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 && (
|
||||
<SettingItem
|
||||
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 }))}
|
||||
/>
|
||||
)}
|
||||
<McpServersPanel />
|
||||
|
||||
{settings.agentMode.enabled && <McpServersPanel />}
|
||||
|
||||
{settings.agentMode.enabled &&
|
||||
orderedDescriptors.map((descriptor) => (
|
||||
<BackendSection key={descriptor.id} descriptor={descriptor} plugin={plugin} />
|
||||
))}
|
||||
{orderedDescriptors.map((descriptor) => (
|
||||
<BackendSection key={descriptor.id} descriptor={descriptor} plugin={plugin} />
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
|
|
|
|||
Loading…
Reference in a new issue