summaryrefslogtreecommitdiff
path: root/libpanto/src
diff options
context:
space:
mode:
authort <t@tjp.lol>2026-06-16 12:15:49 -0600
committert <t@tjp.lol>2026-06-16 12:16:03 -0600
commit493a15c310fe2566107a1b200cb654295502657a (patch)
tree02385378bb11460926b16b9e49e80727aa55492b /libpanto/src
parente9708f910b74fa0f5412d0157cb2d43c9425a480 (diff)
esc key to interrupt the agent
Diffstat (limited to 'libpanto/src')
-rw-r--r--libpanto/src/agent.zig20
1 files changed, 20 insertions, 0 deletions
diff --git a/libpanto/src/agent.zig b/libpanto/src/agent.zig
index 8a8a2e2..39c2f1a 100644
--- a/libpanto/src/agent.zig
+++ b/libpanto/src/agent.zig
@@ -1179,6 +1179,26 @@ pub const Stream = struct {
self._agent._allocator.destroy(self);
}
+ /// Abort this turn from the embedder side (for example, Escape in a TUI).
+ /// Provider/tool work that is currently inside `next()` cannot be unwound
+ /// until that call returns, but once control reaches the embedder this
+ /// drops every assistant/tool-result message produced by this stream before
+ /// `deinit()` has a chance to persist them. The already-persisted user
+ /// prompt (written by `Agent.run`) is intentionally kept, leaving a valid
+ /// conversation prefix with no dangling ToolUse blocks.
+ pub fn cancel(self: *Stream) void {
+ if (self._response) |ps| {
+ ps.deinit();
+ self._response = null;
+ }
+ const conv = &self._agent.conversation;
+ while (conv.messages.items.len > self._start) {
+ var msg = conv.messages.pop().?;
+ msg.deinit(conv.allocator);
+ }
+ self.state = .done;
+ }
+
fn persistTail(self: *Stream) void {
if (self._persisted) return;
self._persisted = true;