fix(collab-web): render the user-added note in ask tool cards
The ask tool stores the user-attached note in result details (note on the single-question shape, per-item note inside results[]), but the shared tool renderer dropped it: AskAnswer carried no note field and the card never rendered one. Extract and render it as a muted row so HTML exports and the collab guest view keep the user's context.
This commit is contained in:
@@ -2,6 +2,10 @@
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Fixed
|
||||
|
||||
- The ask tool card now renders the note the user attached to their answer; previously it was dropped from HTML exports and the collab guest view.
|
||||
|
||||
## [17.2.10] - 2026-08-06
|
||||
|
||||
### Changed
|
||||
|
||||
@@ -22,6 +22,8 @@ interface AskAnswer {
|
||||
id?: string;
|
||||
selectedOptions: string[];
|
||||
customInput?: string;
|
||||
/** Free-form note the user attached to the answer via the rich ask dialog. */
|
||||
note?: string;
|
||||
timedOut?: boolean;
|
||||
}
|
||||
|
||||
@@ -106,6 +108,7 @@ function answerOf(rec: Record<string, unknown>): AskAnswer {
|
||||
id: str(rec.id) ?? undefined,
|
||||
selectedOptions,
|
||||
customInput: str(rec.customInput) ?? undefined,
|
||||
note: str(rec.note) ?? undefined,
|
||||
timedOut: rec.timedOut === true,
|
||||
};
|
||||
}
|
||||
@@ -187,6 +190,11 @@ function QuestionBlock({ q, answer }: { q: AskQuestion; answer: AskAnswer | unde
|
||||
<span className="tv-ok-text">{answer.customInput}</span>
|
||||
</Row>
|
||||
)}
|
||||
{answer?.note !== undefined && (
|
||||
<Row k="note:">
|
||||
<span className="tv-muted">{answer.note}</span>
|
||||
</Row>
|
||||
)}
|
||||
{answer && answer.selectedOptions.length === 0 && answer.customInput === undefined && (
|
||||
<Row k="—">
|
||||
<span className="tv-warn-text">no selection</span>
|
||||
|
||||
@@ -152,3 +152,65 @@ describe("ToolView xd:// dispatches", () => {
|
||||
expect(html).not.toContain("tv-out-title");
|
||||
});
|
||||
});
|
||||
|
||||
describe("ToolView ask renderer", () => {
|
||||
const questions = [
|
||||
{
|
||||
id: "auth",
|
||||
question: "Which auth method?",
|
||||
options: [{ label: "JWT" }, { label: "OAuth2" }],
|
||||
},
|
||||
];
|
||||
|
||||
it("renders the user-added note from a single-question answer", () => {
|
||||
const html = renderToStaticMarkup(
|
||||
<ToolView
|
||||
name="ask"
|
||||
defaultOpen
|
||||
args={{ questions }}
|
||||
result={{
|
||||
content: [{ type: "text", text: "OAuth2 User added note: keep the redirect short-lived" }],
|
||||
details: {
|
||||
question: "Which auth method?",
|
||||
options: ["JWT", "OAuth2"],
|
||||
multi: false,
|
||||
selectedOptions: ["OAuth2"],
|
||||
note: "keep the redirect short-lived",
|
||||
},
|
||||
}}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(html).toContain('<span>OAuth2</span>');
|
||||
expect(html).toContain("keep the redirect short-lived");
|
||||
});
|
||||
|
||||
it("renders per-question notes from results[] answers", () => {
|
||||
const html = renderToStaticMarkup(
|
||||
<ToolView
|
||||
name="ask"
|
||||
defaultOpen
|
||||
args={{
|
||||
questions: [
|
||||
{ id: "db", question: "Storage backend?", options: [{ label: "SQLite" }, { label: "Postgres" }] },
|
||||
{ id: "cache", question: "Cache?", options: [{ label: "Redis" }, { label: "None" }] },
|
||||
],
|
||||
}}
|
||||
result={{
|
||||
content: [{ type: "text", text: "User answers:" }],
|
||||
details: {
|
||||
results: [
|
||||
{ id: "db", question: "Storage backend?", multi: false, selectedOptions: ["Postgres"], note: "managed instance" },
|
||||
{ id: "cache", question: "Cache?", multi: false, selectedOptions: ["Redis"] },
|
||||
],
|
||||
},
|
||||
}}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(html).toContain('<span>Postgres</span>');
|
||||
expect(html).toContain("managed instance");
|
||||
// The cache question answered without a note must not leak the db note.
|
||||
expect(html.match(/managed instance/g)?.length).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user