summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDax Raad <[email protected]>2025-10-23 16:28:20 -0400
committerDax Raad <[email protected]>2025-10-23 16:28:20 -0400
commitcee7106054e36bc4cd7197e28fea953afd4d0e48 (patch)
treed5a373758a2e6c6f064c85c864fd13b4eccfaaba
parentf4dfae0bb044673930684497aee6721aece48b67 (diff)
downloadopencode-cee7106054e36bc4cd7197e28fea953afd4d0e48.tar.gz
opencode-cee7106054e36bc4cd7197e28fea953afd4d0e48.zip
session summaries in data
-rw-r--r--packages/opencode/src/server/server.ts8
-rw-r--r--packages/opencode/src/session/index.ts5
-rw-r--r--packages/opencode/src/session/prompt.ts4
-rw-r--r--packages/opencode/src/session/summary.ts82
4 files changed, 60 insertions, 39 deletions
diff --git a/packages/opencode/src/server/server.ts b/packages/opencode/src/server/server.ts
index d8c80a475..8d10ef873 100644
--- a/packages/opencode/src/server/server.ts
+++ b/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,
})
diff --git a/packages/opencode/src/session/index.ts b/packages/opencode/src/session/index.ts
index cf3219529..64f64082e 100644
--- a/packages/opencode/src/session/index.ts
+++ b/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(),
diff --git a/packages/opencode/src/session/prompt.ts b/packages/opencode/src/session/prompt.ts
index 3ce7ff9d3..3fb7d85ba 100644
--- a/packages/opencode/src/session/prompt.ts
+++ b/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,
diff --git a/packages/opencode/src/session/summary.ts b/packages/opencode/src/session/summary.ts
index 36441ea46..6d7b59e5b 100644
--- a/packages/opencode/src/session/summary.ts
+++ b/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({