Răsfoiți Sursa

refactor(ui): isolate session components (#33670)

Victor Navarro 1 lună în urmă
părinte
comite
04c1730c90
100 a modificat fișierele cu 239 adăugiri și 115 ștergeri
  1. 2 0
      .github/workflows/storybook.yml
  2. 51 2
      bun.lock
  3. 1 0
      packages/app/package.json
  4. 1 1
      packages/app/src/app.tsx
  5. 2 2
      packages/app/src/components/session/session-context-tab.tsx
  6. 1 1
      packages/app/src/context/global-sync/bootstrap.test.ts
  7. 1 1
      packages/app/src/context/global-sync/bootstrap.ts
  8. 1 1
      packages/app/src/context/global-sync/child-store.test.ts
  9. 1 1
      packages/app/src/context/global-sync/child-store.ts
  10. 1 1
      packages/app/src/context/global-sync/types.ts
  11. 1 1
      packages/app/src/context/global-sync/utils.ts
  12. 2 1
      packages/app/src/context/server-sync.tsx
  13. 1 0
      packages/app/src/index.css
  14. 1 1
      packages/app/src/pages/directory-layout.tsx
  15. 1 1
      packages/app/src/pages/home.tsx
  16. 1 1
      packages/app/src/pages/layout/session-tab-avatar.tsx
  17. 1 1
      packages/app/src/pages/session.tsx
  18. 1 1
      packages/app/src/pages/session/composer/session-permission-dock.tsx
  19. 1 1
      packages/app/src/pages/session/composer/session-question-dock.tsx
  20. 0 0
      packages/app/src/pages/session/composer/todo-panel-motion.stories.tsx
  21. 3 3
      packages/app/src/pages/session/file-tabs.tsx
  22. 2 2
      packages/app/src/pages/session/review-tab.tsx
  23. 3 3
      packages/app/src/pages/session/timeline/message-timeline.tsx
  24. 1 1
      packages/app/src/pages/session/timeline/rows.ts
  25. 1 1
      packages/app/src/pages/session/use-session-commands.tsx
  26. 1 0
      packages/enterprise/package.json
  27. 1 0
      packages/enterprise/src/app.css
  28. 6 6
      packages/enterprise/src/routes/share/[shareID].tsx
  29. 67 0
      packages/session-ui/package.json
  30. 0 0
      packages/session-ui/src/components/apply-patch-file.test.ts
  31. 0 0
      packages/session-ui/src/components/apply-patch-file.ts
  32. 0 0
      packages/session-ui/src/components/basic-tool.css
  33. 1 1
      packages/session-ui/src/components/basic-tool.stories.tsx
  34. 4 4
      packages/session-ui/src/components/basic-tool.tsx
  35. 1 1
      packages/session-ui/src/components/dock-prompt.stories.tsx
  36. 1 1
      packages/session-ui/src/components/dock-prompt.tsx
  37. 1 1
      packages/session-ui/src/components/file-media.tsx
  38. 2 2
      packages/session-ui/src/components/file-search.tsx
  39. 1 1
      packages/session-ui/src/components/file-ssr.tsx
  40. 0 0
      packages/session-ui/src/components/file.css
  41. 0 0
      packages/session-ui/src/components/file.tsx
  42. 1 1
      packages/session-ui/src/components/line-comment-annotations.tsx
  43. 0 0
      packages/session-ui/src/components/line-comment-styles.ts
  44. 0 0
      packages/session-ui/src/components/line-comment.stories.tsx
  45. 4 4
      packages/session-ui/src/components/line-comment.tsx
  46. 0 0
      packages/session-ui/src/components/markdown-cache.tsx
  47. 0 0
      packages/session-ui/src/components/markdown-code-state.test.ts
  48. 0 0
      packages/session-ui/src/components/markdown-code-state.ts
  49. 0 0
      packages/session-ui/src/components/markdown-preload.test.ts
  50. 0 0
      packages/session-ui/src/components/markdown-shiki.worker.ts
  51. 0 0
      packages/session-ui/src/components/markdown-stream.test.ts
  52. 0 0
      packages/session-ui/src/components/markdown-stream.ts
  53. 0 0
      packages/session-ui/src/components/markdown-worker-protocol.test.ts
  54. 0 0
      packages/session-ui/src/components/markdown-worker-protocol.ts
  55. 0 0
      packages/session-ui/src/components/markdown-worker-queue.test.ts
  56. 0 0
      packages/session-ui/src/components/markdown-worker-queue.ts
  57. 0 0
      packages/session-ui/src/components/markdown-worker-transport.test.ts
  58. 0 0
      packages/session-ui/src/components/markdown-worker-transport.ts
  59. 1 1
      packages/session-ui/src/components/markdown-worker.ts
  60. 0 0
      packages/session-ui/src/components/markdown.css
  61. 2 2
      packages/session-ui/src/components/markdown.stories.tsx
  62. 2 2
      packages/session-ui/src/components/markdown.tsx
  63. 0 0
      packages/session-ui/src/components/message-file.test.ts
  64. 0 0
      packages/session-ui/src/components/message-file.ts
  65. 0 0
      packages/session-ui/src/components/message-nav.css
  66. 1 1
      packages/session-ui/src/components/message-nav.stories.tsx
  67. 2 2
      packages/session-ui/src/components/message-nav.tsx
  68. 0 0
      packages/session-ui/src/components/message-part-text.ts
  69. 0 0
      packages/session-ui/src/components/message-part.css
  70. 1 1
      packages/session-ui/src/components/message-part.stories.tsx
  71. 0 0
      packages/session-ui/src/components/message-part.test.ts
  72. 16 16
      packages/session-ui/src/components/message-part.tsx
  73. 0 0
      packages/session-ui/src/components/session-diff.test.ts
  74. 0 0
      packages/session-ui/src/components/session-diff.ts
  75. 4 4
      packages/session-ui/src/components/session-retry.tsx
  76. 0 0
      packages/session-ui/src/components/session-review.css
  77. 1 1
      packages/session-ui/src/components/session-review.stories.tsx
  78. 13 13
      packages/session-ui/src/components/session-review.tsx
  79. 0 0
      packages/session-ui/src/components/session-turn.css
  80. 1 1
      packages/session-ui/src/components/session-turn.stories.tsx
  81. 10 10
      packages/session-ui/src/components/session-turn.tsx
  82. 0 0
      packages/session-ui/src/components/shell-submessage-motion.stories.tsx
  83. 0 0
      packages/session-ui/src/components/shell-submessage.css
  84. 2 2
      packages/session-ui/src/components/timeline-playground.stories.tsx
  85. 0 0
      packages/session-ui/src/components/tool-count-label.css
  86. 1 1
      packages/session-ui/src/components/tool-count-label.tsx
  87. 0 0
      packages/session-ui/src/components/tool-count-summary.css
  88. 0 0
      packages/session-ui/src/components/tool-count-summary.stories.tsx
  89. 0 0
      packages/session-ui/src/components/tool-count-summary.tsx
  90. 0 0
      packages/session-ui/src/components/tool-error-card.css
  91. 0 0
      packages/session-ui/src/components/tool-error-card.stories.tsx
  92. 6 6
      packages/session-ui/src/components/tool-error-card.tsx
  93. 0 0
      packages/session-ui/src/components/tool-status-title.css
  94. 1 1
      packages/session-ui/src/components/tool-status-title.tsx
  95. 1 1
      packages/session-ui/src/context/data.tsx
  96. 1 0
      packages/session-ui/src/context/index.ts
  97. 0 0
      packages/session-ui/src/pierre/comment-hover.ts
  98. 0 0
      packages/session-ui/src/pierre/commented-lines.ts
  99. 0 0
      packages/session-ui/src/pierre/diff-selection.ts
  100. 0 0
      packages/session-ui/src/pierre/file-find.ts

+ 2 - 0
.github/workflows/storybook.yml

@@ -9,6 +9,7 @@ on:
       - "bun.lock"
       - "packages/storybook/**"
       - "packages/ui/**"
+      - "packages/session-ui/**"
   pull_request:
     branches: [dev]
     paths:
@@ -17,6 +18,7 @@ on:
       - "bun.lock"
       - "packages/storybook/**"
       - "packages/ui/**"
+      - "packages/session-ui/**"
   workflow_dispatch:
 
 concurrency:

+ 51 - 2
bun.lock

@@ -34,6 +34,7 @@
         "@kobalte/core": "catalog:",
         "@opencode-ai/core": "workspace:*",
         "@opencode-ai/sdk": "workspace:*",
+        "@opencode-ai/session-ui": "workspace:*",
         "@opencode-ai/ui": "workspace:*",
         "@pierre/trees": "1.0.0-beta.4",
         "@sentry/solid": "catalog:",
@@ -417,6 +418,7 @@
       "dependencies": {
         "@hono/standard-validator": "catalog:",
         "@opencode-ai/core": "workspace:*",
+        "@opencode-ai/session-ui": "workspace:*",
         "@opencode-ai/ui": "workspace:*",
         "@pierre/diffs": "catalog:",
         "@solidjs/meta": "catalog:",
@@ -703,6 +705,50 @@
         "@typescript/native-preview": "catalog:",
       },
     },
+    "packages/session-ui": {
+      "name": "@opencode-ai/session-ui",
+      "version": "1.17.9",
+      "dependencies": {
+        "@kobalte/core": "catalog:",
+        "@opencode-ai/core": "workspace:*",
+        "@opencode-ai/sdk": "workspace:*",
+        "@opencode-ai/ui": "workspace:*",
+        "@pierre/diffs": "catalog:",
+        "@shikijs/stream": "catalog:",
+        "@shikijs/transformers": "3.9.2",
+        "@solid-primitives/bounds": "0.1.3",
+        "@solid-primitives/event-listener": "2.4.5",
+        "@solid-primitives/media": "2.3.3",
+        "@solid-primitives/resize-observer": "2.1.3",
+        "@solidjs/meta": "catalog:",
+        "@solidjs/router": "catalog:",
+        "diff": "catalog:",
+        "dompurify": "3.3.1",
+        "fuzzysort": "catalog:",
+        "katex": "0.16.27",
+        "luxon": "catalog:",
+        "marked": "catalog:",
+        "marked-katex-extension": "5.1.6",
+        "marked-shiki": "catalog:",
+        "morphdom": "2.7.8",
+        "motion": "12.34.5",
+        "remeda": "catalog:",
+        "remend": "catalog:",
+        "shiki": "catalog:",
+        "solid-js": "catalog:",
+        "solid-list": "catalog:",
+        "strip-ansi": "7.1.2",
+      },
+      "devDependencies": {
+        "@tsconfig/node22": "catalog:",
+        "@types/bun": "catalog:",
+        "@types/katex": "0.16.7",
+        "@types/luxon": "catalog:",
+        "@typescript/native-preview": "catalog:",
+        "typescript": "catalog:",
+        "vite": "catalog:",
+      },
+    },
     "packages/slack": {
       "name": "@opencode-ai/slack",
       "version": "1.17.9",
@@ -789,6 +835,7 @@
     "packages/storybook": {
       "name": "@opencode-ai/storybook",
       "devDependencies": {
+        "@opencode-ai/session-ui": "workspace:*",
         "@opencode-ai/ui": "workspace:*",
         "@solidjs/meta": "catalog:",
         "@storybook/addon-a11y": "^10.2.13",
@@ -840,8 +887,6 @@
       "version": "1.17.9",
       "dependencies": {
         "@kobalte/core": "catalog:",
-        "@opencode-ai/core": "workspace:*",
-        "@opencode-ai/sdk": "workspace:*",
         "@pierre/diffs": "catalog:",
         "@shikijs/stream": "catalog:",
         "@shikijs/transformers": "3.9.2",
@@ -1825,6 +1870,8 @@
 
     "@opencode-ai/server": ["@opencode-ai/server@workspace:packages/server"],
 
+    "@opencode-ai/session-ui": ["@opencode-ai/session-ui@workspace:packages/session-ui"],
+
     "@opencode-ai/slack": ["@opencode-ai/slack@workspace:packages/slack"],
 
     "@opencode-ai/stats-app": ["@opencode-ai/stats-app@workspace:packages/stats/app"],
@@ -5843,6 +5890,8 @@
 
     "@opencode-ai/llm/@smithy/util-utf8": ["@smithy/util-utf8@4.2.2", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-75MeYpjdWRe8M5E3AW0O4Cx3UadweS+cwdXjwYGBW5h/gxxnbeZ877sLPX/ZJA9GVTlL/qG0dXP29JWFCD1Ayw=="],
 
+    "@opencode-ai/session-ui/@solid-primitives/resize-observer": ["@solid-primitives/resize-observer@2.1.3", "", { "dependencies": { "@solid-primitives/event-listener": "^2.4.3", "@solid-primitives/rootless": "^1.5.2", "@solid-primitives/static-store": "^0.1.2", "@solid-primitives/utils": "^6.3.2" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-zBLje5E06TgOg93S7rGPldmhDnouNGhvfZVKOp+oG2XU8snA+GoCSSCz1M+jpNAg5Ek2EakU5UVQqL152WmdXQ=="],
+
     "@opencode-ai/ui/@solid-primitives/resize-observer": ["@solid-primitives/resize-observer@2.1.3", "", { "dependencies": { "@solid-primitives/event-listener": "^2.4.3", "@solid-primitives/rootless": "^1.5.2", "@solid-primitives/static-store": "^0.1.2", "@solid-primitives/utils": "^6.3.2" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-zBLje5E06TgOg93S7rGPldmhDnouNGhvfZVKOp+oG2XU8snA+GoCSSCz1M+jpNAg5Ek2EakU5UVQqL152WmdXQ=="],
 
     "@opencode-ai/web/@shikijs/transformers": ["@shikijs/transformers@3.20.0", "", { "dependencies": { "@shikijs/core": "3.20.0", "@shikijs/types": "3.20.0" } }, "sha512-PrHHMRr3Q5W1qB/42kJW6laqFyWdhrPF2hNR9qjOm1xcSiAO3hAHo7HaVyHE6pMyevmy3i51O8kuGGXC78uK3g=="],

+ 1 - 0
packages/app/package.json

@@ -47,6 +47,7 @@
     "@kobalte/core": "catalog:",
     "@opencode-ai/core": "workspace:*",
     "@opencode-ai/sdk": "workspace:*",
+    "@opencode-ai/session-ui": "workspace:*",
     "@opencode-ai/ui": "workspace:*",
     "@pierre/trees": "1.0.0-beta.4",
     "@sentry/solid": "catalog:",

+ 1 - 1
packages/app/src/app.tsx

@@ -4,7 +4,7 @@ import { I18nProvider } from "@opencode-ai/ui/context"
 import { DialogProvider } from "@opencode-ai/ui/context/dialog"
 import { FileComponentProvider } from "@opencode-ai/ui/context/file"
 import { MarkedProvider } from "@opencode-ai/ui/context/marked"
-import { File } from "@opencode-ai/ui/file"
+import { File } from "@opencode-ai/session-ui/file"
 import { Font } from "@opencode-ai/ui/font"
 import { Splash } from "@opencode-ai/ui/logo"
 import { ThemeProvider } from "@opencode-ai/ui/theme/context"

+ 2 - 2
packages/app/src/components/session/session-context-tab.tsx

@@ -7,8 +7,8 @@ import { same } from "@/utils/same"
 import { Icon } from "@opencode-ai/ui/icon"
 import { Accordion } from "@opencode-ai/ui/accordion"
 import { StickyAccordionHeader } from "@opencode-ai/ui/sticky-accordion-header"
-import { File } from "@opencode-ai/ui/file"
-import { Markdown } from "@opencode-ai/ui/markdown"
+import { File } from "@opencode-ai/session-ui/file"
+import { Markdown } from "@opencode-ai/session-ui/markdown"
 import { ScrollView } from "@opencode-ai/ui/scroll-view"
 import type { Message, Part, UserMessage } from "@opencode-ai/sdk/v2/client"
 import { useLanguage } from "@/context/language"

+ 1 - 1
packages/app/src/context/global-sync/bootstrap.test.ts

@@ -2,7 +2,7 @@ import { describe, expect, test } from "bun:test"
 import { createStore } from "solid-js/store"
 import { QueryClient } from "@tanstack/solid-query"
 import type { Config, OpencodeClient, Project } from "@opencode-ai/sdk/v2/client"
-import type { NormalizedProviderListResponse } from "@opencode-ai/ui/context"
+import type { NormalizedProviderListResponse } from "@opencode-ai/session-ui/context"
 import { bootstrapDirectory, loadPathQuery, loadProvidersQuery } from "./bootstrap"
 import type { State, VcsCache } from "./types"
 import { ServerScope } from "@/utils/server-scope"

+ 1 - 1
packages/app/src/context/global-sync/bootstrap.ts

@@ -19,7 +19,7 @@ import { cmp, normalizeAgentList, normalizeProviderList } from "./utils"
 import { formatServerError } from "@/utils/server-errors"
 import { QueryClient, queryOptions } from "@tanstack/solid-query"
 import { loadMcpQuery } from "../server-sync"
-import { NormalizedProviderListResponse } from "@opencode-ai/ui/context"
+import { NormalizedProviderListResponse } from "@opencode-ai/session-ui/context"
 import { ScopedKey, type ServerScope } from "@/utils/server-scope"
 
 type GlobalStore = {

+ 1 - 1
packages/app/src/context/global-sync/child-store.test.ts

@@ -1,7 +1,7 @@
 import { beforeAll, describe, expect, mock, test } from "bun:test"
 import { createRoot, getOwner, type Owner } from "solid-js"
 import { createStore } from "solid-js/store"
-import type { NormalizedProviderListResponse } from "@opencode-ai/ui/context"
+import type { NormalizedProviderListResponse } from "@opencode-ai/session-ui/context"
 import type { State } from "./types"
 import type { QueryOptionsApi } from "../server-sync"
 import { ServerScope } from "@/utils/server-scope"

+ 1 - 1
packages/app/src/context/global-sync/child-store.ts

@@ -17,7 +17,7 @@ import { canDisposeDirectory, pickDirectoriesToEvict } from "./eviction"
 import { useQuery } from "@tanstack/solid-query"
 import { QueryOptionsApi } from "../server-sync"
 import { directoryKey, type DirectoryKey } from "./utils"
-import { NormalizedProviderListResponse } from "@opencode-ai/ui/context"
+import { NormalizedProviderListResponse } from "@opencode-ai/session-ui/context"
 import type { ServerScope } from "@/utils/server-scope"
 
 export function createChildStoreManager(input: {

+ 1 - 1
packages/app/src/context/global-sync/types.ts

@@ -15,7 +15,7 @@ import type {
   Todo,
   VcsInfo,
 } from "@opencode-ai/sdk/v2/client"
-import { NormalizedProviderListResponse } from "@opencode-ai/ui/context"
+import { NormalizedProviderListResponse } from "@opencode-ai/session-ui/context"
 import type { Accessor } from "solid-js"
 import type { SetStoreFunction, Store } from "solid-js/store"
 

+ 1 - 1
packages/app/src/context/global-sync/utils.ts

@@ -1,5 +1,5 @@
 import type { Agent, Project, ProviderListResponse } from "@opencode-ai/sdk/v2/client"
-import { NormalizedProviderListResponse } from "@opencode-ai/ui/context"
+import { NormalizedProviderListResponse } from "@opencode-ai/session-ui/context"
 export { pathKey as directoryKey, type PathKey as DirectoryKey } from "@/utils/path-key"
 
 export const cmp = (a: string, b: string) => (a < b ? -1 : a > b ? 1 : 0)

+ 2 - 1
packages/app/src/context/server-sync.tsx

@@ -29,7 +29,8 @@ import { createRefreshQueue } from "./global-sync/queue"
 import { directoryKey } from "./global-sync/utils"
 import { PathKey } from "@/utils/path-key"
 import { createDirSyncContext } from "./directory-sync"
-import { createSimpleContext, NormalizedProviderListResponse } from "@opencode-ai/ui/context"
+import { createSimpleContext } from "@opencode-ai/ui/context"
+import { NormalizedProviderListResponse } from "@opencode-ai/session-ui/context"
 import { createRefCountMap } from "@/utils/refcount"
 import { useGlobal } from "./global"
 import { ServerConnection, useServer } from "./server"

+ 1 - 0
packages/app/src/index.css

@@ -1,4 +1,5 @@
 @import "@opencode-ai/ui/styles/tailwind";
+@import "@opencode-ai/session-ui/styles";
 @import "@opencode-ai/ui/v2/styles/tailwind.css";
 
 @font-face {

+ 1 - 1
packages/app/src/pages/directory-layout.tsx

@@ -1,4 +1,4 @@
-import { DataProvider } from "@opencode-ai/ui/context"
+import { DataProvider } from "@opencode-ai/session-ui/context"
 import { showToast } from "@/utils/toast"
 import { base64Encode } from "@opencode-ai/core/util/encode"
 import { useLocation, useNavigate, useParams } from "@solidjs/router"

+ 1 - 1
packages/app/src/pages/home.tsx

@@ -60,7 +60,7 @@ import { ServerHealthIndicator } from "@/components/server/server-row"
 import { type ServerHealth } from "@/utils/server-health"
 import { Persist, persisted } from "@/utils/persist"
 import { useMarked } from "@opencode-ai/ui/context/marked"
-import { preloadMarkdown } from "@opencode-ai/ui/markdown-cache"
+import { preloadMarkdown } from "@opencode-ai/session-ui/markdown-cache"
 
 const HOME_SESSION_LIMIT = 64
 const HOME_ROW_LAYOUT =

+ 1 - 1
packages/app/src/pages/layout/session-tab-avatar.tsx

@@ -3,7 +3,7 @@ import { getProjectAvatarVariant } from "@/context/layout"
 import { displayName, getProjectAvatarSource } from "@/pages/layout/helpers"
 import { useSessionTabAvatarState } from "@/pages/layout/project-avatar-state"
 import { ProjectAvatar } from "@opencode-ai/ui/v2/project-avatar-v2"
-import { SessionProgressIndicatorV2 } from "@opencode-ai/ui/v2/session-progress-indicator-v2"
+import { SessionProgressIndicatorV2 } from "@opencode-ai/session-ui/v2/session-progress-indicator-v2"
 import { Show } from "solid-js"
 
 export function SessionTabAvatar(props: {

+ 1 - 1
packages/app/src/pages/session.tsx

@@ -25,7 +25,7 @@ import { ResizeHandle } from "@opencode-ai/ui/resize-handle"
 import { Select } from "@opencode-ai/ui/select"
 import { Tabs } from "@opencode-ai/ui/tabs"
 import { createAutoScroll } from "@opencode-ai/ui/hooks"
-import { previewSelectedLines } from "@opencode-ai/ui/pierre/selection-bridge"
+import { previewSelectedLines } from "@opencode-ai/session-ui/pierre/selection-bridge"
 import { Button } from "@opencode-ai/ui/button"
 import { showToast } from "@/utils/toast"
 import { base64Encode, checksum } from "@opencode-ai/core/util/encode"

+ 1 - 1
packages/app/src/pages/session/composer/session-permission-dock.tsx

@@ -1,7 +1,7 @@
 import { For, Show } from "solid-js"
 import type { PermissionRequest } from "@opencode-ai/sdk/v2"
 import { Button } from "@opencode-ai/ui/button"
-import { DockPrompt } from "@opencode-ai/ui/dock-prompt"
+import { DockPrompt } from "@opencode-ai/session-ui/dock-prompt"
 import { Icon } from "@opencode-ai/ui/icon"
 import { useLanguage } from "@/context/language"
 

+ 1 - 1
packages/app/src/pages/session/composer/session-question-dock.tsx

@@ -2,7 +2,7 @@ import { For, Show, createMemo, onCleanup, onMount, type Component } from "solid
 import { createStore } from "solid-js/store"
 import { useMutation } from "@tanstack/solid-query"
 import { Button } from "@opencode-ai/ui/button"
-import { DockPrompt } from "@opencode-ai/ui/dock-prompt"
+import { DockPrompt } from "@opencode-ai/session-ui/dock-prompt"
 import { Icon } from "@opencode-ai/ui/icon"
 import { showToast } from "@/utils/toast"
 import type { QuestionAnswer, QuestionRequest } from "@opencode-ai/sdk/v2"

+ 0 - 0
packages/ui/src/components/todo-panel-motion.stories.tsx → packages/app/src/pages/session/composer/todo-panel-motion.stories.tsx


+ 3 - 3
packages/app/src/pages/session/file-tabs.tsx

@@ -2,10 +2,10 @@ import { createEffect, createMemo, createSignal, Match, on, onCleanup, Switch }
 import { createStore } from "solid-js/store"
 import { Dynamic } from "solid-js/web"
 import { makeEventListener } from "@solid-primitives/event-listener"
-import type { FileSearchHandle } from "@opencode-ai/ui/file"
+import type { FileSearchHandle } from "@opencode-ai/session-ui/file"
 import { useFileComponent } from "@opencode-ai/ui/context/file"
-import { cloneSelectedLineRange, previewSelectedLines } from "@opencode-ai/ui/pierre/selection-bridge"
-import { createLineCommentController } from "@opencode-ai/ui/line-comment-annotations"
+import { cloneSelectedLineRange, previewSelectedLines } from "@opencode-ai/session-ui/pierre/selection-bridge"
+import { createLineCommentController } from "@opencode-ai/session-ui/line-comment-annotations"
 import { sampledChecksum } from "@opencode-ai/core/util/encode"
 import { DropdownMenu } from "@opencode-ai/ui/dropdown-menu"
 import { IconButton } from "@opencode-ai/ui/icon-button"

+ 2 - 2
packages/app/src/pages/session/review-tab.tsx

@@ -1,12 +1,12 @@
 import { createEffect, onCleanup, type JSX } from "solid-js"
 import { makeEventListener } from "@solid-primitives/event-listener"
 import type { SnapshotFileDiff, VcsFileDiff } from "@opencode-ai/sdk/v2"
-import { SessionReview } from "@opencode-ai/ui/session-review"
+import { SessionReview } from "@opencode-ai/session-ui/session-review"
 import type {
   SessionReviewCommentActions,
   SessionReviewCommentDelete,
   SessionReviewCommentUpdate,
-} from "@opencode-ai/ui/session-review"
+} from "@opencode-ai/session-ui/session-review"
 import type { SelectedLineRange } from "@/context/file"
 import { useSDK } from "@/context/sdk"
 import { useLayout } from "@/context/layout"

+ 3 - 3
packages/app/src/pages/session/timeline/message-timeline.tsx

@@ -26,7 +26,7 @@ import {
   Part as MessagePart,
   partDefaultOpen,
   type UserActions,
-} from "@opencode-ai/ui/message-part"
+} from "@opencode-ai/session-ui/message-part"
 import { DiffChanges } from "@opencode-ai/ui/diff-changes"
 import { FileIcon } from "@opencode-ai/ui/file-icon"
 import { Icon } from "@opencode-ai/ui/icon"
@@ -35,7 +35,7 @@ import { DropdownMenu } from "@opencode-ai/ui/dropdown-menu"
 import { Dialog } from "@opencode-ai/ui/dialog"
 import { InlineInput } from "@opencode-ai/ui/inline-input"
 import { Spinner } from "@opencode-ai/ui/spinner"
-import { SessionRetry } from "@opencode-ai/ui/session-retry"
+import { SessionRetry } from "@opencode-ai/session-ui/session-retry"
 import { ScrollView } from "@opencode-ai/ui/scroll-view"
 import { StickyAccordionHeader } from "@opencode-ai/ui/sticky-accordion-header"
 import { TextField } from "@opencode-ai/ui/text-field"
@@ -51,7 +51,7 @@ import type {
 import { showToast } from "@/utils/toast"
 import { getDirectory, getFilename } from "@opencode-ai/core/util/path"
 import { Popover as KobaltePopover } from "@kobalte/core/popover"
-import { normalize } from "@opencode-ai/ui/session-diff"
+import { normalize } from "@opencode-ai/session-ui/session-diff"
 import { useFileComponent } from "@opencode-ai/ui/context/file"
 import { shouldMarkBoundaryGesture, normalizeWheelDelta } from "@/pages/session/message-gesture"
 import { SessionContextUsage } from "@/components/session-context-usage"

+ 1 - 1
packages/app/src/pages/session/timeline/rows.ts

@@ -1,6 +1,6 @@
 import { parseCommentNote, readCommentMetadata } from "@/utils/comment-note"
 import { AssistantMessage, Part, SessionStatus, SnapshotFileDiff, UserMessage } from "@opencode-ai/sdk/v2"
-import { groupParts, PartGroup, renderable } from "@opencode-ai/ui/message-part"
+import { groupParts, PartGroup, renderable } from "@opencode-ai/session-ui/message-part"
 import { Data, Equal } from "effect"
 
 export type SummaryDiff = SnapshotFileDiff & { file: string }

+ 1 - 1
packages/app/src/pages/session/use-session-commands.tsx

@@ -1,7 +1,7 @@
 import { useNavigate } from "@solidjs/router"
 import { useCommand, type CommandOption } from "@/context/command"
 import { useDialog } from "@opencode-ai/ui/context/dialog"
-import { previewSelectedLines } from "@opencode-ai/ui/pierre/selection-bridge"
+import { previewSelectedLines } from "@opencode-ai/session-ui/pierre/selection-bridge"
 import { useFile, selectionFromLines, type FileSelection, type SelectedLineRange } from "@/context/file"
 import { useLanguage } from "@/context/language"
 import { useLayout } from "@/context/layout"

+ 1 - 0
packages/enterprise/package.json

@@ -14,6 +14,7 @@
   },
   "dependencies": {
     "@opencode-ai/core": "workspace:*",
+    "@opencode-ai/session-ui": "workspace:*",
     "@opencode-ai/ui": "workspace:*",
     "aws4fetch": "^1.0.20",
     "@pierre/diffs": "catalog:",

+ 1 - 0
packages/enterprise/src/app.css

@@ -1 +1,2 @@
 @import "@opencode-ai/ui/styles/tailwind";
+@import "@opencode-ai/session-ui/styles";

+ 6 - 6
packages/enterprise/src/routes/share/[shareID].tsx

@@ -1,7 +1,7 @@
 import { Message, Model, Part, Session, SessionStatus, SnapshotFileDiff, UserMessage } from "@opencode-ai/sdk/v2"
-import { SessionTurn } from "@opencode-ai/ui/session-turn"
-import { SessionReview } from "@opencode-ai/ui/session-review"
-import { DataProvider } from "@opencode-ai/ui/context"
+import { SessionTurn } from "@opencode-ai/session-ui/session-turn"
+import { SessionReview } from "@opencode-ai/session-ui/session-review"
+import { DataProvider } from "@opencode-ai/session-ui/context"
 import { FileComponentProvider } from "@opencode-ai/ui/context/file"
 import { WorkerPoolProvider } from "@opencode-ai/ui/context/worker-pool"
 import { createAsync, query, useParams } from "@solidjs/router"
@@ -17,15 +17,15 @@ import { DateTime } from "luxon"
 import { createStore } from "solid-js/store"
 import NotFound from "../[...404]"
 import { Tabs } from "@opencode-ai/ui/tabs"
-import { MessageNav } from "@opencode-ai/ui/message-nav"
-import { FileSSR } from "@opencode-ai/ui/file-ssr"
+import { MessageNav } from "@opencode-ai/session-ui/message-nav"
+import { FileSSR } from "@opencode-ai/session-ui/file-ssr"
 import { clientOnly } from "@solidjs/start"
 import { Meta, Title } from "@solidjs/meta"
 import { Base64 } from "js-base64"
 import { getRequestEvent } from "solid-js/web"
 
 const ClientOnlyWorkerPoolProvider = clientOnly(() =>
-  import("@opencode-ai/ui/pierre/worker").then((m) => ({
+  import("@opencode-ai/session-ui/pierre/worker").then((m) => ({
     default: (props: { children: any }) => (
       <WorkerPoolProvider pools={m.getWorkerPools()}>{props.children}</WorkerPoolProvider>
     ),

+ 67 - 0
packages/session-ui/package.json

@@ -0,0 +1,67 @@
+{
+  "name": "@opencode-ai/session-ui",
+  "version": "1.17.9",
+  "private": true,
+  "type": "module",
+  "license": "MIT",
+  "exports": {
+    "./*": "./src/components/*.tsx",
+    "./session-diff": "./src/components/session-diff.ts",
+    "./message-file": "./src/components/message-file.ts",
+    "./message-part-text": "./src/components/message-part-text.ts",
+    "./markdown-stream": "./src/components/markdown-stream.ts",
+    "./markdown-cache": "./src/components/markdown-cache.tsx",
+    "./line-comment-styles": "./src/components/line-comment-styles.ts",
+    "./pierre": "./src/pierre/index.ts",
+    "./pierre/*": "./src/pierre/*.ts",
+    "./context": "./src/context/index.ts",
+    "./context/*": "./src/context/*.tsx",
+    "./styles": "./src/styles/index.css",
+    "./v2/*.css": "./src/v2/components/*.css",
+    "./v2/*": "./src/v2/components/*.tsx"
+  },
+  "scripts": {
+    "typecheck": "tsgo --noEmit",
+    "test": "bun test src --only-failures"
+  },
+  "devDependencies": {
+    "@tsconfig/node22": "catalog:",
+    "@types/bun": "catalog:",
+    "@types/katex": "0.16.7",
+    "@types/luxon": "catalog:",
+    "@typescript/native-preview": "catalog:",
+    "typescript": "catalog:",
+    "vite": "catalog:"
+  },
+  "dependencies": {
+    "@kobalte/core": "catalog:",
+    "@opencode-ai/core": "workspace:*",
+    "@opencode-ai/sdk": "workspace:*",
+    "@opencode-ai/ui": "workspace:*",
+    "@pierre/diffs": "catalog:",
+    "@shikijs/stream": "catalog:",
+    "@shikijs/transformers": "3.9.2",
+    "@solid-primitives/bounds": "0.1.3",
+    "@solid-primitives/event-listener": "2.4.5",
+    "@solid-primitives/media": "2.3.3",
+    "@solid-primitives/resize-observer": "2.1.3",
+    "@solidjs/meta": "catalog:",
+    "@solidjs/router": "catalog:",
+    "diff": "catalog:",
+    "dompurify": "3.3.1",
+    "fuzzysort": "catalog:",
+    "katex": "0.16.27",
+    "luxon": "catalog:",
+    "marked": "catalog:",
+    "marked-katex-extension": "5.1.6",
+    "marked-shiki": "catalog:",
+    "morphdom": "2.7.8",
+    "motion": "12.34.5",
+    "remeda": "catalog:",
+    "remend": "catalog:",
+    "shiki": "catalog:",
+    "solid-js": "catalog:",
+    "solid-list": "catalog:",
+    "strip-ansi": "7.1.2"
+  }
+}

+ 0 - 0
packages/ui/src/components/apply-patch-file.test.ts → packages/session-ui/src/components/apply-patch-file.test.ts


+ 0 - 0
packages/ui/src/components/apply-patch-file.ts → packages/session-ui/src/components/apply-patch-file.ts


+ 0 - 0
packages/ui/src/components/basic-tool.css → packages/session-ui/src/components/basic-tool.css


+ 1 - 1
packages/ui/src/components/basic-tool.stories.tsx → packages/session-ui/src/components/basic-tool.stories.tsx

@@ -1,7 +1,7 @@
 // @ts-nocheck
 import { createSignal } from "solid-js"
 import * as mod from "./basic-tool"
-import { create } from "../storybook/scaffold"
+import { create } from "@opencode-ai/ui/storybook/scaffold"
 
 const docs = `### Overview
 Expandable tool panel with a structured trigger and optional details.

+ 4 - 4
packages/ui/src/components/basic-tool.tsx → packages/session-ui/src/components/basic-tool.tsx

@@ -1,10 +1,10 @@
 import { createEffect, For, Match, on, onCleanup, onMount, Show, Switch, type Accessor, type JSX } from "solid-js"
 import { animate, type AnimationPlaybackControls } from "motion"
-import { useI18n } from "../context/i18n"
+import { useI18n } from "@opencode-ai/ui/context/i18n"
 import { createStore } from "solid-js/store"
-import { Collapsible } from "./collapsible"
-import type { IconProps } from "./icon"
-import { TextShimmer } from "./text-shimmer"
+import { Collapsible } from "@opencode-ai/ui/collapsible"
+import type { IconProps } from "@opencode-ai/ui/icon"
+import { TextShimmer } from "@opencode-ai/ui/text-shimmer"
 
 export type TriggerTitle = {
   title: string

+ 1 - 1
packages/ui/src/components/dock-prompt.stories.tsx → packages/session-ui/src/components/dock-prompt.stories.tsx

@@ -1,6 +1,6 @@
 // @ts-nocheck
 import * as mod from "./dock-prompt"
-import { create } from "../storybook/scaffold"
+import { create } from "@opencode-ai/ui/storybook/scaffold"
 
 const docs = `### Overview
 Docked prompt layout for questions and permission requests.

+ 1 - 1
packages/ui/src/components/dock-prompt.tsx → packages/session-ui/src/components/dock-prompt.tsx

@@ -1,5 +1,5 @@
 import type { JSX } from "solid-js"
-import { DockShell, DockTray } from "./dock-surface"
+import { DockShell, DockTray } from "@opencode-ai/ui/dock-surface"
 
 export function DockPrompt(props: {
   kind: "question" | "permission"

+ 1 - 1
packages/ui/src/components/file-media.tsx → packages/session-ui/src/components/file-media.tsx

@@ -1,6 +1,6 @@
 import type { FileContent } from "@opencode-ai/sdk/v2"
 import { createEffect, createMemo, createResource, Match, on, Show, Switch, type JSX } from "solid-js"
-import { useI18n } from "../context/i18n"
+import { useI18n } from "@opencode-ai/ui/context/i18n"
 import {
   dataUrlFromMediaValue,
   hasMediaValue,

+ 2 - 2
packages/ui/src/components/file-search.tsx → packages/session-ui/src/components/file-search.tsx

@@ -1,6 +1,6 @@
 import { Portal } from "solid-js/web"
-import { useI18n } from "../context/i18n"
-import { Icon } from "./icon"
+import { useI18n } from "@opencode-ai/ui/context/i18n"
+import { Icon } from "@opencode-ai/ui/icon"
 
 export function FileSearchBar(props: {
   pos: () => { top: number; right: number }

+ 1 - 1
packages/ui/src/components/file-ssr.tsx → packages/session-ui/src/components/file-ssr.tsx

@@ -2,7 +2,7 @@ import { DIFFS_TAG_NAME, FileDiff, VirtualizedFileDiff } from "@pierre/diffs"
 import { type PreloadFileDiffResult, type PreloadMultiFileDiffResult } from "@pierre/diffs/ssr"
 import { createEffect, onCleanup, onMount, Show, splitProps } from "solid-js"
 import { Dynamic, isServer } from "solid-js/web"
-import { useWorkerPool } from "../context/worker-pool"
+import { useWorkerPool } from "@opencode-ai/ui/context/worker-pool"
 import { createDefaultOptions, styleVariables } from "../pierre"
 import { markCommentedDiffLines } from "../pierre/commented-lines"
 import { fixDiffSelection } from "../pierre/diff-selection"

+ 0 - 0
packages/ui/src/components/file.css → packages/session-ui/src/components/file.css


+ 0 - 0
packages/ui/src/components/file.tsx → packages/session-ui/src/components/file.tsx


+ 1 - 1
packages/ui/src/components/line-comment-annotations.tsx → packages/session-ui/src/components/line-comment-annotations.tsx

@@ -2,7 +2,7 @@ import { type DiffLineAnnotation, type SelectedLineRange } from "@pierre/diffs"
 import { createEffect, createMemo, createSignal, onCleanup, Show, type Accessor, type JSX } from "solid-js"
 import { createStore } from "solid-js/store"
 import { render as renderSolid } from "solid-js/web"
-import { useI18n } from "../context/i18n"
+import { useI18n } from "@opencode-ai/ui/context/i18n"
 import { createHoverCommentUtility } from "../pierre/comment-hover"
 import { cloneSelectedLineRange, formatSelectedLineLabel, lineInSelectedRange } from "../pierre/selection-bridge"
 import { LineComment, LineCommentEditor, type LineCommentEditorProps } from "./line-comment"

+ 0 - 0
packages/ui/src/components/line-comment-styles.ts → packages/session-ui/src/components/line-comment-styles.ts


+ 0 - 0
packages/ui/src/components/line-comment.stories.tsx → packages/session-ui/src/components/line-comment.stories.tsx


+ 4 - 4
packages/ui/src/components/line-comment.tsx → packages/session-ui/src/components/line-comment.tsx

@@ -1,11 +1,11 @@
 import { useFilteredList } from "@opencode-ai/ui/hooks"
 import { getDirectory, getFilename } from "@opencode-ai/core/util/path"
 import { createSignal, For, onMount, Show, splitProps, type JSX } from "solid-js"
-import { Button } from "./button"
-import { FileIcon } from "./file-icon"
-import { Icon } from "./icon"
+import { Button } from "@opencode-ai/ui/button"
+import { FileIcon } from "@opencode-ai/ui/file-icon"
+import { Icon } from "@opencode-ai/ui/icon"
 import { installLineCommentStyles } from "./line-comment-styles"
-import { useI18n } from "../context/i18n"
+import { useI18n } from "@opencode-ai/ui/context/i18n"
 
 installLineCommentStyles()
 

+ 0 - 0
packages/ui/src/components/markdown-cache.tsx → packages/session-ui/src/components/markdown-cache.tsx


+ 0 - 0
packages/ui/src/components/markdown-code-state.test.ts → packages/session-ui/src/components/markdown-code-state.test.ts


+ 0 - 0
packages/ui/src/components/markdown-code-state.ts → packages/session-ui/src/components/markdown-code-state.ts


+ 0 - 0
packages/ui/src/components/markdown-preload.test.ts → packages/session-ui/src/components/markdown-preload.test.ts


+ 0 - 0
packages/ui/src/components/markdown-shiki.worker.ts → packages/session-ui/src/components/markdown-shiki.worker.ts


+ 0 - 0
packages/ui/src/components/markdown-stream.test.ts → packages/session-ui/src/components/markdown-stream.test.ts


+ 0 - 0
packages/ui/src/components/markdown-stream.ts → packages/session-ui/src/components/markdown-stream.ts


+ 0 - 0
packages/ui/src/components/markdown-worker-protocol.test.ts → packages/session-ui/src/components/markdown-worker-protocol.test.ts


+ 0 - 0
packages/ui/src/components/markdown-worker-protocol.ts → packages/session-ui/src/components/markdown-worker-protocol.ts


+ 0 - 0
packages/ui/src/components/markdown-worker-queue.test.ts → packages/session-ui/src/components/markdown-worker-queue.test.ts


+ 0 - 0
packages/ui/src/components/markdown-worker-queue.ts → packages/session-ui/src/components/markdown-worker-queue.ts


+ 0 - 0
packages/ui/src/components/markdown-worker-transport.test.ts → packages/session-ui/src/components/markdown-worker-transport.test.ts


+ 0 - 0
packages/ui/src/components/markdown-worker-transport.ts → packages/session-ui/src/components/markdown-worker-transport.ts


+ 1 - 1
packages/ui/src/components/markdown-worker.ts → packages/session-ui/src/components/markdown-worker.ts

@@ -1,5 +1,5 @@
 import MarkdownShikiWorkerUrl from "./markdown-shiki.worker.ts?worker&url"
-import { OpenCodeTheme } from "../context/marked"
+import { OpenCodeTheme } from "@opencode-ai/ui/context/marked"
 import {
   applyMarkdownWorkerResponse,
   shouldReleaseMarkdownWorkerState,

+ 0 - 0
packages/ui/src/components/markdown.css → packages/session-ui/src/components/markdown.css


+ 2 - 2
packages/ui/src/components/markdown.stories.tsx → packages/session-ui/src/components/markdown.stories.tsx

@@ -1,7 +1,7 @@
 // @ts-nocheck
 import * as mod from "./markdown"
-import { create } from "../storybook/scaffold"
-import { markdown } from "../storybook/fixtures"
+import { create } from "@opencode-ai/ui/storybook/scaffold"
+import { markdown } from "@opencode-ai/ui/storybook/fixtures"
 
 const docs = `### Overview
 Render sanitized Markdown with code blocks, inline code, and safe links.

+ 2 - 2
packages/ui/src/components/markdown.tsx → packages/session-ui/src/components/markdown.tsx

@@ -1,5 +1,5 @@
-import { useMarked } from "../context/marked"
-import { useI18n } from "../context/i18n"
+import { useMarked } from "@opencode-ai/ui/context/marked"
+import { useI18n } from "@opencode-ai/ui/context/i18n"
 import morphdom from "morphdom"
 import { checksum } from "@opencode-ai/core/util/encode"
 import {

+ 0 - 0
packages/ui/src/components/message-file.test.ts → packages/session-ui/src/components/message-file.test.ts


+ 0 - 0
packages/ui/src/components/message-file.ts → packages/session-ui/src/components/message-file.ts


+ 0 - 0
packages/ui/src/components/message-nav.css → packages/session-ui/src/components/message-nav.css


+ 1 - 1
packages/ui/src/components/message-nav.stories.tsx → packages/session-ui/src/components/message-nav.stories.tsx

@@ -1,6 +1,6 @@
 // @ts-nocheck
 import * as mod from "./message-nav"
-import { create } from "../storybook/scaffold"
+import { create } from "@opencode-ai/ui/storybook/scaffold"
 
 const story = create({ title: "UI/MessageNav", mod })
 export default { title: "UI/MessageNav", id: "components-message-nav", component: story.meta.component }

+ 2 - 2
packages/ui/src/components/message-nav.tsx → packages/session-ui/src/components/message-nav.tsx

@@ -1,8 +1,8 @@
 import { UserMessage } from "@opencode-ai/sdk/v2"
 import { HoverCard } from "@kobalte/core/hover-card"
 import { ComponentProps, For, Match, Show, createSignal, splitProps, Switch } from "solid-js"
-import { DiffChanges } from "./diff-changes"
-import { useI18n } from "../context/i18n"
+import { DiffChanges } from "@opencode-ai/ui/diff-changes"
+import { useI18n } from "@opencode-ai/ui/context/i18n"
 
 export function MessageNav(
   props: ComponentProps<"ul"> & {

+ 0 - 0
packages/ui/src/components/message-part-text.ts → packages/session-ui/src/components/message-part-text.ts


+ 0 - 0
packages/ui/src/components/message-part.css → packages/session-ui/src/components/message-part.css


+ 1 - 1
packages/ui/src/components/message-part.stories.tsx → packages/session-ui/src/components/message-part.stories.tsx

@@ -1,6 +1,6 @@
 // @ts-nocheck
 import * as mod from "./message-part"
-import { create } from "../storybook/scaffold"
+import { create } from "@opencode-ai/ui/storybook/scaffold"
 
 const story = create({ title: "UI/MessagePart", mod })
 export default { title: "UI/MessagePart", id: "components-message-part", component: story.meta.component }

+ 0 - 0
packages/ui/src/components/message-part.test.ts → packages/session-ui/src/components/message-part.test.ts


+ 16 - 16
packages/ui/src/components/message-part.tsx → packages/session-ui/src/components/message-part.tsx

@@ -31,26 +31,26 @@ import {
   QuestionInfo,
 } from "@opencode-ai/sdk/v2"
 import { useData } from "../context"
-import { useFileComponent } from "../context/file"
-import { useDialog } from "../context/dialog"
-import { type UiI18n, useI18n } from "../context/i18n"
+import { useFileComponent } from "@opencode-ai/ui/context/file"
+import { useDialog } from "@opencode-ai/ui/context/dialog"
+import { type UiI18n, useI18n } from "@opencode-ai/ui/context/i18n"
 import { BasicTool, GenericTool } from "./basic-tool"
-import { Accordion } from "./accordion"
-import { StickyAccordionHeader } from "./sticky-accordion-header"
-import { Collapsible } from "./collapsible"
-import { FileIcon } from "./file-icon"
-import { Icon } from "./icon"
+import { Accordion } from "@opencode-ai/ui/accordion"
+import { StickyAccordionHeader } from "@opencode-ai/ui/sticky-accordion-header"
+import { Collapsible } from "@opencode-ai/ui/collapsible"
+import { FileIcon } from "@opencode-ai/ui/file-icon"
+import { Icon } from "@opencode-ai/ui/icon"
 import { ToolErrorCard } from "./tool-error-card"
-import { Checkbox } from "./checkbox"
-import { DiffChanges } from "./diff-changes"
+import { Checkbox } from "@opencode-ai/ui/checkbox"
+import { DiffChanges } from "@opencode-ai/ui/diff-changes"
 import { Markdown } from "./markdown"
-import { ImagePreview } from "./image-preview"
+import { ImagePreview } from "@opencode-ai/ui/image-preview"
 import { getDirectory as _getDirectory, getFilename } from "@opencode-ai/core/util/path"
 import { checksum } from "@opencode-ai/core/util/encode"
-import { Tooltip } from "./tooltip"
-import { IconButton } from "./icon-button"
-import { Spinner } from "./spinner"
-import { TextShimmer } from "./text-shimmer"
+import { Tooltip } from "@opencode-ai/ui/tooltip"
+import { IconButton } from "@opencode-ai/ui/icon-button"
+import { Spinner } from "@opencode-ai/ui/spinner"
+import { TextShimmer } from "@opencode-ai/ui/text-shimmer"
 import { AnimatedCountList } from "./tool-count-summary"
 import { ToolStatusTitle } from "./tool-status-title"
 import { patchFiles } from "./apply-patch-file"
@@ -303,7 +303,7 @@ function getDirectory(path: string | undefined) {
   return relativizeProjectPath(_getDirectory(path), data.directory)
 }
 
-import type { IconProps } from "./icon"
+import type { IconProps } from "@opencode-ai/ui/icon"
 import { normalize, resolveFileDiff } from "./session-diff"
 
 export type ToolInfo = {

+ 0 - 0
packages/ui/src/components/session-diff.test.ts → packages/session-ui/src/components/session-diff.test.ts


+ 0 - 0
packages/ui/src/components/session-diff.ts → packages/session-ui/src/components/session-diff.ts


+ 4 - 4
packages/ui/src/components/session-retry.tsx → packages/session-ui/src/components/session-retry.tsx

@@ -1,9 +1,9 @@
 import { createEffect, createMemo, createSignal, on, onCleanup, Show } from "solid-js"
 import type { SessionStatus } from "@opencode-ai/sdk/v2/client"
-import { useI18n } from "../context/i18n"
-import { Card } from "./card"
-import { Tooltip } from "./tooltip"
-import { Spinner } from "./spinner"
+import { useI18n } from "@opencode-ai/ui/context/i18n"
+import { Card } from "@opencode-ai/ui/card"
+import { Tooltip } from "@opencode-ai/ui/tooltip"
+import { Spinner } from "@opencode-ai/ui/spinner"
 
 export function SessionRetry(props: { status: SessionStatus; show?: boolean }) {
   const i18n = useI18n()

+ 0 - 0
packages/ui/src/components/session-review.css → packages/session-ui/src/components/session-review.css


+ 1 - 1
packages/ui/src/components/session-review.stories.tsx → packages/session-ui/src/components/session-review.stories.tsx

@@ -1,6 +1,6 @@
 // @ts-nocheck
 import * as mod from "./session-review"
-import { create } from "../storybook/scaffold"
+import { create } from "@opencode-ai/ui/storybook/scaffold"
 
 const story = create({ title: "UI/SessionReview", mod })
 export default { title: "UI/SessionReview", id: "components-session-review", component: story.meta.component }

+ 13 - 13
packages/ui/src/components/session-review.tsx → packages/session-ui/src/components/session-review.tsx

@@ -1,16 +1,16 @@
-import { Accordion } from "./accordion"
-import { Button } from "./button"
-import { DropdownMenu } from "./dropdown-menu"
-import { RadioGroup } from "./radio-group"
-import { DiffChanges } from "./diff-changes"
-import { FileIcon } from "./file-icon"
-import { Icon } from "./icon"
-import { IconButton } from "./icon-button"
-import { StickyAccordionHeader } from "./sticky-accordion-header"
-import { Tooltip } from "./tooltip"
-import { ScrollView } from "./scroll-view"
-import { useFileComponent } from "../context/file"
-import { useI18n } from "../context/i18n"
+import { Accordion } from "@opencode-ai/ui/accordion"
+import { Button } from "@opencode-ai/ui/button"
+import { DropdownMenu } from "@opencode-ai/ui/dropdown-menu"
+import { RadioGroup } from "@opencode-ai/ui/radio-group"
+import { DiffChanges } from "@opencode-ai/ui/diff-changes"
+import { FileIcon } from "@opencode-ai/ui/file-icon"
+import { Icon } from "@opencode-ai/ui/icon"
+import { IconButton } from "@opencode-ai/ui/icon-button"
+import { StickyAccordionHeader } from "@opencode-ai/ui/sticky-accordion-header"
+import { Tooltip } from "@opencode-ai/ui/tooltip"
+import { ScrollView } from "@opencode-ai/ui/scroll-view"
+import { useFileComponent } from "@opencode-ai/ui/context/file"
+import { useI18n } from "@opencode-ai/ui/context/i18n"
 import { getDirectory, getFilename } from "@opencode-ai/core/util/path"
 import { checksum } from "@opencode-ai/core/util/encode"
 import { createEffect, createMemo, For, Match, onCleanup, Show, Switch, untrack, type JSX } from "solid-js"

+ 0 - 0
packages/ui/src/components/session-turn.css → packages/session-ui/src/components/session-turn.css


+ 1 - 1
packages/ui/src/components/session-turn.stories.tsx → packages/session-ui/src/components/session-turn.stories.tsx

@@ -1,6 +1,6 @@
 // @ts-nocheck
 import * as mod from "./session-turn"
-import { create } from "../storybook/scaffold"
+import { create } from "@opencode-ai/ui/storybook/scaffold"
 
 const story = create({ title: "UI/SessionTurn", mod })
 export default { title: "UI/SessionTurn", id: "components-session-turn", component: story.meta.component }

+ 10 - 10
packages/ui/src/components/session-turn.tsx → packages/session-ui/src/components/session-turn.tsx

@@ -6,7 +6,7 @@ import {
 } from "@opencode-ai/sdk/v2/client"
 import type { SessionStatus } from "@opencode-ai/sdk/v2"
 import { useData } from "../context"
-import { useFileComponent } from "../context/file"
+import { useFileComponent } from "@opencode-ai/ui/context/file"
 
 import { Binary } from "@opencode-ai/core/util/binary"
 import { getDirectory, getFilename } from "@opencode-ai/core/util/path"
@@ -14,16 +14,16 @@ import { createEffect, createMemo, createSignal, For, on, ParentProps, Show } fr
 import { createStore } from "solid-js/store"
 import { Dynamic } from "solid-js/web"
 import { AssistantParts, Message, MessageDivider, PART_MAPPING, type UserActions } from "./message-part"
-import { Card } from "./card"
-import { Accordion } from "./accordion"
-import { StickyAccordionHeader } from "./sticky-accordion-header"
-import { DiffChanges } from "./diff-changes"
-import { Icon } from "./icon"
-import { TextShimmer } from "./text-shimmer"
+import { Card } from "@opencode-ai/ui/card"
+import { Accordion } from "@opencode-ai/ui/accordion"
+import { StickyAccordionHeader } from "@opencode-ai/ui/sticky-accordion-header"
+import { DiffChanges } from "@opencode-ai/ui/diff-changes"
+import { Icon } from "@opencode-ai/ui/icon"
+import { TextShimmer } from "@opencode-ai/ui/text-shimmer"
 import { SessionRetry } from "./session-retry"
-import { TextReveal } from "./text-reveal"
-import { createAutoScroll } from "../hooks"
-import { useI18n } from "../context/i18n"
+import { TextReveal } from "@opencode-ai/ui/text-reveal"
+import { createAutoScroll } from "@opencode-ai/ui/hooks"
+import { useI18n } from "@opencode-ai/ui/context/i18n"
 import { normalize } from "./session-diff"
 
 function record(value: unknown): value is Record<string, unknown> {

+ 0 - 0
packages/ui/src/components/shell-submessage-motion.stories.tsx → packages/session-ui/src/components/shell-submessage-motion.stories.tsx


+ 0 - 0
packages/ui/src/components/shell-submessage.css → packages/session-ui/src/components/shell-submessage.css


+ 2 - 2
packages/ui/src/components/timeline-playground.stories.tsx → packages/session-ui/src/components/timeline-playground.stories.tsx

@@ -13,7 +13,7 @@ import type {
   AgentPart,
 } from "@opencode-ai/sdk/v2"
 import { DataProvider } from "../context/data"
-import { FileComponentProvider } from "../context/file"
+import { FileComponentProvider } from "@opencode-ai/ui/context/file"
 import { SessionTurn } from "./session-turn"
 
 // ---------------------------------------------------------------------------
@@ -558,7 +558,7 @@ function toolPart(sample: (typeof TOOL_SAMPLES)[keyof typeof TOOL_SAMPLES], stat
 // CSS Controls definition
 // ---------------------------------------------------------------------------
 
-// Source file basenames inside packages/ui/src/components/
+// Source file basenames inside the UI component packages.
 const MD = "markdown.css"
 const MP = "message-part.css"
 const ST = "session-turn.css"

+ 0 - 0
packages/ui/src/components/tool-count-label.css → packages/session-ui/src/components/tool-count-label.css


+ 1 - 1
packages/ui/src/components/tool-count-label.tsx → packages/session-ui/src/components/tool-count-label.tsx

@@ -1,5 +1,5 @@
 import { createMemo } from "solid-js"
-import { AnimatedNumber } from "./animated-number"
+import { AnimatedNumber } from "@opencode-ai/ui/animated-number"
 
 function split(text: string) {
   const match = /{{\s*count\s*}}/.exec(text)

+ 0 - 0
packages/ui/src/components/tool-count-summary.css → packages/session-ui/src/components/tool-count-summary.css


+ 0 - 0
packages/ui/src/components/tool-count-summary.stories.tsx → packages/session-ui/src/components/tool-count-summary.stories.tsx


+ 0 - 0
packages/ui/src/components/tool-count-summary.tsx → packages/session-ui/src/components/tool-count-summary.tsx


+ 0 - 0
packages/ui/src/components/tool-error-card.css → packages/session-ui/src/components/tool-error-card.css


+ 0 - 0
packages/ui/src/components/tool-error-card.stories.tsx → packages/session-ui/src/components/tool-error-card.stories.tsx


+ 6 - 6
packages/ui/src/components/tool-error-card.tsx → packages/session-ui/src/components/tool-error-card.tsx

@@ -1,11 +1,11 @@
 import { type ComponentProps, createMemo, Show, splitProps } from "solid-js"
 import { createStore } from "solid-js/store"
-import { Card, CardDescription } from "./card"
-import { Collapsible } from "./collapsible"
-import { Icon } from "./icon"
-import { IconButton } from "./icon-button"
-import { Tooltip } from "./tooltip"
-import { useI18n } from "../context/i18n"
+import { Card, CardDescription } from "@opencode-ai/ui/card"
+import { Collapsible } from "@opencode-ai/ui/collapsible"
+import { Icon } from "@opencode-ai/ui/icon"
+import { IconButton } from "@opencode-ai/ui/icon-button"
+import { Tooltip } from "@opencode-ai/ui/tooltip"
+import { useI18n } from "@opencode-ai/ui/context/i18n"
 
 export interface ToolErrorCardProps extends Omit<ComponentProps<typeof Card>, "children" | "variant"> {
   tool: string

+ 0 - 0
packages/ui/src/components/tool-status-title.css → packages/session-ui/src/components/tool-status-title.css


+ 1 - 1
packages/ui/src/components/tool-status-title.tsx → packages/session-ui/src/components/tool-status-title.tsx

@@ -1,6 +1,6 @@
 import { Show, createEffect, createMemo, on, onCleanup } from "solid-js"
 import { createStore } from "solid-js/store"
-import { TextShimmer } from "./text-shimmer"
+import { TextShimmer } from "@opencode-ai/ui/text-shimmer"
 
 function common(active: string, done: string) {
   const a = Array.from(active)

+ 1 - 1
packages/ui/src/context/data.tsx → packages/session-ui/src/context/data.tsx

@@ -1,5 +1,5 @@
 import type { Message, Session, Part, SnapshotFileDiff, SessionStatus, Provider } from "@opencode-ai/sdk/v2"
-import { createSimpleContext } from "./helper"
+import { createSimpleContext } from "@opencode-ai/ui/context"
 import { PreloadMultiFileDiffResult } from "@pierre/diffs/ssr"
 
 export type NormalizedProviderListResponse = {

+ 1 - 0
packages/session-ui/src/context/index.ts

@@ -0,0 +1 @@
+export * from "./data"

+ 0 - 0
packages/ui/src/pierre/comment-hover.ts → packages/session-ui/src/pierre/comment-hover.ts


+ 0 - 0
packages/ui/src/pierre/commented-lines.ts → packages/session-ui/src/pierre/commented-lines.ts


+ 0 - 0
packages/ui/src/pierre/diff-selection.ts → packages/session-ui/src/pierre/diff-selection.ts


+ 0 - 0
packages/ui/src/pierre/file-find.ts → packages/session-ui/src/pierre/file-find.ts


Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff