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

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