summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authort <t@tjp.lol>2026-06-07 14:57:58 -0600
committert <t@tjp.lol>2026-06-07 14:57:58 -0600
commit17a985cb41727b8a1bca4d95f334106c09386040 (patch)
tree237a7f1e0d45dafb61ace13f5112ecd31170df4c /src
parent1eddee33902757f7e06993825a3ad1011e7ec346 (diff)
Alias Conversation instead of facading it; merge addAssistantMessage
A facade that forwards every method 1:1 is worse than paring the real type down to the intended surface and aliasing it. conversation.Conversation's interface is already the public surface we want (init/deinit, the add*/replace* builders, and messages/allocator as plain data fields), so public.zig now aliases it straight through and Agent.conversation() returns a borrowed *Conversation for in-place surgery. Drops the ConversationData alias and the pointer-wrapper. Merged addAssistantMessageWithUsage into addAssistantMessage(blocks, ?usage) on the real type (separate method deleted), so the alias has the intended one-method shape; all call sites updated. Only Agent and Stream remain true facades -- they have genuinely-internal fields plus API-shaping renames (Stream.phase->state, Phase->State) an alias can't express.
Diffstat (limited to 'src')
-rw-r--r--src/main.zig2
-rw-r--r--src/system_prompt.zig18
2 files changed, 10 insertions, 10 deletions
diff --git a/src/main.zig b/src/main.zig
index 61a88bd..2887730 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -358,7 +358,7 @@ pub fn main(init: std.process.Init) !void {
// On resume, reconstruct the conversation from the store. (The
// dangling-prompt recovery feature was dropped in R2.) On a fresh
// session, the agent starts with an empty conversation.
- var adopted_conversation: ?panto.ConversationData = null;
+ var adopted_conversation: ?panto.Conversation = null;
if (is_resume) {
adopted_conversation = try session.load();
const sid = session.info.id;
diff --git a/src/system_prompt.zig b/src/system_prompt.zig
index 39c3ea8..eea0b97 100644
--- a/src/system_prompt.zig
+++ b/src/system_prompt.zig
@@ -193,7 +193,7 @@ pub fn reconcileResumeLayers(
const resolved = try resolveLayers(arena, io, base_dir, user_dir, project_dir);
const config_blocks = try resolved.blocks(arena);
- const window = try effectiveConfigWindow(arena, agent.conversation().messages());
+ const window = try effectiveConfigWindow(arena, agent.conversation().messages.items);
if (blocksEqual(config_blocks, window)) return;
@@ -339,7 +339,7 @@ test "blocksEqual - length and content" {
test "effectiveConfigWindow - no replace anchors to leading system blocks" {
const alloc = testing.allocator;
- var conv = panto.ConversationData.init(alloc);
+ var conv = panto.Conversation.init(alloc);
defer conv.deinit();
try conv.addSystemMessage("seed");
@@ -357,7 +357,7 @@ test "effectiveConfigWindow - no replace anchors to leading system blocks" {
test "effectiveConfigWindow - anchors to last replace block" {
const alloc = testing.allocator;
- var conv = panto.ConversationData.init(alloc);
+ var conv = panto.Conversation.init(alloc);
defer conv.deinit();
try conv.addSystemMessage("old seed");
@@ -483,7 +483,7 @@ const SPAgentHarness = struct {
fn init(
self: *SPAgentHarness,
session: panto.Session,
- adopted: ?panto.ConversationData,
+ adopted: ?panto.Conversation,
) !void {
self.config = .{
.provider = .{ .openai_chat = .{ .api_key = "k", .base_url = "u", .model = "m" } },
@@ -502,9 +502,9 @@ const SPAgentHarness = struct {
/// memory until the first assistant message; a realistic resume only
/// sees what a completed turn persisted.)
fn forceFlush(self: *SPAgentHarness) !void {
- var conv = panto.ConversationData.init(testing.allocator);
+ var conv = panto.Conversation.init(testing.allocator);
defer conv.deinit();
- try conv.addAssistantMessage(&.{});
+ try conv.addAssistantMessage(&.{}, null);
const id: panto.WireIdentity = .{ .api_style = .openai_chat, .base_url = "u", .model = "m" };
var batch = [_]panto.PersistentMessage{
.{ .message = conv.messages.items[0], .identity = id },
@@ -557,7 +557,7 @@ test "seedFresh then no-config-change resume is a no-op" {
try h2.init(sess2, conv2);
defer h2.deinit();
try reconcileResumeLayers(arena, testing.io, null, null, project_dir, h2.agent);
- const eff_after = try panto.effectiveSystemBlocks(arena, h2.agent.conversation().messages());
+ const eff_after = try panto.effectiveSystemBlocks(arena, h2.agent.conversation().messages.items);
try testing.expectEqual(seeded_count, eff_after.items.len);
}
@@ -600,7 +600,7 @@ test "resume after config change appends replace + append sequence" {
try reconcileResumeLayers(arena, testing.io, null, null, project_dir, h2.agent);
// The effective prompt now reflects only the new config blocks.
- const eff = try panto.effectiveSystemBlocks(arena, h2.agent.conversation().messages());
+ const eff = try panto.effectiveSystemBlocks(arena, h2.agent.conversation().messages.items);
try testing.expectEqual(@as(usize, 2), eff.items.len);
try testing.expectEqualStrings("new seed", eff.items[0]);
try testing.expectEqualStrings("new append", eff.items[1]);
@@ -608,7 +608,7 @@ test "resume after config change appends replace + append sequence" {
// A second no-op resume must not change the effective prompt (anchors
// to the new `replace` window, not the stale original seed).
try reconcileResumeLayers(arena, testing.io, null, null, project_dir, h2.agent);
- const eff2 = try panto.effectiveSystemBlocks(arena, h2.agent.conversation().messages());
+ const eff2 = try panto.effectiveSystemBlocks(arena, h2.agent.conversation().messages.items);
try testing.expectEqual(@as(usize, 2), eff2.items.len);
}