Skip to content

Commit 5381a9e

Browse files
committed
feat: add /fast toggle command for quick Opus Sonnet switching
- Add /fast slash command that toggles fast mode on/off - Add fastMode and fastModel settings to UnifiedBotSettings - Override model in getQueryOptions() when fast mode is active - Switch model mid-session via Query.setModel() on active queries - Wire settings deps to InfoCommandHandlerDeps for read/write access - Update help system with /fast documentation - Default fast model: claude-sonnet-4-6
1 parent 0754b41 commit 5381a9e

File tree

5 files changed

+94
-4
lines changed

5 files changed

+94
-4
lines changed

claude/info-commands.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ export const infoCommands = [
7272
option.setName('value')
7373
.setDescription('Value for the action (model name or permission mode)')
7474
.setRequired(false)),
75+
76+
new SlashCommandBuilder()
77+
.setName('fast')
78+
.setDescription('Toggle fast mode — switch between default model and a fast/cheap model (Sonnet)'),
7579
];
7680

7781
// ================================
@@ -81,6 +85,10 @@ export const infoCommands = [
8185
export interface InfoCommandHandlerDeps {
8286
workDir: string;
8387
getQueryOptions?: () => ClaudeModelOptions;
88+
/** Read current unified settings (for /fast toggle) */
89+
getUnifiedSettings?: () => import("../settings/unified-settings.ts").UnifiedBotSettings;
90+
/** Update unified settings (for /fast toggle) */
91+
updateUnifiedSettings?: (partial: Partial<import("../settings/unified-settings.ts").UnifiedBotSettings>) => void;
8492
}
8593

8694
export function createInfoCommandHandlers(deps: InfoCommandHandlerDeps) {
@@ -427,6 +435,55 @@ export function createInfoCommandHandlers(deps: InfoCommandHandlerDeps) {
427435
});
428436
}
429437
},
438+
439+
// ================================
440+
// /fast — Toggle fast mode
441+
// ================================
442+
// deno-lint-ignore no-explicit-any
443+
async onFast(ctx: any): Promise<void> {
444+
if (!deps.getUnifiedSettings || !deps.updateUnifiedSettings) {
445+
await ctx.reply({ content: 'Fast mode not available (settings not wired).', ephemeral: true });
446+
return;
447+
}
448+
449+
const current = deps.getUnifiedSettings();
450+
const newFastMode = !current.fastMode;
451+
deps.updateUnifiedSettings({ fastMode: newFastMode });
452+
453+
// If there's an active query, switch the model mid-session
454+
const activeQuery = getActiveQuery();
455+
if (activeQuery) {
456+
try {
457+
if (newFastMode) {
458+
await setActiveModel(current.fastModel || 'claude-sonnet-4-6');
459+
} else {
460+
// Revert to default model (undefined = SDK default)
461+
await setActiveModel(current.defaultModel || undefined);
462+
}
463+
} catch {
464+
// Mid-session switch failed — setting still applies to next query
465+
}
466+
}
467+
468+
const modelName = newFastMode
469+
? (current.fastModel || 'claude-sonnet-4-6')
470+
: (current.defaultModel || 'default (Opus)');
471+
const midSessionNote = activeQuery
472+
? '\nModel switched on active session.'
473+
: '';
474+
475+
await ctx.reply({
476+
embeds: [{
477+
color: newFastMode ? 0xffaa00 : 0x5865f2,
478+
title: newFastMode ? '⚡ Fast Mode ON' : '🧠 Fast Mode OFF',
479+
description: newFastMode
480+
? `Switched to **${modelName}** — faster responses, lower cost.${midSessionNote}`
481+
: `Switched to **${modelName}** — full reasoning power.${midSessionNote}`,
482+
footer: { text: 'Use /fast again to toggle back' },
483+
timestamp: new Date().toISOString()
484+
}]
485+
});
486+
},
430487
};
431488
}
432489

core/command-wrappers.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,11 @@ function createInfoCommandsMap(
545545
await infoHandlers.onClaudeControl(ctx, action, value || undefined);
546546
}
547547
}],
548+
['fast', {
549+
execute: async (ctx: InteractionContext) => {
550+
await infoHandlers.onFast(ctx);
551+
}
552+
}],
548553
]);
549554
}
550555

core/handler-registry.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -383,8 +383,10 @@ export function createAllHandlers(
383383
const s = settings.getSettings().unified;
384384
const opts: ClaudeModelOptions = {};
385385

386-
// Model
387-
if (s.defaultModel) {
386+
// Model — fast mode overrides default model
387+
if (s.fastMode && s.fastModel) {
388+
opts.model = s.fastModel;
389+
} else if (s.defaultModel) {
388390
opts.model = s.defaultModel;
389391
}
390392

@@ -546,6 +548,8 @@ export function createAllHandlers(
546548
const infoCommandHandlers = createInfoCommandHandlers({
547549
workDir,
548550
getQueryOptions,
551+
getUnifiedSettings: () => settings.getSettings().unified,
552+
updateUnifiedSettings: (partial) => settings.updateUnified(partial),
549553
});
550554

551555
return {

help/commands.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -783,6 +783,22 @@ export const COMMAND_HELP = {
783783
"Shows model capabilities and features",
784784
"Applies to all new conversations until changed again"
785785
]
786+
},
787+
"fast": {
788+
title: "⚡ Fast Mode Toggle",
789+
description: "Toggle between the default model (Opus) and a fast/cheap model (Sonnet)",
790+
usage: "/fast",
791+
examples: [
792+
"/fast"
793+
],
794+
parameters: [],
795+
notes: [
796+
"Toggles fast mode on/off",
797+
"Fast mode uses Sonnet for faster, cheaper responses",
798+
"Works mid-session — switches model on an active query",
799+
"Configure the fast model via /settings",
800+
"Use /fast again to toggle back to your default model"
801+
]
786802
}
787803
};
788804

@@ -861,7 +877,7 @@ export function createHelpHandlers(deps: HelpHandlerDeps) {
861877
fields: [
862878
{
863879
name: "🤖 Claude Code Commands",
864-
value: "`/claude` - Send prompts to Claude Code\n`/claude-enhanced` - Advanced Claude with options\n`/continue` - Continue conversation\n`/claude-cancel` - Cancel running operation",
880+
value: "`/claude` - Send prompts to Claude Code\n`/claude-enhanced` - Advanced Claude with options\n`/resume` - Resume conversation\n`/claude-cancel` - Cancel running operation\n`/fast` - Toggle fast mode (Opus ↔ Sonnet)",
865881
inline: false
866882
},
867883
{
@@ -881,7 +897,7 @@ export function createHelpHandlers(deps: HelpHandlerDeps) {
881897
},
882898
{
883899
name: "⚙️ Advanced Settings",
884-
value: "`/settings` - Unified bot settings (NEW)\n`/claude-settings` - Claude preferences\n`/output-settings` - Display settings\n`/quick-model` - Switch Claude model",
900+
value: "`/settings` - Unified bot settings (NEW)\n`/claude-settings` - Claude preferences\n`/output-settings` - Display settings\n`/quick-model` - Switch Claude model\n`/fast` - Toggle fast mode",
885901
inline: false
886902
},
887903
{

settings/unified-settings.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ export interface UnifiedBotSettings {
2323
// Mode settings
2424
operationMode: 'normal' | 'plan' | 'auto-accept' | 'danger' | 'dont-ask';
2525

26+
// Fast mode — toggles between default model and a fast/cheap model
27+
fastMode: boolean;
28+
fastModel: string;
29+
2630
// Budget settings
2731
maxBudgetUsd: number | null;
2832

@@ -83,6 +87,10 @@ export const UNIFIED_DEFAULT_SETTINGS: UnifiedBotSettings = {
8387
// Operation mode
8488
operationMode: 'normal',
8589

90+
// Fast mode — off by default, uses Sonnet as fast model
91+
fastMode: false,
92+
fastModel: 'claude-sonnet-4-6',
93+
8694
// Budget
8795
maxBudgetUsd: null,
8896

0 commit comments

Comments
 (0)