@yu_robotics/remote-cli 1.6.158 → 1.6.165

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 (66) hide show
  1. package/README.md +10 -3
  2. package/dist/client/MessageHandler.d.ts +4 -5
  3. package/dist/client/MessageHandler.d.ts.map +1 -1
  4. package/dist/client/MessageHandler.js +102 -9
  5. package/dist/client/MessageHandler.js.map +1 -1
  6. package/dist/commands/config.d.ts.map +1 -1
  7. package/dist/commands/config.js +15 -0
  8. package/dist/commands/config.js.map +1 -1
  9. package/dist/commands/session.d.ts +17 -0
  10. package/dist/commands/session.d.ts.map +1 -0
  11. package/dist/commands/session.js +37 -0
  12. package/dist/commands/session.js.map +1 -0
  13. package/dist/delegation/GitCheckpoint.d.ts +1 -0
  14. package/dist/delegation/GitCheckpoint.d.ts.map +1 -1
  15. package/dist/delegation/GitCheckpoint.js +15 -4
  16. package/dist/delegation/GitCheckpoint.js.map +1 -1
  17. package/dist/executor/IExecutor.d.ts +21 -0
  18. package/dist/executor/IExecutor.d.ts.map +1 -1
  19. package/dist/executor/PiExecutor.d.ts +26 -1
  20. package/dist/executor/PiExecutor.d.ts.map +1 -1
  21. package/dist/executor/PiExecutor.js +256 -15
  22. package/dist/executor/PiExecutor.js.map +1 -1
  23. package/dist/index.js +19 -0
  24. package/dist/index.js.map +1 -1
  25. package/dist/maintenance/release-notes.json +1 -1
  26. package/dist/session/SessionCatalog.d.ts +76 -0
  27. package/dist/session/SessionCatalog.d.ts.map +1 -0
  28. package/dist/session/SessionCatalog.js +197 -0
  29. package/dist/session/SessionCatalog.js.map +1 -0
  30. package/dist/session/SessionControl.d.ts +56 -0
  31. package/dist/session/SessionControl.d.ts.map +1 -0
  32. package/dist/session/SessionControl.js +262 -0
  33. package/dist/session/SessionControl.js.map +1 -0
  34. package/dist/session/SessionLocalInfo.d.ts +48 -0
  35. package/dist/session/SessionLocalInfo.d.ts.map +1 -0
  36. package/dist/session/SessionLocalInfo.js +145 -0
  37. package/dist/session/SessionLocalInfo.js.map +1 -0
  38. package/dist/session/SessionMenu.d.ts +102 -0
  39. package/dist/session/SessionMenu.d.ts.map +1 -0
  40. package/dist/session/SessionMenu.js +144 -0
  41. package/dist/session/SessionMenu.js.map +1 -0
  42. package/dist/session/SessionResumeService.d.ts +38 -0
  43. package/dist/session/SessionResumeService.d.ts.map +1 -0
  44. package/dist/session/SessionResumeService.js +147 -0
  45. package/dist/session/SessionResumeService.js.map +1 -0
  46. package/dist/session/adapters/ClaudeSessionCatalog.d.ts +10 -0
  47. package/dist/session/adapters/ClaudeSessionCatalog.d.ts.map +1 -0
  48. package/dist/session/adapters/ClaudeSessionCatalog.js +156 -0
  49. package/dist/session/adapters/ClaudeSessionCatalog.js.map +1 -0
  50. package/dist/session/adapters/CodexSessionCatalog.d.ts +9 -0
  51. package/dist/session/adapters/CodexSessionCatalog.d.ts.map +1 -0
  52. package/dist/session/adapters/CodexSessionCatalog.js +214 -0
  53. package/dist/session/adapters/CodexSessionCatalog.js.map +1 -0
  54. package/dist/session/adapters/PiSessionCatalog.d.ts +52 -0
  55. package/dist/session/adapters/PiSessionCatalog.d.ts.map +1 -0
  56. package/dist/session/adapters/PiSessionCatalog.js +252 -0
  57. package/dist/session/adapters/PiSessionCatalog.js.map +1 -0
  58. package/dist/session/adapters/index.d.ts +13 -0
  59. package/dist/session/adapters/index.d.ts.map +1 -0
  60. package/dist/session/adapters/index.js +17 -0
  61. package/dist/session/adapters/index.js.map +1 -0
  62. package/dist/types/config.d.ts +11 -0
  63. package/dist/types/config.d.ts.map +1 -1
  64. package/dist/types/config.js +3 -0
  65. package/dist/types/config.js.map +1 -1
  66. package/package.json +1 -1
package/README.md CHANGED
@@ -178,7 +178,7 @@ Linux users upgrading from version 1.6.23 or earlier should run `remote-cli serv
178
178
  | `/model [name]` | Open native model settings, or set the active backend model with a text argument |
179
179
  | `/effort [auto|level]` | Open native effort settings, or set/clear the active backend effort with a text argument |
180
180
  | `/sandbox [on/off/read-only/default]` | Configure the current Codex or Claude Code thread sandbox, directory grants, and networking |
181
- | `/backend` | Open backend settings; Current thread is the default and Confirm applies the selection |
181
+ | `/backend` | Open backend settings; click a backend to switch immediately, defaulting to Current thread |
182
182
  | `/delegation [on|off]` | Inspect or enable delegation between installed agent backends in this thread |
183
183
  | `/backend <index>` | Switch all threads and clear per-thread backend overrides |
184
184
  | `/backend <index> @` | Switch only the current thread |
@@ -187,9 +187,9 @@ Linux users upgrading from version 1.6.23 or earlier should run `remote-cli serv
187
187
  | `/unbind` | Unbind all devices |
188
188
  | `/device` | List and switch between bound devices |
189
189
 
190
- CLI and Router 1.6.152 add standalone settings cards. `/backend` lists all eight stable backend choices, disables missing installations and applies only after Confirm; Current thread is the default and All threads on this device is opt-in. `/model` and `/effort` submit native options immediately, and show applied state only after a saved-setting acknowledgement. Their target-backend selector configures future worker launches without switching the coordinator. Busy work, expired cards and changed settings require refresh; older peers and parameterized text commands retain their existing behavior. See [Model and Reasoning Effort](../../README.md#model-and-reasoning-effort).
190
+ CLI and Router 1.6.152 add standalone settings cards. `/backend` lists all eight stable backend choices, disables missing installations and defaults to Current thread, with All threads on this device opt-in. From Router 1.6.160, clicking a backend submits immediately without Confirm; scope controls only set the next click's target. Scope persists in the same card across backend acknowledgements, while a new card defaults to Current thread. Follow global applies immediately to the original thread and restores Current thread scope after acknowledgement. `/model` and `/effort` submit native options immediately, and show applied state only after a saved-setting acknowledgement. Their target-backend selector configures future worker launches without switching the coordinator. Busy work, expired cards and changed settings require refresh; older peers and parameterized text commands retain their existing behavior. See [Model and Reasoning Effort](../../README.md#model-and-reasoning-effort).
191
191
 
192
- From 1.6.154, numbered sections separate backend selection, scope and Confirm, or target backend, model/effort choices and secondary actions. Selected drafts and known preferences carry explicit checks; changing the target still never switches the coordinator. AGY model catalogs accept tab-delimited and formatted multi-space native rows, with exact IDs and explicit failures for empty, unusable or oversized responses. No inference or additional protocol capability is needed.
192
+ From 1.6.154, numbered sections separate backend selection above scope (Confirm removed in Router 1.6.160), or target backend, model/effort choices and secondary actions. The acknowledged backend, selected scope and known preferences carry explicit checks; changing the target still never switches the coordinator. AGY model catalogs accept tab-delimited and formatted multi-space native rows, with exact IDs and explicit failures for empty, unusable or oversized responses. No inference or additional protocol capability is needed.
193
193
 
194
194
  From Router 1.6.155, the selected backend application scope is highlighted in blue, and model/effort target selectors separate the main backend from other backends' worker preferences. Choices are shown together when the complete card fits its node and byte budgets; only oversized catalogs paginate, with headers, groups and pending/retry controls included. Viewing a target never changes the coordinator, and same-backend workers continue to share its per-thread preference. Existing CLI settings metadata is sufficient; no new capability or native request is required.
195
195
 
@@ -328,6 +328,7 @@ source reservations remain held until owned operations settle, even on cancellat
328
328
  no late worker is launched. Failed collection after confirmed exit preserves only
329
329
  the affected lane and files for recovery rather than quarantining the source.
330
330
  Individual Git command deadlines remain; cancellation may wait for Git to settle.
331
+ From CLI 1.6.159, delegated `git worktree add` and `git checkout` commands have a 120-second deadline per command. Other Git commands, including worktree listing/removal and nested object transfers, retain their 15-second deadlines. Git command timeout errors show the operation, elapsed milliseconds and deadline without paths or checkout references. Preparation remains pending until the Git child exits; cancellation can wait for this bounded cleanup, and the existing task ID remains available for polling.
331
332
  Slow launch/cancel tools return the accepted task ID and a pending status before
332
333
  the adapter timeout; poll that ID with `remote_cli_result`, not a new delegation.
333
334
  The response does not claim cancellation cleanup or workspace release is complete.
@@ -451,6 +452,12 @@ Claude Code also supports opt-in `/sandbox` policies. Workspace-write mode autom
451
452
  - **Device authentication**: Each device has a unique hardware-based ID
452
453
  - **Binding codes**: Expire after 5 minutes
453
454
 
455
+ ## Session Resume
456
+
457
+ CLI 1.6.164 supports confirmed Pi native session connections and read-only Pi/Codex/Claude Code discovery. Adopted Pi history reloads before every remote turn; `/session detach` preserves it and `/session release` is removed. Foreground Pi `/new` and `/clear` also preserve old history and start independent IDs; new default names use native session IDs and persisted names are not overwritten on reopen. Worker/metadata cleanup is unchanged. Resume drafts keep ordinary messages in the current conversation until confirmation succeeds. Use only one side at a time. Local Pi windows may stay open but must use native `/resume` before their next local turn; automatic local refresh and writer locking are not provided. Existing Router command/response envelopes support the text workflow without a new wire capability. See the [session resume specification](../../SESSION_RESUME_SPEC.md).
458
+
459
+ From CLI 1.6.165, Pi connection and detach confirmations exclude simultaneous settings/context mutations and reject queued work, active delegated tasks, and automatic updates. One daemon reserves a selected Pi file before startup; successful connection/detach requires pointer persistence. Failed writes keep the previous association. Uncertain process cleanup keeps the selected file reserved; confirm Pi has exited before restarting the client to clear that quarantine. Discovery respects `PI_CODING_AGENT_DIR`, and Pi local reopen commands quote file paths. These guards do not lock unmanaged terminals or other CLI instances. Claude Code and Codex catalogs remain read-only; their executor, settings, and history behavior is unchanged.
460
+
454
461
  ## Documentation
455
462
 
456
463
  For full documentation including router server deployment, see the [project README](https://github.com/Yu-Robotics/remote-cli#readme).
@@ -13,11 +13,6 @@ export interface Message {
13
13
  content?: string;
14
14
  timestamp?: number;
15
15
  }
16
- /**
17
- * Thread-aware Message Handler.
18
- * Each thread has its own executor process managed by ThreadExecutorPool.
19
- * Commands without a threadId are routed to the default thread.
20
- */
21
16
  export declare class MessageHandler {
22
17
  private wsClient;
23
18
  private threadPool;
@@ -33,6 +28,10 @@ export declare class MessageHandler {
33
28
  private readonly pendingQueueConfirmations;
34
29
  private readonly pausedQueues;
35
30
  private readonly messageOpenIds;
31
+ /** Thread operations held by session controls (adopt and detach). */
32
+ private readonly sessionOperations;
33
+ /** `/resume` and `/session`: read-only listing plus confirmed, strict native adoption. */
34
+ private readonly sessionControl;
36
35
  private readonly activeThreadOperations;
37
36
  private readonly abortOperations;
38
37
  private automaticUpdateInProgress;
@@ -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":"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"}
@@ -8,6 +8,8 @@ const FileInbox_1 = require("../files/FileInbox");
8
8
  const DeviceIdentity_1 = require("../files/DeviceIdentity");
9
9
  const crypto_1 = require("crypto");
10
10
  const DocumentExtractor_1 = require("../files/DocumentExtractor");
11
+ const fs_1 = __importDefault(require("fs"));
12
+ const os_1 = __importDefault(require("os"));
11
13
  const path_1 = __importDefault(require("path"));
12
14
  const DelegationSettings_1 = require("../thread/DelegationSettings");
13
15
  const hooks_1 = require("../hooks");
@@ -17,8 +19,8 @@ const WorkingDirectory_1 = require("../utils/WorkingDirectory");
17
19
  const MachineCommands_1 = require("../machines/MachineCommands");
18
20
  const child_process_1 = require("child_process");
19
21
  const promises_1 = require("fs/promises");
20
- const fs_1 = require("fs");
21
- const os_1 = require("os");
22
+ const fs_2 = require("fs");
23
+ const os_2 = require("os");
22
24
  const path_2 = require("path");
23
25
  const config_1 = require("../types/config");
24
26
  const uuid_1 = require("uuid");
@@ -35,6 +37,10 @@ const ActivityProgress_1 = require("../utils/ActivityProgress");
35
37
  const SettingsAdmission_1 = require("../settings/SettingsAdmission");
36
38
  const SettingsCatalog_1 = require("../settings/SettingsCatalog");
37
39
  const SettingsService_1 = require("../settings/SettingsService");
40
+ const SessionResumeService_1 = require("../session/SessionResumeService");
41
+ const adapters_1 = require("../session/adapters");
42
+ const PiSessionCatalog_1 = require("../session/adapters/PiSessionCatalog");
43
+ const SessionControl_1 = require("../session/SessionControl");
38
44
  const EFFORT_BACKENDS = new Set(['claude', 'codex', 'agy', 'opencode', 'kimi', 'zcode', 'pi', 'dsh']);
39
45
  const SLASH_SESSION_BACKENDS = new Set(['opencode', 'kimi', 'zcode', 'pi']);
40
46
  const NATIVE_SKILLS_BACKENDS = new Set(['claude', 'agy', 'opencode', 'kimi', 'zcode', 'pi']);
@@ -92,6 +98,20 @@ const MAX_THREAD_QUEUE_LENGTH = 10;
92
98
  * Each thread has its own executor process managed by ThreadExecutorPool.
93
99
  * Commands without a threadId are routed to the default thread.
94
100
  */
101
+ /** Same base directory PiExecutor uses for its per-thread pointers. */
102
+ function remoteCliDirectory() {
103
+ return path_1.default.join(process.env.HOME || os_1.default.homedir(), '.remote-cli');
104
+ }
105
+ /** Read the thread's Pi pointer binding flags without starting an executor. */
106
+ function readPiBinding(threadId) {
107
+ try {
108
+ const pointer = JSON.parse(fs_1.default.readFileSync(path_1.default.join(remoteCliDirectory(), 'pi-sessions', `${threadId}.json`), 'utf8'));
109
+ return { id: typeof pointer.id === 'string' ? pointer.id : undefined, adopted: pointer.adopted === true };
110
+ }
111
+ catch {
112
+ return undefined;
113
+ }
114
+ }
95
115
  class MessageHandler {
96
116
  wsClient;
97
117
  threadPool;
@@ -107,6 +127,43 @@ class MessageHandler {
107
127
  pendingQueueConfirmations = new Map();
108
128
  pausedQueues = new Set();
109
129
  messageOpenIds = new Map();
130
+ /** Thread operations held by session controls (adopt and detach). */
131
+ sessionOperations = new Map();
132
+ /** `/resume` and `/session`: read-only listing plus confirmed, strict native adoption. */
133
+ sessionControl = new SessionControl_1.SessionControl({
134
+ sharingConfig: () => this.config.get('sessionSharing'),
135
+ backendOf: threadId => this.threadPool.getBackendKey(threadId),
136
+ workingDirectory: threadId => {
137
+ const directory = this.threadManager.getThread(threadId)?.workingDirectory;
138
+ try {
139
+ return directory ? this.directoryGuard.resolveWorkingDirectory(directory) : undefined;
140
+ }
141
+ catch {
142
+ return undefined;
143
+ }
144
+ },
145
+ threadName: threadId => this.threadManager.getThread(threadId)?.name,
146
+ // Queued or pending work counts as busy: a confirmation must never redirect it into another session.
147
+ isBusy: threadId => this.threadPool.isThreadBusy(threadId) || this.hasThreadQueueState(threadId)
148
+ || this.abortOperations.has(threadId) || this.isDestroyed || this.automaticUpdateInProgress
149
+ || this.delegation.hasActiveTasks(threadId) || this.settingsAdmission.hasCommand(threadId),
150
+ setBusy: (threadId, busy) => {
151
+ if (busy) {
152
+ this.sessionOperations.set(threadId, this.beginThreadOperation(threadId));
153
+ return;
154
+ }
155
+ const token = this.sessionOperations.get(threadId);
156
+ this.sessionOperations.delete(threadId);
157
+ // Messages that arrived during the operation were queued; resume draining them.
158
+ if (token && this.finishThreadOperation(threadId, token))
159
+ void this.startNextQueuedCommand(threadId);
160
+ },
161
+ executor: threadId => this.threadPool.getExecutor(threadId),
162
+ readCatalog: (backend, cwd) => (0, adapters_1.readSessionCatalog)(backend, cwd),
163
+ resolvePi: (cwd, id) => (0, PiSessionCatalog_1.resolvePiSessionLocator)(cwd, id, { remoteCliDirectory: remoteCliDirectory() }),
164
+ piHolder: (file, threadId) => (0, PiSessionCatalog_1.piSessionHolder)(file, threadId, { remoteCliDirectory: remoteCliDirectory() }),
165
+ piBinding: threadId => readPiBinding(threadId),
166
+ });
110
167
  activeThreadOperations = new Map();
111
168
  abortOperations = new Map();
112
169
  automaticUpdateInProgress = false;
@@ -310,6 +367,41 @@ class MessageHandler {
310
367
  const content = message.content?.trim() ?? '';
311
368
  const body = () => this.handleAdmittedCommandMessage(message, fileOrder);
312
369
  this.messageOpenIds.set(message.messageId, message.openId);
370
+ if ((0, SessionResumeService_1.isSessionControl)(content)) {
371
+ if (!this.threadManager.getThread(threadId)) {
372
+ this.sendResponse(message.messageId, undefined, { success: false, error: 'The selected thread no longer exists.' });
373
+ return;
374
+ }
375
+ let response;
376
+ try {
377
+ const control = () => this.sessionControl.handle(content, { openId: message.openId, threadId });
378
+ // Only Pi confirmations mutate native context. Other catalogs remain read-only.
379
+ if (this.threadPool.getBackendKey(threadId) === 'pi' && /^\/(?:resume|r|session)\s+confirm(?:\s|$)/i.test(content)) {
380
+ try {
381
+ response = await this.settingsAdmission.mutation(threadId, async () => {
382
+ this.settingsService.invalidate(threadId);
383
+ try {
384
+ return await control();
385
+ }
386
+ finally {
387
+ this.settingsService.invalidate(threadId);
388
+ }
389
+ });
390
+ }
391
+ finally {
392
+ void this.startNextQueuedCommand(threadId);
393
+ }
394
+ }
395
+ else {
396
+ response = await control();
397
+ }
398
+ }
399
+ catch (error) {
400
+ response = { success: false, error: `Session control failed: ${error instanceof Error ? error.message : String(error)}. No task was sent.` };
401
+ }
402
+ this.sendResponse(message.messageId, threadId, { ...response, threads: this.threadPool.getSummaries() }, true);
403
+ return;
404
+ }
313
405
  try {
314
406
  // Abort and addressed human replies must remain available during native work.
315
407
  if (content === '/abort' || /^(?:yes|no)(?:\s|$)/.test(content) || content.startsWith('/input '))
@@ -907,6 +999,8 @@ Use /compact to reduce conversation context or /clear to start a fresh context.`
907
999
  - /thread list - List all threads with their status
908
1000
  - /thread new [name] - Create a new thread
909
1001
  - /thread delete <name> - Delete a thread (only when idle)
1002
+ - /session - Show this thread's native session binding; /session detach
1003
+ - /resume - List this workspace's Pi sessions and connect one after confirmation (Pi only)
910
1004
 
911
1005
  Remote Machine commands:
912
1006
  - /proxy set <proxyHost> <proxyPort> <hostSuffix> [proxyAuth] - Configure global proxy
@@ -1680,8 +1774,6 @@ You can also use natural language commands to control Claude Code CLI.`,
1680
1774
  */
1681
1775
  expandCommandShortcuts(content) {
1682
1776
  const trimmed = content.trim();
1683
- if (trimmed === '/r' || trimmed === '/resume')
1684
- return 'Please resume the previous conversation';
1685
1777
  if (trimmed === '/c' || trimmed === '/continue')
1686
1778
  return 'Please continue from where we left off';
1687
1779
  return content;
@@ -1699,8 +1791,8 @@ You can also use natural language commands to control Claude Code CLI.`,
1699
1791
  ]);
1700
1792
  async listLocalSkills(cwd, backend) {
1701
1793
  const roots = backend === 'codex'
1702
- ? [(0, path_2.join)(cwd, '.agents', 'skills'), (0, path_2.join)((0, os_1.homedir)(), '.codex', 'skills'), (0, path_2.join)((0, os_1.homedir)(), '.codex', 'skills', '.system')]
1703
- : [(0, path_2.join)(cwd, '.claude', 'skills'), (0, path_2.join)((0, os_1.homedir)(), '.claude', 'skills')];
1794
+ ? [(0, path_2.join)(cwd, '.agents', 'skills'), (0, path_2.join)((0, os_2.homedir)(), '.codex', 'skills'), (0, path_2.join)((0, os_2.homedir)(), '.codex', 'skills', '.system')]
1795
+ : [(0, path_2.join)(cwd, '.claude', 'skills'), (0, path_2.join)((0, os_2.homedir)(), '.claude', 'skills')];
1704
1796
  const skills = [];
1705
1797
  const seen = new Set();
1706
1798
  for (const root of roots) {
@@ -1967,7 +2059,7 @@ You can also use natural language commands to control Claude Code CLI.`,
1967
2059
  if (other.id === threadId || !this.threadPool.isThreadBusy(other.id))
1968
2060
  return false;
1969
2061
  try {
1970
- return (0, DelegationManager_1.workspacesOverlap)((0, fs_1.realpathSync)(this.threadPool.getExecutor(other.id).getCurrentWorkingDirectory()), cwd);
2062
+ return (0, DelegationManager_1.workspacesOverlap)((0, fs_2.realpathSync)(this.threadPool.getExecutor(other.id).getCurrentWorkingDirectory()), cwd);
1971
2063
  }
1972
2064
  catch {
1973
2065
  return true;
@@ -2504,7 +2596,7 @@ You can also use natural language commands to control Claude Code CLI.`,
2504
2596
  console.error('Failed to send structured content:', error);
2505
2597
  }
2506
2598
  }
2507
- sendResponse(messageId, threadId, result) {
2599
+ sendResponse(messageId, threadId, result, metadataOnly = false) {
2508
2600
  if (!result.queueConfirmation)
2509
2601
  this.fileInbox?.release(messageId, !result.success);
2510
2602
  try {
@@ -2512,7 +2604,8 @@ You can also use natural language commands to control Claude Code CLI.`,
2512
2604
  let cwd;
2513
2605
  try {
2514
2606
  if (threadId) {
2515
- cwd = this.threadPool.getExecutor(threadId).getCurrentWorkingDirectory();
2607
+ cwd = metadataOnly ? this.threadManager.getThread(threadId)?.workingDirectory
2608
+ : this.threadPool.getExecutor(threadId).getCurrentWorkingDirectory();
2516
2609
  }
2517
2610
  }
2518
2611
  catch {