@ganglion/xacpx 0.9.1 → 0.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -13,6 +13,8 @@ English · **[中文](./docs/zh/README_zh.md)**
13
13
 
14
14
  `xacpx` is a tool that lets you control ACP agents such as Codex / Claude Code / Gemini / OpenCode directly from WeChat, Feishu, or Yuanbao. It connects chat messages to your agent CLI sessions through `acpx`, so you can, right from your phone:
15
15
 
16
+ [![xacpx.png](https://s41.ax1x.com/2026/06/05/pmZXIv6.png)](https://imgchr.com/i/pmZXIv6)
17
+
16
18
  - Create and switch between sessions
17
19
  - Have the agent keep working in a specific project directory
18
20
  - View streaming replies, final results, and tool-call summaries
@@ -427,7 +429,7 @@ Notes:
427
429
 
428
430
  If you want to first understand when to delegate and when to dispatch multiple subtasks in parallel, see:
429
431
 
430
- - [docs/weacpx-group-usage-guide.md](./docs/weacpx-group-usage-guide.md)
432
+ - [docs/xacpx-group-usage-guide.md](./docs/xacpx-group-usage-guide.md)
431
433
 
432
434
 
433
435
  ### MCP integration: external coordinator
@@ -579,7 +581,7 @@ If what you're about to do is one of the following, you can continue from here:
579
581
 
580
582
  - Want the full chat-command reference: [docs/commands.md](./docs/commands.md)
581
583
  - Want to schedule a one-time future message with scheduled tasks (`/later`): [docs/later-command.md](./docs/later-command.md)
582
- - Want to understand when to delegate and when to open a group: [docs/weacpx-group-usage-guide.md](./docs/weacpx-group-usage-guide.md)
584
+ - Want to understand when to delegate and when to open a group: [docs/xacpx-group-usage-guide.md](./docs/xacpx-group-usage-guide.md)
583
585
 
584
586
  ### Troubleshooting and verification
585
587
 
@@ -880,10 +880,11 @@ var init_session = __esm(() => {
880
880
  replyModeHeader: "Current reply mode:",
881
881
  replyModeSessionLabel: (alias) => `- Session: ${alias}`,
882
882
  replyModeGlobalDefault: (value) => `- Global default: ${value}`,
883
+ replyModeChannelDefault: (value) => `- Channel default: ${value}`,
883
884
  replyModeSessionOverride: (value) => `- Session override: ${value}`,
884
885
  replyModeEffective: (value) => `- Effective: ${value}`,
885
886
  replyModeSet: (replyMode) => `Current session reply mode set to: ${replyMode}`,
886
- replyModeReset: (globalDefault) => `Session reply mode reset. Falling back to global default: ${globalDefault}`,
887
+ replyModeReset: (effective) => `Session reply mode reset. Now effective: ${effective}`,
887
888
  statusHeader: "Current session:",
888
889
  statusNameLabel: (alias) => `- Name: ${alias}`,
889
890
  statusAgentLabel: (agent) => `- Agent: ${agent}`,
@@ -1426,6 +1427,8 @@ var init_config = __esm(() => {
1426
1427
  mustBePositiveNumber: (path2) => `${path2} must be a positive number.`,
1427
1428
  channelTypeDisabled: "channel.type is a legacy single-channel field; /config set writes are disabled. Use `xacpx channel ...` to manage channels[], then restart xacpx.",
1428
1429
  channelReplyModeInvalid: "channel.replyMode only supports: stream, final, verbose",
1430
+ channelRuntimeNotFound: (id) => `Channel "${id}" does not exist; add it first with \`xacpx channel add ${id}\`.`,
1431
+ channelRuntimeReplyModeInvalid: (id) => `channels.${id}.replyMode only supports: stream, final, verbose`,
1429
1432
  wechatReplyModeInvalid: "wechat.replyMode only supports: stream, final, verbose",
1430
1433
  wechatReplyModeMapped: (value) => `${value} (mapped to channel.replyMode)`,
1431
1434
  agentNotFound: (name) => `Agent "${name}" does not exist. Create it first.`,
@@ -1646,6 +1649,8 @@ var init_channel_cli = __esm(() => {
1646
1649
  channelRemoved: (id) => `Channel ${id} removed`,
1647
1650
  cannotDisableLastEnabled: "Cannot disable the last enabled channel.",
1648
1651
  channelEnabledToggled: (id, enabled) => `Channel ${id} ${enabled ? "enabled" : "disabled"}`,
1652
+ channelReplyModeSet: (id, mode) => `Channel ${id} default reply mode set to: ${mode}`,
1653
+ channelReplyModeInvalid: (mode) => `reply mode must be stream / final / verbose, got: ${mode}`,
1649
1654
  channelAccountAlreadyExists: (type, accountId) => `Account ${accountId} already exists on channel ${type}; run xacpx channel rm ${type} --account ${accountId} first`,
1650
1655
  channelAccountAdded: (type, accountId) => `Channel ${type} account ${accountId} added`,
1651
1656
  channelReEnabled: (type) => `Channel ${type} was disabled; it has been automatically re-enabled.`,
@@ -1946,10 +1951,11 @@ var init_session2 = __esm(() => {
1946
1951
  replyModeHeader: "当前 reply mode:",
1947
1952
  replyModeSessionLabel: (alias) => `- 会话:${alias}`,
1948
1953
  replyModeGlobalDefault: (value) => `- 全局默认:${value}`,
1954
+ replyModeChannelDefault: (value) => `- 频道默认:${value}`,
1949
1955
  replyModeSessionOverride: (value) => `- 当前会话覆盖:${value}`,
1950
1956
  replyModeEffective: (value) => `- 当前生效:${value}`,
1951
1957
  replyModeSet: (replyMode) => `已设置当前会话 reply mode:${replyMode}`,
1952
- replyModeReset: (globalDefault) => `已重置当前会话 reply mode,当前回退到全局默认:${globalDefault}`,
1958
+ replyModeReset: (effective) => `已重置当前会话 reply mode,当前生效:${effective}`,
1953
1959
  statusHeader: "当前会话:",
1954
1960
  statusNameLabel: (alias) => `- 名称:${alias}`,
1955
1961
  statusAgentLabel: (agent2) => `- Agent:${agent2}`,
@@ -2492,6 +2498,8 @@ var init_config2 = __esm(() => {
2492
2498
  mustBePositiveNumber: (path2) => `${path2} 必须是正数。`,
2493
2499
  channelTypeDisabled: "channel.type 是旧单频道字段,/config set 已禁用写入;请使用 `xacpx channel ...` 管理 channels[],然后重启 xacpx。",
2494
2500
  channelReplyModeInvalid: "channel.replyMode 只支持:stream、final、verbose",
2501
+ channelRuntimeNotFound: (id) => `频道「${id}」不存在;请先用 \`xacpx channel add ${id}\` 添加。`,
2502
+ channelRuntimeReplyModeInvalid: (id) => `channels.${id}.replyMode 只支持:stream、final、verbose`,
2495
2503
  wechatReplyModeInvalid: "wechat.replyMode 只支持:stream、final、verbose",
2496
2504
  wechatReplyModeMapped: (value) => `${value}(已映射到 channel.replyMode)`,
2497
2505
  agentNotFound: (name) => `Agent「${name}」不存在,请先创建。`,
@@ -2712,6 +2720,8 @@ var init_channel_cli2 = __esm(() => {
2712
2720
  channelRemoved: (id) => `频道 ${id} 已删除`,
2713
2721
  cannotDisableLastEnabled: "不能禁用最后一个启用的频道。",
2714
2722
  channelEnabledToggled: (id, enabled) => `频道 ${id} 已${enabled ? "启用" : "禁用"}`,
2723
+ channelReplyModeSet: (id, mode) => `频道 ${id} 的默认 reply mode 已设置为:${mode}`,
2724
+ channelReplyModeInvalid: (mode) => `reply mode 只支持 stream / final / verbose,收到:${mode}`,
2715
2725
  channelAccountAlreadyExists: (type, accountId) => `频道 ${type} 的账号 ${accountId} 已存在;先 xacpx channel rm ${type} --account ${accountId}`,
2716
2726
  channelAccountAdded: (type, accountId) => `频道 ${type} 账号 ${accountId} 已添加`,
2717
2727
  channelReEnabled: (type) => `频道 ${type} 此前是 disabled 状态,已自动启用。`,
@@ -3030,10 +3040,10 @@ import { spawn as spawn3 } from "node:child_process";
3030
3040
  import { readFile, unlink } from "node:fs/promises";
3031
3041
  import { homedir as homedir2 } from "node:os";
3032
3042
  import { join as join2 } from "node:path";
3033
- function buildWeacpxMcpServerSpec(input) {
3034
- const { command, args } = splitCommandLine(input.weacpxCommand);
3043
+ function buildXacpxMcpServerSpec(input) {
3044
+ const { command, args } = splitCommandLine(input.xacpxCommand);
3035
3045
  return {
3036
- name: "weacpx",
3046
+ name: "xacpx",
3037
3047
  type: "stdio",
3038
3048
  command,
3039
3049
  args: [
@@ -3060,7 +3070,7 @@ function buildQueueOwnerPayload(input) {
3060
3070
 
3061
3071
  class AcpxQueueOwnerLauncher {
3062
3072
  acpxCommand;
3063
- weacpxCommand;
3073
+ xacpxCommand;
3064
3074
  spawnOwner;
3065
3075
  terminateOwner;
3066
3076
  baseEnv;
@@ -3069,7 +3079,7 @@ class AcpxQueueOwnerLauncher {
3069
3079
  launchLocks = new Map;
3070
3080
  constructor(options) {
3071
3081
  this.acpxCommand = options.acpxCommand;
3072
- this.weacpxCommand = options.weacpxCommand ?? resolveDefaultWeacpxCommand(options.baseEnv ?? process.env);
3082
+ this.xacpxCommand = options.xacpxCommand ?? resolveDefaultXacpxCommand(options.baseEnv ?? process.env);
3073
3083
  this.spawnOwner = options.spawnOwner ?? defaultQueueOwnerSpawner;
3074
3084
  this.terminateOwner = options.terminateOwner ?? createDefaultQueueOwnerTerminator(options.acpxCommand);
3075
3085
  this.baseEnv = options.baseEnv ?? process.env;
@@ -3097,8 +3107,8 @@ class AcpxQueueOwnerLauncher {
3097
3107
  nonInteractivePermissions: input.nonInteractivePermissions,
3098
3108
  ttlMs: this.ttlMs,
3099
3109
  maxQueueDepth: this.maxQueueDepth,
3100
- mcpServers: [buildWeacpxMcpServerSpec({
3101
- weacpxCommand: this.weacpxCommand,
3110
+ mcpServers: [buildXacpxMcpServerSpec({
3111
+ xacpxCommand: this.xacpxCommand,
3102
3112
  coordinatorSession: input.coordinatorSession,
3103
3113
  ...input.sourceHandle ? { sourceHandle: input.sourceHandle } : {}
3104
3114
  })]
@@ -3153,13 +3163,13 @@ function splitCommandLine(value) {
3153
3163
  current += "\\";
3154
3164
  }
3155
3165
  if (quote) {
3156
- throw new Error("weacpx MCP command has an unterminated quote");
3166
+ throw new Error("xacpx MCP command has an unterminated quote");
3157
3167
  }
3158
3168
  if (current.length > 0) {
3159
3169
  parts.push(current);
3160
3170
  }
3161
3171
  if (parts.length === 0) {
3162
- throw new Error("weacpx MCP command must not be empty");
3172
+ throw new Error("xacpx MCP command must not be empty");
3163
3173
  }
3164
3174
  return { command: parts[0], args: parts.slice(1) };
3165
3175
  }
@@ -3205,7 +3215,7 @@ function queueLockFilePath(sessionId) {
3205
3215
  function shortHash(value, length) {
3206
3216
  return createHash("sha256").update(value).digest("hex").slice(0, length);
3207
3217
  }
3208
- function resolveDefaultWeacpxCommand(env) {
3218
+ function resolveDefaultXacpxCommand(env) {
3209
3219
  const cliCommand = coreEnv("CLI_COMMAND", env);
3210
3220
  if (cliCommand?.trim()) {
3211
3221
  return cliCommand.trim();
@@ -3641,8 +3651,9 @@ class BridgeRuntime {
3641
3651
  } else if (typeof parsed.id === "string") {
3642
3652
  acpxRecordId = parsed.id;
3643
3653
  }
3654
+ const agentSessionId = typeof parsed.agentSessionId === "string" ? parsed.agentSessionId : undefined;
3644
3655
  if (acpxRecordId) {
3645
- return { acpxRecordId };
3656
+ return { acpxRecordId, agentSessionId };
3646
3657
  }
3647
3658
  } catch {
3648
3659
  const firstLine = result.stdout.trim().split(/\r?\n/, 1)[0];
@@ -3652,6 +3663,10 @@ class BridgeRuntime {
3652
3663
  }
3653
3664
  throw new Error("failed to resolve acpx session record id");
3654
3665
  }
3666
+ async getAgentSessionId(input) {
3667
+ const record = await this.readSessionRecord(input);
3668
+ return { agentSessionId: record.agentSessionId };
3669
+ }
3655
3670
  async setMode(input) {
3656
3671
  const spawnSpec = resolveSpawnCommand(this.command, this.buildSessionArgs(input, [
3657
3672
  "set-mode",
@@ -3919,7 +3934,8 @@ var BRIDGE_METHODS = new Set([
3919
3934
  "prompt",
3920
3935
  "setMode",
3921
3936
  "cancel",
3922
- "removeSession"
3937
+ "removeSession",
3938
+ "getAgentSessionId"
3923
3939
  ]);
3924
3940
  var SESSION_SCOPED_METHODS = new Set([
3925
3941
  "hasSession",
@@ -3929,7 +3945,8 @@ var SESSION_SCOPED_METHODS = new Set([
3929
3945
  "prompt",
3930
3946
  "setMode",
3931
3947
  "cancel",
3932
- "removeSession"
3948
+ "removeSession",
3949
+ "getAgentSessionId"
3933
3950
  ]);
3934
3951
 
3935
3952
  class BridgeServer {
@@ -4105,6 +4122,13 @@ class BridgeServer {
4105
4122
  cwd: requireString(params, "cwd"),
4106
4123
  name: requireString(params, "name")
4107
4124
  });
4125
+ case "getAgentSessionId":
4126
+ return await this.runtime.getAgentSessionId({
4127
+ agent: requireString(params, "agent"),
4128
+ agentCommand: asOptionalString(params.agentCommand),
4129
+ cwd: requireString(params, "cwd"),
4130
+ name: requireString(params, "name")
4131
+ });
4108
4132
  default:
4109
4133
  throw new Error(`unsupported bridge method: ${method}`);
4110
4134
  }
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.`,
@@ -879,6 +882,8 @@ var init_channel_cli = __esm(() => {
879
882
  channelRemoved: (id) => `Channel ${id} removed`,
880
883
  cannotDisableLastEnabled: "Cannot disable the last enabled channel.",
881
884
  channelEnabledToggled: (id, enabled) => `Channel ${id} ${enabled ? "enabled" : "disabled"}`,
885
+ channelReplyModeSet: (id, mode) => `Channel ${id} default reply mode set to: ${mode}`,
886
+ channelReplyModeInvalid: (mode) => `reply mode must be stream / final / verbose, got: ${mode}`,
882
887
  channelAccountAlreadyExists: (type, accountId) => `Account ${accountId} already exists on channel ${type}; run xacpx channel rm ${type} --account ${accountId} first`,
883
888
  channelAccountAdded: (type, accountId) => `Channel ${type} account ${accountId} added`,
884
889
  channelReEnabled: (type) => `Channel ${type} was disabled; it has been automatically re-enabled.`,
@@ -1179,10 +1184,11 @@ var init_session2 = __esm(() => {
1179
1184
  replyModeHeader: "当前 reply mode:",
1180
1185
  replyModeSessionLabel: (alias) => `- 会话:${alias}`,
1181
1186
  replyModeGlobalDefault: (value) => `- 全局默认:${value}`,
1187
+ replyModeChannelDefault: (value) => `- 频道默认:${value}`,
1182
1188
  replyModeSessionOverride: (value) => `- 当前会话覆盖:${value}`,
1183
1189
  replyModeEffective: (value) => `- 当前生效:${value}`,
1184
1190
  replyModeSet: (replyMode) => `已设置当前会话 reply mode:${replyMode}`,
1185
- replyModeReset: (globalDefault) => `已重置当前会话 reply mode,当前回退到全局默认:${globalDefault}`,
1191
+ replyModeReset: (effective) => `已重置当前会话 reply mode,当前生效:${effective}`,
1186
1192
  statusHeader: "当前会话:",
1187
1193
  statusNameLabel: (alias) => `- 名称:${alias}`,
1188
1194
  statusAgentLabel: (agent2) => `- Agent:${agent2}`,
@@ -1725,6 +1731,8 @@ var init_config2 = __esm(() => {
1725
1731
  mustBePositiveNumber: (path) => `${path} 必须是正数。`,
1726
1732
  channelTypeDisabled: "channel.type 是旧单频道字段,/config set 已禁用写入;请使用 `xacpx channel ...` 管理 channels[],然后重启 xacpx。",
1727
1733
  channelReplyModeInvalid: "channel.replyMode 只支持:stream、final、verbose",
1734
+ channelRuntimeNotFound: (id) => `频道「${id}」不存在;请先用 \`xacpx channel add ${id}\` 添加。`,
1735
+ channelRuntimeReplyModeInvalid: (id) => `channels.${id}.replyMode 只支持:stream、final、verbose`,
1728
1736
  wechatReplyModeInvalid: "wechat.replyMode 只支持:stream、final、verbose",
1729
1737
  wechatReplyModeMapped: (value) => `${value}(已映射到 channel.replyMode)`,
1730
1738
  agentNotFound: (name) => `Agent「${name}」不存在,请先创建。`,
@@ -1945,6 +1953,8 @@ var init_channel_cli2 = __esm(() => {
1945
1953
  channelRemoved: (id) => `频道 ${id} 已删除`,
1946
1954
  cannotDisableLastEnabled: "不能禁用最后一个启用的频道。",
1947
1955
  channelEnabledToggled: (id, enabled) => `频道 ${id} 已${enabled ? "启用" : "禁用"}`,
1956
+ channelReplyModeSet: (id, mode) => `频道 ${id} 的默认 reply mode 已设置为:${mode}`,
1957
+ channelReplyModeInvalid: (mode) => `reply mode 只支持 stream / final / verbose,收到:${mode}`,
1948
1958
  channelAccountAlreadyExists: (type, accountId) => `频道 ${type} 的账号 ${accountId} 已存在;先 xacpx channel rm ${type} --account ${accountId}`,
1949
1959
  channelAccountAdded: (type, accountId) => `频道 ${type} 账号 ${accountId} 已添加`,
1950
1960
  channelReEnabled: (type) => `频道 ${type} 此前是 disabled 状态,已自动启用。`,
@@ -4647,6 +4657,9 @@ function parseRuntimeChannelConfig(raw, index) {
4647
4657
  throw new Error(`channels[${index}].type must be a non-empty string`);
4648
4658
  }
4649
4659
  const enabled = raw.enabled !== false;
4660
+ if ("replyMode" in raw && !isReplyMode(raw.replyMode)) {
4661
+ throw new Error(`channels[${index}].replyMode must be stream, final, or verbose`);
4662
+ }
4650
4663
  let options = undefined;
4651
4664
  if ("feishu" in raw && isRecord(raw.feishu)) {
4652
4665
  options = raw.feishu;
@@ -4657,6 +4670,7 @@ function parseRuntimeChannelConfig(raw, index) {
4657
4670
  id,
4658
4671
  type: raw.type,
4659
4672
  enabled,
4673
+ ...isReplyMode(raw.replyMode) ? { replyMode: raw.replyMode } : {},
4660
4674
  ...options ? { options } : {}
4661
4675
  };
4662
4676
  }
@@ -5394,7 +5408,7 @@ function resolveOrchestrationEndpoint(runtimeDir, platform = process.platform) {
5394
5408
  const suffix = createHash("sha256").update(runtimeDir).digest("hex").slice(0, 12);
5395
5409
  return {
5396
5410
  kind: "named-pipe",
5397
- path: `\\\\.\\pipe\\weacpx-orchestration-${suffix}`
5411
+ path: `\\\\.\\pipe\\xacpx-orchestration-${suffix}`
5398
5412
  };
5399
5413
  }
5400
5414
  return {
@@ -11940,9 +11954,9 @@ function readVersion(moduleUrl = import.meta.url) {
11940
11954
  }
11941
11955
  return "unknown";
11942
11956
  }
11943
- var PACKAGE_NAME = "@ganglion/xacpx", WEACPX_CORE_VERSION;
11957
+ var PACKAGE_NAME = "@ganglion/xacpx", XACPX_CORE_VERSION;
11944
11958
  var init_version = __esm(() => {
11945
- WEACPX_CORE_VERSION = readVersion();
11959
+ XACPX_CORE_VERSION = readVersion();
11946
11960
  });
11947
11961
 
11948
11962
  // src/orchestration/task-watch-timeouts.ts
@@ -12281,7 +12295,7 @@ function isReplyMode2(value) {
12281
12295
  return value === "stream" || value === "final" || value === "verbose";
12282
12296
  }
12283
12297
  function isSessionSource(value) {
12284
- return value === undefined || value === "weacpx" || value === "agent-side";
12298
+ return value === undefined || value === "weacpx" || value === "xacpx" || value === "agent-side";
12285
12299
  }
12286
12300
  function isSessionRecord(value) {
12287
12301
  if (!isRecord2(value)) {
@@ -12813,7 +12827,7 @@ async function ensureCoreResolution(pluginHome) {
12813
12827
  await copyFile(srcJs, dstJs);
12814
12828
  } catch (error2) {
12815
12829
  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.`);
12830
+ 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
12831
  continue;
12818
12832
  }
12819
12833
  await writeFile4(join6(targetDir, "package.json"), JSON.stringify({
@@ -13712,7 +13726,7 @@ async function sendTyping(params) {
13712
13726
  label: "sendTyping"
13713
13727
  });
13714
13728
  }
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;
13729
+ 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
13730
  var init_api = __esm(() => {
13717
13731
  init_version();
13718
13732
  init_accounts();
@@ -19158,19 +19172,19 @@ function cmpTuple(a, b) {
19158
19172
  return 0;
19159
19173
  }
19160
19174
  function validatePluginCompatibility(metadata, context) {
19161
- const { packageName, currentWeacpxVersion } = context;
19175
+ const { packageName, currentXacpxVersion } = context;
19162
19176
  const apiVersion = metadata.apiVersion;
19163
19177
  if (typeof apiVersion !== "number") {
19164
19178
  throw new Error(t().pluginCli.compatMissingApiVersion(packageName));
19165
19179
  }
19166
- if (!WEACPX_PLUGIN_API_SUPPORTED_VERSIONS.includes(apiVersion)) {
19167
- const supported = WEACPX_PLUGIN_API_SUPPORTED_VERSIONS.join(", ");
19180
+ if (!XACPX_PLUGIN_API_SUPPORTED_VERSIONS.includes(apiVersion)) {
19181
+ const supported = XACPX_PLUGIN_API_SUPPORTED_VERSIONS.join(", ");
19168
19182
  throw new Error(t().pluginCli.compatUnsupportedApiVersion(packageName, apiVersion, supported));
19169
19183
  }
19170
- if (!currentWeacpxVersion || currentWeacpxVersion === "unknown") {
19184
+ if (!currentXacpxVersion || currentXacpxVersion === "unknown") {
19171
19185
  return;
19172
19186
  }
19173
- const normalizedCurrent = normalizeCoreVersionForCompat(currentWeacpxVersion);
19187
+ const normalizedCurrent = normalizeCoreVersionForCompat(currentXacpxVersion);
19174
19188
  const minVersion = metadata.minXacpxVersion ?? metadata.minWeacpxVersion;
19175
19189
  const minVersionField = metadata.minXacpxVersion !== undefined ? "minXacpxVersion" : "minWeacpxVersion";
19176
19190
  if (minVersion !== undefined) {
@@ -19185,7 +19199,7 @@ function validatePluginCompatibility(metadata, context) {
19185
19199
  throw new Error(t().pluginCli.compatInvalidMinVersionDetail(packageName, minVersionField, detail));
19186
19200
  }
19187
19201
  if (!satisfied) {
19188
- throw new Error(t().pluginCli.compatMinVersionNotSatisfied(packageName, minVersion, currentWeacpxVersion));
19202
+ throw new Error(t().pluginCli.compatMinVersionNotSatisfied(packageName, minVersion, currentXacpxVersion));
19189
19203
  }
19190
19204
  }
19191
19205
  const compatibleVersions = metadata.compatibleXacpxVersions ?? metadata.compatibleWeacpxVersions;
@@ -19202,14 +19216,17 @@ function validatePluginCompatibility(metadata, context) {
19202
19216
  throw new Error(t().pluginCli.compatInvalidCompatibleVersionsDetail(packageName, compatibleField, detail));
19203
19217
  }
19204
19218
  if (!satisfied) {
19205
- throw new Error(t().pluginCli.compatCompatibleVersionsNotSatisfied(packageName, compatibleVersions, currentWeacpxVersion));
19219
+ throw new Error(t().pluginCli.compatCompatibleVersionsNotSatisfied(packageName, compatibleVersions, currentXacpxVersion));
19206
19220
  }
19207
19221
  }
19208
19222
  }
19209
- var WEACPX_PLUGIN_API_VERSION = 1, WEACPX_PLUGIN_API_SUPPORTED_VERSIONS, WEACPX_PLUGIN_MIN_CORE_VERSION = "0.5.0", SEMVER_RE;
19223
+ 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
19224
  var init_compatibility = __esm(() => {
19211
19225
  init_i18n();
19212
- WEACPX_PLUGIN_API_SUPPORTED_VERSIONS = [1];
19226
+ XACPX_PLUGIN_API_SUPPORTED_VERSIONS = [1];
19227
+ WEACPX_PLUGIN_API_VERSION = XACPX_PLUGIN_API_VERSION;
19228
+ WEACPX_PLUGIN_API_SUPPORTED_VERSIONS = XACPX_PLUGIN_API_SUPPORTED_VERSIONS;
19229
+ WEACPX_PLUGIN_MIN_CORE_VERSION = XACPX_PLUGIN_MIN_CORE_VERSION;
19213
19230
  SEMVER_RE = /^(\d+)\.(\d+)\.(\d+)$/;
19214
19231
  });
19215
19232
 
@@ -19224,14 +19241,14 @@ function validateWeacpxPlugin(value, packageName, options = {}) {
19224
19241
  if (!isRecord(plugin)) {
19225
19242
  throw new Error(t().pluginCli.pluginNoDefaultExport(packageName));
19226
19243
  }
19227
- const currentWeacpxVersion = options.currentWeacpxVersion ?? readVersion();
19244
+ const currentXacpxVersion = options.currentXacpxVersion ?? readVersion();
19228
19245
  validatePluginCompatibility({
19229
19246
  apiVersion: plugin.apiVersion,
19230
19247
  minWeacpxVersion: plugin.minWeacpxVersion,
19231
19248
  compatibleWeacpxVersions: plugin.compatibleWeacpxVersions,
19232
19249
  minXacpxVersion: plugin.minXacpxVersion,
19233
19250
  compatibleXacpxVersions: plugin.compatibleXacpxVersions
19234
- }, { packageName, currentWeacpxVersion });
19251
+ }, { packageName, currentXacpxVersion });
19235
19252
  if ("name" in plugin && typeof plugin.name === "string" && plugin.name.trim() && plugin.name.trim() !== packageName) {
19236
19253
  throw new Error(t().pluginCli.pluginNameMismatch(packageName, plugin.name));
19237
19254
  }
@@ -19260,7 +19277,7 @@ function validateWeacpxPlugin(value, packageName, options = {}) {
19260
19277
  }
19261
19278
  }
19262
19279
  const normalized = {
19263
- apiVersion: WEACPX_PLUGIN_API_VERSION,
19280
+ apiVersion: XACPX_PLUGIN_API_VERSION,
19264
19281
  ...typeof plugin.name === "string" && plugin.name.trim() ? { name: plugin.name.trim() } : { name: packageName },
19265
19282
  channels
19266
19283
  };
@@ -19314,7 +19331,7 @@ async function loadConfiguredPlugins(input) {
19314
19331
  throw new Error(`failed to load plugin ${config4.name}: ${message}`);
19315
19332
  }
19316
19333
  const plugin = validateWeacpxPlugin(moduleValue, config4.name, {
19317
- ...input.currentWeacpxVersion !== undefined ? { currentWeacpxVersion: input.currentWeacpxVersion } : {}
19334
+ ...input.currentXacpxVersion !== undefined ? { currentXacpxVersion: input.currentXacpxVersion } : {}
19318
19335
  });
19319
19336
  const channels = plugin.channels ?? [];
19320
19337
  for (const channel of channels) {
@@ -19566,16 +19583,16 @@ var init_prompt_output = __esm(() => {
19566
19583
  });
19567
19584
 
19568
19585
  // src/commands/command-list.ts
19569
- function isKnownWeacpxCommandPrefix(prefix) {
19586
+ function isKnownXacpxCommandPrefix(prefix) {
19570
19587
  return KNOWN_COMMAND_PREFIX_SET.has(prefix.toLowerCase());
19571
19588
  }
19572
- function isKnownWeacpxCommandText(text) {
19589
+ function isKnownXacpxCommandText(text) {
19573
19590
  const firstToken = text.trim().split(/\s+/, 1)[0];
19574
- return Boolean(firstToken && isKnownWeacpxCommandPrefix(firstToken));
19591
+ return Boolean(firstToken && isKnownXacpxCommandPrefix(firstToken));
19575
19592
  }
19576
- var WEACPX_KNOWN_COMMAND_PREFIXES, KNOWN_COMMAND_PREFIX_SET;
19593
+ var XACPX_KNOWN_COMMAND_PREFIXES, KNOWN_COMMAND_PREFIX_SET;
19577
19594
  var init_command_list = __esm(() => {
19578
- WEACPX_KNOWN_COMMAND_PREFIXES = [
19595
+ XACPX_KNOWN_COMMAND_PREFIXES = [
19579
19596
  "/help",
19580
19597
  "/agents",
19581
19598
  "/workspaces",
@@ -19605,7 +19622,7 @@ var init_command_list = __esm(() => {
19605
19622
  "/later",
19606
19623
  "/lt"
19607
19624
  ];
19608
- KNOWN_COMMAND_PREFIX_SET = new Set(WEACPX_KNOWN_COMMAND_PREFIXES);
19625
+ KNOWN_COMMAND_PREFIX_SET = new Set(XACPX_KNOWN_COMMAND_PREFIXES);
19609
19626
  });
19610
19627
 
19611
19628
  // src/commands/parse-command.ts
@@ -20095,7 +20112,7 @@ function normalizeCommand(command) {
20095
20112
  return command;
20096
20113
  }
20097
20114
  function isRecognizedCommand(command) {
20098
- return isKnownWeacpxCommandPrefix(command);
20115
+ return isKnownXacpxCommandPrefix(command);
20099
20116
  }
20100
20117
  function toPermissionMode(value) {
20101
20118
  if (value === "allow")
@@ -20609,6 +20626,23 @@ function applySupportedConfigUpdate(config4, path14, rawValue) {
20609
20626
  }
20610
20627
  return { renderedValue: rawValue };
20611
20628
  }
20629
+ const channelMatch = path14.match(/^channels\.([^.]+)\.replyMode$/);
20630
+ if (channelMatch) {
20631
+ const [, id] = channelMatch;
20632
+ if (!id) {
20633
+ return { error: c.pathNotSupported(path14) };
20634
+ }
20635
+ const channel = config4.channels.find((entry) => entry.id === id);
20636
+ if (!channel) {
20637
+ return { error: c.channelRuntimeNotFound(id) };
20638
+ }
20639
+ const parsed = parseEnum(rawValue, ["stream", "final", "verbose"]);
20640
+ if (!parsed) {
20641
+ return { error: c.channelRuntimeReplyModeInvalid(id) };
20642
+ }
20643
+ channel.replyMode = parsed;
20644
+ return { renderedValue: parsed };
20645
+ }
20612
20646
  return { error: c.pathNotSupported(path14) };
20613
20647
  }
20614
20648
  function parseEnum(value, allowed) {
@@ -20638,6 +20672,7 @@ var init_config_handler = __esm(() => {
20638
20672
  "logging.maxFiles",
20639
20673
  "logging.retentionDays",
20640
20674
  "channel.replyMode",
20675
+ "channels.<id>.replyMode",
20641
20676
  "agents.<name>.driver",
20642
20677
  "agents.<name>.command",
20643
20678
  "workspaces.<name>.cwd",
@@ -20978,6 +21013,20 @@ var init_build_coordinator_prompt = __esm(() => {
20978
21013
  init_render_delegate_question_package();
20979
21014
  });
20980
21015
 
21016
+ // src/commands/handlers/resolve-reply-mode.ts
21017
+ function resolveChannelDefaultReplyMode(config4, chatKey) {
21018
+ if (!config4)
21019
+ return;
21020
+ const channelId = getChannelIdFromChatKey(chatKey);
21021
+ return config4.channels.find((channel) => channel.id === channelId)?.replyMode;
21022
+ }
21023
+ function resolveEffectiveReplyMode(config4, chatKey, sessionOverride) {
21024
+ return sessionOverride ?? resolveChannelDefaultReplyMode(config4, chatKey) ?? config4?.channel.replyMode ?? "verbose";
21025
+ }
21026
+ var init_resolve_reply_mode = __esm(() => {
21027
+ init_channel_scope();
21028
+ });
21029
+
20981
21030
  // src/commands/handlers/session-list-marker.ts
20982
21031
  function decorateUnread(label, hasUnread) {
20983
21032
  return hasUnread ? `● ${label}` : label;
@@ -21282,14 +21331,16 @@ async function handleReplyModeShow(context, chatKey) {
21282
21331
  return { text: t().session.noCurrent };
21283
21332
  }
21284
21333
  const globalDefault = context.config?.channel.replyMode ?? "verbose";
21334
+ const channelDefault = resolveChannelDefaultReplyMode(context.config, chatKey);
21285
21335
  const sessionOverride = session3.replyMode;
21286
- const effective = sessionOverride ?? globalDefault;
21336
+ const effective = resolveEffectiveReplyMode(context.config, chatKey, sessionOverride);
21287
21337
  const s = t().session;
21288
21338
  return {
21289
21339
  text: [
21290
21340
  s.replyModeHeader,
21291
21341
  s.replyModeSessionLabel(toDisplaySessionAlias(session3.alias)),
21292
21342
  s.replyModeGlobalDefault(globalDefault),
21343
+ s.replyModeChannelDefault(channelDefault ?? s.modeNotSet),
21293
21344
  s.replyModeSessionOverride(sessionOverride ?? s.modeNotSet),
21294
21345
  s.replyModeEffective(effective)
21295
21346
  ].join(`
@@ -21310,8 +21361,8 @@ async function handleReplyModeReset(context, chatKey) {
21310
21361
  return { text: t().session.noCurrent };
21311
21362
  }
21312
21363
  await context.sessions.setCurrentSessionReplyMode(chatKey, undefined);
21313
- const globalDefault = context.config?.channel.replyMode ?? "verbose";
21314
- return { text: t().session.replyModeReset(globalDefault) };
21364
+ const fallback = resolveEffectiveReplyMode(context.config, chatKey, undefined);
21365
+ return { text: t().session.replyModeReset(fallback) };
21315
21366
  }
21316
21367
  async function handleStatus(context, chatKey) {
21317
21368
  const session3 = await context.sessions.getCurrentSession(chatKey);
@@ -21458,7 +21509,7 @@ async function handleSessionRemove(context, chatKey, alias) {
21458
21509
  `) };
21459
21510
  }
21460
21511
  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";
21512
+ const effectiveReplyMode = resolveEffectiveReplyMode(context.config, chatKey, session3.replyMode);
21462
21513
  if (!session3.replyMode)
21463
21514
  session3.replyMode = effectiveReplyMode;
21464
21515
  const transportReply = effectiveReplyMode !== "final" ? reply : undefined;
@@ -21606,6 +21657,7 @@ var DEFAULT_SESSION_TAIL_LINES = 50, MAX_SESSION_TAIL_LINES = 500;
21606
21657
  var init_session_handler = __esm(() => {
21607
21658
  init_build_coordinator_prompt();
21608
21659
  init_channel_scope();
21660
+ init_resolve_reply_mode();
21609
21661
  init_workspace_name();
21610
21662
  init_i18n();
21611
21663
  });
@@ -23657,23 +23709,43 @@ var init_translate_acpx_note = __esm(() => {
23657
23709
 
23658
23710
  // src/commands/handlers/session-reset-handler.ts
23659
23711
  async function handleSessionResetCommand(context, ops, chatKey) {
23660
- const session3 = await context.sessions.getCurrentSession(chatKey);
23661
- if (!session3) {
23712
+ const previous = await context.sessions.getCurrentSession(chatKey);
23713
+ if (!previous) {
23662
23714
  return { text: t().misc.sessionResetNoCurrentSession };
23663
23715
  }
23664
- const resetSession = ops.resolveSession(session3.alias, session3.agent, session3.workspace, buildResetTransportSessionName(session3, ops.now()));
23716
+ const wasNative = previous.source === "agent-side";
23717
+ const resetSession = ops.resolveSession(previous.alias, previous.agent, previous.workspace, buildResetTransportSessionName(previous, ops.now()));
23665
23718
  const releaseTransportReservation = await ops.reserveTransportSession(resetSession.transportSession);
23666
23719
  try {
23667
23720
  try {
23668
23721
  await ops.ensureTransportSession(resetSession);
23669
23722
  const exists = await ops.checkTransportSession(resetSession);
23670
23723
  if (!exists) {
23671
- return { text: t().misc.sessionResetFailed(session3.alias) };
23724
+ return { text: t().misc.sessionResetFailed(previous.alias) };
23672
23725
  }
23673
23726
  } catch (error2) {
23674
23727
  return renderTransportError(resetSession, error2);
23675
23728
  }
23676
- await context.sessions.attachSession(resetSession.alias, resetSession.agent, resetSession.workspace, resetSession.transportSession);
23729
+ let freshAgentSessionId;
23730
+ if (wasNative) {
23731
+ try {
23732
+ freshAgentSessionId = await context.transport.getAgentSessionId?.(resetSession);
23733
+ } catch (error2) {
23734
+ 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) });
23735
+ }
23736
+ }
23737
+ if (wasNative && freshAgentSessionId) {
23738
+ await context.sessions.attachNativeSession({
23739
+ alias: resetSession.alias,
23740
+ agent: resetSession.agent,
23741
+ workspace: resetSession.workspace,
23742
+ transportSession: resetSession.transportSession,
23743
+ agentSessionId: freshAgentSessionId,
23744
+ updatedAt: new Date(ops.now()).toISOString()
23745
+ });
23746
+ } else {
23747
+ await context.sessions.attachSession(resetSession.alias, resetSession.agent, resetSession.workspace, resetSession.transportSession);
23748
+ }
23677
23749
  await ops.refreshSessionTransportAgentCommand(resetSession.alias);
23678
23750
  await context.sessions.useSession(chatKey, resetSession.alias);
23679
23751
  await context.logger.info("session.reset", "reset current logical session", {
@@ -23681,8 +23753,19 @@ async function handleSessionResetCommand(context, ops, chatKey) {
23681
23753
  agent: resetSession.agent,
23682
23754
  workspace: resetSession.workspace,
23683
23755
  transportSession: resetSession.transportSession,
23684
- chatKey
23756
+ chatKey,
23757
+ native: wasNative && Boolean(freshAgentSessionId)
23685
23758
  });
23759
+ if (wasNative && context.transport.removeSession && context.sessions.countAliasesSharingTransport(previous.transportSession) === 0) {
23760
+ try {
23761
+ await context.transport.removeSession(previous);
23762
+ } catch (error2) {
23763
+ await context.logger.info("session.reset.close_previous_failed", "failed to close previous native session after reset", {
23764
+ transportSession: previous.transportSession,
23765
+ error: error2 instanceof Error ? error2.message : String(error2)
23766
+ });
23767
+ }
23768
+ }
23686
23769
  } finally {
23687
23770
  await releaseTransportReservation();
23688
23771
  }
@@ -24351,7 +24434,7 @@ class ConsoleAgent {
24351
24434
  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
24435
  }
24353
24436
  isKnownCommand(text) {
24354
- return isKnownWeacpxCommandText(text);
24437
+ return isKnownXacpxCommandText(text);
24355
24438
  }
24356
24439
  async clearSession(conversationId) {
24357
24440
  await this.router.clearSession?.(conversationId);
@@ -29175,7 +29258,7 @@ class DebouncedStateStore {
29175
29258
  }
29176
29259
 
29177
29260
  // src/commands/command-hints.ts
29178
- function listWeacpxCommandHints() {
29261
+ function listXacpxCommandHints() {
29179
29262
  const hints3 = [{ name: "/help", description: t().hints.helpDescription }];
29180
29263
  for (const topic of listHelpTopics()) {
29181
29264
  const name = PRIMARY_COMMAND_BY_TOPIC[topic.topic];
@@ -29323,8 +29406,8 @@ async function runConsole(paths, deps) {
29323
29406
  activeTurns: runtime.activeTurns,
29324
29407
  logger: runtime.logger,
29325
29408
  perfTracer: runtime.perfTracer,
29326
- commandHints: listWeacpxCommandHints(),
29327
- coreVersion: WEACPX_CORE_VERSION,
29409
+ commandHints: listXacpxCommandHints(),
29410
+ coreVersion: XACPX_CORE_VERSION,
29328
29411
  locale: getLocale()
29329
29412
  });
29330
29413
  channelStartPromise.catch(() => {});
@@ -30016,6 +30099,10 @@ ${result.text}` : "" };
30016
30099
  async removeSession(session3) {
30017
30100
  await this.client.request("removeSession", this.toParams(session3));
30018
30101
  }
30102
+ async getAgentSessionId(session3) {
30103
+ const result = await this.client.request("getAgentSessionId", this.toParams(session3));
30104
+ return result.agentSessionId;
30105
+ }
30019
30106
  async hasSession(session3) {
30020
30107
  const result = await this.client.request("hasSession", this.toParams(session3));
30021
30108
  return result.exists;
@@ -30510,10 +30597,10 @@ import { spawn as spawn8 } from "node:child_process";
30510
30597
  import { readFile as readFile12, unlink } from "node:fs/promises";
30511
30598
  import { homedir as homedir8 } from "node:os";
30512
30599
  import { join as join17 } from "node:path";
30513
- function buildWeacpxMcpServerSpec(input) {
30514
- const { command, args } = splitCommandLine(input.weacpxCommand);
30600
+ function buildXacpxMcpServerSpec(input) {
30601
+ const { command, args } = splitCommandLine(input.xacpxCommand);
30515
30602
  return {
30516
- name: "weacpx",
30603
+ name: "xacpx",
30517
30604
  type: "stdio",
30518
30605
  command,
30519
30606
  args: [
@@ -30540,7 +30627,7 @@ function buildQueueOwnerPayload(input) {
30540
30627
 
30541
30628
  class AcpxQueueOwnerLauncher {
30542
30629
  acpxCommand;
30543
- weacpxCommand;
30630
+ xacpxCommand;
30544
30631
  spawnOwner;
30545
30632
  terminateOwner;
30546
30633
  baseEnv;
@@ -30549,7 +30636,7 @@ class AcpxQueueOwnerLauncher {
30549
30636
  launchLocks = new Map;
30550
30637
  constructor(options) {
30551
30638
  this.acpxCommand = options.acpxCommand;
30552
- this.weacpxCommand = options.weacpxCommand ?? resolveDefaultWeacpxCommand(options.baseEnv ?? process.env);
30639
+ this.xacpxCommand = options.xacpxCommand ?? resolveDefaultXacpxCommand(options.baseEnv ?? process.env);
30553
30640
  this.spawnOwner = options.spawnOwner ?? defaultQueueOwnerSpawner;
30554
30641
  this.terminateOwner = options.terminateOwner ?? createDefaultQueueOwnerTerminator(options.acpxCommand);
30555
30642
  this.baseEnv = options.baseEnv ?? process.env;
@@ -30577,8 +30664,8 @@ class AcpxQueueOwnerLauncher {
30577
30664
  nonInteractivePermissions: input.nonInteractivePermissions,
30578
30665
  ttlMs: this.ttlMs,
30579
30666
  maxQueueDepth: this.maxQueueDepth,
30580
- mcpServers: [buildWeacpxMcpServerSpec({
30581
- weacpxCommand: this.weacpxCommand,
30667
+ mcpServers: [buildXacpxMcpServerSpec({
30668
+ xacpxCommand: this.xacpxCommand,
30582
30669
  coordinatorSession: input.coordinatorSession,
30583
30670
  ...input.sourceHandle ? { sourceHandle: input.sourceHandle } : {}
30584
30671
  })]
@@ -30633,13 +30720,13 @@ function splitCommandLine(value) {
30633
30720
  current += "\\";
30634
30721
  }
30635
30722
  if (quote) {
30636
- throw new Error("weacpx MCP command has an unterminated quote");
30723
+ throw new Error("xacpx MCP command has an unterminated quote");
30637
30724
  }
30638
30725
  if (current.length > 0) {
30639
30726
  parts.push(current);
30640
30727
  }
30641
30728
  if (parts.length === 0) {
30642
- throw new Error("weacpx MCP command must not be empty");
30729
+ throw new Error("xacpx MCP command must not be empty");
30643
30730
  }
30644
30731
  return { command: parts[0], args: parts.slice(1) };
30645
30732
  }
@@ -30685,7 +30772,7 @@ function queueLockFilePath(sessionId) {
30685
30772
  function shortHash(value, length) {
30686
30773
  return createHash3("sha256").update(value).digest("hex").slice(0, length);
30687
30774
  }
30688
- function resolveDefaultWeacpxCommand(env) {
30775
+ function resolveDefaultXacpxCommand(env) {
30689
30776
  const cliCommand = coreEnv("CLI_COMMAND", env);
30690
30777
  if (cliCommand?.trim()) {
30691
30778
  return cliCommand.trim();
@@ -31036,8 +31123,9 @@ ${baseText}` : "" };
31036
31123
  try {
31037
31124
  const parsed = JSON.parse(result.stdout);
31038
31125
  const acpxRecordId = typeof parsed.acpxRecordId === "string" ? parsed.acpxRecordId : typeof parsed.id === "string" ? parsed.id : undefined;
31126
+ const agentSessionId = typeof parsed.agentSessionId === "string" ? parsed.agentSessionId : undefined;
31039
31127
  if (acpxRecordId) {
31040
- return { acpxRecordId };
31128
+ return { acpxRecordId, agentSessionId };
31041
31129
  }
31042
31130
  } catch {
31043
31131
  const firstLine = result.stdout.trim().split(/\r?\n/, 1)[0];
@@ -31047,6 +31135,10 @@ ${baseText}` : "" };
31047
31135
  }
31048
31136
  throw new Error("failed to resolve acpx session record id");
31049
31137
  }
31138
+ async getAgentSessionId(session3) {
31139
+ const record3 = await this.readSessionRecord(session3);
31140
+ return record3.agentSessionId;
31141
+ }
31050
31142
  async run(args, options) {
31051
31143
  const result = await this.runCommandWithTimeout(this.runCommand, args, options);
31052
31144
  if (result.code !== 0) {
@@ -33583,7 +33675,7 @@ class DaemonRuntime {
33583
33675
  }
33584
33676
  }
33585
33677
 
33586
- // src/mcp/weacpx-mcp-server.ts
33678
+ // src/mcp/xacpx-mcp-server.ts
33587
33679
  import { stdin, stdout } from "node:process";
33588
33680
 
33589
33681
  // node_modules/@modelcontextprotocol/sdk/node_modules/zod/v4/core/core.js
@@ -45939,7 +46031,7 @@ class StdioServerTransport {
45939
46031
  }
45940
46032
  }
45941
46033
 
45942
- // src/mcp/weacpx-mcp-server.ts
46034
+ // src/mcp/xacpx-mcp-server.ts
45943
46035
  init_version();
45944
46036
 
45945
46037
  // src/mcp/resolve-endpoint.ts
@@ -45967,7 +46059,7 @@ function requireHome(env) {
45967
46059
  return home;
45968
46060
  }
45969
46061
 
45970
- // src/mcp/weacpx-mcp-tools.ts
46062
+ // src/mcp/xacpx-mcp-tools.ts
45971
46063
  init_task_watch_timeouts();
45972
46064
  init_quota_errors();
45973
46065
  var taskStatusSchema = exports_external.enum([
@@ -45988,7 +46080,7 @@ var taskQuestionSchema = exports_external.object({
45988
46080
  taskId: exports_external.string().min(1),
45989
46081
  questionId: exports_external.string().min(1)
45990
46082
  }).strict();
45991
- function buildWeacpxMcpToolRegistry(input) {
46083
+ function buildXacpxMcpToolRegistry(input) {
45992
46084
  const { transport, coordinatorSession, sourceHandle, isExternalCoordinator, internalSessionTools, availableAgents } = input;
45993
46085
  const tools = [
45994
46086
  {
@@ -46146,7 +46238,7 @@ function buildWeacpxMcpToolRegistry(input) {
46146
46238
  }).strict(),
46147
46239
  handler: async (args) => await asToolResult(async () => {
46148
46240
  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");
46241
+ throw new Error("worker_raise_question requires a bound sourceHandle; start mcp-stdio with --source-handle or XACPX_SOURCE_HANDLE");
46150
46242
  }
46151
46243
  const result = await transport.workerRaiseQuestion({
46152
46244
  sourceHandle,
@@ -46209,7 +46301,7 @@ function buildWeacpxMcpToolRegistry(input) {
46209
46301
  if (internalSessionTools && !isExternalCoordinator && !sourceHandle) {
46210
46302
  tools.push({
46211
46303
  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.",
46304
+ 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
46305
  inputSchema: exports_external.object({
46214
46306
  timeText: exports_external.string().min(1).describe("Time expression, e.g. 'in 2h', '30分钟后', 'tomorrow 09:00', or '周五 09:00'."),
46215
46307
  message: exports_external.string().min(1).describe("Natural-language message to run at the scheduled time."),
@@ -46619,7 +46711,7 @@ function getWatchRequestTimeoutMs(watchTimeoutMs, defaultTimeoutMs) {
46619
46711
  return Math.max(defaultTimeoutMs, boundedWatchTimeoutMs + TASK_WATCH_RPC_TIMEOUT_PADDING_MS);
46620
46712
  }
46621
46713
 
46622
- // src/mcp/weacpx-mcp-transport.ts
46714
+ // src/mcp/xacpx-mcp-transport.ts
46623
46715
  function createOrchestrationTransport(endpoint, deps = {}) {
46624
46716
  const client = deps.client ?? new OrchestrationClient(endpoint);
46625
46717
  return {
@@ -46647,7 +46739,7 @@ function createOrchestrationTransport(endpoint, deps = {}) {
46647
46739
  workerRaiseQuestion: async (input) => {
46648
46740
  const sourceHandle = input.sourceHandle.trim();
46649
46741
  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");
46742
+ throw new Error("worker_raise_question requires a bound sourceHandle; start mcp-stdio with --source-handle or XACPX_SOURCE_HANDLE");
46651
46743
  }
46652
46744
  return await client.workerRaiseQuestion({
46653
46745
  taskId: input.taskId,
@@ -46681,11 +46773,11 @@ function createOrchestrationTransport(endpoint, deps = {}) {
46681
46773
  };
46682
46774
  }
46683
46775
 
46684
- // src/mcp/weacpx-mcp-server.ts
46776
+ // src/mcp/xacpx-mcp-server.ts
46685
46777
  var TASK_OPTIONS_CACHE_LIMIT = 1000;
46686
46778
  var TASKS_LIST_PAGE_SIZE = 100;
46687
46779
  var WATCH_TASKS_CACHE_LIMIT = 256;
46688
- var WEACPX_MCP_SERVER_INSTRUCTIONS = [
46780
+ var XACPX_MCP_SERVER_INSTRUCTIONS = [
46689
46781
  "Use these tools to orchestrate work across other agents under your coordinator session.",
46690
46782
  "",
46691
46783
  "Delegate with delegate_request (one task) or delegate_batch (several at once). Each returns a taskId and a status.",
@@ -46696,12 +46788,12 @@ var WEACPX_MCP_SERVER_INSTRUCTIONS = [
46696
46788
  "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
46789
  ].join(`
46698
46790
  `);
46699
- function createWeacpxMcpServer(options) {
46791
+ function createXacpxMcpServer(options) {
46700
46792
  let getToolState;
46701
46793
  const taskOptionsById = new Map;
46702
46794
  const watchTasksById = new Map;
46703
46795
  const server = new Server({
46704
- name: "weacpx",
46796
+ name: "xacpx",
46705
46797
  version: readVersion()
46706
46798
  }, {
46707
46799
  capabilities: {
@@ -46712,8 +46804,8 @@ function createWeacpxMcpServer(options) {
46712
46804
  requests: { tools: { call: {} } }
46713
46805
  }
46714
46806
  },
46715
- instructions: WEACPX_MCP_SERVER_INSTRUCTIONS,
46716
- taskStore: createWeacpxTaskStore(async () => await getToolState(), taskOptionsById, watchTasksById)
46807
+ instructions: XACPX_MCP_SERVER_INSTRUCTIONS,
46808
+ taskStore: createXacpxTaskStore(async () => await getToolState(), taskOptionsById, watchTasksById)
46717
46809
  });
46718
46810
  let toolState = null;
46719
46811
  let toolStatePromise = null;
@@ -46726,7 +46818,7 @@ function createWeacpxMcpServer(options) {
46726
46818
  }
46727
46819
  toolStatePromise = resolveMcpIdentity(server, options).then((identity) => {
46728
46820
  if (!options.transport) {
46729
- throw new Error("weacpx MCP transport is not configured");
46821
+ throw new Error("xacpx MCP transport is not configured");
46730
46822
  }
46731
46823
  toolState = buildToolState({
46732
46824
  transport: options.transport,
@@ -46807,7 +46899,7 @@ function createWeacpxMcpServer(options) {
46807
46899
  return server;
46808
46900
  }
46809
46901
  function buildToolState(options) {
46810
- const tools = buildWeacpxMcpToolRegistry(options);
46902
+ const tools = buildXacpxMcpToolRegistry(options);
46811
46903
  return {
46812
46904
  tools,
46813
46905
  toolMap: new Map(tools.map((tool) => [tool.name, tool])),
@@ -46966,10 +47058,10 @@ function renderWatchMcpTaskResult(result, watchTaskId) {
46966
47058
  structuredContent: { watchTaskId, ...result }
46967
47059
  };
46968
47060
  }
46969
- function createWeacpxTaskStore(resolveState, taskOptionsById, watchTasksById) {
47061
+ function createXacpxTaskStore(resolveState, taskOptionsById, watchTasksById) {
46970
47062
  return {
46971
47063
  createTask: async () => {
46972
- throw new Error("weacpx native MCP tasks are created by delegate_request");
47064
+ throw new Error("xacpx native MCP tasks are created by delegate_request");
46973
47065
  },
46974
47066
  getTask: async (taskId) => {
46975
47067
  const watchTask = watchTasksById.get(taskId);
@@ -46980,7 +47072,7 @@ function createWeacpxTaskStore(resolveState, taskOptionsById, watchTasksById) {
46980
47072
  return task ? toMcpTask(task, taskOptionsById.get(taskId)) : null;
46981
47073
  },
46982
47074
  storeTaskResult: async () => {
46983
- throw new Error("weacpx native MCP task results are stored by orchestration");
47075
+ throw new Error("xacpx native MCP task results are stored by orchestration");
46984
47076
  },
46985
47077
  getTaskResult: async (taskId) => {
46986
47078
  const watchTask = watchTasksById.get(taskId);
@@ -47004,7 +47096,7 @@ function createWeacpxTaskStore(resolveState, taskOptionsById, watchTasksById) {
47004
47096
  await state.transport.cancelTask({ coordinatorSession: state.coordinatorSession, taskId });
47005
47097
  return;
47006
47098
  }
47007
- throw new Error(`weacpx MCP task status is read-only (${status}${statusMessage ? `: ${statusMessage}` : ""})`);
47099
+ throw new Error(`xacpx MCP task status is read-only (${status}${statusMessage ? `: ${statusMessage}` : ""})`);
47008
47100
  },
47009
47101
  listTasks: async (cursor) => {
47010
47102
  const state = await resolveState();
@@ -47264,9 +47356,9 @@ function defaultIsProcessRunning3(pid) {
47264
47356
  return code !== "ESRCH";
47265
47357
  }
47266
47358
  }
47267
- async function runWeacpxMcpServer(options) {
47359
+ async function runXacpxMcpServer(options) {
47268
47360
  const transport = options.transport ?? createOrchestrationTransport(options.endpoint ?? resolveDefaultOrchestrationEndpoint(process.env, process.platform));
47269
- const server = createWeacpxMcpServer({
47361
+ const server = createXacpxMcpServer({
47270
47362
  transport,
47271
47363
  ...options.coordinatorSession ? { coordinatorSession: options.coordinatorSession } : {},
47272
47364
  ...options.sourceHandle ? { sourceHandle: options.sourceHandle } : {},
@@ -47851,6 +47943,10 @@ async function handleChannelCli(args, deps) {
47851
47943
  if (args.length < 2 || !args[1])
47852
47944
  return null;
47853
47945
  return await dispatchSetEnabled(args[1], false, args.slice(2), deps);
47946
+ case "set-reply-mode":
47947
+ if (args.length < 3 || !args[1] || !args[2])
47948
+ return null;
47949
+ return await setChannelReplyMode(args[1], args[2], args.slice(3), deps);
47854
47950
  default:
47855
47951
  return null;
47856
47952
  }
@@ -48167,6 +48263,28 @@ async function setChannelEnabled(type, enabled, rawArgs, deps) {
48167
48263
  deps.print(t().channelCli.channelEnabledToggled(channel.id, enabled));
48168
48264
  return await maybeRestartAfterMutation(restartFlags.restart, deps);
48169
48265
  }
48266
+ async function setChannelReplyMode(type, mode, rawArgs, deps) {
48267
+ const restartFlags = parseRestartFlags(rawArgs);
48268
+ if (!restartFlags.ok) {
48269
+ deps.print(restartFlags.message);
48270
+ return 1;
48271
+ }
48272
+ if (mode !== "stream" && mode !== "final" && mode !== "verbose") {
48273
+ deps.print(t().channelCli.channelReplyModeInvalid(mode));
48274
+ return 1;
48275
+ }
48276
+ const config4 = await deps.loadConfig();
48277
+ ensureChannelsArray(config4);
48278
+ const channel = findChannel(config4.channels, type);
48279
+ if (!channel) {
48280
+ deps.print(t().channelCli.channelNotFound(type));
48281
+ return 1;
48282
+ }
48283
+ channel.replyMode = mode;
48284
+ await deps.saveConfig(config4);
48285
+ deps.print(t().channelCli.channelReplyModeSet(channel.id, mode));
48286
+ return await maybeRestartAfterMutation(restartFlags.restart, deps);
48287
+ }
48170
48288
  function requireMultiAccountProvider(type, deps) {
48171
48289
  const provider = getChannelCliProvider(type);
48172
48290
  if (!provider) {
@@ -48493,7 +48611,7 @@ async function inspectPlugins(input) {
48493
48611
  }
48494
48612
  try {
48495
48613
  const plugin = validateWeacpxPlugin(moduleValue, configPlugin.name, {
48496
- ...input.currentWeacpxVersion !== undefined ? { currentWeacpxVersion: input.currentWeacpxVersion } : {}
48614
+ ...input.currentXacpxVersion !== undefined ? { currentXacpxVersion: input.currentXacpxVersion } : {}
48497
48615
  });
48498
48616
  const channels = plugin.channels ?? [];
48499
48617
  const channelTypes = channels.map((channel) => channel.type);
@@ -49836,7 +49954,7 @@ async function defaultMcpStdio(args, deps = {}) {
49836
49954
  `);
49837
49955
  return 2;
49838
49956
  }
49839
- await runWeacpxMcpServer({
49957
+ await runXacpxMcpServer({
49840
49958
  transport,
49841
49959
  ...coordinatorSession ? { coordinatorSession } : {},
49842
49960
  ...sourceHandle ? { sourceHandle } : {},
@@ -8,4 +8,4 @@ export interface CommandHint {
8
8
  * 从 HELP_TOPICS 派生输入框命令提示(单一真源,与 /help 同源不漂移)。
9
9
  * 额外置顶 /help。
10
10
  */
11
- export declare function listWeacpxCommandHints(): CommandHint[];
11
+ export declare function listXacpxCommandHints(): CommandHint[];
@@ -1,3 +1,3 @@
1
- export declare const WEACPX_KNOWN_COMMAND_PREFIXES: readonly ["/help", "/agents", "/workspaces", "/sessions", "/tasks", "/status", "/cancel", "/stop", "/clear", "/mode", "/replymode", "/config", "/permission", "/pm", "/session", "/ss", "/ssn", "/workspace", "/ws", "/use", "/agent", "/delegate", "/dg", "/group", "/groups", "/task", "/later", "/lt"];
2
- export declare function isKnownWeacpxCommandPrefix(prefix: string): boolean;
3
- export declare function isKnownWeacpxCommandText(text: string): boolean;
1
+ export declare const XACPX_KNOWN_COMMAND_PREFIXES: readonly ["/help", "/agents", "/workspaces", "/sessions", "/tasks", "/status", "/cancel", "/stop", "/clear", "/mode", "/replymode", "/config", "/permission", "/pm", "/session", "/ss", "/ssn", "/workspace", "/ws", "/use", "/agent", "/delegate", "/dg", "/group", "/groups", "/task", "/later", "/lt"];
2
+ export declare function isKnownXacpxCommandPrefix(prefix: string): boolean;
3
+ export declare function isKnownXacpxCommandText(text: string): boolean;
@@ -0,0 +1,13 @@
1
+ import type { AppConfig, ReplyMode } from "../../config/types";
2
+ /**
3
+ * The per-channel default reply mode declared on `channels[].replyMode`, or
4
+ * `undefined` when the channel does not set one (so callers fall through to the
5
+ * global default). The channel is derived from the chatKey the same way the rest
6
+ * of the system scopes sessions.
7
+ */
8
+ export declare function resolveChannelDefaultReplyMode(config: AppConfig | undefined, chatKey: string): ReplyMode | undefined;
9
+ /**
10
+ * Effective reply mode precedence:
11
+ * session override → per-channel default → global channel.replyMode → "verbose".
12
+ */
13
+ export declare function resolveEffectiveReplyMode(config: AppConfig | undefined, chatKey: string, sessionOverride: ReplyMode | undefined): ReplyMode;
@@ -66,6 +66,7 @@ export interface ChannelRuntimeConfig {
66
66
  id: string;
67
67
  type: string;
68
68
  enabled: boolean;
69
+ replyMode?: ReplyMode;
69
70
  options?: Record<string, unknown>;
70
71
  }
71
72
  export interface PluginConfig {
@@ -27,10 +27,11 @@ export interface SessionMessages {
27
27
  replyModeHeader: string;
28
28
  replyModeSessionLabel: (alias: string) => string;
29
29
  replyModeGlobalDefault: (value: string) => string;
30
+ replyModeChannelDefault: (value: string) => string;
30
31
  replyModeSessionOverride: (value: string) => string;
31
32
  replyModeEffective: (value: string) => string;
32
33
  replyModeSet: (replyMode: string) => string;
33
- replyModeReset: (globalDefault: string) => string;
34
+ replyModeReset: (effective: string) => string;
34
35
  statusHeader: string;
35
36
  statusNameLabel: (alias: string) => string;
36
37
  statusAgentLabel: (agent: string) => string;
@@ -503,6 +504,8 @@ export interface ConfigMessages {
503
504
  mustBePositiveNumber: (path: string) => string;
504
505
  channelTypeDisabled: string;
505
506
  channelReplyModeInvalid: string;
507
+ channelRuntimeNotFound: (id: string) => string;
508
+ channelRuntimeReplyModeInvalid: (id: string) => string;
506
509
  wechatReplyModeInvalid: string;
507
510
  wechatReplyModeMapped: (value: string) => string;
508
511
  agentNotFound: (name: string) => string;
@@ -658,6 +661,8 @@ export interface ChannelCliMessages {
658
661
  channelRemoved: (id: string) => string;
659
662
  cannotDisableLastEnabled: string;
660
663
  channelEnabledToggled: (id: string, enabled: boolean) => string;
664
+ channelReplyModeSet: (id: string, mode: string) => string;
665
+ channelReplyModeInvalid: (mode: string) => string;
661
666
  channelAccountAlreadyExists: (type: string, accountId: string) => string;
662
667
  channelAccountAdded: (type: string, accountId: string) => string;
663
668
  channelReEnabled: (type: string) => string;
@@ -6,7 +6,7 @@ export type { ChannelRuntimeConfig } from "./config/types.js";
6
6
  export type { CommandHint } from "./commands/command-hints.js";
7
7
  export type { AppLogger } from "./logging/app-logger.js";
8
8
  export type { WeacpxPlugin, XacpxPlugin } from "./plugins/types.js";
9
- export { WEACPX_PLUGIN_API_VERSION, WEACPX_PLUGIN_API_SUPPORTED_VERSIONS, WEACPX_PLUGIN_MIN_CORE_VERSION, } from "./plugins/types.js";
9
+ export { XACPX_PLUGIN_API_VERSION, XACPX_PLUGIN_API_SUPPORTED_VERSIONS, XACPX_PLUGIN_MIN_CORE_VERSION, WEACPX_PLUGIN_API_VERSION, WEACPX_PLUGIN_API_SUPPORTED_VERSIONS, WEACPX_PLUGIN_MIN_CORE_VERSION, } from "./plugins/types.js";
10
10
  export { createConversationExecutor } from "./runtime/conversation-executor.js";
11
11
  export type { ConversationExecutor, ConversationExecutorLane } from "./runtime/conversation-executor.js";
12
12
  export { resolveTurnLane } from "./runtime/turn-lane.js";
@@ -88,10 +88,11 @@ var init_session = __esm(() => {
88
88
  replyModeHeader: "Current reply mode:",
89
89
  replyModeSessionLabel: (alias) => `- Session: ${alias}`,
90
90
  replyModeGlobalDefault: (value) => `- Global default: ${value}`,
91
+ replyModeChannelDefault: (value) => `- Channel default: ${value}`,
91
92
  replyModeSessionOverride: (value) => `- Session override: ${value}`,
92
93
  replyModeEffective: (value) => `- Effective: ${value}`,
93
94
  replyModeSet: (replyMode) => `Current session reply mode set to: ${replyMode}`,
94
- replyModeReset: (globalDefault) => `Session reply mode reset. Falling back to global default: ${globalDefault}`,
95
+ replyModeReset: (effective) => `Session reply mode reset. Now effective: ${effective}`,
95
96
  statusHeader: "Current session:",
96
97
  statusNameLabel: (alias) => `- Name: ${alias}`,
97
98
  statusAgentLabel: (agent) => `- Agent: ${agent}`,
@@ -634,6 +635,8 @@ var init_config = __esm(() => {
634
635
  mustBePositiveNumber: (path) => `${path} must be a positive number.`,
635
636
  channelTypeDisabled: "channel.type is a legacy single-channel field; /config set writes are disabled. Use `xacpx channel ...` to manage channels[], then restart xacpx.",
636
637
  channelReplyModeInvalid: "channel.replyMode only supports: stream, final, verbose",
638
+ channelRuntimeNotFound: (id) => `Channel "${id}" does not exist; add it first with \`xacpx channel add ${id}\`.`,
639
+ channelRuntimeReplyModeInvalid: (id) => `channels.${id}.replyMode only supports: stream, final, verbose`,
637
640
  wechatReplyModeInvalid: "wechat.replyMode only supports: stream, final, verbose",
638
641
  wechatReplyModeMapped: (value) => `${value} (mapped to channel.replyMode)`,
639
642
  agentNotFound: (name) => `Agent "${name}" does not exist. Create it first.`,
@@ -854,6 +857,8 @@ var init_channel_cli = __esm(() => {
854
857
  channelRemoved: (id) => `Channel ${id} removed`,
855
858
  cannotDisableLastEnabled: "Cannot disable the last enabled channel.",
856
859
  channelEnabledToggled: (id, enabled) => `Channel ${id} ${enabled ? "enabled" : "disabled"}`,
860
+ channelReplyModeSet: (id, mode) => `Channel ${id} default reply mode set to: ${mode}`,
861
+ channelReplyModeInvalid: (mode) => `reply mode must be stream / final / verbose, got: ${mode}`,
857
862
  channelAccountAlreadyExists: (type, accountId) => `Account ${accountId} already exists on channel ${type}; run xacpx channel rm ${type} --account ${accountId} first`,
858
863
  channelAccountAdded: (type, accountId) => `Channel ${type} account ${accountId} added`,
859
864
  channelReEnabled: (type) => `Channel ${type} was disabled; it has been automatically re-enabled.`,
@@ -1154,10 +1159,11 @@ var init_session2 = __esm(() => {
1154
1159
  replyModeHeader: "当前 reply mode:",
1155
1160
  replyModeSessionLabel: (alias) => `- 会话:${alias}`,
1156
1161
  replyModeGlobalDefault: (value) => `- 全局默认:${value}`,
1162
+ replyModeChannelDefault: (value) => `- 频道默认:${value}`,
1157
1163
  replyModeSessionOverride: (value) => `- 当前会话覆盖:${value}`,
1158
1164
  replyModeEffective: (value) => `- 当前生效:${value}`,
1159
1165
  replyModeSet: (replyMode) => `已设置当前会话 reply mode:${replyMode}`,
1160
- replyModeReset: (globalDefault) => `已重置当前会话 reply mode,当前回退到全局默认:${globalDefault}`,
1166
+ replyModeReset: (effective) => `已重置当前会话 reply mode,当前生效:${effective}`,
1161
1167
  statusHeader: "当前会话:",
1162
1168
  statusNameLabel: (alias) => `- 名称:${alias}`,
1163
1169
  statusAgentLabel: (agent2) => `- Agent:${agent2}`,
@@ -1700,6 +1706,8 @@ var init_config2 = __esm(() => {
1700
1706
  mustBePositiveNumber: (path) => `${path} 必须是正数。`,
1701
1707
  channelTypeDisabled: "channel.type 是旧单频道字段,/config set 已禁用写入;请使用 `xacpx channel ...` 管理 channels[],然后重启 xacpx。",
1702
1708
  channelReplyModeInvalid: "channel.replyMode 只支持:stream、final、verbose",
1709
+ channelRuntimeNotFound: (id) => `频道「${id}」不存在;请先用 \`xacpx channel add ${id}\` 添加。`,
1710
+ channelRuntimeReplyModeInvalid: (id) => `channels.${id}.replyMode 只支持:stream、final、verbose`,
1703
1711
  wechatReplyModeInvalid: "wechat.replyMode 只支持:stream、final、verbose",
1704
1712
  wechatReplyModeMapped: (value) => `${value}(已映射到 channel.replyMode)`,
1705
1713
  agentNotFound: (name) => `Agent「${name}」不存在,请先创建。`,
@@ -1920,6 +1928,8 @@ var init_channel_cli2 = __esm(() => {
1920
1928
  channelRemoved: (id) => `频道 ${id} 已删除`,
1921
1929
  cannotDisableLastEnabled: "不能禁用最后一个启用的频道。",
1922
1930
  channelEnabledToggled: (id, enabled) => `频道 ${id} 已${enabled ? "启用" : "禁用"}`,
1931
+ channelReplyModeSet: (id, mode) => `频道 ${id} 的默认 reply mode 已设置为:${mode}`,
1932
+ channelReplyModeInvalid: (mode) => `reply mode 只支持 stream / final / verbose,收到:${mode}`,
1923
1933
  channelAccountAlreadyExists: (type, accountId) => `频道 ${type} 的账号 ${accountId} 已存在;先 xacpx channel rm ${type} --account ${accountId}`,
1924
1934
  channelAccountAdded: (type, accountId) => `频道 ${type} 账号 ${accountId} 已添加`,
1925
1935
  channelReEnabled: (type) => `频道 ${type} 此前是 disabled 状态,已自动启用。`,
@@ -2295,19 +2305,19 @@ function cmpTuple(a, b) {
2295
2305
  return 0;
2296
2306
  }
2297
2307
  function validatePluginCompatibility(metadata, context) {
2298
- const { packageName, currentWeacpxVersion } = context;
2308
+ const { packageName, currentXacpxVersion } = context;
2299
2309
  const apiVersion = metadata.apiVersion;
2300
2310
  if (typeof apiVersion !== "number") {
2301
2311
  throw new Error(t().pluginCli.compatMissingApiVersion(packageName));
2302
2312
  }
2303
- if (!WEACPX_PLUGIN_API_SUPPORTED_VERSIONS.includes(apiVersion)) {
2304
- const supported = WEACPX_PLUGIN_API_SUPPORTED_VERSIONS.join(", ");
2313
+ if (!XACPX_PLUGIN_API_SUPPORTED_VERSIONS.includes(apiVersion)) {
2314
+ const supported = XACPX_PLUGIN_API_SUPPORTED_VERSIONS.join(", ");
2305
2315
  throw new Error(t().pluginCli.compatUnsupportedApiVersion(packageName, apiVersion, supported));
2306
2316
  }
2307
- if (!currentWeacpxVersion || currentWeacpxVersion === "unknown") {
2317
+ if (!currentXacpxVersion || currentXacpxVersion === "unknown") {
2308
2318
  return;
2309
2319
  }
2310
- const normalizedCurrent = normalizeCoreVersionForCompat(currentWeacpxVersion);
2320
+ const normalizedCurrent = normalizeCoreVersionForCompat(currentXacpxVersion);
2311
2321
  const minVersion = metadata.minXacpxVersion ?? metadata.minWeacpxVersion;
2312
2322
  const minVersionField = metadata.minXacpxVersion !== undefined ? "minXacpxVersion" : "minWeacpxVersion";
2313
2323
  if (minVersion !== undefined) {
@@ -2322,7 +2332,7 @@ function validatePluginCompatibility(metadata, context) {
2322
2332
  throw new Error(t().pluginCli.compatInvalidMinVersionDetail(packageName, minVersionField, detail));
2323
2333
  }
2324
2334
  if (!satisfied) {
2325
- throw new Error(t().pluginCli.compatMinVersionNotSatisfied(packageName, minVersion, currentWeacpxVersion));
2335
+ throw new Error(t().pluginCli.compatMinVersionNotSatisfied(packageName, minVersion, currentXacpxVersion));
2326
2336
  }
2327
2337
  }
2328
2338
  const compatibleVersions = metadata.compatibleXacpxVersions ?? metadata.compatibleWeacpxVersions;
@@ -2339,14 +2349,17 @@ function validatePluginCompatibility(metadata, context) {
2339
2349
  throw new Error(t().pluginCli.compatInvalidCompatibleVersionsDetail(packageName, compatibleField, detail));
2340
2350
  }
2341
2351
  if (!satisfied) {
2342
- throw new Error(t().pluginCli.compatCompatibleVersionsNotSatisfied(packageName, compatibleVersions, currentWeacpxVersion));
2352
+ throw new Error(t().pluginCli.compatCompatibleVersionsNotSatisfied(packageName, compatibleVersions, currentXacpxVersion));
2343
2353
  }
2344
2354
  }
2345
2355
  }
2346
- var WEACPX_PLUGIN_API_VERSION = 1, WEACPX_PLUGIN_API_SUPPORTED_VERSIONS, WEACPX_PLUGIN_MIN_CORE_VERSION = "0.5.0", SEMVER_RE;
2356
+ 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;
2347
2357
  var init_compatibility = __esm(() => {
2348
2358
  init_i18n();
2349
- WEACPX_PLUGIN_API_SUPPORTED_VERSIONS = [1];
2359
+ XACPX_PLUGIN_API_SUPPORTED_VERSIONS = [1];
2360
+ WEACPX_PLUGIN_API_VERSION = XACPX_PLUGIN_API_VERSION;
2361
+ WEACPX_PLUGIN_API_SUPPORTED_VERSIONS = XACPX_PLUGIN_API_SUPPORTED_VERSIONS;
2362
+ WEACPX_PLUGIN_MIN_CORE_VERSION = XACPX_PLUGIN_MIN_CORE_VERSION;
2350
2363
  SEMVER_RE = /^(\d+)\.(\d+)\.(\d+)$/;
2351
2364
  });
2352
2365
 
@@ -2517,6 +2530,9 @@ export {
2517
2530
  getLocale,
2518
2531
  createConversationExecutor,
2519
2532
  createActiveTurnRegistry,
2533
+ XACPX_PLUGIN_MIN_CORE_VERSION,
2534
+ XACPX_PLUGIN_API_VERSION,
2535
+ XACPX_PLUGIN_API_SUPPORTED_VERSIONS,
2520
2536
  WEACPX_PLUGIN_MIN_CORE_VERSION,
2521
2537
  WEACPX_PLUGIN_API_VERSION,
2522
2538
  WEACPX_PLUGIN_API_SUPPORTED_VERSIONS
@@ -1,3 +1,6 @@
1
+ export declare const XACPX_PLUGIN_API_VERSION: 1;
2
+ export declare const XACPX_PLUGIN_API_SUPPORTED_VERSIONS: readonly number[];
3
+ export declare const XACPX_PLUGIN_MIN_CORE_VERSION: "0.5.0";
1
4
  export declare const WEACPX_PLUGIN_API_VERSION: 1;
2
5
  export declare const WEACPX_PLUGIN_API_SUPPORTED_VERSIONS: readonly number[];
3
6
  export declare const WEACPX_PLUGIN_MIN_CORE_VERSION: "0.5.0";
@@ -13,6 +16,6 @@ export interface PluginCompatibilityMetadata {
13
16
  }
14
17
  export interface PluginCompatibilityContext {
15
18
  packageName: string;
16
- currentWeacpxVersion: string;
19
+ currentXacpxVersion: string;
17
20
  }
18
21
  export declare function validatePluginCompatibility(metadata: PluginCompatibilityMetadata, context: PluginCompatibilityContext): void;
@@ -1,6 +1,6 @@
1
1
  import type { ChannelPluginDefinition } from "../channels/plugin.js";
2
- import { WEACPX_PLUGIN_API_VERSION, WEACPX_PLUGIN_API_SUPPORTED_VERSIONS, WEACPX_PLUGIN_MIN_CORE_VERSION } from "./compatibility.js";
3
- export { WEACPX_PLUGIN_API_VERSION, WEACPX_PLUGIN_API_SUPPORTED_VERSIONS, WEACPX_PLUGIN_MIN_CORE_VERSION, };
2
+ import { XACPX_PLUGIN_API_VERSION, XACPX_PLUGIN_API_SUPPORTED_VERSIONS, XACPX_PLUGIN_MIN_CORE_VERSION, WEACPX_PLUGIN_API_VERSION, WEACPX_PLUGIN_API_SUPPORTED_VERSIONS, WEACPX_PLUGIN_MIN_CORE_VERSION } from "./compatibility.js";
3
+ export { XACPX_PLUGIN_API_VERSION, XACPX_PLUGIN_API_SUPPORTED_VERSIONS, XACPX_PLUGIN_MIN_CORE_VERSION, WEACPX_PLUGIN_API_VERSION, WEACPX_PLUGIN_API_SUPPORTED_VERSIONS, WEACPX_PLUGIN_MIN_CORE_VERSION, };
4
4
  export interface WeacpxPlugin {
5
5
  apiVersion: 1;
6
6
  name?: string;
@@ -1,6 +1,6 @@
1
1
  import { type OrchestrationState } from "../orchestration/orchestration-types";
2
2
  import type { ScheduledTaskRecord } from "../scheduled/scheduled-types";
3
- export type LogicalSessionSource = "weacpx" | "agent-side";
3
+ export type LogicalSessionSource = "xacpx" | "agent-side";
4
4
  export interface NativeSessionCacheEntry {
5
5
  session_id: string;
6
6
  cwd?: string;
@@ -24,7 +24,7 @@ export interface ResolvedSession {
24
24
  agentCommand?: string;
25
25
  workspace: string;
26
26
  transportSession: string;
27
- source?: "weacpx" | "agent-side";
27
+ source?: "xacpx" | "agent-side";
28
28
  agentSessionId?: string;
29
29
  agentSessionTitle?: string;
30
30
  agentSessionUpdatedAt?: string;
@@ -124,6 +124,14 @@ export interface SessionTransport {
124
124
  listAgentSessions?(query: AgentSessionListQuery): Promise<AgentSessionListResult | undefined>;
125
125
  resumeAgentSession?(session: ResolvedSession, agentSessionId: string): Promise<void>;
126
126
  removeSession?(session: ResolvedSession): Promise<void>;
127
+ /**
128
+ * Read the underlying agent-native session id for an existing transport
129
+ * session. Used by `/clear` to keep a native session native: the fresh
130
+ * post-clear session is itself backed by a new agent rollout, and this
131
+ * returns that rollout's resumable id. Returns undefined when the agent did
132
+ * not advertise one. Optional: transports that can't resolve it omit it.
133
+ */
134
+ getAgentSessionId?(session: ResolvedSession): Promise<string | undefined>;
127
135
  updatePermissionPolicy?(policy: PermissionPolicy): Promise<void>;
128
136
  dispose?(): Promise<void>;
129
137
  }
package/dist/version.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  export declare function readVersion(moduleUrl?: string): string;
2
- /** weacpx 核心版本,派生自 package.json(经 readVersion 动态读取,无硬编码漂移)。 */
3
- export declare const WEACPX_CORE_VERSION: string;
2
+ /** xacpx 核心版本,派生自 package.json(经 readVersion 动态读取,无硬编码漂移)。 */
3
+ export declare const XACPX_CORE_VERSION: string;
@@ -62,7 +62,7 @@ export interface ChatRequestMetadata {
62
62
  senderName?: string;
63
63
  groupId?: string;
64
64
  isOwner?: boolean;
65
- /** Internal weacpx session alias to use for non-interactive scheduled prompts. */
65
+ /** Internal xacpx session alias to use for non-interactive scheduled prompts. */
66
66
  scheduledSessionAlias?: string;
67
67
  /** Transient session descriptor for temp-mode scheduled prompts (no persisted alias). */
68
68
  scheduledSessionDescriptor?: ScheduledSessionDescriptor;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ganglion/xacpx",
3
- "version": "0.9.1",
3
+ "version": "0.9.2",
4
4
  "description": "随时随地通过聊天频道(微信 / 飞书 / 元宝等)远程控制 `acpx` 上的 Claude Code、Codex 等 Agents。",
5
5
  "keywords": [
6
6
  "acpx",