[Bug] Task lifecycle progress never reaches history, so the panel cannot show the running tool

Open Beginner friendly
#445 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

  • #446 by @audichuang — closed without merging
  • #624 by @Dante-dan — closed without merging

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
65/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
react, typescript
Domain
backend

Research direction

Start at filterNotificationsForHistory in apps/cli/src/lib/acp/history.ts:835-861: the tool_call_update branch keeps only completed/failed status, non-empty rawInput, or _meta.claudeCode.toolResponse, so _meta.lody.task falls through to the return false at :861. Then read applyNotificationOnHistory in packages/shared/src/acp/history-apply.ts:1737-1749, which already upserts snapshots by taskId. Reproduce with a handleACPUpdateMessage test in apps/cli/src/lib/acp/history.test.ts using the _meta.lody.task payload from the report; the existing test at :233 only covers the legacy rawInput.lodyClaudeTaskLifecycle carrier. Done means the persisted subagent_task item carries lastToolName and usage.

Written by the indexing model from the issue text.

Description

Affected area

Agent runtime / ACP

Installation method

Built from source

Lody version or commit

f90842d6

Operating system

Linux 7.0.0-30-generic (Ubuntu)

Agent or runtime

Claude Code — bundled acp-extension-claude 0.70.0 on @anthropic-ai/claude-agent-sdk 0.3.258

What happened?

The subagent task panel's "Running {{tool}}" line can never appear, for any provider. Every non-terminal task lifecycle snapshot is dropped before it reaches persisted history, so the only field that carries the running tool name never arrives.

The chain, verified on origin/main at f90842d6:

  1. last_tool_name reaches Lody on exactly one message. grep -n "last_tool_name" over the bundled @anthropic-ai/claude-agent-sdk/sdk.d.ts returns a single hit, line 5160, inside SDKTaskProgressMessage. SDKTaskStartedMessage, SDKTaskUpdatedMessage and SDKTaskNotificationMessage do not declare it.

  2. The bundled adapter emits that as a non-terminal tool_call_update. packages/acp-extension-claude/src/acp-agent.ts:242-245 maps task_progress to status: "in_progress", and the object built at :300-309 has sessionUpdate: "tool_call_update", _meta: { lody: { task } }, and no rawInput key at all. lastToolName rides inside that task payload (:274, :296). The adapter's own test asserts this shape: packages/acp-extension-claude/src/tests/acp-agent.test.ts:8727 ("emits task lifecycle notifications with full task payloads") feeds a task_progress carrying last_tool_name: "Read" at :8749 and asserts the four emitted notifications are ["tool_call", "tool_call_update", "tool_call_update", "tool_call_update"].

  3. filterNotificationsForHistory drops it. apps/cli/src/lib/acp/history.ts:835-861 keeps a tool_call_update only when status === 'completed' || status === 'failed' (:839), or it carries a non-empty rawInput (:844-847), or it carries _meta.claudeCode.toolResponse (:851-859); otherwise :861 return false. _meta.lody.task is not a keep-reason, so the update never reaches applyNotificationOnHistory.

  4. The panel reads only from persisted history. packages/components/src/components/ai-gui/subagent-task-panel.tsx:88-91 renders Running {{tool}} from task.lastToolName, fed exclusively by collectSubagentTasks(message.items) (view.tsx:807, :3381), where message is the persisted Loro history. There is no client-side applier: grep -rn "applyNotificationOnHistory\|parseLodyTaskMeta\|handleACPUpdateMessage" packages/components/src apps/electron/src returns zero hits.

The same drop also loses a non-terminal task_updated snapshot, so mid-flight status changes and in-progress usage are lost too.

Why this survived: the only existing coverage, apps/cli/src/lib/acp/history.test.ts:233 ("upserts Claude task lifecycle progress into a single subagent_task item"), exercises the legacy rawInput.lodyClaudeTaskLifecycle carrier, which passes the non-empty-rawInput branch. The shipped _meta.lody.task carrier has no history coverage at all.

What did you expect?

A task lifecycle snapshot should reach history and update the existing subagent_task item, so the panel can show the running tool while a subagent works, instead of a static "Working…" until the task settles.

The filter's stated reason does not apply to this carrier. Its comment says persisting all intermediate snapshots "causes the CRDT history to blow up" — that concern is about per-tick payload bytes from terminal-output snapshots. A task snapshot is a handful of small scalars, and the applier upserts it in place by taskId (packages/shared/src/acp/history-apply.ts:1737-1749), so a kept tick is a few LoroMap.set operations on one item.

How can we reproduce it?

This was reproduced at the code and unit level, not by observing the desktop UI — stated plainly so the report is not read as a UI observation.

Add a test to apps/cli/src/lib/acp/history.test.ts that drives handleACPUpdateMessage with the shape the bundled adapter emits for task_progress, then read the persisted history:

sessionUpdate: 'tool_call_update'
toolCallId:    'task:task-1'
kind:          'think'
status:        'in_progress'
_meta:         { lody: { task: { version: 1, taskId: 'task-1', kind: 'subagent',
                 status: 'in_progress', actor: 'Explore', lastToolName: 'Read',
                 usage: { totalTokens: 100, toolUses: 2, durationMs: 500 } } } }

No subagent_task item gains lastToolName or usage. Sending the identical _meta.lody.task payload on a tool_call (which is what task_started becomes) does persist, because the filter's tool_call_update branch is never reached for it — which isolates the filter as the only difference.

How often does it happen?

Every time

Additional context

Scope note: the sibling path apps/cli/src/agent/claude-task-lifecycle.ts, reached through the _claude/taskLifecycle extension method, is documented as "One-release compatibility for pre-Core-v0.1 managed runtimes" (apps/cli/src/agent/lody-acp-extension.ts:181). grep -rn "taskLifecycle" packages/acp-extension-claude/src/ returns zero non-test hits, so the bundled adapter never uses that lane and _meta.lody.task is the live carrier.

Before submitting
  • I searched the existing issues and did not find a duplicate.
  • This report concerns an open-source component in this repository, not a hosted service, Web or mobile app, account, or billing issue.
  • This is not a security vulnerability; security reports follow the repository's security policy.
  • I removed credentials, private source, conversations, prompts, personal data, and other sensitive information.
Dominant language
TypeScript
Stars
1.2k
Forks
141
Avg merge
12h 37m
Merged PRs (30d)
718

Getting set up

This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from LodyAI/Lody

All issues in LodyAI/Lody

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.