Browse Source

wip(share): more styling

Adam 4 months ago
parent
commit
3fb57044d1

+ 6 - 4
.opencode/opencode.jsonc

@@ -1,9 +1,11 @@
 {
   "$schema": "https://opencode.ai/config.json",
-  "plugin": ["opencode-openai-codex-auth"],
-  // "enterprise": {
-  //   "url": "http://localhost:3000",
-  // },
+  "plugin": [
+    "opencode-openai-codex-auth"
+  ],
+  "enterprise": {
+    "url": "http://localhost:3000",
+  },
   "provider": {
     "opencode": {
       "options": {

+ 8 - 1
packages/enterprise/src/core/share.ts

@@ -1,4 +1,4 @@
-import { FileDiff, Message, Part, Session, SessionStatus } from "@opencode-ai/sdk"
+import { FileDiff, Message, Model, Part, Session, SessionStatus } from "@opencode-ai/sdk"
 import { fn } from "@opencode-ai/util/fn"
 import { iife } from "@opencode-ai/util/iife"
 import z from "zod"
@@ -32,6 +32,10 @@ export namespace Share {
       type: z.literal("session_status"),
       data: z.custom<SessionStatus>(),
     }),
+    z.object({
+      type: z.literal("model"),
+      data: z.custom<Model[]>(),
+    }),
   ])
   export type Data = z.infer<typeof Data>
 
@@ -111,6 +115,9 @@ export namespace Share {
               case "session_status":
                 await Storage.write(["share_data", input.share.id, "session_status"], item.data)
                 break
+              case "model":
+                await Storage.write(["share_data", input.share.id, "model"], item.data)
+                break
             }
           }),
         )

+ 17 - 10
packages/enterprise/src/routes/share/[sessionID].tsx

@@ -1,7 +1,7 @@
-import { FileDiff, Message, Part, Session, SessionStatus, UserMessage } from "@opencode-ai/sdk"
+import { FileDiff, Message, Model, Part, Session, SessionStatus, UserMessage } from "@opencode-ai/sdk"
 import { SessionTurn } from "@opencode-ai/ui/session-turn"
 import { SessionReview } from "@opencode-ai/ui/session-review"
-import { DataProvider, useData } from "@opencode-ai/ui/context"
+import { DataProvider } from "@opencode-ai/ui/context"
 import { createAsync, query, RouteDefinition, useParams } from "@solidjs/router"
 import { createMemo, Show } from "solid-js"
 import { Share } from "~/core/share"
@@ -29,6 +29,9 @@ const getData = query(async (sessionID) => {
     part: {
       [messageID: string]: Part[]
     }
+    model: {
+      [sessionID: string]: Model[]
+    }
   } = {
     session: [],
     session_diff: {
@@ -41,6 +44,7 @@ const getData = query(async (sessionID) => {
     },
     message: {},
     part: {},
+    model: {},
   }
   for (const item of data) {
     switch (item.type) {
@@ -61,6 +65,9 @@ const getData = query(async (sessionID) => {
         result.part[item.data.messageID] = result.part[item.data.messageID] ?? []
         result.part[item.data.messageID].push(item.data)
         break
+      case "model":
+        result.model[sessionID] = item.data
+        break
     }
   }
   return result
@@ -82,15 +89,14 @@ export default function () {
       {(data) => (
         <DataProvider data={data()}>
           {iife(() => {
-            const data = useData()
             const [store, setStore] = createStore({
               messageId: undefined as string | undefined,
             })
-            const match = createMemo(() => Binary.search(data.session, params.sessionID!, (s) => s.id))
+            const match = createMemo(() => Binary.search(data().session, params.sessionID!, (s) => s.id))
             if (!match().found) throw new Error(`Session ${params.sessionID} not found`)
-            const info = createMemo(() => data.session[match().index])
+            const info = createMemo(() => data().session[match().index])
             const messages = createMemo(() =>
-              params.sessionID ? (data.message[params.sessionID]?.filter((m) => m.role === "user") ?? []) : [],
+              params.sessionID ? (data().message[params.sessionID]?.filter((m) => m.role === "user") ?? []) : [],
             )
             const firstUserMessage = createMemo(() => messages().at(0))
             const activeMessage = createMemo(
@@ -104,8 +110,9 @@ export default function () {
               }
             }
             const provider = createMemo(() => activeMessage()?.model?.providerID)
-            const model = createMemo(() => activeMessage()?.model?.modelID)
-            const diffs = createMemo(() => data.session_diff[params.sessionID!] ?? [])
+            const modelID = createMemo(() => activeMessage()?.model?.modelID)
+            const model = createMemo(() => data().model[params.sessionID!]?.find((m) => m.id === modelID()))
+            const diffs = createMemo(() => data().session_diff[params.sessionID!] ?? [])
 
             return (
               <div class="relative bg-background-stronger w-screen h-screen overflow-hidden flex flex-col">
@@ -152,7 +159,7 @@ export default function () {
                               src={`https://models.dev/logos/${provider()}.svg`}
                               class="size-4 shrink-0 dark:invert"
                             />
-                            <div class="text-12-regular text-text-base">{model()}</div>
+                            <div class="text-12-regular text-text-base">{model()?.name ?? modelID()}</div>
                           </div>
                           <div class="text-12-regular text-text-weaker">
                             {DateTime.fromMillis(info().time.created).toFormat("dd MMM yyyy, HH:mm")}
@@ -163,7 +170,7 @@ export default function () {
                       <div class="flex items-start justify-start h-full min-h-0">
                         <Show when={messages().length > 1}>
                           <MessageNav
-                            classList={{ "mt-3 mr-3": true }}
+                            classList={{ "mt-2 mr-3": true }}
                             messages={messages()}
                             current={activeMessage()}
                             onMessageSelect={setActiveMessage}

+ 28 - 0
packages/opencode/src/share/share-next.ts

@@ -1,5 +1,7 @@
 import { Bus } from "@/bus"
 import { Config } from "@/config/config"
+import type { ModelsDev } from "@/provider/models"
+import { Provider } from "@/provider/provider"
 import { Session } from "@/session"
 import { MessageV2 } from "@/session/message-v2"
 import { Storage } from "@/storage/storage"
@@ -26,6 +28,18 @@ export namespace ShareNext {
           data: evt.properties.info,
         },
       ])
+      if (evt.properties.info.role === "user") {
+        await sync(evt.properties.info.sessionID, [
+          {
+            type: "model",
+            data: [
+              await Provider.getModel(evt.properties.info.model.providerID, evt.properties.info.model.modelID).then(
+                (m) => m.info,
+              ),
+            ],
+          },
+        ])
+      }
     })
     Bus.subscribe(MessageV2.Event.PartUpdated, async (evt) => {
       await sync(evt.properties.part.sessionID, [
@@ -90,6 +104,10 @@ export namespace ShareNext {
         type: "session_diff"
         data: SDK.FileDiff[]
       }
+    | {
+        type: "model"
+        data: ModelsDev.Model[]
+      }
 
   async function sync(sessionID: string, data: Data[]) {
     const url = await Config.get().then((x) => x.enterprise!.url)
@@ -129,6 +147,12 @@ export namespace ShareNext {
     const session = await Session.get(sessionID)
     const diffs = await Session.diff(sessionID)
     const messages = await Array.fromAsync(MessageV2.stream(sessionID))
+    const models = await Promise.all(
+      messages
+        .filter((m) => m.info.role === "user")
+        .map((m) => (m.info as SDK.UserMessage).model)
+        .map((m) => Provider.getModel(m.providerID, m.modelID).then((m) => m.info)),
+    )
     await sync(sessionID, [
       {
         type: "session",
@@ -143,6 +167,10 @@ export namespace ShareNext {
         type: "session_diff",
         data: diffs,
       },
+      {
+        type: "model",
+        data: models,
+      },
     ])
   }
 }