@logictan/dsh-desktop-agent 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/lib/index.js +33 -7
  2. package/package.json +1 -1
package/lib/index.js CHANGED
@@ -235,7 +235,12 @@ async function resolveTarget(input) {
235
235
 
236
236
  const value = await dispatch('cua_driver_native__list_windows', {}, signal);
237
237
  const payload = structured(value, 'list_windows');
238
- const windows = Array.isArray(payload.windows) ? payload.windows : [];
238
+ // A payload that parses but carries no window array is a driver contract
239
+ // failure, not an empty desktop. Flattening it to [] would report the two as
240
+ // the same sentence, and the driver is a third-party boundary whose response
241
+ // shape this plugin does not control.
242
+ if (!Array.isArray(payload.windows)) throw new Error('desktop_agent: list_windows returned no window array.');
243
+ const windows = payload.windows;
239
244
  if (windows.length === 0) throw new Error('desktop_agent: the driver listed no windows.');
240
245
 
241
246
  if (args.windowId !== undefined) {
@@ -262,20 +267,41 @@ async function resolveTarget(input) {
262
267
  }
263
268
 
264
269
  const needle = args.app.toLowerCase();
265
- const matches = onScreen.filter(
266
- (window) =>
267
- String(window.app_name ?? '').toLowerCase().includes(needle) ||
268
- String(window.title ?? '').toLowerCase().includes(needle),
269
- );
270
+ const matches = onScreen.filter((window) => matchesApp(window, needle));
270
271
  if (matches.length === 0) {
272
+ // An app that is running but has no window on screen is a different fact
273
+ // from an app that is not running, and only the second one suggests
274
+ // launching it. The windowId path already tells them apart.
275
+ if (windows.some((window) => matchesApp(window, needle))) {
276
+ throw new Error(
277
+ 'desktop_agent: "' + args.app + '" is open, but no window of it is on screen, so it cannot be captured or acted on.',
278
+ );
279
+ }
271
280
  const names = [...new Set(onScreen.map((window) => window.app_name).filter(Boolean))];
272
281
  throw new Error(
273
- 'desktop_agent: no on-screen window matches "' + args.app + '". Open windows: ' + (names.join(', ') || '(none)') + '.',
282
+ 'desktop_agent: no on-screen window matches "' + args.app + '". On-screen apps: ' + (names.join(', ') || '(none)') + '.',
274
283
  );
275
284
  }
276
285
  return targetOf(bestMatch(matches));
277
286
  }
278
287
 
288
+ /**
289
+ * Whether a window answers to an app argument.
290
+ *
291
+ * The needle is matched against the application name and the window title,
292
+ * because both are things a caller can reasonably name.
293
+ *
294
+ * @param window - a window from the driver's list.
295
+ * @param needle - the app argument, lower-cased.
296
+ * @returns whether the window matches.
297
+ */
298
+ function matchesApp(window, needle) {
299
+ return (
300
+ String(window.app_name ?? '').toLowerCase().includes(needle) ||
301
+ String(window.title ?? '').toLowerCase().includes(needle)
302
+ );
303
+ }
304
+
279
305
  /**
280
306
  * Choose the window to drive from the candidates an app argument matched.
281
307
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@logictan/dsh-desktop-agent",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "DSH desktop agent: a native-vision decision loop that drives the host desktop through the Cua Driver tools. DSH 桌面 Agent 子插件。",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",