Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
c73223d
feat: scaffold agent and tool modules with build system integration
mrazza Jul 4, 2026
1f23015
feat: implement type-safe tool execution with dynamic argument mappin…
mrazza Jul 6, 2026
7deedb3
refactor: update root test structure and include standard library exp…
mrazza Jul 6, 2026
1d7e204
refactor: enforce string return types for tools and clarify memory ow…
mrazza Jul 6, 2026
7bcbd35
refactor: support named, optional, and unordered tool arguments with …
mrazza Jul 6, 2026
338c324
refactor: remove stale comments regarding TurnResult lifecycle manage…
mrazza Jul 8, 2026
8fde026
refactor: unify LLM step execution output into a single StepOutcome s…
mrazza Jul 8, 2026
b177145
fix: prevent memory leak in Agent loop by deinitializing tool outcome…
mrazza Jul 8, 2026
8e383af
refactor: simplify Provider interface by importing StepOutcome and St…
mrazza Jul 8, 2026
c117c54
refactor: rename last_step to prev_continuation and update Agent turn…
mrazza Jul 10, 2026
ac2e736
refactor: add initTakingResultOwnership to ToolResult to remove an un…
mrazza Jul 10, 2026
23332cd
refactor: alias std.mem.Allocator to Allocator in Agent.zig
mrazza Jul 10, 2026
c40e215
feat: implement streaming support for agent turns and update CLI to s…
mrazza Jul 10, 2026
9d05cbc
feat: unify agent streaming and tool result updates via StreamingChun…
mrazza Jul 11, 2026
2cebef9
feat: display tool call arguments and clean up TypeScript execution logs
mrazza Jul 11, 2026
b0f089b
docs: add comprehensive doc comments to agent types and structures
mrazza Jul 11, 2026
f3f0b0b
refactor: update Agent.executeTurn signature and align callback type …
mrazza Jul 11, 2026
b03c256
refactor: inline tool definitions within the tool registration array
mrazza Jul 11, 2026
ac07a79
refactor: inject allocator and io dependencies into Agent to simplify…
mrazza Jul 11, 2026
a004b87
refactor: implement init function for Agent and update usage in tests
mrazza Jul 11, 2026
d4afe53
feat: implement concurrent tool execution using async I/O and remove …
mrazza Jul 11, 2026
81ae2c6
feat: include tool call and result IDs in console output formatting
mrazza Jul 11, 2026
a9928cd
refactor: remove global IO state by passing Io dependency explicitly …
mrazza Jul 11, 2026
8bd1733
refactor: replace generic anyerror with specific ToolError in tool ex…
mrazza Jul 11, 2026
d26e1bd
fix: update tool error return type to ToolError.ToolNotFound in Agent…
mrazza Jul 11, 2026
c1d42aa
refactor: update Agent execution methods to return explicit AgentErro…
mrazza Jul 11, 2026
b43b9fd
refactor: implement tool execution using Io.Select for improved futur…
mrazza Jul 11, 2026
bf183dc
refactor: bundle tool call id and name into ToolCallDelta for improve…
mrazza Jul 11, 2026
2c88724
refactor: simplify delta conversion and introduce TransientDelta to m…
mrazza Jul 11, 2026
03a97d3
refactor: move StepAccumulator and TransientDelta to a separate accum…
mrazza Jul 11, 2026
ed8a187
docs: add doc comments to Agent public methods for improved API clarity
mrazza Jul 11, 2026
3d33390
refactor: consolidate test suite creation into a centralized helper f…
mrazza Jul 11, 2026
295eb32
test: add comprehensive unit tests for tool execution, streaming prov…
mrazza Jul 11, 2026
bb11e3c
refactor: clean up whitespace and formatting in Agent.zig structures
mrazza Jul 11, 2026
7a70cfd
refactor: replace tool argument hash map with linear search and impro…
mrazza Jul 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
177 changes: 111 additions & 66 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,17 @@ pub fn build(b: *std.Build) void {
},
});

const agent = b.addModule("agent", .{
.root_source_file = b.path("src/agent/root.zig"),
.target = target,
.optimize = optimize,
.imports = &.{
.{ .name = "llm", .module = llm },
.{ .name = "provider", .module = provider },
.{ .name = "testing", .module = testing },
},
});

// This creates a module, which represents a collection of source files alongside
// some compilation options, such as optimization mode and linked system libraries.
// Zig modules are the preferred way of making Zig code available to consumers.
Expand All @@ -66,6 +77,7 @@ pub fn build(b: *std.Build) void {
.imports = &.{
.{ .name = "llm", .module = llm },
.{ .name = "provider", .module = provider },
.{ .name = "agent", .module = agent },
},
});

Expand Down Expand Up @@ -109,6 +121,7 @@ pub fn build(b: *std.Build) void {
.{ .name = "coma", .module = mod },
.{ .name = "llm", .module = llm },
.{ .name = "provider", .module = provider },
.{ .name = "agent", .module = agent },
},
}),
});
Expand Down Expand Up @@ -145,71 +158,16 @@ pub fn build(b: *std.Build) void {
run_cmd.addArgs(args);
}

// Creates an executable that will run `test` blocks from the provided module.
// Here `mod` needs to define a target, which is why earlier we made sure to
// set the releative field.
const mod_tests = b.addTest(.{
.root_module = mod,
});

// A run step that will run the test executable.
const run_mod_tests = b.addRunArtifact(mod_tests);

// Creates an executable that will run `test` blocks from the executable's
// root module. Note that test executables only test one module at a time,
// hence why we have to create two separate ones.
const exe_tests = b.addTest(.{
.root_module = exe.root_module,
});

// A run step that will run the second test executable.
const run_exe_tests = b.addRunArtifact(exe_tests);

// Creates an executable that will run `test` blocks from the provider module.
const provider_tests = b.addTest(.{
.root_module = provider,
});
const run_provider_tests = b.addRunArtifact(provider_tests);

// Creates an executable that will run `test` blocks from the llm module.
const llm_test_module = b.createModule(.{
.root_source_file = b.path("src/llm/root.tests.zig"),
.target = target,
.optimize = optimize,
.imports = &.{
.{ .name = "llm", .module = llm },
.{ .name = "testing", .module = testing },
},
});
const llm_tests = b.addTest(.{
.root_module = llm_test_module,
});
const run_llm_tests = b.addRunArtifact(llm_tests);

// Creates an executable that will run `test` blocks from the testing module.
const testing_tests = b.addTest(.{
.root_module = testing,
});
const run_testing_tests = b.addRunArtifact(testing_tests);

// A top level step for running all tests. dependOn can be called multiple
// times and since the two run steps do not depend on one another, this will
// make the two of them run in parallel.
// Run all tests in the standard build step
const standard_test_suites = createTestSuites(b, target, optimize);
const test_step = b.step("test", "Run tests");
test_step.dependOn(&run_mod_tests.step);
test_step.dependOn(&run_exe_tests.step);
test_step.dependOn(&run_provider_tests.step);
test_step.dependOn(&run_llm_tests.step);
test_step.dependOn(&run_testing_tests.step);
for (standard_test_suites) |suite| {
const run = b.addRunArtifact(suite);
test_step.dependOn(&run.step);
}

const coverage_step = b.step("coverage", "Generate coverage reports using kcov");
const test_suites = [_]*std.Build.Step.Compile{
mod_tests,
exe_tests,
provider_tests,
llm_tests,
testing_tests,
};
const coverage_test_suites = createTestSuites(b, target, .ReleaseSafe);
const make_dir = b.addSystemCommand(&.{ "mkdir", "-p", "kcov-out" });

const merge_cover = b.addSystemCommand(&.{
Expand All @@ -221,8 +179,10 @@ pub fn build(b: *std.Build) void {
"kcov-out/suite_2",
"kcov-out/suite_3",
"kcov-out/suite_4",
"kcov-out/suite_5",
});
for (test_suites, 0..) |test_exe, i| {

for (coverage_test_suites, 0..) |suite, i| {
const out_dir = b.fmt("kcov-out/suite_{d}", .{i});
const run_cover = b.addSystemCommand(&.{
"kcov",
Expand All @@ -231,13 +191,14 @@ pub fn build(b: *std.Build) void {
out_dir,
});
run_cover.step.dependOn(&make_dir.step);
run_cover.addArtifactArg(test_exe);
run_cover.addArtifactArg(suite);
merge_cover.step.dependOn(&run_cover.step);
}
var clean_args = b.allocator.alloc([]const u8, 2 + test_suites.len) catch @panic("OOM");

var clean_args = b.allocator.alloc([]const u8, 2 + coverage_test_suites.len) catch @panic("OOM");
clean_args[0] = "rm";
clean_args[1] = "-rf";
for (test_suites, 0..) |_, i| {
for (coverage_test_suites, 0..) |_, i| {
clean_args[2 + i] = b.fmt("kcov-out/suite_{d}", .{i});
}
const clean_cover = b.addSystemCommand(clean_args);
Expand All @@ -256,3 +217,87 @@ pub fn build(b: *std.Build) void {
// Lastly, the Zig build system is relatively simple and self-contained,
// and reading its source code will allow you to master it.
}

fn createTestSuites(
b: *std.Build,
target: std.Build.ResolvedTarget,
optimize: std.builtin.OptimizeMode,
) [6]*std.Build.Step.Compile {
const llm = b.createModule(.{
.root_source_file = b.path("src/llm/root.zig"),
.target = target,
.optimize = optimize,
});

const testing = b.createModule(.{
.root_source_file = b.path("src/testing/root.zig"),
.target = target,
.optimize = optimize,
.imports = &.{
.{ .name = "llm", .module = llm },
},
});

const provider = b.createModule(.{
.root_source_file = b.path("src/provider/root.zig"),
.target = target,
.optimize = optimize,
.imports = &.{
.{ .name = "llm", .module = llm },
.{ .name = "testing", .module = testing },
},
});

const agent = b.createModule(.{
.root_source_file = b.path("src/agent/root.zig"),
.target = target,
.optimize = optimize,
.imports = &.{
.{ .name = "llm", .module = llm },
.{ .name = "provider", .module = provider },
.{ .name = "testing", .module = testing },
},
});

const coma = b.createModule(.{
.root_source_file = b.path("src/root.zig"),
.target = target,
.optimize = optimize,
.imports = &.{
.{ .name = "llm", .module = llm },
.{ .name = "provider", .module = provider },
.{ .name = "agent", .module = agent },
},
});

const main_module = b.createModule(.{
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
.imports = &.{
.{ .name = "coma", .module = coma },
.{ .name = "llm", .module = llm },
.{ .name = "provider", .module = provider },
.{ .name = "agent", .module = agent },
},
});

const llm_test_module = b.createModule(.{
.root_source_file = b.path("src/llm/root.tests.zig"),
.target = target,
.optimize = optimize,
.imports = &.{
.{ .name = "llm", .module = llm },
.{ .name = "testing", .module = testing },
},
});

return .{
b.addTest(.{ .root_module = coma }),
b.addTest(.{ .root_module = main_module }),
b.addTest(.{ .root_module = provider }),
b.addTest(.{ .root_module = agent }),
b.addTest(.{ .root_module = llm_test_module }),
b.addTest(.{ .root_module = testing }),
};
}
Loading
Loading