Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 0 additions & 15 deletions .claude/settings.local.json

This file was deleted.

1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ Thumbs.db

# OpenCode
.opencode/
AGENTS.md

# Tests (local development only)
tests/
Expand Down
12 changes: 12 additions & 0 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,18 @@ const plugin: Plugin = (async (ctx) => {
workingDirectory: ctx.directory
}),
} : undefined,
config: async (opencodeConfig) => {
// Add prune to primary_tools by mutating the opencode config
// This works because config is cached and passed by reference
if (config.strategies.pruneTool.enabled) {
const existingPrimaryTools = opencodeConfig.experimental?.primary_tools ?? []
opencodeConfig.experimental = {
...opencodeConfig.experimental,
primary_tools: [...existingPrimaryTools, "prune"],
}
logger.info("Added 'prune' to experimental.primary_tools via config mutation")
}
},
}
}) satisfies Plugin

Expand Down
8 changes: 6 additions & 2 deletions lib/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,15 @@ export function createChatMessageTransformHandler(
input: {},
output: { messages: WithParts[] }
) => {
checkSession(state, logger, output.messages);
checkSession(client, state, logger, output.messages);
if (state.isSubAgent) {
return
}

syncToolCache(state, config, logger, output.messages);


deduplicate(state, logger, config, output.messages)
deduplicate(client, state, logger, config, output.messages)

prune(state, logger, config, output.messages)

Expand Down
10 changes: 10 additions & 0 deletions lib/state/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import type { SessionState, ToolParameterEntry, WithParts } from "./types"
import type { Logger } from "../logger"
import { loadSessionState } from "./persistence"
import { getLastUserMessage } from "../messages/utils"
import { isSubAgentSession } from "../utils"

export const checkSession = (
client: any,
state: SessionState,
logger: Logger,
messages: WithParts[]
Expand All @@ -19,6 +21,7 @@ export const checkSession = (
if (state.sessionId === null || state.sessionId !== lastSessionId) {
logger.info(`Session changed: ${state.sessionId} -> ${lastSessionId}`)
ensureSessionInitialized(
client,
state,
lastSessionId,
logger
Expand All @@ -31,6 +34,7 @@ export const checkSession = (
export function createSessionState(): SessionState {
return {
sessionId: null,
isSubAgent: false,
prune: {
toolIds: []
},
Expand All @@ -45,6 +49,7 @@ export function createSessionState(): SessionState {

export function resetSessionState(state: SessionState): void {
state.sessionId = null
state.isSubAgent = false
state.prune = {
toolIds: []
}
Expand All @@ -57,6 +62,7 @@ export function resetSessionState(state: SessionState): void {
}

export async function ensureSessionInitialized(
client: any,
state: SessionState,
sessionId: string,
logger: Logger
Expand All @@ -72,6 +78,10 @@ export async function ensureSessionInitialized(
resetSessionState(state)
state.sessionId = sessionId

const isSubAgent = await isSubAgentSession(client, sessionId)
state.isSubAgent = isSubAgent
logger.info("isSubAgent = " + isSubAgent)

// Load session data from storage
const persisted = await loadSessionState(sessionId, logger)
if (persisted === null) {
Expand Down
1 change: 1 addition & 0 deletions lib/state/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export interface Prune {

export interface SessionState {
sessionId: string | null
isSubAgent: boolean
prune: Prune
stats: SessionStats
toolParameters: Map<string, ToolParameterEntry>
Expand Down
1 change: 1 addition & 0 deletions lib/strategies/deduplication.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { calculateTokensSaved } from "../utils"
* Modifies the session state in place to add pruned tool call IDs.
*/
export const deduplicate = (
client: any,
state: SessionState,
logger: Logger,
config: PluginConfig,
Expand Down
Empty file added lib/strategies/on-idle.ts
Empty file.
2 changes: 1 addition & 1 deletion lib/strategies/prune-tool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export function createPruneTool(
return "No numeric IDs provided. Format: [reason, id1, id2, ...] where reason is 'completion', 'noise', or 'consolidation'."
}

await ensureSessionInitialized(state, sessionId, logger)
await ensureSessionInitialized(ctx.client, state, sessionId, logger)

// Fetch messages to calculate tokens and find current agent
const messagesResponse = await client.session.messages({
Expand Down
2 changes: 1 addition & 1 deletion lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export function formatTokenCount(tokens: number): string {
/**
* Checks if a session is a subagent session by looking for a parentID.
*/
export async function isSubagentSession(client: any, sessionID: string): Promise<boolean> {
export async function isSubAgentSession(client: any, sessionID: string): Promise<boolean> {
try {
const result = await client.session.get({ path: { id: sessionID } })
return !!result.data?.parentID
Expand Down