@zqagent/core 0.2.10 → 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.
@@ -10094,6 +10094,38 @@ function countRawEscapes(chunk) {
10094
10094
  for (const ch of cleaned) if (ch === "\x1B") escCount++;
10095
10095
  return escCount;
10096
10096
  }
10097
+ function patchReadlineHistoryNav(rl2) {
10098
+ const iface = rl2;
10099
+ const orig = iface._ttyWrite;
10100
+ let draft = null;
10101
+ iface._ttyWrite = function(s, key) {
10102
+ const k = key;
10103
+ const name = k?.name;
10104
+ const plainArrow = (name === "up" || name === "down") && !k?.ctrl && !k?.meta && !k?.shift;
10105
+ if (plainArrow) {
10106
+ if (name === "up" && iface.historyIndex === -1) {
10107
+ draft = { line: iface.line, cursor: iface.cursor };
10108
+ }
10109
+ if (iface.cursor > 0) {
10110
+ iface._moveCursor(-iface.cursor);
10111
+ }
10112
+ }
10113
+ const prevHistoryIndex = iface.historyIndex;
10114
+ orig.call(rl2, s, key);
10115
+ if (plainArrow && name === "down" && prevHistoryIndex >= 0 && iface.historyIndex === -1) {
10116
+ const saved = draft;
10117
+ draft = null;
10118
+ if (saved) {
10119
+ iface.line = saved.line;
10120
+ iface.cursor = Math.min(saved.cursor, saved.line.length);
10121
+ iface._refreshLine?.();
10122
+ }
10123
+ }
10124
+ };
10125
+ rl2.on("line", () => {
10126
+ draft = null;
10127
+ });
10128
+ }
10097
10129
  var PASTE_PLACEHOLDER_PREFIX = "\u7C98\u8D34\u6587\u672C #";
10098
10130
  var InputRouter = class {
10099
10131
  rl;
@@ -10481,7 +10513,7 @@ function renderTerminalTutorial() {
10481
10513
 
10482
10514
  // src/cli/link.ts
10483
10515
  init_cjs_shims();
10484
- var path21 = __toESM(require("path"), 1);
10516
+ var path22 = __toESM(require("path"), 1);
10485
10517
 
10486
10518
  // src/server/store.ts
10487
10519
  init_cjs_shims();
@@ -10891,11 +10923,186 @@ async function hubEnrollByAccount(baseUrl, input) {
10891
10923
 
10892
10924
  // src/cli/serve-instances.ts
10893
10925
  init_cjs_shims();
10894
- var import_node_child_process4 = require("child_process");
10926
+ var import_node_child_process5 = require("child_process");
10927
+ var fs19 = __toESM(require("fs"), 1);
10928
+ var os5 = __toESM(require("os"), 1);
10929
+ var path21 = __toESM(require("path"), 1);
10930
+
10931
+ // src/update/platform.ts
10932
+ init_cjs_shims();
10895
10933
  var fs18 = __toESM(require("fs"), 1);
10934
+ var os4 = __toESM(require("os"), 1);
10896
10935
  var path20 = __toESM(require("path"), 1);
10936
+ var import_node_child_process4 = require("child_process");
10937
+ var import_node_module3 = require("module");
10938
+ function currentVersion() {
10939
+ const injected = "0.2.11"?.trim();
10940
+ if (injected) return injected;
10941
+ try {
10942
+ const req2 = (0, import_node_module3.createRequire)(importMetaUrl);
10943
+ const pkg = req2("../../package.json");
10944
+ if (pkg?.version) return pkg.version;
10945
+ } catch {
10946
+ }
10947
+ return "dev";
10948
+ }
10949
+ function isSeaRuntime() {
10950
+ if (process.env.ZQAGENT_SEA === "1") return true;
10951
+ const base = path20.basename(process.execPath).toLowerCase().replace(/\.exe$/, "");
10952
+ return base !== "node" && base !== "nodejs";
10953
+ }
10954
+ var DEFAULT_SERVICE_NAME = "zqagent";
10955
+ var DEFAULT_SERVICE_LABEL = "com.zqagent.node";
10956
+ function serviceManagerFromCgroup(cgroup, serviceName = DEFAULT_SERVICE_NAME) {
10957
+ const unitName = `${serviceName}.service`;
10958
+ for (const line of cgroup.split("\n")) {
10959
+ const idx = line.lastIndexOf(":");
10960
+ if (idx < 0) continue;
10961
+ const unitPath = line.slice(idx + 1).trim();
10962
+ if (unitPath.split("/").includes(unitName)) return "systemd";
10963
+ }
10964
+ return null;
10965
+ }
10966
+ function launchdDomain() {
10967
+ const uid = typeof process.getuid === "function" ? process.getuid() : -1;
10968
+ return uid === 0 ? "system" : `gui/${uid}`;
10969
+ }
10970
+ function launchdLabel() {
10971
+ return process.env.ZQAGENT_SERVICE_LABEL?.trim() || DEFAULT_SERVICE_LABEL;
10972
+ }
10973
+ function launchdPlistPath() {
10974
+ const label = launchdLabel();
10975
+ const uid = typeof process.getuid === "function" ? process.getuid() : -1;
10976
+ if (uid === 0) return `/Library/LaunchDaemons/${label}.plist`;
10977
+ return path20.join(os4.homedir(), "Library", "LaunchAgents", `${label}.plist`);
10978
+ }
10979
+ function serviceManagerFromLaunchctl(output, pid, execPath, sea = true) {
10980
+ const pidMatch = /^\s*pid = (\d+)\s*$/m.exec(output);
10981
+ if (pidMatch && Number(pidMatch[1]) === pid) return "launchd";
10982
+ const program = /^\s*program = (.+?)\s*$/m.exec(output);
10983
+ if (program) {
10984
+ const shown = program[1].replace(/^"|"$/g, "");
10985
+ if (path20.resolve(shown) === path20.resolve(execPath)) return "launchd";
10986
+ }
10987
+ if (!sea && /^\s*state = /m.test(output)) return "launchd";
10988
+ return null;
10989
+ }
10990
+ function parseLaunchdEnvironment(xml) {
10991
+ const out = {};
10992
+ const marker = xml.indexOf("<key>EnvironmentVariables</key>");
10993
+ if (marker < 0) return out;
10994
+ const open = xml.indexOf("<dict>", marker);
10995
+ if (open < 0) return out;
10996
+ const close = xml.indexOf("</dict>", open);
10997
+ if (close < 0) return out;
10998
+ const body = xml.slice(open + "<dict>".length, close);
10999
+ for (const m of body.matchAll(/<key>([^<]+)<\/key>\s*<string>([^<]*)<\/string>/g)) {
11000
+ out[m[1]] = m[2];
11001
+ }
11002
+ return out;
11003
+ }
11004
+ function detectServiceManager() {
11005
+ if (process.platform === "darwin") return detectLaunchd();
11006
+ if (process.platform !== "linux") return null;
11007
+ const serviceName = process.env.ZQAGENT_SERVICE_NAME?.trim() || DEFAULT_SERVICE_NAME;
11008
+ try {
11009
+ return serviceManagerFromCgroup(
11010
+ fs18.readFileSync("/proc/self/cgroup", "utf8"),
11011
+ serviceName
11012
+ );
11013
+ } catch {
11014
+ return null;
11015
+ }
11016
+ }
11017
+ function detectLaunchd() {
11018
+ try {
11019
+ const res = (0, import_node_child_process4.spawnSync)(
11020
+ "launchctl",
11021
+ ["print", `${launchdDomain()}/${launchdLabel()}`],
11022
+ { encoding: "utf8", timeout: 3e3 }
11023
+ );
11024
+ if (res.status !== 0 || !res.stdout) return null;
11025
+ return serviceManagerFromLaunchctl(
11026
+ res.stdout,
11027
+ process.pid,
11028
+ process.execPath,
11029
+ isSeaRuntime()
11030
+ );
11031
+ } catch {
11032
+ return null;
11033
+ }
11034
+ }
11035
+ function serviceManager() {
11036
+ const v = process.env.ZQAGENT_SERVICE_MANAGER?.trim().toLowerCase();
11037
+ if (v === "systemd" || v === "launchd") return v;
11038
+ return detectServiceManager();
11039
+ }
11040
+ function parseServiceEnvironment(raw) {
11041
+ const out = {};
11042
+ for (const token of raw.trim().split(/\s+/)) {
11043
+ const idx = token.indexOf("=");
11044
+ if (idx > 0) out[token.slice(0, idx)] = token.slice(idx + 1);
11045
+ }
11046
+ return out;
11047
+ }
11048
+ var cachedServiceEnv = null;
11049
+ function readServiceEnvironment() {
11050
+ const serviceName = process.env.ZQAGENT_SERVICE_NAME?.trim() || DEFAULT_SERVICE_NAME;
11051
+ try {
11052
+ const res = (0, import_node_child_process4.spawnSync)(
11053
+ "systemctl",
11054
+ ["show", serviceName, "--property=Environment", "--value", "--no-pager"],
11055
+ { encoding: "utf8", timeout: 3e3 }
11056
+ );
11057
+ if (res.status !== 0 || !res.stdout) return {};
11058
+ return parseServiceEnvironment(res.stdout);
11059
+ } catch {
11060
+ return {};
11061
+ }
11062
+ }
11063
+ function serviceEnvValue(key) {
11064
+ if (process.platform === "darwin") {
11065
+ if (serviceManager() !== "launchd") return void 0;
11066
+ cachedLaunchdEnv ??= readLaunchdEnvironment();
11067
+ return cachedLaunchdEnv[key];
11068
+ }
11069
+ if (process.platform !== "linux") return void 0;
11070
+ if (serviceManager() !== "systemd") return void 0;
11071
+ cachedServiceEnv ??= readServiceEnvironment();
11072
+ return cachedServiceEnv[key];
11073
+ }
11074
+ var cachedLaunchdEnv = null;
11075
+ function readLaunchdEnvironment() {
11076
+ try {
11077
+ return parseLaunchdEnvironment(fs18.readFileSync(launchdPlistPath(), "utf8"));
11078
+ } catch {
11079
+ return {};
11080
+ }
11081
+ }
11082
+ function selfUpdateCapability(hasPublicKey) {
11083
+ if (!isSeaRuntime()) {
11084
+ return {
11085
+ ok: false,
11086
+ 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"
11087
+ };
11088
+ }
11089
+ if (!serviceManager()) {
11090
+ return {
11091
+ ok: false,
11092
+ reason: "\u672A\u88AB systemd/launchd \u6258\u7BA1\uFF1A\u8BF7\u7528 deploy/service/install.sh \u5B89\u88C5\uFF0C\u6216\u624B\u52A8\u5347\u7EA7"
11093
+ };
11094
+ }
11095
+ if (!hasPublicKey) {
11096
+ return { ok: false, reason: "\u672A\u914D\u7F6E ZQAGENT_UPDATE_PUBKEY\uFF0C\u65E0\u6CD5\u9A8C\u7B7E\uFF0C\u5DF2\u7981\u7528\u81EA\u52A8\u66F4\u65B0" };
11097
+ }
11098
+ return { ok: true };
11099
+ }
11100
+
11101
+ // src/cli/serve-instances.ts
10897
11102
  var DEFAULT_SERVE_HOST = "127.0.0.1";
10898
11103
  var DEFAULT_SERVE_PORT = 8787;
11104
+ var DEFAULT_SERVICE_NAME2 = "zqagent";
11105
+ var DEFAULT_SERVICE_LABEL2 = "com.zqagent.node";
10899
11106
  function serveSubcommandIndex(argv) {
10900
11107
  for (let i = 1; i < argv.length; i++) {
10901
11108
  if (argv[i].startsWith("-")) continue;
@@ -10930,20 +11137,24 @@ function parseServeArgs(argv) {
10930
11137
  return { dataDir, host, port };
10931
11138
  }
10932
11139
  function buildHotCandidates(explicitDataDir, discovered, fallback) {
10933
- const out = explicitDataDir ? [{ dataDir: path20.resolve(explicitDataDir), ...fallback }] : [{ dataDir: path20.resolve(DEFAULT_DATA_DIR), ...fallback }];
10934
- for (const inst of discovered) {
11140
+ const out = [];
11141
+ const push = (inst) => {
10935
11142
  if (!out.some((o) => o.dataDir === inst.dataDir)) out.push(inst);
10936
- }
11143
+ };
11144
+ if (explicitDataDir) push({ dataDir: path21.resolve(explicitDataDir), ...fallback });
11145
+ for (const inst of discovered) if (inst.managed) push(inst);
11146
+ for (const inst of discovered) if (!inst.managed) push(inst);
11147
+ if (!explicitDataDir) push({ dataDir: path21.resolve(DEFAULT_DATA_DIR), ...fallback });
10937
11148
  return out;
10938
11149
  }
10939
11150
  function isWindowsAbsolute(p) {
10940
11151
  return /^[A-Za-z]:[\\/]/.test(p) || /^\\\\/.test(p);
10941
11152
  }
10942
11153
  function isAbsolutePath(p) {
10943
- return path20.isAbsolute(p) || isWindowsAbsolute(p);
11154
+ return path21.isAbsolute(p) || isWindowsAbsolute(p);
10944
11155
  }
10945
11156
  function normalizePath(p) {
10946
- return isWindowsAbsolute(p) ? path20.win32.normalize(p) : path20.normalize(p);
11157
+ return isWindowsAbsolute(p) ? path21.win32.normalize(p) : path21.normalize(p);
10947
11158
  }
10948
11159
  function parseServeCommandLine(line) {
10949
11160
  if (!/(?:^|\s)["']?serve["']?(?=\s|$)/.test(line)) return null;
@@ -10962,7 +11173,7 @@ function parseServeCommandLine(line) {
10962
11173
  }
10963
11174
  function processCwd(pid) {
10964
11175
  try {
10965
- return fs18.readlinkSync(`/proc/${pid}/cwd`);
11176
+ return fs19.readlinkSync(`/proc/${pid}/cwd`);
10966
11177
  } catch {
10967
11178
  return null;
10968
11179
  }
@@ -10970,7 +11181,7 @@ function processCwd(pid) {
10970
11181
  function processEnv(pid) {
10971
11182
  const out = {};
10972
11183
  try {
10973
- const raw = fs18.readFileSync(`/proc/${pid}/environ`, "utf-8");
11184
+ const raw = fs19.readFileSync(`/proc/${pid}/environ`, "utf-8");
10974
11185
  for (const entry of raw.split("\0")) {
10975
11186
  const eq = entry.indexOf("=");
10976
11187
  if (eq > 0) out[entry.slice(0, eq)] = entry.slice(eq + 1);
@@ -10981,14 +11192,24 @@ function processEnv(pid) {
10981
11192
  }
10982
11193
  function resolveDataDir(rawDataDir, cwd, env3) {
10983
11194
  const pick = rawDataDir ?? env3.DATA_DIR ?? null;
10984
- if (pick) return path20.isAbsolute(pick) ? path20.normalize(pick) : cwd ? path20.resolve(cwd, pick) : null;
10985
- return cwd ? path20.resolve(cwd, DEFAULT_DATA_DIR) : null;
11195
+ if (pick) return path21.isAbsolute(pick) ? path21.normalize(pick) : cwd ? path21.resolve(cwd, pick) : null;
11196
+ return cwd ? path21.resolve(cwd, DEFAULT_DATA_DIR) : null;
11197
+ }
11198
+ function isManagedBySystemd(pid, env3) {
11199
+ if (env3.ZQAGENT_SERVICE_MANAGER?.trim()) return true;
11200
+ try {
11201
+ const cgroup = fs19.readFileSync(`/proc/${pid}/cgroup`, "utf-8");
11202
+ const serviceName = env3.ZQAGENT_SERVICE_NAME?.trim() || "zqagent";
11203
+ return serviceManagerFromCgroup(cgroup, serviceName) !== null;
11204
+ } catch {
11205
+ return false;
11206
+ }
10986
11207
  }
10987
11208
  function discoverFromProc() {
10988
11209
  const out = [];
10989
11210
  let pids;
10990
11211
  try {
10991
- pids = fs18.readdirSync("/proc");
11212
+ pids = fs19.readdirSync("/proc");
10992
11213
  } catch {
10993
11214
  return out;
10994
11215
  }
@@ -10997,22 +11218,29 @@ function discoverFromProc() {
10997
11218
  const pid = Number(name);
10998
11219
  if (pid === process.pid) continue;
10999
11220
  let argv;
11221
+ let env3;
11000
11222
  try {
11001
- argv = fs18.readFileSync(`/proc/${pid}/cmdline`, "utf-8").split("\0").filter(Boolean);
11223
+ argv = fs19.readFileSync(`/proc/${pid}/cmdline`, "utf-8").split("\0").filter(Boolean);
11224
+ env3 = processEnv(pid);
11002
11225
  } catch {
11003
11226
  continue;
11004
11227
  }
11005
11228
  const parsed = parseServeArgs(argv);
11006
11229
  if (!parsed) continue;
11007
- const dataDir = resolveDataDir(parsed.dataDir, processCwd(pid), processEnv(pid));
11230
+ const dataDir = resolveDataDir(parsed.dataDir, processCwd(pid), env3);
11008
11231
  if (!dataDir) continue;
11009
- out.push({ dataDir, host: parsed.host, port: parsed.port });
11232
+ out.push({
11233
+ dataDir,
11234
+ host: parsed.host,
11235
+ port: parsed.port,
11236
+ managed: isManagedBySystemd(pid, env3)
11237
+ });
11010
11238
  }
11011
11239
  return out;
11012
11240
  }
11013
11241
  function discoverFromPs() {
11014
11242
  const out = [];
11015
- const res = (0, import_node_child_process4.spawnSync)("ps", ["-axo", "command="], { encoding: "utf-8", stdio: ["ignore", "pipe", "ignore"] });
11243
+ const res = (0, import_node_child_process5.spawnSync)("ps", ["-axo", "command="], { encoding: "utf-8", stdio: ["ignore", "pipe", "ignore"] });
11016
11244
  if (res.status !== 0 || !res.stdout) return out;
11017
11245
  for (const line of res.stdout.split("\n")) {
11018
11246
  const inst = parseServeCommandLine(line);
@@ -11023,7 +11251,7 @@ function discoverFromPs() {
11023
11251
  function discoverFromWindows() {
11024
11252
  const out = [];
11025
11253
  const script = `[Console]::OutputEncoding=[Text.Encoding]::UTF8; Get-CimInstance Win32_Process -Filter "Name='zqagent.exe' OR Name='node.exe'" | ForEach-Object { $_.CommandLine }`;
11026
- const res = (0, import_node_child_process4.spawnSync)(
11254
+ const res = (0, import_node_child_process5.spawnSync)(
11027
11255
  "powershell.exe",
11028
11256
  ["-NoProfile", "-NonInteractive", "-Command", script],
11029
11257
  { encoding: "utf-8", timeout: 15e3, windowsHide: true, stdio: ["ignore", "pipe", "ignore"] }
@@ -11035,14 +11263,126 @@ function discoverFromWindows() {
11035
11263
  }
11036
11264
  return out;
11037
11265
  }
11266
+ function decodeXmlEntities(s) {
11267
+ return s.replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"').replace(/&apos;/g, "'").replace(/&amp;/g, "&");
11268
+ }
11269
+ function parseLaunchdProgramArguments(xml) {
11270
+ const marker = xml.indexOf("<key>ProgramArguments</key>");
11271
+ if (marker < 0) return [];
11272
+ const open = xml.indexOf("<array>", marker);
11273
+ if (open < 0) return [];
11274
+ const close = xml.indexOf("</array>", open);
11275
+ if (close < 0) return [];
11276
+ return [...xml.slice(open + "<array>".length, close).matchAll(/<string>([^<]*)<\/string>/g)].map(
11277
+ (m) => decodeXmlEntities(m[1])
11278
+ );
11279
+ }
11280
+ function launchdServiceInstances() {
11281
+ if (process.platform !== "darwin") return [];
11282
+ const label = process.env.ZQAGENT_SERVICE_LABEL?.trim() || DEFAULT_SERVICE_LABEL2;
11283
+ const plists = [
11284
+ `/Library/LaunchDaemons/${label}.plist`,
11285
+ path21.join(os5.homedir(), "Library", "LaunchAgents", `${label}.plist`)
11286
+ ];
11287
+ const out = [];
11288
+ for (const plist of plists) {
11289
+ let xml;
11290
+ try {
11291
+ xml = fs19.readFileSync(plist, "utf-8");
11292
+ } catch {
11293
+ continue;
11294
+ }
11295
+ const parsed = parseServeArgs(parseLaunchdProgramArguments(xml));
11296
+ if (!parsed?.dataDir || !isAbsolutePath(parsed.dataDir)) continue;
11297
+ out.push({
11298
+ dataDir: normalizePath(parsed.dataDir),
11299
+ host: parsed.host,
11300
+ port: parsed.port,
11301
+ managed: true
11302
+ });
11303
+ }
11304
+ return out;
11305
+ }
11306
+ function parseSystemdUnit(text) {
11307
+ let dataDir = null;
11308
+ let host = DEFAULT_SERVE_HOST;
11309
+ let port = DEFAULT_SERVE_PORT;
11310
+ for (const line of text.split("\n")) {
11311
+ const trimmed = line.trim();
11312
+ if (trimmed.startsWith("WorkingDirectory=")) {
11313
+ const v = trimmed.slice("WorkingDirectory=".length).trim();
11314
+ if (v && isAbsolutePath(v)) dataDir = v;
11315
+ } else if (trimmed.startsWith("ExecStart=")) {
11316
+ const tokens = trimmed.slice("ExecStart=".length).trim().split(/\s+/).map((t) => t.replace(/^["']|["']$/g, ""));
11317
+ const parsed = parseServeArgs(tokens);
11318
+ if (!parsed) continue;
11319
+ if (parsed.dataDir && isAbsolutePath(parsed.dataDir)) dataDir = parsed.dataDir;
11320
+ host = parsed.host;
11321
+ port = parsed.port;
11322
+ }
11323
+ }
11324
+ if (!dataDir) return null;
11325
+ return { dataDir: normalizePath(dataDir), host, port, managed: true };
11326
+ }
11327
+ function systemdServiceInstances() {
11328
+ if (process.platform !== "linux") return [];
11329
+ const unit = process.env.ZQAGENT_SERVICE_NAME?.trim() || DEFAULT_SERVICE_NAME2;
11330
+ const configHome = process.env.XDG_CONFIG_HOME?.trim() || path21.join(os5.homedir(), ".config");
11331
+ const units = [
11332
+ `/etc/systemd/system/${unit}.service`,
11333
+ path21.join(configHome, "systemd", "user", `${unit}.service`)
11334
+ ];
11335
+ const out = [];
11336
+ for (const file of units) {
11337
+ let text;
11338
+ try {
11339
+ text = fs19.readFileSync(file, "utf-8");
11340
+ } catch {
11341
+ continue;
11342
+ }
11343
+ const inst = parseSystemdUnit(text);
11344
+ if (inst) out.push(inst);
11345
+ }
11346
+ return out;
11347
+ }
11348
+ function windowsServiceInstances() {
11349
+ if (process.platform !== "win32") return [];
11350
+ const appdata = process.env.APPDATA?.trim();
11351
+ if (!appdata) return [];
11352
+ const base = path21.join(appdata, "zqagent");
11353
+ try {
11354
+ const raw = fs19.readFileSync(path21.join(base, "runtime", "service.json"), "utf-8");
11355
+ const v = JSON.parse(raw);
11356
+ const dataDir = v.dataDir && isAbsolutePath(v.dataDir) ? v.dataDir : base;
11357
+ const port = Number(v.port);
11358
+ return [
11359
+ {
11360
+ dataDir: normalizePath(dataDir),
11361
+ host: DEFAULT_SERVE_HOST,
11362
+ port: Number.isFinite(port) && port > 0 ? port : DEFAULT_SERVE_PORT,
11363
+ managed: true
11364
+ }
11365
+ ];
11366
+ } catch {
11367
+ return [];
11368
+ }
11369
+ }
11370
+ function mergeServeInstances(discovered, managed) {
11371
+ const out = [];
11372
+ const push = (inst) => {
11373
+ if (!out.some((o) => o.dataDir === inst.dataDir)) out.push(inst);
11374
+ };
11375
+ for (const inst of discovered) {
11376
+ const hit = managed.find((m) => m.dataDir === inst.dataDir);
11377
+ push(hit ? { ...inst, managed: true } : inst);
11378
+ }
11379
+ for (const inst of managed) push(inst);
11380
+ return out;
11381
+ }
11038
11382
  function discoverRunningServeInstances() {
11039
11383
  const found = process.platform === "linux" ? discoverFromProc() : process.platform === "win32" ? discoverFromWindows() : discoverFromPs();
11040
- const seen = /* @__PURE__ */ new Set();
11041
- return found.filter((inst) => {
11042
- if (seen.has(inst.dataDir)) return false;
11043
- seen.add(inst.dataDir);
11044
- return true;
11045
- });
11384
+ const declared = process.platform === "linux" ? systemdServiceInstances() : process.platform === "win32" ? windowsServiceInstances() : launchdServiceInstances();
11385
+ return mergeServeInstances(found, declared);
11046
11386
  }
11047
11387
 
11048
11388
  // src/cli/link.ts
@@ -11050,12 +11390,12 @@ function expandHome(p) {
11050
11390
  const home = process.env.HOME || process.env.USERPROFILE;
11051
11391
  if (!home) return p;
11052
11392
  if (p === "~") return home;
11053
- if (p.startsWith("~/") || p.startsWith("~\\")) return path21.join(home, p.slice(2));
11393
+ if (p.startsWith("~/") || p.startsWith("~\\")) return path22.join(home, p.slice(2));
11054
11394
  return p;
11055
11395
  }
11056
11396
  function installDataDirHint() {
11057
11397
  if (process.platform === "darwin") return "$HOME/Library/Application Support/zqagent";
11058
- if (process.platform === "win32") return "%LOCALAPPDATA%\\zqagent";
11398
+ if (process.platform === "win32") return "%APPDATA%\\zqagent";
11059
11399
  return "/var/lib/zqagent\uFF08\u9700 root\uFF1B\u666E\u901A\u7528\u6237\u7528 ~/.zqagent_data\uFF09";
11060
11400
  }
11061
11401
  function parseLinkArgs(argv) {
@@ -11130,6 +11470,23 @@ async function enrollViaServer(host, port, adminKey, opts) {
11130
11470
  }
11131
11471
  return payload?.data;
11132
11472
  }
11473
+ function hotWarnings(inst, running) {
11474
+ const warnings = [];
11475
+ const managed = running.filter((r) => r.managed && r.dataDir !== inst.dataDir);
11476
+ if (!inst.managed && managed.length > 0) {
11477
+ warnings.push(
11478
+ `\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`
11479
+ );
11480
+ warnings.push(
11481
+ "\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"
11482
+ );
11483
+ }
11484
+ const others = [...new Set(running.map((r) => r.dataDir).filter((d) => d !== inst.dataDir))];
11485
+ if (others.length > 0) {
11486
+ 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`);
11487
+ }
11488
+ return warnings;
11489
+ }
11133
11490
  async function linkNode(opts) {
11134
11491
  const rawDataDir = opts.dataDir?.trim() || process.env.DATA_DIR?.trim() || void 0;
11135
11492
  const explicitDataDir = rawDataDir ? expandHome(rawDataDir) : void 0;
@@ -11143,9 +11500,17 @@ async function linkNode(opts) {
11143
11500
  if (!adminKey) continue;
11144
11501
  if (!await probeServer(inst.host, inst.port, adminKey)) continue;
11145
11502
  const status = await enrollViaServer(inst.host, inst.port, adminKey, opts);
11146
- return { mode: "hot", ...status, dataDir: inst.dataDir };
11503
+ return {
11504
+ mode: "hot",
11505
+ ...status,
11506
+ dataDir: inst.dataDir,
11507
+ managed: inst.managed,
11508
+ warnings: hotWarnings(inst, running)
11509
+ };
11147
11510
  }
11148
- const dataDir = path21.resolve(explicitDataDir ?? DEFAULT_DATA_DIR);
11511
+ const managedDir = running.find((r) => r.managed)?.dataDir;
11512
+ const dataDir = path22.resolve(explicitDataDir ?? managedDir ?? DEFAULT_DATA_DIR);
11513
+ const targetedService = !explicitDataDir && Boolean(managedDir) && dataDir === managedDir;
11149
11514
  const store = new Store(dataDir);
11150
11515
  const nodeId = ensureNodeId(store);
11151
11516
  const cred = await hubEnrollByCode(opts.hubUrl, {
@@ -11182,14 +11547,16 @@ async function linkNode(opts) {
11182
11547
  label: opts.label,
11183
11548
  dataDir,
11184
11549
  explicitDataDir: Boolean(explicitDataDir),
11185
- runningServiceDirs: otherRunningDirs
11550
+ runningServiceDirs: otherRunningDirs,
11551
+ targetedService
11186
11552
  };
11187
11553
  }
11188
11554
  function printLinkHelp() {
11189
- cliLog("\u7528\u6CD5: zqagent link --hub <url> --code <\u6CE8\u518C\u7801> [--label \u540D\u79F0] [--data-dir \u76EE\u5F55]");
11555
+ cliLog("\u7528\u6CD5: zqagent link --hub <url> --code <\u6CE8\u518C\u7801> [--label \u540D\u79F0]");
11190
11556
  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");
11191
- cliLog(" \u5DF2\u6709\u672C\u673A server \u65F6\u70ED\u63A5\u5165\uFF08\u514D\u91CD\u542F\uFF0C\u4F1A\u81EA\u52A8\u53D1\u73B0\u8FD0\u884C\u4E2D\u670D\u52A1\u7684 --data-dir\uFF09\uFF1B");
11192
- cliLog(" \u5426\u5219\u5199\u5165 <\u6570\u636E\u76EE\u5F55>/fleet.json\uFF0C\u4E0B\u6B21\u542F\u52A8\u81EA\u52A8\u63A5\u5165\u3002");
11557
+ 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");
11558
+ 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");
11559
+ 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");
11193
11560
  }
11194
11561
  async function runLinkCommand(argv) {
11195
11562
  const args = parseLinkArgs(argv);
@@ -11217,14 +11584,23 @@ async function runLinkCommand(argv) {
11217
11584
  cliLog("\u2705 \u5DF2\u63A5\u5165 Hub\uFF08\u70ED\u63A5\u5165\uFF0C\u514D\u91CD\u542F\uFF09");
11218
11585
  cliLog(` \u8282\u70B9: ${r.nodeId}${r.label ? ` (${r.label})` : ""}`);
11219
11586
  cliLog(` \u7F51\u5173: ${r.gatewayUrl ?? "\uFF08\u672A\u4E0B\u53D1\uFF09"} \u5728\u7EBF: ${r.online ? "\u662F" : "\u8FDE\u63A5\u4E2D\u2026"}`);
11220
- cliLog(` \u6570\u636E\u76EE\u5F55: ${r.dataDir}`);
11587
+ cliLog(` \u6570\u636E\u76EE\u5F55: ${r.dataDir}${r.managed ? "\uFF08\u6258\u7BA1\u670D\u52A1\uFF0C\u5F00\u673A\u81EA\u542F\uFF09" : ""}`);
11588
+ if (r.warnings.length > 0) {
11589
+ cliLog("");
11590
+ for (const w of r.warnings) cliLog(`\u26A0\uFE0F ${w}`);
11591
+ }
11221
11592
  } else {
11222
11593
  cliLog("\u2705 \u63A5\u5165\u51ED\u636E\u5DF2\u4FDD\u5B58\uFF08\u672C\u673A\u6682\u65E0\u8FD0\u884C\u4E2D\u7684 server\uFF09");
11223
11594
  cliLog(` \u8282\u70B9: ${r.nodeId}`);
11224
11595
  cliLog(` \u7F51\u5173: ${r.gatewayUrl ?? "\uFF08\u672A\u4E0B\u53D1\uFF09"}`);
11225
11596
  cliLog(` \u6570\u636E\u76EE\u5F55: ${r.dataDir}`);
11226
11597
  cliLog(" \u4E0B\u6B21\u542F\u52A8 server \u5373\u81EA\u52A8\u63A5\u5165\uFF1B\u6216\u8FD0\u884C zqagent serve \u5E38\u9A7B\u4E3A\u8282\u70B9\u3002");
11227
- if (r.runningServiceDirs.length > 0) {
11598
+ if (r.targetedService) {
11599
+ cliLog("");
11600
+ 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");
11601
+ cliLog(" \u7ACB\u5373\u751F\u6548\uFF1A\u91CD\u542F\u8BE5\u670D\u52A1\uFF08Linux: systemctl restart zqagent\uFF1B");
11602
+ cliLog(" macOS: launchctl kickstart -k gui/$(id -u)/com.zqagent.node\uFF09\u3002");
11603
+ } else if (r.runningServiceDirs.length > 0) {
11228
11604
  cliLog("");
11229
11605
  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");
11230
11606
  cliLog(` \u672C\u6B21\u5199\u5165: ${r.dataDir}`);
@@ -11234,11 +11610,10 @@ async function runLinkCommand(argv) {
11234
11610
  cliLog(` zqagent link --hub <Hub\u5730\u5740> --code <\u65B0\u63A5\u5165\u7801> --data-dir "${r.runningServiceDirs[0]}"`);
11235
11611
  } else if (!r.explicitDataDir) {
11236
11612
  cliLog("");
11237
- cliLog("\u26A0\uFE0F \u672A\u6307\u5B9A --data-dir\uFF0C\u51ED\u636E\u5199\u5165\u4E86\u5F53\u524D\u76EE\u5F55\u4E0B\u7684 .zqagent_data\u3002");
11238
- cliLog(" \u82E5\u672C\u673A\u670D\u52A1\u662F\u7531\u5B89\u88C5\u811A\u672C\uFF08systemd / launchd\uFF09\u542F\u52A8\u7684\uFF0C\u5B83\u8BFB\u4E0D\u5230\u8FD9\u4EFD\u51ED\u636E\uFF0C");
11239
- cliLog(" Hub \u4F1A\u4E00\u76F4\u663E\u793A\u672A\u5728\u7EBF\u3002\u8BF7\u7528\u670D\u52A1\u7684\u6570\u636E\u76EE\u5F55\u91CD\u65B0\u6267\u884C\uFF1A");
11240
- cliLog(" zqagent link --hub <Hub\u5730\u5740> --code <\u65B0\u63A5\u5165\u7801> --data-dir <\u670D\u52A1\u6570\u636E\u76EE\u5F55>");
11241
- cliLog(` \uFF08\u672C\u5E73\u53F0\u5B89\u88C5\u811A\u672C\u9ED8\u8BA4\uFF1A${installDataDirHint()}\uFF1B\u63A5\u5165\u7801\u4E00\u6B21\u6027\uFF0C\u9700\u8981\u91CD\u65B0\u751F\u6210\uFF09`);
11613
+ 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");
11614
+ 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");
11615
+ cliLog(" curl -fsSL https://agent.cd-zq.com/install.sh | sh");
11616
+ cliLog(` \uFF08\u670D\u52A1\u9ED8\u8BA4\u6570\u636E\u76EE\u5F55\uFF1A${installDataDirHint()}\uFF09`);
11242
11617
  }
11243
11618
  }
11244
11619
  return true;
@@ -11258,7 +11633,7 @@ var path37 = __toESM(require("path"), 1);
11258
11633
 
11259
11634
  // src/server/session.ts
11260
11635
  init_cjs_shims();
11261
- var path24 = __toESM(require("path"), 1);
11636
+ var path25 = __toESM(require("path"), 1);
11262
11637
  var import_async_hooks = require("async_hooks");
11263
11638
 
11264
11639
  // src/server/mcpConfig.ts
@@ -11439,8 +11814,8 @@ function resolveSessionProvider(store, tenant, providerId) {
11439
11814
 
11440
11815
  // src/server/usage.ts
11441
11816
  init_cjs_shims();
11442
- var fs20 = __toESM(require("fs"), 1);
11443
- var path23 = __toESM(require("path"), 1);
11817
+ var fs21 = __toESM(require("fs"), 1);
11818
+ var path24 = __toESM(require("path"), 1);
11444
11819
  var LEDGER_RETENTION_MONTHS = 12;
11445
11820
  var USAGE_SCHEMA = 1;
11446
11821
  var DEFAULT_PRICING = {
@@ -11521,15 +11896,15 @@ function retainedMonths(now = /* @__PURE__ */ new Date()) {
11521
11896
  return out;
11522
11897
  }
11523
11898
  function atomicWrite(file, content) {
11524
- fs20.mkdirSync(path23.dirname(file), { recursive: true });
11899
+ fs21.mkdirSync(path24.dirname(file), { recursive: true });
11525
11900
  const tmp = `${file}.tmp`;
11526
- fs20.writeFileSync(tmp, content, "utf-8");
11527
- fs20.renameSync(tmp, file);
11901
+ fs21.writeFileSync(tmp, content, "utf-8");
11902
+ fs21.renameSync(tmp, file);
11528
11903
  }
11529
11904
  var UsageLedger = class {
11530
11905
  constructor(root) {
11531
11906
  this.root = root;
11532
- this.dir = path23.join(root, "usage");
11907
+ this.dir = path24.join(root, "usage");
11533
11908
  }
11534
11909
  root;
11535
11910
  dir;
@@ -11542,18 +11917,18 @@ var UsageLedger = class {
11542
11917
  return this.dir;
11543
11918
  }
11544
11919
  ledgerFile(month) {
11545
- return path23.join(this.ledgerDir, `ledger-${month}.jsonl`);
11920
+ return path24.join(this.ledgerDir, `ledger-${month}.jsonl`);
11546
11921
  }
11547
11922
  get rollupFile() {
11548
- return path23.join(this.ledgerDir, "rollup.json");
11923
+ return path24.join(this.ledgerDir, "rollup.json");
11549
11924
  }
11550
11925
  get pricingFile() {
11551
- return path23.join(this.ledgerDir, "pricing.json");
11926
+ return path24.join(this.ledgerDir, "pricing.json");
11552
11927
  }
11553
11928
  // ===================== 初始化 =====================
11554
11929
  init(now = /* @__PURE__ */ new Date()) {
11555
11930
  if (this.inited) return;
11556
- fs20.mkdirSync(this.ledgerDir, { recursive: true });
11931
+ fs21.mkdirSync(this.ledgerDir, { recursive: true });
11557
11932
  this.pricing = this.loadPricing();
11558
11933
  this.rollup = this.loadRollup(now);
11559
11934
  this.pruneLedgers(now);
@@ -11561,7 +11936,7 @@ var UsageLedger = class {
11561
11936
  }
11562
11937
  loadPricing() {
11563
11938
  try {
11564
- const raw = fs20.readFileSync(this.pricingFile, "utf-8");
11939
+ const raw = fs21.readFileSync(this.pricingFile, "utf-8");
11565
11940
  const parsed = JSON.parse(raw);
11566
11941
  const vendors = {};
11567
11942
  for (const v of /* @__PURE__ */ new Set([
@@ -11590,7 +11965,7 @@ var UsageLedger = class {
11590
11965
  }
11591
11966
  loadRollup(now) {
11592
11967
  try {
11593
- const raw = fs20.readFileSync(this.rollupFile, "utf-8");
11968
+ const raw = fs21.readFileSync(this.rollupFile, "utf-8");
11594
11969
  const parsed = JSON.parse(raw);
11595
11970
  return {
11596
11971
  schema: USAGE_SCHEMA,
@@ -11617,10 +11992,10 @@ var UsageLedger = class {
11617
11992
  const keep = retainedMonths(now);
11618
11993
  let changed = false;
11619
11994
  try {
11620
- for (const f of fs20.readdirSync(this.ledgerDir)) {
11995
+ for (const f of fs21.readdirSync(this.ledgerDir)) {
11621
11996
  const m = /^ledger-(\d{4}-\d{2})\.jsonl$/.exec(f);
11622
11997
  if (m && !keep.has(m[1])) {
11623
- fs20.unlinkSync(path23.join(this.ledgerDir, f));
11998
+ fs21.unlinkSync(path24.join(this.ledgerDir, f));
11624
11999
  }
11625
12000
  }
11626
12001
  } catch {
@@ -11697,7 +12072,7 @@ var UsageLedger = class {
11697
12072
  };
11698
12073
  const line = JSON.stringify(rec) + "\n";
11699
12074
  try {
11700
- fs20.appendFileSync(this.ledgerFile(monthOf(rec.ts)), line);
12075
+ fs21.appendFileSync(this.ledgerFile(monthOf(rec.ts)), line);
11701
12076
  } catch (e) {
11702
12077
  console.error(`[usage] \u5199\u8D26\u672C\u5931\u8D25: ${String(e)}`);
11703
12078
  }
@@ -11869,10 +12244,10 @@ var UsageLedger = class {
11869
12244
  const rows = [];
11870
12245
  for (const month of months) {
11871
12246
  const file = this.ledgerFile(month);
11872
- if (!fs20.existsSync(file)) continue;
12247
+ if (!fs21.existsSync(file)) continue;
11873
12248
  let content = "";
11874
12249
  try {
11875
- content = fs20.readFileSync(file, "utf-8");
12250
+ content = fs21.readFileSync(file, "utf-8");
11876
12251
  } catch {
11877
12252
  continue;
11878
12253
  }
@@ -11981,10 +12356,10 @@ var UsageLedger = class {
11981
12356
  const seen = /* @__PURE__ */ new Set();
11982
12357
  for (const month of this.monthsInRange("", "")) {
11983
12358
  const file = this.ledgerFile(month);
11984
- if (!fs20.existsSync(file)) continue;
12359
+ if (!fs21.existsSync(file)) continue;
11985
12360
  let content = "";
11986
12361
  try {
11987
- content = fs20.readFileSync(file, "utf-8");
12362
+ content = fs21.readFileSync(file, "utf-8");
11988
12363
  } catch {
11989
12364
  continue;
11990
12365
  }
@@ -13295,7 +13670,7 @@ data: ${JSON.stringify(entry.data)}
13295
13670
  softThresholdPct: parseRatio(process.env.COMPACTION_SOFT_THRESHOLD_PCT),
13296
13671
  capTokens: parseOptionalPositiveNumber(process.env.COMPACTION_CAP_TOKENS) ?? null,
13297
13672
  // 超预算工具结果按租户/工作区隔离落盘(多租户共用一个状态目录会混内容)
13298
- toolResultDir: path24.join(workspace, ".agent", "tool-results")
13673
+ toolResultDir: path25.join(workspace, ".agent", "tool-results")
13299
13674
  });
13300
13675
  engine.setApprover(this._makeApprover(rt));
13301
13676
  const mcpConfigs = loadServerMcpConfigs(tenant);
@@ -13476,11 +13851,11 @@ var ApiError = class extends Error {
13476
13851
  // src/server/routes.ts
13477
13852
  init_cjs_shims();
13478
13853
  var import_http = require("http");
13479
- var path29 = __toESM(require("path"), 1);
13854
+ var path30 = __toESM(require("path"), 1);
13480
13855
 
13481
13856
  // src/server/projects.ts
13482
13857
  init_cjs_shims();
13483
- var path25 = __toESM(require("path"), 1);
13858
+ var path26 = __toESM(require("path"), 1);
13484
13859
  var DEFAULT_MODEL = () => process.env.OPENAI_MODEL || process.env.MODEL || "gpt-4o";
13485
13860
  function toProjectSummary(store, tenant) {
13486
13861
  return {
@@ -13613,9 +13988,9 @@ function createProject(store, input) {
13613
13988
  if (store.loadTenant(id)) {
13614
13989
  throw new ApiError(409, "project_exists", `\u9879\u76EE ${id} \u5DF2\u5B58\u5728`);
13615
13990
  }
13616
- const workspaceRoot = typeof raw.workspaceRoot === "string" && raw.workspaceRoot.trim() ? path25.resolve(raw.workspaceRoot.trim()) : void 0;
13991
+ const workspaceRoot = typeof raw.workspaceRoot === "string" && raw.workspaceRoot.trim() ? path26.resolve(raw.workspaceRoot.trim()) : void 0;
13617
13992
  const explicitName = typeof raw.name === "string" && raw.name.trim() ? raw.name.trim() : "";
13618
- const defaultName = workspaceRoot ? path25.basename(workspaceRoot) : id;
13993
+ const defaultName = workspaceRoot ? path26.basename(workspaceRoot) : id;
13619
13994
  const tenant = {
13620
13995
  id,
13621
13996
  name: explicitName || defaultName,
@@ -13645,7 +14020,7 @@ function buildNodeInfo(store, opts) {
13645
14020
  nodeId: opts.nodeId ?? ensureNodeId2(store),
13646
14021
  platform: process.platform,
13647
14022
  mode: process.env.NODE_MODE ?? "standalone",
13648
- version: "0.2.10",
14023
+ version: "0.2.11",
13649
14024
  admin: opts.admin,
13650
14025
  projects: opts.projects
13651
14026
  };
@@ -13824,34 +14199,34 @@ async function handleHubProxy(req2, res) {
13824
14199
 
13825
14200
  // src/server/fsBrowser.ts
13826
14201
  init_cjs_shims();
13827
- var fs21 = __toESM(require("fs"), 1);
13828
- var os4 = __toESM(require("os"), 1);
13829
- var path26 = __toESM(require("path"), 1);
14202
+ var fs22 = __toESM(require("fs"), 1);
14203
+ var os6 = __toESM(require("os"), 1);
14204
+ var path27 = __toESM(require("path"), 1);
13830
14205
  var MAX_ENTRIES = 2e3;
13831
14206
  var DEFAULT_SEARCH_LIMIT = 200;
13832
14207
  var MAX_SEARCH_LIMIT = 1e3;
13833
14208
  function listDirs(input) {
13834
- const base = (input ?? "").trim() || os4.homedir();
13835
- const target = path26.resolve(base);
14209
+ const base = (input ?? "").trim() || os6.homedir();
14210
+ const target = path27.resolve(base);
13836
14211
  let st;
13837
14212
  try {
13838
- st = fs21.statSync(target);
14213
+ st = fs22.statSync(target);
13839
14214
  } catch {
13840
14215
  throw new Error(`\u8DEF\u5F84\u4E0D\u5B58\u5728: ${target}`);
13841
14216
  }
13842
14217
  if (!st.isDirectory()) throw new Error(`\u4E0D\u662F\u76EE\u5F55: ${target}`);
13843
14218
  let dirents;
13844
14219
  try {
13845
- dirents = fs21.readdirSync(target, { withFileTypes: true });
14220
+ dirents = fs22.readdirSync(target, { withFileTypes: true });
13846
14221
  } catch {
13847
14222
  throw new Error(`\u65E0\u6CD5\u8BFB\u53D6\u76EE\u5F55\uFF08\u6743\u9650\u4E0D\u8DB3\uFF1F\uFF09: ${target}`);
13848
14223
  }
13849
14224
  const entries = dirents.map((d) => {
13850
- const full = path26.join(target, d.name);
14225
+ const full = path27.join(target, d.name);
13851
14226
  let isDir = d.isDirectory();
13852
14227
  if (d.isSymbolicLink()) {
13853
14228
  try {
13854
- isDir = fs21.statSync(full).isDirectory();
14229
+ isDir = fs22.statSync(full).isDirectory();
13855
14230
  } catch {
13856
14231
  }
13857
14232
  }
@@ -13860,7 +14235,7 @@ function listDirs(input) {
13860
14235
  entries.sort(
13861
14236
  (a, b) => a.type === b.type ? a.name.localeCompare(b.name) : a.type === "dir" ? -1 : 1
13862
14237
  );
13863
- const parentDir = path26.dirname(target);
14238
+ const parentDir = path27.dirname(target);
13864
14239
  return {
13865
14240
  path: target,
13866
14241
  parent: parentDir !== target ? parentDir : null,
@@ -13891,7 +14266,7 @@ var NAME_CACHE_MAX_DIRS = 4;
13891
14266
  var NAME_CACHE_MAX_ENTRIES = 5e4;
13892
14267
  var nameCache = /* @__PURE__ */ new Map();
13893
14268
  function invalidateDirNames(target) {
13894
- nameCache.delete(path26.resolve(target));
14269
+ nameCache.delete(path27.resolve(target));
13895
14270
  }
13896
14271
  async function loadDirNames(target) {
13897
14272
  const now = Date.now();
@@ -13903,7 +14278,7 @@ async function loadDirNames(target) {
13903
14278
  }
13904
14279
  let dirents;
13905
14280
  try {
13906
- dirents = await fs21.promises.readdir(target, { withFileTypes: true });
14281
+ dirents = await fs22.promises.readdir(target, { withFileTypes: true });
13907
14282
  } catch {
13908
14283
  throw new Error(`\u65E0\u6CD5\u8BFB\u53D6\u76EE\u5F55\uFF08\u6743\u9650\u4E0D\u8DB3\uFF1F\uFF09: ${target}`);
13909
14284
  }
@@ -13926,22 +14301,22 @@ async function loadDirNames(target) {
13926
14301
  return entries;
13927
14302
  }
13928
14303
  async function toDirEntry(dir, e) {
13929
- const full = path26.join(dir, e.name);
14304
+ const full = path27.join(dir, e.name);
13930
14305
  let isDir = e.isDir;
13931
14306
  if (e.isLink) {
13932
14307
  try {
13933
- isDir = (await fs21.promises.stat(full)).isDirectory();
14308
+ isDir = (await fs22.promises.stat(full)).isDirectory();
13934
14309
  } catch {
13935
14310
  }
13936
14311
  }
13937
14312
  return { name: e.name, path: full, type: isDir ? "dir" : "file" };
13938
14313
  }
13939
14314
  async function searchDirs(input, query, limit) {
13940
- const base = (input ?? "").trim() || os4.homedir();
13941
- const target = path26.resolve(base);
14315
+ const base = (input ?? "").trim() || os6.homedir();
14316
+ const target = path27.resolve(base);
13942
14317
  let st;
13943
14318
  try {
13944
- st = await fs21.promises.stat(target);
14319
+ st = await fs22.promises.stat(target);
13945
14320
  } catch {
13946
14321
  throw new Error(`\u8DEF\u5F84\u4E0D\u5B58\u5728: ${target}`);
13947
14322
  }
@@ -13971,7 +14346,7 @@ async function searchDirs(input, query, limit) {
13971
14346
  );
13972
14347
  const hit = scored.slice(0, max);
13973
14348
  const entries = await Promise.all(hit.map(({ entry }) => toDirEntry(target, entry)));
13974
- const parentDir = path26.dirname(target);
14349
+ const parentDir = path27.dirname(target);
13975
14350
  return {
13976
14351
  path: target,
13977
14352
  parent: parentDir !== target ? parentDir : null,
@@ -13982,52 +14357,52 @@ async function searchDirs(input, query, limit) {
13982
14357
  };
13983
14358
  }
13984
14359
  function makeDirIn(parentInput, name) {
13985
- const parent = path26.resolve((parentInput ?? "").trim() || os4.homedir());
14360
+ const parent = path27.resolve((parentInput ?? "").trim() || os6.homedir());
13986
14361
  const clean = (name ?? "").trim();
13987
14362
  if (!clean) throw new Error("\u76EE\u5F55\u540D\u4E0D\u80FD\u4E3A\u7A7A");
13988
14363
  if (clean === "." || clean === "..") throw new Error("\u76EE\u5F55\u540D\u975E\u6CD5");
13989
- const target = path26.resolve(parent, clean);
13990
- const rel = path26.relative(parent, target);
13991
- if (!rel || rel.startsWith("..") || path26.isAbsolute(rel)) {
14364
+ const target = path27.resolve(parent, clean);
14365
+ const rel = path27.relative(parent, target);
14366
+ if (!rel || rel.startsWith("..") || path27.isAbsolute(rel)) {
13992
14367
  throw new Error("\u76EE\u5F55\u540D\u4E0D\u80FD\u8D8A\u51FA\u5F53\u524D\u76EE\u5F55");
13993
14368
  }
13994
14369
  let st = null;
13995
14370
  try {
13996
- st = fs21.statSync(target);
14371
+ st = fs22.statSync(target);
13997
14372
  } catch {
13998
14373
  st = null;
13999
14374
  }
14000
14375
  if (st && !st.isDirectory()) throw new Error(`\u5DF2\u5B58\u5728\u540C\u540D\u6587\u4EF6: ${target}`);
14001
14376
  try {
14002
- fs21.mkdirSync(target, { recursive: true });
14377
+ fs22.mkdirSync(target, { recursive: true });
14003
14378
  } catch (e) {
14004
14379
  throw new Error(`\u521B\u5EFA\u76EE\u5F55\u5931\u8D25: ${e instanceof Error ? e.message : String(e)}`);
14005
14380
  }
14006
14381
  invalidateDirNames(parent);
14007
- return { name: path26.basename(target), path: target, type: "dir" };
14382
+ return { name: path27.basename(target), path: target, type: "dir" };
14008
14383
  }
14009
14384
 
14010
14385
  // src/server/projectFiles.ts
14011
14386
  init_cjs_shims();
14012
- var fs22 = __toESM(require("fs"), 1);
14013
- var path27 = __toESM(require("path"), 1);
14387
+ var fs23 = __toESM(require("fs"), 1);
14388
+ var path28 = __toESM(require("path"), 1);
14014
14389
  var MAX_FILE_BYTES = 2 * 1024 * 1024;
14015
14390
  var MAX_DOWNLOAD_BYTES = 16 * 1024 * 1024;
14016
14391
  var MAX_ENTRIES2 = 2e3;
14017
14392
  function toPosix(p) {
14018
- return p.split(path27.sep).join("/");
14393
+ return p.split(path28.sep).join("/");
14019
14394
  }
14020
14395
  function projectRoot(workspaceRoot) {
14021
14396
  const r = (workspaceRoot ?? "").trim();
14022
14397
  if (!r) {
14023
14398
  throw new Error("\u9879\u76EE\u672A\u8BBE\u7F6E\u5DE5\u4F5C\u533A\u76EE\u5F55\uFF08workspaceRoot\uFF09\uFF0C\u65E0\u6CD5\u6D4F\u89C8\u6587\u4EF6");
14024
14399
  }
14025
- const abs = path27.resolve(r);
14026
- if (!fs22.existsSync(abs)) {
14400
+ const abs = path28.resolve(r);
14401
+ if (!fs23.existsSync(abs)) {
14027
14402
  throw new Error(`\u5DE5\u4F5C\u533A\u76EE\u5F55\u4E0D\u5B58\u5728: ${abs}`);
14028
14403
  }
14029
14404
  try {
14030
- return fs22.realpathSync(abs);
14405
+ return fs23.realpathSync(abs);
14031
14406
  } catch {
14032
14407
  return abs;
14033
14408
  }
@@ -14045,37 +14420,37 @@ function listProjectFiles(workspaceRoot, relPath) {
14045
14420
  const dir = resolveWithin(base, relPath ?? "");
14046
14421
  let st;
14047
14422
  try {
14048
- st = fs22.statSync(dir);
14423
+ st = fs23.statSync(dir);
14049
14424
  } catch {
14050
- throw new Error(`\u76EE\u5F55\u4E0D\u5B58\u5728: ${toPosix(path27.relative(base, dir)) || "/"}`);
14425
+ throw new Error(`\u76EE\u5F55\u4E0D\u5B58\u5728: ${toPosix(path28.relative(base, dir)) || "/"}`);
14051
14426
  }
14052
14427
  if (!st.isDirectory()) throw new Error("\u76EE\u6807\u4E0D\u662F\u76EE\u5F55");
14053
14428
  let dirents;
14054
14429
  try {
14055
- dirents = fs22.readdirSync(dir, { withFileTypes: true });
14430
+ dirents = fs23.readdirSync(dir, { withFileTypes: true });
14056
14431
  } catch {
14057
14432
  throw new Error("\u65E0\u6CD5\u8BFB\u53D6\u76EE\u5F55\uFF08\u6743\u9650\u4E0D\u8DB3\uFF1F\uFF09");
14058
14433
  }
14059
14434
  const entries = dirents.map((d) => {
14060
- const full = path27.join(dir, d.name);
14435
+ const full = path28.join(dir, d.name);
14061
14436
  let isDir = d.isDirectory();
14062
14437
  if (d.isSymbolicLink()) {
14063
14438
  try {
14064
- isDir = fs22.statSync(full).isDirectory();
14439
+ isDir = fs23.statSync(full).isDirectory();
14065
14440
  } catch {
14066
14441
  }
14067
14442
  }
14068
14443
  let size = 0;
14069
14444
  let mtime = "";
14070
14445
  try {
14071
- const s = fs22.statSync(full);
14446
+ const s = fs23.statSync(full);
14072
14447
  size = s.size;
14073
14448
  mtime = s.mtime.toISOString();
14074
14449
  } catch {
14075
14450
  }
14076
14451
  return {
14077
14452
  name: d.name,
14078
- path: toPosix(path27.relative(base, full)),
14453
+ path: toPosix(path28.relative(base, full)),
14079
14454
  type: isDir ? "dir" : "file",
14080
14455
  size,
14081
14456
  mtime
@@ -14084,12 +14459,12 @@ function listProjectFiles(workspaceRoot, relPath) {
14084
14459
  entries.sort(
14085
14460
  (a, b) => a.type === b.type ? a.name.localeCompare(b.name) : a.type === "dir" ? -1 : 1
14086
14461
  );
14087
- const relDir = toPosix(path27.relative(base, dir));
14088
- const parentAbs = path27.dirname(dir);
14462
+ const relDir = toPosix(path28.relative(base, dir));
14463
+ const parentAbs = path28.dirname(dir);
14089
14464
  return {
14090
14465
  root: base,
14091
14466
  path: relDir,
14092
- parent: isWithinRoot(base, parentAbs) ? toPosix(path27.relative(base, parentAbs)) : null,
14467
+ parent: isWithinRoot(base, parentAbs) ? toPosix(path28.relative(base, parentAbs)) : null,
14093
14468
  entries: entries.slice(0, MAX_ENTRIES2)
14094
14469
  };
14095
14470
  }
@@ -14098,17 +14473,17 @@ function readProjectFile(workspaceRoot, relPath) {
14098
14473
  const file = resolveWithin(base, relPath ?? "");
14099
14474
  let st;
14100
14475
  try {
14101
- st = fs22.statSync(file);
14476
+ st = fs23.statSync(file);
14102
14477
  } catch {
14103
14478
  throw new Error("\u6587\u4EF6\u4E0D\u5B58\u5728");
14104
14479
  }
14105
14480
  if (!st.isFile()) throw new Error("\u76EE\u6807\u4E0D\u662F\u6587\u4EF6");
14106
- const buf = fs22.readFileSync(file);
14481
+ const buf = fs23.readFileSync(file);
14107
14482
  const binary = isBinary(buf);
14108
14483
  const truncated = buf.length > MAX_FILE_BYTES;
14109
14484
  const slice = truncated ? buf.subarray(0, MAX_FILE_BYTES) : buf;
14110
14485
  return {
14111
- path: toPosix(path27.relative(base, file)),
14486
+ path: toPosix(path28.relative(base, file)),
14112
14487
  size: st.size,
14113
14488
  binary,
14114
14489
  truncated,
@@ -14120,7 +14495,7 @@ function downloadProjectFile(workspaceRoot, relPath) {
14120
14495
  const file = resolveWithin(base, relPath ?? "");
14121
14496
  let st;
14122
14497
  try {
14123
- st = fs22.statSync(file);
14498
+ st = fs23.statSync(file);
14124
14499
  } catch {
14125
14500
  throw new Error("\u6587\u4EF6\u4E0D\u5B58\u5728");
14126
14501
  }
@@ -14128,10 +14503,10 @@ function downloadProjectFile(workspaceRoot, relPath) {
14128
14503
  if (st.size > MAX_DOWNLOAD_BYTES) {
14129
14504
  throw new Error(`\u6587\u4EF6\u8D85\u8FC7\u4E0B\u8F7D\u4E0A\u9650\uFF08${MAX_DOWNLOAD_BYTES / (1024 * 1024)}MB\uFF09`);
14130
14505
  }
14131
- const buf = fs22.readFileSync(file);
14506
+ const buf = fs23.readFileSync(file);
14132
14507
  return {
14133
- path: toPosix(path27.relative(base, file)),
14134
- name: path27.basename(file),
14508
+ path: toPosix(path28.relative(base, file)),
14509
+ name: path28.basename(file),
14135
14510
  size: buf.length,
14136
14511
  base64: buf.toString("base64")
14137
14512
  };
@@ -14153,12 +14528,12 @@ function writeProjectFile(workspaceRoot, relPath, content) {
14153
14528
  throw new Error("\u5185\u5BB9\u8D85\u8FC7 2MB \u4E0A\u9650\uFF0C\u65E0\u6CD5\u4FDD\u5B58");
14154
14529
  }
14155
14530
  try {
14156
- fs22.mkdirSync(path27.dirname(file), { recursive: true });
14157
- fs22.writeFileSync(file, buf);
14531
+ fs23.mkdirSync(path28.dirname(file), { recursive: true });
14532
+ fs23.writeFileSync(file, buf);
14158
14533
  } catch (e) {
14159
14534
  throw new Error(`\u5199\u5165\u5931\u8D25\uFF1A${e instanceof Error ? e.message : String(e)}`);
14160
14535
  }
14161
- return { path: toPosix(path27.relative(base, file)), size: buf.length };
14536
+ return { path: toPosix(path28.relative(base, file)), size: buf.length };
14162
14537
  }
14163
14538
  function createProjectDir(workspaceRoot, relPath) {
14164
14539
  const base = projectRoot(workspaceRoot);
@@ -14166,26 +14541,26 @@ function createProjectDir(workspaceRoot, relPath) {
14166
14541
  if (!rel) throw new Error("\u76EE\u5F55\u8DEF\u5F84\u4E0D\u80FD\u4E3A\u7A7A");
14167
14542
  const dir = resolveWithin(base, rel);
14168
14543
  try {
14169
- fs22.mkdirSync(dir, { recursive: true });
14544
+ fs23.mkdirSync(dir, { recursive: true });
14170
14545
  } catch (e) {
14171
14546
  throw new Error(`\u521B\u5EFA\u76EE\u5F55\u5931\u8D25\uFF1A${e instanceof Error ? e.message : String(e)}`);
14172
14547
  }
14173
- return { path: toPosix(path27.relative(base, dir)) };
14548
+ return { path: toPosix(path28.relative(base, dir)) };
14174
14549
  }
14175
14550
  function createProjectFile(workspaceRoot, relPath, content = "") {
14176
14551
  const base = projectRoot(workspaceRoot);
14177
14552
  const rel = (relPath ?? "").trim();
14178
14553
  if (!rel) throw new Error("\u6587\u4EF6\u8DEF\u5F84\u4E0D\u80FD\u4E3A\u7A7A");
14179
14554
  const file = resolveWithin(base, rel);
14180
- if (fs22.existsSync(file)) throw new Error("\u6587\u4EF6\u5DF2\u5B58\u5728");
14555
+ if (fs23.existsSync(file)) throw new Error("\u6587\u4EF6\u5DF2\u5B58\u5728");
14181
14556
  const buf = Buffer.from(String(content ?? ""), "utf-8");
14182
14557
  try {
14183
- fs22.mkdirSync(path27.dirname(file), { recursive: true });
14184
- fs22.writeFileSync(file, buf);
14558
+ fs23.mkdirSync(path28.dirname(file), { recursive: true });
14559
+ fs23.writeFileSync(file, buf);
14185
14560
  } catch (e) {
14186
14561
  throw new Error(`\u521B\u5EFA\u6587\u4EF6\u5931\u8D25\uFF1A${e instanceof Error ? e.message : String(e)}`);
14187
14562
  }
14188
- return { path: toPosix(path27.relative(base, file)), size: buf.length };
14563
+ return { path: toPosix(path28.relative(base, file)), size: buf.length };
14189
14564
  }
14190
14565
  function searchProjectFiles(workspaceRoot, query) {
14191
14566
  const base = projectRoot(workspaceRoot);
@@ -14208,7 +14583,7 @@ function searchProjectFiles(workspaceRoot, query) {
14208
14583
  if (out.length >= LIMIT) return;
14209
14584
  let dirents;
14210
14585
  try {
14211
- dirents = fs22.readdirSync(dir, { withFileTypes: true });
14586
+ dirents = fs23.readdirSync(dir, { withFileTypes: true });
14212
14587
  } catch {
14213
14588
  return;
14214
14589
  }
@@ -14219,7 +14594,7 @@ function searchProjectFiles(workspaceRoot, query) {
14219
14594
  let isDir = d.isDirectory();
14220
14595
  if (d.isSymbolicLink()) {
14221
14596
  try {
14222
- isDir = fs22.statSync(path27.join(dir, d.name)).isDirectory();
14597
+ isDir = fs23.statSync(path28.join(dir, d.name)).isDirectory();
14223
14598
  } catch {
14224
14599
  isDir = false;
14225
14600
  }
@@ -14227,7 +14602,7 @@ function searchProjectFiles(workspaceRoot, query) {
14227
14602
  if (d.name.toLowerCase().includes(q)) {
14228
14603
  out.push({ path: rel, type: isDir ? "dir" : "file" });
14229
14604
  }
14230
- if (isDir) walk(path27.join(dir, d.name), rel);
14605
+ if (isDir) walk(path28.join(dir, d.name), rel);
14231
14606
  }
14232
14607
  };
14233
14608
  walk(base, "");
@@ -14236,8 +14611,8 @@ function searchProjectFiles(workspaceRoot, query) {
14236
14611
 
14237
14612
  // src/server/projectOps.ts
14238
14613
  init_cjs_shims();
14239
- var os5 = __toESM(require("os"), 1);
14240
- var path28 = __toESM(require("path"), 1);
14614
+ var os7 = __toESM(require("os"), 1);
14615
+ var path29 = __toESM(require("path"), 1);
14241
14616
  var MAX_STDOUT2 = 2e4;
14242
14617
  var MAX_STDERR2 = 1e4;
14243
14618
  var MAX_BUFFER3 = 1024 * 1024 * 5;
@@ -14251,7 +14626,7 @@ function resolveInvocation2(spec, prepared) {
14251
14626
  }
14252
14627
  function workRoot(workspaceRoot) {
14253
14628
  const r = (workspaceRoot ?? "").trim();
14254
- return r ? path28.resolve(r) : os5.homedir();
14629
+ return r ? path29.resolve(r) : os7.homedir();
14255
14630
  }
14256
14631
  async function runProjectCommand(workspaceRoot, command, timeoutSeconds) {
14257
14632
  const cmd = String(command ?? "");
@@ -14562,11 +14937,11 @@ function projectStats(manager, tenantId) {
14562
14937
 
14563
14938
  // src/server/nodeHost.ts
14564
14939
  init_cjs_shims();
14565
- var fs23 = __toESM(require("fs"), 1);
14566
- var os6 = __toESM(require("os"), 1);
14940
+ var fs24 = __toESM(require("fs"), 1);
14941
+ var os8 = __toESM(require("os"), 1);
14567
14942
  function diskInfo(pathStr) {
14568
14943
  try {
14569
- const st = fs23.statfsSync(pathStr);
14944
+ const st = fs24.statfsSync(pathStr);
14570
14945
  return {
14571
14946
  path: pathStr,
14572
14947
  total: Number(st.blocks) * Number(st.bsize),
@@ -14578,7 +14953,7 @@ function diskInfo(pathStr) {
14578
14953
  }
14579
14954
  function networkInfo() {
14580
14955
  const out = [];
14581
- const ifaces = os6.networkInterfaces();
14956
+ const ifaces = os8.networkInterfaces();
14582
14957
  for (const [name, list] of Object.entries(ifaces)) {
14583
14958
  for (const info of list ?? []) {
14584
14959
  out.push({
@@ -14629,23 +15004,23 @@ function overview(store, manager) {
14629
15004
  return { projects, sessions: { total, running, waiting, items }, usage: { tokensIn, tokensOut } };
14630
15005
  }
14631
15006
  function buildNodeHost(store, manager, diskPath) {
14632
- const cpus2 = os6.cpus();
15007
+ const cpus2 = os8.cpus();
14633
15008
  const ov = overview(store, manager);
14634
15009
  return {
14635
15010
  nodeId: store.loadNodeId() ?? "",
14636
- hostname: os6.hostname(),
15011
+ hostname: os8.hostname(),
14637
15012
  platform: process.platform,
14638
15013
  arch: process.arch,
14639
- release: os6.release(),
14640
- uptimeSec: Math.round(os6.uptime()),
14641
- version: "0.2.10",
15014
+ release: os8.release(),
15015
+ uptimeSec: Math.round(os8.uptime()),
15016
+ version: "0.2.11",
14642
15017
  mode: process.env.NODE_MODE ?? "standalone",
14643
15018
  cpu: {
14644
15019
  count: cpus2.length,
14645
15020
  model: cpus2[0]?.model ?? "",
14646
- loadAvg: os6.loadavg().map((n) => Math.round(n * 100) / 100)
15021
+ loadAvg: os8.loadavg().map((n) => Math.round(n * 100) / 100)
14647
15022
  },
14648
- memory: { total: os6.totalmem(), free: os6.freemem() },
15023
+ memory: { total: os8.totalmem(), free: os8.freemem() },
14649
15024
  network: networkInfo(),
14650
15025
  disk: diskInfo(diskPath || process.cwd()),
14651
15026
  ...ov
@@ -15213,7 +15588,7 @@ function createApp(store, manager, opts = {}) {
15213
15588
  applyProvidersPatch(tenant, raw);
15214
15589
  if (typeof raw.workspaceRoot === "string") {
15215
15590
  const ws = raw.workspaceRoot.trim();
15216
- const next = ws ? path29.resolve(ws) : void 0;
15591
+ const next = ws ? path30.resolve(ws) : void 0;
15217
15592
  if (tenant.workspaceRoot) {
15218
15593
  if (next !== tenant.workspaceRoot) {
15219
15594
  throw new ApiError(
@@ -16200,7 +16575,7 @@ function createApp(store, manager, opts = {}) {
16200
16575
  json(res, 200, {
16201
16576
  status: "ok",
16202
16577
  // 版本让运维/探针能确认线上跑的是哪个构建(更新与回滚据此判断)
16203
- version: "0.2.10",
16578
+ version: "0.2.11",
16204
16579
  features: { mcp: hasServerMcpConfig() }
16205
16580
  });
16206
16581
  return;
@@ -16295,7 +16670,7 @@ function createApp(store, manager, opts = {}) {
16295
16670
 
16296
16671
  // src/server/fleet/FleetNodeBridge.ts
16297
16672
  init_cjs_shims();
16298
- var os7 = __toESM(require("os"), 1);
16673
+ var os9 = __toESM(require("os"), 1);
16299
16674
  var import_node_perf_hooks = require("perf_hooks");
16300
16675
 
16301
16676
  // src/server/fleet/FleetCommands.ts
@@ -17489,7 +17864,7 @@ function withTimeout(p, ms) {
17489
17864
  }
17490
17865
  function primaryIp() {
17491
17866
  let v6;
17492
- for (const infos of Object.values(os7.networkInterfaces())) {
17867
+ for (const infos of Object.values(os9.networkInterfaces())) {
17493
17868
  for (const info of infos ?? []) {
17494
17869
  if (info.internal) continue;
17495
17870
  if (info.family === "IPv4") return info.address;
@@ -17838,7 +18213,7 @@ var FleetNodeBridge = class {
17838
18213
  label: this.opts.deps.store.loadNodeLabel() ?? void 0,
17839
18214
  platform: process.platform,
17840
18215
  mode: process.env.NODE_MODE ?? "standalone",
17841
- version: "0.2.10",
18216
+ version: "0.2.11",
17842
18217
  ip: primaryIp()
17843
18218
  };
17844
18219
  }
@@ -17893,7 +18268,7 @@ var FleetNodeBridge = class {
17893
18268
  label: this.opts.deps.store.loadNodeLabel() ?? void 0,
17894
18269
  platform: process.platform,
17895
18270
  mode: process.env.NODE_MODE ?? "standalone",
17896
- version: "0.2.10",
18271
+ version: "0.2.11",
17897
18272
  ip: primaryIp(),
17898
18273
  projects,
17899
18274
  totals,
@@ -18662,8 +19037,8 @@ init_cjs_shims();
18662
19037
 
18663
19038
  // src/server/qq/bindings.ts
18664
19039
  init_cjs_shims();
18665
- var fs24 = __toESM(require("fs"), 1);
18666
- var path30 = __toESM(require("path"), 1);
19040
+ var fs25 = __toESM(require("fs"), 1);
19041
+ var path31 = __toESM(require("path"), 1);
18667
19042
  function conversationKey(target) {
18668
19043
  switch (target.kind) {
18669
19044
  case "c2c":
@@ -18702,12 +19077,12 @@ var QqBindingsStore = class _QqBindingsStore {
18702
19077
  cache = null;
18703
19078
  /** 基于 DATA_DIR 构造 */
18704
19079
  static in(dataDir) {
18705
- return new _QqBindingsStore(path30.join(dataDir, "qq", "bindings.json"));
19080
+ return new _QqBindingsStore(path31.join(dataDir, "qq", "bindings.json"));
18706
19081
  }
18707
19082
  load() {
18708
19083
  if (this.cache) return this.cache;
18709
19084
  try {
18710
- const raw = JSON.parse(fs24.readFileSync(this.file, "utf-8"));
19085
+ const raw = JSON.parse(fs25.readFileSync(this.file, "utf-8"));
18711
19086
  this.cache = {
18712
19087
  conversations: raw.conversations ?? {}
18713
19088
  };
@@ -18739,8 +19114,8 @@ var QqBindingsStore = class _QqBindingsStore {
18739
19114
  return null;
18740
19115
  }
18741
19116
  persist() {
18742
- fs24.mkdirSync(path30.dirname(this.file), { recursive: true });
18743
- fs24.writeFileSync(this.file, JSON.stringify(this.cache, null, 2), "utf-8");
19117
+ fs25.mkdirSync(path31.dirname(this.file), { recursive: true });
19118
+ fs25.writeFileSync(this.file, JSON.stringify(this.cache, null, 2), "utf-8");
18744
19119
  }
18745
19120
  };
18746
19121
 
@@ -19152,8 +19527,8 @@ ${lines.join("\n")}`, msgId);
19152
19527
 
19153
19528
  // src/server/qq/QqManager.ts
19154
19529
  init_cjs_shims();
19155
- var fs25 = __toESM(require("fs"), 1);
19156
- var path31 = __toESM(require("path"), 1);
19530
+ var fs26 = __toESM(require("fs"), 1);
19531
+ var path32 = __toESM(require("path"), 1);
19157
19532
  var QqManager = class {
19158
19533
  constructor(opts) {
19159
19534
  this.opts = opts;
@@ -19162,7 +19537,7 @@ var QqManager = class {
19162
19537
  adapter = null;
19163
19538
  config = null;
19164
19539
  get configFile() {
19165
- return path31.join(this.opts.dataDir, "qq", "config.json");
19540
+ return path32.join(this.opts.dataDir, "qq", "config.json");
19166
19541
  }
19167
19542
  /** 启动:读配置(env 优先,其次文件),有则建连接 */
19168
19543
  start() {
@@ -19200,7 +19575,7 @@ var QqManager = class {
19200
19575
  /** 清空配置:删除文件 + 断开 */
19201
19576
  clearConfig() {
19202
19577
  try {
19203
- fs25.rmSync(this.configFile, { force: true });
19578
+ fs26.rmSync(this.configFile, { force: true });
19204
19579
  } catch {
19205
19580
  }
19206
19581
  this.stop();
@@ -19242,7 +19617,7 @@ var QqManager = class {
19242
19617
  }
19243
19618
  _readConfigFile() {
19244
19619
  try {
19245
- const raw = JSON.parse(fs25.readFileSync(this.configFile, "utf-8"));
19620
+ const raw = JSON.parse(fs26.readFileSync(this.configFile, "utf-8"));
19246
19621
  if (raw.appId && raw.appSecret) {
19247
19622
  return {
19248
19623
  appId: raw.appId,
@@ -19255,8 +19630,8 @@ var QqManager = class {
19255
19630
  return null;
19256
19631
  }
19257
19632
  _persistConfig(cfg) {
19258
- fs25.mkdirSync(path31.dirname(this.configFile), { recursive: true });
19259
- fs25.writeFileSync(this.configFile, JSON.stringify(cfg, null, 2), "utf-8");
19633
+ fs26.mkdirSync(path32.dirname(this.configFile), { recursive: true });
19634
+ fs26.writeFileSync(this.configFile, JSON.stringify(cfg, null, 2), "utf-8");
19260
19635
  }
19261
19636
  };
19262
19637
 
@@ -19310,11 +19685,11 @@ var path36 = __toESM(require("path"), 1);
19310
19685
  // src/update/downloader.ts
19311
19686
  init_cjs_shims();
19312
19687
  var import_node_crypto5 = require("crypto");
19313
- var fs26 = __toESM(require("fs"), 1);
19688
+ var fs27 = __toESM(require("fs"), 1);
19314
19689
  var import_node_stream2 = require("stream");
19315
19690
  var import_promises2 = require("stream/promises");
19316
- var import_node_child_process5 = require("child_process");
19317
- var path32 = __toESM(require("path"), 1);
19691
+ var import_node_child_process6 = require("child_process");
19692
+ var path33 = __toESM(require("path"), 1);
19318
19693
 
19319
19694
  // src/update/manifest.ts
19320
19695
  init_cjs_shims();
@@ -19491,8 +19866,8 @@ async function fetchManifest(url, publicKey, opts = {}) {
19491
19866
  async function downloadBinary(bin, destPath, log = () => {
19492
19867
  }) {
19493
19868
  const partPath = `${destPath}.part`;
19494
- fs26.mkdirSync(path32.dirname(destPath), { recursive: true });
19495
- fs26.rmSync(partPath, { force: true });
19869
+ fs27.mkdirSync(path33.dirname(destPath), { recursive: true });
19870
+ fs27.rmSync(partPath, { force: true });
19496
19871
  let res;
19497
19872
  try {
19498
19873
  res = await fetch(bin.url, { signal: AbortSignal.timeout(DOWNLOAD_TIMEOUT_MS2) });
@@ -19517,30 +19892,30 @@ async function downloadBinary(bin, destPath, log = () => {
19517
19892
  yield chunk;
19518
19893
  }
19519
19894
  },
19520
- fs26.createWriteStream(partPath, { mode: 493 })
19895
+ fs27.createWriteStream(partPath, { mode: 493 })
19521
19896
  );
19522
19897
  } catch (err) {
19523
- fs26.rmSync(partPath, { force: true });
19898
+ fs27.rmSync(partPath, { force: true });
19524
19899
  return { error: `\u4E0B\u8F7D\u4E2D\u65AD\uFF1A${err.message}` };
19525
19900
  }
19526
19901
  const actual = hash.digest("hex");
19527
19902
  if (actual !== bin.sha256) {
19528
- fs26.rmSync(partPath, { force: true });
19903
+ fs27.rmSync(partPath, { force: true });
19529
19904
  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` };
19530
19905
  }
19531
19906
  if (expected && bytes !== expected) {
19532
- fs26.rmSync(partPath, { force: true });
19907
+ fs27.rmSync(partPath, { force: true });
19533
19908
  return { error: `\u4EA7\u7269\u5927\u5C0F\u4E0D\u5339\u914D\uFF08\u671F\u671B ${expected}\uFF0C\u5B9E\u9645 ${bytes}\uFF09` };
19534
19909
  }
19535
- fs26.rmSync(destPath, { force: true });
19536
- fs26.renameSync(partPath, destPath);
19537
- fs26.chmodSync(destPath, 493);
19538
- log(`\u5DF2\u4E0B\u8F7D ${path32.basename(destPath)}\uFF08${Math.round(bytes / 1024 / 1024)}MB\uFF0C\u6821\u9A8C\u901A\u8FC7\uFF09`);
19910
+ fs27.rmSync(destPath, { force: true });
19911
+ fs27.renameSync(partPath, destPath);
19912
+ fs27.chmodSync(destPath, 493);
19913
+ log(`\u5DF2\u4E0B\u8F7D ${path33.basename(destPath)}\uFF08${Math.round(bytes / 1024 / 1024)}MB\uFF0C\u6821\u9A8C\u901A\u8FC7\uFF09`);
19539
19914
  return { bytes };
19540
19915
  }
19541
19916
  function selfCheck(binPath, expectedVersion) {
19542
19917
  try {
19543
- const r = (0, import_node_child_process5.spawnSync)(binPath, ["--version"], {
19918
+ const r = (0, import_node_child_process6.spawnSync)(binPath, ["--version"], {
19544
19919
  timeout: 2e4,
19545
19920
  encoding: "utf-8",
19546
19921
  env: { ...process.env, ZQAGENT_AUTO_UPDATE: "0" }
@@ -19557,176 +19932,6 @@ function selfCheck(binPath, expectedVersion) {
19557
19932
  }
19558
19933
  }
19559
19934
 
19560
- // src/update/platform.ts
19561
- init_cjs_shims();
19562
- var fs27 = __toESM(require("fs"), 1);
19563
- var os8 = __toESM(require("os"), 1);
19564
- var path33 = __toESM(require("path"), 1);
19565
- var import_node_child_process6 = require("child_process");
19566
- var import_node_module3 = require("module");
19567
- function currentVersion() {
19568
- const injected = "0.2.10"?.trim();
19569
- if (injected) return injected;
19570
- try {
19571
- const req2 = (0, import_node_module3.createRequire)(importMetaUrl);
19572
- const pkg = req2("../../package.json");
19573
- if (pkg?.version) return pkg.version;
19574
- } catch {
19575
- }
19576
- return "dev";
19577
- }
19578
- function isSeaRuntime() {
19579
- if (process.env.ZQAGENT_SEA === "1") return true;
19580
- const base = path33.basename(process.execPath).toLowerCase().replace(/\.exe$/, "");
19581
- return base !== "node" && base !== "nodejs";
19582
- }
19583
- var DEFAULT_SERVICE_NAME = "zqagent";
19584
- var DEFAULT_SERVICE_LABEL = "com.zqagent.node";
19585
- function serviceManagerFromCgroup(cgroup, serviceName = DEFAULT_SERVICE_NAME) {
19586
- const unitName = `${serviceName}.service`;
19587
- for (const line of cgroup.split("\n")) {
19588
- const idx = line.lastIndexOf(":");
19589
- if (idx < 0) continue;
19590
- const unitPath = line.slice(idx + 1).trim();
19591
- if (unitPath.split("/").includes(unitName)) return "systemd";
19592
- }
19593
- return null;
19594
- }
19595
- function launchdDomain() {
19596
- const uid = typeof process.getuid === "function" ? process.getuid() : -1;
19597
- return uid === 0 ? "system" : `gui/${uid}`;
19598
- }
19599
- function launchdLabel() {
19600
- return process.env.ZQAGENT_SERVICE_LABEL?.trim() || DEFAULT_SERVICE_LABEL;
19601
- }
19602
- function launchdPlistPath() {
19603
- const label = launchdLabel();
19604
- const uid = typeof process.getuid === "function" ? process.getuid() : -1;
19605
- if (uid === 0) return `/Library/LaunchDaemons/${label}.plist`;
19606
- return path33.join(os8.homedir(), "Library", "LaunchAgents", `${label}.plist`);
19607
- }
19608
- function serviceManagerFromLaunchctl(output, pid, execPath, sea = true) {
19609
- const pidMatch = /^\s*pid = (\d+)\s*$/m.exec(output);
19610
- if (pidMatch && Number(pidMatch[1]) === pid) return "launchd";
19611
- const program = /^\s*program = (.+?)\s*$/m.exec(output);
19612
- if (program) {
19613
- const shown = program[1].replace(/^"|"$/g, "");
19614
- if (path33.resolve(shown) === path33.resolve(execPath)) return "launchd";
19615
- }
19616
- if (!sea && /^\s*state = /m.test(output)) return "launchd";
19617
- return null;
19618
- }
19619
- function parseLaunchdEnvironment(xml) {
19620
- const out = {};
19621
- const marker = xml.indexOf("<key>EnvironmentVariables</key>");
19622
- if (marker < 0) return out;
19623
- const open = xml.indexOf("<dict>", marker);
19624
- if (open < 0) return out;
19625
- const close = xml.indexOf("</dict>", open);
19626
- if (close < 0) return out;
19627
- const body = xml.slice(open + "<dict>".length, close);
19628
- for (const m of body.matchAll(/<key>([^<]+)<\/key>\s*<string>([^<]*)<\/string>/g)) {
19629
- out[m[1]] = m[2];
19630
- }
19631
- return out;
19632
- }
19633
- function detectServiceManager() {
19634
- if (process.platform === "darwin") return detectLaunchd();
19635
- if (process.platform !== "linux") return null;
19636
- const serviceName = process.env.ZQAGENT_SERVICE_NAME?.trim() || DEFAULT_SERVICE_NAME;
19637
- try {
19638
- return serviceManagerFromCgroup(
19639
- fs27.readFileSync("/proc/self/cgroup", "utf8"),
19640
- serviceName
19641
- );
19642
- } catch {
19643
- return null;
19644
- }
19645
- }
19646
- function detectLaunchd() {
19647
- try {
19648
- const res = (0, import_node_child_process6.spawnSync)(
19649
- "launchctl",
19650
- ["print", `${launchdDomain()}/${launchdLabel()}`],
19651
- { encoding: "utf8", timeout: 3e3 }
19652
- );
19653
- if (res.status !== 0 || !res.stdout) return null;
19654
- return serviceManagerFromLaunchctl(
19655
- res.stdout,
19656
- process.pid,
19657
- process.execPath,
19658
- isSeaRuntime()
19659
- );
19660
- } catch {
19661
- return null;
19662
- }
19663
- }
19664
- function serviceManager() {
19665
- const v = process.env.ZQAGENT_SERVICE_MANAGER?.trim().toLowerCase();
19666
- if (v === "systemd" || v === "launchd") return v;
19667
- return detectServiceManager();
19668
- }
19669
- function parseServiceEnvironment(raw) {
19670
- const out = {};
19671
- for (const token of raw.trim().split(/\s+/)) {
19672
- const idx = token.indexOf("=");
19673
- if (idx > 0) out[token.slice(0, idx)] = token.slice(idx + 1);
19674
- }
19675
- return out;
19676
- }
19677
- var cachedServiceEnv = null;
19678
- function readServiceEnvironment() {
19679
- const serviceName = process.env.ZQAGENT_SERVICE_NAME?.trim() || DEFAULT_SERVICE_NAME;
19680
- try {
19681
- const res = (0, import_node_child_process6.spawnSync)(
19682
- "systemctl",
19683
- ["show", serviceName, "--property=Environment", "--value", "--no-pager"],
19684
- { encoding: "utf8", timeout: 3e3 }
19685
- );
19686
- if (res.status !== 0 || !res.stdout) return {};
19687
- return parseServiceEnvironment(res.stdout);
19688
- } catch {
19689
- return {};
19690
- }
19691
- }
19692
- function serviceEnvValue(key) {
19693
- if (process.platform === "darwin") {
19694
- if (serviceManager() !== "launchd") return void 0;
19695
- cachedLaunchdEnv ??= readLaunchdEnvironment();
19696
- return cachedLaunchdEnv[key];
19697
- }
19698
- if (process.platform !== "linux") return void 0;
19699
- if (serviceManager() !== "systemd") return void 0;
19700
- cachedServiceEnv ??= readServiceEnvironment();
19701
- return cachedServiceEnv[key];
19702
- }
19703
- var cachedLaunchdEnv = null;
19704
- function readLaunchdEnvironment() {
19705
- try {
19706
- return parseLaunchdEnvironment(fs27.readFileSync(launchdPlistPath(), "utf8"));
19707
- } catch {
19708
- return {};
19709
- }
19710
- }
19711
- function selfUpdateCapability(hasPublicKey) {
19712
- if (!isSeaRuntime()) {
19713
- return {
19714
- ok: false,
19715
- 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"
19716
- };
19717
- }
19718
- if (!serviceManager()) {
19719
- return {
19720
- ok: false,
19721
- reason: "\u672A\u88AB systemd/launchd \u6258\u7BA1\uFF1A\u8BF7\u7528 deploy/service/install.sh \u5B89\u88C5\uFF0C\u6216\u624B\u52A8\u5347\u7EA7"
19722
- };
19723
- }
19724
- if (!hasPublicKey) {
19725
- return { ok: false, reason: "\u672A\u914D\u7F6E ZQAGENT_UPDATE_PUBKEY\uFF0C\u65E0\u6CD5\u9A8C\u7B7E\uFF0C\u5DF2\u7981\u7528\u81EA\u52A8\u66F4\u65B0" };
19726
- }
19727
- return { ok: true };
19728
- }
19729
-
19730
19935
  // src/update/installer.ts
19731
19936
  init_cjs_shims();
19732
19937
  var fs29 = __toESM(require("fs"), 1);
@@ -20923,7 +21128,7 @@ function updateSessionMetaFile(stateDir2, sessionId, patch) {
20923
21128
  // src/cli/debug.ts
20924
21129
  init_cjs_shims();
20925
21130
  var fs33 = __toESM(require("fs"), 1);
20926
- var os9 = __toESM(require("os"), 1);
21131
+ var os10 = __toESM(require("os"), 1);
20927
21132
  var path41 = __toESM(require("path"), 1);
20928
21133
  var LOG_NAME = "zqagent-debug.log";
20929
21134
  var TRUTHY = /^(1|true|yes|on)$/i;
@@ -20937,7 +21142,7 @@ function resolveLogFile() {
20937
21142
  const explicit = process.env.ZQAGENT_DEBUG_LOG;
20938
21143
  if (explicit) return path41.resolve(explicit);
20939
21144
  const dir = process.env.ZQAGENT_DEBUG_DIR;
20940
- return path41.join(dir ? path41.resolve(dir) : os9.tmpdir(), LOG_NAME);
21145
+ return path41.join(dir ? path41.resolve(dir) : os10.tmpdir(), LOG_NAME);
20941
21146
  }
20942
21147
  function enableDebug(argv = process.argv) {
20943
21148
  if (enabled) return true;
@@ -21375,20 +21580,7 @@ var _exitHandler = null;
21375
21580
  rl.on("SIGINT", () => {
21376
21581
  _exitHandler?.();
21377
21582
  });
21378
- function patchReadlineHistoryNav() {
21379
- const iface = rl;
21380
- const orig = iface._ttyWrite;
21381
- iface._ttyWrite = function(s, key) {
21382
- const k = key;
21383
- if (k && (k.name === "up" || k.name === "down") && !k.ctrl && !k.meta && !k.shift) {
21384
- if (iface.cursor > 0) {
21385
- iface._moveCursor(-iface.cursor);
21386
- }
21387
- }
21388
- orig.call(rl, s, key);
21389
- };
21390
- }
21391
- patchReadlineHistoryNav();
21583
+ patchReadlineHistoryNav(rl);
21392
21584
  dlog("init", "\u6A21\u5757\u521D\u59CB\u5316\u5B8C\u6210\uFF08readline / \u8F93\u5165\u8DEF\u7531 / \u5386\u53F2\u5BFC\u822A\u5C31\u7EEA\uFF09");
21393
21585
  function question(prompt) {
21394
21586
  return inputRouter.ask(prompt);
@@ -21852,7 +22044,7 @@ async function offerTerminalSetup(engine, canUseAgent) {
21852
22044
  }
21853
22045
  var KNOWN_SUBCOMMANDS = /* @__PURE__ */ new Set(["link", "serve", "update"]);
21854
22046
  function cliVersion() {
21855
- const env3 = "0.2.10"?.trim();
22047
+ const env3 = "0.2.11"?.trim();
21856
22048
  if (env3) return env3;
21857
22049
  try {
21858
22050
  const req2 = (0, import_module.createRequire)(importMetaUrl);