Skip to content

Commit 6e9d2ab

Browse files
authored
Merge pull request #207 from Opencode-DCP/refactor/consolidate-distillation-notification
refactor: consolidate distillation into unified notification
2 parents 59cf96a + 4c77846 commit 6e9d2ab

File tree

5 files changed

+53
-59
lines changed

5 files changed

+53
-59
lines changed

lib/strategies/tools.ts

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,7 @@ import { tool } from "@opencode-ai/plugin"
22
import type { SessionState, ToolParameterEntry, WithParts } from "../state"
33
import type { PluginConfig } from "../config"
44
import { buildToolIdList } from "../messages/utils"
5-
import {
6-
PruneReason,
7-
sendUnifiedNotification,
8-
sendDistillationNotification,
9-
} from "../ui/notification"
5+
import { PruneReason, sendUnifiedNotification } from "../ui/notification"
106
import { formatPruningResultForTool } from "../ui/utils"
117
import { ensureSessionInitialized } from "../state"
128
import { saveSessionState } from "../state/persistence"
@@ -120,12 +116,9 @@ async function executePruneOperation(
120116
reason,
121117
currentParams,
122118
workingDirectory,
119+
distillation,
123120
)
124121

125-
if (distillation && config.tools.extract.showDistillation) {
126-
await sendDistillationNotification(client, logger, sessionId, distillation, currentParams)
127-
}
128-
129122
state.stats.totalPruneTokens += state.stats.pruneTokenCounter
130123
state.stats.pruneTokenCounter = 0
131124
state.nudgeCounter = 0
@@ -192,7 +185,7 @@ export function createExtractTool(ctx: PruneToolContext): ReturnType<typeof tool
192185
ctx,
193186
toolCtx,
194187
args.ids,
195-
"consolidation" as PruneReason,
188+
"extraction" as PruneReason,
196189
"Extract",
197190
args.distillation,
198191
)

lib/ui/notification.ts

Lines changed: 31 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,32 @@
11
import type { Logger } from "../logger"
22
import type { SessionState } from "../state"
3-
import { formatPrunedItemsList, formatTokenCount } from "./utils"
3+
import {
4+
formatExtracted,
5+
formatPrunedItemsList,
6+
formatStatsHeader,
7+
formatTokenCount,
8+
} from "./utils"
49
import { ToolParameterEntry } from "../state"
510
import { PluginConfig } from "../config"
611

7-
export type PruneReason = "completion" | "noise" | "consolidation"
12+
export type PruneReason = "completion" | "noise" | "extraction"
813
export const PRUNE_REASON_LABELS: Record<PruneReason, string> = {
914
completion: "Task Complete",
1015
noise: "Noise Removal",
11-
consolidation: "Consolidation",
16+
extraction: "Extraction",
1217
}
1318

14-
function formatStatsHeader(totalTokensSaved: number, pruneTokenCounter: number): string {
15-
const totalTokensSavedStr = `~${formatTokenCount(totalTokensSaved + pruneTokenCounter)}`
16-
return [`▣ DCP | ${totalTokensSavedStr} saved total`].join("\n")
17-
}
18-
19-
function buildMinimalMessage(state: SessionState, reason: PruneReason | undefined): string {
20-
const reasonSuffix = reason ? ` [${PRUNE_REASON_LABELS[reason]}]` : ""
21-
return (
19+
function buildMinimalMessage(
20+
state: SessionState,
21+
reason: PruneReason | undefined,
22+
distillation?: string[],
23+
): string {
24+
const reasonSuffix = reason ? ` — ${PRUNE_REASON_LABELS[reason]}` : ""
25+
let message =
2226
formatStatsHeader(state.stats.totalPruneTokens, state.stats.pruneTokenCounter) +
2327
reasonSuffix
24-
)
28+
29+
return message + formatExtracted(distillation)
2530
}
2631

2732
function buildDetailedMessage(
@@ -30,6 +35,7 @@ function buildDetailedMessage(
3035
pruneToolIds: string[],
3136
toolMetadata: Map<string, ToolParameterEntry>,
3237
workingDirectory?: string,
38+
distillation?: string[],
3339
): string {
3440
let message = formatStatsHeader(state.stats.totalPruneTokens, state.stats.pruneTokenCounter)
3541

@@ -42,7 +48,7 @@ function buildDetailedMessage(
4248
message += "\n" + itemLines.join("\n")
4349
}
4450

45-
return message.trim()
51+
return (message + formatExtracted(distillation)).trim()
4652
}
4753

4854
export async function sendUnifiedNotification(
@@ -56,6 +62,7 @@ export async function sendUnifiedNotification(
5662
reason: PruneReason | undefined,
5763
params: any,
5864
workingDirectory: string,
65+
distillation?: string[],
5966
): Promise<boolean> {
6067
const hasPruned = pruneToolIds.length > 0
6168
if (!hasPruned) {
@@ -66,42 +73,20 @@ export async function sendUnifiedNotification(
6673
return false
6774
}
6875

76+
const showExtraction = config.tools.extract.showDistillation ? distillation : undefined
77+
6978
const message =
7079
config.pruneNotification === "minimal"
71-
? buildMinimalMessage(state, reason)
72-
: buildDetailedMessage(state, reason, pruneToolIds, toolMetadata, workingDirectory)
73-
74-
await sendIgnoredMessage(client, sessionId, message, params, logger)
75-
return true
76-
}
77-
78-
function formatDistillationMessage(distillation: Record<string, any>): string {
79-
const lines: string[] = ["▣ DCP | Extracted Distillation"]
80-
81-
for (const findings of Object.values(distillation)) {
82-
lines.push(`\n───`)
83-
if (typeof findings === "object" && findings !== null) {
84-
lines.push(JSON.stringify(findings, null, 2))
85-
} else {
86-
lines.push(String(findings))
87-
}
88-
}
89-
90-
return lines.join("\n")
91-
}
92-
93-
export async function sendDistillationNotification(
94-
client: any,
95-
logger: Logger,
96-
sessionId: string,
97-
distillation: Record<string, any>,
98-
params: any,
99-
): Promise<boolean> {
100-
if (!distillation || Object.keys(distillation).length === 0) {
101-
return false
102-
}
80+
? buildMinimalMessage(state, reason, showExtraction)
81+
: buildDetailedMessage(
82+
state,
83+
reason,
84+
pruneToolIds,
85+
toolMetadata,
86+
workingDirectory,
87+
showExtraction,
88+
)
10389

104-
const message = formatDistillationMessage(distillation)
10590
await sendIgnoredMessage(client, sessionId, message, params, logger)
10691
return true
10792
}

lib/ui/utils.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,22 @@
11
import { ToolParameterEntry } from "../state"
22
import { extractParameterKey } from "../messages/utils"
33

4+
export function formatExtracted(distillation?: string[]): string {
5+
if (!distillation || distillation.length === 0) {
6+
return ""
7+
}
8+
let result = `\n\n▣ Extracted`
9+
for (const finding of distillation) {
10+
result += `\n───\n${finding}`
11+
}
12+
return result
13+
}
14+
15+
export function formatStatsHeader(totalTokensSaved: number, pruneTokenCounter: number): string {
16+
const totalTokensSavedStr = `~${formatTokenCount(totalTokensSaved + pruneTokenCounter)}`
17+
return [`▣ DCP | ${totalTokensSavedStr} saved total`].join("\n")
18+
}
19+
420
export function formatTokenCount(tokens: number): string {
521
if (tokens >= 1000) {
622
return `${(tokens / 1000).toFixed(1)}K`.replace(".0K", "K") + " tokens"

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"$schema": "https://json.schemastore.org/package.json",
33
"name": "@tarquinen/opencode-dcp",
4-
"version": "1.1.1",
4+
"version": "1.1.2",
55
"type": "module",
66
"description": "OpenCode plugin that optimizes token usage by pruning obsolete tool outputs from conversation context",
77
"main": "./dist/index.js",

0 commit comments

Comments
 (0)