This commit is contained in:
eleanorjboyd
2026-01-28 10:09:48 -08:00
parent 69a9b7235d
commit 7b2081533c
4 changed files with 38 additions and 9 deletions
@@ -104,6 +104,14 @@ export class ChatSuggestNextWidget extends Disposable {
private createPromptButton(handoff: IHandOff): HTMLElement {
const disposables = new DisposableStore();
// Capture the label to look up the current handoff at click time
// This ensures we get the latest handoff data (e.g., updated model from settings)
const handoffLabel = handoff.label;
const getCurrentHandoff = (): IHandOff | undefined => {
const currentHandoffs = this._currentMode?.handOffs?.get();
return currentHandoffs?.find(h => h.label === handoffLabel) ?? handoff;
};
const button = dom.$('.chat-welcome-view-suggested-prompt');
button.setAttribute('tabindex', '0');
button.setAttribute('role', 'button');
@@ -155,7 +163,10 @@ export class ChatSuggestNextWidget extends Disposable {
ThemeIcon.isThemeIcon(icon) ? ThemeIcon.asClassName(icon) : undefined,
true,
() => {
this._onDidSelectPrompt.fire({ handoff, agentId: contrib.name });
const currentHandoff = getCurrentHandoff();
if (currentHandoff) {
this._onDidSelectPrompt.fire({ handoff: currentHandoff, agentId: contrib.name });
}
}
);
});
@@ -180,18 +191,27 @@ export class ChatSuggestNextWidget extends Disposable {
if (dom.isHTMLElement(e.target) && e.target.closest('.chat-suggest-next-dropdown')) {
return;
}
this._onDidSelectPrompt.fire({ handoff });
const currentHandoff = getCurrentHandoff();
if (currentHandoff) {
this._onDidSelectPrompt.fire({ handoff: currentHandoff });
}
}));
} else {
disposables.add(dom.addDisposableListener(button, 'click', () => {
this._onDidSelectPrompt.fire({ handoff });
const currentHandoff = getCurrentHandoff();
if (currentHandoff) {
this._onDidSelectPrompt.fire({ handoff: currentHandoff });
}
}));
}
disposables.add(dom.addDisposableListener(button, 'keydown', (e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
this._onDidSelectPrompt.fire({ handoff });
const currentHandoff = getCurrentHandoff();
if (currentHandoff) {
this._onDidSelectPrompt.fire({ handoff: currentHandoff });
}
}
}));
@@ -1210,7 +1210,7 @@ export class ChatWidget extends Disposable implements IChatWidget {
this._switchToAgentByName(handoff.agent);
// Switch to the specified model if provided
if (handoff.model) {
this.input.switchModelByQualifiedName(handoff.model);
this.input.switchModelByQualifiedName([handoff.model]);
}
// Insert the handoff prompt into the input
this.input.setValue(promptToUse, false);
@@ -514,8 +514,13 @@ export class PromptValidator {
report(toMarker(localize('promptValidator.handoffShowContinueOnMustBeBoolean', "The 'showContinueOn' property in a handoff must be a boolean."), prop.value.range, MarkerSeverity.Error));
}
break;
case 'model':
if (prop.value.type !== 'string') {
report(toMarker(localize('promptValidator.handoffModelMustBeString', "The 'model' property in a handoff must be a string."), prop.value.range, MarkerSeverity.Error));
}
break;
default:
report(toMarker(localize('promptValidator.unknownHandoffProperty', "Unknown property '{0}' in handoff object. Supported properties are 'label', 'agent', 'prompt' and optional 'send', 'showContinueOn'.", prop.key.value), prop.value.range, MarkerSeverity.Warning));
report(toMarker(localize('promptValidator.unknownHandoffProperty', "Unknown property '{0}' in handoff object. Supported properties are 'label', 'agent', 'prompt' and optional 'send', 'showContinueOn', 'model'.", prop.key.value), prop.value.range, MarkerSeverity.Warning));
}
required.delete(prop.key.value);
}
@@ -238,7 +238,7 @@ export class PromptHeader {
return undefined;
}
if (handoffsAttribute.value.type === 'array') {
// Array format: list of objects: { agent, label, prompt, send?, showContinueOn? }
// Array format: list of objects: { agent, label, prompt, send?, showContinueOn?, model? }
const handoffs: IHandOff[] = [];
for (const item of handoffsAttribute.value.items) {
if (item.type === 'object') {
@@ -247,6 +247,7 @@ export class PromptHeader {
let prompt: string | undefined;
let send: boolean | undefined;
let showContinueOn: boolean | undefined;
let model: string | undefined;
for (const prop of item.properties) {
if (prop.key.value === 'agent' && prop.value.type === 'string') {
agent = prop.value.value;
@@ -258,6 +259,8 @@ export class PromptHeader {
send = prop.value.value;
} else if (prop.key.value === 'showContinueOn' && prop.value.type === 'boolean') {
showContinueOn = prop.value.value;
} else if (prop.key.value === 'model' && prop.value.type === 'string') {
model = prop.value.value;
}
}
if (agent && label && prompt !== undefined) {
@@ -266,7 +269,8 @@ export class PromptHeader {
label,
prompt,
...(send !== undefined ? { send } : {}),
...(showContinueOn !== undefined ? { showContinueOn } : {})
...(showContinueOn !== undefined ? { showContinueOn } : {}),
...(model !== undefined ? { model } : {})
};
handoffs.push(handoff);
}
@@ -325,7 +329,7 @@ export interface IHandOff {
readonly prompt: string;
readonly send?: boolean;
readonly showContinueOn?: boolean; // treated exactly like send (optional boolean)
readonly model?: readonly string[]; // qualified model name(s) to switch to (e.g., "GPT-4o (copilot)")
readonly model?: string; // qualified model name to switch to (e.g., "GPT-4o (copilot)")
}
export interface IHeaderAttribute {