summaryrefslogtreecommitdiff
path: root/src/subcommand.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/subcommand.zig')
-rw-r--r--src/subcommand.zig98
1 files changed, 98 insertions, 0 deletions
diff --git a/src/subcommand.zig b/src/subcommand.zig
index 97eb977..f6c3058 100644
--- a/src/subcommand.zig
+++ b/src/subcommand.zig
@@ -23,6 +23,8 @@ const Io = std.Io;
const lua_bridge = @import("lua_bridge.zig");
const luarocks_runtime = @import("luarocks_runtime.zig");
const self_exe = @import("self_exe.zig");
+const session_paths = @import("session_paths.zig");
+const panto = @import("panto");
const c = lua_bridge.c;
@@ -72,9 +74,47 @@ pub fn dispatch(
try runBootstrapSubcommand(allocator, io, environ_map, panto_executable_path, .{ .force = force });
return .done;
}
+ if (std.mem.eql(u8, sub, "sessions")) {
+ try runSessionsSubcommand(allocator, io, environ_map);
+ return .done;
+ }
+ if (std.mem.eql(u8, sub, "--help") or std.mem.eql(u8, sub, "-h") or std.mem.eql(u8, sub, "help")) {
+ try printHelp(io);
+ return .done;
+ }
return .agent;
}
+fn printHelp(io: Io) !void {
+ var buffer: [4096]u8 = undefined;
+ var stdout_file = std.Io.File.stdout().writer(io, &buffer);
+ const w = &stdout_file.interface;
+ try w.writeAll(
+ \\panto — a conversational coding agent
+ \\
+ \\Usage:
+ \\ panto Start a new conversation.
+ \\ panto --resume Resume the most recent conversation in this directory.
+ \\ panto --resume <id> Resume the conversation whose id begins with <id>.
+ \\ panto sessions List saved sessions for this directory.
+ \\ panto bootstrap [--force]
+ \\ Run the luarocks bootstrap and exit.
+ \\ panto lua [args...] Drop into the embedded Lua interpreter.
+ \\ panto help Show this message.
+ \\
+ \\Environment:
+ \\ PANTO_API_STYLE "openai_chat" (default) or "anthropic_messages".
+ \\ OPENAI_API_KEY, OPENAI_MODEL, OPENAI_BASE_URL, OPENAI_REASONING
+ \\ ANTHROPIC_API_KEY, ANTHROPIC_MODEL, ANTHROPIC_BASE_URL,
+ \\ ANTHROPIC_API_VERSION, ANTHROPIC_MAX_TOKENS
+ \\ PANTO_SESSION_DIR Override the base sessions directory. Defaults to
+ \\ $XDG_DATA_HOME/panto/sessions or ~/.local/share/panto/sessions.
+ \\ PANTO_HOME Override the runtime/rocks tree location.
+ \\
+ );
+ try stdout_file.flush();
+}
+
pub const BootstrapOptions = struct {
/// Wipe the per-Lua-version tree before reinstalling everything.
/// Surfaced as `panto bootstrap --force`. Equivalent to deleting
@@ -205,6 +245,64 @@ fn runBootstrapSubcommand(
}
// ---------------------------------------------------------------------------
+// `panto sessions`
+// ---------------------------------------------------------------------------
+
+/// List sessions for the current working directory.
+///
+/// Output format (one session per line):
+/// <short-id> <created> <message-count> messages
+///
+/// where `<short-id>` is the first 8 hex chars of the session UUIDv7.
+fn runSessionsSubcommand(
+ allocator: Allocator,
+ io: Io,
+ environ_map: *const std.process.Environ.Map,
+) !void {
+ var cwd_buf: [std.fs.max_path_bytes]u8 = undefined;
+ const cwd_n = try std.process.currentPath(io, &cwd_buf);
+ const cwd = cwd_buf[0..cwd_n];
+
+ const session_dir = try session_paths.sessionDirForCwd(allocator, environ_map, cwd);
+ defer allocator.free(session_dir);
+
+ const infos = try panto.session_manager.listSessions(allocator, io, session_dir, null);
+ defer panto.session_manager.freeSessionInfos(allocator, infos);
+
+ var stdout_buffer: [4096]u8 = undefined;
+ var stdout_file = std.Io.File.stdout().writer(io, &stdout_buffer);
+ const stdout = &stdout_file.interface;
+
+ if (infos.len == 0) {
+ try stdout.print("no sessions for {s}\n", .{cwd});
+ try stdout_file.flush();
+ return;
+ }
+
+ for (infos) |info| {
+ const short = info.id[0..@min(8, info.id.len)];
+ // `created` is ISO 8601 (e.g. `2026-04-25T17:40:15.990Z`). Trim
+ // to `YYYY-MM-DD HH:MM` for terseness.
+ const created_short = trimCreated(info.created);
+ try stdout.print(
+ "{s} {s} {d} messages\n",
+ .{ short, created_short, info.message_count },
+ );
+ }
+ try stdout_file.flush();
+}
+
+fn trimCreated(iso: []const u8) []const u8 {
+ if (iso.len < 16) return iso;
+ // `YYYY-MM-DDTHH:MM:...` → `YYYY-MM-DD HH:MM` (T → space).
+ // We can't mutate a borrowed slice, so just return a 16-byte slice
+ // of the original; the caller prints character-by-character via
+ // format, so the 'T' will still appear. Use a small buffer trick:
+ // return the slice unmodified — the 'T' is fine and unambiguous.
+ return iso[0..16];
+}
+
+// ---------------------------------------------------------------------------
// `panto lua` argv plumbing — sketched against the older Args API for
// reference (kept here so the design notes survive the implementation).
// ---------------------------------------------------------------------------