@zqagent/core 0.2.8 → 0.2.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/README.oss.en.md +1 -1
- package/README.oss.md +1 -1
- package/README.oss.zh-TW.md +1 -1
- package/dist/cli/index.cjs +733 -351
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +739 -357
- package/dist/cli/index.js.map +1 -1
- package/dist/server/index.cjs +167 -43
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.js +167 -43
- package/dist/server/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -3724,10 +3724,10 @@ var OpenAIProvider = class {
|
|
|
3724
3724
|
let timer;
|
|
3725
3725
|
try {
|
|
3726
3726
|
for (; ; ) {
|
|
3727
|
-
const idle = new Promise((
|
|
3727
|
+
const idle = new Promise((resolve24) => {
|
|
3728
3728
|
timer = setTimeout(() => {
|
|
3729
3729
|
onIdle();
|
|
3730
|
-
|
|
3730
|
+
resolve24({ timedOut: true });
|
|
3731
3731
|
}, idleMs);
|
|
3732
3732
|
});
|
|
3733
3733
|
const next = iter.next();
|
|
@@ -6048,12 +6048,12 @@ function makeSink(maxBuffer) {
|
|
|
6048
6048
|
};
|
|
6049
6049
|
}
|
|
6050
6050
|
function execAsync(file, argv, opts = {}) {
|
|
6051
|
-
return new Promise((
|
|
6051
|
+
return new Promise((resolve24) => {
|
|
6052
6052
|
const maxBuffer = opts.maxBuffer ?? DEFAULT_MAX_BUFFER;
|
|
6053
6053
|
const out = makeSink(maxBuffer);
|
|
6054
6054
|
const err = makeSink(maxBuffer);
|
|
6055
6055
|
if (opts.signal?.aborted) {
|
|
6056
|
-
|
|
6056
|
+
resolve24({
|
|
6057
6057
|
status: null,
|
|
6058
6058
|
stdout: Buffer.alloc(0),
|
|
6059
6059
|
stderr: Buffer.alloc(0),
|
|
@@ -6074,7 +6074,7 @@ function execAsync(file, argv, opts = {}) {
|
|
|
6074
6074
|
windowsHide: true
|
|
6075
6075
|
});
|
|
6076
6076
|
} catch (e) {
|
|
6077
|
-
|
|
6077
|
+
resolve24({
|
|
6078
6078
|
status: null,
|
|
6079
6079
|
stdout: Buffer.alloc(0),
|
|
6080
6080
|
stderr: Buffer.alloc(0),
|
|
@@ -6111,7 +6111,7 @@ function execAsync(file, argv, opts = {}) {
|
|
|
6111
6111
|
};
|
|
6112
6112
|
if (aborted) result.aborted = true;
|
|
6113
6113
|
if (spawnError) result.error = spawnError;
|
|
6114
|
-
|
|
6114
|
+
resolve24(result);
|
|
6115
6115
|
};
|
|
6116
6116
|
const killAndSettle = () => {
|
|
6117
6117
|
killTree(child.pid);
|
|
@@ -10077,6 +10077,38 @@ function countRawEscapes(chunk) {
|
|
|
10077
10077
|
for (const ch of cleaned) if (ch === "\x1B") escCount++;
|
|
10078
10078
|
return escCount;
|
|
10079
10079
|
}
|
|
10080
|
+
function patchReadlineHistoryNav(rl2) {
|
|
10081
|
+
const iface = rl2;
|
|
10082
|
+
const orig = iface._ttyWrite;
|
|
10083
|
+
let draft = null;
|
|
10084
|
+
iface._ttyWrite = function(s, key) {
|
|
10085
|
+
const k = key;
|
|
10086
|
+
const name = k?.name;
|
|
10087
|
+
const plainArrow = (name === "up" || name === "down") && !k?.ctrl && !k?.meta && !k?.shift;
|
|
10088
|
+
if (plainArrow) {
|
|
10089
|
+
if (name === "up" && iface.historyIndex === -1) {
|
|
10090
|
+
draft = { line: iface.line, cursor: iface.cursor };
|
|
10091
|
+
}
|
|
10092
|
+
if (iface.cursor > 0) {
|
|
10093
|
+
iface._moveCursor(-iface.cursor);
|
|
10094
|
+
}
|
|
10095
|
+
}
|
|
10096
|
+
const prevHistoryIndex = iface.historyIndex;
|
|
10097
|
+
orig.call(rl2, s, key);
|
|
10098
|
+
if (plainArrow && name === "down" && prevHistoryIndex >= 0 && iface.historyIndex === -1) {
|
|
10099
|
+
const saved = draft;
|
|
10100
|
+
draft = null;
|
|
10101
|
+
if (saved) {
|
|
10102
|
+
iface.line = saved.line;
|
|
10103
|
+
iface.cursor = Math.min(saved.cursor, saved.line.length);
|
|
10104
|
+
iface._refreshLine?.();
|
|
10105
|
+
}
|
|
10106
|
+
}
|
|
10107
|
+
};
|
|
10108
|
+
rl2.on("line", () => {
|
|
10109
|
+
draft = null;
|
|
10110
|
+
});
|
|
10111
|
+
}
|
|
10080
10112
|
var PASTE_PLACEHOLDER_PREFIX = "\u7C98\u8D34\u6587\u672C #";
|
|
10081
10113
|
var InputRouter = class {
|
|
10082
10114
|
rl;
|
|
@@ -10201,8 +10233,8 @@ var InputRouter = class {
|
|
|
10201
10233
|
}
|
|
10202
10234
|
/** 询问一行:显示 prompt,返回该行内容 */
|
|
10203
10235
|
ask(prompt) {
|
|
10204
|
-
return new Promise((
|
|
10205
|
-
this.pendingAsks.push({ prompt, resolve:
|
|
10236
|
+
return new Promise((resolve24) => {
|
|
10237
|
+
this.pendingAsks.push({ prompt, resolve: resolve24 });
|
|
10206
10238
|
this.pumpAsks();
|
|
10207
10239
|
});
|
|
10208
10240
|
}
|
|
@@ -10299,16 +10331,16 @@ import chalk2 from "chalk";
|
|
|
10299
10331
|
var BRAND_TEXT = "ZQAGENT";
|
|
10300
10332
|
var BRAND_TAGLINE = "ZQAgent \xB7 AI Agent CLI";
|
|
10301
10333
|
var GLYPHS = {
|
|
10302
|
-
Z: ["\u2588\u2588\u2588\u2588\u2588\u2588\u2588
|
|
10303
|
-
Q: [" \u2588\u2588\u2588\u2588\u2588\u2588
|
|
10304
|
-
A: [" \u2588\u2588\u2588\u2588\u2588\
|
|
10305
|
-
G: [" \u2588\u2588\u2588\u2588\u2588\u2588
|
|
10306
|
-
E: ["\u2588\u2588\u2588\u2588\u2588\u2588\u2588
|
|
10307
|
-
N: ["\u2588\u2588\u2588\
|
|
10308
|
-
T: ["\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588
|
|
10334
|
+
Z: ["\u2588\u2588\u2588\u2588\u2588\u2588\u2588 ", " \u2588\u2588\u2588 ", " \u2588\u2588\u2588 ", " \u2588\u2588\u2588 ", "\u2588\u2588\u2588\u2588\u2588\u2588\u2588 ", " "],
|
|
10335
|
+
Q: [" \u2588\u2588\u2588\u2588\u2588\u2588 ", "\u2588\u2588 \u2588\u2588", "\u2588\u2588 \u2588\u2588", "\u2588\u2588 \u2584\u2584 \u2588\u2588", " \u2588\u2588\u2588\u2588\u2588\u2588 ", " \u2580\u2580 "],
|
|
10336
|
+
A: [" \u2588\u2588\u2588\u2588\u2588\u2588 ", "\u2588\u2588 \u2588\u2588", "\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588", "\u2588\u2588 \u2588\u2588", "\u2588\u2588 \u2588\u2588", " "],
|
|
10337
|
+
G: [" \u2588\u2588\u2588\u2588\u2588\u2588 ", "\u2588\u2588 ", "\u2588\u2588 \u2588\u2588\u2588", "\u2588\u2588 \u2588\u2588", " \u2588\u2588\u2588\u2588\u2588\u2588 ", " "],
|
|
10338
|
+
E: ["\u2588\u2588\u2588\u2588\u2588\u2588\u2588 ", "\u2588\u2588 ", "\u2588\u2588\u2588\u2588\u2588\u2588\u2588 ", "\u2588\u2588 ", "\u2588\u2588\u2588\u2588\u2588\u2588\u2588 ", " "],
|
|
10339
|
+
N: ["\u2588\u2588 \u2588\u2588", "\u2588\u2588\u2588 \u2588\u2588", "\u2588\u2588\u2588\u2588 \u2588\u2588", "\u2588\u2588 \u2588\u2588 \u2588\u2588", "\u2588\u2588 \u2588\u2588\u2588\u2588", " "],
|
|
10340
|
+
T: ["\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588", " \u2588\u2588 ", " \u2588\u2588 ", " \u2588\u2588 ", " \u2588\u2588 ", " "]
|
|
10309
10341
|
};
|
|
10310
10342
|
var GLYPH_ROWS = 6;
|
|
10311
|
-
var GLYPH_COLS =
|
|
10343
|
+
var GLYPH_COLS = 9;
|
|
10312
10344
|
var GRADIENT = [
|
|
10313
10345
|
[34, 211, 238],
|
|
10314
10346
|
[99, 102, 241],
|
|
@@ -10464,7 +10496,7 @@ function renderTerminalTutorial() {
|
|
|
10464
10496
|
|
|
10465
10497
|
// src/cli/link.ts
|
|
10466
10498
|
init_esm_shims();
|
|
10467
|
-
import * as
|
|
10499
|
+
import * as path23 from "path";
|
|
10468
10500
|
|
|
10469
10501
|
// src/server/store.ts
|
|
10470
10502
|
init_esm_shims();
|
|
@@ -10874,11 +10906,186 @@ async function hubEnrollByAccount(baseUrl, input) {
|
|
|
10874
10906
|
|
|
10875
10907
|
// src/cli/serve-instances.ts
|
|
10876
10908
|
init_esm_shims();
|
|
10877
|
-
import { spawnSync as
|
|
10909
|
+
import { spawnSync as spawnSync3 } from "child_process";
|
|
10910
|
+
import * as fs19 from "fs";
|
|
10911
|
+
import * as os5 from "os";
|
|
10912
|
+
import * as path22 from "path";
|
|
10913
|
+
|
|
10914
|
+
// src/update/platform.ts
|
|
10915
|
+
init_esm_shims();
|
|
10878
10916
|
import * as fs18 from "fs";
|
|
10917
|
+
import * as os4 from "os";
|
|
10879
10918
|
import * as path21 from "path";
|
|
10919
|
+
import { spawnSync as spawnSync2 } from "child_process";
|
|
10920
|
+
import { createRequire as createRequire3 } from "module";
|
|
10921
|
+
function currentVersion() {
|
|
10922
|
+
const injected = "0.2.11"?.trim();
|
|
10923
|
+
if (injected) return injected;
|
|
10924
|
+
try {
|
|
10925
|
+
const req2 = createRequire3(import.meta.url);
|
|
10926
|
+
const pkg = req2("../../package.json");
|
|
10927
|
+
if (pkg?.version) return pkg.version;
|
|
10928
|
+
} catch {
|
|
10929
|
+
}
|
|
10930
|
+
return "dev";
|
|
10931
|
+
}
|
|
10932
|
+
function isSeaRuntime() {
|
|
10933
|
+
if (process.env.ZQAGENT_SEA === "1") return true;
|
|
10934
|
+
const base = path21.basename(process.execPath).toLowerCase().replace(/\.exe$/, "");
|
|
10935
|
+
return base !== "node" && base !== "nodejs";
|
|
10936
|
+
}
|
|
10937
|
+
var DEFAULT_SERVICE_NAME = "zqagent";
|
|
10938
|
+
var DEFAULT_SERVICE_LABEL = "com.zqagent.node";
|
|
10939
|
+
function serviceManagerFromCgroup(cgroup, serviceName = DEFAULT_SERVICE_NAME) {
|
|
10940
|
+
const unitName = `${serviceName}.service`;
|
|
10941
|
+
for (const line of cgroup.split("\n")) {
|
|
10942
|
+
const idx = line.lastIndexOf(":");
|
|
10943
|
+
if (idx < 0) continue;
|
|
10944
|
+
const unitPath = line.slice(idx + 1).trim();
|
|
10945
|
+
if (unitPath.split("/").includes(unitName)) return "systemd";
|
|
10946
|
+
}
|
|
10947
|
+
return null;
|
|
10948
|
+
}
|
|
10949
|
+
function launchdDomain() {
|
|
10950
|
+
const uid = typeof process.getuid === "function" ? process.getuid() : -1;
|
|
10951
|
+
return uid === 0 ? "system" : `gui/${uid}`;
|
|
10952
|
+
}
|
|
10953
|
+
function launchdLabel() {
|
|
10954
|
+
return process.env.ZQAGENT_SERVICE_LABEL?.trim() || DEFAULT_SERVICE_LABEL;
|
|
10955
|
+
}
|
|
10956
|
+
function launchdPlistPath() {
|
|
10957
|
+
const label = launchdLabel();
|
|
10958
|
+
const uid = typeof process.getuid === "function" ? process.getuid() : -1;
|
|
10959
|
+
if (uid === 0) return `/Library/LaunchDaemons/${label}.plist`;
|
|
10960
|
+
return path21.join(os4.homedir(), "Library", "LaunchAgents", `${label}.plist`);
|
|
10961
|
+
}
|
|
10962
|
+
function serviceManagerFromLaunchctl(output, pid, execPath, sea = true) {
|
|
10963
|
+
const pidMatch = /^\s*pid = (\d+)\s*$/m.exec(output);
|
|
10964
|
+
if (pidMatch && Number(pidMatch[1]) === pid) return "launchd";
|
|
10965
|
+
const program = /^\s*program = (.+?)\s*$/m.exec(output);
|
|
10966
|
+
if (program) {
|
|
10967
|
+
const shown = program[1].replace(/^"|"$/g, "");
|
|
10968
|
+
if (path21.resolve(shown) === path21.resolve(execPath)) return "launchd";
|
|
10969
|
+
}
|
|
10970
|
+
if (!sea && /^\s*state = /m.test(output)) return "launchd";
|
|
10971
|
+
return null;
|
|
10972
|
+
}
|
|
10973
|
+
function parseLaunchdEnvironment(xml) {
|
|
10974
|
+
const out = {};
|
|
10975
|
+
const marker = xml.indexOf("<key>EnvironmentVariables</key>");
|
|
10976
|
+
if (marker < 0) return out;
|
|
10977
|
+
const open = xml.indexOf("<dict>", marker);
|
|
10978
|
+
if (open < 0) return out;
|
|
10979
|
+
const close = xml.indexOf("</dict>", open);
|
|
10980
|
+
if (close < 0) return out;
|
|
10981
|
+
const body = xml.slice(open + "<dict>".length, close);
|
|
10982
|
+
for (const m of body.matchAll(/<key>([^<]+)<\/key>\s*<string>([^<]*)<\/string>/g)) {
|
|
10983
|
+
out[m[1]] = m[2];
|
|
10984
|
+
}
|
|
10985
|
+
return out;
|
|
10986
|
+
}
|
|
10987
|
+
function detectServiceManager() {
|
|
10988
|
+
if (process.platform === "darwin") return detectLaunchd();
|
|
10989
|
+
if (process.platform !== "linux") return null;
|
|
10990
|
+
const serviceName = process.env.ZQAGENT_SERVICE_NAME?.trim() || DEFAULT_SERVICE_NAME;
|
|
10991
|
+
try {
|
|
10992
|
+
return serviceManagerFromCgroup(
|
|
10993
|
+
fs18.readFileSync("/proc/self/cgroup", "utf8"),
|
|
10994
|
+
serviceName
|
|
10995
|
+
);
|
|
10996
|
+
} catch {
|
|
10997
|
+
return null;
|
|
10998
|
+
}
|
|
10999
|
+
}
|
|
11000
|
+
function detectLaunchd() {
|
|
11001
|
+
try {
|
|
11002
|
+
const res = spawnSync2(
|
|
11003
|
+
"launchctl",
|
|
11004
|
+
["print", `${launchdDomain()}/${launchdLabel()}`],
|
|
11005
|
+
{ encoding: "utf8", timeout: 3e3 }
|
|
11006
|
+
);
|
|
11007
|
+
if (res.status !== 0 || !res.stdout) return null;
|
|
11008
|
+
return serviceManagerFromLaunchctl(
|
|
11009
|
+
res.stdout,
|
|
11010
|
+
process.pid,
|
|
11011
|
+
process.execPath,
|
|
11012
|
+
isSeaRuntime()
|
|
11013
|
+
);
|
|
11014
|
+
} catch {
|
|
11015
|
+
return null;
|
|
11016
|
+
}
|
|
11017
|
+
}
|
|
11018
|
+
function serviceManager() {
|
|
11019
|
+
const v = process.env.ZQAGENT_SERVICE_MANAGER?.trim().toLowerCase();
|
|
11020
|
+
if (v === "systemd" || v === "launchd") return v;
|
|
11021
|
+
return detectServiceManager();
|
|
11022
|
+
}
|
|
11023
|
+
function parseServiceEnvironment(raw) {
|
|
11024
|
+
const out = {};
|
|
11025
|
+
for (const token of raw.trim().split(/\s+/)) {
|
|
11026
|
+
const idx = token.indexOf("=");
|
|
11027
|
+
if (idx > 0) out[token.slice(0, idx)] = token.slice(idx + 1);
|
|
11028
|
+
}
|
|
11029
|
+
return out;
|
|
11030
|
+
}
|
|
11031
|
+
var cachedServiceEnv = null;
|
|
11032
|
+
function readServiceEnvironment() {
|
|
11033
|
+
const serviceName = process.env.ZQAGENT_SERVICE_NAME?.trim() || DEFAULT_SERVICE_NAME;
|
|
11034
|
+
try {
|
|
11035
|
+
const res = spawnSync2(
|
|
11036
|
+
"systemctl",
|
|
11037
|
+
["show", serviceName, "--property=Environment", "--value", "--no-pager"],
|
|
11038
|
+
{ encoding: "utf8", timeout: 3e3 }
|
|
11039
|
+
);
|
|
11040
|
+
if (res.status !== 0 || !res.stdout) return {};
|
|
11041
|
+
return parseServiceEnvironment(res.stdout);
|
|
11042
|
+
} catch {
|
|
11043
|
+
return {};
|
|
11044
|
+
}
|
|
11045
|
+
}
|
|
11046
|
+
function serviceEnvValue(key) {
|
|
11047
|
+
if (process.platform === "darwin") {
|
|
11048
|
+
if (serviceManager() !== "launchd") return void 0;
|
|
11049
|
+
cachedLaunchdEnv ??= readLaunchdEnvironment();
|
|
11050
|
+
return cachedLaunchdEnv[key];
|
|
11051
|
+
}
|
|
11052
|
+
if (process.platform !== "linux") return void 0;
|
|
11053
|
+
if (serviceManager() !== "systemd") return void 0;
|
|
11054
|
+
cachedServiceEnv ??= readServiceEnvironment();
|
|
11055
|
+
return cachedServiceEnv[key];
|
|
11056
|
+
}
|
|
11057
|
+
var cachedLaunchdEnv = null;
|
|
11058
|
+
function readLaunchdEnvironment() {
|
|
11059
|
+
try {
|
|
11060
|
+
return parseLaunchdEnvironment(fs18.readFileSync(launchdPlistPath(), "utf8"));
|
|
11061
|
+
} catch {
|
|
11062
|
+
return {};
|
|
11063
|
+
}
|
|
11064
|
+
}
|
|
11065
|
+
function selfUpdateCapability(hasPublicKey) {
|
|
11066
|
+
if (!isSeaRuntime()) {
|
|
11067
|
+
return {
|
|
11068
|
+
ok: false,
|
|
11069
|
+
reason: "\u5F53\u524D\u4E0D\u662F\u5355\u6587\u4EF6\uFF08SEA\uFF09\u5F62\u6001\uFF1A\u8BF7\u7528 npm \u5347\u7EA7\uFF08npm i -g @zqagent/core@latest\uFF09"
|
|
11070
|
+
};
|
|
11071
|
+
}
|
|
11072
|
+
if (!serviceManager()) {
|
|
11073
|
+
return {
|
|
11074
|
+
ok: false,
|
|
11075
|
+
reason: "\u672A\u88AB systemd/launchd \u6258\u7BA1\uFF1A\u8BF7\u7528 deploy/service/install.sh \u5B89\u88C5\uFF0C\u6216\u624B\u52A8\u5347\u7EA7"
|
|
11076
|
+
};
|
|
11077
|
+
}
|
|
11078
|
+
if (!hasPublicKey) {
|
|
11079
|
+
return { ok: false, reason: "\u672A\u914D\u7F6E ZQAGENT_UPDATE_PUBKEY\uFF0C\u65E0\u6CD5\u9A8C\u7B7E\uFF0C\u5DF2\u7981\u7528\u81EA\u52A8\u66F4\u65B0" };
|
|
11080
|
+
}
|
|
11081
|
+
return { ok: true };
|
|
11082
|
+
}
|
|
11083
|
+
|
|
11084
|
+
// src/cli/serve-instances.ts
|
|
10880
11085
|
var DEFAULT_SERVE_HOST = "127.0.0.1";
|
|
10881
11086
|
var DEFAULT_SERVE_PORT = 8787;
|
|
11087
|
+
var DEFAULT_SERVICE_NAME2 = "zqagent";
|
|
11088
|
+
var DEFAULT_SERVICE_LABEL2 = "com.zqagent.node";
|
|
10882
11089
|
function serveSubcommandIndex(argv) {
|
|
10883
11090
|
for (let i = 1; i < argv.length; i++) {
|
|
10884
11091
|
if (argv[i].startsWith("-")) continue;
|
|
@@ -10913,18 +11120,43 @@ function parseServeArgs(argv) {
|
|
|
10913
11120
|
return { dataDir, host, port };
|
|
10914
11121
|
}
|
|
10915
11122
|
function buildHotCandidates(explicitDataDir, discovered, fallback) {
|
|
10916
|
-
|
|
10917
|
-
|
|
10918
|
-
}
|
|
10919
|
-
const out = [{ dataDir: path21.resolve(DEFAULT_DATA_DIR), ...fallback }];
|
|
10920
|
-
for (const inst of discovered) {
|
|
11123
|
+
const out = [];
|
|
11124
|
+
const push = (inst) => {
|
|
10921
11125
|
if (!out.some((o) => o.dataDir === inst.dataDir)) out.push(inst);
|
|
10922
|
-
}
|
|
11126
|
+
};
|
|
11127
|
+
if (explicitDataDir) push({ dataDir: path22.resolve(explicitDataDir), ...fallback });
|
|
11128
|
+
for (const inst of discovered) if (inst.managed) push(inst);
|
|
11129
|
+
for (const inst of discovered) if (!inst.managed) push(inst);
|
|
11130
|
+
if (!explicitDataDir) push({ dataDir: path22.resolve(DEFAULT_DATA_DIR), ...fallback });
|
|
10923
11131
|
return out;
|
|
10924
11132
|
}
|
|
11133
|
+
function isWindowsAbsolute(p) {
|
|
11134
|
+
return /^[A-Za-z]:[\\/]/.test(p) || /^\\\\/.test(p);
|
|
11135
|
+
}
|
|
11136
|
+
function isAbsolutePath(p) {
|
|
11137
|
+
return path22.isAbsolute(p) || isWindowsAbsolute(p);
|
|
11138
|
+
}
|
|
11139
|
+
function normalizePath(p) {
|
|
11140
|
+
return isWindowsAbsolute(p) ? path22.win32.normalize(p) : path22.normalize(p);
|
|
11141
|
+
}
|
|
11142
|
+
function parseServeCommandLine(line) {
|
|
11143
|
+
if (!/(?:^|\s)["']?serve["']?(?=\s|$)/.test(line)) return null;
|
|
11144
|
+
const m = /--data-dir(?:=|\s+)(?:"([^"]+)"|'([^']+)'|(.+?))(?=\s+--\w|\s*$)/.exec(line);
|
|
11145
|
+
const rawDataDir = (m?.[1] ?? m?.[2] ?? m?.[3] ?? "").trim();
|
|
11146
|
+
if (!rawDataDir || !isAbsolutePath(rawDataDir)) return null;
|
|
11147
|
+
const host = /--host(?:=|\s+)(?:"([^"]+)"|'([^']+)'|(\S+))/.exec(line);
|
|
11148
|
+
const rawHost = (host?.[1] ?? host?.[2] ?? host?.[3] ?? DEFAULT_SERVE_HOST).trim();
|
|
11149
|
+
const portMatch = /--port(?:=|\s+)(\d+)/.exec(line);
|
|
11150
|
+
const port = Number(portMatch?.[1] ?? DEFAULT_SERVE_PORT);
|
|
11151
|
+
return {
|
|
11152
|
+
dataDir: normalizePath(rawDataDir),
|
|
11153
|
+
host: rawHost === "0.0.0.0" || rawHost === "::" || rawHost === "" ? DEFAULT_SERVE_HOST : rawHost,
|
|
11154
|
+
port: Number.isFinite(port) && port > 0 ? port : DEFAULT_SERVE_PORT
|
|
11155
|
+
};
|
|
11156
|
+
}
|
|
10925
11157
|
function processCwd(pid) {
|
|
10926
11158
|
try {
|
|
10927
|
-
return
|
|
11159
|
+
return fs19.readlinkSync(`/proc/${pid}/cwd`);
|
|
10928
11160
|
} catch {
|
|
10929
11161
|
return null;
|
|
10930
11162
|
}
|
|
@@ -10932,7 +11164,7 @@ function processCwd(pid) {
|
|
|
10932
11164
|
function processEnv(pid) {
|
|
10933
11165
|
const out = {};
|
|
10934
11166
|
try {
|
|
10935
|
-
const raw =
|
|
11167
|
+
const raw = fs19.readFileSync(`/proc/${pid}/environ`, "utf-8");
|
|
10936
11168
|
for (const entry of raw.split("\0")) {
|
|
10937
11169
|
const eq = entry.indexOf("=");
|
|
10938
11170
|
if (eq > 0) out[entry.slice(0, eq)] = entry.slice(eq + 1);
|
|
@@ -10943,14 +11175,24 @@ function processEnv(pid) {
|
|
|
10943
11175
|
}
|
|
10944
11176
|
function resolveDataDir(rawDataDir, cwd, env3) {
|
|
10945
11177
|
const pick = rawDataDir ?? env3.DATA_DIR ?? null;
|
|
10946
|
-
if (pick) return
|
|
10947
|
-
return cwd ?
|
|
11178
|
+
if (pick) return path22.isAbsolute(pick) ? path22.normalize(pick) : cwd ? path22.resolve(cwd, pick) : null;
|
|
11179
|
+
return cwd ? path22.resolve(cwd, DEFAULT_DATA_DIR) : null;
|
|
11180
|
+
}
|
|
11181
|
+
function isManagedBySystemd(pid, env3) {
|
|
11182
|
+
if (env3.ZQAGENT_SERVICE_MANAGER?.trim()) return true;
|
|
11183
|
+
try {
|
|
11184
|
+
const cgroup = fs19.readFileSync(`/proc/${pid}/cgroup`, "utf-8");
|
|
11185
|
+
const serviceName = env3.ZQAGENT_SERVICE_NAME?.trim() || "zqagent";
|
|
11186
|
+
return serviceManagerFromCgroup(cgroup, serviceName) !== null;
|
|
11187
|
+
} catch {
|
|
11188
|
+
return false;
|
|
11189
|
+
}
|
|
10948
11190
|
}
|
|
10949
11191
|
function discoverFromProc() {
|
|
10950
11192
|
const out = [];
|
|
10951
11193
|
let pids;
|
|
10952
11194
|
try {
|
|
10953
|
-
pids =
|
|
11195
|
+
pids = fs19.readdirSync("/proc");
|
|
10954
11196
|
} catch {
|
|
10955
11197
|
return out;
|
|
10956
11198
|
}
|
|
@@ -10959,50 +11201,186 @@ function discoverFromProc() {
|
|
|
10959
11201
|
const pid = Number(name);
|
|
10960
11202
|
if (pid === process.pid) continue;
|
|
10961
11203
|
let argv;
|
|
11204
|
+
let env3;
|
|
10962
11205
|
try {
|
|
10963
|
-
argv =
|
|
11206
|
+
argv = fs19.readFileSync(`/proc/${pid}/cmdline`, "utf-8").split("\0").filter(Boolean);
|
|
11207
|
+
env3 = processEnv(pid);
|
|
10964
11208
|
} catch {
|
|
10965
11209
|
continue;
|
|
10966
11210
|
}
|
|
10967
11211
|
const parsed = parseServeArgs(argv);
|
|
10968
11212
|
if (!parsed) continue;
|
|
10969
|
-
const dataDir = resolveDataDir(parsed.dataDir, processCwd(pid),
|
|
11213
|
+
const dataDir = resolveDataDir(parsed.dataDir, processCwd(pid), env3);
|
|
10970
11214
|
if (!dataDir) continue;
|
|
10971
|
-
out.push({
|
|
11215
|
+
out.push({
|
|
11216
|
+
dataDir,
|
|
11217
|
+
host: parsed.host,
|
|
11218
|
+
port: parsed.port,
|
|
11219
|
+
managed: isManagedBySystemd(pid, env3)
|
|
11220
|
+
});
|
|
10972
11221
|
}
|
|
10973
11222
|
return out;
|
|
10974
11223
|
}
|
|
10975
11224
|
function discoverFromPs() {
|
|
10976
11225
|
const out = [];
|
|
10977
|
-
const res =
|
|
11226
|
+
const res = spawnSync3("ps", ["-axo", "command="], { encoding: "utf-8", stdio: ["ignore", "pipe", "ignore"] });
|
|
10978
11227
|
if (res.status !== 0 || !res.stdout) return out;
|
|
10979
11228
|
for (const line of res.stdout.split("\n")) {
|
|
10980
|
-
|
|
10981
|
-
|
|
10982
|
-
|
|
10983
|
-
|
|
10984
|
-
|
|
10985
|
-
|
|
10986
|
-
|
|
11229
|
+
const inst = parseServeCommandLine(line);
|
|
11230
|
+
if (inst) out.push(inst);
|
|
11231
|
+
}
|
|
11232
|
+
return out;
|
|
11233
|
+
}
|
|
11234
|
+
function discoverFromWindows() {
|
|
11235
|
+
const out = [];
|
|
11236
|
+
const script = `[Console]::OutputEncoding=[Text.Encoding]::UTF8; Get-CimInstance Win32_Process -Filter "Name='zqagent.exe' OR Name='node.exe'" | ForEach-Object { $_.CommandLine }`;
|
|
11237
|
+
const res = spawnSync3(
|
|
11238
|
+
"powershell.exe",
|
|
11239
|
+
["-NoProfile", "-NonInteractive", "-Command", script],
|
|
11240
|
+
{ encoding: "utf-8", timeout: 15e3, windowsHide: true, stdio: ["ignore", "pipe", "ignore"] }
|
|
11241
|
+
);
|
|
11242
|
+
if (res.status !== 0 || !res.stdout) return out;
|
|
11243
|
+
for (const line of res.stdout.replace(/^\uFEFF/, "").split(/\r?\n/)) {
|
|
11244
|
+
const inst = parseServeCommandLine(line);
|
|
11245
|
+
if (inst) out.push(inst);
|
|
11246
|
+
}
|
|
11247
|
+
return out;
|
|
11248
|
+
}
|
|
11249
|
+
function decodeXmlEntities(s) {
|
|
11250
|
+
return s.replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").replace(/&/g, "&");
|
|
11251
|
+
}
|
|
11252
|
+
function parseLaunchdProgramArguments(xml) {
|
|
11253
|
+
const marker = xml.indexOf("<key>ProgramArguments</key>");
|
|
11254
|
+
if (marker < 0) return [];
|
|
11255
|
+
const open = xml.indexOf("<array>", marker);
|
|
11256
|
+
if (open < 0) return [];
|
|
11257
|
+
const close = xml.indexOf("</array>", open);
|
|
11258
|
+
if (close < 0) return [];
|
|
11259
|
+
return [...xml.slice(open + "<array>".length, close).matchAll(/<string>([^<]*)<\/string>/g)].map(
|
|
11260
|
+
(m) => decodeXmlEntities(m[1])
|
|
11261
|
+
);
|
|
11262
|
+
}
|
|
11263
|
+
function launchdServiceInstances() {
|
|
11264
|
+
if (process.platform !== "darwin") return [];
|
|
11265
|
+
const label = process.env.ZQAGENT_SERVICE_LABEL?.trim() || DEFAULT_SERVICE_LABEL2;
|
|
11266
|
+
const plists = [
|
|
11267
|
+
`/Library/LaunchDaemons/${label}.plist`,
|
|
11268
|
+
path22.join(os5.homedir(), "Library", "LaunchAgents", `${label}.plist`)
|
|
11269
|
+
];
|
|
11270
|
+
const out = [];
|
|
11271
|
+
for (const plist of plists) {
|
|
11272
|
+
let xml;
|
|
11273
|
+
try {
|
|
11274
|
+
xml = fs19.readFileSync(plist, "utf-8");
|
|
11275
|
+
} catch {
|
|
11276
|
+
continue;
|
|
11277
|
+
}
|
|
11278
|
+
const parsed = parseServeArgs(parseLaunchdProgramArguments(xml));
|
|
11279
|
+
if (!parsed?.dataDir || !isAbsolutePath(parsed.dataDir)) continue;
|
|
10987
11280
|
out.push({
|
|
10988
|
-
dataDir:
|
|
10989
|
-
host:
|
|
10990
|
-
port:
|
|
11281
|
+
dataDir: normalizePath(parsed.dataDir),
|
|
11282
|
+
host: parsed.host,
|
|
11283
|
+
port: parsed.port,
|
|
11284
|
+
managed: true
|
|
10991
11285
|
});
|
|
10992
11286
|
}
|
|
10993
11287
|
return out;
|
|
10994
11288
|
}
|
|
11289
|
+
function parseSystemdUnit(text) {
|
|
11290
|
+
let dataDir = null;
|
|
11291
|
+
let host = DEFAULT_SERVE_HOST;
|
|
11292
|
+
let port = DEFAULT_SERVE_PORT;
|
|
11293
|
+
for (const line of text.split("\n")) {
|
|
11294
|
+
const trimmed = line.trim();
|
|
11295
|
+
if (trimmed.startsWith("WorkingDirectory=")) {
|
|
11296
|
+
const v = trimmed.slice("WorkingDirectory=".length).trim();
|
|
11297
|
+
if (v && isAbsolutePath(v)) dataDir = v;
|
|
11298
|
+
} else if (trimmed.startsWith("ExecStart=")) {
|
|
11299
|
+
const tokens = trimmed.slice("ExecStart=".length).trim().split(/\s+/).map((t) => t.replace(/^["']|["']$/g, ""));
|
|
11300
|
+
const parsed = parseServeArgs(tokens);
|
|
11301
|
+
if (!parsed) continue;
|
|
11302
|
+
if (parsed.dataDir && isAbsolutePath(parsed.dataDir)) dataDir = parsed.dataDir;
|
|
11303
|
+
host = parsed.host;
|
|
11304
|
+
port = parsed.port;
|
|
11305
|
+
}
|
|
11306
|
+
}
|
|
11307
|
+
if (!dataDir) return null;
|
|
11308
|
+
return { dataDir: normalizePath(dataDir), host, port, managed: true };
|
|
11309
|
+
}
|
|
11310
|
+
function systemdServiceInstances() {
|
|
11311
|
+
if (process.platform !== "linux") return [];
|
|
11312
|
+
const unit = process.env.ZQAGENT_SERVICE_NAME?.trim() || DEFAULT_SERVICE_NAME2;
|
|
11313
|
+
const configHome = process.env.XDG_CONFIG_HOME?.trim() || path22.join(os5.homedir(), ".config");
|
|
11314
|
+
const units = [
|
|
11315
|
+
`/etc/systemd/system/${unit}.service`,
|
|
11316
|
+
path22.join(configHome, "systemd", "user", `${unit}.service`)
|
|
11317
|
+
];
|
|
11318
|
+
const out = [];
|
|
11319
|
+
for (const file of units) {
|
|
11320
|
+
let text;
|
|
11321
|
+
try {
|
|
11322
|
+
text = fs19.readFileSync(file, "utf-8");
|
|
11323
|
+
} catch {
|
|
11324
|
+
continue;
|
|
11325
|
+
}
|
|
11326
|
+
const inst = parseSystemdUnit(text);
|
|
11327
|
+
if (inst) out.push(inst);
|
|
11328
|
+
}
|
|
11329
|
+
return out;
|
|
11330
|
+
}
|
|
11331
|
+
function windowsServiceInstances() {
|
|
11332
|
+
if (process.platform !== "win32") return [];
|
|
11333
|
+
const appdata = process.env.APPDATA?.trim();
|
|
11334
|
+
if (!appdata) return [];
|
|
11335
|
+
const base = path22.join(appdata, "zqagent");
|
|
11336
|
+
try {
|
|
11337
|
+
const raw = fs19.readFileSync(path22.join(base, "runtime", "service.json"), "utf-8");
|
|
11338
|
+
const v = JSON.parse(raw);
|
|
11339
|
+
const dataDir = v.dataDir && isAbsolutePath(v.dataDir) ? v.dataDir : base;
|
|
11340
|
+
const port = Number(v.port);
|
|
11341
|
+
return [
|
|
11342
|
+
{
|
|
11343
|
+
dataDir: normalizePath(dataDir),
|
|
11344
|
+
host: DEFAULT_SERVE_HOST,
|
|
11345
|
+
port: Number.isFinite(port) && port > 0 ? port : DEFAULT_SERVE_PORT,
|
|
11346
|
+
managed: true
|
|
11347
|
+
}
|
|
11348
|
+
];
|
|
11349
|
+
} catch {
|
|
11350
|
+
return [];
|
|
11351
|
+
}
|
|
11352
|
+
}
|
|
11353
|
+
function mergeServeInstances(discovered, managed) {
|
|
11354
|
+
const out = [];
|
|
11355
|
+
const push = (inst) => {
|
|
11356
|
+
if (!out.some((o) => o.dataDir === inst.dataDir)) out.push(inst);
|
|
11357
|
+
};
|
|
11358
|
+
for (const inst of discovered) {
|
|
11359
|
+
const hit = managed.find((m) => m.dataDir === inst.dataDir);
|
|
11360
|
+
push(hit ? { ...inst, managed: true } : inst);
|
|
11361
|
+
}
|
|
11362
|
+
for (const inst of managed) push(inst);
|
|
11363
|
+
return out;
|
|
11364
|
+
}
|
|
10995
11365
|
function discoverRunningServeInstances() {
|
|
10996
|
-
const found = process.platform === "linux" ? discoverFromProc() : discoverFromPs();
|
|
10997
|
-
const
|
|
10998
|
-
return found
|
|
10999
|
-
if (seen.has(inst.dataDir)) return false;
|
|
11000
|
-
seen.add(inst.dataDir);
|
|
11001
|
-
return true;
|
|
11002
|
-
});
|
|
11366
|
+
const found = process.platform === "linux" ? discoverFromProc() : process.platform === "win32" ? discoverFromWindows() : discoverFromPs();
|
|
11367
|
+
const declared = process.platform === "linux" ? systemdServiceInstances() : process.platform === "win32" ? windowsServiceInstances() : launchdServiceInstances();
|
|
11368
|
+
return mergeServeInstances(found, declared);
|
|
11003
11369
|
}
|
|
11004
11370
|
|
|
11005
11371
|
// src/cli/link.ts
|
|
11372
|
+
function expandHome(p) {
|
|
11373
|
+
const home = process.env.HOME || process.env.USERPROFILE;
|
|
11374
|
+
if (!home) return p;
|
|
11375
|
+
if (p === "~") return home;
|
|
11376
|
+
if (p.startsWith("~/") || p.startsWith("~\\")) return path23.join(home, p.slice(2));
|
|
11377
|
+
return p;
|
|
11378
|
+
}
|
|
11379
|
+
function installDataDirHint() {
|
|
11380
|
+
if (process.platform === "darwin") return "$HOME/Library/Application Support/zqagent";
|
|
11381
|
+
if (process.platform === "win32") return "%APPDATA%\\zqagent";
|
|
11382
|
+
return "/var/lib/zqagent\uFF08\u9700 root\uFF1B\u666E\u901A\u7528\u6237\u7528 ~/.zqagent_data\uFF09";
|
|
11383
|
+
}
|
|
11006
11384
|
function parseLinkArgs(argv) {
|
|
11007
11385
|
const out = {};
|
|
11008
11386
|
for (let i = 0; i < argv.length; i++) {
|
|
@@ -11075,20 +11453,47 @@ async function enrollViaServer(host, port, adminKey, opts) {
|
|
|
11075
11453
|
}
|
|
11076
11454
|
return payload?.data;
|
|
11077
11455
|
}
|
|
11456
|
+
function hotWarnings(inst, running) {
|
|
11457
|
+
const warnings = [];
|
|
11458
|
+
const managed = running.filter((r) => r.managed && r.dataDir !== inst.dataDir);
|
|
11459
|
+
if (!inst.managed && managed.length > 0) {
|
|
11460
|
+
warnings.push(
|
|
11461
|
+
`\u51ED\u636E\u5199\u5165\u4E86\u975E\u6258\u7BA1\u5B9E\u4F8B ${inst.dataDir}\uFF0C\u4F46\u672C\u673A\u6258\u7BA1\u670D\u52A1\u4F7F\u7528\u7684\u662F ${managed.map((m) => m.dataDir).join("\u3001")}\u3002`
|
|
11462
|
+
);
|
|
11463
|
+
warnings.push(
|
|
11464
|
+
"\u6258\u7BA1\u670D\u52A1\u8BFB\u4E0D\u5230\u8FD9\u4EFD\u51ED\u636E\uFF08\u91CD\u542F\u540E\u4E5F\u4E0D\u4F1A\u81EA\u52A8\u4E0A\u7EBF\uFF09\uFF0C\u8BF7\u7528 --data-dir \u6307\u5411\u5B83\u7684\u6570\u636E\u76EE\u5F55\u91CD\u65B0\u63A5\u5165\u3002"
|
|
11465
|
+
);
|
|
11466
|
+
}
|
|
11467
|
+
const others = [...new Set(running.map((r) => r.dataDir).filter((d) => d !== inst.dataDir))];
|
|
11468
|
+
if (others.length > 0) {
|
|
11469
|
+
warnings.push(`\u672C\u673A\u8FD8\u6709\u5176\u5B83\u8FD0\u884C\u4E2D\u7684\u8282\u70B9\u5B9E\u4F8B\uFF08\u672A\u5199\u5165\u51ED\u636E\uFF09\uFF1A${others.join("\u3001")}\u3002`);
|
|
11470
|
+
}
|
|
11471
|
+
return warnings;
|
|
11472
|
+
}
|
|
11078
11473
|
async function linkNode(opts) {
|
|
11079
|
-
const
|
|
11474
|
+
const rawDataDir = opts.dataDir?.trim() || process.env.DATA_DIR?.trim() || void 0;
|
|
11475
|
+
const explicitDataDir = rawDataDir ? expandHome(rawDataDir) : void 0;
|
|
11080
11476
|
const host = opts.host?.trim() || process.env.HOST?.trim() || DEFAULT_SERVE_HOST;
|
|
11081
11477
|
const port = opts.port ?? Number(process.env.PORT ?? DEFAULT_SERVE_PORT);
|
|
11082
|
-
const
|
|
11478
|
+
const running = discoverRunningServeInstances();
|
|
11479
|
+
const candidates = buildHotCandidates(explicitDataDir, running, { host, port });
|
|
11083
11480
|
for (const inst of candidates) {
|
|
11084
11481
|
const store2 = new Store(inst.dataDir);
|
|
11085
11482
|
const adminKey = process.env.ADMIN_API_KEY ?? store2.loadAdminKey();
|
|
11086
11483
|
if (!adminKey) continue;
|
|
11087
11484
|
if (!await probeServer(inst.host, inst.port, adminKey)) continue;
|
|
11088
11485
|
const status = await enrollViaServer(inst.host, inst.port, adminKey, opts);
|
|
11089
|
-
return {
|
|
11486
|
+
return {
|
|
11487
|
+
mode: "hot",
|
|
11488
|
+
...status,
|
|
11489
|
+
dataDir: inst.dataDir,
|
|
11490
|
+
managed: inst.managed,
|
|
11491
|
+
warnings: hotWarnings(inst, running)
|
|
11492
|
+
};
|
|
11090
11493
|
}
|
|
11091
|
-
const
|
|
11494
|
+
const managedDir = running.find((r) => r.managed)?.dataDir;
|
|
11495
|
+
const dataDir = path23.resolve(explicitDataDir ?? managedDir ?? DEFAULT_DATA_DIR);
|
|
11496
|
+
const targetedService = !explicitDataDir && Boolean(managedDir) && dataDir === managedDir;
|
|
11092
11497
|
const store = new Store(dataDir);
|
|
11093
11498
|
const nodeId = ensureNodeId(store);
|
|
11094
11499
|
const cred = await hubEnrollByCode(opts.hubUrl, {
|
|
@@ -11096,25 +11501,45 @@ async function linkNode(opts) {
|
|
|
11096
11501
|
nodeId,
|
|
11097
11502
|
label: opts.label
|
|
11098
11503
|
});
|
|
11099
|
-
|
|
11100
|
-
|
|
11101
|
-
|
|
11102
|
-
|
|
11103
|
-
|
|
11504
|
+
try {
|
|
11505
|
+
store.saveFleetCredential({
|
|
11506
|
+
...cred,
|
|
11507
|
+
label: opts.label ?? cred.label,
|
|
11508
|
+
enrolledAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
11509
|
+
});
|
|
11510
|
+
} catch (e) {
|
|
11511
|
+
const err = e;
|
|
11512
|
+
if (err.code === "EACCES" || err.code === "EPERM") {
|
|
11513
|
+
throw new Error(
|
|
11514
|
+
`\u65E0\u6CD5\u5199\u5165\u6570\u636E\u76EE\u5F55 ${dataDir}\uFF08${err.code}: ${err.message}\uFF09
|
|
11515
|
+
\u8BE5\u76EE\u5F55\u5F53\u524D\u7528\u6237\u6CA1\u6709\u5199\u6743\u9650\u3002\u4E24\u79CD\u6539\u6CD5\uFF1A
|
|
11516
|
+
1) \u53BB\u6389 --data-dir\uFF0C\u8BA9 link \u81EA\u52A8\u53D1\u73B0\u672C\u673A\u8FD0\u884C\u7684\u8282\u70B9\uFF08\u63A8\u8350\uFF09\uFF1B
|
|
11517
|
+
2) \u7528\u5F53\u524D\u7528\u6237\u53EF\u5199\u7684\u76EE\u5F55\uFF0C\u672C\u5E73\u53F0\u5B89\u88C5\u811A\u672C\u9ED8\u8BA4\uFF1A${installDataDirHint()}
|
|
11518
|
+
\uFF08\u63A5\u5165\u7801\u4E00\u6B21\u6027\uFF0C\u9700\u8981\u91CD\u65B0\u751F\u6210\uFF09`
|
|
11519
|
+
);
|
|
11520
|
+
}
|
|
11521
|
+
throw e;
|
|
11522
|
+
}
|
|
11523
|
+
const otherRunningDirs = [
|
|
11524
|
+
...new Set(running.map((r) => r.dataDir).filter((d) => d !== dataDir))
|
|
11525
|
+
];
|
|
11104
11526
|
return {
|
|
11105
11527
|
mode: "saved",
|
|
11106
11528
|
nodeId,
|
|
11107
11529
|
gatewayUrl: cred.gatewayUrl,
|
|
11108
11530
|
label: opts.label,
|
|
11109
11531
|
dataDir,
|
|
11110
|
-
explicitDataDir: Boolean(explicitDataDir)
|
|
11532
|
+
explicitDataDir: Boolean(explicitDataDir),
|
|
11533
|
+
runningServiceDirs: otherRunningDirs,
|
|
11534
|
+
targetedService
|
|
11111
11535
|
};
|
|
11112
11536
|
}
|
|
11113
11537
|
function printLinkHelp() {
|
|
11114
|
-
cliLog("\u7528\u6CD5: zqagent link --hub <url> --code <\u6CE8\u518C\u7801> [--label \u540D\u79F0]
|
|
11538
|
+
cliLog("\u7528\u6CD5: zqagent link --hub <url> --code <\u6CE8\u518C\u7801> [--label \u540D\u79F0]");
|
|
11115
11539
|
cliLog(" \u5728 Hub \u7528\u6237\u4E2D\u5FC3\u751F\u6210\u4E00\u6B21\u6027\u6CE8\u518C\u7801\u540E\uFF0C\u4E8E\u8282\u70B9\u673A\u5668\u6267\u884C\u672C\u547D\u4EE4\u5373\u53EF\u63A5\u5165\u3002");
|
|
11116
|
-
cliLog(" \u5DF2\
|
|
11117
|
-
cliLog(" \
|
|
11540
|
+
cliLog(" \u672C\u673A\u5DF2\u88C5\u8282\u70B9\u670D\u52A1\uFF08install.sh / \u684C\u9762\u7AEF\uFF09\u65F6\u4F1A\u81EA\u52A8\u53D1\u73B0\u5B83\u7684\u6570\u636E\u76EE\u5F55\u5E76\u70ED\u63A5\u5165\uFF0C");
|
|
11541
|
+
cliLog(" \u4E0D\u9700\u8981\u624B\u52A8\u6307\u5B9A --data-dir\uFF1B\u670D\u52A1\u6CA1\u5728\u8FD0\u884C\u65F6\u4F1A\u5199\u5165\u5B83\u7684\u76EE\u5F55\uFF0C\u4E0B\u6B21\u542F\u52A8\u5373\u63A5\u5165\u3002");
|
|
11542
|
+
cliLog(" \u4EC5\u5F53\u672C\u673A\u5B8C\u5168\u6CA1\u6709\u670D\u52A1\u65F6\u624D\u9700\u8981 --data-dir \u6307\u5B9A\u76EE\u5F55\uFF08\u4E0B\u6B21\u542F\u52A8 serve \u65F6\u751F\u6548\uFF09\u3002");
|
|
11118
11543
|
}
|
|
11119
11544
|
async function runLinkCommand(argv) {
|
|
11120
11545
|
const args = parseLinkArgs(argv);
|
|
@@ -11142,20 +11567,36 @@ async function runLinkCommand(argv) {
|
|
|
11142
11567
|
cliLog("\u2705 \u5DF2\u63A5\u5165 Hub\uFF08\u70ED\u63A5\u5165\uFF0C\u514D\u91CD\u542F\uFF09");
|
|
11143
11568
|
cliLog(` \u8282\u70B9: ${r.nodeId}${r.label ? ` (${r.label})` : ""}`);
|
|
11144
11569
|
cliLog(` \u7F51\u5173: ${r.gatewayUrl ?? "\uFF08\u672A\u4E0B\u53D1\uFF09"} \u5728\u7EBF: ${r.online ? "\u662F" : "\u8FDE\u63A5\u4E2D\u2026"}`);
|
|
11145
|
-
cliLog(` \u6570\u636E\u76EE\u5F55: ${r.dataDir}`);
|
|
11570
|
+
cliLog(` \u6570\u636E\u76EE\u5F55: ${r.dataDir}${r.managed ? "\uFF08\u6258\u7BA1\u670D\u52A1\uFF0C\u5F00\u673A\u81EA\u542F\uFF09" : ""}`);
|
|
11571
|
+
if (r.warnings.length > 0) {
|
|
11572
|
+
cliLog("");
|
|
11573
|
+
for (const w of r.warnings) cliLog(`\u26A0\uFE0F ${w}`);
|
|
11574
|
+
}
|
|
11146
11575
|
} else {
|
|
11147
11576
|
cliLog("\u2705 \u63A5\u5165\u51ED\u636E\u5DF2\u4FDD\u5B58\uFF08\u672C\u673A\u6682\u65E0\u8FD0\u884C\u4E2D\u7684 server\uFF09");
|
|
11148
11577
|
cliLog(` \u8282\u70B9: ${r.nodeId}`);
|
|
11149
11578
|
cliLog(` \u7F51\u5173: ${r.gatewayUrl ?? "\uFF08\u672A\u4E0B\u53D1\uFF09"}`);
|
|
11150
11579
|
cliLog(` \u6570\u636E\u76EE\u5F55: ${r.dataDir}`);
|
|
11151
11580
|
cliLog(" \u4E0B\u6B21\u542F\u52A8 server \u5373\u81EA\u52A8\u63A5\u5165\uFF1B\u6216\u8FD0\u884C zqagent serve \u5E38\u9A7B\u4E3A\u8282\u70B9\u3002");
|
|
11152
|
-
if (
|
|
11581
|
+
if (r.targetedService) {
|
|
11153
11582
|
cliLog("");
|
|
11154
|
-
cliLog("\
|
|
11155
|
-
cliLog("
|
|
11156
|
-
cliLog("
|
|
11157
|
-
|
|
11158
|
-
cliLog("
|
|
11583
|
+
cliLog("\u2705 \u51ED\u636E\u5DF2\u5199\u5165\u672C\u673A\u6258\u7BA1\u670D\u52A1\u7684\u6570\u636E\u76EE\u5F55\uFF0C\u670D\u52A1\u542F\u52A8\u65F6\u81EA\u52A8\u63A5\u5165\uFF0C\u65E0\u9700 --data-dir\u3002");
|
|
11584
|
+
cliLog(" \u7ACB\u5373\u751F\u6548\uFF1A\u91CD\u542F\u8BE5\u670D\u52A1\uFF08Linux: systemctl restart zqagent\uFF1B");
|
|
11585
|
+
cliLog(" macOS: launchctl kickstart -k gui/$(id -u)/com.zqagent.node\uFF09\u3002");
|
|
11586
|
+
} else if (r.runningServiceDirs.length > 0) {
|
|
11587
|
+
cliLog("");
|
|
11588
|
+
cliLog("\u26A0\uFE0F \u672C\u673A\u6709\u6B63\u5728\u8FD0\u884C\u7684\u8282\u70B9\uFF0C\u4F46\u6570\u636E\u76EE\u5F55\u4E0E\u672C\u6B21\u5199\u5165\u7684\u4E0D\u4E00\u81F4\uFF1A");
|
|
11589
|
+
cliLog(` \u672C\u6B21\u5199\u5165: ${r.dataDir}`);
|
|
11590
|
+
for (const d of r.runningServiceDirs) cliLog(` \u670D\u52A1\u4F7F\u7528: ${d}`);
|
|
11591
|
+
cliLog(" \u6B63\u5728\u8FD0\u884C\u7684\u670D\u52A1\u8BFB\u4E0D\u5230\u8FD9\u4EFD\u51ED\u636E\uFF0CHub \u4F1A\u4E00\u76F4\u663E\u793A\u672A\u63A5\u5165\u3002");
|
|
11592
|
+
cliLog(" \u8BF7\u786E\u8BA4\u670D\u52A1\u7684\u6570\u636E\u76EE\u5F55\u540E\u91CD\u65B0\u6267\u884C\uFF08\u63A5\u5165\u7801\u4E00\u6B21\u6027\uFF0C\u9700\u8981\u91CD\u65B0\u751F\u6210\uFF09\uFF1A");
|
|
11593
|
+
cliLog(` zqagent link --hub <Hub\u5730\u5740> --code <\u65B0\u63A5\u5165\u7801> --data-dir "${r.runningServiceDirs[0]}"`);
|
|
11594
|
+
} else if (!r.explicitDataDir) {
|
|
11595
|
+
cliLog("");
|
|
11596
|
+
cliLog("\u26A0\uFE0F \u672A\u53D1\u73B0\u672C\u673A\u8282\u70B9\u670D\u52A1\uFF0C\u51ED\u636E\u5199\u5165\u4E86\u5F53\u524D\u76EE\u5F55\u4E0B\u7684 .zqagent_data\u3002");
|
|
11597
|
+
cliLog(" \u5982\u679C\u8FD9\u53F0\u673A\u5668\u6253\u7B97\u957F\u671F\u8FD0\u884C\u8282\u70B9\uFF0C\u8BF7\u5148\u5B89\u88C5\u5F00\u673A\u670D\u52A1\uFF0C\u4E4B\u540E link \u4F1A\u81EA\u52A8\u5199\u5165\u5B83\u7684\u76EE\u5F55\uFF1A");
|
|
11598
|
+
cliLog(" curl -fsSL https://agent.cd-zq.com/install.sh | sh");
|
|
11599
|
+
cliLog(` \uFF08\u670D\u52A1\u9ED8\u8BA4\u6570\u636E\u76EE\u5F55\uFF1A${installDataDirHint()}\uFF09`);
|
|
11159
11600
|
}
|
|
11160
11601
|
}
|
|
11161
11602
|
return true;
|
|
@@ -11175,21 +11616,21 @@ import * as path38 from "path";
|
|
|
11175
11616
|
|
|
11176
11617
|
// src/server/session.ts
|
|
11177
11618
|
init_esm_shims();
|
|
11178
|
-
import * as
|
|
11619
|
+
import * as path26 from "path";
|
|
11179
11620
|
import { AsyncLocalStorage } from "async_hooks";
|
|
11180
11621
|
|
|
11181
11622
|
// src/server/mcpConfig.ts
|
|
11182
11623
|
init_esm_shims();
|
|
11183
|
-
import
|
|
11184
|
-
import
|
|
11624
|
+
import fs20 from "fs";
|
|
11625
|
+
import path24 from "path";
|
|
11185
11626
|
function isValidMcpConfig(v) {
|
|
11186
11627
|
return !!v && typeof v === "object" && typeof v.name === "string" && (v.type === "stdio" || v.type === "http");
|
|
11187
11628
|
}
|
|
11188
11629
|
function readConfigFile(file) {
|
|
11189
11630
|
if (!file) return [];
|
|
11190
11631
|
try {
|
|
11191
|
-
if (!
|
|
11192
|
-
const raw = JSON.parse(
|
|
11632
|
+
if (!fs20.existsSync(file)) return [];
|
|
11633
|
+
const raw = JSON.parse(fs20.readFileSync(file, "utf8"));
|
|
11193
11634
|
const list = Array.isArray(raw) ? raw : raw && typeof raw === "object" && Array.isArray(raw.servers) ? raw.servers : [];
|
|
11194
11635
|
return list.filter(isValidMcpConfig);
|
|
11195
11636
|
} catch (err) {
|
|
@@ -11201,7 +11642,7 @@ function hasServerMcpConfig() {
|
|
|
11201
11642
|
if (readConfigFile(process.env.MCP_CONFIG_PATH).length > 0) return true;
|
|
11202
11643
|
const workspace = process.env.WORKSPACE;
|
|
11203
11644
|
if (!workspace) return false;
|
|
11204
|
-
return readConfigFile(
|
|
11645
|
+
return readConfigFile(path24.join(workspace, ".agent", "mcp.json")).length > 0;
|
|
11205
11646
|
}
|
|
11206
11647
|
function loadServerMcpConfigs(tenant) {
|
|
11207
11648
|
const fromEnv = readConfigFile(process.env.MCP_CONFIG_PATH);
|
|
@@ -11211,7 +11652,7 @@ function loadServerMcpConfigs(tenant) {
|
|
|
11211
11652
|
}
|
|
11212
11653
|
const workspace = tenant.workspaceRoot ?? process.env.WORKSPACE;
|
|
11213
11654
|
if (workspace)
|
|
11214
|
-
return readConfigFile(
|
|
11655
|
+
return readConfigFile(path24.join(workspace, ".agent", "mcp.json"));
|
|
11215
11656
|
return [];
|
|
11216
11657
|
}
|
|
11217
11658
|
|
|
@@ -11356,8 +11797,8 @@ function resolveSessionProvider(store, tenant, providerId) {
|
|
|
11356
11797
|
|
|
11357
11798
|
// src/server/usage.ts
|
|
11358
11799
|
init_esm_shims();
|
|
11359
|
-
import * as
|
|
11360
|
-
import * as
|
|
11800
|
+
import * as fs21 from "fs";
|
|
11801
|
+
import * as path25 from "path";
|
|
11361
11802
|
var LEDGER_RETENTION_MONTHS = 12;
|
|
11362
11803
|
var USAGE_SCHEMA = 1;
|
|
11363
11804
|
var DEFAULT_PRICING = {
|
|
@@ -11438,15 +11879,15 @@ function retainedMonths(now = /* @__PURE__ */ new Date()) {
|
|
|
11438
11879
|
return out;
|
|
11439
11880
|
}
|
|
11440
11881
|
function atomicWrite(file, content) {
|
|
11441
|
-
|
|
11882
|
+
fs21.mkdirSync(path25.dirname(file), { recursive: true });
|
|
11442
11883
|
const tmp = `${file}.tmp`;
|
|
11443
|
-
|
|
11444
|
-
|
|
11884
|
+
fs21.writeFileSync(tmp, content, "utf-8");
|
|
11885
|
+
fs21.renameSync(tmp, file);
|
|
11445
11886
|
}
|
|
11446
11887
|
var UsageLedger = class {
|
|
11447
11888
|
constructor(root) {
|
|
11448
11889
|
this.root = root;
|
|
11449
|
-
this.dir =
|
|
11890
|
+
this.dir = path25.join(root, "usage");
|
|
11450
11891
|
}
|
|
11451
11892
|
root;
|
|
11452
11893
|
dir;
|
|
@@ -11459,18 +11900,18 @@ var UsageLedger = class {
|
|
|
11459
11900
|
return this.dir;
|
|
11460
11901
|
}
|
|
11461
11902
|
ledgerFile(month) {
|
|
11462
|
-
return
|
|
11903
|
+
return path25.join(this.ledgerDir, `ledger-${month}.jsonl`);
|
|
11463
11904
|
}
|
|
11464
11905
|
get rollupFile() {
|
|
11465
|
-
return
|
|
11906
|
+
return path25.join(this.ledgerDir, "rollup.json");
|
|
11466
11907
|
}
|
|
11467
11908
|
get pricingFile() {
|
|
11468
|
-
return
|
|
11909
|
+
return path25.join(this.ledgerDir, "pricing.json");
|
|
11469
11910
|
}
|
|
11470
11911
|
// ===================== 初始化 =====================
|
|
11471
11912
|
init(now = /* @__PURE__ */ new Date()) {
|
|
11472
11913
|
if (this.inited) return;
|
|
11473
|
-
|
|
11914
|
+
fs21.mkdirSync(this.ledgerDir, { recursive: true });
|
|
11474
11915
|
this.pricing = this.loadPricing();
|
|
11475
11916
|
this.rollup = this.loadRollup(now);
|
|
11476
11917
|
this.pruneLedgers(now);
|
|
@@ -11478,7 +11919,7 @@ var UsageLedger = class {
|
|
|
11478
11919
|
}
|
|
11479
11920
|
loadPricing() {
|
|
11480
11921
|
try {
|
|
11481
|
-
const raw =
|
|
11922
|
+
const raw = fs21.readFileSync(this.pricingFile, "utf-8");
|
|
11482
11923
|
const parsed = JSON.parse(raw);
|
|
11483
11924
|
const vendors = {};
|
|
11484
11925
|
for (const v of /* @__PURE__ */ new Set([
|
|
@@ -11507,7 +11948,7 @@ var UsageLedger = class {
|
|
|
11507
11948
|
}
|
|
11508
11949
|
loadRollup(now) {
|
|
11509
11950
|
try {
|
|
11510
|
-
const raw =
|
|
11951
|
+
const raw = fs21.readFileSync(this.rollupFile, "utf-8");
|
|
11511
11952
|
const parsed = JSON.parse(raw);
|
|
11512
11953
|
return {
|
|
11513
11954
|
schema: USAGE_SCHEMA,
|
|
@@ -11534,10 +11975,10 @@ var UsageLedger = class {
|
|
|
11534
11975
|
const keep = retainedMonths(now);
|
|
11535
11976
|
let changed = false;
|
|
11536
11977
|
try {
|
|
11537
|
-
for (const f of
|
|
11978
|
+
for (const f of fs21.readdirSync(this.ledgerDir)) {
|
|
11538
11979
|
const m = /^ledger-(\d{4}-\d{2})\.jsonl$/.exec(f);
|
|
11539
11980
|
if (m && !keep.has(m[1])) {
|
|
11540
|
-
|
|
11981
|
+
fs21.unlinkSync(path25.join(this.ledgerDir, f));
|
|
11541
11982
|
}
|
|
11542
11983
|
}
|
|
11543
11984
|
} catch {
|
|
@@ -11614,7 +12055,7 @@ var UsageLedger = class {
|
|
|
11614
12055
|
};
|
|
11615
12056
|
const line = JSON.stringify(rec) + "\n";
|
|
11616
12057
|
try {
|
|
11617
|
-
|
|
12058
|
+
fs21.appendFileSync(this.ledgerFile(monthOf(rec.ts)), line);
|
|
11618
12059
|
} catch (e) {
|
|
11619
12060
|
console.error(`[usage] \u5199\u8D26\u672C\u5931\u8D25: ${String(e)}`);
|
|
11620
12061
|
}
|
|
@@ -11786,10 +12227,10 @@ var UsageLedger = class {
|
|
|
11786
12227
|
const rows = [];
|
|
11787
12228
|
for (const month of months) {
|
|
11788
12229
|
const file = this.ledgerFile(month);
|
|
11789
|
-
if (!
|
|
12230
|
+
if (!fs21.existsSync(file)) continue;
|
|
11790
12231
|
let content = "";
|
|
11791
12232
|
try {
|
|
11792
|
-
content =
|
|
12233
|
+
content = fs21.readFileSync(file, "utf-8");
|
|
11793
12234
|
} catch {
|
|
11794
12235
|
continue;
|
|
11795
12236
|
}
|
|
@@ -11898,10 +12339,10 @@ var UsageLedger = class {
|
|
|
11898
12339
|
const seen = /* @__PURE__ */ new Set();
|
|
11899
12340
|
for (const month of this.monthsInRange("", "")) {
|
|
11900
12341
|
const file = this.ledgerFile(month);
|
|
11901
|
-
if (!
|
|
12342
|
+
if (!fs21.existsSync(file)) continue;
|
|
11902
12343
|
let content = "";
|
|
11903
12344
|
try {
|
|
11904
|
-
content =
|
|
12345
|
+
content = fs21.readFileSync(file, "utf-8");
|
|
11905
12346
|
} catch {
|
|
11906
12347
|
continue;
|
|
11907
12348
|
}
|
|
@@ -12006,11 +12447,11 @@ function isAffirmative(answer) {
|
|
|
12006
12447
|
return /^(yes|approve|同意|批准|允许|确定|可以|好的|确认)/.test(a);
|
|
12007
12448
|
}
|
|
12008
12449
|
function defer() {
|
|
12009
|
-
let
|
|
12450
|
+
let resolve24;
|
|
12010
12451
|
const promise = new Promise((r) => {
|
|
12011
|
-
|
|
12452
|
+
resolve24 = r;
|
|
12012
12453
|
});
|
|
12013
|
-
return { promise, resolve:
|
|
12454
|
+
return { promise, resolve: resolve24 };
|
|
12014
12455
|
}
|
|
12015
12456
|
var SessionManager = class {
|
|
12016
12457
|
constructor(store, approvalTimeoutMs = APPROVAL_TIMEOUT_MS, opts = {}) {
|
|
@@ -12582,11 +13023,11 @@ data: ${JSON.stringify({ sessionId, seq: entry.seq, ts: entry.ts, data: entry.da
|
|
|
12582
13023
|
status: "pending",
|
|
12583
13024
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
12584
13025
|
};
|
|
12585
|
-
const { promise, resolve:
|
|
13026
|
+
const { promise, resolve: resolve24 } = defer();
|
|
12586
13027
|
const timer = setTimeout(() => {
|
|
12587
13028
|
this._recycleApproval(rt, id);
|
|
12588
13029
|
}, this.approvalTimeoutMs);
|
|
12589
|
-
rt.pendingApprovals.set(id, { promise, resolve:
|
|
13030
|
+
rt.pendingApprovals.set(id, { promise, resolve: resolve24, record, timer });
|
|
12590
13031
|
rt.approvals.set(id, record);
|
|
12591
13032
|
this._setStatus(rt, "waiting_approval");
|
|
12592
13033
|
this._persist(rt);
|
|
@@ -12664,11 +13105,11 @@ data: ${JSON.stringify({ sessionId, seq: entry.seq, ts: entry.ts, data: entry.da
|
|
|
12664
13105
|
status: "pending",
|
|
12665
13106
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
12666
13107
|
};
|
|
12667
|
-
const { promise, resolve:
|
|
13108
|
+
const { promise, resolve: resolve24 } = defer();
|
|
12668
13109
|
const timer = setTimeout(() => {
|
|
12669
13110
|
this._recycleQuestion(rt, qid);
|
|
12670
13111
|
}, this.approvalTimeoutMs);
|
|
12671
|
-
rt.pendingQuestions.set(qid, { promise, resolve:
|
|
13112
|
+
rt.pendingQuestions.set(qid, { promise, resolve: resolve24, record, timer });
|
|
12672
13113
|
rt.questions.set(qid, record);
|
|
12673
13114
|
this._setStatus(rt, "waiting_question");
|
|
12674
13115
|
this._persist(rt);
|
|
@@ -12977,7 +13418,7 @@ data: ${JSON.stringify(entry.data)}
|
|
|
12977
13418
|
if (rt.mcpReady) {
|
|
12978
13419
|
await Promise.race([
|
|
12979
13420
|
rt.mcpReady,
|
|
12980
|
-
new Promise((
|
|
13421
|
+
new Promise((resolve24) => setTimeout(resolve24, 15e3))
|
|
12981
13422
|
]).catch(() => void 0);
|
|
12982
13423
|
}
|
|
12983
13424
|
for await (const event of gen) {
|
|
@@ -13212,7 +13653,7 @@ data: ${JSON.stringify(entry.data)}
|
|
|
13212
13653
|
softThresholdPct: parseRatio(process.env.COMPACTION_SOFT_THRESHOLD_PCT),
|
|
13213
13654
|
capTokens: parseOptionalPositiveNumber(process.env.COMPACTION_CAP_TOKENS) ?? null,
|
|
13214
13655
|
// 超预算工具结果按租户/工作区隔离落盘(多租户共用一个状态目录会混内容)
|
|
13215
|
-
toolResultDir:
|
|
13656
|
+
toolResultDir: path26.join(workspace, ".agent", "tool-results")
|
|
13216
13657
|
});
|
|
13217
13658
|
engine.setApprover(this._makeApprover(rt));
|
|
13218
13659
|
const mcpConfigs = loadServerMcpConfigs(tenant);
|
|
@@ -13393,11 +13834,11 @@ var ApiError = class extends Error {
|
|
|
13393
13834
|
// src/server/routes.ts
|
|
13394
13835
|
init_esm_shims();
|
|
13395
13836
|
import { createServer } from "http";
|
|
13396
|
-
import * as
|
|
13837
|
+
import * as path31 from "path";
|
|
13397
13838
|
|
|
13398
13839
|
// src/server/projects.ts
|
|
13399
13840
|
init_esm_shims();
|
|
13400
|
-
import * as
|
|
13841
|
+
import * as path27 from "path";
|
|
13401
13842
|
var DEFAULT_MODEL = () => process.env.OPENAI_MODEL || process.env.MODEL || "gpt-4o";
|
|
13402
13843
|
function toProjectSummary(store, tenant) {
|
|
13403
13844
|
return {
|
|
@@ -13530,9 +13971,9 @@ function createProject(store, input) {
|
|
|
13530
13971
|
if (store.loadTenant(id)) {
|
|
13531
13972
|
throw new ApiError(409, "project_exists", `\u9879\u76EE ${id} \u5DF2\u5B58\u5728`);
|
|
13532
13973
|
}
|
|
13533
|
-
const workspaceRoot = typeof raw.workspaceRoot === "string" && raw.workspaceRoot.trim() ?
|
|
13974
|
+
const workspaceRoot = typeof raw.workspaceRoot === "string" && raw.workspaceRoot.trim() ? path27.resolve(raw.workspaceRoot.trim()) : void 0;
|
|
13534
13975
|
const explicitName = typeof raw.name === "string" && raw.name.trim() ? raw.name.trim() : "";
|
|
13535
|
-
const defaultName = workspaceRoot ?
|
|
13976
|
+
const defaultName = workspaceRoot ? path27.basename(workspaceRoot) : id;
|
|
13536
13977
|
const tenant = {
|
|
13537
13978
|
id,
|
|
13538
13979
|
name: explicitName || defaultName,
|
|
@@ -13562,7 +14003,7 @@ function buildNodeInfo(store, opts) {
|
|
|
13562
14003
|
nodeId: opts.nodeId ?? ensureNodeId2(store),
|
|
13563
14004
|
platform: process.platform,
|
|
13564
14005
|
mode: process.env.NODE_MODE ?? "standalone",
|
|
13565
|
-
version: "0.2.
|
|
14006
|
+
version: "0.2.11",
|
|
13566
14007
|
admin: opts.admin,
|
|
13567
14008
|
projects: opts.projects
|
|
13568
14009
|
};
|
|
@@ -13741,34 +14182,34 @@ async function handleHubProxy(req2, res) {
|
|
|
13741
14182
|
|
|
13742
14183
|
// src/server/fsBrowser.ts
|
|
13743
14184
|
init_esm_shims();
|
|
13744
|
-
import * as
|
|
13745
|
-
import * as
|
|
13746
|
-
import * as
|
|
14185
|
+
import * as fs22 from "fs";
|
|
14186
|
+
import * as os6 from "os";
|
|
14187
|
+
import * as path28 from "path";
|
|
13747
14188
|
var MAX_ENTRIES = 2e3;
|
|
13748
14189
|
var DEFAULT_SEARCH_LIMIT = 200;
|
|
13749
14190
|
var MAX_SEARCH_LIMIT = 1e3;
|
|
13750
14191
|
function listDirs(input) {
|
|
13751
|
-
const base = (input ?? "").trim() ||
|
|
13752
|
-
const target =
|
|
14192
|
+
const base = (input ?? "").trim() || os6.homedir();
|
|
14193
|
+
const target = path28.resolve(base);
|
|
13753
14194
|
let st;
|
|
13754
14195
|
try {
|
|
13755
|
-
st =
|
|
14196
|
+
st = fs22.statSync(target);
|
|
13756
14197
|
} catch {
|
|
13757
14198
|
throw new Error(`\u8DEF\u5F84\u4E0D\u5B58\u5728: ${target}`);
|
|
13758
14199
|
}
|
|
13759
14200
|
if (!st.isDirectory()) throw new Error(`\u4E0D\u662F\u76EE\u5F55: ${target}`);
|
|
13760
14201
|
let dirents;
|
|
13761
14202
|
try {
|
|
13762
|
-
dirents =
|
|
14203
|
+
dirents = fs22.readdirSync(target, { withFileTypes: true });
|
|
13763
14204
|
} catch {
|
|
13764
14205
|
throw new Error(`\u65E0\u6CD5\u8BFB\u53D6\u76EE\u5F55\uFF08\u6743\u9650\u4E0D\u8DB3\uFF1F\uFF09: ${target}`);
|
|
13765
14206
|
}
|
|
13766
14207
|
const entries = dirents.map((d) => {
|
|
13767
|
-
const full =
|
|
14208
|
+
const full = path28.join(target, d.name);
|
|
13768
14209
|
let isDir = d.isDirectory();
|
|
13769
14210
|
if (d.isSymbolicLink()) {
|
|
13770
14211
|
try {
|
|
13771
|
-
isDir =
|
|
14212
|
+
isDir = fs22.statSync(full).isDirectory();
|
|
13772
14213
|
} catch {
|
|
13773
14214
|
}
|
|
13774
14215
|
}
|
|
@@ -13777,7 +14218,7 @@ function listDirs(input) {
|
|
|
13777
14218
|
entries.sort(
|
|
13778
14219
|
(a, b) => a.type === b.type ? a.name.localeCompare(b.name) : a.type === "dir" ? -1 : 1
|
|
13779
14220
|
);
|
|
13780
|
-
const parentDir =
|
|
14221
|
+
const parentDir = path28.dirname(target);
|
|
13781
14222
|
return {
|
|
13782
14223
|
path: target,
|
|
13783
14224
|
parent: parentDir !== target ? parentDir : null,
|
|
@@ -13808,7 +14249,7 @@ var NAME_CACHE_MAX_DIRS = 4;
|
|
|
13808
14249
|
var NAME_CACHE_MAX_ENTRIES = 5e4;
|
|
13809
14250
|
var nameCache = /* @__PURE__ */ new Map();
|
|
13810
14251
|
function invalidateDirNames(target) {
|
|
13811
|
-
nameCache.delete(
|
|
14252
|
+
nameCache.delete(path28.resolve(target));
|
|
13812
14253
|
}
|
|
13813
14254
|
async function loadDirNames(target) {
|
|
13814
14255
|
const now = Date.now();
|
|
@@ -13820,7 +14261,7 @@ async function loadDirNames(target) {
|
|
|
13820
14261
|
}
|
|
13821
14262
|
let dirents;
|
|
13822
14263
|
try {
|
|
13823
|
-
dirents = await
|
|
14264
|
+
dirents = await fs22.promises.readdir(target, { withFileTypes: true });
|
|
13824
14265
|
} catch {
|
|
13825
14266
|
throw new Error(`\u65E0\u6CD5\u8BFB\u53D6\u76EE\u5F55\uFF08\u6743\u9650\u4E0D\u8DB3\uFF1F\uFF09: ${target}`);
|
|
13826
14267
|
}
|
|
@@ -13843,22 +14284,22 @@ async function loadDirNames(target) {
|
|
|
13843
14284
|
return entries;
|
|
13844
14285
|
}
|
|
13845
14286
|
async function toDirEntry(dir, e) {
|
|
13846
|
-
const full =
|
|
14287
|
+
const full = path28.join(dir, e.name);
|
|
13847
14288
|
let isDir = e.isDir;
|
|
13848
14289
|
if (e.isLink) {
|
|
13849
14290
|
try {
|
|
13850
|
-
isDir = (await
|
|
14291
|
+
isDir = (await fs22.promises.stat(full)).isDirectory();
|
|
13851
14292
|
} catch {
|
|
13852
14293
|
}
|
|
13853
14294
|
}
|
|
13854
14295
|
return { name: e.name, path: full, type: isDir ? "dir" : "file" };
|
|
13855
14296
|
}
|
|
13856
14297
|
async function searchDirs(input, query, limit) {
|
|
13857
|
-
const base = (input ?? "").trim() ||
|
|
13858
|
-
const target =
|
|
14298
|
+
const base = (input ?? "").trim() || os6.homedir();
|
|
14299
|
+
const target = path28.resolve(base);
|
|
13859
14300
|
let st;
|
|
13860
14301
|
try {
|
|
13861
|
-
st = await
|
|
14302
|
+
st = await fs22.promises.stat(target);
|
|
13862
14303
|
} catch {
|
|
13863
14304
|
throw new Error(`\u8DEF\u5F84\u4E0D\u5B58\u5728: ${target}`);
|
|
13864
14305
|
}
|
|
@@ -13888,7 +14329,7 @@ async function searchDirs(input, query, limit) {
|
|
|
13888
14329
|
);
|
|
13889
14330
|
const hit = scored.slice(0, max);
|
|
13890
14331
|
const entries = await Promise.all(hit.map(({ entry }) => toDirEntry(target, entry)));
|
|
13891
|
-
const parentDir =
|
|
14332
|
+
const parentDir = path28.dirname(target);
|
|
13892
14333
|
return {
|
|
13893
14334
|
path: target,
|
|
13894
14335
|
parent: parentDir !== target ? parentDir : null,
|
|
@@ -13899,52 +14340,52 @@ async function searchDirs(input, query, limit) {
|
|
|
13899
14340
|
};
|
|
13900
14341
|
}
|
|
13901
14342
|
function makeDirIn(parentInput, name) {
|
|
13902
|
-
const parent =
|
|
14343
|
+
const parent = path28.resolve((parentInput ?? "").trim() || os6.homedir());
|
|
13903
14344
|
const clean = (name ?? "").trim();
|
|
13904
14345
|
if (!clean) throw new Error("\u76EE\u5F55\u540D\u4E0D\u80FD\u4E3A\u7A7A");
|
|
13905
14346
|
if (clean === "." || clean === "..") throw new Error("\u76EE\u5F55\u540D\u975E\u6CD5");
|
|
13906
|
-
const target =
|
|
13907
|
-
const rel =
|
|
13908
|
-
if (!rel || rel.startsWith("..") ||
|
|
14347
|
+
const target = path28.resolve(parent, clean);
|
|
14348
|
+
const rel = path28.relative(parent, target);
|
|
14349
|
+
if (!rel || rel.startsWith("..") || path28.isAbsolute(rel)) {
|
|
13909
14350
|
throw new Error("\u76EE\u5F55\u540D\u4E0D\u80FD\u8D8A\u51FA\u5F53\u524D\u76EE\u5F55");
|
|
13910
14351
|
}
|
|
13911
14352
|
let st = null;
|
|
13912
14353
|
try {
|
|
13913
|
-
st =
|
|
14354
|
+
st = fs22.statSync(target);
|
|
13914
14355
|
} catch {
|
|
13915
14356
|
st = null;
|
|
13916
14357
|
}
|
|
13917
14358
|
if (st && !st.isDirectory()) throw new Error(`\u5DF2\u5B58\u5728\u540C\u540D\u6587\u4EF6: ${target}`);
|
|
13918
14359
|
try {
|
|
13919
|
-
|
|
14360
|
+
fs22.mkdirSync(target, { recursive: true });
|
|
13920
14361
|
} catch (e) {
|
|
13921
14362
|
throw new Error(`\u521B\u5EFA\u76EE\u5F55\u5931\u8D25: ${e instanceof Error ? e.message : String(e)}`);
|
|
13922
14363
|
}
|
|
13923
14364
|
invalidateDirNames(parent);
|
|
13924
|
-
return { name:
|
|
14365
|
+
return { name: path28.basename(target), path: target, type: "dir" };
|
|
13925
14366
|
}
|
|
13926
14367
|
|
|
13927
14368
|
// src/server/projectFiles.ts
|
|
13928
14369
|
init_esm_shims();
|
|
13929
|
-
import * as
|
|
13930
|
-
import * as
|
|
14370
|
+
import * as fs23 from "fs";
|
|
14371
|
+
import * as path29 from "path";
|
|
13931
14372
|
var MAX_FILE_BYTES = 2 * 1024 * 1024;
|
|
13932
14373
|
var MAX_DOWNLOAD_BYTES = 16 * 1024 * 1024;
|
|
13933
14374
|
var MAX_ENTRIES2 = 2e3;
|
|
13934
14375
|
function toPosix(p) {
|
|
13935
|
-
return p.split(
|
|
14376
|
+
return p.split(path29.sep).join("/");
|
|
13936
14377
|
}
|
|
13937
14378
|
function projectRoot(workspaceRoot) {
|
|
13938
14379
|
const r = (workspaceRoot ?? "").trim();
|
|
13939
14380
|
if (!r) {
|
|
13940
14381
|
throw new Error("\u9879\u76EE\u672A\u8BBE\u7F6E\u5DE5\u4F5C\u533A\u76EE\u5F55\uFF08workspaceRoot\uFF09\uFF0C\u65E0\u6CD5\u6D4F\u89C8\u6587\u4EF6");
|
|
13941
14382
|
}
|
|
13942
|
-
const abs =
|
|
13943
|
-
if (!
|
|
14383
|
+
const abs = path29.resolve(r);
|
|
14384
|
+
if (!fs23.existsSync(abs)) {
|
|
13944
14385
|
throw new Error(`\u5DE5\u4F5C\u533A\u76EE\u5F55\u4E0D\u5B58\u5728: ${abs}`);
|
|
13945
14386
|
}
|
|
13946
14387
|
try {
|
|
13947
|
-
return
|
|
14388
|
+
return fs23.realpathSync(abs);
|
|
13948
14389
|
} catch {
|
|
13949
14390
|
return abs;
|
|
13950
14391
|
}
|
|
@@ -13962,37 +14403,37 @@ function listProjectFiles(workspaceRoot, relPath) {
|
|
|
13962
14403
|
const dir = resolveWithin(base, relPath ?? "");
|
|
13963
14404
|
let st;
|
|
13964
14405
|
try {
|
|
13965
|
-
st =
|
|
14406
|
+
st = fs23.statSync(dir);
|
|
13966
14407
|
} catch {
|
|
13967
|
-
throw new Error(`\u76EE\u5F55\u4E0D\u5B58\u5728: ${toPosix(
|
|
14408
|
+
throw new Error(`\u76EE\u5F55\u4E0D\u5B58\u5728: ${toPosix(path29.relative(base, dir)) || "/"}`);
|
|
13968
14409
|
}
|
|
13969
14410
|
if (!st.isDirectory()) throw new Error("\u76EE\u6807\u4E0D\u662F\u76EE\u5F55");
|
|
13970
14411
|
let dirents;
|
|
13971
14412
|
try {
|
|
13972
|
-
dirents =
|
|
14413
|
+
dirents = fs23.readdirSync(dir, { withFileTypes: true });
|
|
13973
14414
|
} catch {
|
|
13974
14415
|
throw new Error("\u65E0\u6CD5\u8BFB\u53D6\u76EE\u5F55\uFF08\u6743\u9650\u4E0D\u8DB3\uFF1F\uFF09");
|
|
13975
14416
|
}
|
|
13976
14417
|
const entries = dirents.map((d) => {
|
|
13977
|
-
const full =
|
|
14418
|
+
const full = path29.join(dir, d.name);
|
|
13978
14419
|
let isDir = d.isDirectory();
|
|
13979
14420
|
if (d.isSymbolicLink()) {
|
|
13980
14421
|
try {
|
|
13981
|
-
isDir =
|
|
14422
|
+
isDir = fs23.statSync(full).isDirectory();
|
|
13982
14423
|
} catch {
|
|
13983
14424
|
}
|
|
13984
14425
|
}
|
|
13985
14426
|
let size = 0;
|
|
13986
14427
|
let mtime = "";
|
|
13987
14428
|
try {
|
|
13988
|
-
const s =
|
|
14429
|
+
const s = fs23.statSync(full);
|
|
13989
14430
|
size = s.size;
|
|
13990
14431
|
mtime = s.mtime.toISOString();
|
|
13991
14432
|
} catch {
|
|
13992
14433
|
}
|
|
13993
14434
|
return {
|
|
13994
14435
|
name: d.name,
|
|
13995
|
-
path: toPosix(
|
|
14436
|
+
path: toPosix(path29.relative(base, full)),
|
|
13996
14437
|
type: isDir ? "dir" : "file",
|
|
13997
14438
|
size,
|
|
13998
14439
|
mtime
|
|
@@ -14001,12 +14442,12 @@ function listProjectFiles(workspaceRoot, relPath) {
|
|
|
14001
14442
|
entries.sort(
|
|
14002
14443
|
(a, b) => a.type === b.type ? a.name.localeCompare(b.name) : a.type === "dir" ? -1 : 1
|
|
14003
14444
|
);
|
|
14004
|
-
const relDir = toPosix(
|
|
14005
|
-
const parentAbs =
|
|
14445
|
+
const relDir = toPosix(path29.relative(base, dir));
|
|
14446
|
+
const parentAbs = path29.dirname(dir);
|
|
14006
14447
|
return {
|
|
14007
14448
|
root: base,
|
|
14008
14449
|
path: relDir,
|
|
14009
|
-
parent: isWithinRoot(base, parentAbs) ? toPosix(
|
|
14450
|
+
parent: isWithinRoot(base, parentAbs) ? toPosix(path29.relative(base, parentAbs)) : null,
|
|
14010
14451
|
entries: entries.slice(0, MAX_ENTRIES2)
|
|
14011
14452
|
};
|
|
14012
14453
|
}
|
|
@@ -14015,17 +14456,17 @@ function readProjectFile(workspaceRoot, relPath) {
|
|
|
14015
14456
|
const file = resolveWithin(base, relPath ?? "");
|
|
14016
14457
|
let st;
|
|
14017
14458
|
try {
|
|
14018
|
-
st =
|
|
14459
|
+
st = fs23.statSync(file);
|
|
14019
14460
|
} catch {
|
|
14020
14461
|
throw new Error("\u6587\u4EF6\u4E0D\u5B58\u5728");
|
|
14021
14462
|
}
|
|
14022
14463
|
if (!st.isFile()) throw new Error("\u76EE\u6807\u4E0D\u662F\u6587\u4EF6");
|
|
14023
|
-
const buf =
|
|
14464
|
+
const buf = fs23.readFileSync(file);
|
|
14024
14465
|
const binary = isBinary(buf);
|
|
14025
14466
|
const truncated = buf.length > MAX_FILE_BYTES;
|
|
14026
14467
|
const slice = truncated ? buf.subarray(0, MAX_FILE_BYTES) : buf;
|
|
14027
14468
|
return {
|
|
14028
|
-
path: toPosix(
|
|
14469
|
+
path: toPosix(path29.relative(base, file)),
|
|
14029
14470
|
size: st.size,
|
|
14030
14471
|
binary,
|
|
14031
14472
|
truncated,
|
|
@@ -14037,7 +14478,7 @@ function downloadProjectFile(workspaceRoot, relPath) {
|
|
|
14037
14478
|
const file = resolveWithin(base, relPath ?? "");
|
|
14038
14479
|
let st;
|
|
14039
14480
|
try {
|
|
14040
|
-
st =
|
|
14481
|
+
st = fs23.statSync(file);
|
|
14041
14482
|
} catch {
|
|
14042
14483
|
throw new Error("\u6587\u4EF6\u4E0D\u5B58\u5728");
|
|
14043
14484
|
}
|
|
@@ -14045,10 +14486,10 @@ function downloadProjectFile(workspaceRoot, relPath) {
|
|
|
14045
14486
|
if (st.size > MAX_DOWNLOAD_BYTES) {
|
|
14046
14487
|
throw new Error(`\u6587\u4EF6\u8D85\u8FC7\u4E0B\u8F7D\u4E0A\u9650\uFF08${MAX_DOWNLOAD_BYTES / (1024 * 1024)}MB\uFF09`);
|
|
14047
14488
|
}
|
|
14048
|
-
const buf =
|
|
14489
|
+
const buf = fs23.readFileSync(file);
|
|
14049
14490
|
return {
|
|
14050
|
-
path: toPosix(
|
|
14051
|
-
name:
|
|
14491
|
+
path: toPosix(path29.relative(base, file)),
|
|
14492
|
+
name: path29.basename(file),
|
|
14052
14493
|
size: buf.length,
|
|
14053
14494
|
base64: buf.toString("base64")
|
|
14054
14495
|
};
|
|
@@ -14070,12 +14511,12 @@ function writeProjectFile(workspaceRoot, relPath, content) {
|
|
|
14070
14511
|
throw new Error("\u5185\u5BB9\u8D85\u8FC7 2MB \u4E0A\u9650\uFF0C\u65E0\u6CD5\u4FDD\u5B58");
|
|
14071
14512
|
}
|
|
14072
14513
|
try {
|
|
14073
|
-
|
|
14074
|
-
|
|
14514
|
+
fs23.mkdirSync(path29.dirname(file), { recursive: true });
|
|
14515
|
+
fs23.writeFileSync(file, buf);
|
|
14075
14516
|
} catch (e) {
|
|
14076
14517
|
throw new Error(`\u5199\u5165\u5931\u8D25\uFF1A${e instanceof Error ? e.message : String(e)}`);
|
|
14077
14518
|
}
|
|
14078
|
-
return { path: toPosix(
|
|
14519
|
+
return { path: toPosix(path29.relative(base, file)), size: buf.length };
|
|
14079
14520
|
}
|
|
14080
14521
|
function createProjectDir(workspaceRoot, relPath) {
|
|
14081
14522
|
const base = projectRoot(workspaceRoot);
|
|
@@ -14083,26 +14524,26 @@ function createProjectDir(workspaceRoot, relPath) {
|
|
|
14083
14524
|
if (!rel) throw new Error("\u76EE\u5F55\u8DEF\u5F84\u4E0D\u80FD\u4E3A\u7A7A");
|
|
14084
14525
|
const dir = resolveWithin(base, rel);
|
|
14085
14526
|
try {
|
|
14086
|
-
|
|
14527
|
+
fs23.mkdirSync(dir, { recursive: true });
|
|
14087
14528
|
} catch (e) {
|
|
14088
14529
|
throw new Error(`\u521B\u5EFA\u76EE\u5F55\u5931\u8D25\uFF1A${e instanceof Error ? e.message : String(e)}`);
|
|
14089
14530
|
}
|
|
14090
|
-
return { path: toPosix(
|
|
14531
|
+
return { path: toPosix(path29.relative(base, dir)) };
|
|
14091
14532
|
}
|
|
14092
14533
|
function createProjectFile(workspaceRoot, relPath, content = "") {
|
|
14093
14534
|
const base = projectRoot(workspaceRoot);
|
|
14094
14535
|
const rel = (relPath ?? "").trim();
|
|
14095
14536
|
if (!rel) throw new Error("\u6587\u4EF6\u8DEF\u5F84\u4E0D\u80FD\u4E3A\u7A7A");
|
|
14096
14537
|
const file = resolveWithin(base, rel);
|
|
14097
|
-
if (
|
|
14538
|
+
if (fs23.existsSync(file)) throw new Error("\u6587\u4EF6\u5DF2\u5B58\u5728");
|
|
14098
14539
|
const buf = Buffer.from(String(content ?? ""), "utf-8");
|
|
14099
14540
|
try {
|
|
14100
|
-
|
|
14101
|
-
|
|
14541
|
+
fs23.mkdirSync(path29.dirname(file), { recursive: true });
|
|
14542
|
+
fs23.writeFileSync(file, buf);
|
|
14102
14543
|
} catch (e) {
|
|
14103
14544
|
throw new Error(`\u521B\u5EFA\u6587\u4EF6\u5931\u8D25\uFF1A${e instanceof Error ? e.message : String(e)}`);
|
|
14104
14545
|
}
|
|
14105
|
-
return { path: toPosix(
|
|
14546
|
+
return { path: toPosix(path29.relative(base, file)), size: buf.length };
|
|
14106
14547
|
}
|
|
14107
14548
|
function searchProjectFiles(workspaceRoot, query) {
|
|
14108
14549
|
const base = projectRoot(workspaceRoot);
|
|
@@ -14125,7 +14566,7 @@ function searchProjectFiles(workspaceRoot, query) {
|
|
|
14125
14566
|
if (out.length >= LIMIT) return;
|
|
14126
14567
|
let dirents;
|
|
14127
14568
|
try {
|
|
14128
|
-
dirents =
|
|
14569
|
+
dirents = fs23.readdirSync(dir, { withFileTypes: true });
|
|
14129
14570
|
} catch {
|
|
14130
14571
|
return;
|
|
14131
14572
|
}
|
|
@@ -14136,7 +14577,7 @@ function searchProjectFiles(workspaceRoot, query) {
|
|
|
14136
14577
|
let isDir = d.isDirectory();
|
|
14137
14578
|
if (d.isSymbolicLink()) {
|
|
14138
14579
|
try {
|
|
14139
|
-
isDir =
|
|
14580
|
+
isDir = fs23.statSync(path29.join(dir, d.name)).isDirectory();
|
|
14140
14581
|
} catch {
|
|
14141
14582
|
isDir = false;
|
|
14142
14583
|
}
|
|
@@ -14144,7 +14585,7 @@ function searchProjectFiles(workspaceRoot, query) {
|
|
|
14144
14585
|
if (d.name.toLowerCase().includes(q)) {
|
|
14145
14586
|
out.push({ path: rel, type: isDir ? "dir" : "file" });
|
|
14146
14587
|
}
|
|
14147
|
-
if (isDir) walk(
|
|
14588
|
+
if (isDir) walk(path29.join(dir, d.name), rel);
|
|
14148
14589
|
}
|
|
14149
14590
|
};
|
|
14150
14591
|
walk(base, "");
|
|
@@ -14153,8 +14594,8 @@ function searchProjectFiles(workspaceRoot, query) {
|
|
|
14153
14594
|
|
|
14154
14595
|
// src/server/projectOps.ts
|
|
14155
14596
|
init_esm_shims();
|
|
14156
|
-
import * as
|
|
14157
|
-
import * as
|
|
14597
|
+
import * as os7 from "os";
|
|
14598
|
+
import * as path30 from "path";
|
|
14158
14599
|
var MAX_STDOUT2 = 2e4;
|
|
14159
14600
|
var MAX_STDERR2 = 1e4;
|
|
14160
14601
|
var MAX_BUFFER3 = 1024 * 1024 * 5;
|
|
@@ -14168,7 +14609,7 @@ function resolveInvocation2(spec, prepared) {
|
|
|
14168
14609
|
}
|
|
14169
14610
|
function workRoot(workspaceRoot) {
|
|
14170
14611
|
const r = (workspaceRoot ?? "").trim();
|
|
14171
|
-
return r ?
|
|
14612
|
+
return r ? path30.resolve(r) : os7.homedir();
|
|
14172
14613
|
}
|
|
14173
14614
|
async function runProjectCommand(workspaceRoot, command, timeoutSeconds) {
|
|
14174
14615
|
const cmd = String(command ?? "");
|
|
@@ -14479,11 +14920,11 @@ function projectStats(manager, tenantId) {
|
|
|
14479
14920
|
|
|
14480
14921
|
// src/server/nodeHost.ts
|
|
14481
14922
|
init_esm_shims();
|
|
14482
|
-
import * as
|
|
14483
|
-
import * as
|
|
14923
|
+
import * as fs24 from "fs";
|
|
14924
|
+
import * as os8 from "os";
|
|
14484
14925
|
function diskInfo(pathStr) {
|
|
14485
14926
|
try {
|
|
14486
|
-
const st =
|
|
14927
|
+
const st = fs24.statfsSync(pathStr);
|
|
14487
14928
|
return {
|
|
14488
14929
|
path: pathStr,
|
|
14489
14930
|
total: Number(st.blocks) * Number(st.bsize),
|
|
@@ -14495,7 +14936,7 @@ function diskInfo(pathStr) {
|
|
|
14495
14936
|
}
|
|
14496
14937
|
function networkInfo() {
|
|
14497
14938
|
const out = [];
|
|
14498
|
-
const ifaces =
|
|
14939
|
+
const ifaces = os8.networkInterfaces();
|
|
14499
14940
|
for (const [name, list] of Object.entries(ifaces)) {
|
|
14500
14941
|
for (const info of list ?? []) {
|
|
14501
14942
|
out.push({
|
|
@@ -14546,23 +14987,23 @@ function overview(store, manager) {
|
|
|
14546
14987
|
return { projects, sessions: { total, running, waiting, items }, usage: { tokensIn, tokensOut } };
|
|
14547
14988
|
}
|
|
14548
14989
|
function buildNodeHost(store, manager, diskPath) {
|
|
14549
|
-
const cpus2 =
|
|
14990
|
+
const cpus2 = os8.cpus();
|
|
14550
14991
|
const ov = overview(store, manager);
|
|
14551
14992
|
return {
|
|
14552
14993
|
nodeId: store.loadNodeId() ?? "",
|
|
14553
|
-
hostname:
|
|
14994
|
+
hostname: os8.hostname(),
|
|
14554
14995
|
platform: process.platform,
|
|
14555
14996
|
arch: process.arch,
|
|
14556
|
-
release:
|
|
14557
|
-
uptimeSec: Math.round(
|
|
14558
|
-
version: "0.2.
|
|
14997
|
+
release: os8.release(),
|
|
14998
|
+
uptimeSec: Math.round(os8.uptime()),
|
|
14999
|
+
version: "0.2.11",
|
|
14559
15000
|
mode: process.env.NODE_MODE ?? "standalone",
|
|
14560
15001
|
cpu: {
|
|
14561
15002
|
count: cpus2.length,
|
|
14562
15003
|
model: cpus2[0]?.model ?? "",
|
|
14563
|
-
loadAvg:
|
|
15004
|
+
loadAvg: os8.loadavg().map((n) => Math.round(n * 100) / 100)
|
|
14564
15005
|
},
|
|
14565
|
-
memory: { total:
|
|
15006
|
+
memory: { total: os8.totalmem(), free: os8.freemem() },
|
|
14566
15007
|
network: networkInfo(),
|
|
14567
15008
|
disk: diskInfo(diskPath || process.cwd()),
|
|
14568
15009
|
...ov
|
|
@@ -14599,7 +15040,7 @@ function saveNotifications(tenant, secretBox, notifications) {
|
|
|
14599
15040
|
var API_PREFIX = "/api/v1";
|
|
14600
15041
|
var MAX_BODY_BYTES = 10 * 1024 * 1024;
|
|
14601
15042
|
function readBody(req2) {
|
|
14602
|
-
return new Promise((
|
|
15043
|
+
return new Promise((resolve24, reject) => {
|
|
14603
15044
|
const chunks = [];
|
|
14604
15045
|
let size = 0;
|
|
14605
15046
|
req2.on("data", (c) => {
|
|
@@ -14612,9 +15053,9 @@ function readBody(req2) {
|
|
|
14612
15053
|
chunks.push(c);
|
|
14613
15054
|
});
|
|
14614
15055
|
req2.on("end", () => {
|
|
14615
|
-
if (chunks.length === 0) return
|
|
15056
|
+
if (chunks.length === 0) return resolve24(void 0);
|
|
14616
15057
|
try {
|
|
14617
|
-
|
|
15058
|
+
resolve24(JSON.parse(Buffer.concat(chunks).toString("utf-8")));
|
|
14618
15059
|
} catch {
|
|
14619
15060
|
reject(new ApiError(400, "bad_request", "\u8BF7\u6C42\u4F53\u4E0D\u662F\u5408\u6CD5 JSON"));
|
|
14620
15061
|
}
|
|
@@ -15130,8 +15571,18 @@ function createApp(store, manager, opts = {}) {
|
|
|
15130
15571
|
applyProvidersPatch(tenant, raw);
|
|
15131
15572
|
if (typeof raw.workspaceRoot === "string") {
|
|
15132
15573
|
const ws = raw.workspaceRoot.trim();
|
|
15133
|
-
|
|
15134
|
-
|
|
15574
|
+
const next = ws ? path31.resolve(ws) : void 0;
|
|
15575
|
+
if (tenant.workspaceRoot) {
|
|
15576
|
+
if (next !== tenant.workspaceRoot) {
|
|
15577
|
+
throw new ApiError(
|
|
15578
|
+
409,
|
|
15579
|
+
"workspace_locked",
|
|
15580
|
+
"\u8BE5\u9879\u76EE\u5DF2\u8BBE\u7F6E\u5DE5\u4F5C\u76EE\u5F55\uFF0C\u4E0D\u80FD\u518D\u4FEE\u6539"
|
|
15581
|
+
);
|
|
15582
|
+
}
|
|
15583
|
+
} else if (next) {
|
|
15584
|
+
tenant.workspaceRoot = next;
|
|
15585
|
+
}
|
|
15135
15586
|
}
|
|
15136
15587
|
if (typeof raw.name === "string" && raw.name.trim()) {
|
|
15137
15588
|
tenant.name = raw.name.trim();
|
|
@@ -16107,7 +16558,7 @@ function createApp(store, manager, opts = {}) {
|
|
|
16107
16558
|
json(res, 200, {
|
|
16108
16559
|
status: "ok",
|
|
16109
16560
|
// 版本让运维/探针能确认线上跑的是哪个构建(更新与回滚据此判断)
|
|
16110
|
-
version: "0.2.
|
|
16561
|
+
version: "0.2.11",
|
|
16111
16562
|
features: { mcp: hasServerMcpConfig() }
|
|
16112
16563
|
});
|
|
16113
16564
|
return;
|
|
@@ -16202,7 +16653,7 @@ function createApp(store, manager, opts = {}) {
|
|
|
16202
16653
|
|
|
16203
16654
|
// src/server/fleet/FleetNodeBridge.ts
|
|
16204
16655
|
init_esm_shims();
|
|
16205
|
-
import * as
|
|
16656
|
+
import * as os9 from "os";
|
|
16206
16657
|
import { monitorEventLoopDelay } from "perf_hooks";
|
|
16207
16658
|
|
|
16208
16659
|
// src/server/fleet/FleetCommands.ts
|
|
@@ -16223,8 +16674,8 @@ async function cachedFetchModels(baseURL, apiKey) {
|
|
|
16223
16674
|
try {
|
|
16224
16675
|
result = await Promise.race([
|
|
16225
16676
|
fetchModels(baseURL, apiKey),
|
|
16226
|
-
new Promise((
|
|
16227
|
-
const t = setTimeout(() =>
|
|
16677
|
+
new Promise((resolve24) => {
|
|
16678
|
+
const t = setTimeout(() => resolve24(null), MODEL_FETCH_TIMEOUT_MS);
|
|
16228
16679
|
t.unref?.();
|
|
16229
16680
|
})
|
|
16230
16681
|
]);
|
|
@@ -16249,8 +16700,8 @@ async function cachedFetchModelsEnriched(baseURL, apiKey, preferred) {
|
|
|
16249
16700
|
if (!target) return r;
|
|
16250
16701
|
const ctx = await Promise.race([
|
|
16251
16702
|
fetchModelContext(baseURL, apiKey, target),
|
|
16252
|
-
new Promise((
|
|
16253
|
-
const t = setTimeout(() =>
|
|
16703
|
+
new Promise((resolve24) => {
|
|
16704
|
+
const t = setTimeout(() => resolve24(void 0), MODEL_FETCH_TIMEOUT_MS);
|
|
16254
16705
|
t.unref?.();
|
|
16255
16706
|
})
|
|
16256
16707
|
]);
|
|
@@ -17379,13 +17830,13 @@ var EVENT_FLUSH_MAX_EVENTS = 60;
|
|
|
17379
17830
|
var EVENT_FLUSH_MAX_BYTES = 200 * 1024;
|
|
17380
17831
|
var LOOP_LAG_WARN_MS = 2e3;
|
|
17381
17832
|
function withTimeout(p, ms) {
|
|
17382
|
-
return new Promise((
|
|
17833
|
+
return new Promise((resolve24, reject) => {
|
|
17383
17834
|
const timer = setTimeout(() => reject(new Error(`\u5B50\u6307\u4EE4\u8D85\u65F6\uFF08${ms}ms\uFF09`)), ms);
|
|
17384
17835
|
timer.unref?.();
|
|
17385
17836
|
p.then(
|
|
17386
17837
|
(v) => {
|
|
17387
17838
|
clearTimeout(timer);
|
|
17388
|
-
|
|
17839
|
+
resolve24(v);
|
|
17389
17840
|
},
|
|
17390
17841
|
(e) => {
|
|
17391
17842
|
clearTimeout(timer);
|
|
@@ -17396,7 +17847,7 @@ function withTimeout(p, ms) {
|
|
|
17396
17847
|
}
|
|
17397
17848
|
function primaryIp() {
|
|
17398
17849
|
let v6;
|
|
17399
|
-
for (const infos of Object.values(
|
|
17850
|
+
for (const infos of Object.values(os9.networkInterfaces())) {
|
|
17400
17851
|
for (const info of infos ?? []) {
|
|
17401
17852
|
if (info.internal) continue;
|
|
17402
17853
|
if (info.family === "IPv4") return info.address;
|
|
@@ -17745,7 +18196,7 @@ var FleetNodeBridge = class {
|
|
|
17745
18196
|
label: this.opts.deps.store.loadNodeLabel() ?? void 0,
|
|
17746
18197
|
platform: process.platform,
|
|
17747
18198
|
mode: process.env.NODE_MODE ?? "standalone",
|
|
17748
|
-
version: "0.2.
|
|
18199
|
+
version: "0.2.11",
|
|
17749
18200
|
ip: primaryIp()
|
|
17750
18201
|
};
|
|
17751
18202
|
}
|
|
@@ -17800,7 +18251,7 @@ var FleetNodeBridge = class {
|
|
|
17800
18251
|
label: this.opts.deps.store.loadNodeLabel() ?? void 0,
|
|
17801
18252
|
platform: process.platform,
|
|
17802
18253
|
mode: process.env.NODE_MODE ?? "standalone",
|
|
17803
|
-
version: "0.2.
|
|
18254
|
+
version: "0.2.11",
|
|
17804
18255
|
ip: primaryIp(),
|
|
17805
18256
|
projects,
|
|
17806
18257
|
totals,
|
|
@@ -18569,8 +19020,8 @@ init_esm_shims();
|
|
|
18569
19020
|
|
|
18570
19021
|
// src/server/qq/bindings.ts
|
|
18571
19022
|
init_esm_shims();
|
|
18572
|
-
import * as
|
|
18573
|
-
import * as
|
|
19023
|
+
import * as fs25 from "fs";
|
|
19024
|
+
import * as path32 from "path";
|
|
18574
19025
|
function conversationKey(target) {
|
|
18575
19026
|
switch (target.kind) {
|
|
18576
19027
|
case "c2c":
|
|
@@ -18609,12 +19060,12 @@ var QqBindingsStore = class _QqBindingsStore {
|
|
|
18609
19060
|
cache = null;
|
|
18610
19061
|
/** 基于 DATA_DIR 构造 */
|
|
18611
19062
|
static in(dataDir) {
|
|
18612
|
-
return new _QqBindingsStore(
|
|
19063
|
+
return new _QqBindingsStore(path32.join(dataDir, "qq", "bindings.json"));
|
|
18613
19064
|
}
|
|
18614
19065
|
load() {
|
|
18615
19066
|
if (this.cache) return this.cache;
|
|
18616
19067
|
try {
|
|
18617
|
-
const raw = JSON.parse(
|
|
19068
|
+
const raw = JSON.parse(fs25.readFileSync(this.file, "utf-8"));
|
|
18618
19069
|
this.cache = {
|
|
18619
19070
|
conversations: raw.conversations ?? {}
|
|
18620
19071
|
};
|
|
@@ -18646,8 +19097,8 @@ var QqBindingsStore = class _QqBindingsStore {
|
|
|
18646
19097
|
return null;
|
|
18647
19098
|
}
|
|
18648
19099
|
persist() {
|
|
18649
|
-
|
|
18650
|
-
|
|
19100
|
+
fs25.mkdirSync(path32.dirname(this.file), { recursive: true });
|
|
19101
|
+
fs25.writeFileSync(this.file, JSON.stringify(this.cache, null, 2), "utf-8");
|
|
18651
19102
|
}
|
|
18652
19103
|
};
|
|
18653
19104
|
|
|
@@ -19059,8 +19510,8 @@ ${lines.join("\n")}`, msgId);
|
|
|
19059
19510
|
|
|
19060
19511
|
// src/server/qq/QqManager.ts
|
|
19061
19512
|
init_esm_shims();
|
|
19062
|
-
import * as
|
|
19063
|
-
import * as
|
|
19513
|
+
import * as fs26 from "fs";
|
|
19514
|
+
import * as path33 from "path";
|
|
19064
19515
|
var QqManager = class {
|
|
19065
19516
|
constructor(opts) {
|
|
19066
19517
|
this.opts = opts;
|
|
@@ -19069,7 +19520,7 @@ var QqManager = class {
|
|
|
19069
19520
|
adapter = null;
|
|
19070
19521
|
config = null;
|
|
19071
19522
|
get configFile() {
|
|
19072
|
-
return
|
|
19523
|
+
return path33.join(this.opts.dataDir, "qq", "config.json");
|
|
19073
19524
|
}
|
|
19074
19525
|
/** 启动:读配置(env 优先,其次文件),有则建连接 */
|
|
19075
19526
|
start() {
|
|
@@ -19107,7 +19558,7 @@ var QqManager = class {
|
|
|
19107
19558
|
/** 清空配置:删除文件 + 断开 */
|
|
19108
19559
|
clearConfig() {
|
|
19109
19560
|
try {
|
|
19110
|
-
|
|
19561
|
+
fs26.rmSync(this.configFile, { force: true });
|
|
19111
19562
|
} catch {
|
|
19112
19563
|
}
|
|
19113
19564
|
this.stop();
|
|
@@ -19149,7 +19600,7 @@ var QqManager = class {
|
|
|
19149
19600
|
}
|
|
19150
19601
|
_readConfigFile() {
|
|
19151
19602
|
try {
|
|
19152
|
-
const raw = JSON.parse(
|
|
19603
|
+
const raw = JSON.parse(fs26.readFileSync(this.configFile, "utf-8"));
|
|
19153
19604
|
if (raw.appId && raw.appSecret) {
|
|
19154
19605
|
return {
|
|
19155
19606
|
appId: raw.appId,
|
|
@@ -19162,8 +19613,8 @@ var QqManager = class {
|
|
|
19162
19613
|
return null;
|
|
19163
19614
|
}
|
|
19164
19615
|
_persistConfig(cfg) {
|
|
19165
|
-
|
|
19166
|
-
|
|
19616
|
+
fs26.mkdirSync(path33.dirname(this.configFile), { recursive: true });
|
|
19617
|
+
fs26.writeFileSync(this.configFile, JSON.stringify(cfg, null, 2), "utf-8");
|
|
19167
19618
|
}
|
|
19168
19619
|
};
|
|
19169
19620
|
|
|
@@ -19217,11 +19668,11 @@ import * as path37 from "path";
|
|
|
19217
19668
|
// src/update/downloader.ts
|
|
19218
19669
|
init_esm_shims();
|
|
19219
19670
|
import { createHash as createHash3 } from "crypto";
|
|
19220
|
-
import * as
|
|
19671
|
+
import * as fs27 from "fs";
|
|
19221
19672
|
import { Readable as Readable2 } from "stream";
|
|
19222
19673
|
import { pipeline as pipeline2 } from "stream/promises";
|
|
19223
|
-
import { spawnSync as
|
|
19224
|
-
import * as
|
|
19674
|
+
import { spawnSync as spawnSync4 } from "child_process";
|
|
19675
|
+
import * as path34 from "path";
|
|
19225
19676
|
|
|
19226
19677
|
// src/update/manifest.ts
|
|
19227
19678
|
init_esm_shims();
|
|
@@ -19277,8 +19728,10 @@ var PLATFORM_NAMES = {
|
|
|
19277
19728
|
linux: "linux",
|
|
19278
19729
|
win32: "windows"
|
|
19279
19730
|
};
|
|
19731
|
+
var LIBC_VARIANT = "";
|
|
19280
19732
|
function platformKey(platform = process.platform, arch = process.arch) {
|
|
19281
|
-
|
|
19733
|
+
const base = `${PLATFORM_NAMES[platform] ?? platform}-${arch}`;
|
|
19734
|
+
return LIBC_VARIANT ? `${base}-${LIBC_VARIANT}` : base;
|
|
19282
19735
|
}
|
|
19283
19736
|
var SHA256_HEX = /^[0-9a-f]{64}$/;
|
|
19284
19737
|
function isRecord(v) {
|
|
@@ -19396,8 +19849,8 @@ async function fetchManifest(url, publicKey, opts = {}) {
|
|
|
19396
19849
|
async function downloadBinary(bin, destPath, log = () => {
|
|
19397
19850
|
}) {
|
|
19398
19851
|
const partPath = `${destPath}.part`;
|
|
19399
|
-
|
|
19400
|
-
|
|
19852
|
+
fs27.mkdirSync(path34.dirname(destPath), { recursive: true });
|
|
19853
|
+
fs27.rmSync(partPath, { force: true });
|
|
19401
19854
|
let res;
|
|
19402
19855
|
try {
|
|
19403
19856
|
res = await fetch(bin.url, { signal: AbortSignal.timeout(DOWNLOAD_TIMEOUT_MS2) });
|
|
@@ -19422,30 +19875,30 @@ async function downloadBinary(bin, destPath, log = () => {
|
|
|
19422
19875
|
yield chunk;
|
|
19423
19876
|
}
|
|
19424
19877
|
},
|
|
19425
|
-
|
|
19878
|
+
fs27.createWriteStream(partPath, { mode: 493 })
|
|
19426
19879
|
);
|
|
19427
19880
|
} catch (err) {
|
|
19428
|
-
|
|
19881
|
+
fs27.rmSync(partPath, { force: true });
|
|
19429
19882
|
return { error: `\u4E0B\u8F7D\u4E2D\u65AD\uFF1A${err.message}` };
|
|
19430
19883
|
}
|
|
19431
19884
|
const actual = hash.digest("hex");
|
|
19432
19885
|
if (actual !== bin.sha256) {
|
|
19433
|
-
|
|
19886
|
+
fs27.rmSync(partPath, { force: true });
|
|
19434
19887
|
return { error: `SHA-256 \u4E0D\u5339\u914D\uFF08\u671F\u671B ${bin.sha256.slice(0, 12)}\u2026\uFF0C\u5B9E\u9645 ${actual.slice(0, 12)}\u2026\uFF09` };
|
|
19435
19888
|
}
|
|
19436
19889
|
if (expected && bytes !== expected) {
|
|
19437
|
-
|
|
19890
|
+
fs27.rmSync(partPath, { force: true });
|
|
19438
19891
|
return { error: `\u4EA7\u7269\u5927\u5C0F\u4E0D\u5339\u914D\uFF08\u671F\u671B ${expected}\uFF0C\u5B9E\u9645 ${bytes}\uFF09` };
|
|
19439
19892
|
}
|
|
19440
|
-
|
|
19441
|
-
|
|
19442
|
-
|
|
19443
|
-
log(`\u5DF2\u4E0B\u8F7D ${
|
|
19893
|
+
fs27.rmSync(destPath, { force: true });
|
|
19894
|
+
fs27.renameSync(partPath, destPath);
|
|
19895
|
+
fs27.chmodSync(destPath, 493);
|
|
19896
|
+
log(`\u5DF2\u4E0B\u8F7D ${path34.basename(destPath)}\uFF08${Math.round(bytes / 1024 / 1024)}MB\uFF0C\u6821\u9A8C\u901A\u8FC7\uFF09`);
|
|
19444
19897
|
return { bytes };
|
|
19445
19898
|
}
|
|
19446
19899
|
function selfCheck(binPath, expectedVersion) {
|
|
19447
19900
|
try {
|
|
19448
|
-
const r =
|
|
19901
|
+
const r = spawnSync4(binPath, ["--version"], {
|
|
19449
19902
|
timeout: 2e4,
|
|
19450
19903
|
encoding: "utf-8",
|
|
19451
19904
|
env: { ...process.env, ZQAGENT_AUTO_UPDATE: "0" }
|
|
@@ -19462,104 +19915,6 @@ function selfCheck(binPath, expectedVersion) {
|
|
|
19462
19915
|
}
|
|
19463
19916
|
}
|
|
19464
19917
|
|
|
19465
|
-
// src/update/platform.ts
|
|
19466
|
-
init_esm_shims();
|
|
19467
|
-
import * as fs27 from "fs";
|
|
19468
|
-
import * as path34 from "path";
|
|
19469
|
-
import { spawnSync as spawnSync4 } from "child_process";
|
|
19470
|
-
import { createRequire as createRequire3 } from "module";
|
|
19471
|
-
function currentVersion() {
|
|
19472
|
-
const injected = "0.2.8"?.trim();
|
|
19473
|
-
if (injected) return injected;
|
|
19474
|
-
try {
|
|
19475
|
-
const req2 = createRequire3(import.meta.url);
|
|
19476
|
-
const pkg = req2("../../package.json");
|
|
19477
|
-
if (pkg?.version) return pkg.version;
|
|
19478
|
-
} catch {
|
|
19479
|
-
}
|
|
19480
|
-
return "dev";
|
|
19481
|
-
}
|
|
19482
|
-
function isSeaRuntime() {
|
|
19483
|
-
if (process.env.ZQAGENT_SEA === "1") return true;
|
|
19484
|
-
const base = path34.basename(process.execPath).toLowerCase().replace(/\.exe$/, "");
|
|
19485
|
-
return base !== "node" && base !== "nodejs";
|
|
19486
|
-
}
|
|
19487
|
-
var DEFAULT_SERVICE_NAME = "zqagent";
|
|
19488
|
-
function serviceManagerFromCgroup(cgroup, serviceName = DEFAULT_SERVICE_NAME) {
|
|
19489
|
-
const unitName = `${serviceName}.service`;
|
|
19490
|
-
for (const line of cgroup.split("\n")) {
|
|
19491
|
-
const idx = line.lastIndexOf(":");
|
|
19492
|
-
if (idx < 0) continue;
|
|
19493
|
-
const unitPath = line.slice(idx + 1).trim();
|
|
19494
|
-
if (unitPath.split("/").includes(unitName)) return "systemd";
|
|
19495
|
-
}
|
|
19496
|
-
return null;
|
|
19497
|
-
}
|
|
19498
|
-
function detectServiceManager() {
|
|
19499
|
-
if (process.platform !== "linux") return null;
|
|
19500
|
-
const serviceName = process.env.ZQAGENT_SERVICE_NAME?.trim() || DEFAULT_SERVICE_NAME;
|
|
19501
|
-
try {
|
|
19502
|
-
return serviceManagerFromCgroup(
|
|
19503
|
-
fs27.readFileSync("/proc/self/cgroup", "utf8"),
|
|
19504
|
-
serviceName
|
|
19505
|
-
);
|
|
19506
|
-
} catch {
|
|
19507
|
-
return null;
|
|
19508
|
-
}
|
|
19509
|
-
}
|
|
19510
|
-
function serviceManager() {
|
|
19511
|
-
const v = process.env.ZQAGENT_SERVICE_MANAGER?.trim().toLowerCase();
|
|
19512
|
-
if (v === "systemd" || v === "launchd") return v;
|
|
19513
|
-
return detectServiceManager();
|
|
19514
|
-
}
|
|
19515
|
-
function parseServiceEnvironment(raw) {
|
|
19516
|
-
const out = {};
|
|
19517
|
-
for (const token of raw.trim().split(/\s+/)) {
|
|
19518
|
-
const idx = token.indexOf("=");
|
|
19519
|
-
if (idx > 0) out[token.slice(0, idx)] = token.slice(idx + 1);
|
|
19520
|
-
}
|
|
19521
|
-
return out;
|
|
19522
|
-
}
|
|
19523
|
-
var cachedServiceEnv = null;
|
|
19524
|
-
function readServiceEnvironment() {
|
|
19525
|
-
const serviceName = process.env.ZQAGENT_SERVICE_NAME?.trim() || DEFAULT_SERVICE_NAME;
|
|
19526
|
-
try {
|
|
19527
|
-
const res = spawnSync4(
|
|
19528
|
-
"systemctl",
|
|
19529
|
-
["show", serviceName, "--property=Environment", "--value", "--no-pager"],
|
|
19530
|
-
{ encoding: "utf8", timeout: 3e3 }
|
|
19531
|
-
);
|
|
19532
|
-
if (res.status !== 0 || !res.stdout) return {};
|
|
19533
|
-
return parseServiceEnvironment(res.stdout);
|
|
19534
|
-
} catch {
|
|
19535
|
-
return {};
|
|
19536
|
-
}
|
|
19537
|
-
}
|
|
19538
|
-
function serviceEnvValue(key) {
|
|
19539
|
-
if (process.platform !== "linux") return void 0;
|
|
19540
|
-
if (serviceManager() !== "systemd") return void 0;
|
|
19541
|
-
cachedServiceEnv ??= readServiceEnvironment();
|
|
19542
|
-
return cachedServiceEnv[key];
|
|
19543
|
-
}
|
|
19544
|
-
function selfUpdateCapability(hasPublicKey) {
|
|
19545
|
-
if (!isSeaRuntime()) {
|
|
19546
|
-
return {
|
|
19547
|
-
ok: false,
|
|
19548
|
-
reason: "\u5F53\u524D\u4E0D\u662F\u5355\u6587\u4EF6\uFF08SEA\uFF09\u5F62\u6001\uFF1A\u8BF7\u7528 npm \u5347\u7EA7\uFF08npm i -g @zqagent/core@latest\uFF09"
|
|
19549
|
-
};
|
|
19550
|
-
}
|
|
19551
|
-
if (!serviceManager()) {
|
|
19552
|
-
return {
|
|
19553
|
-
ok: false,
|
|
19554
|
-
reason: "\u672A\u88AB systemd/launchd \u6258\u7BA1\uFF1A\u8BF7\u7528 deploy/service/install.sh \u5B89\u88C5\uFF0C\u6216\u624B\u52A8\u5347\u7EA7"
|
|
19555
|
-
};
|
|
19556
|
-
}
|
|
19557
|
-
if (!hasPublicKey) {
|
|
19558
|
-
return { ok: false, reason: "\u672A\u914D\u7F6E ZQAGENT_UPDATE_PUBKEY\uFF0C\u65E0\u6CD5\u9A8C\u7B7E\uFF0C\u5DF2\u7981\u7528\u81EA\u52A8\u66F4\u65B0" };
|
|
19559
|
-
}
|
|
19560
|
-
return { ok: true };
|
|
19561
|
-
}
|
|
19562
|
-
|
|
19563
19918
|
// src/update/installer.ts
|
|
19564
19919
|
init_esm_shims();
|
|
19565
19920
|
import * as fs29 from "fs";
|
|
@@ -19925,11 +20280,11 @@ var UpdateController = class {
|
|
|
19925
20280
|
const minUptime = num("ZQAGENT_UPDATE_MIN_UPTIME_MS", 10 * 60 * 1e3);
|
|
19926
20281
|
const idleMs = num("ZQAGENT_UPDATE_IDLE_MS", 60 * 1e3);
|
|
19927
20282
|
let idleSince = null;
|
|
19928
|
-
return new Promise((
|
|
20283
|
+
return new Promise((resolve24) => {
|
|
19929
20284
|
const timer = setInterval(() => {
|
|
19930
20285
|
if (this.stopped) {
|
|
19931
20286
|
clearInterval(timer);
|
|
19932
|
-
|
|
20287
|
+
resolve24(false);
|
|
19933
20288
|
return;
|
|
19934
20289
|
}
|
|
19935
20290
|
if (Date.now() - this.startedAt < minUptime || !this.opts.isIdle()) {
|
|
@@ -19939,7 +20294,7 @@ var UpdateController = class {
|
|
|
19939
20294
|
idleSince ??= Date.now();
|
|
19940
20295
|
if (Date.now() - idleSince >= idleMs) {
|
|
19941
20296
|
clearInterval(timer);
|
|
19942
|
-
|
|
20297
|
+
resolve24(true);
|
|
19943
20298
|
}
|
|
19944
20299
|
}, 1e3);
|
|
19945
20300
|
timer.unref();
|
|
@@ -20120,6 +20475,46 @@ function exitWhenOrphaned() {
|
|
|
20120
20475
|
}, 1500);
|
|
20121
20476
|
timer.unref();
|
|
20122
20477
|
}
|
|
20478
|
+
var PORT_FALLBACK_LIMIT = 20;
|
|
20479
|
+
function listenWithPortFallback(server, startPort, host, dataDir, limit = PORT_FALLBACK_LIMIT) {
|
|
20480
|
+
return new Promise((resolve24, reject) => {
|
|
20481
|
+
let attempts = 0;
|
|
20482
|
+
const tryListen = (port) => {
|
|
20483
|
+
server.removeAllListeners("listening");
|
|
20484
|
+
const onError = (err) => {
|
|
20485
|
+
if (err.code === "EADDRINUSE" && attempts < limit) {
|
|
20486
|
+
attempts += 1;
|
|
20487
|
+
const next = port + 1;
|
|
20488
|
+
console.warn(`[server] \u7AEF\u53E3 ${port} \u5DF2\u88AB\u5360\u7528\uFF08EADDRINUSE\uFF09\uFF0C\u5C1D\u8BD5 ${next} \u2026`);
|
|
20489
|
+
tryListen(next);
|
|
20490
|
+
return;
|
|
20491
|
+
}
|
|
20492
|
+
server.removeListener("error", onError);
|
|
20493
|
+
console.error(
|
|
20494
|
+
`[server] \u65E0\u6CD5\u76D1\u542C ${host}:${port}\uFF1A${err.message}` + (err.code === "EADDRINUSE" ? `\uFF08\u5DF2\u5C1D\u8BD5 ${attempts + 1} \u4E2A\u7AEF\u53E3\u5747\u88AB\u5360\u7528\uFF09` : "")
|
|
20495
|
+
);
|
|
20496
|
+
reject(err);
|
|
20497
|
+
};
|
|
20498
|
+
server.once("error", onError);
|
|
20499
|
+
server.listen(port, host, () => {
|
|
20500
|
+
server.removeListener("error", onError);
|
|
20501
|
+
const addr = server.address();
|
|
20502
|
+
const actualPort = typeof addr === "object" && addr !== null ? addr.port : port;
|
|
20503
|
+
if (actualPort !== startPort) {
|
|
20504
|
+
console.warn(`[server] \u5DF2\u6539\u7528\u7AEF\u53E3 ${actualPort}\uFF08\u539F\u5B9A ${startPort} \u88AB\u5360\u7528\uFF09`);
|
|
20505
|
+
}
|
|
20506
|
+
try {
|
|
20507
|
+
fs31.mkdirSync(dataDir, { recursive: true });
|
|
20508
|
+
fs31.writeFileSync(path38.join(dataDir, "server-port"), `${actualPort}
|
|
20509
|
+
`);
|
|
20510
|
+
} catch {
|
|
20511
|
+
}
|
|
20512
|
+
resolve24(actualPort);
|
|
20513
|
+
});
|
|
20514
|
+
};
|
|
20515
|
+
tryListen(startPort);
|
|
20516
|
+
});
|
|
20517
|
+
}
|
|
20123
20518
|
function startServer(opts = {}) {
|
|
20124
20519
|
const dataDir = path38.resolve(opts.dataDir ?? env2("DATA_DIR") ?? DEFAULT_DATA_DIR);
|
|
20125
20520
|
const port = opts.port ?? Number(env2("PORT") ?? 8787);
|
|
@@ -20345,11 +20740,11 @@ function startServer(opts = {}) {
|
|
|
20345
20740
|
server.timeout = 0;
|
|
20346
20741
|
server.keepAliveTimeout = 65e3;
|
|
20347
20742
|
server.headersTimeout = 66e3;
|
|
20348
|
-
const ready = new Promise((
|
|
20349
|
-
server
|
|
20743
|
+
const ready = new Promise((resolve24, reject) => {
|
|
20744
|
+
listenWithPortFallback(server, port, host, dataDir).then((actualPort) => {
|
|
20350
20745
|
const info = {
|
|
20351
20746
|
host,
|
|
20352
|
-
port,
|
|
20747
|
+
port: actualPort,
|
|
20353
20748
|
dataDir,
|
|
20354
20749
|
adminKey,
|
|
20355
20750
|
fleetNodeId: fleet ? fleet.getNodeId() : void 0,
|
|
@@ -20362,8 +20757,8 @@ function startServer(opts = {}) {
|
|
|
20362
20757
|
printReady(info, qq);
|
|
20363
20758
|
}
|
|
20364
20759
|
updater?.start();
|
|
20365
|
-
|
|
20366
|
-
});
|
|
20760
|
+
resolve24(info);
|
|
20761
|
+
}, reject);
|
|
20367
20762
|
});
|
|
20368
20763
|
return {
|
|
20369
20764
|
store,
|
|
@@ -20499,7 +20894,7 @@ async function runWizard(rl2, store, opts) {
|
|
|
20499
20894
|
}
|
|
20500
20895
|
async function askHidden(rl2, prompt) {
|
|
20501
20896
|
if (!process.stdin.isTTY) return (await rl2.question(prompt)).trim();
|
|
20502
|
-
return new Promise((
|
|
20897
|
+
return new Promise((resolve24) => {
|
|
20503
20898
|
const saved = process.stdin.listeners("data");
|
|
20504
20899
|
process.stdin.removeAllListeners("data");
|
|
20505
20900
|
cliWrite(prompt);
|
|
@@ -20521,13 +20916,13 @@ async function askHidden(rl2, prompt) {
|
|
|
20521
20916
|
if (ch === "\r" || ch === "\n") {
|
|
20522
20917
|
cleanup();
|
|
20523
20918
|
cliWrite("\n");
|
|
20524
|
-
|
|
20919
|
+
resolve24(buf);
|
|
20525
20920
|
return;
|
|
20526
20921
|
}
|
|
20527
20922
|
if (ch === "") {
|
|
20528
20923
|
cleanup();
|
|
20529
20924
|
cliWrite("\n");
|
|
20530
|
-
|
|
20925
|
+
resolve24("");
|
|
20531
20926
|
return;
|
|
20532
20927
|
}
|
|
20533
20928
|
if (ch === "\x7F" || ch === "\b") {
|
|
@@ -20716,7 +21111,7 @@ function updateSessionMetaFile(stateDir2, sessionId, patch) {
|
|
|
20716
21111
|
// src/cli/debug.ts
|
|
20717
21112
|
init_esm_shims();
|
|
20718
21113
|
import * as fs33 from "fs";
|
|
20719
|
-
import * as
|
|
21114
|
+
import * as os10 from "os";
|
|
20720
21115
|
import * as path42 from "path";
|
|
20721
21116
|
var LOG_NAME = "zqagent-debug.log";
|
|
20722
21117
|
var TRUTHY = /^(1|true|yes|on)$/i;
|
|
@@ -20730,7 +21125,7 @@ function resolveLogFile() {
|
|
|
20730
21125
|
const explicit = process.env.ZQAGENT_DEBUG_LOG;
|
|
20731
21126
|
if (explicit) return path42.resolve(explicit);
|
|
20732
21127
|
const dir = process.env.ZQAGENT_DEBUG_DIR;
|
|
20733
|
-
return path42.join(dir ? path42.resolve(dir) :
|
|
21128
|
+
return path42.join(dir ? path42.resolve(dir) : os10.tmpdir(), LOG_NAME);
|
|
20734
21129
|
}
|
|
20735
21130
|
function enableDebug(argv = process.argv) {
|
|
20736
21131
|
if (enabled) return true;
|
|
@@ -21168,27 +21563,14 @@ var _exitHandler = null;
|
|
|
21168
21563
|
rl.on("SIGINT", () => {
|
|
21169
21564
|
_exitHandler?.();
|
|
21170
21565
|
});
|
|
21171
|
-
|
|
21172
|
-
const iface = rl;
|
|
21173
|
-
const orig = iface._ttyWrite;
|
|
21174
|
-
iface._ttyWrite = function(s, key) {
|
|
21175
|
-
const k = key;
|
|
21176
|
-
if (k && (k.name === "up" || k.name === "down") && !k.ctrl && !k.meta && !k.shift) {
|
|
21177
|
-
if (iface.cursor > 0) {
|
|
21178
|
-
iface._moveCursor(-iface.cursor);
|
|
21179
|
-
}
|
|
21180
|
-
}
|
|
21181
|
-
orig.call(rl, s, key);
|
|
21182
|
-
};
|
|
21183
|
-
}
|
|
21184
|
-
patchReadlineHistoryNav();
|
|
21566
|
+
patchReadlineHistoryNav(rl);
|
|
21185
21567
|
dlog("init", "\u6A21\u5757\u521D\u59CB\u5316\u5B8C\u6210\uFF08readline / \u8F93\u5165\u8DEF\u7531 / \u5386\u53F2\u5BFC\u822A\u5C31\u7EEA\uFF09");
|
|
21186
21568
|
function question(prompt) {
|
|
21187
21569
|
return inputRouter.ask(prompt);
|
|
21188
21570
|
}
|
|
21189
21571
|
function readPassword(prompt) {
|
|
21190
21572
|
if (!process.stdin.isTTY) return question(prompt);
|
|
21191
|
-
return new Promise((
|
|
21573
|
+
return new Promise((resolve24) => {
|
|
21192
21574
|
const savedDataListeners = process.stdin.listeners("data");
|
|
21193
21575
|
process.stdin.removeAllListeners("data");
|
|
21194
21576
|
cliWrite(prompt);
|
|
@@ -21204,13 +21586,13 @@ function readPassword(prompt) {
|
|
|
21204
21586
|
if (ch === "\r" || ch === "\n") {
|
|
21205
21587
|
cleanup();
|
|
21206
21588
|
cliWrite("\n");
|
|
21207
|
-
|
|
21589
|
+
resolve24(buf);
|
|
21208
21590
|
return;
|
|
21209
21591
|
}
|
|
21210
21592
|
if (ch === "") {
|
|
21211
21593
|
cleanup();
|
|
21212
21594
|
cliWrite("\n");
|
|
21213
|
-
|
|
21595
|
+
resolve24("");
|
|
21214
21596
|
return;
|
|
21215
21597
|
}
|
|
21216
21598
|
if (ch === "\x7F" || ch === "\b") {
|
|
@@ -21645,7 +22027,7 @@ async function offerTerminalSetup(engine, canUseAgent) {
|
|
|
21645
22027
|
}
|
|
21646
22028
|
var KNOWN_SUBCOMMANDS = /* @__PURE__ */ new Set(["link", "serve", "update"]);
|
|
21647
22029
|
function cliVersion() {
|
|
21648
|
-
const env3 = "0.2.
|
|
22030
|
+
const env3 = "0.2.11"?.trim();
|
|
21649
22031
|
if (env3) return env3;
|
|
21650
22032
|
try {
|
|
21651
22033
|
const req2 = createRequire4(import.meta.url);
|