rlm-cli 0.2.1 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/interactive.js +61 -30
  2. package/package.json +1 -1
@@ -153,23 +153,23 @@ function printWelcome() {
153
153
  function printCommandHelp() {
154
154
  console.log(`
155
155
  ${c.bold}Context${c.reset}
156
- ${c.yellow}/file${c.reset} <path> Load file as context
157
- ${c.yellow}/url${c.reset} <url> Fetch URL as context
158
- ${c.yellow}/paste${c.reset} Multi-line paste mode (EOF to finish)
159
- ${c.yellow}/context${c.reset} Show loaded context info
160
- ${c.yellow}/clear-context${c.reset} Unload context
156
+ ${c.cyan}/file${c.reset} <path> Load file as context
157
+ ${c.cyan}/url${c.reset} <url> Fetch URL as context
158
+ ${c.cyan}/paste${c.reset} Multi-line paste mode (EOF to finish)
159
+ ${c.cyan}/context${c.reset} Show loaded context info
160
+ ${c.cyan}/clear-context${c.reset} Unload context
161
161
 
162
162
  ${c.bold}Model${c.reset}
163
- ${c.yellow}/model${c.reset} Show current model & list available
164
- ${c.yellow}/model${c.reset} <id> Switch model for this session
163
+ ${c.cyan}/model${c.reset} List available models
164
+ ${c.cyan}/model${c.reset} <#|id> Switch model by number or ID
165
165
 
166
166
  ${c.bold}Tools${c.reset}
167
- ${c.yellow}/trajectories${c.reset} List saved runs
167
+ ${c.cyan}/trajectories${c.reset} List saved runs
168
168
 
169
169
  ${c.bold}General${c.reset}
170
- ${c.yellow}/clear${c.reset} Clear screen
171
- ${c.yellow}/help${c.reset} Show this help
172
- ${c.yellow}/quit${c.reset} Exit
170
+ ${c.cyan}/clear${c.reset} Clear screen
171
+ ${c.cyan}/help${c.reset} Show this help
172
+ ${c.cyan}/quit${c.reset} Exit
173
173
 
174
174
  ${c.dim}Or just paste a URL or 4+ lines of code, then type your query.${c.reset}
175
175
  `);
@@ -357,6 +357,20 @@ function displaySubQueryResult(info) {
357
357
  }
358
358
  console.log(` ${c.magenta}└─${c.reset} ${c.dim}${elapsed}s · ${formatSize(info.resultLength)} received${c.reset}`);
359
359
  }
360
+ // ── Available models list ────────────────────────────────────────────────────
361
+ /** Collect models from providers that have an API key set. */
362
+ function getAvailableModels() {
363
+ const items = [];
364
+ for (const provider of getProviders()) {
365
+ const providerKey = `${provider.toUpperCase().replace(/-/g, "_")}_API_KEY`;
366
+ if (!process.env[providerKey] && provider !== detectProvider())
367
+ continue;
368
+ for (const m of getModels(provider)) {
369
+ items.push({ id: m.id, provider });
370
+ }
371
+ }
372
+ return items;
373
+ }
360
374
  // ── Truncate helper ─────────────────────────────────────────────────────────
361
375
  function truncateStr(text, max) {
362
376
  return text.length <= max ? text : text.slice(0, max - 3) + "...";
@@ -621,6 +635,21 @@ async function interactive() {
621
635
  prompt: `${c.cyan}>${c.reset} `,
622
636
  terminal: true,
623
637
  });
638
+ // Color slash commands cyan as the user types
639
+ const rlAny = rl;
640
+ const promptStr = rl.getPrompt();
641
+ rlAny._writeToOutput = function (str) {
642
+ if (!rlAny.line?.startsWith("/")) {
643
+ rlAny.output.write(str);
644
+ return;
645
+ }
646
+ if (str.startsWith(promptStr)) {
647
+ rlAny.output.write(promptStr + c.cyan + str.slice(promptStr.length) + c.reset);
648
+ }
649
+ else {
650
+ rlAny.output.write(c.cyan + str + c.reset);
651
+ }
652
+ };
624
653
  rl.prompt();
625
654
  rl.on("line", async (rawLine) => {
626
655
  if (isRunning)
@@ -684,38 +713,40 @@ async function interactive() {
684
713
  console.log(` ${c.green}✓${c.reset} Context cleared.`);
685
714
  break;
686
715
  case "model":
687
- case "m":
716
+ case "m": {
717
+ const available = getAvailableModels();
688
718
  if (arg) {
689
- const newModel = resolveModel(arg);
690
- if (newModel) {
691
- currentModelId = arg;
719
+ // Accept a number or a model ID
720
+ const pick = /^\d+$/.test(arg) ? available[parseInt(arg, 10) - 1]?.id : arg;
721
+ const newModel = pick ? resolveModel(pick) : undefined;
722
+ if (newModel && pick) {
723
+ currentModelId = pick;
692
724
  currentModel = newModel;
693
725
  console.log(` ${c.green}✓${c.reset} Switched to ${c.bold}${currentModelId}${c.reset}`);
694
726
  console.log();
695
727
  printStatusLine();
696
728
  }
697
729
  else {
698
- console.log(` ${c.red}Model "${arg}" not found.${c.reset} Use ${c.yellow}/model${c.reset} to list available models.`);
730
+ console.log(` ${c.red}Model "${arg}" not found.${c.reset} Use ${c.cyan}/model${c.reset} to list available models.`);
699
731
  }
700
732
  }
701
733
  else {
702
734
  console.log(`\n ${c.bold}Current model:${c.reset} ${c.cyan}${currentModelId}${c.reset}\n`);
703
- for (const provider of getProviders()) {
704
- const providerKey = `${provider.toUpperCase().replace(/-/g, "_")}_API_KEY`;
705
- if (!process.env[providerKey] && provider !== detectProvider())
706
- continue;
707
- const models = getModels(provider);
708
- if (models.length === 0)
709
- continue;
710
- console.log(` ${c.bold}${provider}${c.reset}`);
711
- for (const m of models) {
712
- const marker = m.id === currentModelId ? `${c.green}● ${c.reset}` : ` `;
713
- console.log(` ${marker}${c.dim}${m.id}${c.reset}`);
714
- }
715
- console.log();
735
+ const pad = String(available.length).length;
736
+ for (let i = 0; i < available.length; i++) {
737
+ const m = available[i];
738
+ const num = String(i + 1).padStart(pad);
739
+ const dot = m.id === currentModelId ? `${c.green}●${c.reset}` : ` `;
740
+ const label = m.id === currentModelId
741
+ ? `${c.cyan}${m.id}${c.reset}`
742
+ : `${c.dim}${m.id}${c.reset}`;
743
+ console.log(` ${c.dim}${num}${c.reset} ${dot} ${label}`);
716
744
  }
745
+ console.log(`\n ${c.dim}${available.length} models · scroll up to see full list.${c.reset}`);
746
+ console.log(` ${c.dim}Type${c.reset} ${c.cyan}/model <number>${c.reset} ${c.dim}or${c.reset} ${c.cyan}/model <id>${c.reset} ${c.dim}to switch.${c.reset}`);
717
747
  }
718
748
  break;
749
+ }
719
750
  case "trajectories":
720
751
  case "traj":
721
752
  handleTrajectories();
@@ -730,7 +761,7 @@ async function interactive() {
730
761
  process.exit(0);
731
762
  break;
732
763
  default:
733
- console.log(` ${c.red}Unknown command: /${cmd}${c.reset}. Type ${c.yellow}/help${c.reset} for commands.`);
764
+ console.log(` ${c.red}Unknown command: /${cmd}${c.reset}. Type ${c.cyan}/help${c.reset} for commands.`);
734
765
  }
735
766
  rl.prompt();
736
767
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rlm-cli",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "description": "Standalone CLI for Recursive Language Models (RLMs) — implements Algorithm 1 from arXiv:2512.24601",
5
5
  "type": "module",
6
6
  "bin": {