Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
65 changes: 0 additions & 65 deletions bin/recs-tui.ts

This file was deleted.

93 changes: 80 additions & 13 deletions bin/recs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,19 +99,79 @@ if (command === "story") {
process.exit(0);
}

// Handle TUI subcommand
if (command === "tui") {
const tuiArgs = args.slice(1);
// Re-exec via recs-tui.ts with remaining args
const { join } = await import("node:path");
const tuiEntry = join(import.meta.dir, "recs-tui.ts");
const proc = Bun.spawn(["bun", "run", tuiEntry, ...tuiArgs], {
stdin: "inherit",
stdout: "inherit",
stderr: "inherit",
});
const code = await proc.exited;
process.exit(code);
// Handle Explorer subcommand
if (command === "explorer") {
const explorerArgs = args.slice(1);
// Dynamically import the explorer entry point so it works in compiled binaries
const explorerModule = await import("../src/explorer/index.tsx");
const launchExplorer = explorerModule.launchExplorer;
type ExplorerOptions = import("../src/explorer/index.tsx").ExplorerOptions;
const { SessionManager } = await import("../src/explorer/session/session-manager.ts");

const sessionManager = new SessionManager();

// Handle --list
if (explorerArgs.includes("--list")) {
const sessions = await sessionManager.list();
if (sessions.length === 0) {
console.log("No saved sessions.");
} else {
console.log("Saved sessions:\n");
for (const s of sessions) {
const label = s.name || s.sessionId;
console.log(` ${label}`);
console.log(` ${s.stageCount} stages, last used ${formatAge(Date.now() - s.lastAccessedAt)}`);
console.log();
}
}
process.exit(0);
}

// Handle --clean
if (explorerArgs.includes("--clean")) {
const removed = await sessionManager.clean();
console.log(removed === 0
? "No sessions to clean up."
: `Removed ${removed} session${removed === 1 ? "" : "s"} older than 7 days.`);
process.exit(0);
}

// Parse explorer options
const explorerOptions: ExplorerOptions = {};
for (let i = 0; i < explorerArgs.length; i++) {
const arg = explorerArgs[i]!;
if (arg === "--session" || arg === "-s") {
explorerOptions.sessionId = explorerArgs[++i];
} else if (arg === "--pipeline" || arg === "-p") {
explorerOptions.pipeline = explorerArgs[++i];
} else if (arg === "--help" || arg === "-h") {
console.log(`Usage: recs explorer [options] [inputfile]
Options:
--session, -s <id> Resume a saved session
--pipeline, -p <cmd> Start with an initial pipeline command
--list List saved sessions
--clean Remove sessions older than 7 days
Supported file types: .csv, .tsv, .xml, .jsonl, .json, .ndjson`);
process.exit(0);
} else if (!arg.startsWith("-")) {
explorerOptions.inputFile = arg;
}
}

try {
await launchExplorer(explorerOptions);
} catch (err) {
process.stderr.write(
`\nExplorer error: ${err instanceof Error ? err.message : String(err)}\n`,
);
if (err instanceof Error && err.stack) {
process.stderr.write(err.stack + "\n");
}
process.exit(1);
}
process.exit(0);
}

// Handle alias management subcommand
Expand Down Expand Up @@ -194,3 +254,10 @@ if (!noUpdateCheck && shouldCheck(getConfigDir())) {
}

process.exit(exitCode);

function formatAge(ms: number): string {
if (ms < 60_000) return "just now";
if (ms < 3_600_000) return `${Math.floor(ms / 60_000)}m ago`;
if (ms < 86_400_000) return `${Math.floor(ms / 3_600_000)}h ago`;
return `${Math.floor(ms / 86_400_000)}d ago`;
}
Loading