fix: mutate prefixContext object instead of reassigning for closure correctness

This commit is contained in:
Sebastian
2026-01-14 23:20:19 -05:00
parent 7b04e6ac42
commit 113eea5047
8 changed files with 30 additions and 53 deletions

View File

@@ -127,9 +127,6 @@ export async function runAgentTurnWithFallback(params: {
run: (provider, model) => { run: (provider, model) => {
// Notify that model selection is complete (including after fallback). // Notify that model selection is complete (including after fallback).
// This allows responsePrefix template interpolation with the actual model. // This allows responsePrefix template interpolation with the actual model.
logVerbose(
`[prefix-debug] onModelSelected firing: provider=${provider} model=${model} thinkLevel=${params.followupRun.run.thinkLevel}`,
);
params.opts?.onModelSelected?.({ params.opts?.onModelSelected?.({
provider, provider,
model, model,

View File

@@ -75,14 +75,6 @@ function normalizeReplyPayloadInternal(
// Prefer dynamic context provider over static context // Prefer dynamic context provider over static context
const prefixContext = opts.responsePrefixContextProvider?.() ?? opts.responsePrefixContext; const prefixContext = opts.responsePrefixContextProvider?.() ?? opts.responsePrefixContext;
// Debug logging for prefix template resolution
if (opts.responsePrefix?.includes("{")) {
// eslint-disable-next-line no-console
console.log(
`[prefix-debug] normalizing with context: ${JSON.stringify(prefixContext)} prefix: ${opts.responsePrefix}`,
);
}
return normalizeReplyPayload(payload, { return normalizeReplyPayload(payload, {
responsePrefix: opts.responsePrefix, responsePrefix: opts.responsePrefix,
responsePrefixContext: prefixContext, responsePrefixContext: prefixContext,

View File

@@ -329,13 +329,11 @@ export async function processDiscordMessage(ctx: DiscordMessagePreflightContext)
? !discordConfig.blockStreaming ? !discordConfig.blockStreaming
: undefined, : undefined,
onModelSelected: (ctx) => { onModelSelected: (ctx) => {
prefixContext = { // Mutate the object directly instead of reassigning to ensure the closure sees updates
...prefixContext, prefixContext.provider = ctx.provider;
provider: ctx.provider, prefixContext.model = extractShortModelName(ctx.model);
model: extractShortModelName(ctx.model), prefixContext.modelFull = `${ctx.provider}/${ctx.model}`;
modelFull: `${ctx.provider}/${ctx.model}`, prefixContext.thinkingLevel = ctx.thinkLevel ?? "off";
thinkingLevel: ctx.thinkLevel ?? "off",
};
}, },
}, },
}); });

View File

@@ -386,13 +386,11 @@ export async function monitorIMessageProvider(opts: MonitorIMessageOpts = {}): P
? !accountInfo.config.blockStreaming ? !accountInfo.config.blockStreaming
: undefined, : undefined,
onModelSelected: (ctx) => { onModelSelected: (ctx) => {
prefixContext = { // Mutate the object directly instead of reassigning to ensure the closure sees updates
...prefixContext, prefixContext.provider = ctx.provider;
provider: ctx.provider, prefixContext.model = extractShortModelName(ctx.model);
model: extractShortModelName(ctx.model), prefixContext.modelFull = `${ctx.provider}/${ctx.model}`;
modelFull: `${ctx.provider}/${ctx.model}`, prefixContext.thinkingLevel = ctx.thinkLevel ?? "off";
thinkingLevel: ctx.thinkLevel ?? "off",
};
}, },
}, },
}); });

View File

@@ -354,13 +354,11 @@ export function createSignalEventHandler(deps: SignalEventHandlerDeps) {
disableBlockStreaming: disableBlockStreaming:
typeof deps.blockStreaming === "boolean" ? !deps.blockStreaming : undefined, typeof deps.blockStreaming === "boolean" ? !deps.blockStreaming : undefined,
onModelSelected: (ctx) => { onModelSelected: (ctx) => {
prefixContext = { // Mutate the object directly instead of reassigning to ensure the closure sees updates
...prefixContext, prefixContext.provider = ctx.provider;
provider: ctx.provider, prefixContext.model = extractShortModelName(ctx.model);
model: extractShortModelName(ctx.model), prefixContext.modelFull = `${ctx.provider}/${ctx.model}`;
modelFull: `${ctx.provider}/${ctx.model}`, prefixContext.thinkingLevel = ctx.thinkLevel ?? "off";
thinkingLevel: ctx.thinkLevel ?? "off",
};
}, },
}, },
}); });

View File

@@ -117,13 +117,11 @@ export async function dispatchPreparedSlackMessage(prepared: PreparedSlackMessag
? !account.config.blockStreaming ? !account.config.blockStreaming
: undefined, : undefined,
onModelSelected: (ctx) => { onModelSelected: (ctx) => {
prefixContext = { // Mutate the object directly instead of reassigning to ensure the closure sees updates
...prefixContext, prefixContext.provider = ctx.provider;
provider: ctx.provider, prefixContext.model = extractShortModelName(ctx.model);
model: extractShortModelName(ctx.model), prefixContext.modelFull = `${ctx.provider}/${ctx.model}`;
modelFull: `${ctx.provider}/${ctx.model}`, prefixContext.thinkingLevel = ctx.thinkLevel ?? "off";
thinkingLevel: ctx.thinkLevel ?? "off",
};
}, },
}, },
}); });

View File

@@ -162,13 +162,11 @@ export const dispatchTelegramMessage = async ({
: undefined, : undefined,
disableBlockStreaming, disableBlockStreaming,
onModelSelected: (ctx) => { onModelSelected: (ctx) => {
prefixContext = { // Mutate the object directly instead of reassigning to ensure the closure sees updates
...prefixContext, prefixContext.provider = ctx.provider;
provider: ctx.provider, prefixContext.model = extractShortModelName(ctx.model);
model: extractShortModelName(ctx.model), prefixContext.modelFull = `${ctx.provider}/${ctx.model}`;
modelFull: `${ctx.provider}/${ctx.model}`, prefixContext.thinkingLevel = ctx.thinkLevel ?? "off";
thinkingLevel: ctx.thinkLevel ?? "off",
};
}, },
}, },
}); });

View File

@@ -278,13 +278,11 @@ export async function processMessage(params: {
? !params.cfg.channels.whatsapp.blockStreaming ? !params.cfg.channels.whatsapp.blockStreaming
: undefined, : undefined,
onModelSelected: (ctx) => { onModelSelected: (ctx) => {
prefixContext = { // Mutate the object directly instead of reassigning to ensure the closure sees updates
...prefixContext, prefixContext.provider = ctx.provider;
provider: ctx.provider, prefixContext.model = extractShortModelName(ctx.model);
model: extractShortModelName(ctx.model), prefixContext.modelFull = `${ctx.provider}/${ctx.model}`;
modelFull: `${ctx.provider}/${ctx.model}`, prefixContext.thinkingLevel = ctx.thinkLevel ?? "off";
thinkingLevel: ctx.thinkLevel ?? "off",
};
}, },
}, },
}); });