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