@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.
@@ -2180,12 +2180,12 @@ var MUTATING_TOOLS = /* @__PURE__ */ new Set([
2180
2180
  ]);
2181
2181
  function parseReadFileSpan(content) {
2182
2182
  const body = content.replace(/^\[tool output truncated:[^\n]*\]\n\n/, "");
2183
- let path36;
2183
+ let path37;
2184
2184
  let start;
2185
2185
  let end;
2186
2186
  try {
2187
2187
  const obj = JSON.parse(body);
2188
- path36 = obj.path;
2188
+ path37 = obj.path;
2189
2189
  start = obj.start_line;
2190
2190
  end = obj.end_line;
2191
2191
  } catch {
@@ -2194,14 +2194,14 @@ function parseReadFileSpan(content) {
2194
2194
  const m = new RegExp(`"${key}"\\s*:\\s*(\\d+)`).exec(body);
2195
2195
  return m ? Number(m[1]) : void 0;
2196
2196
  };
2197
- path36 = str2("path");
2197
+ path37 = str2("path");
2198
2198
  start = num2("start_line");
2199
2199
  end = num2("end_line");
2200
2200
  }
2201
- if (typeof path36 !== "string" || !path36) return null;
2201
+ if (typeof path37 !== "string" || !path37) return null;
2202
2202
  if (typeof start !== "number" || typeof end !== "number") return null;
2203
2203
  if (!Number.isFinite(start) || !Number.isFinite(end)) return null;
2204
- return { path: path36, start, end };
2204
+ return { path: path37, start, end };
2205
2205
  }
2206
2206
  function addSpan(spans, start, end) {
2207
2207
  spans.push([start, end]);
@@ -3818,9 +3818,9 @@ var TurnEngine = class _TurnEngine {
3818
3818
  return;
3819
3819
  }
3820
3820
  if (result && typeof result === "object") {
3821
- const path36 = result.path;
3822
- if (path36) {
3823
- this._producedFiles.push(path36);
3821
+ const path37 = result.path;
3822
+ if (path37) {
3823
+ this._producedFiles.push(path37);
3824
3824
  return;
3825
3825
  }
3826
3826
  const changed = result.changed_files;
@@ -5147,10 +5147,10 @@ var OpenAIProvider = class {
5147
5147
  let timer;
5148
5148
  try {
5149
5149
  for (; ; ) {
5150
- const idle = new Promise((resolve19) => {
5150
+ const idle = new Promise((resolve20) => {
5151
5151
  timer = setTimeout(() => {
5152
5152
  onIdle();
5153
- resolve19({ timedOut: true });
5153
+ resolve20({ timedOut: true });
5154
5154
  }, idleMs);
5155
5155
  });
5156
5156
  const next = iter.next();
@@ -5778,12 +5778,12 @@ function makeSink(maxBuffer) {
5778
5778
  };
5779
5779
  }
5780
5780
  function execAsync(file, argv, opts = {}) {
5781
- return new Promise((resolve19) => {
5781
+ return new Promise((resolve20) => {
5782
5782
  const maxBuffer = opts.maxBuffer ?? DEFAULT_MAX_BUFFER;
5783
5783
  const out = makeSink(maxBuffer);
5784
5784
  const err = makeSink(maxBuffer);
5785
5785
  if (opts.signal?.aborted) {
5786
- resolve19({
5786
+ resolve20({
5787
5787
  status: null,
5788
5788
  stdout: Buffer.alloc(0),
5789
5789
  stderr: Buffer.alloc(0),
@@ -5804,7 +5804,7 @@ function execAsync(file, argv, opts = {}) {
5804
5804
  windowsHide: true
5805
5805
  });
5806
5806
  } catch (e) {
5807
- resolve19({
5807
+ resolve20({
5808
5808
  status: null,
5809
5809
  stdout: Buffer.alloc(0),
5810
5810
  stderr: Buffer.alloc(0),
@@ -5841,7 +5841,7 @@ function execAsync(file, argv, opts = {}) {
5841
5841
  };
5842
5842
  if (aborted) result.aborted = true;
5843
5843
  if (spawnError) result.error = spawnError;
5844
- resolve19(result);
5844
+ resolve20(result);
5845
5845
  };
5846
5846
  const killAndSettle = () => {
5847
5847
  killTree(child.pid);
@@ -7736,18 +7736,18 @@ function makeApplyPatch(workspace) {
7736
7736
  return { changed_files: changedFiles, added_files: addedFiles, deleted_files: deletedFiles, file_count: fileCount };
7737
7737
  };
7738
7738
  }
7739
- function applyPatchHunks(oldLines, chunks, path36) {
7739
+ function applyPatchHunks(oldLines, chunks, path37) {
7740
7740
  let newLines = [...oldLines];
7741
7741
  let cursor = 0;
7742
7742
  for (const chunk of chunks) {
7743
7743
  const oldBlock = chunk.filter((l) => l[0] === " " || l[0] === "-").map((l) => l.slice(1));
7744
7744
  const newBlock = chunk.filter((l) => l[0] === " " || l[0] === "+").map((l) => l.slice(1));
7745
7745
  if (!oldBlock.length) {
7746
- throw new Error(`\u8865\u4E01 hunk \u5FC5\u987B\u5305\u542B\u4E0A\u4E0B\u6587\u6216\u5220\u9664\u884C: ${path36}`);
7746
+ throw new Error(`\u8865\u4E01 hunk \u5FC5\u987B\u5305\u542B\u4E0A\u4E0B\u6587\u6216\u5220\u9664\u884C: ${path37}`);
7747
7747
  }
7748
7748
  const matchStart = findBlockMatch(newLines, oldBlock, cursor);
7749
7749
  if (matchStart === -1) {
7750
- throw new Error(`\u8865\u4E01\u4E0A\u4E0B\u6587\u4E0D\u5339\u914D: ${path36}`);
7750
+ throw new Error(`\u8865\u4E01\u4E0A\u4E0B\u6587\u4E0D\u5339\u914D: ${path37}`);
7751
7751
  }
7752
7752
  const matchEnd = matchStart + oldBlock.length;
7753
7753
  newLines.splice(matchStart, oldBlock.length, ...newBlock);
@@ -9840,11 +9840,11 @@ function isAffirmative(answer) {
9840
9840
  return /^(yes|approve|同意|批准|允许|确定|可以|好的|确认)/.test(a);
9841
9841
  }
9842
9842
  function defer() {
9843
- let resolve19;
9843
+ let resolve20;
9844
9844
  const promise = new Promise((r) => {
9845
- resolve19 = r;
9845
+ resolve20 = r;
9846
9846
  });
9847
- return { promise, resolve: resolve19 };
9847
+ return { promise, resolve: resolve20 };
9848
9848
  }
9849
9849
  var SessionManager = class {
9850
9850
  constructor(store, approvalTimeoutMs = APPROVAL_TIMEOUT_MS, opts = {}) {
@@ -10416,11 +10416,11 @@ data: ${JSON.stringify({ sessionId, seq: entry.seq, ts: entry.ts, data: entry.da
10416
10416
  status: "pending",
10417
10417
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
10418
10418
  };
10419
- const { promise, resolve: resolve19 } = defer();
10419
+ const { promise, resolve: resolve20 } = defer();
10420
10420
  const timer = setTimeout(() => {
10421
10421
  this._recycleApproval(rt, id);
10422
10422
  }, this.approvalTimeoutMs);
10423
- rt.pendingApprovals.set(id, { promise, resolve: resolve19, record, timer });
10423
+ rt.pendingApprovals.set(id, { promise, resolve: resolve20, record, timer });
10424
10424
  rt.approvals.set(id, record);
10425
10425
  this._setStatus(rt, "waiting_approval");
10426
10426
  this._persist(rt);
@@ -10498,11 +10498,11 @@ data: ${JSON.stringify({ sessionId, seq: entry.seq, ts: entry.ts, data: entry.da
10498
10498
  status: "pending",
10499
10499
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
10500
10500
  };
10501
- const { promise, resolve: resolve19 } = defer();
10501
+ const { promise, resolve: resolve20 } = defer();
10502
10502
  const timer = setTimeout(() => {
10503
10503
  this._recycleQuestion(rt, qid);
10504
10504
  }, this.approvalTimeoutMs);
10505
- rt.pendingQuestions.set(qid, { promise, resolve: resolve19, record, timer });
10505
+ rt.pendingQuestions.set(qid, { promise, resolve: resolve20, record, timer });
10506
10506
  rt.questions.set(qid, record);
10507
10507
  this._setStatus(rt, "waiting_question");
10508
10508
  this._persist(rt);
@@ -10811,7 +10811,7 @@ data: ${JSON.stringify(entry.data)}
10811
10811
  if (rt.mcpReady) {
10812
10812
  await Promise.race([
10813
10813
  rt.mcpReady,
10814
- new Promise((resolve19) => setTimeout(resolve19, 15e3))
10814
+ new Promise((resolve20) => setTimeout(resolve20, 15e3))
10815
10815
  ]).catch(() => void 0);
10816
10816
  }
10817
10817
  for await (const event of gen) {
@@ -11396,7 +11396,7 @@ function buildNodeInfo(store, opts) {
11396
11396
  nodeId: opts.nodeId ?? ensureNodeId(store),
11397
11397
  platform: process.platform,
11398
11398
  mode: process.env.NODE_MODE ?? "standalone",
11399
- version: "0.2.10",
11399
+ version: "0.2.12",
11400
11400
  admin: opts.admin,
11401
11401
  projects: opts.projects
11402
11402
  };
@@ -11480,8 +11480,8 @@ function hubProxyEnabled(host) {
11480
11480
  const h = (host ?? "127.0.0.1").trim();
11481
11481
  return h === "127.0.0.1" || h === "localhost" || h === "::1";
11482
11482
  }
11483
- function isHubProxyPath(path36) {
11484
- return path36.startsWith(HUB_PROXY_PREFIX);
11483
+ function isHubProxyPath(path37) {
11484
+ return path37.startsWith(HUB_PROXY_PREFIX);
11485
11485
  }
11486
11486
  function decodeTarget(enc) {
11487
11487
  try {
@@ -12389,7 +12389,7 @@ function buildNodeHost(store, manager, diskPath) {
12389
12389
  arch: process.arch,
12390
12390
  release: os6.release(),
12391
12391
  uptimeSec: Math.round(os6.uptime()),
12392
- version: "0.2.10",
12392
+ version: "0.2.12",
12393
12393
  mode: process.env.NODE_MODE ?? "standalone",
12394
12394
  cpu: {
12395
12395
  count: cpus2.length,
@@ -12433,7 +12433,7 @@ function saveNotifications(tenant, secretBox, notifications) {
12433
12433
  var API_PREFIX = "/api/v1";
12434
12434
  var MAX_BODY_BYTES = 10 * 1024 * 1024;
12435
12435
  function readBody(req2) {
12436
- return new Promise((resolve19, reject) => {
12436
+ return new Promise((resolve20, reject) => {
12437
12437
  const chunks = [];
12438
12438
  let size = 0;
12439
12439
  req2.on("data", (c) => {
@@ -12446,9 +12446,9 @@ function readBody(req2) {
12446
12446
  chunks.push(c);
12447
12447
  });
12448
12448
  req2.on("end", () => {
12449
- if (chunks.length === 0) return resolve19(void 0);
12449
+ if (chunks.length === 0) return resolve20(void 0);
12450
12450
  try {
12451
- resolve19(JSON.parse(Buffer.concat(chunks).toString("utf-8")));
12451
+ resolve20(JSON.parse(Buffer.concat(chunks).toString("utf-8")));
12452
12452
  } catch {
12453
12453
  reject(new ApiError(400, "bad_request", "\u8BF7\u6C42\u4F53\u4E0D\u662F\u5408\u6CD5 JSON"));
12454
12454
  }
@@ -12759,7 +12759,7 @@ function createApp(store, manager, opts = {}) {
12759
12759
  ok(res, opts.fleet.status());
12760
12760
  }
12761
12761
  },
12762
- // 运行时热接入:凭一次性注册码接入 Hub(落盘 fleet.json + 立即连接,免重启)
12762
+ // 运行时热接入:凭一次性注册码或 Hub 账号接入(落盘 fleet.json + 立即连接,免重启)
12763
12763
  {
12764
12764
  method: "POST",
12765
12765
  pattern: ["fleet", "enroll"],
@@ -12771,15 +12771,42 @@ function createApp(store, manager, opts = {}) {
12771
12771
  const raw = body ?? {};
12772
12772
  const hubUrl2 = String(raw.hubUrl ?? "").trim().replace(/\/$/, "");
12773
12773
  const code = String(raw.code ?? "").trim();
12774
- if (!hubUrl2 || !code) {
12775
- throw new ApiError(400, "bad_request", "hubUrl \u4E0E code \u5FC5\u586B");
12774
+ const email = String(raw.email ?? "").trim();
12775
+ const phone = String(raw.phone ?? "").trim();
12776
+ const password = String(raw.password ?? "");
12777
+ const smsCode = String(raw.smsCode ?? "").trim();
12778
+ const hasAccount = Boolean(email || phone);
12779
+ if (!hubUrl2) {
12780
+ throw new ApiError(400, "bad_request", "hubUrl \u5FC5\u586B");
12781
+ }
12782
+ if (code && hasAccount) {
12783
+ throw new ApiError(400, "bad_request", "code \u4E0E\u8D26\u53F7\u51ED\u636E\u53EA\u80FD\u4E8C\u9009\u4E00");
12784
+ }
12785
+ if (!code && !hasAccount) {
12786
+ throw new ApiError(400, "bad_request", "\u9700\u8981 code\uFF0C\u6216 email/phone + password/smsCode");
12787
+ }
12788
+ if (hasAccount && !password && !smsCode) {
12789
+ throw new ApiError(400, "bad_request", "\u8D26\u53F7\u63A5\u5165\u9700\u8981 password \u6216 smsCode");
12776
12790
  }
12777
12791
  const label2 = typeof raw.label === "string" ? raw.label.trim() : void 0;
12778
12792
  try {
12779
- ok(res, await opts.fleet.enroll({ hubUrl: hubUrl2, code, label: label2 }));
12793
+ ok(
12794
+ res,
12795
+ await opts.fleet.enroll({
12796
+ hubUrl: hubUrl2,
12797
+ code: code || void 0,
12798
+ account: hasAccount ? {
12799
+ email: email || void 0,
12800
+ phone: phone || void 0,
12801
+ password: password || void 0,
12802
+ smsCode: smsCode || void 0
12803
+ } : void 0,
12804
+ label: label2
12805
+ })
12806
+ );
12780
12807
  } catch (e) {
12781
12808
  const code2 = e.code;
12782
- 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;
12809
+ 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;
12783
12810
  const msg = e instanceof Error ? e.message : String(e);
12784
12811
  throw new ApiError(
12785
12812
  status,
@@ -13925,10 +13952,10 @@ function createApp(store, manager, opts = {}) {
13925
13952
  function handle(req2, res) {
13926
13953
  const startedAt = Date.now();
13927
13954
  const url = new URL(req2.url ?? "/", "http://localhost");
13928
- const path36 = url.pathname;
13955
+ const path37 = url.pathname;
13929
13956
  const method = req2.method ?? "GET";
13930
13957
  console.log(
13931
- `[api] ${(/* @__PURE__ */ new Date()).toISOString()} \u2192 ${method} ${path36}${url.search}`
13958
+ `[api] ${(/* @__PURE__ */ new Date()).toISOString()} \u2192 ${method} ${path37}${url.search}`
13932
13959
  );
13933
13960
  let tenantId = null;
13934
13961
  let logged = false;
@@ -13936,7 +13963,7 @@ function createApp(store, manager, opts = {}) {
13936
13963
  if (logged) return;
13937
13964
  logged = true;
13938
13965
  console.log(
13939
- `[api] ${(/* @__PURE__ */ new Date()).toISOString()} \u2190 ${method} ${path36} ${extra} (${Date.now() - startedAt}ms) tenant=${tenantId ?? "-"}`
13966
+ `[api] ${(/* @__PURE__ */ new Date()).toISOString()} \u2190 ${method} ${path37} ${extra} (${Date.now() - startedAt}ms) tenant=${tenantId ?? "-"}`
13940
13967
  );
13941
13968
  };
13942
13969
  res.on("finish", () => logDone(`HTTP ${res.statusCode}`));
@@ -13947,16 +13974,16 @@ function createApp(store, manager, opts = {}) {
13947
13974
  res.end();
13948
13975
  return;
13949
13976
  }
13950
- if (req2.method === "GET" && path36 === "/healthz") {
13977
+ if (req2.method === "GET" && path37 === "/healthz") {
13951
13978
  json(res, 200, {
13952
13979
  status: "ok",
13953
13980
  // 版本让运维/探针能确认线上跑的是哪个构建(更新与回滚据此判断)
13954
- version: "0.2.10",
13981
+ version: "0.2.12",
13955
13982
  features: { mcp: hasServerMcpConfig() }
13956
13983
  });
13957
13984
  return;
13958
13985
  }
13959
- if (hubProxyEnabled(opts.host) && isHubProxyPath(path36)) {
13986
+ if (hubProxyEnabled(opts.host) && isHubProxyPath(path37)) {
13960
13987
  void handleHubProxy(req2, res).catch(() => {
13961
13988
  if (!res.headersSent) {
13962
13989
  res.writeHead(502, { "Content-Type": "application/json; charset=utf-8" });
@@ -13967,11 +13994,11 @@ function createApp(store, manager, opts = {}) {
13967
13994
  });
13968
13995
  return;
13969
13996
  }
13970
- if (!path36.startsWith(API_PREFIX)) {
13997
+ if (!path37.startsWith(API_PREFIX)) {
13971
13998
  json(res, 404, { error: { code: "not_found", message: "\u672A\u77E5\u8DEF\u5F84" } });
13972
13999
  return;
13973
14000
  }
13974
- const segs = path36.slice(API_PREFIX.length).split("/").filter(Boolean);
14001
+ const segs = path37.slice(API_PREFIX.length).split("/").filter(Boolean);
13975
14002
  const apiKey = extractApiKey(req2);
13976
14003
  if (!apiKey) {
13977
14004
  json(res, 401, {
@@ -14036,7 +14063,7 @@ function createApp(store, manager, opts = {}) {
14036
14063
  ).catch((err) => {
14037
14064
  const msg = err instanceof Error ? err.message : String(err);
14038
14065
  console.log(
14039
- `[api] ${(/* @__PURE__ */ new Date()).toISOString()} ! ${method} ${path36} ERROR: ${msg}`
14066
+ `[api] ${(/* @__PURE__ */ new Date()).toISOString()} ! ${method} ${path37} ERROR: ${msg}`
14040
14067
  );
14041
14068
  error(res, err);
14042
14069
  });
@@ -14067,8 +14094,8 @@ async function cachedFetchModels(baseURL, apiKey) {
14067
14094
  try {
14068
14095
  result = await Promise.race([
14069
14096
  fetchModels(baseURL, apiKey),
14070
- new Promise((resolve19) => {
14071
- const t = setTimeout(() => resolve19(null), MODEL_FETCH_TIMEOUT_MS);
14097
+ new Promise((resolve20) => {
14098
+ const t = setTimeout(() => resolve20(null), MODEL_FETCH_TIMEOUT_MS);
14072
14099
  t.unref?.();
14073
14100
  })
14074
14101
  ]);
@@ -14093,8 +14120,8 @@ async function cachedFetchModelsEnriched(baseURL, apiKey, preferred) {
14093
14120
  if (!target) return r;
14094
14121
  const ctx = await Promise.race([
14095
14122
  fetchModelContext(baseURL, apiKey, target),
14096
- new Promise((resolve19) => {
14097
- const t = setTimeout(() => resolve19(void 0), MODEL_FETCH_TIMEOUT_MS);
14123
+ new Promise((resolve20) => {
14124
+ const t = setTimeout(() => resolve20(void 0), MODEL_FETCH_TIMEOUT_MS);
14098
14125
  t.unref?.();
14099
14126
  })
14100
14127
  ]);
@@ -15288,13 +15315,13 @@ var EVENT_FLUSH_MAX_EVENTS = 60;
15288
15315
  var EVENT_FLUSH_MAX_BYTES = 200 * 1024;
15289
15316
  var LOOP_LAG_WARN_MS = 2e3;
15290
15317
  function withTimeout(p, ms) {
15291
- return new Promise((resolve19, reject) => {
15318
+ return new Promise((resolve20, reject) => {
15292
15319
  const timer = setTimeout(() => reject(new Error(`\u5B50\u6307\u4EE4\u8D85\u65F6\uFF08${ms}ms\uFF09`)), ms);
15293
15320
  timer.unref?.();
15294
15321
  p.then(
15295
15322
  (v) => {
15296
15323
  clearTimeout(timer);
15297
- resolve19(v);
15324
+ resolve20(v);
15298
15325
  },
15299
15326
  (e) => {
15300
15327
  clearTimeout(timer);
@@ -15654,7 +15681,7 @@ var FleetNodeBridge = class {
15654
15681
  label: this.opts.deps.store.loadNodeLabel() ?? void 0,
15655
15682
  platform: process.platform,
15656
15683
  mode: process.env.NODE_MODE ?? "standalone",
15657
- version: "0.2.10",
15684
+ version: "0.2.12",
15658
15685
  ip: primaryIp()
15659
15686
  };
15660
15687
  }
@@ -15709,7 +15736,7 @@ var FleetNodeBridge = class {
15709
15736
  label: this.opts.deps.store.loadNodeLabel() ?? void 0,
15710
15737
  platform: process.platform,
15711
15738
  mode: process.env.NODE_MODE ?? "standalone",
15712
- version: "0.2.10",
15739
+ version: "0.2.12",
15713
15740
  ip: primaryIp(),
15714
15741
  projects,
15715
15742
  totals,
@@ -17124,13 +17151,13 @@ var baseUrlResolver = null;
17124
17151
  function resolveBase(baseUrl) {
17125
17152
  return baseUrlResolver ? baseUrlResolver(baseUrl) : baseUrl;
17126
17153
  }
17127
- async function req(baseUrl, token, path36, init = {}) {
17154
+ async function req(baseUrl, token, path37, init = {}) {
17128
17155
  const headers = {
17129
17156
  ...init.body ? { "Content-Type": "application/json" } : {},
17130
17157
  ...init.headers ?? {}
17131
17158
  };
17132
17159
  if (token) headers.Authorization = `Bearer ${token}`;
17133
- const res = await fetch(`${resolveBase(baseUrl).replace(/\/$/, "")}${path36}`, {
17160
+ const res = await fetch(`${resolveBase(baseUrl).replace(/\/$/, "")}${path37}`, {
17134
17161
  ...init,
17135
17162
  headers
17136
17163
  });
@@ -17433,7 +17460,7 @@ import * as path30 from "path";
17433
17460
  import { spawnSync as spawnSync3 } from "child_process";
17434
17461
  import { createRequire as createRequire3 } from "module";
17435
17462
  function currentVersion() {
17436
- const injected = "0.2.10"?.trim();
17463
+ const injected = "0.2.12"?.trim();
17437
17464
  if (injected) return injected;
17438
17465
  try {
17439
17466
  const req2 = createRequire3(import.meta.url);
@@ -17960,11 +17987,11 @@ var UpdateController = class {
17960
17987
  const minUptime = num("ZQAGENT_UPDATE_MIN_UPTIME_MS", 10 * 60 * 1e3);
17961
17988
  const idleMs = num("ZQAGENT_UPDATE_IDLE_MS", 60 * 1e3);
17962
17989
  let idleSince = null;
17963
- return new Promise((resolve19) => {
17990
+ return new Promise((resolve20) => {
17964
17991
  const timer = setInterval(() => {
17965
17992
  if (this.stopped) {
17966
17993
  clearInterval(timer);
17967
- resolve19(false);
17994
+ resolve20(false);
17968
17995
  return;
17969
17996
  }
17970
17997
  if (Date.now() - this.startedAt < minUptime || !this.opts.isIdle()) {
@@ -17974,7 +18001,7 @@ var UpdateController = class {
17974
18001
  idleSince ??= Date.now();
17975
18002
  if (Date.now() - idleSince >= idleMs) {
17976
18003
  clearInterval(timer);
17977
- resolve19(true);
18004
+ resolve20(true);
17978
18005
  }
17979
18006
  }, 1e3);
17980
18007
  timer.unref();
@@ -18157,7 +18184,7 @@ function exitWhenOrphaned() {
18157
18184
  }
18158
18185
  var PORT_FALLBACK_LIMIT = 20;
18159
18186
  function listenWithPortFallback(server, startPort, host, dataDir, limit = PORT_FALLBACK_LIMIT) {
18160
- return new Promise((resolve19, reject) => {
18187
+ return new Promise((resolve20, reject) => {
18161
18188
  let attempts = 0;
18162
18189
  const tryListen = (port) => {
18163
18190
  server.removeAllListeners("listening");
@@ -18189,7 +18216,7 @@ function listenWithPortFallback(server, startPort, host, dataDir, limit = PORT_F
18189
18216
  `);
18190
18217
  } catch {
18191
18218
  }
18192
- resolve19(actualPort);
18219
+ resolve20(actualPort);
18193
18220
  });
18194
18221
  };
18195
18222
  tryListen(startPort);
@@ -18276,7 +18303,14 @@ function startServer(opts = {}) {
18276
18303
  status: fleetStatus,
18277
18304
  async enroll(input) {
18278
18305
  const nodeId = ensureNodeId(store);
18279
- const cred = await hubEnrollByCode(input.hubUrl, {
18306
+ const cred = input.account ? await hubEnrollByAccount(input.hubUrl, {
18307
+ email: input.account.email,
18308
+ phone: input.account.phone,
18309
+ password: input.account.password,
18310
+ code: input.account.smsCode,
18311
+ nodeId,
18312
+ label: input.label
18313
+ }) : await hubEnrollByCode(input.hubUrl, {
18280
18314
  code: input.code,
18281
18315
  nodeId,
18282
18316
  label: input.label
@@ -18420,7 +18454,7 @@ function startServer(opts = {}) {
18420
18454
  server.timeout = 0;
18421
18455
  server.keepAliveTimeout = 65e3;
18422
18456
  server.headersTimeout = 66e3;
18423
- const ready = new Promise((resolve19, reject) => {
18457
+ const ready = new Promise((resolve20, reject) => {
18424
18458
  listenWithPortFallback(server, port, host, dataDir).then((actualPort) => {
18425
18459
  const info = {
18426
18460
  host,
@@ -18437,7 +18471,7 @@ function startServer(opts = {}) {
18437
18471
  printReady(info, qq);
18438
18472
  }
18439
18473
  updater?.start();
18440
- resolve19(info);
18474
+ resolve20(info);
18441
18475
  }, reject);
18442
18476
  });
18443
18477
  return {
@@ -18487,39 +18521,12 @@ function parseHubAnswer(answer, fallback) {
18487
18521
  if (SKIP_ANSWERS.has(a.toLowerCase())) return null;
18488
18522
  return (a || fallback).replace(/\/$/, "");
18489
18523
  }
18490
- function resolveDataDir(dataDir) {
18491
- return path35.resolve(dataDir ?? process.env.DATA_DIR ?? DEFAULT_DATA_DIR);
18492
- }
18493
- async function maybeAccountEnroll(opts = {}) {
18494
- if (!process.stdin.isTTY || !process.stdout.isTTY) return;
18495
- let store;
18496
- try {
18497
- store = new Store(resolveDataDir(opts.dataDir));
18498
- if (resolveFleetConfig(store)) return;
18499
- } catch (e) {
18500
- cliErr(`\u63A5\u5165\u68C0\u67E5\u5931\u8D25\uFF1A${e instanceof Error ? e.message : String(e)}`);
18501
- return;
18502
- }
18503
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
18504
- try {
18505
- await runWizard(rl, store, opts);
18506
- } catch (e) {
18507
- cliErr(`\u63A5\u5165\u5931\u8D25\uFF1A${e instanceof Error ? e.message : String(e)}`);
18508
- 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>");
18509
- } finally {
18510
- rl.close();
18511
- }
18512
- }
18513
- async function runWizard(rl, store, opts) {
18514
- cliLog("");
18515
- 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");
18516
- const fallback = resolveDefaultHub(opts.hubUrl);
18524
+ async function promptHubUrl(rl, hubUrl2) {
18525
+ const fallback = resolveDefaultHub(hubUrl2);
18517
18526
  const answer = await rl.question(`Hub \u5730\u5740 [${fallback}]\uFF1A`);
18518
- const hubUrl2 = parseHubAnswer(answer, fallback);
18519
- if (!hubUrl2) {
18520
- cliLog("\u5DF2\u8DF3\u8FC7\u63A5\u5165\uFF1A\u8282\u70B9\u4FDD\u6301\u7EAF\u672C\u5730\u8FD0\u884C\u3002");
18521
- return;
18522
- }
18527
+ return parseHubAnswer(answer, fallback);
18528
+ }
18529
+ async function promptAccountLogin(rl, hubUrl2) {
18523
18530
  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");
18524
18531
  const mode = (await rl.question("\u8BF7\u9009\u62E9 [1]\uFF1A")).trim() || "1";
18525
18532
  const input = {};
@@ -18528,42 +18535,94 @@ async function runWizard(rl, store, opts) {
18528
18535
  input.password = await askHidden(rl, "\u5BC6\u7801\uFF1A");
18529
18536
  if (!input.email || !input.password) {
18530
18537
  cliErr("\u90AE\u7BB1\u4E0E\u5BC6\u7801\u4E0D\u80FD\u4E3A\u7A7A\uFF0C\u5DF2\u8DF3\u8FC7\u63A5\u5165\u3002");
18531
- return;
18538
+ return null;
18532
18539
  }
18533
18540
  } else if (mode === "2") {
18534
18541
  input.phone = (await rl.question("\u624B\u673A\u53F7\uFF1A")).trim();
18535
18542
  input.password = await askHidden(rl, "\u5BC6\u7801\uFF1A");
18536
18543
  if (!input.phone || !input.password) {
18537
18544
  cliErr("\u624B\u673A\u53F7\u4E0E\u5BC6\u7801\u4E0D\u80FD\u4E3A\u7A7A\uFF0C\u5DF2\u8DF3\u8FC7\u63A5\u5165\u3002");
18538
- return;
18545
+ return null;
18539
18546
  }
18540
18547
  } else if (mode === "3") {
18541
18548
  input.phone = (await rl.question("\u624B\u673A\u53F7\uFF1A")).trim();
18542
18549
  if (!input.phone) {
18543
18550
  cliErr("\u624B\u673A\u53F7\u4E0D\u80FD\u4E3A\u7A7A\uFF0C\u5DF2\u8DF3\u8FC7\u63A5\u5165\u3002");
18544
- return;
18551
+ return null;
18545
18552
  }
18546
18553
  try {
18547
- const sent = await hubSendSms(hubUrl2, { phone: input.phone, purpose: "login" });
18554
+ const sent = await hubSendSms(resolveDefaultHub(hubUrl2), {
18555
+ phone: input.phone,
18556
+ purpose: "login"
18557
+ });
18548
18558
  if (sent.debugCode) cliLog(`\uFF08\u8C03\u8BD5\u6A21\u5F0F\u9A8C\u8BC1\u7801\uFF1A${sent.debugCode}\uFF09`);
18549
18559
  else cliLog("\u9A8C\u8BC1\u7801\u5DF2\u53D1\u9001\uFF0C5 \u5206\u949F\u5185\u6709\u6548\u3002");
18550
18560
  } catch (e) {
18551
18561
  cliErr(`\u77ED\u4FE1\u9A8C\u8BC1\u7801\u53D1\u9001\u5931\u8D25\uFF1A${e instanceof Error ? e.message : String(e)}`);
18552
18562
  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");
18553
18563
  cliLog(" zqagent link --hub <Hub\u5730\u5740> --code <\u63A5\u5165\u7801>");
18554
- return;
18564
+ return null;
18555
18565
  }
18556
18566
  input.code = (await rl.question("\u77ED\u4FE1\u9A8C\u8BC1\u7801\uFF1A")).trim();
18557
18567
  if (!input.code) {
18558
18568
  cliErr("\u9A8C\u8BC1\u7801\u4E0D\u80FD\u4E3A\u7A7A\uFF0C\u5DF2\u8DF3\u8FC7\u63A5\u5165\u3002");
18559
- return;
18569
+ return null;
18560
18570
  }
18561
18571
  } else {
18562
18572
  cliErr("\u672A\u77E5\u7684\u767B\u5F55\u65B9\u5F0F\uFF0C\u5DF2\u8DF3\u8FC7\u63A5\u5165\u3002");
18573
+ return null;
18574
+ }
18575
+ return input;
18576
+ }
18577
+ async function promptLinkAccount(rl, hubUrl2, opts = {}) {
18578
+ const fallback = resolveDefaultHub(hubUrl2);
18579
+ let resolved = fallback;
18580
+ if (opts.askHub !== false) {
18581
+ const answer = await promptHubUrl(rl, fallback);
18582
+ if (!answer) {
18583
+ cliLog("\u5DF2\u8DF3\u8FC7\u63A5\u5165\uFF1A\u8282\u70B9\u4FDD\u6301\u7EAF\u672C\u5730\u8FD0\u884C\u3002");
18584
+ return null;
18585
+ }
18586
+ resolved = answer;
18587
+ }
18588
+ const auth = await promptAccountLogin(rl, resolved);
18589
+ if (!auth) return null;
18590
+ return { hubUrl: resolved, auth };
18591
+ }
18592
+ function resolveDataDir(dataDir) {
18593
+ return path35.resolve(dataDir ?? process.env.DATA_DIR ?? DEFAULT_DATA_DIR);
18594
+ }
18595
+ async function maybeAccountEnroll(opts = {}) {
18596
+ if (!process.stdin.isTTY || !process.stdout.isTTY) return;
18597
+ let store;
18598
+ try {
18599
+ store = new Store(resolveDataDir(opts.dataDir));
18600
+ if (resolveFleetConfig(store)) return;
18601
+ } catch (e) {
18602
+ cliErr(`\u63A5\u5165\u68C0\u67E5\u5931\u8D25\uFF1A${e instanceof Error ? e.message : String(e)}`);
18563
18603
  return;
18564
18604
  }
18605
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
18606
+ try {
18607
+ await runWizard(rl, store, opts);
18608
+ } catch (e) {
18609
+ cliErr(`\u63A5\u5165\u5931\u8D25\uFF1A${e instanceof Error ? e.message : String(e)}`);
18610
+ 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>");
18611
+ } finally {
18612
+ rl.close();
18613
+ }
18614
+ }
18615
+ async function runWizard(rl, store, opts) {
18616
+ cliLog("");
18617
+ 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");
18618
+ const prompted = await promptLinkAccount(rl, opts.hubUrl);
18619
+ if (!prompted) return;
18565
18620
  const nodeId = ensureNodeId(store);
18566
- const cred = await hubEnrollByAccount(hubUrl2, { ...input, nodeId, label: opts.label });
18621
+ const cred = await hubEnrollByAccount(prompted.hubUrl, {
18622
+ ...prompted.auth,
18623
+ nodeId,
18624
+ label: opts.label
18625
+ });
18567
18626
  store.saveFleetCredential({
18568
18627
  ...cred,
18569
18628
  label: opts.label ?? cred.label,
@@ -18574,7 +18633,7 @@ async function runWizard(rl, store, opts) {
18574
18633
  }
18575
18634
  async function askHidden(rl, prompt) {
18576
18635
  if (!process.stdin.isTTY) return (await rl.question(prompt)).trim();
18577
- return new Promise((resolve19) => {
18636
+ return new Promise((resolve20) => {
18578
18637
  const saved = process.stdin.listeners("data");
18579
18638
  process.stdin.removeAllListeners("data");
18580
18639
  cliWrite(prompt);
@@ -18596,13 +18655,13 @@ async function askHidden(rl, prompt) {
18596
18655
  if (ch === "\r" || ch === "\n") {
18597
18656
  cleanup();
18598
18657
  cliWrite("\n");
18599
- resolve19(buf);
18658
+ resolve20(buf);
18600
18659
  return;
18601
18660
  }
18602
18661
  if (ch === "") {
18603
18662
  cleanup();
18604
18663
  cliWrite("\n");
18605
- resolve19("");
18664
+ resolve20("");
18606
18665
  return;
18607
18666
  }
18608
18667
  if (ch === "\x7F" || ch === "\b") {
@@ -18620,6 +18679,40 @@ async function askHidden(rl, prompt) {
18620
18679
  });
18621
18680
  }
18622
18681
 
18682
+ // src/cli/link.ts
18683
+ init_esm_shims();
18684
+ import * as readline2 from "readline";
18685
+
18686
+ // src/cli/serve-instances.ts
18687
+ init_esm_shims();
18688
+ import { spawnSync as spawnSync4 } from "child_process";
18689
+ import * as fs30 from "fs";
18690
+ import * as os9 from "os";
18691
+ import * as path36 from "path";
18692
+
18693
+ // src/cli/link.ts
18694
+ function buildAccountAuth(flags, env3 = process.env) {
18695
+ const username = (flags.username ?? env3.ZQAGENT_HUB_USERNAME ?? "").trim();
18696
+ let email = (flags.email ?? "").trim();
18697
+ let phone = (flags.phone ?? "").trim();
18698
+ if (username && !email && !phone) {
18699
+ if (username.includes("@")) email = username;
18700
+ else phone = username;
18701
+ }
18702
+ if (!email && !phone) return null;
18703
+ const password = flags.password ?? env3.ZQAGENT_HUB_PASSWORD ?? "";
18704
+ const smsCode = (flags.smsCode ?? env3.ZQAGENT_HUB_SMS_CODE ?? "").trim();
18705
+ return {
18706
+ email: email ? email.toLowerCase() : void 0,
18707
+ phone: phone || void 0,
18708
+ password: password || void 0,
18709
+ smsCode: smsCode || void 0
18710
+ };
18711
+ }
18712
+ function isCompleteAccount(account2) {
18713
+ return Boolean(account2 && (account2.password || account2.smsCode));
18714
+ }
18715
+
18623
18716
  // src/server/index.ts
18624
18717
  function arg(name) {
18625
18718
  const i = process.argv.indexOf(`--${name}`);
@@ -18628,13 +18721,22 @@ function arg(name) {
18628
18721
  var hubUrl = (arg("hub") ?? process.env.HUB_URL ?? "").trim();
18629
18722
  var enrollCode = (arg("enroll-code") ?? process.env.HUB_ENROLL_CODE ?? "").trim();
18630
18723
  var label = arg("label")?.trim();
18631
- void maybeAccountEnroll({ dataDir: arg("data-dir"), hubUrl: arg("hub"), label }).finally(() => {
18724
+ var account = buildAccountAuth({
18725
+ username: arg("username") ?? arg("user"),
18726
+ email: arg("email"),
18727
+ phone: arg("phone"),
18728
+ password: arg("password"),
18729
+ smsCode: arg("sms-code")
18730
+ });
18731
+ var autoEnroll = hubUrl && enrollCode ? { hubUrl, code: enrollCode, label } : hubUrl && isCompleteAccount(account) ? { hubUrl, account, label } : null;
18732
+ var beforeStart = autoEnroll ? Promise.resolve() : maybeAccountEnroll({ dataDir: arg("data-dir"), hubUrl: arg("hub"), label });
18733
+ void beforeStart.finally(() => {
18632
18734
  startServer({
18633
18735
  dataDir: arg("data-dir"),
18634
18736
  port: arg("port") ? Number(arg("port")) : void 0,
18635
18737
  host: arg("host"),
18636
- // 仅当两者齐备时启用「启动即接入」;已有 fleet.json 时会在 runtime 内被忽略
18637
- autoEnroll: hubUrl && enrollCode ? { hubUrl, code: enrollCode, label } : null,
18738
+ // 已有 fleet.json 时会在 runtime 内被忽略
18739
+ autoEnroll,
18638
18740
  autoUpdate: true
18639
18741
  });
18640
18742
  });