Skip to content

Commit 0393c99

Browse files
authored
Merge branch 'main' into feat/nori-client-mcp-cleanup
2 parents 8752274 + cb3f150 commit 0393c99

5 files changed

Lines changed: 45 additions & 5 deletions

File tree

nori-rs/tui-pty-e2e/tests/snapshots/acp_tool_calls__acp_tool_call_no_duplicates.snap

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ expression: normalize_for_input_snapshot(contents)
1212

1313
Processing command...
1414

15-
────────────────────────────────────────────────────────────────────────────────
16-
1715
Interleaved test done.
1816

1917
› [DEFAULT_PROMPT]

nori-rs/tui/docs.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ Tool cells always appear in scrollback history before the agent text that follow
150150
- `handle_streaming_delta()` always calls `flush_active_cell()` before streaming text, even when the active cell contains an incomplete (still-running) ExecCell. The incomplete cell is sent to history immediately rather than held in `active_cell` until completion.
151151
- `flush_active_cell()` marks pending call_ids of incomplete ExecCells as completed (via `completed_client_tool_calls`) so that later completion events for the same call_ids do not create duplicate cells. The `pending_exec_cells` tracker is bypassed for this path -- cells go directly to history.
152152
- `add_boxed_history()` also always flushes the active cell first, applying the same ordering guarantee when non-streaming history cells are inserted.
153+
- Assistant message cells do not re-arm the final-message separator; a single tool-to-answer boundary should not become repeated dividers when one assistant turn arrives as multiple message cells.
153154

154155
The trade-off: incomplete cells may appear in scrollback showing "Running"/"Exploring" status rather than their final "Ran"/"Explored" state, because they are flushed before completion events arrive.
155156

nori-rs/tui/src/chatwidget/tests/part5.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use super::*;
2+
use pretty_assertions::assert_eq;
23

34
/// ACP agents may stream reasoning before producing their final answer.
45
/// This test verifies reasoning + answer rendering from an ACP agent.
@@ -895,3 +896,43 @@ fn exec_end_not_deferred_during_streaming() {
895896
done_pos.unwrap(),
896897
);
897898
}
899+
900+
#[test]
901+
fn repeated_agent_messages_after_tool_use_share_one_separator() {
902+
let (mut chat, mut rx, _op_rx) = make_chatwidget_manual();
903+
904+
chat.handle_codex_event(Event {
905+
id: "turn-1".into(),
906+
msg: EventMsg::TaskStarted(TaskStartedEvent {
907+
model_context_window: None,
908+
}),
909+
});
910+
drain_insert_history(&mut rx);
911+
912+
let begin_ev = begin_exec(&mut chat, "call-1", "cargo test");
913+
end_exec(&mut chat, begin_ev, "ok\n", "", 0);
914+
915+
for message in ["The", "suite is", "now in the ACP backend"] {
916+
chat.handle_codex_event(Event {
917+
id: "turn-1".into(),
918+
msg: EventMsg::AgentMessage(AgentMessageEvent {
919+
message: message.to_string(),
920+
}),
921+
});
922+
}
923+
924+
chat.handle_codex_event(Event {
925+
id: "turn-1".into(),
926+
msg: EventMsg::TaskComplete(TaskCompleteEvent {
927+
last_agent_message: None,
928+
}),
929+
});
930+
931+
let rendered = drain_insert_history(&mut rx)
932+
.into_iter()
933+
.map(|lines| lines_to_single_string(&lines))
934+
.collect::<Vec<_>>()
935+
.join("");
936+
937+
assert_eq!(rendered.matches("Worked for").count(), 1, "{rendered}");
938+
}

nori-rs/tui/src/chatwidget/tests/snapshots/nori_tui__chatwidget__tests__part5__acp_multi_turn_conversation.snap

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ expression: combined
44
---
55
I can help you refactor that function. First, let me analyze the current
66
implementation.
7-
─ Worked for 0s ────────────────────────────────────────────────────────────────
8-
97
• Here's the refactored version:
108

119
fn process(data: &str) -> Result<String, Error> {

nori-rs/tui/src/chatwidget/user_input.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ impl ChatWidget {
3939
// Always flush active cell before inserting new history to preserve
4040
// chronological ordering.
4141
self.flush_active_cell();
42-
self.needs_final_message_separator = true;
42+
if !cell.as_any().is::<history_cell::AgentMessageCell>() {
43+
self.needs_final_message_separator = true;
44+
}
4345
}
4446
self.app_event_tx.send(AppEvent::InsertHistoryCell(cell));
4547
}

0 commit comments

Comments
 (0)