Browse Source

only display last 100 messages in TUI

Dax Raad 3 months ago
parent
commit
e45e94634f

+ 1 - 1
packages/opencode/src/cli/cmd/export.ts

@@ -67,7 +67,7 @@ export const ExportCommand = cmd({
 
       try {
         const sessionInfo = await Session.get(sessionID!)
-        const messages = await Session.messages(sessionID!)
+        const messages = await Session.messages({ sessionID: sessionID! })
 
         const exportData = {
           info: sessionInfo,

+ 1 - 1
packages/opencode/src/cli/cmd/stats.ts

@@ -142,7 +142,7 @@ async function aggregateSessionStats(days?: number, projectFilter?: string): Pro
     const batch = filteredSessions.slice(i, i + BATCH_SIZE)
 
     const batchPromises = batch.map(async (session) => {
-      const messages = await Session.messages(session.id)
+      const messages = await Session.messages({ sessionID: session.id })
 
       let sessionCost = 0
       let sessionTokens = { input: 0, output: 0, reasoning: 0, cache: { read: 0, write: 0 } }

+ 2 - 1
packages/opencode/src/cli/cmd/tui/context/sync.tsx

@@ -159,6 +159,7 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
             event.properties.info.sessionID,
             produce((draft) => {
               draft.splice(result.index, 0, event.properties.info)
+              if (draft.length > 100) draft.shift()
             }),
           )
           break
@@ -272,7 +273,7 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
           console.log("syncing", sessionID)
           const [session, messages, todo, diff] = await Promise.all([
             sdk.client.session.get({ path: { id: sessionID }, throwOnError: true }),
-            sdk.client.session.messages({ path: { id: sessionID } }),
+            sdk.client.session.messages({ path: { id: sessionID }, query: { limit: 100 } }),
             sdk.client.session.todo({ path: { id: sessionID } }),
             sdk.client.session.diff({ path: { id: sessionID } }),
           ])

+ 12 - 2
packages/opencode/src/server/server.ts

@@ -753,9 +753,19 @@ export namespace Server {
             id: z.string().meta({ description: "Session ID" }),
           }),
         ),
+        validator(
+          "query",
+          z.object({
+            limit: z.coerce.number().optional(),
+          }),
+        ),
         async (c) => {
-          const messages = await Session.messages(c.req.valid("param").id)
-          return c.json(messages.slice(-100))
+          const query = c.req.valid("query")
+          const messages = await Session.messages({
+            sessionID: c.req.valid("param").id,
+            limit: query.limit,
+          })
+          return c.json(messages)
         },
       )
       .get(

+ 2 - 2
packages/opencode/src/session/compaction.ts

@@ -55,7 +55,7 @@ export namespace SessionCompaction {
   export async function prune(input: { sessionID: string }) {
     if (Flag.OPENCODE_DISABLE_PRUNE) return
     log.info("pruning")
-    const msgs = await Session.messages(input.sessionID)
+    const msgs = await Session.messages({ sessionID: input.sessionID })
     let total = 0
     let pruned = 0
     const toPrune = []
@@ -111,7 +111,7 @@ export namespace SessionCompaction {
         draft.time.compacting = undefined
       })
     })
-    const toSummarize = await Session.messages(input.sessionID).then(MessageV2.filterCompacted)
+    const toSummarize = await Session.messages({ sessionID: input.sessionID }).then(MessageV2.filterCompacted)
     const model = await Provider.getModel(input.providerID, input.modelID)
     const system = [
       ...SystemPrompt.summarize(model.providerID),

+ 22 - 14
packages/opencode/src/session/index.ts

@@ -144,7 +144,7 @@ export namespace Session {
       const session = await createNext({
         directory: Instance.directory,
       })
-      const msgs = await messages(input.sessionID)
+      const msgs = await messages({ sessionID: input.sessionID })
       for (const msg of msgs) {
         if (input.messageID && msg.info.id >= input.messageID) break
         const cloned = await updateMessage({
@@ -237,7 +237,7 @@ export namespace Session {
     })
     await Storage.write(["share", id], share)
     await Share.sync("session/info/" + id, session)
-    for (const msg of await messages(id)) {
+    for (const msg of await messages({ sessionID: id })) {
       await Share.sync("session/message/" + id + "/" + msg.info.id, msg.info)
       for (const part of msg.parts) {
         await Share.sync("session/part/" + id + "/" + msg.info.id + "/" + part.id, part)
@@ -273,18 +273,26 @@ export namespace Session {
     return diffs ?? []
   })
 
-  export const messages = fn(Identifier.schema("session"), async (sessionID) => {
-    const result = [] as MessageV2.WithParts[]
-    for (const p of await Storage.list(["message", sessionID])) {
-      const read = await Storage.read<MessageV2.Info>(p)
-      result.push({
-        info: read,
-        parts: await getParts(read.id),
-      })
-    }
-    result.sort((a, b) => (a.info.id > b.info.id ? 1 : -1))
-    return result
-  })
+  export const messages = fn(
+    z.object({
+      sessionID: Identifier.schema("session"),
+      limit: z.number().optional(),
+    }),
+    async (input) => {
+      const result = [] as MessageV2.WithParts[]
+      const list = (await Array.fromAsync(await Storage.list(["message", input.sessionID])))
+        .toSorted((a, b) => a.at(-1)!.localeCompare(b.at(-1)!))
+        .slice(-1 * (input.limit ?? 1_000_000))
+      for (const p of list) {
+        const read = await Storage.read<MessageV2.Info>(p)
+        result.push({
+          info: read,
+          parts: await getParts(read.id),
+        })
+      }
+      return result
+    },
+  )
 
   export const getMessage = fn(
     z.object({

+ 1 - 1
packages/opencode/src/session/prompt.ts

@@ -434,7 +434,7 @@ export namespace SessionPrompt {
     providerID: string
     signal: AbortSignal
   }) {
-    let msgs = await Session.messages(input.sessionID).then(MessageV2.filterCompacted)
+    let msgs = await Session.messages({ sessionID: input.sessionID }).then(MessageV2.filterCompacted)
     const lastAssistant = msgs.findLast((msg) => msg.info.role === "assistant")
     if (
       lastAssistant?.info.role === "assistant" &&

+ 2 - 2
packages/opencode/src/session/revert.ts

@@ -25,7 +25,7 @@ export namespace SessionRevert {
       sessionID: input.sessionID,
     })
 
-    const all = await Session.messages(input.sessionID)
+    const all = await Session.messages({ sessionID: input.sessionID })
     let lastUser: MessageV2.User | undefined
     const session = await Session.get(input.sessionID)
 
@@ -88,7 +88,7 @@ export namespace SessionRevert {
   export async function cleanup(session: Session.Info) {
     if (!session.revert) return
     const sessionID = session.id
-    let msgs = await Session.messages(sessionID)
+    let msgs = await Session.messages({ sessionID })
     const messageID = session.revert.messageID
     const [preserve, remove] = splitWhen(msgs, (x) => x.info.id === messageID)
     msgs = preserve

+ 2 - 2
packages/opencode/src/session/summary.ts

@@ -23,7 +23,7 @@ export namespace SessionSummary {
       messageID: z.string(),
     }),
     async (input) => {
-      const all = await Session.messages(input.sessionID)
+      const all = await Session.messages({ sessionID: input.sessionID })
       await Promise.all([
         summarizeSession({ sessionID: input.sessionID, messages: all }),
         summarizeMessage({ messageID: input.messageID, messages: all }),
@@ -151,7 +151,7 @@ export namespace SessionSummary {
       messageID: Identifier.schema("message").optional(),
     }),
     async (input) => {
-      let all = await Session.messages(input.sessionID)
+      let all = await Session.messages({ sessionID: input.sessionID })
       if (input.messageID)
         all = all.filter(
           (x) =>

+ 1 - 1
packages/opencode/src/tool/task.ts

@@ -93,7 +93,7 @@ export const TaskTool = Tool.define("task", async () => {
       })
       unsub()
       let all
-      all = await Session.messages(session.id)
+      all = await Session.messages({ sessionID: session.id })
       all = all.filter((x) => x.info.role === "assistant")
       all = all.flatMap(
         (msg) => msg.parts.filter((x: any) => x.type === "tool") as MessageV2.ToolPart[],

+ 1 - 1
packages/sdk/js/src/gen/types.gen.ts

@@ -650,7 +650,6 @@ export type AssistantMessage = {
     | MessageOutputLengthError
     | MessageAbortedError
     | ApiError
-  system: Array<string>
   parentID: string
   modelID: string
   providerID: string
@@ -1982,6 +1981,7 @@ export type SessionMessagesData = {
   }
   query?: {
     directory?: string
+    limit?: number
   }
   url: "/session/{id}/message"
 }