index.ts

  1#!/usr/bin/env bun
  2import { runWebCommand } from "./commands/web.js";
  3import { runRepoCommand } from "./commands/repo.js";
  4import { RumiloError } from "../util/errors.js";
  5
  6interface ParsedArgs {
  7  command?: string;
  8  options: Record<string, string | boolean>;
  9  positional: string[];
 10}
 11
 12function parseArgs(args: string[]): ParsedArgs {
 13  const [, , command, ...rest] = args;
 14  const options: Record<string, string | boolean> = {};
 15  const positional: string[] = [];
 16
 17  for (let i = 0; i < rest.length; i += 1) {
 18    const arg = rest[i];
 19    if (!arg) continue;
 20
 21    if (arg.startsWith("--")) {
 22      const [key, value] = arg.slice(2).split("=");
 23      if (!key) continue;
 24      if (value !== undefined) {
 25        options[key] = value;
 26      } else if (rest[i + 1] && !rest[i + 1]?.startsWith("-")) {
 27        options[key] = rest[i + 1] as string;
 28        i += 1;
 29      } else {
 30        options[key] = true;
 31      }
 32    } else if (arg.startsWith("-")) {
 33      const short = arg.slice(1);
 34      if (short === "u" && rest[i + 1]) {
 35        options["uri"] = rest[i + 1] as string;
 36        i += 1;
 37      } else if (short === "f") {
 38        options["full"] = true;
 39      } else {
 40        options[short] = true;
 41      }
 42    } else {
 43      positional.push(arg);
 44    }
 45  }
 46
 47  return { command, options, positional };
 48}
 49
 50async function main() {
 51  const { command, options, positional } = parseArgs(process.argv);
 52
 53  if (!command || command === "help") {
 54    console.log("rumilo web <query> [-u URL] [--model <provider:model>] [--verbose] [--no-cleanup]");
 55    console.log("rumilo repo -u <uri> <query> [--ref <ref>] [--full] [--model <provider:model>] [--verbose] [--no-cleanup]");
 56    process.exit(0);
 57  }
 58
 59  try {
 60    if (command === "web") {
 61      const query = positional.join(" ");
 62      if (!query) {
 63        throw new RumiloError("Missing query", "CLI_ERROR");
 64      }
 65
 66      await runWebCommand({
 67        query,
 68        url: options["uri"] ? String(options["uri"]) : undefined,
 69        model: options["model"] ? String(options["model"]) : undefined,
 70        verbose: Boolean(options["verbose"]),
 71        cleanup: !options["no-cleanup"],
 72      });
 73      return;
 74    }
 75
 76    if (command === "repo") {
 77      const query = positional.join(" ");
 78      const uri = options["uri"] ? String(options["uri"]) : undefined;
 79      if (!uri) {
 80        throw new RumiloError("Missing repo URI", "CLI_ERROR");
 81      }
 82      if (!query) {
 83        throw new RumiloError("Missing query", "CLI_ERROR");
 84      }
 85
 86      await runRepoCommand({
 87        query,
 88        uri,
 89        ref: options["ref"] ? String(options["ref"]) : undefined,
 90        full: Boolean(options["full"]),
 91        model: options["model"] ? String(options["model"]) : undefined,
 92        verbose: Boolean(options["verbose"]),
 93        cleanup: !options["no-cleanup"],
 94      });
 95      return;
 96    }
 97
 98    throw new RumiloError(`Unknown command: ${command}`, "CLI_ERROR");
 99  } catch (error: any) {
100    const message = error instanceof Error ? error.message : String(error);
101    console.error(message);
102    process.exitCode = 1;
103  }
104}
105
106main();