Add compact agent context command
This commit is contained in:
+76
-17
@@ -1,4 +1,5 @@
|
||||
const std = @import("std");
|
||||
const context_mod = @import("context.zig");
|
||||
const input = @import("input.zig");
|
||||
const job = @import("job.zig");
|
||||
const layout = @import("layout.zig");
|
||||
@@ -23,10 +24,12 @@ const help_text =
|
||||
\\Usage:
|
||||
\\ mim [--help]
|
||||
\\ mim [--version]
|
||||
\\ mim context [task] [intent]
|
||||
\\ mim mimctl context <socket|-> [task] [intent]
|
||||
\\ mim --mimctl <socket|-> <request...>
|
||||
\\
|
||||
\\This early build exposes the canonical smoke path and a minimal local
|
||||
\\session-control client for trusted tools.
|
||||
\\This early build exposes the canonical smoke path, compact local context,
|
||||
\\and a minimal local session-control client for trusted tools.
|
||||
\\
|
||||
;
|
||||
|
||||
@@ -63,6 +66,29 @@ pub fn main(init: std.process.Init) !u8 {
|
||||
|
||||
const first_arg = args.next();
|
||||
if (first_arg) |arg| {
|
||||
if (std.mem.eql(u8, arg, "context")) {
|
||||
try printLocalContext(allocator, init.io, &args, stdout);
|
||||
return 0;
|
||||
}
|
||||
if (std.mem.eql(u8, arg, "mimctl")) {
|
||||
const sub = args.next() orelse {
|
||||
try stderr.writeStreamingAll(init.io, "mim: mimctl requires a subcommand\n");
|
||||
return 64;
|
||||
};
|
||||
if (!std.mem.eql(u8, sub, "context")) {
|
||||
try stderr.writeStreamingAll(init.io, "mim: unknown mimctl subcommand\n");
|
||||
return 64;
|
||||
}
|
||||
const socket_path = args.next() orelse {
|
||||
try stderr.writeStreamingAll(init.io, "mim: mimctl context requires a socket path or '-'\n");
|
||||
return 64;
|
||||
};
|
||||
const line = try collectContextRequest(allocator, &args);
|
||||
defer allocator.free(line);
|
||||
requestMimctl(allocator, init.io, init.minimal.environ, stdout, stderr, socket_path, line) catch return 69;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (std.mem.eql(u8, arg, "--mimctl")) {
|
||||
const socket_path = args.next() orelse {
|
||||
try stderr.writeStreamingAll(init.io, "mim: --mimctl requires a socket path\n");
|
||||
@@ -74,21 +100,7 @@ pub fn main(init: std.process.Init) !u8 {
|
||||
try stderr.writeStreamingAll(init.io, "mim: --mimctl requires a request\n");
|
||||
return 64;
|
||||
}
|
||||
const resolved_socket_path = if (std.mem.eql(u8, socket_path, "-"))
|
||||
std.process.Environ.getAlloc(init.minimal.environ, allocator, socket.socket_env_name) catch {
|
||||
try stderr.writeStreamingAll(init.io, "mim: MIM_SOCKET is not set\n");
|
||||
return 69;
|
||||
}
|
||||
else
|
||||
try allocator.dupe(u8, socket_path);
|
||||
defer allocator.free(resolved_socket_path);
|
||||
|
||||
const response = socket.request(allocator, resolved_socket_path, line) catch {
|
||||
try stderr.writeStreamingAll(init.io, "mim: mimctl request failed\n");
|
||||
return 69;
|
||||
};
|
||||
defer allocator.free(response);
|
||||
try stdout.writeStreamingAll(init.io, response);
|
||||
requestMimctl(allocator, init.io, init.minimal.environ, stdout, stderr, socket_path, line) catch return 69;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -113,6 +125,51 @@ pub fn main(init: std.process.Init) !u8 {
|
||||
return 0;
|
||||
}
|
||||
|
||||
fn printLocalContext(allocator: std.mem.Allocator, io: std.Io, args: *std.process.Args.Iterator, stdout: std.Io.File) !void {
|
||||
const task = args.next();
|
||||
const intent = args.next();
|
||||
const text = try context_mod.localContextAlloc(allocator, ".", task, intent, .{});
|
||||
defer allocator.free(text);
|
||||
try stdout.writeStreamingAll(io, text);
|
||||
}
|
||||
|
||||
fn requestMimctl(
|
||||
allocator: std.mem.Allocator,
|
||||
io: std.Io,
|
||||
environ: std.process.Environ,
|
||||
stdout: std.Io.File,
|
||||
stderr: std.Io.File,
|
||||
socket_path: []const u8,
|
||||
line: []const u8,
|
||||
) !void {
|
||||
const resolved_socket_path = if (std.mem.eql(u8, socket_path, "-"))
|
||||
std.process.Environ.getAlloc(environ, allocator, socket.socket_env_name) catch {
|
||||
try stderr.writeStreamingAll(io, "mim: MIM_SOCKET is not set\n");
|
||||
return error.MimctlFailed;
|
||||
}
|
||||
else
|
||||
try allocator.dupe(u8, socket_path);
|
||||
defer allocator.free(resolved_socket_path);
|
||||
|
||||
const response = socket.request(allocator, resolved_socket_path, line) catch {
|
||||
try stderr.writeStreamingAll(io, "mim: mimctl request failed\n");
|
||||
return error.MimctlFailed;
|
||||
};
|
||||
defer allocator.free(response);
|
||||
try stdout.writeStreamingAll(io, response);
|
||||
}
|
||||
|
||||
fn collectContextRequest(allocator: std.mem.Allocator, args: *std.process.Args.Iterator) ![]u8 {
|
||||
var line = std.ArrayList(u8).empty;
|
||||
errdefer line.deinit(allocator);
|
||||
try line.appendSlice(allocator, "context");
|
||||
while (args.next()) |arg| {
|
||||
try line.append(allocator, ' ');
|
||||
try line.appendSlice(allocator, arg);
|
||||
}
|
||||
return line.toOwnedSlice(allocator);
|
||||
}
|
||||
|
||||
fn collectRemainingArgs(allocator: std.mem.Allocator, args: *std.process.Args.Iterator) ![]u8 {
|
||||
var line = std.ArrayList(u8).empty;
|
||||
errdefer line.deinit(allocator);
|
||||
@@ -126,6 +183,7 @@ fn collectRemainingArgs(allocator: std.mem.Allocator, args: *std.process.Args.It
|
||||
}
|
||||
|
||||
test {
|
||||
_ = context_mod;
|
||||
_ = input;
|
||||
_ = job;
|
||||
_ = layout;
|
||||
@@ -146,6 +204,7 @@ test {
|
||||
test "regular: help text names the binary and smoke boundary" {
|
||||
try std.testing.expect(std.mem.indexOf(u8, help_text, "mim - mobile-first terminal code editor") != null);
|
||||
try std.testing.expect(std.mem.indexOf(u8, help_text, "canonical smoke path") != null);
|
||||
try std.testing.expect(std.mem.indexOf(u8, help_text, "mim context") != null);
|
||||
}
|
||||
|
||||
test "regular: version output is stable enough for smoke checks" {
|
||||
|
||||
Reference in New Issue
Block a user