session-timeline-reasoning-projection.spec.ts 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. import { expect, test } from "@playwright/test"
  2. import {
  3. assistantMessage,
  4. reasoningPart,
  5. setupTimeline,
  6. status,
  7. textPart,
  8. toolPart,
  9. userMessage,
  10. } from "../performance/timeline-stability/fixture"
  11. const profiles = [
  12. { name: "summaries off no reasoning", summaries: false, reasoning: "", other: false, thinking: true, body: false },
  13. {
  14. name: "summaries off reasoning heading",
  15. summaries: false,
  16. reasoning: "## Inspecting stability",
  17. other: false,
  18. thinking: true,
  19. body: false,
  20. },
  21. {
  22. name: "summaries off with visible tool",
  23. summaries: false,
  24. reasoning: "## Inspecting stability",
  25. other: true,
  26. thinking: true,
  27. body: false,
  28. },
  29. { name: "summaries on no content", summaries: true, reasoning: "", other: false, thinking: true, body: false },
  30. {
  31. name: "summaries on blank reasoning",
  32. summaries: true,
  33. reasoning: " ",
  34. other: false,
  35. thinking: true,
  36. body: false,
  37. },
  38. {
  39. name: "summaries on visible reasoning",
  40. summaries: true,
  41. reasoning: "## Inspecting stability",
  42. other: false,
  43. thinking: false,
  44. body: true,
  45. },
  46. {
  47. name: "summaries on visible tool no reasoning",
  48. summaries: true,
  49. reasoning: "",
  50. other: true,
  51. thinking: false,
  52. body: false,
  53. },
  54. ] as const
  55. for (const profile of profiles) {
  56. test(`projects busy reasoning profile ${profile.name}`, async ({ page }) => {
  57. const reasoningID = `prt_reasoning_matrix_${profiles.indexOf(profile)}`
  58. const parts = [
  59. ...(profile.reasoning ? [reasoningPart(reasoningID, profile.reasoning)] : []),
  60. ...(profile.other
  61. ? [toolPart(`prt_reasoning_tool_${profiles.indexOf(profile)}`, "skill", "running", { name: "inspect" })]
  62. : []),
  63. ]
  64. const timeline = await setupTimeline(page, {
  65. messages: [userMessage(), assistantMessage(parts, { completed: false })],
  66. settings: { showReasoningSummaries: profile.summaries },
  67. })
  68. await timeline.send(status("busy"), 150)
  69. await expect(page.locator('[data-timeline-row="Thinking"]')).toHaveCount(profile.thinking ? 1 : 0)
  70. await expect(page.locator(`[data-timeline-part-id="${reasoningID}"]`)).toHaveCount(profile.body ? 1 : 0)
  71. if (!profile.summaries && profile.reasoning.trim()) {
  72. await expect(page.getByText("Inspecting stability", { exact: true })).toBeVisible()
  73. }
  74. })
  75. }
  76. test("does not infer reasoning visibility from provider identity", async ({ page }) => {
  77. const timeline = await setupTimeline(page, {
  78. messages: [
  79. userMessage(),
  80. assistantMessage([textPart("prt_provider_text", "No reasoning payload")], { completed: false }),
  81. ],
  82. settings: { showReasoningSummaries: true },
  83. })
  84. await timeline.send(status("busy"), 150)
  85. await expect(page.locator('[data-timeline-row="Thinking"]')).toHaveCount(0)
  86. await expect(page.locator('[data-timeline-part-id*="reasoning"]')).toHaveCount(0)
  87. await expect(page.locator('[data-timeline-part-id="prt_provider_text"]')).toBeVisible()
  88. })