@miosa/sdk 3.4.1 → 3.6.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.
@@ -0,0 +1,195 @@
1
+ import { MiosaError } from './chunk-BMWUKYWU.js';
2
+
3
+ // src/resources/desktop-act.ts
4
+ var ACTION_NAMES = [
5
+ "screenshot",
6
+ "zoom",
7
+ "cursor_position",
8
+ "left_click",
9
+ "right_click",
10
+ "middle_click",
11
+ "double_click",
12
+ "triple_click",
13
+ "left_click_drag",
14
+ "mouse_move",
15
+ "left_mouse_down",
16
+ "left_mouse_up",
17
+ "scroll",
18
+ "type",
19
+ "key",
20
+ "hold_key",
21
+ "wait"
22
+ ];
23
+ var InvalidActionInputError = class extends MiosaError {
24
+ constructor(action, message) {
25
+ super(`${action}: ${message}`, 0, "INVALID_ACTION_INPUT", { action }, void 0, false);
26
+ this.name = "InvalidActionInputError";
27
+ }
28
+ };
29
+ function point(action, value, field) {
30
+ if (!value || value.length !== 2 || !Number.isFinite(value[0]) || !Number.isFinite(value[1])) {
31
+ throw new InvalidActionInputError(action, `${field} must be [x, y]`);
32
+ }
33
+ return [Math.round(value[0]), Math.round(value[1])];
34
+ }
35
+ function pngSize(bytes) {
36
+ if (bytes.length < 24 || bytes[1] !== 80 || bytes[2] !== 78 || bytes[3] !== 71) return [0, 0];
37
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
38
+ return [view.getUint32(16), view.getUint32(20)];
39
+ }
40
+ function toBase64(bytes) {
41
+ return Buffer.from(bytes).toString("base64");
42
+ }
43
+ function screenshotResult(action, bytes, started) {
44
+ const [width, height] = pngSize(bytes);
45
+ return {
46
+ ok: true,
47
+ action,
48
+ durationMs: Date.now() - started,
49
+ imageBase64: toBase64(bytes),
50
+ mediaType: "image/png",
51
+ width,
52
+ height,
53
+ takenAt: (/* @__PURE__ */ new Date()).toISOString()
54
+ };
55
+ }
56
+ async function withModifier(desktop, modifier, run) {
57
+ if (!modifier) {
58
+ await run();
59
+ return;
60
+ }
61
+ await desktop.keyDown(modifier);
62
+ try {
63
+ await run();
64
+ } finally {
65
+ await desktop.keyUp(modifier);
66
+ }
67
+ }
68
+ var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
69
+ async function performAction(desktop, action, ...args) {
70
+ const started = Date.now();
71
+ const params = args[0] ?? {};
72
+ const done = (fields) => ({ ok: true, durationMs: Date.now() - started, ...fields });
73
+ const clickAt = async (button) => {
74
+ const where = params["coordinate"] ? point(action, params["coordinate"], "coordinate") : await desktop.cursor().then((c) => [c.x, c.y]);
75
+ await withModifier(desktop, params["text"], async () => {
76
+ if (button === "double") await desktop.doubleClick(where[0], where[1]);
77
+ else if (button === "triple") {
78
+ await desktop.click(where[0], where[1], "left");
79
+ await desktop.doubleClick(where[0], where[1]);
80
+ } else await desktop.click(where[0], where[1], button);
81
+ });
82
+ return done({ action, coordinate: where });
83
+ };
84
+ switch (action) {
85
+ case "screenshot":
86
+ return screenshotResult("screenshot", await desktop.screenshot(), started);
87
+ case "zoom": {
88
+ const region = params["region"];
89
+ if (!region || region.length !== 4 || !region.every(Number.isFinite)) {
90
+ throw new InvalidActionInputError(action, "region must be [x1, y1, x2, y2]");
91
+ }
92
+ const [x1, y1, x2, y2] = region;
93
+ if (x2 <= x1 || y2 <= y1) throw new InvalidActionInputError(action, "region must have positive width and height");
94
+ const bytes = await desktop.screenshotRegion(Math.round(x1), Math.round(y1), Math.round(x2 - x1), Math.round(y2 - y1));
95
+ return screenshotResult("zoom", bytes, started);
96
+ }
97
+ case "cursor_position": {
98
+ const cursor = await desktop.cursor();
99
+ return done({ action, x: cursor.x, y: cursor.y });
100
+ }
101
+ case "left_click":
102
+ return clickAt("left");
103
+ case "right_click":
104
+ return clickAt("right");
105
+ case "middle_click":
106
+ return clickAt("middle");
107
+ case "double_click":
108
+ return clickAt("double");
109
+ case "triple_click":
110
+ return clickAt("triple");
111
+ case "left_click_drag": {
112
+ const from = point(action, params["start_coordinate"], "start_coordinate");
113
+ const to = point(action, params["coordinate"], "coordinate");
114
+ await withModifier(desktop, params["text"], () => desktop.drag(from[0], from[1], to[0], to[1]));
115
+ return done({ action, coordinate: to });
116
+ }
117
+ case "mouse_move": {
118
+ const to = point(action, params["coordinate"], "coordinate");
119
+ await desktop.moveMouse(to[0], to[1]);
120
+ return done({ action, coordinate: to });
121
+ }
122
+ case "left_mouse_down":
123
+ case "left_mouse_up": {
124
+ const cursor = await desktop.cursor();
125
+ if (action === "left_mouse_down") await desktop.mouseDown(cursor.x, cursor.y, "left");
126
+ else await desktop.mouseUp(cursor.x, cursor.y, "left");
127
+ return done({ action, coordinate: [cursor.x, cursor.y] });
128
+ }
129
+ case "scroll": {
130
+ const direction = params["scroll_direction"];
131
+ const amount = params["scroll_amount"];
132
+ if (!direction || !["up", "down", "left", "right"].includes(direction)) {
133
+ throw new InvalidActionInputError(action, "scroll_direction must be up, down, left or right");
134
+ }
135
+ if (typeof amount !== "number" || !Number.isFinite(amount) || amount < 0) {
136
+ throw new InvalidActionInputError(action, "scroll_amount must be a non-negative number");
137
+ }
138
+ const where = params["coordinate"] ? point(action, params["coordinate"], "coordinate") : await desktop.cursor().then((c) => [c.x, c.y]);
139
+ await withModifier(
140
+ desktop,
141
+ params["text"],
142
+ () => desktop.scroll(direction, amount, where[0], where[1])
143
+ );
144
+ return done({ action, coordinate: where });
145
+ }
146
+ case "type": {
147
+ const text = params["text"];
148
+ if (typeof text !== "string") throw new InvalidActionInputError(action, "text is required");
149
+ await desktop.type(text);
150
+ return done({ action });
151
+ }
152
+ case "key": {
153
+ const text = params["text"];
154
+ if (typeof text !== "string" || text === "") throw new InvalidActionInputError(action, "text is required");
155
+ const repeat = typeof params["repeat"] === "number" ? Math.max(1, Math.floor(params["repeat"])) : 1;
156
+ for (let i = 0; i < repeat; i += 1) await desktop.key(text);
157
+ return done({ action });
158
+ }
159
+ case "hold_key": {
160
+ const text = params["text"];
161
+ const duration = params["duration"];
162
+ if (typeof text !== "string" || text === "") throw new InvalidActionInputError(action, "text is required");
163
+ if (typeof duration !== "number" || !Number.isFinite(duration) || duration < 0) {
164
+ throw new InvalidActionInputError(action, "duration must be a non-negative number of seconds");
165
+ }
166
+ await desktop.keyDown(text);
167
+ try {
168
+ await sleep(duration * 1e3);
169
+ } finally {
170
+ await desktop.keyUp(text);
171
+ }
172
+ return done({ action });
173
+ }
174
+ case "wait": {
175
+ const duration = params["duration"];
176
+ if (typeof duration !== "number" || !Number.isFinite(duration) || duration < 0) {
177
+ throw new InvalidActionInputError(action, "duration must be a non-negative number of seconds");
178
+ }
179
+ await desktop.wait(duration);
180
+ return done({ action });
181
+ }
182
+ default: {
183
+ const unknown = action;
184
+ throw new InvalidActionInputError(String(unknown), "unknown action");
185
+ }
186
+ }
187
+ }
188
+ function performActionDynamic(desktop, action, params = {}) {
189
+ const run = performAction;
190
+ return run(desktop, action, params);
191
+ }
192
+
193
+ export { ACTION_NAMES, InvalidActionInputError, performAction, performActionDynamic, pngSize, toBase64 };
194
+ //# sourceMappingURL=chunk-H245ZDMW.js.map
195
+ //# sourceMappingURL=chunk-H245ZDMW.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/resources/desktop-act.ts"],"names":[],"mappings":"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","file":"chunk-H245ZDMW.js","sourcesContent":["import { MiosaError } from \"../errors.js\";\nimport type { Desktop } from \"./desktop.js\";\n\n/**\n * One typed dispatcher over the desktop routes, named after the members of\n * Anthropic's `computer_toolset_20260801` so the same names work in an agent\n * loop and in `computer.act()`.\n */\n\n/** Every action `act()` understands. */\nexport const ACTION_NAMES = [\n \"screenshot\",\n \"zoom\",\n \"cursor_position\",\n \"left_click\",\n \"right_click\",\n \"middle_click\",\n \"double_click\",\n \"triple_click\",\n \"left_click_drag\",\n \"mouse_move\",\n \"left_mouse_down\",\n \"left_mouse_up\",\n \"scroll\",\n \"type\",\n \"key\",\n \"hold_key\",\n \"wait\",\n] as const;\n\nexport type ActionName = (typeof ACTION_NAMES)[number];\n\n/** `[x, y]` in screenshot pixels. */\nexport type Coordinate = readonly [number, number] | readonly number[];\n\ninterface ClickParams {\n /** Where to click. Omitted: the current pointer position. */\n coordinate?: Coordinate;\n /** A modifier key held during the click, for example `\"shift\"`. */\n text?: string;\n}\n\nexport interface ActParamsMap {\n screenshot: Record<string, never>;\n zoom: { region: readonly [number, number, number, number] | readonly number[] };\n cursor_position: Record<string, never>;\n left_click: ClickParams;\n right_click: ClickParams;\n middle_click: ClickParams;\n double_click: ClickParams;\n triple_click: ClickParams;\n left_click_drag: { start_coordinate: Coordinate; coordinate: Coordinate; text?: string };\n mouse_move: { coordinate: Coordinate };\n left_mouse_down: Record<string, never>;\n left_mouse_up: Record<string, never>;\n scroll: {\n scroll_direction: \"up\" | \"down\" | \"left\" | \"right\";\n scroll_amount: number;\n coordinate?: Coordinate;\n text?: string;\n };\n type: { text: string };\n key: { text: string; repeat?: number };\n hold_key: { text: string; duration: number };\n wait: { duration: number };\n}\n\ninterface ActionBase<A extends ActionName> {\n ok: true;\n action: A;\n /** Client-measured time for the whole action, including the round trips. */\n durationMs: number;\n}\n\nexport interface ScreenshotActionResult<A extends \"screenshot\" | \"zoom\" = \"screenshot\" | \"zoom\"> extends ActionBase<A> {\n imageBase64: string;\n mediaType: \"image/png\";\n /** Pixels, read from the PNG header. */\n width: number;\n height: number;\n takenAt: string;\n}\n\nexport interface CursorActionResult extends ActionBase<\"cursor_position\"> {\n x: number;\n y: number;\n}\n\n/** An action that moved or clicked the pointer. `coordinate` is where it ended. */\nexport interface PointerActionResult<A extends ActionName> extends ActionBase<A> {\n coordinate: [number, number];\n}\n\nexport type ActionResultMap = {\n [A in ActionName]: A extends \"screenshot\" | \"zoom\"\n ? ScreenshotActionResult<A>\n : A extends \"cursor_position\"\n ? CursorActionResult\n : A extends\n | \"left_click\"\n | \"right_click\"\n | \"middle_click\"\n | \"double_click\"\n | \"triple_click\"\n | \"left_click_drag\"\n | \"mouse_move\"\n | \"left_mouse_down\"\n | \"left_mouse_up\"\n | \"scroll\"\n ? PointerActionResult<A>\n : ActionBase<A>;\n};\n\n/** What `act()` returns, discriminated on `action`. */\nexport type ActionResult = ActionResultMap[ActionName];\n\n/** Parameters are optional only for actions that take none. */\nexport type ActArgs<A extends ActionName> = A extends\n | \"screenshot\"\n | \"cursor_position\"\n | \"left_mouse_down\"\n | \"left_mouse_up\"\n ? [params?: ActParamsMap[A]]\n : A extends \"left_click\" | \"right_click\" | \"middle_click\" | \"double_click\" | \"triple_click\"\n ? [params?: ActParamsMap[A]]\n : [params: ActParamsMap[A]];\n\nexport class InvalidActionInputError extends MiosaError {\n constructor(action: string, message: string) {\n super(`${action}: ${message}`, 0, \"INVALID_ACTION_INPUT\", { action }, undefined, false);\n this.name = \"InvalidActionInputError\";\n }\n}\n\nfunction point(action: string, value: Coordinate | undefined, field: string): [number, number] {\n if (\n !value ||\n value.length !== 2 ||\n !Number.isFinite(value[0]) ||\n !Number.isFinite(value[1])\n ) {\n throw new InvalidActionInputError(action, `${field} must be [x, y]`);\n }\n return [Math.round(value[0] as number), Math.round(value[1] as number)];\n}\n\n/** Width and height from a PNG's IHDR chunk; `[0, 0]` for anything else. */\nexport function pngSize(bytes: Uint8Array): [number, number] {\n if (bytes.length < 24 || bytes[1] !== 0x50 || bytes[2] !== 0x4e || bytes[3] !== 0x47) return [0, 0];\n const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n return [view.getUint32(16), view.getUint32(20)];\n}\n\nexport function toBase64(bytes: Uint8Array): string {\n return Buffer.from(bytes).toString(\"base64\");\n}\n\nfunction screenshotResult<A extends \"screenshot\" | \"zoom\">(\n action: A,\n bytes: Uint8Array,\n started: number,\n): ScreenshotActionResult<A> {\n const [width, height] = pngSize(bytes);\n return {\n ok: true,\n action,\n durationMs: Date.now() - started,\n imageBase64: toBase64(bytes),\n mediaType: \"image/png\",\n width,\n height,\n takenAt: new Date().toISOString(),\n };\n}\n\nasync function withModifier(desktop: Desktop, modifier: string | undefined, run: () => Promise<unknown>): Promise<void> {\n if (!modifier) {\n await run();\n return;\n }\n await desktop.keyDown(modifier);\n try {\n await run();\n } finally {\n await desktop.keyUp(modifier);\n }\n}\n\nconst sleep = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));\n\n/** Run one action against a desktop. */\nexport async function performAction<A extends ActionName>(\n desktop: Desktop,\n action: A,\n ...args: ActArgs<A>\n): Promise<ActionResultMap[A]> {\n const started = Date.now();\n const params = (args[0] ?? {}) as Record<string, unknown>;\n // The switch below builds exactly the shape ActionResultMap names for each action.\n const done = (fields: Record<string, unknown>): ActionResultMap[A] =>\n ({ ok: true, durationMs: Date.now() - started, ...fields }) as unknown as ActionResultMap[A];\n\n const clickAt = async (button: \"left\" | \"right\" | \"middle\" | \"double\" | \"triple\"): Promise<ActionResultMap[A]> => {\n const where = params[\"coordinate\"]\n ? point(action, params[\"coordinate\"] as Coordinate, \"coordinate\")\n : await desktop.cursor().then((c): [number, number] => [c.x, c.y]);\n await withModifier(desktop, params[\"text\"] as string | undefined, async () => {\n if (button === \"double\") await desktop.doubleClick(where[0], where[1]);\n else if (button === \"triple\") {\n await desktop.click(where[0], where[1], \"left\");\n await desktop.doubleClick(where[0], where[1]);\n } else await desktop.click(where[0], where[1], button);\n });\n return done({ action, coordinate: where });\n };\n\n switch (action) {\n case \"screenshot\":\n return screenshotResult(\"screenshot\", await desktop.screenshot(), started) as unknown as ActionResultMap[A];\n case \"zoom\": {\n const region = params[\"region\"] as readonly number[] | undefined;\n if (!region || region.length !== 4 || !region.every(Number.isFinite)) {\n throw new InvalidActionInputError(action, \"region must be [x1, y1, x2, y2]\");\n }\n const [x1, y1, x2, y2] = region as [number, number, number, number];\n if (x2 <= x1 || y2 <= y1) throw new InvalidActionInputError(action, \"region must have positive width and height\");\n const bytes = await desktop.screenshotRegion(Math.round(x1), Math.round(y1), Math.round(x2 - x1), Math.round(y2 - y1));\n return screenshotResult(\"zoom\", bytes, started) as unknown as ActionResultMap[A];\n }\n case \"cursor_position\": {\n const cursor = await desktop.cursor();\n return done({ action, x: cursor.x, y: cursor.y });\n }\n case \"left_click\":\n return clickAt(\"left\");\n case \"right_click\":\n return clickAt(\"right\");\n case \"middle_click\":\n return clickAt(\"middle\");\n case \"double_click\":\n return clickAt(\"double\");\n case \"triple_click\":\n return clickAt(\"triple\");\n case \"left_click_drag\": {\n const from = point(action, params[\"start_coordinate\"] as Coordinate, \"start_coordinate\");\n const to = point(action, params[\"coordinate\"] as Coordinate, \"coordinate\");\n await withModifier(desktop, params[\"text\"] as string | undefined, () => desktop.drag(from[0], from[1], to[0], to[1]));\n return done({ action, coordinate: to });\n }\n case \"mouse_move\": {\n const to = point(action, params[\"coordinate\"] as Coordinate, \"coordinate\");\n await desktop.moveMouse(to[0], to[1]);\n return done({ action, coordinate: to });\n }\n case \"left_mouse_down\":\n case \"left_mouse_up\": {\n const cursor = await desktop.cursor();\n if (action === \"left_mouse_down\") await desktop.mouseDown(cursor.x, cursor.y, \"left\");\n else await desktop.mouseUp(cursor.x, cursor.y, \"left\");\n return done({ action, coordinate: [cursor.x, cursor.y] as [number, number] });\n }\n case \"scroll\": {\n const direction = params[\"scroll_direction\"] as ActParamsMap[\"scroll\"][\"scroll_direction\"] | undefined;\n const amount = params[\"scroll_amount\"] as number | undefined;\n if (!direction || ![\"up\", \"down\", \"left\", \"right\"].includes(direction)) {\n throw new InvalidActionInputError(action, \"scroll_direction must be up, down, left or right\");\n }\n if (typeof amount !== \"number\" || !Number.isFinite(amount) || amount < 0) {\n throw new InvalidActionInputError(action, \"scroll_amount must be a non-negative number\");\n }\n const where = params[\"coordinate\"]\n ? point(action, params[\"coordinate\"] as Coordinate, \"coordinate\")\n : await desktop.cursor().then((c): [number, number] => [c.x, c.y]);\n await withModifier(desktop, params[\"text\"] as string | undefined, () =>\n desktop.scroll(direction, amount, where[0], where[1]),\n );\n return done({ action, coordinate: where });\n }\n case \"type\": {\n const text = params[\"text\"];\n if (typeof text !== \"string\") throw new InvalidActionInputError(action, \"text is required\");\n await desktop.type(text);\n return done({ action });\n }\n case \"key\": {\n const text = params[\"text\"];\n if (typeof text !== \"string\" || text === \"\") throw new InvalidActionInputError(action, \"text is required\");\n const repeat = typeof params[\"repeat\"] === \"number\" ? Math.max(1, Math.floor(params[\"repeat\"])) : 1;\n for (let i = 0; i < repeat; i += 1) await desktop.key(text);\n return done({ action });\n }\n case \"hold_key\": {\n const text = params[\"text\"];\n const duration = params[\"duration\"];\n if (typeof text !== \"string\" || text === \"\") throw new InvalidActionInputError(action, \"text is required\");\n if (typeof duration !== \"number\" || !Number.isFinite(duration) || duration < 0) {\n throw new InvalidActionInputError(action, \"duration must be a non-negative number of seconds\");\n }\n await desktop.keyDown(text);\n try {\n await sleep(duration * 1000);\n } finally {\n await desktop.keyUp(text);\n }\n return done({ action });\n }\n case \"wait\": {\n const duration = params[\"duration\"];\n if (typeof duration !== \"number\" || !Number.isFinite(duration) || duration < 0) {\n throw new InvalidActionInputError(action, \"duration must be a non-negative number of seconds\");\n }\n await desktop.wait(duration);\n return done({ action });\n }\n default: {\n const unknown: never = action;\n throw new InvalidActionInputError(String(unknown), \"unknown action\");\n }\n }\n}\n\n/**\n * `performAction` for callers that hold the action name and parameters as\n * data (a model's tool call) rather than as literals. Parameters are checked\n * at run time and a bad one raises {@link InvalidActionInputError}.\n */\nexport function performActionDynamic(\n desktop: Desktop,\n action: ActionName,\n params: Record<string, unknown> = {},\n): Promise<ActionResult> {\n const run = performAction as (d: Desktop, a: ActionName, p: Record<string, unknown>) => Promise<ActionResult>;\n return run(desktop, action, params);\n}\n"]}