@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.
- package/dist/cli/index.cjs +3665 -3178
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +3662 -3175
- package/dist/cli/index.js.map +1 -1
- package/dist/server/index.cjs +308 -117
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.js +308 -117
- package/dist/server/index.js.map +1 -1
- package/package.json +1 -1
package/dist/server/index.cjs
CHANGED
|
@@ -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
|
|
2200
|
+
let path36;
|
|
2201
2201
|
let start;
|
|
2202
2202
|
let end;
|
|
2203
2203
|
try {
|
|
2204
2204
|
const obj = JSON.parse(body);
|
|
2205
|
-
|
|
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
|
-
|
|
2214
|
+
path36 = str2("path");
|
|
2215
2215
|
start = num2("start_line");
|
|
2216
2216
|
end = num2("end_line");
|
|
2217
2217
|
}
|
|
2218
|
-
if (typeof
|
|
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:
|
|
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
|
|
3839
|
-
if (
|
|
3840
|
-
this._producedFiles.push(
|
|
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((
|
|
5167
|
+
const idle = new Promise((resolve20) => {
|
|
5168
5168
|
timer = setTimeout(() => {
|
|
5169
5169
|
onIdle();
|
|
5170
|
-
|
|
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((
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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: ${
|
|
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: ${
|
|
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
|
|
9860
|
+
let resolve20;
|
|
9861
9861
|
const promise = new Promise((r) => {
|
|
9862
|
-
|
|
9862
|
+
resolve20 = r;
|
|
9863
9863
|
});
|
|
9864
|
-
return { promise, resolve:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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((
|
|
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.
|
|
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(
|
|
11501
|
-
return
|
|
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.
|
|
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((
|
|
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
|
|
12466
|
+
if (chunks.length === 0) return resolve20(void 0);
|
|
12467
12467
|
try {
|
|
12468
|
-
|
|
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
|
-
//
|
|
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
|
-
|
|
12792
|
-
|
|
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(
|
|
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
|
|
13990
|
+
const path36 = url.pathname;
|
|
13946
13991
|
const method = req2.method ?? "GET";
|
|
13947
13992
|
console.log(
|
|
13948
|
-
`[api] ${(/* @__PURE__ */ new Date()).toISOString()} \u2192 ${method} ${
|
|
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} ${
|
|
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" &&
|
|
14012
|
+
if (req2.method === "GET" && path36 === "/healthz") {
|
|
13968
14013
|
json(res, 200, {
|
|
13969
14014
|
status: "ok",
|
|
13970
14015
|
// 版本让运维/探针能确认线上跑的是哪个构建(更新与回滚据此判断)
|
|
13971
|
-
version: "0.2.
|
|
14016
|
+
version: "0.2.15",
|
|
13972
14017
|
features: { mcp: hasServerMcpConfig() }
|
|
13973
14018
|
});
|
|
13974
14019
|
return;
|
|
13975
14020
|
}
|
|
13976
|
-
if (hubProxyEnabled(opts.host) && isHubProxyPath(
|
|
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 (!
|
|
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 =
|
|
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} ${
|
|
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((
|
|
14088
|
-
const t = setTimeout(() =>
|
|
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((
|
|
14114
|
-
const t = setTimeout(() =>
|
|
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((
|
|
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
|
-
|
|
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.
|
|
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 {
|
|
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.
|
|
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,
|
|
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(/\/$/, "")}${
|
|
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
|
|
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.
|
|
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(
|
|
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((
|
|
18068
|
+
return new Promise((resolve20) => {
|
|
17981
18069
|
const timer = setInterval(() => {
|
|
17982
18070
|
if (this.stopped) {
|
|
17983
18071
|
clearInterval(timer);
|
|
17984
|
-
|
|
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
|
-
|
|
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((
|
|
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
|
-
|
|
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
|
|
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:
|
|
18395
|
+
label: label2
|
|
18300
18396
|
});
|
|
18301
18397
|
const full = {
|
|
18302
18398
|
...cred,
|
|
18303
|
-
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((
|
|
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
|
-
|
|
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
|
|
18508
|
-
|
|
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
|
-
|
|
18536
|
-
|
|
18537
|
-
|
|
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, {
|
|
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
|
|
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:
|
|
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((
|
|
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
|
-
|
|
18764
|
+
resolve20(buf);
|
|
18617
18765
|
return;
|
|
18618
18766
|
}
|
|
18619
18767
|
if (ch === "") {
|
|
18620
18768
|
cleanup();
|
|
18621
18769
|
cliWrite("\n");
|
|
18622
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
18654
|
-
autoEnroll
|
|
18844
|
+
// 已有 fleet.json 时会在 runtime 内被忽略
|
|
18845
|
+
autoEnroll,
|
|
18655
18846
|
autoUpdate: true
|
|
18656
18847
|
});
|
|
18657
18848
|
});
|