Skip to content

feat(cli): add /thinkback command to review session timeline of decisions, changes and fixes#2917

Closed
wenshao wants to merge 14 commits intoQwenLM:mainfrom
wenshao:feat/thinkback-command
Closed

feat(cli): add /thinkback command to review session timeline of decisions, changes and fixes#2917
wenshao wants to merge 14 commits intoQwenLM:mainfrom
wenshao:feat/thinkback-command

Conversation

@wenshao
Copy link
Copy Markdown
Collaborator

@wenshao wenshao commented Apr 5, 2026

Summary

Add a new /thinkback slash command that leverages the LLM to analyze conversation history and generate a structured timeline of key events in the current session.

Comparison with Claude Code

Claude Code currently does not have a built-in session timeline review command. Users must manually scroll through conversation or rely on /compact (context compression) which discards detail rather than summarizing it.

Capability Claude Code Qwen Code (/thinkback)
Session timeline review ❌ Not available ✅ Auto-generated structured timeline
Filter by time range ❌ N/A --from "1h ago"
Filter by topic ❌ N/A --topic "auth"
Key decision tracking ❌ Manual scrolling ✅ Highlights decisions, changes, fixes
Multi-mode support N/A ✅ interactive / non_interactive / acp
i18n N/A ✅ 6 locales (en/zh/ja/ru/pt/de)

This is a new capability beyond Claude Code's feature set, giving Qwen Code users a structured way to review session progress without losing context.

Before / After

Before

Users have no structured way to review what happened during a session. To recall key decisions, file changes, or bug fixes, they must manually scroll through the entire conversation history.

After

Users can run /thinkback to get an auto-generated timeline:

> /thinkback

# Timeline Review
- **Step 1** — [Change] Updated auth middleware to fix session token storage (auth.ts)
- **Step 2** — [Decision] Switched to JWT-based tokens for compliance (config.ts, auth.ts)
- **Step 3** — [Fix] Resolved token refresh race condition (tokenManager.ts)

With optional filtering:

> /thinkback --from "30 min ago" --topic "auth"

Changes

File Change
thinkbackCommand.ts New command implementation following summaryCommand pattern
thinkbackCommand.test.ts 5 test cases covering empty history, generation, args parsing, missing config, concurrent blocking
BuiltinCommandLoader.ts Register the new command
en.js, zh.js, ja.js, ru.js, pt.js, de.js i18n keys for all 6 locales

Review notes (fixes applied during audit)

Original implementation was by gemini-3.1-pro-preview. The following issues were found and fixed:

  1. TS compile errorimport('./types.js').HistoryItemWithoutId referenced wrong module, fixed to import('../types.js')
  2. Missing i18n keys — All UI-facing strings were unregistered in locale files, added to all 6 locales (en/zh/ja + en-fallback for ru/pt/de)
  3. LLM prompts wrapped in t() — Translating prompts sent to the LLM degrades output quality. Removed t() wrapping, now uses plain strings (consistent with btwCommand pattern)

Test plan

  • npx tsc --noEmit — no type errors
  • vitest run thinkbackCommand.test.ts — 5/5 passed
  • vitest run BuiltinCommandLoader.test.ts — 9/9 passed

- Added a new `/thinkback` slash command to review the current session's key decisions and changes.
- Added support for `--from` and `--topic` filters to narrow down the timeline context.
- Registered the command in `BuiltinCommandLoader.ts`.
- Included a comprehensive test suite covering empty histories, missing configs, concurrent triggers, and argument passing.
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 5, 2026

📋 Review Summary

This PR introduces a new /thinkback slash command that leverages the LLM to generate a timeline review of the current session's key decisions, modifications, and bug fixes. The implementation is well-structured with comprehensive test coverage. Overall, the code follows project conventions and demonstrates good practices, though there are a few areas for improvement in argument parsing robustness and error handling.

🔍 General Feedback

  • Positive aspects:

    • Comprehensive test suite covering edge cases (empty history, missing config, concurrent triggers, argument passing)
    • Good separation of concerns with the generateThinkbackMarkdown helper function
    • Proper support for multiple execution modes (interactive, non_interactive, acp)
    • Consistent use of the i18n t() function for all user-facing strings
    • Proper abort signal handling for cancellation support
    • Good pattern matching with existing commands like compressCommand
  • Architectural decisions:

    • Using LLM to parse conversation history and generate timeline is a clean approach
    • Streaming support for ACP mode follows established patterns
    • Pending item management for interactive mode is well-implemented

🎯 Specific Feedback

🟡 High

  • File: thinkbackCommand.ts:67-72 - The regex-based argument parsing is fragile and doesn't handle edge cases well (e.g., multiple --from arguments, invalid formats). Consider using a more robust argument parsing library like minimist or yargs-parser that's already used elsewhere in the project, or at minimum add validation for the parsed arguments.

  • File: thinkbackCommand.ts:80-85 - The getChatHistory function is defined but doesn't handle potential errors from geminiClient.getChat() returning null/undefined. Add a null check before calling getHistory():

    const getChatHistory = () => {
      const chat = geminiClient.getChat();
      if (!chat) {
        return [];
      }
      return chat.getHistory();
    };

🟢 Medium

  • File: thinkbackCommand.ts:78-82 - The history length check (history.length <= 2) is somewhat arbitrary. Consider making this threshold configurable or documenting why "2" was chosen (likely accounting for initial system messages). A comment explaining this would improve maintainability.

  • File: thinkbackCommand.ts:125-129 - The error message for empty LLM response could be more specific. Consider distinguishing between "no response from LLM" vs "response contained no text parts" for better debugging.

  • File: thinkbackCommand.test.ts:104-117 - The test for --from and --topic arguments validates the prompt string content, but doesn't test edge cases like:

    • Empty string arguments
    • Arguments with special characters
    • Missing one argument but not the other
      Consider adding tests for these scenarios.

🔵 Low

  • File: thinkbackCommand.ts:1 - The copyright notice says "Copyright 2025 Qwen" but other files in the codebase show "Copyright 2025 Google LLC" (as seen in compressCommand.ts and types.ts). Verify the correct copyright holder and update accordingly.

  • File: thinkbackCommand.ts:93-98 - The prompt template is quite long and could benefit from being extracted to a constant or using a template tag function for better readability and testability.

  • File: thinkbackCommand.test.ts:5 - The import of createMockCommandContext uses a relative path. Consider verifying this follows the project's import conventions (some commands use absolute imports from test-utils).

  • File: thinkbackCommand.ts:147-150 - The error message "Thinkback generation cancelled" is only thrown but never shown to the user in interactive mode when aborted (the abort check at line 143 returns early). This is inconsistent with compressCommand.ts which handles abort silently. Consider aligning the behavior.

✅ Highlights

  • Test coverage excellence: The test suite in thinkbackCommand.test.ts is comprehensive, covering 5 distinct scenarios including edge cases like empty history, missing config, and concurrent generation attempts.

  • Consistent pattern adoption: The implementation closely follows the established patterns from compressCommand.ts, particularly in:

    • Pending item management
    • Execution mode handling (interactive vs acp)
    • Error handling structure with try/catch/finally
    • Abort signal integration
  • Good i18n practices: All user-facing strings are wrapped with t() for internationalization, including dynamic interpolation for the --from and --topic arguments.

  • Clean async/await flow: The code properly handles async operations with appropriate error boundaries and cleanup in finally blocks where needed.

… from LLM prompts

- Fix TS compile error: HistoryItemWithoutId import path in test
- Add i18n keys for all 6 locales (en/zh/ja/ru/pt/de)
- Remove t() wrapping from LLM prompt strings to avoid degrading model output quality

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@wenshao wenshao requested a review from Copilot April 5, 2026 22:01
@wenshao wenshao changed the title feat(cli): add /thinkback command for timeline-based session review feat(cli): add /thinkback command to review session timeline of decisions, changes and fixes Apr 5, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a new built-in CLI slash command (/thinkback) that generates a timeline-style review of the current session, with optional --from and --topic filters, plus registration and localization updates.

Changes:

  • Introduces thinkbackCommand to generate a timeline review from chat history via the Gemini client.
  • Registers /thinkback in BuiltinCommandLoader.
  • Adds tests and new i18n strings for multiple locales.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
packages/cli/src/ui/commands/thinkbackCommand.ts Implements /thinkback command logic, argument parsing, and ACP streaming support.
packages/cli/src/ui/commands/thinkbackCommand.test.ts Adds unit tests for empty history, argument passing, missing config, and interactive concurrency blocking.
packages/cli/src/services/BuiltinCommandLoader.ts Registers the new built-in command so it’s available in the CLI.
packages/cli/src/i18n/locales/en.js Adds English strings for the new command.
packages/cli/src/i18n/locales/zh.js Adds Chinese translations for the new command strings.
packages/cli/src/i18n/locales/ja.js Adds Japanese translations for the new command strings.
packages/cli/src/i18n/locales/ru.js Adds Russian locale keys (currently untranslated English values).
packages/cli/src/i18n/locales/pt.js Adds Portuguese locale keys (currently untranslated English values).
packages/cli/src/i18n/locales/de.js Adds German locale keys (currently untranslated English values).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Add proper ru/pt/de translations for thinkback i18n keys
- Add vi.clearAllMocks() in beforeEach to prevent mock state leakage between tests

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Switch to getHistory(true) to exclude invalid/empty model contents
- Rename fromTopic -> fromTimeRange, topicMatch -> topicFilter for clarity

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Add session timeline review section (1.6) with usage examples,
execution modes, and tips. Update section numbering (1.7-1.9).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Verify stream_messages async generator yields progress and timeline
messages in ACP execution mode.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Add formatThinkbackError() helper with translated error template
"Failed to generate thinkback timeline: {{error}}" consistent with
summaryCommand's formatErrorMessage pattern. Applied across all
error paths (interactive, non-interactive, ACP).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

…ck paths

Returning {type:'message', content:''} still creates an empty history
entry. Return void so slashCommandProcessor skips result processing
entirely when ui.addItem already handled the display.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

The inner "Failed to generate thinkback - ..." message was wrapped by
formatThinkbackError, producing redundant output. Shortened to
"No text content received from LLM response" so the outer wrapper
provides full context. Also fix "Tokens" -> "tokens" in docs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

…back

Move setPendingItem(null) to a finally block so the pending indicator
is always cleared regardless of how the operation ends (success, error,
or external abort).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Verify that non-interactive mode returns {type:'message', messageType:'error'}
with formatted error content, unlike interactive mode which returns void.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@wenshao
Copy link
Copy Markdown
Collaborator Author

wenshao commented Apr 7, 2026

Closing: Claude Code's /think-back is a Year in Review animation feature, not a session timeline review command. This PR was based on an incorrect analysis of Claude Code's thinkback functionality.

@wenshao wenshao closed this Apr 7, 2026
@wenshao wenshao reopened this Apr 7, 2026
@wenshao wenshao closed this Apr 7, 2026
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.

2 participants