mirror of
https://github.com/davidkaya/aryx.git
synced 2026-07-24 13:38:43 +02:00
fix: strip reasoning effort on prompt model override, show actual model badge
When a prompt file overrides the turn model, the original agent's reasoning effort was carried through even when the target model does not support it. This caused session.create failures for models like Claude Opus 4.5 which reject reasoning effort configuration. Now: if the target model's reasoning capabilities are unknown (supportedReasoningEfforts undefined) or it's an unresolved model reference, reasoning effort is stripped entirely. Also adds a model override badge on assistant messages when the run used a different model than the session's primary agent. The badge reads the actual model from the run record (SessionRunRecord.agents) rather than inferring from the prompt invocation metadata. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -2944,9 +2944,16 @@ export class AryxAppService extends EventEmitter<AppServiceEvents> {
|
||||
|
||||
let didChange = false;
|
||||
const agents = pattern.agents.map((agent) => {
|
||||
const reasoningEffort = resolvedModel
|
||||
? resolveReasoningEffort(resolvedModel, agent.reasoningEffort)
|
||||
: agent.reasoningEffort;
|
||||
// When overriding the model, re-normalize reasoning effort for the target model.
|
||||
// If the target model's reasoning capabilities are unknown (supportedReasoningEfforts
|
||||
// is undefined — common for dynamically-discovered models), strip reasoning effort
|
||||
// entirely to avoid sending it to a model that may not support it.
|
||||
let reasoningEffort: ReasoningEffort | undefined;
|
||||
if (resolvedModel?.supportedReasoningEfforts) {
|
||||
reasoningEffort = resolveReasoningEffort(resolvedModel, agent.reasoningEffort);
|
||||
} else {
|
||||
reasoningEffort = undefined;
|
||||
}
|
||||
|
||||
if (agent.model === effectiveModelId && agent.reasoningEffort === reasoningEffort) {
|
||||
return agent;
|
||||
|
||||
@@ -195,6 +195,30 @@ export function ChatPane({
|
||||
const promptFiles = useMemo(() => project.customization?.promptFiles ?? [], [project.customization?.promptFiles]);
|
||||
const [armedPrompt, setArmedPrompt] = useState<ArmedPrompt | null>(null);
|
||||
|
||||
// Map assistant message IDs to the actual model that executed the run, but only
|
||||
// when it differs from the session's primary agent model (i.e. a prompt override).
|
||||
const modelOverrideByMessageId = useMemo(() => {
|
||||
const runsByTrigger = new Map(session.runs.map((r) => [r.triggerMessageId, r]));
|
||||
const map = new Map<string, string>();
|
||||
let activeOverrideModel: string | undefined;
|
||||
|
||||
for (const message of session.messages) {
|
||||
if (message.role === 'user') {
|
||||
const run = runsByTrigger.get(message.id);
|
||||
const runModel = run?.agents[0]?.model;
|
||||
if (runModel && runModel !== primaryAgent?.model) {
|
||||
const resolved = findModel(runModel, availableModels);
|
||||
activeOverrideModel = resolved?.name ?? runModel;
|
||||
} else {
|
||||
activeOverrideModel = undefined;
|
||||
}
|
||||
} else if (activeOverrideModel && message.messageKind !== 'thinking') {
|
||||
map.set(message.id, activeOverrideModel);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}, [session.messages, session.runs, primaryAgent?.model, availableModels]);
|
||||
|
||||
const toolSelection = useMemo(() => resolveSessionToolingSelection(session), [session]);
|
||||
const mcpServers = toolingSettings.mcpServers;
|
||||
const lspProfiles = toolingSettings.lspProfiles;
|
||||
@@ -469,6 +493,7 @@ export function ChatPane({
|
||||
: 'border-[var(--color-status-success)]/20 bg-[var(--color-status-success)]/10 text-[var(--color-status-success)]';
|
||||
const phaseLabel =
|
||||
phase === 'thinking' ? 'Thinking' : phase === 'final' ? 'Final' : undefined;
|
||||
const modelOverride = !isUser ? modelOverrideByMessageId.get(message.id) : undefined;
|
||||
const showActions = !isSessionBusy && !message.pending;
|
||||
|
||||
return (
|
||||
@@ -495,6 +520,11 @@ export function ChatPane({
|
||||
{phaseLabel}
|
||||
</span>
|
||||
)}
|
||||
{modelOverride && (
|
||||
<span className="inline-flex items-center gap-1 rounded-full bg-[var(--color-accent-purple)]/10 px-2 py-0.5 text-[10px] font-medium text-[var(--color-accent-purple)]">
|
||||
{modelOverride}
|
||||
</span>
|
||||
)}
|
||||
{showActions && (
|
||||
<div className="ml-auto">
|
||||
<MessageActions
|
||||
|
||||
Reference in New Issue
Block a user