-
-
Notifications
You must be signed in to change notification settings - Fork 209
Expand file tree
/
Copy pathmessage.ts
More file actions
137 lines (122 loc) · 4.87 KB
/
Copy pathmessage.ts
File metadata and controls
137 lines (122 loc) · 4.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import { tool } from "@opencode-ai/plugin"
import type { ToolContext } from "./types"
import { countTokens } from "../token-utils"
import { MESSAGE_FORMAT_EXTENSION } from "../prompts/extensions/tool"
import { formatIssues, formatResult, resolveMessages, validateArgs } from "./message-utils"
import { finalizeSession, prepareSession, type NotificationEntry } from "./pipeline"
import { appendProtectedTools } from "./protected-content"
import {
allocateBlockId,
allocateRunId,
applyCompressionState,
wrapCompressedSummary,
} from "./state"
import type { CompressMessageToolArgs } from "./types"
function buildSchema() {
return {
topic: tool.schema
.string()
.describe(
"Short label (3-5 words) for the overall batch - e.g., 'Closed Research Notes'",
),
content: tool.schema
.array(
tool.schema.object({
messageId: tool.schema
.string()
.describe("Raw message ID to compress (e.g. m0001)"),
topic: tool.schema
.string()
.describe("Short label (3-5 words) for this one message summary"),
summary: tool.schema
.string()
.describe("Complete technical summary replacing that one message"),
}),
)
.describe("Batch of individual message summaries to create in one tool call"),
}
}
export function createCompressMessageTool(ctx: ToolContext): ReturnType<typeof tool> {
ctx.prompts.reload()
const runtimePrompts = ctx.prompts.getRuntimePrompts()
return tool({
description: runtimePrompts.compressMessage + MESSAGE_FORMAT_EXTENSION,
args: buildSchema(),
async execute(args, toolCtx) {
const input = args as CompressMessageToolArgs
validateArgs(input)
const callId =
typeof (toolCtx as unknown as { callID?: unknown }).callID === "string"
? (toolCtx as unknown as { callID: string }).callID
: undefined
const { rawMessages, searchContext } = await prepareSession(
ctx,
toolCtx,
`Compress Message: ${input.topic}`,
)
const { plans, skippedIssues, skippedCount } = resolveMessages(
input,
searchContext,
ctx.state,
ctx.config,
)
if (plans.length === 0 && skippedCount > 0) {
throw new Error(formatIssues(skippedIssues, skippedCount))
}
const notifications: NotificationEntry[] = []
const preparedPlans: Array<{
plan: (typeof plans)[number]
summaryWithTools: string
}> = []
for (const plan of plans) {
const summaryWithTools = await appendProtectedTools(
ctx.client,
ctx.state,
ctx.config.experimental.allowSubAgents,
plan.entry.summary,
plan.selection,
searchContext,
ctx.config.compress.protectedTools,
ctx.config.protectedFilePatterns,
)
preparedPlans.push({
plan,
summaryWithTools,
})
}
const runId = allocateRunId(ctx.state)
for (const { plan, summaryWithTools } of preparedPlans) {
const blockId = allocateBlockId(ctx.state)
const storedSummary = wrapCompressedSummary(blockId, summaryWithTools)
const summaryTokens = countTokens(storedSummary)
applyCompressionState(
ctx.state,
{
topic: plan.entry.topic,
batchTopic: input.topic,
startId: plan.entry.messageId,
endId: plan.entry.messageId,
mode: "message",
runId,
compressMessageId: toolCtx.messageID,
compressCallId: callId,
summaryTokens,
},
plan.selection,
plan.anchorMessageId,
blockId,
storedSummary,
[],
)
notifications.push({
blockId,
runId,
summary: summaryWithTools,
summaryTokens,
})
}
await finalizeSession(ctx, toolCtx, rawMessages, notifications, input.topic)
return formatResult(plans.length, skippedIssues, skippedCount)
},
})
}