@mediar-ai/terminator 0.24.12 → 0.24.14

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/index.d.ts CHANGED
@@ -526,6 +526,27 @@ export interface ComputerUseResult {
526
526
  /** Execution ID for finding screenshots (e.g., "20251205_134500_geminiComputerUse_msedge") */
527
527
  executionId?: string
528
528
  }
529
+ /** Result of closing a browser tab */
530
+ export interface CloseTabResult {
531
+ closed: boolean
532
+ tab: ClosedTabInfo
533
+ }
534
+ /** Information about a closed tab */
535
+ export interface ClosedTabInfo {
536
+ id: number
537
+ url?: string
538
+ title?: string
539
+ windowId?: number
540
+ }
541
+ /** Options for closing a browser tab */
542
+ export interface CloseTabOptions {
543
+ /** Specific Chrome tab ID to close */
544
+ tabId?: number
545
+ /** URL to match (partial match supported) */
546
+ url?: string
547
+ /** Title to match (case-insensitive partial match) */
548
+ title?: string
549
+ }
529
550
  /** Information about a window */
530
551
  export interface WindowInfo {
531
552
  /** Window handle */
@@ -973,6 +994,40 @@ export declare class Desktop {
973
994
  * @returns {Promise<string>} The result of script execution.
974
995
  */
975
996
  executeBrowserScript(script: string, process: string, timeoutMs?: number | undefined | null): Promise<string>
997
+ /**
998
+ * (async) Close a browser tab safely.
999
+ *
1000
+ * This method can identify the tab to close by:
1001
+ * - tabId: Close a specific tab by its Chrome tab ID
1002
+ * - url: Find and close a tab matching this URL (partial match supported)
1003
+ * - title: Find and close a tab matching this title (case-insensitive partial match)
1004
+ * - If none provided, closes the currently active tab
1005
+ *
1006
+ * Returns information about the closed tab for verification.
1007
+ * Returns null if no browser extension is connected or tab couldn't be found.
1008
+ *
1009
+ * Safety:
1010
+ * - Will NOT close protected browser pages (chrome://, edge://, about:, etc.)
1011
+ * - Returns the closed tab's URL/title so you can verify the correct tab was closed
1012
+ *
1013
+ * @param {number} [tabId] - Specific Chrome tab ID to close.
1014
+ * @param {string} [url] - URL to match (partial match supported).
1015
+ * @param {string} [title] - Title to match (case-insensitive partial match).
1016
+ * @returns {Promise<CloseTabResult | null>} Info about closed tab, or null if no extension/tab found.
1017
+ *
1018
+ * @example
1019
+ * // Close by URL
1020
+ * const result = await desktop.closeTab({ url: "example.com" });
1021
+ *
1022
+ * @example
1023
+ * // Close by title
1024
+ * const result = await desktop.closeTab({ title: "My Page" });
1025
+ *
1026
+ * @example
1027
+ * // Close active tab
1028
+ * const result = await desktop.closeTab();
1029
+ */
1030
+ closeTab(options?: CloseTabOptions | undefined | null): Promise<CloseTabResult | null>
976
1031
  /**
977
1032
  * (async) Delay execution for a specified number of milliseconds.
978
1033
  * Useful for waiting between actions to ensure UI stability.
package/package.json CHANGED
@@ -4,12 +4,12 @@
4
4
  "url": "https://github.com/mediar-ai/terminator/issues"
5
5
  },
6
6
  "dependencies": {
7
- "@mediar-ai/kv": "^0.23.30",
8
- "esbuild": "^0.25.11"
7
+ "@mediar-ai/kv": "^0.23.30"
9
8
  },
10
9
  "description": "Node.js/TypeScript bindings for the Terminator Rust library (via napi-rs)",
11
10
  "devDependencies": {
12
- "@napi-rs/cli": "^2.18.4"
11
+ "@napi-rs/cli": "^2.18.4",
12
+ "esbuild": "^0.25.11"
13
13
  },
14
14
  "engines": {
15
15
  "node": ">= 10"
@@ -38,8 +38,8 @@
38
38
  }
39
39
  },
40
40
  "optionalDependencies": {
41
- "@mediar-ai/terminator-win32-arm64-msvc": "0.24.12",
42
- "@mediar-ai/terminator-win32-x64-msvc": "0.24.12"
41
+ "@mediar-ai/terminator-win32-arm64-msvc": "0.24.14",
42
+ "@mediar-ai/terminator-win32-x64-msvc": "0.24.14"
43
43
  },
44
44
  "repository": {
45
45
  "type": "git",
@@ -57,5 +57,5 @@
57
57
  "test-hook": "powershell.exe -ExecutionPolicy Bypass -File \"../../.git/hooks/pre-push.ps1\""
58
58
  },
59
59
  "types": "wrapper.d.ts",
60
- "version": "0.24.12"
60
+ "version": "0.24.14"
61
61
  }
package/src/desktop.rs CHANGED
@@ -12,6 +12,17 @@ use napi_derive::napi;
12
12
  use std::sync::{Arc, Once};
13
13
  use terminator::Desktop as TerminatorDesktop;
14
14
 
15
+ /// Normalize key format to ensure curly brace syntax for special keys.
16
+ /// If key already contains `{`, assume it's correctly formatted.
17
+ /// Otherwise, wrap the entire key in `{}` to ensure it's treated as a special key press.
18
+ fn normalize_key(key: &str) -> String {
19
+ if key.contains('{') {
20
+ key.to_string()
21
+ } else {
22
+ format!("{{{}}}", key)
23
+ }
24
+ }
25
+
15
26
  /// Result of screenshot capture operations
16
27
  #[derive(Default)]
17
28
  struct ScreenshotPaths {
@@ -2398,7 +2409,18 @@ impl Desktop {
2398
2409
  include_window_screenshot: Option<bool>,
2399
2410
  include_monitor_screenshots: Option<bool>,
2400
2411
  ) -> napi::Result<()> {
2401
- let result = self.inner.press_key(&key).await.map_err(map_error);
2412
+ // Normalize key to ensure curly brace format (e.g., "Enter" -> "{Enter}")
2413
+ let normalized_key = normalize_key(&key);
2414
+ tracing::debug!(
2415
+ "[TS SDK] desktop.press_key: normalized key: {} -> {}",
2416
+ key,
2417
+ normalized_key
2418
+ );
2419
+ let result = self
2420
+ .inner
2421
+ .press_key(&normalized_key)
2422
+ .await
2423
+ .map_err(map_error);
2402
2424
 
2403
2425
  // Get PID from process name if provided
2404
2426
  let pid = process
package/src/element.rs CHANGED
@@ -13,6 +13,17 @@ use crate::{
13
13
  use crate::Selector;
14
14
  use napi::bindgen_prelude::Either;
15
15
 
16
+ /// Normalize key format to ensure curly brace syntax for special keys.
17
+ /// If key already contains `{`, assume it's correctly formatted.
18
+ /// Otherwise, wrap the entire key in `{}` to ensure it's treated as a special key press.
19
+ fn normalize_key(key: &str) -> String {
20
+ if key.contains('{') {
21
+ key.to_string()
22
+ } else {
23
+ format!("{{{}}}", key)
24
+ }
25
+ }
26
+
16
27
  /// Click position within element bounds as percentages (0-100)
17
28
  #[napi(object)]
18
29
  #[derive(Default, Clone)]
@@ -646,8 +657,15 @@ impl Element {
646
657
  let _ = self.inner.activate_window();
647
658
  let try_focus_before = opts.try_focus_before.unwrap_or(true);
648
659
  let try_click_before = opts.try_click_before.unwrap_or(true);
660
+ // Normalize key to ensure curly brace format (e.g., "Enter" -> "{Enter}")
661
+ let normalized_key = normalize_key(&key);
662
+ tracing::debug!(
663
+ "[TS SDK] press_key: normalized key: {} -> {}",
664
+ key,
665
+ normalized_key
666
+ );
649
667
  self.inner
650
- .press_key_with_state_and_focus(&key, try_focus_before, try_click_before)
668
+ .press_key_with_state_and_focus(&normalized_key, try_focus_before, try_click_before)
651
669
  .map_err(map_error)?;
652
670
 
653
671
  // Capture screenshots if requested