limbo-ai 1.9.1 → 1.9.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/cli.js +21 -6
  2. package/package.json +1 -1
package/cli.js CHANGED
@@ -20,6 +20,8 @@ const COMPOSE_FILE = path.join(LIMBO_DIR, 'docker-compose.yml');
20
20
  const GHCR_IMAGE = 'ghcr.io/tomasward1/limbo';
21
21
  const DEFAULT_TAG = require('./package.json').version;
22
22
  const PORT = 18789;
23
+ // OpenClaw's OAuth callback server port — must be exposed when running auth inside Docker
24
+ const OPENCLAW_AUTH_PORT = 1453;
23
25
 
24
26
  // OpenClaw compatibility snapshots from official docs:
25
27
  // - https://docs.openclaw.ai/providers/openai
@@ -256,6 +258,7 @@ const TEXT = {
256
258
  anthropicSubscriptionIntro: 'Generate a Claude setup-token on any machine with `claude setup-token`, then paste it into the next step.',
257
259
  authFlowStart: 'Starting authentication...',
258
260
  authFlowDone: 'Authentication complete.',
261
+ modelConnected: (model) => `Model connected: ${model}`,
259
262
  authFlowFailed: 'Authentication did not complete successfully.',
260
263
  authStatusFailed: 'Provider auth is still missing or invalid. Try running with --reconfigure.',
261
264
  configFlowStart: 'Applying configuration...',
@@ -348,6 +351,7 @@ const TEXT = {
348
351
  anthropicSubscriptionIntro: 'Genera un Claude setup-token en cualquier maquina con `claude setup-token` y pegalo en el siguiente paso.',
349
352
  authFlowStart: 'Iniciando autenticacion...',
350
353
  authFlowDone: 'Autenticacion completada.',
354
+ modelConnected: (model) => `Modelo conectado: ${model}`,
351
355
  authFlowFailed: 'La autenticacion no termino correctamente.',
352
356
  authStatusFailed: 'La autenticacion del provider sigue siendo invalida o no esta configurada. Proba con --reconfigure.',
353
357
  configFlowStart: 'Aplicando configuracion...',
@@ -815,7 +819,8 @@ const stripAnsi = (str) => str.replace(/\x1b\[[0-9;]*[A-Za-z]/g, '').replace(/\r
815
819
  // Spawn OpenClaw auth with filtered output: extract OAuth URLs, suppress branding.
816
820
  // --tty is required so openclaw sees a TTY inside the container and runs the auth wizard.
817
821
  // We pipe stdout/stderr to filter content while the container gets a proper PTY allocation.
818
- function streamFilteredAuth(dockerArgs) {
822
+ // onUrl: optional callback invoked with each unique URL as it appears (e.g. to auto-open browser).
823
+ function streamFilteredAuth(dockerArgs, onUrl = null) {
819
824
  return new Promise((resolve) => {
820
825
  const proc = spawn('docker', dockerArgs, {
821
826
  cwd: LIMBO_DIR,
@@ -828,7 +833,8 @@ function streamFilteredAuth(dockerArgs) {
828
833
 
829
834
  const handleData = (data) => {
830
835
  buf += data.toString();
831
- const lines = buf.split('\n');
836
+ // Split on \r\n, \n, or bare \r — TUIs use carriage returns for in-place redraws
837
+ const lines = buf.split(/\r?\n|\r/);
832
838
  buf = lines.pop(); // hold incomplete last line
833
839
  for (const line of lines) emitLine(line);
834
840
  };
@@ -841,11 +847,12 @@ function streamFilteredAuth(dockerArgs) {
841
847
  if (!seenUrls.has(url)) {
842
848
  seenUrls.add(url);
843
849
  console.log(`\n ${c.cyan}${c.bold}→ ${url}${c.reset}\n`);
850
+ if (onUrl) onUrl(url);
844
851
  }
845
852
  }
846
- return;
853
+ return; // don't double-print the line containing the URL
847
854
  }
848
- // Suppress lines that only contain internal gateway/runtime branding
855
+ // Suppress OpenClaw branding; show everything else (prompts, status, interactive questions)
849
856
  if (/openclaw/i.test(line)) return;
850
857
  if (line.trim()) console.log(` ${line}`);
851
858
  };
@@ -876,8 +883,16 @@ async function runSubscriptionAuthFlow(cfg) {
876
883
  let exitCode;
877
884
  if (cfg.providerFamily === 'openai') {
878
885
  // --tty allocates a PTY inside the container so openclaw's auth wizard runs correctly.
886
+ // -p exposes the OAuth callback port so the browser redirect reaches the in-container server.
879
887
  // We still pipe stdout/stderr to filter out branding and highlight the OAuth URL.
880
- exitCode = await streamFilteredAuth(['compose', 'run', '--tty', '--rm', '--entrypoint', 'openclaw', 'limbo', ...authArgs]);
888
+ const opener = process.platform === 'darwin' ? 'open' : 'xdg-open';
889
+ exitCode = await streamFilteredAuth(
890
+ ['compose', 'run', '--tty', '--rm', '-p', `${OPENCLAW_AUTH_PORT}:${OPENCLAW_AUTH_PORT}`, '--entrypoint', 'openclaw', 'limbo', ...authArgs],
891
+ (url) => {
892
+ // Auto-open the browser so the user doesn't need to copy/paste the URL
893
+ try { spawnSync(opener, [url], { stdio: 'ignore', timeout: 3000 }); } catch {}
894
+ },
895
+ );
881
896
  } else {
882
897
  // Anthropic paste-token is interactive (user pastes a token); keep stdio inherited
883
898
  const authResult = runOpenClaw(authArgs);
@@ -897,7 +912,7 @@ async function runSubscriptionAuthFlow(cfg) {
897
912
  die(t(cfg.language, 'authStatusFailed'));
898
913
  }
899
914
 
900
- ok(t(cfg.language, 'authFlowDone'));
915
+ ok(t(cfg.language, 'modelConnected', `${cfg.provider}/${cfg.modelName}`));
901
916
  }
902
917
 
903
918
  function printSuccess(cfg, gatewayToken) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "limbo-ai",
3
- "version": "1.9.1",
3
+ "version": "1.9.3",
4
4
  "description": "Your personal AI memory agent — install and manage Limbo via npx",
5
5
  "type": "commonjs",
6
6
  "bin": {