Break down exec.zig into focused modules: - exec/mod.zig - Main entry point and command dispatch (211 lines) - exec/remote.zig - Remote execution via WebSocket (87 lines) - exec/local.zig - Local execution with fork/exec (137 lines) - exec/dryrun.zig - Dry-run preview functionality (53 lines) Original exec.zig now acts as backward-compatible wrapper. Benefits: - Each module <150 lines (highly maintainable) - Clear separation: remote vs local vs dry-run logic - Easier to test individual execution paths - Original 533-line file split into 4 focused modules All tests pass.
116 lines
3.6 KiB
Zig
116 lines
3.6 KiB
Zig
const std = @import("std");
|
|
const config = @import("../../config.zig");
|
|
const ws = @import("../../net/ws/client.zig");
|
|
const crypto = @import("../../utils/crypto.zig");
|
|
const protocol = @import("../../net/protocol.zig");
|
|
const history = @import("../../utils/history.zig");
|
|
|
|
/// Execute job on remote server
|
|
pub fn execute(
|
|
allocator: std.mem.Allocator,
|
|
job_name: []const u8,
|
|
priority: u8,
|
|
options: anytype,
|
|
args_str: []const u8,
|
|
cfg: config.Config,
|
|
) !void {
|
|
// Use queue command logic for remote execution
|
|
std.log.info("Queueing job on remote server: {s}", .{job_name});
|
|
|
|
const ws_url = try cfg.getWebSocketUrl(allocator);
|
|
defer allocator.free(ws_url);
|
|
|
|
var client = try ws.Client.connect(allocator, ws_url, cfg.api_key);
|
|
defer client.close();
|
|
|
|
const api_key_hash = try crypto.hashApiKey(allocator, cfg.api_key);
|
|
defer allocator.free(api_key_hash);
|
|
|
|
// Generate commit ID
|
|
var commit_bytes: [20]u8 = undefined;
|
|
std.crypto.random.bytes(&commit_bytes);
|
|
|
|
// Build narrative JSON if provided
|
|
const narrative_json = buildNarrativeJson(allocator, options) catch null;
|
|
defer if (narrative_json) |j| allocator.free(j);
|
|
|
|
// Send queue request
|
|
try client.sendQueueJobWithArgsAndResources(
|
|
job_name,
|
|
&commit_bytes,
|
|
priority,
|
|
api_key_hash,
|
|
args_str,
|
|
false, // force
|
|
options.cpu,
|
|
options.memory,
|
|
options.gpu,
|
|
options.gpu_memory,
|
|
);
|
|
|
|
// Receive response
|
|
const message = try client.receiveMessage(allocator);
|
|
defer allocator.free(message);
|
|
|
|
const packet = protocol.ResponsePacket.deserialize(message, allocator) catch {
|
|
std.debug.print("Server response: {s}\n", .{message});
|
|
return;
|
|
};
|
|
defer packet.deinit(allocator);
|
|
|
|
switch (packet.packet_type) {
|
|
.success => {
|
|
const commit_hex = try crypto.encodeHexLower(allocator, &commit_bytes);
|
|
defer allocator.free(commit_hex);
|
|
history.record(allocator, job_name, commit_hex) catch {};
|
|
std.debug.print("Job queued: {s} (commit: {s})\n", .{ job_name, commit_hex[0..8] });
|
|
},
|
|
.error_packet => {
|
|
const err_msg = packet.error_message orelse "Unknown error";
|
|
std.debug.print("Error: {s}\n", .{err_msg});
|
|
return error.ServerError;
|
|
},
|
|
else => {
|
|
std.debug.print("Job queued: {s}\n", .{job_name});
|
|
},
|
|
}
|
|
}
|
|
|
|
fn buildNarrativeJson(allocator: std.mem.Allocator, options: anytype) !?[]const u8 {
|
|
if (options.hypothesis == null and options.context == null and
|
|
options.intent == null and options.expected_outcome == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
var buf = try std.ArrayList(u8).initCapacity(allocator, 256);
|
|
defer buf.deinit(allocator);
|
|
const writer = buf.writer(allocator);
|
|
|
|
try writer.writeAll("{");
|
|
var first = true;
|
|
|
|
if (options.hypothesis) |h| {
|
|
if (!first) try writer.writeAll(",");
|
|
try writer.print("\"hypothesis\":\"{s}\"", .{h});
|
|
first = false;
|
|
}
|
|
if (options.context) |c| {
|
|
if (!first) try writer.writeAll(",");
|
|
try writer.print("\"context\":\"{s}\"", .{c});
|
|
first = false;
|
|
}
|
|
if (options.intent) |i| {
|
|
if (!first) try writer.writeAll(",");
|
|
try writer.print("\"intent\":\"{s}\"", .{i});
|
|
first = false;
|
|
}
|
|
if (options.expected_outcome) |eo| {
|
|
if (!first) try writer.writeAll(",");
|
|
try writer.print("\"expected_outcome\":\"{s}\"", .{eo});
|
|
first = false;
|
|
}
|
|
|
|
try writer.writeAll("}");
|
|
return try buf.toOwnedSlice(allocator);
|
|
}
|