Skip to content

Commit 2dabe82

Browse files
committed
feat: add manual mode controls for context tools
Introduce configurable manual mode with command triggers so users can control prune, distill, and compress execution while preserving optional automatic strategies.
1 parent d7a4ad2 commit 2dabe82

10 files changed

Lines changed: 251 additions & 13 deletions

File tree

dcp.schema.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,27 @@
5656
"protectedTools": []
5757
}
5858
},
59+
"manualMode": {
60+
"type": "object",
61+
"description": "Manual mode behavior for context management tools",
62+
"additionalProperties": false,
63+
"properties": {
64+
"enabled": {
65+
"type": "boolean",
66+
"default": false,
67+
"description": "Start new sessions with manual mode enabled"
68+
},
69+
"automaticStrategies": {
70+
"type": "boolean",
71+
"default": true,
72+
"description": "When manual mode is enabled, keep automatic deduplication/supersede/purge strategies running"
73+
}
74+
},
75+
"default": {
76+
"enabled": false,
77+
"automaticStrategies": true
78+
}
79+
},
5980
"turnProtection": {
6081
"type": "object",
6182
"description": "Protect recent tool outputs from being pruned",

index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const plugin: Plugin = (async (ctx) => {
1818
}
1919

2020
const logger = new Logger(config.debug)
21-
const state = createSessionState()
21+
const state = createSessionState(config.manualMode.enabled)
2222

2323
if (isSecureMode()) {
2424
configureClientAuth(ctx.client)

lib/commands/help.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,22 @@ export interface HelpCommandContext {
1616
messages: WithParts[]
1717
}
1818

19-
function formatHelpMessage(): string {
19+
function formatHelpMessage(manualMode: boolean): string {
2020
const lines: string[] = []
2121

2222
lines.push("╭───────────────────────────────────────────────────────────╮")
2323
lines.push("│ DCP Commands │")
2424
lines.push("╰───────────────────────────────────────────────────────────╯")
2525
lines.push("")
26+
lines.push(` Manual mode: ${manualMode ? "ON" : "OFF"}`)
27+
lines.push("")
2628
lines.push(" /dcp context Show token usage breakdown for current session")
2729
lines.push(" /dcp stats Show DCP pruning statistics")
2830
lines.push(" /dcp sweep [n] Prune tools since last user message, or last n tools")
31+
lines.push(" /dcp manual [on|off] Toggle manual mode or set explicit state")
32+
lines.push(" /dcp prune Trigger manual prune tool execution")
33+
lines.push(" /dcp distill Trigger manual distill tool execution")
34+
lines.push(" /dcp compress Trigger manual compress tool execution")
2935
lines.push("")
3036

3137
return lines.join("\n")
@@ -34,7 +40,7 @@ function formatHelpMessage(): string {
3440
export async function handleHelpCommand(ctx: HelpCommandContext): Promise<void> {
3541
const { client, state, logger, sessionId, messages } = ctx
3642

37-
const message = formatHelpMessage()
43+
const message = formatHelpMessage(state.manualMode)
3844

3945
const params = getCurrentParams(state, messages, logger)
4046
await sendIgnoredMessage(client, sessionId, message, params, logger)

lib/config.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ export interface Commands {
4343
protectedTools: string[]
4444
}
4545

46+
export interface ManualModeConfig {
47+
enabled: boolean
48+
automaticStrategies: boolean
49+
}
50+
4651
export interface SupersedeWrites {
4752
enabled: boolean
4853
}
@@ -64,6 +69,7 @@ export interface PluginConfig {
6469
pruneNotification: "off" | "minimal" | "detailed"
6570
pruneNotificationType: "chat" | "toast"
6671
commands: Commands
72+
manualMode: ManualModeConfig
6773
turnProtection: TurnProtection
6874
protectedFilePatterns: string[]
6975
tools: Tools
@@ -102,6 +108,9 @@ export const VALID_CONFIG_KEYS = new Set([
102108
"commands",
103109
"commands.enabled",
104110
"commands.protectedTools",
111+
"manualMode",
112+
"manualMode.enabled",
113+
"manualMode.automaticStrategies",
105114
"tools",
106115
"tools.settings",
107116
"tools.settings.nudgeEnabled",
@@ -263,6 +272,36 @@ export function validateConfigTypes(config: Record<string, any>): ValidationErro
263272
}
264273
}
265274

275+
// Manual mode validator
276+
const manualMode = config.manualMode
277+
if (manualMode !== undefined) {
278+
if (typeof manualMode === "object") {
279+
if (manualMode.enabled !== undefined && typeof manualMode.enabled !== "boolean") {
280+
errors.push({
281+
key: "manualMode.enabled",
282+
expected: "boolean",
283+
actual: typeof manualMode.enabled,
284+
})
285+
}
286+
if (
287+
manualMode.automaticStrategies !== undefined &&
288+
typeof manualMode.automaticStrategies !== "boolean"
289+
) {
290+
errors.push({
291+
key: "manualMode.automaticStrategies",
292+
expected: "boolean",
293+
actual: typeof manualMode.automaticStrategies,
294+
})
295+
}
296+
} else {
297+
errors.push({
298+
key: "manualMode",
299+
expected: "{ enabled: boolean, automaticStrategies: boolean }",
300+
actual: typeof manualMode,
301+
})
302+
}
303+
}
304+
266305
// Tools validators
267306
const tools = config.tools
268307
if (tools) {
@@ -529,6 +568,10 @@ const defaultConfig: PluginConfig = {
529568
enabled: true,
530569
protectedTools: [...DEFAULT_PROTECTED_TOOLS],
531570
},
571+
manualMode: {
572+
enabled: false,
573+
automaticStrategies: true,
574+
},
532575
turnProtection: {
533576
enabled: false,
534577
turns: 4,
@@ -747,13 +790,29 @@ function mergeCommands(
747790
}
748791
}
749792

793+
function mergeManualMode(
794+
base: PluginConfig["manualMode"],
795+
override?: Partial<PluginConfig["manualMode"]>,
796+
): PluginConfig["manualMode"] {
797+
if (override === undefined) return base
798+
799+
return {
800+
enabled: override.enabled ?? base.enabled,
801+
automaticStrategies: override.automaticStrategies ?? base.automaticStrategies,
802+
}
803+
}
804+
750805
function deepCloneConfig(config: PluginConfig): PluginConfig {
751806
return {
752807
...config,
753808
commands: {
754809
enabled: config.commands.enabled,
755810
protectedTools: [...config.commands.protectedTools],
756811
},
812+
manualMode: {
813+
enabled: config.manualMode.enabled,
814+
automaticStrategies: config.manualMode.automaticStrategies,
815+
},
757816
turnProtection: { ...config.turnProtection },
758817
protectedFilePatterns: [...config.protectedFilePatterns],
759818
tools: {
@@ -812,6 +871,7 @@ export function getConfig(ctx: PluginInput): PluginConfig {
812871
pruneNotificationType:
813872
result.data.pruneNotificationType ?? config.pruneNotificationType,
814873
commands: mergeCommands(config.commands, result.data.commands as any),
874+
manualMode: mergeManualMode(config.manualMode, result.data.manualMode as any),
815875
turnProtection: {
816876
enabled: result.data.turnProtection?.enabled ?? config.turnProtection.enabled,
817877
turns: result.data.turnProtection?.turns ?? config.turnProtection.turns,
@@ -857,6 +917,7 @@ export function getConfig(ctx: PluginInput): PluginConfig {
857917
pruneNotificationType:
858918
result.data.pruneNotificationType ?? config.pruneNotificationType,
859919
commands: mergeCommands(config.commands, result.data.commands as any),
920+
manualMode: mergeManualMode(config.manualMode, result.data.manualMode as any),
860921
turnProtection: {
861922
enabled: result.data.turnProtection?.enabled ?? config.turnProtection.enabled,
862923
turns: result.data.turnProtection?.turns ?? config.turnProtection.turns,
@@ -899,6 +960,7 @@ export function getConfig(ctx: PluginInput): PluginConfig {
899960
pruneNotificationType:
900961
result.data.pruneNotificationType ?? config.pruneNotificationType,
901962
commands: mergeCommands(config.commands, result.data.commands as any),
963+
manualMode: mergeManualMode(config.manualMode, result.data.manualMode as any),
902964
turnProtection: {
903965
enabled: result.data.turnProtection?.enabled ?? config.turnProtection.enabled,
904966
turns: result.data.turnProtection?.turns ?? config.turnProtection.turns,

0 commit comments

Comments
 (0)