Skip to content

Commit 3259b34

Browse files
authored
Merge pull request #130 from Opencode-DCP/refactor/consolidate-message-utils
refactor: consolidate message utilities and eliminate duplicate iteration
2 parents 84cc8e3 + 1637f1b commit 3259b34

File tree

6 files changed

+37
-55
lines changed

6 files changed

+37
-55
lines changed

lib/messages/prune.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import type { SessionState, WithParts } from "../state"
22
import type { Logger } from "../logger"
33
import type { PluginConfig } from "../config"
4-
import { buildToolIdList } from "../utils"
5-
import { getLastUserMessage, extractParameterKey } from "./utils"
4+
import { getLastUserMessage, extractParameterKey, buildToolIdList } from "./utils"
65
import { loadPrompt } from "../prompt"
76

87
const PRUNED_TOOL_OUTPUT_REPLACEMENT = '[Output removed to save context - information superseded or no longer needed]'

lib/messages/utils.ts

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import type { WithParts } from "../state"
22

33
/**
44
* Extracts a human-readable key from tool metadata for display purposes.
5-
* Used by both deduplication and AI analysis to show what was pruned.
65
*/
76
export const extractParameterKey = (tool: string, parameters: any): string => {
87
if (!parameters) return ''
@@ -83,3 +82,33 @@ export const getLastUserMessage = (
8382
}
8483
return null
8584
}
85+
86+
export function findCurrentAgent(messages: WithParts[]): string | undefined {
87+
const userMsg = getLastUserMessage(messages)
88+
if (!userMsg) return undefined
89+
return (userMsg.info as any).agent || 'build'
90+
}
91+
92+
export function buildToolIdList(messages: WithParts[]): string[] {
93+
const toolIds: string[] = []
94+
for (const msg of messages) {
95+
if (msg.parts) {
96+
for (const part of msg.parts) {
97+
if (part.type === 'tool' && part.callID && part.tool) {
98+
toolIds.push(part.callID)
99+
}
100+
}
101+
}
102+
}
103+
return toolIds
104+
}
105+
106+
export function getPruneToolIds(numericToolIds: number[], toolIdList: string[]): string[] {
107+
const pruneToolIds: string[] = []
108+
for (const index of numericToolIds) {
109+
if (!isNaN(index) && index >= 0 && index < toolIdList.length) {
110+
pruneToolIds.push(toolIdList[index])
111+
}
112+
}
113+
return pruneToolIds
114+
}

lib/strategies/deduplication.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { PluginConfig } from "../config"
22
import { Logger } from "../logger"
33
import type { SessionState, WithParts } from "../state"
4-
import { buildToolIdList, calculateTokensSaved } from "../utils"
4+
import { calculateTokensSaved } from "../utils"
5+
import { buildToolIdList } from "../messages/utils"
56

67
/**
78
* Deduplication strategy - prunes older tool calls that have identical

lib/strategies/on-idle.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import type { Logger } from "../logger"
44
import type { PluginConfig } from "../config"
55
import { buildAnalysisPrompt } from "../prompt"
66
import { selectModel, extractModelFromSession, ModelInfo } from "../model-selector"
7-
import { calculateTokensSaved, findCurrentAgent } from "../utils"
7+
import { calculateTokensSaved } from "../utils"
8+
import { findCurrentAgent } from "../messages/utils"
89
import { saveSessionState } from "../state/persistence"
910
import { sendUnifiedNotification } from "../ui/notification"
1011

lib/strategies/prune-tool.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { tool } from "@opencode-ai/plugin"
22
import type { SessionState, ToolParameterEntry, WithParts } from "../state"
33
import type { PluginConfig } from "../config"
4-
import { findCurrentAgent, buildToolIdList, getPruneToolIds, calculateTokensSaved } from "../utils"
4+
import { findCurrentAgent, buildToolIdList, getPruneToolIds } from "../messages/utils"
5+
import { calculateTokensSaved } from "../utils"
56
import { PruneReason, sendUnifiedNotification } from "../ui/notification"
67
import { formatPruningResultForTool } from "../ui/display-utils"
78
import { ensureSessionInitialized } from "../state"

lib/utils.ts

Lines changed: 0 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { encode } from 'gpt-tokenizer'
33

44
/**
55
* Estimates token counts for a batch of texts using gpt-tokenizer.
6-
* TODO: ensure we aren't falling back to catch branch
76
*/
87
function estimateTokensBatch(texts: string[]): number[] {
98
try {
@@ -15,7 +14,6 @@ function estimateTokensBatch(texts: string[]): number[] {
1514

1615
/**
1716
* Calculates approximate tokens saved by pruning the given tool call IDs.
18-
* Uses pre-fetched messages to avoid duplicate API calls.
1917
* TODO: Make it count message content that are not tool outputs. Currently it ONLY covers tool outputs and errors
2018
*/
2119
export const calculateTokensSaved = (
@@ -57,9 +55,6 @@ export function formatTokenCount(tokens: number): string {
5755
return tokens.toString() + ' tokens'
5856
}
5957

60-
/**
61-
* Checks if a session is a subagent session by looking for a parentID.
62-
*/
6358
export async function isSubAgentSession(client: any, sessionID: string): Promise<boolean> {
6459
try {
6560
const result = await client.session.get({ path: { id: sessionID } })
@@ -68,47 +63,3 @@ export async function isSubAgentSession(client: any, sessionID: string): Promise
6863
return false
6964
}
7065
}
71-
72-
/**
73-
* Finds the current agent from messages by scanning backward for user messages.
74-
*/
75-
export function findCurrentAgent(messages: any[]): string | undefined {
76-
for (let i = messages.length - 1; i >= 0; i--) {
77-
const msg = messages[i]
78-
const info = msg.info
79-
if (info?.role === 'user') {
80-
return info.agent || 'build'
81-
}
82-
}
83-
return undefined
84-
}
85-
86-
/**
87-
* Builds a list of tool call IDs from messages.
88-
*/
89-
export function buildToolIdList(messages: WithParts[]): string[] {
90-
const toolIds: string[] = []
91-
for (const msg of messages) {
92-
if (msg.parts) {
93-
for (const part of msg.parts) {
94-
if (part.type === 'tool' && part.callID && part.tool) {
95-
toolIds.push(part.callID)
96-
}
97-
}
98-
}
99-
}
100-
return toolIds
101-
}
102-
103-
/**
104-
* Prunes numeric tool IDs to valid tool call IDs based on the provided tool ID list.
105-
*/
106-
export function getPruneToolIds(numericToolIds: number[], toolIdList: string[]): string[] {
107-
const pruneToolIds: string[] = []
108-
for (const index of numericToolIds) {
109-
if (!isNaN(index) && index >= 0 && index < toolIdList.length) {
110-
pruneToolIds.push(toolIdList[index])
111-
}
112-
}
113-
return pruneToolIds
114-
}

0 commit comments

Comments
 (0)