@midscene/computer 1.12.7-beta-20260911063016.0 → 1.12.7
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/README.md +1 -49
- package/bin/darwin/rdp-helper +0 -0
- package/bin/linux/rdp-helper +0 -0
- package/dist/es/cli.mjs +239 -157
- package/dist/es/index.mjs +239 -157
- package/dist/lib/cli.js +239 -157
- package/dist/lib/index.js +239 -157
- package/dist/types/index.d.ts +20 -1
- package/native/rdp/CMakeLists.txt +22 -0
- package/native/rdp/include/rdp_helper_framebuffer.hpp +24 -0
- package/native/rdp/include/rdp_helper_session.hpp +7 -3
- package/native/rdp/src/png.cpp +5 -2
- package/native/rdp/src/session.cpp +60 -55
- package/native/rdp/tests/screenshot_test.cpp +365 -0
- package/native/rdp/tests/xrdp_desktop.py +135 -0
- package/package.json +3 -3
package/dist/es/index.mjs
CHANGED
|
@@ -19,6 +19,73 @@ import { z } from "@midscene/core";
|
|
|
19
19
|
import { agentBehaviorInitArgShape, extractAgentBehaviorInitArgs, getAgentInitArgsSignature, shouldRebuildAgentForInitArgs } from "@midscene/shared/agent-tools/agent-behavior-init-args";
|
|
20
20
|
import { BaseMidsceneTools } from "@midscene/shared/agent-tools/base-tools";
|
|
21
21
|
import { overrideAIConfig } from "@midscene/shared/env";
|
|
22
|
+
const debugKeyboard = getDebug('computer:keyboard');
|
|
23
|
+
const APPLE_SCRIPT_KEY_CODES = {
|
|
24
|
+
return: 36,
|
|
25
|
+
enter: 36,
|
|
26
|
+
tab: 48,
|
|
27
|
+
space: 49,
|
|
28
|
+
backspace: 51,
|
|
29
|
+
delete: 51,
|
|
30
|
+
escape: 53,
|
|
31
|
+
forwarddelete: 117,
|
|
32
|
+
left: 123,
|
|
33
|
+
right: 124,
|
|
34
|
+
down: 125,
|
|
35
|
+
up: 126,
|
|
36
|
+
home: 115,
|
|
37
|
+
end: 119,
|
|
38
|
+
pageup: 116,
|
|
39
|
+
pagedown: 121,
|
|
40
|
+
f1: 122,
|
|
41
|
+
f2: 120,
|
|
42
|
+
f3: 99,
|
|
43
|
+
f4: 118,
|
|
44
|
+
f5: 96,
|
|
45
|
+
f6: 97,
|
|
46
|
+
f7: 98,
|
|
47
|
+
f8: 100,
|
|
48
|
+
f9: 101,
|
|
49
|
+
f10: 109,
|
|
50
|
+
f11: 103,
|
|
51
|
+
f12: 111
|
|
52
|
+
};
|
|
53
|
+
const APPLE_SCRIPT_MODIFIER_KEYS = {
|
|
54
|
+
command: 'command',
|
|
55
|
+
cmd: 'command',
|
|
56
|
+
control: 'control',
|
|
57
|
+
ctrl: 'control',
|
|
58
|
+
shift: 'shift',
|
|
59
|
+
alt: 'option',
|
|
60
|
+
option: 'option',
|
|
61
|
+
meta: 'command'
|
|
62
|
+
};
|
|
63
|
+
function buildKeyCommand(key) {
|
|
64
|
+
const keyCode = APPLE_SCRIPT_KEY_CODES[key.toLowerCase()];
|
|
65
|
+
if (void 0 !== keyCode) return `key code ${keyCode}`;
|
|
66
|
+
const escapedKey = key.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
67
|
+
return `keystroke "${escapedKey}"`;
|
|
68
|
+
}
|
|
69
|
+
function resolveModifierKeys(modifiers) {
|
|
70
|
+
return modifiers.map((modifier)=>APPLE_SCRIPT_MODIFIER_KEYS[modifier.toLowerCase()]).filter((modifier)=>void 0 !== modifier);
|
|
71
|
+
}
|
|
72
|
+
function buildAppleScriptKeyPress(key, modifiers = []) {
|
|
73
|
+
const modifierKeys = resolveModifierKeys(modifiers);
|
|
74
|
+
const modifierClause = modifierKeys.length ? ` using {${modifierKeys.map((modifier)=>`${modifier} down`).join(', ')}}` : '';
|
|
75
|
+
return `tell application "System Events" to ${buildKeyCommand(key)}${modifierClause}`;
|
|
76
|
+
}
|
|
77
|
+
function sendKeyViaAppleScript(key, modifiers = []) {
|
|
78
|
+
const script = buildAppleScriptKeyPress(key, modifiers);
|
|
79
|
+
debugKeyboard('sendKeyViaAppleScript', {
|
|
80
|
+
key,
|
|
81
|
+
modifiers,
|
|
82
|
+
script
|
|
83
|
+
});
|
|
84
|
+
execFileSync("osascript", [
|
|
85
|
+
'-e',
|
|
86
|
+
script
|
|
87
|
+
]);
|
|
88
|
+
}
|
|
22
89
|
function _define_property(obj, key, value) {
|
|
23
90
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
24
91
|
value: value,
|
|
@@ -91,6 +158,41 @@ class ComputerInputDriver {
|
|
|
91
158
|
if (void 0 !== modifiers) lib.keyTap(key, modifiers);
|
|
92
159
|
else lib.keyTap(key);
|
|
93
160
|
}
|
|
161
|
+
keyToggle(key, state, modifiers) {
|
|
162
|
+
const lib = this.getLibnutOrThrow('keyToggle');
|
|
163
|
+
if (void 0 !== modifiers) lib.keyToggle(key, state, modifiers);
|
|
164
|
+
else lib.keyToggle(key, state);
|
|
165
|
+
}
|
|
166
|
+
async keyTapWithModifierDelay(key, modifiers, delayMs) {
|
|
167
|
+
const uniqueModifiers = [
|
|
168
|
+
...new Set(modifiers)
|
|
169
|
+
];
|
|
170
|
+
if (0 === uniqueModifiers.length) return void this.keyTap(key);
|
|
171
|
+
if (0 === delayMs) return void this.keyTap(key, uniqueModifiers);
|
|
172
|
+
const pressedModifiers = [];
|
|
173
|
+
let failure;
|
|
174
|
+
try {
|
|
175
|
+
for (const modifier of uniqueModifiers){
|
|
176
|
+
this.keyToggle(modifier, 'down');
|
|
177
|
+
pressedModifiers.push(modifier);
|
|
178
|
+
await this.delay(delayMs);
|
|
179
|
+
}
|
|
180
|
+
this.keyTap(key);
|
|
181
|
+
await this.delay(delayMs);
|
|
182
|
+
} catch (error) {
|
|
183
|
+
failure = error;
|
|
184
|
+
}
|
|
185
|
+
for (const modifier of pressedModifiers.reverse()){
|
|
186
|
+
const releaseFailure = this.tryReleaseKey(modifier);
|
|
187
|
+
if (void 0 === failure && void 0 !== releaseFailure) failure = releaseFailure;
|
|
188
|
+
if (void 0 === failure) try {
|
|
189
|
+
await this.delay(delayMs);
|
|
190
|
+
} catch (error) {
|
|
191
|
+
failure = error;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
if (void 0 !== failure) throw failure;
|
|
195
|
+
}
|
|
94
196
|
typeString(text) {
|
|
95
197
|
this.getLibnutOrThrow('typeString').typeString(text);
|
|
96
198
|
}
|
|
@@ -163,6 +265,20 @@ class ComputerInputDriver {
|
|
|
163
265
|
this.options.debug(`Failed to release mouse button ${button}: ${error}`);
|
|
164
266
|
}
|
|
165
267
|
}
|
|
268
|
+
tryReleaseKey(key) {
|
|
269
|
+
try {
|
|
270
|
+
const libnut = this.options.getLibnut();
|
|
271
|
+
node_assert(libnut, 'libnut not initialized');
|
|
272
|
+
libnut.keyToggle(key, 'up');
|
|
273
|
+
return;
|
|
274
|
+
} catch (error) {
|
|
275
|
+
const releaseError = new Error(`Failed to release modifier key "${key}"`, {
|
|
276
|
+
cause: error
|
|
277
|
+
});
|
|
278
|
+
this.options.debug(`${releaseError.message}: ${error}`);
|
|
279
|
+
return releaseError;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
166
282
|
rejectPendingInputDelays() {
|
|
167
283
|
const error = this.createDestroyedError('in-flight input');
|
|
168
284
|
for (const waitRef of this.pendingInputDelayWaits){
|
|
@@ -180,6 +296,96 @@ class ComputerInputDriver {
|
|
|
180
296
|
this.pendingInputDelayWaits = new Set();
|
|
181
297
|
}
|
|
182
298
|
}
|
|
299
|
+
const US_SHIFTED_CHARACTER_KEYS = new Map([
|
|
300
|
+
[
|
|
301
|
+
'~',
|
|
302
|
+
'`'
|
|
303
|
+
],
|
|
304
|
+
[
|
|
305
|
+
'!',
|
|
306
|
+
'1'
|
|
307
|
+
],
|
|
308
|
+
[
|
|
309
|
+
'@',
|
|
310
|
+
'2'
|
|
311
|
+
],
|
|
312
|
+
[
|
|
313
|
+
'#',
|
|
314
|
+
'3'
|
|
315
|
+
],
|
|
316
|
+
[
|
|
317
|
+
'$',
|
|
318
|
+
'4'
|
|
319
|
+
],
|
|
320
|
+
[
|
|
321
|
+
'%',
|
|
322
|
+
'5'
|
|
323
|
+
],
|
|
324
|
+
[
|
|
325
|
+
'^',
|
|
326
|
+
'6'
|
|
327
|
+
],
|
|
328
|
+
[
|
|
329
|
+
'&',
|
|
330
|
+
'7'
|
|
331
|
+
],
|
|
332
|
+
[
|
|
333
|
+
'*',
|
|
334
|
+
'8'
|
|
335
|
+
],
|
|
336
|
+
[
|
|
337
|
+
'(',
|
|
338
|
+
'9'
|
|
339
|
+
],
|
|
340
|
+
[
|
|
341
|
+
')',
|
|
342
|
+
'0'
|
|
343
|
+
],
|
|
344
|
+
[
|
|
345
|
+
'_',
|
|
346
|
+
'-'
|
|
347
|
+
],
|
|
348
|
+
[
|
|
349
|
+
'+',
|
|
350
|
+
'='
|
|
351
|
+
],
|
|
352
|
+
[
|
|
353
|
+
'{',
|
|
354
|
+
'['
|
|
355
|
+
],
|
|
356
|
+
[
|
|
357
|
+
'}',
|
|
358
|
+
']'
|
|
359
|
+
],
|
|
360
|
+
[
|
|
361
|
+
'|',
|
|
362
|
+
'\\'
|
|
363
|
+
],
|
|
364
|
+
[
|
|
365
|
+
':',
|
|
366
|
+
';'
|
|
367
|
+
],
|
|
368
|
+
[
|
|
369
|
+
'"',
|
|
370
|
+
"'"
|
|
371
|
+
],
|
|
372
|
+
[
|
|
373
|
+
'<',
|
|
374
|
+
','
|
|
375
|
+
],
|
|
376
|
+
[
|
|
377
|
+
'>',
|
|
378
|
+
'.'
|
|
379
|
+
],
|
|
380
|
+
[
|
|
381
|
+
'?',
|
|
382
|
+
'/'
|
|
383
|
+
]
|
|
384
|
+
]);
|
|
385
|
+
function resolveShiftedKey(character, keyboardLayout) {
|
|
386
|
+
if (/^[A-Z]$/.test(character)) return character.toLowerCase();
|
|
387
|
+
return 'en-US' === keyboardLayout ? US_SHIFTED_CHARACTER_KEYS.get(character) : void 0;
|
|
388
|
+
}
|
|
183
389
|
const POWERSHELL_TIMEOUT_MS = 15000;
|
|
184
390
|
const POWERSHELL_MAX_BUFFER = 67108864;
|
|
185
391
|
const WINDOWS_PHYSICAL_PIXEL_POWERSHELL_PREAMBLE = `
|
|
@@ -543,92 +749,6 @@ const LIBNUT_FALLBACK_PIXELS_PER_DETENT = 100;
|
|
|
543
749
|
const LIBNUT_FALLBACK_TICK_DELAY_MS = 30;
|
|
544
750
|
const LIBNUT_FALLBACK_MAX_DETENTS = 200;
|
|
545
751
|
const LIBNUT_FALLBACK_DETENT_AMOUNT = 'win32' === process.platform ? 120 : 1;
|
|
546
|
-
const LINUX_SHIFTED_CHARACTER_KEYS = new Map([
|
|
547
|
-
[
|
|
548
|
-
'~',
|
|
549
|
-
'`'
|
|
550
|
-
],
|
|
551
|
-
[
|
|
552
|
-
'!',
|
|
553
|
-
'1'
|
|
554
|
-
],
|
|
555
|
-
[
|
|
556
|
-
'@',
|
|
557
|
-
'2'
|
|
558
|
-
],
|
|
559
|
-
[
|
|
560
|
-
'#',
|
|
561
|
-
'3'
|
|
562
|
-
],
|
|
563
|
-
[
|
|
564
|
-
'$',
|
|
565
|
-
'4'
|
|
566
|
-
],
|
|
567
|
-
[
|
|
568
|
-
'%',
|
|
569
|
-
'5'
|
|
570
|
-
],
|
|
571
|
-
[
|
|
572
|
-
'^',
|
|
573
|
-
'6'
|
|
574
|
-
],
|
|
575
|
-
[
|
|
576
|
-
'&',
|
|
577
|
-
'7'
|
|
578
|
-
],
|
|
579
|
-
[
|
|
580
|
-
'*',
|
|
581
|
-
'8'
|
|
582
|
-
],
|
|
583
|
-
[
|
|
584
|
-
'(',
|
|
585
|
-
'9'
|
|
586
|
-
],
|
|
587
|
-
[
|
|
588
|
-
')',
|
|
589
|
-
'0'
|
|
590
|
-
],
|
|
591
|
-
[
|
|
592
|
-
'_',
|
|
593
|
-
'-'
|
|
594
|
-
],
|
|
595
|
-
[
|
|
596
|
-
'+',
|
|
597
|
-
'='
|
|
598
|
-
],
|
|
599
|
-
[
|
|
600
|
-
'{',
|
|
601
|
-
'['
|
|
602
|
-
],
|
|
603
|
-
[
|
|
604
|
-
'}',
|
|
605
|
-
']'
|
|
606
|
-
],
|
|
607
|
-
[
|
|
608
|
-
'|',
|
|
609
|
-
'\\'
|
|
610
|
-
],
|
|
611
|
-
[
|
|
612
|
-
':',
|
|
613
|
-
';'
|
|
614
|
-
],
|
|
615
|
-
[
|
|
616
|
-
'"',
|
|
617
|
-
"'"
|
|
618
|
-
],
|
|
619
|
-
[
|
|
620
|
-
'<',
|
|
621
|
-
','
|
|
622
|
-
],
|
|
623
|
-
[
|
|
624
|
-
'>',
|
|
625
|
-
'.'
|
|
626
|
-
],
|
|
627
|
-
[
|
|
628
|
-
'?',
|
|
629
|
-
'/'
|
|
630
|
-
]
|
|
631
|
-
]);
|
|
632
752
|
const LIBNUT_FALLBACK_EDGE_DETENTS = Math.min(LIBNUT_FALLBACK_MAX_DETENTS, Math.max(1, Math.ceil(EDGE_SCROLL_TOTAL_PX / LIBNUT_FALLBACK_PIXELS_PER_DETENT)));
|
|
633
753
|
const DEFAULT_SCROLL_VIEWPORT_RATIO = 0.7;
|
|
634
754
|
const EDGE_SCROLL_SPEC = {
|
|
@@ -665,67 +785,6 @@ const EDGE_SCROLL_SPEC = {
|
|
|
665
785
|
]
|
|
666
786
|
}
|
|
667
787
|
};
|
|
668
|
-
const APPLESCRIPT_KEY_CODE_MAP = {
|
|
669
|
-
return: 36,
|
|
670
|
-
enter: 36,
|
|
671
|
-
tab: 48,
|
|
672
|
-
space: 49,
|
|
673
|
-
backspace: 51,
|
|
674
|
-
delete: 51,
|
|
675
|
-
escape: 53,
|
|
676
|
-
forwarddelete: 117,
|
|
677
|
-
left: 123,
|
|
678
|
-
right: 124,
|
|
679
|
-
down: 125,
|
|
680
|
-
up: 126,
|
|
681
|
-
home: 115,
|
|
682
|
-
end: 119,
|
|
683
|
-
pageup: 116,
|
|
684
|
-
pagedown: 121,
|
|
685
|
-
f1: 122,
|
|
686
|
-
f2: 120,
|
|
687
|
-
f3: 99,
|
|
688
|
-
f4: 118,
|
|
689
|
-
f5: 96,
|
|
690
|
-
f6: 97,
|
|
691
|
-
f7: 98,
|
|
692
|
-
f8: 100,
|
|
693
|
-
f9: 101,
|
|
694
|
-
f10: 109,
|
|
695
|
-
f11: 103,
|
|
696
|
-
f12: 111
|
|
697
|
-
};
|
|
698
|
-
const APPLESCRIPT_MODIFIER_MAP = {
|
|
699
|
-
command: 'command down',
|
|
700
|
-
cmd: 'command down',
|
|
701
|
-
control: 'control down',
|
|
702
|
-
ctrl: 'control down',
|
|
703
|
-
shift: 'shift down',
|
|
704
|
-
alt: 'option down',
|
|
705
|
-
option: 'option down',
|
|
706
|
-
meta: 'command down'
|
|
707
|
-
};
|
|
708
|
-
function sendKeyViaAppleScript(key, modifiers = []) {
|
|
709
|
-
const lowerKey = key.toLowerCase();
|
|
710
|
-
const keyCode = APPLESCRIPT_KEY_CODE_MAP[lowerKey];
|
|
711
|
-
const modifierParts = modifiers.map((m)=>APPLESCRIPT_MODIFIER_MAP[m.toLowerCase()]).filter(Boolean);
|
|
712
|
-
const modifierStr = modifierParts.length > 0 ? ` using {${modifierParts.join(', ')}}` : '';
|
|
713
|
-
let script;
|
|
714
|
-
if (void 0 !== keyCode) script = `tell application "System Events" to key code ${keyCode}${modifierStr}`;
|
|
715
|
-
else {
|
|
716
|
-
const escapedKey = key.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
717
|
-
script = `tell application "System Events" to keystroke "${escapedKey}"${modifierStr}`;
|
|
718
|
-
}
|
|
719
|
-
debugDevice('sendKeyViaAppleScript', {
|
|
720
|
-
key,
|
|
721
|
-
modifiers,
|
|
722
|
-
script
|
|
723
|
-
});
|
|
724
|
-
execFileSync("osascript", [
|
|
725
|
-
'-e',
|
|
726
|
-
script
|
|
727
|
-
]);
|
|
728
|
-
}
|
|
729
788
|
function escapePowershellSingleQuoted(value) {
|
|
730
789
|
return value.replace(/'/g, "''");
|
|
731
790
|
}
|
|
@@ -1153,7 +1212,7 @@ Available Displays: ${displays.length > 0 ? displays.map((d)=>d.name).join(', ')
|
|
|
1153
1212
|
}
|
|
1154
1213
|
async healthCheck(displays) {
|
|
1155
1214
|
console.log('[HealthCheck] Starting health check...');
|
|
1156
|
-
console.log("[HealthCheck] @midscene/computer v1.12.7
|
|
1215
|
+
console.log("[HealthCheck] @midscene/computer v1.12.7");
|
|
1157
1216
|
console.log('[HealthCheck] Taking screenshot...');
|
|
1158
1217
|
const screenshotTimeout = 15000;
|
|
1159
1218
|
let timeoutId;
|
|
@@ -1330,9 +1389,9 @@ $g.Dispose(); $bmp.Dispose(); $ms.Dispose()
|
|
|
1330
1389
|
]);
|
|
1331
1390
|
else {
|
|
1332
1391
|
const modifier = 'darwin' === process.platform ? 'command' : 'control';
|
|
1333
|
-
this.inputDriver.
|
|
1392
|
+
await this.inputDriver.keyTapWithModifierDelay('v', [
|
|
1334
1393
|
modifier
|
|
1335
|
-
]);
|
|
1394
|
+
], this.options?.keyboardModifierDelay ?? 0);
|
|
1336
1395
|
}
|
|
1337
1396
|
await this.inputDriver.delay(100);
|
|
1338
1397
|
} finally{
|
|
@@ -1347,12 +1406,16 @@ $g.Dispose(); $bmp.Dispose(); $ms.Dispose()
|
|
|
1347
1406
|
}
|
|
1348
1407
|
async typeStringWithDelay(text, keyboardTypeDelay) {
|
|
1349
1408
|
await sendTextSequentially(text.replace(/\r\n?/g, '\n'), {
|
|
1350
|
-
sendCharacter: (character)=>{
|
|
1351
|
-
const linuxShiftedKey = 'linux' === process.platform ?
|
|
1409
|
+
sendCharacter: async (character)=>{
|
|
1410
|
+
const linuxShiftedKey = 'linux' === process.platform ? US_SHIFTED_CHARACTER_KEYS.get(character) : void 0;
|
|
1411
|
+
const pacedShiftedKey = !this.useAppleScript && (this.options?.keyboardModifierDelay ?? 0) > 0 ? resolveShiftedKey(character, this.options?.keyboardLayout) : void 0;
|
|
1352
1412
|
if ('\n' === character) this.inputDriver.sendKey('return');
|
|
1353
1413
|
else if ('\t' === character) this.inputDriver.sendKey('tab');
|
|
1354
1414
|
else if (' ' === character) this.inputDriver.sendKey('space');
|
|
1355
1415
|
else if (this.useAppleScript) this.inputDriver.sendKeyViaAppleScript(character);
|
|
1416
|
+
else if (void 0 !== pacedShiftedKey) await this.inputDriver.keyTapWithModifierDelay(pacedShiftedKey, [
|
|
1417
|
+
'shift'
|
|
1418
|
+
], this.options?.keyboardModifierDelay ?? 0);
|
|
1356
1419
|
else if (void 0 !== linuxShiftedKey) this.inputDriver.keyTap(linuxShiftedKey, [
|
|
1357
1420
|
'shift'
|
|
1358
1421
|
]);
|
|
@@ -1373,9 +1436,9 @@ $g.Dispose(); $bmp.Dispose(); $ms.Dispose()
|
|
|
1373
1436
|
return;
|
|
1374
1437
|
}
|
|
1375
1438
|
const modifier = 'darwin' === process.platform ? 'command' : 'control';
|
|
1376
|
-
this.inputDriver.
|
|
1439
|
+
await this.inputDriver.keyTapWithModifierDelay('a', [
|
|
1377
1440
|
modifier
|
|
1378
|
-
]);
|
|
1441
|
+
], this.options?.keyboardModifierDelay ?? 0);
|
|
1379
1442
|
await this.inputDriver.delay(50);
|
|
1380
1443
|
this.inputDriver.keyTap('backspace');
|
|
1381
1444
|
}
|
|
@@ -1389,6 +1452,7 @@ $g.Dispose(); $bmp.Dispose(); $ms.Dispose()
|
|
|
1389
1452
|
modifiers,
|
|
1390
1453
|
driver: this.useAppleScript ? "applescript" : 'libnut'
|
|
1391
1454
|
});
|
|
1455
|
+
if (!this.useAppleScript && modifiers.length > 0 && (this.options?.keyboardModifierDelay ?? 0) > 0) return void await this.inputDriver.keyTapWithModifierDelay(key, modifiers, this.options?.keyboardModifierDelay ?? 0);
|
|
1392
1456
|
this.inputDriver.sendKey(key, modifiers);
|
|
1393
1457
|
}
|
|
1394
1458
|
resolveUntargetedScrollPoint(screenSize) {
|
|
@@ -1542,7 +1606,7 @@ $g.Dispose(); $bmp.Dispose(); $ms.Dispose()
|
|
|
1542
1606
|
device_define_property(this, "inputDriver", new ComputerInputDriver({
|
|
1543
1607
|
getLibnut: ()=>device_libnut,
|
|
1544
1608
|
useAppleScript: ()=>this.useAppleScript,
|
|
1545
|
-
sendKeyViaAppleScript,
|
|
1609
|
+
sendKeyViaAppleScript: sendKeyViaAppleScript,
|
|
1546
1610
|
runPhasedScroll,
|
|
1547
1611
|
debug: (message)=>debugDevice(message)
|
|
1548
1612
|
}));
|
|
@@ -1668,6 +1732,8 @@ $g.Dispose(); $bmp.Dispose(); $ms.Dispose()
|
|
|
1668
1732
|
}
|
|
1669
1733
|
}
|
|
1670
1734
|
});
|
|
1735
|
+
if (options?.keyboardModifierDelay !== void 0 && (!Number.isFinite(options.keyboardModifierDelay) || options.keyboardModifierDelay < 0)) throw new Error('keyboardModifierDelay must be a finite non-negative number');
|
|
1736
|
+
if (options?.keyboardLayout !== void 0 && 'en-US' !== options.keyboardLayout) throw new Error('keyboardLayout must be "en-US" when specified');
|
|
1671
1737
|
this.options = options;
|
|
1672
1738
|
this.displayId = options?.displayId;
|
|
1673
1739
|
this.useAppleScript = 'darwin' === process.platform && options?.keyboardDriver !== 'libnut';
|
|
@@ -2413,6 +2479,8 @@ function createLocalComputerDevice(opts) {
|
|
|
2413
2479
|
keyboardTypeDelay: opts?.keyboardTypeDelay,
|
|
2414
2480
|
inputStrategy: opts?.inputStrategy,
|
|
2415
2481
|
keyboardDriver: opts?.keyboardDriver,
|
|
2482
|
+
keyboardModifierDelay: opts?.keyboardModifierDelay,
|
|
2483
|
+
keyboardLayout: opts?.keyboardLayout,
|
|
2416
2484
|
headless: opts?.headless,
|
|
2417
2485
|
xvfbResolution: opts?.xvfbResolution,
|
|
2418
2486
|
keepXvfbAliveUntilProcessExit: opts?.keepXvfbAliveUntilProcessExit
|
|
@@ -2470,6 +2538,10 @@ const computerInitArgShape = {
|
|
|
2470
2538
|
headless: z.boolean().optional().describe('Start virtual display via Xvfb (Linux local mode only). Ignored when host is set.'),
|
|
2471
2539
|
keyboardTypeDelay: z.number().finite().nonnegative().optional().describe('Finite non-negative delay in milliseconds between keystrokes. In "legacy" mode, positive values enable key-by-key input; zero or omitted uses clipboard input.'),
|
|
2472
2540
|
inputStrategy: z["enum"](inputStrategies).optional().describe('Text input strategy. "legacy" (default) preserves current Computer behavior, "sequential" sends one Unicode code point at a time, and "bulk" uses one backend input operation. "bulk" requires keyboardTypeDelay to be omitted or set to 0.'),
|
|
2541
|
+
keyboardModifierDelay: z.number().finite().nonnegative().optional().describe('Finite non-negative delay in milliseconds after each modifier transition and the main key for local libnut keyboard events. Positive values pace shortcuts and the implicit Shift used by uppercase letters during sequential input. Layout-dependent punctuation also requires keyboardLayout. Ignored in RDP mode and by the macOS AppleScript driver.'),
|
|
2542
|
+
keyboardLayout: z["enum"]([
|
|
2543
|
+
'en-US'
|
|
2544
|
+
]).optional().describe('Keyboard layout used to resolve layout-dependent shifted punctuation to base keys during sequential local libnut input. Currently only "en-US" is supported. Ignored in RDP mode and by the macOS AppleScript driver.'),
|
|
2473
2545
|
host: z.string().optional().describe('RDP host (FQDN or IP). Set this to switch into RDP mode.'),
|
|
2474
2546
|
port: z.number().optional().describe('RDP port (default 3389). Requires host.'),
|
|
2475
2547
|
username: z.string().optional().describe('RDP username. Requires host.'),
|
|
@@ -2486,7 +2558,7 @@ const computerInitArgShape = {
|
|
|
2486
2558
|
function adaptComputerInitArgs(extracted) {
|
|
2487
2559
|
if (!extracted || 0 === Object.keys(extracted).length) return;
|
|
2488
2560
|
if (extracted.host) {
|
|
2489
|
-
const { displayId: _d, headless: _h, ...rdpFields } = extracted;
|
|
2561
|
+
const { displayId: _d, headless: _h, keyboardModifierDelay: _s, keyboardLayout: _l, ...rdpFields } = extracted;
|
|
2490
2562
|
const host = normalizeRdpHost(extracted.host);
|
|
2491
2563
|
return {
|
|
2492
2564
|
mode: 'rdp',
|
|
@@ -2500,6 +2572,8 @@ function adaptComputerInitArgs(extracted) {
|
|
|
2500
2572
|
headless: extracted.headless,
|
|
2501
2573
|
keyboardTypeDelay: extracted.keyboardTypeDelay,
|
|
2502
2574
|
inputStrategy: extracted.inputStrategy,
|
|
2575
|
+
keyboardModifierDelay: extracted.keyboardModifierDelay,
|
|
2576
|
+
keyboardLayout: extracted.keyboardLayout,
|
|
2503
2577
|
...extractAgentBehaviorInitArgs(extracted) ?? {}
|
|
2504
2578
|
};
|
|
2505
2579
|
}
|
|
@@ -2551,6 +2625,8 @@ class ComputerMidsceneTools extends BaseMidsceneTools {
|
|
|
2551
2625
|
const headless = opts?.mode === 'local' ? opts.headless : void 0;
|
|
2552
2626
|
const keyboardTypeDelay = opts?.keyboardTypeDelay;
|
|
2553
2627
|
const inputStrategy = opts?.inputStrategy;
|
|
2628
|
+
const keyboardModifierDelay = opts?.mode === 'local' ? opts.keyboardModifierDelay : void 0;
|
|
2629
|
+
const keyboardLayout = opts?.mode === 'local' ? opts.keyboardLayout : void 0;
|
|
2554
2630
|
agent_tools_debug('Creating Computer agent with displayId:', displayId || 'primary');
|
|
2555
2631
|
const agentOpts = {
|
|
2556
2632
|
...displayId ? {
|
|
@@ -2565,6 +2641,12 @@ class ComputerMidsceneTools extends BaseMidsceneTools {
|
|
|
2565
2641
|
...void 0 !== inputStrategy ? {
|
|
2566
2642
|
inputStrategy
|
|
2567
2643
|
} : {},
|
|
2644
|
+
...void 0 !== keyboardModifierDelay ? {
|
|
2645
|
+
keyboardModifierDelay
|
|
2646
|
+
} : {},
|
|
2647
|
+
...void 0 !== keyboardLayout ? {
|
|
2648
|
+
keyboardLayout
|
|
2649
|
+
} : {},
|
|
2568
2650
|
...this.options.keepXvfbAliveUntilProcessExit ? {
|
|
2569
2651
|
keepXvfbAliveUntilProcessExit: true
|
|
2570
2652
|
} : {},
|
|
@@ -2645,7 +2727,7 @@ class ComputerMidsceneTools extends BaseMidsceneTools {
|
|
|
2645
2727
|
}
|
|
2646
2728
|
}
|
|
2647
2729
|
function version() {
|
|
2648
|
-
const currentVersion = "1.12.7
|
|
2730
|
+
const currentVersion = "1.12.7";
|
|
2649
2731
|
console.log(`@midscene/computer v${currentVersion}`);
|
|
2650
2732
|
return currentVersion;
|
|
2651
2733
|
}
|