rlm-cli 0.2.8 → 0.2.10

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.
package/dist/env.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  /**
2
- * Load .env file into process.env.
2
+ * Load env vars into process.env.
3
3
  * Must be imported BEFORE any module that reads env vars (e.g. pi-ai).
4
4
  *
5
- * Supports:
6
- * - ANTHROPIC_API_KEY
7
- * - RLM_MODEL (model name, e.g. claude-sonnet-4-5-20250929)
5
+ * Load order (later wins):
6
+ * 1. ~/.rlm/credentials — persistent keys saved by first-run setup
7
+ * 2. .env in package root local overrides
8
8
  */
9
9
  export {};
package/dist/env.js CHANGED
@@ -1,18 +1,18 @@
1
1
  /**
2
- * Load .env file into process.env.
2
+ * Load env vars into process.env.
3
3
  * Must be imported BEFORE any module that reads env vars (e.g. pi-ai).
4
4
  *
5
- * Supports:
6
- * - ANTHROPIC_API_KEY
7
- * - RLM_MODEL (model name, e.g. claude-sonnet-4-5-20250929)
5
+ * Load order (later wins):
6
+ * 1. ~/.rlm/credentials — persistent keys saved by first-run setup
7
+ * 2. .env in package root local overrides
8
8
  */
9
9
  import * as fs from "node:fs";
10
10
  import * as path from "node:path";
11
- // Load .env file from the package root (not CWD, which could be untrusted)
12
- const __dir = path.dirname(new URL(import.meta.url).pathname);
13
- const envPath = path.resolve(__dir, "..", ".env");
14
- if (fs.existsSync(envPath)) {
15
- const content = fs.readFileSync(envPath, "utf-8");
11
+ import * as os from "node:os";
12
+ function loadEnvFile(filePath) {
13
+ if (!fs.existsSync(filePath))
14
+ return;
15
+ const content = fs.readFileSync(filePath, "utf-8");
16
16
  for (const line of content.split("\n")) {
17
17
  const trimmed = line.trim();
18
18
  if (!trimmed || trimmed.startsWith("#"))
@@ -22,13 +22,18 @@ if (fs.existsSync(envPath)) {
22
22
  continue;
23
23
  const key = trimmed.slice(0, eqIndex).trim();
24
24
  const value = trimmed.slice(eqIndex + 1).trim();
25
- if (key) {
25
+ if (key && !process.env[key]) {
26
26
  process.env[key] = value;
27
27
  }
28
28
  }
29
29
  }
30
+ // 1. Load persistent credentials (~/.rlm/credentials)
31
+ loadEnvFile(path.join(os.homedir(), ".rlm", "credentials"));
32
+ // 2. Load .env from package root (local overrides)
33
+ const __dir = path.dirname(new URL(import.meta.url).pathname);
34
+ loadEnvFile(path.resolve(__dir, "..", ".env"));
30
35
  // Default model
31
36
  if (!process.env.RLM_MODEL) {
32
- process.env.RLM_MODEL = "claude-sonnet-4-5-20250929";
37
+ process.env.RLM_MODEL = "claude-sonnet-4-6";
33
38
  }
34
39
  //# sourceMappingURL=env.js.map
@@ -67,7 +67,7 @@ class Spinner {
67
67
  }
68
68
  }
69
69
  // ── Constants ───────────────────────────────────────────────────────────────
70
- const DEFAULT_MODEL = process.env.RLM_MODEL || "claude-sonnet-4-5-20250929";
70
+ const DEFAULT_MODEL = process.env.RLM_MODEL || "claude-sonnet-4-6";
71
71
  const TRAJ_DIR = path.resolve(process.cwd(), "trajectories");
72
72
  const W = Math.min(process.stdout.columns || 80, 100);
73
73
  // ── Session state ───────────────────────────────────────────────────────────
@@ -152,9 +152,26 @@ function resolveModelWithProvider(modelId) {
152
152
  }
153
153
  return undefined;
154
154
  }
155
- /** Returns the first model ID from a given pi-ai provider. */
155
+ /** Sensible default model per provider. */
156
+ const PROVIDER_DEFAULT_MODELS = {
157
+ anthropic: "claude-sonnet-4-6",
158
+ openai: "gpt-4o",
159
+ google: "gemini-2.5-flash",
160
+ groq: "llama-3.3-70b-versatile",
161
+ xai: "grok-4",
162
+ mistral: "mistral-large-latest",
163
+ openrouter: "claude-sonnet-4-6",
164
+ };
165
+ /** Returns the recommended default model for a provider. */
156
166
  function getDefaultModelForProvider(provider) {
157
- const models = getModels(provider);
167
+ const preferred = PROVIDER_DEFAULT_MODELS[provider];
168
+ if (preferred) {
169
+ const model = resolveModel(preferred);
170
+ if (model)
171
+ return preferred;
172
+ }
173
+ // Fallback: first non-excluded model
174
+ const models = getModelsForProvider(provider);
158
175
  return models.length > 0 ? models[0].id : undefined;
159
176
  }
160
177
  /** Wrap rl.question with ESC-to-cancel. Returns user input or null on ESC/empty. */
@@ -189,15 +206,17 @@ async function promptForProviderKey(rlInstance, providerInfo) {
189
206
  if (!key)
190
207
  return false; // empty
191
208
  process.env[providerInfo.env] = key;
192
- // Save to shell profile
193
- const shellRc = process.env.SHELL?.includes("zsh") ? "~/.zshrc" : "~/.bashrc";
194
- const rcPath = shellRc.replace("~", process.env.HOME || "~");
209
+ // Save to ~/.rlm/credentials (persistent across sessions)
210
+ const credDir = path.join(process.env.HOME || "~", ".rlm");
211
+ const credPath = path.join(credDir, "credentials");
195
212
  try {
196
- fs.appendFileSync(rcPath, `\nexport ${providerInfo.env}=${key}\n`);
197
- console.log(`\n ${c.green}✓${c.reset} ${providerInfo.name} key saved to ${c.dim}${shellRc}${c.reset}`);
213
+ if (!fs.existsSync(credDir))
214
+ fs.mkdirSync(credDir, { recursive: true });
215
+ fs.appendFileSync(credPath, `${providerInfo.env}=${key}\n`);
216
+ console.log(`\n ${c.green}✓${c.reset} ${providerInfo.name} key saved to ${c.dim}~/.rlm/credentials${c.reset}`);
198
217
  }
199
218
  catch {
200
- console.log(`\n ${c.yellow}!${c.reset} Could not write to ${shellRc}. Add manually:`);
219
+ console.log(`\n ${c.yellow}!${c.reset} Could not save key. Add manually:`);
201
220
  console.log(` ${c.yellow}export ${providerInfo.env}=${key}${c.reset}`);
202
221
  }
203
222
  return true;
@@ -466,11 +485,8 @@ function displaySubQueryResult(info) {
466
485
  // ── Available models list ────────────────────────────────────────────────────
467
486
  /** Filter out deprecated, retired, and non-chat models (Feb 2026). */
468
487
  const EXCLUDED_MODEL_PATTERNS = [
469
- // ── Anthropic retired ──
470
- /^claude-3-haiku/, // retired Feb 19, 2026
471
- /^claude-3-sonnet/, // long retired
472
- /^claude-3-opus/, // long retired
473
- /^claude-3-5-sonnet/, // retired Jan 5, 2026
488
+ // ── Anthropic retired / old gen ──
489
+ /^claude-3-/, // all claude 3.x retired (haiku, sonnet, opus, 3-5-*, 3-7-*)
474
490
  // ── OpenAI legacy / specialized ──
475
491
  /^gpt-4$/, // superseded by gpt-4.1
476
492
  /^gpt-4-turbo/, // superseded by gpt-4.1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rlm-cli",
3
- "version": "0.2.8",
3
+ "version": "0.2.10",
4
4
  "description": "Standalone CLI for Recursive Language Models (RLMs) — implements Algorithm 1 from arXiv:2512.24601",
5
5
  "type": "module",
6
6
  "bin": {