@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.
- package/README.md +336 -0
- package/dist/chunk-BMWUKYWU.js +463 -0
- package/dist/chunk-BMWUKYWU.js.map +1 -0
- package/dist/chunk-H245ZDMW.js +195 -0
- package/dist/chunk-H245ZDMW.js.map +1 -0
- package/dist/client-C_uXhex9.d.ts +9221 -0
- package/dist/computer-CKDK0Ahy.d.ts +3689 -0
- package/dist/computer-use/index.d.ts +154 -0
- package/dist/computer-use/index.js +185 -0
- package/dist/computer-use/index.js.map +1 -0
- package/dist/helpers/index.d.ts +77 -0
- package/dist/helpers/index.js +151 -0
- package/dist/helpers/index.js.map +1 -0
- package/dist/index.d.ts +7 -9312
- package/dist/index.js +7256 -4169
- package/dist/index.js.map +1 -1
- package/package.json +18 -1
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { BetaAbstractComputerToolset20260801, BetaComputerConfirmCallable, BetaToolsetCallContext } from '@anthropic-ai/sdk/helpers/beta/toolsets';
|
|
2
|
+
export { BetaComputerMemberResult, ToolError } from '@anthropic-ai/sdk/helpers/beta/toolsets';
|
|
3
|
+
import { BetaComputerToolsetConfigs, BetaComputerZoomInput, BetaComputerMouseMoveInput, BetaComputerLeftClickInput, BetaComputerRightClickInput, BetaComputerMiddleClickInput, BetaComputerDoubleClickInput, BetaComputerTripleClickInput, BetaComputerLeftClickDragInput, BetaComputerScrollInput, BetaComputerTypeInput, BetaComputerKeyInput, BetaComputerHoldKeyInput, BetaComputerWaitInput } from '@anthropic-ai/sdk/resources/beta';
|
|
4
|
+
import { e as ActionName, D as Computer } from '../computer-CKDK0Ahy.js';
|
|
5
|
+
import 'ws';
|
|
6
|
+
import 'node:events';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The older, named `computer` tool (`computer_20241022`, `computer_20250124`,
|
|
10
|
+
* `computer_20251124`) for models and platforms that do not take the toolset.
|
|
11
|
+
* These carry an `action` field in the input, which maps one to one onto
|
|
12
|
+
* `computer.act()`.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
type LegacyComputerToolVersion = "computer_20241022" | "computer_20250124" | "computer_20251124";
|
|
16
|
+
/** Actions each version accepts. */
|
|
17
|
+
declare const LEGACY_ACTIONS: Readonly<Record<LegacyComputerToolVersion, readonly ActionName[]>>;
|
|
18
|
+
/** The beta header each version needs. */
|
|
19
|
+
declare const LEGACY_BETA_HEADERS: Readonly<Record<LegacyComputerToolVersion, string>>;
|
|
20
|
+
interface LegacyComputerToolOptions {
|
|
21
|
+
version: LegacyComputerToolVersion;
|
|
22
|
+
displayWidthPx: number;
|
|
23
|
+
displayHeightPx: number;
|
|
24
|
+
/** Asked before every `type`, `key` and `hold_key`. Return false to refuse. */
|
|
25
|
+
confirm: (call: {
|
|
26
|
+
action: string;
|
|
27
|
+
input: Record<string, unknown>;
|
|
28
|
+
}) => boolean | Promise<boolean>;
|
|
29
|
+
}
|
|
30
|
+
type LegacyToolResultContent = {
|
|
31
|
+
type: "text";
|
|
32
|
+
text: string;
|
|
33
|
+
} | {
|
|
34
|
+
type: "image";
|
|
35
|
+
source: {
|
|
36
|
+
type: "base64";
|
|
37
|
+
media_type: "image/png";
|
|
38
|
+
data: string;
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
interface LegacyComputerTool {
|
|
42
|
+
/** The entry for `tools[]`. */
|
|
43
|
+
definition: {
|
|
44
|
+
type: LegacyComputerToolVersion;
|
|
45
|
+
name: "computer";
|
|
46
|
+
display_width_px: number;
|
|
47
|
+
display_height_px: number;
|
|
48
|
+
};
|
|
49
|
+
/** The `anthropic-beta` header value this version needs. */
|
|
50
|
+
betaHeader: string;
|
|
51
|
+
/** Run one `tool_use` input and get the `tool_result` content. A failure is returned as text with `isError`. */
|
|
52
|
+
execute(input: Record<string, unknown>): Promise<{
|
|
53
|
+
content: LegacyToolResultContent[];
|
|
54
|
+
isError: boolean;
|
|
55
|
+
}>;
|
|
56
|
+
}
|
|
57
|
+
declare function miosaComputerToolLegacy(computer: Computer, options: LegacyComputerToolOptions): LegacyComputerTool;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Claude computer-use over a MIOSA computer.
|
|
61
|
+
*
|
|
62
|
+
* `miosaComputerToolset(computer, { confirm })` is a `computer_toolset_20260801`
|
|
63
|
+
* toolset: it subclasses Anthropic's `BetaAbstractComputerToolset20260801`, so
|
|
64
|
+
* the SDK owns the model loop contract (one `tool_use` per member, the
|
|
65
|
+
* `toolset_name` echo, stop at the first failure in a batch, the skipped-action
|
|
66
|
+
* text and the approval gate). This file only drives the desktop.
|
|
67
|
+
*
|
|
68
|
+
* Needs the optional peer `@anthropic-ai/sdk` (0.133 or newer). Import it from
|
|
69
|
+
* `@miosa/sdk/computer-use`.
|
|
70
|
+
*
|
|
71
|
+
* ```ts
|
|
72
|
+
* import Anthropic from "@anthropic-ai/sdk";
|
|
73
|
+
* import { miosaComputerToolset } from "@miosa/sdk/computer-use";
|
|
74
|
+
*
|
|
75
|
+
* const toolset = miosaComputerToolset(computer, {
|
|
76
|
+
* confirm: async ({ member, input }) => member !== "type" || askHuman(input),
|
|
77
|
+
* });
|
|
78
|
+
* const runner = client.beta.messages.toolRunner({
|
|
79
|
+
* model: "claude-sonnet-5",
|
|
80
|
+
* max_tokens: 8192,
|
|
81
|
+
* messages: [{ role: "user", content: "Open the browser" }],
|
|
82
|
+
* tools: [toolset],
|
|
83
|
+
* });
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
|
|
87
|
+
type Disabled = {
|
|
88
|
+
enabled: false;
|
|
89
|
+
};
|
|
90
|
+
interface CommonOptions {
|
|
91
|
+
/** Set `triple_click` on. It is two requests (click, then double-click) and needs a low-latency link. Default: off. */
|
|
92
|
+
emulateTripleClick?: boolean;
|
|
93
|
+
/** Entry-level fields such as `{ cache_control: { type: "ephemeral" } }`. */
|
|
94
|
+
toolConfigs?: {
|
|
95
|
+
cache_control?: {
|
|
96
|
+
type: "ephemeral";
|
|
97
|
+
} | null;
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Either pass `confirm`, or switch off `type`, `key` and `hold_key` in
|
|
102
|
+
* `configs`. A toolset that can type with neither is refused, as in
|
|
103
|
+
* Anthropic's own constructor.
|
|
104
|
+
*/
|
|
105
|
+
type MiosaComputerToolsetOptions = (CommonOptions & {
|
|
106
|
+
confirm: BetaComputerConfirmCallable;
|
|
107
|
+
configs?: BetaComputerToolsetConfigs;
|
|
108
|
+
}) | (CommonOptions & {
|
|
109
|
+
confirm?: undefined;
|
|
110
|
+
configs: BetaComputerToolsetConfigs & {
|
|
111
|
+
type: Disabled;
|
|
112
|
+
key: Disabled;
|
|
113
|
+
hold_key: Disabled;
|
|
114
|
+
};
|
|
115
|
+
});
|
|
116
|
+
/** The desktop driver behind the toolset. */
|
|
117
|
+
declare class MiosaComputerToolset extends BetaAbstractComputerToolset20260801 {
|
|
118
|
+
private readonly computer;
|
|
119
|
+
constructor(computer: Computer, options: MiosaComputerToolsetOptions);
|
|
120
|
+
private act;
|
|
121
|
+
protected screenshot(): Promise<{
|
|
122
|
+
data: string;
|
|
123
|
+
mediaType: "image/png";
|
|
124
|
+
}>;
|
|
125
|
+
protected zoom(_ctx: BetaToolsetCallContext, input: BetaComputerZoomInput): Promise<{
|
|
126
|
+
data: string;
|
|
127
|
+
mediaType: "image/png";
|
|
128
|
+
}>;
|
|
129
|
+
protected cursor_position(): Promise<{
|
|
130
|
+
x: number;
|
|
131
|
+
y: number;
|
|
132
|
+
}>;
|
|
133
|
+
protected mouse_move(_ctx: BetaToolsetCallContext, input: BetaComputerMouseMoveInput): Promise<void>;
|
|
134
|
+
protected left_mouse_down(): Promise<void>;
|
|
135
|
+
protected left_mouse_up(): Promise<void>;
|
|
136
|
+
protected left_click(_ctx: BetaToolsetCallContext, input: BetaComputerLeftClickInput): Promise<void>;
|
|
137
|
+
protected right_click(_ctx: BetaToolsetCallContext, input: BetaComputerRightClickInput): Promise<void>;
|
|
138
|
+
protected middle_click(_ctx: BetaToolsetCallContext, input: BetaComputerMiddleClickInput): Promise<void>;
|
|
139
|
+
protected double_click(_ctx: BetaToolsetCallContext, input: BetaComputerDoubleClickInput): Promise<void>;
|
|
140
|
+
protected triple_click(_ctx: BetaToolsetCallContext, input: BetaComputerTripleClickInput): Promise<void>;
|
|
141
|
+
protected left_click_drag(_ctx: BetaToolsetCallContext, input: BetaComputerLeftClickDragInput): Promise<void>;
|
|
142
|
+
protected scroll(_ctx: BetaToolsetCallContext, input: BetaComputerScrollInput): Promise<void>;
|
|
143
|
+
protected type_(_ctx: BetaToolsetCallContext, input: BetaComputerTypeInput): Promise<void>;
|
|
144
|
+
protected key(_ctx: BetaToolsetCallContext, input: BetaComputerKeyInput): Promise<void>;
|
|
145
|
+
protected hold_key(_ctx: BetaToolsetCallContext, input: BetaComputerHoldKeyInput): Promise<void>;
|
|
146
|
+
protected wait(_ctx: BetaToolsetCallContext, input: BetaComputerWaitInput): Promise<void>;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Build the toolset for one computer. `confirm` is required unless `type`,
|
|
150
|
+
* `key` and `hold_key` are switched off in `configs`.
|
|
151
|
+
*/
|
|
152
|
+
declare function miosaComputerToolset(computer: Computer, options: MiosaComputerToolsetOptions): MiosaComputerToolset;
|
|
153
|
+
|
|
154
|
+
export { LEGACY_ACTIONS, LEGACY_BETA_HEADERS, type LegacyComputerTool, type LegacyComputerToolOptions, type LegacyComputerToolVersion, type LegacyToolResultContent, MiosaComputerToolset, type MiosaComputerToolsetOptions, miosaComputerToolLegacy, miosaComputerToolset };
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { performActionDynamic, InvalidActionInputError } from '../chunk-H245ZDMW.js';
|
|
2
|
+
import { MiosaError } from '../chunk-BMWUKYWU.js';
|
|
3
|
+
import { BetaAbstractComputerToolset20260801, ToolError } from '@anthropic-ai/sdk/helpers/beta/toolsets';
|
|
4
|
+
export { ToolError } from '@anthropic-ai/sdk/helpers/beta/toolsets';
|
|
5
|
+
|
|
6
|
+
// src/computer-use/legacy.ts
|
|
7
|
+
var BASE_ACTIONS = [
|
|
8
|
+
"key",
|
|
9
|
+
"type",
|
|
10
|
+
"mouse_move",
|
|
11
|
+
"left_click",
|
|
12
|
+
"left_click_drag",
|
|
13
|
+
"right_click",
|
|
14
|
+
"middle_click",
|
|
15
|
+
"double_click",
|
|
16
|
+
"screenshot",
|
|
17
|
+
"cursor_position"
|
|
18
|
+
];
|
|
19
|
+
var V20250124_ACTIONS = [...BASE_ACTIONS, "left_mouse_down", "left_mouse_up", "scroll", "hold_key", "wait", "triple_click"];
|
|
20
|
+
var V20251124_ACTIONS = [...V20250124_ACTIONS, "zoom"];
|
|
21
|
+
var LEGACY_ACTIONS = {
|
|
22
|
+
computer_20241022: BASE_ACTIONS,
|
|
23
|
+
computer_20250124: V20250124_ACTIONS,
|
|
24
|
+
computer_20251124: V20251124_ACTIONS
|
|
25
|
+
};
|
|
26
|
+
var LEGACY_BETA_HEADERS = {
|
|
27
|
+
computer_20241022: "computer-use-2024-10-22",
|
|
28
|
+
computer_20250124: "computer-use-2025-01-24",
|
|
29
|
+
computer_20251124: "computer-use-2025-11-24"
|
|
30
|
+
};
|
|
31
|
+
var NEEDS_CONFIRM = /* @__PURE__ */ new Set(["type", "key", "hold_key"]);
|
|
32
|
+
function miosaComputerToolLegacy(computer, options) {
|
|
33
|
+
if (typeof options.confirm !== "function") {
|
|
34
|
+
throw new MiosaError("a confirm callable is required", 0, "CONFIRM_REQUIRED", {}, void 0, false);
|
|
35
|
+
}
|
|
36
|
+
const allowed = new Set(LEGACY_ACTIONS[options.version]);
|
|
37
|
+
return {
|
|
38
|
+
definition: {
|
|
39
|
+
type: options.version,
|
|
40
|
+
name: "computer",
|
|
41
|
+
display_width_px: options.displayWidthPx,
|
|
42
|
+
display_height_px: options.displayHeightPx
|
|
43
|
+
},
|
|
44
|
+
betaHeader: LEGACY_BETA_HEADERS[options.version],
|
|
45
|
+
async execute(input) {
|
|
46
|
+
const { action, ...params } = input;
|
|
47
|
+
const fail = (text) => ({ content: [{ type: "text", text }], isError: true });
|
|
48
|
+
if (typeof action !== "string" || !allowed.has(action)) {
|
|
49
|
+
return fail(`${options.version} does not support the action ${JSON.stringify(action)}`);
|
|
50
|
+
}
|
|
51
|
+
if (NEEDS_CONFIRM.has(action) && !await options.confirm({ action, input: params })) {
|
|
52
|
+
return fail(`The ${action} action was declined.`);
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
const result = await performActionDynamic(computer.desktop, action, params);
|
|
56
|
+
if (result.action === "screenshot" || result.action === "zoom") {
|
|
57
|
+
return {
|
|
58
|
+
content: [{ type: "image", source: { type: "base64", media_type: "image/png", data: result.imageBase64 } }],
|
|
59
|
+
isError: false
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
if (result.action === "cursor_position") {
|
|
63
|
+
return { content: [{ type: "text", text: `X=${result.x}, Y=${result.y}` }], isError: false };
|
|
64
|
+
}
|
|
65
|
+
return { content: [{ type: "text", text: "Done." }], isError: false };
|
|
66
|
+
} catch (error) {
|
|
67
|
+
return fail(error instanceof Error ? error.message : String(error));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// src/computer-use/index.ts
|
|
74
|
+
var NEEDS_CONFIRM2 = ["type", "key", "hold_key"];
|
|
75
|
+
function toToolError(error) {
|
|
76
|
+
if (error instanceof ToolError) return error;
|
|
77
|
+
if (error instanceof InvalidActionInputError) return new ToolError(error.message);
|
|
78
|
+
if (error instanceof MiosaError) return new ToolError(`${error.code ?? "ERROR"}: ${error.message}`);
|
|
79
|
+
return new ToolError(error instanceof Error ? error.message : String(error));
|
|
80
|
+
}
|
|
81
|
+
var MiosaComputerToolset = class extends BetaAbstractComputerToolset20260801 {
|
|
82
|
+
constructor(computer, options) {
|
|
83
|
+
const configs = { ...options.configs ?? {} };
|
|
84
|
+
if (!options.emulateTripleClick && configs.triple_click === void 0) {
|
|
85
|
+
configs.triple_click = { enabled: false };
|
|
86
|
+
}
|
|
87
|
+
super({
|
|
88
|
+
configs,
|
|
89
|
+
...options.confirm ? { confirm: options.confirm } : {},
|
|
90
|
+
...options.toolConfigs ? { toolConfigs: options.toolConfigs } : {}
|
|
91
|
+
});
|
|
92
|
+
this.computer = computer;
|
|
93
|
+
}
|
|
94
|
+
computer;
|
|
95
|
+
async act(action, params) {
|
|
96
|
+
try {
|
|
97
|
+
return await performActionDynamic(this.computer.desktop, action, params);
|
|
98
|
+
} catch (error) {
|
|
99
|
+
throw toToolError(error);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
async screenshot() {
|
|
103
|
+
const shot = await this.act("screenshot", {});
|
|
104
|
+
if (shot.action !== "screenshot") throw new ToolError("unexpected screenshot result");
|
|
105
|
+
return { data: shot.imageBase64, mediaType: "image/png" };
|
|
106
|
+
}
|
|
107
|
+
async zoom(_ctx, input) {
|
|
108
|
+
const shot = await this.act("zoom", { region: input.region });
|
|
109
|
+
if (shot.action !== "zoom") throw new ToolError("unexpected zoom result");
|
|
110
|
+
return { data: shot.imageBase64, mediaType: "image/png" };
|
|
111
|
+
}
|
|
112
|
+
async cursor_position() {
|
|
113
|
+
const at = await this.act("cursor_position", {});
|
|
114
|
+
if (at.action !== "cursor_position") throw new ToolError("unexpected cursor result");
|
|
115
|
+
return { x: at.x, y: at.y };
|
|
116
|
+
}
|
|
117
|
+
async mouse_move(_ctx, input) {
|
|
118
|
+
await this.act("mouse_move", { coordinate: input.coordinate });
|
|
119
|
+
}
|
|
120
|
+
async left_mouse_down() {
|
|
121
|
+
await this.act("left_mouse_down", {});
|
|
122
|
+
}
|
|
123
|
+
async left_mouse_up() {
|
|
124
|
+
await this.act("left_mouse_up", {});
|
|
125
|
+
}
|
|
126
|
+
async left_click(_ctx, input) {
|
|
127
|
+
await this.act("left_click", clean(input));
|
|
128
|
+
}
|
|
129
|
+
async right_click(_ctx, input) {
|
|
130
|
+
await this.act("right_click", clean(input));
|
|
131
|
+
}
|
|
132
|
+
async middle_click(_ctx, input) {
|
|
133
|
+
await this.act("middle_click", clean(input));
|
|
134
|
+
}
|
|
135
|
+
async double_click(_ctx, input) {
|
|
136
|
+
await this.act("double_click", clean(input));
|
|
137
|
+
}
|
|
138
|
+
async triple_click(_ctx, input) {
|
|
139
|
+
await this.act("triple_click", clean(input));
|
|
140
|
+
}
|
|
141
|
+
async left_click_drag(_ctx, input) {
|
|
142
|
+
await this.act("left_click_drag", clean(input));
|
|
143
|
+
}
|
|
144
|
+
async scroll(_ctx, input) {
|
|
145
|
+
await this.act("scroll", clean(input));
|
|
146
|
+
}
|
|
147
|
+
async type_(_ctx, input) {
|
|
148
|
+
await this.act("type", clean(input));
|
|
149
|
+
}
|
|
150
|
+
async key(_ctx, input) {
|
|
151
|
+
await this.act("key", clean(input));
|
|
152
|
+
}
|
|
153
|
+
async hold_key(_ctx, input) {
|
|
154
|
+
await this.act("hold_key", clean(input));
|
|
155
|
+
}
|
|
156
|
+
async wait(_ctx, input) {
|
|
157
|
+
await this.act("wait", clean(input));
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
function clean(input) {
|
|
161
|
+
return Object.fromEntries(Object.entries(input).filter(([, value]) => value !== null && value !== void 0));
|
|
162
|
+
}
|
|
163
|
+
function miosaComputerToolset(computer, options) {
|
|
164
|
+
const confirmMissing = options.confirm === void 0;
|
|
165
|
+
if (confirmMissing) {
|
|
166
|
+
for (const member of NEEDS_CONFIRM2) {
|
|
167
|
+
const config = (options.configs ?? {})[member];
|
|
168
|
+
if (config?.enabled !== false) {
|
|
169
|
+
throw new MiosaError(
|
|
170
|
+
`${member} needs a confirm callable: pass confirm, or disable ${NEEDS_CONFIRM2.join(", ")} in configs`,
|
|
171
|
+
0,
|
|
172
|
+
"CONFIRM_REQUIRED",
|
|
173
|
+
{ member },
|
|
174
|
+
void 0,
|
|
175
|
+
false
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return new MiosaComputerToolset(computer, options);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export { LEGACY_ACTIONS, LEGACY_BETA_HEADERS, MiosaComputerToolset, miosaComputerToolLegacy, miosaComputerToolset };
|
|
184
|
+
//# sourceMappingURL=index.js.map
|
|
185
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/computer-use/legacy.ts","../../src/computer-use/index.ts"],"names":["NEEDS_CONFIRM"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * The older, named `computer` tool (`computer_20241022`, `computer_20250124`,\n * `computer_20251124`) for models and platforms that do not take the toolset.\n * These carry an `action` field in the input, which maps one to one onto\n * `computer.act()`.\n */\n\nimport { MiosaError } from \"../errors.js\";\nimport type { Computer } from \"../resources/computer.js\";\nimport { performActionDynamic, type ActionName } from \"../resources/desktop-act.js\";\n\nexport type LegacyComputerToolVersion = \"computer_20241022\" | \"computer_20250124\" | \"computer_20251124\";\n\nconst BASE_ACTIONS = [\n \"key\",\n \"type\",\n \"mouse_move\",\n \"left_click\",\n \"left_click_drag\",\n \"right_click\",\n \"middle_click\",\n \"double_click\",\n \"screenshot\",\n \"cursor_position\",\n] as const satisfies readonly ActionName[];\n\nconst V20250124_ACTIONS = [...BASE_ACTIONS, \"left_mouse_down\", \"left_mouse_up\", \"scroll\", \"hold_key\", \"wait\", \"triple_click\"] as const;\nconst V20251124_ACTIONS = [...V20250124_ACTIONS, \"zoom\"] as const;\n\n/** Actions each version accepts. */\nexport const LEGACY_ACTIONS: Readonly<Record<LegacyComputerToolVersion, readonly ActionName[]>> = {\n computer_20241022: BASE_ACTIONS,\n computer_20250124: V20250124_ACTIONS,\n computer_20251124: V20251124_ACTIONS,\n};\n\n/** The beta header each version needs. */\nexport const LEGACY_BETA_HEADERS: Readonly<Record<LegacyComputerToolVersion, string>> = {\n computer_20241022: \"computer-use-2024-10-22\",\n computer_20250124: \"computer-use-2025-01-24\",\n computer_20251124: \"computer-use-2025-11-24\",\n};\n\nconst NEEDS_CONFIRM: ReadonlySet<string> = new Set([\"type\", \"key\", \"hold_key\"]);\n\nexport interface LegacyComputerToolOptions {\n version: LegacyComputerToolVersion;\n displayWidthPx: number;\n displayHeightPx: number;\n /** Asked before every `type`, `key` and `hold_key`. Return false to refuse. */\n confirm: (call: { action: string; input: Record<string, unknown> }) => boolean | Promise<boolean>;\n}\n\nexport type LegacyToolResultContent =\n | { type: \"text\"; text: string }\n | { type: \"image\"; source: { type: \"base64\"; media_type: \"image/png\"; data: string } };\n\nexport interface LegacyComputerTool {\n /** The entry for `tools[]`. */\n definition: {\n type: LegacyComputerToolVersion;\n name: \"computer\";\n display_width_px: number;\n display_height_px: number;\n };\n /** The `anthropic-beta` header value this version needs. */\n betaHeader: string;\n /** Run one `tool_use` input and get the `tool_result` content. A failure is returned as text with `isError`. */\n execute(input: Record<string, unknown>): Promise<{ content: LegacyToolResultContent[]; isError: boolean }>;\n}\n\nexport function miosaComputerToolLegacy(computer: Computer, options: LegacyComputerToolOptions): LegacyComputerTool {\n if (typeof options.confirm !== \"function\") {\n throw new MiosaError(\"a confirm callable is required\", 0, \"CONFIRM_REQUIRED\", {}, undefined, false);\n }\n const allowed = new Set<string>(LEGACY_ACTIONS[options.version]);\n return {\n definition: {\n type: options.version,\n name: \"computer\",\n display_width_px: options.displayWidthPx,\n display_height_px: options.displayHeightPx,\n },\n betaHeader: LEGACY_BETA_HEADERS[options.version],\n async execute(input) {\n const { action, ...params } = input;\n const fail = (text: string) => ({ content: [{ type: \"text\" as const, text }], isError: true });\n if (typeof action !== \"string\" || !allowed.has(action)) {\n return fail(`${options.version} does not support the action ${JSON.stringify(action)}`);\n }\n if (NEEDS_CONFIRM.has(action) && !(await options.confirm({ action, input: params }))) {\n return fail(`The ${action} action was declined.`);\n }\n try {\n const result = await performActionDynamic(computer.desktop, action as ActionName, params);\n if (result.action === \"screenshot\" || result.action === \"zoom\") {\n return {\n content: [{ type: \"image\" as const, source: { type: \"base64\" as const, media_type: \"image/png\" as const, data: result.imageBase64 } }],\n isError: false,\n };\n }\n if (result.action === \"cursor_position\") {\n return { content: [{ type: \"text\" as const, text: `X=${result.x}, Y=${result.y}` }], isError: false };\n }\n return { content: [{ type: \"text\" as const, text: \"Done.\" }], isError: false };\n } catch (error) {\n return fail(error instanceof Error ? error.message : String(error));\n }\n },\n };\n}\n","/**\n * Claude computer-use over a MIOSA computer.\n *\n * `miosaComputerToolset(computer, { confirm })` is a `computer_toolset_20260801`\n * toolset: it subclasses Anthropic's `BetaAbstractComputerToolset20260801`, so\n * the SDK owns the model loop contract (one `tool_use` per member, the\n * `toolset_name` echo, stop at the first failure in a batch, the skipped-action\n * text and the approval gate). This file only drives the desktop.\n *\n * Needs the optional peer `@anthropic-ai/sdk` (0.133 or newer). Import it from\n * `@miosa/sdk/computer-use`.\n *\n * ```ts\n * import Anthropic from \"@anthropic-ai/sdk\";\n * import { miosaComputerToolset } from \"@miosa/sdk/computer-use\";\n *\n * const toolset = miosaComputerToolset(computer, {\n * confirm: async ({ member, input }) => member !== \"type\" || askHuman(input),\n * });\n * const runner = client.beta.messages.toolRunner({\n * model: \"claude-sonnet-5\",\n * max_tokens: 8192,\n * messages: [{ role: \"user\", content: \"Open the browser\" }],\n * tools: [toolset],\n * });\n * ```\n */\n\nimport {\n BetaAbstractComputerToolset20260801,\n ToolError,\n type BetaComputerConfirmCallable,\n type BetaComputerMemberResult,\n type BetaToolsetCallContext,\n} from \"@anthropic-ai/sdk/helpers/beta/toolsets\";\nimport type {\n BetaComputerDoubleClickInput,\n BetaComputerHoldKeyInput,\n BetaComputerKeyInput,\n BetaComputerLeftClickDragInput,\n BetaComputerLeftClickInput,\n BetaComputerMiddleClickInput,\n BetaComputerMouseMoveInput,\n BetaComputerRightClickInput,\n BetaComputerScrollInput,\n BetaComputerToolsetConfigs,\n BetaComputerTripleClickInput,\n BetaComputerTypeInput,\n BetaComputerWaitInput,\n BetaComputerZoomInput,\n} from \"@anthropic-ai/sdk/resources/beta\";\n\nimport type { Computer } from \"../resources/computer.js\";\nimport {\n InvalidActionInputError,\n performActionDynamic,\n type ActionName,\n type ActionResult,\n} from \"../resources/desktop-act.js\";\nimport { MiosaError } from \"../errors.js\";\n\n/** Members that type or press keys. Anthropic requires an approval callable for them. */\nconst NEEDS_CONFIRM = [\"type\", \"key\", \"hold_key\"] as const;\n\ntype Disabled = { enabled: false };\n\ninterface CommonOptions {\n /** Set `triple_click` on. It is two requests (click, then double-click) and needs a low-latency link. Default: off. */\n emulateTripleClick?: boolean;\n /** Entry-level fields such as `{ cache_control: { type: \"ephemeral\" } }`. */\n toolConfigs?: { cache_control?: { type: \"ephemeral\" } | null };\n}\n\n/**\n * Either pass `confirm`, or switch off `type`, `key` and `hold_key` in\n * `configs`. A toolset that can type with neither is refused, as in\n * Anthropic's own constructor.\n */\nexport type MiosaComputerToolsetOptions =\n | (CommonOptions & { confirm: BetaComputerConfirmCallable; configs?: BetaComputerToolsetConfigs })\n | (CommonOptions & {\n confirm?: undefined;\n configs: BetaComputerToolsetConfigs & { type: Disabled; key: Disabled; hold_key: Disabled };\n });\n\nfunction toToolError(error: unknown): ToolError {\n if (error instanceof ToolError) return error;\n if (error instanceof InvalidActionInputError) return new ToolError(error.message);\n if (error instanceof MiosaError) return new ToolError(`${error.code ?? \"ERROR\"}: ${error.message}`);\n return new ToolError(error instanceof Error ? error.message : String(error));\n}\n\n/** The desktop driver behind the toolset. */\nexport class MiosaComputerToolset extends BetaAbstractComputerToolset20260801 {\n constructor(\n private readonly computer: Computer,\n options: MiosaComputerToolsetOptions,\n ) {\n const configs: BetaComputerToolsetConfigs = { ...(options.configs ?? {}) };\n if (!options.emulateTripleClick && configs.triple_click === undefined) {\n configs.triple_click = { enabled: false };\n }\n super({\n configs,\n ...(options.confirm ? { confirm: options.confirm } : {}),\n ...(options.toolConfigs ? { toolConfigs: options.toolConfigs } : {}),\n });\n }\n\n private async act(action: ActionName, params: Record<string, unknown>): Promise<ActionResult> {\n try {\n return await performActionDynamic(this.computer.desktop, action, params);\n } catch (error) {\n throw toToolError(error);\n }\n }\n\n protected override async screenshot(): Promise<{ data: string; mediaType: \"image/png\" }> {\n const shot = await this.act(\"screenshot\", {});\n if (shot.action !== \"screenshot\") throw new ToolError(\"unexpected screenshot result\");\n return { data: shot.imageBase64, mediaType: \"image/png\" };\n }\n\n protected override async zoom(_ctx: BetaToolsetCallContext, input: BetaComputerZoomInput) {\n const shot = await this.act(\"zoom\", { region: input.region });\n if (shot.action !== \"zoom\") throw new ToolError(\"unexpected zoom result\");\n return { data: shot.imageBase64, mediaType: \"image/png\" as const };\n }\n\n protected override async cursor_position(): Promise<{ x: number; y: number }> {\n const at = await this.act(\"cursor_position\", {});\n if (at.action !== \"cursor_position\") throw new ToolError(\"unexpected cursor result\");\n return { x: at.x, y: at.y };\n }\n\n protected override async mouse_move(_ctx: BetaToolsetCallContext, input: BetaComputerMouseMoveInput): Promise<void> {\n await this.act(\"mouse_move\", { coordinate: input.coordinate });\n }\n\n protected override async left_mouse_down(): Promise<void> {\n await this.act(\"left_mouse_down\", {});\n }\n\n protected override async left_mouse_up(): Promise<void> {\n await this.act(\"left_mouse_up\", {});\n }\n\n protected override async left_click(_ctx: BetaToolsetCallContext, input: BetaComputerLeftClickInput): Promise<void> {\n await this.act(\"left_click\", clean(input));\n }\n\n protected override async right_click(_ctx: BetaToolsetCallContext, input: BetaComputerRightClickInput): Promise<void> {\n await this.act(\"right_click\", clean(input));\n }\n\n protected override async middle_click(_ctx: BetaToolsetCallContext, input: BetaComputerMiddleClickInput): Promise<void> {\n await this.act(\"middle_click\", clean(input));\n }\n\n protected override async double_click(_ctx: BetaToolsetCallContext, input: BetaComputerDoubleClickInput): Promise<void> {\n await this.act(\"double_click\", clean(input));\n }\n\n protected override async triple_click(_ctx: BetaToolsetCallContext, input: BetaComputerTripleClickInput): Promise<void> {\n await this.act(\"triple_click\", clean(input));\n }\n\n protected override async left_click_drag(_ctx: BetaToolsetCallContext, input: BetaComputerLeftClickDragInput): Promise<void> {\n await this.act(\"left_click_drag\", clean(input));\n }\n\n protected override async scroll(_ctx: BetaToolsetCallContext, input: BetaComputerScrollInput): Promise<void> {\n await this.act(\"scroll\", clean(input));\n }\n\n protected override async type_(_ctx: BetaToolsetCallContext, input: BetaComputerTypeInput): Promise<void> {\n await this.act(\"type\", clean(input));\n }\n\n protected override async key(_ctx: BetaToolsetCallContext, input: BetaComputerKeyInput): Promise<void> {\n await this.act(\"key\", clean(input));\n }\n\n protected override async hold_key(_ctx: BetaToolsetCallContext, input: BetaComputerHoldKeyInput): Promise<void> {\n await this.act(\"hold_key\", clean(input));\n }\n\n protected override async wait(_ctx: BetaToolsetCallContext, input: BetaComputerWaitInput): Promise<void> {\n await this.act(\"wait\", clean(input));\n }\n}\n\n/** Drop `null` fields: the API sends `null` for an omitted optional input. */\nfunction clean(input: object): Record<string, unknown> {\n return Object.fromEntries(Object.entries(input).filter(([, value]) => value !== null && value !== undefined));\n}\n\n/**\n * Build the toolset for one computer. `confirm` is required unless `type`,\n * `key` and `hold_key` are switched off in `configs`.\n */\nexport function miosaComputerToolset(computer: Computer, options: MiosaComputerToolsetOptions): MiosaComputerToolset {\n const confirmMissing = options.confirm === undefined;\n if (confirmMissing) {\n for (const member of NEEDS_CONFIRM) {\n const config = (options.configs ?? {})[member];\n if (config?.enabled !== false) {\n throw new MiosaError(\n `${member} needs a confirm callable: pass confirm, or disable ${NEEDS_CONFIRM.join(\", \")} in configs`,\n 0,\n \"CONFIRM_REQUIRED\",\n { member },\n undefined,\n false,\n );\n }\n }\n }\n return new MiosaComputerToolset(computer, options);\n}\n\nexport type { BetaComputerMemberResult };\nexport { ToolError };\n\nexport {\n LEGACY_ACTIONS,\n LEGACY_BETA_HEADERS,\n miosaComputerToolLegacy,\n type LegacyComputerTool,\n type LegacyComputerToolOptions,\n type LegacyComputerToolVersion,\n type LegacyToolResultContent,\n} from \"./legacy.js\";\n"]}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { eH as Miosa } from '../client-C_uXhex9.js';
|
|
2
|
+
import { c$ as ComputerEvent, be as MachineCommandOptions, bf as MachineCommandResult, bR as RunActivity, cT as WaitOptions, D as Computer, c8 as RunWaitOptions, bQ as Run, cS as WaitIdleOptions } from '../computer-CKDK0Ahy.js';
|
|
3
|
+
import 'ws';
|
|
4
|
+
import 'node:events';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* One import for the things every agent loop reaches for, keyed by computer id:
|
|
8
|
+
*
|
|
9
|
+
* ```ts
|
|
10
|
+
* import { waitUntilReady, execCommand, stopAndRemove } from "@miosa/sdk/helpers";
|
|
11
|
+
* ```
|
|
12
|
+
*
|
|
13
|
+
* | Helper | Does |
|
|
14
|
+
* |---|---|
|
|
15
|
+
* | `waitUntilReady` | poll until the computer is `active` or `running` |
|
|
16
|
+
* | `waitForDesktop` | ready, and the desktop answers |
|
|
17
|
+
* | `waitUntilIdle` | the screen stopped changing |
|
|
18
|
+
* | `waitForPrompt` | wait for an agent run to finish |
|
|
19
|
+
* | `streamPrompt` | follow an agent run's activity |
|
|
20
|
+
* | `streamEvents` | follow in-VM events (window, file, process, clipboard, idle) |
|
|
21
|
+
* | `streamCommand` | run a command and follow its output |
|
|
22
|
+
* | `execCommand` | run a command and get the result |
|
|
23
|
+
* | `readText` / `writeText` | UTF-8 files |
|
|
24
|
+
* | `stopAndRemove` | stop, then destroy; safe to call twice |
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
/** Poll until the computer is ready. Throws `COMPUTER_NOT_READY` if it errors, `COMPUTER_READY_TIMEOUT` (retryable) if it is slow. */
|
|
28
|
+
declare function waitUntilReady(miosa: Miosa, computerId: string, options?: WaitOptions): Promise<Computer>;
|
|
29
|
+
/** Wait until the computer is ready and `GET /desktop/screen-size` answers. */
|
|
30
|
+
declare function waitForDesktop(miosa: Miosa, computerId: string, options?: WaitOptions): Promise<Computer>;
|
|
31
|
+
/** Wait until two screenshots `quietMs` apart match (default 1000 ms). Throws `DESKTOP_IDLE_TIMEOUT` (retryable). */
|
|
32
|
+
declare function waitUntilIdle(miosa: Miosa, computerId: string, options?: WaitIdleOptions): Promise<void>;
|
|
33
|
+
/** Wait for an agent run to reach a terminal status. */
|
|
34
|
+
declare function waitForPrompt(miosa: Miosa, runId: string, options?: RunWaitOptions): Promise<Run>;
|
|
35
|
+
/** Follow an agent run's activity (`GET /runs/:id/activity`). */
|
|
36
|
+
declare function streamPrompt(miosa: Miosa, runId: string): AsyncIterableIterator<RunActivity>;
|
|
37
|
+
type StreamedEvent = {
|
|
38
|
+
type: ComputerEvent["type"];
|
|
39
|
+
payload: ComputerEvent["payload"];
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Follow in-VM events as an async iterator. Breaking out of the loop (or an
|
|
43
|
+
* abort) closes the WebSocket. Needs the optional `ws` package on Node.
|
|
44
|
+
*/
|
|
45
|
+
declare function streamEvents(miosa: Miosa, computerId: string, options: {
|
|
46
|
+
subscribe: Array<"window" | "clipboard" | "file" | "process" | "idle">;
|
|
47
|
+
paths?: string[];
|
|
48
|
+
idleThresholdSec?: number;
|
|
49
|
+
signal?: AbortSignal;
|
|
50
|
+
}): AsyncGenerator<StreamedEvent>;
|
|
51
|
+
type CommandChunk = {
|
|
52
|
+
stream: "stdout" | "stderr";
|
|
53
|
+
data: Uint8Array;
|
|
54
|
+
} | {
|
|
55
|
+
stream: "exit";
|
|
56
|
+
code: number;
|
|
57
|
+
};
|
|
58
|
+
/** Run a command and follow its output; the last item is `{ stream: "exit", code }`. */
|
|
59
|
+
declare function streamCommand(miosa: Miosa, computerId: string, command: string, options?: {
|
|
60
|
+
args?: string[];
|
|
61
|
+
cwd?: string;
|
|
62
|
+
env?: string[];
|
|
63
|
+
signal?: AbortSignal;
|
|
64
|
+
}): AsyncGenerator<CommandChunk>;
|
|
65
|
+
/** Run a command and wait for it (`POST /computers/:id/commands`, up to 600 seconds). */
|
|
66
|
+
declare function execCommand(miosa: Miosa, computerId: string, command: string, options?: MachineCommandOptions): Promise<MachineCommandResult>;
|
|
67
|
+
/** Read a UTF-8 file from the computer. */
|
|
68
|
+
declare function readText(miosa: Miosa, computerId: string, path: string): Promise<string>;
|
|
69
|
+
/** Write a UTF-8 file to the computer. */
|
|
70
|
+
declare function writeText(miosa: Miosa, computerId: string, path: string, content: string): Promise<void>;
|
|
71
|
+
/**
|
|
72
|
+
* Stop the computer and destroy it. A computer that is already stopped, or
|
|
73
|
+
* already gone, is not an error, so calling this twice is safe.
|
|
74
|
+
*/
|
|
75
|
+
declare function stopAndRemove(miosa: Miosa, computerId: string): Promise<void>;
|
|
76
|
+
|
|
77
|
+
export { type CommandChunk, type StreamedEvent, WaitIdleOptions, WaitOptions, execCommand, readText, stopAndRemove, streamCommand, streamEvents, streamPrompt, waitForDesktop, waitForPrompt, waitUntilIdle, waitUntilReady, writeText };
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { NotFoundError } from '../chunk-BMWUKYWU.js';
|
|
2
|
+
|
|
3
|
+
// src/helpers/index.ts
|
|
4
|
+
async function waitUntilReady(miosa, computerId, options = {}) {
|
|
5
|
+
return (await miosa.computers.get(computerId)).waitUntilReady(options);
|
|
6
|
+
}
|
|
7
|
+
async function waitForDesktop(miosa, computerId, options = {}) {
|
|
8
|
+
return (await miosa.computers.get(computerId)).waitForDesktop(options);
|
|
9
|
+
}
|
|
10
|
+
async function waitUntilIdle(miosa, computerId, options = {}) {
|
|
11
|
+
return (await miosa.computers.get(computerId)).waitUntilIdle(options);
|
|
12
|
+
}
|
|
13
|
+
function waitForPrompt(miosa, runId, options = {}) {
|
|
14
|
+
return miosa.runs.waitForCompletion(runId, options);
|
|
15
|
+
}
|
|
16
|
+
function streamPrompt(miosa, runId) {
|
|
17
|
+
return miosa.runs.streamActivity(runId);
|
|
18
|
+
}
|
|
19
|
+
async function* streamEvents(miosa, computerId, options) {
|
|
20
|
+
const computer = await miosa.computers.get(computerId);
|
|
21
|
+
const { signal, ...subscription } = options;
|
|
22
|
+
const stream = computer.events.subscribe(subscription);
|
|
23
|
+
const queue = [];
|
|
24
|
+
let failure;
|
|
25
|
+
let done = false;
|
|
26
|
+
let wake;
|
|
27
|
+
const notify = () => {
|
|
28
|
+
wake?.();
|
|
29
|
+
wake = void 0;
|
|
30
|
+
};
|
|
31
|
+
const emit = stream.emit.bind(stream);
|
|
32
|
+
stream.emit = (type, ...args) => {
|
|
33
|
+
if (type === "error") failure = args[0] instanceof Error ? args[0] : new Error(String(args[0]));
|
|
34
|
+
else if (type === "close") done = true;
|
|
35
|
+
else queue.push({ type, payload: args[0] });
|
|
36
|
+
notify();
|
|
37
|
+
return emit(type, ...args);
|
|
38
|
+
};
|
|
39
|
+
signal?.addEventListener("abort", () => {
|
|
40
|
+
done = true;
|
|
41
|
+
notify();
|
|
42
|
+
});
|
|
43
|
+
try {
|
|
44
|
+
for (; ; ) {
|
|
45
|
+
const next = queue.shift();
|
|
46
|
+
if (next) {
|
|
47
|
+
yield next;
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
if (failure) throw failure;
|
|
51
|
+
if (done) return;
|
|
52
|
+
await new Promise((resolve) => {
|
|
53
|
+
wake = resolve;
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
} finally {
|
|
57
|
+
await stream.close();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
async function* streamCommand(miosa, computerId, command, options = {}) {
|
|
61
|
+
const computer = await miosa.computers.get(computerId);
|
|
62
|
+
const { signal, ...rest } = options;
|
|
63
|
+
const handle = computer.exec.stream({ command, ...rest });
|
|
64
|
+
const queue = [];
|
|
65
|
+
let failure;
|
|
66
|
+
let done = false;
|
|
67
|
+
let wake;
|
|
68
|
+
const notify = () => {
|
|
69
|
+
wake?.();
|
|
70
|
+
wake = void 0;
|
|
71
|
+
};
|
|
72
|
+
handle.on("stdout", (data) => {
|
|
73
|
+
queue.push({ stream: "stdout", data });
|
|
74
|
+
notify();
|
|
75
|
+
});
|
|
76
|
+
handle.on("stderr", (data) => {
|
|
77
|
+
queue.push({ stream: "stderr", data });
|
|
78
|
+
notify();
|
|
79
|
+
});
|
|
80
|
+
handle.on("exit", (code) => {
|
|
81
|
+
queue.push({ stream: "exit", code });
|
|
82
|
+
done = true;
|
|
83
|
+
notify();
|
|
84
|
+
});
|
|
85
|
+
handle.on("error", (error) => {
|
|
86
|
+
failure = error;
|
|
87
|
+
notify();
|
|
88
|
+
});
|
|
89
|
+
handle.on("close", () => {
|
|
90
|
+
done = true;
|
|
91
|
+
notify();
|
|
92
|
+
});
|
|
93
|
+
signal?.addEventListener("abort", () => {
|
|
94
|
+
done = true;
|
|
95
|
+
notify();
|
|
96
|
+
});
|
|
97
|
+
try {
|
|
98
|
+
for (; ; ) {
|
|
99
|
+
const next = queue.shift();
|
|
100
|
+
if (next) {
|
|
101
|
+
yield next;
|
|
102
|
+
if (next.stream === "exit") return;
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
if (failure) throw failure;
|
|
106
|
+
if (done) return;
|
|
107
|
+
await new Promise((resolve) => {
|
|
108
|
+
wake = resolve;
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
} finally {
|
|
112
|
+
await handle.close();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
async function execCommand(miosa, computerId, command, options = {}) {
|
|
116
|
+
const computer = await miosa.computers.get(computerId);
|
|
117
|
+
return computer.runCommand(command, options);
|
|
118
|
+
}
|
|
119
|
+
async function readText(miosa, computerId, path) {
|
|
120
|
+
const computer = await miosa.computers.get(computerId);
|
|
121
|
+
return computer.files.readFile(path);
|
|
122
|
+
}
|
|
123
|
+
async function writeText(miosa, computerId, path, content) {
|
|
124
|
+
const computer = await miosa.computers.get(computerId);
|
|
125
|
+
await computer.files.writeFile(path, content);
|
|
126
|
+
}
|
|
127
|
+
async function stopAndRemove(miosa, computerId) {
|
|
128
|
+
let computer;
|
|
129
|
+
try {
|
|
130
|
+
computer = await miosa.computers.get(computerId);
|
|
131
|
+
} catch (error) {
|
|
132
|
+
if (error instanceof NotFoundError) return;
|
|
133
|
+
throw error;
|
|
134
|
+
}
|
|
135
|
+
if (computer.status !== "stopped" && computer.status !== "destroyed") {
|
|
136
|
+
try {
|
|
137
|
+
await computer.stop();
|
|
138
|
+
} catch (error) {
|
|
139
|
+
if (error instanceof NotFoundError) return;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
try {
|
|
143
|
+
await computer.destroy();
|
|
144
|
+
} catch (error) {
|
|
145
|
+
if (!(error instanceof NotFoundError)) throw error;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export { execCommand, readText, stopAndRemove, streamCommand, streamEvents, streamPrompt, waitForDesktop, waitForPrompt, waitUntilIdle, waitUntilReady, writeText };
|
|
150
|
+
//# sourceMappingURL=index.js.map
|
|
151
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/helpers/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * One import for the things every agent loop reaches for, keyed by computer id:\n *\n * ```ts\n * import { waitUntilReady, execCommand, stopAndRemove } from \"@miosa/sdk/helpers\";\n * ```\n *\n * | Helper | Does |\n * |---|---|\n * | `waitUntilReady` | poll until the computer is `active` or `running` |\n * | `waitForDesktop` | ready, and the desktop answers |\n * | `waitUntilIdle` | the screen stopped changing |\n * | `waitForPrompt` | wait for an agent run to finish |\n * | `streamPrompt` | follow an agent run's activity |\n * | `streamEvents` | follow in-VM events (window, file, process, clipboard, idle) |\n * | `streamCommand` | run a command and follow its output |\n * | `execCommand` | run a command and get the result |\n * | `readText` / `writeText` | UTF-8 files |\n * | `stopAndRemove` | stop, then destroy; safe to call twice |\n */\n\nimport { NotFoundError } from \"../errors.js\";\nimport type { Miosa } from \"../client.js\";\nimport type { Computer } from \"../resources/computer.js\";\nimport type { WaitIdleOptions, WaitOptions } from \"../resources/computer-agent.js\";\nimport type { ComputerEvent } from \"../resources/events.js\";\nimport type { MachineCommandOptions, MachineCommandResult } from \"../resources/machine-common.js\";\nimport type { Run, RunActivity, RunWaitOptions } from \"../resources/runs.js\";\n\nexport type { WaitIdleOptions, WaitOptions };\n\n// The polling lives on the Computer (src/resources/computer-agent.ts). These\n// look the computer up by id and delegate, so there is one implementation.\n\n/** Poll until the computer is ready. Throws `COMPUTER_NOT_READY` if it errors, `COMPUTER_READY_TIMEOUT` (retryable) if it is slow. */\nexport async function waitUntilReady(miosa: Miosa, computerId: string, options: WaitOptions = {}): Promise<Computer> {\n return (await miosa.computers.get(computerId)).waitUntilReady(options);\n}\n\n/** Wait until the computer is ready and `GET /desktop/screen-size` answers. */\nexport async function waitForDesktop(miosa: Miosa, computerId: string, options: WaitOptions = {}): Promise<Computer> {\n return (await miosa.computers.get(computerId)).waitForDesktop(options);\n}\n\n/** Wait until two screenshots `quietMs` apart match (default 1000 ms). Throws `DESKTOP_IDLE_TIMEOUT` (retryable). */\nexport async function waitUntilIdle(miosa: Miosa, computerId: string, options: WaitIdleOptions = {}): Promise<void> {\n return (await miosa.computers.get(computerId)).waitUntilIdle(options);\n}\n\n/** Wait for an agent run to reach a terminal status. */\nexport function waitForPrompt(miosa: Miosa, runId: string, options: RunWaitOptions = {}): Promise<Run> {\n return miosa.runs.waitForCompletion(runId, options);\n}\n\n/** Follow an agent run's activity (`GET /runs/:id/activity`). */\nexport function streamPrompt(miosa: Miosa, runId: string): AsyncIterableIterator<RunActivity> {\n return miosa.runs.streamActivity(runId);\n}\n\nexport type StreamedEvent = { type: ComputerEvent[\"type\"]; payload: ComputerEvent[\"payload\"] };\n\n/**\n * Follow in-VM events as an async iterator. Breaking out of the loop (or an\n * abort) closes the WebSocket. Needs the optional `ws` package on Node.\n */\nexport async function* streamEvents(\n miosa: Miosa,\n computerId: string,\n options: { subscribe: Array<\"window\" | \"clipboard\" | \"file\" | \"process\" | \"idle\">; paths?: string[]; idleThresholdSec?: number; signal?: AbortSignal },\n): AsyncGenerator<StreamedEvent> {\n const computer = await miosa.computers.get(computerId);\n const { signal, ...subscription } = options;\n const stream = computer.events.subscribe(subscription);\n const queue: StreamedEvent[] = [];\n let failure: Error | undefined;\n let done = false;\n let wake: (() => void) | undefined;\n const notify = (): void => {\n wake?.();\n wake = undefined;\n };\n\n // The stream emits one event name per type; tap `emit` to see them all.\n const emit = stream.emit.bind(stream) as (type: string, ...args: unknown[]) => boolean;\n (stream as unknown as { emit: typeof emit }).emit = (type: string, ...args: unknown[]): boolean => {\n if (type === \"error\") failure = args[0] instanceof Error ? args[0] : new Error(String(args[0]));\n else if (type === \"close\") done = true;\n else queue.push({ type: type as StreamedEvent[\"type\"], payload: args[0] as StreamedEvent[\"payload\"] });\n notify();\n return emit(type, ...args);\n };\n signal?.addEventListener(\"abort\", () => {\n done = true;\n notify();\n });\n\n try {\n for (;;) {\n const next = queue.shift();\n if (next) {\n yield next;\n continue;\n }\n if (failure) throw failure;\n if (done) return;\n await new Promise<void>((resolve) => {\n wake = resolve;\n });\n }\n } finally {\n await stream.close();\n }\n}\n\nexport type CommandChunk =\n | { stream: \"stdout\" | \"stderr\"; data: Uint8Array }\n | { stream: \"exit\"; code: number };\n\n/** Run a command and follow its output; the last item is `{ stream: \"exit\", code }`. */\nexport async function* streamCommand(\n miosa: Miosa,\n computerId: string,\n command: string,\n options: { args?: string[]; cwd?: string; env?: string[]; signal?: AbortSignal } = {},\n): AsyncGenerator<CommandChunk> {\n const computer = await miosa.computers.get(computerId);\n const { signal, ...rest } = options;\n const handle = computer.exec.stream({ command, ...rest });\n const queue: CommandChunk[] = [];\n let failure: Error | undefined;\n let done = false;\n let wake: (() => void) | undefined;\n const notify = (): void => {\n wake?.();\n wake = undefined;\n };\n handle.on(\"stdout\", (data) => {\n queue.push({ stream: \"stdout\", data });\n notify();\n });\n handle.on(\"stderr\", (data) => {\n queue.push({ stream: \"stderr\", data });\n notify();\n });\n handle.on(\"exit\", (code) => {\n queue.push({ stream: \"exit\", code });\n done = true;\n notify();\n });\n handle.on(\"error\", (error) => {\n failure = error;\n notify();\n });\n handle.on(\"close\", () => {\n done = true;\n notify();\n });\n signal?.addEventListener(\"abort\", () => {\n done = true;\n notify();\n });\n try {\n for (;;) {\n const next = queue.shift();\n if (next) {\n yield next;\n if (next.stream === \"exit\") return;\n continue;\n }\n if (failure) throw failure;\n if (done) return;\n await new Promise<void>((resolve) => {\n wake = resolve;\n });\n }\n } finally {\n await handle.close();\n }\n}\n\n/** Run a command and wait for it (`POST /computers/:id/commands`, up to 600 seconds). */\nexport async function execCommand(\n miosa: Miosa,\n computerId: string,\n command: string,\n options: MachineCommandOptions = {},\n): Promise<MachineCommandResult> {\n const computer = await miosa.computers.get(computerId);\n return computer.runCommand(command, options);\n}\n\n/** Read a UTF-8 file from the computer. */\nexport async function readText(miosa: Miosa, computerId: string, path: string): Promise<string> {\n const computer = await miosa.computers.get(computerId);\n return computer.files.readFile(path);\n}\n\n/** Write a UTF-8 file to the computer. */\nexport async function writeText(miosa: Miosa, computerId: string, path: string, content: string): Promise<void> {\n const computer = await miosa.computers.get(computerId);\n await computer.files.writeFile(path, content);\n}\n\n/**\n * Stop the computer and destroy it. A computer that is already stopped, or\n * already gone, is not an error, so calling this twice is safe.\n */\nexport async function stopAndRemove(miosa: Miosa, computerId: string): Promise<void> {\n let computer: Computer;\n try {\n computer = await miosa.computers.get(computerId);\n } catch (error) {\n if (error instanceof NotFoundError) return;\n throw error;\n }\n if (computer.status !== \"stopped\" && computer.status !== \"destroyed\") {\n try {\n await computer.stop();\n } catch (error) {\n if (error instanceof NotFoundError) return;\n // A computer that cannot stop (already stopping) is still destroyed below.\n }\n }\n try {\n await computer.destroy();\n } catch (error) {\n if (!(error instanceof NotFoundError)) throw error;\n }\n}\n"]}
|