dsh-lark-bot 0.19.2 → 0.19.3

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 CHANGED
@@ -334,7 +334,7 @@ profile 的前台进程会拒绝并提示先停止,生命周期锁阻止并发
334
334
 
335
335
  ### 升级
336
336
 
337
- **完全不接触命令行:** profile 管理员在飞书发送 `/upgrade`。有新版本时 bot 弹出只允许发起人操作的确认卡;点击“确认更新”后,Guardian 通过独立 worker 安装卡片中确认的精确 npm 版本,复用完整升级、runtime profile 修复、guardian/profile 重启和 doctor 验证链,并在重载后回到原会话报告结果。点击“取消”不会产生任何变更。更新会重启机器人,正在执行的任务可能被中断;配置、会话、归档和凭据保持不变。每次 `/new` / `/reset` 都会 best-effort 查询一次 npm;仅在有新版本时额外发送一条简短普通消息。
337
+ **完全不接触命令行:** profile 管理员在飞书发送 `/upgrade`。有新版本时 bot 弹出只允许发起人操作的确认卡;点击“确认更新”后,Guardian 通过独立 worker 安装卡片中确认的精确 npm 版本,复用完整升级、runtime profile 修复、guardian/profile 重启和 doctor 验证链,并在重载后回到原会话报告结果。worker 使用 owner-only 中立工作目录与每次请求隔离的 npm cache,不依赖 bridge 启动目录或用户全局 npm cache;失败时只回传脱敏的可行动类别,不发送原始命令输出。点击“取消”不会产生任何变更。更新会重启机器人,正在执行的任务可能被中断;配置、会话、归档和凭据保持不变。每次 `/new` / `/reset` 都会 best-effort 查询一次 npm;仅在有新版本时额外发送一条简短普通消息。
338
338
 
339
339
  **推荐:一行命令彻底升级(v0.12.0+ 新增,issue #10)**
340
340
 
@@ -724,6 +724,8 @@ pnpm publish:dual
724
724
  默认安装的「安全网守护」(`src/guardian/`)独立于 dsh 进程常驻:dsh 在线时静默,下线时接管飞书
725
725
  通道接收 `/safemode` 控制信号,以仅核心 profile(`dsh-base` + `dsh-headless`)拉起受限对话
726
726
  用于自愈,`/safemode exit` 重启完整 profile 并交还通道。
727
+ `dsh-lark-bot guardian status` 只报告精确 `guardian run` 进程身份唯一且存活的常驻 PID,并在
728
+ 系统服务 PID 可用时交叉验证;身份不确定时显示“未发现”,不会把查询命令自身 PID 当成守护进程。
727
729
 
728
730
  ## 目录结构
729
731
 
package/dist/cli.js CHANGED
@@ -838,14 +838,67 @@ var init_acp_adapter = __esm({
838
838
  var process_exports = {};
839
839
  __export(process_exports, {
840
840
  captureOutput: () => captureOutput,
841
+ findGuardianProcess: () => findGuardianProcess,
841
842
  findProfileProcess: () => findProfileProcess,
842
843
  isProcessAlive: () => isProcessAlive,
843
844
  listProcesses: () => listProcesses,
844
845
  looksLikeDshProcess: () => looksLikeDshProcess,
846
+ matchGuardianProcess: () => matchGuardianProcess,
845
847
  matchProfileProcess: () => matchProfileProcess,
846
848
  spawnDetached: () => spawnDetached
847
849
  });
848
850
  import { spawn as spawn5 } from "child_process";
851
+ function commandTokens(cmdline) {
852
+ const tokens = [];
853
+ let token = "";
854
+ let quote;
855
+ const input = cmdline.trim();
856
+ for (let index = 0; index < input.length; index += 1) {
857
+ const character = input[index] ?? "";
858
+ const next = input[index + 1];
859
+ if (character === "\\" && quote === void 0 && next !== void 0 && /[\s\\"']/u.test(next)) {
860
+ token += next;
861
+ index += 1;
862
+ } else if (character === "\\" && quote === '"' && next === '"') {
863
+ token += next;
864
+ index += 1;
865
+ } else if (quote !== void 0) {
866
+ if (character === quote) quote = void 0;
867
+ else token += character;
868
+ } else if (character === '"' || character === "'") {
869
+ quote = character;
870
+ } else if (/\s/u.test(character)) {
871
+ if (token !== "") {
872
+ tokens.push(token);
873
+ token = "";
874
+ }
875
+ } else {
876
+ token += character;
877
+ }
878
+ }
879
+ if (token !== "") tokens.push(token);
880
+ return tokens;
881
+ }
882
+ function isGuardianCliEntry(token) {
883
+ const normalized = token.replace(/\\/gu, "/").toLowerCase();
884
+ return normalized.endsWith("/dist/cli.js") && (normalized.includes("/dsh-lark-bot/") || normalized.includes("/dsh-feishu-bot/"));
885
+ }
886
+ function hasOnlyGuardianRunOptions(tokens) {
887
+ for (let index = 0; index < tokens.length; index += 2) {
888
+ if (tokens[index] !== "--dsh-profile" && tokens[index] !== "--bridge-profile") return false;
889
+ if (tokens[index + 1] === void 0 || tokens[index + 1]?.startsWith("--")) return false;
890
+ }
891
+ return true;
892
+ }
893
+ function matchGuardianProcess(cmdline) {
894
+ const tokens = commandTokens(cmdline);
895
+ const cliIndex = tokens.findIndex(isGuardianCliEntry);
896
+ if (cliIndex < 1) return false;
897
+ const executable = tokens[cliIndex - 1]?.replace(/\\/gu, "/").split("/").pop()?.toLowerCase();
898
+ if (executable !== "node" && executable !== "node.exe") return false;
899
+ if (tokens[cliIndex + 1] !== "guardian" || tokens[cliIndex + 2] !== "run") return false;
900
+ return hasOnlyGuardianRunOptions(tokens.slice(cliIndex + 3));
901
+ }
849
902
  function hasProfileFlag(cmdline, dshProfile) {
850
903
  const pattern = new RegExp(
851
904
  `(?:^|\\s)--profile(?:\\s+|=)${escapeRegExp(dshProfile)}(?:\\s|$)`
@@ -865,14 +918,14 @@ function matchProfileProcess(cmdline, dshProfile) {
865
918
  if (/(?:^|\s)plugin(?:\s|$)/.test(cmdline)) return false;
866
919
  return hasProfileFlag(cmdline, dshProfile) && looksLikeDshProcess(cmdline);
867
920
  }
868
- async function listProcesses() {
869
- if (process.platform === "win32") {
870
- return listProcessesWindows();
921
+ async function listProcesses(platform = process.platform, run = captureOutput) {
922
+ if (platform === "win32") {
923
+ return listProcessesWindows(run);
871
924
  }
872
- return listProcessesPosix();
925
+ return listProcessesPosix(run);
873
926
  }
874
- async function listProcessesPosix() {
875
- const { stdout } = await captureOutput("ps", ["-axo", "pid=,args="], 1e4);
927
+ async function listProcessesPosix(run) {
928
+ const { stdout } = await run("ps", ["-axo", "pid=,args="], 1e4);
876
929
  const result = [];
877
930
  for (const line of stdout.split("\n")) {
878
931
  const match = /^\s*(\d+)\s+(.+)$/.exec(line);
@@ -882,33 +935,46 @@ async function listProcessesPosix() {
882
935
  }
883
936
  return result;
884
937
  }
885
- async function listProcessesWindows() {
886
- const { stdout } = await captureOutput(
938
+ async function listProcessesWindows(run) {
939
+ const { stdout } = await run(
887
940
  "powershell.exe",
888
941
  [
889
942
  "-NoProfile",
890
943
  "-NonInteractive",
891
944
  "-Command",
892
- "Get-CimInstance Win32_Process | Select-Object ProcessId, CommandLine | ConvertTo-Csv -NoTypeInformation"
945
+ "Get-CimInstance Win32_Process | Select-Object ProcessId, CommandLine | ConvertTo-Json -Compress"
893
946
  ],
894
947
  1e4
895
948
  );
896
- const result = [];
897
- for (const line of stdout.split("\n").slice(1)) {
898
- const [pid, ...rest] = line.trim().split(",");
899
- const numeric = Number(pid?.replace(/"/g, ""));
900
- if (Number.isInteger(numeric) && rest.length > 0) {
901
- result.push({ pid: numeric, cmdline: rest.join(",").replace(/^"|"$/g, "") });
902
- }
949
+ try {
950
+ const parsed = JSON.parse(stdout);
951
+ const rows = Array.isArray(parsed) ? parsed : [parsed];
952
+ return rows.flatMap((row) => {
953
+ if (typeof row !== "object" || row === null) return [];
954
+ const record = row;
955
+ const pid = Number(record.ProcessId);
956
+ const cmdline = record.CommandLine;
957
+ return Number.isInteger(pid) && pid > 0 && typeof cmdline === "string" ? [{ pid, cmdline }] : [];
958
+ });
959
+ } catch {
960
+ return [];
903
961
  }
904
- return result;
905
962
  }
906
- async function captureOutput(command, args, timeoutMs = 3e4) {
963
+ async function captureOutput(command, args, timeoutMs = 3e4, options = {}) {
907
964
  return new Promise((resolve6) => {
908
- const child = spawn5(command, [...args], {
909
- stdio: ["ignore", "pipe", "pipe"],
910
- windowsHide: true
911
- });
965
+ const previousUmask = options.umask !== void 0 && process.platform !== "win32" ? process.umask(options.umask) : void 0;
966
+ const child = (() => {
967
+ try {
968
+ return spawn5(command, [...args], {
969
+ stdio: ["ignore", "pipe", "pipe"],
970
+ windowsHide: true,
971
+ ...options.cwd ? { cwd: options.cwd } : {},
972
+ ...options.env ? { env: options.env } : {}
973
+ });
974
+ } finally {
975
+ if (previousUmask !== void 0) process.umask(previousUmask);
976
+ }
977
+ })();
912
978
  let stdout = "";
913
979
  let stderr = "";
914
980
  child.stdout?.on("data", (chunk) => {
@@ -934,6 +1000,47 @@ async function findProfileProcess(dshProfile) {
934
1000
  const processes = await listProcesses();
935
1001
  return processes.find((entry) => matchProfileProcess(entry.cmdline, dshProfile));
936
1002
  }
1003
+ async function managedGuardianPid(platform, run, uid) {
1004
+ let result;
1005
+ if (platform === "linux") {
1006
+ result = await run(
1007
+ "systemctl",
1008
+ ["--user", "show", "dsh-lark-guardian.service", "--property=MainPID", "--value"],
1009
+ 1e4
1010
+ );
1011
+ } else if (platform === "darwin") {
1012
+ result = await run(
1013
+ "launchctl",
1014
+ ["print", `gui/${uid}/io.dsh-lark.dsh-lark-guardian`],
1015
+ 1e4
1016
+ );
1017
+ } else {
1018
+ return void 0;
1019
+ }
1020
+ if (result.code !== 0) return void 0;
1021
+ const raw = platform === "darwin" ? /(?:^|\n)\s*pid\s*=\s*(\d+)\s*(?:\n|$)/u.exec(result.stdout)?.[1] : /^(\d+)\s*$/u.exec(result.stdout.trim())?.[1];
1022
+ const pid = Number(raw);
1023
+ return Number.isInteger(pid) && pid > 0 ? pid : void 0;
1024
+ }
1025
+ async function findGuardianProcess(options = {}) {
1026
+ const platform = options.platform ?? process.platform;
1027
+ const run = options.run ?? captureOutput;
1028
+ const isAlive = options.isAlive ?? isProcessAlive;
1029
+ const currentPid = options.currentPid ?? process.pid;
1030
+ const candidates = (await listProcesses(platform, run)).filter(
1031
+ (entry) => entry.pid !== currentPid && matchGuardianProcess(entry.cmdline) && isAlive(entry.pid)
1032
+ );
1033
+ if (candidates.length !== 1) return void 0;
1034
+ const candidate = candidates[0];
1035
+ if (candidate === void 0) return void 0;
1036
+ const servicePid = await managedGuardianPid(
1037
+ platform,
1038
+ run,
1039
+ options.uid ?? process.getuid?.() ?? 0
1040
+ );
1041
+ if (servicePid !== void 0 && servicePid !== candidate.pid) return void 0;
1042
+ return isAlive(candidate.pid) ? candidate : void 0;
1043
+ }
937
1044
  function isProcessAlive(pid) {
938
1045
  try {
939
1046
  process.kill(pid, 0);
@@ -997,9 +1104,9 @@ async function writeFileAtomic(target, data, options = {}) {
997
1104
  }
998
1105
  }
999
1106
  async function rmSilently(path) {
1000
- const { rm: rm12 } = await import("fs/promises");
1107
+ const { rm: rm13 } = await import("fs/promises");
1001
1108
  try {
1002
- await rm12(path, { force: true });
1109
+ await rm13(path, { force: true });
1003
1110
  } catch {
1004
1111
  }
1005
1112
  }
@@ -17059,12 +17166,36 @@ function buildSecretHandler(deps) {
17059
17166
  init_own_package();
17060
17167
 
17061
17168
  // src/guardian/update-handoff.ts
17062
- import { randomUUID as randomUUID13 } from "crypto";
17169
+ import { createHash as createHash3, randomUUID as randomUUID13 } from "crypto";
17063
17170
  import { spawn as spawn7 } from "child_process";
17064
- import { mkdir as mkdir21, readFile as readFile31 } from "fs/promises";
17171
+ import { chmod, mkdir as mkdir21, readFile as readFile31, rm as rm10 } from "fs/promises";
17065
17172
  import { dirname as dirname16, join as join26 } from "path";
17066
17173
  init_own_package();
17067
17174
  init_process();
17175
+ function guardianUpdateFailureHint(code) {
17176
+ switch (code) {
17177
+ case "filesystem-access":
17178
+ return {
17179
+ zh: "\u66F4\u65B0\u5DE5\u4F5C\u76EE\u5F55\u4E0D\u53EF\u8BBF\u95EE\uFF1B\u8BF7\u53D1\u9001 `/doctor` \u68C0\u67E5\u6587\u4EF6\u6743\u9650\u540E\u91CD\u8BD5\u3002",
17180
+ en: "The private update workspace is inaccessible. Send `/doctor` to check file permissions, then retry."
17181
+ };
17182
+ case "registry-unavailable":
17183
+ return {
17184
+ zh: "\u65E0\u6CD5\u8FDE\u63A5 npm \u6B63\u5F0F\u6E90\uFF1B\u8BF7\u68C0\u67E5\u7F51\u7EDC\u540E\u91CD\u8BD5\u3002",
17185
+ en: "The npm registry is unreachable. Check the network, then retry."
17186
+ };
17187
+ case "bootstrap-unavailable":
17188
+ return {
17189
+ zh: "\u65E0\u6CD5\u542F\u52A8 npm/npx\uFF1B\u8BF7\u53D1\u9001 `/doctor` \u68C0\u67E5 Node.js \u4E0E npm\u3002",
17190
+ en: "npm/npx could not start. Send `/doctor` to check Node.js and npm."
17191
+ };
17192
+ default:
17193
+ return {
17194
+ zh: "\u5347\u7EA7\u547D\u4EE4\u672A\u5B8C\u6210\uFF1B\u8BF7\u53D1\u9001 `/doctor` \u68C0\u67E5\u540E\u91CD\u8BD5\u3002",
17195
+ en: "The upgrade command did not complete. Send `/doctor`, then retry."
17196
+ };
17197
+ }
17198
+ }
17068
17199
  async function loadState(file) {
17069
17200
  try {
17070
17201
  const parsed = JSON.parse(await readFile31(file, "utf8"));
@@ -17085,6 +17216,36 @@ function validPackageName(value) {
17085
17216
  function validVersion(value) {
17086
17217
  return /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(value);
17087
17218
  }
17219
+ async function ensurePrivateDirectory(path) {
17220
+ await mkdir21(path, { recursive: true, mode: 448 });
17221
+ if (process.platform !== "win32") await chmod(path, 448);
17222
+ }
17223
+ function classifyWorkerFailure(code, stdout, stderr) {
17224
+ const output = `${stderr}
17225
+ ${stdout}`;
17226
+ if (/\b(?:EACCES|EPERM)\b|permission denied|access is denied/iu.test(output)) {
17227
+ return {
17228
+ errorCode: "filesystem-access",
17229
+ error: "upgrade worker could not access its private working files"
17230
+ };
17231
+ }
17232
+ if (/\b(?:ENOTFOUND|EAI_AGAIN|ECONNREFUSED|ETIMEDOUT)\b|registry unavailable/iu.test(output)) {
17233
+ return {
17234
+ errorCode: "registry-unavailable",
17235
+ error: "upgrade worker could not reach the npm registry"
17236
+ };
17237
+ }
17238
+ if (/\bENOENT\b|not found|not recognized/iu.test(output)) {
17239
+ return {
17240
+ errorCode: "bootstrap-unavailable",
17241
+ error: "upgrade worker could not start the npm bootstrap command"
17242
+ };
17243
+ }
17244
+ return {
17245
+ errorCode: "upgrade-failed",
17246
+ error: `upgrade worker exited with code ${code}`
17247
+ };
17248
+ }
17088
17249
  async function defaultLaunch(request) {
17089
17250
  const cliPath = join26(ownPackageInfo().root, "dist", "cli.js");
17090
17251
  await new Promise((resolve6, reject) => {
@@ -17120,23 +17281,48 @@ async function runGuardianUpdateWorker(request, options = {}) {
17120
17281
  if (delayMs > 0) await new Promise((resolve6) => setTimeout(resolve6, delayMs));
17121
17282
  const spec = `${state.packageName}@${state.targetVersion}`;
17122
17283
  const run = options.run ?? captureOutput;
17123
- const result = await run(
17124
- process.platform === "win32" ? "npx.cmd" : "npx",
17125
- [
17126
- "--yes",
17127
- "--registry",
17128
- defaultRegistryUrl(),
17129
- spec,
17130
- "upgrade",
17131
- "--profile",
17132
- state.dshProfile,
17133
- "--yes",
17134
- "--restart",
17135
- "--package",
17136
- spec
17137
- ],
17138
- 30 * 6e4
17284
+ const workerRoot = join26(dirname16(request.stateFile), "update-worker");
17285
+ const cacheRoot = join26(workerRoot, "npm-cache");
17286
+ const cacheDir = join26(
17287
+ cacheRoot,
17288
+ createHash3("sha256").update(state.id).digest("hex")
17139
17289
  );
17290
+ const cwd = join26(workerRoot, "cwd");
17291
+ let result;
17292
+ try {
17293
+ await ensurePrivateDirectory(workerRoot);
17294
+ await rm10(cacheRoot, { recursive: true, force: true });
17295
+ await rm10(cwd, { recursive: true, force: true });
17296
+ await ensurePrivateDirectory(cacheRoot);
17297
+ await ensurePrivateDirectory(cacheDir);
17298
+ await ensurePrivateDirectory(cwd);
17299
+ result = await run(
17300
+ process.platform === "win32" ? "npx.cmd" : "npx",
17301
+ [
17302
+ "--yes",
17303
+ "--cache",
17304
+ cacheDir,
17305
+ "--registry",
17306
+ defaultRegistryUrl(),
17307
+ spec,
17308
+ "upgrade",
17309
+ "--profile",
17310
+ state.dshProfile,
17311
+ "--yes",
17312
+ "--restart",
17313
+ "--package",
17314
+ spec
17315
+ ],
17316
+ 30 * 6e4,
17317
+ { cwd, umask: 63 }
17318
+ );
17319
+ } catch (error) {
17320
+ result = {
17321
+ code: 1,
17322
+ stdout: "",
17323
+ stderr: error instanceof Error ? `${error.name}: ${error.message}` : "unknown worker failure"
17324
+ };
17325
+ }
17140
17326
  const latest = await loadState(request.stateFile);
17141
17327
  if (!latest || latest.id !== request.id) return;
17142
17328
  if (latest.status === "succeeded") return;
@@ -17145,7 +17331,7 @@ async function runGuardianUpdateWorker(request, options = {}) {
17145
17331
  status: result.code === 0 ? "succeeded" : "failed",
17146
17332
  finishedAt: (options.now ?? (() => /* @__PURE__ */ new Date()))().toISOString(),
17147
17333
  delivered: false,
17148
- ...result.code === 0 ? {} : { error: `upgrade worker exited with code ${result.code}` }
17334
+ ...result.code === 0 ? {} : classifyWorkerFailure(result.code, result.stdout, result.stderr)
17149
17335
  };
17150
17336
  await saveState(request.stateFile, finished);
17151
17337
  }
@@ -17913,12 +18099,13 @@ async function startBridgeEngine(options) {
17913
18099
  const deliverUpdateResult = async () => {
17914
18100
  await updateHandoff.deliverResult(async (state) => {
17915
18101
  if (!streaming) throw new Error("channel is not ready");
18102
+ const failureHint = guardianUpdateFailureHint(state.errorCode);
17916
18103
  const markdown2 = state.status === "succeeded" ? bilingualMarkdown(
17917
18104
  `\u2705 dsh-lark-bot \u5DF2\u66F4\u65B0\u5230 \`${state.targetVersion}\`\uFF0C\u673A\u5668\u4EBA\u5DF2\u5B8C\u6210\u91CD\u8F7D\u3002`,
17918
18105
  `\u2705 dsh-lark-bot was updated to \`${state.targetVersion}\` and reloaded.`
17919
18106
  ) : bilingualMarkdown(
17920
- `\u26A0\uFE0F dsh-lark-bot \u66F4\u65B0\u5230 \`${state.targetVersion}\` \u5931\u8D25\u3002\u8BF7\u91CD\u65B0\u53D1\u9001 \`/upgrade\`\uFF1B\u5982\u4ECD\u5931\u8D25\uFF0C\u53D1\u9001 \`/doctor\` \u68C0\u67E5\u3002`,
17921
- `\u26A0\uFE0F Failed to update dsh-lark-bot to \`${state.targetVersion}\`. Send \`/upgrade\` to retry, or \`/doctor\` if it still fails.`
18107
+ `\u26A0\uFE0F dsh-lark-bot \u66F4\u65B0\u5230 \`${state.targetVersion}\` \u5931\u8D25\u3002${failureHint.zh}`,
18108
+ `\u26A0\uFE0F Failed to update dsh-lark-bot to \`${state.targetVersion}\`. ${failureHint.en}`
17922
18109
  );
17923
18110
  await streaming.sendMarkdown(state.route.chatId, markdown2, {
17924
18111
  ...state.route.threadId ? { threadId: state.route.threadId } : {}
@@ -18310,11 +18497,11 @@ async function restartProfileProcess(profile, options = {}) {
18310
18497
  // src/upgrade/runtime.ts
18311
18498
  init_own_package();
18312
18499
  import { existsSync as existsSync7, readFileSync as readFileSync5 } from "fs";
18313
- import { mkdir as mkdir24, rm as rm10, symlink } from "fs/promises";
18500
+ import { mkdir as mkdir24, rm as rm11, symlink } from "fs/promises";
18314
18501
  import { join as join29 } from "path";
18315
18502
  init_acp_runtime();
18316
18503
  async function defaultRelink(linkPath, target) {
18317
- await rm10(linkPath, { recursive: true, force: true });
18504
+ await rm11(linkPath, { recursive: true, force: true });
18318
18505
  await mkdir24(join29(linkPath, ".."), { recursive: true });
18319
18506
  await symlink(target, linkPath, process.platform === "win32" ? "junction" : "dir");
18320
18507
  }
@@ -20055,7 +20242,7 @@ async function uninstallGuardianCommand(options = {}) {
20055
20242
  const result = await uninstallGuardian({ env });
20056
20243
  printResult(result);
20057
20244
  }
20058
- async function statusGuardianCommand(options = {}) {
20245
+ async function statusGuardianCommand(options = {}, deps = {}) {
20059
20246
  const env = envWithOverrides(options);
20060
20247
  const paths = resolveAppPaths(env.home);
20061
20248
  const fallback = newGuardianState({
@@ -20066,6 +20253,7 @@ async function statusGuardianCommand(options = {}) {
20066
20253
  const layout = guardianLayoutFor(env, state.bridgeProfile);
20067
20254
  const heartbeat = await readHeartbeat(layout.heartbeatFile);
20068
20255
  const processFound = await findProfileProcess(state.dshProfile);
20256
+ const guardianProcess = await (deps.findGuardianProcess ?? findGuardianProcess)();
20069
20257
  const up = isHeartbeatFresh(heartbeat, env.guardianStaleMs) || processFound !== void 0;
20070
20258
  printLines([
20071
20259
  "\u5B89\u5168\u7F51\u5B88\u62A4\u72B6\u6001",
@@ -20077,7 +20265,7 @@ async function statusGuardianCommand(options = {}) {
20077
20265
  `dsh \u662F\u5426\u5728\u7EBF\uFF1A${up ? "\u662F" : "\u5426"}${processFound ? `\uFF08pid ${processFound.pid}\uFF09` : ""}`,
20078
20266
  `\u5FC3\u8DF3\u9F84\uFF1A${heartbeat ? `${heartbeatAgeMs(heartbeat)}ms` : "\u65E0"}`,
20079
20267
  `\u5DF2\u89C2\u5BDF\u8FC7 dsh \u8FD0\u884C\uFF1A${state.profileSeenUp ? "\u662F" : "\u5426"}`,
20080
- "\u5B88\u62A4\u8FDB\u7A0B pid\uFF1A\u672A\u53D1\u73B0\uFF08\u72B6\u6001\u547D\u4EE4\u4E0D\u4F1A\u628A\u81EA\u8EAB PID \u5192\u5145\u4E3A\u5B88\u62A4\u8FDB\u7A0B\uFF09",
20268
+ guardianProcess === void 0 ? "\u5B88\u62A4\u8FDB\u7A0B pid\uFF1A\u672A\u53D1\u73B0\uFF08\u65E0\u6CD5\u552F\u4E00\u8BC1\u660E resident guardian \u8EAB\u4EFD\uFF09" : `\u5B88\u62A4\u8FDB\u7A0B pid\uFF1A${guardianProcess.pid}`,
20081
20269
  `\u72B6\u6001\u6587\u4EF6\uFF1A${layout.stateFile}`,
20082
20270
  `\u5FC3\u8DF3\u6587\u4EF6\uFF1A${layout.heartbeatFile}`
20083
20271
  ]);
@@ -20320,7 +20508,7 @@ async function runServiceRuntime(options = {}, deps = {}) {
20320
20508
  // src/cli/commands/bot.ts
20321
20509
  init_dsh_runtime();
20322
20510
  import { homedir as homedir24 } from "os";
20323
- import { rm as rm11 } from "fs/promises";
20511
+ import { rm as rm12 } from "fs/promises";
20324
20512
  import { join as join34 } from "path";
20325
20513
  async function runBotCommand(action, options = {}, deps = {}) {
20326
20514
  const output = deps.output ?? ((text) => process.stdout.write(text));
@@ -20379,7 +20567,7 @@ ${rows.join("\n")}
20379
20567
  current.dshProfile,
20380
20568
  instanceEnv(sourceEnv, name, current.dshHome)
20381
20569
  ).uninstall();
20382
- await rm11(join34(paths.botDshHome(name), ".credentials.yaml"), { force: true });
20570
+ await rm12(join34(paths.botDshHome(name), ".credentials.yaml"), { force: true });
20383
20571
  await configs.removeProfile(current.bridgeProfile);
20384
20572
  await fleet.remove(name);
20385
20573
  output(
@@ -20416,7 +20604,7 @@ ${rows.join("\n")}
20416
20604
  } catch (error) {
20417
20605
  try {
20418
20606
  await service.uninstall();
20419
- await rm11(join34(dshHome, ".credentials.yaml"), { force: true });
20607
+ await rm12(join34(dshHome, ".credentials.yaml"), { force: true });
20420
20608
  await fleet.remove(name);
20421
20609
  await configs.removeProfile(name);
20422
20610
  } catch (cleanupError) {