@yu_robotics/remote-cli 1.6.74 → 1.6.84

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/README.md +27 -1
  2. package/dist/client/MessageHandler.d.ts +2 -0
  3. package/dist/client/MessageHandler.d.ts.map +1 -1
  4. package/dist/client/MessageHandler.js +136 -26
  5. package/dist/client/MessageHandler.js.map +1 -1
  6. package/dist/delegation/BackendRegistry.d.ts +22 -0
  7. package/dist/delegation/BackendRegistry.d.ts.map +1 -0
  8. package/dist/delegation/BackendRegistry.js +44 -0
  9. package/dist/delegation/BackendRegistry.js.map +1 -0
  10. package/dist/delegation/DelegationBridge.d.ts +14 -0
  11. package/dist/delegation/DelegationBridge.d.ts.map +1 -0
  12. package/dist/delegation/DelegationBridge.js +130 -0
  13. package/dist/delegation/DelegationBridge.js.map +1 -0
  14. package/dist/delegation/DelegationManager.d.ts +56 -0
  15. package/dist/delegation/DelegationManager.d.ts.map +1 -0
  16. package/dist/delegation/DelegationManager.js +346 -0
  17. package/dist/delegation/DelegationManager.js.map +1 -0
  18. package/dist/delegation/DelegationStore.d.ts +27 -0
  19. package/dist/delegation/DelegationStore.d.ts.map +1 -0
  20. package/dist/delegation/DelegationStore.js +114 -0
  21. package/dist/delegation/DelegationStore.js.map +1 -0
  22. package/dist/delegation/WorkerPolicy.d.ts +6 -0
  23. package/dist/delegation/WorkerPolicy.d.ts.map +1 -0
  24. package/dist/delegation/WorkerPolicy.js +35 -0
  25. package/dist/delegation/WorkerPolicy.js.map +1 -0
  26. package/dist/delegation/contract.d.ts +82 -0
  27. package/dist/delegation/contract.d.ts.map +1 -0
  28. package/dist/delegation/contract.js +68 -0
  29. package/dist/delegation/contract.js.map +1 -0
  30. package/dist/delegation/mcpServer.d.ts +2 -0
  31. package/dist/delegation/mcpServer.d.ts.map +1 -0
  32. package/dist/delegation/mcpServer.js +87 -0
  33. package/dist/delegation/mcpServer.js.map +1 -0
  34. package/dist/delegation/piExtension.d.ts +15 -0
  35. package/dist/delegation/piExtension.d.ts.map +1 -0
  36. package/dist/delegation/piExtension.js +42 -0
  37. package/dist/delegation/piExtension.js.map +1 -0
  38. package/dist/executor/AcpExecutor.d.ts +11 -0
  39. package/dist/executor/AcpExecutor.d.ts.map +1 -1
  40. package/dist/executor/AcpExecutor.js +77 -7
  41. package/dist/executor/AcpExecutor.js.map +1 -1
  42. package/dist/executor/AgyExecutor.d.ts +10 -0
  43. package/dist/executor/AgyExecutor.d.ts.map +1 -1
  44. package/dist/executor/AgyExecutor.js +82 -8
  45. package/dist/executor/AgyExecutor.js.map +1 -1
  46. package/dist/executor/ClaudePersistentExecutor.d.ts +5 -1
  47. package/dist/executor/ClaudePersistentExecutor.d.ts.map +1 -1
  48. package/dist/executor/ClaudePersistentExecutor.js +65 -38
  49. package/dist/executor/ClaudePersistentExecutor.js.map +1 -1
  50. package/dist/executor/CodexAppServerExecutor.d.ts +6 -0
  51. package/dist/executor/CodexAppServerExecutor.d.ts.map +1 -1
  52. package/dist/executor/CodexAppServerExecutor.js +26 -1
  53. package/dist/executor/CodexAppServerExecutor.js.map +1 -1
  54. package/dist/executor/CodexSandbox.d.ts +1 -1
  55. package/dist/executor/CodexSandbox.d.ts.map +1 -1
  56. package/dist/executor/CodexSandbox.js +5 -1
  57. package/dist/executor/CodexSandbox.js.map +1 -1
  58. package/dist/executor/IExecutor.d.ts +5 -0
  59. package/dist/executor/IExecutor.d.ts.map +1 -1
  60. package/dist/executor/KimiExecutor.d.ts +1 -0
  61. package/dist/executor/KimiExecutor.d.ts.map +1 -1
  62. package/dist/executor/KimiExecutor.js +1 -0
  63. package/dist/executor/KimiExecutor.js.map +1 -1
  64. package/dist/executor/OpenCodeExecutor.d.ts +1 -0
  65. package/dist/executor/OpenCodeExecutor.d.ts.map +1 -1
  66. package/dist/executor/OpenCodeExecutor.js +1 -0
  67. package/dist/executor/OpenCodeExecutor.js.map +1 -1
  68. package/dist/executor/PiExecutor.d.ts +7 -0
  69. package/dist/executor/PiExecutor.d.ts.map +1 -1
  70. package/dist/executor/PiExecutor.js +61 -12
  71. package/dist/executor/PiExecutor.js.map +1 -1
  72. package/dist/executor/ZCodeExecutor.d.ts +1 -0
  73. package/dist/executor/ZCodeExecutor.d.ts.map +1 -1
  74. package/dist/executor/ZCodeExecutor.js +1 -0
  75. package/dist/executor/ZCodeExecutor.js.map +1 -1
  76. package/dist/executor/acp/AcpClient.d.ts +11 -6
  77. package/dist/executor/acp/AcpClient.d.ts.map +1 -1
  78. package/dist/executor/acp/AcpClient.js +23 -7
  79. package/dist/executor/acp/AcpClient.js.map +1 -1
  80. package/dist/executor/acp/AcpTypes.d.ts +10 -0
  81. package/dist/executor/acp/AcpTypes.d.ts.map +1 -1
  82. package/dist/executor/agy/AgyDelegationConfig.d.ts +3 -0
  83. package/dist/executor/agy/AgyDelegationConfig.d.ts.map +1 -0
  84. package/dist/executor/agy/AgyDelegationConfig.js +105 -0
  85. package/dist/executor/agy/AgyDelegationConfig.js.map +1 -0
  86. package/dist/executor/index.d.ts +4 -1
  87. package/dist/executor/index.d.ts.map +1 -1
  88. package/dist/executor/index.js +10 -4
  89. package/dist/executor/index.js.map +1 -1
  90. package/dist/executor/pi/PiClient.d.ts +2 -0
  91. package/dist/executor/pi/PiClient.d.ts.map +1 -1
  92. package/dist/executor/pi/PiClient.js +43 -5
  93. package/dist/executor/pi/PiClient.js.map +1 -1
  94. package/dist/executor/pi/PiTypes.d.ts +3 -0
  95. package/dist/executor/pi/PiTypes.d.ts.map +1 -1
  96. package/dist/executor/pi/PiTypes.js +6 -0
  97. package/dist/executor/pi/PiTypes.js.map +1 -1
  98. package/dist/executor/zcode/ZCodeClient.d.ts +7 -3
  99. package/dist/executor/zcode/ZCodeClient.d.ts.map +1 -1
  100. package/dist/executor/zcode/ZCodeClient.js +13 -2
  101. package/dist/executor/zcode/ZCodeClient.js.map +1 -1
  102. package/dist/thread/ThreadExecutorPool.d.ts +7 -0
  103. package/dist/thread/ThreadExecutorPool.d.ts.map +1 -1
  104. package/dist/thread/ThreadExecutorPool.js +1 -0
  105. package/dist/thread/ThreadExecutorPool.js.map +1 -1
  106. package/dist/thread/ThreadManager.d.ts +1 -1
  107. package/dist/thread/ThreadManager.d.ts.map +1 -1
  108. package/dist/thread/ThreadManager.js.map +1 -1
  109. package/dist/thread/types.d.ts +4 -0
  110. package/dist/thread/types.d.ts.map +1 -1
  111. package/package.json +1 -1
package/README.md CHANGED
@@ -91,7 +91,7 @@ Linux users upgrading from version 1.6.23 or earlier should run `remote-cli serv
91
91
  | Command | Description |
92
92
  |---------|-------------|
93
93
  | `/help` | Show help information |
94
- | `/status` | Show backend, model, effort, queue, and thread status |
94
+ | `/status` | Show backend, model, effort, delegation, queue, and thread status |
95
95
  | `/context` | Show current session context and queue diagnostics |
96
96
  | `/skills` | List available skills for the active backend |
97
97
  | `/abort` | Abort executing task in current thread |
@@ -104,6 +104,7 @@ Linux users upgrading from version 1.6.23 or earlier should run `remote-cli serv
104
104
  | `/effort [auto|level]` | Show or set Codex/AGY/OpenCode/Kimi/ZCode/Pi reasoning effort |
105
105
  | `/sandbox [on/off/read-only/default]` | Configure the current Codex or Claude Code thread sandbox, directory grants, and networking |
106
106
  | `/backend` | List backends and show the current thread's effective backend |
107
+ | `/delegation [on|off]` | Inspect or enable delegation between installed agent backends in this thread |
107
108
  | `/backend <index>` | Switch all threads and clear per-thread backend overrides |
108
109
  | `/backend <index> @` | Switch only the current thread |
109
110
  | `/backend default @` | Clear the current thread override and follow the global backend |
@@ -113,6 +114,31 @@ Linux users upgrading from version 1.6.23 or earlier should run `remote-cli serv
113
114
 
114
115
  ### Threads & Machines
115
116
 
117
+ Use `/delegation on` in an existing thread to let its selected backend assign
118
+ bounded tasks to other installed, authenticated backends. Claude Code, Codex,
119
+ Pi, AGY, OpenCode, Kimi Code, and ZCode can coordinate or work, including sessions of
120
+ the same backend. Workers return results to the original conversation and use
121
+ its working directory; they do not create extra thread buttons. `/delegation`
122
+ shows discovery and restrictions; `/delegation off` disables the feature. The
123
+ setting is off by default and persists per thread. Start with one trial thread;
124
+ never-enabled threads skip managed tools, prompt changes, and delegation
125
+ configuration. Turning it off cleans only backends used for delegation, including
126
+ when resumed after a CLI restart or a backend switch, while preserving their
127
+ conversations.
128
+
129
+ `/status` shows `Delegation: on/off (current thread)` for the thread receiving
130
+ the command. Reading this setting does not initialize delegation or start workers.
131
+
132
+ Child progress, approvals, and questions use the existing reply flow. `/abort`
133
+ stops managed children as well as the parent. Sandboxed coordinators can delegate
134
+ only to the same backend; enforced read-only workers require Claude Code or Codex. There is one
135
+ active child per parent and at most three per CLI process, with overlapping
136
+ workspaces serialized and bounded time/output. Workspace reservations apply to
137
+ delegation-enabled work; opted-out threads keep ordinary workspace access, so
138
+ use separate workspaces for independent writers. See
139
+ [Cross-backend Delegation](../../README.md#cross-backend-delegation) for limits,
140
+ recovery, context transfer, and permission behavior.
141
+
116
142
  | Command | Description |
117
143
  |---------|-------------|
118
144
  | `/thread list/new/delete` | Manage session threads |
@@ -38,6 +38,8 @@ export declare class MessageHandler {
38
38
  private automaticUpdateInProgress;
39
39
  private approvalCardsSupported;
40
40
  private readonly pendingApprovalCards;
41
+ private readonly delegation;
42
+ private readonly delegationBridges;
41
43
  constructor(wsClient: WebSocketClient, threadPool: ThreadExecutorPool, threadManager: ThreadManager, directoryGuard: DirectoryGuard, config: ConfigManager);
42
44
  /**
43
45
  * Handle message (supports new IncomingMessage format)
@@ -1 +1 @@
1
- {"version":3,"file":"MessageHandler.d.ts","sourceRoot":"","sources":["../../src/client/MessageHandler.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"MessageHandler.d.ts","sourceRoot":"","sources":["../../src/client/MessageHandler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAwI,MAAM,UAAU,CAAC;AACjL,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAKxD,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAsGxD;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAkB;IAClC,OAAO,CAAC,UAAU,CAAqB;IACvC,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,aAAa,CAAC,CAAS;IAC/B,OAAO,CAAC,mBAAmB,CAA4B;IACvD,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,eAAe,CAA0C;IACjE,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAsC;IACnE,OAAO,CAAC,QAAQ,CAAC,yBAAyB,CAA+C;IACzF,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAqB;IAClD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAyC;IACxE,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAA4C;IACnF,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAoC;IACpE,OAAO,CAAC,yBAAyB,CAAS;IAC1C,OAAO,CAAC,sBAAsB,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAoG;IACzI,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAoB;IAC/C,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAuC;gBAGvE,QAAQ,EAAE,eAAe,EACzB,UAAU,EAAE,kBAAkB,EAC9B,aAAa,EAAE,aAAa,EAC5B,cAAc,EAAE,cAAc,EAC9B,MAAM,EAAE,aAAa;IAiBvB;;OAEG;IACG,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAgDtE,uBAAuB,IAAI,OAAO;IAoBlC,kBAAkB,IAAI,IAAI;IAI1B;;OAEG;YACW,oBAAoB;IAkOlC;;OAEG;YACW,kBAAkB;IAuDhC;;OAEG;YACW,iBAAiB;IAiB/B,OAAO,CAAC,cAAc;IAOtB;;;OAGG;YACW,oBAAoB;IA4YlC,OAAO,CAAC,uBAAuB;IAgC/B,OAAO,CAAC,+BAA+B;IAOvC,OAAO,CAAC,gBAAgB;IAaxB,OAAO,CAAC,cAAc;YASR,kBAAkB;YA0ElB,sBAAsB;IAkDpC,OAAO,CAAC,sBAAsB;IAU9B,OAAO,CAAC,oBAAoB;IAS5B,OAAO,CAAC,qBAAqB;IAS7B,OAAO,CAAC,mBAAmB;IAK3B;;;;;;;;;OASG;YACW,eAAe;IA+C7B;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAkCzB;;OAEG;YACW,mBAAmB;IA0GjC;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAS1B;;;OAGG;YACW,oBAAoB;IA6MlC;;OAEG;YACW,qBAAqB;IAiBnC;;OAEG;IACH,OAAO,CAAC,UAAU;IAuBlB;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAO9B;;;;;;OAMG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,wBAAwB,CAG7C;YAEW,eAAe;IAgC7B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAI3B;;;;;;;;;;;;;OAaG;YACW,mBAAmB;IAyDjC;;;OAGG;IACH,OAAO,CAAC,uBAAuB;IA2D/B;;OAEG;YACW,cAAc;YAoJd,sBAAsB;IAoBpC,OAAO,CAAC,4BAA4B;IAOpC,OAAO,CAAC,gBAAgB;IAIxB,OAAO,CAAC,SAAS;IASjB,OAAO,CAAC,eAAe;IAWvB,OAAO,CAAC,mBAAmB;IAI3B,OAAO,CAAC,oBAAoB;IAQ5B,OAAO,CAAC,mBAAmB;IAQ3B,OAAO,CAAC,sBAAsB;IAuB9B,OAAO,CAAC,eAAe;IAgBvB,OAAO,CAAC,WAAW;IAgBnB,OAAO,CAAC,cAAc;IAgBtB,OAAO,CAAC,oBAAoB;IAe5B,OAAO,CAAC,YAAY;IAgBpB,OAAO,CAAC,SAAS;IAgBjB,OAAO,CAAC,qBAAqB;IAmB7B,OAAO,CAAC,YAAY;IA6CpB,OAAO,CAAC,YAAY;YAMN,cAAc;YAqBd,oBAAoB;IAkHlC;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAa/B"}
@@ -7,11 +7,15 @@ const LocalImageDetector_1 = require("../utils/LocalImageDetector");
7
7
  const MachineCommands_1 = require("../machines/MachineCommands");
8
8
  const child_process_1 = require("child_process");
9
9
  const promises_1 = require("fs/promises");
10
+ const fs_1 = require("fs");
10
11
  const os_1 = require("os");
11
12
  const path_1 = require("path");
12
13
  const config_1 = require("../types/config");
13
14
  const uuid_1 = require("uuid");
14
15
  const ZCodeCommand_1 = require("../executor/zcode/ZCodeCommand");
16
+ const DelegationManager_1 = require("../delegation/DelegationManager");
17
+ const DelegationBridge_1 = require("../delegation/DelegationBridge");
18
+ const contract_1 = require("../delegation/contract");
15
19
  const EFFORT_BACKENDS = new Set(['codex', 'agy', 'opencode', 'kimi', 'zcode', 'pi']);
16
20
  const NATIVE_MODEL_LIST_BACKENDS = new Set(['codex', 'opencode', 'kimi', 'zcode', 'pi']);
17
21
  const SLASH_SESSION_BACKENDS = new Set(['opencode', 'kimi', 'zcode', 'pi']);
@@ -89,12 +93,15 @@ class MessageHandler {
89
93
  automaticUpdateInProgress = false;
90
94
  approvalCardsSupported = false;
91
95
  pendingApprovalCards = new Map();
96
+ delegation;
97
+ delegationBridges = new Map();
92
98
  constructor(wsClient, threadPool, threadManager, directoryGuard, config) {
93
99
  this.wsClient = wsClient;
94
100
  this.threadPool = threadPool;
95
101
  this.threadManager = threadManager;
96
102
  this.directoryGuard = directoryGuard;
97
103
  this.config = config;
104
+ this.delegation = new DelegationManager_1.DelegationManager(directoryGuard);
98
105
  this.notificationAdapter = new hooks_1.FeishuNotificationAdapter(wsClient);
99
106
  this.notificationAdapter.setThreadNameResolver((threadId) => this.threadManager.getThread(threadId)?.name);
100
107
  this.notificationAdapter.register();
@@ -242,9 +249,10 @@ class MessageHandler {
242
249
  await this.handleBackendCommand(messageId, resolvedThreadId, content.trim());
243
250
  return;
244
251
  }
245
- // Check if executor is waiting for interactive input
246
- if ('isWaitingInput' in executor && typeof executor.isWaitingInput === 'function') {
247
- const ex = executor;
252
+ // Child input belongs to the child executor, even though the parent owns the thread.
253
+ const inputExecutor = this.delegation.waitingExecutor(resolvedThreadId) ?? executor;
254
+ if ('isWaitingInput' in inputExecutor && typeof inputExecutor.isWaitingInput === 'function') {
255
+ const ex = inputExecutor;
248
256
  if (ex.isWaitingInput()) {
249
257
  const input = content?.trim();
250
258
  if (input) {
@@ -308,6 +316,7 @@ class MessageHandler {
308
316
  return;
309
317
  }
310
318
  const queueSensitiveCommand = /^\/(?:clear|new|compact|cd|model|effort|sandbox)(?:\s|$)/.test(content?.trim() ?? '')
319
+ || /^\/delegation\s+(?:on|off)(?:\s|$)/.test(content?.trim() ?? '')
311
320
  || /^\/thread\s+delete(?:\s|$)/.test(content?.trim() ?? '');
312
321
  if (queueSensitiveCommand && this.hasThreadQueueState(resolvedThreadId)) {
313
322
  this.sendResponse(messageId, resolvedThreadId, {
@@ -384,6 +393,8 @@ class MessageHandler {
384
393
  const activeOperation = this.activeThreadOperations.get(threadId);
385
394
  let aborted = false;
386
395
  const operation = (async () => {
396
+ if (this.threadManager.getThread(threadId)?.delegation)
397
+ await this.delegation.cancelThread(threadId);
387
398
  aborted = await executor.abort();
388
399
  if (activeOperation)
389
400
  await activeOperation.done;
@@ -453,6 +464,51 @@ class MessageHandler {
453
464
  */
454
465
  async handleBuiltInCommand(messageId, threadId, content, executor) {
455
466
  const trimmed = content.trim();
467
+ if (trimmed === '/delegation' || trimmed.startsWith('/delegation ')) {
468
+ const argument = trimmed.slice('/delegation'.length).trim();
469
+ if (argument && argument !== 'on' && argument !== 'off') {
470
+ this.sendResponse(messageId, threadId, { success: false, error: 'Usage: /delegation [on|off]' });
471
+ return true;
472
+ }
473
+ if (argument === 'on' && !executor.configureDelegation) {
474
+ this.sendResponse(messageId, threadId, { success: false, error: 'This executor does not support delegation tool registration.' });
475
+ return true;
476
+ }
477
+ if (argument) {
478
+ if (argument === 'off') {
479
+ const thread = this.threadManager.getThread(threadId);
480
+ const backend = this.threadPool.getBackendKey(threadId);
481
+ if (thread.delegationBackends?.includes(backend) || (thread.delegation && !thread.delegationBackends)) {
482
+ await executor.configureDelegation?.(undefined);
483
+ // Preserve cleanup ownership across process recreation and backend switches.
484
+ if (!thread.delegationBackends)
485
+ await this.threadManager.updateThread(threadId, { delegationBackends: [backend] });
486
+ }
487
+ await this.delegationBridges.get(threadId)?.close();
488
+ this.delegationBridges.delete(threadId);
489
+ }
490
+ await this.threadManager.updateThread(threadId, { delegation: argument === 'on' });
491
+ }
492
+ const config = this.config.get('executor') ?? { type: 'auto' };
493
+ const backends = await this.delegation.registry.list(config);
494
+ this.sendResponse(messageId, threadId, { success: true, output: [
495
+ `Delegation: ${this.threadManager.getThread(threadId)?.delegation ? 'on' : 'off'}`,
496
+ `Coordinator: ${executor.configureDelegation ? backendDisplayName(this.threadPool.getBackendKey(threadId)) : 'unsupported for this backend'}`,
497
+ ...(this.threadPool.getBackendKey(threadId) === 'zcode'
498
+ ? ['ZCode delegation temporarily replaces user-configured MCP servers. Native tools and plugins remain available; /delegation off restores the normal MCP configuration.'] : []),
499
+ ...backends.map(item => `${item.backend}: ${item.installed ? item.version : item.reason}`),
500
+ 'Authentication and quota are checked when a task runs. Sandboxed coordinators can delegate only to the same backend. Enforced read-only workers are available only for Claude Code and Codex.',
501
+ 'Usage: /delegation on|off. Applies to this thread; workers use independent sessions.',
502
+ ].join('\n') });
503
+ return true;
504
+ }
505
+ if (trimmed.startsWith('/')) {
506
+ const thread = this.threadManager.getThread(threadId);
507
+ if (!thread?.delegation && thread?.delegationBackends?.includes(this.threadPool.getBackendKey(threadId))) {
508
+ // Native slash commands can resume a session before the next ordinary turn.
509
+ await executor.configureDelegation?.(undefined);
510
+ }
511
+ }
456
512
  if (trimmed === '/sandbox' || trimmed.startsWith('/sandbox ')) {
457
513
  if (!('getSandboxStatus' in executor) || !('configureSandbox' in executor)) {
458
514
  this.sendResponse(messageId, threadId, { success: false, error: '/sandbox is currently supported by the Codex and Claude Code backends.' });
@@ -497,6 +553,7 @@ class MessageHandler {
497
553
  output: `📊 Status:
498
554
  - Thread: ${thread?.name ?? threadId}
499
555
  - Backend: ${backend}
556
+ - Delegation: ${thread?.delegation ? 'on' : 'off'} (current thread)
500
557
  - Model: ${model ?? 'backend default'}
501
558
  - Reasoning effort: ${effort}
502
559
  - Working Directory: ${cwd}
@@ -567,6 +624,7 @@ Use /compact to reduce conversation context or /clear to start a fresh context.`
567
624
  - /model [name] - Show models for the active backend, or set this thread's model
568
625
  - /effort [auto|level] - Show or set effort for Codex/AGY/OpenCode/Kimi/ZCode/Pi (Claude Code is unsupported)
569
626
  - /sandbox [on|off|read-only|default|allow <directory>|remove <directory>|network on|off] - Configure this thread's sandbox (Codex, Claude Code)
627
+ - /delegation [on|off] - Delegate tasks between installed agent backends in this thread
570
628
  - /backend - List backends and show the current thread's effective backend
571
629
  - /backend <index> - Switch all threads and clear per-thread backend overrides
572
630
  - /backend <index> @ - Switch only the current thread
@@ -1143,6 +1201,12 @@ You can also use natural language commands to control Claude Code CLI.`,
1143
1201
  return;
1144
1202
  }
1145
1203
  try {
1204
+ if (target.delegation || target.delegationBackends?.length) {
1205
+ await this.delegation.cancelThread(target.id);
1206
+ await this.delegationBridges.get(target.id)?.close();
1207
+ this.delegationBridges.delete(target.id);
1208
+ await this.delegation.store.deleteThread(target.id);
1209
+ }
1146
1210
  await this.threadPool.destroyThread(target.id);
1147
1211
  await this.threadManager.deleteThread(target.id);
1148
1212
  this.sendResponse(messageId, callerThreadId, {
@@ -1407,7 +1471,7 @@ You can also use natural language commands to control Claude Code CLI.`,
1407
1471
  * its own --print invocation").
1408
1472
  */
1409
1473
  static AGY_PASSTHROUGH_COMMANDS = new Set([
1410
- '/help', '/model', '/skills', '/usage', '/config', '/changelog',
1474
+ '/help', '/model', '/skills', '/usage', '/quota', '/config', '/changelog',
1411
1475
  '/agents', '/permissions', '/hooks', '/credits',
1412
1476
  ]);
1413
1477
  async listLocalSkills(cwd, backend) {
@@ -1482,7 +1546,7 @@ You can also use natural language commands to control Claude Code CLI.`,
1482
1546
  if (backend === 'codex') {
1483
1547
  this.sendResponse(messageId, threadId, {
1484
1548
  success: false,
1485
- error: `❌ "${command}" is not exposed as a Codex backend command.\n\nBuilt-in commands (/clear, /compact, /model, /effort, /cd, /thread, /backend, /abort, /status, /help) work on the supported backends.`,
1549
+ error: `❌ "${command}" is not exposed as a Codex backend command.\n\nBuilt-in commands (/clear, /compact, /model, /effort, /cd, /thread, /backend, /delegation, /abort, /status, /help) work on the supported backends.`,
1486
1550
  });
1487
1551
  return;
1488
1552
  }
@@ -1561,7 +1625,12 @@ You can also use natural language commands to control Claude Code CLI.`,
1561
1625
  * Execute AI command on a specific executor
1562
1626
  */
1563
1627
  async executeCommand(messageId, threadId, content, executor, attachments, fromQueue = false) {
1564
- const complete = (success, error) => {
1628
+ let delegationScope;
1629
+ let delegationBridge;
1630
+ const complete = async (success, error) => {
1631
+ delegationBridge?.activate(undefined);
1632
+ if (delegationScope)
1633
+ await delegationScope.close();
1565
1634
  const responseError = fromQueue && !success
1566
1635
  ? this.pauseQueueAfterFailure(threadId, error || 'Queued command failed') : error;
1567
1636
  this.sendResponse(messageId, threadId, { success, error: responseError, threads: this.threadPool.getSummaries() });
@@ -1571,6 +1640,47 @@ You can also use natural language commands to control Claude Code CLI.`,
1571
1640
  };
1572
1641
  try {
1573
1642
  const openId = this.getMessageOpenId(messageId);
1643
+ const thread = this.threadManager.getThread(threadId);
1644
+ if (thread?.delegation && executor.configureDelegation) {
1645
+ if (this.delegation.blocksWorkspace(executor.getCurrentWorkingDirectory(), threadId)) {
1646
+ throw new Error('A delegated worker holds this workspace. Wait for it to finish; if worker cleanup failed, stop the worker and restart the CLI.');
1647
+ }
1648
+ const backend = this.threadPool.getBackendKey(threadId);
1649
+ if (!thread.delegationBackends?.includes(backend)) {
1650
+ await this.threadManager.updateThread(threadId, { delegationBackends: [...(thread.delegationBackends ?? []), backend] });
1651
+ }
1652
+ delegationScope = this.delegation.begin({ thread, messageId,
1653
+ backend: this.threadPool.getBackendKey(threadId),
1654
+ config: this.config.get('executor') ?? { type: 'auto' },
1655
+ cwd: executor.getCurrentWorkingDirectory(),
1656
+ onToolUse: tool => this.sendToolUse(messageId, threadId, tool),
1657
+ onToolResult: result => this.sendToolResult(messageId, threadId, result),
1658
+ onNotice: text => this.sendStreamChunk(messageId, threadId, text),
1659
+ onApproval: (request, child) => this.forwardApproval(request, child, messageId, threadId, true),
1660
+ onApprovalResolved: (id, status) => this.resolveApprovalCard(id, status),
1661
+ isWorkspaceBusy: cwd => this.threadManager.listThreads().some(other => {
1662
+ if (other.id === threadId || !this.threadPool.isThreadBusy(other.id))
1663
+ return false;
1664
+ try {
1665
+ return (0, DelegationManager_1.workspacesOverlap)((0, fs_1.realpathSync)(this.threadPool.getExecutor(other.id).getCurrentWorkingDirectory()), cwd);
1666
+ }
1667
+ catch {
1668
+ return true;
1669
+ }
1670
+ }), });
1671
+ delegationBridge = this.delegationBridges.get(threadId) ?? new DelegationBridge_1.DelegationBridge();
1672
+ this.delegationBridges.set(threadId, delegationBridge);
1673
+ const connection = await delegationBridge.start();
1674
+ delegationBridge.activate(delegationScope.invoke);
1675
+ await executor.configureDelegation(connection);
1676
+ if (delegationScope.isClosed() || this.isDestroyed || this.abortOperations.has(threadId)) {
1677
+ throw new Error('Delegation was cancelled before the coordinator started');
1678
+ }
1679
+ content = `${contract_1.DELEGATION_INSTRUCTIONS}\n\nUser request:\n${content}`;
1680
+ }
1681
+ else if (thread?.delegationBackends?.includes(this.threadPool.getBackendKey(threadId)) && executor.configureDelegation) {
1682
+ await executor.configureDelegation(undefined);
1683
+ }
1574
1684
  const onTaskNotification = (notification) => {
1575
1685
  if (this.isDestroyed || !this.threadManager.getThread(threadId))
1576
1686
  return;
@@ -1578,6 +1688,7 @@ You can also use natural language commands to control Claude Code CLI.`,
1578
1688
  };
1579
1689
  const emittedLocalImages = new Set();
1580
1690
  const pendingLocalImageEmissions = new Set();
1691
+ const delegationControlTools = new Set();
1581
1692
  let streamedOutput = '';
1582
1693
  const emitLocalImages = async (text) => {
1583
1694
  const thread = this.threadManager.getThread(threadId);
@@ -1607,8 +1718,16 @@ You can also use natural language commands to control Claude Code CLI.`,
1607
1718
  streamedOutput += chunk;
1608
1719
  this.sendStreamChunk(messageId, threadId, chunk);
1609
1720
  },
1610
- onToolUse: (toolUse) => this.sendToolUse(messageId, threadId, toolUse),
1721
+ onToolUse: (toolUse) => {
1722
+ if (delegationScope && /remote_cli_(list_backends|delegate|result|cancel)$/.test(toolUse.name)) {
1723
+ delegationControlTools.add(toolUse.id);
1724
+ return;
1725
+ }
1726
+ this.sendToolUse(messageId, threadId, toolUse);
1727
+ },
1611
1728
  onToolResult: (toolResult) => {
1729
+ if (delegationControlTools.delete(toolResult.tool_use_id))
1730
+ return;
1612
1731
  this.sendToolResult(messageId, threadId, toolResult);
1613
1732
  queueLocalImages(toolResult.content);
1614
1733
  },
@@ -1634,22 +1753,8 @@ You can also use natural language commands to control Claude Code CLI.`,
1634
1753
  return complete(false, `❌ Auto-compact failed: ${compactResult.error}\n\nUse /compact to try again, or /clear to start fresh.`);
1635
1754
  }
1636
1755
  this.sendStreamChunk(messageId, threadId, '✅ Compaction done. Retrying your request...\n');
1637
- const retryResult = await executor.execute(content, {
1638
- onTaskNotification,
1639
- onStream: (chunk) => {
1640
- streamedOutput += chunk;
1641
- this.sendStreamChunk(messageId, threadId, chunk);
1642
- },
1643
- onToolUse: (toolUse) => this.sendToolUse(messageId, threadId, toolUse),
1644
- onToolResult: (toolResult) => {
1645
- this.sendToolResult(messageId, threadId, toolResult);
1646
- queueLocalImages(toolResult.content);
1647
- },
1648
- onRedactedThinking: () => this.sendRedactedThinking(messageId, threadId),
1649
- onPlanMode: (planContent) => this.sendPlanMode(messageId, threadId, planContent),
1650
- onImage: (image) => this.sendImage(messageId, threadId, image),
1651
- attachments,
1652
- });
1756
+ const { onApprovalRequest, onApprovalResolved, ...ordinaryRetryOptions } = executeOptions;
1757
+ const retryResult = await executor.execute(content, delegationScope ? executeOptions : ordinaryRetryOptions);
1653
1758
  await Promise.all(pendingLocalImageEmissions);
1654
1759
  await emitLocalImages(`${streamedOutput}\n${retryResult.output ?? ''}`);
1655
1760
  return complete(retryResult.success, retryResult.error);
@@ -1694,14 +1799,14 @@ You can also use natural language commands to control Claude Code CLI.`,
1694
1799
  backend: this.threadPool.getBackendKey(threadId),
1695
1800
  cwd: this.threadPool.getExecutor(threadId).getCurrentWorkingDirectory(), preview: content });
1696
1801
  }
1697
- forwardApproval(approval, executor, taskMessageId, threadId) {
1802
+ forwardApproval(approval, executor, taskMessageId, threadId, delegated = false) {
1698
1803
  const openId = this.getMessageOpenId(taskMessageId);
1699
1804
  if (!openId)
1700
1805
  return false;
1701
1806
  const request = { type: 'approval_request', messageId: approval.requestId,
1702
1807
  taskMessageId, openId, threadId, threadName: this.threadManager.getThread(threadId)?.name ?? threadId,
1703
1808
  cwd: executor.getCurrentWorkingDirectory(), approval, timestamp: Date.now() };
1704
- this.pendingApprovalCards.set(approval.requestId, { request, executor });
1809
+ this.pendingApprovalCards.set(approval.requestId, { request, executor, delegated });
1705
1810
  if (this.approvalCardsSupported)
1706
1811
  this.sendApprovalMessage(request);
1707
1812
  return this.approvalCardsSupported;
@@ -1738,7 +1843,9 @@ You can also use natural language commands to control Claude Code CLI.`,
1738
1843
  }
1739
1844
  let accepted = false;
1740
1845
  try {
1741
- accepted = pending.executor.respondToApproval?.(message.messageId, message.action) === true;
1846
+ if (!pending.delegated || message.action !== 'remember' || pending.request.approval.canRemember) {
1847
+ accepted = pending.executor.respondToApproval?.(message.messageId, message.action) === true;
1848
+ }
1742
1849
  }
1743
1850
  catch { /* Report failure without approving another request. */ }
1744
1851
  if (accepted) {
@@ -2025,6 +2132,9 @@ You can also use natural language commands to control Claude Code CLI.`,
2025
2132
  this.isDestroyed = true;
2026
2133
  this.notificationAdapter.unregister();
2027
2134
  try {
2135
+ await this.delegation.destroy();
2136
+ await Promise.all([...this.delegationBridges.values()].map(bridge => bridge.close()));
2137
+ this.delegationBridges.clear();
2028
2138
  await this.threadPool.destroyAll({ deleteData: false });
2029
2139
  this.pendingApprovalCards.clear();
2030
2140
  }