weacpx 0.6.0 → 0.6.1

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.
Files changed (48) hide show
  1. package/dist/bridge/bridge-main.js +59 -23
  2. package/dist/channels/types.d.ts +5 -0
  3. package/dist/cli.js +328 -158
  4. package/dist/commands/command-hints.d.ts +11 -0
  5. package/dist/commands/command-list.d.ts +3 -0
  6. package/dist/commands/config-clone.d.ts +2 -0
  7. package/dist/commands/handlers/agent-handler.d.ts +6 -0
  8. package/dist/commands/handlers/config-handler.d.ts +5 -0
  9. package/dist/commands/handlers/later-handler.d.ts +21 -0
  10. package/dist/commands/handlers/orchestration-handler.d.ts +16 -0
  11. package/dist/commands/handlers/permission-handler.d.ts +9 -0
  12. package/dist/commands/handlers/session-handler.d.ts +37 -0
  13. package/dist/commands/handlers/workspace-handler.d.ts +8 -0
  14. package/dist/commands/help/help-registry.d.ts +4 -0
  15. package/dist/commands/help/help-types.d.ts +12 -0
  16. package/dist/commands/parse-command.d.ts +175 -0
  17. package/dist/commands/router-types.d.ts +144 -0
  18. package/dist/commands/workspace-name.d.ts +4 -0
  19. package/dist/commands/workspace-path.d.ts +4 -0
  20. package/dist/config/agent-templates.d.ts +4 -0
  21. package/dist/config/config-store.d.ts +13 -0
  22. package/dist/config/load-config.d.ts +10 -0
  23. package/dist/config/resolve-agent-command.d.ts +2 -0
  24. package/dist/formatting/render-text.d.ts +23 -0
  25. package/dist/orchestration/async-mutex.d.ts +4 -0
  26. package/dist/orchestration/build-coordinator-prompt.d.ts +66 -0
  27. package/dist/orchestration/orchestration-service.d.ts +471 -0
  28. package/dist/orchestration/progress-line-parser.d.ts +19 -0
  29. package/dist/orchestration/render-delegate-group-result.d.ts +6 -0
  30. package/dist/orchestration/render-delegate-question-package.d.ts +21 -0
  31. package/dist/orchestration/render-delegate-result.d.ts +2 -0
  32. package/dist/orchestration/task-watch-timeouts.d.ts +5 -0
  33. package/dist/plugin-api.d.ts +1 -0
  34. package/dist/scheduled/parse-later-time.d.ts +11 -0
  35. package/dist/scheduled/scheduled-render.d.ts +7 -0
  36. package/dist/scheduled/scheduled-service.d.ts +41 -0
  37. package/dist/scheduled/scheduled-types.d.ts +29 -0
  38. package/dist/sessions/session-service.d.ts +83 -0
  39. package/dist/state/state-store.d.ts +8 -0
  40. package/dist/state/types.d.ts +44 -0
  41. package/dist/transport/tool-event-mode.d.ts +14 -0
  42. package/dist/transport/types.d.ts +129 -0
  43. package/dist/util/path.d.ts +4 -0
  44. package/dist/util/sanitize.d.ts +10 -0
  45. package/dist/util/text.d.ts +3 -0
  46. package/dist/version.d.ts +2 -0
  47. package/dist/weixin/auth/accounts.d.ts +0 -1
  48. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -2088,36 +2088,56 @@ var init_private_file = __esm(() => {
2088
2088
  import_write_file_atomic = __toESM(require_lib(), 1);
2089
2089
  });
2090
2090
 
2091
- // src/commands/workspace-path.ts
2092
- import { access } from "node:fs/promises";
2093
- import { homedir } from "node:os";
2091
+ // src/util/path.ts
2094
2092
  import path from "node:path";
2095
- function normalizeWorkspacePath(input) {
2093
+ import { homedir } from "node:os";
2094
+ function normalizePath(input) {
2096
2095
  const expanded = expandHome(input);
2097
2096
  if (isWindowsLikePath(expanded)) {
2098
2097
  return path.win32.normalize(expanded).replace(/\\/g, "/");
2099
2098
  }
2100
2099
  return path.posix.normalize(expanded.replace(/\\/g, "/"));
2101
2100
  }
2102
- function basenameForWorkspacePath(input) {
2103
- const normalized = normalizeWorkspacePath(input);
2101
+ function basenameForPath(input) {
2102
+ const normalized = normalizePath(input);
2104
2103
  if (ROOT_PATH_RE.test(normalized)) {
2105
2104
  return normalized;
2106
2105
  }
2107
2106
  const base = path.posix.basename(normalized);
2108
2107
  return base || normalized;
2109
2108
  }
2110
- function sameWorkspacePath(left, right) {
2111
- const normalizedLeft = normalizeWorkspacePath(left);
2112
- const normalizedRight = normalizeWorkspacePath(right);
2109
+ function isSamePath(left, right) {
2110
+ const normalizedLeft = normalizePath(left);
2111
+ const normalizedRight = normalizePath(right);
2113
2112
  if (isWindowsLikePath(normalizedLeft) || isWindowsLikePath(normalizedRight)) {
2114
2113
  return normalizedLeft.toLowerCase() === normalizedRight.toLowerCase();
2115
2114
  }
2116
2115
  return normalizedLeft === normalizedRight;
2117
2116
  }
2117
+ function isWindowsLikePath(input) {
2118
+ return WINDOWS_DRIVE_PATH_RE.test(input) || WINDOWS_UNC_PATH_RE.test(input);
2119
+ }
2118
2120
  function expandHome(input) {
2119
2121
  return input.startsWith("~") ? homedir() + input.slice(1) : input;
2120
2122
  }
2123
+ var WINDOWS_DRIVE_PATH_RE, WINDOWS_UNC_PATH_RE, ROOT_PATH_RE;
2124
+ var init_path = __esm(() => {
2125
+ WINDOWS_DRIVE_PATH_RE = /^[a-zA-Z]:[\\/]/;
2126
+ WINDOWS_UNC_PATH_RE = /^\\\\/;
2127
+ ROOT_PATH_RE = /^(\/|[a-zA-Z]:\/?)$/;
2128
+ });
2129
+
2130
+ // src/commands/workspace-path.ts
2131
+ import { access } from "node:fs/promises";
2132
+ function normalizeWorkspacePath(input) {
2133
+ return normalizePath(input);
2134
+ }
2135
+ function basenameForWorkspacePath(input) {
2136
+ return basenameForPath(input);
2137
+ }
2138
+ function sameWorkspacePath(left, right) {
2139
+ return isSamePath(left, right);
2140
+ }
2121
2141
  async function pathExists(filePath) {
2122
2142
  try {
2123
2143
  await access(filePath);
@@ -2126,14 +2146,8 @@ async function pathExists(filePath) {
2126
2146
  return false;
2127
2147
  }
2128
2148
  }
2129
- function isWindowsLikePath(input) {
2130
- return WINDOWS_DRIVE_PATH_RE.test(input) || WINDOWS_UNC_PATH_RE.test(input);
2131
- }
2132
- var WINDOWS_DRIVE_PATH_RE, WINDOWS_UNC_PATH_RE, ROOT_PATH_RE;
2133
2149
  var init_workspace_path = __esm(() => {
2134
- WINDOWS_DRIVE_PATH_RE = /^[a-zA-Z]:[\\/]/;
2135
- WINDOWS_UNC_PATH_RE = /^\\\\/;
2136
- ROOT_PATH_RE = /^(\/|[a-zA-Z]:\/?)$/;
2150
+ init_path();
2137
2151
  });
2138
2152
 
2139
2153
  // src/config/resolve-agent-command.ts
@@ -9688,8 +9702,10 @@ function readVersion(moduleUrl = import.meta.url) {
9688
9702
  }
9689
9703
  return "unknown";
9690
9704
  }
9691
- var PACKAGE_NAME = "weacpx";
9692
- var init_version = () => {};
9705
+ var PACKAGE_NAME = "weacpx", WEACPX_CORE_VERSION;
9706
+ var init_version = __esm(() => {
9707
+ WEACPX_CORE_VERSION = readVersion();
9708
+ });
9693
9709
 
9694
9710
  // src/orchestration/task-watch-timeouts.ts
9695
9711
  var DEFAULT_TASK_WATCH_TIMEOUT_MS = 60000, MAX_TASK_WATCH_TIMEOUT_MS, DEFAULT_TASK_WATCH_POLL_INTERVAL_MS = 1000, MAX_TASK_WATCH_POLL_INTERVAL_MS = 1e4, TASK_WATCH_RPC_TIMEOUT_PADDING_MS = 5000;
@@ -9713,10 +9729,60 @@ var init_quota_errors = __esm(() => {
9713
9729
  };
9714
9730
  });
9715
9731
 
9732
+ // src/util/sanitize.ts
9733
+ function sanitizeString(input, options = {}) {
9734
+ const {
9735
+ replacement = "-",
9736
+ collapse = false,
9737
+ trim = false,
9738
+ lowercase: lowercase2 = false,
9739
+ fallback
9740
+ } = options;
9741
+ let result = lowercase2 ? input.toLowerCase() : input;
9742
+ if (options.allow) {
9743
+ const pattern = new RegExp(`[^${options.allow.source.slice(1, -1)}]+`, "g");
9744
+ result = result.replace(pattern, replacement);
9745
+ } else if (options.deny) {
9746
+ result = result.replace(options.deny, replacement);
9747
+ }
9748
+ if (collapse) {
9749
+ const escaped = escapeRegExp(replacement);
9750
+ result = result.replace(new RegExp(`${escaped}+`, "g"), replacement);
9751
+ }
9752
+ if (trim) {
9753
+ const escaped = escapeRegExp(replacement);
9754
+ result = result.replace(new RegExp(`^${escaped}+|${escaped}+$`, "g"), "");
9755
+ }
9756
+ if (fallback !== undefined && result.length === 0) {
9757
+ return fallback;
9758
+ }
9759
+ return result;
9760
+ }
9761
+ function escapeRegExp(s) {
9762
+ return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
9763
+ }
9764
+
9765
+ // src/util/text.ts
9766
+ function truncateText(text, maxLength, ellipsis = "…") {
9767
+ if (text.length <= maxLength)
9768
+ return text;
9769
+ return text.slice(0, maxLength - ellipsis.length) + ellipsis;
9770
+ }
9771
+ function escapeForDoubleQuotes(input) {
9772
+ return input.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
9773
+ }
9774
+ function quoteIfNeeded(input) {
9775
+ return `"${escapeForDoubleQuotes(input)}"`;
9776
+ }
9777
+
9716
9778
  // src/commands/workspace-name.ts
9717
9779
  function sanitizeWorkspaceName(input, fallback = "workspace") {
9718
- const sanitized = input.trim().replace(UNSAFE_RUN_RE, "-").replace(TRIM_DASHES_RE, "");
9719
- return sanitized.length > 0 ? sanitized : fallback;
9780
+ return sanitizeString(input.trim(), {
9781
+ allow: /[a-zA-Z0-9._-]/,
9782
+ replacement: "-",
9783
+ trim: true,
9784
+ fallback
9785
+ });
9720
9786
  }
9721
9787
  function allocateWorkspaceName(base, existing) {
9722
9788
  if (!Object.prototype.hasOwnProperty.call(existing, base))
@@ -9732,13 +9798,11 @@ function isWorkspaceNameValid(input) {
9732
9798
  function quoteWorkspaceNameIfNeeded(input) {
9733
9799
  if (isWorkspaceNameValid(input))
9734
9800
  return input;
9735
- return `"${input.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`;
9801
+ return quoteIfNeeded(input);
9736
9802
  }
9737
- var VALID_WORKSPACE_NAME_RE, UNSAFE_RUN_RE, TRIM_DASHES_RE;
9803
+ var VALID_WORKSPACE_NAME_RE;
9738
9804
  var init_workspace_name = __esm(() => {
9739
9805
  VALID_WORKSPACE_NAME_RE = /^[a-zA-Z0-9._-]+$/;
9740
- UNSAFE_RUN_RE = /[^a-zA-Z0-9._-]+/g;
9741
- TRIM_DASHES_RE = /^-+|-+$/g;
9742
9806
  });
9743
9807
 
9744
9808
  // src/orchestration/orchestration-types.ts
@@ -10288,7 +10352,7 @@ function renderLaterList(tasks, displaySession) {
10288
10352
  `).trimEnd();
10289
10353
  }
10290
10354
  function preview(text) {
10291
- return text.length <= LATER_MESSAGE_PREVIEW_CHARS ? text : `${text.slice(0, LATER_MESSAGE_PREVIEW_CHARS - 1)}…`;
10355
+ return truncateText(text, LATER_MESSAGE_PREVIEW_CHARS);
10292
10356
  }
10293
10357
  function formatLocalDateTime(date4) {
10294
10358
  const weekdays = ["周日", "周一", "周二", "周三", "周四", "周五", "周六"];
@@ -10434,7 +10498,10 @@ class ScheduledTaskService {
10434
10498
  }
10435
10499
  nextId() {
10436
10500
  for (let attempt = 0;attempt < 20; attempt += 1) {
10437
- const id = normalizeId(this.generateId()).replace(/[^0-9a-z]/g, "").slice(0, 6);
10501
+ const id = sanitizeString(normalizeId(this.generateId()), {
10502
+ allow: /[0-9a-z]/,
10503
+ replacement: ""
10504
+ }).slice(0, 6);
10438
10505
  if (id.length >= 4 && !this.state.scheduled_tasks[id])
10439
10506
  return id;
10440
10507
  }
@@ -10448,12 +10515,16 @@ class ScheduledTaskService {
10448
10515
  }
10449
10516
  }
10450
10517
  function normalizeId(input) {
10451
- return input.trim().replace(/^#/, "").toLowerCase();
10518
+ return sanitizeString(input.trim(), {
10519
+ deny: /^#/,
10520
+ replacement: "",
10521
+ lowercase: true
10522
+ });
10452
10523
  }
10453
10524
  var init_scheduled_service = () => {};
10454
10525
 
10455
10526
  // src/plugins/plugin-home.ts
10456
- import { mkdir as mkdir6, writeFile as writeFile4 } from "node:fs/promises";
10527
+ import { mkdir as mkdir6, readFile as readFile6, writeFile as writeFile4 } from "node:fs/promises";
10457
10528
  import { homedir as homedir3 } from "node:os";
10458
10529
  import { join as join3 } from "node:path";
10459
10530
  function coerceMissing(value) {
@@ -10477,6 +10548,27 @@ function resolvePluginHome(input = {}) {
10477
10548
  const home = coerceMissing(input.home) ?? coerceMissing(process.env.HOME) ?? homedir3();
10478
10549
  return join3(home, ".weacpx", "plugins");
10479
10550
  }
10551
+ async function normalizePluginHomeManifest(pluginHome) {
10552
+ const manifestPath = join3(pluginHome, "package.json");
10553
+ let raw;
10554
+ try {
10555
+ raw = await readFile6(manifestPath, "utf8");
10556
+ } catch {
10557
+ return false;
10558
+ }
10559
+ let parsed;
10560
+ try {
10561
+ parsed = JSON.parse(raw);
10562
+ } catch {
10563
+ return false;
10564
+ }
10565
+ const normalized = JSON.stringify(parsed, null, 2) + `
10566
+ `;
10567
+ if (normalized === raw)
10568
+ return false;
10569
+ await writeFile4(manifestPath, normalized, { mode: 384 });
10570
+ return true;
10571
+ }
10480
10572
  async function ensurePluginHome(pluginHome) {
10481
10573
  await mkdir6(pluginHome, { recursive: true, mode: 448 });
10482
10574
  await writeFile4(join3(pluginHome, "package.json"), JSON.stringify({ private: true, type: "module" }, null, 2) + `
@@ -10515,7 +10607,11 @@ var init_state_dir = () => {};
10515
10607
  import fs3 from "node:fs";
10516
10608
  import path4 from "node:path";
10517
10609
  function normalizeAccountId(raw) {
10518
- return raw.trim().toLowerCase().replace(/[@.]/g, "-");
10610
+ return sanitizeString(raw.trim(), {
10611
+ deny: /[@.]/g,
10612
+ replacement: "-",
10613
+ lowercase: true
10614
+ });
10519
10615
  }
10520
10616
  function deriveRawAccountId(normalizedId) {
10521
10617
  if (normalizedId.endsWith("-im-bot")) {
@@ -13024,16 +13120,24 @@ class RuntimeMediaStore {
13024
13120
  }
13025
13121
  function sanitizeMediaFileName(fileName, mimeType) {
13026
13122
  const base = path7.basename(fileName.trim() || "attachment");
13027
- const replaced = base.replace(/[\\/:*?"<>|\s]+/g, "-").replace(/^-+|-+$/g, "");
13028
- const safe = replaced || "attachment";
13123
+ const safe = sanitizeString(base, {
13124
+ deny: /[\\/:*?"<>|\s]+/g,
13125
+ replacement: "-",
13126
+ trim: true,
13127
+ fallback: "attachment"
13128
+ });
13029
13129
  const ext = path7.extname(safe);
13030
13130
  if (ext)
13031
13131
  return safe;
13032
13132
  return `${safe}${extensionFromMime(mimeType)}`;
13033
13133
  }
13034
13134
  function safePathSegment(value) {
13035
- const safe = value.replace(/[^A-Za-z0-9._-]+/g, "_").replace(/^_+|_+$/g, "");
13036
- return safe || "unknown";
13135
+ return sanitizeString(value, {
13136
+ allow: /[A-Za-z0-9._-]/,
13137
+ replacement: "_",
13138
+ trim: true,
13139
+ fallback: "unknown"
13140
+ });
13037
13141
  }
13038
13142
  async function uniqueFileName(dir, baseName) {
13039
13143
  const ext = path7.extname(baseName);
@@ -16021,7 +16125,7 @@ var init_scheduled_turn = __esm(() => {
16021
16125
  });
16022
16126
 
16023
16127
  // src/weixin/monitor/consumer-lock.ts
16024
- import { mkdir as mkdir8, open as open3, readFile as readFile6, rm as rm6 } from "node:fs/promises";
16128
+ import { mkdir as mkdir8, open as open3, readFile as readFile7, rm as rm6 } from "node:fs/promises";
16025
16129
  import { dirname as dirname8, join as join5 } from "node:path";
16026
16130
  import { homedir as homedir4 } from "node:os";
16027
16131
  function createWeixinConsumerLock(options = {}) {
@@ -16103,7 +16207,7 @@ function createWeixinConsumerLock(options = {}) {
16103
16207
  }
16104
16208
  async function loadLockMetadata(path14) {
16105
16209
  try {
16106
- const raw = await readFile6(path14, "utf8");
16210
+ const raw = await readFile7(path14, "utf8");
16107
16211
  const parsed = JSON.parse(raw);
16108
16212
  if (!parsed || typeof parsed.pid !== "number" || !parsed.mode || !parsed.configPath || !parsed.statePath) {
16109
16213
  return null;
@@ -16785,7 +16889,7 @@ var init_app_logger = __esm(() => {
16785
16889
  });
16786
16890
 
16787
16891
  // src/transport/acpx-session-index.ts
16788
- import { readFile as readFile10 } from "node:fs/promises";
16892
+ import { readFile as readFile11 } from "node:fs/promises";
16789
16893
  import { homedir as homedir5 } from "node:os";
16790
16894
  import { resolve as resolve2 } from "node:path";
16791
16895
  async function resolveSessionAgentCommandFromIndex(session) {
@@ -16794,7 +16898,7 @@ async function resolveSessionAgentCommandFromIndex(session) {
16794
16898
  return;
16795
16899
  }
16796
16900
  try {
16797
- const raw = await readFile10(resolve2(home, ".acpx", "sessions", "index.json"), "utf8");
16901
+ const raw = await readFile11(resolve2(home, ".acpx", "sessions", "index.json"), "utf8");
16798
16902
  const parsed = JSON.parse(raw);
16799
16903
  const targetCwd = resolve2(session.cwd);
16800
16904
  const match = parsed.entries?.find((entry) => entry.name === session.transportSession && entry.cwd === targetCwd && typeof entry.agentCommand === "string" && entry.agentCommand.trim().length > 0);
@@ -18295,7 +18399,7 @@ async function buildCoordinatorPrompt(input) {
18295
18399
 
18296
18400
  `) : input.userText ?? "";
18297
18401
  if (input.maxPromptLength && promptText.length > input.maxPromptLength) {
18298
- promptText = promptText.slice(0, input.maxPromptLength - 3) + "...";
18402
+ promptText = truncateText(promptText, input.maxPromptLength, "...");
18299
18403
  }
18300
18404
  return {
18301
18405
  promptText,
@@ -19788,6 +19892,27 @@ function handleHelp(topic) {
19788
19892
  }
19789
19893
  return { text: renderHelpTopic(entry) };
19790
19894
  }
19895
+ function handleInvalidCommand(recognizedCommand) {
19896
+ const topicName = recognizedCommand.replace(/^\//, "");
19897
+ const entry = getHelpTopic(topicName);
19898
+ if (entry) {
19899
+ return { text: `命令格式不正确,请参考下面的用法:
19900
+
19901
+ ${renderHelpTopic(entry)}` };
19902
+ }
19903
+ return {
19904
+ text: [
19905
+ "无法识别的命令格式。",
19906
+ "",
19907
+ "正确的会话创建格式:",
19908
+ "/session new <别名> --agent <Agent名> --ws <工作区名>",
19909
+ "",
19910
+ "例如:",
19911
+ "/session new demo --agent claude --ws weacpx"
19912
+ ].join(`
19913
+ `)
19914
+ };
19915
+ }
19791
19916
  function renderHelpIndex() {
19792
19917
  const topics = listHelpTopics();
19793
19918
  return [
@@ -20925,18 +21050,7 @@ class CommandRouter {
20925
21050
  return await this.executeCommand(chatKey, command.kind, startedAt, async () => {
20926
21051
  switch (command.kind) {
20927
21052
  case "invalid":
20928
- return {
20929
- text: [
20930
- "无法识别的命令格式。",
20931
- "",
20932
- "正确的会话创建格式:",
20933
- "/session new <别名> --agent <Agent名> --ws <工作区名>",
20934
- "",
20935
- "例如:",
20936
- "/session new demo --agent claude --ws weacpx"
20937
- ].join(`
20938
- `)
20939
- };
21053
+ return handleInvalidCommand(command.recognizedCommand);
20940
21054
  case "help":
20941
21055
  return handleHelp(command.topic);
20942
21056
  case "agents":
@@ -24588,7 +24702,11 @@ class OrchestrationService {
24588
24702
  }
24589
24703
  workspaceLabelFromCwd(cwd) {
24590
24704
  const base = basename2(cwd).trim() || "cwd";
24591
- return base.replace(/[^a-zA-Z0-9._-]+/g, "_") || "cwd";
24705
+ return sanitizeString(base, {
24706
+ allow: /[a-zA-Z0-9._-]/,
24707
+ replacement: "_",
24708
+ fallback: "cwd"
24709
+ });
24592
24710
  }
24593
24711
  cwdWorkerSessionPart(cwd) {
24594
24712
  const label = this.workspaceLabelFromCwd(cwd);
@@ -26185,6 +26303,37 @@ class DebouncedStateStore {
26185
26303
  }
26186
26304
  }
26187
26305
 
26306
+ // src/commands/command-hints.ts
26307
+ function listWeacpxCommandHints() {
26308
+ const hints = [{ name: "/help", description: "查看命令帮助。" }];
26309
+ for (const topic of HELP_TOPICS) {
26310
+ const name = PRIMARY_COMMAND_BY_TOPIC[topic.topic];
26311
+ if (!name) {
26312
+ throw new Error(`command-hints: 未登记 help topic 的主命令: ${topic.topic}`);
26313
+ }
26314
+ hints.push({ name, description: topic.summary });
26315
+ }
26316
+ return hints;
26317
+ }
26318
+ var PRIMARY_COMMAND_BY_TOPIC;
26319
+ var init_command_hints = __esm(() => {
26320
+ init_help_registry();
26321
+ PRIMARY_COMMAND_BY_TOPIC = {
26322
+ session: "/session",
26323
+ native: "/ssn",
26324
+ workspace: "/workspace",
26325
+ agent: "/agent",
26326
+ permission: "/permission",
26327
+ config: "/config",
26328
+ orchestration: "/delegate",
26329
+ mode: "/mode",
26330
+ replymode: "/replymode",
26331
+ status: "/status",
26332
+ cancel: "/cancel",
26333
+ later: "/later"
26334
+ };
26335
+ });
26336
+
26188
26337
  // src/run-console.ts
26189
26338
  var exports_run_console = {};
26190
26339
  __export(exports_run_console, {
@@ -26299,7 +26448,9 @@ async function runConsole(paths, deps) {
26299
26448
  abortSignal: shutdownController.signal,
26300
26449
  quota: runtime.quota,
26301
26450
  logger: runtime.logger,
26302
- perfTracer: runtime.perfTracer
26451
+ perfTracer: runtime.perfTracer,
26452
+ commandHints: listWeacpxCommandHints(),
26453
+ coreVersion: WEACPX_CORE_VERSION
26303
26454
  });
26304
26455
  channelStartPromise.catch(() => {});
26305
26456
  let channelStartSettled = false;
@@ -26417,6 +26568,8 @@ async function runCleanupSequence(input) {
26417
26568
  }
26418
26569
  var init_run_console = __esm(() => {
26419
26570
  init_consumer_lock();
26571
+ init_command_hints();
26572
+ init_version();
26420
26573
  });
26421
26574
 
26422
26575
  // src/transport/acpx-bridge/acpx-bridge-protocol.ts
@@ -27473,7 +27626,7 @@ var init_node_pty_helper = () => {};
27473
27626
  // src/transport/acpx-queue-owner-launcher.ts
27474
27627
  import { createHash as createHash3 } from "node:crypto";
27475
27628
  import { spawn as spawn8 } from "node:child_process";
27476
- import { readFile as readFile11, unlink } from "node:fs/promises";
27629
+ import { readFile as readFile12, unlink } from "node:fs/promises";
27477
27630
  import { homedir as homedir8 } from "node:os";
27478
27631
  import { join as join13 } from "node:path";
27479
27632
  function buildWeacpxMcpServerSpec(input) {
@@ -27629,7 +27782,7 @@ async function terminateAcpxQueueOwner(sessionId) {
27629
27782
  const lockPath = queueLockFilePath(sessionId);
27630
27783
  let owner;
27631
27784
  try {
27632
- owner = JSON.parse(await readFile11(lockPath, "utf8"));
27785
+ owner = JSON.parse(await readFile12(lockPath, "utf8"));
27633
27786
  } catch {
27634
27787
  return;
27635
27788
  }
@@ -27657,7 +27810,7 @@ function resolveDefaultWeacpxCommand(env) {
27657
27810
  return "weacpx";
27658
27811
  }
27659
27812
  function quoteCommandPart(value) {
27660
- return `"${value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`;
27813
+ return quoteIfNeeded(value);
27661
27814
  }
27662
27815
  var init_acpx_queue_owner_launcher = __esm(() => {
27663
27816
  init_spawn_command();
@@ -27677,7 +27830,6 @@ function permissionModeToFlag(permissionMode) {
27677
27830
  }
27678
27831
 
27679
27832
  // src/transport/agent-session-list.ts
27680
- import path15 from "node:path";
27681
27833
  function isUnknownFilterCwdOption(output) {
27682
27834
  return /(?:unknown|unrecognized) option/i.test(output) && output.includes("--filter-cwd");
27683
27835
  }
@@ -27724,27 +27876,12 @@ function isAgentSessionListResult(value) {
27724
27876
  function filterAgentSessionListByCwd(result, cwd) {
27725
27877
  return {
27726
27878
  ...result,
27727
- sessions: result.sessions.filter((session) => session.cwd && sameAgentSessionCwd(session.cwd, cwd))
27879
+ sessions: result.sessions.filter((session) => session.cwd && isSamePath(session.cwd, cwd))
27728
27880
  };
27729
27881
  }
27730
- function sameAgentSessionCwd(left, right) {
27731
- const normalizedLeft = normalizeAgentSessionCwd(left);
27732
- const normalizedRight = normalizeAgentSessionCwd(right);
27733
- if (isWindowsLikePath2(normalizedLeft) || isWindowsLikePath2(normalizedRight)) {
27734
- return normalizedLeft.toLowerCase() === normalizedRight.toLowerCase();
27735
- }
27736
- return normalizedLeft === normalizedRight;
27737
- }
27738
- function normalizeAgentSessionCwd(input) {
27739
- if (isWindowsLikePath2(input)) {
27740
- return path15.win32.normalize(input).replace(/\\/g, "/");
27741
- }
27742
- return path15.posix.normalize(input.replace(/\\/g, "/"));
27743
- }
27744
- function isWindowsLikePath2(input) {
27745
- return /^[a-zA-Z]:[\\/]/.test(input) || input.startsWith("\\\\");
27746
- }
27747
- var init_agent_session_list = () => {};
27882
+ var init_agent_session_list = __esm(() => {
27883
+ init_path();
27884
+ });
27748
27885
 
27749
27886
  // src/transport/acpx-cli/acpx-cli-transport.ts
27750
27887
  import { createRequire as createRequire5 } from "node:module";
@@ -28263,6 +28400,30 @@ var init_acpx_cli_transport = __esm(() => {
28263
28400
  require4 = createRequire5(import.meta.url);
28264
28401
  });
28265
28402
 
28403
+ // src/util/async.ts
28404
+ function settleWithinTimeout(work, timeoutMs) {
28405
+ return new Promise((resolve3) => {
28406
+ let settled = false;
28407
+ const finish = () => {
28408
+ if (!settled) {
28409
+ settled = true;
28410
+ resolve3();
28411
+ }
28412
+ };
28413
+ const timer = setTimeout(finish, timeoutMs);
28414
+ if (typeof timer.unref === "function") {
28415
+ timer.unref();
28416
+ }
28417
+ work.then(() => {
28418
+ clearTimeout(timer);
28419
+ finish();
28420
+ }, () => {
28421
+ clearTimeout(timer);
28422
+ finish();
28423
+ });
28424
+ });
28425
+ }
28426
+
28266
28427
  // src/transport/queue-owner-reaper.ts
28267
28428
  import { spawn as spawn10 } from "node:child_process";
28268
28429
  async function reapQueueOwners(acpxCommand, targets, deps = {}) {
@@ -28293,28 +28454,6 @@ async function reapQueueOwners(acpxCommand, targets, deps = {}) {
28293
28454
  await settleWithinTimeout(Promise.all(unique.map(reapOne)), timeoutMs);
28294
28455
  return { terminated, attempted: unique.length };
28295
28456
  }
28296
- function settleWithinTimeout(work, timeoutMs) {
28297
- return new Promise((resolve3) => {
28298
- let settled = false;
28299
- const finish = () => {
28300
- if (!settled) {
28301
- settled = true;
28302
- resolve3();
28303
- }
28304
- };
28305
- const timer = setTimeout(finish, timeoutMs);
28306
- if (typeof timer.unref === "function") {
28307
- timer.unref();
28308
- }
28309
- work.then(() => {
28310
- clearTimeout(timer);
28311
- finish();
28312
- }, () => {
28313
- clearTimeout(timer);
28314
- finish();
28315
- });
28316
- });
28317
- }
28318
28457
  async function defaultResolveRecordId(acpxCommand, target) {
28319
28458
  const args = [
28320
28459
  "--format",
@@ -29651,107 +29790,107 @@ async function checkRuntime(options = {}) {
29651
29790
  }
29652
29791
  function createRuntimeFsProbe() {
29653
29792
  return {
29654
- stat: async (path16) => await stat3(path16),
29655
- access: async (path16, mode) => await access4(path16, mode)
29793
+ stat: async (path15) => await stat3(path15),
29794
+ access: async (path15, mode) => await access4(path15, mode)
29656
29795
  };
29657
29796
  }
29658
- async function checkDirectoryCreatable(label, path16, probe, platform) {
29797
+ async function checkDirectoryCreatable(label, path15, probe, platform) {
29659
29798
  try {
29660
- const stats = await probe.stat(path16);
29799
+ const stats = await probe.stat(path15);
29661
29800
  if (!stats.isDirectory()) {
29662
29801
  return {
29663
29802
  ok: false,
29664
- detail: `${label}: ${path16} (exists but is not a directory)`
29803
+ detail: `${label}: ${path15} (exists but is not a directory)`
29665
29804
  };
29666
29805
  }
29667
- await probe.access(path16, directoryAccessMode(platform));
29806
+ await probe.access(path15, directoryAccessMode(platform));
29668
29807
  return {
29669
29808
  ok: true,
29670
- detail: `${label}: ${path16} (writable)`
29809
+ detail: `${label}: ${path15} (writable)`
29671
29810
  };
29672
29811
  } catch (error2) {
29673
29812
  if (!isMissingPathError(error2)) {
29674
29813
  return {
29675
29814
  ok: false,
29676
- detail: `${label}: ${path16} (unusable: ${formatError6(error2)})`
29815
+ detail: `${label}: ${path15} (unusable: ${formatError6(error2)})`
29677
29816
  };
29678
29817
  }
29679
- const parentCheck = await checkCreatableAncestorDirectory(path16, probe, platform);
29818
+ const parentCheck = await checkCreatableAncestorDirectory(path15, probe, platform);
29680
29819
  if (!parentCheck.ok) {
29681
29820
  return {
29682
29821
  ok: false,
29683
- detail: `${label}: ${path16} (parent not writable: ${parentCheck.blockingPath})`
29822
+ detail: `${label}: ${path15} (parent not writable: ${parentCheck.blockingPath})`
29684
29823
  };
29685
29824
  }
29686
29825
  return {
29687
29826
  ok: true,
29688
- detail: `${label}: ${path16} (creatable via ${parentCheck.creatableFrom})`
29827
+ detail: `${label}: ${path15} (creatable via ${parentCheck.creatableFrom})`
29689
29828
  };
29690
29829
  }
29691
29830
  }
29692
- async function checkFileCreatable(label, path16, probe, platform) {
29831
+ async function checkFileCreatable(label, path15, probe, platform) {
29693
29832
  try {
29694
- const stats = await probe.stat(path16);
29833
+ const stats = await probe.stat(path15);
29695
29834
  if (stats.isDirectory()) {
29696
29835
  return {
29697
29836
  ok: false,
29698
- detail: `${label}: ${path16} (exists but is a directory)`
29837
+ detail: `${label}: ${path15} (exists but is a directory)`
29699
29838
  };
29700
29839
  }
29701
- await probe.access(path16, constants.W_OK);
29840
+ await probe.access(path15, constants.W_OK);
29702
29841
  return {
29703
29842
  ok: true,
29704
- detail: `${label}: ${path16} (writable)`
29843
+ detail: `${label}: ${path15} (writable)`
29705
29844
  };
29706
29845
  } catch (error2) {
29707
29846
  if (!isMissingPathError(error2)) {
29708
29847
  return {
29709
29848
  ok: false,
29710
- detail: `${label}: ${path16} (unusable: ${formatError6(error2)})`
29849
+ detail: `${label}: ${path15} (unusable: ${formatError6(error2)})`
29711
29850
  };
29712
29851
  }
29713
- const parentCheck = await checkCreatableAncestorDirectory(dirname14(path16), probe, platform);
29852
+ const parentCheck = await checkCreatableAncestorDirectory(dirname14(path15), probe, platform);
29714
29853
  if (!parentCheck.ok) {
29715
29854
  return {
29716
29855
  ok: false,
29717
- detail: `${label}: ${path16} (parent not writable: ${parentCheck.blockingPath})`
29856
+ detail: `${label}: ${path15} (parent not writable: ${parentCheck.blockingPath})`
29718
29857
  };
29719
29858
  }
29720
29859
  return {
29721
29860
  ok: true,
29722
- detail: `${label}: ${path16} (creatable via ${parentCheck.creatableFrom})`
29861
+ detail: `${label}: ${path15} (creatable via ${parentCheck.creatableFrom})`
29723
29862
  };
29724
29863
  }
29725
29864
  }
29726
- async function checkCreatableAncestorDirectory(path16, probe, platform) {
29865
+ async function checkCreatableAncestorDirectory(path15, probe, platform) {
29727
29866
  try {
29728
- const stats = await probe.stat(path16);
29867
+ const stats = await probe.stat(path15);
29729
29868
  if (!stats.isDirectory()) {
29730
29869
  return {
29731
29870
  ok: false,
29732
- creatableFrom: path16,
29733
- blockingPath: path16
29871
+ creatableFrom: path15,
29872
+ blockingPath: path15
29734
29873
  };
29735
29874
  }
29736
- await probe.access(path16, directoryAccessMode(platform));
29875
+ await probe.access(path15, directoryAccessMode(platform));
29737
29876
  return {
29738
29877
  ok: true,
29739
- creatableFrom: path16
29878
+ creatableFrom: path15
29740
29879
  };
29741
29880
  } catch (error2) {
29742
29881
  if (!isMissingPathError(error2)) {
29743
29882
  return {
29744
29883
  ok: false,
29745
- creatableFrom: path16,
29746
- blockingPath: path16
29884
+ creatableFrom: path15,
29885
+ blockingPath: path15
29747
29886
  };
29748
29887
  }
29749
- const parent = dirname14(path16);
29750
- if (parent === path16) {
29888
+ const parent = dirname14(path15);
29889
+ if (parent === path15) {
29751
29890
  return {
29752
29891
  ok: false,
29753
- creatableFrom: path16,
29754
- blockingPath: path16
29892
+ creatableFrom: path15,
29893
+ blockingPath: path15
29755
29894
  };
29756
29895
  }
29757
29896
  const parentCheck = await checkCreatableAncestorDirectory(parent, probe, platform);
@@ -42853,16 +42992,15 @@ function buildWeacpxMcpToolRegistry(input) {
42853
42992
  },
42854
42993
  {
42855
42994
  name: "task_get",
42856
- description: "Fetch a single task under the current coordinator, including the worker's final result and any pending question. Use to inspect a task snapshot non-blockingly, read the actual output after completion, or inspect a task that requires attention.",
42995
+ description: "Fetch a single task under the current coordinator: its summary, latest progress, and — once terminal — the worker's final result. Prefer task_watch to follow a task; its terminal result already carries the output, so a follow-up task_get is unnecessary. Reach for task_get to recover a task you lost track of, to inspect one that requires attention, or to re-read the original delegated prompt. The full prompt is included only for needs_confirmation tasks unless you pass includePrompt:true.",
42857
42996
  inputSchema: exports_external.object({
42858
- taskId: exports_external.string().min(1)
42997
+ taskId: exports_external.string().min(1),
42998
+ includePrompt: exports_external.boolean().optional()
42859
42999
  }).strict(),
42860
43000
  handler: async (args) => await asToolResult(async () => {
42861
- const task = await transport.getTask({
42862
- coordinatorSession,
42863
- taskId: args.taskId
42864
- });
42865
- return createSuccessResult(task ? renderTaskSummary(task) : "Task not found.", { task });
43001
+ const { taskId, includePrompt } = args;
43002
+ const task = await transport.getTask({ coordinatorSession, taskId });
43003
+ return createSuccessResult(task ? renderTaskSummary(task, { includePrompt: includePrompt ?? false }) : "Task not found.", { task });
42866
43004
  })
42867
43005
  },
42868
43006
  {
@@ -43101,12 +43239,23 @@ function renderTaskWatchResult(result) {
43101
43239
  const events = result.events.length > 0 ? [
43102
43240
  "- Events:",
43103
43241
  ...result.events.map((event) => {
43104
- const detail = event.summary ?? event.message ?? event.status ?? "";
43105
- return ` - #${event.seq} ${event.type} at ${event.at}${detail ? `: ${detail}` : ""}`;
43242
+ const detail2 = event.summary ?? event.message ?? event.status ?? "";
43243
+ return ` - #${event.seq} ${event.type} at ${event.at}${detail2 ? `: ${detail2}` : ""}`;
43106
43244
  })
43107
43245
  ] : ["- Events: none"];
43108
- const next = result.status === "terminal" ? "Next: call task_get to read the final result." : result.status === "attention_required" ? "Next: call task_get to inspect openQuestion / reviewPending, then resolve it with the recommended action tool." : `Next: call task_watch again with afterSeq=${result.nextAfterSeq} to keep watching, preferably as an MCP task if your client supports background task execution.`;
43109
- return [...header, ...events, next].join(`
43246
+ const detail = [];
43247
+ if (result.status === "terminal") {
43248
+ const resultText = result.task.resultText?.trim() ?? "";
43249
+ const summary = result.task.summary?.trim() ?? "";
43250
+ if (resultText.length > 0)
43251
+ detail.push(`- Result: ${resultText}`);
43252
+ else if (summary.length > 0)
43253
+ detail.push(`- Summary: ${summary}`);
43254
+ } else if (result.status === "attention_required" && result.task.openQuestion) {
43255
+ detail.push(`- Open question: ${result.task.openQuestion.question}`);
43256
+ }
43257
+ const next = result.status === "terminal" ? "Next: summarize this result for the user." : result.status === "attention_required" ? "Next: resolve the pending question / contested review with the recommended action tool (coordinator_answer_question or coordinator_review_contested_result); call task_get only if you need more detail." : `Next: call task_watch again with afterSeq=${result.nextAfterSeq} to keep watching, preferably as an MCP task if your client supports background task execution.`;
43258
+ return [...header, ...events, ...detail, next].join(`
43110
43259
  `);
43111
43260
  }
43112
43261
  function createSuccessResult(text, structuredContent) {
@@ -43122,7 +43271,7 @@ function createErrorResult(message) {
43122
43271
  };
43123
43272
  }
43124
43273
  function renderDelegateSuccess(result) {
43125
- const next = result.status === "needs_confirmation" ? `Next: this delegation requires user approval. Tell the user, then call task_approve or task_cancel based on their response.` : result.status === "queued" ? `Next: task "${result.taskId}" is queued (agent at parallel capacity). It will start automatically when a slot frees. Call task_watch to long-poll for the transition to running, or task_get/task_list for non-blocking snapshots.` : `Next: task "${result.taskId}" is running. Return this taskId to the user, call task_get/task_list for non-blocking progress snapshots, or task_watch to long-poll for the next event or terminal state.`;
43274
+ const next = result.status === "needs_confirmation" ? `Next: this delegation requires user approval. Tell the user, then call task_approve or task_cancel based on their response.` : result.status === "queued" ? `Next: task "${result.taskId}" is queued (agent at parallel capacity). It will start automatically when a slot frees. Call task_watch to long-poll until it runs and then finishes — the terminal watch carries the result. Use task_list only to resurvey in-flight tasks.` : `Next: task "${result.taskId}" is running. Return this taskId to the user, then call task_watch to long-poll until it finishes the terminal watch carries the worker's result, so no follow-up task_get is needed. Use task_list only to resurvey in-flight tasks.`;
43126
43275
  return [`Delegation task "${result.taskId}" created.`, `- Status: ${result.status}`, next].join(`
43127
43276
  `);
43128
43277
  }
@@ -43166,7 +43315,7 @@ function renderTaskListItem(task) {
43166
43315
  ].filter(Boolean).map((item) => `; ${item}`).join("");
43167
43316
  return `- ${task.taskId} [${task.status}] ${task.targetAgent}${role} -> ${task.workerSession ?? "unassigned"}${group}${source}${summary}${reliability}`;
43168
43317
  }
43169
- function renderTaskSummary(task) {
43318
+ function renderTaskSummary(task, options = {}) {
43170
43319
  const header = [
43171
43320
  `Task "${task.taskId}"`,
43172
43321
  `- Status: ${task.status}`,
@@ -43181,7 +43330,9 @@ function renderTaskSummary(task) {
43181
43330
  if (task.status === "needs_confirmation") {
43182
43331
  header.push(`- Source: ${task.sourceKind} / ${task.sourceHandle}${task.role ? ` / ${task.role}` : ""}`);
43183
43332
  }
43184
- header.push(`- Task: ${task.task}`);
43333
+ if (task.status === "needs_confirmation" || options.includePrompt) {
43334
+ header.push(`- Task: ${task.task}`);
43335
+ }
43185
43336
  if (task.summary.trim().length > 0)
43186
43337
  header.push(`- Summary: ${task.summary}`);
43187
43338
  if (task.lastProgressSummary)
@@ -43232,7 +43383,7 @@ function renderTaskApprovalSuccess(task) {
43232
43383
  return [
43233
43384
  `Task "${task.taskId}" approved.`,
43234
43385
  `- Current status: ${task.status}`,
43235
- `Next: use task_get/task_list for non-blocking progress snapshots, or task_watch to long-poll until the worker finishes; then task_get to read the final result.`
43386
+ `Next: call task_watch to long-poll until the worker finishes the terminal watch returns the result directly, so no follow-up task_get is needed. Use task_list only to resurvey in-flight tasks.`
43236
43387
  ].join(`
43237
43388
  `);
43238
43389
  }
@@ -43730,13 +43881,24 @@ function renderWatchMcpTaskResult(result, watchTaskId) {
43730
43881
  const events = result.events.length > 0 ? [
43731
43882
  "Events:",
43732
43883
  ...result.events.map((event) => {
43733
- const detail = event.summary ?? event.message ?? event.status ?? "";
43734
- return `- #${event.seq} ${event.type} at ${event.at}${detail ? `: ${detail}` : ""}`;
43884
+ const detail2 = event.summary ?? event.message ?? event.status ?? "";
43885
+ return `- #${event.seq} ${event.type} at ${event.at}${detail2 ? `: ${detail2}` : ""}`;
43735
43886
  })
43736
43887
  ] : ["Events: none"];
43737
- const next = result.status === "terminal" ? "Next: call task_get on the watched task to read the final result." : result.status === "attention_required" ? "Next: call task_get on the watched task, then resolve openQuestion / reviewPending with the recommended action tool." : `Next: call task_watch again with afterSeq=${result.nextAfterSeq} to keep watching.`;
43888
+ const detail = [];
43889
+ if (result.status === "terminal") {
43890
+ const resultText = result.task.resultText.trim();
43891
+ const summary = result.task.summary.trim();
43892
+ if (resultText.length > 0)
43893
+ detail.push(`Result: ${resultText}`);
43894
+ else if (summary.length > 0)
43895
+ detail.push(`Summary: ${summary}`);
43896
+ } else if (result.status === "attention_required" && result.task.openQuestion) {
43897
+ detail.push(`Open question: ${result.task.openQuestion.question}`);
43898
+ }
43899
+ const next = result.status === "terminal" ? "Next: summarize this result for the user." : result.status === "attention_required" ? "Next: resolve the pending question / contested review with the recommended action tool (coordinator_answer_question or coordinator_review_contested_result)." : `Next: call task_watch again with afterSeq=${result.nextAfterSeq} to keep watching.`;
43738
43900
  return {
43739
- content: [{ type: "text", text: [...header, ...events, next].join(`
43901
+ content: [{ type: "text", text: [...header, ...events, ...detail, next].join(`
43740
43902
  `) }],
43741
43903
  structuredContent: { watchTaskId, ...result }
43742
43904
  };
@@ -44096,8 +44258,14 @@ function inferExternalCoordinatorSession(input) {
44096
44258
  return `external_${sanitizeMcpClientName(input.clientName)}:${suffix}`;
44097
44259
  }
44098
44260
  function sanitizeMcpClientName(input) {
44099
- const normalized = (input ?? "").trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
44100
- return normalized.length > 0 ? normalized : "mcp-host";
44261
+ return sanitizeString((input ?? "").trim(), {
44262
+ allow: /[a-z0-9._-]/,
44263
+ replacement: "-",
44264
+ lowercase: true,
44265
+ collapse: true,
44266
+ trim: true,
44267
+ fallback: "mcp-host"
44268
+ });
44101
44269
  }
44102
44270
 
44103
44271
  // src/mcp/parse-string-flag.ts
@@ -44222,11 +44390,12 @@ function resolveTemplateChoice(answer, names) {
44222
44390
  // src/cli-update.ts
44223
44391
  init_plugin_home();
44224
44392
  import { spawn as spawn4 } from "node:child_process";
44225
- import { readFile as readFile7 } from "node:fs/promises";
44393
+ import { readFile as readFile8 } from "node:fs/promises";
44226
44394
  import { dirname as dirname9, join as join7 } from "node:path";
44227
44395
  import { fileURLToPath as fileURLToPath2 } from "node:url";
44228
44396
 
44229
44397
  // src/plugins/package-manager.ts
44398
+ init_plugin_home();
44230
44399
  import { spawn as spawn3 } from "node:child_process";
44231
44400
  async function defaultRunCommand(command, args, options) {
44232
44401
  await new Promise((resolve, reject) => {
@@ -44267,6 +44436,7 @@ async function detectPackageManager(runCommand) {
44267
44436
  async function installPluginPackage(input) {
44268
44437
  const runCommand = input.runCommand ?? defaultRunCommand;
44269
44438
  const packageManager = input.packageManager ?? await detectPackageManager();
44439
+ await normalizePluginHomeManifest(input.pluginHome);
44270
44440
  const spec = input.version ? `${input.packageName}@${input.version}` : input.packageName;
44271
44441
  if (packageManager === "bun") {
44272
44442
  await runCommand("bun", ["add", spec], { cwd: input.pluginHome });
@@ -44504,7 +44674,7 @@ async function readPackageName() {
44504
44674
  const here = dirname9(fileURLToPath2(import.meta.url));
44505
44675
  for (const candidate of [join7(here, "..", "package.json"), join7(here, "..", "..", "package.json")]) {
44506
44676
  try {
44507
- const parsed = JSON.parse(await readFile7(candidate, "utf8"));
44677
+ const parsed = JSON.parse(await readFile8(candidate, "utf8"));
44508
44678
  if (typeof parsed.name === "string" && parsed.name.trim())
44509
44679
  return parsed.name.trim();
44510
44680
  } catch {}
@@ -45127,7 +45297,7 @@ async function setChannelAccountEnabled(type, accountId, enabled, rawArgs, deps)
45127
45297
 
45128
45298
  // src/plugins/plugin-cli.ts
45129
45299
  init_plugin_home();
45130
- import { readFile as readFile9 } from "node:fs/promises";
45300
+ import { readFile as readFile10 } from "node:fs/promises";
45131
45301
  import { isAbsolute, join as join9, resolve } from "node:path";
45132
45302
  init_plugin_loader();
45133
45303
  init_validate_plugin();
@@ -45137,14 +45307,14 @@ init_channel_scope();
45137
45307
  init_plugin_loader();
45138
45308
  init_validate_plugin();
45139
45309
  init_known_plugins();
45140
- import { readFile as readFile8 } from "node:fs/promises";
45310
+ import { readFile as readFile9 } from "node:fs/promises";
45141
45311
  import { join as join8 } from "node:path";
45142
45312
  function suggestedPluginPackageForChannel(type) {
45143
45313
  return findKnownPluginByChannel(type)?.packageName ?? `<npm-package-that-provides-${type}>`;
45144
45314
  }
45145
45315
  async function readDependencyEntries(pluginHome) {
45146
45316
  try {
45147
- const raw = await readFile8(join8(pluginHome, "package.json"), "utf8");
45317
+ const raw = await readFile9(join8(pluginHome, "package.json"), "utf8");
45148
45318
  const parsed = JSON.parse(raw);
45149
45319
  const out = {};
45150
45320
  for (const [name, value] of Object.entries(parsed.dependencies ?? {})) {
@@ -45242,11 +45412,11 @@ async function inspectPlugins(input) {
45242
45412
  // src/plugins/plugin-cli.ts
45243
45413
  init_known_plugins();
45244
45414
  function looksLikePath(spec) {
45245
- return spec.startsWith("./") || spec.startsWith("../") || spec.startsWith("/") || isAbsolute(spec) || spec === ".";
45415
+ return spec === "." || spec.startsWith("./") || spec.startsWith("../") || spec.startsWith("/") || spec.startsWith(".\\") || spec.startsWith("..\\") || spec.startsWith("\\") || /^[a-zA-Z]:[\\/]/.test(spec) || isAbsolute(spec);
45246
45416
  }
45247
45417
  async function readDependencyEntries2(pluginHome) {
45248
45418
  try {
45249
- const raw = await readFile9(join9(pluginHome, "package.json"), "utf8");
45419
+ const raw = await readFile10(join9(pluginHome, "package.json"), "utf8");
45250
45420
  const parsed = JSON.parse(raw);
45251
45421
  const out = {};
45252
45422
  for (const [name, value] of Object.entries(parsed.dependencies ?? {})) {
@@ -45272,7 +45442,7 @@ async function resolveLocalPluginName(installSpec, pluginHome, namesBeforeInstal
45272
45442
  return name;
45273
45443
  }
45274
45444
  try {
45275
- const raw = await readFile9(join9(installSpec, "package.json"), "utf8");
45445
+ const raw = await readFile10(join9(installSpec, "package.json"), "utf8");
45276
45446
  const parsed = JSON.parse(raw);
45277
45447
  if (typeof parsed.name === "string" && parsed.name.trim())
45278
45448
  return parsed.name.trim();