@rebind.gg/mcp-server 0.1.3 → 0.1.5
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 +10 -3
- package/package.json +1 -1
- package/src/coords.ts +7 -0
- package/src/index.ts +92 -25
- package/src/rebind.d.luau +698 -0
package/README.md
CHANGED
|
@@ -60,9 +60,16 @@ Off unless set.
|
|
|
60
60
|
cursor and sending relative HID deltas (which map 1:1 to pixels), correcting
|
|
61
61
|
against the true cursor until it lands. This sidesteps the relay's own absolute
|
|
62
62
|
move, whose delta is computed from a cached cursor position that goes stale and
|
|
63
|
-
flings the pointer to a screen edge. A mouse scale probe
|
|
64
|
-
if pointer ballistics are detected (enhance pointer precision,
|
|
65
|
-
probe reports it, since acceleration would break the 1:1
|
|
63
|
+
flings the pointer to a screen edge. A mouse scale probe runs on the first
|
|
64
|
+
click/move_mouse; if pointer ballistics are detected (enhance pointer precision,
|
|
65
|
+
DPI mismatch) the probe reports it, since acceleration would break the 1:1
|
|
66
|
+
assumption.
|
|
67
|
+
|
|
68
|
+
Tool calls are serialized through a single queue: there is one physical cursor
|
|
69
|
+
and keyboard, so parallel tool calls from the model (e.g. two `move_mouse` in
|
|
70
|
+
one turn) run one after another instead of interleaving HID input. All results
|
|
71
|
+
are reported in the coordinate space of the last screenshot, the same space the
|
|
72
|
+
model emits.
|
|
66
73
|
|
|
67
74
|
## Develop
|
|
68
75
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rebind.gg/mcp-server",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "MCP server exposing Rebind as computer-use tools: screenshot, verified click, type, key, scroll, and window control over the Remote Access protocol.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
package/src/coords.ts
CHANGED
|
@@ -28,6 +28,13 @@ export function mapToScreen(shot: ShotMapping, ix: number, iy: number): Point {
|
|
|
28
28
|
};
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
export function mapToImage(shot: ShotMapping, sx: number, sy: number): Point {
|
|
32
|
+
return {
|
|
33
|
+
x: Math.round((sx - shot.originX) * shot.scale),
|
|
34
|
+
y: Math.round((sy - shot.originY) * shot.scale),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
31
38
|
export function inImageBounds(
|
|
32
39
|
shot: ShotMapping,
|
|
33
40
|
ix: number,
|
package/src/index.ts
CHANGED
|
@@ -12,8 +12,9 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
|
12
12
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
13
13
|
import { RebindRemote } from "@rebind.gg/client-ts";
|
|
14
14
|
import { z } from "zod";
|
|
15
|
+
import { mapToImage } from "./coords.ts";
|
|
15
16
|
import { renderScreenshot } from "./image.ts";
|
|
16
|
-
import { Session } from "./session.ts";
|
|
17
|
+
import { CLICK_EPS_PX, Session } from "./session.ts";
|
|
17
18
|
|
|
18
19
|
const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));
|
|
19
20
|
|
|
@@ -52,7 +53,7 @@ async function main() {
|
|
|
52
53
|
|
|
53
54
|
const session = new Session(client);
|
|
54
55
|
|
|
55
|
-
const server = new McpServer({ name: "rebind", version: "0.1.
|
|
56
|
+
const server = new McpServer({ name: "rebind", version: "0.1.5" });
|
|
56
57
|
|
|
57
58
|
// REBIND_AGENT_LOG=<path>: opt-in telemetry — one JSONL line per tool call
|
|
58
59
|
// ({ts, tool, ok, latency_ms, note}). No screenshot bytes, no user content.
|
|
@@ -69,17 +70,28 @@ async function main() {
|
|
|
69
70
|
// telemetry must never break a tool call
|
|
70
71
|
}
|
|
71
72
|
};
|
|
73
|
+
// one physical cursor and keyboard: tool calls must never overlap. Models
|
|
74
|
+
// routinely emit parallel calls in a single turn (two move_mouse at once)
|
|
75
|
+
// and the MCP SDK runs handlers concurrently; interleaved HID deltas and
|
|
76
|
+
// cursor readbacks make every overlapping move land nowhere. Chain all
|
|
77
|
+
// handlers through a single queue.
|
|
78
|
+
let chain: Promise<unknown> = Promise.resolve();
|
|
72
79
|
const register = (name: string, config: object, handler: (args: any) => Promise<any>) => {
|
|
73
|
-
server.registerTool(name, config as any,
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
80
|
+
server.registerTool(name, config as any, (args: any) => {
|
|
81
|
+
const run = async () => {
|
|
82
|
+
const t0 = performance.now();
|
|
83
|
+
try {
|
|
84
|
+
const result = await handler(args);
|
|
85
|
+
logCall(name, true, t0);
|
|
86
|
+
return result;
|
|
87
|
+
} catch (e) {
|
|
88
|
+
logCall(name, false, t0, String(e));
|
|
89
|
+
throw e;
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
const p = chain.then(run, run);
|
|
93
|
+
chain = p.catch(() => {});
|
|
94
|
+
return p;
|
|
83
95
|
});
|
|
84
96
|
};
|
|
85
97
|
|
|
@@ -89,7 +101,8 @@ async function main() {
|
|
|
89
101
|
description:
|
|
90
102
|
"Capture a display and return it as an image. The cursor is marked with a red crosshair. " +
|
|
91
103
|
"All click/move coordinates you emit must be pixel coordinates in the MOST RECENT screenshot. " +
|
|
92
|
-
"After every action, take a new screenshot and verify the action had the intended effect before continuing; if not, correct and retry."
|
|
104
|
+
"After every action, take a new screenshot and verify the action had the intended effect before continuing; if not, correct and retry. " +
|
|
105
|
+
"Identify UI elements (labels, inputs, search boxes) before acting; prefer type/key over blind clicking.",
|
|
93
106
|
inputSchema: {
|
|
94
107
|
display: z
|
|
95
108
|
.number()
|
|
@@ -212,7 +225,8 @@ async function main() {
|
|
|
212
225
|
{
|
|
213
226
|
description:
|
|
214
227
|
"Capture a region of the last screenshot at full native resolution, for reading small text or inspecting small targets. " +
|
|
215
|
-
"READ-ONLY: click coordinates still refer to the last full screenshot, not the zoomed image."
|
|
228
|
+
"READ-ONLY: click coordinates still refer to the last full screenshot, not the zoomed image. " +
|
|
229
|
+
"Useful to check cursor-target alignment when a click missed.",
|
|
216
230
|
inputSchema: {
|
|
217
231
|
x: z
|
|
218
232
|
.number()
|
|
@@ -276,7 +290,8 @@ async function main() {
|
|
|
276
290
|
{
|
|
277
291
|
description:
|
|
278
292
|
"Move the mouse to a point in the last screenshot and click. The landing position is verified and corrected before pressing. " +
|
|
279
|
-
"Prefer keyboard shortcuts (the key tool) for fiddly widgets like address bars and dropdowns."
|
|
293
|
+
"Prefer keyboard shortcuts (the key tool) for fiddly widgets like address bars and dropdowns. " +
|
|
294
|
+
"Identify the target (read its label/text) before clicking, and confirm the effect with a screenshot after.",
|
|
280
295
|
inputSchema: {
|
|
281
296
|
x: z.number().describe("x in last-screenshot image pixels"),
|
|
282
297
|
y: z.number().describe("y in last-screenshot image pixels"),
|
|
@@ -287,10 +302,13 @@ async function main() {
|
|
|
287
302
|
async ({ x, y, button, double }) => {
|
|
288
303
|
const target = session.mapImagePoint(x, y);
|
|
289
304
|
const r = await session.verifiedClick(target.x, target.y, button, double);
|
|
305
|
+
// report in the same image space the model emits — mixing in raw screen
|
|
306
|
+
// coordinates sends smaller models into ad-hoc rescaling math
|
|
307
|
+
const at = mapToImage(session.lastShot!, r.landed.x, r.landed.y);
|
|
290
308
|
return text(
|
|
291
309
|
r.ok
|
|
292
|
-
? `clicked ${button}${double ? " (double)" : ""} at
|
|
293
|
-
: `WARNING: cursor landed at (${
|
|
310
|
+
? `clicked ${button}${double ? " (double)" : ""} at image (${at.x}, ${at.y})${r.corrected ? " after one correction" : ""}`
|
|
311
|
+
: `WARNING: cursor landed at image (${at.x}, ${at.y}) instead of (${x}, ${y}) — the click may have missed. Take a screenshot to verify.`,
|
|
294
312
|
);
|
|
295
313
|
},
|
|
296
314
|
);
|
|
@@ -299,7 +317,8 @@ async function main() {
|
|
|
299
317
|
"move_mouse",
|
|
300
318
|
{
|
|
301
319
|
description:
|
|
302
|
-
"Move the mouse to a point in the last screenshot without clicking."
|
|
320
|
+
"Move the mouse to a point in the last screenshot without clicking. " +
|
|
321
|
+
"If the response warns the cursor stopped short, take a fresh screenshot and retry.",
|
|
303
322
|
inputSchema: {
|
|
304
323
|
x: z.number().describe("x in last-screenshot image pixels"),
|
|
305
324
|
y: z.number().describe("y in last-screenshot image pixels"),
|
|
@@ -308,14 +327,23 @@ async function main() {
|
|
|
308
327
|
async ({ x, y }) => {
|
|
309
328
|
const target = session.mapImagePoint(x, y);
|
|
310
329
|
const landed = await session.moveTo(target.x, target.y);
|
|
311
|
-
|
|
330
|
+
const at = mapToImage(session.lastShot!, landed.x, landed.y);
|
|
331
|
+
const missed =
|
|
332
|
+
Math.hypot(landed.x - target.x, landed.y - target.y) > CLICK_EPS_PX;
|
|
333
|
+
return text(
|
|
334
|
+
missed
|
|
335
|
+
? `WARNING: cursor stopped at image (${at.x}, ${at.y}) instead of (${x}, ${y}) — take a fresh screenshot and retry`
|
|
336
|
+
: `cursor at image (${at.x}, ${at.y})`,
|
|
337
|
+
);
|
|
312
338
|
},
|
|
313
339
|
);
|
|
314
340
|
|
|
315
341
|
register(
|
|
316
342
|
"type",
|
|
317
343
|
{
|
|
318
|
-
description:
|
|
344
|
+
description:
|
|
345
|
+
"Type text into the focused element via the keyboard. " +
|
|
346
|
+
"Use LCtrl+A / LMeta+A (key tool) to select all first when replacing existing text.",
|
|
319
347
|
inputSchema: { text: z.string() },
|
|
320
348
|
},
|
|
321
349
|
async ({ text: t }) => {
|
|
@@ -331,7 +359,8 @@ async function main() {
|
|
|
331
359
|
{
|
|
332
360
|
description:
|
|
333
361
|
'Press a key or combo. Names: "Enter", "Escape", "Tab", "Backspace", arrows ("Up", "Down", "Left", "Right"), letters/digits, modifiers "LCtrl", "LAlt", "LShift", "LMeta". ' +
|
|
334
|
-
'Combos join with "+", e.g. "LCtrl+L" (focus address bar), "LCtrl+C", "LAlt+Tab".'
|
|
362
|
+
'Combos join with "+", e.g. "LCtrl+L" (focus address bar), "LCtrl+C", "LAlt+Tab". ' +
|
|
363
|
+
'Useful shortcuts: Space/PageDown/PageUp to scroll, LCtrl+F or LMeta+F to find text on the page, Escape to close dialogs.',
|
|
335
364
|
inputSchema: { combo: z.string() },
|
|
336
365
|
},
|
|
337
366
|
async ({ combo }) => {
|
|
@@ -345,7 +374,8 @@ async function main() {
|
|
|
345
374
|
"scroll",
|
|
346
375
|
{
|
|
347
376
|
description:
|
|
348
|
-
"Scroll the mouse wheel at the current cursor position. Positive = up, negative = down."
|
|
377
|
+
"Scroll the mouse wheel at the current cursor position. Positive = up, negative = down. " +
|
|
378
|
+
"Key shortcuts (Space, PageDown/PageUp, arrows) are often more reliable for page-level scrolling.",
|
|
349
379
|
inputSchema: { clicks: z.number().int().describe("wheel clicks") },
|
|
350
380
|
},
|
|
351
381
|
async ({ clicks }) => {
|
|
@@ -375,8 +405,31 @@ async function main() {
|
|
|
375
405
|
inputSchema: { handle: z.number() },
|
|
376
406
|
},
|
|
377
407
|
async ({ handle }) => {
|
|
378
|
-
|
|
379
|
-
|
|
408
|
+
// handle-based activation can raise without focusing on macOS; fall back
|
|
409
|
+
// to app-name activation (App.Activate, macOS-only, no-op elsewhere via
|
|
410
|
+
// pcall). Decided relay-side: this process may run on a different
|
|
411
|
+
// machine than the relay, so process.platform is the wrong signal.
|
|
412
|
+
const r = (await client.luaExec(`
|
|
413
|
+
local h = ${handle}
|
|
414
|
+
Window.Activate(h)
|
|
415
|
+
Sleep(150)
|
|
416
|
+
if Window.IsActive(h) then return { ok = true } end
|
|
417
|
+
local name
|
|
418
|
+
for _, w in ipairs(Window.List()) do
|
|
419
|
+
if w.handle == h then name = w.process; break end
|
|
420
|
+
end
|
|
421
|
+
if not name then return { ok = false, err = "window handle not found" } end
|
|
422
|
+
pcall(function() App.Activate(name) end)
|
|
423
|
+
Sleep(150)
|
|
424
|
+
return { ok = Window.IsActive(h), name = name }
|
|
425
|
+
`)) as { ok?: boolean; name?: string; err?: string };
|
|
426
|
+
if (r.ok)
|
|
427
|
+
return text(
|
|
428
|
+
`activated window ${handle}${r.name ? ` via app "${r.name}"` : ""}`,
|
|
429
|
+
);
|
|
430
|
+
return text(
|
|
431
|
+
`WARNING: window ${handle} ${r.err ?? "may not be focused"} — verify with active_window or a screenshot`,
|
|
432
|
+
);
|
|
380
433
|
},
|
|
381
434
|
);
|
|
382
435
|
|
|
@@ -423,7 +476,8 @@ async function main() {
|
|
|
423
476
|
"reliable, and it sidesteps multi-monitor guessing. Use it to: launch apps (`System.ExecDetached(\"cmd\", {\"/c\",\"start\",\"\",url})`), " +
|
|
424
477
|
"wait for and place windows on a known display (`local h=Window.Wait(title, ms); Window.Move(h, x, y, w, h)`), " +
|
|
425
478
|
"run shell commands (`System.Exec(cmd) -> {exit,stdout,stderr}`), find UI by color (`Screen.SearchForColor(region,hex)`), " +
|
|
426
|
-
"type, click, read pixels, manage processes. Namespaces: System, HID, Input, Screen, Window, Process, File, Clipboard, Net, Macro, Env, Log. " +
|
|
479
|
+
"type, click, read pixels, manage processes. Namespaces: System, HID, Input, Screen, Window, App, Process, File, Clipboard, Net, Macro, Env, Log; global Sleep(ms). " +
|
|
480
|
+
"Call `lua_docs` for exact signatures BEFORE writing nontrivial scripts — do not guess APIs. " +
|
|
427
481
|
"Fall back to `screenshot` only for genuinely visual reasoning the script cannot resolve. End the script with `return <value>` to get data back.",
|
|
428
482
|
inputSchema: {
|
|
429
483
|
source: z
|
|
@@ -439,6 +493,19 @@ async function main() {
|
|
|
439
493
|
},
|
|
440
494
|
);
|
|
441
495
|
|
|
496
|
+
register(
|
|
497
|
+
"lua_docs",
|
|
498
|
+
{
|
|
499
|
+
description:
|
|
500
|
+
"Return the full Luau SDK type definitions for run_lua: every namespace, function signature, and type. " +
|
|
501
|
+
"Read this before writing any nontrivial run_lua script instead of guessing APIs.",
|
|
502
|
+
},
|
|
503
|
+
// byte-identical copy of packages/lua-sdk/types/rebind.d.luau, shipped in
|
|
504
|
+
// the package; tests/lua-docs-sync.test.ts guards against drift
|
|
505
|
+
async () =>
|
|
506
|
+
text(await Bun.file(new URL("./rebind.d.luau", import.meta.url)).text()),
|
|
507
|
+
);
|
|
508
|
+
|
|
442
509
|
await server.connect(new StdioServerTransport());
|
|
443
510
|
// stdout carries the MCP protocol — log to stderr only
|
|
444
511
|
console.error(
|
|
@@ -0,0 +1,698 @@
|
|
|
1
|
+
-- rebind sdk type definitions for luau language server
|
|
2
|
+
-- provides autocomplete, hover docs, and type checking for all sdk namespaces.
|
|
3
|
+
-- reference this file in your .luaurc: { "languageMode": "strict", "paths": ["types"] }
|
|
4
|
+
|
|
5
|
+
-- handle types
|
|
6
|
+
|
|
7
|
+
export type TaskHandle = {
|
|
8
|
+
Cancel: (self: TaskHandle) -> (),
|
|
9
|
+
IsRunning: (self: TaskHandle) -> boolean,
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export type TimerHandle = {
|
|
13
|
+
Cancel: (self: TimerHandle) -> (),
|
|
14
|
+
Pause: (self: TimerHandle) -> (),
|
|
15
|
+
Resume: (self: TimerHandle) -> (),
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export type MacroHandle = {
|
|
19
|
+
Stop: (self: MacroHandle) -> (),
|
|
20
|
+
Pause: (self: MacroHandle) -> (),
|
|
21
|
+
Resume: (self: MacroHandle) -> (),
|
|
22
|
+
IsPlaying: (self: MacroHandle) -> boolean,
|
|
23
|
+
GetProgress: (self: MacroHandle) -> number,
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export type BindHandle = {
|
|
27
|
+
unbind: (self: BindHandle) -> (),
|
|
28
|
+
disable: (self: BindHandle) -> (),
|
|
29
|
+
enable: (self: BindHandle) -> (),
|
|
30
|
+
enabled: boolean,
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export type ServerHandle = {
|
|
34
|
+
port: number,
|
|
35
|
+
Stop: (self: ServerHandle) -> (),
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
-- WebSocket: server-side per-connection handle passed to OnConnect/OnMessage/OnClose.
|
|
39
|
+
-- `id` is a monotonic identifier unique to this connection.
|
|
40
|
+
export type WsClient = {
|
|
41
|
+
id: number,
|
|
42
|
+
Send: (self: WsClient, text: string) -> (),
|
|
43
|
+
SendBinary: (self: WsClient, bytes: string) -> (),
|
|
44
|
+
Close: (self: WsClient) -> (),
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
-- WebSocket: server handle returned by Net.WSListen.
|
|
48
|
+
export type WsServerHandle = {
|
|
49
|
+
port: number,
|
|
50
|
+
Broadcast: (self: WsServerHandle, text: string) -> (),
|
|
51
|
+
BroadcastBinary: (self: WsServerHandle, bytes: string) -> (),
|
|
52
|
+
ClientCount: (self: WsServerHandle) -> number,
|
|
53
|
+
Stop: (self: WsServerHandle) -> (),
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
-- WebSocket: outbound-connection handle returned by Net.WSConnect.
|
|
57
|
+
export type WsConnectHandle = {
|
|
58
|
+
Send: (self: WsConnectHandle, text: string) -> (),
|
|
59
|
+
SendBinary: (self: WsConnectHandle, bytes: string) -> (),
|
|
60
|
+
Close: (self: WsConnectHandle) -> (),
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
-- WebSocket: server event-handler table passed to Net.WSListen.
|
|
64
|
+
-- All fields are optional; handlers that are absent are never called.
|
|
65
|
+
export type WsListenHandlers = {
|
|
66
|
+
OnConnect: ((client: WsClient) -> ())?,
|
|
67
|
+
OnMessage: ((client: WsClient, payload: string, isBinary: boolean) -> ())?,
|
|
68
|
+
OnClose: ((client: WsClient) -> ())?,
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
-- WebSocket: client event-handler table passed to Net.WSConnect.
|
|
72
|
+
export type WsConnectHandlers = {
|
|
73
|
+
OnOpen: (() -> ())?,
|
|
74
|
+
OnMessage: ((payload: string, isBinary: boolean) -> ())?,
|
|
75
|
+
OnClose: (() -> ())?,
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export type PipeHandle = {
|
|
79
|
+
name: string,
|
|
80
|
+
size: number,
|
|
81
|
+
capacity: number,
|
|
82
|
+
Read: (self: PipeHandle) -> string?,
|
|
83
|
+
Write: (self: PipeHandle, data: string) -> (),
|
|
84
|
+
Close: (self: PipeHandle) -> (),
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
-- data types
|
|
88
|
+
|
|
89
|
+
export type WindowInfo = {
|
|
90
|
+
title: string,
|
|
91
|
+
process: string,
|
|
92
|
+
x: number,
|
|
93
|
+
y: number,
|
|
94
|
+
width: number,
|
|
95
|
+
height: number,
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export type WindowEntry = {
|
|
99
|
+
handle: number,
|
|
100
|
+
title: string,
|
|
101
|
+
process: string,
|
|
102
|
+
x: number,
|
|
103
|
+
y: number,
|
|
104
|
+
width: number,
|
|
105
|
+
height: number,
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export type WindowPos = {
|
|
109
|
+
x: number,
|
|
110
|
+
y: number,
|
|
111
|
+
width: number,
|
|
112
|
+
height: number,
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export type MousePos = {
|
|
116
|
+
x: number,
|
|
117
|
+
y: number,
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export type ModifierState = {
|
|
121
|
+
ctrl: boolean,
|
|
122
|
+
shift: boolean,
|
|
123
|
+
alt: boolean,
|
|
124
|
+
win: boolean,
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export type HttpResponse = {
|
|
128
|
+
status: number,
|
|
129
|
+
body: string,
|
|
130
|
+
headers: { [string]: string },
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
-- `body` may contain arbitrary bytes (Luau strings are byte strings).
|
|
134
|
+
export type HttpRequest = {
|
|
135
|
+
method: string,
|
|
136
|
+
path: string,
|
|
137
|
+
body: string,
|
|
138
|
+
headers: { [string]: string },
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
-- `body` may contain arbitrary bytes; set a Content-Type header for binary.
|
|
142
|
+
export type HttpResponseSpec = {
|
|
143
|
+
status: number?,
|
|
144
|
+
body: string?,
|
|
145
|
+
headers: { [string]: string }?,
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export type HttpOptions = {
|
|
149
|
+
timeout: number?,
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export type HttpRequestOptions = {
|
|
153
|
+
method: string,
|
|
154
|
+
url: string,
|
|
155
|
+
body: string?,
|
|
156
|
+
headers: { [string]: string }?,
|
|
157
|
+
timeout: number?,
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
-- macro action types
|
|
161
|
+
|
|
162
|
+
export type MacroMoveAction = {
|
|
163
|
+
x: number,
|
|
164
|
+
y: number,
|
|
165
|
+
delay: number,
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export type MacroExplicitAction = {
|
|
169
|
+
action: string,
|
|
170
|
+
code: string?,
|
|
171
|
+
dx: number?,
|
|
172
|
+
dy: number?,
|
|
173
|
+
x: number?,
|
|
174
|
+
y: number?,
|
|
175
|
+
text: string?,
|
|
176
|
+
amount: number?,
|
|
177
|
+
holdMs: number?,
|
|
178
|
+
charDelay: number?,
|
|
179
|
+
delay: number,
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export type MacroAction = MacroMoveAction | MacroExplicitAction
|
|
183
|
+
|
|
184
|
+
-- ui widget option types
|
|
185
|
+
|
|
186
|
+
export type ToggleOpts = {
|
|
187
|
+
label: string?,
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export type SliderOpts = {
|
|
191
|
+
label: string?,
|
|
192
|
+
min: number?,
|
|
193
|
+
max: number?,
|
|
194
|
+
step: number?,
|
|
195
|
+
suffix: string?,
|
|
196
|
+
tooltip: string?,
|
|
197
|
+
group: string?,
|
|
198
|
+
tab: string?,
|
|
199
|
+
showIf: string?,
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export type KeybindOpts = {
|
|
203
|
+
label: string?,
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export type SelectOpts = {
|
|
207
|
+
label: string?,
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export type TextOpts = {
|
|
211
|
+
label: string?,
|
|
212
|
+
placeholder: string?,
|
|
213
|
+
maxLength: number?,
|
|
214
|
+
tooltip: string?,
|
|
215
|
+
group: string?,
|
|
216
|
+
tab: string?,
|
|
217
|
+
showIf: string?,
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export type ColorOpts = {
|
|
221
|
+
label: string?,
|
|
222
|
+
tooltip: string?,
|
|
223
|
+
group: string?,
|
|
224
|
+
tab: string?,
|
|
225
|
+
showIf: string?,
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
export type RecordOpts = {
|
|
229
|
+
ignore_mouse: boolean?,
|
|
230
|
+
ignore_keyboard: boolean?,
|
|
231
|
+
precision: string?,
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
-- ui proxy: returned by UI.Schema, supports dynamic field access
|
|
235
|
+
-- cfg.key reads the current value, cfg.key = value writes it
|
|
236
|
+
export type UiProxy = { [string]: any }
|
|
237
|
+
|
|
238
|
+
-- bind config for table-style binding
|
|
239
|
+
export type BindConfig = {
|
|
240
|
+
when: (() -> boolean)?,
|
|
241
|
+
action: (() -> boolean?)?,
|
|
242
|
+
release: (() -> ())?,
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
-- runtime identity table
|
|
246
|
+
export type RebindInfo = {
|
|
247
|
+
min_sdk: string,
|
|
248
|
+
tick_rate: number,
|
|
249
|
+
version: string,
|
|
250
|
+
name: string,
|
|
251
|
+
runtime_uuid: string,
|
|
252
|
+
id: string?,
|
|
253
|
+
instance: string,
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
-- global functions
|
|
257
|
+
|
|
258
|
+
declare function Run(fn: () -> ()): TaskHandle
|
|
259
|
+
-- RunAsync was removed. Use Run() directly.
|
|
260
|
+
declare function Sleep(ms: number): ()
|
|
261
|
+
declare function After(ms: number, fn: () -> ()): TaskHandle
|
|
262
|
+
declare function Async(fn: (...any) -> ...any): (...any) -> ...any
|
|
263
|
+
declare function print(...: any): ()
|
|
264
|
+
declare function require(module: string): any
|
|
265
|
+
|
|
266
|
+
-- global tables
|
|
267
|
+
|
|
268
|
+
declare _REBIND: RebindInfo
|
|
269
|
+
|
|
270
|
+
-- system namespace
|
|
271
|
+
|
|
272
|
+
export type ExecOptions = {
|
|
273
|
+
timeout: number?,
|
|
274
|
+
cwd: string?,
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
export type ExecResult = {
|
|
278
|
+
exit: number,
|
|
279
|
+
stdout: string,
|
|
280
|
+
stderr: string,
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
export type ExecDetachedOptions = {
|
|
284
|
+
cwd: string?,
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
declare System: {
|
|
288
|
+
Time: () -> number,
|
|
289
|
+
Mouse: () -> (number, number),
|
|
290
|
+
Screen: () -> (number, number),
|
|
291
|
+
Window: () -> WindowInfo,
|
|
292
|
+
Exec: (cmd: string, options: ExecOptions?) -> ExecResult,
|
|
293
|
+
ExecDetached: (cmd: string, args: { string }?, options: ExecDetachedOptions?) -> number,
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
-- hid namespace
|
|
297
|
+
|
|
298
|
+
declare HID: {
|
|
299
|
+
Down: (code: string) -> (),
|
|
300
|
+
Up: (code: string) -> (),
|
|
301
|
+
Press: (code: string, holdMs: number?) -> (),
|
|
302
|
+
-- fire a chord in one synchronous call (press L→R, release R→L). no sleep,
|
|
303
|
+
-- so callable directly from a Bind action / OnDown. modifier tokens accept
|
|
304
|
+
-- macOS aliases: "cmd", "opt"/"option", plus "ctrl"/"shift"/"alt"/"win".
|
|
305
|
+
Combo: (code: string) -> (),
|
|
306
|
+
-- instant whole-string insertion (native; no coroutine). For a human-like
|
|
307
|
+
-- per-character typewriter effect use Typewriter (coroutine-only).
|
|
308
|
+
Type: (text: string) -> (),
|
|
309
|
+
Typewriter: (text: string, delayMs: number?) -> (),
|
|
310
|
+
Move: (dx: number, dy: number) -> (),
|
|
311
|
+
MoveTo: (x: number, y: number) -> (),
|
|
312
|
+
Scroll: (amount: number) -> (),
|
|
313
|
+
SetMouseMode: (mode: string) -> (),
|
|
314
|
+
GetMouseMode: () -> string,
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
-- input namespace
|
|
318
|
+
|
|
319
|
+
declare Input: {
|
|
320
|
+
IsDown: (code: string) -> boolean,
|
|
321
|
+
GetDuration: (code: string) -> number,
|
|
322
|
+
GetActiveKeys: () -> { string },
|
|
323
|
+
GetMousePos: () -> MousePos,
|
|
324
|
+
GetModifiers: () -> ModifierState,
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
-- ui namespace
|
|
328
|
+
|
|
329
|
+
declare UI: {
|
|
330
|
+
Schema: (descriptors: { [string]: any }) -> UiProxy,
|
|
331
|
+
Toggle: (default: boolean, opts: ToggleOpts?) -> any,
|
|
332
|
+
Slider: (default: number, opts: SliderOpts?) -> any,
|
|
333
|
+
Keybind: (default: string, opts: KeybindOpts?) -> any,
|
|
334
|
+
Select: (default: string, choices: { string }, opts: SelectOpts?) -> any,
|
|
335
|
+
Text: (default: string, opts: TextOpts?) -> any,
|
|
336
|
+
Color: (default: string, opts: ColorOpts?) -> any,
|
|
337
|
+
Get: (id: string) -> any,
|
|
338
|
+
Set: (id: string, value: any) -> (),
|
|
339
|
+
GetAll: () -> { [string]: any },
|
|
340
|
+
GetSchema: () -> { any },
|
|
341
|
+
Notify: (text: string, variant: string?) -> (),
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
-- bind namespace (callable table)
|
|
345
|
+
|
|
346
|
+
declare Bind: typeof(setmetatable({} :: {
|
|
347
|
+
Toggle: (key: string, uiId: string) -> BindHandle,
|
|
348
|
+
Remap: (from: string, to: string) -> BindHandle,
|
|
349
|
+
}, {} :: {
|
|
350
|
+
__call: (self: any, key: string, config: (() -> boolean?) | BindConfig) -> BindHandle,
|
|
351
|
+
}))
|
|
352
|
+
|
|
353
|
+
-- timer namespace
|
|
354
|
+
|
|
355
|
+
declare Timer: {
|
|
356
|
+
After: (ms: number, callback: () -> ()) -> TimerHandle,
|
|
357
|
+
Every: (ms: number, callback: () -> ()) -> TimerHandle,
|
|
358
|
+
CancelAll: () -> (),
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
-- macro namespace
|
|
362
|
+
|
|
363
|
+
declare Macro: {
|
|
364
|
+
Play: (macro: { MacroAction }, speed: number?, mode: string?) -> MacroHandle,
|
|
365
|
+
StopAll: () -> (),
|
|
366
|
+
Record: (options: RecordOpts?) -> (),
|
|
367
|
+
Finish: () -> { MacroAction },
|
|
368
|
+
Stream: (macro: { MacroAction }) -> (),
|
|
369
|
+
Abort: () -> (),
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
-- math namespace
|
|
373
|
+
|
|
374
|
+
declare Math: {
|
|
375
|
+
Random: (min: number, max: number) -> number,
|
|
376
|
+
Gaussian: (mean: number, stdDev: number) -> number,
|
|
377
|
+
Scale: (macro: { MacroAction }, xFactor: number, yFactor: number) -> { MacroAction },
|
|
378
|
+
Spline: (macro: { MacroAction }, tension: number) -> { MacroAction },
|
|
379
|
+
Resample: (macro: { MacroAction }, intervalMs: number) -> { MacroAction },
|
|
380
|
+
TimeComp: (macro: { MacroAction }, targetMs: number) -> { MacroAction },
|
|
381
|
+
Interpolate: (macro: { MacroAction }, intervalMs: number, mode: string?) -> { MacroAction },
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
-- log namespace
|
|
385
|
+
|
|
386
|
+
declare Log: {
|
|
387
|
+
Info: (msg: string) -> (),
|
|
388
|
+
Warn: (msg: string) -> (),
|
|
389
|
+
Error: (msg: string) -> (),
|
|
390
|
+
Debug: (msg: string) -> (),
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
-- json namespace
|
|
394
|
+
|
|
395
|
+
declare JSON: {
|
|
396
|
+
Parse: (s: string) -> any,
|
|
397
|
+
Stringify: (value: any) -> string,
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
-- process namespace
|
|
401
|
+
|
|
402
|
+
export type ProcessEntry = {
|
|
403
|
+
pid: number,
|
|
404
|
+
name: string,
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
declare Process: {
|
|
408
|
+
Exists: (name: string) -> number?,
|
|
409
|
+
List: (name: string?) -> { ProcessEntry },
|
|
410
|
+
Kill: (pid: number) -> boolean,
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
-- screen namespace
|
|
414
|
+
|
|
415
|
+
export type PixelMatch = {
|
|
416
|
+
x: number,
|
|
417
|
+
y: number,
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
export type MonitorEntry = {
|
|
421
|
+
index: number,
|
|
422
|
+
x: number,
|
|
423
|
+
y: number,
|
|
424
|
+
width: number,
|
|
425
|
+
height: number,
|
|
426
|
+
primary: boolean,
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
declare Screen: {
|
|
430
|
+
GetPixelColor: (x: number?, y: number?) -> string,
|
|
431
|
+
SearchForColor: (region: {number}, color: string, tolerance: number?) -> PixelMatch?,
|
|
432
|
+
List: () -> { MonitorEntry },
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
-- window namespace
|
|
436
|
+
|
|
437
|
+
declare Window: {
|
|
438
|
+
Find: (title: string) -> number?,
|
|
439
|
+
List: (title: string?) -> { WindowEntry },
|
|
440
|
+
GetTitle: (handle: number?) -> string,
|
|
441
|
+
GetClass: (handle: number?) -> string,
|
|
442
|
+
GetPos: (handle: number?) -> WindowPos,
|
|
443
|
+
GetPID: (handle: number?) -> number,
|
|
444
|
+
Activate: (handle: number) -> (),
|
|
445
|
+
Move: (handle: number, x: number?, y: number?, width: number?, height: number?) -> (),
|
|
446
|
+
SetAlwaysOnTop: (handle: number, enabled: boolean) -> (),
|
|
447
|
+
SetTransparency: (handle: number, alpha: number) -> (),
|
|
448
|
+
SetTitle: (handle: number, title: string) -> (),
|
|
449
|
+
Minimize: (handle: number?) -> (),
|
|
450
|
+
Maximize: (handle: number?) -> (),
|
|
451
|
+
Restore: (handle: number?) -> (),
|
|
452
|
+
Hide: (handle: number?) -> (),
|
|
453
|
+
Show: (handle: number?) -> (),
|
|
454
|
+
Close: (handle: number?) -> (),
|
|
455
|
+
Kill: (handle: number?) -> (),
|
|
456
|
+
IsVisible: (handle: number) -> boolean,
|
|
457
|
+
IsActive: (handle: number?) -> boolean,
|
|
458
|
+
Wait: (title: string, timeout: number?) -> number?,
|
|
459
|
+
WaitActive: (title: string, timeout: number?) -> boolean,
|
|
460
|
+
WaitClose: (title: string, timeout: number?) -> boolean,
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
-- app namespace: application-level control (Keyboard Maestro's Application
|
|
464
|
+
-- Control). names match case-insensitively by app display name. Front/IsRunning/
|
|
465
|
+
-- Activate are permission-free; Hide/Quit/IsHidden drive an AppleEvent and
|
|
466
|
+
-- prompt for macOS Automation permission on first use.
|
|
467
|
+
|
|
468
|
+
export type AppInfo = {
|
|
469
|
+
name: string,
|
|
470
|
+
pid: number,
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
declare App: {
|
|
474
|
+
Front: () -> AppInfo?,
|
|
475
|
+
IsFront: (name: string) -> boolean,
|
|
476
|
+
IsRunning: (name: string) -> boolean,
|
|
477
|
+
IsHidden: (name: string) -> boolean,
|
|
478
|
+
Activate: (name: string) -> (),
|
|
479
|
+
Hide: (name: string) -> (),
|
|
480
|
+
Quit: (name: string) -> (),
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
-- net namespace
|
|
484
|
+
|
|
485
|
+
declare Net: {
|
|
486
|
+
Get: (url: string, headers: { [string]: string }?, options: HttpOptions?) -> HttpResponse,
|
|
487
|
+
Post: (url: string, body: string, headers: { [string]: string }?, options: HttpOptions?) -> HttpResponse,
|
|
488
|
+
Put: (url: string, body: string, headers: { [string]: string }?, options: HttpOptions?) -> HttpResponse,
|
|
489
|
+
Patch: (url: string, body: string, headers: { [string]: string }?, options: HttpOptions?) -> HttpResponse,
|
|
490
|
+
Delete: (url: string, headers: { [string]: string }?, options: HttpOptions?) -> HttpResponse,
|
|
491
|
+
Head: (url: string, headers: { [string]: string }?, options: HttpOptions?) -> HttpResponse,
|
|
492
|
+
Request: (options: HttpRequestOptions) -> HttpResponse,
|
|
493
|
+
Listen: (port: number, handler: (request: HttpRequest) -> HttpResponseSpec | string) -> ServerHandle,
|
|
494
|
+
WSListen: (port: number, handlers: WsListenHandlers) -> WsServerHandle,
|
|
495
|
+
WSConnect: (url: string, handlers: WsConnectHandlers) -> WsConnectHandle,
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
-- pipe namespace
|
|
499
|
+
|
|
500
|
+
declare Pipe: {
|
|
501
|
+
Open: (name: string, options: { size: number? }?) -> PipeHandle,
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
-- file namespace
|
|
505
|
+
|
|
506
|
+
declare File: {
|
|
507
|
+
Read: (path: string) -> string,
|
|
508
|
+
ReadBytes: (path: string) -> string,
|
|
509
|
+
Write: (path: string, content: string) -> (),
|
|
510
|
+
Append: (path: string, content: string) -> (),
|
|
511
|
+
Exists: (path: string) -> boolean,
|
|
512
|
+
Delete: (path: string) -> boolean,
|
|
513
|
+
List: (path: string?) -> { string },
|
|
514
|
+
MkDir: (path: string) -> boolean,
|
|
515
|
+
RmDir: (path: string) -> (),
|
|
516
|
+
ReadJSON: (path: string) -> any,
|
|
517
|
+
WriteJSON: (path: string, value: any) -> (),
|
|
518
|
+
GetScriptDir: () -> string,
|
|
519
|
+
GetSize: (path: string) -> number,
|
|
520
|
+
GetTime: (path: string) -> number,
|
|
521
|
+
Copy: (src: string, dst: string) -> (),
|
|
522
|
+
Move: (src: string, dst: string) -> (),
|
|
523
|
+
IsDir: (path: string) -> boolean,
|
|
524
|
+
IsFile: (path: string) -> boolean,
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
-- audio namespace
|
|
528
|
+
|
|
529
|
+
export type PlayOptions = {
|
|
530
|
+
volume: number?,
|
|
531
|
+
loop: boolean?,
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
export type SoundHandle = {
|
|
535
|
+
Stop: (self: SoundHandle) -> (),
|
|
536
|
+
Pause: (self: SoundHandle) -> (),
|
|
537
|
+
Resume: (self: SoundHandle) -> (),
|
|
538
|
+
IsPlaying: (self: SoundHandle) -> boolean,
|
|
539
|
+
SetVolume: (self: SoundHandle, vol: number) -> (),
|
|
540
|
+
GetVolume: (self: SoundHandle) -> number,
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
declare Audio: {
|
|
544
|
+
Beep: () -> (),
|
|
545
|
+
Play: (path: string, options: PlayOptions?) -> SoundHandle,
|
|
546
|
+
StopAll: () -> (),
|
|
547
|
+
SetMasterVolume: (vol: number) -> (),
|
|
548
|
+
GetMasterVolume: () -> number,
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
-- dialog namespace
|
|
552
|
+
|
|
553
|
+
export type DialogMessageOptions = {
|
|
554
|
+
title: string?,
|
|
555
|
+
level: string?,
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
export type DialogFileFilter = {
|
|
559
|
+
name: string,
|
|
560
|
+
extensions: { string },
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
export type DialogFileOptions = {
|
|
564
|
+
title: string?,
|
|
565
|
+
location: string?,
|
|
566
|
+
filters: { DialogFileFilter }?,
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
declare Dialog: {
|
|
570
|
+
Message: (text: string, options: DialogMessageOptions?) -> (),
|
|
571
|
+
Confirm: (text: string, options: DialogMessageOptions?) -> boolean,
|
|
572
|
+
OpenFile: (options: DialogFileOptions?) -> string?,
|
|
573
|
+
OpenDir: (options: DialogFileOptions?) -> string?,
|
|
574
|
+
SaveFile: (options: DialogFileOptions?) -> string?,
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
-- clipboard namespace
|
|
578
|
+
|
|
579
|
+
declare Clipboard: {
|
|
580
|
+
Get: () -> string?,
|
|
581
|
+
Set: (text: string) -> (),
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
-- script namespace
|
|
585
|
+
|
|
586
|
+
declare Script: {
|
|
587
|
+
Exit: (reason: string?) -> (),
|
|
588
|
+
Reload: () -> (),
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
-- regex namespace
|
|
592
|
+
|
|
593
|
+
export type RegexMatch = {
|
|
594
|
+
match: string,
|
|
595
|
+
captures: { string },
|
|
596
|
+
start: number,
|
|
597
|
+
finish: number,
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
declare Regex: {
|
|
601
|
+
IsMatch: (text: string, pattern: string) -> boolean,
|
|
602
|
+
Find: (text: string, pattern: string) -> RegexMatch?,
|
|
603
|
+
FindAll: (text: string, pattern: string) -> { RegexMatch },
|
|
604
|
+
Replace: (text: string, pattern: string, replacement: string) -> string,
|
|
605
|
+
ReplaceAll: (text: string, pattern: string, replacement: string) -> string,
|
|
606
|
+
Split: (text: string, pattern: string) -> { string },
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
-- config namespace
|
|
610
|
+
|
|
611
|
+
declare Config: {
|
|
612
|
+
ParseTOML: (text: string) -> { [string]: any },
|
|
613
|
+
ToTOML: (value: { [string]: any }) -> string,
|
|
614
|
+
ReadTOML: (path: string) -> { [string]: any },
|
|
615
|
+
WriteTOML: (path: string, value: { [string]: any }) -> (),
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
-- hash namespace
|
|
619
|
+
|
|
620
|
+
declare Hash: {
|
|
621
|
+
MD5: (data: string) -> string,
|
|
622
|
+
SHA1: (data: string) -> string,
|
|
623
|
+
SHA256: (data: string) -> string,
|
|
624
|
+
SHA512: (data: string) -> string,
|
|
625
|
+
CRC32: (data: string) -> number,
|
|
626
|
+
HMAC: (algo: string, key: string, data: string) -> string,
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
-- codec namespace
|
|
630
|
+
|
|
631
|
+
declare Codec: {
|
|
632
|
+
Base64: (data: string) -> string,
|
|
633
|
+
Base64Decode: (str: string) -> string,
|
|
634
|
+
Hex: (data: string) -> string,
|
|
635
|
+
HexDecode: (str: string) -> string,
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
-- env namespace
|
|
639
|
+
|
|
640
|
+
declare Env: {
|
|
641
|
+
Get: (name: string) -> string?,
|
|
642
|
+
Set: (name: string, value: string) -> (),
|
|
643
|
+
Home: () -> string?,
|
|
644
|
+
Config: () -> string?,
|
|
645
|
+
Data: () -> string?,
|
|
646
|
+
Desktop: () -> string?,
|
|
647
|
+
Documents: () -> string?,
|
|
648
|
+
Downloads: () -> string?,
|
|
649
|
+
AppData: () -> string?,
|
|
650
|
+
Temp: () -> string?,
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
-- registry namespace (windows only)
|
|
654
|
+
|
|
655
|
+
declare Registry: {
|
|
656
|
+
Read: (keyPath: string, valueName: string) -> string | number,
|
|
657
|
+
Write: (keyPath: string, type: string, valueName: string, value: any) -> (),
|
|
658
|
+
DeleteValue: (keyPath: string, valueName: string) -> (),
|
|
659
|
+
DeleteKey: (keyPath: string) -> (),
|
|
660
|
+
CreateKey: (keyPath: string) -> (),
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
-- valid key names for input hooks (OnDown, OnUp):
|
|
664
|
+
--
|
|
665
|
+
-- letters: A-Z
|
|
666
|
+
-- numbers: 0-9
|
|
667
|
+
-- function: F1-F12
|
|
668
|
+
-- mouse: Mouse1 (left), Mouse2 (right), Mouse3 (middle), Mouse4, Mouse5
|
|
669
|
+
-- modifiers: LCtrl, RCtrl, LShift, RShift, LAlt, RAlt, LWin, RWin
|
|
670
|
+
-- navigation: Up, Down, Left, Right, Home, End, PageUp, PageDown, Insert, Delete
|
|
671
|
+
-- editing: Backspace, Tab, Enter, Space, Escape
|
|
672
|
+
-- punctuation: Minus, Equal, LeftBrace, RightBrace, Backslash, Semicolon,
|
|
673
|
+
-- Apostrophe, Grave, Comma, Period, Slash
|
|
674
|
+
-- locks: CapsLock, ScrollLock, NumLock
|
|
675
|
+
-- system: PrintScreen, Pause, Menu
|
|
676
|
+
-- numpad: Kp0-Kp9, KpPlus, KpMinus, KpMultiply, KpDivide, KpEnter, KpDot
|
|
677
|
+
--
|
|
678
|
+
-- HID output only (HID.Down, HID.Press, etc.):
|
|
679
|
+
-- function: F13-F24
|
|
680
|
+
-- media: MediaNext, MediaPrev, MediaStop, MediaPlay, VolumeUp, VolumeDown, Mute
|
|
681
|
+
-- aliases: Numpad0-9, NP0-9, NPAdd, NPSubtract, NPMultiply, NPDivide, NPEnter,
|
|
682
|
+
-- NPDecimal, Ctrl, Shift, Alt, Win, Meta, Del, PgUp, PgDn, etc.
|
|
683
|
+
|
|
684
|
+
-- hooks: declare these as global functions in your script.
|
|
685
|
+
-- uncomment the ones you use; the runtime calls them when events occur.
|
|
686
|
+
|
|
687
|
+
-- declare function OnStart(): ()
|
|
688
|
+
-- declare function OnStop(): ()
|
|
689
|
+
-- declare function OnFocus(window: WindowInfo): ()
|
|
690
|
+
-- declare function OnBlur(window: WindowInfo): ()
|
|
691
|
+
-- declare function OnTick(dtMs: number): () -- ms elapsed since the previous OnTick (0 on the first)
|
|
692
|
+
-- declare function OnDown(key: string): boolean?
|
|
693
|
+
-- declare function OnUp(key: string, durationMs: number): boolean?
|
|
694
|
+
-- declare function OnMove(dx: number, dy: number): boolean? -- return value only used with mouse_block=true (hardware mode only)
|
|
695
|
+
-- declare function OnScroll(delta: number): boolean?
|
|
696
|
+
-- declare function OnScrollH(delta: number): boolean?
|
|
697
|
+
-- declare function OnError(): ()
|
|
698
|
+
-- declare function OnReload(): ()
|