@yu_robotics/remote-cli 1.6.158 → 1.6.166

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 (73) hide show
  1. package/README.md +12 -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 +121 -22
  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/ClaudePersistentExecutor.d.ts.map +1 -1
  18. package/dist/executor/ClaudePersistentExecutor.js +18 -8
  19. package/dist/executor/ClaudePersistentExecutor.js.map +1 -1
  20. package/dist/executor/IExecutor.d.ts +21 -0
  21. package/dist/executor/IExecutor.d.ts.map +1 -1
  22. package/dist/executor/PiExecutor.d.ts +26 -1
  23. package/dist/executor/PiExecutor.d.ts.map +1 -1
  24. package/dist/executor/PiExecutor.js +256 -15
  25. package/dist/executor/PiExecutor.js.map +1 -1
  26. package/dist/index.js +19 -0
  27. package/dist/index.js.map +1 -1
  28. package/dist/maintenance/release-notes.json +1 -1
  29. package/dist/session/SessionCatalog.d.ts +76 -0
  30. package/dist/session/SessionCatalog.d.ts.map +1 -0
  31. package/dist/session/SessionCatalog.js +197 -0
  32. package/dist/session/SessionCatalog.js.map +1 -0
  33. package/dist/session/SessionControl.d.ts +56 -0
  34. package/dist/session/SessionControl.d.ts.map +1 -0
  35. package/dist/session/SessionControl.js +262 -0
  36. package/dist/session/SessionControl.js.map +1 -0
  37. package/dist/session/SessionLocalInfo.d.ts +48 -0
  38. package/dist/session/SessionLocalInfo.d.ts.map +1 -0
  39. package/dist/session/SessionLocalInfo.js +145 -0
  40. package/dist/session/SessionLocalInfo.js.map +1 -0
  41. package/dist/session/SessionMenu.d.ts +102 -0
  42. package/dist/session/SessionMenu.d.ts.map +1 -0
  43. package/dist/session/SessionMenu.js +144 -0
  44. package/dist/session/SessionMenu.js.map +1 -0
  45. package/dist/session/SessionResumeService.d.ts +38 -0
  46. package/dist/session/SessionResumeService.d.ts.map +1 -0
  47. package/dist/session/SessionResumeService.js +147 -0
  48. package/dist/session/SessionResumeService.js.map +1 -0
  49. package/dist/session/adapters/ClaudeSessionCatalog.d.ts +10 -0
  50. package/dist/session/adapters/ClaudeSessionCatalog.d.ts.map +1 -0
  51. package/dist/session/adapters/ClaudeSessionCatalog.js +156 -0
  52. package/dist/session/adapters/ClaudeSessionCatalog.js.map +1 -0
  53. package/dist/session/adapters/CodexSessionCatalog.d.ts +9 -0
  54. package/dist/session/adapters/CodexSessionCatalog.d.ts.map +1 -0
  55. package/dist/session/adapters/CodexSessionCatalog.js +214 -0
  56. package/dist/session/adapters/CodexSessionCatalog.js.map +1 -0
  57. package/dist/session/adapters/PiSessionCatalog.d.ts +52 -0
  58. package/dist/session/adapters/PiSessionCatalog.d.ts.map +1 -0
  59. package/dist/session/adapters/PiSessionCatalog.js +252 -0
  60. package/dist/session/adapters/PiSessionCatalog.js.map +1 -0
  61. package/dist/session/adapters/index.d.ts +13 -0
  62. package/dist/session/adapters/index.d.ts.map +1 -0
  63. package/dist/session/adapters/index.js +17 -0
  64. package/dist/session/adapters/index.js.map +1 -0
  65. package/dist/types/config.d.ts +11 -0
  66. package/dist/types/config.d.ts.map +1 -1
  67. package/dist/types/config.js +3 -0
  68. package/dist/types/config.js.map +1 -1
  69. package/dist/utils/LocalImageDetector.d.ts +2 -2
  70. package/dist/utils/LocalImageDetector.d.ts.map +1 -1
  71. package/dist/utils/LocalImageDetector.js +2 -0
  72. package/dist/utils/LocalImageDetector.js.map +1 -1
  73. package/package.json +1 -1
package/README.md CHANGED
@@ -76,6 +76,8 @@ The client is normally installed and run directly on the developer's machine rat
76
76
 
77
77
  ## Installation
78
78
 
79
+ Claude tool-result content blocks are normalized to text; embedded media and unknown payloads are not scanned for local files. Local image detection and forwarding are best-effort: failures do not fail the task or terminate the CLI. Web-result excerpts remain excluded from local-file scanning.
80
+
79
81
  Sending local image files requires a Router with image forwarding support and
80
82
  the bot application's `im:resource` permission. Router 1.6.85 and newer render
81
83
  local and URL-based Markdown image references as captions; the uploaded image
@@ -178,7 +180,7 @@ Linux users upgrading from version 1.6.23 or earlier should run `remote-cli serv
178
180
  | `/model [name]` | Open native model settings, or set the active backend model with a text argument |
179
181
  | `/effort [auto|level]` | Open native effort settings, or set/clear the active backend effort with a text argument |
180
182
  | `/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 |
183
+ | `/backend` | Open backend settings; click a backend to switch immediately, defaulting to Current thread |
182
184
  | `/delegation [on|off]` | Inspect or enable delegation between installed agent backends in this thread |
183
185
  | `/backend <index>` | Switch all threads and clear per-thread backend overrides |
184
186
  | `/backend <index> @` | Switch only the current thread |
@@ -187,9 +189,9 @@ Linux users upgrading from version 1.6.23 or earlier should run `remote-cli serv
187
189
  | `/unbind` | Unbind all devices |
188
190
  | `/device` | List and switch between bound devices |
189
191
 
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).
192
+ 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
193
 
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.
194
+ 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
195
 
194
196
  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
197
 
@@ -328,6 +330,7 @@ source reservations remain held until owned operations settle, even on cancellat
328
330
  no late worker is launched. Failed collection after confirmed exit preserves only
329
331
  the affected lane and files for recovery rather than quarantining the source.
330
332
  Individual Git command deadlines remain; cancellation may wait for Git to settle.
333
+ 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
334
  Slow launch/cancel tools return the accepted task ID and a pending status before
332
335
  the adapter timeout; poll that ID with `remote_cli_result`, not a new delegation.
333
336
  The response does not claim cancellation cleanup or workspace release is complete.
@@ -451,6 +454,12 @@ Claude Code also supports opt-in `/sandbox` policies. Workspace-write mode autom
451
454
  - **Device authentication**: Each device has a unique hardware-based ID
452
455
  - **Binding codes**: Expire after 5 minutes
453
456
 
457
+ ## Session Resume
458
+
459
+ 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).
460
+
461
+ 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.
462
+
454
463
  ## Documentation
455
464
 
456
465
  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;
@@ -1997,19 +2089,25 @@ You can also use natural language commands to control Claude Code CLI.`,
1997
2089
  const webToolNames = new Set(['websearch', 'webfetch', 'web_search', 'web_fetch', 'search_web', 'read_url_content', 'fetch']);
1998
2090
  let streamedOutput = '';
1999
2091
  const emitLocalImages = async (text) => {
2000
- const thread = this.threadManager.getThread(threadId);
2001
- if (!text || !thread?.workingDirectory)
2002
- return;
2003
- const images = await (0, LocalImageDetector_1.readLocalImages)(text, thread.workingDirectory, (candidate, cwd) => (this.directoryGuard.isSafePath(candidate, cwd)));
2004
- for (const image of images) {
2005
- if (emittedLocalImages.has(image.path))
2006
- continue;
2007
- emittedLocalImages.add(image.path);
2008
- this.sendImage(messageId, threadId, {
2009
- type: 'image',
2010
- data: image.data,
2011
- mimeType: image.mimeType,
2012
- });
2092
+ try {
2093
+ const thread = this.threadManager.getThread(threadId);
2094
+ if (typeof text !== 'string' || !text || !thread?.workingDirectory)
2095
+ return;
2096
+ const images = await (0, LocalImageDetector_1.readLocalImages)(text, thread.workingDirectory, (candidate, cwd) => (this.directoryGuard.isSafePath(candidate, cwd)));
2097
+ for (const image of images) {
2098
+ if (emittedLocalImages.has(image.path))
2099
+ continue;
2100
+ emittedLocalImages.add(image.path);
2101
+ this.sendImage(messageId, threadId, {
2102
+ type: 'image',
2103
+ data: image.data,
2104
+ mimeType: image.mimeType,
2105
+ });
2106
+ }
2107
+ }
2108
+ catch {
2109
+ // Image forwarding is optional; never reject a task or log native content on failure.
2110
+ console.warn('Failed to forward local images; continuing task output.');
2013
2111
  }
2014
2112
  };
2015
2113
  const queueLocalImages = (text) => {
@@ -2504,7 +2602,7 @@ You can also use natural language commands to control Claude Code CLI.`,
2504
2602
  console.error('Failed to send structured content:', error);
2505
2603
  }
2506
2604
  }
2507
- sendResponse(messageId, threadId, result) {
2605
+ sendResponse(messageId, threadId, result, metadataOnly = false) {
2508
2606
  if (!result.queueConfirmation)
2509
2607
  this.fileInbox?.release(messageId, !result.success);
2510
2608
  try {
@@ -2512,7 +2610,8 @@ You can also use natural language commands to control Claude Code CLI.`,
2512
2610
  let cwd;
2513
2611
  try {
2514
2612
  if (threadId) {
2515
- cwd = this.threadPool.getExecutor(threadId).getCurrentWorkingDirectory();
2613
+ cwd = metadataOnly ? this.threadManager.getThread(threadId)?.workingDirectory
2614
+ : this.threadPool.getExecutor(threadId).getCurrentWorkingDirectory();
2516
2615
  }
2517
2616
  }
2518
2617
  catch {