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.
- package/cli.js +21 -6
- 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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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, '
|
|
915
|
+
ok(t(cfg.language, 'modelConnected', `${cfg.provider}/${cfg.modelName}`));
|
|
901
916
|
}
|
|
902
917
|
|
|
903
918
|
function printSuccess(cfg, gatewayToken) {
|