@gowuai/cli 0.1.0 → 0.1.1

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/README.md CHANGED
@@ -13,7 +13,7 @@ npm i -g @gowuai/cli
13
13
  gowu login
14
14
  ```
15
15
 
16
- `gowu login` 会给出一个网址和授权码:在任意设备(手机也行)的浏览器打开,用手机号登录、选择要授权的应用即可。第一次登录会自动开通体验应用。
16
+ `gowu login` 会自动打开浏览器授权页,用手机号登录、选择要授权的应用即可;同时打印网址和授权码,没弹出浏览器(远程服务器、SSH、Agent 沙箱)时手动打开,或在手机上打开也行。`--no-browser` 不自动打开。第一次登录会自动开通体验应用。
17
17
  不需要填任何密钥;登录后令牌自动续期,30 天内不用再登录。凭证保存在 `~/.config/gowu/credentials.json`(只有本人可读)。
18
18
 
19
19
  可以登录多个应用:`gowu apps` 查看,`gowu use <应用名>` 切换;单条命令也可以用 `--app <应用名>` 指定。
@@ -0,0 +1,34 @@
1
+ import { spawn } from "node:child_process";
2
+ /**
3
+ * 登录时尽量自动打开授权页(gh auth login 同款体验)。打不开不影响登录:网址与授权码照样打印,用户可以手动打开、
4
+ * 或在手机上打开——设备码登录本来就是为打不开浏览器的环境(Agent 沙箱、远程服务器)设计的。
5
+ *
6
+ * 不自动打开的情况:--no-browser / GOWU_NO_BROWSER、CI、SSH 远程会话、Linux 没有图形界面。
7
+ */
8
+ export function canOpenBrowser(noBrowserFlag) {
9
+ const env = process.env;
10
+ if (noBrowserFlag || env.GOWU_NO_BROWSER || env.CI)
11
+ return false;
12
+ if (env.SSH_CONNECTION || env.SSH_TTY)
13
+ return false;
14
+ if (process.platform === "linux" && !env.DISPLAY && !env.WAYLAND_DISPLAY)
15
+ return false;
16
+ return process.platform === "darwin" || process.platform === "win32" || process.platform === "linux";
17
+ }
18
+ export function openBrowser(url) {
19
+ try {
20
+ const [cmd, args] = process.platform === "darwin"
21
+ ? ["open", [url]]
22
+ : process.platform === "win32"
23
+ ? // start 的第一个带引号参数是窗口标题,所以先给个空标题
24
+ ["cmd", ["/c", "start", "", url.replace(/&/g, "^&")]]
25
+ : ["xdg-open", [url]];
26
+ const child = spawn(cmd, args, { stdio: "ignore", detached: true });
27
+ child.on("error", () => undefined);
28
+ child.unref();
29
+ return true;
30
+ }
31
+ catch {
32
+ return false;
33
+ }
34
+ }
package/dist/index.js CHANGED
@@ -3,6 +3,7 @@ import { CliError, pollDeviceLogin, startDeviceLogin, tokenToCredential } from "
3
3
  import { COMMANDS, commandsFor, makeCtx } from "./commands.js";
4
4
  import { clearCredentials, currentApp, findAppKey, loadCredentials, resolveBase, saveCredentials, sceneOf } from "./config.js";
5
5
  import { callTool } from "./mcp.js";
6
+ import { canOpenBrowser, openBrowser } from "./browser.js";
6
7
  /**
7
8
  * gowu —— 格物开放平台命令行。
8
9
  *
@@ -67,7 +68,7 @@ function help(scene, appName) {
67
68
  appName ? `当前应用:${appName}(${scene === "enterprise" ? "企业购" : "消费者购物"})` : "还没登录:先执行 gowu login",
68
69
  "",
69
70
  "账号",
70
- " gowu login 在浏览器里授权(设备码登录,可在手机上完成)",
71
+ " gowu login 在浏览器里授权(自动打开授权页;--no-browser 不打开,也可在手机上完成)",
71
72
  " Agent 用:gowu login --start 先拿网址与授权码,用户授权后 gowu login --finish",
72
73
  " gowu whoami 当前应用与账号",
73
74
  " gowu apps 已登录的应用;gowu use <应用名|appKey> 切换",
@@ -103,11 +104,15 @@ async function login(opts) {
103
104
  pending = await startDeviceLogin(c);
104
105
  c.pending = pending;
105
106
  saveCredentials(c);
107
+ // 能打开就直接打开授权页(Agent 跑在用户电脑上时也会弹出,省得用户复制网址);打不开就靠打印的网址
108
+ const opened = canOpenBrowser(Boolean(opts["no-browser"])) && openBrowser(pending.verificationUriComplete);
106
109
  if (opts.start) {
107
110
  const data = { verificationUri: pending.verificationUri, verificationUriComplete: pending.verificationUriComplete, userCode: pending.userCode, expiresIn: Math.round((pending.expiresAt - Date.now()) / 1000) };
108
- return print(opts.json ? JSON.stringify(data, null, 2) : `${codeMessage(pending)}\n\n用户在浏览器里授权后,执行 gowu login --finish 完成登录。`);
111
+ return print(opts.json
112
+ ? JSON.stringify({ ...data, browserOpened: opened }, null, 2)
113
+ : `${opened ? "已在浏览器中打开授权页。" : ""}${codeMessage(pending)}\n\n用户在浏览器里授权后,执行 gowu login --finish 完成登录。`);
109
114
  }
110
- print(`${codeMessage(pending)}\n正在等待授权…`);
115
+ print(`${opened ? "已在浏览器中打开授权页;没有弹出的话请手动打开下面的网址。\n\n" : ""}${codeMessage(pending)}\n正在等待授权…`);
111
116
  }
112
117
  const t = await pollDeviceLogin(c, pending, { once: Boolean(opts.once) });
113
118
  if (!t)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gowuai/cli",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "格物(GoWu)开放平台命令行:搜索商品、下单付款、订单售后、企业购额度与企业管理。给人用,也给 AI Agent 用。",
5
5
  "type": "module",
6
6
  "bin": {