From 17a985cb41727b8a1bca4d95f334106c09386040 Mon Sep 17 00:00:00 2001 From: t Date: Sun, 7 Jun 2026 14:57:58 -0600 Subject: 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. --- src/system_prompt.zig | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'src/system_prompt.zig') 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); } -- cgit v1.3