drive-mermaid-visual.ts 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. import { mkdir } from "node:fs/promises"
  2. import { defineScript, Effect, Llm } from "opencode-drive"
  3. const theme = Bun.env.DRIVE_THEME ?? "opencode"
  4. const output = Bun.env.DRIVE_SCREENSHOT ?? `artifacts/mermaid-${theme}.png`
  5. const animate = Bun.env.DRIVE_ANIMATE === "1"
  6. const cycleThemes = Bun.env.DRIVE_CYCLE_THEMES === "1"
  7. const response = `\`\`\`mermaid
  8. sequenceDiagram
  9. participant B as Browser
  10. participant S as Server
  11. participant T as Ticket store
  12. participant P as PTY
  13. B->>S: GET /
  14. S-->>B: 401 WWW-Auth
  15. Note over B,S: native browser Basic prompt
  16. B->>S: GET / · Basic
  17. S-->>B: 200 web UI
  18. Note over B,S: user opens terminal
  19. B->>S: POST connect-token<br/>· Basic (cached by browser)<br/>· X-OpenCode-Ticket: 1
  20. S->>T: issue { ptyID, … }
  21. S-->>B: { ticket }
  22. B->>S: WS …?ticket=…<br/>Upgrade: websocket
  23. S->>T: consume(token,scope)
  24. T-->>S: ok, delete
  25. S->>P: attach
  26. P-->>B: WS frames
  27. \`\`\``
  28. export default defineScript({
  29. config: {
  30. autoupdate: false,
  31. },
  32. tuiConfig: {
  33. theme: {
  34. name: theme,
  35. mode: "dark",
  36. },
  37. },
  38. tui: {
  39. viewport: { cols: 180, rows: 64 },
  40. },
  41. run: ({ ui, llm }) =>
  42. Effect.gen(function* () {
  43. yield* ui.submit("Show the connection flow as a Mermaid sequence diagram")
  44. yield* llm.send(
  45. Llm.text(response, animate ? { delay: 80, chunkSize: 20 } : { delay: 0, chunkSize: response.length }),
  46. )
  47. yield* ui.waitFor("WS frames", { timeout: 10_000 })
  48. if (cycleThemes) {
  49. yield* Effect.sleep(800)
  50. yield* Effect.forEach(
  51. ["everforest", "synthwave84", "matrix", "opencode"],
  52. (next) =>
  53. Effect.gen(function* () {
  54. yield* ui.press("x", { ctrl: true })
  55. yield* ui.press("t")
  56. yield* ui.waitFor("Themes")
  57. yield* ui.type(next)
  58. yield* Effect.sleep(700)
  59. yield* ui.enter()
  60. yield* Effect.sleep(1_200)
  61. }),
  62. { discard: true },
  63. )
  64. }
  65. const screenshot = yield* ui.screenshot(`mermaid-${theme}`)
  66. yield* Effect.promise(async () => {
  67. await mkdir("artifacts", { recursive: true })
  68. await Bun.write(output, Bun.file(screenshot))
  69. })
  70. yield* Effect.log(`Saved ${output}`)
  71. }),
  72. })