ucu-mcp 0.1.3 → 0.3.0

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.
@@ -38,10 +38,12 @@ export interface AppInfo {
38
38
  windowCount: number;
39
39
  }
40
40
  export interface AppTarget {
41
+ targetId: string;
41
42
  appName: string;
42
43
  pid: number;
43
44
  windowId?: string;
44
45
  title?: string;
46
+ capturedAt: string;
45
47
  }
46
48
  export interface BrowserContext {
47
49
  appName: string;
@@ -81,6 +83,17 @@ export interface FindElementOptions {
81
83
  depth?: number;
82
84
  includeBounds?: boolean;
83
85
  maxResults?: number;
86
+ textMode?: "contains" | "exact" | "regex";
87
+ visibleOnly?: boolean;
88
+ /** Match against the AX element's current value attribute (respects textMode). */
89
+ value?: string;
90
+ /** Return only the Nth match (0-based) after all other filtering and sorting. */
91
+ index?: number;
92
+ /** Sort results by ascending distance to this point and return closest first. */
93
+ near?: {
94
+ x: number;
95
+ y: number;
96
+ };
84
97
  }
85
98
  export interface FindElementResult {
86
99
  id: string;
@@ -95,6 +108,16 @@ export interface FindElementResult {
95
108
  };
96
109
  description?: string;
97
110
  }
111
+ export interface FindElementMetrics {
112
+ scannedCount: number;
113
+ matchedCount: number;
114
+ durationMs: number;
115
+ truncated: boolean;
116
+ }
117
+ export interface FindElementResponse {
118
+ results: FindElementResult[];
119
+ metrics: FindElementMetrics;
120
+ }
98
121
  export interface WindowState {
99
122
  window: WindowInfo;
100
123
  focusedElement?: ElementInfo;
@@ -117,11 +140,13 @@ export interface Platform {
117
140
  ocr(display?: number, region?: ScreenRegion): Promise<OcrResult>;
118
141
  type(text: string, delay?: number): Promise<void>;
119
142
  key(keys: string[]): Promise<void>;
120
- findElement(options: FindElementOptions): Promise<FindElementResult[]>;
143
+ findElement(options: FindElementOptions): Promise<FindElementResponse>;
121
144
  clickElement(elementId: string, app?: string): Promise<void>;
122
145
  typeInElement(elementId: string, text: string, app?: string, clearFirst?: boolean): Promise<void>;
123
146
  setElementValue?(elementId: string, value: string, app?: string): Promise<void>;
124
147
  isScreenLocked?(): boolean;
125
148
  saveFocus?(): Promise<void>;
126
149
  restoreFocus?(): Promise<void>;
150
+ readClipboard(): Promise<string>;
151
+ writeClipboard(text: string): Promise<void>;
127
152
  }
@@ -1,4 +1,4 @@
1
- import type { Platform, ScreenRegion, ScreenSize, CursorPosition, WindowInfo, WindowState, OcrResult, FindElementOptions, FindElementResult } from "./base.js";
1
+ import type { Platform, ScreenRegion, ScreenSize, CursorPosition, WindowInfo, WindowState, OcrResult, FindElementOptions, FindElementResponse } from "./base.js";
2
2
  /**
3
3
  * Linux platform adapter (AT-SPI2 + xdotool fallback)
4
4
  * TODO: Implement with D-Bus AT-SPI2 bindings
@@ -16,7 +16,9 @@ export declare class LinuxPlatform implements Platform {
16
16
  type(text: string, delay?: number): Promise<void>;
17
17
  key(keys: string[]): Promise<void>;
18
18
  ocr(_display?: number, _region?: ScreenRegion): Promise<OcrResult>;
19
- findElement(_options: FindElementOptions): Promise<FindElementResult[]>;
19
+ findElement(_options: FindElementOptions): Promise<FindElementResponse>;
20
20
  clickElement(_elementId: string, _app?: string): Promise<void>;
21
21
  typeInElement(_elementId: string, _text: string, _app?: string, _clearFirst?: boolean): Promise<void>;
22
+ readClipboard(): Promise<string>;
23
+ writeClipboard(text: string): Promise<void>;
22
24
  }
@@ -1,3 +1,27 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import { existsSync } from "node:fs";
3
+ import { PlatformError } from "../util/errors.js";
4
+ /** Pick the first available clipboard utility, preferring xclip. */
5
+ function pickClipboardTool() {
6
+ for (const bin of ["/usr/bin/xclip", "/usr/local/bin/xclip", "xclip"]) {
7
+ if (bin.startsWith("/") ? existsSync(bin) : which(bin))
8
+ return "xclip";
9
+ }
10
+ for (const bin of ["/usr/bin/xsel", "/usr/local/bin/xsel", "xsel"]) {
11
+ if (bin.startsWith("/") ? existsSync(bin) : which(bin))
12
+ return "xsel";
13
+ }
14
+ return undefined;
15
+ }
16
+ function which(bin) {
17
+ try {
18
+ execFileSync("which", [bin], { encoding: "utf-8", timeout: 2000, stdio: "ignore" });
19
+ return true;
20
+ }
21
+ catch {
22
+ return false;
23
+ }
24
+ }
1
25
  /**
2
26
  * Linux platform adapter (AT-SPI2 + xdotool fallback)
3
27
  * TODO: Implement with D-Bus AT-SPI2 bindings
@@ -59,4 +83,31 @@ export class LinuxPlatform {
59
83
  async typeInElement(_elementId, _text, _app, _clearFirst) {
60
84
  throw new Error("Not implemented: Linux typeInElement");
61
85
  }
86
+ async readClipboard() {
87
+ const tool = pickClipboardTool();
88
+ if (!tool) {
89
+ throw new PlatformError("readClipboard requires xclip or xsel on PATH", false);
90
+ }
91
+ try {
92
+ const args = tool === "xclip" ? ["-selection", "clipboard", "-o"] : ["--clipboard", "--output"];
93
+ const out = execFileSync(tool, args, { encoding: "utf-8", timeout: 5000 });
94
+ return out;
95
+ }
96
+ catch (error) {
97
+ throw new PlatformError(`read_clipboard failed: ${error.message}`);
98
+ }
99
+ }
100
+ async writeClipboard(text) {
101
+ const tool = pickClipboardTool();
102
+ if (!tool) {
103
+ throw new PlatformError("writeClipboard requires xclip or xsel on PATH", false);
104
+ }
105
+ try {
106
+ const args = tool === "xclip" ? ["-selection", "clipboard"] : ["--clipboard", "--input"];
107
+ execFileSync(tool, args, { input: text, encoding: "utf-8", timeout: 5000 });
108
+ }
109
+ catch (error) {
110
+ throw new PlatformError(`write_clipboard failed: ${error.message}`);
111
+ }
112
+ }
62
113
  }
@@ -1,8 +1,10 @@
1
- import type { Platform, ScreenRegion, ScreenSize, CursorPosition, WindowInfo, WindowState, OcrResult, FindElementOptions, FindElementResult, AppInfo, AppTarget, BrowserContext, ScreenshotOptions } from "./base.js";
1
+ import type { Platform, ScreenRegion, ScreenSize, CursorPosition, WindowInfo, WindowState, OcrResult, FindElementOptions, FindElementResponse, AppInfo, AppTarget, BrowserContext, ScreenshotOptions } from "./base.js";
2
2
  export declare class MacOSPlatform implements Platform {
3
3
  private readonly elementCache;
4
4
  private readonly elementCacheTtlMs;
5
5
  private readonly elementCacheMaxSize;
6
+ private readonly windowCacheTtlMs;
7
+ private windowCache;
6
8
  private activeTarget;
7
9
  private savedFocus;
8
10
  /** Remove expired entries from the element cache. */
@@ -11,6 +13,8 @@ export declare class MacOSPlatform implements Platform {
11
13
  private evictOverflowCacheEntries;
12
14
  /** Check whether a cached element descriptor has expired. */
13
15
  private isCacheEntryExpired;
16
+ /** Validate that the active target window still exists. */
17
+ validateActiveTarget(): Promise<void>;
14
18
  /** Save the current frontmost app/window so we can restore after an action. */
15
19
  saveFocus(): Promise<void>;
16
20
  /** Restore the previously saved frontmost app/window. */
@@ -30,10 +34,14 @@ export declare class MacOSPlatform implements Platform {
30
34
  scroll(x: number, y: number, deltaX: number, deltaY: number): Promise<void>;
31
35
  getCursorPosition(): CursorPosition;
32
36
  ocr(display?: number, region?: ScreenRegion): Promise<OcrResult>;
37
+ private ocrNative;
38
+ private ocrJxa;
33
39
  type(text: string, delay?: number): Promise<void>;
34
40
  key(keys: string[]): Promise<void>;
35
- findElement(options: FindElementOptions): Promise<FindElementResult[]>;
41
+ findElement(options: FindElementOptions): Promise<FindElementResponse>;
36
42
  clickElement(elementId: string, app?: string): Promise<void>;
37
43
  typeInElement(elementId: string, text: string, app?: string, clearFirst?: boolean): Promise<void>;
44
+ readClipboard(): Promise<string>;
45
+ writeClipboard(text: string): Promise<void>;
38
46
  setElementValue(elementId: string, value: string, app?: string): Promise<void>;
39
47
  }