traderclaw-cli 1.0.114 → 1.0.116
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/bin/installer-step-engine.mjs +17 -11
- package/bin/openclaw-trader.mjs +51 -11
- package/package.json +2 -2
|
@@ -1827,12 +1827,13 @@ function configureOpenClawLlmModelPrimaryOnly({ provider, model }, configPath =
|
|
|
1827
1827
|
}
|
|
1828
1828
|
|
|
1829
1829
|
/**
|
|
1830
|
-
* Spawns `openclaw models auth login --provider openai-codex` with a pseudo-TTY when possible.
|
|
1830
|
+
* Spawns `openclaw models auth login --provider openai-codex --method oauth` with a pseudo-TTY when possible.
|
|
1831
|
+
* `--method oauth` skips the interactive Browser vs Device pairing menu (OpenClaw 2026.4.29+); device flow is `device-code`.
|
|
1831
1832
|
* The CLI often exits immediately when stdin/stdout are plain pipes (no TTY). On Unix, `script(1)`
|
|
1832
1833
|
* allocates a PTY so the same flow works as in an interactive terminal.
|
|
1833
1834
|
*/
|
|
1834
1835
|
export function spawnOpenClawCodexAuthLoginChild() {
|
|
1835
|
-
const argv = ["models", "auth", "login", "--provider", "openai-codex"];
|
|
1836
|
+
const argv = ["models", "auth", "login", "--provider", "openai-codex", "--method", "oauth"];
|
|
1836
1837
|
if (process.platform === "win32") {
|
|
1837
1838
|
return spawn("openclaw", argv, { stdio: ["pipe", "pipe", "pipe"], shell: false });
|
|
1838
1839
|
}
|
|
@@ -1840,14 +1841,19 @@ export function spawnOpenClawCodexAuthLoginChild() {
|
|
|
1840
1841
|
return spawn("unbuffer", ["openclaw", ...argv], { stdio: ["pipe", "pipe", "pipe"], shell: false });
|
|
1841
1842
|
}
|
|
1842
1843
|
if (commandExists("script")) {
|
|
1843
|
-
|
|
1844
|
-
//
|
|
1845
|
-
//
|
|
1846
|
-
//
|
|
1847
|
-
//
|
|
1848
|
-
//
|
|
1844
|
+
// stty cols 32767: set an extremely wide PTY column so OpenClaw/Clack never
|
|
1845
|
+
// wraps the OAuth URL across lines (default PTY width when spawned via pipe is 80).
|
|
1846
|
+
// A wrapped URL causes the wizard's regex to only capture the first segment.
|
|
1847
|
+
// --return propagates openclaw's exit code (util-linux 2.38+).
|
|
1848
|
+
// -f/--flush: force immediate forwarding of each PTY write to the pipe so the
|
|
1849
|
+
// wizard sees the URL as soon as OpenClaw prints it (default is block-buffered).
|
|
1850
|
+
const cmdline =
|
|
1851
|
+
"stty cols 32767 rows 50 2>/dev/null; openclaw models auth login --provider openai-codex --method oauth";
|
|
1849
1852
|
return spawn("script", ["--return", "-f", "-q", "-c", cmdline, "/dev/null"], {
|
|
1850
1853
|
stdio: ["pipe", "pipe", "pipe"],
|
|
1854
|
+
// COLUMNS/LINES: belt-and-suspenders env fallback for programs that read env
|
|
1855
|
+
// instead of ioctl(TIOCGWINSZ) to determine terminal dimensions.
|
|
1856
|
+
env: { ...process.env, COLUMNS: "32767", LINES: "50" },
|
|
1851
1857
|
shell: false,
|
|
1852
1858
|
});
|
|
1853
1859
|
}
|
|
@@ -1855,7 +1861,7 @@ export function spawnOpenClawCodexAuthLoginChild() {
|
|
|
1855
1861
|
}
|
|
1856
1862
|
|
|
1857
1863
|
/**
|
|
1858
|
-
* Runs `openclaw models auth login --provider openai-codex` and feeds the pasted redirect URL or code on stdin
|
|
1864
|
+
* Runs `openclaw models auth login --provider openai-codex --method oauth` and feeds the pasted redirect URL or code on stdin
|
|
1859
1865
|
* when the CLI prompts (with a timed fallback for non-interactive / SSH).
|
|
1860
1866
|
*/
|
|
1861
1867
|
function runOpenClawCodexOAuthLogin(paste, emitLog) {
|
|
@@ -2329,7 +2335,7 @@ export class InstallerStepEngine {
|
|
|
2329
2335
|
} catch (err) {
|
|
2330
2336
|
const tail = `${err?.stderr || ""}\n${err?.stdout || ""}\n${err?.message || ""}`.trim();
|
|
2331
2337
|
throw new Error(
|
|
2332
|
-
`${tail}\n\nIf OAuth cannot complete from the wizard, run in a shell: openclaw models auth login --provider openai-codex — then re-run the wizard with "already logged in" checked.`,
|
|
2338
|
+
`${tail}\n\nIf OAuth cannot complete from the wizard, run in a shell: openclaw models auth login --provider openai-codex --method oauth — then re-run the wizard with "already logged in" checked.`,
|
|
2333
2339
|
);
|
|
2334
2340
|
}
|
|
2335
2341
|
}
|
|
@@ -2343,7 +2349,7 @@ export class InstallerStepEngine {
|
|
|
2343
2349
|
throw new Error(
|
|
2344
2350
|
"No OAuth credentials found at " + authFile + ". " +
|
|
2345
2351
|
"The wizard OAuth flow did not save tokens (the callback may not have reached the OpenClaw CLI). " +
|
|
2346
|
-
"Run 'openclaw models auth login --provider openai-codex' in a terminal, " +
|
|
2352
|
+
"Run 'openclaw models auth login --provider openai-codex --method oauth' in a terminal, " +
|
|
2347
2353
|
"then re-run the wizard with the 'already logged in' option.",
|
|
2348
2354
|
);
|
|
2349
2355
|
}
|
package/bin/openclaw-trader.mjs
CHANGED
|
@@ -3043,7 +3043,11 @@ function wizardHtml(defaults) {
|
|
|
3043
3043
|
setOauthStep(oauthStepOpen, "error");
|
|
3044
3044
|
setOauthStep(oauthStepComplete, "error");
|
|
3045
3045
|
setOauthStep(oauthStepVerify, "error");
|
|
3046
|
-
|
|
3046
|
+
let msg = (data && (data.message || data.error)) || "Could not start OAuth sign-in.";
|
|
3047
|
+
if (data && typeof data.detail === "string" && data.detail.trim()) {
|
|
3048
|
+
msg += " " + data.detail.trim().slice(0, 1500);
|
|
3049
|
+
}
|
|
3050
|
+
setOauthStatus(msg, true);
|
|
3047
3051
|
if (oauthRetryBtn) oauthRetryBtn.classList.remove("hidden");
|
|
3048
3052
|
updateStartButtonState();
|
|
3049
3053
|
return;
|
|
@@ -3629,6 +3633,27 @@ async function cmdInstall(args) {
|
|
|
3629
3633
|
// The \S+ (non-whitespace) tail captures the full query string; see trySendUrl()
|
|
3630
3634
|
// for why we run this against a stripAnsi+CR-stripped copy of the output.
|
|
3631
3635
|
const OPENAI_OAUTH_AUTHORIZE_RE = /https:\/\/auth\.openai\.com\/(?:oauth\/authorize|authorize)[^\s"]*/;
|
|
3636
|
+
const OPENAI_OAUTH_AUTHORIZE_RE_LOOSE =
|
|
3637
|
+
/https:\/\/(?:[a-z0-9-]+\.)*openai\.com\/[^\s"]*?(?:oauth\/authorize|\/authorize[^\s"]*)/i;
|
|
3638
|
+
|
|
3639
|
+
/** Best-effort: primary regex, then subdomain/openai authorize URLs, then token-like query heuristics. */
|
|
3640
|
+
function tryExtractOpenAiCodexAuthorizeUrl(cleaned) {
|
|
3641
|
+
let m = cleaned.match(OPENAI_OAUTH_AUTHORIZE_RE);
|
|
3642
|
+
if (m?.[0]) return m[0];
|
|
3643
|
+
m = cleaned.match(OPENAI_OAUTH_AUTHORIZE_RE_LOOSE);
|
|
3644
|
+
if (m?.[0]) return m[0];
|
|
3645
|
+
const candidates = cleaned.match(/https:\/\/[^\s"]+/g) || [];
|
|
3646
|
+
for (const u of candidates) {
|
|
3647
|
+
if (
|
|
3648
|
+
/openai\.com/i.test(u)
|
|
3649
|
+
&& /authorize/i.test(u)
|
|
3650
|
+
&& /oauth|response_type|client_id|redirect_uri|scope=/i.test(u)
|
|
3651
|
+
) {
|
|
3652
|
+
return u;
|
|
3653
|
+
}
|
|
3654
|
+
}
|
|
3655
|
+
return null;
|
|
3656
|
+
}
|
|
3632
3657
|
const oauthSessionTtlMs = 15 * 60 * 1000;
|
|
3633
3658
|
|
|
3634
3659
|
// Long-lived callback proxy on port 1455. Bound at wizard startup so
|
|
@@ -3856,6 +3881,10 @@ async function cmdInstall(args) {
|
|
|
3856
3881
|
const urlTimeout = setTimeout(() => {
|
|
3857
3882
|
if (responded) return;
|
|
3858
3883
|
responded = true;
|
|
3884
|
+
const detail = stripAnsi(combined).slice(-4000);
|
|
3885
|
+
if (process.env.TRADERCLAW_WIZARD_OAUTH_DEBUG === "1") {
|
|
3886
|
+
printWarn(`[TRADERCLAW_WIZARD_OAUTH_DEBUG] OpenClaw output tail before oauth_url_timeout:\n${detail}`);
|
|
3887
|
+
}
|
|
3859
3888
|
try {
|
|
3860
3889
|
child.kill("SIGTERM");
|
|
3861
3890
|
} catch {
|
|
@@ -3868,20 +3897,31 @@ async function cmdInstall(args) {
|
|
|
3868
3897
|
error: "oauth_url_timeout",
|
|
3869
3898
|
message:
|
|
3870
3899
|
"OpenClaw did not provide a ChatGPT sign-in URL in time. Try again.",
|
|
3900
|
+
detail,
|
|
3871
3901
|
});
|
|
3872
3902
|
}, 120_000);
|
|
3873
3903
|
|
|
3874
3904
|
const trySendUrl = () => {
|
|
3875
3905
|
if (responded) return;
|
|
3876
|
-
//
|
|
3877
|
-
//
|
|
3878
|
-
//
|
|
3879
|
-
//
|
|
3880
|
-
|
|
3881
|
-
const
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
|
|
3906
|
+
// Layer 1: strip ANSI codes and carriage returns, then join any URL continuation
|
|
3907
|
+
// lines caused by PTY column-wrapping (e.g. at 80-col default). When the URL is
|
|
3908
|
+
// split across lines the [^\s] tail of the regex stops at the newline and only the
|
|
3909
|
+
// first fragment is captured. Removing newlines that are sandwiched between URL-safe
|
|
3910
|
+
// characters reconnects all fragments before matching.
|
|
3911
|
+
const cleanedForUrl = stripAnsi(combined)
|
|
3912
|
+
.replace(/\r/g, "")
|
|
3913
|
+
.replace(/([A-Za-z0-9%&=+?#:/@._~!$'()*,;-])\n([A-Za-z0-9%&=+?#:/@._~!$'()*,;-])/g, "$1$2");
|
|
3914
|
+
let authUrl = tryExtractOpenAiCodexAuthorizeUrl(cleanedForUrl);
|
|
3915
|
+
// Layer 2: try the raw combined buffer in case stripAnsi dropped a character that
|
|
3916
|
+
// broke the URL detection (raw ANSI seqs don't include space so regex still works).
|
|
3917
|
+
if (!authUrl) {
|
|
3918
|
+
const rawCleaned = combined.replace(/\r/g, "")
|
|
3919
|
+
.replace(/([A-Za-z0-9%&=+?#:/@._~!$'()*,;-])\n([A-Za-z0-9%&=+?#:/@._~!$'()*,;-])/g, "$1$2");
|
|
3920
|
+
authUrl = tryExtractOpenAiCodexAuthorizeUrl(rawCleaned);
|
|
3921
|
+
}
|
|
3922
|
+
if (!authUrl) return;
|
|
3923
|
+
// Strip any trailing ANSI remnants (e.g. \x1b[0m appended by colour reset)
|
|
3924
|
+
authUrl = stripAnsi(authUrl).replace(/\r/g, "").trim();
|
|
3885
3925
|
if (!authUrl.startsWith("https://")) return;
|
|
3886
3926
|
clearTimeout(urlTimeout);
|
|
3887
3927
|
responded = true;
|
|
@@ -3944,7 +3984,7 @@ async function cmdInstall(args) {
|
|
|
3944
3984
|
pending.status = "failed";
|
|
3945
3985
|
pending.message =
|
|
3946
3986
|
"OpenClaw exited OK but no auth tokens were saved. " +
|
|
3947
|
-
"Run 'openclaw models auth login --provider openai-codex' in a terminal, " +
|
|
3987
|
+
"Run 'openclaw models auth login --provider openai-codex --method oauth' in a terminal, " +
|
|
3948
3988
|
"then re-run the wizard with the already-logged-in option.";
|
|
3949
3989
|
} else {
|
|
3950
3990
|
pending.status = "failed";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "traderclaw-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.116",
|
|
4
4
|
"description": "Global TraderClaw CLI (install --wizard, setup, precheck). Installs solana-traderclaw as a dependency for OpenClaw plugin files.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"node": ">=22"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"solana-traderclaw": "^1.0.
|
|
20
|
+
"solana-traderclaw": "^1.0.116"
|
|
21
21
|
},
|
|
22
22
|
"keywords": [
|
|
23
23
|
"traderclaw",
|