fix(vscode): add mode field to plan follow-up Continue here option so picker updates instantly

This commit is contained in:
kirillk
2026-05-09 20:49:26 -04:00
parent c08ff0c8f1
commit b539c6920e
6 changed files with 103 additions and 0 deletions
@@ -105,6 +105,67 @@ describe("resolveSelectedQuestionMode", () => {
})
})
describe("plan follow-up Continue here option", () => {
it("resolves to code mode when option carries mode: code matching the Continue here label", () => {
const questions = [
{
options: [
{
label: "Start new session",
description: "Implement in a fresh session",
labelKey: "plan.followup.answer.newSession",
descriptionKey: "plan.followup.answer.newSession.description",
},
{
label: "Continue here",
description: "Implement the plan in this session",
labelKey: "plan.followup.answer.continue",
descriptionKey: "plan.followup.answer.continue.description",
mode: "code",
},
],
},
]
expect(resolveSelectedQuestionMode(questions, [["Continue here"]])).toBe("code")
})
it("does not resolve a mode for Start new session (it carries no mode)", () => {
const questions = [
{
options: [
{
label: "Start new session",
description: "Implement in a fresh session",
labelKey: "plan.followup.answer.newSession",
descriptionKey: "plan.followup.answer.newSession.description",
},
{
label: "Continue here",
description: "Implement the plan in this session",
labelKey: "plan.followup.answer.continue",
descriptionKey: "plan.followup.answer.continue.description",
mode: "code",
},
],
},
]
expect(resolveSelectedQuestionMode(questions, [["Start new session"]])).toBeUndefined()
})
it("resolves optimistic agent to code when Continue here is picked while in plan mode", () => {
const mode = resolveSelectedQuestionMode(
[
{
options: [{ label: "Continue here", description: "Implement here", mode: "code" }],
},
],
[["Continue here"]],
)
const result = resolveOptimisticQuestionAgent(undefined, "plan", mode)
expect(result).toEqual({ base: "plan", agent: "code" })
})
})
describe("resolveOptimisticQuestionAgent", () => {
it("stores the previous agent when applying an optimistic mode", () => {
const result = resolveOptimisticQuestionAgent(undefined, "ask", "code")
@@ -297,6 +297,7 @@ export namespace PlanFollowup {
labelKey: "plan.followup.answer.continue",
description: "Implement the plan in this session",
descriptionKey: "plan.followup.answer.continue.description",
mode: "code",
},
],
},
+5
View File
@@ -29,6 +29,11 @@ export class Option extends Schema.Class<Option>("QuestionOption")({
descriptionKey: Schema.optional(Schema.String).annotate({
description: "Optional i18n key for the description",
}),
// Hint to VS Code and other UI clients to switch the active agent/mode picker
// when this option is selected (before the reply is confirmed by the server).
mode: Schema.optional(Schema.String).annotate({
description: "Optional agent/mode name to pre-select in the UI when this option is picked",
}),
// kilocode_change end
}) {
static readonly zod = zod(this)
@@ -296,6 +296,34 @@ describe("plan follow-up", () => {
await expect(pending).resolves.toBe("break")
}))
test("ask - Continue here option carries mode: code so VS Code picker updates immediately", () =>
withInstance(async () => {
const seeded = await seed({ text: "1. Build" })
const pending = PlanFollowup.ask({
sessionID: seeded.sessionID,
messages: seeded.messages,
abort: AbortSignal.any([]),
})
const item = await waitQuestion(seeded.sessionID)
expect(item).toBeDefined()
if (!item) return
const q = item.questions[0]
expect(q).toBeDefined()
if (!q) return
const continueOpt = q.options.find((o) => o.label === PlanFollowup.ANSWER_CONTINUE)
expect(continueOpt?.mode).toBe("code")
// Start new session should not carry a mode (it opens a new session — the
// current picker is irrelevant once the session switches).
const newOpt = q.options.find((o) => o.label === PlanFollowup.ANSWER_NEW_SESSION)
expect(newOpt?.mode).toBeUndefined()
await question.reject(item.id)
await expect(pending).resolves.toBe("break")
}))
test("ask - hides custom answer row on VS Code where the main prompt input handles typed replies", () =>
withInstance(async () => {
const prev = process.env.KILO_CLIENT
+4
View File
@@ -93,6 +93,10 @@ export type QuestionOption = {
* Optional i18n key for the description
*/
descriptionKey?: string
/**
* Optional agent/mode name to pre-select in the UI when this option is picked
*/
mode?: string
}
export type QuestionInfo = {
+4
View File
@@ -11215,6 +11215,10 @@
"descriptionKey": {
"description": "Optional i18n key for the description",
"type": "string"
},
"mode": {
"description": "Optional agent/mode name to pre-select in the UI when this option is picked",
"type": "string"
}
},
"required": ["label", "description"]