diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/command.zig | 4 | ||||
| -rw-r--r-- | src/extension_loader.zig | 4 | ||||
| -rw-r--r-- | src/lua_bridge.zig | 33 | ||||
| -rw-r--r-- | src/lua_runtime.zig | 16 | ||||
| -rw-r--r-- | src/main.zig | 2 | ||||
| -rw-r--r-- | src/system_prompt.zig | 18 |
6 files changed, 39 insertions, 38 deletions
diff --git a/src/command.zig b/src/command.zig index 0f6fb01..588490c 100644 --- a/src/command.zig +++ b/src/command.zig @@ -33,9 +33,9 @@ pub const Context = struct { allocator: std.mem.Allocator, /// The active agent (a copyable public handle). Commands reach the - /// conversation via `agent.conversation()` and compact via + /// conversation via `agent.conversation` and compact via /// `agent.compact(...)`. - agent: panto.Agent, + agent: *panto.Agent, /// REPL output writer and its backing file writer (for flushing). stdout: *std.Io.Writer, diff --git a/src/extension_loader.zig b/src/extension_loader.zig index ff49022..6d74559 100644 --- a/src/extension_loader.zig +++ b/src/extension_loader.zig @@ -495,7 +495,7 @@ const testing = std.testing; fn xokText(result: panto.ToolCallResult) []const u8 { switch (result) { .ok => |parts| { - for (parts) |p| { + for (parts.items) |p| { if (p == .text) return p.text; } return ""; @@ -507,7 +507,7 @@ fn xokText(result: panto.ToolCallResult) []const u8 { /// Test helper: free a results slice (parts on `.ok`). fn xfreeResults(results: []panto.ToolCallResult) void { for (results) |r| switch (r) { - .ok => |b| (panto.ResultParts{ .items = b }).deinit(testing.allocator), + .ok => |b| b.deinit(testing.allocator), .err => {}, }; } diff --git a/src/lua_bridge.zig b/src/lua_bridge.zig index 444cedc..9276e1d 100644 --- a/src/lua_bridge.zig +++ b/src/lua_bridge.zig @@ -262,7 +262,7 @@ pub fn pushJsonAsLua( } /// Read a tool handler's return value at `idx` and convert it into an -/// owned `[]panto.ResultPart`. Two accepted shapes: +/// owned `panto.ResultParts`. Two accepted shapes: /// /// * a plain string -> one `.text` part; /// * a table `{ text = "...", attachments = { { media_type = "...", @@ -275,14 +275,14 @@ pub fn readHandlerResult( L: *c.lua_State, idx: c_int, allocator: Allocator, -) BridgeError![]panto.ResultPart { +) BridgeError!panto.ResultParts { const ty = c.lua_type(L, idx); if (ty == T_STRING) { var len: usize = 0; const ptr = c.lua_tolstring(L, idx, &len); if (ptr == null) return BridgeError.BadHandlerReturn; - return ((panto.ResultParts.fromText(allocator, ptr[0..len]) catch - return BridgeError.OutOfMemory).items); + return panto.ResultParts.fromText(allocator, ptr[0..len]) catch + return BridgeError.OutOfMemory; } if (ty != T_TABLE) return BridgeError.BadHandlerReturn; return readHandlerResultTable(L, idx, allocator); @@ -315,7 +315,7 @@ fn readHandlerResultTable( L: *c.lua_State, idx: c_int, allocator: Allocator, -) BridgeError![]panto.ResultPart { +) BridgeError!panto.ResultParts { var parts: std.ArrayList(panto.ResultPart) = .empty; errdefer { for (parts.items) |p| p.deinit(allocator); @@ -372,7 +372,8 @@ fn readHandlerResultTable( } } - return parts.toOwnedSlice(allocator) catch BridgeError.OutOfMemory; + const items = parts.toOwnedSlice(allocator) catch return BridgeError.OutOfMemory; + return .{ .items = items }; } // --------------------------------------------------------------------------- @@ -796,9 +797,9 @@ test "handler invocation: input parsed, result captured" { } const result = try readHandlerResult(L, -1, std.testing.allocator); - defer (panto.ResultParts{ .items = result }).deinit(std.testing.allocator); - try std.testing.expectEqual(@as(usize, 1), result.len); - try std.testing.expectEqualStrings("got: hello", result[0].text); + defer result.deinit(std.testing.allocator); + try std.testing.expectEqual(@as(usize, 1), result.items.len); + try std.testing.expectEqualStrings("got: hello", result.items[0].text); } test "readHandlerResult: table with text and attachments" { @@ -821,13 +822,13 @@ test "readHandlerResult: table with text and attachments" { } const result = try readHandlerResult(L, -1, std.testing.allocator); - defer (panto.ResultParts{ .items = result }).deinit(std.testing.allocator); - try std.testing.expectEqual(@as(usize, 3), result.len); - try std.testing.expectEqualStrings("see image", result[0].text); - try std.testing.expectEqualStrings("image/png", result[1].media.media_type.?); - try std.testing.expectEqualStrings("AAA=", result[1].media.data); - try std.testing.expectEqualStrings("application/pdf", result[2].media.media_type.?); - try std.testing.expectEqualStrings("BBB=", result[2].media.data); + defer result.deinit(std.testing.allocator); + try std.testing.expectEqual(@as(usize, 3), result.items.len); + try std.testing.expectEqualStrings("see image", result.items[0].text); + try std.testing.expectEqualStrings("image/png", result.items[1].media.media_type.?); + try std.testing.expectEqualStrings("AAA=", result.items[1].media.data); + try std.testing.expectEqualStrings("application/pdf", result.items[2].media.media_type.?); + try std.testing.expectEqualStrings("BBB=", result.items[2].media.data); } test "handler crash: error message surfaces via xpcall traceback hook" { diff --git a/src/lua_runtime.zig b/src/lua_runtime.zig index c15ee63..eb760f8 100644 --- a/src/lua_runtime.zig +++ b/src/lua_runtime.zig @@ -550,7 +550,7 @@ const Slot = struct { ok: bool = false, /// Result payload as owned parts. Allocated from `allocator`. /// Caller frees via `panto.ResultParts.deinit`. - value: ?[]panto.ResultPart = null, + value: ?panto.ResultParts = null, /// On `ok = false`, an owned copy of the error message. err_msg: ?[]u8 = null, }; @@ -703,11 +703,11 @@ fn runBatch( continue; } if (slot.ok) { - results[i] = .{ .ok = slot.value orelse (try panto.ResultParts.fromText(allocator, "")).items }; + results[i] = .{ .ok = slot.value orelse try panto.ResultParts.fromText(allocator, "") }; // Free the err_msg if both ended up set somehow. if (slot.err_msg) |m| allocator.free(m); } else { - if (slot.value) |v| (panto.ResultParts{ .items = v }).deinit(allocator); + if (slot.value) |v| v.deinit(allocator); std.log.warn( "panto-lua: tool '{s}' failed: {s}", .{ @@ -734,13 +734,13 @@ fn formatToolError( allocator: Allocator, tool_name: []const u8, message: []const u8, -) ![]panto.ResultPart { +) !panto.ResultParts { const text = try std.fmt.allocPrint( allocator, "panto-lua: tool '{s}' failed: {s}", .{ tool_name, message }, ); - return (try panto.ResultParts.fromTextOwned(allocator, text)).items; + return panto.ResultParts.fromTextOwned(allocator, text); } /// Start one coroutine: create a thread under the runtime's lua_State, @@ -848,7 +848,7 @@ fn invokeCoroutineSync( input: []const u8, allocator: Allocator, err_msg_out: *?[]u8, -) ![]panto.ResultPart { +) !panto.ResultParts { const co = c.lua_newthread(L) orelse return RuntimeError.LuaInitFailed; defer c.lua_settop(L, c.lua_gettop(L) - 1); @@ -1065,7 +1065,7 @@ const testing = std.testing; fn okText(result: panto.ToolCallResult) []const u8 { switch (result) { .ok => |parts| { - for (parts) |p| { + for (parts.items) |p| { if (p == .text) return p.text; } return ""; @@ -1077,7 +1077,7 @@ fn okText(result: panto.ToolCallResult) []const u8 { /// Test helper: free a results slice (parts on `.ok`). fn freeResults(results: []panto.ToolCallResult) void { for (results) |r| switch (r) { - .ok => |b| (panto.ResultParts{ .items = b }).deinit(testing.allocator), + .ok => |b| b.deinit(testing.allocator), .err => {}, }; } diff --git a/src/main.zig b/src/main.zig index a4d524b..2a1de27 100644 --- a/src/main.zig +++ b/src/main.zig @@ -144,7 +144,7 @@ const CLIRenderer = struct { /// it terminates (`turn_complete` → `next()` returns null). A failure /// surfaces as the error from `next()`; the caller renders it. The stream is /// always `deinit`ed (persisting the turn tail) on every exit path. -fn driveTurn(agent: panto.Agent, message: panto.UserMessage, renderer: *CLIRenderer) !void { +fn driveTurn(agent: *panto.Agent, message: panto.UserMessage, renderer: *CLIRenderer) !void { var stream = try agent.run(message); defer stream.deinit(); while (try stream.next()) |ev| try renderer.render(ev); diff --git a/src/system_prompt.zig b/src/system_prompt.zig index eea0b97..6676442 100644 --- a/src/system_prompt.zig +++ b/src/system_prompt.zig @@ -137,7 +137,7 @@ pub fn seedFresh( io: Io, environ_map: *const std.process.Environ.Map, base_dir: []const u8, - agent: panto.Agent, + agent: *panto.Agent, ) !void { const user_dir = try userLayerDir(arena, environ_map); const project_dir = try projectLayerDir(arena, io); @@ -151,7 +151,7 @@ pub fn seedFreshLayers( base_dir: ?[]const u8, user_dir: ?[]const u8, project_dir: ?[]const u8, - agent: panto.Agent, + agent: *panto.Agent, ) !void { const resolved = try resolveLayers(arena, io, base_dir, user_dir, project_dir); const blocks = try resolved.blocks(arena); @@ -174,7 +174,7 @@ pub fn reconcileResume( io: Io, environ_map: *const std.process.Environ.Map, base_dir: []const u8, - agent: panto.Agent, + agent: *panto.Agent, ) !void { const user_dir = try userLayerDir(arena, environ_map); const project_dir = try projectLayerDir(arena, io); @@ -188,12 +188,12 @@ pub fn reconcileResumeLayers( base_dir: ?[]const u8, user_dir: ?[]const u8, project_dir: ?[]const u8, - agent: panto.Agent, + agent: *panto.Agent, ) !void { 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.items); + const window = try effectiveConfigWindow(arena, agent.conversation.messages.items); if (blocksEqual(config_blocks, window)) return; @@ -473,7 +473,7 @@ fn openTmpStore(arena: Allocator, root: []const u8) !panto.FileSystemJSONLStore /// harness only holds the config to keep the agent's borrowed pointer valid. const SPAgentHarness = struct { config: panto.Config, - agent: panto.Agent, + agent: *panto.Agent, /// A second handle onto the same session (a copyable value proxying to /// the same store + id) so the test can `forceFlush` without reaching /// agent internals. `session_id` mirrors the agent's session 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.items); + 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.items); + 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.items); + const eff2 = try panto.effectiveSystemBlocks(arena, h2.agent.conversation.messages.items); try testing.expectEqual(@as(usize, 2), eff2.items.len); } |
