Dax Raad 4 месяцев назад
Родитель
Сommit
cee7106054

+ 4 - 4
packages/opencode/src/server/server.ts

@@ -36,7 +36,7 @@ import { MCP } from "../mcp"
 import { Storage } from "../storage/storage"
 import type { ContentfulStatusCode } from "hono/utils/http-status"
 import { Snapshot } from "@/snapshot"
-import { MessageSummary } from "@/session/summary"
+import { SessionSummary } from "@/session/summary"
 
 const ERRORS = {
   400: {
@@ -629,19 +629,19 @@ export namespace Server {
         validator(
           "param",
           z.object({
-            id: MessageSummary.diff.schema.shape.sessionID,
+            id: SessionSummary.diff.schema.shape.sessionID,
           }),
         ),
         validator(
           "query",
           z.object({
-            messageID: MessageSummary.diff.schema.shape.messageID,
+            messageID: SessionSummary.diff.schema.shape.messageID,
           }),
         ),
         async (c) => {
           const query = c.req.valid("query")
           const params = c.req.valid("param")
-          const result = await MessageSummary.diff({
+          const result = await SessionSummary.diff({
             sessionID: params.id,
             messageID: query.messageID,
           })

+ 5 - 0
packages/opencode/src/session/index.ts

@@ -36,6 +36,11 @@ export namespace Session {
       projectID: z.string(),
       directory: z.string(),
       parentID: Identifier.schema("session").optional(),
+      summary: z
+        .object({
+          diffs: Snapshot.FileDiff.array(),
+        })
+        .optional(),
       share: z
         .object({
           url: z.string(),

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

@@ -49,7 +49,7 @@ import { spawn } from "child_process"
 import { Command } from "../command"
 import { $, fileURLToPath } from "bun"
 import { ConfigMarkdown } from "../config/markdown"
-import { MessageSummary } from "./summary"
+import { SessionSummary } from "./summary"
 
 export namespace SessionPrompt {
   const log = Log.create({ service: "session.prompt" })
@@ -1292,7 +1292,7 @@ export namespace SessionPrompt {
                   }
                   snapshot = undefined
                 }
-                MessageSummary.summarize({
+                SessionSummary.summarize({
                   sessionID: input.sessionID,
                   messageID: assistantMsg.parentID,
                   providerID: assistantMsg.modelID,

+ 49 - 33
packages/opencode/src/session/summary.ts

@@ -8,7 +8,7 @@ import { Flag } from "@/flag/flag"
 import { Identifier } from "@/id/id"
 import { Snapshot } from "@/snapshot"
 
-export namespace MessageSummary {
+export namespace SessionSummary {
   export const summarize = fn(
     z.object({
       sessionID: z.string(),
@@ -16,46 +16,62 @@ export namespace MessageSummary {
       providerID: z.string(),
     }),
     async (input) => {
-      const messages = await Session.messages(input.sessionID).then((msgs) =>
-        msgs.filter(
-          (m) => m.info.id === input.messageID || (m.info.role === "assistant" && m.info.parentID === input.messageID),
-        ),
-      )
-      const userMsg = messages.find((m) => m.info.id === input.messageID)!
-      const diffs = await computeDiff({ messages })
-      userMsg.info.summary = {
+      const all = await Session.messages(input.sessionID)
+      await Promise.all([
+        summarizeSession({ sessionID: input.sessionID, messages: all }),
+        summarizeMessage({ messageID: input.messageID, messages: all }),
+      ])
+    },
+  )
+
+  async function summarizeSession(input: { sessionID: string; messages: MessageV2.WithParts[] }) {
+    const diffs = await computeDiff({ messages: input.messages })
+    await Session.update(input.sessionID, (draft) => {
+      draft.summary = {
         diffs,
-        text: "",
       }
-      if (
-        Flag.OPENCODE_EXPERIMENTAL_TURN_SUMMARY &&
-        messages.every((m) => m.info.role !== "assistant" || m.info.time.completed)
-      ) {
-        const small = await Provider.getSmallModel(input.providerID)
-        if (!small) return
-        const result = await generateText({
-          model: small.language,
-          maxOutputTokens: 100,
-          messages: [
-            {
-              role: "user",
-              content: `
+    })
+  }
+
+  async function summarizeMessage(input: { messageID: string; messages: MessageV2.WithParts[] }) {
+    const messages = input.messages.filter(
+      (m) => m.info.id === input.messageID || (m.info.role === "assistant" && m.info.parentID === input.messageID),
+    )
+    const userMsg = messages.find((m) => m.info.id === input.messageID)!
+    const diffs = await computeDiff({ messages })
+    userMsg.info.summary = {
+      diffs,
+      text: "",
+    }
+    if (
+      Flag.OPENCODE_EXPERIMENTAL_TURN_SUMMARY &&
+      messages.every((m) => m.info.role !== "assistant" || m.info.time.completed)
+    ) {
+      const assistantMsg = messages.find((m) => m.info.role === "assistant")!.info as MessageV2.Assistant
+      const small = await Provider.getSmallModel(assistantMsg.providerID)
+      if (!small) return
+      const result = await generateText({
+        model: small.language,
+        maxOutputTokens: 100,
+        messages: [
+          {
+            role: "user",
+            content: `
             Summarize the following conversation into 2 sentences MAX explaining what the assistant did and why. Do not explain the user's input.
             <conversation>
             ${JSON.stringify(MessageV2.toModelMessage(messages))}
             </conversation>
             `,
-            },
-          ],
-        })
-        userMsg.info.summary = {
-          text: result.text,
-          diffs: [],
-        }
+          },
+        ],
+      })
+      userMsg.info.summary = {
+        text: result.text,
+        diffs: [],
       }
-      await Session.updateMessage(userMsg.info)
-    },
-  )
+    }
+    await Session.updateMessage(userMsg.info)
+  }
 
   export const diff = fn(
     z.object({