@midscene/computer 1.12.5 → 1.12.6-beta-20260909033030.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.
- package/README.md +1 -49
- package/dist/es/cli.mjs +269 -155
- package/dist/es/index.mjs +269 -155
- package/dist/lib/cli.js +269 -155
- package/dist/lib/index.js +269 -155
- package/dist/types/index.d.ts +39 -1
- package/package.json +3 -3
package/dist/es/index.mjs
CHANGED
|
@@ -19,6 +19,207 @@ 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 US_SHIFTED_CHARACTER_KEYS = new Map([
|
|
23
|
+
[
|
|
24
|
+
'~',
|
|
25
|
+
'`'
|
|
26
|
+
],
|
|
27
|
+
[
|
|
28
|
+
'!',
|
|
29
|
+
'1'
|
|
30
|
+
],
|
|
31
|
+
[
|
|
32
|
+
'@',
|
|
33
|
+
'2'
|
|
34
|
+
],
|
|
35
|
+
[
|
|
36
|
+
'#',
|
|
37
|
+
'3'
|
|
38
|
+
],
|
|
39
|
+
[
|
|
40
|
+
'$',
|
|
41
|
+
'4'
|
|
42
|
+
],
|
|
43
|
+
[
|
|
44
|
+
'%',
|
|
45
|
+
'5'
|
|
46
|
+
],
|
|
47
|
+
[
|
|
48
|
+
'^',
|
|
49
|
+
'6'
|
|
50
|
+
],
|
|
51
|
+
[
|
|
52
|
+
'&',
|
|
53
|
+
'7'
|
|
54
|
+
],
|
|
55
|
+
[
|
|
56
|
+
'*',
|
|
57
|
+
'8'
|
|
58
|
+
],
|
|
59
|
+
[
|
|
60
|
+
'(',
|
|
61
|
+
'9'
|
|
62
|
+
],
|
|
63
|
+
[
|
|
64
|
+
')',
|
|
65
|
+
'0'
|
|
66
|
+
],
|
|
67
|
+
[
|
|
68
|
+
'_',
|
|
69
|
+
'-'
|
|
70
|
+
],
|
|
71
|
+
[
|
|
72
|
+
'+',
|
|
73
|
+
'='
|
|
74
|
+
],
|
|
75
|
+
[
|
|
76
|
+
'{',
|
|
77
|
+
'['
|
|
78
|
+
],
|
|
79
|
+
[
|
|
80
|
+
'}',
|
|
81
|
+
']'
|
|
82
|
+
],
|
|
83
|
+
[
|
|
84
|
+
'|',
|
|
85
|
+
'\\'
|
|
86
|
+
],
|
|
87
|
+
[
|
|
88
|
+
':',
|
|
89
|
+
';'
|
|
90
|
+
],
|
|
91
|
+
[
|
|
92
|
+
'"',
|
|
93
|
+
"'"
|
|
94
|
+
],
|
|
95
|
+
[
|
|
96
|
+
'<',
|
|
97
|
+
','
|
|
98
|
+
],
|
|
99
|
+
[
|
|
100
|
+
'>',
|
|
101
|
+
'.'
|
|
102
|
+
],
|
|
103
|
+
[
|
|
104
|
+
'?',
|
|
105
|
+
'/'
|
|
106
|
+
]
|
|
107
|
+
]);
|
|
108
|
+
function resolveUSShiftedKey(character) {
|
|
109
|
+
if (/^[A-Z]$/.test(character)) return character.toLowerCase();
|
|
110
|
+
return US_SHIFTED_CHARACTER_KEYS.get(character);
|
|
111
|
+
}
|
|
112
|
+
const debugKeyboard = getDebug('computer:keyboard');
|
|
113
|
+
const APPLE_SCRIPT_KEY_CODES = {
|
|
114
|
+
return: 36,
|
|
115
|
+
enter: 36,
|
|
116
|
+
tab: 48,
|
|
117
|
+
space: 49,
|
|
118
|
+
backspace: 51,
|
|
119
|
+
delete: 51,
|
|
120
|
+
escape: 53,
|
|
121
|
+
forwarddelete: 117,
|
|
122
|
+
left: 123,
|
|
123
|
+
right: 124,
|
|
124
|
+
down: 125,
|
|
125
|
+
up: 126,
|
|
126
|
+
home: 115,
|
|
127
|
+
end: 119,
|
|
128
|
+
pageup: 116,
|
|
129
|
+
pagedown: 121,
|
|
130
|
+
f1: 122,
|
|
131
|
+
f2: 120,
|
|
132
|
+
f3: 99,
|
|
133
|
+
f4: 118,
|
|
134
|
+
f5: 96,
|
|
135
|
+
f6: 97,
|
|
136
|
+
f7: 98,
|
|
137
|
+
f8: 100,
|
|
138
|
+
f9: 101,
|
|
139
|
+
f10: 109,
|
|
140
|
+
f11: 103,
|
|
141
|
+
f12: 111
|
|
142
|
+
};
|
|
143
|
+
const APPLE_SCRIPT_MODIFIER_KEYS = {
|
|
144
|
+
command: 'command',
|
|
145
|
+
cmd: 'command',
|
|
146
|
+
control: 'control',
|
|
147
|
+
ctrl: 'control',
|
|
148
|
+
shift: 'shift',
|
|
149
|
+
alt: 'option',
|
|
150
|
+
option: 'option',
|
|
151
|
+
meta: 'command'
|
|
152
|
+
};
|
|
153
|
+
function buildKeyCommand(key) {
|
|
154
|
+
const keyCode = APPLE_SCRIPT_KEY_CODES[key.toLowerCase()];
|
|
155
|
+
if (void 0 !== keyCode) return `key code ${keyCode}`;
|
|
156
|
+
const escapedKey = key.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
157
|
+
return `keystroke "${escapedKey}"`;
|
|
158
|
+
}
|
|
159
|
+
function resolveModifierKeys(modifiers) {
|
|
160
|
+
return modifiers.map((modifier)=>APPLE_SCRIPT_MODIFIER_KEYS[modifier.toLowerCase()]).filter((modifier)=>void 0 !== modifier);
|
|
161
|
+
}
|
|
162
|
+
function buildLogicalKeyPress(key, modifiers) {
|
|
163
|
+
const modifierKeys = resolveModifierKeys(modifiers);
|
|
164
|
+
const modifierClause = modifierKeys.length ? ` using {${modifierKeys.map((modifier)=>`${modifier} down`).join(', ')}}` : '';
|
|
165
|
+
return `tell application "System Events" to ${buildKeyCommand(key)}${modifierClause}`;
|
|
166
|
+
}
|
|
167
|
+
function resolvePhysicalKey(key, modifiers) {
|
|
168
|
+
const resolvedModifiers = [
|
|
169
|
+
...modifiers
|
|
170
|
+
];
|
|
171
|
+
const shiftedBaseKey = resolveUSShiftedKey(key);
|
|
172
|
+
if (void 0 !== shiftedBaseKey) {
|
|
173
|
+
resolvedModifiers.push('shift');
|
|
174
|
+
return {
|
|
175
|
+
key: shiftedBaseKey,
|
|
176
|
+
modifiers: resolvedModifiers
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
return {
|
|
180
|
+
key,
|
|
181
|
+
modifiers: resolvedModifiers
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
function buildPhysicalKeyPress(key, modifiers) {
|
|
185
|
+
const resolved = resolvePhysicalKey(key, modifiers);
|
|
186
|
+
const modifierKeys = [
|
|
187
|
+
...new Set(resolveModifierKeys(resolved.modifiers))
|
|
188
|
+
];
|
|
189
|
+
const keyCommand = buildKeyCommand(resolved.key);
|
|
190
|
+
if (0 === modifierKeys.length) return `tell application "System Events" to ${keyCommand}`;
|
|
191
|
+
const releaseCommands = [
|
|
192
|
+
...modifierKeys
|
|
193
|
+
].reverse().map((modifier)=>`key up ${modifier}`);
|
|
194
|
+
return [
|
|
195
|
+
'tell application "System Events"',
|
|
196
|
+
'try',
|
|
197
|
+
...modifierKeys.map((modifier)=>`key down ${modifier}`),
|
|
198
|
+
keyCommand,
|
|
199
|
+
'on error errorMessage number errorNumber',
|
|
200
|
+
...releaseCommands,
|
|
201
|
+
'error errorMessage number errorNumber',
|
|
202
|
+
'end try',
|
|
203
|
+
...releaseCommands,
|
|
204
|
+
'end tell'
|
|
205
|
+
].join('\n');
|
|
206
|
+
}
|
|
207
|
+
function buildAppleScriptKeyPress(key, modifiers = [], eventMode = 'logical') {
|
|
208
|
+
return 'physical' === eventMode ? buildPhysicalKeyPress(key, modifiers) : buildLogicalKeyPress(key, modifiers);
|
|
209
|
+
}
|
|
210
|
+
function sendKeyViaAppleScript(key, modifiers = [], eventMode = 'logical') {
|
|
211
|
+
const script = buildAppleScriptKeyPress(key, modifiers, eventMode);
|
|
212
|
+
debugKeyboard('sendKeyViaAppleScript', {
|
|
213
|
+
key,
|
|
214
|
+
modifiers,
|
|
215
|
+
eventMode,
|
|
216
|
+
script
|
|
217
|
+
});
|
|
218
|
+
execFileSync("osascript", [
|
|
219
|
+
'-e',
|
|
220
|
+
script
|
|
221
|
+
]);
|
|
222
|
+
}
|
|
22
223
|
function _define_property(obj, key, value) {
|
|
23
224
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
24
225
|
value: value,
|
|
@@ -91,6 +292,29 @@ class ComputerInputDriver {
|
|
|
91
292
|
if (void 0 !== modifiers) lib.keyTap(key, modifiers);
|
|
92
293
|
else lib.keyTap(key);
|
|
93
294
|
}
|
|
295
|
+
keyToggle(key, state, modifiers) {
|
|
296
|
+
const lib = this.getLibnutOrThrow('keyToggle');
|
|
297
|
+
if (void 0 !== modifiers) lib.keyToggle(key, state, modifiers);
|
|
298
|
+
else lib.keyToggle(key, state);
|
|
299
|
+
}
|
|
300
|
+
async keyTapWithExplicitModifiers(key, modifiers, delayMs) {
|
|
301
|
+
const uniqueModifiers = [
|
|
302
|
+
...new Set(modifiers)
|
|
303
|
+
];
|
|
304
|
+
if (0 === uniqueModifiers.length) return void this.keyTap(key);
|
|
305
|
+
const pressedModifiers = [];
|
|
306
|
+
try {
|
|
307
|
+
for (const modifier of uniqueModifiers){
|
|
308
|
+
this.keyToggle(modifier, 'down');
|
|
309
|
+
pressedModifiers.push(modifier);
|
|
310
|
+
}
|
|
311
|
+
await this.delay(delayMs);
|
|
312
|
+
this.keyTap(key);
|
|
313
|
+
await this.delay(delayMs);
|
|
314
|
+
} finally{
|
|
315
|
+
for (const modifier of pressedModifiers.reverse())this.releaseKey(modifier);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
94
318
|
typeString(text) {
|
|
95
319
|
this.getLibnutOrThrow('typeString').typeString(text);
|
|
96
320
|
}
|
|
@@ -163,6 +387,15 @@ class ComputerInputDriver {
|
|
|
163
387
|
this.options.debug(`Failed to release mouse button ${button}: ${error}`);
|
|
164
388
|
}
|
|
165
389
|
}
|
|
390
|
+
releaseKey(key) {
|
|
391
|
+
try {
|
|
392
|
+
const libnut = this.options.getLibnut();
|
|
393
|
+
node_assert(libnut, 'libnut not initialized');
|
|
394
|
+
libnut.keyToggle(key, 'up');
|
|
395
|
+
} catch (error) {
|
|
396
|
+
this.options.debug(`Failed to release key ${key}: ${error}`);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
166
399
|
rejectPendingInputDelays() {
|
|
167
400
|
const error = this.createDestroyedError('in-flight input');
|
|
168
401
|
for (const waitRef of this.pendingInputDelayWaits){
|
|
@@ -543,92 +776,6 @@ const LIBNUT_FALLBACK_PIXELS_PER_DETENT = 100;
|
|
|
543
776
|
const LIBNUT_FALLBACK_TICK_DELAY_MS = 30;
|
|
544
777
|
const LIBNUT_FALLBACK_MAX_DETENTS = 200;
|
|
545
778
|
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
779
|
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
780
|
const DEFAULT_SCROLL_VIEWPORT_RATIO = 0.7;
|
|
634
781
|
const EDGE_SCROLL_SPEC = {
|
|
@@ -665,67 +812,6 @@ const EDGE_SCROLL_SPEC = {
|
|
|
665
812
|
]
|
|
666
813
|
}
|
|
667
814
|
};
|
|
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
815
|
function escapePowershellSingleQuoted(value) {
|
|
730
816
|
return value.replace(/'/g, "''");
|
|
731
817
|
}
|
|
@@ -1153,7 +1239,7 @@ Available Displays: ${displays.length > 0 ? displays.map((d)=>d.name).join(', ')
|
|
|
1153
1239
|
}
|
|
1154
1240
|
async healthCheck(displays) {
|
|
1155
1241
|
console.log('[HealthCheck] Starting health check...');
|
|
1156
|
-
console.log("[HealthCheck] @midscene/computer v1.12.
|
|
1242
|
+
console.log("[HealthCheck] @midscene/computer v1.12.6-beta-20260909033030.0");
|
|
1157
1243
|
console.log('[HealthCheck] Taking screenshot...');
|
|
1158
1244
|
const screenshotTimeout = 15000;
|
|
1159
1245
|
let timeoutId;
|
|
@@ -1330,7 +1416,7 @@ $g.Dispose(); $bmp.Dispose(); $ms.Dispose()
|
|
|
1330
1416
|
]);
|
|
1331
1417
|
else {
|
|
1332
1418
|
const modifier = 'darwin' === process.platform ? 'command' : 'control';
|
|
1333
|
-
this.
|
|
1419
|
+
await this.sendLocalModifiedKey('v', [
|
|
1334
1420
|
modifier
|
|
1335
1421
|
]);
|
|
1336
1422
|
}
|
|
@@ -1347,12 +1433,16 @@ $g.Dispose(); $bmp.Dispose(); $ms.Dispose()
|
|
|
1347
1433
|
}
|
|
1348
1434
|
async typeStringWithDelay(text, keyboardTypeDelay) {
|
|
1349
1435
|
await sendTextSequentially(text.replace(/\r\n?/g, '\n'), {
|
|
1350
|
-
sendCharacter: (character)=>{
|
|
1351
|
-
const linuxShiftedKey = 'linux' === process.platform ?
|
|
1436
|
+
sendCharacter: async (character)=>{
|
|
1437
|
+
const linuxShiftedKey = 'linux' === process.platform ? US_SHIFTED_CHARACTER_KEYS.get(character) : void 0;
|
|
1438
|
+
const pacedShiftedKey = !this.useAppleScript && (this.options?.keyboardShortcutDelay ?? 0) > 0 ? resolveUSShiftedKey(character) : void 0;
|
|
1352
1439
|
if ('\n' === character) this.inputDriver.sendKey('return');
|
|
1353
1440
|
else if ('\t' === character) this.inputDriver.sendKey('tab');
|
|
1354
1441
|
else if (' ' === character) this.inputDriver.sendKey('space');
|
|
1355
1442
|
else if (this.useAppleScript) this.inputDriver.sendKeyViaAppleScript(character);
|
|
1443
|
+
else if (void 0 !== pacedShiftedKey) await this.sendLocalModifiedKey(pacedShiftedKey, [
|
|
1444
|
+
'shift'
|
|
1445
|
+
]);
|
|
1356
1446
|
else if (void 0 !== linuxShiftedKey) this.inputDriver.keyTap(linuxShiftedKey, [
|
|
1357
1447
|
'shift'
|
|
1358
1448
|
]);
|
|
@@ -1373,12 +1463,17 @@ $g.Dispose(); $bmp.Dispose(); $ms.Dispose()
|
|
|
1373
1463
|
return;
|
|
1374
1464
|
}
|
|
1375
1465
|
const modifier = 'darwin' === process.platform ? 'command' : 'control';
|
|
1376
|
-
this.
|
|
1466
|
+
await this.sendLocalModifiedKey('a', [
|
|
1377
1467
|
modifier
|
|
1378
1468
|
]);
|
|
1379
1469
|
await this.inputDriver.delay(50);
|
|
1380
1470
|
this.inputDriver.keyTap('backspace');
|
|
1381
1471
|
}
|
|
1472
|
+
async sendLocalModifiedKey(key, modifiers) {
|
|
1473
|
+
const shortcutDelay = this.options?.keyboardShortcutDelay ?? 0;
|
|
1474
|
+
if (modifiers.length > 0 && shortcutDelay > 0) return void await this.inputDriver.keyTapWithExplicitModifiers(key, modifiers, shortcutDelay);
|
|
1475
|
+
this.inputDriver.keyTap(key, modifiers);
|
|
1476
|
+
}
|
|
1382
1477
|
async pressKeyboardShortcut(keyName) {
|
|
1383
1478
|
const keys = keyName.split('+');
|
|
1384
1479
|
const modifiers = keys.slice(0, -1).map(normalizeKeyName);
|
|
@@ -1389,6 +1484,7 @@ $g.Dispose(); $bmp.Dispose(); $ms.Dispose()
|
|
|
1389
1484
|
modifiers,
|
|
1390
1485
|
driver: this.useAppleScript ? "applescript" : 'libnut'
|
|
1391
1486
|
});
|
|
1487
|
+
if (!this.useAppleScript && modifiers.length > 0 && (this.options?.keyboardShortcutDelay ?? 0) > 0) return void await this.sendLocalModifiedKey(key, modifiers);
|
|
1392
1488
|
this.inputDriver.sendKey(key, modifiers);
|
|
1393
1489
|
}
|
|
1394
1490
|
resolveUntargetedScrollPoint(screenSize) {
|
|
@@ -1542,7 +1638,7 @@ $g.Dispose(); $bmp.Dispose(); $ms.Dispose()
|
|
|
1542
1638
|
device_define_property(this, "inputDriver", new ComputerInputDriver({
|
|
1543
1639
|
getLibnut: ()=>device_libnut,
|
|
1544
1640
|
useAppleScript: ()=>this.useAppleScript,
|
|
1545
|
-
sendKeyViaAppleScript,
|
|
1641
|
+
sendKeyViaAppleScript: (key, modifiers)=>sendKeyViaAppleScript(key, modifiers, this.options?.keyboardEventMode ?? 'logical'),
|
|
1546
1642
|
runPhasedScroll,
|
|
1547
1643
|
debug: (message)=>debugDevice(message)
|
|
1548
1644
|
}));
|
|
@@ -1668,6 +1764,7 @@ $g.Dispose(); $bmp.Dispose(); $ms.Dispose()
|
|
|
1668
1764
|
}
|
|
1669
1765
|
}
|
|
1670
1766
|
});
|
|
1767
|
+
if (options?.keyboardShortcutDelay !== void 0 && (!Number.isFinite(options.keyboardShortcutDelay) || options.keyboardShortcutDelay < 0)) throw new Error('keyboardShortcutDelay must be a finite non-negative number');
|
|
1671
1768
|
this.options = options;
|
|
1672
1769
|
this.displayId = options?.displayId;
|
|
1673
1770
|
this.useAppleScript = 'darwin' === process.platform && options?.keyboardDriver !== 'libnut';
|
|
@@ -2413,6 +2510,8 @@ function createLocalComputerDevice(opts) {
|
|
|
2413
2510
|
keyboardTypeDelay: opts?.keyboardTypeDelay,
|
|
2414
2511
|
inputStrategy: opts?.inputStrategy,
|
|
2415
2512
|
keyboardDriver: opts?.keyboardDriver,
|
|
2513
|
+
keyboardEventMode: opts?.keyboardEventMode,
|
|
2514
|
+
keyboardShortcutDelay: opts?.keyboardShortcutDelay,
|
|
2416
2515
|
headless: opts?.headless,
|
|
2417
2516
|
xvfbResolution: opts?.xvfbResolution,
|
|
2418
2517
|
keepXvfbAliveUntilProcessExit: opts?.keepXvfbAliveUntilProcessExit
|
|
@@ -2470,6 +2569,11 @@ const computerInitArgShape = {
|
|
|
2470
2569
|
headless: z.boolean().optional().describe('Start virtual display via Xvfb (Linux local mode only). Ignored when host is set.'),
|
|
2471
2570
|
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
2571
|
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.'),
|
|
2572
|
+
keyboardEventMode: z["enum"]([
|
|
2573
|
+
'logical',
|
|
2574
|
+
'physical'
|
|
2575
|
+
]).optional().describe('macOS AppleScript keyboard event mode for local control. "logical" (default) uses a compact keystroke command; "physical" sends explicit modifier transitions for foreground apps that require separate key state changes. Both modes use AppleScript, and "physical" is not hardware input. It assumes an en-US layout for shifted punctuation and requires sequential text input or a positive keyboardTypeDelay. Ignored in RDP mode and outside the macOS AppleScript driver.'),
|
|
2576
|
+
keyboardShortcutDelay: z.number().finite().nonnegative().optional().describe('Finite non-negative delay in milliseconds around modifier transitions for local libnut keyboard events. Positive values pace shortcuts and the implicit Shift used by uppercase or en-US punctuation during sequential input. Ignored in RDP mode and by the macOS AppleScript driver.'),
|
|
2473
2577
|
host: z.string().optional().describe('RDP host (FQDN or IP). Set this to switch into RDP mode.'),
|
|
2474
2578
|
port: z.number().optional().describe('RDP port (default 3389). Requires host.'),
|
|
2475
2579
|
username: z.string().optional().describe('RDP username. Requires host.'),
|
|
@@ -2486,7 +2590,7 @@ const computerInitArgShape = {
|
|
|
2486
2590
|
function adaptComputerInitArgs(extracted) {
|
|
2487
2591
|
if (!extracted || 0 === Object.keys(extracted).length) return;
|
|
2488
2592
|
if (extracted.host) {
|
|
2489
|
-
const { displayId: _d, headless: _h, ...rdpFields } = extracted;
|
|
2593
|
+
const { displayId: _d, headless: _h, keyboardEventMode: _k, keyboardShortcutDelay: _s, ...rdpFields } = extracted;
|
|
2490
2594
|
const host = normalizeRdpHost(extracted.host);
|
|
2491
2595
|
return {
|
|
2492
2596
|
mode: 'rdp',
|
|
@@ -2500,6 +2604,8 @@ function adaptComputerInitArgs(extracted) {
|
|
|
2500
2604
|
headless: extracted.headless,
|
|
2501
2605
|
keyboardTypeDelay: extracted.keyboardTypeDelay,
|
|
2502
2606
|
inputStrategy: extracted.inputStrategy,
|
|
2607
|
+
keyboardEventMode: extracted.keyboardEventMode,
|
|
2608
|
+
keyboardShortcutDelay: extracted.keyboardShortcutDelay,
|
|
2503
2609
|
...extractAgentBehaviorInitArgs(extracted) ?? {}
|
|
2504
2610
|
};
|
|
2505
2611
|
}
|
|
@@ -2551,6 +2657,8 @@ class ComputerMidsceneTools extends BaseMidsceneTools {
|
|
|
2551
2657
|
const headless = opts?.mode === 'local' ? opts.headless : void 0;
|
|
2552
2658
|
const keyboardTypeDelay = opts?.keyboardTypeDelay;
|
|
2553
2659
|
const inputStrategy = opts?.inputStrategy;
|
|
2660
|
+
const keyboardEventMode = opts?.mode === 'local' ? opts.keyboardEventMode : void 0;
|
|
2661
|
+
const keyboardShortcutDelay = opts?.mode === 'local' ? opts.keyboardShortcutDelay : void 0;
|
|
2554
2662
|
agent_tools_debug('Creating Computer agent with displayId:', displayId || 'primary');
|
|
2555
2663
|
const agentOpts = {
|
|
2556
2664
|
...displayId ? {
|
|
@@ -2565,6 +2673,12 @@ class ComputerMidsceneTools extends BaseMidsceneTools {
|
|
|
2565
2673
|
...void 0 !== inputStrategy ? {
|
|
2566
2674
|
inputStrategy
|
|
2567
2675
|
} : {},
|
|
2676
|
+
...void 0 !== keyboardEventMode ? {
|
|
2677
|
+
keyboardEventMode
|
|
2678
|
+
} : {},
|
|
2679
|
+
...void 0 !== keyboardShortcutDelay ? {
|
|
2680
|
+
keyboardShortcutDelay
|
|
2681
|
+
} : {},
|
|
2568
2682
|
...this.options.keepXvfbAliveUntilProcessExit ? {
|
|
2569
2683
|
keepXvfbAliveUntilProcessExit: true
|
|
2570
2684
|
} : {},
|
|
@@ -2645,7 +2759,7 @@ class ComputerMidsceneTools extends BaseMidsceneTools {
|
|
|
2645
2759
|
}
|
|
2646
2760
|
}
|
|
2647
2761
|
function version() {
|
|
2648
|
-
const currentVersion = "1.12.
|
|
2762
|
+
const currentVersion = "1.12.6-beta-20260909033030.0";
|
|
2649
2763
|
console.log(`@midscene/computer v${currentVersion}`);
|
|
2650
2764
|
return currentVersion;
|
|
2651
2765
|
}
|