@ganglion/xacpx 0.9.1 → 0.9.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/dist/cli.js CHANGED
@@ -113,10 +113,11 @@ var init_session = __esm(() => {
113
113
  replyModeHeader: "Current reply mode:",
114
114
  replyModeSessionLabel: (alias) => `- Session: ${alias}`,
115
115
  replyModeGlobalDefault: (value) => `- Global default: ${value}`,
116
+ replyModeChannelDefault: (value) => `- Channel default: ${value}`,
116
117
  replyModeSessionOverride: (value) => `- Session override: ${value}`,
117
118
  replyModeEffective: (value) => `- Effective: ${value}`,
118
119
  replyModeSet: (replyMode) => `Current session reply mode set to: ${replyMode}`,
119
- replyModeReset: (globalDefault) => `Session reply mode reset. Falling back to global default: ${globalDefault}`,
120
+ replyModeReset: (effective) => `Session reply mode reset. Now effective: ${effective}`,
120
121
  statusHeader: "Current session:",
121
122
  statusNameLabel: (alias) => `- Name: ${alias}`,
122
123
  statusAgentLabel: (agent) => `- Agent: ${agent}`,
@@ -659,6 +660,8 @@ var init_config = __esm(() => {
659
660
  mustBePositiveNumber: (path) => `${path} must be a positive number.`,
660
661
  channelTypeDisabled: "channel.type is a legacy single-channel field; /config set writes are disabled. Use `xacpx channel ...` to manage channels[], then restart xacpx.",
661
662
  channelReplyModeInvalid: "channel.replyMode only supports: stream, final, verbose",
663
+ channelRuntimeNotFound: (id) => `Channel "${id}" does not exist; add it first with \`xacpx channel add ${id}\`.`,
664
+ channelRuntimeReplyModeInvalid: (id) => `channels.${id}.replyMode only supports: stream, final, verbose`,
662
665
  wechatReplyModeInvalid: "wechat.replyMode only supports: stream, final, verbose",
663
666
  wechatReplyModeMapped: (value) => `${value} (mapped to channel.replyMode)`,
664
667
  agentNotFound: (name) => `Agent "${name}" does not exist. Create it first.`,
@@ -848,7 +851,6 @@ var init_cli_update = __esm(() => {
848
851
  updateFailed: (name, error) => `${name} update failed: ${error}`,
849
852
  targetNotFound: (name) => `Update target not found: ${name}`,
850
853
  targetVersionUnknown: (name) => `${name}: cannot check latest version; skipped.`,
851
- targetNotPinned: (name) => `${name} has no recorded version; use \`xacpx plugin update ${name}\` or specify a version explicitly.`,
852
854
  multiTargetNonInteractive: "Installed plugins detected; in non-interactive mode use `xacpx update --all` or `xacpx update <name>`.",
853
855
  selectionPrompt: "Select items to update (numbers, comma-separated; a=all; Enter to cancel): ",
854
856
  selectionInvalid: (part) => `Invalid selection: ${part}`,
@@ -879,6 +881,8 @@ var init_channel_cli = __esm(() => {
879
881
  channelRemoved: (id) => `Channel ${id} removed`,
880
882
  cannotDisableLastEnabled: "Cannot disable the last enabled channel.",
881
883
  channelEnabledToggled: (id, enabled) => `Channel ${id} ${enabled ? "enabled" : "disabled"}`,
884
+ channelReplyModeSet: (id, mode) => `Channel ${id} default reply mode set to: ${mode}`,
885
+ channelReplyModeInvalid: (mode) => `reply mode must be stream / final / verbose, got: ${mode}`,
882
886
  channelAccountAlreadyExists: (type, accountId) => `Account ${accountId} already exists on channel ${type}; run xacpx channel rm ${type} --account ${accountId} first`,
883
887
  channelAccountAdded: (type, accountId) => `Channel ${type} account ${accountId} added`,
884
888
  channelReEnabled: (type) => `Channel ${type} was disabled; it has been automatically re-enabled.`,
@@ -1179,10 +1183,11 @@ var init_session2 = __esm(() => {
1179
1183
  replyModeHeader: "当前 reply mode:",
1180
1184
  replyModeSessionLabel: (alias) => `- 会话:${alias}`,
1181
1185
  replyModeGlobalDefault: (value) => `- 全局默认:${value}`,
1186
+ replyModeChannelDefault: (value) => `- 频道默认:${value}`,
1182
1187
  replyModeSessionOverride: (value) => `- 当前会话覆盖:${value}`,
1183
1188
  replyModeEffective: (value) => `- 当前生效:${value}`,
1184
1189
  replyModeSet: (replyMode) => `已设置当前会话 reply mode:${replyMode}`,
1185
- replyModeReset: (globalDefault) => `已重置当前会话 reply mode,当前回退到全局默认:${globalDefault}`,
1190
+ replyModeReset: (effective) => `已重置当前会话 reply mode,当前生效:${effective}`,
1186
1191
  statusHeader: "当前会话:",
1187
1192
  statusNameLabel: (alias) => `- 名称:${alias}`,
1188
1193
  statusAgentLabel: (agent2) => `- Agent:${agent2}`,
@@ -1725,6 +1730,8 @@ var init_config2 = __esm(() => {
1725
1730
  mustBePositiveNumber: (path) => `${path} 必须是正数。`,
1726
1731
  channelTypeDisabled: "channel.type 是旧单频道字段,/config set 已禁用写入;请使用 `xacpx channel ...` 管理 channels[],然后重启 xacpx。",
1727
1732
  channelReplyModeInvalid: "channel.replyMode 只支持:stream、final、verbose",
1733
+ channelRuntimeNotFound: (id) => `频道「${id}」不存在;请先用 \`xacpx channel add ${id}\` 添加。`,
1734
+ channelRuntimeReplyModeInvalid: (id) => `channels.${id}.replyMode 只支持:stream、final、verbose`,
1728
1735
  wechatReplyModeInvalid: "wechat.replyMode 只支持:stream、final、verbose",
1729
1736
  wechatReplyModeMapped: (value) => `${value}(已映射到 channel.replyMode)`,
1730
1737
  agentNotFound: (name) => `Agent「${name}」不存在,请先创建。`,
@@ -1914,7 +1921,6 @@ var init_cli_update2 = __esm(() => {
1914
1921
  updateFailed: (name, error) => `${name} 更新失败:${error}`,
1915
1922
  targetNotFound: (name) => `没有找到更新项:${name}`,
1916
1923
  targetVersionUnknown: (name) => `${name} 无法检查最新版本,已跳过。`,
1917
- targetNotPinned: (name) => `${name} 未记录当前版本;请先使用 \`xacpx plugin update ${name}\` 或显式选择版本。`,
1918
1924
  multiTargetNonInteractive: "检测到已安装插件;非交互模式请使用 `xacpx update --all` 或 `xacpx update <name>`。",
1919
1925
  selectionPrompt: "请选择要更新的项目(数字,逗号分隔,a=全部,回车取消):",
1920
1926
  selectionInvalid: (part) => `无效选择:${part}`,
@@ -1945,6 +1951,8 @@ var init_channel_cli2 = __esm(() => {
1945
1951
  channelRemoved: (id) => `频道 ${id} 已删除`,
1946
1952
  cannotDisableLastEnabled: "不能禁用最后一个启用的频道。",
1947
1953
  channelEnabledToggled: (id, enabled) => `频道 ${id} 已${enabled ? "启用" : "禁用"}`,
1954
+ channelReplyModeSet: (id, mode) => `频道 ${id} 的默认 reply mode 已设置为:${mode}`,
1955
+ channelReplyModeInvalid: (mode) => `reply mode 只支持 stream / final / verbose,收到:${mode}`,
1948
1956
  channelAccountAlreadyExists: (type, accountId) => `频道 ${type} 的账号 ${accountId} 已存在;先 xacpx channel rm ${type} --account ${accountId}`,
1949
1957
  channelAccountAdded: (type, accountId) => `频道 ${type} 账号 ${accountId} 已添加`,
1950
1958
  channelReEnabled: (type) => `频道 ${type} 此前是 disabled 状态,已自动启用。`,
@@ -4647,6 +4655,9 @@ function parseRuntimeChannelConfig(raw, index) {
4647
4655
  throw new Error(`channels[${index}].type must be a non-empty string`);
4648
4656
  }
4649
4657
  const enabled = raw.enabled !== false;
4658
+ if ("replyMode" in raw && !isReplyMode(raw.replyMode)) {
4659
+ throw new Error(`channels[${index}].replyMode must be stream, final, or verbose`);
4660
+ }
4650
4661
  let options = undefined;
4651
4662
  if ("feishu" in raw && isRecord(raw.feishu)) {
4652
4663
  options = raw.feishu;
@@ -4657,6 +4668,7 @@ function parseRuntimeChannelConfig(raw, index) {
4657
4668
  id,
4658
4669
  type: raw.type,
4659
4670
  enabled,
4671
+ ...isReplyMode(raw.replyMode) ? { replyMode: raw.replyMode } : {},
4660
4672
  ...options ? { options } : {}
4661
4673
  };
4662
4674
  }
@@ -5394,7 +5406,7 @@ function resolveOrchestrationEndpoint(runtimeDir, platform = process.platform) {
5394
5406
  const suffix = createHash("sha256").update(runtimeDir).digest("hex").slice(0, 12);
5395
5407
  return {
5396
5408
  kind: "named-pipe",
5397
- path: `\\\\.\\pipe\\weacpx-orchestration-${suffix}`
5409
+ path: `\\\\.\\pipe\\xacpx-orchestration-${suffix}`
5398
5410
  };
5399
5411
  }
5400
5412
  return {
@@ -11940,11 +11952,46 @@ function readVersion(moduleUrl = import.meta.url) {
11940
11952
  }
11941
11953
  return "unknown";
11942
11954
  }
11943
- var PACKAGE_NAME = "@ganglion/xacpx", WEACPX_CORE_VERSION;
11955
+ var PACKAGE_NAME = "@ganglion/xacpx", XACPX_CORE_VERSION;
11944
11956
  var init_version = __esm(() => {
11945
- WEACPX_CORE_VERSION = readVersion();
11957
+ XACPX_CORE_VERSION = readVersion();
11946
11958
  });
11947
11959
 
11960
+ // src/orchestration/endpoint-probe.ts
11961
+ import { createConnection } from "node:net";
11962
+ async function canConnectToEndpoint(path3, timeoutMs) {
11963
+ return await new Promise((resolve) => {
11964
+ const socket = createConnection(path3);
11965
+ let settled = false;
11966
+ let timer;
11967
+ const finish = (result) => {
11968
+ if (settled) {
11969
+ return;
11970
+ }
11971
+ settled = true;
11972
+ if (timer) {
11973
+ clearTimeout(timer);
11974
+ }
11975
+ socket.destroy();
11976
+ resolve(result);
11977
+ };
11978
+ if (timeoutMs !== undefined && timeoutMs > 0) {
11979
+ timer = setTimeout(() => finish(true), timeoutMs);
11980
+ timer.unref?.();
11981
+ }
11982
+ socket.once("connect", () => finish(true));
11983
+ socket.once("error", (error2) => {
11984
+ const code = error2.code;
11985
+ if (code === "ENOENT" || code === "ECONNREFUSED") {
11986
+ finish(false);
11987
+ return;
11988
+ }
11989
+ finish(true);
11990
+ });
11991
+ });
11992
+ }
11993
+ var init_endpoint_probe = () => {};
11994
+
11948
11995
  // src/orchestration/task-watch-timeouts.ts
11949
11996
  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;
11950
11997
  var init_task_watch_timeouts = __esm(() => {
@@ -12000,6 +12047,14 @@ function escapeRegExp(s) {
12000
12047
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
12001
12048
  }
12002
12049
 
12050
+ // src/orchestration/coordinator-identity.ts
12051
+ function stableCoordinatorSession(transportSession) {
12052
+ return transportSession.replace(/:reset-\d+$/, "");
12053
+ }
12054
+ function sameCoordinatorSession(a, b) {
12055
+ return stableCoordinatorSession(a) === stableCoordinatorSession(b);
12056
+ }
12057
+
12003
12058
  // src/util/text.ts
12004
12059
  function truncateText(text, maxLength, ellipsis = "…") {
12005
12060
  if (text.length <= maxLength)
@@ -12281,7 +12336,7 @@ function isReplyMode2(value) {
12281
12336
  return value === "stream" || value === "final" || value === "verbose";
12282
12337
  }
12283
12338
  function isSessionSource(value) {
12284
- return value === undefined || value === "weacpx" || value === "agent-side";
12339
+ return value === undefined || value === "weacpx" || value === "xacpx" || value === "agent-side";
12285
12340
  }
12286
12341
  function isSessionRecord(value) {
12287
12342
  if (!isRecord2(value)) {
@@ -12813,7 +12868,7 @@ async function ensureCoreResolution(pluginHome) {
12813
12868
  await copyFile(srcJs, dstJs);
12814
12869
  } catch (error2) {
12815
12870
  const message = error2 instanceof Error ? error2.message : String(error2);
12816
- console.warn(`weacpx: skipped plugin-api resolution shim for "${name}" — could not copy ${srcJs} (${message}). ` + `Channel plugins importing "${name}/plugin-api" at runtime may fail to load.`);
12871
+ console.warn(`xacpx: skipped plugin-api resolution shim for "${name}" — could not copy ${srcJs} (${message}). ` + `Channel plugins importing "${name}/plugin-api" at runtime may fail to load.`);
12817
12872
  continue;
12818
12873
  }
12819
12874
  await writeFile4(join6(targetDir, "package.json"), JSON.stringify({
@@ -13712,7 +13767,7 @@ async function sendTyping(params) {
13712
13767
  label: "sendTyping"
13713
13768
  });
13714
13769
  }
13715
- var CHANNEL_VERSION, ILINK_APP_CLIENT_VERSION, ILINK_APP_ID, DEFAULT_BOT_AGENT = "weacpx", BOT_AGENT_MAX_LEN = 256, DEFAULT_LONG_POLL_TIMEOUT_MS = 35000, DEFAULT_API_TIMEOUT_MS = 15000, DEFAULT_CONFIG_TIMEOUT_MS = 1e4;
13770
+ var CHANNEL_VERSION, ILINK_APP_CLIENT_VERSION, ILINK_APP_ID, DEFAULT_BOT_AGENT = "xacpx", BOT_AGENT_MAX_LEN = 256, DEFAULT_LONG_POLL_TIMEOUT_MS = 35000, DEFAULT_API_TIMEOUT_MS = 15000, DEFAULT_CONFIG_TIMEOUT_MS = 1e4;
13716
13771
  var init_api = __esm(() => {
13717
13772
  init_version();
13718
13773
  init_accounts();
@@ -19158,19 +19213,19 @@ function cmpTuple(a, b) {
19158
19213
  return 0;
19159
19214
  }
19160
19215
  function validatePluginCompatibility(metadata, context) {
19161
- const { packageName, currentWeacpxVersion } = context;
19216
+ const { packageName, currentXacpxVersion } = context;
19162
19217
  const apiVersion = metadata.apiVersion;
19163
19218
  if (typeof apiVersion !== "number") {
19164
19219
  throw new Error(t().pluginCli.compatMissingApiVersion(packageName));
19165
19220
  }
19166
- if (!WEACPX_PLUGIN_API_SUPPORTED_VERSIONS.includes(apiVersion)) {
19167
- const supported = WEACPX_PLUGIN_API_SUPPORTED_VERSIONS.join(", ");
19221
+ if (!XACPX_PLUGIN_API_SUPPORTED_VERSIONS.includes(apiVersion)) {
19222
+ const supported = XACPX_PLUGIN_API_SUPPORTED_VERSIONS.join(", ");
19168
19223
  throw new Error(t().pluginCli.compatUnsupportedApiVersion(packageName, apiVersion, supported));
19169
19224
  }
19170
- if (!currentWeacpxVersion || currentWeacpxVersion === "unknown") {
19225
+ if (!currentXacpxVersion || currentXacpxVersion === "unknown") {
19171
19226
  return;
19172
19227
  }
19173
- const normalizedCurrent = normalizeCoreVersionForCompat(currentWeacpxVersion);
19228
+ const normalizedCurrent = normalizeCoreVersionForCompat(currentXacpxVersion);
19174
19229
  const minVersion = metadata.minXacpxVersion ?? metadata.minWeacpxVersion;
19175
19230
  const minVersionField = metadata.minXacpxVersion !== undefined ? "minXacpxVersion" : "minWeacpxVersion";
19176
19231
  if (minVersion !== undefined) {
@@ -19185,7 +19240,7 @@ function validatePluginCompatibility(metadata, context) {
19185
19240
  throw new Error(t().pluginCli.compatInvalidMinVersionDetail(packageName, minVersionField, detail));
19186
19241
  }
19187
19242
  if (!satisfied) {
19188
- throw new Error(t().pluginCli.compatMinVersionNotSatisfied(packageName, minVersion, currentWeacpxVersion));
19243
+ throw new Error(t().pluginCli.compatMinVersionNotSatisfied(packageName, minVersion, currentXacpxVersion));
19189
19244
  }
19190
19245
  }
19191
19246
  const compatibleVersions = metadata.compatibleXacpxVersions ?? metadata.compatibleWeacpxVersions;
@@ -19202,14 +19257,17 @@ function validatePluginCompatibility(metadata, context) {
19202
19257
  throw new Error(t().pluginCli.compatInvalidCompatibleVersionsDetail(packageName, compatibleField, detail));
19203
19258
  }
19204
19259
  if (!satisfied) {
19205
- throw new Error(t().pluginCli.compatCompatibleVersionsNotSatisfied(packageName, compatibleVersions, currentWeacpxVersion));
19260
+ throw new Error(t().pluginCli.compatCompatibleVersionsNotSatisfied(packageName, compatibleVersions, currentXacpxVersion));
19206
19261
  }
19207
19262
  }
19208
19263
  }
19209
- var WEACPX_PLUGIN_API_VERSION = 1, WEACPX_PLUGIN_API_SUPPORTED_VERSIONS, WEACPX_PLUGIN_MIN_CORE_VERSION = "0.5.0", SEMVER_RE;
19264
+ var XACPX_PLUGIN_API_VERSION = 1, XACPX_PLUGIN_API_SUPPORTED_VERSIONS, XACPX_PLUGIN_MIN_CORE_VERSION = "0.5.0", WEACPX_PLUGIN_API_VERSION, WEACPX_PLUGIN_API_SUPPORTED_VERSIONS, WEACPX_PLUGIN_MIN_CORE_VERSION, SEMVER_RE;
19210
19265
  var init_compatibility = __esm(() => {
19211
19266
  init_i18n();
19212
- WEACPX_PLUGIN_API_SUPPORTED_VERSIONS = [1];
19267
+ XACPX_PLUGIN_API_SUPPORTED_VERSIONS = [1];
19268
+ WEACPX_PLUGIN_API_VERSION = XACPX_PLUGIN_API_VERSION;
19269
+ WEACPX_PLUGIN_API_SUPPORTED_VERSIONS = XACPX_PLUGIN_API_SUPPORTED_VERSIONS;
19270
+ WEACPX_PLUGIN_MIN_CORE_VERSION = XACPX_PLUGIN_MIN_CORE_VERSION;
19213
19271
  SEMVER_RE = /^(\d+)\.(\d+)\.(\d+)$/;
19214
19272
  });
19215
19273
 
@@ -19224,14 +19282,14 @@ function validateWeacpxPlugin(value, packageName, options = {}) {
19224
19282
  if (!isRecord(plugin)) {
19225
19283
  throw new Error(t().pluginCli.pluginNoDefaultExport(packageName));
19226
19284
  }
19227
- const currentWeacpxVersion = options.currentWeacpxVersion ?? readVersion();
19285
+ const currentXacpxVersion = options.currentXacpxVersion ?? readVersion();
19228
19286
  validatePluginCompatibility({
19229
19287
  apiVersion: plugin.apiVersion,
19230
19288
  minWeacpxVersion: plugin.minWeacpxVersion,
19231
19289
  compatibleWeacpxVersions: plugin.compatibleWeacpxVersions,
19232
19290
  minXacpxVersion: plugin.minXacpxVersion,
19233
19291
  compatibleXacpxVersions: plugin.compatibleXacpxVersions
19234
- }, { packageName, currentWeacpxVersion });
19292
+ }, { packageName, currentXacpxVersion });
19235
19293
  if ("name" in plugin && typeof plugin.name === "string" && plugin.name.trim() && plugin.name.trim() !== packageName) {
19236
19294
  throw new Error(t().pluginCli.pluginNameMismatch(packageName, plugin.name));
19237
19295
  }
@@ -19260,7 +19318,7 @@ function validateWeacpxPlugin(value, packageName, options = {}) {
19260
19318
  }
19261
19319
  }
19262
19320
  const normalized = {
19263
- apiVersion: WEACPX_PLUGIN_API_VERSION,
19321
+ apiVersion: XACPX_PLUGIN_API_VERSION,
19264
19322
  ...typeof plugin.name === "string" && plugin.name.trim() ? { name: plugin.name.trim() } : { name: packageName },
19265
19323
  channels
19266
19324
  };
@@ -19314,7 +19372,7 @@ async function loadConfiguredPlugins(input) {
19314
19372
  throw new Error(`failed to load plugin ${config4.name}: ${message}`);
19315
19373
  }
19316
19374
  const plugin = validateWeacpxPlugin(moduleValue, config4.name, {
19317
- ...input.currentWeacpxVersion !== undefined ? { currentWeacpxVersion: input.currentWeacpxVersion } : {}
19375
+ ...input.currentXacpxVersion !== undefined ? { currentXacpxVersion: input.currentXacpxVersion } : {}
19318
19376
  });
19319
19377
  const channels = plugin.channels ?? [];
19320
19378
  for (const channel of channels) {
@@ -19566,16 +19624,16 @@ var init_prompt_output = __esm(() => {
19566
19624
  });
19567
19625
 
19568
19626
  // src/commands/command-list.ts
19569
- function isKnownWeacpxCommandPrefix(prefix) {
19627
+ function isKnownXacpxCommandPrefix(prefix) {
19570
19628
  return KNOWN_COMMAND_PREFIX_SET.has(prefix.toLowerCase());
19571
19629
  }
19572
- function isKnownWeacpxCommandText(text) {
19630
+ function isKnownXacpxCommandText(text) {
19573
19631
  const firstToken = text.trim().split(/\s+/, 1)[0];
19574
- return Boolean(firstToken && isKnownWeacpxCommandPrefix(firstToken));
19632
+ return Boolean(firstToken && isKnownXacpxCommandPrefix(firstToken));
19575
19633
  }
19576
- var WEACPX_KNOWN_COMMAND_PREFIXES, KNOWN_COMMAND_PREFIX_SET;
19634
+ var XACPX_KNOWN_COMMAND_PREFIXES, KNOWN_COMMAND_PREFIX_SET;
19577
19635
  var init_command_list = __esm(() => {
19578
- WEACPX_KNOWN_COMMAND_PREFIXES = [
19636
+ XACPX_KNOWN_COMMAND_PREFIXES = [
19579
19637
  "/help",
19580
19638
  "/agents",
19581
19639
  "/workspaces",
@@ -19605,7 +19663,7 @@ var init_command_list = __esm(() => {
19605
19663
  "/later",
19606
19664
  "/lt"
19607
19665
  ];
19608
- KNOWN_COMMAND_PREFIX_SET = new Set(WEACPX_KNOWN_COMMAND_PREFIXES);
19666
+ KNOWN_COMMAND_PREFIX_SET = new Set(XACPX_KNOWN_COMMAND_PREFIXES);
19609
19667
  });
19610
19668
 
19611
19669
  // src/commands/parse-command.ts
@@ -20095,7 +20153,7 @@ function normalizeCommand(command) {
20095
20153
  return command;
20096
20154
  }
20097
20155
  function isRecognizedCommand(command) {
20098
- return isKnownWeacpxCommandPrefix(command);
20156
+ return isKnownXacpxCommandPrefix(command);
20099
20157
  }
20100
20158
  function toPermissionMode(value) {
20101
20159
  if (value === "allow")
@@ -20609,6 +20667,23 @@ function applySupportedConfigUpdate(config4, path14, rawValue) {
20609
20667
  }
20610
20668
  return { renderedValue: rawValue };
20611
20669
  }
20670
+ const channelMatch = path14.match(/^channels\.([^.]+)\.replyMode$/);
20671
+ if (channelMatch) {
20672
+ const [, id] = channelMatch;
20673
+ if (!id) {
20674
+ return { error: c.pathNotSupported(path14) };
20675
+ }
20676
+ const channel = config4.channels.find((entry) => entry.id === id);
20677
+ if (!channel) {
20678
+ return { error: c.channelRuntimeNotFound(id) };
20679
+ }
20680
+ const parsed = parseEnum(rawValue, ["stream", "final", "verbose"]);
20681
+ if (!parsed) {
20682
+ return { error: c.channelRuntimeReplyModeInvalid(id) };
20683
+ }
20684
+ channel.replyMode = parsed;
20685
+ return { renderedValue: parsed };
20686
+ }
20612
20687
  return { error: c.pathNotSupported(path14) };
20613
20688
  }
20614
20689
  function parseEnum(value, allowed) {
@@ -20638,6 +20713,7 @@ var init_config_handler = __esm(() => {
20638
20713
  "logging.maxFiles",
20639
20714
  "logging.retentionDays",
20640
20715
  "channel.replyMode",
20716
+ "channels.<id>.replyMode",
20641
20717
  "agents.<name>.driver",
20642
20718
  "agents.<name>.command",
20643
20719
  "workspaces.<name>.cwd",
@@ -20978,6 +21054,20 @@ var init_build_coordinator_prompt = __esm(() => {
20978
21054
  init_render_delegate_question_package();
20979
21055
  });
20980
21056
 
21057
+ // src/commands/handlers/resolve-reply-mode.ts
21058
+ function resolveChannelDefaultReplyMode(config4, chatKey) {
21059
+ if (!config4)
21060
+ return;
21061
+ const channelId = getChannelIdFromChatKey(chatKey);
21062
+ return config4.channels.find((channel) => channel.id === channelId)?.replyMode;
21063
+ }
21064
+ function resolveEffectiveReplyMode(config4, chatKey, sessionOverride) {
21065
+ return sessionOverride ?? resolveChannelDefaultReplyMode(config4, chatKey) ?? config4?.channel.replyMode ?? "verbose";
21066
+ }
21067
+ var init_resolve_reply_mode = __esm(() => {
21068
+ init_channel_scope();
21069
+ });
21070
+
20981
21071
  // src/commands/handlers/session-list-marker.ts
20982
21072
  function decorateUnread(label, hasUnread) {
20983
21073
  return hasUnread ? `● ${label}` : label;
@@ -21282,14 +21372,16 @@ async function handleReplyModeShow(context, chatKey) {
21282
21372
  return { text: t().session.noCurrent };
21283
21373
  }
21284
21374
  const globalDefault = context.config?.channel.replyMode ?? "verbose";
21375
+ const channelDefault = resolveChannelDefaultReplyMode(context.config, chatKey);
21285
21376
  const sessionOverride = session3.replyMode;
21286
- const effective = sessionOverride ?? globalDefault;
21377
+ const effective = resolveEffectiveReplyMode(context.config, chatKey, sessionOverride);
21287
21378
  const s = t().session;
21288
21379
  return {
21289
21380
  text: [
21290
21381
  s.replyModeHeader,
21291
21382
  s.replyModeSessionLabel(toDisplaySessionAlias(session3.alias)),
21292
21383
  s.replyModeGlobalDefault(globalDefault),
21384
+ s.replyModeChannelDefault(channelDefault ?? s.modeNotSet),
21293
21385
  s.replyModeSessionOverride(sessionOverride ?? s.modeNotSet),
21294
21386
  s.replyModeEffective(effective)
21295
21387
  ].join(`
@@ -21310,8 +21402,8 @@ async function handleReplyModeReset(context, chatKey) {
21310
21402
  return { text: t().session.noCurrent };
21311
21403
  }
21312
21404
  await context.sessions.setCurrentSessionReplyMode(chatKey, undefined);
21313
- const globalDefault = context.config?.channel.replyMode ?? "verbose";
21314
- return { text: t().session.replyModeReset(globalDefault) };
21405
+ const fallback = resolveEffectiveReplyMode(context.config, chatKey, undefined);
21406
+ return { text: t().session.replyModeReset(fallback) };
21315
21407
  }
21316
21408
  async function handleStatus(context, chatKey) {
21317
21409
  const session3 = await context.sessions.getCurrentSession(chatKey);
@@ -21458,14 +21550,14 @@ async function handleSessionRemove(context, chatKey, alias) {
21458
21550
  `) };
21459
21551
  }
21460
21552
  async function promptWithSession(context, session3, chatKey, text, reply, replyContextToken, accountId, media, abortSignal, onToolEvent, onThought, perfSpan, metadata) {
21461
- const effectiveReplyMode = session3.replyMode ?? context.config?.channel.replyMode ?? "verbose";
21553
+ const effectiveReplyMode = resolveEffectiveReplyMode(context.config, chatKey, session3.replyMode);
21462
21554
  if (!session3.replyMode)
21463
21555
  session3.replyMode = effectiveReplyMode;
21464
21556
  const transportReply = effectiveReplyMode !== "final" ? reply : undefined;
21465
21557
  if (context.orchestration) {
21466
21558
  try {
21467
21559
  await context.orchestration.recordCoordinatorRouteContext?.({
21468
- coordinatorSession: session3.transportSession,
21560
+ coordinatorSession: stableCoordinatorSession(session3.transportSession),
21469
21561
  chatKey,
21470
21562
  sessionAlias: session3.alias,
21471
21563
  ...replyContextToken ? { replyContextToken } : {},
@@ -21548,7 +21640,7 @@ async function preparePromptWithFallback(context, session3, chatKey, text, reply
21548
21640
  try {
21549
21641
  return await buildCoordinatorPrompt({
21550
21642
  orchestration: orchestration3,
21551
- coordinatorSession: session3.transportSession,
21643
+ coordinatorSession: stableCoordinatorSession(session3.transportSession),
21552
21644
  chatKey,
21553
21645
  userText: text,
21554
21646
  ...replyContextToken ? { replyContextToken } : {},
@@ -21606,6 +21698,7 @@ var DEFAULT_SESSION_TAIL_LINES = 50, MAX_SESSION_TAIL_LINES = 500;
21606
21698
  var init_session_handler = __esm(() => {
21607
21699
  init_build_coordinator_prompt();
21608
21700
  init_channel_scope();
21701
+ init_resolve_reply_mode();
21609
21702
  init_workspace_name();
21610
21703
  init_i18n();
21611
21704
  });
@@ -21882,6 +21975,7 @@ async function handleDelegateRequest(context, chatKey, targetAgent, task, role,
21882
21975
  if (!session3) {
21883
21976
  return { text: t().orchestration.noCurrentSession };
21884
21977
  }
21978
+ const coordinatorSession = stableCoordinatorSession(session3.transportSession);
21885
21979
  const orchestration3 = getOrchestration(context);
21886
21980
  if (!orchestration3) {
21887
21981
  return { text: renderOrchestrationUnavailable() };
@@ -21889,7 +21983,7 @@ async function handleDelegateRequest(context, chatKey, targetAgent, task, role,
21889
21983
  const result = await orchestration3.requestDelegate({
21890
21984
  sourceHandle: session3.transportSession,
21891
21985
  sourceKind: "coordinator",
21892
- coordinatorSession: session3.transportSession,
21986
+ coordinatorSession,
21893
21987
  workspace: session3.workspace,
21894
21988
  targetAgent,
21895
21989
  task,
@@ -21906,12 +22000,13 @@ async function handleGroupCreate(context, chatKey, title) {
21906
22000
  if (!session3) {
21907
22001
  return { text: t().orchestration.noCurrentSession };
21908
22002
  }
22003
+ const coordinatorSession = stableCoordinatorSession(session3.transportSession);
21909
22004
  const orchestration3 = getOrchestration(context);
21910
22005
  if (!orchestration3) {
21911
22006
  return { text: renderOrchestrationUnavailable() };
21912
22007
  }
21913
22008
  const group = await orchestration3.createGroup({
21914
- coordinatorSession: session3.transportSession,
22009
+ coordinatorSession,
21915
22010
  title
21916
22011
  });
21917
22012
  return { text: renderGroupCreated(group) };
@@ -21921,12 +22016,13 @@ async function handleGroupList(context, chatKey, filter) {
21921
22016
  if (!session3) {
21922
22017
  return { text: t().orchestration.noCurrentSession };
21923
22018
  }
22019
+ const coordinatorSession = stableCoordinatorSession(session3.transportSession);
21924
22020
  const orchestration3 = getOrchestration(context);
21925
22021
  if (!orchestration3) {
21926
22022
  return { text: renderOrchestrationUnavailable() };
21927
22023
  }
21928
22024
  const groups = await orchestration3.listGroupSummaries({
21929
- coordinatorSession: session3.transportSession,
22025
+ coordinatorSession,
21930
22026
  ...filter ?? {}
21931
22027
  });
21932
22028
  return { text: renderGroupList(groups) };
@@ -21936,13 +22032,14 @@ async function handleGroupGet(context, chatKey, groupId) {
21936
22032
  if (!session3) {
21937
22033
  return { text: t().orchestration.noCurrentSession };
21938
22034
  }
22035
+ const coordinatorSession = stableCoordinatorSession(session3.transportSession);
21939
22036
  const orchestration3 = getOrchestration(context);
21940
22037
  if (!orchestration3) {
21941
22038
  return { text: renderOrchestrationUnavailable() };
21942
22039
  }
21943
22040
  const group = await orchestration3.getGroupSummary({
21944
22041
  groupId,
21945
- coordinatorSession: session3.transportSession
22042
+ coordinatorSession
21946
22043
  });
21947
22044
  if (!group) {
21948
22045
  return { text: t().orchestration.groupNotFound };
@@ -21954,20 +22051,21 @@ async function handleGroupCancel(context, chatKey, groupId) {
21954
22051
  if (!session3) {
21955
22052
  return { text: t().orchestration.noCurrentSession };
21956
22053
  }
22054
+ const coordinatorSession = stableCoordinatorSession(session3.transportSession);
21957
22055
  const orchestration3 = getOrchestration(context);
21958
22056
  if (!orchestration3) {
21959
22057
  return { text: renderOrchestrationUnavailable() };
21960
22058
  }
21961
22059
  const group = await orchestration3.getGroupSummary({
21962
22060
  groupId,
21963
- coordinatorSession: session3.transportSession
22061
+ coordinatorSession
21964
22062
  });
21965
22063
  if (!group) {
21966
22064
  return { text: t().orchestration.groupNotFound };
21967
22065
  }
21968
22066
  const cancelled = await orchestration3.cancelGroup({
21969
22067
  groupId,
21970
- coordinatorSession: session3.transportSession
22068
+ coordinatorSession
21971
22069
  });
21972
22070
  return { text: renderGroupCancelSuccess(cancelled) };
21973
22071
  }
@@ -21976,13 +22074,14 @@ async function handleGroupDelegate(context, chatKey, groupId, targetAgent, task,
21976
22074
  if (!session3) {
21977
22075
  return { text: t().orchestration.noCurrentSession };
21978
22076
  }
22077
+ const coordinatorSession = stableCoordinatorSession(session3.transportSession);
21979
22078
  const orchestration3 = getOrchestration(context);
21980
22079
  if (!orchestration3) {
21981
22080
  return { text: renderOrchestrationUnavailable() };
21982
22081
  }
21983
22082
  const group = await orchestration3.getGroupSummary({
21984
22083
  groupId,
21985
- coordinatorSession: session3.transportSession
22084
+ coordinatorSession
21986
22085
  });
21987
22086
  if (!group) {
21988
22087
  return { text: t().orchestration.groupNotFound };
@@ -21994,12 +22093,13 @@ async function handleTaskList(context, chatKey, filter) {
21994
22093
  if (!session3) {
21995
22094
  return { text: t().orchestration.noCurrentSession };
21996
22095
  }
22096
+ const coordinatorSession = stableCoordinatorSession(session3.transportSession);
21997
22097
  const orchestration3 = getOrchestration(context);
21998
22098
  if (!orchestration3) {
21999
22099
  return { text: renderOrchestrationUnavailable() };
22000
22100
  }
22001
22101
  const tasks = await orchestration3.listTasks({
22002
- coordinatorSession: session3.transportSession,
22102
+ coordinatorSession,
22003
22103
  ...filter ?? {}
22004
22104
  });
22005
22105
  return { text: renderTaskList2(tasks) };
@@ -22009,12 +22109,13 @@ async function handleTaskGet(context, chatKey, taskId) {
22009
22109
  if (!session3) {
22010
22110
  return { text: t().orchestration.noCurrentSession };
22011
22111
  }
22112
+ const coordinatorSession = stableCoordinatorSession(session3.transportSession);
22012
22113
  const orchestration3 = getOrchestration(context);
22013
22114
  if (!orchestration3) {
22014
22115
  return { text: renderOrchestrationUnavailable() };
22015
22116
  }
22016
22117
  const task = await orchestration3.getTask(taskId);
22017
- if (!task || task.coordinatorSession !== session3.transportSession) {
22118
+ if (!task || !sameCoordinatorSession(task.coordinatorSession, coordinatorSession)) {
22018
22119
  return { text: t().orchestration.taskNotFound };
22019
22120
  }
22020
22121
  return { text: renderTaskSummary2(task) };
@@ -22024,12 +22125,13 @@ async function handleTaskApprove(context, chatKey, taskId) {
22024
22125
  if (!session3) {
22025
22126
  return { text: t().orchestration.noCurrentSession };
22026
22127
  }
22128
+ const coordinatorSession = stableCoordinatorSession(session3.transportSession);
22027
22129
  const orchestration3 = getOrchestration(context);
22028
22130
  if (!orchestration3) {
22029
22131
  return { text: renderOrchestrationUnavailable() };
22030
22132
  }
22031
22133
  const task = await orchestration3.getTask(taskId);
22032
- if (!task || task.coordinatorSession !== session3.transportSession) {
22134
+ if (!task || !sameCoordinatorSession(task.coordinatorSession, coordinatorSession)) {
22033
22135
  return { text: t().orchestration.taskNotFound };
22034
22136
  }
22035
22137
  if (task.status !== "needs_confirmation") {
@@ -22037,7 +22139,7 @@ async function handleTaskApprove(context, chatKey, taskId) {
22037
22139
  }
22038
22140
  const approved = await orchestration3.approveTask({
22039
22141
  taskId,
22040
- coordinatorSession: session3.transportSession
22142
+ coordinatorSession
22041
22143
  });
22042
22144
  return { text: renderTaskApprovalSuccess2(approved) };
22043
22145
  }
@@ -22046,12 +22148,13 @@ async function handleTaskReject(context, chatKey, taskId) {
22046
22148
  if (!session3) {
22047
22149
  return { text: t().orchestration.noCurrentSession };
22048
22150
  }
22151
+ const coordinatorSession = stableCoordinatorSession(session3.transportSession);
22049
22152
  const orchestration3 = getOrchestration(context);
22050
22153
  if (!orchestration3) {
22051
22154
  return { text: renderOrchestrationUnavailable() };
22052
22155
  }
22053
22156
  const task = await orchestration3.getTask(taskId);
22054
- if (!task || task.coordinatorSession !== session3.transportSession) {
22157
+ if (!task || !sameCoordinatorSession(task.coordinatorSession, coordinatorSession)) {
22055
22158
  return { text: t().orchestration.taskNotFound };
22056
22159
  }
22057
22160
  if (task.status !== "needs_confirmation") {
@@ -22059,7 +22162,7 @@ async function handleTaskReject(context, chatKey, taskId) {
22059
22162
  }
22060
22163
  const rejected = await orchestration3.cancelTask({
22061
22164
  taskId,
22062
- coordinatorSession: session3.transportSession
22165
+ coordinatorSession
22063
22166
  });
22064
22167
  return { text: renderTaskRejectSuccess(rejected) };
22065
22168
  }
@@ -22068,17 +22171,18 @@ async function handleTaskCancel(context, chatKey, taskId) {
22068
22171
  if (!session3) {
22069
22172
  return { text: t().orchestration.noCurrentSession };
22070
22173
  }
22174
+ const coordinatorSession = stableCoordinatorSession(session3.transportSession);
22071
22175
  const orchestration3 = getOrchestration(context);
22072
22176
  if (!orchestration3) {
22073
22177
  return { text: renderOrchestrationUnavailable() };
22074
22178
  }
22075
22179
  const task = await orchestration3.getTask(taskId);
22076
- if (!task || task.coordinatorSession !== session3.transportSession) {
22180
+ if (!task || !sameCoordinatorSession(task.coordinatorSession, coordinatorSession)) {
22077
22181
  return { text: t().orchestration.taskNotFound };
22078
22182
  }
22079
22183
  const cancelled = await orchestration3.requestTaskCancellation({
22080
22184
  taskId,
22081
- coordinatorSession: session3.transportSession
22185
+ coordinatorSession
22082
22186
  });
22083
22187
  return { text: renderTaskCancelSuccess(cancelled) };
22084
22188
  }
@@ -22087,11 +22191,12 @@ async function handleTasksClean(context, chatKey) {
22087
22191
  if (!session3) {
22088
22192
  return { text: t().orchestration.noCurrentSession };
22089
22193
  }
22194
+ const coordinatorSession = stableCoordinatorSession(session3.transportSession);
22090
22195
  const orchestration3 = getOrchestration(context);
22091
22196
  if (!orchestration3) {
22092
22197
  return { text: renderOrchestrationUnavailable() };
22093
22198
  }
22094
- const result = await orchestration3.cleanTasks(session3.transportSession);
22199
+ const result = await orchestration3.cleanTasks(coordinatorSession);
22095
22200
  return { text: renderTasksCleanResult(result.removedTasks, result.removedBindings) };
22096
22201
  }
22097
22202
  async function getCurrentSession(context, chatKey) {
@@ -23657,23 +23762,43 @@ var init_translate_acpx_note = __esm(() => {
23657
23762
 
23658
23763
  // src/commands/handlers/session-reset-handler.ts
23659
23764
  async function handleSessionResetCommand(context, ops, chatKey) {
23660
- const session3 = await context.sessions.getCurrentSession(chatKey);
23661
- if (!session3) {
23765
+ const previous = await context.sessions.getCurrentSession(chatKey);
23766
+ if (!previous) {
23662
23767
  return { text: t().misc.sessionResetNoCurrentSession };
23663
23768
  }
23664
- const resetSession = ops.resolveSession(session3.alias, session3.agent, session3.workspace, buildResetTransportSessionName(session3, ops.now()));
23769
+ const wasNative = previous.source === "agent-side";
23770
+ const resetSession = ops.resolveSession(previous.alias, previous.agent, previous.workspace, buildResetTransportSessionName(previous, ops.now()));
23665
23771
  const releaseTransportReservation = await ops.reserveTransportSession(resetSession.transportSession);
23666
23772
  try {
23667
23773
  try {
23668
23774
  await ops.ensureTransportSession(resetSession);
23669
23775
  const exists = await ops.checkTransportSession(resetSession);
23670
23776
  if (!exists) {
23671
- return { text: t().misc.sessionResetFailed(session3.alias) };
23777
+ return { text: t().misc.sessionResetFailed(previous.alias) };
23672
23778
  }
23673
23779
  } catch (error2) {
23674
23780
  return renderTransportError(resetSession, error2);
23675
23781
  }
23676
- await context.sessions.attachSession(resetSession.alias, resetSession.agent, resetSession.workspace, resetSession.transportSession);
23782
+ let freshAgentSessionId;
23783
+ if (wasNative) {
23784
+ try {
23785
+ freshAgentSessionId = await context.transport.getAgentSessionId?.(resetSession);
23786
+ } catch (error2) {
23787
+ await context.logger.info("session.reset.native_id_unavailable", "failed to read fresh agent session id; falling back to xacpx session", { alias: resetSession.alias, error: error2 instanceof Error ? error2.message : String(error2) });
23788
+ }
23789
+ }
23790
+ if (wasNative && freshAgentSessionId) {
23791
+ await context.sessions.attachNativeSession({
23792
+ alias: resetSession.alias,
23793
+ agent: resetSession.agent,
23794
+ workspace: resetSession.workspace,
23795
+ transportSession: resetSession.transportSession,
23796
+ agentSessionId: freshAgentSessionId,
23797
+ updatedAt: new Date(ops.now()).toISOString()
23798
+ });
23799
+ } else {
23800
+ await context.sessions.attachSession(resetSession.alias, resetSession.agent, resetSession.workspace, resetSession.transportSession);
23801
+ }
23677
23802
  await ops.refreshSessionTransportAgentCommand(resetSession.alias);
23678
23803
  await context.sessions.useSession(chatKey, resetSession.alias);
23679
23804
  await context.logger.info("session.reset", "reset current logical session", {
@@ -23681,8 +23806,19 @@ async function handleSessionResetCommand(context, ops, chatKey) {
23681
23806
  agent: resetSession.agent,
23682
23807
  workspace: resetSession.workspace,
23683
23808
  transportSession: resetSession.transportSession,
23684
- chatKey
23809
+ chatKey,
23810
+ native: wasNative && Boolean(freshAgentSessionId)
23685
23811
  });
23812
+ if (wasNative && context.transport.removeSession && context.sessions.countAliasesSharingTransport(previous.transportSession) === 0) {
23813
+ try {
23814
+ await context.transport.removeSession(previous);
23815
+ } catch (error2) {
23816
+ await context.logger.info("session.reset.close_previous_failed", "failed to close previous native session after reset", {
23817
+ transportSession: previous.transportSession,
23818
+ error: error2 instanceof Error ? error2.message : String(error2)
23819
+ });
23820
+ }
23821
+ }
23686
23822
  } finally {
23687
23823
  await releaseTransportReservation();
23688
23824
  }
@@ -24121,7 +24257,7 @@ class CommandRouter {
24121
24257
  return await this.measureTransportCall("has_session", session3, () => this.transport.hasSession(session3));
24122
24258
  }
24123
24259
  async promptTransportSession(session3, text, reply, replyContext, media, abortSignal, onToolEvent, onThought, perfSpan) {
24124
- session3.mcpCoordinatorSession ??= session3.transportSession;
24260
+ session3.mcpCoordinatorSession ??= stableCoordinatorSession(session3.transportSession);
24125
24261
  let done = false;
24126
24262
  let abortRequested = false;
24127
24263
  let cancelOnAbort;
@@ -24351,7 +24487,7 @@ class ConsoleAgent {
24351
24487
  return await this.router.handle(request.conversationId, request.text, request.reply, request.replyContextToken, request.accountId, promptMedia, request.metadata, request.abortSignal, request.onToolEvent, request.onThought, request.perfSpan);
24352
24488
  }
24353
24489
  isKnownCommand(text) {
24354
- return isKnownWeacpxCommandText(text);
24490
+ return isKnownXacpxCommandText(text);
24355
24491
  }
24356
24492
  async clearSession(conversationId) {
24357
24493
  await this.router.clearSession?.(conversationId);
@@ -24372,7 +24508,7 @@ var init_console_agent = __esm(() => {
24372
24508
 
24373
24509
  // src/orchestration/orchestration-server.ts
24374
24510
  import { rm as rm8 } from "node:fs/promises";
24375
- import { createConnection as createConnection2, createServer } from "node:net";
24511
+ import { createServer } from "node:net";
24376
24512
 
24377
24513
  class OrchestrationServer {
24378
24514
  endpoint;
@@ -24600,7 +24736,7 @@ class OrchestrationServer {
24600
24736
  if (!task) {
24601
24737
  return null;
24602
24738
  }
24603
- if (task.coordinatorSession !== coordinatorSession) {
24739
+ if (!sameCoordinatorSession(task.coordinatorSession, coordinatorSession)) {
24604
24740
  return null;
24605
24741
  }
24606
24742
  return task;
@@ -24865,29 +25001,6 @@ function requireTaskQuestions(params, key) {
24865
25001
  };
24866
25002
  });
24867
25003
  }
24868
- async function canConnectToEndpoint(path14) {
24869
- return await new Promise((resolve3) => {
24870
- const socket = createConnection2(path14);
24871
- let settled = false;
24872
- const finish = (result) => {
24873
- if (settled) {
24874
- return;
24875
- }
24876
- settled = true;
24877
- socket.destroy();
24878
- resolve3(result);
24879
- };
24880
- socket.once("connect", () => finish(true));
24881
- socket.once("error", (error2) => {
24882
- const code = error2.code;
24883
- if (code === "ENOENT" || code === "ECONNREFUSED") {
24884
- finish(false);
24885
- return;
24886
- }
24887
- finish(true);
24888
- });
24889
- });
24890
- }
24891
25004
  async function listen(server, path14) {
24892
25005
  await new Promise((resolve3, reject) => {
24893
25006
  const onError = (error2) => {
@@ -24910,6 +25023,7 @@ var OrchestrationInvalidRequestError, ORCHESTRATION_RPC_METHODS;
24910
25023
  var init_orchestration_server = __esm(() => {
24911
25024
  init_orchestration_ipc();
24912
25025
  init_task_watch_timeouts();
25026
+ init_endpoint_probe();
24913
25027
  OrchestrationInvalidRequestError = class OrchestrationInvalidRequestError extends Error {
24914
25028
  };
24915
25029
  ORCHESTRATION_RPC_METHODS = new Set([
@@ -25110,7 +25224,7 @@ class OrchestrationService {
25110
25224
  async getGroupSummary(input) {
25111
25225
  const state = await this.deps.loadState();
25112
25226
  const group = this.ensureGroups(state)[input.groupId];
25113
- if (!group || group.coordinatorSession !== input.coordinatorSession) {
25227
+ if (!group || !sameCoordinatorSession(group.coordinatorSession, input.coordinatorSession)) {
25114
25228
  return null;
25115
25229
  }
25116
25230
  return this.buildGroupSummary(group, Object.values(state.orchestration.tasks).filter((task) => task.groupId === input.groupId));
@@ -25122,7 +25236,7 @@ class OrchestrationService {
25122
25236
  const now = this.deps.now().getTime();
25123
25237
  const sortField = input.sort ?? "updatedAt";
25124
25238
  const order = input.order ?? "desc";
25125
- return Object.values(this.ensureGroups(state)).filter((group) => group.coordinatorSession === input.coordinatorSession).map((group) => ({
25239
+ return Object.values(this.ensureGroups(state)).filter((group) => sameCoordinatorSession(group.coordinatorSession, input.coordinatorSession)).map((group) => ({
25126
25240
  group,
25127
25241
  summary: this.buildGroupSummary(group, tasks.filter((task) => task.groupId === group.groupId))
25128
25242
  })).filter(({ summary }) => {
@@ -25612,7 +25726,7 @@ class OrchestrationService {
25612
25726
  const workerSession = task.workerSession;
25613
25727
  const taskStillOwnsWorkerSession = current?.workerSession === workerSession;
25614
25728
  const currentBinding = state.orchestration.workerBindings[workerSession];
25615
- const bindingStillBelongsToThisStartup = currentBinding?.sourceHandle === workerSession && currentBinding.coordinatorSession === task.coordinatorSession && currentBinding.workspace === task.workspace && currentBinding.cwd === task.cwd && currentBinding.targetAgent === task.targetAgent && currentBinding.role === task.role;
25729
+ const bindingStillBelongsToThisStartup = currentBinding?.sourceHandle === workerSession && sameCoordinatorSession(currentBinding.coordinatorSession, task.coordinatorSession) && currentBinding.workspace === task.workspace && currentBinding.cwd === task.cwd && currentBinding.targetAgent === task.targetAgent && currentBinding.role === task.role;
25616
25730
  const otherActiveOwner = Object.values(state.orchestration.tasks).some((candidate) => candidate.taskId !== task.taskId && candidate.workerSession === workerSession && (!this.isTerminalStatus(candidate.status) || candidate.reviewPending !== undefined));
25617
25731
  const restoreOrDeleteBinding = () => {
25618
25732
  if (!bindingStillBelongsToThisStartup || otherActiveOwner) {
@@ -25671,7 +25785,7 @@ class OrchestrationService {
25671
25785
  current.updatedAt = now;
25672
25786
  this.bumpGroupUpdated(state, current.groupId, now);
25673
25787
  const currentBinding = state.orchestration.workerBindings[workerSession];
25674
- const bindingStillBelongsToThisStartup = currentBinding?.sourceHandle === workerSession && currentBinding.coordinatorSession === task.coordinatorSession && currentBinding.workspace === task.workspace && currentBinding.cwd === task.cwd && currentBinding.targetAgent === task.targetAgent && currentBinding.role === task.role;
25788
+ const bindingStillBelongsToThisStartup = currentBinding?.sourceHandle === workerSession && sameCoordinatorSession(currentBinding.coordinatorSession, task.coordinatorSession) && currentBinding.workspace === task.workspace && currentBinding.cwd === task.cwd && currentBinding.targetAgent === task.targetAgent && currentBinding.role === task.role;
25675
25789
  const otherActiveOwner = Object.values(state.orchestration.tasks).some((candidate) => candidate.taskId !== task.taskId && candidate.workerSession === workerSession && (!this.isTerminalStatus(candidate.status) || candidate.reviewPending !== undefined));
25676
25790
  if (bindingStillBelongsToThisStartup && !otherActiveOwner) {
25677
25791
  if (input.previousBinding) {
@@ -25690,7 +25804,7 @@ class OrchestrationService {
25690
25804
  const state = await this.deps.loadState();
25691
25805
  const workerSession = task.workerSession;
25692
25806
  const currentBinding = state.orchestration.workerBindings[workerSession];
25693
- const bindingStillBelongsToThisStartup = currentBinding?.sourceHandle === workerSession && currentBinding.coordinatorSession === task.coordinatorSession && currentBinding.workspace === task.workspace && currentBinding.cwd === task.cwd && currentBinding.targetAgent === task.targetAgent && currentBinding.role === task.role;
25807
+ const bindingStillBelongsToThisStartup = currentBinding?.sourceHandle === workerSession && sameCoordinatorSession(currentBinding.coordinatorSession, task.coordinatorSession) && currentBinding.workspace === task.workspace && currentBinding.cwd === task.cwd && currentBinding.targetAgent === task.targetAgent && currentBinding.role === task.role;
25694
25808
  if (!bindingStillBelongsToThisStartup) {
25695
25809
  return false;
25696
25810
  }
@@ -25863,7 +25977,7 @@ class OrchestrationService {
25863
25977
  while (true) {
25864
25978
  const state = await this.deps.loadState();
25865
25979
  const task = state.orchestration.tasks[input.taskId];
25866
- if (!task || task.coordinatorSession !== input.coordinatorSession) {
25980
+ if (!task || !sameCoordinatorSession(task.coordinatorSession, input.coordinatorSession)) {
25867
25981
  return { status: "not_found", task: null, events: [], nextAfterSeq: afterSeq };
25868
25982
  }
25869
25983
  const snapshot = { ...task };
@@ -25921,7 +26035,8 @@ class OrchestrationService {
25921
26035
  return await this.mutate(async () => {
25922
26036
  const state = await this.deps.loadState();
25923
26037
  const now = this.deps.now().toISOString();
25924
- const existing = this.ensureCoordinatorRoutes(state)[input.coordinatorSession];
26038
+ const routeKey = stableCoordinatorSession(input.coordinatorSession);
26039
+ const existing = this.ensureCoordinatorRoutes(state)[routeKey];
25925
26040
  const sameChat = existing?.chatKey === input.chatKey;
25926
26041
  const hasAccountId = input.accountId !== undefined;
25927
26042
  const hasReplyContextToken = input.replyContextToken !== undefined;
@@ -25935,14 +26050,14 @@ class OrchestrationService {
25935
26050
  replyContextToken: existing.replyContextToken
25936
26051
  } : undefined;
25937
26052
  const route = {
25938
- coordinatorSession: input.coordinatorSession,
26053
+ coordinatorSession: routeKey,
25939
26054
  chatKey: input.chatKey,
25940
26055
  ...input.sessionAlias ? { sessionAlias: input.sessionAlias } : {},
25941
26056
  ...replyRoute ? replyRoute : {},
25942
26057
  ...buildCoordinatorRouteChatMetadata(input, sameChat ? existing : undefined),
25943
26058
  updatedAt: now
25944
26059
  };
25945
- this.ensureCoordinatorRoutes(state)[input.coordinatorSession] = route;
26060
+ this.ensureCoordinatorRoutes(state)[routeKey] = route;
25946
26061
  await this.deps.saveState(state);
25947
26062
  return { ...route };
25948
26063
  });
@@ -26186,7 +26301,7 @@ class OrchestrationService {
26186
26301
  return task;
26187
26302
  });
26188
26303
  const now = this.deps.now().toISOString();
26189
- const route = this.snapshotCoordinatorDeliveryRoute(this.ensureCoordinatorRoutes(state)[input.coordinatorSession]);
26304
+ const route = this.snapshotCoordinatorDeliveryRoute(this.ensureCoordinatorRoutes(state)[stableCoordinatorSession(input.coordinatorSession)]);
26190
26305
  if (coordinatorState.activePackageId) {
26191
26306
  const activePackage = this.ensureHumanQuestionPackages(state)[coordinatorState.activePackageId];
26192
26307
  if (!activePackage) {
@@ -26288,7 +26403,7 @@ class OrchestrationService {
26288
26403
  if (!packageRecord) {
26289
26404
  throw new Error(`package "${input.packageId}" does not exist`);
26290
26405
  }
26291
- if (packageRecord.coordinatorSession !== input.coordinatorSession) {
26406
+ if (!sameCoordinatorSession(packageRecord.coordinatorSession, input.coordinatorSession)) {
26292
26407
  throw new Error(`package "${input.packageId}" belongs to coordinator "${packageRecord.coordinatorSession}", not "${input.coordinatorSession}"`);
26293
26408
  }
26294
26409
  if (packageRecord.status !== "active") {
@@ -26303,7 +26418,7 @@ class OrchestrationService {
26303
26418
  }
26304
26419
  let route = this.resolveFrozenPackageMessageRoute(message);
26305
26420
  if (!route) {
26306
- route = this.snapshotCoordinatorDeliveryRoute(this.ensureCoordinatorRoutes(state)[input.coordinatorSession]) ?? null;
26421
+ route = this.snapshotCoordinatorDeliveryRoute(this.ensureCoordinatorRoutes(state)[stableCoordinatorSession(input.coordinatorSession)]) ?? null;
26307
26422
  if (route) {
26308
26423
  Object.assign(message, this.serializeFrozenDeliveryRoute(route));
26309
26424
  }
@@ -26372,7 +26487,7 @@ class OrchestrationService {
26372
26487
  if (this.isExternalCoordinatorSession(state, coordinatorSession)) {
26373
26488
  return null;
26374
26489
  }
26375
- const coordinatorState = state.orchestration.coordinatorQuestionState[coordinatorSession];
26490
+ const coordinatorState = state.orchestration.coordinatorQuestionState[stableCoordinatorSession(coordinatorSession)];
26376
26491
  const activePackageId = coordinatorState?.activePackageId;
26377
26492
  if (!activePackageId) {
26378
26493
  return null;
@@ -26512,7 +26627,7 @@ class OrchestrationService {
26512
26627
  const bindings = state.orchestration.workerBindings;
26513
26628
  const terminalTaskIds = [];
26514
26629
  for (const [taskId, task] of Object.entries(tasks)) {
26515
- if (task.coordinatorSession === coordinatorSession && this.isTerminalStatus(task.status) && task.reviewPending === undefined) {
26630
+ if (sameCoordinatorSession(task.coordinatorSession, coordinatorSession) && this.isTerminalStatus(task.status) && task.reviewPending === undefined) {
26516
26631
  terminalTaskIds.push(taskId);
26517
26632
  }
26518
26633
  }
@@ -26522,7 +26637,7 @@ class OrchestrationService {
26522
26637
  const remainingWorkerSessions = new Set(Object.values(tasks).map((task) => task.workerSession).filter(Boolean));
26523
26638
  let removedBindings = 0;
26524
26639
  for (const [workerSession, binding] of Object.entries(bindings)) {
26525
- if (binding.coordinatorSession !== coordinatorSession) {
26640
+ if (!sameCoordinatorSession(binding.coordinatorSession, coordinatorSession)) {
26526
26641
  continue;
26527
26642
  }
26528
26643
  if (!remainingWorkerSessions.has(workerSession)) {
@@ -26542,16 +26657,17 @@ class OrchestrationService {
26542
26657
  }
26543
26658
  async listSessionBlockingTasks(transportSession) {
26544
26659
  const state = await this.deps.loadState();
26545
- return Object.values(state.orchestration.tasks).filter((task) => (!this.isTerminalStatus(task.status) || task.reviewPending !== undefined) && (task.coordinatorSession === transportSession || task.workerSession === transportSession)).map((task) => ({ ...task }));
26660
+ return Object.values(state.orchestration.tasks).filter((task) => (!this.isTerminalStatus(task.status) || task.reviewPending !== undefined) && (sameCoordinatorSession(task.coordinatorSession, transportSession) || task.workerSession !== undefined && sameCoordinatorSession(task.workerSession, transportSession))).map((task) => ({ ...task }));
26546
26661
  }
26547
26662
  async purgeSessionReferences(transportSession) {
26548
26663
  return await this.mutate(async () => {
26549
26664
  const state = await this.deps.loadState();
26665
+ const sessionIdentity = stableCoordinatorSession(transportSession);
26550
26666
  const tasks = state.orchestration.tasks;
26551
26667
  const bindings = state.orchestration.workerBindings;
26552
26668
  const removedTaskIds = [];
26553
26669
  for (const [taskId, task] of Object.entries(tasks)) {
26554
- if (this.isTerminalStatus(task.status) && task.reviewPending === undefined && (task.coordinatorSession === transportSession || task.workerSession === transportSession)) {
26670
+ if (this.isTerminalStatus(task.status) && task.reviewPending === undefined && (sameCoordinatorSession(task.coordinatorSession, transportSession) || task.workerSession !== undefined && sameCoordinatorSession(task.workerSession, transportSession))) {
26555
26671
  removedTaskIds.push(taskId);
26556
26672
  }
26557
26673
  }
@@ -26561,14 +26677,14 @@ class OrchestrationService {
26561
26677
  const remainingWorkerSessions = new Set(Object.values(tasks).map((task) => task.workerSession).filter(Boolean));
26562
26678
  let removedBindings = 0;
26563
26679
  for (const [workerSession, binding] of Object.entries(bindings)) {
26564
- const shouldPurgeBinding = workerSession === transportSession || binding.coordinatorSession === transportSession;
26680
+ const shouldPurgeBinding = sameCoordinatorSession(workerSession, transportSession) || sameCoordinatorSession(binding.coordinatorSession, transportSession);
26565
26681
  if (shouldPurgeBinding && !remainingWorkerSessions.has(workerSession)) {
26566
26682
  delete bindings[workerSession];
26567
26683
  removedBindings += 1;
26568
26684
  }
26569
26685
  }
26570
- const removedEmptyGroups = this.removeEmptyGroupsForCoordinator(state, transportSession);
26571
- const removedCoordinatorMetadata = this.removeCoordinatorMetadataIfUnused(state, transportSession);
26686
+ const removedEmptyGroups = this.removeEmptyGroupsForCoordinator(state, sessionIdentity);
26687
+ const removedCoordinatorMetadata = this.removeCoordinatorMetadataIfUnused(state, sessionIdentity);
26572
26688
  if (removedTaskIds.length > 0 || removedBindings > 0 || removedEmptyGroups || removedCoordinatorMetadata) {
26573
26689
  await this.deps.saveState(state);
26574
26690
  }
@@ -26578,106 +26694,28 @@ class OrchestrationService {
26578
26694
  };
26579
26695
  });
26580
26696
  }
26581
- async purgeExpiredResetCoordinators(input) {
26582
- try {
26583
- if (!Number.isFinite(input.cutoffDays) || input.cutoffDays < 0) {
26584
- throw new Error(`cutoffDays must be a non-negative number, got ${String(input.cutoffDays)}`);
26585
- }
26586
- const result = await this.mutate(async () => {
26587
- const state = await this.deps.loadState();
26588
- const candidates = this.collectResetCoordinatorCandidates(state);
26589
- const activeTransportSessions = new Set(Object.values(state.sessions).map((session3) => session3.transport_session));
26590
- const MS_PER_DAY = 24 * 60 * 60 * 1000;
26591
- const cutoffMs = input.cutoffDays * MS_PER_DAY;
26592
- const nowMs = this.deps.now().getTime();
26593
- let purgedCoordinators = 0;
26594
- const removed = {
26595
- tasks: 0,
26596
- workerBindings: 0,
26597
- groups: 0,
26598
- coordinatorRoutes: 0,
26599
- humanQuestionPackages: 0,
26600
- coordinatorQuestionState: 0
26601
- };
26602
- for (const coordinatorSession of candidates) {
26603
- if (activeTransportSessions.has(coordinatorSession)) {
26604
- continue;
26605
- }
26606
- const activityAtMs = this.resolveResetCoordinatorActivityAtMs(state, coordinatorSession);
26607
- if (activityAtMs === null) {
26608
- continue;
26609
- }
26610
- if (nowMs - activityAtMs <= cutoffMs) {
26611
- continue;
26612
- }
26613
- const delta = this.cascadeRemoveCoordinatorRecords(state, coordinatorSession);
26614
- const changed = delta.tasks > 0 || delta.workerBindings > 0 || delta.groups > 0 || delta.coordinatorRoutes > 0 || delta.humanQuestionPackages > 0 || delta.coordinatorQuestionState > 0;
26615
- if (!changed) {
26616
- continue;
26617
- }
26618
- purgedCoordinators += 1;
26619
- removed.tasks += delta.tasks;
26620
- removed.workerBindings += delta.workerBindings;
26621
- removed.groups += delta.groups;
26622
- removed.coordinatorRoutes += delta.coordinatorRoutes;
26623
- removed.humanQuestionPackages += delta.humanQuestionPackages;
26624
- removed.coordinatorQuestionState += delta.coordinatorQuestionState;
26625
- }
26626
- const removedAny = removed.tasks > 0 || removed.workerBindings > 0 || removed.groups > 0 || removed.coordinatorRoutes > 0 || removed.humanQuestionPackages > 0 || removed.coordinatorQuestionState > 0;
26627
- if (removedAny) {
26628
- await this.deps.saveState(state);
26629
- }
26630
- return {
26631
- candidates: candidates.length,
26632
- purgedCoordinators,
26633
- removed
26634
- };
26635
- });
26636
- if (this.deps.logger) {
26637
- this.deps.logger.info("orchestration.reset_gc.completed", "reset coordinator gc completed", {
26638
- trigger: input.trigger,
26639
- cutoffDays: input.cutoffDays,
26640
- candidates: result.candidates,
26641
- purgedCoordinators: result.purgedCoordinators,
26642
- deletedCounts: result.removed
26643
- });
26644
- }
26645
- return result;
26646
- } catch (error2) {
26647
- const logger2 = this.deps.logger;
26648
- if (logger2) {
26649
- const message = error2 instanceof Error ? error2.message : String(error2);
26650
- logger2.error("orchestration.reset_gc.failed", "reset coordinator gc failed", {
26651
- trigger: input.trigger,
26652
- cutoffDays: input.cutoffDays,
26653
- message
26654
- });
26655
- }
26656
- throw error2;
26657
- }
26658
- }
26659
26697
  async listPendingCoordinatorResults(coordinatorSession) {
26660
26698
  const state = await this.deps.loadState();
26661
26699
  if (this.isExternalCoordinatorSession(state, coordinatorSession)) {
26662
26700
  return [];
26663
26701
  }
26664
- return Object.values(state.orchestration.tasks).filter((task) => task.coordinatorSession === coordinatorSession && this.canInjectTaskIntoCoordinator(state, task) && (task.injectionPending === true || task.coordinatorInjectedAt === undefined)).sort((left, right) => left.updatedAt.localeCompare(right.updatedAt)).map((task) => ({ ...task }));
26702
+ return Object.values(state.orchestration.tasks).filter((task) => sameCoordinatorSession(task.coordinatorSession, coordinatorSession) && this.canInjectTaskIntoCoordinator(state, task) && (task.injectionPending === true || task.coordinatorInjectedAt === undefined)).sort((left, right) => left.updatedAt.localeCompare(right.updatedAt)).map((task) => ({ ...task }));
26665
26703
  }
26666
26704
  async listPendingCoordinatorBlockers(coordinatorSession) {
26667
26705
  const state = await this.deps.loadState();
26668
26706
  if (this.isExternalCoordinatorSession(state, coordinatorSession)) {
26669
26707
  return [];
26670
26708
  }
26671
- const coordinatorState = state.orchestration.coordinatorQuestionState[coordinatorSession];
26709
+ const coordinatorState = state.orchestration.coordinatorQuestionState[stableCoordinatorSession(coordinatorSession)];
26672
26710
  const hiddenQueuedQuestionKeys = coordinatorState?.activePackageId ? new Set((coordinatorState.queuedQuestions ?? []).map((entry) => `${entry.taskId}:${entry.questionId}`)) : null;
26673
- return Object.values(state.orchestration.tasks).filter((task) => task.coordinatorSession === coordinatorSession && task.status === "blocked" && task.openQuestion?.status === "open" && !hiddenQueuedQuestionKeys?.has(`${task.taskId}:${task.openQuestion.questionId}`)).sort((left, right) => left.updatedAt.localeCompare(right.updatedAt)).map((task) => ({ ...task }));
26711
+ return Object.values(state.orchestration.tasks).filter((task) => sameCoordinatorSession(task.coordinatorSession, coordinatorSession) && task.status === "blocked" && task.openQuestion?.status === "open" && !hiddenQueuedQuestionKeys?.has(`${task.taskId}:${task.openQuestion.questionId}`)).sort((left, right) => left.updatedAt.localeCompare(right.updatedAt)).map((task) => ({ ...task }));
26674
26712
  }
26675
26713
  async listContestedCoordinatorResults(coordinatorSession) {
26676
26714
  const state = await this.deps.loadState();
26677
26715
  if (this.isExternalCoordinatorSession(state, coordinatorSession)) {
26678
26716
  return [];
26679
26717
  }
26680
- return Object.values(state.orchestration.tasks).filter((task) => task.coordinatorSession === coordinatorSession && task.reviewPending !== undefined).sort((left, right) => left.updatedAt.localeCompare(right.updatedAt)).map((task) => ({ ...task }));
26718
+ return Object.values(state.orchestration.tasks).filter((task) => sameCoordinatorSession(task.coordinatorSession, coordinatorSession) && task.reviewPending !== undefined).sort((left, right) => left.updatedAt.localeCompare(right.updatedAt)).map((task) => ({ ...task }));
26681
26719
  }
26682
26720
  async listPendingCoordinatorGroups(coordinatorSession) {
26683
26721
  const state = await this.deps.loadState();
@@ -26686,7 +26724,7 @@ class OrchestrationService {
26686
26724
  }
26687
26725
  const groups = this.ensureGroups(state);
26688
26726
  const tasks = Object.values(state.orchestration.tasks);
26689
- return Object.values(groups).filter((group) => group.coordinatorSession === coordinatorSession).filter((group) => {
26727
+ return Object.values(groups).filter((group) => sameCoordinatorSession(group.coordinatorSession, coordinatorSession)).filter((group) => {
26690
26728
  const groupTasks = tasks.filter((task) => task.groupId === group.groupId);
26691
26729
  return this.canInjectGroupIntoCoordinator(state, group.groupId, groupTasks);
26692
26730
  }).sort((left, right) => left.updatedAt.localeCompare(right.updatedAt)).map((group) => ({ ...group }));
@@ -26901,7 +26939,7 @@ class OrchestrationService {
26901
26939
  if (input.sourceHandle !== undefined && task.sourceHandle !== input.sourceHandle) {
26902
26940
  throw new Error(`task "${input.taskId}" belongs to source "${task.sourceHandle}", not "${input.sourceHandle}"`);
26903
26941
  }
26904
- if (input.coordinatorSession !== undefined && task.coordinatorSession !== input.coordinatorSession) {
26942
+ if (input.coordinatorSession !== undefined && !sameCoordinatorSession(task.coordinatorSession, input.coordinatorSession)) {
26905
26943
  throw new Error(`task "${input.taskId}" belongs to coordinator "${task.coordinatorSession}", not "${input.coordinatorSession}"`);
26906
26944
  }
26907
26945
  if (this.isTerminalStatus(task.status)) {
@@ -27328,11 +27366,11 @@ class OrchestrationService {
27328
27366
  ...binding.cwd ? { cwd: binding.cwd } : {}
27329
27367
  };
27330
27368
  }
27331
- const coordinatorSession = Object.values(state.sessions).find((session3) => session3.transport_session === sourceHandle);
27369
+ const coordinatorSession = Object.values(state.sessions).find((session3) => sameCoordinatorSession(session3.transport_session, sourceHandle));
27332
27370
  if (coordinatorSession) {
27333
27371
  return {
27334
27372
  sourceKind: "coordinator",
27335
- coordinatorSession: sourceHandle,
27373
+ coordinatorSession: stableCoordinatorSession(sourceHandle),
27336
27374
  workspace: coordinatorSession.workspace
27337
27375
  };
27338
27376
  }
@@ -27370,7 +27408,7 @@ class OrchestrationService {
27370
27408
  if (role && policy.allowedAgentRequestRoles.length > 0 && !policy.allowedAgentRequestRoles.includes(role)) {
27371
27409
  throw new Error(`role "${role}" is not allowed for agent-requested delegation`);
27372
27410
  }
27373
- const outstandingRequests = Object.values(state.orchestration.tasks).filter((task) => task.coordinatorSession === coordinatorSession && task.sourceKind !== "human" && (task.status === "needs_confirmation" || task.status === "running" || task.status === "queued"));
27411
+ const outstandingRequests = Object.values(state.orchestration.tasks).filter((task) => sameCoordinatorSession(task.coordinatorSession, coordinatorSession) && task.sourceKind !== "human" && (task.status === "needs_confirmation" || task.status === "running" || task.status === "queued"));
27374
27412
  if (outstandingRequests.length >= policy.maxPendingAgentRequestsPerCoordinator) {
27375
27413
  throw new Error("agent-requested delegation quota exceeded for this coordinator");
27376
27414
  }
@@ -27474,13 +27512,13 @@ class OrchestrationService {
27474
27512
  if (!filter) {
27475
27513
  return true;
27476
27514
  }
27477
- return (filter.sourceHandle === undefined || task.sourceHandle === filter.sourceHandle) && (filter.coordinatorSession === undefined || task.coordinatorSession === filter.coordinatorSession) && (filter.workspace === undefined || task.workspace === filter.workspace) && (filter.targetAgent === undefined || task.targetAgent === filter.targetAgent) && (filter.role === undefined || task.role === filter.role) && (filter.status === undefined || task.status === filter.status);
27515
+ return (filter.sourceHandle === undefined || task.sourceHandle === filter.sourceHandle) && (filter.coordinatorSession === undefined || sameCoordinatorSession(task.coordinatorSession, filter.coordinatorSession)) && (filter.workspace === undefined || task.workspace === filter.workspace) && (filter.targetAgent === undefined || task.targetAgent === filter.targetAgent) && (filter.role === undefined || task.role === filter.role) && (filter.status === undefined || task.status === filter.status);
27478
27516
  }
27479
27517
  isTerminalStatus(status) {
27480
27518
  return status === "completed" || status === "failed" || status === "cancelled";
27481
27519
  }
27482
27520
  assertCoordinatorOwnership(task, coordinatorSession) {
27483
- if (task.coordinatorSession !== coordinatorSession) {
27521
+ if (!sameCoordinatorSession(task.coordinatorSession, coordinatorSession)) {
27484
27522
  throw new Error(`task "${task.taskId}" belongs to coordinator "${task.coordinatorSession}", not "${coordinatorSession}"`);
27485
27523
  }
27486
27524
  }
@@ -27493,7 +27531,7 @@ class OrchestrationService {
27493
27531
  if (!group) {
27494
27532
  throw new Error(`group "${groupId}" does not exist`);
27495
27533
  }
27496
- if (group.coordinatorSession !== coordinatorSession) {
27534
+ if (!sameCoordinatorSession(group.coordinatorSession, coordinatorSession)) {
27497
27535
  throw new Error(`group "${groupId}" belongs to coordinator "${group.coordinatorSession}", not "${coordinatorSession}"`);
27498
27536
  }
27499
27537
  }
@@ -27504,13 +27542,14 @@ class OrchestrationService {
27504
27542
  return state.orchestration.humanQuestionPackages;
27505
27543
  }
27506
27544
  ensureCoordinatorQuestionState(state, coordinatorSession) {
27545
+ const key = stableCoordinatorSession(coordinatorSession);
27507
27546
  if (!("coordinatorQuestionState" in state.orchestration) || !state.orchestration.coordinatorQuestionState) {
27508
27547
  state.orchestration.coordinatorQuestionState = {};
27509
27548
  }
27510
- state.orchestration.coordinatorQuestionState[coordinatorSession] ??= {
27549
+ state.orchestration.coordinatorQuestionState[key] ??= {
27511
27550
  queuedQuestions: []
27512
27551
  };
27513
- return state.orchestration.coordinatorQuestionState[coordinatorSession];
27552
+ return state.orchestration.coordinatorQuestionState[key];
27514
27553
  }
27515
27554
  ensureCoordinatorRoutes(state) {
27516
27555
  if (!("coordinatorRoutes" in state.orchestration) || !state.orchestration.coordinatorRoutes) {
@@ -27691,7 +27730,7 @@ class OrchestrationService {
27691
27730
  const referencedGroupIds = new Set(Object.values(state.orchestration.tasks).map((task) => task.groupId).filter((groupId) => typeof groupId === "string"));
27692
27731
  let removedAny = false;
27693
27732
  for (const [groupId, group] of Object.entries(groups)) {
27694
- if (group.coordinatorSession !== coordinatorSession) {
27733
+ if (!sameCoordinatorSession(group.coordinatorSession, coordinatorSession)) {
27695
27734
  continue;
27696
27735
  }
27697
27736
  if (!referencedGroupIds.has(groupId)) {
@@ -27702,125 +27741,30 @@ class OrchestrationService {
27702
27741
  return removedAny;
27703
27742
  }
27704
27743
  removeCoordinatorMetadataIfUnused(state, coordinatorSession) {
27705
- const hasCoordinatorTasks = Object.values(state.orchestration.tasks).some((task) => task.coordinatorSession === coordinatorSession);
27706
- const hasCoordinatorBindings = Object.values(state.orchestration.workerBindings).some((binding) => binding.coordinatorSession === coordinatorSession);
27744
+ const key = stableCoordinatorSession(coordinatorSession);
27745
+ const hasCoordinatorTasks = Object.values(state.orchestration.tasks).some((task) => sameCoordinatorSession(task.coordinatorSession, coordinatorSession));
27746
+ const hasCoordinatorBindings = Object.values(state.orchestration.workerBindings).some((binding) => sameCoordinatorSession(binding.coordinatorSession, coordinatorSession));
27707
27747
  if (hasCoordinatorTasks || hasCoordinatorBindings) {
27708
27748
  return false;
27709
27749
  }
27710
27750
  let removedAny = false;
27711
27751
  const packages = this.ensureHumanQuestionPackages(state);
27712
27752
  for (const [packageId, packageRecord] of Object.entries(packages)) {
27713
- if (packageRecord.coordinatorSession === coordinatorSession) {
27753
+ if (sameCoordinatorSession(packageRecord.coordinatorSession, coordinatorSession)) {
27714
27754
  delete packages[packageId];
27715
27755
  removedAny = true;
27716
27756
  }
27717
27757
  }
27718
- if (state.orchestration.coordinatorQuestionState?.[coordinatorSession] !== undefined) {
27719
- delete state.orchestration.coordinatorQuestionState[coordinatorSession];
27758
+ if (state.orchestration.coordinatorQuestionState?.[key] !== undefined) {
27759
+ delete state.orchestration.coordinatorQuestionState[key];
27720
27760
  removedAny = true;
27721
27761
  }
27722
- if (state.orchestration.coordinatorRoutes?.[coordinatorSession] !== undefined) {
27723
- delete state.orchestration.coordinatorRoutes[coordinatorSession];
27762
+ if (state.orchestration.coordinatorRoutes?.[key] !== undefined) {
27763
+ delete state.orchestration.coordinatorRoutes[key];
27724
27764
  removedAny = true;
27725
27765
  }
27726
27766
  return removedAny;
27727
27767
  }
27728
- isResetCoordinatorSession(coordinatorSession) {
27729
- return coordinatorSession.includes(":reset-");
27730
- }
27731
- collectResetCoordinatorCandidates(state) {
27732
- const candidates = new Set;
27733
- for (const coordinatorSession of Object.keys(state.orchestration.coordinatorRoutes ?? {})) {
27734
- if (this.isResetCoordinatorSession(coordinatorSession)) {
27735
- candidates.add(coordinatorSession);
27736
- }
27737
- }
27738
- for (const task of Object.values(state.orchestration.tasks ?? {})) {
27739
- if (this.isResetCoordinatorSession(task.coordinatorSession)) {
27740
- candidates.add(task.coordinatorSession);
27741
- }
27742
- }
27743
- return [...candidates];
27744
- }
27745
- parseDateMs(value) {
27746
- if (!value) {
27747
- return null;
27748
- }
27749
- const ms = new Date(value).getTime();
27750
- return Number.isFinite(ms) ? ms : null;
27751
- }
27752
- resolveResetCoordinatorActivityAtMs(state, coordinatorSession) {
27753
- const routeUpdatedAt = state.orchestration.coordinatorRoutes?.[coordinatorSession]?.updatedAt;
27754
- const routeMs = this.parseDateMs(routeUpdatedAt);
27755
- let tasksMs = null;
27756
- for (const task of Object.values(state.orchestration.tasks ?? {})) {
27757
- if (task.coordinatorSession !== coordinatorSession) {
27758
- continue;
27759
- }
27760
- const candidate = this.parseDateMs(task.updatedAt);
27761
- if (candidate === null) {
27762
- continue;
27763
- }
27764
- tasksMs = tasksMs === null ? candidate : Math.max(tasksMs, candidate);
27765
- }
27766
- if (routeMs === null && tasksMs === null) {
27767
- return null;
27768
- }
27769
- if (routeMs === null) {
27770
- return tasksMs;
27771
- }
27772
- if (tasksMs === null) {
27773
- return routeMs;
27774
- }
27775
- return Math.max(routeMs, tasksMs);
27776
- }
27777
- cascadeRemoveCoordinatorRecords(state, coordinatorSession) {
27778
- const removed = {
27779
- tasks: 0,
27780
- workerBindings: 0,
27781
- groups: 0,
27782
- coordinatorRoutes: 0,
27783
- humanQuestionPackages: 0,
27784
- coordinatorQuestionState: 0
27785
- };
27786
- const tasks = state.orchestration.tasks;
27787
- for (const [taskId, task] of Object.entries(tasks ?? {})) {
27788
- if (task.coordinatorSession === coordinatorSession) {
27789
- delete tasks[taskId];
27790
- removed.tasks += 1;
27791
- }
27792
- }
27793
- const workerBindings = state.orchestration.workerBindings;
27794
- for (const [workerSession, binding] of Object.entries(workerBindings ?? {})) {
27795
- if (binding.coordinatorSession === coordinatorSession) {
27796
- delete workerBindings[workerSession];
27797
- removed.workerBindings += 1;
27798
- }
27799
- }
27800
- const groups = this.ensureGroups(state);
27801
- for (const [groupId, group] of Object.entries(groups ?? {})) {
27802
- if (group.coordinatorSession === coordinatorSession) {
27803
- delete groups[groupId];
27804
- removed.groups += 1;
27805
- }
27806
- }
27807
- if (state.orchestration.coordinatorRoutes?.[coordinatorSession] !== undefined) {
27808
- delete state.orchestration.coordinatorRoutes[coordinatorSession];
27809
- removed.coordinatorRoutes += 1;
27810
- }
27811
- const packages = this.ensureHumanQuestionPackages(state);
27812
- for (const [packageId, packageRecord] of Object.entries(packages ?? {})) {
27813
- if (packageRecord.coordinatorSession === coordinatorSession) {
27814
- delete packages[packageId];
27815
- removed.humanQuestionPackages += 1;
27816
- }
27817
- }
27818
- if (state.orchestration.coordinatorQuestionState?.[coordinatorSession] !== undefined) {
27819
- delete state.orchestration.coordinatorQuestionState[coordinatorSession];
27820
- removed.coordinatorQuestionState += 1;
27821
- }
27822
- return removed;
27823
- }
27824
27768
  bumpGroupUpdated(state, groupId, now) {
27825
27769
  if (!groupId) {
27826
27770
  return;
@@ -27994,7 +27938,7 @@ class OrchestrationService {
27994
27938
  }
27995
27939
  const validQueuedQuestions = coordinatorState.queuedQuestions.filter((entry) => {
27996
27940
  const task = state.orchestration.tasks[entry.taskId];
27997
- return task?.coordinatorSession === coordinatorSession && task.status === "blocked" && task.openQuestion?.status === "open" && task.openQuestion.questionId === entry.questionId;
27941
+ return task !== undefined && sameCoordinatorSession(task.coordinatorSession, coordinatorSession) && task.status === "blocked" && task.openQuestion?.status === "open" && task.openQuestion.questionId === entry.questionId;
27998
27942
  });
27999
27943
  if (validQueuedQuestions.length !== coordinatorState.queuedQuestions.length) {
28000
27944
  coordinatorState.queuedQuestions = validQueuedQuestions;
@@ -28483,7 +28427,7 @@ async function createScheduledTaskFromRoute(input, deps) {
28483
28427
  if (coordinatorSession.length === 0) {
28484
28428
  throw new Error("coordinatorSession must be a non-empty string");
28485
28429
  }
28486
- const route = deps.state.orchestration.coordinatorRoutes[coordinatorSession];
28430
+ const route = deps.state.orchestration.coordinatorRoutes[stableCoordinatorSession(coordinatorSession)];
28487
28431
  if (!route) {
28488
28432
  throw new Error(`no chat route is recorded for coordinator session "${coordinatorSession}"`);
28489
28433
  }
@@ -28510,7 +28454,7 @@ async function createScheduledTaskFromRoute(input, deps) {
28510
28454
  if (!session3) {
28511
28455
  throw new Error(`session "${route.sessionAlias}" recorded for coordinator session "${coordinatorSession}" was not found`);
28512
28456
  }
28513
- if (session3.transportSession !== coordinatorSession) {
28457
+ if (!sameCoordinatorSession(session3.transportSession, coordinatorSession)) {
28514
28458
  throw new Error(`session "${route.sessionAlias}" is no longer attached to coordinator session "${coordinatorSession}"`);
28515
28459
  }
28516
28460
  const executeAt = parseRouteScheduledTime(input.timeText, deps.now?.() ?? new Date);
@@ -28576,7 +28520,7 @@ function resolveOwnedCoordinatorRoute(coordinatorSession, state, label) {
28576
28520
  if (session3.length === 0) {
28577
28521
  throw new Error("coordinatorSession must be a non-empty string");
28578
28522
  }
28579
- const route = state.orchestration.coordinatorRoutes[session3];
28523
+ const route = state.orchestration.coordinatorRoutes[stableCoordinatorSession(session3)];
28580
28524
  if (!route) {
28581
28525
  throw new Error(`no chat route is recorded for coordinator session "${session3}"`);
28582
28526
  }
@@ -28668,9 +28612,10 @@ class SessionService {
28668
28612
  return this.state.chat_contexts[chatKey]?.current_session;
28669
28613
  }
28670
28614
  async getPreferredSessionForTransport(transportSession) {
28671
- const matches = Object.values(this.state.sessions).filter((session3) => session3.transport_session === transportSession).sort((left, right) => right.last_used_at.localeCompare(left.last_used_at));
28672
- const expectedAlias = transportSession.split(":").at(-1);
28673
- const expectedWorkspace = transportSession.split(":")[0];
28615
+ const target = stableCoordinatorSession(transportSession);
28616
+ const matches = Object.values(this.state.sessions).filter((session3) => stableCoordinatorSession(session3.transport_session) === target).sort((left, right) => right.last_used_at.localeCompare(left.last_used_at));
28617
+ const expectedAlias = target.split(":").at(-1);
28618
+ const expectedWorkspace = target.split(":")[0];
28674
28619
  const preferred = matches.find((session3) => session3.alias === expectedAlias && session3.workspace === expectedWorkspace) ?? matches[0];
28675
28620
  return preferred ? this.toResolvedSession(preferred) : null;
28676
28621
  }
@@ -29175,7 +29120,7 @@ class DebouncedStateStore {
29175
29120
  }
29176
29121
 
29177
29122
  // src/commands/command-hints.ts
29178
- function listWeacpxCommandHints() {
29123
+ function listXacpxCommandHints() {
29179
29124
  const hints3 = [{ name: "/help", description: t().hints.helpDescription }];
29180
29125
  for (const topic of listHelpTopics()) {
29181
29126
  const name = PRIMARY_COMMAND_BY_TOPIC[topic.topic];
@@ -29222,7 +29167,6 @@ async function runConsole(paths, deps) {
29222
29167
  let runtime = null;
29223
29168
  let consumerLock;
29224
29169
  let heartbeatTimer = null;
29225
- let gcResetTimer = null;
29226
29170
  let consumerLockAcquired = false;
29227
29171
  let daemonRuntimeStarted = false;
29228
29172
  const shutdownController = new AbortController;
@@ -29236,12 +29180,6 @@ async function runConsole(paths, deps) {
29236
29180
  if (deps.afterBuild) {
29237
29181
  await deps.afterBuild(runtime);
29238
29182
  }
29239
- try {
29240
- await runtime.orchestration.service.purgeExpiredResetCoordinators({
29241
- cutoffDays: 7,
29242
- trigger: "startup"
29243
- });
29244
- } catch {}
29245
29183
  try {
29246
29184
  await runtime.orchestration.service.reconcileParallelSlots();
29247
29185
  } catch (reconcileError) {
@@ -29297,6 +29235,7 @@ async function runConsole(paths, deps) {
29297
29235
  throw error2;
29298
29236
  }
29299
29237
  }
29238
+ await runtime.reapStaleQueueOwners();
29300
29239
  if (deps.beforeReady) {
29301
29240
  await deps.beforeReady(runtime);
29302
29241
  }
@@ -29310,10 +29249,6 @@ async function runConsole(paths, deps) {
29310
29249
  heartbeatTimer = setIntervalFn(() => {
29311
29250
  deps.daemonRuntime?.heartbeat().catch(() => {});
29312
29251
  }, deps.heartbeatIntervalMs ?? 30000);
29313
- const runtimeForGc = runtime;
29314
- gcResetTimer = setIntervalFn(() => {
29315
- runtimeForGc.orchestration.service.purgeExpiredResetCoordinators({ cutoffDays: 7, trigger: "interval" }).catch(() => {});
29316
- }, 86400000);
29317
29252
  }
29318
29253
  const channelStartPromise = deps.channels.startAll({
29319
29254
  agent: runtime.agent,
@@ -29323,8 +29258,8 @@ async function runConsole(paths, deps) {
29323
29258
  activeTurns: runtime.activeTurns,
29324
29259
  logger: runtime.logger,
29325
29260
  perfTracer: runtime.perfTracer,
29326
- commandHints: listWeacpxCommandHints(),
29327
- coreVersion: WEACPX_CORE_VERSION,
29261
+ commandHints: listXacpxCommandHints(),
29262
+ coreVersion: XACPX_CORE_VERSION,
29328
29263
  locale: getLocale()
29329
29264
  });
29330
29265
  channelStartPromise.catch(() => {});
@@ -29368,7 +29303,6 @@ async function runConsole(paths, deps) {
29368
29303
  signalHandler,
29369
29304
  clearIntervalFn,
29370
29305
  heartbeatTimer,
29371
- gcResetTimer,
29372
29306
  ...deps.daemonRuntime ? { daemonRuntime: deps.daemonRuntime } : {},
29373
29307
  runtime,
29374
29308
  consumerLock,
@@ -29394,9 +29328,6 @@ async function runCleanupSequence(input) {
29394
29328
  if (input.heartbeatTimer !== null) {
29395
29329
  input.clearIntervalFn(input.heartbeatTimer);
29396
29330
  }
29397
- if (input.gcResetTimer !== null) {
29398
- input.clearIntervalFn(input.gcResetTimer);
29399
- }
29400
29331
  if (input.daemonRuntime && input.runtime) {
29401
29332
  try {
29402
29333
  await input.runtime.orchestration.server.stop();
@@ -30016,6 +29947,10 @@ ${result.text}` : "" };
30016
29947
  async removeSession(session3) {
30017
29948
  await this.client.request("removeSession", this.toParams(session3));
30018
29949
  }
29950
+ async getAgentSessionId(session3) {
29951
+ const result = await this.client.request("getAgentSessionId", this.toParams(session3));
29952
+ return result.agentSessionId;
29953
+ }
30019
29954
  async hasSession(session3) {
30020
29955
  const result = await this.client.request("hasSession", this.toParams(session3));
30021
29956
  return result.exists;
@@ -30510,10 +30445,10 @@ import { spawn as spawn8 } from "node:child_process";
30510
30445
  import { readFile as readFile12, unlink } from "node:fs/promises";
30511
30446
  import { homedir as homedir8 } from "node:os";
30512
30447
  import { join as join17 } from "node:path";
30513
- function buildWeacpxMcpServerSpec(input) {
30514
- const { command, args } = splitCommandLine(input.weacpxCommand);
30448
+ function buildXacpxMcpServerSpec(input) {
30449
+ const { command, args } = splitCommandLine(input.xacpxCommand);
30515
30450
  return {
30516
- name: "weacpx",
30451
+ name: "xacpx",
30517
30452
  type: "stdio",
30518
30453
  command,
30519
30454
  args: [
@@ -30540,7 +30475,7 @@ function buildQueueOwnerPayload(input) {
30540
30475
 
30541
30476
  class AcpxQueueOwnerLauncher {
30542
30477
  acpxCommand;
30543
- weacpxCommand;
30478
+ xacpxCommand;
30544
30479
  spawnOwner;
30545
30480
  terminateOwner;
30546
30481
  baseEnv;
@@ -30549,7 +30484,7 @@ class AcpxQueueOwnerLauncher {
30549
30484
  launchLocks = new Map;
30550
30485
  constructor(options) {
30551
30486
  this.acpxCommand = options.acpxCommand;
30552
- this.weacpxCommand = options.weacpxCommand ?? resolveDefaultWeacpxCommand(options.baseEnv ?? process.env);
30487
+ this.xacpxCommand = options.xacpxCommand ?? resolveDefaultXacpxCommand(options.baseEnv ?? process.env);
30553
30488
  this.spawnOwner = options.spawnOwner ?? defaultQueueOwnerSpawner;
30554
30489
  this.terminateOwner = options.terminateOwner ?? createDefaultQueueOwnerTerminator(options.acpxCommand);
30555
30490
  this.baseEnv = options.baseEnv ?? process.env;
@@ -30577,8 +30512,8 @@ class AcpxQueueOwnerLauncher {
30577
30512
  nonInteractivePermissions: input.nonInteractivePermissions,
30578
30513
  ttlMs: this.ttlMs,
30579
30514
  maxQueueDepth: this.maxQueueDepth,
30580
- mcpServers: [buildWeacpxMcpServerSpec({
30581
- weacpxCommand: this.weacpxCommand,
30515
+ mcpServers: [buildXacpxMcpServerSpec({
30516
+ xacpxCommand: this.xacpxCommand,
30582
30517
  coordinatorSession: input.coordinatorSession,
30583
30518
  ...input.sourceHandle ? { sourceHandle: input.sourceHandle } : {}
30584
30519
  })]
@@ -30633,13 +30568,13 @@ function splitCommandLine(value) {
30633
30568
  current += "\\";
30634
30569
  }
30635
30570
  if (quote) {
30636
- throw new Error("weacpx MCP command has an unterminated quote");
30571
+ throw new Error("xacpx MCP command has an unterminated quote");
30637
30572
  }
30638
30573
  if (current.length > 0) {
30639
30574
  parts.push(current);
30640
30575
  }
30641
30576
  if (parts.length === 0) {
30642
- throw new Error("weacpx MCP command must not be empty");
30577
+ throw new Error("xacpx MCP command must not be empty");
30643
30578
  }
30644
30579
  return { command: parts[0], args: parts.slice(1) };
30645
30580
  }
@@ -30685,7 +30620,7 @@ function queueLockFilePath(sessionId) {
30685
30620
  function shortHash(value, length) {
30686
30621
  return createHash3("sha256").update(value).digest("hex").slice(0, length);
30687
30622
  }
30688
- function resolveDefaultWeacpxCommand(env) {
30623
+ function resolveDefaultXacpxCommand(env) {
30689
30624
  const cliCommand = coreEnv("CLI_COMMAND", env);
30690
30625
  if (cliCommand?.trim()) {
30691
30626
  return cliCommand.trim();
@@ -31036,8 +30971,9 @@ ${baseText}` : "" };
31036
30971
  try {
31037
30972
  const parsed = JSON.parse(result.stdout);
31038
30973
  const acpxRecordId = typeof parsed.acpxRecordId === "string" ? parsed.acpxRecordId : typeof parsed.id === "string" ? parsed.id : undefined;
30974
+ const agentSessionId = typeof parsed.agentSessionId === "string" ? parsed.agentSessionId : undefined;
31039
30975
  if (acpxRecordId) {
31040
- return { acpxRecordId };
30976
+ return { acpxRecordId, agentSessionId };
31041
30977
  }
31042
30978
  } catch {
31043
30979
  const firstLine = result.stdout.trim().split(/\r?\n/, 1)[0];
@@ -31047,6 +30983,10 @@ ${baseText}` : "" };
31047
30983
  }
31048
30984
  throw new Error("failed to resolve acpx session record id");
31049
30985
  }
30986
+ async getAgentSessionId(session3) {
30987
+ const record3 = await this.readSessionRecord(session3);
30988
+ return record3.agentSessionId;
30989
+ }
31050
30990
  async run(args, options) {
31051
30991
  const result = await this.runCommandWithTimeout(this.runCommand, args, options);
31052
30992
  if (result.code !== 0) {
@@ -31411,6 +31351,17 @@ var init_queue_owner_reaper = __esm(() => {
31411
31351
  });
31412
31352
 
31413
31353
  // src/transport/collect-reap-targets.ts
31354
+ function collectReapTargets(sessions, orchestration3, config4) {
31355
+ return [
31356
+ ...sessions.listAllResolvedSessions().map((session3) => ({
31357
+ agent: session3.agent,
31358
+ ...session3.agentCommand ? { agentCommand: session3.agentCommand } : {},
31359
+ cwd: session3.cwd,
31360
+ transportSession: session3.transportSession
31361
+ })),
31362
+ ...workerBindingReapTargets(orchestration3, config4)
31363
+ ];
31364
+ }
31414
31365
  function workerBindingReapTargets(orchestration3, config4) {
31415
31366
  const targets = [];
31416
31367
  for (const [workerSession, binding] of Object.entries(orchestration3.workerBindings)) {
@@ -32132,7 +32083,7 @@ async function buildApp(paths, deps = {}) {
32132
32083
  }
32133
32084
  },
32134
32085
  findReusableWorkerSession: async ({ coordinatorSession, workspace: workspace3, cwd, targetAgent, role }) => {
32135
- const binding = Object.entries(state.orchestration.workerBindings).find(([, current]) => current.ephemeral !== true && current.coordinatorSession === coordinatorSession && current.workspace === workspace3 && current.cwd === cwd && current.targetAgent === targetAgent && current.role === role);
32086
+ const binding = Object.entries(state.orchestration.workerBindings).find(([, current]) => current.ephemeral !== true && sameCoordinatorSession(current.coordinatorSession, coordinatorSession) && current.workspace === workspace3 && current.cwd === cwd && current.targetAgent === targetAgent && current.role === role);
32136
32087
  return binding?.[0] ?? null;
32137
32088
  },
32138
32089
  logger: logger2
@@ -32190,6 +32141,33 @@ async function buildApp(paths, deps = {}) {
32190
32141
  }),
32191
32142
  logger: logger2
32192
32143
  });
32144
+ const reapWarmQueueOwners = async (phase) => {
32145
+ try {
32146
+ const targets = collectReapTargets(sessions, state.orchestration, config4);
32147
+ if (targets.length === 0) {
32148
+ return;
32149
+ }
32150
+ const { terminated, attempted } = await reapQueueOwners(acpxCommand, targets, {
32151
+ onError: (target, error2) => {
32152
+ logger2.info("transport.queue_owner_reap.failed", "failed to reap queue owner", {
32153
+ phase,
32154
+ transport_session: target.transportSession,
32155
+ error: error2 instanceof Error ? error2.message : String(error2)
32156
+ }).catch(() => {});
32157
+ }
32158
+ });
32159
+ await logger2.info("transport.queue_owner_reap.completed", "reaped warm queue owners", {
32160
+ phase,
32161
+ terminated,
32162
+ attempted
32163
+ }).catch(() => {});
32164
+ } catch (err) {
32165
+ await logger2.error("transport.queue_owner_reap.error", "queue owner reap failed", {
32166
+ phase,
32167
+ error: err instanceof Error ? err.message : String(err)
32168
+ }).catch(() => {});
32169
+ }
32170
+ };
32193
32171
  return {
32194
32172
  agent: agent3,
32195
32173
  router: router3,
@@ -32210,41 +32188,14 @@ async function buildApp(paths, deps = {}) {
32210
32188
  service: scheduledService,
32211
32189
  scheduler: scheduledScheduler
32212
32190
  },
32191
+ reapStaleQueueOwners: () => reapWarmQueueOwners("startup"),
32213
32192
  dispose: async () => {
32214
32193
  scheduledScheduler.stop();
32215
32194
  if (progressHeartbeatInterval !== undefined) {
32216
32195
  clearInterval(progressHeartbeatInterval);
32217
32196
  }
32218
32197
  await Promise.allSettled([...pendingWorkerDispatches]);
32219
- try {
32220
- const targets = [
32221
- ...sessions.listAllResolvedSessions().map((session3) => ({
32222
- agent: session3.agent,
32223
- ...session3.agentCommand ? { agentCommand: session3.agentCommand } : {},
32224
- cwd: session3.cwd,
32225
- transportSession: session3.transportSession
32226
- })),
32227
- ...workerBindingReapTargets(state.orchestration, config4)
32228
- ];
32229
- if (targets.length > 0) {
32230
- const { terminated, attempted } = await reapQueueOwners(acpxCommand, targets, {
32231
- onError: (target, error2) => {
32232
- logger2.info("transport.queue_owner_reap.failed", "failed to reap queue owner on shutdown", {
32233
- transport_session: target.transportSession,
32234
- error: error2 instanceof Error ? error2.message : String(error2)
32235
- }).catch(() => {});
32236
- }
32237
- });
32238
- await logger2.info("transport.queue_owner_reap.completed", "reaped warm queue owners on shutdown", {
32239
- terminated,
32240
- attempted
32241
- }).catch(() => {});
32242
- }
32243
- } catch (err) {
32244
- await logger2.error("transport.queue_owner_reap.error", "queue owner reap failed during shutdown", {
32245
- error: err instanceof Error ? err.message : String(err)
32246
- }).catch(() => {});
32247
- }
32198
+ await reapWarmQueueOwners("shutdown");
32248
32199
  await debouncedStateStore.dispose();
32249
32200
  if ("dispose" in transport && typeof transport.dispose === "function") {
32250
32201
  await transport.dispose();
@@ -33583,7 +33534,7 @@ class DaemonRuntime {
33583
33534
  }
33584
33535
  }
33585
33536
 
33586
- // src/mcp/weacpx-mcp-server.ts
33537
+ // src/mcp/xacpx-mcp-server.ts
33587
33538
  import { stdin, stdout } from "node:process";
33588
33539
 
33589
33540
  // node_modules/@modelcontextprotocol/sdk/node_modules/zod/v4/core/core.js
@@ -45939,7 +45890,7 @@ class StdioServerTransport {
45939
45890
  }
45940
45891
  }
45941
45892
 
45942
- // src/mcp/weacpx-mcp-server.ts
45893
+ // src/mcp/xacpx-mcp-server.ts
45943
45894
  init_version();
45944
45895
 
45945
45896
  // src/mcp/resolve-endpoint.ts
@@ -45967,7 +45918,10 @@ function requireHome(env) {
45967
45918
  return home;
45968
45919
  }
45969
45920
 
45970
- // src/mcp/weacpx-mcp-tools.ts
45921
+ // src/mcp/xacpx-mcp-server.ts
45922
+ init_endpoint_probe();
45923
+
45924
+ // src/mcp/xacpx-mcp-tools.ts
45971
45925
  init_task_watch_timeouts();
45972
45926
  init_quota_errors();
45973
45927
  var taskStatusSchema = exports_external.enum([
@@ -45988,7 +45942,7 @@ var taskQuestionSchema = exports_external.object({
45988
45942
  taskId: exports_external.string().min(1),
45989
45943
  questionId: exports_external.string().min(1)
45990
45944
  }).strict();
45991
- function buildWeacpxMcpToolRegistry(input) {
45945
+ function buildXacpxMcpToolRegistry(input) {
45992
45946
  const { transport, coordinatorSession, sourceHandle, isExternalCoordinator, internalSessionTools, availableAgents } = input;
45993
45947
  const tools = [
45994
45948
  {
@@ -46146,7 +46100,7 @@ function buildWeacpxMcpToolRegistry(input) {
46146
46100
  }).strict(),
46147
46101
  handler: async (args) => await asToolResult(async () => {
46148
46102
  if (!sourceHandle || sourceHandle.trim().length === 0) {
46149
- throw new Error("worker_raise_question requires a bound sourceHandle; start mcp-stdio with --source-handle or WEACPX_SOURCE_HANDLE");
46103
+ throw new Error("worker_raise_question requires a bound sourceHandle; start mcp-stdio with --source-handle or XACPX_SOURCE_HANDLE");
46150
46104
  }
46151
46105
  const result = await transport.workerRaiseQuestion({
46152
46106
  sourceHandle,
@@ -46209,7 +46163,7 @@ function buildWeacpxMcpToolRegistry(input) {
46209
46163
  if (internalSessionTools && !isExternalCoordinator && !sourceHandle) {
46210
46164
  tools.push({
46211
46165
  name: "scheduled_create",
46212
- description: "Schedule a one-shot task to run a natural-language message at a future time, using the recorded chat route. By default — and like /later — the task runs in a FRESH TEMPORARY session (it snapshots the current agent and workspace but starts with brand-new history and is destroyed after running, so it does not pollute this conversation); the reply is still pushed back to this chat. Provide only timeText and message and OMIT mode to get this default. Routing, session, and account are resolved by weacpx.",
46166
+ description: "Schedule a one-shot task to run a natural-language message at a future time, using the recorded chat route. By default — and like /later — the task runs in a FRESH TEMPORARY session (it snapshots the current agent and workspace but starts with brand-new history and is destroyed after running, so it does not pollute this conversation); the reply is still pushed back to this chat. Provide only timeText and message and OMIT mode to get this default. Routing, session, and account are resolved by xacpx.",
46213
46167
  inputSchema: exports_external.object({
46214
46168
  timeText: exports_external.string().min(1).describe("Time expression, e.g. 'in 2h', '30分钟后', 'tomorrow 09:00', or '周五 09:00'."),
46215
46169
  message: exports_external.string().min(1).describe("Natural-language message to run at the scheduled time."),
@@ -46482,7 +46436,7 @@ function formatToolError(error2) {
46482
46436
  init_orchestration_ipc();
46483
46437
  init_task_watch_timeouts();
46484
46438
  import { randomUUID } from "node:crypto";
46485
- import { createConnection } from "node:net";
46439
+ import { createConnection as createConnection2 } from "node:net";
46486
46440
 
46487
46441
  class OrchestrationClient {
46488
46442
  endpoint;
@@ -46550,7 +46504,7 @@ class OrchestrationClient {
46550
46504
  async request(method, params, timeoutMs = this.timeoutMs) {
46551
46505
  const id = this.createId();
46552
46506
  return await new Promise((resolve, reject) => {
46553
- const socket = createConnection(this.endpoint.path);
46507
+ const socket = createConnection2(this.endpoint.path);
46554
46508
  let buffer = "";
46555
46509
  let settled = false;
46556
46510
  let timer;
@@ -46619,7 +46573,7 @@ function getWatchRequestTimeoutMs(watchTimeoutMs, defaultTimeoutMs) {
46619
46573
  return Math.max(defaultTimeoutMs, boundedWatchTimeoutMs + TASK_WATCH_RPC_TIMEOUT_PADDING_MS);
46620
46574
  }
46621
46575
 
46622
- // src/mcp/weacpx-mcp-transport.ts
46576
+ // src/mcp/xacpx-mcp-transport.ts
46623
46577
  function createOrchestrationTransport(endpoint, deps = {}) {
46624
46578
  const client = deps.client ?? new OrchestrationClient(endpoint);
46625
46579
  return {
@@ -46647,7 +46601,7 @@ function createOrchestrationTransport(endpoint, deps = {}) {
46647
46601
  workerRaiseQuestion: async (input) => {
46648
46602
  const sourceHandle = input.sourceHandle.trim();
46649
46603
  if (sourceHandle.length === 0) {
46650
- throw new Error("worker_raise_question requires a bound sourceHandle; start mcp-stdio with --source-handle or WEACPX_SOURCE_HANDLE");
46604
+ throw new Error("worker_raise_question requires a bound sourceHandle; start mcp-stdio with --source-handle or XACPX_SOURCE_HANDLE");
46651
46605
  }
46652
46606
  return await client.workerRaiseQuestion({
46653
46607
  taskId: input.taskId,
@@ -46681,11 +46635,11 @@ function createOrchestrationTransport(endpoint, deps = {}) {
46681
46635
  };
46682
46636
  }
46683
46637
 
46684
- // src/mcp/weacpx-mcp-server.ts
46638
+ // src/mcp/xacpx-mcp-server.ts
46685
46639
  var TASK_OPTIONS_CACHE_LIMIT = 1000;
46686
46640
  var TASKS_LIST_PAGE_SIZE = 100;
46687
46641
  var WATCH_TASKS_CACHE_LIMIT = 256;
46688
- var WEACPX_MCP_SERVER_INSTRUCTIONS = [
46642
+ var XACPX_MCP_SERVER_INSTRUCTIONS = [
46689
46643
  "Use these tools to orchestrate work across other agents under your coordinator session.",
46690
46644
  "",
46691
46645
  "Delegate with delegate_request (one task) or delegate_batch (several at once). Each returns a taskId and a status.",
@@ -46696,12 +46650,12 @@ var WEACPX_MCP_SERVER_INSTRUCTIONS = [
46696
46650
  "worker_raise_question is worker-side only — call it from inside a delegated task when you are blocked, not from the coordinator waiting on a delegation."
46697
46651
  ].join(`
46698
46652
  `);
46699
- function createWeacpxMcpServer(options) {
46653
+ function createXacpxMcpServer(options) {
46700
46654
  let getToolState;
46701
46655
  const taskOptionsById = new Map;
46702
46656
  const watchTasksById = new Map;
46703
46657
  const server = new Server({
46704
- name: "weacpx",
46658
+ name: "xacpx",
46705
46659
  version: readVersion()
46706
46660
  }, {
46707
46661
  capabilities: {
@@ -46712,8 +46666,8 @@ function createWeacpxMcpServer(options) {
46712
46666
  requests: { tools: { call: {} } }
46713
46667
  }
46714
46668
  },
46715
- instructions: WEACPX_MCP_SERVER_INSTRUCTIONS,
46716
- taskStore: createWeacpxTaskStore(async () => await getToolState(), taskOptionsById, watchTasksById)
46669
+ instructions: XACPX_MCP_SERVER_INSTRUCTIONS,
46670
+ taskStore: createXacpxTaskStore(async () => await getToolState(), taskOptionsById, watchTasksById)
46717
46671
  });
46718
46672
  let toolState = null;
46719
46673
  let toolStatePromise = null;
@@ -46726,7 +46680,7 @@ function createWeacpxMcpServer(options) {
46726
46680
  }
46727
46681
  toolStatePromise = resolveMcpIdentity(server, options).then((identity) => {
46728
46682
  if (!options.transport) {
46729
- throw new Error("weacpx MCP transport is not configured");
46683
+ throw new Error("xacpx MCP transport is not configured");
46730
46684
  }
46731
46685
  toolState = buildToolState({
46732
46686
  transport: options.transport,
@@ -46807,7 +46761,7 @@ function createWeacpxMcpServer(options) {
46807
46761
  return server;
46808
46762
  }
46809
46763
  function buildToolState(options) {
46810
- const tools = buildWeacpxMcpToolRegistry(options);
46764
+ const tools = buildXacpxMcpToolRegistry(options);
46811
46765
  return {
46812
46766
  tools,
46813
46767
  toolMap: new Map(tools.map((tool) => [tool.name, tool])),
@@ -46966,10 +46920,10 @@ function renderWatchMcpTaskResult(result, watchTaskId) {
46966
46920
  structuredContent: { watchTaskId, ...result }
46967
46921
  };
46968
46922
  }
46969
- function createWeacpxTaskStore(resolveState, taskOptionsById, watchTasksById) {
46923
+ function createXacpxTaskStore(resolveState, taskOptionsById, watchTasksById) {
46970
46924
  return {
46971
46925
  createTask: async () => {
46972
- throw new Error("weacpx native MCP tasks are created by delegate_request");
46926
+ throw new Error("xacpx native MCP tasks are created by delegate_request");
46973
46927
  },
46974
46928
  getTask: async (taskId) => {
46975
46929
  const watchTask = watchTasksById.get(taskId);
@@ -46980,7 +46934,7 @@ function createWeacpxTaskStore(resolveState, taskOptionsById, watchTasksById) {
46980
46934
  return task ? toMcpTask(task, taskOptionsById.get(taskId)) : null;
46981
46935
  },
46982
46936
  storeTaskResult: async () => {
46983
- throw new Error("weacpx native MCP task results are stored by orchestration");
46937
+ throw new Error("xacpx native MCP task results are stored by orchestration");
46984
46938
  },
46985
46939
  getTaskResult: async (taskId) => {
46986
46940
  const watchTask = watchTasksById.get(taskId);
@@ -47004,7 +46958,7 @@ function createWeacpxTaskStore(resolveState, taskOptionsById, watchTasksById) {
47004
46958
  await state.transport.cancelTask({ coordinatorSession: state.coordinatorSession, taskId });
47005
46959
  return;
47006
46960
  }
47007
- throw new Error(`weacpx MCP task status is read-only (${status}${statusMessage ? `: ${statusMessage}` : ""})`);
46961
+ throw new Error(`xacpx MCP task status is read-only (${status}${statusMessage ? `: ${statusMessage}` : ""})`);
47008
46962
  },
47009
46963
  listTasks: async (cursor) => {
47010
46964
  const state = await resolveState();
@@ -47193,7 +47147,9 @@ function installMcpStdioShutdownHooks(options) {
47193
47147
  const setIntervalFn = options.setIntervalFn ?? ((callback, ms) => setInterval(callback, ms));
47194
47148
  const clearIntervalFn = options.clearIntervalFn ?? ((handle) => clearInterval(handle));
47195
47149
  const parentPid = options.parentPid ?? process.ppid;
47196
- const parentCheckIntervalMs = options.parentCheckIntervalMs ?? parseParentCheckIntervalMs(coreEnv("MCP_PARENT_CHECK_INTERVAL_MS"));
47150
+ const parentCheckIntervalMs = options.parentCheckIntervalMs ?? parseIntervalMs(coreEnv("MCP_PARENT_CHECK_INTERVAL_MS"), 5000);
47151
+ const endpointCheckIntervalMs = options.endpointCheckIntervalMs ?? parseIntervalMs(coreEnv("MCP_ENDPOINT_CHECK_INTERVAL_MS"), 1e4);
47152
+ const endpointFailureThreshold = options.endpointFailureThreshold ?? 3;
47197
47153
  let disposed = false;
47198
47154
  let triggered = false;
47199
47155
  const triggerShutdown = (reason, context) => {
@@ -47226,6 +47182,31 @@ function installMcpStdioShutdownHooks(options) {
47226
47182
  }, parentCheckIntervalMs);
47227
47183
  parentTimer.unref?.();
47228
47184
  }
47185
+ let endpointTimer;
47186
+ const probeEndpoint = options.probeEndpoint;
47187
+ if (probeEndpoint && endpointCheckIntervalMs > 0 && endpointFailureThreshold > 0) {
47188
+ let consecutiveDead = 0;
47189
+ let probing = false;
47190
+ const runEndpointCheck = async () => {
47191
+ if (disposed || triggered || probing)
47192
+ return;
47193
+ probing = true;
47194
+ try {
47195
+ if (await probeEndpoint()) {
47196
+ consecutiveDead = 0;
47197
+ return;
47198
+ }
47199
+ consecutiveDead += 1;
47200
+ if (consecutiveDead >= endpointFailureThreshold) {
47201
+ triggerShutdown("daemon_endpoint_dead", { consecutiveFailures: consecutiveDead });
47202
+ }
47203
+ } catch {} finally {
47204
+ probing = false;
47205
+ }
47206
+ };
47207
+ endpointTimer = setIntervalFn(runEndpointCheck, endpointCheckIntervalMs);
47208
+ endpointTimer.unref?.();
47209
+ }
47229
47210
  return () => {
47230
47211
  if (disposed)
47231
47212
  return;
@@ -47240,13 +47221,16 @@ function installMcpStdioShutdownHooks(options) {
47240
47221
  if (parentTimer) {
47241
47222
  clearIntervalFn(parentTimer);
47242
47223
  }
47224
+ if (endpointTimer) {
47225
+ clearIntervalFn(endpointTimer);
47226
+ }
47243
47227
  };
47244
47228
  }
47245
- function parseParentCheckIntervalMs(raw) {
47229
+ function parseIntervalMs(raw, fallback) {
47246
47230
  if (raw === undefined || raw.trim().length === 0)
47247
- return 5000;
47231
+ return fallback;
47248
47232
  const parsed = Number(raw);
47249
- return Number.isFinite(parsed) && parsed >= 0 ? parsed : 5000;
47233
+ return Number.isFinite(parsed) && parsed >= 0 ? parsed : fallback;
47250
47234
  }
47251
47235
  function errorContext(error2) {
47252
47236
  const record3 = error2;
@@ -47264,9 +47248,10 @@ function defaultIsProcessRunning3(pid) {
47264
47248
  return code !== "ESRCH";
47265
47249
  }
47266
47250
  }
47267
- async function runWeacpxMcpServer(options) {
47268
- const transport = options.transport ?? createOrchestrationTransport(options.endpoint ?? resolveDefaultOrchestrationEndpoint(process.env, process.platform));
47269
- const server = createWeacpxMcpServer({
47251
+ async function runXacpxMcpServer(options) {
47252
+ const endpoint = options.endpoint ?? resolveDefaultOrchestrationEndpoint(process.env, process.platform);
47253
+ const transport = options.transport ?? createOrchestrationTransport(endpoint);
47254
+ const server = createXacpxMcpServer({
47270
47255
  transport,
47271
47256
  ...options.coordinatorSession ? { coordinatorSession: options.coordinatorSession } : {},
47272
47257
  ...options.sourceHandle ? { sourceHandle: options.sourceHandle } : {},
@@ -47298,6 +47283,7 @@ async function runWeacpxMcpServer(options) {
47298
47283
  stdin,
47299
47284
  stdout,
47300
47285
  shutdown,
47286
+ probeEndpoint: () => canConnectToEndpoint(endpoint.path, 4000),
47301
47287
  onDiagnostic: options.onDiagnostic
47302
47288
  });
47303
47289
  await server.connect(stdio);
@@ -47330,7 +47316,6 @@ function sanitizeMcpClientName(input) {
47330
47316
  fallback: "mcp-host"
47331
47317
  });
47332
47318
  }
47333
-
47334
47319
  // src/mcp/parse-string-flag.ts
47335
47320
  function parseStringFlag(args, env, options) {
47336
47321
  let fromFlag = null;
@@ -47566,7 +47551,6 @@ async function handleUpdateCli(args, deps) {
47566
47551
  kind: "plugin",
47567
47552
  name: plugin.name,
47568
47553
  currentVersion: plugin.version,
47569
- pinned: Boolean(plugin.version),
47570
47554
  latestVersion: await latestOf(plugin.name)
47571
47555
  });
47572
47556
  }
@@ -47575,12 +47559,12 @@ async function handleUpdateCli(args, deps) {
47575
47559
  const target = targets[index];
47576
47560
  deps.print(`${index + 1}. ${formatTarget(target)}`);
47577
47561
  }
47578
- const unavailable = targets.filter((target) => !target.latestVersion || target.kind === "plugin" && !target.pinned);
47562
+ const unavailable = targets.filter((target) => !target.latestVersion);
47579
47563
  if (all && unavailable.length > 0) {
47580
47564
  deps.print(t().cliUpdate.unavailableAborted(unavailable.map((target) => target.name).join(", ")));
47581
47565
  return 1;
47582
47566
  }
47583
- const candidates = targets.filter((target) => target.latestVersion && (target.kind !== "plugin" || target.pinned) && (target.successorPackage ? true : target.currentVersion !== target.latestVersion));
47567
+ const candidates = targets.filter((target) => target.latestVersion && (target.successorPackage ? true : target.currentVersion !== target.latestVersion));
47584
47568
  const selected = await selectTargets(targets, candidates, { all, explicitTarget: explicitTargets[0], deps });
47585
47569
  if (!selected.ok) {
47586
47570
  deps.print(selected.message);
@@ -47673,8 +47657,6 @@ async function selectTargets(targets, candidates, input) {
47673
47657
  return { ok: false, message: t().cliUpdate.targetNotFound(input.explicitTarget), exitCode: 1 };
47674
47658
  if (!target.latestVersion)
47675
47659
  return { ok: false, message: t().cliUpdate.targetVersionUnknown(target.name), exitCode: 1 };
47676
- if (target.kind === "plugin" && !target.pinned)
47677
- return { ok: false, message: t().cliUpdate.targetNotPinned(target.name), exitCode: 1 };
47678
47660
  if (!target.successorPackage && target.currentVersion === target.latestVersion)
47679
47661
  return { ok: true, targets: [] };
47680
47662
  return { ok: true, targets: [target] };
@@ -47698,8 +47680,6 @@ async function selectTargets(targets, candidates, input) {
47698
47680
  const target = targets[index - 1];
47699
47681
  if (!target.latestVersion)
47700
47682
  return { ok: false, message: t().cliUpdate.targetVersionUnknown(target.name), exitCode: 1 };
47701
- if (target.kind === "plugin" && !target.pinned)
47702
- return { ok: false, message: t().cliUpdate.targetNotPinned(target.name), exitCode: 1 };
47703
47683
  if (!target.successorPackage && target.currentVersion === target.latestVersion)
47704
47684
  continue;
47705
47685
  if (!selected.includes(target))
@@ -47851,6 +47831,10 @@ async function handleChannelCli(args, deps) {
47851
47831
  if (args.length < 2 || !args[1])
47852
47832
  return null;
47853
47833
  return await dispatchSetEnabled(args[1], false, args.slice(2), deps);
47834
+ case "set-reply-mode":
47835
+ if (args.length < 3 || !args[1] || !args[2])
47836
+ return null;
47837
+ return await setChannelReplyMode(args[1], args[2], args.slice(3), deps);
47854
47838
  default:
47855
47839
  return null;
47856
47840
  }
@@ -48167,6 +48151,28 @@ async function setChannelEnabled(type, enabled, rawArgs, deps) {
48167
48151
  deps.print(t().channelCli.channelEnabledToggled(channel.id, enabled));
48168
48152
  return await maybeRestartAfterMutation(restartFlags.restart, deps);
48169
48153
  }
48154
+ async function setChannelReplyMode(type, mode, rawArgs, deps) {
48155
+ const restartFlags = parseRestartFlags(rawArgs);
48156
+ if (!restartFlags.ok) {
48157
+ deps.print(restartFlags.message);
48158
+ return 1;
48159
+ }
48160
+ if (mode !== "stream" && mode !== "final" && mode !== "verbose") {
48161
+ deps.print(t().channelCli.channelReplyModeInvalid(mode));
48162
+ return 1;
48163
+ }
48164
+ const config4 = await deps.loadConfig();
48165
+ ensureChannelsArray(config4);
48166
+ const channel = findChannel(config4.channels, type);
48167
+ if (!channel) {
48168
+ deps.print(t().channelCli.channelNotFound(type));
48169
+ return 1;
48170
+ }
48171
+ channel.replyMode = mode;
48172
+ await deps.saveConfig(config4);
48173
+ deps.print(t().channelCli.channelReplyModeSet(channel.id, mode));
48174
+ return await maybeRestartAfterMutation(restartFlags.restart, deps);
48175
+ }
48170
48176
  function requireMultiAccountProvider(type, deps) {
48171
48177
  const provider = getChannelCliProvider(type);
48172
48178
  if (!provider) {
@@ -48493,7 +48499,7 @@ async function inspectPlugins(input) {
48493
48499
  }
48494
48500
  try {
48495
48501
  const plugin = validateWeacpxPlugin(moduleValue, configPlugin.name, {
48496
- ...input.currentWeacpxVersion !== undefined ? { currentWeacpxVersion: input.currentWeacpxVersion } : {}
48502
+ ...input.currentXacpxVersion !== undefined ? { currentXacpxVersion: input.currentXacpxVersion } : {}
48497
48503
  });
48498
48504
  const channels = plugin.channels ?? [];
48499
48505
  const channelTypes = channels.map((channel) => channel.type);
@@ -49087,7 +49093,7 @@ init_i18n();
49087
49093
  init_bootstrap();
49088
49094
  async function prepareMcpCoordinatorStartup(input) {
49089
49095
  const coordinatorSession = input.coordinatorSession.trim();
49090
- const existingSession = Object.values(input.state.sessions).find((session3) => session3.transport_session === coordinatorSession);
49096
+ const existingSession = Object.values(input.state.sessions).find((session3) => stableCoordinatorSession(session3.transport_session) === stableCoordinatorSession(coordinatorSession));
49091
49097
  const workspace3 = input.workspace?.trim();
49092
49098
  if (workspace3) {
49093
49099
  if (existingSession) {
@@ -49133,10 +49139,10 @@ function createMcpStdioIdentityResolver(input) {
49133
49139
  const workspace3 = input.workspace?.trim() || null;
49134
49140
  const sourceHandle = input.sourceHandle?.trim() || null;
49135
49141
  const resolvedWorkspace = workspace3;
49136
- const resolvedCoordinatorSession = parsedCoordinatorSession ?? inferExternalCoordinatorSession({
49142
+ const resolvedCoordinatorSession = stableCoordinatorSession(parsedCoordinatorSession ?? inferExternalCoordinatorSession({
49137
49143
  clientName: context.clientName,
49138
49144
  ...resolvedWorkspace ? { workspace: resolvedWorkspace } : { instanceId }
49139
- });
49145
+ }));
49140
49146
  const startup = await prepareMcpCoordinatorStartup({
49141
49147
  coordinatorSession: resolvedCoordinatorSession,
49142
49148
  ...resolvedWorkspace ? { workspace: resolvedWorkspace } : {},
@@ -49836,7 +49842,7 @@ async function defaultMcpStdio(args, deps = {}) {
49836
49842
  `);
49837
49843
  return 2;
49838
49844
  }
49839
- await runWeacpxMcpServer({
49845
+ await runXacpxMcpServer({
49840
49846
  transport,
49841
49847
  ...coordinatorSession ? { coordinatorSession } : {},
49842
49848
  ...sourceHandle ? { sourceHandle } : {},