You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maka.apache.org by zh...@apache.org on 2026/10/21 05:54:50 UTC

(maka) branch main updated: fix(ui): preserve steering position in resumed turns (#6191)

This is an automated email from the ASF dual-hosted git repository.

me2seeks pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/maka.git


The following commit(s) were added to refs/heads/main by this push:
     new 61041323a8 fix(ui): preserve steering position in resumed turns (#6191)
61041323a8 is described below

commit 61041323a886550ec305142698a1a05d915219d2
Author: Zhang <96...@users.noreply.github.com>
AuthorDate: Wed Oct 21 13:54:45 2026 +0800

    fix(ui): preserve steering position in resumed turns (#6191)
    
    Fixes #6190
    
    Keep persisted steering messages in the timeline when a resumed Turn has
    no root user prompt. Preserve the ordinary first user message as the
    opening prompt.
    
    Generated-by: Codex
---
 .../src/__tests__/chat-turn-steering-order.test.ts | 37 ++++++++++++++++++++++
 packages/ui/src/materialize.ts                     | 12 ++++---
 2 files changed, 45 insertions(+), 4 deletions(-)

diff --git a/packages/ui/src/__tests__/chat-turn-steering-order.test.ts b/packages/ui/src/__tests__/chat-turn-steering-order.test.ts
index dced134f47..d1038529b5 100644
--- a/packages/ui/src/__tests__/chat-turn-steering-order.test.ts
+++ b/packages/ui/src/__tests__/chat-turn-steering-order.test.ts
@@ -97,6 +97,43 @@ test('renders steering where it arrived in the assistant timeline', () => {
   }
 });
 
+test('keeps the first steering message in a resumed Turn at its timeline position', () => {
+  const messages: StoredMessage[] = [
+    { type: 'user', id: 'original-user', turnId: 'original-turn', ts: 1, text: 'original request' },
+    { type: 'assistant', id: 'before-steer', turnId: 'resumed-turn', ts: 10, modelId: 'mock', text: 'work before the steer' },
+    { type: 'user', id: 'first-steer', turnId: 'resumed-turn', ts: 11, text: 'remember to commit after each point', steeringEventId: 'steer-event' },
+    { type: 'assistant', id: 'after-steer', turnId: 'resumed-turn', ts: 12, modelId: 'mock', text: 'work after the steer' },
+  ];
+  const turn = materializeTurns(messages, 'en').find((candidate) => candidate.turnId === 'resumed-turn');
+  assert.ok(turn);
+  assert.equal(turn.user, undefined, 'a resumed Turn does not get a synthetic opening prompt');
+  assert.deepEqual(
+    turn.timeline.map((item) => item.kind === 'user' ? `user:${item.message.text}` : `${item.kind}:${'text' in item ? item.text : ''}`),
+    [
+      'text:work before the steer',
+      'user:remember to commit after each point',
+      'text:work after the steer',
+    ],
+  );
+
+  const markup = renderToStaticMarkup(
+    createElement(LocaleProvider, {
+      locale: 'en',
+      children: createElement(TurnView, { turn }),
+    }),
+  );
+  const visibleText = parseHTML(`<html><body>${markup}</body></html>`).document.body.textContent ?? '';
+  const positions = [
+    'work before the steer',
+    'remember to commit after each point',
+    'work after the steer',
+  ].map((text) => visibleText.indexOf(text));
+  assert.ok(
+    positions[0]! < positions[1]! && positions[1]! < positions[2]!,
+    `expected before < steer < after; positions=${positions.join(',')}; visible=${visibleText}`,
+  );
+});
+
 test('holds queued steering in the transcript while old output continues, then renders its real reply boundary', async () => {
   const messages: StoredMessage[] = [{ type: 'user', id: 'original', turnId: 'turn-1', ts: 1, text: 'request' }];
   const pending = { id: 'steer', ts: 2, text: 'inserted instruction', transientPlacement: 'transcript' as const };
diff --git a/packages/ui/src/materialize.ts b/packages/ui/src/materialize.ts
index 66388fe10c..d424bb8302 100644
--- a/packages/ui/src/materialize.ts
+++ b/packages/ui/src/materialize.ts
@@ -760,7 +760,10 @@ export function materializeTurns(
     else messagesByTurn.set(turnId, [message]);
     if (message.type === "user") {
       const user = chatItemFromUserMessage(message);
-      if (!turn.user) {
+      // A resumed Turn starts without a new root prompt. Its first user row can
+      // therefore be a steering message, which belongs at its event position
+      // in the timeline instead of being promoted to the Turn's opening prompt.
+      if (!turn.user && message.steeringEventId === undefined) {
         turn.user = user;
       }
     } else if (message.type === "assistant") {
@@ -1022,16 +1025,17 @@ function buildTurnTimeline(
 ): TurnTimelineItem[] {
   const raw: TurnTimelineItem[] = [];
   let pending: ToolActivityItem[] = [];
-  let sawUser = false;
+  let sawRootUser = false;
   const flushTools = (items: ToolActivityItem[]): void => {
     if (items.length > 0) raw.push({ kind: "tools", items });
   };
   for (const message of turnMessages) {
     if (message.type === "user") {
-      if (!sawUser) {
-        sawUser = true;
+      if (message.steeringEventId === undefined && !sawRootUser) {
+        sawRootUser = true;
         continue;
       }
+      if (message.steeringEventId === undefined) sawRootUser = true;
       flushTools(pending);
       pending = [];
       raw.push({


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@maka.apache.org
For additional commands, e-mail: commits-help@maka.apache.org