Skip to content

feat(agent): add progress todo tool#1635

Merged
zerob13 merged 7 commits into
devfrom
feat/add-todo-progress
May 19, 2026
Merged

feat(agent): add progress todo tool#1635
zerob13 merged 7 commits into
devfrom
feat/add-todo-progress

Conversation

@zerob13
Copy link
Copy Markdown
Collaborator

@zerob13 zerob13 commented May 18, 2026

Summary

  • add an agent-core update_plan tool with strict plan validation and guidance
  • publish plan updates through chat.plan.updated without inserting todo blocks into the message list
  • add a default-collapsed animated progress float backed by a renderer plan store
  • document the SDD spec, plan, and tasks for the progress todo feature

Tests

  • pnpm run format
  • pnpm run i18n
  • pnpm run typecheck
  • pnpm run lint
  • pnpm exec vitest run test/main/presenter/agentRuntimePresenter/dispatch.test.ts test/renderer/components/AgentProgressFloat.test.ts test/renderer/stores/agentPlanStore.test.ts test/renderer/components/ChatPage.test.ts test/main/presenter/toolPresenter/agentTools/agentPlanTool.test.ts test/renderer/components/message/MessageBlockBasics.test.ts

Note: local Node is v22.13.1, while package engines request >=24.14.1 <25; commands completed with engine warnings.

Summary by CodeRabbit

  • New Features

    • Collapsible floating agent progress panel, richer in-message plan checklist, live revisioned plan snapshots and a tool-driven "update plan" workflow with real-time renderer updates.
  • Bug Fixes

    • Prevented renderer crash from null/invalid assistant action types.
    • Internal progress updates are hidden from normal tool UI and message rendering.
  • Accessibility & Localization

    • Added ARIA label templates and translations for plan items.
  • Documentation

    • Added feature spec, implementation plan, tasks and crash spec with rollout and testing guidance.
  • Tests

    • Added/updated unit and UI tests for progress events, hydration, store behavior and rendering.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 18, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2ef03f5d-8d90-4fe7-8780-54cd9da767cf

📥 Commits

Reviewing files that changed from the base of the PR and between 4f1bfe2 and 62fd6d6.

📒 Files selected for processing (4)
  • src/renderer/src/components/chat/messageListItems.ts
  • src/renderer/src/components/message/MessageItemAssistant.vue
  • src/shared/contracts/common.ts
  • src/shared/types/agent-interface.d.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/renderer/src/components/message/MessageItemAssistant.vue
  • src/shared/types/agent-interface.d.ts
  • src/renderer/src/components/chat/messageListItems.ts

📝 Walkthrough

Walkthrough

Adds an agent progress “update_plan” MCP tool and chat.plan.updated event, server-side dispatch handling, renderer subscription and per-session Pinia store, floating progress UI and updated plan block rendering, Zod/type additions, hydration fix for nullable assistant action_type, and comprehensive tests and docs.

Changes

Agent Progress / Todo

Layer / File(s) Summary
Feature docs and tasks
docs/features/agent-progress-todo/*, docs/issues/assistant-action-type-null-renderer-crash/*
Spec, implementation plan, and task checklists for Agent Progress/Todo and action_type crash fix.
Shared types & event contracts
src/shared/types/agent-plan.ts, src/shared/contracts/events/chat.events.ts, src/shared/contracts/events.ts, src/shared/types/core/chat.ts, src/shared/chat.d.ts, src/shared/types/agent-interface.d.ts
Adds AgentPlan types, AgentPlanItem schema, chat.plan.updated event contract and registers it; extends assistant/block types with plan metadata.
AgentPlanTool implementation
src/main/presenter/toolPresenter/agentTools/agentPlanTool.ts
New AgentPlanTool with Zod validation, per-conversation in-memory state, revision/update timestamps, call() with optional onProgress emission and fixed response, plus getState/clearState.
Tool manager & presenter integration
src/main/presenter/toolPresenter/agentTools/agentToolManager.ts, src/main/presenter/toolPresenter/agentTools/index.ts, src/main/presenter/toolPresenter/index.ts
Initializes and exposes AgentPlanTool, routes update_plan calls, reserves tool name, re-exports constants, and injects progress checklist guidance into system prompt when available.
Runtime dispatch & event publishing
src/main/presenter/agentRuntimePresenter/dispatch.ts
Detects agent_plan progress updates, marks internal plan tool-call blocks, publishes chat.plan.updated events, and schedules renderer flushing.
Hydration: normalize persisted action_type
src/main/presenter/agentRuntimePresenter/messageStore.ts
Adds normalizePersistedActionType and omits action_type in hydrated assistant blocks when persisted value is null/unknown.
Renderer client & store
src/renderer/api/ChatClient.ts, src/renderer/src/stores/ui/agentPlan.ts
Adds onPlanUpdated subscription to ChatClient and new Pinia useAgentPlanStore with per-session snapshots, revision deduping, and persisted collapsed state.
Renderer UI & integration
src/renderer/src/components/chat/AgentProgressFloat.vue, src/renderer/src/components/message/MessageBlockPlan.vue, src/renderer/src/components/message/MessageItemAssistant.vue, src/renderer/src/pages/ChatPage.vue, src/renderer/src/components/chat/messageListItems.ts
New floating plan panel, richer plan block rendering, filter internal update_plan tool_call from tool-call UI, ChatPage integration with ResizeObserver and subscription wiring, and message-list type extensions.
i18n
src/renderer/src/i18n/*/chat.json
Adds workspace.plan.itemAriaLabel translations across locales for ARIA labels.
Tests
test/main/**, test/renderer/**
Adds/updates tests covering AgentPlanTool, dispatch event emission, messageStore hydration regression, ChatClient subscription, AgentProgressFloat, ChatPage integration, MCP indicator tool toggles, and agentPlanStore behavior.

Sequence diagrams: (skipped — changes are heterogeneous across many components)

Estimated code review effort: 🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs:

"I hopped through code and fields so bright,
I nudged the plan steps into the light.
A tiny carrot, a revision tick,
Floating panels that pop, not stick.
— rabbit dev, 🐇 celebrating updates tonight"

🚥 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 progress todo tool' accurately summarizes the main feature addition—implementing an agent progress/todo tool with plan validation and event publishing.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ 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 feat/add-todo-progress

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


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: 4

🧹 Nitpick comments (1)
src/main/presenter/agentRuntimePresenter/dispatch.ts (1)

362-363: ⚡ Quick win

Use shared tool-name constant instead of string literal.

Line 362 hardcodes 'update_plan'; this can drift from the source constant and silently stop internal plan-block marking if renamed.

♻️ Suggested patch
-import type { AgentPlanSnapshot } from '`@shared/types/agent-plan`'
+import type { AgentPlanSnapshot } from '`@shared/types/agent-plan`'
+import { UPDATE_PLAN_TOOL_NAME } from '../toolPresenter/agentTools'

 function markInternalPlanToolCallBlock(blocks: AssistantMessageBlock[], toolCallId: string): void {
@@
-  if (!block?.tool_call || block.tool_call.name !== 'update_plan') {
+  if (!block?.tool_call || block.tool_call.name !== UPDATE_PLAN_TOOL_NAME) {
     return
   }
🤖 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/main/presenter/agentRuntimePresenter/dispatch.ts` around lines 362 - 363,
The conditional currently compares block.tool_call.name to the hardcoded string
'update_plan'; change it to use the centralized tool-name constant exported by
the tools module (e.g. UPDATE_PLAN_TOOL_NAME or the exported symbol that
represents the update-plan tool) instead, updating the import at the top of
dispatch.ts and replacing the literal in the if check that references
block?.tool_call and block.tool_call.name so the code always uses the shared
constant.
🤖 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 `@docs/features/agent-progress-todo/plan.md`:
- Line 175: The doc currently contradicts the architecture by calling the
renderer store / event `chat.plan.updated` canonical while line 175 instructs to
keep the message block as canonical; update the wording so the message block is
explicitly the single source-of-truth for DeepChat progress state and describe
`chat.plan.updated` and the renderer store as derived/secondary views used for
UI rendering and fallback only; change the sentence at line 175 to state the
floating panel should be collapsed by default and that the message block is
canonical, and scan other mentions of `chat.plan.updated` and "renderer store"
to rephrase them as derived or fallback mechanisms to avoid implementation
drift.

In `@docs/features/agent-progress-todo/spec.md`:
- Line 7: Replace the machine-specific absolute path
`/Users/zerob13/Downloads/agent-progress-todo-spec.md` in
docs/features/agent-progress-todo/spec.md with a portable reference: either a
repo-relative path (e.g.,
docs/features/agent-progress-todo/agent-progress-todo-spec.md) or a generic
external-note like "see agent-progress-todo-spec.md in project docs"; keep the
`update_plan` mention and any other identifiers unchanged so reviewers can still
find the referenced model behavior.

In `@src/renderer/src/components/chat/AgentProgressFloat.vue`:
- Line 43: Replace the hardcoded ARIA label construction in
AgentProgressFloat.vue that directly interpolates entry.status and entry.step
with the vue-i18n translation lookup; map the possible status tokens (e.g.,
in_progress, completed, failed) to i18n keys in src/renderer/src/i18n and build
the aria-label via $t(...) (or the composable useI18n) so aria-label uses
translated status text and the translated step label rather than raw tokens
(refer to entry.status, entry.step and the :aria-label binding when making the
change).

In `@src/renderer/src/components/message/MessageBlockPlan.vue`:
- Line 31: The aria-label currently hardcodes "[${entry.status}] ${entry.label}"
in MessageBlockPlan.vue; replace this with a vue-i18n lookup that composes a
localized message and localized status label (e.g. use a key like
message.planEntryAria with params { status: $t(`status.${entry.status}`), label:
entry.label }) and ensure corresponding i18n keys exist in src/renderer/src/i18n
(message.planEntryAria and status.<statusName> entries); implement the lookup
either inline in the template using $t or via a computed property (referencing
entry.status and entry.label) so assistive text is fully translatable.

---

Nitpick comments:
In `@src/main/presenter/agentRuntimePresenter/dispatch.ts`:
- Around line 362-363: The conditional currently compares block.tool_call.name
to the hardcoded string 'update_plan'; change it to use the centralized
tool-name constant exported by the tools module (e.g. UPDATE_PLAN_TOOL_NAME or
the exported symbol that represents the update-plan tool) instead, updating the
import at the top of dispatch.ts and replacing the literal in the if check that
references block?.tool_call and block.tool_call.name so the code always uses the
shared constant.
🪄 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: 98d1b010-58bd-466c-8884-b50bff61bebc

📥 Commits

Reviewing files that changed from the base of the PR and between 2b8816d and d3b4622.

📒 Files selected for processing (38)
  • docs/features/agent-progress-todo/plan.md
  • docs/features/agent-progress-todo/spec.md
  • docs/features/agent-progress-todo/tasks.md
  • docs/issues/assistant-action-type-null-renderer-crash/plan.md
  • docs/issues/assistant-action-type-null-renderer-crash/spec.md
  • docs/issues/assistant-action-type-null-renderer-crash/tasks.md
  • src/main/presenter/agentRuntimePresenter/dispatch.ts
  • src/main/presenter/agentRuntimePresenter/messageStore.ts
  • src/main/presenter/toolPresenter/agentTools/agentPlanTool.ts
  • src/main/presenter/toolPresenter/agentTools/agentToolManager.ts
  • src/main/presenter/toolPresenter/agentTools/index.ts
  • src/main/presenter/toolPresenter/index.ts
  • src/renderer/api/ChatClient.ts
  • src/renderer/src/components/chat/AgentProgressFloat.vue
  • src/renderer/src/components/chat/messageListItems.ts
  • src/renderer/src/components/message/MessageBlockPlan.vue
  • src/renderer/src/components/message/MessageItemAssistant.vue
  • src/renderer/src/pages/ChatPage.vue
  • src/renderer/src/stores/ui/agentPlan.ts
  • src/shared/chat.d.ts
  • src/shared/contracts/common.ts
  • src/shared/contracts/events.ts
  • src/shared/contracts/events/chat.events.ts
  • src/shared/types/agent-interface.d.ts
  • src/shared/types/agent-plan.ts
  • src/shared/types/core/chat.ts
  • src/shared/types/presenters/tool.presenter.d.ts
  • test/main/presenter/agentRuntimePresenter/dispatch.test.ts
  • test/main/presenter/agentRuntimePresenter/messageStore.test.ts
  • test/main/presenter/toolPresenter/agentTools/agentPlanTool.test.ts
  • test/main/presenter/toolPresenter/toolPresenter.test.ts
  • test/main/routes/contracts.test.ts
  • test/renderer/api/clients.test.ts
  • test/renderer/components/AgentProgressFloat.test.ts
  • test/renderer/components/ChatPage.test.ts
  • test/renderer/components/McpIndicator.test.ts
  • test/renderer/components/message/MessageBlockBasics.test.ts
  • test/renderer/stores/agentPlanStore.test.ts

Comment thread docs/features/agent-progress-todo/plan.md Outdated
Comment thread docs/features/agent-progress-todo/spec.md Outdated
Comment thread src/renderer/src/components/chat/AgentProgressFloat.vue Outdated
Comment thread src/renderer/src/components/message/MessageBlockPlan.vue Outdated
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: 1

🤖 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 `@docs/features/agent-progress-todo/spec.md`:
- Line 60: The line claiming the floating panel "retains persistent records in
messages" conflicts with the rule that update_plan must not write plan blocks
into assistant messages; reword it to state that the floating progress panel
provides a lightweight, collapsible UI that shows real-time progress while
persisting state outside of assistant messages (e.g., in the UI
state/storage/logging), and explicitly reference update_plan and "plan" blocks
to clarify they must not be injected into assistant messages.
🪄 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: 53fa7856-c354-42d1-8ea5-0671bdd62064

📥 Commits

Reviewing files that changed from the base of the PR and between d3b4622 and 3a7cd0d.

📒 Files selected for processing (19)
  • docs/features/agent-progress-todo/plan.md
  • docs/features/agent-progress-todo/spec.md
  • src/main/presenter/agentRuntimePresenter/dispatch.ts
  • src/renderer/src/components/chat/AgentProgressFloat.vue
  • src/renderer/src/components/message/MessageBlockPlan.vue
  • 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
  • test/renderer/components/AgentProgressFloat.test.ts
  • test/renderer/components/message/MessageBlockBasics.test.ts
✅ Files skipped from review due to trivial changes (8)
  • 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/zh-HK/chat.json
  • src/renderer/src/i18n/fa-IR/chat.json
  • src/renderer/src/i18n/zh-CN/chat.json
  • src/renderer/src/i18n/da-DK/chat.json
  • src/renderer/src/i18n/fr-FR/chat.json
🚧 Files skipped from review as they are similar to previous changes (5)
  • src/renderer/src/components/chat/AgentProgressFloat.vue
  • test/renderer/components/AgentProgressFloat.test.ts
  • test/renderer/components/message/MessageBlockBasics.test.ts
  • src/renderer/src/components/message/MessageBlockPlan.vue
  • src/main/presenter/agentRuntimePresenter/dispatch.ts

Comment thread docs/features/agent-progress-todo/spec.md Outdated
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: 1

🤖 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/renderer/src/pages/ChatPage.vue`:
- Around line 283-294: syncPlanFloatReservedHeight currently uses only the
trigger's offsetHeight which causes the expanded plan body to overlap messages;
modify syncPlanFloatReservedHeight to reserve the full floating panel height by
using the layer's full offsetHeight (or, if there is an expanded-inner element,
query its offsetHeight) instead of just the trigger height, then add
PLAN_FLOAT_SAFE_GAP and set planFloatReservedHeight.value accordingly; reference
planFloatLayer, latestPlanSnapshot, syncPlanFloatReservedHeight,
PLAN_FLOAT_SAFE_GAP and planFloatReservedHeight when making the change.
🪄 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: e801c8b2-513d-4b2b-b84b-02314f867667

📥 Commits

Reviewing files that changed from the base of the PR and between 1eef9b5 and 4f1bfe2.

📒 Files selected for processing (3)
  • src/renderer/src/components/chat/AgentProgressFloat.vue
  • src/renderer/src/pages/ChatPage.vue
  • test/renderer/components/ChatPage.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • test/renderer/components/ChatPage.test.ts

Comment thread src/renderer/src/pages/ChatPage.vue
@zerob13 zerob13 merged commit f238aff into dev May 19, 2026
3 checks passed
@zhangmo8 zhangmo8 deleted the feat/add-todo-progress branch May 19, 2026 07:04
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