fix(model): require confirmation for expensive model selections
Rebased onto current main and re-ported across the restructured surfaces: model flows now thread confirm_provider/base_url/api_key through hermes_cli/model_setup_flows.py, the Discord picker lives in plugins/platforms/discord/adapter.py, and the web dashboard picker applies chat-mode switches via config.set so the expensive-model confirmation can ride the response. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
committed by
Teknium
co-authored by
Claude Fable 5
parent
4eadef18a9
commit
af978ecb17
@@ -108,6 +108,7 @@ describe('createSlashHandler', () => {
|
||||
|
||||
expect(createSlashHandler(ctx)('/model x-model')).toBe(true)
|
||||
expect(ctx.gateway.rpc).toHaveBeenCalledWith('config.set', {
|
||||
confirm_expensive_model: false,
|
||||
key: 'model',
|
||||
session_id: 'sid-abc',
|
||||
value: 'x-model'
|
||||
@@ -128,6 +129,7 @@ describe('createSlashHandler', () => {
|
||||
createSlashHandler(ctx)(`/model anthropic/claude-sonnet-4.6 --provider openrouter ${TUI_SESSION_MODEL_FLAG}`)
|
||||
).toBe(true)
|
||||
expect(ctx.gateway.rpc).toHaveBeenCalledWith('config.set', {
|
||||
confirm_expensive_model: false,
|
||||
key: 'model',
|
||||
session_id: 'sid-abc',
|
||||
value: 'anthropic/claude-sonnet-4.6 --provider openrouter'
|
||||
@@ -140,6 +142,7 @@ describe('createSlashHandler', () => {
|
||||
|
||||
createSlashHandler(ctx)('/model x-model --global')
|
||||
expect(ctx.gateway.rpc).toHaveBeenCalledWith('config.set', {
|
||||
confirm_expensive_model: false,
|
||||
key: 'model',
|
||||
session_id: 'sid-abc',
|
||||
value: 'x-model --global'
|
||||
|
||||
@@ -72,10 +72,25 @@ export const sessionCommands: SlashCommand[] = [
|
||||
return patchOverlayState({ modelPicker: true })
|
||||
}
|
||||
|
||||
ctx.gateway
|
||||
.rpc<ConfigSetResponse>('config.set', { key: 'model', session_id: ctx.sid, value: modelValueForConfigSet(arg) })
|
||||
const switchModel = (confirmExpensiveModel = false) => ctx.gateway
|
||||
.rpc<ConfigSetResponse>('config.set', { confirm_expensive_model: confirmExpensiveModel, key: 'model', session_id: ctx.sid, value: modelValueForConfigSet(arg) })
|
||||
.then(
|
||||
ctx.guarded<ConfigSetResponse>(r => {
|
||||
if (r.confirm_required) {
|
||||
patchOverlayState({
|
||||
confirm: {
|
||||
cancelLabel: 'Cancel',
|
||||
confirmLabel: 'Switch anyway',
|
||||
danger: true,
|
||||
detail: r.confirm_message || r.warning || 'This model has unusually high known pricing.',
|
||||
onConfirm: () => switchModel(true),
|
||||
title: 'Expensive model selection'
|
||||
}
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if (!r.value) {
|
||||
return ctx.transcript.sys('error: invalid response: model switch')
|
||||
}
|
||||
@@ -89,6 +104,8 @@ export const sessionCommands: SlashCommand[] = [
|
||||
}))
|
||||
})
|
||||
)
|
||||
|
||||
switchModel()
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -103,6 +103,8 @@ export interface ConfigGetValueResponse {
|
||||
}
|
||||
|
||||
export interface ConfigSetResponse {
|
||||
confirm_message?: string
|
||||
confirm_required?: boolean
|
||||
credential_warning?: string
|
||||
history_reset?: boolean
|
||||
info?: SessionInfo
|
||||
|
||||
Reference in New Issue
Block a user