Skip to content
Closed
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
38 changes: 38 additions & 0 deletions devlog/2026-06-29_merge-blocks/REQ.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# REQ: merge-blocks Command

## Problem
Sessions accumulate many small compressed blocks (e.g., 435 blocks in model-editing session). The model can't easily merge them because:
- It doesn't know compress can cover existing blocks
- mark_block is deferred + one-at-a-time (8 calls for 8 blocks)
- It doesn't know block message ranges
- Eventually gives up and focuses on actual task

## Solution
Three changes:

### 1. `/acp merge-blocks` Command
Usage: `/acp merge-blocks 421-428` or `/acp merge-blocks 421,422,423`
- Parses block IDs from args (ranges + lists)
- Looks up blocks in state.prune.messages.blocksById
- Finds message range from anchorMessageId fields
- Creates merged summary by concatenating block topics + summaries
- Creates new CompressionBlock covering the entire range
- Sets consumedBlockIds to deactivate old blocks
- Calls syncCompressionBlocks to apply

### 2. Enhanced Block List Display
When listing blocks (≤20 case), include topic per block:
`b1: "Proxy cost analysis", b2: "Awork deployment"`

### 3. Nudge Text Update
When blockCount > 50, guide to use merge-blocks:
`🔀 Use /acp merge-blocks <range> to merge adjacent blocks.`

## Acceptance Criteria
- [x] `/acp merge-blocks` parses ranges and lists
- [x] Merged block deactivates old blocks via consumedBlockIds
- [x] Enhanced block list shows topics
- [x] Nudge text guides to merge-blocks when >50 blocks
- [x] typecheck clean
- [x] tests pass
- [x] build success
26 changes: 26 additions & 0 deletions devlog/2026-06-29_merge-blocks/WORKLOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# WORKLOG: merge-blocks Command

## Branch
`ranxianglei/2026-06-29_merge-blocks` from master

## Changes

### New File
- `lib/commands/merge-blocks.ts` (350 lines) — merge-blocks command implementation
- Parses block ID args (ranges: `421-428`, lists: `421,422,423`)
- Resolves blocks from state.prune.messages.blocksById
- Creates merged summary from block topics + summaries
- Creates new CompressionBlock with consumedBlockIds
- Calls syncCompressionBlocks to deactivate old blocks

### Modified Files
- `lib/commands/help.ts` — Added merge-blocks to help text
- `lib/commands/index.ts` — Registered merge-blocks command
- `lib/hooks.ts` — Wired merge-blocks command handler
- `lib/prompts/extensions/nudge.ts` — Enhanced block list (show topics) + merge guidance (>50 blocks)
- `tests/nudge-text.test.ts` — Updated tests for enhanced block list

## Verification
- typecheck: clean (exit 0)
- tests: all pass (0 fail)
- build: success
4 changes: 3 additions & 1 deletion index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
createCompressRangeTool,
createDecompressTool,
createMarkBlockTool,
createMergeBlocksTool,
createUnmarkBlockTool,
} from "./lib/compress"
import {
Expand Down Expand Up @@ -93,6 +94,7 @@ const server: Plugin = (async (ctx) => {
decompress: createDecompressTool(compressToolContext),
mark_block: createMarkBlockTool(compressToolContext),
unmark_block: createUnmarkBlockTool(compressToolContext),
merge_blocks: createMergeBlocksTool(compressToolContext),
}),
},
config: async (opencodeConfig) => {
Expand All @@ -113,7 +115,7 @@ const server: Plugin = (async (ctx) => {

const toolsToAdd: string[] = []
if (config.compress.permission !== "deny" && !config.experimental.allowSubAgents) {
toolsToAdd.push("compress", "decompress", "mark_block", "unmark_block")
toolsToAdd.push("compress", "decompress", "mark_block", "unmark_block", "merge_blocks")
}

if (toolsToAdd.length > 0) {
Expand Down
2 changes: 2 additions & 0 deletions lib/commands/help.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const TOOL_COMMANDS: Record<string, [string, string]> = {
compress: ["/acp compress [focus]", "Trigger manual compress tool execution"],
decompress: ["/acp decompress <n>", "Restore selected compression"],
recompress: ["/acp recompress <n>", "Re-apply a user-decompressed compression"],
"merge-blocks": ["/acp merge-blocks <range|list>", "Merge adjacent compressed blocks into one"],
}

function getVisibleCommands(state: SessionState, config: PluginConfig): [string, string][] {
Expand All @@ -39,6 +40,7 @@ function getVisibleCommands(state: SessionState, config: PluginConfig): [string,
commands.push(TOOL_COMMANDS.compress)
commands.push(TOOL_COMMANDS.decompress)
commands.push(TOOL_COMMANDS.recompress)
commands.push(TOOL_COMMANDS["merge-blocks"]!)
}

return commands
Expand Down
1 change: 1 addition & 0 deletions lib/commands/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export {
handleManualToggleCommand,
handleManualTriggerCommand,
} from "./manual"
export { handleMergeBlocksCommand } from "./merge-blocks"
export { handleRecompressCommand } from "./recompress"
export { handleStatsCommand } from "./stats"
export { handleSweepCommand } from "./sweep"
Loading
Loading