fix: pass custom answers through elaborate output
This commit is contained in:
+2
-1
@@ -184,7 +184,8 @@ This document defines the stable external behavior. It does not explain internal
|
|||||||
- after clarification, agents should prefer another structured follow-up over plain-text multiple choice when a decision is still unresolved
|
- after clarification, agents should prefer another structured follow-up over plain-text multiple choice when a decision is still unresolved
|
||||||
- once prior answers narrow the branch, agents should bundle the next 2-3 related unresolved questions into one follow-up ask when possible, instead of using a long sequence of single-question asks
|
- once prior answers narrow the branch, agents should bundle the next 2-3 related unresolved questions into one follow-up ask when possible, instead of using a long sequence of single-question asks
|
||||||
- `elaboration` is only present when `mode === "elaborate"`
|
- `elaboration` is only present when `mode === "elaborate"`
|
||||||
- elaborate `content` text and transcript rendering describe each note directly using the full question prompt and option label, instead of a generic elaboration banner
|
- elaborate `content` text and transcript rendering describe each note directly using the full question prompt and option label, and include the current committed answer text when available, instead of a generic elaboration banner
|
||||||
|
- when the user selects `Elaborate` without adding notes, elaborate `content` text and transcript rendering still include the committed answer text so the agent can elaborate on that answer directly
|
||||||
|
|
||||||
## Supported UX
|
## Supported UX
|
||||||
|
|
||||||
|
|||||||
+28
-4
@@ -71,16 +71,40 @@ export function formatElaborationLines(
|
|||||||
): string[] {
|
): string[] {
|
||||||
const items = result.elaboration?.items ?? [];
|
const items = result.elaboration?.items ?? [];
|
||||||
const lines = items.map((item) => {
|
const lines = items.map((item) => {
|
||||||
|
const answerContext = formatElaborationAnswerContext(item.answer);
|
||||||
if (item.target.kind === "question") {
|
if (item.target.kind === "question") {
|
||||||
return `User asked to elaborate on question ${quote(item.question.prompt)} with note ${quote(item.note)}`;
|
return `User asked to elaborate on question ${quote(item.question.prompt)}${answerContext} with note ${quote(item.note)}`;
|
||||||
}
|
}
|
||||||
if (!("option" in item)) {
|
if (!("option" in item)) {
|
||||||
return `User asked to elaborate on question ${quote(item.question.prompt)} with note ${quote(item.note)}`;
|
return `User asked to elaborate on question ${quote(item.question.prompt)}${answerContext} with note ${quote(item.note)}`;
|
||||||
}
|
}
|
||||||
return `User asked to elaborate on question ${quote(item.question.prompt)} option ${quote(item.option.label)} with note ${quote(item.note)}`;
|
return `User asked to elaborate on question ${quote(item.question.prompt)} option ${quote(item.option.label)}${answerContext} with note ${quote(item.note)}`;
|
||||||
});
|
});
|
||||||
|
|
||||||
return lines.length > 0 ? lines : [ELABORATED_SUMMARY];
|
if (lines.length > 0) {
|
||||||
|
return lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
const answerLines = result.questions
|
||||||
|
.map((question) => {
|
||||||
|
const answer = result.answers[question.id];
|
||||||
|
return answer?.labels.length
|
||||||
|
? `User asked to elaborate on question ${quote(question.prompt)} after current answer ${quote(answer.labels.join(", "))}`
|
||||||
|
: undefined;
|
||||||
|
})
|
||||||
|
.filter((line): line is string => Boolean(line));
|
||||||
|
|
||||||
|
return answerLines.length > 0 ? answerLines : [ELABORATED_SUMMARY];
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatElaborationAnswerContext(
|
||||||
|
answer: AskResult["answers"][string] | undefined
|
||||||
|
): string {
|
||||||
|
const labels = answer?.labels ?? [];
|
||||||
|
if (labels.length === 0) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return ` after current answer ${quote(labels.join(", "))}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function quote(value: string): string {
|
function quote(value: string): string {
|
||||||
|
|||||||
@@ -334,6 +334,85 @@ test("elaborate results keep committed answers alongside elaboration context", (
|
|||||||
},
|
},
|
||||||
note: "Compare tradeoffs",
|
note: "Compare tradeoffs",
|
||||||
});
|
});
|
||||||
|
assert.equal(
|
||||||
|
summarizeResult(result),
|
||||||
|
'User asked to elaborate on question "Pick a framework" after current answer "Vue" with note "Compare tradeoffs"'
|
||||||
|
);
|
||||||
|
assert.equal(
|
||||||
|
renderResultText(result),
|
||||||
|
'User asked to elaborate on question "Pick a framework" after current answer "Vue" with note "Compare tradeoffs"'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("elaboration summary includes custom answers in note context", () => {
|
||||||
|
let state = createInitialState({
|
||||||
|
questions: [
|
||||||
|
{
|
||||||
|
id: "framework",
|
||||||
|
label: "Framework",
|
||||||
|
prompt: "Pick a framework",
|
||||||
|
options: [
|
||||||
|
{ value: "react", label: "React" },
|
||||||
|
{ value: "vue", label: "Vue" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
state = applyNumberShortcut(state, 3);
|
||||||
|
state = submitCustomAnswer(state, "SolidStart");
|
||||||
|
state = enterQuestionNoteMode(state, "framework");
|
||||||
|
state = saveNote(state, "Compare tradeoffs");
|
||||||
|
state = { ...state, mode: "elaborate" };
|
||||||
|
const result = toAskResult(state);
|
||||||
|
|
||||||
|
assert.equal(
|
||||||
|
summarizeResult(result),
|
||||||
|
'User asked to elaborate on question "Pick a framework" after current answer "SolidStart" with note "Compare tradeoffs"'
|
||||||
|
);
|
||||||
|
assert.equal(
|
||||||
|
renderResultText(result),
|
||||||
|
'User asked to elaborate on question "Pick a framework" after current answer "SolidStart" with note "Compare tradeoffs"'
|
||||||
|
);
|
||||||
|
assert.deepEqual(result.elaboration?.items[0]?.answer, {
|
||||||
|
values: ["SolidStart"],
|
||||||
|
labels: ["SolidStart"],
|
||||||
|
indices: [],
|
||||||
|
customText: "SolidStart",
|
||||||
|
note: "Compare tradeoffs",
|
||||||
|
optionNotes: undefined,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("elaboration summary includes answered custom text even without notes", () => {
|
||||||
|
let state = createInitialState({
|
||||||
|
questions: [
|
||||||
|
{
|
||||||
|
id: "demo_goal",
|
||||||
|
label: "Goal",
|
||||||
|
prompt: "What kind of ask_user showcase would you like?",
|
||||||
|
options: [
|
||||||
|
{ value: "simple-demo", label: "Simple demo" },
|
||||||
|
{ value: "code-example", label: "Code example" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
state = applyNumberShortcut(state, 3);
|
||||||
|
state = submitCustomAnswer(state, "teeeel meee whyyyyy");
|
||||||
|
state = { ...state, mode: "elaborate" };
|
||||||
|
const result = toAskResult(state);
|
||||||
|
|
||||||
|
assert.equal(
|
||||||
|
summarizeResult(result),
|
||||||
|
'User asked to elaborate on question "What kind of ask_user showcase would you like?" after current answer "teeeel meee whyyyyy"'
|
||||||
|
);
|
||||||
|
assert.equal(
|
||||||
|
renderResultText(result),
|
||||||
|
'User asked to elaborate on question "What kind of ask_user showcase would you like?" after current answer "teeeel meee whyyyyy"'
|
||||||
|
);
|
||||||
|
assert.deepEqual(result.elaboration?.items, []);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("elaborate continuation preserves unrelated committed answers", () => {
|
test("elaborate continuation preserves unrelated committed answers", () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user