alink-cli 0.11.6 → 0.11.7

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
@@ -17,11 +17,11 @@ AgentLink 让你随时从手机或浏览器继续使用运行在自己电脑上
17
17
 
18
18
  ```bash
19
19
  npm install -g alink-cli
20
- alink-cli
20
+ alink
21
21
  ```
22
22
 
23
23
  按提示登录,然后在手机或浏览器打开 [AgentLink 控制台](https://link.harmopath.com/login),即可开始任务或继续已有工作。
24
24
 
25
- `alink-cli login` 会打开浏览器,支持使用 GitHub 或已有 AgentLink 账号登录并添加当前电脑。
25
+ `alink login` 会打开浏览器,支持使用 GitHub 或已有 AgentLink 账号登录并添加当前电脑。原命令 `alink-cli` 继续可用。
26
26
 
27
27
  [GitHub](https://github.com/baichen99/agentlink) · [提交问题](https://github.com/baichen99/agentlink/issues)
package/bin/agentlink.js CHANGED
@@ -61,6 +61,7 @@ const OFFICIAL_HUB = process.env.AGENTLINK_DEFAULT_HUB || "wss://link.harmopath.
61
61
  const STATE_DIR = process.env.AGENTLINK_STATE_DIR || join(homedir(), ".agentlink");
62
62
  const CREDENTIAL_FILE = join(STATE_DIR, "credential");
63
63
  const SESSION_FILE = join(STATE_DIR, "session");
64
+ const STATUS_FILE = join(STATE_DIR, "status.json");
64
65
  const args = process.argv.slice(2);
65
66
  const legacyCredentialCommands = process.env.AGENTLINK_ENABLE_LEGACY_CREDENTIALS === "1";
66
67
  const forceTui = process.env.AGENTLINK_TUI === "1";
@@ -273,7 +274,7 @@ async function pair(hub) {
273
274
 
274
275
  async function showHelp() {
275
276
  console.log(
276
- `用法:\n alink-cli 进入交互式 TUI(默认)\n alink-cli --no-tui 跳过 TUI,按旧行为启动 daemon\n alink-cli login 登录账号\n alink-cli status 查看登录状态\n alink-cli machines 查看账号下的所有机器\n alink-cli logout 退出账号\n alink-cli --legacy 临时运行旧 daemon\n alink-cli help 查看帮助\n\n选项:\n --hub <wss://…> Hub 地址\n --dir <目录> 默认工作目录\n --no-tui 禁用交互式 TUI`,
277
+ `用法:\n alink-cli 打开 AgentLink\n alink-cli login 登录账号\n alink-cli status 查看连接状态\n alink-cli machines 查看账号下的机器\n alink-cli logout 退出账号\n alink-cli help 查看帮助`,
277
278
  );
278
279
  }
279
280
 
@@ -288,9 +289,31 @@ async function showVersion() {
288
289
 
289
290
  async function showStatus() {
290
291
  const hub = value("hub") || OFFICIAL_HUB;
292
+ let status = {};
293
+ try {
294
+ status = JSON.parse(readFileSync(STATUS_FILE, "utf8"));
295
+ } catch {
296
+ // No daemon status yet.
297
+ }
298
+ let running = false;
299
+ if (Number.isInteger(status.pid) && status.pid > 0) {
300
+ try {
301
+ process.kill(status.pid, 0);
302
+ running = true;
303
+ } catch {
304
+ // Stale status file.
305
+ }
306
+ }
307
+ const statusMatchesHub =
308
+ typeof status.hub !== "string" || normalizeHub(status.hub) === normalizeHub(hub);
309
+ const hubStatus = !running || !statusMatchesHub
310
+ ? "未连接"
311
+ : status.hubConnected
312
+ ? "已连接"
313
+ : "连接中";
291
314
  console.log(`[agentlink] 登录状态:${savedCredential(hub) ? "已登录" : "未登录"}`);
292
- console.log(`[agentlink] 会话状态:${savedSessionJwt(hub) ? "已缓存" : "未缓存"}`);
293
- console.log(`[agentlink] Hub:${normalizeHub(hub)}`);
315
+ console.log(`[agentlink] 本机服务:${running ? "运行中" : "已停止"}`);
316
+ console.log(`[agentlink] Hub 连接:${hubStatus}`);
294
317
  }
295
318
 
296
319
  async function doLogout() {
package/dist/bin.mjs CHANGED
@@ -10,8 +10,9 @@ import * as NodeChildProcess from "node:child_process";
10
10
  import * as NodeCrypto from "node:crypto";
11
11
  import { createCipheriv, createDecipheriv, hkdfSync, randomBytes, randomUUID } from "node:crypto";
12
12
  import * as NodeFS from "node:fs";
13
- import { closeSync, mkdirSync, openSync, readFileSync, rmSync, writeSync } from "node:fs";
13
+ import { closeSync, mkdirSync, openSync, readFileSync, rmSync, writeFileSync, writeSync } from "node:fs";
14
14
  import * as NodeOS from "node:os";
15
+ import { homedir } from "node:os";
15
16
  import * as NodePath from "node:path";
16
17
  import { join } from "node:path";
17
18
  import { fileURLToPath } from "node:url";
@@ -53204,6 +53205,26 @@ function hubHttpUrl(hub) {
53204
53205
  url.hash = "";
53205
53206
  return url.toString().replace(/\/$/, "");
53206
53207
  }
53208
+ function writeHubConnectionStatus(config, connected, stateDir = process.env.AGENTLINK_STATE_DIR || join(homedir(), ".agentlink")) {
53209
+ try {
53210
+ mkdirSync(stateDir, { recursive: true });
53211
+ const statusPath = join(stateDir, "status.json");
53212
+ let current = {};
53213
+ try {
53214
+ current = JSON.parse(readFileSync(statusPath, "utf8"));
53215
+ } catch {}
53216
+ writeFileSync(statusPath, JSON.stringify({
53217
+ ...current,
53218
+ pid: process.pid,
53219
+ state: connected ? "connected" : "reconnecting",
53220
+ hub: config.hubUrl,
53221
+ hubConnected: connected,
53222
+ machineId: machineIdFromToken(config.machineToken) ?? void 0,
53223
+ startedAt: typeof current.startedAt === "number" ? current.startedAt : Date.now(),
53224
+ ts: Date.now()
53225
+ }));
53226
+ } catch {}
53227
+ }
53207
53228
  const uploadHubEnckey = (config) => gen(function* () {
53208
53229
  const machineId = machineIdFromToken(config.machineToken);
53209
53230
  if (!machineId) return yield* fail(/* @__PURE__ */ new Error("machine id is missing from the machine token"));
@@ -53334,6 +53355,7 @@ const runHubTunnel = (config) => gen(function* () {
53334
53355
  yield* wsRpcServices.pipe(asVoid);
53335
53356
  yield* ChildProcessSpawner;
53336
53357
  yield* retry(gen(function* () {
53358
+ yield* sync(() => writeHubConnectionStatus(config, false));
53337
53359
  yield* logInfo("hub tunnel: connection effect entered");
53338
53360
  const url = `${config.hubUrl.replace(/\/+$/, "")}/daemon-tunnel?token=${encodeURIComponent(config.machineToken)}&v=1`;
53339
53361
  yield* logInfo("hub tunnel: connecting", { hubUrl: config.hubUrl });
@@ -53582,7 +53604,7 @@ const runHubTunnel = (config) => gen(function* () {
53582
53604
  else dropTunnel(framed.tunnelId);
53583
53605
  return;
53584
53606
  }
53585
- }, { onOpen: logInfo("hub tunnel: connected to hub").pipe(tap(() => sync(() => void runFork(upload)))) }).pipe(tapDefect((cause) => logWarning$1("hub tunnel: hub socket defect", { cause: String(cause) })));
53607
+ }, { onOpen: logInfo("hub tunnel: connected to hub").pipe(tap(() => sync(() => writeHubConnectionStatus(config, true))), tap(() => sync(() => void runFork(upload)))) }).pipe(ensuring(sync(() => writeHubConnectionStatus(config, false))), tapDefect((cause) => logWarning$1("hub tunnel: hub socket defect", { cause: String(cause) })));
53586
53608
  yield* logWarning$1("hub tunnel: hub connection closed");
53587
53609
  return yield* fail(/* @__PURE__ */ new Error("hub tunnel closed"));
53588
53610
  }).pipe(scoped, tapError((error) => logWarning$1("hub tunnel: connection error", { error }))), {