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();