Skip to content

feat(desktop): mid-turn steer injection and tool-call details in history#3263

Closed
JesonChou wants to merge 2 commits into
esengine:main-v2from
JesonChou:fix/session-steer
Closed

feat(desktop): mid-turn steer injection and tool-call details in history#3263
JesonChou wants to merge 2 commits into
esengine:main-v2from
JesonChou:fix/session-steer

Conversation

@JesonChou
Copy link
Copy Markdown

Fix two core desktop features:

  1. Model dialogue mid-turn steer: when the model is running, user input is now injected as mid-turn guidance via a steer queue instead of being silently dropped by runGuarded. A runningRef replaces the stale state.running closure in handleSend, and the steer flows through App.Steer -> Controller.Steer -> Agent.Steer into a FIFO queue consumed each iteration of the agent loop, persisted to the session so it remains visible for subsequent API calls. A Steer event confirms delivery to the frontend.

  2. History tool-call details: HistoryMessage now carries ToolName, ToolArgs, ToolOutput, ToolID, and ToolTruncated fields mapped from the provider's tool-call records. The history reducer and HistoryPanel's previewMessagesToItems render tool messages as ToolCard items, so switching between saved sessions shows full tool invocation details.

Changes:

  • internal/event/event.go: add Steer event kind
  • internal/agent/agent.go: add steerQueue, Steer/consumeSteer/ SteerConsumed/clearSteerQueue/steerQueueLen, midTurnSteerPrefix, and steer consumption/peristence in Run loop
  • internal/control/controller.go: add Steer/SteerConsumed methods
  • desktop/app.go: add App.Steer, expand HistoryMessage struct with tool fields, map tool messages in historyMessages via toolCallByID
  • desktop/frontend/src/lib/bridge.ts: add Steer to AppBindings and mock
  • desktop/frontend/src/lib/types.ts: add steer event kind, tool fields to HistoryMessage
  • desktop/frontend/src/lib/useController.ts: add steer callback, update history reducer for tool messages
  • desktop/frontend/src/App.tsx: add runningRef + steer in handleSend
  • desktop/frontend/src/components/HistoryPanel.tsx: update previewMessagesToItems for tool messages

Fix two core desktop features:
1. Model dialogue mid-turn steer: when the model is running, user input
   is now injected as mid-turn guidance via a steer queue instead of
   being silently dropped by runGuarded. A runningRef replaces the stale
   state.running closure in handleSend, and the steer flows through
   App.Steer -> Controller.Steer -> Agent.Steer into a FIFO queue
   consumed each iteration of the agent loop, persisted to the session
   so it remains visible for subsequent API calls. A Steer event
   confirms delivery to the frontend.

2. History tool-call details: HistoryMessage now carries ToolName,
   ToolArgs, ToolOutput, ToolID, and ToolTruncated fields mapped from
   the provider's tool-call records. The history reducer and
   HistoryPanel's previewMessagesToItems render tool messages as
   ToolCard items, so switching between saved sessions shows full
   tool invocation details.

Changes:
- internal/event/event.go: add Steer event kind
- internal/agent/agent.go: add steerQueue, Steer/consumeSteer/
  SteerConsumed/clearSteerQueue/steerQueueLen, midTurnSteerPrefix,
  and steer consumption/peristence in Run loop
- internal/control/controller.go: add Steer/SteerConsumed methods
- desktop/app.go: add App.Steer, expand HistoryMessage struct with
  tool fields, map tool messages in historyMessages via toolCallByID
- desktop/frontend/src/lib/bridge.ts: add Steer to AppBindings and mock
- desktop/frontend/src/lib/types.ts: add steer event kind, tool fields
  to HistoryMessage
- desktop/frontend/src/lib/useController.ts: add steer callback,
  update history reducer for tool messages
- desktop/frontend/src/App.tsx: add runningRef + steer in handleSend
- desktop/frontend/src/components/HistoryPanel.tsx: update
  previewMessagesToItems for tool messages
@github-actions github-actions Bot added the v2 Go rewrite (1.x) — main-v2 branch, active development label Jun 5, 2026
Copy link
Copy Markdown
Collaborator

@SivanCola SivanCola left a comment

Choose a reason for hiding this comment

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

Requesting changes after reviewing this PR against main-v2.\n\nFindings:\n\n1. is not wired into the desktop/server wire event kind maps. The PR adds the new event kind, but and do not map it, while serializes . That means steer events are emitted with an empty , so the frontend cannot reliably receive the intended event. Please add the wire mappings and a regression test.\n\n2. Steer injection is not tab-scoped. The frontend dispatches the local user bubble to , but routes through . In a multi-tab/background-running scenario, the UI can show the steer message in one tab while the backend injects it into a different active controller. Please add a tab-scoped API, analogous to Submit/Cancel/ApproveForTab, and route the frontend call with the tab id.\n\nThis PR also overlaps with #3286 for history tool details. I would recommend splitting the mid-turn steer feature from the history replay fix, then rebasing on the dedicated history fix once it lands.

@SivanCola
Copy link
Copy Markdown
Collaborator

Correction to my review above: the shell stripped the inline code identifiers from the submitted review body. The exact findings are:

  1. event.Steer is not wired into the desktop/server wire event kind maps. The PR adds the new event kind in internal/event/event.go, but desktop/wire.go and internal/serve/wire.go do not map event.Steer, while toWire serializes kindNames[e.Kind]. That means steer events are emitted with an empty kind, so the frontend cannot reliably receive the intended steer event. Please add the wire mappings and a regression test.

  2. Steer injection is not tab-scoped. The frontend dispatches the local user bubble to activeTabId, but App.Steer(text) routes through ctrlByTabID(""). In a multi-tab/background-running scenario, the UI can show the steer message in one tab while the backend injects it into a different active controller. Please add a tab-scoped API, analogous to SubmitForTab / CancelForTab / ApproveCommandForTab, and route the frontend call with the tab id.

This PR also overlaps with #3286 for history tool details. I would recommend splitting the mid-turn steer feature from the history replay fix, then rebasing on the dedicated history fix once it lands.

@JesonChou JesonChou requested a review from SivanCola June 5, 2026 16:43
@JesonChou
Copy link
Copy Markdown
Author

感谢大佬意见,我继续修改

@JesonChou JesonChou changed the base branch from main-v2 to codex/fix-history-tool-details June 6, 2026 06:56
@JesonChou JesonChou changed the base branch from codex/fix-history-tool-details to main-v2 June 6, 2026 06:56
@JesonChou JesonChou closed this Jun 6, 2026
@JesonChou JesonChou deleted the fix/session-steer branch June 6, 2026 13:03
JesonChou added a commit to JesonChou/DeepSeek-Reasonix that referenced this pull request Jun 6, 2026
…osition-aware tool-result pairing

- Add Steer event kind (internal/event/event.go) with wire mappings in
  desktop/wire.go and internal/serve/wire.go, plus regression tests.
- Add Agent.steerQueue with Steer / consumeSteer / SteerConsumed /
  clearSteerQueue / steerQueueLen and mid-turn injection in the Run loop:
  each queued steer is persisted to the session and emitted as a Steer
  event so the frontend can confirm delivery.
- Add Controller.Steer / SteerConsumed methods that delegate to the
  current executor.
- Add App.Steer / App.SteerForTab with per-tab routing, matching the
  SubmitForTab / CancelForTab pattern (reviewer feedback esengine#3263).
- Add Steer / SteerForTab to the frontend AppBindings, mock, useController
  steer callback (routed with activeTabId), and runningRef + steer
  dispatch in App.handleSend.
- Expand HistoryMessage with ToolCalls []HistoryToolCall (assistant) and
  ToolCallID / ToolName (tool result), and add historyMessagesToItems that
  pairs tool calls with results.
- Fix historyMessagesToItems and serve renderHistoryMessages to use
  position-aware tool-result pairing (collectToolResultsAfter) instead of
  a global resultByID map, so cross-turn tool-call ID collisions (e.g.
  synthesized call_0 from gateways that omit IDs) do not shadow later
  turns' results.  Mirrors SanitizeToolPairing's turn-scoped pairing.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

v2 Go rewrite (1.x) — main-v2 branch, active development

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants