mirror of
https://github.com/openai/codex.git
synced 2026-05-01 03:42:05 +03:00
Re-add markdown streaming (#2029)
Wait for newlines, then render markdown on a line by line basis. Word wrap it for the current terminal size and then spit it out line by line into the UI. Also adds tests and fixes some UI regressions.
This commit is contained in:
89
codex-rs/tui/src/chatwidget/interrupts.rs
Normal file
89
codex-rs/tui/src/chatwidget/interrupts.rs
Normal file
@@ -0,0 +1,89 @@
|
||||
use std::collections::VecDeque;
|
||||
|
||||
use codex_core::protocol::ApplyPatchApprovalRequestEvent;
|
||||
use codex_core::protocol::ExecApprovalRequestEvent;
|
||||
use codex_core::protocol::ExecCommandBeginEvent;
|
||||
use codex_core::protocol::ExecCommandEndEvent;
|
||||
use codex_core::protocol::McpToolCallBeginEvent;
|
||||
use codex_core::protocol::McpToolCallEndEvent;
|
||||
use codex_core::protocol::PatchApplyEndEvent;
|
||||
|
||||
use super::ChatWidget;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) enum QueuedInterrupt {
|
||||
ExecApproval(String, ExecApprovalRequestEvent),
|
||||
ApplyPatchApproval(String, ApplyPatchApprovalRequestEvent),
|
||||
ExecBegin(ExecCommandBeginEvent),
|
||||
ExecEnd(ExecCommandEndEvent),
|
||||
McpBegin(McpToolCallBeginEvent),
|
||||
McpEnd(McpToolCallEndEvent),
|
||||
PatchEnd(PatchApplyEndEvent),
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub(crate) struct InterruptManager {
|
||||
queue: VecDeque<QueuedInterrupt>,
|
||||
}
|
||||
|
||||
impl InterruptManager {
|
||||
pub(crate) fn new() -> Self {
|
||||
Self {
|
||||
queue: VecDeque::new(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn is_empty(&self) -> bool {
|
||||
self.queue.is_empty()
|
||||
}
|
||||
|
||||
pub(crate) fn push_exec_approval(&mut self, id: String, ev: ExecApprovalRequestEvent) {
|
||||
self.queue.push_back(QueuedInterrupt::ExecApproval(id, ev));
|
||||
}
|
||||
|
||||
pub(crate) fn push_apply_patch_approval(
|
||||
&mut self,
|
||||
id: String,
|
||||
ev: ApplyPatchApprovalRequestEvent,
|
||||
) {
|
||||
self.queue
|
||||
.push_back(QueuedInterrupt::ApplyPatchApproval(id, ev));
|
||||
}
|
||||
|
||||
pub(crate) fn push_exec_begin(&mut self, ev: ExecCommandBeginEvent) {
|
||||
self.queue.push_back(QueuedInterrupt::ExecBegin(ev));
|
||||
}
|
||||
|
||||
pub(crate) fn push_exec_end(&mut self, ev: ExecCommandEndEvent) {
|
||||
self.queue.push_back(QueuedInterrupt::ExecEnd(ev));
|
||||
}
|
||||
|
||||
pub(crate) fn push_mcp_begin(&mut self, ev: McpToolCallBeginEvent) {
|
||||
self.queue.push_back(QueuedInterrupt::McpBegin(ev));
|
||||
}
|
||||
|
||||
pub(crate) fn push_mcp_end(&mut self, ev: McpToolCallEndEvent) {
|
||||
self.queue.push_back(QueuedInterrupt::McpEnd(ev));
|
||||
}
|
||||
|
||||
pub(crate) fn push_patch_end(&mut self, ev: PatchApplyEndEvent) {
|
||||
self.queue.push_back(QueuedInterrupt::PatchEnd(ev));
|
||||
}
|
||||
|
||||
pub(crate) fn flush_all(&mut self, chat: &mut ChatWidget<'_>) {
|
||||
while let Some(q) = self.queue.pop_front() {
|
||||
match q {
|
||||
QueuedInterrupt::ExecApproval(id, ev) => chat.handle_exec_approval_now(id, ev),
|
||||
QueuedInterrupt::ApplyPatchApproval(id, ev) => {
|
||||
chat.handle_apply_patch_approval_now(id, ev)
|
||||
}
|
||||
QueuedInterrupt::ExecBegin(ev) => chat.handle_exec_begin_now(ev),
|
||||
QueuedInterrupt::ExecEnd(ev) => chat.handle_exec_end_now(ev),
|
||||
QueuedInterrupt::McpBegin(ev) => chat.handle_mcp_begin_now(ev),
|
||||
QueuedInterrupt::McpEnd(ev) => chat.handle_mcp_end_now(ev),
|
||||
QueuedInterrupt::PatchEnd(ev) => chat.handle_patch_apply_end_now(ev),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user