@zqagent/core 0.2.11 → 0.2.15

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.
@@ -2197,12 +2197,12 @@ var MUTATING_TOOLS = /* @__PURE__ */ new Set([
2197
2197
  ]);
2198
2198
  function parseReadFileSpan(content) {
2199
2199
  const body = content.replace(/^\[tool output truncated:[^\n]*\]\n\n/, "");
2200
- let path35;
2200
+ let path36;
2201
2201
  let start;
2202
2202
  let end;
2203
2203
  try {
2204
2204
  const obj = JSON.parse(body);
2205
- path35 = obj.path;
2205
+ path36 = obj.path;
2206
2206
  start = obj.start_line;
2207
2207
  end = obj.end_line;
2208
2208
  } catch {
@@ -2211,14 +2211,14 @@ function parseReadFileSpan(content) {
2211
2211
  const m = new RegExp(`"${key}"\\s*:\\s*(\\d+)`).exec(body);
2212
2212
  return m ? Number(m[1]) : void 0;
2213
2213
  };
2214
- path35 = str2("path");
2214
+ path36 = str2("path");
2215
2215
  start = num2("start_line");
2216
2216
  end = num2("end_line");
2217
2217
  }
2218
- if (typeof path35 !== "string" || !path35) return null;
2218
+ if (typeof path36 !== "string" || !path36) return null;
2219
2219
  if (typeof start !== "number" || typeof end !== "number") return null;
2220
2220
  if (!Number.isFinite(start) || !Number.isFinite(end)) return null;
2221
- return { path: path35, start, end };
2221
+ return { path: path36, start, end };
2222
2222
  }
2223
2223
  function addSpan(spans, start, end) {
2224
2224
  spans.push([start, end]);
@@ -3835,9 +3835,9 @@ var TurnEngine = class _TurnEngine {
3835
3835
  return;
3836
3836
  }
3837
3837
  if (result && typeof result === "object") {
3838
- const path35 = result.path;
3839
- if (path35) {
3840
- this._producedFiles.push(path35);
3838
+ const path36 = result.path;
3839
+ if (path36) {
3840
+ this._producedFiles.push(path36);
3841
3841
  return;
3842
3842
  }
3843
3843
  const changed = result.changed_files;
@@ -5164,10 +5164,10 @@ var OpenAIProvider = class {
5164
5164
  let timer;
5165
5165
  try {
5166
5166
  for (; ; ) {
5167
- const idle = new Promise((resolve19) => {
5167
+ const idle = new Promise((resolve20) => {
5168
5168
  timer = setTimeout(() => {
5169
5169
  onIdle();
5170
- resolve19({ timedOut: true });
5170
+ resolve20({ timedOut: true });
5171
5171
  }, idleMs);
5172
5172
  });
5173
5173
  const next = iter.next();
@@ -5795,12 +5795,12 @@ function makeSink(maxBuffer) {
5795
5795
  };
5796
5796
  }
5797
5797
  function execAsync(file, argv, opts = {}) {
5798
- return new Promise((resolve19) => {
5798
+ return new Promise((resolve20) => {
5799
5799
  const maxBuffer = opts.maxBuffer ?? DEFAULT_MAX_BUFFER;
5800
5800
  const out = makeSink(maxBuffer);
5801
5801
  const err = makeSink(maxBuffer);
5802
5802
  if (opts.signal?.aborted) {
5803
- resolve19({
5803
+ resolve20({
5804
5804
  status: null,
5805
5805
  stdout: Buffer.alloc(0),
5806
5806
  stderr: Buffer.alloc(0),
@@ -5821,7 +5821,7 @@ function execAsync(file, argv, opts = {}) {
5821
5821
  windowsHide: true
5822
5822
  });
5823
5823
  } catch (e) {
5824
- resolve19({
5824
+ resolve20({
5825
5825
  status: null,
5826
5826
  stdout: Buffer.alloc(0),
5827
5827
  stderr: Buffer.alloc(0),
@@ -5858,7 +5858,7 @@ function execAsync(file, argv, opts = {}) {
5858
5858
  };
5859
5859
  if (aborted) result.aborted = true;
5860
5860
  if (spawnError) result.error = spawnError;
5861
- resolve19(result);
5861
+ resolve20(result);
5862
5862
  };
5863
5863
  const killAndSettle = () => {
5864
5864
  killTree(child.pid);
@@ -7753,18 +7753,18 @@ function makeApplyPatch(workspace) {
7753
7753
  return { changed_files: changedFiles, added_files: addedFiles, deleted_files: deletedFiles, file_count: fileCount };
7754
7754
  };
7755
7755
  }
7756
- function applyPatchHunks(oldLines, chunks, path35) {
7756
+ function applyPatchHunks(oldLines, chunks, path36) {
7757
7757
  let newLines = [...oldLines];
7758
7758
  let cursor = 0;
7759
7759
  for (const chunk of chunks) {
7760
7760
  const oldBlock = chunk.filter((l) => l[0] === " " || l[0] === "-").map((l) => l.slice(1));
7761
7761
  const newBlock = chunk.filter((l) => l[0] === " " || l[0] === "+").map((l) => l.slice(1));
7762
7762
  if (!oldBlock.length) {
7763
- throw new Error(`\u8865\u4E01 hunk \u5FC5\u987B\u5305\u542B\u4E0A\u4E0B\u6587\u6216\u5220\u9664\u884C: ${path35}`);
7763
+ throw new Error(`\u8865\u4E01 hunk \u5FC5\u987B\u5305\u542B\u4E0A\u4E0B\u6587\u6216\u5220\u9664\u884C: ${path36}`);
7764
7764
  }
7765
7765
  const matchStart = findBlockMatch(newLines, oldBlock, cursor);
7766
7766
  if (matchStart === -1) {
7767
- throw new Error(`\u8865\u4E01\u4E0A\u4E0B\u6587\u4E0D\u5339\u914D: ${path35}`);
7767
+ throw new Error(`\u8865\u4E01\u4E0A\u4E0B\u6587\u4E0D\u5339\u914D: ${path36}`);
7768
7768
  }
7769
7769
  const matchEnd = matchStart + oldBlock.length;
7770
7770
  newLines.splice(matchStart, oldBlock.length, ...newBlock);
@@ -9857,11 +9857,11 @@ function isAffirmative(answer) {
9857
9857
  return /^(yes|approve|同意|批准|允许|确定|可以|好的|确认)/.test(a);
9858
9858
  }
9859
9859
  function defer() {
9860
- let resolve19;
9860
+ let resolve20;
9861
9861
  const promise = new Promise((r) => {
9862
- resolve19 = r;
9862
+ resolve20 = r;
9863
9863
  });
9864
- return { promise, resolve: resolve19 };
9864
+ return { promise, resolve: resolve20 };
9865
9865
  }
9866
9866
  var SessionManager = class {
9867
9867
  constructor(store, approvalTimeoutMs = APPROVAL_TIMEOUT_MS, opts = {}) {
@@ -10433,11 +10433,11 @@ data: ${JSON.stringify({ sessionId, seq: entry.seq, ts: entry.ts, data: entry.da
10433
10433
  status: "pending",
10434
10434
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
10435
10435
  };
10436
- const { promise, resolve: resolve19 } = defer();
10436
+ const { promise, resolve: resolve20 } = defer();
10437
10437
  const timer = setTimeout(() => {
10438
10438
  this._recycleApproval(rt, id);
10439
10439
  }, this.approvalTimeoutMs);
10440
- rt.pendingApprovals.set(id, { promise, resolve: resolve19, record, timer });
10440
+ rt.pendingApprovals.set(id, { promise, resolve: resolve20, record, timer });
10441
10441
  rt.approvals.set(id, record);
10442
10442
  this._setStatus(rt, "waiting_approval");
10443
10443
  this._persist(rt);
@@ -10515,11 +10515,11 @@ data: ${JSON.stringify({ sessionId, seq: entry.seq, ts: entry.ts, data: entry.da
10515
10515
  status: "pending",
10516
10516
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
10517
10517
  };
10518
- const { promise, resolve: resolve19 } = defer();
10518
+ const { promise, resolve: resolve20 } = defer();
10519
10519
  const timer = setTimeout(() => {
10520
10520
  this._recycleQuestion(rt, qid);
10521
10521
  }, this.approvalTimeoutMs);
10522
- rt.pendingQuestions.set(qid, { promise, resolve: resolve19, record, timer });
10522
+ rt.pendingQuestions.set(qid, { promise, resolve: resolve20, record, timer });
10523
10523
  rt.questions.set(qid, record);
10524
10524
  this._setStatus(rt, "waiting_question");
10525
10525
  this._persist(rt);
@@ -10828,7 +10828,7 @@ data: ${JSON.stringify(entry.data)}
10828
10828
  if (rt.mcpReady) {
10829
10829
  await Promise.race([
10830
10830
  rt.mcpReady,
10831
- new Promise((resolve19) => setTimeout(resolve19, 15e3))
10831
+ new Promise((resolve20) => setTimeout(resolve20, 15e3))
10832
10832
  ]).catch(() => void 0);
10833
10833
  }
10834
10834
  for await (const event of gen) {
@@ -11413,7 +11413,7 @@ function buildNodeInfo(store, opts) {
11413
11413
  nodeId: opts.nodeId ?? ensureNodeId(store),
11414
11414
  platform: process.platform,
11415
11415
  mode: process.env.NODE_MODE ?? "standalone",
11416
- version: "0.2.11",
11416
+ version: "0.2.15",
11417
11417
  admin: opts.admin,
11418
11418
  projects: opts.projects
11419
11419
  };
@@ -11497,8 +11497,8 @@ function hubProxyEnabled(host) {
11497
11497
  const h = (host ?? "127.0.0.1").trim();
11498
11498
  return h === "127.0.0.1" || h === "localhost" || h === "::1";
11499
11499
  }
11500
- function isHubProxyPath(path35) {
11501
- return path35.startsWith(HUB_PROXY_PREFIX);
11500
+ function isHubProxyPath(path36) {
11501
+ return path36.startsWith(HUB_PROXY_PREFIX);
11502
11502
  }
11503
11503
  function decodeTarget(enc) {
11504
11504
  try {
@@ -12406,7 +12406,7 @@ function buildNodeHost(store, manager, diskPath) {
12406
12406
  arch: process.arch,
12407
12407
  release: os6.release(),
12408
12408
  uptimeSec: Math.round(os6.uptime()),
12409
- version: "0.2.11",
12409
+ version: "0.2.15",
12410
12410
  mode: process.env.NODE_MODE ?? "standalone",
12411
12411
  cpu: {
12412
12412
  count: cpus2.length,
@@ -12450,7 +12450,7 @@ function saveNotifications(tenant, secretBox, notifications) {
12450
12450
  var API_PREFIX = "/api/v1";
12451
12451
  var MAX_BODY_BYTES = 10 * 1024 * 1024;
12452
12452
  function readBody(req2) {
12453
- return new Promise((resolve19, reject) => {
12453
+ return new Promise((resolve20, reject) => {
12454
12454
  const chunks = [];
12455
12455
  let size = 0;
12456
12456
  req2.on("data", (c) => {
@@ -12463,9 +12463,9 @@ function readBody(req2) {
12463
12463
  chunks.push(c);
12464
12464
  });
12465
12465
  req2.on("end", () => {
12466
- if (chunks.length === 0) return resolve19(void 0);
12466
+ if (chunks.length === 0) return resolve20(void 0);
12467
12467
  try {
12468
- resolve19(JSON.parse(Buffer.concat(chunks).toString("utf-8")));
12468
+ resolve20(JSON.parse(Buffer.concat(chunks).toString("utf-8")));
12469
12469
  } catch {
12470
12470
  reject(new ApiError(400, "bad_request", "\u8BF7\u6C42\u4F53\u4E0D\u662F\u5408\u6CD5 JSON"));
12471
12471
  }
@@ -12776,7 +12776,25 @@ function createApp(store, manager, opts = {}) {
12776
12776
  ok(res, opts.fleet.status());
12777
12777
  }
12778
12778
  },
12779
- // 运行时热接入:凭一次性注册码接入 Hub(落盘 fleet.json + 立即连接,免重启)
12779
+ // 修改本机节点显示名:写本地配置并立即上报;已接入 Hub 时同步 Hub 记录。
12780
+ // `zqagent rename` 在有 server 在跑时走这里(热生效,免重启)。
12781
+ {
12782
+ method: "POST",
12783
+ pattern: ["fleet", "label"],
12784
+ adminOnly: true,
12785
+ fn: async (_req, res, { body }) => {
12786
+ if (!opts.fleet) {
12787
+ throw new ApiError(503, "fleet_disabled", "\u8282\u70B9\u7BA1\u7406\u63A7\u5236\u5668\u672A\u542F\u7528");
12788
+ }
12789
+ const raw = body ?? {};
12790
+ const label2 = typeof raw.label === "string" ? raw.label.trim() : "";
12791
+ if (!label2) {
12792
+ throw new ApiError(400, "bad_request", "label \u4E0D\u80FD\u4E3A\u7A7A");
12793
+ }
12794
+ ok(res, await opts.fleet.rename(label2));
12795
+ }
12796
+ },
12797
+ // 运行时热接入:凭一次性注册码或 Hub 账号接入(落盘 fleet.json + 立即连接,免重启)
12780
12798
  {
12781
12799
  method: "POST",
12782
12800
  pattern: ["fleet", "enroll"],
@@ -12788,15 +12806,42 @@ function createApp(store, manager, opts = {}) {
12788
12806
  const raw = body ?? {};
12789
12807
  const hubUrl2 = String(raw.hubUrl ?? "").trim().replace(/\/$/, "");
12790
12808
  const code = String(raw.code ?? "").trim();
12791
- if (!hubUrl2 || !code) {
12792
- throw new ApiError(400, "bad_request", "hubUrl \u4E0E code \u5FC5\u586B");
12809
+ const email = String(raw.email ?? "").trim();
12810
+ const phone = String(raw.phone ?? "").trim();
12811
+ const password = String(raw.password ?? "");
12812
+ const smsCode = String(raw.smsCode ?? "").trim();
12813
+ const hasAccount = Boolean(email || phone);
12814
+ if (!hubUrl2) {
12815
+ throw new ApiError(400, "bad_request", "hubUrl \u5FC5\u586B");
12816
+ }
12817
+ if (code && hasAccount) {
12818
+ throw new ApiError(400, "bad_request", "code \u4E0E\u8D26\u53F7\u51ED\u636E\u53EA\u80FD\u4E8C\u9009\u4E00");
12819
+ }
12820
+ if (!code && !hasAccount) {
12821
+ throw new ApiError(400, "bad_request", "\u9700\u8981 code\uFF0C\u6216 email/phone + password/smsCode");
12822
+ }
12823
+ if (hasAccount && !password && !smsCode) {
12824
+ throw new ApiError(400, "bad_request", "\u8D26\u53F7\u63A5\u5165\u9700\u8981 password \u6216 smsCode");
12793
12825
  }
12794
12826
  const label2 = typeof raw.label === "string" ? raw.label.trim() : void 0;
12795
12827
  try {
12796
- ok(res, await opts.fleet.enroll({ hubUrl: hubUrl2, code, label: label2 }));
12828
+ ok(
12829
+ res,
12830
+ await opts.fleet.enroll({
12831
+ hubUrl: hubUrl2,
12832
+ code: code || void 0,
12833
+ account: hasAccount ? {
12834
+ email: email || void 0,
12835
+ phone: phone || void 0,
12836
+ password: password || void 0,
12837
+ smsCode: smsCode || void 0
12838
+ } : void 0,
12839
+ label: label2
12840
+ })
12841
+ );
12797
12842
  } catch (e) {
12798
12843
  const code2 = e.code;
12799
- const status = code2 === "code_expired" ? 410 : code2 === "code_used" || code2 === "node_taken" ? 409 : code2 === "not_found" ? 404 : code2 === "plan_limit" || code2 === "subscription_required" ? 402 : 400;
12844
+ const status = code2 === "code_expired" ? 410 : code2 === "unauthorized" ? 401 : code2 === "account_disabled" ? 403 : code2 === "code_used" || code2 === "node_taken" ? 409 : code2 === "not_found" ? 404 : code2 === "plan_limit" || code2 === "subscription_required" ? 402 : 400;
12800
12845
  const msg = e instanceof Error ? e.message : String(e);
12801
12846
  throw new ApiError(
12802
12847
  status,
@@ -13942,10 +13987,10 @@ function createApp(store, manager, opts = {}) {
13942
13987
  function handle(req2, res) {
13943
13988
  const startedAt = Date.now();
13944
13989
  const url = new URL(req2.url ?? "/", "http://localhost");
13945
- const path35 = url.pathname;
13990
+ const path36 = url.pathname;
13946
13991
  const method = req2.method ?? "GET";
13947
13992
  console.log(
13948
- `[api] ${(/* @__PURE__ */ new Date()).toISOString()} \u2192 ${method} ${path35}${url.search}`
13993
+ `[api] ${(/* @__PURE__ */ new Date()).toISOString()} \u2192 ${method} ${path36}${url.search}`
13949
13994
  );
13950
13995
  let tenantId = null;
13951
13996
  let logged = false;
@@ -13953,7 +13998,7 @@ function createApp(store, manager, opts = {}) {
13953
13998
  if (logged) return;
13954
13999
  logged = true;
13955
14000
  console.log(
13956
- `[api] ${(/* @__PURE__ */ new Date()).toISOString()} \u2190 ${method} ${path35} ${extra} (${Date.now() - startedAt}ms) tenant=${tenantId ?? "-"}`
14001
+ `[api] ${(/* @__PURE__ */ new Date()).toISOString()} \u2190 ${method} ${path36} ${extra} (${Date.now() - startedAt}ms) tenant=${tenantId ?? "-"}`
13957
14002
  );
13958
14003
  };
13959
14004
  res.on("finish", () => logDone(`HTTP ${res.statusCode}`));
@@ -13964,16 +14009,16 @@ function createApp(store, manager, opts = {}) {
13964
14009
  res.end();
13965
14010
  return;
13966
14011
  }
13967
- if (req2.method === "GET" && path35 === "/healthz") {
14012
+ if (req2.method === "GET" && path36 === "/healthz") {
13968
14013
  json(res, 200, {
13969
14014
  status: "ok",
13970
14015
  // 版本让运维/探针能确认线上跑的是哪个构建(更新与回滚据此判断)
13971
- version: "0.2.11",
14016
+ version: "0.2.15",
13972
14017
  features: { mcp: hasServerMcpConfig() }
13973
14018
  });
13974
14019
  return;
13975
14020
  }
13976
- if (hubProxyEnabled(opts.host) && isHubProxyPath(path35)) {
14021
+ if (hubProxyEnabled(opts.host) && isHubProxyPath(path36)) {
13977
14022
  void handleHubProxy(req2, res).catch(() => {
13978
14023
  if (!res.headersSent) {
13979
14024
  res.writeHead(502, { "Content-Type": "application/json; charset=utf-8" });
@@ -13984,11 +14029,11 @@ function createApp(store, manager, opts = {}) {
13984
14029
  });
13985
14030
  return;
13986
14031
  }
13987
- if (!path35.startsWith(API_PREFIX)) {
14032
+ if (!path36.startsWith(API_PREFIX)) {
13988
14033
  json(res, 404, { error: { code: "not_found", message: "\u672A\u77E5\u8DEF\u5F84" } });
13989
14034
  return;
13990
14035
  }
13991
- const segs = path35.slice(API_PREFIX.length).split("/").filter(Boolean);
14036
+ const segs = path36.slice(API_PREFIX.length).split("/").filter(Boolean);
13992
14037
  const apiKey = extractApiKey(req2);
13993
14038
  if (!apiKey) {
13994
14039
  json(res, 401, {
@@ -14053,7 +14098,7 @@ function createApp(store, manager, opts = {}) {
14053
14098
  ).catch((err) => {
14054
14099
  const msg = err instanceof Error ? err.message : String(err);
14055
14100
  console.log(
14056
- `[api] ${(/* @__PURE__ */ new Date()).toISOString()} ! ${method} ${path35} ERROR: ${msg}`
14101
+ `[api] ${(/* @__PURE__ */ new Date()).toISOString()} ! ${method} ${path36} ERROR: ${msg}`
14057
14102
  );
14058
14103
  error(res, err);
14059
14104
  });
@@ -14084,8 +14129,8 @@ async function cachedFetchModels(baseURL, apiKey) {
14084
14129
  try {
14085
14130
  result = await Promise.race([
14086
14131
  fetchModels(baseURL, apiKey),
14087
- new Promise((resolve19) => {
14088
- const t = setTimeout(() => resolve19(null), MODEL_FETCH_TIMEOUT_MS);
14132
+ new Promise((resolve20) => {
14133
+ const t = setTimeout(() => resolve20(null), MODEL_FETCH_TIMEOUT_MS);
14089
14134
  t.unref?.();
14090
14135
  })
14091
14136
  ]);
@@ -14110,8 +14155,8 @@ async function cachedFetchModelsEnriched(baseURL, apiKey, preferred) {
14110
14155
  if (!target) return r;
14111
14156
  const ctx = await Promise.race([
14112
14157
  fetchModelContext(baseURL, apiKey, target),
14113
- new Promise((resolve19) => {
14114
- const t = setTimeout(() => resolve19(void 0), MODEL_FETCH_TIMEOUT_MS);
14158
+ new Promise((resolve20) => {
14159
+ const t = setTimeout(() => resolve20(void 0), MODEL_FETCH_TIMEOUT_MS);
14115
14160
  t.unref?.();
14116
14161
  })
14117
14162
  ]);
@@ -15305,13 +15350,13 @@ var EVENT_FLUSH_MAX_EVENTS = 60;
15305
15350
  var EVENT_FLUSH_MAX_BYTES = 200 * 1024;
15306
15351
  var LOOP_LAG_WARN_MS = 2e3;
15307
15352
  function withTimeout(p, ms) {
15308
- return new Promise((resolve19, reject) => {
15353
+ return new Promise((resolve20, reject) => {
15309
15354
  const timer = setTimeout(() => reject(new Error(`\u5B50\u6307\u4EE4\u8D85\u65F6\uFF08${ms}ms\uFF09`)), ms);
15310
15355
  timer.unref?.();
15311
15356
  p.then(
15312
15357
  (v) => {
15313
15358
  clearTimeout(timer);
15314
- resolve19(v);
15359
+ resolve20(v);
15315
15360
  },
15316
15361
  (e) => {
15317
15362
  clearTimeout(timer);
@@ -15662,6 +15707,11 @@ var FleetNodeBridge = class {
15662
15707
  refreshInfo() {
15663
15708
  this._publishInfo();
15664
15709
  }
15710
+ /** 本地改名后把 status(含 label)与 info 立即重发,控制台不必等下一次周期上报 */
15711
+ republishLabel() {
15712
+ this._send({ kind: "status", status: this._status(this.isConnected()) });
15713
+ this._publishInfo();
15714
+ }
15665
15715
  // ===================== 内部 =====================
15666
15716
  _status(online) {
15667
15717
  return {
@@ -15671,7 +15721,7 @@ var FleetNodeBridge = class {
15671
15721
  label: this.opts.deps.store.loadNodeLabel() ?? void 0,
15672
15722
  platform: process.platform,
15673
15723
  mode: process.env.NODE_MODE ?? "standalone",
15674
- version: "0.2.11",
15724
+ version: "0.2.15",
15675
15725
  ip: primaryIp()
15676
15726
  };
15677
15727
  }
@@ -15690,7 +15740,23 @@ var FleetNodeBridge = class {
15690
15740
  byDay: days
15691
15741
  };
15692
15742
  }
15743
+ /**
15744
+ * 上报 info(项目/会话快照)。
15745
+ *
15746
+ * 失败必须留痕:这是控制台「项目列表」的唯一数据源,静默失败会表现为
15747
+ * 「这台节点永远没有任何项目」,且只能靠网关 detail=null 才发现。
15748
+ * 同时用 try 包住,避免一次读盘异常中断 `_onUp` 后续的状态通知。
15749
+ */
15693
15750
  _publishInfo() {
15751
+ try {
15752
+ this._publishInfoNow();
15753
+ } catch (e) {
15754
+ console.warn(
15755
+ `[fleet] \u8282\u70B9 ${this.nodeId} \u4E0A\u62A5 info \u5931\u8D25: ${e instanceof Error ? e.message : String(e)}`
15756
+ );
15757
+ }
15758
+ }
15759
+ _publishInfoNow() {
15694
15760
  const totals = { projects: 0, sessions: 0, running: 0, waiting: 0 };
15695
15761
  const sessions = [];
15696
15762
  const projects = allProjectSummaries(this.opts.deps.store).map((p) => {
@@ -15717,7 +15783,15 @@ var FleetNodeBridge = class {
15717
15783
  totals.sessions += p.sessionCount;
15718
15784
  totals.running += running;
15719
15785
  totals.waiting += waiting;
15720
- return { id: p.id, name: p.name, sessionCount: p.sessionCount, running, waiting };
15786
+ return {
15787
+ id: p.id,
15788
+ name: p.name,
15789
+ sessionCount: p.sessionCount,
15790
+ running,
15791
+ waiting,
15792
+ // 控制台项目列表要展示工作目录(Hub 落盘快照后即可离线查看)
15793
+ workspaceRoot: p.workspaceRoot ?? null
15794
+ };
15721
15795
  });
15722
15796
  this._send({
15723
15797
  kind: "info",
@@ -15726,7 +15800,7 @@ var FleetNodeBridge = class {
15726
15800
  label: this.opts.deps.store.loadNodeLabel() ?? void 0,
15727
15801
  platform: process.platform,
15728
15802
  mode: process.env.NODE_MODE ?? "standalone",
15729
- version: "0.2.11",
15803
+ version: "0.2.15",
15730
15804
  ip: primaryIp(),
15731
15805
  projects,
15732
15806
  totals,
@@ -15936,6 +16010,14 @@ function resolveFleetConfig(store) {
15936
16010
  return fleetConfigFromEnv(store);
15937
16011
  }
15938
16012
 
16013
+ // src/node-name.ts
16014
+ init_cjs_shims();
16015
+ var os8 = __toESM(require("os"), 1);
16016
+ function defaultNodeLabel() {
16017
+ const name = os8.hostname().trim();
16018
+ return name || "zqagent-node";
16019
+ }
16020
+
15939
16021
  // src/server/notify/index.ts
15940
16022
  init_cjs_shims();
15941
16023
 
@@ -17141,13 +17223,13 @@ var baseUrlResolver = null;
17141
17223
  function resolveBase(baseUrl) {
17142
17224
  return baseUrlResolver ? baseUrlResolver(baseUrl) : baseUrl;
17143
17225
  }
17144
- async function req(baseUrl, token, path35, init = {}) {
17226
+ async function req(baseUrl, token, path36, init = {}) {
17145
17227
  const headers = {
17146
17228
  ...init.body ? { "Content-Type": "application/json" } : {},
17147
17229
  ...init.headers ?? {}
17148
17230
  };
17149
17231
  if (token) headers.Authorization = `Bearer ${token}`;
17150
- const res = await fetch(`${resolveBase(baseUrl).replace(/\/$/, "")}${path35}`, {
17232
+ const res = await fetch(`${resolveBase(baseUrl).replace(/\/$/, "")}${path36}`, {
17151
17233
  ...init,
17152
17234
  headers
17153
17235
  });
@@ -17186,6 +17268,12 @@ async function hubEnrollByAccount(baseUrl, input) {
17186
17268
  });
17187
17269
  return { hubUrl: baseUrl.replace(/\/$/, ""), ...data };
17188
17270
  }
17271
+ async function hubUpdateNodeLabelSelf(baseUrl, fleetToken, input) {
17272
+ return await req(baseUrl, fleetToken, "/api/hub/nodes/self/label", {
17273
+ method: "POST",
17274
+ body: JSON.stringify(input)
17275
+ });
17276
+ }
17189
17277
 
17190
17278
  // src/update/controller.ts
17191
17279
  init_cjs_shims();
@@ -17445,12 +17533,12 @@ function selfCheck(binPath, expectedVersion) {
17445
17533
  // src/update/platform.ts
17446
17534
  init_cjs_shims();
17447
17535
  var fs25 = __toESM(require("fs"), 1);
17448
- var os8 = __toESM(require("os"), 1);
17536
+ var os9 = __toESM(require("os"), 1);
17449
17537
  var path29 = __toESM(require("path"), 1);
17450
17538
  var import_node_child_process5 = require("child_process");
17451
17539
  var import_node_module3 = require("module");
17452
17540
  function currentVersion() {
17453
- const injected = "0.2.11"?.trim();
17541
+ const injected = "0.2.15"?.trim();
17454
17542
  if (injected) return injected;
17455
17543
  try {
17456
17544
  const req2 = (0, import_node_module3.createRequire)(importMetaUrl);
@@ -17488,7 +17576,7 @@ function launchdPlistPath() {
17488
17576
  const label2 = launchdLabel();
17489
17577
  const uid = typeof process.getuid === "function" ? process.getuid() : -1;
17490
17578
  if (uid === 0) return `/Library/LaunchDaemons/${label2}.plist`;
17491
- return path29.join(os8.homedir(), "Library", "LaunchAgents", `${label2}.plist`);
17579
+ return path29.join(os9.homedir(), "Library", "LaunchAgents", `${label2}.plist`);
17492
17580
  }
17493
17581
  function serviceManagerFromLaunchctl(output, pid, execPath, sea = true) {
17494
17582
  const pidMatch = /^\s*pid = (\d+)\s*$/m.exec(output);
@@ -17977,11 +18065,11 @@ var UpdateController = class {
17977
18065
  const minUptime = num("ZQAGENT_UPDATE_MIN_UPTIME_MS", 10 * 60 * 1e3);
17978
18066
  const idleMs = num("ZQAGENT_UPDATE_IDLE_MS", 60 * 1e3);
17979
18067
  let idleSince = null;
17980
- return new Promise((resolve19) => {
18068
+ return new Promise((resolve20) => {
17981
18069
  const timer = setInterval(() => {
17982
18070
  if (this.stopped) {
17983
18071
  clearInterval(timer);
17984
- resolve19(false);
18072
+ resolve20(false);
17985
18073
  return;
17986
18074
  }
17987
18075
  if (Date.now() - this.startedAt < minUptime || !this.opts.isIdle()) {
@@ -17991,7 +18079,7 @@ var UpdateController = class {
17991
18079
  idleSince ??= Date.now();
17992
18080
  if (Date.now() - idleSince >= idleMs) {
17993
18081
  clearInterval(timer);
17994
- resolve19(true);
18082
+ resolve20(true);
17995
18083
  }
17996
18084
  }, 1e3);
17997
18085
  timer.unref();
@@ -18174,7 +18262,7 @@ function exitWhenOrphaned() {
18174
18262
  }
18175
18263
  var PORT_FALLBACK_LIMIT = 20;
18176
18264
  function listenWithPortFallback(server, startPort, host, dataDir, limit = PORT_FALLBACK_LIMIT) {
18177
- return new Promise((resolve19, reject) => {
18265
+ return new Promise((resolve20, reject) => {
18178
18266
  let attempts = 0;
18179
18267
  const tryListen = (port) => {
18180
18268
  server.removeAllListeners("listening");
@@ -18206,7 +18294,7 @@ function listenWithPortFallback(server, startPort, host, dataDir, limit = PORT_F
18206
18294
  `);
18207
18295
  } catch {
18208
18296
  }
18209
- resolve19(actualPort);
18297
+ resolve20(actualPort);
18210
18298
  });
18211
18299
  };
18212
18300
  tryListen(startPort);
@@ -18284,7 +18372,7 @@ function startServer(opts = {}) {
18284
18372
  hubUrl: fleetCred?.hubUrl,
18285
18373
  gatewayUrl: fleetCred?.gatewayUrl ?? env2("FLEET_GATEWAY_URL"),
18286
18374
  online: fleet?.isConnected() ?? false,
18287
- label: fleetCred?.label,
18375
+ label: fleetCred?.label ?? store.loadNodeLabel() ?? void 0,
18288
18376
  lastError: fleet?.getLastError() ?? void 0,
18289
18377
  reconnectCount: fleet?.getErrorCount() ?? 0
18290
18378
  };
@@ -18293,20 +18381,53 @@ function startServer(opts = {}) {
18293
18381
  status: fleetStatus,
18294
18382
  async enroll(input) {
18295
18383
  const nodeId = ensureNodeId(store);
18296
- const cred = await hubEnrollByCode(input.hubUrl, {
18384
+ const label2 = input.label?.trim() || defaultNodeLabel();
18385
+ const cred = input.account ? await hubEnrollByAccount(input.hubUrl, {
18386
+ email: input.account.email,
18387
+ phone: input.account.phone,
18388
+ password: input.account.password,
18389
+ code: input.account.smsCode,
18390
+ nodeId,
18391
+ label: label2
18392
+ }) : await hubEnrollByCode(input.hubUrl, {
18297
18393
  code: input.code,
18298
18394
  nodeId,
18299
- label: input.label
18395
+ label: label2
18300
18396
  });
18301
18397
  const full = {
18302
18398
  ...cred,
18303
- label: input.label ?? cred.label,
18399
+ label: label2,
18304
18400
  enrolledAt: (/* @__PURE__ */ new Date()).toISOString()
18305
18401
  };
18306
18402
  store.saveFleetCredential(full);
18403
+ store.saveNodeLabel(label2);
18307
18404
  connectFleet(full);
18308
18405
  return fleetStatus();
18309
18406
  },
18407
+ async rename(label2) {
18408
+ const name = label2.trim();
18409
+ store.saveNodeLabel(name);
18410
+ if (fleetCred) {
18411
+ fleetCred = { ...fleetCred, label: name };
18412
+ store.saveFleetCredential(fleetCred);
18413
+ }
18414
+ fleet?.republishLabel();
18415
+ let hubSynced = false;
18416
+ let hubError;
18417
+ const cred = fleetCred;
18418
+ if (cred?.hubUrl && cred.fleetToken) {
18419
+ try {
18420
+ await hubUpdateNodeLabelSelf(cred.hubUrl, cred.fleetToken, {
18421
+ nodeId: ensureNodeId(store),
18422
+ label: name
18423
+ });
18424
+ hubSynced = true;
18425
+ } catch (e) {
18426
+ hubError = e instanceof Error ? e.message : String(e);
18427
+ }
18428
+ }
18429
+ return { ...fleetStatus(), hubSynced, hubError };
18430
+ },
18310
18431
  unlink() {
18311
18432
  fleet?.close();
18312
18433
  fleet = null;
@@ -18437,7 +18558,7 @@ function startServer(opts = {}) {
18437
18558
  server.timeout = 0;
18438
18559
  server.keepAliveTimeout = 65e3;
18439
18560
  server.headersTimeout = 66e3;
18440
- const ready = new Promise((resolve19, reject) => {
18561
+ const ready = new Promise((resolve20, reject) => {
18441
18562
  listenWithPortFallback(server, port, host, dataDir).then((actualPort) => {
18442
18563
  const info = {
18443
18564
  host,
@@ -18454,7 +18575,7 @@ function startServer(opts = {}) {
18454
18575
  printReady(info, qq);
18455
18576
  }
18456
18577
  updater?.start();
18457
- resolve19(info);
18578
+ resolve20(info);
18458
18579
  }, reject);
18459
18580
  });
18460
18581
  return {
@@ -18504,39 +18625,12 @@ function parseHubAnswer(answer, fallback) {
18504
18625
  if (SKIP_ANSWERS.has(a.toLowerCase())) return null;
18505
18626
  return (a || fallback).replace(/\/$/, "");
18506
18627
  }
18507
- function resolveDataDir(dataDir) {
18508
- return path34.resolve(dataDir ?? process.env.DATA_DIR ?? DEFAULT_DATA_DIR);
18509
- }
18510
- async function maybeAccountEnroll(opts = {}) {
18511
- if (!process.stdin.isTTY || !process.stdout.isTTY) return;
18512
- let store;
18513
- try {
18514
- store = new Store(resolveDataDir(opts.dataDir));
18515
- if (resolveFleetConfig(store)) return;
18516
- } catch (e) {
18517
- cliErr(`\u63A5\u5165\u68C0\u67E5\u5931\u8D25\uFF1A${e instanceof Error ? e.message : String(e)}`);
18518
- return;
18519
- }
18520
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
18521
- try {
18522
- await runWizard(rl, store, opts);
18523
- } catch (e) {
18524
- cliErr(`\u63A5\u5165\u5931\u8D25\uFF1A${e instanceof Error ? e.message : String(e)}`);
18525
- cliLog(" \u53EF\u7A0D\u540E\u5728\u63A7\u5236\u53F0\u751F\u6210\u63A5\u5165\u7801\uFF0C\u518D\u6267\u884C\uFF1Azqagent link --hub <Hub\u5730\u5740> --code <\u63A5\u5165\u7801>");
18526
- } finally {
18527
- rl.close();
18528
- }
18529
- }
18530
- async function runWizard(rl, store, opts) {
18531
- cliLog("");
18532
- cliLog("\u672C\u673A\u5C1A\u672A\u63A5\u5165 Hub\u3002\u53EF\u7528 Hub \u8D26\u53F7\u63A5\u5165\uFF08\u8282\u70B9\u9ED8\u8BA4\u8FDB\u5165\u300C\u672A\u5206\u7EC4\u300D\uFF09\uFF1B\u8F93\u5165 - \u8DF3\u8FC7\u4FDD\u6301\u7EAF\u672C\u5730\u3002");
18533
- const fallback = resolveDefaultHub(opts.hubUrl);
18628
+ async function promptHubUrl(rl, hubUrl2) {
18629
+ const fallback = resolveDefaultHub(hubUrl2);
18534
18630
  const answer = await rl.question(`Hub \u5730\u5740 [${fallback}]\uFF1A`);
18535
- const hubUrl2 = parseHubAnswer(answer, fallback);
18536
- if (!hubUrl2) {
18537
- cliLog("\u5DF2\u8DF3\u8FC7\u63A5\u5165\uFF1A\u8282\u70B9\u4FDD\u6301\u7EAF\u672C\u5730\u8FD0\u884C\u3002");
18538
- return;
18539
- }
18631
+ return parseHubAnswer(answer, fallback);
18632
+ }
18633
+ async function promptAccountLogin(rl, hubUrl2) {
18540
18634
  cliLog("\u767B\u5F55\u65B9\u5F0F\uFF1A1) \u90AE\u7BB1 + \u5BC6\u7801 2) \u624B\u673A\u53F7 + \u5BC6\u7801 3) \u624B\u673A\u53F7 + \u77ED\u4FE1\u9A8C\u8BC1\u7801");
18541
18635
  const mode = (await rl.question("\u8BF7\u9009\u62E9 [1]\uFF1A")).trim() || "1";
18542
18636
  const input = {};
@@ -18545,53 +18639,107 @@ async function runWizard(rl, store, opts) {
18545
18639
  input.password = await askHidden(rl, "\u5BC6\u7801\uFF1A");
18546
18640
  if (!input.email || !input.password) {
18547
18641
  cliErr("\u90AE\u7BB1\u4E0E\u5BC6\u7801\u4E0D\u80FD\u4E3A\u7A7A\uFF0C\u5DF2\u8DF3\u8FC7\u63A5\u5165\u3002");
18548
- return;
18642
+ return null;
18549
18643
  }
18550
18644
  } else if (mode === "2") {
18551
18645
  input.phone = (await rl.question("\u624B\u673A\u53F7\uFF1A")).trim();
18552
18646
  input.password = await askHidden(rl, "\u5BC6\u7801\uFF1A");
18553
18647
  if (!input.phone || !input.password) {
18554
18648
  cliErr("\u624B\u673A\u53F7\u4E0E\u5BC6\u7801\u4E0D\u80FD\u4E3A\u7A7A\uFF0C\u5DF2\u8DF3\u8FC7\u63A5\u5165\u3002");
18555
- return;
18649
+ return null;
18556
18650
  }
18557
18651
  } else if (mode === "3") {
18558
18652
  input.phone = (await rl.question("\u624B\u673A\u53F7\uFF1A")).trim();
18559
18653
  if (!input.phone) {
18560
18654
  cliErr("\u624B\u673A\u53F7\u4E0D\u80FD\u4E3A\u7A7A\uFF0C\u5DF2\u8DF3\u8FC7\u63A5\u5165\u3002");
18561
- return;
18655
+ return null;
18562
18656
  }
18563
18657
  try {
18564
- const sent = await hubSendSms(hubUrl2, { phone: input.phone, purpose: "login" });
18658
+ const sent = await hubSendSms(resolveDefaultHub(hubUrl2), {
18659
+ phone: input.phone,
18660
+ purpose: "login"
18661
+ });
18565
18662
  if (sent.debugCode) cliLog(`\uFF08\u8C03\u8BD5\u6A21\u5F0F\u9A8C\u8BC1\u7801\uFF1A${sent.debugCode}\uFF09`);
18566
18663
  else cliLog("\u9A8C\u8BC1\u7801\u5DF2\u53D1\u9001\uFF0C5 \u5206\u949F\u5185\u6709\u6548\u3002");
18567
18664
  } catch (e) {
18568
18665
  cliErr(`\u77ED\u4FE1\u9A8C\u8BC1\u7801\u53D1\u9001\u5931\u8D25\uFF1A${e instanceof Error ? e.message : String(e)}`);
18569
18666
  cliLog(" \u53EF\u6539\u7528\u65B9\u5F0F 1/2\uFF08\u5BC6\u7801\u767B\u5F55\uFF09\uFF0C\u6216\u5728\u7F51\u9875\u7AEF\u751F\u6210\u63A5\u5165\u7801\u540E\u6267\u884C\uFF1A");
18570
18667
  cliLog(" zqagent link --hub <Hub\u5730\u5740> --code <\u63A5\u5165\u7801>");
18571
- return;
18668
+ return null;
18572
18669
  }
18573
18670
  input.code = (await rl.question("\u77ED\u4FE1\u9A8C\u8BC1\u7801\uFF1A")).trim();
18574
18671
  if (!input.code) {
18575
18672
  cliErr("\u9A8C\u8BC1\u7801\u4E0D\u80FD\u4E3A\u7A7A\uFF0C\u5DF2\u8DF3\u8FC7\u63A5\u5165\u3002");
18576
- return;
18673
+ return null;
18577
18674
  }
18578
18675
  } else {
18579
18676
  cliErr("\u672A\u77E5\u7684\u767B\u5F55\u65B9\u5F0F\uFF0C\u5DF2\u8DF3\u8FC7\u63A5\u5165\u3002");
18677
+ return null;
18678
+ }
18679
+ return input;
18680
+ }
18681
+ async function promptLinkAccount(rl, hubUrl2, opts = {}) {
18682
+ const fallback = resolveDefaultHub(hubUrl2);
18683
+ let resolved = fallback;
18684
+ if (opts.askHub !== false) {
18685
+ const answer = await promptHubUrl(rl, fallback);
18686
+ if (!answer) {
18687
+ cliLog("\u5DF2\u8DF3\u8FC7\u63A5\u5165\uFF1A\u8282\u70B9\u4FDD\u6301\u7EAF\u672C\u5730\u8FD0\u884C\u3002");
18688
+ return null;
18689
+ }
18690
+ resolved = answer;
18691
+ }
18692
+ const auth = await promptAccountLogin(rl, resolved);
18693
+ if (!auth) return null;
18694
+ return { hubUrl: resolved, auth };
18695
+ }
18696
+ function resolveDataDir(dataDir) {
18697
+ return path34.resolve(dataDir ?? process.env.DATA_DIR ?? DEFAULT_DATA_DIR);
18698
+ }
18699
+ async function maybeAccountEnroll(opts = {}) {
18700
+ if (!process.stdin.isTTY || !process.stdout.isTTY) return;
18701
+ let store;
18702
+ try {
18703
+ store = new Store(resolveDataDir(opts.dataDir));
18704
+ if (resolveFleetConfig(store)) return;
18705
+ } catch (e) {
18706
+ cliErr(`\u63A5\u5165\u68C0\u67E5\u5931\u8D25\uFF1A${e instanceof Error ? e.message : String(e)}`);
18580
18707
  return;
18581
18708
  }
18709
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
18710
+ try {
18711
+ await runWizard(rl, store, opts);
18712
+ } catch (e) {
18713
+ cliErr(`\u63A5\u5165\u5931\u8D25\uFF1A${e instanceof Error ? e.message : String(e)}`);
18714
+ cliLog(" \u53EF\u7A0D\u540E\u5728\u63A7\u5236\u53F0\u751F\u6210\u63A5\u5165\u7801\uFF0C\u518D\u6267\u884C\uFF1Azqagent link --hub <Hub\u5730\u5740> --code <\u63A5\u5165\u7801>");
18715
+ } finally {
18716
+ rl.close();
18717
+ }
18718
+ }
18719
+ async function runWizard(rl, store, opts) {
18720
+ cliLog("");
18721
+ cliLog("\u672C\u673A\u5C1A\u672A\u63A5\u5165 Hub\u3002\u53EF\u7528 Hub \u8D26\u53F7\u63A5\u5165\uFF08\u8282\u70B9\u9ED8\u8BA4\u8FDB\u5165\u300C\u672A\u5206\u7EC4\u300D\uFF09\uFF1B\u8F93\u5165 - \u8DF3\u8FC7\u4FDD\u6301\u7EAF\u672C\u5730\u3002");
18722
+ const prompted = await promptLinkAccount(rl, opts.hubUrl);
18723
+ if (!prompted) return;
18582
18724
  const nodeId = ensureNodeId(store);
18583
- const cred = await hubEnrollByAccount(hubUrl2, { ...input, nodeId, label: opts.label });
18725
+ const label2 = opts.label?.trim() || defaultNodeLabel();
18726
+ const cred = await hubEnrollByAccount(prompted.hubUrl, {
18727
+ ...prompted.auth,
18728
+ nodeId,
18729
+ label: label2
18730
+ });
18584
18731
  store.saveFleetCredential({
18585
18732
  ...cred,
18586
- label: opts.label ?? cred.label,
18733
+ label: label2,
18587
18734
  enrolledAt: (/* @__PURE__ */ new Date()).toISOString()
18588
18735
  });
18736
+ store.saveNodeLabel(label2);
18589
18737
  cliLog(`\u2705 \u5DF2\u63A5\u5165 Hub\uFF1A\u8282\u70B9 ${cred.nodeId}\uFF08\u7F51\u5173 ${cred.gatewayUrl ?? "\u672A\u4E0B\u53D1"}\uFF09`);
18590
18738
  cliLog(" \u51ED\u636E\u5DF2\u4FDD\u5B58\u5230 fleet.json\uFF0C\u672C\u6B21\u542F\u52A8\u5373\u8FDE\u63A5 Hub\u3002");
18591
18739
  }
18592
18740
  async function askHidden(rl, prompt) {
18593
18741
  if (!process.stdin.isTTY) return (await rl.question(prompt)).trim();
18594
- return new Promise((resolve19) => {
18742
+ return new Promise((resolve20) => {
18595
18743
  const saved = process.stdin.listeners("data");
18596
18744
  process.stdin.removeAllListeners("data");
18597
18745
  cliWrite(prompt);
@@ -18613,13 +18761,13 @@ async function askHidden(rl, prompt) {
18613
18761
  if (ch === "\r" || ch === "\n") {
18614
18762
  cleanup();
18615
18763
  cliWrite("\n");
18616
- resolve19(buf);
18764
+ resolve20(buf);
18617
18765
  return;
18618
18766
  }
18619
18767
  if (ch === "") {
18620
18768
  cleanup();
18621
18769
  cliWrite("\n");
18622
- resolve19("");
18770
+ resolve20("");
18623
18771
  return;
18624
18772
  }
18625
18773
  if (ch === "\x7F" || ch === "\b") {
@@ -18637,6 +18785,40 @@ async function askHidden(rl, prompt) {
18637
18785
  });
18638
18786
  }
18639
18787
 
18788
+ // src/cli/link.ts
18789
+ init_cjs_shims();
18790
+ var readline2 = __toESM(require("readline"), 1);
18791
+
18792
+ // src/cli/serve-instances.ts
18793
+ init_cjs_shims();
18794
+ var import_node_child_process6 = require("child_process");
18795
+ var fs30 = __toESM(require("fs"), 1);
18796
+ var os10 = __toESM(require("os"), 1);
18797
+ var path35 = __toESM(require("path"), 1);
18798
+
18799
+ // src/cli/link.ts
18800
+ function buildAccountAuth(flags, env3 = process.env) {
18801
+ const username = (flags.username ?? env3.ZQAGENT_HUB_USERNAME ?? "").trim();
18802
+ let email = (flags.email ?? "").trim();
18803
+ let phone = (flags.phone ?? "").trim();
18804
+ if (username && !email && !phone) {
18805
+ if (username.includes("@")) email = username;
18806
+ else phone = username;
18807
+ }
18808
+ if (!email && !phone) return null;
18809
+ const password = flags.password ?? env3.ZQAGENT_HUB_PASSWORD ?? "";
18810
+ const smsCode = (flags.smsCode ?? env3.ZQAGENT_HUB_SMS_CODE ?? "").trim();
18811
+ return {
18812
+ email: email ? email.toLowerCase() : void 0,
18813
+ phone: phone || void 0,
18814
+ password: password || void 0,
18815
+ smsCode: smsCode || void 0
18816
+ };
18817
+ }
18818
+ function isCompleteAccount(account2) {
18819
+ return Boolean(account2 && (account2.password || account2.smsCode));
18820
+ }
18821
+
18640
18822
  // src/server/index.ts
18641
18823
  function arg(name) {
18642
18824
  const i = process.argv.indexOf(`--${name}`);
@@ -18645,13 +18827,22 @@ function arg(name) {
18645
18827
  var hubUrl = (arg("hub") ?? process.env.HUB_URL ?? "").trim();
18646
18828
  var enrollCode = (arg("enroll-code") ?? process.env.HUB_ENROLL_CODE ?? "").trim();
18647
18829
  var label = arg("label")?.trim();
18648
- void maybeAccountEnroll({ dataDir: arg("data-dir"), hubUrl: arg("hub"), label }).finally(() => {
18830
+ var account = buildAccountAuth({
18831
+ username: arg("username") ?? arg("user"),
18832
+ email: arg("email"),
18833
+ phone: arg("phone"),
18834
+ password: arg("password"),
18835
+ smsCode: arg("sms-code")
18836
+ });
18837
+ var autoEnroll = hubUrl && enrollCode ? { hubUrl, code: enrollCode, label } : hubUrl && isCompleteAccount(account) ? { hubUrl, account, label } : null;
18838
+ var beforeStart = autoEnroll ? Promise.resolve() : maybeAccountEnroll({ dataDir: arg("data-dir"), hubUrl: arg("hub"), label });
18839
+ void beforeStart.finally(() => {
18649
18840
  startServer({
18650
18841
  dataDir: arg("data-dir"),
18651
18842
  port: arg("port") ? Number(arg("port")) : void 0,
18652
18843
  host: arg("host"),
18653
- // 仅当两者齐备时启用「启动即接入」;已有 fleet.json 时会在 runtime 内被忽略
18654
- autoEnroll: hubUrl && enrollCode ? { hubUrl, code: enrollCode, label } : null,
18844
+ // 已有 fleet.json 时会在 runtime 内被忽略
18845
+ autoEnroll,
18655
18846
  autoUpdate: true
18656
18847
  });
18657
18848
  });