Skip to content

feat(agent): add manual compaction command#1619

Merged
zerob13 merged 2 commits into
devfrom
codex/compact-command
May 12, 2026
Merged

feat(agent): add manual compaction command#1619
zerob13 merged 2 commits into
devfrom
codex/compact-command

Conversation

@zerob13
Copy link
Copy Markdown
Collaborator

@zerob13 zerob13 commented May 12, 2026

Summary

  • Add DeepChat-only /compact slash command and typed sessions.compact route
  • Reuse existing compaction message/event flow for manual compaction while ignoring auto-only threshold/retain settings
  • Hide /compact during generation without disabling other slash completions, and keep ACP/new-thread behavior unchanged
  • Refresh chat messages after manual compaction and update neutral compaction copy

Closes #1618

Tests

  • pnpm run format
  • pnpm run i18n
  • pnpm run lint
  • pnpm run typecheck
  • pnpm exec vitest run test/renderer/components/ChatPage.test.ts test/renderer/components/NewThreadPage.test.ts test/renderer/composables/useChatInputMentions.test.ts test/renderer/components/MessageList.test.ts test/main/presenter/agentRuntimePresenter/agentRuntimePresenter.test.ts test/main/presenter/agentRuntimePresenter/compactionService.test.ts test/main/routes/contracts.test.ts test/main/routes/dispatcher.test.ts

Summary by CodeRabbit

  • New Features

    • Added a DeepChat /compact slash command to manually compress conversation context for idle sessions (runs without sending a user message).
  • Improvements

    • Updated compaction UX copy and localization across multiple languages.
    • Command visibility: shown only for idle sessions and suppressed during generation; UI input aware of generating state; toast feedback for no-op/failure.
  • Documentation

    • Added plan, spec, and task checklist for the manual compaction command.
  • Tests

    • Added unit and integration tests covering command visibility, route, presenter, and compaction flows.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 12, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a1fe1032-e762-41d5-9a29-e3ab56532e7f

📥 Commits

Reviewing files that changed from the base of the PR and between a4c1d40 and 6cfabbb.

📒 Files selected for processing (3)
  • src/main/presenter/agentRuntimePresenter/index.ts
  • src/renderer/src/components/chat/composables/useChatInputMentions.ts
  • test/main/presenter/agentRuntimePresenter/agentRuntimePresenter.test.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/renderer/src/components/chat/composables/useChatInputMentions.ts
  • src/main/presenter/agentRuntimePresenter/index.ts

📝 Walkthrough

Walkthrough

Adds a DeepChat-only /compact slash command: typed sessions.compact route, CompactionService manual preparation, presenter wiring, renderer suggestion + ChatPage interception, i18n updates, docs, and tests across backend, routes, and renderer.

Changes

Manual Compaction Command Feature

Layer / File(s) Summary
Shared contracts & types
src/shared/contracts/common.ts, src/shared/types/agent-interface.d.ts, src/shared/types/presenters/agent-session.presenter.d.ts, src/shared/contracts/routes.ts, src/shared/contracts/routes/sessions.routes.ts
Adds SessionCompactionStateSchema, declares sessions.compact route, and adds compactSession method signatures to agent/presenter types.
CompactionService and presenters
src/main/presenter/agentRuntimePresenter/compactionService.ts, src/main/presenter/agentRuntimePresenter/index.ts, src/main/presenter/agentSessionPresenter/index.ts
Implements prepareForManualCompaction and compactSession entrypoints; enforces DeepChat-only and idle checks, computes generation settings and system prompt, prepares/apply compaction intent, and returns updated compaction state.
Route dispatcher & validation
src/main/routes/index.ts, test/main/routes/contracts.test.ts, test/main/routes/dispatcher.test.ts
Wires sessionsCompactRoute into dispatchDeepchatRoute, validates route input/output parsing and dispatcher calls presenter for compactSession.
Renderer session client (IPC)
src/renderer/api/SessionClient.ts
Exports SessionClient.compactSession(sessionId) that invokes sessionsCompactRoute via IPC.
Slash command UI, mentions & ChatInputBox
src/renderer/src/components/chat/mentions/utils.ts, src/renderer/src/components/chat/composables/useChatInputMentions.ts, src/renderer/src/components/chat/ChatInputBox.vue
Adds /compact command constants, matcher, visibility logic, and suggestion builder; useChatInputMentions optionally prepends the manual compaction suggestion when idle/non-ACP/non-generating; ChatInputBox forwards isGenerating and command description.
ChatPage & NewThreadPage integration
src/renderer/src/pages/ChatPage.vue, src/renderer/src/pages/NewThreadPage.vue
ChatPage intercepts exact /compact submissions (idle DeepChat only), calls sessionClient.compactSession, refreshes messages, and shows noop/error toasts; NewThreadPage guards against creating deepchat drafts for /compact in non-ACP mode.
Internationalization
src/renderer/src/i18n/{da-DK,en-US,fa-IR,fr-FR,he-IL,ja-JP,ko-KR,pt-BR,ru-RU,zh-CN,zh-HK,zh-TW}/chat.json
Updates compaction blocks: removes “automatic” wording, adds commandDescription, noopTitle, noopDescription, and failedTitle for manual compaction UI states.
Documentation
docs/features/manual-compaction-command/plan.md, docs/features/manual-compaction-command/spec.md, docs/features/manual-compaction-command/tasks.md
Adds plan, spec, and completed tasks documenting the implementation approach, acceptance criteria, and task checklist for the manual compaction command.
Comprehensive tests
test/main/presenter/agentRuntimePresenter/agentRuntimePresenter.test.ts, test/main/presenter/agentRuntimePresenter/compactionService.test.ts, test/main/routes/*, test/renderer/components/*, test/renderer/composables/useChatInputMentions.test.ts
Adds/updates tests: backend compaction intent creation and presenter guards (idle/ACP/generating/no-history), route/dispatcher contract tests, renderer tests for ChatPage/NewThreadPage interception and toast behavior, mentions visibility and exact-match tests, and MessageList i18n assertions.

Sequence Diagram(s)

sequenceDiagram
    participant User as User/ChatPage
    participant Client as SessionClient
    participant IPC as IPC Bridge
    participant Dispatcher as Dispatcher
    participant Presenter as AgentSessionPresenter
    participant Runtime as AgentRuntimePresenter
    participant Service as CompactionService
    participant DB as Session Storage
    User->>Client: /compact command detected
    Client->>IPC: invoke sessions.compact route
    IPC->>Dispatcher: route to dispatchDeepchatRoute
    Dispatcher->>Presenter: compactSession(sessionId)
    Presenter->>Runtime: agent.compactSession(sessionId)
    Runtime->>Service: prepareForManualCompaction()
    Service->>DB: load context-history, sort by order
    Service->>Service: prepareCompaction(protectedTurns:0, force:true)
    Service-->>Runtime: CompactionIntent | null
    alt Intent exists
        Runtime->>DB: applyCompactionIntent()
        Runtime-->>Presenter: { compacted: true, state }
    else No intent
        Runtime-->>Presenter: { compacted: false, state }
    end
    Presenter-->>Dispatcher: return result
    Dispatcher-->>IPC: validated output
    IPC-->>Client: { compacted, state }
    Client->>User: refresh messages / show toast
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • ThinkInAIXYZ/deepchat#1605: Modifies presenter code related to context-budget/streaming and touches the same presenter areas as this PR.

Poem

🐰 Hop, hop—I compact with a twitch and a click,
A /compact command makes the old context stick,
Idle DeepChat listens, no model sees the line,
History shrinks neatly; the session feels fine.
Rabbit cheers softly: small hops, tidy mind—so slick!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(agent): add manual compaction command' accurately summarizes the main change—adding a manual /compact slash command feature for session compaction in DeepChat.
Linked Issues check ✅ Passed The PR fully addresses issue #1618's request for manual/proactive session compaction: implements a /compact slash command for DeepChat sessions that allows early manual compaction before automatic thresholds are reached.
Out of Scope Changes check ✅ Passed All changes are in scope: the PR adds manual compaction route/contract, presenter methods, renderer UI components, slash command integration, i18n translations, and comprehensive tests—all directly supporting the /compact command feature.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/compact-command

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/main/presenter/agentRuntimePresenter/index.ts`:
- Around line 1629-1671: compactSession runs multiple awaits before calling
this.setSessionStatus(sessionId, 'generating'), allowing concurrent
sends/resumes to interleave; acquire the session-level "generating" lock or set
the generating status atomically before any awaited prep work (i.e. before
getEffectiveSessionGenerationSettings / resolveInterleavedReasoningConfig /
resolveDeepChatContextBudgetLength / capAgentRequestMaxTokens /
resolveActiveSkillNamesForToolProfile / resolveProjectDir /
loadToolDefinitionsForSession / buildSystemPromptWithSkills and the call to
compactionService.prepareForManualCompaction), and ensure you release or revert
that lock/status if prepareForManualCompaction returns no intent or on error so
you don't leave the session stuck (use the existing session lock API or move
this.setSessionStatus(sessionId, 'generating') up and add proper cleanup).

In `@src/renderer/src/components/chat/composables/useChatInputMentions.ts`:
- Around line 198-200: The hardcoded fallback string passed into
createManualCompactionSuggestion (options.compactCommandDescription?.value ??
'Compact conversation context') must be replaced with an i18n lookup; change the
fallback to use the component's i18n translator (e.g.,
useI18n().t('your.key.for.compactConversationContext')) so that when
options.compactCommandDescription is missing the user-facing text comes from the
i18n keys, not a raw English string; update the call site around
createManualCompactionSuggestion and ensure you import/use the same i18n
instance used elsewhere in this file.

In `@src/shared/types/presenters/agent-session.presenter.d.ts`:
- Line 104: Typo in the compactSession return type: change the misspelled
property name "compated" to "compacted" in the compactSession declaration so it
returns a Promise with a boolean "compacted" and the existing
SessionCompactionState; update the compactSession signature in
agent-session.presenter (and any related type/implementation that declare the
same shape) to use "compacted" to match consumers and implementations.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f62c17ef-ee48-4a7f-8efe-00bb06d8b9ec

📥 Commits

Reviewing files that changed from the base of the PR and between fc0b458 and a4c1d40.

📒 Files selected for processing (38)
  • docs/features/manual-compaction-command/plan.md
  • docs/features/manual-compaction-command/spec.md
  • docs/features/manual-compaction-command/tasks.md
  • src/main/presenter/agentRuntimePresenter/compactionService.ts
  • src/main/presenter/agentRuntimePresenter/index.ts
  • src/main/presenter/agentSessionPresenter/index.ts
  • src/main/routes/index.ts
  • src/renderer/api/SessionClient.ts
  • src/renderer/src/components/chat/ChatInputBox.vue
  • src/renderer/src/components/chat/composables/useChatInputMentions.ts
  • src/renderer/src/components/chat/mentions/utils.ts
  • src/renderer/src/i18n/da-DK/chat.json
  • src/renderer/src/i18n/en-US/chat.json
  • src/renderer/src/i18n/fa-IR/chat.json
  • src/renderer/src/i18n/fr-FR/chat.json
  • src/renderer/src/i18n/he-IL/chat.json
  • src/renderer/src/i18n/ja-JP/chat.json
  • src/renderer/src/i18n/ko-KR/chat.json
  • src/renderer/src/i18n/pt-BR/chat.json
  • src/renderer/src/i18n/ru-RU/chat.json
  • src/renderer/src/i18n/zh-CN/chat.json
  • src/renderer/src/i18n/zh-HK/chat.json
  • src/renderer/src/i18n/zh-TW/chat.json
  • src/renderer/src/pages/ChatPage.vue
  • src/renderer/src/pages/NewThreadPage.vue
  • src/shared/contracts/common.ts
  • src/shared/contracts/routes.ts
  • src/shared/contracts/routes/sessions.routes.ts
  • src/shared/types/agent-interface.d.ts
  • src/shared/types/presenters/agent-session.presenter.d.ts
  • test/main/presenter/agentRuntimePresenter/agentRuntimePresenter.test.ts
  • test/main/presenter/agentRuntimePresenter/compactionService.test.ts
  • test/main/routes/contracts.test.ts
  • test/main/routes/dispatcher.test.ts
  • test/renderer/components/ChatPage.test.ts
  • test/renderer/components/MessageList.test.ts
  • test/renderer/components/NewThreadPage.test.ts
  • test/renderer/composables/useChatInputMentions.test.ts

Comment thread src/main/presenter/agentRuntimePresenter/index.ts Outdated
Comment on lines +198 to +200
createManualCompactionSuggestion(
options.compactCommandDescription?.value ?? 'Compact conversation context'
)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Avoid hardcoded fallback for command description.

Line 199 falls back to a raw English string ('Compact conversation context'). This is user-facing and should come from i18n keys only.

Suggested fix
-        createManualCompactionSuggestion(
-          options.compactCommandDescription?.value ?? 'Compact conversation context'
-        )
+        createManualCompactionSuggestion(options.compactCommandDescription?.value ?? '')

As per coding guidelines, "All user-facing strings must use vue-i18n keys from src/renderer/src/i18n instead of hardcoded text".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/renderer/src/components/chat/composables/useChatInputMentions.ts` around
lines 198 - 200, The hardcoded fallback string passed into
createManualCompactionSuggestion (options.compactCommandDescription?.value ??
'Compact conversation context') must be replaced with an i18n lookup; change the
fallback to use the component's i18n translator (e.g.,
useI18n().t('your.key.for.compactConversationContext')) so that when
options.compactCommandDescription is missing the user-facing text comes from the
i18n keys, not a raw English string; update the call site around
createManualCompactionSuggestion and ensure you import/use the same i18n
instance used elsewhere in this file.

): Promise<ChatMessagePageResult>
searchHistory(query: string, options?: HistorySearchOptions): Promise<HistorySearchHit[]>
getSessionCompactionState(sessionId: string): Promise<SessionCompactionState>
compactSession(sessionId: string): Promise<{ compacted: boolean; state: SessionCompactionState }>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Fix typo in return type property name.

The return type contains a spelling error: compated should be compacted. This typo will cause type errors throughout the codebase where implementations and consumers use the correct spelling.

🐛 Proposed fix
-  compactSession(sessionId: string): Promise<{ compated: boolean; state: SessionCompactionState }>
+  compactSession(sessionId: string): Promise<{ compacted: boolean; state: SessionCompactionState }>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
compactSession(sessionId: string): Promise<{ compacted: boolean; state: SessionCompactionState }>
compactSession(sessionId: string): Promise<{ compacted: boolean; state: SessionCompactionState }>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/shared/types/presenters/agent-session.presenter.d.ts` at line 104, Typo
in the compactSession return type: change the misspelled property name
"compated" to "compacted" in the compactSession declaration so it returns a
Promise with a boolean "compacted" and the existing SessionCompactionState;
update the compactSession signature in agent-session.presenter (and any related
type/implementation that declare the same shape) to use "compacted" to match
consumers and implementations.

@zerob13 zerob13 merged commit eb75ac5 into dev May 12, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] 能添加一个主动压缩对话的按钮吗

1 participant