@zqagent/core 0.2.10 → 0.2.12

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.10",
11416
+ version: "0.2.12",
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.10",
12409
+ version: "0.2.12",
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,7 @@ function createApp(store, manager, opts = {}) {
12776
12776
  ok(res, opts.fleet.status());
12777
12777
  }
12778
12778
  },
12779
- // 运行时热接入:凭一次性注册码接入 Hub(落盘 fleet.json + 立即连接,免重启)
12779
+ // 运行时热接入:凭一次性注册码或 Hub 账号接入(落盘 fleet.json + 立即连接,免重启)
12780
12780
  {
12781
12781
  method: "POST",
12782
12782
  pattern: ["fleet", "enroll"],
@@ -12788,15 +12788,42 @@ function createApp(store, manager, opts = {}) {
12788
12788
  const raw = body ?? {};
12789
12789
  const hubUrl2 = String(raw.hubUrl ?? "").trim().replace(/\/$/, "");
12790
12790
  const code = String(raw.code ?? "").trim();
12791
- if (!hubUrl2 || !code) {
12792
- throw new ApiError(400, "bad_request", "hubUrl \u4E0E code \u5FC5\u586B");
12791
+ const email = String(raw.email ?? "").trim();
12792
+ const phone = String(raw.phone ?? "").trim();
12793
+ const password = String(raw.password ?? "");
12794
+ const smsCode = String(raw.smsCode ?? "").trim();
12795
+ const hasAccount = Boolean(email || phone);
12796
+ if (!hubUrl2) {
12797
+ throw new ApiError(400, "bad_request", "hubUrl \u5FC5\u586B");
12798
+ }
12799
+ if (code && hasAccount) {
12800
+ throw new ApiError(400, "bad_request", "code \u4E0E\u8D26\u53F7\u51ED\u636E\u53EA\u80FD\u4E8C\u9009\u4E00");
12801
+ }
12802
+ if (!code && !hasAccount) {
12803
+ throw new ApiError(400, "bad_request", "\u9700\u8981 code\uFF0C\u6216 email/phone + password/smsCode");
12804
+ }
12805
+ if (hasAccount && !password && !smsCode) {
12806
+ throw new ApiError(400, "bad_request", "\u8D26\u53F7\u63A5\u5165\u9700\u8981 password \u6216 smsCode");
12793
12807
  }
12794
12808
  const label2 = typeof raw.label === "string" ? raw.label.trim() : void 0;
12795
12809
  try {
12796
- ok(res, await opts.fleet.enroll({ hubUrl: hubUrl2, code, label: label2 }));
12810
+ ok(
12811
+ res,
12812
+ await opts.fleet.enroll({
12813
+ hubUrl: hubUrl2,
12814
+ code: code || void 0,
12815
+ account: hasAccount ? {
12816
+ email: email || void 0,
12817
+ phone: phone || void 0,
12818
+ password: password || void 0,
12819
+ smsCode: smsCode || void 0
12820
+ } : void 0,
12821
+ label: label2
12822
+ })
12823
+ );
12797
12824
  } catch (e) {
12798
12825
  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;
12826
+ 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
12827
  const msg = e instanceof Error ? e.message : String(e);
12801
12828
  throw new ApiError(
12802
12829
  status,
@@ -13942,10 +13969,10 @@ function createApp(store, manager, opts = {}) {
13942
13969
  function handle(req2, res) {
13943
13970
  const startedAt = Date.now();
13944
13971
  const url = new URL(req2.url ?? "/", "http://localhost");
13945
- const path35 = url.pathname;
13972
+ const path36 = url.pathname;
13946
13973
  const method = req2.method ?? "GET";
13947
13974
  console.log(
13948
- `[api] ${(/* @__PURE__ */ new Date()).toISOString()} \u2192 ${method} ${path35}${url.search}`
13975
+ `[api] ${(/* @__PURE__ */ new Date()).toISOString()} \u2192 ${method} ${path36}${url.search}`
13949
13976
  );
13950
13977
  let tenantId = null;
13951
13978
  let logged = false;
@@ -13953,7 +13980,7 @@ function createApp(store, manager, opts = {}) {
13953
13980
  if (logged) return;
13954
13981
  logged = true;
13955
13982
  console.log(
13956
- `[api] ${(/* @__PURE__ */ new Date()).toISOString()} \u2190 ${method} ${path35} ${extra} (${Date.now() - startedAt}ms) tenant=${tenantId ?? "-"}`
13983
+ `[api] ${(/* @__PURE__ */ new Date()).toISOString()} \u2190 ${method} ${path36} ${extra} (${Date.now() - startedAt}ms) tenant=${tenantId ?? "-"}`
13957
13984
  );
13958
13985
  };
13959
13986
  res.on("finish", () => logDone(`HTTP ${res.statusCode}`));
@@ -13964,16 +13991,16 @@ function createApp(store, manager, opts = {}) {
13964
13991
  res.end();
13965
13992
  return;
13966
13993
  }
13967
- if (req2.method === "GET" && path35 === "/healthz") {
13994
+ if (req2.method === "GET" && path36 === "/healthz") {
13968
13995
  json(res, 200, {
13969
13996
  status: "ok",
13970
13997
  // 版本让运维/探针能确认线上跑的是哪个构建(更新与回滚据此判断)
13971
- version: "0.2.10",
13998
+ version: "0.2.12",
13972
13999
  features: { mcp: hasServerMcpConfig() }
13973
14000
  });
13974
14001
  return;
13975
14002
  }
13976
- if (hubProxyEnabled(opts.host) && isHubProxyPath(path35)) {
14003
+ if (hubProxyEnabled(opts.host) && isHubProxyPath(path36)) {
13977
14004
  void handleHubProxy(req2, res).catch(() => {
13978
14005
  if (!res.headersSent) {
13979
14006
  res.writeHead(502, { "Content-Type": "application/json; charset=utf-8" });
@@ -13984,11 +14011,11 @@ function createApp(store, manager, opts = {}) {
13984
14011
  });
13985
14012
  return;
13986
14013
  }
13987
- if (!path35.startsWith(API_PREFIX)) {
14014
+ if (!path36.startsWith(API_PREFIX)) {
13988
14015
  json(res, 404, { error: { code: "not_found", message: "\u672A\u77E5\u8DEF\u5F84" } });
13989
14016
  return;
13990
14017
  }
13991
- const segs = path35.slice(API_PREFIX.length).split("/").filter(Boolean);
14018
+ const segs = path36.slice(API_PREFIX.length).split("/").filter(Boolean);
13992
14019
  const apiKey = extractApiKey(req2);
13993
14020
  if (!apiKey) {
13994
14021
  json(res, 401, {
@@ -14053,7 +14080,7 @@ function createApp(store, manager, opts = {}) {
14053
14080
  ).catch((err) => {
14054
14081
  const msg = err instanceof Error ? err.message : String(err);
14055
14082
  console.log(
14056
- `[api] ${(/* @__PURE__ */ new Date()).toISOString()} ! ${method} ${path35} ERROR: ${msg}`
14083
+ `[api] ${(/* @__PURE__ */ new Date()).toISOString()} ! ${method} ${path36} ERROR: ${msg}`
14057
14084
  );
14058
14085
  error(res, err);
14059
14086
  });
@@ -14084,8 +14111,8 @@ async function cachedFetchModels(baseURL, apiKey) {
14084
14111
  try {
14085
14112
  result = await Promise.race([
14086
14113
  fetchModels(baseURL, apiKey),
14087
- new Promise((resolve19) => {
14088
- const t = setTimeout(() => resolve19(null), MODEL_FETCH_TIMEOUT_MS);
14114
+ new Promise((resolve20) => {
14115
+ const t = setTimeout(() => resolve20(null), MODEL_FETCH_TIMEOUT_MS);
14089
14116
  t.unref?.();
14090
14117
  })
14091
14118
  ]);
@@ -14110,8 +14137,8 @@ async function cachedFetchModelsEnriched(baseURL, apiKey, preferred) {
14110
14137
  if (!target) return r;
14111
14138
  const ctx = await Promise.race([
14112
14139
  fetchModelContext(baseURL, apiKey, target),
14113
- new Promise((resolve19) => {
14114
- const t = setTimeout(() => resolve19(void 0), MODEL_FETCH_TIMEOUT_MS);
14140
+ new Promise((resolve20) => {
14141
+ const t = setTimeout(() => resolve20(void 0), MODEL_FETCH_TIMEOUT_MS);
14115
14142
  t.unref?.();
14116
14143
  })
14117
14144
  ]);
@@ -15305,13 +15332,13 @@ var EVENT_FLUSH_MAX_EVENTS = 60;
15305
15332
  var EVENT_FLUSH_MAX_BYTES = 200 * 1024;
15306
15333
  var LOOP_LAG_WARN_MS = 2e3;
15307
15334
  function withTimeout(p, ms) {
15308
- return new Promise((resolve19, reject) => {
15335
+ return new Promise((resolve20, reject) => {
15309
15336
  const timer = setTimeout(() => reject(new Error(`\u5B50\u6307\u4EE4\u8D85\u65F6\uFF08${ms}ms\uFF09`)), ms);
15310
15337
  timer.unref?.();
15311
15338
  p.then(
15312
15339
  (v) => {
15313
15340
  clearTimeout(timer);
15314
- resolve19(v);
15341
+ resolve20(v);
15315
15342
  },
15316
15343
  (e) => {
15317
15344
  clearTimeout(timer);
@@ -15671,7 +15698,7 @@ var FleetNodeBridge = class {
15671
15698
  label: this.opts.deps.store.loadNodeLabel() ?? void 0,
15672
15699
  platform: process.platform,
15673
15700
  mode: process.env.NODE_MODE ?? "standalone",
15674
- version: "0.2.10",
15701
+ version: "0.2.12",
15675
15702
  ip: primaryIp()
15676
15703
  };
15677
15704
  }
@@ -15726,7 +15753,7 @@ var FleetNodeBridge = class {
15726
15753
  label: this.opts.deps.store.loadNodeLabel() ?? void 0,
15727
15754
  platform: process.platform,
15728
15755
  mode: process.env.NODE_MODE ?? "standalone",
15729
- version: "0.2.10",
15756
+ version: "0.2.12",
15730
15757
  ip: primaryIp(),
15731
15758
  projects,
15732
15759
  totals,
@@ -17141,13 +17168,13 @@ var baseUrlResolver = null;
17141
17168
  function resolveBase(baseUrl) {
17142
17169
  return baseUrlResolver ? baseUrlResolver(baseUrl) : baseUrl;
17143
17170
  }
17144
- async function req(baseUrl, token, path35, init = {}) {
17171
+ async function req(baseUrl, token, path36, init = {}) {
17145
17172
  const headers = {
17146
17173
  ...init.body ? { "Content-Type": "application/json" } : {},
17147
17174
  ...init.headers ?? {}
17148
17175
  };
17149
17176
  if (token) headers.Authorization = `Bearer ${token}`;
17150
- const res = await fetch(`${resolveBase(baseUrl).replace(/\/$/, "")}${path35}`, {
17177
+ const res = await fetch(`${resolveBase(baseUrl).replace(/\/$/, "")}${path36}`, {
17151
17178
  ...init,
17152
17179
  headers
17153
17180
  });
@@ -17450,7 +17477,7 @@ var path29 = __toESM(require("path"), 1);
17450
17477
  var import_node_child_process5 = require("child_process");
17451
17478
  var import_node_module3 = require("module");
17452
17479
  function currentVersion() {
17453
- const injected = "0.2.10"?.trim();
17480
+ const injected = "0.2.12"?.trim();
17454
17481
  if (injected) return injected;
17455
17482
  try {
17456
17483
  const req2 = (0, import_node_module3.createRequire)(importMetaUrl);
@@ -17977,11 +18004,11 @@ var UpdateController = class {
17977
18004
  const minUptime = num("ZQAGENT_UPDATE_MIN_UPTIME_MS", 10 * 60 * 1e3);
17978
18005
  const idleMs = num("ZQAGENT_UPDATE_IDLE_MS", 60 * 1e3);
17979
18006
  let idleSince = null;
17980
- return new Promise((resolve19) => {
18007
+ return new Promise((resolve20) => {
17981
18008
  const timer = setInterval(() => {
17982
18009
  if (this.stopped) {
17983
18010
  clearInterval(timer);
17984
- resolve19(false);
18011
+ resolve20(false);
17985
18012
  return;
17986
18013
  }
17987
18014
  if (Date.now() - this.startedAt < minUptime || !this.opts.isIdle()) {
@@ -17991,7 +18018,7 @@ var UpdateController = class {
17991
18018
  idleSince ??= Date.now();
17992
18019
  if (Date.now() - idleSince >= idleMs) {
17993
18020
  clearInterval(timer);
17994
- resolve19(true);
18021
+ resolve20(true);
17995
18022
  }
17996
18023
  }, 1e3);
17997
18024
  timer.unref();
@@ -18174,7 +18201,7 @@ function exitWhenOrphaned() {
18174
18201
  }
18175
18202
  var PORT_FALLBACK_LIMIT = 20;
18176
18203
  function listenWithPortFallback(server, startPort, host, dataDir, limit = PORT_FALLBACK_LIMIT) {
18177
- return new Promise((resolve19, reject) => {
18204
+ return new Promise((resolve20, reject) => {
18178
18205
  let attempts = 0;
18179
18206
  const tryListen = (port) => {
18180
18207
  server.removeAllListeners("listening");
@@ -18206,7 +18233,7 @@ function listenWithPortFallback(server, startPort, host, dataDir, limit = PORT_F
18206
18233
  `);
18207
18234
  } catch {
18208
18235
  }
18209
- resolve19(actualPort);
18236
+ resolve20(actualPort);
18210
18237
  });
18211
18238
  };
18212
18239
  tryListen(startPort);
@@ -18293,7 +18320,14 @@ function startServer(opts = {}) {
18293
18320
  status: fleetStatus,
18294
18321
  async enroll(input) {
18295
18322
  const nodeId = ensureNodeId(store);
18296
- const cred = await hubEnrollByCode(input.hubUrl, {
18323
+ const cred = input.account ? await hubEnrollByAccount(input.hubUrl, {
18324
+ email: input.account.email,
18325
+ phone: input.account.phone,
18326
+ password: input.account.password,
18327
+ code: input.account.smsCode,
18328
+ nodeId,
18329
+ label: input.label
18330
+ }) : await hubEnrollByCode(input.hubUrl, {
18297
18331
  code: input.code,
18298
18332
  nodeId,
18299
18333
  label: input.label
@@ -18437,7 +18471,7 @@ function startServer(opts = {}) {
18437
18471
  server.timeout = 0;
18438
18472
  server.keepAliveTimeout = 65e3;
18439
18473
  server.headersTimeout = 66e3;
18440
- const ready = new Promise((resolve19, reject) => {
18474
+ const ready = new Promise((resolve20, reject) => {
18441
18475
  listenWithPortFallback(server, port, host, dataDir).then((actualPort) => {
18442
18476
  const info = {
18443
18477
  host,
@@ -18454,7 +18488,7 @@ function startServer(opts = {}) {
18454
18488
  printReady(info, qq);
18455
18489
  }
18456
18490
  updater?.start();
18457
- resolve19(info);
18491
+ resolve20(info);
18458
18492
  }, reject);
18459
18493
  });
18460
18494
  return {
@@ -18504,39 +18538,12 @@ function parseHubAnswer(answer, fallback) {
18504
18538
  if (SKIP_ANSWERS.has(a.toLowerCase())) return null;
18505
18539
  return (a || fallback).replace(/\/$/, "");
18506
18540
  }
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);
18541
+ async function promptHubUrl(rl, hubUrl2) {
18542
+ const fallback = resolveDefaultHub(hubUrl2);
18534
18543
  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
- }
18544
+ return parseHubAnswer(answer, fallback);
18545
+ }
18546
+ async function promptAccountLogin(rl, hubUrl2) {
18540
18547
  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
18548
  const mode = (await rl.question("\u8BF7\u9009\u62E9 [1]\uFF1A")).trim() || "1";
18542
18549
  const input = {};
@@ -18545,42 +18552,94 @@ async function runWizard(rl, store, opts) {
18545
18552
  input.password = await askHidden(rl, "\u5BC6\u7801\uFF1A");
18546
18553
  if (!input.email || !input.password) {
18547
18554
  cliErr("\u90AE\u7BB1\u4E0E\u5BC6\u7801\u4E0D\u80FD\u4E3A\u7A7A\uFF0C\u5DF2\u8DF3\u8FC7\u63A5\u5165\u3002");
18548
- return;
18555
+ return null;
18549
18556
  }
18550
18557
  } else if (mode === "2") {
18551
18558
  input.phone = (await rl.question("\u624B\u673A\u53F7\uFF1A")).trim();
18552
18559
  input.password = await askHidden(rl, "\u5BC6\u7801\uFF1A");
18553
18560
  if (!input.phone || !input.password) {
18554
18561
  cliErr("\u624B\u673A\u53F7\u4E0E\u5BC6\u7801\u4E0D\u80FD\u4E3A\u7A7A\uFF0C\u5DF2\u8DF3\u8FC7\u63A5\u5165\u3002");
18555
- return;
18562
+ return null;
18556
18563
  }
18557
18564
  } else if (mode === "3") {
18558
18565
  input.phone = (await rl.question("\u624B\u673A\u53F7\uFF1A")).trim();
18559
18566
  if (!input.phone) {
18560
18567
  cliErr("\u624B\u673A\u53F7\u4E0D\u80FD\u4E3A\u7A7A\uFF0C\u5DF2\u8DF3\u8FC7\u63A5\u5165\u3002");
18561
- return;
18568
+ return null;
18562
18569
  }
18563
18570
  try {
18564
- const sent = await hubSendSms(hubUrl2, { phone: input.phone, purpose: "login" });
18571
+ const sent = await hubSendSms(resolveDefaultHub(hubUrl2), {
18572
+ phone: input.phone,
18573
+ purpose: "login"
18574
+ });
18565
18575
  if (sent.debugCode) cliLog(`\uFF08\u8C03\u8BD5\u6A21\u5F0F\u9A8C\u8BC1\u7801\uFF1A${sent.debugCode}\uFF09`);
18566
18576
  else cliLog("\u9A8C\u8BC1\u7801\u5DF2\u53D1\u9001\uFF0C5 \u5206\u949F\u5185\u6709\u6548\u3002");
18567
18577
  } catch (e) {
18568
18578
  cliErr(`\u77ED\u4FE1\u9A8C\u8BC1\u7801\u53D1\u9001\u5931\u8D25\uFF1A${e instanceof Error ? e.message : String(e)}`);
18569
18579
  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
18580
  cliLog(" zqagent link --hub <Hub\u5730\u5740> --code <\u63A5\u5165\u7801>");
18571
- return;
18581
+ return null;
18572
18582
  }
18573
18583
  input.code = (await rl.question("\u77ED\u4FE1\u9A8C\u8BC1\u7801\uFF1A")).trim();
18574
18584
  if (!input.code) {
18575
18585
  cliErr("\u9A8C\u8BC1\u7801\u4E0D\u80FD\u4E3A\u7A7A\uFF0C\u5DF2\u8DF3\u8FC7\u63A5\u5165\u3002");
18576
- return;
18586
+ return null;
18577
18587
  }
18578
18588
  } else {
18579
18589
  cliErr("\u672A\u77E5\u7684\u767B\u5F55\u65B9\u5F0F\uFF0C\u5DF2\u8DF3\u8FC7\u63A5\u5165\u3002");
18590
+ return null;
18591
+ }
18592
+ return input;
18593
+ }
18594
+ async function promptLinkAccount(rl, hubUrl2, opts = {}) {
18595
+ const fallback = resolveDefaultHub(hubUrl2);
18596
+ let resolved = fallback;
18597
+ if (opts.askHub !== false) {
18598
+ const answer = await promptHubUrl(rl, fallback);
18599
+ if (!answer) {
18600
+ cliLog("\u5DF2\u8DF3\u8FC7\u63A5\u5165\uFF1A\u8282\u70B9\u4FDD\u6301\u7EAF\u672C\u5730\u8FD0\u884C\u3002");
18601
+ return null;
18602
+ }
18603
+ resolved = answer;
18604
+ }
18605
+ const auth = await promptAccountLogin(rl, resolved);
18606
+ if (!auth) return null;
18607
+ return { hubUrl: resolved, auth };
18608
+ }
18609
+ function resolveDataDir(dataDir) {
18610
+ return path34.resolve(dataDir ?? process.env.DATA_DIR ?? DEFAULT_DATA_DIR);
18611
+ }
18612
+ async function maybeAccountEnroll(opts = {}) {
18613
+ if (!process.stdin.isTTY || !process.stdout.isTTY) return;
18614
+ let store;
18615
+ try {
18616
+ store = new Store(resolveDataDir(opts.dataDir));
18617
+ if (resolveFleetConfig(store)) return;
18618
+ } catch (e) {
18619
+ cliErr(`\u63A5\u5165\u68C0\u67E5\u5931\u8D25\uFF1A${e instanceof Error ? e.message : String(e)}`);
18580
18620
  return;
18581
18621
  }
18622
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
18623
+ try {
18624
+ await runWizard(rl, store, opts);
18625
+ } catch (e) {
18626
+ cliErr(`\u63A5\u5165\u5931\u8D25\uFF1A${e instanceof Error ? e.message : String(e)}`);
18627
+ 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>");
18628
+ } finally {
18629
+ rl.close();
18630
+ }
18631
+ }
18632
+ async function runWizard(rl, store, opts) {
18633
+ cliLog("");
18634
+ 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");
18635
+ const prompted = await promptLinkAccount(rl, opts.hubUrl);
18636
+ if (!prompted) return;
18582
18637
  const nodeId = ensureNodeId(store);
18583
- const cred = await hubEnrollByAccount(hubUrl2, { ...input, nodeId, label: opts.label });
18638
+ const cred = await hubEnrollByAccount(prompted.hubUrl, {
18639
+ ...prompted.auth,
18640
+ nodeId,
18641
+ label: opts.label
18642
+ });
18584
18643
  store.saveFleetCredential({
18585
18644
  ...cred,
18586
18645
  label: opts.label ?? cred.label,
@@ -18591,7 +18650,7 @@ async function runWizard(rl, store, opts) {
18591
18650
  }
18592
18651
  async function askHidden(rl, prompt) {
18593
18652
  if (!process.stdin.isTTY) return (await rl.question(prompt)).trim();
18594
- return new Promise((resolve19) => {
18653
+ return new Promise((resolve20) => {
18595
18654
  const saved = process.stdin.listeners("data");
18596
18655
  process.stdin.removeAllListeners("data");
18597
18656
  cliWrite(prompt);
@@ -18613,13 +18672,13 @@ async function askHidden(rl, prompt) {
18613
18672
  if (ch === "\r" || ch === "\n") {
18614
18673
  cleanup();
18615
18674
  cliWrite("\n");
18616
- resolve19(buf);
18675
+ resolve20(buf);
18617
18676
  return;
18618
18677
  }
18619
18678
  if (ch === "") {
18620
18679
  cleanup();
18621
18680
  cliWrite("\n");
18622
- resolve19("");
18681
+ resolve20("");
18623
18682
  return;
18624
18683
  }
18625
18684
  if (ch === "\x7F" || ch === "\b") {
@@ -18637,6 +18696,40 @@ async function askHidden(rl, prompt) {
18637
18696
  });
18638
18697
  }
18639
18698
 
18699
+ // src/cli/link.ts
18700
+ init_cjs_shims();
18701
+ var readline2 = __toESM(require("readline"), 1);
18702
+
18703
+ // src/cli/serve-instances.ts
18704
+ init_cjs_shims();
18705
+ var import_node_child_process6 = require("child_process");
18706
+ var fs30 = __toESM(require("fs"), 1);
18707
+ var os9 = __toESM(require("os"), 1);
18708
+ var path35 = __toESM(require("path"), 1);
18709
+
18710
+ // src/cli/link.ts
18711
+ function buildAccountAuth(flags, env3 = process.env) {
18712
+ const username = (flags.username ?? env3.ZQAGENT_HUB_USERNAME ?? "").trim();
18713
+ let email = (flags.email ?? "").trim();
18714
+ let phone = (flags.phone ?? "").trim();
18715
+ if (username && !email && !phone) {
18716
+ if (username.includes("@")) email = username;
18717
+ else phone = username;
18718
+ }
18719
+ if (!email && !phone) return null;
18720
+ const password = flags.password ?? env3.ZQAGENT_HUB_PASSWORD ?? "";
18721
+ const smsCode = (flags.smsCode ?? env3.ZQAGENT_HUB_SMS_CODE ?? "").trim();
18722
+ return {
18723
+ email: email ? email.toLowerCase() : void 0,
18724
+ phone: phone || void 0,
18725
+ password: password || void 0,
18726
+ smsCode: smsCode || void 0
18727
+ };
18728
+ }
18729
+ function isCompleteAccount(account2) {
18730
+ return Boolean(account2 && (account2.password || account2.smsCode));
18731
+ }
18732
+
18640
18733
  // src/server/index.ts
18641
18734
  function arg(name) {
18642
18735
  const i = process.argv.indexOf(`--${name}`);
@@ -18645,13 +18738,22 @@ function arg(name) {
18645
18738
  var hubUrl = (arg("hub") ?? process.env.HUB_URL ?? "").trim();
18646
18739
  var enrollCode = (arg("enroll-code") ?? process.env.HUB_ENROLL_CODE ?? "").trim();
18647
18740
  var label = arg("label")?.trim();
18648
- void maybeAccountEnroll({ dataDir: arg("data-dir"), hubUrl: arg("hub"), label }).finally(() => {
18741
+ var account = buildAccountAuth({
18742
+ username: arg("username") ?? arg("user"),
18743
+ email: arg("email"),
18744
+ phone: arg("phone"),
18745
+ password: arg("password"),
18746
+ smsCode: arg("sms-code")
18747
+ });
18748
+ var autoEnroll = hubUrl && enrollCode ? { hubUrl, code: enrollCode, label } : hubUrl && isCompleteAccount(account) ? { hubUrl, account, label } : null;
18749
+ var beforeStart = autoEnroll ? Promise.resolve() : maybeAccountEnroll({ dataDir: arg("data-dir"), hubUrl: arg("hub"), label });
18750
+ void beforeStart.finally(() => {
18649
18751
  startServer({
18650
18752
  dataDir: arg("data-dir"),
18651
18753
  port: arg("port") ? Number(arg("port")) : void 0,
18652
18754
  host: arg("host"),
18653
- // 仅当两者齐备时启用「启动即接入」;已有 fleet.json 时会在 runtime 内被忽略
18654
- autoEnroll: hubUrl && enrollCode ? { hubUrl, code: enrollCode, label } : null,
18755
+ // 已有 fleet.json 时会在 runtime 内被忽略
18756
+ autoEnroll,
18655
18757
  autoUpdate: true
18656
18758
  });
18657
18759
  });