pygpt-net 2.6.58__py3-none-any.whl → 2.6.59__py3-none-any.whl

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.
pygpt_net/CHANGELOG.txt CHANGED
@@ -1,3 +1,9 @@
1
+ 2.6.59 (2025-09-23)
2
+
3
+ - LlamaIndex has been upgraded to v0.13.6.
4
+ - The Responses API is disabled by default in Agents (LlamaIndex) for compatibility.
5
+ - Added WinAPI support to the System (OS) plugin.
6
+
1
7
  2.6.58 (2025-09-22)
2
8
 
3
9
  - Added: internal Web Browser tool.
pygpt_net/__init__.py CHANGED
@@ -6,15 +6,15 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2025.09.22 00:00:00 #
9
+ # Updated Date: 2025.09.23 00:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  __author__ = "Marcin Szczygliński"
13
13
  __copyright__ = "Copyright 2025, Marcin Szczygliński"
14
14
  __credits__ = ["Marcin Szczygliński"]
15
15
  __license__ = "MIT"
16
- __version__ = "2.6.58"
17
- __build__ = "2025-09-22"
16
+ __version__ = "2.6.59"
17
+ __build__ = "2025-09-23"
18
18
  __maintainer__ = "Marcin Szczygliński"
19
19
  __github__ = "https://github.com/szczyglis-dev/py-gpt"
20
20
  __report__ = "https://github.com/szczyglis-dev/py-gpt/issues"
File without changes
@@ -26,28 +26,44 @@ class Parser:
26
26
 
27
27
  def extract_data_paths(self, text: str) -> list:
28
28
  """
29
- Extract file paths from text that contain 'data' segment.
30
-
31
- :param text: input text
32
- :return: list of file paths containing 'data' segment
29
+ Extract file paths from text that contain 'data' segment (case-insensitive).
30
+ Supports quoted and unquoted paths, POSIX/Windows, and ignores URLs.
33
31
  """
34
- if text is None:
32
+ if not text:
35
33
  return []
36
- path_pattern = r"(?:[A-Za-z]:)?(?:[\\/][^\s'\";]+)+"
37
- candidates = re.findall(path_pattern, text)
38
- filtered = [
39
- p for p in candidates
40
- if re.search(r"(?:^|[\\/])data(?:[\\/]|$)", p)
41
- ]
42
- return filtered
43
-
44
- def extract_data_files(self, ctx: CtxItem, response: str) -> list:
34
+
35
+ def is_data_path(p: str) -> bool:
36
+ # 'data' (case-insensitive)
37
+ return re.search(r"(?i)(?:^|[\\/])data(?:[\\/]|$)", p) is not None
38
+
39
+ def is_url(p: str) -> bool:
40
+ return re.match(r"^[a-z][a-z0-9+.-]*://", p, re.I) is not None
41
+
42
+ results = []
43
+
44
+ quoted_pat = re.compile(r"(?P<q>['\"])(?P<p>(?:[A-Za-z]:)?[\\/](?:(?!\1).)+?)\1")
45
+ for m in quoted_pat.finditer(text):
46
+ p = m.group("p").strip()
47
+ if not is_url(p) and is_data_path(p):
48
+ results.append(p)
49
+
50
+ unquoted_pat = re.compile(r"(?P<p>(?:[A-Za-z]:)?(?:[\\/][^\s'\"),;]+)+)")
51
+ for m in unquoted_pat.finditer(text):
52
+ p = m.group("p").strip()
53
+ if not is_url(p) and is_data_path(p):
54
+ results.append(p)
55
+
56
+ seen = set()
57
+ out = []
58
+ for p in results:
59
+ if p not in seen:
60
+ seen.add(p)
61
+ out.append(p)
62
+ return out
63
+
64
+ def extract_data_files(self, ctx: "CtxItem", response: str) -> list:
45
65
  """
46
66
  Extract files from tool outputs and return list of file paths.
47
-
48
- :param ctx: CtxItem
49
- :param response: response text containing file paths
50
- :return: list of file paths
51
67
  """
52
68
  if response is None:
53
69
  return []
@@ -58,14 +74,11 @@ class Parser:
58
74
  def replace_with_local(path):
59
75
  """
60
76
  Replace the path with local data directory path.
61
-
62
- :param path: original path
63
- :return: modified path
64
77
  """
65
78
  segments = re.split(r"[\\/]+", path)
66
- try:
67
- data_index = segments.index("data")
68
- except ValueError:
79
+ # case-insensitive find of 'data'
80
+ data_index = next((i for i, s in enumerate(segments) if s.lower() == "data"), None)
81
+ if data_index is None:
69
82
  return path
70
83
  tail = segments[data_index + 1:]
71
84
  new_path = os.path.join(local_data_dir, *tail) if tail else local_data_dir
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "__meta__": {
3
- "version": "2.6.58",
4
- "app.version": "2.6.58",
5
- "updated_at": "2025-09-22T00:00:00"
3
+ "version": "2.6.59",
4
+ "app.version": "2.6.59",
5
+ "updated_at": "2025-09-23T00:00:00"
6
6
  },
7
7
  "access.audio.event.speech": false,
8
8
  "access.audio.event.speech.disabled": [],
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "__meta__": {
3
- "version": "2.6.58",
4
- "app.version": "2.6.58",
5
- "updated_at": "2025-09-22T00:00:00"
3
+ "version": "2.6.59",
4
+ "app.version": "2.6.59",
5
+ "updated_at": "2025-09-23T00:00:00"
6
6
  },
7
7
  "items": {
8
8
  "SpeakLeash/bielik-11b-v2.3-instruct:Q4_K_M": {
@@ -21,3 +21,71 @@ sandbox_docker.description = Executes all system commands within a sandbox envir
21
21
  sandbox_docker_image.description = Specifies the Docker image to use for the sandbox.
22
22
  sandbox_docker_image.label = Docker Image
23
23
  sandbox_docker.label = Sandbox (Docker Container)
24
+
25
+ # WinAPI tab/options
26
+ winapi_enabled.label = Enable WinAPI
27
+ winapi_enabled.description = Enable Windows API features on Microsoft Windows.
28
+ win_keys_per_char_delay_ms.label = Keys: per-char delay (ms)
29
+ win_keys_per_char_delay_ms.description = Delay between characters for win_keys_text.
30
+ win_keys_hold_ms.label = Keys: hold (ms)
31
+ win_keys_hold_ms.description = Hold duration for modifiers in win_keys_send.
32
+ win_keys_gap_ms.label = Keys: gap (ms)
33
+ win_keys_gap_ms.description = Gap between normal key taps in win_keys_send.
34
+ win_drag_step_delay_ms.label = Drag: step delay (ms)
35
+ win_drag_step_delay_ms.description = Delay between intermediate drag steps in win_drag.
36
+
37
+ # WinAPI commands labels/descriptions
38
+ cmd.win_list.label = Enable: List Windows
39
+ cmd.win_list.description = Lists top-level windows (HWND, title, class, PID, EXE, rect, etc.)
40
+ cmd.win_find.label = Enable: Find Windows
41
+ cmd.win_find.description = Finds windows by title/class/exe/pid.
42
+ cmd.win_children.label = Enable: List Child Windows
43
+ cmd.win_children.description = Lists child windows for a parent HWND.
44
+ cmd.win_foreground.label = Enable: Foreground Window Info
45
+ cmd.win_foreground.description = Returns information about the current foreground window.
46
+ cmd.win_rect.label = Enable: Get Window Rect
47
+ cmd.win_rect.description = Returns window rectangle (geometry).
48
+ cmd.win_get_state.label = Enable: Get Window State
49
+ cmd.win_get_state.description = Returns window metadata and flags.
50
+ cmd.win_focus.label = Enable: Focus Window
51
+ cmd.win_focus.description = Brings a selected window to the foreground.
52
+ cmd.win_move_resize.label = Enable: Move/Resize Window
53
+ cmd.win_move_resize.description = Moves and resizes a window.
54
+ cmd.win_minimize.label = Enable: Minimize Window
55
+ cmd.win_minimize.description = Minimizes a window.
56
+ cmd.win_maximize.label = Enable: Maximize Window
57
+ cmd.win_maximize.description = Maximizes a window.
58
+ cmd.win_restore.label = Enable: Restore Window
59
+ cmd.win_restore.description = Restores a window to normal state.
60
+ cmd.win_close.label = Enable: Close Window
61
+ cmd.win_close.description = Closes a window using WM_CLOSE.
62
+ cmd.win_show.label = Enable: Show Window
63
+ cmd.win_show.description = Shows a window.
64
+ cmd.win_hide.label = Enable: Hide Window
65
+ cmd.win_hide.description = Hides a window.
66
+ cmd.win_always_on_top.label = Enable: Always On Top
67
+ cmd.win_always_on_top.description = Toggles topmost flag of a window.
68
+ cmd.win_set_opacity.label = Enable: Set Opacity
69
+ cmd.win_set_opacity.description = Sets window opacity via layered window attributes.
70
+ cmd.win_screenshot.label = Enable: Window Screenshot
71
+ cmd.win_screenshot.description = Captures a window to PNG file.
72
+ cmd.win_area_screenshot.label = Enable: Area Screenshot
73
+ cmd.win_area_screenshot.description = Captures a rectangular area of the screen to PNG file.
74
+ cmd.win_clipboard_get.label = Enable: Clipboard Get
75
+ cmd.win_clipboard_get.description = Gets text from clipboard.
76
+ cmd.win_clipboard_set.label = Enable: Clipboard Set
77
+ cmd.win_clipboard_set.description = Sets text to clipboard.
78
+ cmd.win_cursor_get.label = Enable: Cursor Get
79
+ cmd.win_cursor_get.description = Gets the cursor position.
80
+ cmd.win_cursor_set.label = Enable: Cursor Set
81
+ cmd.win_cursor_set.description = Sets the cursor position.
82
+ cmd.win_keys_text.label = Enable: Type Text
83
+ cmd.win_keys_text.description = Types Unicode text into active window.
84
+ cmd.win_keys_send.label = Enable: Send Key Combos
85
+ cmd.win_keys_send.description = Sends key combinations to active window.
86
+ cmd.win_click.label = Enable: Mouse Click
87
+ cmd.win_click.description = Sends a mouse click at given coordinates.
88
+ cmd.win_drag.label = Enable: Mouse Drag
89
+ cmd.win_drag.description = Performs a mouse drag from one point to another.
90
+ cmd.win_monitors.label = Enable: List Monitors
91
+ cmd.win_monitors.description = Lists monitors/screens and their geometry.
@@ -6,7 +6,7 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2024.11.24 06:00:00 #
9
+ # Updated Date: 2025.09.23 07:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from pygpt_net.plugin.base.config import BaseConfig, BasePlugin
@@ -49,6 +49,7 @@ class Config(BaseConfig):
49
49
  }
50
50
  ports_items = []
51
51
 
52
+ # Sandbox / sys_exec (original)
52
53
  plugin.add_option(
53
54
  "sandbox_docker",
54
55
  type="bool",
@@ -134,4 +135,379 @@ class Config(BaseConfig):
134
135
  enabled=True,
135
136
  description="Allows system commands execution",
136
137
  tab="general",
138
+ )
139
+
140
+ # -------------------------------
141
+ # WinAPI options (new tab)
142
+ # -------------------------------
143
+ plugin.add_option(
144
+ "winapi_enabled",
145
+ type="bool",
146
+ value=True,
147
+ label="Enable WinAPI",
148
+ description="Enable Windows API features on Microsoft Windows.",
149
+ tab="winapi",
150
+ )
151
+ plugin.add_option(
152
+ "win_keys_per_char_delay_ms",
153
+ type="int",
154
+ value=2,
155
+ label="Keys: per-char delay (ms)",
156
+ description="Delay between characters for win_keys_text.",
157
+ tab="winapi",
158
+ )
159
+ plugin.add_option(
160
+ "win_keys_hold_ms",
161
+ type="int",
162
+ value=50,
163
+ label="Keys: hold (ms)",
164
+ description="Hold duration for modifiers in win_keys_send.",
165
+ tab="winapi",
166
+ )
167
+ plugin.add_option(
168
+ "win_keys_gap_ms",
169
+ type="int",
170
+ value=30,
171
+ label="Keys: gap (ms)",
172
+ description="Gap between normal key taps in win_keys_send.",
173
+ tab="winapi",
174
+ )
175
+ plugin.add_option(
176
+ "win_drag_step_delay_ms",
177
+ type="int",
178
+ value=10,
179
+ label="Drag: step delay (ms)",
180
+ description="Delay between intermediate drag steps in win_drag.",
181
+ tab="winapi",
182
+ )
183
+
184
+ # -------------------------------
185
+ # WinAPI commands
186
+ # -------------------------------
187
+ plugin.add_cmd(
188
+ "win_list",
189
+ instruction="List top-level windows. You can filter by title substring.",
190
+ params=[
191
+ {"name": "filter_title", "type": "str", "description": "Substring to filter by window title", "required": False},
192
+ {"name": "visible_only", "type": "bool", "description": "Only visible windows", "required": False},
193
+ {"name": "limit", "type": "int", "description": "Limit number of results", "required": False},
194
+ ],
195
+ enabled=True,
196
+ description="List top-level windows",
197
+ tab="winapi",
198
+ )
199
+ plugin.add_cmd(
200
+ "win_find",
201
+ instruction="Find windows by multiple attributes.",
202
+ params=[
203
+ {"name": "title", "type": "str", "description": "Title or substring", "required": False},
204
+ {"name": "class_name", "type": "str", "description": "Exact class name", "required": False},
205
+ {"name": "exe", "type": "str", "description": "Process executable name", "required": False},
206
+ {"name": "pid", "type": "int", "description": "Process ID", "required": False},
207
+ {"name": "exact", "type": "bool", "description": "Exact title match", "required": False},
208
+ {"name": "visible_only", "type": "bool", "description": "Only visible", "required": False},
209
+ ],
210
+ enabled=True,
211
+ description="Find windows",
212
+ tab="winapi",
213
+ )
214
+ plugin.add_cmd(
215
+ "win_children",
216
+ instruction="List child windows for a given parent HWND.",
217
+ params=[{"name": "hwnd", "type": "int", "description": "Parent window handle", "required": True}],
218
+ enabled=True,
219
+ description="List child windows",
220
+ tab="winapi",
221
+ )
222
+ plugin.add_cmd(
223
+ "win_foreground",
224
+ instruction="Return info about the current foreground window.",
225
+ params=[],
226
+ enabled=True,
227
+ description="Foreground window info",
228
+ tab="winapi",
229
+ )
230
+ plugin.add_cmd(
231
+ "win_rect",
232
+ instruction="Return window rectangle (geometry).",
233
+ params=[
234
+ {"name": "hwnd", "type": "int", "description": "Target window handle", "required": False},
235
+ {"name": "title", "type": "str", "description": "Title substring to match", "required": False},
236
+ {"name": "exact", "type": "bool", "description": "Exact title match", "required": False},
237
+ ],
238
+ enabled=True,
239
+ description="Get window rect",
240
+ tab="winapi",
241
+ )
242
+ plugin.add_cmd(
243
+ "win_get_state",
244
+ instruction="Return full window state and metadata.",
245
+ params=[
246
+ {"name": "hwnd", "type": "int", "description": "Target window handle", "required": False},
247
+ {"name": "title", "type": "str", "description": "Title substring to match", "required": False},
248
+ {"name": "exact", "type": "bool", "description": "Exact title match", "required": False},
249
+ ],
250
+ enabled=True,
251
+ description="Get window state",
252
+ tab="winapi",
253
+ )
254
+ plugin.add_cmd(
255
+ "win_focus",
256
+ instruction="Bring a window to foreground.",
257
+ params=[
258
+ {"name": "hwnd", "type": "int", "description": "Target window handle", "required": False},
259
+ {"name": "title", "type": "str", "description": "Title substring to match", "required": False},
260
+ {"name": "exact", "type": "bool", "description": "Exact title match", "required": False},
261
+ ],
262
+ enabled=True,
263
+ description="Set focus to a window",
264
+ tab="winapi",
265
+ )
266
+ plugin.add_cmd(
267
+ "win_move_resize",
268
+ instruction="Move and/or resize a window. Omit any of x,y,width,height to keep current.",
269
+ params=[
270
+ {"name": "hwnd", "type": "int", "description": "Target window handle", "required": False},
271
+ {"name": "title", "type": "str", "description": "Title substring to match", "required": False},
272
+ {"name": "exact", "type": "bool", "description": "Exact title match", "required": False},
273
+ {"name": "x", "type": "int", "description": "Left position", "required": False},
274
+ {"name": "y", "type": "int", "description": "Top position", "required": False},
275
+ {"name": "width", "type": "int", "description": "Width", "required": False},
276
+ {"name": "height", "type": "int", "description": "Height", "required": False},
277
+ ],
278
+ enabled=True,
279
+ description="Move/resize window",
280
+ tab="winapi",
281
+ )
282
+ plugin.add_cmd(
283
+ "win_minimize",
284
+ instruction="Minimize a window.",
285
+ params=[
286
+ {"name": "hwnd", "type": "int", "description": "Target window handle", "required": False},
287
+ {"name": "title", "type": "str", "description": "Title substring to match", "required": False},
288
+ {"name": "exact", "type": "bool", "description": "Exact title match", "required": False},
289
+ ],
290
+ enabled=True,
291
+ description="Minimize window",
292
+ tab="winapi",
293
+ )
294
+ plugin.add_cmd(
295
+ "win_maximize",
296
+ instruction="Maximize a window.",
297
+ params=[
298
+ {"name": "hwnd", "type": "int", "description": "Target window handle", "required": False},
299
+ {"name": "title", "type": "str", "description": "Title substring to match", "required": False},
300
+ {"name": "exact", "type": "bool", "description": "Exact title match", "required": False},
301
+ ],
302
+ enabled=True,
303
+ description="Maximize window",
304
+ tab="winapi",
305
+ )
306
+ plugin.add_cmd(
307
+ "win_restore",
308
+ instruction="Restore a minimized or maximized window.",
309
+ params=[
310
+ {"name": "hwnd", "type": "int", "description": "Target window handle", "required": False},
311
+ {"name": "title", "type": "str", "description": "Title substring to match", "required": False},
312
+ {"name": "exact", "type": "bool", "description": "Exact title match", "required": False},
313
+ ],
314
+ enabled=True,
315
+ description="Restore window",
316
+ tab="winapi",
317
+ )
318
+ plugin.add_cmd(
319
+ "win_close",
320
+ instruction="Close a window (sends WM_CLOSE).",
321
+ params=[
322
+ {"name": "hwnd", "type": "int", "description": "Target window handle", "required": False},
323
+ {"name": "title", "type": "str", "description": "Title substring to match", "required": False},
324
+ {"name": "exact", "type": "bool", "description": "Exact title match", "required": False},
325
+ ],
326
+ enabled=True,
327
+ description="Close window",
328
+ tab="winapi",
329
+ )
330
+ plugin.add_cmd(
331
+ "win_show",
332
+ instruction="Show a window.",
333
+ params=[
334
+ {"name": "hwnd", "type": "int", "description": "Target window handle", "required": False},
335
+ {"name": "title", "type": "str", "description": "Title substring to match", "required": False},
336
+ {"name": "exact", "type": "bool", "description": "Exact title match", "required": False},
337
+ ],
338
+ enabled=True,
339
+ description="Show window",
340
+ tab="winapi",
341
+ )
342
+ plugin.add_cmd(
343
+ "win_hide",
344
+ instruction="Hide a window.",
345
+ params=[
346
+ {"name": "hwnd", "type": "int", "description": "Target window handle", "required": False},
347
+ {"name": "title", "type": "str", "description": "Title substring to match", "required": False},
348
+ {"name": "exact", "type": "bool", "description": "Exact title match", "required": False},
349
+ ],
350
+ enabled=True,
351
+ description="Hide window",
352
+ tab="winapi",
353
+ )
354
+ plugin.add_cmd(
355
+ "win_always_on_top",
356
+ instruction="Toggle window always-on-top (topmost).",
357
+ params=[
358
+ {"name": "topmost", "type": "bool", "description": "True to set, False to clear", "required": True},
359
+ {"name": "hwnd", "type": "int", "description": "Target window handle", "required": False},
360
+ {"name": "title", "type": "str", "description": "Title substring to match", "required": False},
361
+ {"name": "exact", "type": "bool", "description": "Exact title match", "required": False},
362
+ ],
363
+ enabled=True,
364
+ description="Always on top",
365
+ tab="winapi",
366
+ )
367
+ plugin.add_cmd(
368
+ "win_set_opacity",
369
+ instruction="Set window opacity using layered style. Provide alpha (0..255) OR opacity (0..1).",
370
+ params=[
371
+ {"name": "alpha", "type": "int", "description": "Alpha 0..255", "required": False},
372
+ {"name": "opacity", "type": "float", "description": "Opacity 0..1", "required": False},
373
+ {"name": "hwnd", "type": "int", "description": "Target window handle", "required": False},
374
+ {"name": "title", "type": "str", "description": "Title substring to match", "required": False},
375
+ {"name": "exact", "type": "bool", "description": "Exact title match", "required": False},
376
+ ],
377
+ enabled=True,
378
+ description="Set window opacity",
379
+ tab="winapi",
380
+ )
381
+ plugin.add_cmd(
382
+ "win_screenshot",
383
+ instruction="Take a window screenshot and save to a PNG file. Returns absolute path.",
384
+ params=[
385
+ {"name": "hwnd", "type": "int", "description": "Target window handle", "required": False},
386
+ {"name": "title", "type": "str", "description": "Title substring to match", "required": False},
387
+ {"name": "exact", "type": "bool", "description": "Exact title match", "required": False},
388
+ {"name": "path", "type": "str", "description": "Output path (relative to data/ if not absolute)", "required": False},
389
+ ],
390
+ enabled=True,
391
+ description="Window screenshot to PNG",
392
+ tab="winapi",
393
+ )
394
+ plugin.add_cmd(
395
+ "win_area_screenshot",
396
+ instruction="Take a rectangular screenshot of the screen or relative to a window.",
397
+ params=[
398
+ {"name": "x", "type": "int", "description": "Left", "required": True},
399
+ {"name": "y", "type": "int", "description": "Top", "required": True},
400
+ {"name": "width", "type": "int", "description": "Width", "required": True},
401
+ {"name": "height", "type": "int", "description": "Height", "required": True},
402
+ {"name": "hwnd", "type": "int", "description": "Base window (optional)", "required": False},
403
+ {"name": "title", "type": "str", "description": "Base window by title (optional)", "required": False},
404
+ {"name": "exact", "type": "bool", "description": "Exact title match", "required": False},
405
+ {"name": "relative", "type": "bool", "description": "Coords relative to window when hwnd/title provided", "required": False},
406
+ {"name": "path", "type": "str", "description": "Output path", "required": False},
407
+ ],
408
+ enabled=True,
409
+ description="Area screenshot to PNG",
410
+ tab="winapi",
411
+ )
412
+ plugin.add_cmd(
413
+ "win_clipboard_get",
414
+ instruction="Get clipboard text.",
415
+ params=[],
416
+ enabled=True,
417
+ description="Clipboard get",
418
+ tab="winapi",
419
+ )
420
+ plugin.add_cmd(
421
+ "win_clipboard_set",
422
+ instruction="Set clipboard text.",
423
+ params=[{"name": "text", "type": "str", "description": "Text to set", "required": True}],
424
+ enabled=True,
425
+ description="Clipboard set",
426
+ tab="winapi",
427
+ )
428
+ plugin.add_cmd(
429
+ "win_cursor_get",
430
+ instruction="Get cursor position.",
431
+ params=[],
432
+ enabled=True,
433
+ description="Cursor get",
434
+ tab="winapi",
435
+ )
436
+ plugin.add_cmd(
437
+ "win_cursor_set",
438
+ instruction="Set cursor position.",
439
+ params=[
440
+ {"name": "x", "type": "int", "description": "X coordinate", "required": True},
441
+ {"name": "y", "type": "int", "description": "Y coordinate", "required": True},
442
+ ],
443
+ enabled=True,
444
+ description="Cursor set",
445
+ tab="winapi",
446
+ )
447
+ plugin.add_cmd(
448
+ "win_keys_text",
449
+ instruction="Type Unicode text into the active window (uses SendInput).",
450
+ params=[
451
+ {"name": "text", "type": "str", "description": "Text to type", "required": True},
452
+ {"name": "per_char_delay_ms", "type": "int", "description": "Delay between characters in ms", "required": False},
453
+ ],
454
+ enabled=True,
455
+ description="Type text",
456
+ tab="winapi",
457
+ )
458
+ plugin.add_cmd(
459
+ "win_keys_send",
460
+ instruction="Send key combinations, e.g. ['CTRL','ALT','T'] or ['F5'].",
461
+ params=[
462
+ {"name": "keys", "type": "list", "description": "List of key tokens", "required": True},
463
+ {"name": "hold_ms", "type": "int", "description": "Hold duration for modifiers", "required": False},
464
+ {"name": "gap_ms", "type": "int", "description": "Gap between taps", "required": False},
465
+ ],
466
+ enabled=True,
467
+ description="Send key combos",
468
+ tab="winapi",
469
+ )
470
+ plugin.add_cmd(
471
+ "win_click",
472
+ instruction="Click at a screen point or relative to a window.",
473
+ params=[
474
+ {"name": "x", "type": "int", "description": "X coordinate", "required": True},
475
+ {"name": "y", "type": "int", "description": "Y coordinate", "required": True},
476
+ {"name": "button", "type": "str", "description": "left/right/middle", "required": False},
477
+ {"name": "double", "type": "bool", "description": "Double click", "required": False},
478
+ {"name": "hwnd", "type": "int", "description": "Base window", "required": False},
479
+ {"name": "title", "type": "str", "description": "Base window by title", "required": False},
480
+ {"name": "exact", "type": "bool", "description": "Exact title match", "required": False},
481
+ {"name": "relative", "type": "bool", "description": "Coords relative to window", "required": False},
482
+ ],
483
+ enabled=True,
484
+ description="Mouse click",
485
+ tab="winapi",
486
+ )
487
+ plugin.add_cmd(
488
+ "win_drag",
489
+ instruction="Drag from (x1,y1) to (x2,y2), absolute or relative to a window.",
490
+ params=[
491
+ {"name": "x1", "type": "int", "description": "Start X", "required": True},
492
+ {"name": "y1", "type": "int", "description": "Start Y", "required": True},
493
+ {"name": "x2", "type": "int", "description": "End X", "required": True},
494
+ {"name": "y2", "type": "int", "description": "End Y", "required": True},
495
+ {"name": "hwnd", "type": "int", "description": "Base window", "required": False},
496
+ {"name": "title", "type": "str", "description": "Base window by title", "required": False},
497
+ {"name": "exact", "type": "bool", "description": "Exact title match", "required": False},
498
+ {"name": "relative", "type": "bool", "description": "Coords relative to window", "required": False},
499
+ {"name": "steps", "type": "int", "description": "Interpolation steps", "required": False},
500
+ {"name": "hold_ms", "type": "int", "description": "Delay between steps (ms)", "required": False},
501
+ ],
502
+ enabled=True,
503
+ description="Mouse drag",
504
+ tab="winapi",
505
+ )
506
+ plugin.add_cmd(
507
+ "win_monitors",
508
+ instruction="List monitors/screens and their geometry.",
509
+ params=[],
510
+ enabled=True,
511
+ description="List monitors",
512
+ tab="winapi",
137
513
  )