Skip to content

Commit 0cd55e8

Browse files
committed
refactor: remove StateManager abstraction in favor of direct Maps
1 parent 7622969 commit 0cd55e8

File tree

3 files changed

+56
-53
lines changed

3 files changed

+56
-53
lines changed

index.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22
import type { Plugin } from "@opencode-ai/plugin"
33
import { getConfig } from "./lib/config"
44
import { Logger } from "./lib/logger"
5-
import { StateManager } from "./lib/state"
6-
import { Janitor } from "./lib/janitor"
5+
import { Janitor, type SessionStats } from "./lib/janitor"
76

87
/**
98
* Checks if a session is a subagent (child session)
@@ -34,10 +33,11 @@ const plugin: Plugin = (async (ctx) => {
3433

3534
// Logger uses ~/.config/opencode/logs/dcp/ for consistent log location
3635
const logger = new Logger(config.debug)
37-
const stateManager = new StateManager()
36+
const prunedIdsState = new Map<string, string[]>()
37+
const statsState = new Map<string, SessionStats>()
3838
const toolParametersCache = new Map<string, any>() // callID -> parameters
3939
const modelCache = new Map<string, { providerID: string; modelID: string }>() // sessionID -> model info
40-
const janitor = new Janitor(ctx.client, stateManager, logger, toolParametersCache, config.protectedTools, modelCache, config.model, config.showModelErrorToasts, config.pruningMode, config.pruning_summary, ctx.directory)
40+
const janitor = new Janitor(ctx.client, prunedIdsState, statsState, logger, toolParametersCache, config.protectedTools, modelCache, config.model, config.showModelErrorToasts, config.pruningMode, config.pruning_summary, ctx.directory)
4141

4242
const cacheToolParameters = (messages: any[]) => {
4343
for (const message of messages) {
@@ -87,8 +87,8 @@ const plugin: Plugin = (async (ctx) => {
8787
if (allSessions.data) {
8888
for (const session of allSessions.data) {
8989
if (session.parentID) continue // Skip subagent sessions
90-
const prunedIds = await stateManager.get(session.id)
91-
prunedIds.forEach(id => allPrunedIds.add(id))
90+
const prunedIds = prunedIdsState.get(session.id) ?? []
91+
prunedIds.forEach((id: string) => allPrunedIds.add(id))
9292
}
9393
}
9494

lib/janitor.ts

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
11
import { z } from "zod"
22
import type { Logger } from "./logger"
3-
import type { StateManager, SessionStats } from "./state"
43
import { buildAnalysisPrompt } from "./prompt"
54
import { selectModel, extractModelFromSession } from "./model-selector"
65
import { estimateTokensBatch, formatTokenCount } from "./tokenizer"
76
import { detectDuplicates, extractParameterKey } from "./deduplicator"
87

8+
export interface SessionStats {
9+
totalToolsPruned: number
10+
totalTokensSaved: number
11+
}
12+
913
export class Janitor {
1014
constructor(
1115
private client: any,
12-
private stateManager: StateManager,
16+
private prunedIdsState: Map<string, string[]>,
17+
private statsState: Map<string, SessionStats>,
1318
private logger: Logger,
1419
private toolParametersCache: Map<string, any>,
1520
private protectedTools: string[],
@@ -114,7 +119,7 @@ export class Janitor {
114119
}
115120

116121
// Get already pruned IDs to filter them out
117-
const alreadyPrunedIds = await this.stateManager.get(sessionID)
122+
const alreadyPrunedIds = this.prunedIdsState.get(sessionID) ?? []
118123
const unprunedToolCallIds = toolCallIds.filter(id => !alreadyPrunedIds.includes(id))
119124

120125
// If there are no unpruned tool calls, skip analysis
@@ -269,7 +274,12 @@ export class Janitor {
269274
const tokensSaved = await this.calculateTokensSaved(finalNewlyPrunedIds, toolOutputs)
270275

271276
// Accumulate session stats (for showing cumulative totals in UI)
272-
const sessionStats = await this.stateManager.addStats(sessionID, finalNewlyPrunedIds.length, tokensSaved)
277+
const currentStats = this.statsState.get(sessionID) ?? { totalToolsPruned: 0, totalTokensSaved: 0 }
278+
const sessionStats: SessionStats = {
279+
totalToolsPruned: currentStats.totalToolsPruned + finalNewlyPrunedIds.length,
280+
totalTokensSaved: currentStats.totalTokensSaved + tokensSaved
281+
}
282+
this.statsState.set(sessionID, sessionStats)
273283

274284
if (this.pruningMode === "auto") {
275285
await this.sendAutoModeNotification(
@@ -296,7 +306,7 @@ export class Janitor {
296306
// ============================================================
297307
// Merge newly pruned IDs with existing ones (using expanded IDs)
298308
const allPrunedIds = [...new Set([...alreadyPrunedIds, ...finalPrunedIds])]
299-
await this.stateManager.set(sessionID, allPrunedIds)
309+
this.prunedIdsState.set(sessionID, allPrunedIds)
300310

301311
// Log final summary
302312
// Format: "Pruned 5/5 tools (~4.2K tokens), 0 kept" or with breakdown if both duplicate and llm
@@ -318,9 +328,38 @@ export class Janitor {
318328
/**
319329
* Helper function to shorten paths for display
320330
*/
321-
private shortenPath(path: string): string {
322-
// Replace home directory with ~
331+
private shortenPath(input: string): string {
332+
// Handle compound strings like: "pattern" in /absolute/path
333+
// Extract and shorten just the path portion
334+
const inPathMatch = input.match(/^(.+) in (.+)$/)
335+
if (inPathMatch) {
336+
const prefix = inPathMatch[1]
337+
const pathPart = inPathMatch[2]
338+
const shortenedPath = this.shortenSinglePath(pathPart)
339+
return `${prefix} in ${shortenedPath}`
340+
}
341+
342+
return this.shortenSinglePath(input)
343+
}
344+
345+
/**
346+
* Shorten a single path string
347+
*/
348+
private shortenSinglePath(path: string): string {
323349
const homeDir = require('os').homedir()
350+
351+
// Strip working directory FIRST (before ~ replacement) for cleaner relative paths
352+
if (this.workingDirectory) {
353+
if (path.startsWith(this.workingDirectory + '/')) {
354+
return path.slice(this.workingDirectory.length + 1)
355+
}
356+
// Exact match (the directory itself)
357+
if (path === this.workingDirectory) {
358+
return '.'
359+
}
360+
}
361+
362+
// Replace home directory with ~
324363
if (path.startsWith(homeDir)) {
325364
path = '~' + path.slice(homeDir.length)
326365
}
@@ -331,21 +370,18 @@ export class Janitor {
331370
return `${nodeModulesMatch[1]}/${nodeModulesMatch[2]}`
332371
}
333372

334-
// Strip working directory to show relative paths
373+
// Try matching against ~ version of working directory (for paths already with ~)
335374
if (this.workingDirectory) {
336-
// Try to match against the absolute working directory first
337-
if (path.startsWith(this.workingDirectory + '/')) {
338-
return path.slice(this.workingDirectory.length + 1)
339-
}
340-
341-
// Also try matching against ~ version of working directory
342375
const workingDirWithTilde = this.workingDirectory.startsWith(homeDir)
343376
? '~' + this.workingDirectory.slice(homeDir.length)
344377
: null
345378

346379
if (workingDirWithTilde && path.startsWith(workingDirWithTilde + '/')) {
347380
return path.slice(workingDirWithTilde.length + 1)
348381
}
382+
if (workingDirWithTilde && path === workingDirWithTilde) {
383+
return '.'
384+
}
349385
}
350386

351387
return path

lib/state.ts

Lines changed: 0 additions & 33 deletions
This file was deleted.

0 commit comments

Comments
 (0)