session-composer.ts 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. import type { Todo } from "@opencode-ai/sdk/v2"
  2. export const composerEvent = "opencode:e2e:composer"
  3. export type ComposerDriverState = {
  4. live?: boolean
  5. todos?: Array<Pick<Todo, "content" | "status" | "priority">>
  6. }
  7. export type ComposerProbeState = {
  8. mounted: boolean
  9. collapsed: boolean
  10. hidden: boolean
  11. count: number
  12. states: Todo["status"][]
  13. }
  14. type ComposerState = {
  15. driver?: ComposerDriverState
  16. probe?: ComposerProbeState
  17. }
  18. export type ComposerWindow = Window & {
  19. __opencode_e2e?: {
  20. composer?: {
  21. enabled?: boolean
  22. sessions?: Record<string, ComposerState>
  23. }
  24. }
  25. }
  26. const clone = (driver: ComposerDriverState) => ({
  27. live: driver.live,
  28. todos: driver.todos?.map((todo) => ({ ...todo })),
  29. })
  30. export const composerEnabled = () => {
  31. if (typeof window === "undefined") return false
  32. return (window as ComposerWindow).__opencode_e2e?.composer?.enabled === true
  33. }
  34. const root = () => {
  35. if (!composerEnabled()) return
  36. const state = (window as ComposerWindow).__opencode_e2e?.composer
  37. if (!state) return
  38. state.sessions ??= {}
  39. return state.sessions
  40. }
  41. export const composerDriver = (sessionID?: string) => {
  42. if (!sessionID) return
  43. const state = root()?.[sessionID]?.driver
  44. if (!state) return
  45. return clone(state)
  46. }
  47. export const composerProbe = (sessionID?: string) => {
  48. const set = (next: ComposerProbeState) => {
  49. if (!sessionID) return
  50. const sessions = root()
  51. if (!sessions) return
  52. const prev = sessions[sessionID] ?? {}
  53. sessions[sessionID] = {
  54. ...prev,
  55. probe: {
  56. ...next,
  57. states: [...next.states],
  58. },
  59. }
  60. }
  61. return {
  62. set,
  63. drop() {
  64. set({
  65. mounted: false,
  66. collapsed: false,
  67. hidden: true,
  68. count: 0,
  69. states: [],
  70. })
  71. },
  72. }
  73. }