diff options
Diffstat (limited to 'src/subcommand.zig')
| -rw-r--r-- | src/subcommand.zig | 98 |
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). // --------------------------------------------------------------------------- |
