@miosa/sdk 1.2.5 → 1.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/README.md +107 -59
  2. package/dist/index.d.ts +513 -193
  3. package/dist/index.js +1266 -891
  4. package/dist/index.js.map +1 -1
  5. package/package.json +1 -2
  6. package/src/client.ts +0 -293
  7. package/src/errors.ts +0 -136
  8. package/src/http.test.ts +0 -374
  9. package/src/http.ts +0 -390
  10. package/src/index.ts +0 -569
  11. package/src/resources/admin.ts +0 -348
  12. package/src/resources/analytics.ts +0 -60
  13. package/src/resources/api-keys.ts +0 -119
  14. package/src/resources/audit-log.ts +0 -64
  15. package/src/resources/benchmarks.ts +0 -104
  16. package/src/resources/builder-sessions.ts +0 -75
  17. package/src/resources/channels.ts +0 -143
  18. package/src/resources/checkpoints.ts +0 -225
  19. package/src/resources/command-center.ts +0 -73
  20. package/src/resources/community.ts +0 -103
  21. package/src/resources/completions.ts +0 -104
  22. package/src/resources/computer-auto-stop.ts +0 -43
  23. package/src/resources/computer-env.ts +0 -76
  24. package/src/resources/computer-logs.ts +0 -50
  25. package/src/resources/computer-osa.ts +0 -76
  26. package/src/resources/computer-ports.ts +0 -91
  27. package/src/resources/computer-terminal.ts +0 -61
  28. package/src/resources/computer-volumes.ts +0 -64
  29. package/src/resources/computer.ts +0 -551
  30. package/src/resources/computers.ts +0 -75
  31. package/src/resources/credits.ts +0 -43
  32. package/src/resources/cron-jobs.ts +0 -191
  33. package/src/resources/custom_domains.ts +0 -123
  34. package/src/resources/dashboard.ts +0 -49
  35. package/src/resources/databases.ts +0 -218
  36. package/src/resources/deployments.test.ts +0 -197
  37. package/src/resources/deployments.ts +0 -1208
  38. package/src/resources/desktop.ts +0 -134
  39. package/src/resources/devices.test.ts +0 -92
  40. package/src/resources/devices.ts +0 -291
  41. package/src/resources/egress.test.ts +0 -318
  42. package/src/resources/egressAudit.ts +0 -245
  43. package/src/resources/egressNetwork.ts +0 -450
  44. package/src/resources/egressSecrets.ts +0 -577
  45. package/src/resources/email.ts +0 -212
  46. package/src/resources/embeddings.ts +0 -36
  47. package/src/resources/events.ts +0 -296
  48. package/src/resources/exec.ts +0 -319
  49. package/src/resources/external-keys.ts +0 -79
  50. package/src/resources/files.test.ts +0 -339
  51. package/src/resources/files.ts +0 -220
  52. package/src/resources/flat-custom-domains.ts +0 -127
  53. package/src/resources/functions.ts +0 -178
  54. package/src/resources/health-checks.ts +0 -165
  55. package/src/resources/integrations.ts +0 -183
  56. package/src/resources/mcp.ts +0 -70
  57. package/src/resources/models.ts +0 -45
  58. package/src/resources/network_policy.ts +0 -73
  59. package/src/resources/open-computers/agents.ts +0 -91
  60. package/src/resources/open-computers/apps.ts +0 -102
  61. package/src/resources/open-computers/clusters.ts +0 -88
  62. package/src/resources/open-computers/desktop.ts +0 -34
  63. package/src/resources/open-computers/files.ts +0 -97
  64. package/src/resources/open-computers/hosts.ts +0 -85
  65. package/src/resources/open-computers/index.ts +0 -98
  66. package/src/resources/open-computers/jobs.ts +0 -75
  67. package/src/resources/open-computers/open_computers.test.ts +0 -288
  68. package/src/resources/open-computers/secrets.ts +0 -115
  69. package/src/resources/open-computers/terminal.ts +0 -33
  70. package/src/resources/open-computers/tunnels.ts +0 -87
  71. package/src/resources/open-computers/types.ts +0 -343
  72. package/src/resources/open-computers/workspaces.ts +0 -135
  73. package/src/resources/org-invites.ts +0 -189
  74. package/src/resources/project-auth.ts +0 -142
  75. package/src/resources/project-integrations.ts +0 -133
  76. package/src/resources/provider-defaults.ts +0 -89
  77. package/src/resources/regions.ts +0 -94
  78. package/src/resources/sandbox-templates.ts +0 -195
  79. package/src/resources/sandboxes.live.test.ts +0 -92
  80. package/src/resources/sandboxes.test.ts +0 -655
  81. package/src/resources/sandboxes.ts +0 -1437
  82. package/src/resources/settings.ts +0 -143
  83. package/src/resources/snapshots-standalone.ts +0 -51
  84. package/src/resources/storage.ts +0 -221
  85. package/src/resources/tenant.ts +0 -66
  86. package/src/resources/usage.ts +0 -85
  87. package/src/resources/volumes.ts +0 -117
  88. package/src/resources/webhooks.ts +0 -239
  89. package/src/resources/workspace-invites.ts +0 -188
  90. package/src/resources/workspace-members.test.ts +0 -121
  91. package/src/resources/workspace-members.ts +0 -143
  92. package/src/types.ts +0 -463
@@ -1,134 +0,0 @@
1
- import { HttpClient } from "../http.js";
2
- import type {
3
- ClickParams,
4
- CursorInfo,
5
- DesktopActionResult,
6
- DoubleClickParams,
7
- DragParams,
8
- KeyParams,
9
- LaunchParams,
10
- ScrollParams,
11
- TypeParams,
12
- WaitParams,
13
- WindowFocusParams,
14
- WindowInfo,
15
- } from "../types.js";
16
-
17
- export class Desktop {
18
- private readonly http: HttpClient;
19
- private readonly computerId: string;
20
-
21
- constructor(http: HttpClient, computerId: string) {
22
- this.http = http;
23
- this.computerId = computerId;
24
- }
25
-
26
- private base(): string {
27
- return `/computers/${this.computerId}/desktop`;
28
- }
29
-
30
- /** Capture a screenshot of the desktop. Returns raw PNG bytes. */
31
- async screenshot(): Promise<Uint8Array> {
32
- return this.http.getBinary(`${this.base()}/screenshot`);
33
- }
34
-
35
- /** Click at the given coordinates. */
36
- async click(
37
- x: number,
38
- y: number,
39
- button: ClickParams["button"] = "left",
40
- ): Promise<DesktopActionResult> {
41
- return this.http.post<DesktopActionResult>(`${this.base()}/click`, {
42
- x,
43
- y,
44
- button,
45
- });
46
- }
47
-
48
- /** Double-click at the given coordinates. */
49
- async doubleClick(x: number, y: number): Promise<DesktopActionResult> {
50
- const params: DoubleClickParams = { x, y };
51
- return this.http.post<DesktopActionResult>(
52
- `${this.base()}/double-click`,
53
- params,
54
- );
55
- }
56
-
57
- /** Type text into the currently focused element. */
58
- async type(text: string, delay?: number): Promise<DesktopActionResult> {
59
- const params: TypeParams = { text, ...(delay !== undefined && { delay }) };
60
- return this.http.post<DesktopActionResult>(`${this.base()}/type`, params);
61
- }
62
-
63
- /** Send a key or key combination (e.g. "Enter", "ctrl+c"). */
64
- async key(key: string): Promise<DesktopActionResult> {
65
- const params: KeyParams = { key };
66
- return this.http.post<DesktopActionResult>(`${this.base()}/key`, params);
67
- }
68
-
69
- /** Scroll in a direction at an optional position. */
70
- async scroll(
71
- direction: ScrollParams["direction"],
72
- clicks: number = 3,
73
- x?: number,
74
- y?: number,
75
- ): Promise<DesktopActionResult> {
76
- const params: ScrollParams = {
77
- direction,
78
- clicks,
79
- ...(x !== undefined && { x }),
80
- ...(y !== undefined && { y }),
81
- };
82
- return this.http.post<DesktopActionResult>(`${this.base()}/scroll`, params);
83
- }
84
-
85
- /** Click and drag from one coordinate to another. */
86
- async drag(
87
- fromX: number,
88
- fromY: number,
89
- toX: number,
90
- toY: number,
91
- ): Promise<DesktopActionResult> {
92
- const params: DragParams = {
93
- from_x: fromX,
94
- from_y: fromY,
95
- to_x: toX,
96
- to_y: toY,
97
- };
98
- return this.http.post<DesktopActionResult>(`${this.base()}/drag`, params);
99
- }
100
-
101
- /** Wait for the given number of seconds. */
102
- async wait(seconds: number): Promise<DesktopActionResult> {
103
- const params: WaitParams = { seconds };
104
- return this.http.post<DesktopActionResult>(`${this.base()}/wait`, params);
105
- }
106
-
107
- /** List all open windows on the desktop. */
108
- async windows(): Promise<WindowInfo[]> {
109
- const result = await this.http.get<{ windows: WindowInfo[] }>(
110
- `${this.base()}/windows`,
111
- );
112
- return result.windows;
113
- }
114
-
115
- /** Get the current cursor position. */
116
- async cursor(): Promise<CursorInfo> {
117
- return this.http.get<CursorInfo>(`${this.base()}/cursor`);
118
- }
119
-
120
- /** Bring the given window into focus. */
121
- async focusWindow(windowId: string): Promise<DesktopActionResult> {
122
- const params: WindowFocusParams = { window_id: windowId };
123
- return this.http.post<DesktopActionResult>(
124
- `${this.base()}/window/focus`,
125
- params,
126
- );
127
- }
128
-
129
- /** Launch an application by name. */
130
- async launch(appName: string): Promise<DesktopActionResult> {
131
- const params: LaunchParams = { app_name: appName };
132
- return this.http.post<DesktopActionResult>(`${this.base()}/launch`, params);
133
- }
134
- }
@@ -1,92 +0,0 @@
1
- import { beforeEach, describe, expect, it, vi } from "vitest";
2
- import { HttpClient } from "../http.js";
3
- import { Devices } from "./devices.js";
4
-
5
- const mockGet = vi.fn();
6
-
7
- function makeHttp(): HttpClient {
8
- const http = {} as HttpClient;
9
- http.get = mockGet;
10
- return http;
11
- }
12
-
13
- beforeEach(() => {
14
- vi.clearAllMocks();
15
- });
16
-
17
- describe("Devices", () => {
18
- it("returns the static agent device catalog", () => {
19
- const catalog = new Devices(makeHttp()).catalog();
20
-
21
- expect(catalog.map((device) => device.kind)).toEqual(
22
- expect.arrayContaining([
23
- "sandbox_worker",
24
- "computer",
25
- "local_device",
26
- "docker_deploy_host",
27
- ]),
28
- );
29
- expect(catalog.find((device) => device.kind === "sandbox_worker")
30
- ?.primaryCommands).toEqual(
31
- expect.arrayContaining([
32
- expect.stringContaining("sandboxes.create"),
33
- expect.stringContaining("sandbox.exec"),
34
- ]),
35
- );
36
- });
37
-
38
- it("normalizes sandboxes and computers into one device list", async () => {
39
- mockGet
40
- .mockResolvedValueOnce({
41
- data: [
42
- {
43
- id: "sbx_123",
44
- name: "builder",
45
- state: "running",
46
- ready: true,
47
- persistent: true,
48
- preview_url: "https://3000-sbx_123.sandbox.miosa.app",
49
- },
50
- ],
51
- })
52
- .mockResolvedValueOnce({
53
- data: [
54
- {
55
- id: "cmp_123",
56
- name: "desktop",
57
- status: "running",
58
- region: "us-nyc",
59
- },
60
- ],
61
- });
62
-
63
- const result = await new Devices(makeHttp()).list();
64
-
65
- expect(mockGet).toHaveBeenNthCalledWith(1, "/sandboxes");
66
- expect(mockGet).toHaveBeenNthCalledWith(2, "/computers");
67
- expect(result.errors).toEqual([]);
68
- expect(result.devices).toEqual(
69
- expect.arrayContaining([
70
- expect.objectContaining({ id: "sbx_123", kind: "sandbox_worker" }),
71
- expect.objectContaining({ id: "cmp_123", kind: "computer" }),
72
- ]),
73
- );
74
- });
75
-
76
- it("returns partial device inventory when one backing endpoint fails", async () => {
77
- mockGet
78
- .mockResolvedValueOnce({
79
- data: [{ id: "sbx_123", state: "running" }],
80
- })
81
- .mockRejectedValueOnce(new Error("HTTP 502"));
82
-
83
- const result = await new Devices(makeHttp()).list();
84
-
85
- expect(result.devices).toEqual([
86
- expect.objectContaining({ id: "sbx_123", kind: "sandbox_worker" }),
87
- ]);
88
- expect(result.errors).toEqual([
89
- expect.objectContaining({ source: "computers", retryable: true }),
90
- ]);
91
- });
92
- });
@@ -1,291 +0,0 @@
1
- import { HttpClient } from "../http.js";
2
-
3
- export type DeviceKind =
4
- | "sandbox_worker"
5
- | "computer"
6
- | "local_device"
7
- | "docker_deploy_host";
8
-
9
- export type DeviceSource = "sandboxes" | "computers";
10
-
11
- export interface DeviceCatalogEntry {
12
- kind: DeviceKind;
13
- label: string;
14
- purpose: string;
15
- lifecycle: string;
16
- persistence: string;
17
- primaryCommands: string[];
18
- useWhen: string[];
19
- avoidWhen: string[];
20
- }
21
-
22
- export interface DeviceRecord {
23
- id: string;
24
- kind: DeviceKind;
25
- source: DeviceSource;
26
- name?: string;
27
- state?: string;
28
- ready?: boolean;
29
- persistent?: boolean;
30
- alwaysOn?: boolean;
31
- region?: string;
32
- template?: string;
33
- previewUrl?: string;
34
- timeoutRemainingMs?: number;
35
- }
36
-
37
- export interface DeviceListError {
38
- source: DeviceSource;
39
- message: string;
40
- retryable: boolean;
41
- }
42
-
43
- export interface DeviceListParams {
44
- kind?: "all" | "sandbox_worker" | "sandbox" | "computer";
45
- }
46
-
47
- export interface DeviceListResponse {
48
- devices: DeviceRecord[];
49
- errors: DeviceListError[];
50
- }
51
-
52
- const DEVICE_CATALOG: DeviceCatalogEntry[] = [
53
- {
54
- kind: "sandbox_worker",
55
- label: "Sandbox Worker",
56
- purpose:
57
- "Isolated Linux workspace for agents to create files, run code, preview apps, snapshot, fork, and publish.",
58
- lifecycle:
59
- "Persistent by default; use stop/resume/snapshot/fork where the account backend supports saved state.",
60
- persistence:
61
- "Use one-hour timeouts for interactive builds and checkpoint before long pauses.",
62
- primaryCommands: [
63
- "miosa.sandboxes.create({ templateId: 'nextjs', timeoutSec: 3600 })",
64
- "sandbox.exec.run('codex ...', { cwd: '/workspace' })",
65
- "sandbox.files.write('/workspace/app/page.jsx', source)",
66
- "miosa.deployments.publishFromSandbox(...)",
67
- ],
68
- useWhen: [
69
- "Coding agents should build inside the remote filesystem.",
70
- "You need command execution, file writes, package installs, previews, artifacts, or app publish.",
71
- "You want virtual-device behavior without a GUI desktop.",
72
- ],
73
- avoidWhen: [
74
- "The workflow requires full browser/desktop control.",
75
- "The app is ready for production; publish it to a deployment runtime.",
76
- ],
77
- },
78
- {
79
- kind: "computer",
80
- label: "Computer",
81
- purpose:
82
- "Durable VM/desktop device for browser automation, CUA sessions, SSH, tunnels, and persistent agent control.",
83
- lifecycle:
84
- "Managed as a Computer with desktop/browser and operator-style control surfaces.",
85
- persistence:
86
- "Use checkpoints, volumes, tunnels, and agent sessions for long-lived desktop workflows.",
87
- primaryCommands: [
88
- "miosa.computers.create({ name: 'browser-agent' })",
89
- "computer.exec.run('npm test')",
90
- "computer.desktop.open()",
91
- ],
92
- useWhen: [
93
- "The agent needs Chromium or a full desktop.",
94
- "The workflow logs into dashboards, fills forms, clicks buttons, or captures screenshots.",
95
- "A human and agent share the same persistent machine state.",
96
- ],
97
- avoidWhen: [
98
- "Simple code generation/build/test work fits a cheaper sandbox worker.",
99
- "You only need durable app hosting.",
100
- ],
101
- },
102
- {
103
- kind: "local_device",
104
- label: "Local Device",
105
- purpose:
106
- "Developer-owned machine connected through CLI/MCP for local discovery and private tooling.",
107
- lifecycle: "Not hosted by MIOSA; the user owns uptime and state.",
108
- persistence:
109
- "State is local machine state. Do not assume cloud resume semantics.",
110
- primaryCommands: ["miosa mcp install", "miosa doctor --json"],
111
- useWhen: [
112
- "The agent needs local repository discovery before cloud execution.",
113
- "The user intentionally wants local private tools.",
114
- ],
115
- avoidWhen: [
116
- "Customer code must stay isolated in MIOSA-hosted infrastructure.",
117
- "The workflow needs reproducible shared cloud state.",
118
- ],
119
- },
120
- {
121
- kind: "docker_deploy_host",
122
- label: "Docker Deploy Host",
123
- purpose:
124
- "Workspace appliance VM that runs Docker containers for durable apps published from sandboxes.",
125
- lifecycle:
126
- "Always-on deployment capacity; not an interactive coding workspace.",
127
- persistence:
128
- "Versioned releases and routing are durable; edits happen in sandboxes before publish.",
129
- primaryCommands: [
130
- "miosa sandbox publish <id> --docker-deploy",
131
- "miosa deploy --docker-deploy",
132
- ],
133
- useWhen: [
134
- "You need many small apps, APIs, funnels, or client sites in one workspace appliance.",
135
- "You want stable public URLs backed by Docker containers.",
136
- ],
137
- avoidWhen: [
138
- "Interactive agent work is still happening.",
139
- "The app needs the standard MIOSA Deploy runtime.",
140
- ],
141
- },
142
- ];
143
-
144
- export class Devices {
145
- private readonly http: HttpClient;
146
-
147
- constructor(http: HttpClient) {
148
- this.http = http;
149
- }
150
-
151
- /**
152
- * Return the static device catalog used by orchestration apps to choose the
153
- * right MIOSA execution surface before creating resources.
154
- */
155
- catalog(): DeviceCatalogEntry[] {
156
- return DEVICE_CATALOG.map((entry) => ({ ...entry }));
157
- }
158
-
159
- /**
160
- * List hosted devices by normalizing existing sandboxes and computers.
161
- * Partial backend failures are returned in `errors` so orchestration UIs can
162
- * still show usable inventory instead of failing the whole page.
163
- */
164
- async list(params: DeviceListParams = {}): Promise<DeviceListResponse> {
165
- const kind = normalizeKind(params.kind ?? "all");
166
- const devices: DeviceRecord[] = [];
167
- const errors: DeviceListError[] = [];
168
-
169
- if (kind === "all" || kind === "sandbox_worker") {
170
- try {
171
- const sandboxes = await this.http.get<unknown>("/sandboxes");
172
- devices.push(...unwrapList(sandboxes, ["sandboxes"]).map(normalizeSandbox));
173
- } catch (err) {
174
- errors.push(toListError("sandboxes", err));
175
- }
176
- }
177
-
178
- if (kind === "all" || kind === "computer") {
179
- try {
180
- const computers = await this.http.get<unknown>("/computers");
181
- devices.push(...unwrapList(computers, ["computers"]).map(normalizeComputer));
182
- } catch (err) {
183
- errors.push(toListError("computers", err));
184
- }
185
- }
186
-
187
- return { devices, errors };
188
- }
189
- }
190
-
191
- function normalizeKind(
192
- kind: NonNullable<DeviceListParams["kind"]>,
193
- ): "all" | "sandbox_worker" | "computer" {
194
- if (kind === "all") return "all";
195
- if (kind === "sandbox" || kind === "sandbox_worker") {
196
- return "sandbox_worker";
197
- }
198
- if (kind === "computer") return "computer";
199
- throw new Error(`Unsupported device kind: ${kind}`);
200
- }
201
-
202
- function normalizeSandbox(row: Record<string, unknown>): DeviceRecord {
203
- return compactRecord({
204
- id: stringField(row, "id"),
205
- kind: "sandbox_worker",
206
- source: "sandboxes",
207
- name: optionalString(row, "name"),
208
- state: optionalString(row, "state") ?? optionalString(row, "status"),
209
- ready: optionalBoolean(row, "ready"),
210
- persistent: optionalBoolean(row, "persistent"),
211
- alwaysOn: optionalBoolean(row, "always_on"),
212
- template:
213
- optionalString(row, "template_id") ?? optionalString(row, "template"),
214
- previewUrl: optionalString(row, "preview_url"),
215
- timeoutRemainingMs: optionalNumber(row, "timeout_remaining_ms"),
216
- });
217
- }
218
-
219
- function normalizeComputer(row: Record<string, unknown>): DeviceRecord {
220
- return compactRecord({
221
- id: stringField(row, "id"),
222
- kind: "computer",
223
- source: "computers",
224
- name: optionalString(row, "name"),
225
- state: optionalString(row, "status") ?? optionalString(row, "state"),
226
- ready: optionalBoolean(row, "ready"),
227
- region: optionalString(row, "region"),
228
- template:
229
- optionalString(row, "template_type") ?? optionalString(row, "template"),
230
- });
231
- }
232
-
233
- function compactRecord(record: Record<string, unknown>): DeviceRecord {
234
- return Object.fromEntries(
235
- Object.entries(record).filter(([, value]) => value !== undefined),
236
- ) as unknown as DeviceRecord;
237
- }
238
-
239
- function unwrapList(payload: unknown, keys: string[]): Record<string, unknown>[] {
240
- const value = isRecord(payload) && "data" in payload ? payload.data : payload;
241
- if (Array.isArray(value)) return value.filter(isRecord);
242
- if (isRecord(value)) {
243
- for (const key of keys) {
244
- const nested = value[key];
245
- if (Array.isArray(nested)) return nested.filter(isRecord);
246
- }
247
- }
248
- return [];
249
- }
250
-
251
- function toListError(source: DeviceSource, err: unknown): DeviceListError {
252
- const message = err instanceof Error ? err.message : String(err);
253
- return {
254
- source,
255
- message,
256
- retryable: /fetch failed|ECONNRESET|HTTP 502|other side closed|socket hang up|bad gateway/i.test(
257
- message,
258
- ),
259
- };
260
- }
261
-
262
- function stringField(row: Record<string, unknown>, key: string): string {
263
- const value = row[key];
264
- return typeof value === "string" ? value : String(value ?? "");
265
- }
266
-
267
- function optionalString(
268
- row: Record<string, unknown>,
269
- key: string,
270
- ): string | undefined {
271
- const value = row[key];
272
- return typeof value === "string" && value.length > 0 ? value : undefined;
273
- }
274
-
275
- function optionalBoolean(
276
- row: Record<string, unknown>,
277
- key: string,
278
- ): boolean | undefined {
279
- return typeof row[key] === "boolean" ? row[key] : undefined;
280
- }
281
-
282
- function optionalNumber(
283
- row: Record<string, unknown>,
284
- key: string,
285
- ): number | undefined {
286
- return typeof row[key] === "number" ? row[key] : undefined;
287
- }
288
-
289
- function isRecord(value: unknown): value is Record<string, unknown> {
290
- return value !== null && typeof value === "object" && !Array.isArray(value);
291
- }