@yu_robotics/remote-cli 1.6.156 → 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.
- package/README.md +14 -3
- package/dist/client/MessageHandler.d.ts +4 -5
- package/dist/client/MessageHandler.d.ts.map +1 -1
- package/dist/client/MessageHandler.js +102 -9
- package/dist/client/MessageHandler.js.map +1 -1
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +15 -0
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/session.d.ts +17 -0
- package/dist/commands/session.d.ts.map +1 -0
- package/dist/commands/session.js +37 -0
- package/dist/commands/session.js.map +1 -0
- package/dist/delegation/GitCheckpoint.d.ts +1 -0
- package/dist/delegation/GitCheckpoint.d.ts.map +1 -1
- package/dist/delegation/GitCheckpoint.js +15 -4
- package/dist/delegation/GitCheckpoint.js.map +1 -1
- package/dist/executor/IExecutor.d.ts +21 -0
- package/dist/executor/IExecutor.d.ts.map +1 -1
- package/dist/executor/PiExecutor.d.ts +26 -1
- package/dist/executor/PiExecutor.d.ts.map +1 -1
- package/dist/executor/PiExecutor.js +256 -15
- package/dist/executor/PiExecutor.js.map +1 -1
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -1
- package/dist/maintenance/release-notes.json +1 -1
- package/dist/session/SessionCatalog.d.ts +76 -0
- package/dist/session/SessionCatalog.d.ts.map +1 -0
- package/dist/session/SessionCatalog.js +197 -0
- package/dist/session/SessionCatalog.js.map +1 -0
- package/dist/session/SessionControl.d.ts +56 -0
- package/dist/session/SessionControl.d.ts.map +1 -0
- package/dist/session/SessionControl.js +262 -0
- package/dist/session/SessionControl.js.map +1 -0
- package/dist/session/SessionLocalInfo.d.ts +48 -0
- package/dist/session/SessionLocalInfo.d.ts.map +1 -0
- package/dist/session/SessionLocalInfo.js +145 -0
- package/dist/session/SessionLocalInfo.js.map +1 -0
- package/dist/session/SessionMenu.d.ts +102 -0
- package/dist/session/SessionMenu.d.ts.map +1 -0
- package/dist/session/SessionMenu.js +144 -0
- package/dist/session/SessionMenu.js.map +1 -0
- package/dist/session/SessionResumeService.d.ts +38 -0
- package/dist/session/SessionResumeService.d.ts.map +1 -0
- package/dist/session/SessionResumeService.js +147 -0
- package/dist/session/SessionResumeService.js.map +1 -0
- package/dist/session/adapters/ClaudeSessionCatalog.d.ts +10 -0
- package/dist/session/adapters/ClaudeSessionCatalog.d.ts.map +1 -0
- package/dist/session/adapters/ClaudeSessionCatalog.js +156 -0
- package/dist/session/adapters/ClaudeSessionCatalog.js.map +1 -0
- package/dist/session/adapters/CodexSessionCatalog.d.ts +9 -0
- package/dist/session/adapters/CodexSessionCatalog.d.ts.map +1 -0
- package/dist/session/adapters/CodexSessionCatalog.js +214 -0
- package/dist/session/adapters/CodexSessionCatalog.js.map +1 -0
- package/dist/session/adapters/PiSessionCatalog.d.ts +52 -0
- package/dist/session/adapters/PiSessionCatalog.d.ts.map +1 -0
- package/dist/session/adapters/PiSessionCatalog.js +252 -0
- package/dist/session/adapters/PiSessionCatalog.js.map +1 -0
- package/dist/session/adapters/index.d.ts +13 -0
- package/dist/session/adapters/index.d.ts.map +1 -0
- package/dist/session/adapters/index.js +17 -0
- package/dist/session/adapters/index.js.map +1 -0
- package/dist/types/config.d.ts +11 -0
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/config.js +3 -0
- package/dist/types/config.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -20,6 +20,8 @@ Router 1.6.117 and newer explicitly label standalone background-task notificatio
|
|
|
20
20
|
|
|
21
21
|
## Public Activity
|
|
22
22
|
|
|
23
|
+
From Router 1.6.158, completion pagination keeps the final body item (or complete worker group) with the completion note, optional model metadata and thread controls when they fit together. This avoids preventable footer-only continuations, including replies without model metadata. Indivisible oversized groups still split according to node, size and table limits; thread-button refreshes preserve the final body. This does not change streaming completion timing or the wire protocol.
|
|
24
|
+
|
|
23
25
|
From CLI 1.6.153, Codex shell calls no longer lose their label when native command actions are absent or unknown. Native reads, searches, and directory listings remain preferred. Other calls use fixed operation labels such as `Run npm command` or `Run Git command` for simple allowlisted programs, and `Run shell command` for compound or unrecognized commands. These are deterministic operation labels, not model-authored purpose summaries: installed Codex 0.160.0 command items have no per-call description field. Arguments, full paths, output, and execution-wide reasoning are never copied into these fallback labels. Late native action metadata can enrich a pending row before its first result; repeated results retain one row. Existing description fields, heading limits, and card-node counts are unchanged; upgrade the CLI, with no new Router capability required.
|
|
24
26
|
|
|
25
27
|
Router 1.6.145 combines each foreground tool call and its matching result into one collapsed row, retaining input, output, and diff previews. Independent calls, workers, and approvals remain separate. This uses the existing CLI protocol; the client does not need a new capability. See [Code Change Previews](../../README.md#code-change-previews).
|
|
@@ -176,7 +178,7 @@ Linux users upgrading from version 1.6.23 or earlier should run `remote-cli serv
|
|
|
176
178
|
| `/model [name]` | Open native model settings, or set the active backend model with a text argument |
|
|
177
179
|
| `/effort [auto|level]` | Open native effort settings, or set/clear the active backend effort with a text argument |
|
|
178
180
|
| `/sandbox [on/off/read-only/default]` | Configure the current Codex or Claude Code thread sandbox, directory grants, and networking |
|
|
179
|
-
| `/backend` | Open backend settings;
|
|
181
|
+
| `/backend` | Open backend settings; click a backend to switch immediately, defaulting to Current thread |
|
|
180
182
|
| `/delegation [on|off]` | Inspect or enable delegation between installed agent backends in this thread |
|
|
181
183
|
| `/backend <index>` | Switch all threads and clear per-thread backend overrides |
|
|
182
184
|
| `/backend <index> @` | Switch only the current thread |
|
|
@@ -185,14 +187,16 @@ Linux users upgrading from version 1.6.23 or earlier should run `remote-cli serv
|
|
|
185
187
|
| `/unbind` | Unbind all devices |
|
|
186
188
|
| `/device` | List and switch between bound devices |
|
|
187
189
|
|
|
188
|
-
CLI and Router 1.6.152 add standalone settings cards. `/backend` lists all eight stable backend choices, disables missing installations and
|
|
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).
|
|
189
191
|
|
|
190
|
-
From 1.6.154, numbered sections separate backend selection
|
|
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.
|
|
191
193
|
|
|
192
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.
|
|
193
195
|
|
|
194
196
|
From CLI and Router 1.6.156, bare `/delegation` opens a thread-only On/Off card with a separate backend-availability section, gated by both `settingsCards` and `delegationCards`. Selection is confirmed only after cleanup and persistence succeed. Busy or queued work blocks toggles but not inspection/refresh; enabling does not bypass sandbox policy or prove authentication/quota. Parameterized toggles and `/delegation reset [backend]` remain text commands, and older peers retain the text menu.
|
|
195
197
|
|
|
198
|
+
Backend availability uses colored status badges: blue for the coordinator, green for installed workers, orange for blocked workers, red for unavailable backends and gray for unknown worker availability. Text labels and version or restriction details remain visible; these badges do not prove authentication or quota.
|
|
199
|
+
|
|
196
200
|
### Threads & Machines
|
|
197
201
|
|
|
198
202
|
From CLI 1.6.121, new and existing threads without a saved preference enable
|
|
@@ -324,6 +328,7 @@ source reservations remain held until owned operations settle, even on cancellat
|
|
|
324
328
|
no late worker is launched. Failed collection after confirmed exit preserves only
|
|
325
329
|
the affected lane and files for recovery rather than quarantining the source.
|
|
326
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.
|
|
327
332
|
Slow launch/cancel tools return the accepted task ID and a pending status before
|
|
328
333
|
the adapter timeout; poll that ID with `remote_cli_result`, not a new delegation.
|
|
329
334
|
The response does not claim cancellation cleanup or workspace release is complete.
|
|
@@ -447,6 +452,12 @@ Claude Code also supports opt-in `/sandbox` policies. Workspace-write mode autom
|
|
|
447
452
|
- **Device authentication**: Each device has a unique hardware-based ID
|
|
448
453
|
- **Binding codes**: Expire after 5 minutes
|
|
449
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
|
+
|
|
450
461
|
## Documentation
|
|
451
462
|
|
|
452
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":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;
|
|
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
|
|
21
|
-
const
|
|
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,
|
|
1703
|
-
: [(0, path_2.join)(cwd, '.claude', 'skills'), (0, path_2.join)((0,
|
|
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,
|
|
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.
|
|
2607
|
+
cwd = metadataOnly ? this.threadManager.getThread(threadId)?.workingDirectory
|
|
2608
|
+
: this.threadPool.getExecutor(threadId).getCurrentWorkingDirectory();
|
|
2516
2609
|
}
|
|
2517
2610
|
}
|
|
2518
2611
|
catch {
|