@kazzle/app 0.1.927 → 0.1.930
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/dist/auth-react.d.ts +20 -0
- package/dist/auth-react.js +52 -0
- package/dist/auth-schema.d.ts +12 -0
- package/dist/auth-schema.js +66 -0
- package/dist/auth.d.ts +50 -0
- package/dist/auth.js +87 -0
- package/dist/connections.d.ts +11 -0
- package/dist/connections.js +56 -0
- package/dist/index.d.ts +7 -0
- package/dist/sdk.d.ts +1 -0
- package/dist/sdk.js +13 -0
- package/dist/vendor/kazzle/browsers.d.ts +56 -0
- package/dist/vendor/kazzle/browsers.js +88 -0
- package/dist/vendor/kazzle/browsers.profiles.d.ts +16 -0
- package/dist/vendor/kazzle/browsers.profiles.js +26 -0
- package/dist/vendor/kazzle/browsers.tabs.d.ts +62 -0
- package/dist/vendor/kazzle/browsers.tabs.js +132 -0
- package/dist/vendor/kazzle/computers.d.ts +35 -0
- package/dist/vendor/kazzle/computers.desktop.d.ts +152 -0
- package/dist/vendor/kazzle/computers.desktop.js +144 -0
- package/dist/vendor/kazzle/computers.fs.d.ts +44 -0
- package/dist/vendor/kazzle/computers.fs.js +37 -0
- package/dist/vendor/kazzle/computers.js +55 -0
- package/dist/vendor/kazzle/computers.terminals.d.ts +36 -0
- package/dist/vendor/kazzle/computers.terminals.js +38 -0
- package/dist/vendor/kazzle/generated/operations.d.ts +8 -0
- package/dist/vendor/kazzle/generated/operations.js +137 -0
- package/dist/vendor/kazzle/http.d.ts +39 -0
- package/dist/vendor/kazzle/http.js +103 -0
- package/dist/vendor/kazzle/index.d.ts +11 -0
- package/dist/vendor/kazzle/index.js +12 -0
- package/dist/vendor/kazzle/kazzle.d.ts +10 -0
- package/dist/vendor/kazzle/kazzle.js +18 -0
- package/dist/vendor/kazzle/sdk.types.d.ts +134 -0
- package/dist/vendor/kazzle/sdk.types.js +6 -0
- package/dist/vendor/kazzle/sse.d.ts +45 -0
- package/dist/vendor/kazzle/sse.js +112 -0
- package/package.json +43 -1
- package/templates/login-app/KAZZLE.md +18 -0
- package/templates/login-app/components/server/index.ts +93 -0
- package/templates/login-app/components/server/package.json +25 -0
- package/templates/login-app/components/server/tsconfig.json +11 -0
- package/templates/login-app/components/ui/index.html +12 -0
- package/templates/login-app/components/ui/package.json +29 -0
- package/templates/login-app/components/ui/public/favicon.svg +4 -0
- package/templates/login-app/components/ui/src/App.tsx +107 -0
- package/templates/login-app/components/ui/src/api.ts +37 -0
- package/templates/login-app/components/ui/src/main.tsx +13 -0
- package/templates/login-app/components/ui/src/styles/theme.css +181 -0
- package/templates/login-app/components/ui/src/vite-env.d.ts +1 -0
- package/templates/login-app/components/ui/tsconfig.json +21 -0
- package/templates/login-app/components/ui/vite.config.ts +19 -0
- package/templates/login-app/kazzle.config.ts +13 -0
- package/templates/login-app/package.json +17 -0
- package/templates/manifest.json +1 -0
- package/templates/ui-db-app/components/ui/tsconfig.json +1 -1
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
// kazzle.browsers.tabs.* — tab-scoped browser actions
|
|
2
|
+
// (/browsers/{id}/tabs/{tid}/{action}). Each method maps to exactly one
|
|
3
|
+
// endpoint; action() is the generic escape hatch for the same set.
|
|
4
|
+
import { apiPath } from './http';
|
|
5
|
+
export class TabsApi {
|
|
6
|
+
http;
|
|
7
|
+
constructor(http) {
|
|
8
|
+
this.http = http;
|
|
9
|
+
}
|
|
10
|
+
/** List the open tabs of a browser session. */
|
|
11
|
+
list(browserId) {
|
|
12
|
+
return this.http.json('GET', apiPath `/browsers/${browserId}/tabs`);
|
|
13
|
+
}
|
|
14
|
+
/** Open a new tab. The new tab id is the response's tab_id. */
|
|
15
|
+
open(browserId, options = {}) {
|
|
16
|
+
return this.http.json('POST', apiPath `/browsers/${browserId}/tabs`, options);
|
|
17
|
+
}
|
|
18
|
+
/** POST one tab action by its URL segment. The named methods below all funnel through this. */
|
|
19
|
+
action(browserId, tabId, segment, body = {}) {
|
|
20
|
+
return this.http.json('POST', `${apiPath `/browsers/${browserId}/tabs/${tabId}/`}${segment}`, body);
|
|
21
|
+
}
|
|
22
|
+
binary(browserId, tabId, segment, body) {
|
|
23
|
+
return this.http.binary(`${apiPath `/browsers/${browserId}/tabs/${tabId}/`}${segment}`, body);
|
|
24
|
+
}
|
|
25
|
+
nav(browserId, tabId, body) {
|
|
26
|
+
return this.action(browserId, tabId, 'nav', body);
|
|
27
|
+
}
|
|
28
|
+
back(browserId, tabId) {
|
|
29
|
+
return this.action(browserId, tabId, 'back');
|
|
30
|
+
}
|
|
31
|
+
forward(browserId, tabId) {
|
|
32
|
+
return this.action(browserId, tabId, 'forward');
|
|
33
|
+
}
|
|
34
|
+
reload(browserId, tabId) {
|
|
35
|
+
return this.action(browserId, tabId, 'reload');
|
|
36
|
+
}
|
|
37
|
+
/** Returns PNG (or JPEG) bytes. */
|
|
38
|
+
screenshot(browserId, tabId, body = {}) {
|
|
39
|
+
return this.binary(browserId, tabId, 'screenshot', body);
|
|
40
|
+
}
|
|
41
|
+
/** Returns PDF bytes. */
|
|
42
|
+
pdf(browserId, tabId, body = {}) {
|
|
43
|
+
return this.binary(browserId, tabId, 'pdf', body);
|
|
44
|
+
}
|
|
45
|
+
/** Accessibility snapshot. Element refs from it target later click/type calls. */
|
|
46
|
+
snapshot(browserId, tabId, body = {}) {
|
|
47
|
+
return this.action(browserId, tabId, 'snapshot', body);
|
|
48
|
+
}
|
|
49
|
+
eval(browserId, tabId, body) {
|
|
50
|
+
return this.action(browserId, tabId, 'eval', body);
|
|
51
|
+
}
|
|
52
|
+
click(browserId, tabId, body) {
|
|
53
|
+
return this.action(browserId, tabId, 'click', body);
|
|
54
|
+
}
|
|
55
|
+
type(browserId, tabId, body) {
|
|
56
|
+
return this.action(browserId, tabId, 'type', body);
|
|
57
|
+
}
|
|
58
|
+
select(browserId, tabId, body) {
|
|
59
|
+
return this.action(browserId, tabId, 'select', body);
|
|
60
|
+
}
|
|
61
|
+
fillForm(browserId, tabId, body) {
|
|
62
|
+
return this.action(browserId, tabId, 'fill_form', body);
|
|
63
|
+
}
|
|
64
|
+
check(browserId, tabId, body) {
|
|
65
|
+
return this.action(browserId, tabId, 'check', body);
|
|
66
|
+
}
|
|
67
|
+
uncheck(browserId, tabId, body) {
|
|
68
|
+
return this.action(browserId, tabId, 'uncheck', body);
|
|
69
|
+
}
|
|
70
|
+
hover(browserId, tabId, body) {
|
|
71
|
+
return this.action(browserId, tabId, 'hover', body);
|
|
72
|
+
}
|
|
73
|
+
drag(browserId, tabId, body) {
|
|
74
|
+
return this.action(browserId, tabId, 'drag', body);
|
|
75
|
+
}
|
|
76
|
+
upload(browserId, tabId, body) {
|
|
77
|
+
return this.action(browserId, tabId, 'upload', body);
|
|
78
|
+
}
|
|
79
|
+
dialog(browserId, tabId, body) {
|
|
80
|
+
return this.action(browserId, tabId, 'dialog', body);
|
|
81
|
+
}
|
|
82
|
+
key(browserId, tabId, body) {
|
|
83
|
+
return this.action(browserId, tabId, 'key', body);
|
|
84
|
+
}
|
|
85
|
+
scroll(browserId, tabId, body) {
|
|
86
|
+
return this.action(browserId, tabId, 'scroll', body);
|
|
87
|
+
}
|
|
88
|
+
content(browserId, tabId, body = {}) {
|
|
89
|
+
return this.action(browserId, tabId, 'content', body);
|
|
90
|
+
}
|
|
91
|
+
dom(browserId, tabId, body) {
|
|
92
|
+
return this.action(browserId, tabId, 'dom', body);
|
|
93
|
+
}
|
|
94
|
+
extract(browserId, tabId, body) {
|
|
95
|
+
return this.action(browserId, tabId, 'extract', body);
|
|
96
|
+
}
|
|
97
|
+
find(browserId, tabId, body) {
|
|
98
|
+
return this.action(browserId, tabId, 'find', body);
|
|
99
|
+
}
|
|
100
|
+
options(browserId, tabId, body) {
|
|
101
|
+
return this.action(browserId, tabId, 'options', body);
|
|
102
|
+
}
|
|
103
|
+
console(browserId, tabId, body = {}) {
|
|
104
|
+
return this.action(browserId, tabId, 'console', body);
|
|
105
|
+
}
|
|
106
|
+
network(browserId, tabId, body = {}) {
|
|
107
|
+
return this.action(browserId, tabId, 'network', body);
|
|
108
|
+
}
|
|
109
|
+
wait(browserId, tabId, body) {
|
|
110
|
+
return this.action(browserId, tabId, 'wait', body);
|
|
111
|
+
}
|
|
112
|
+
status(browserId, tabId, body = {}) {
|
|
113
|
+
return this.action(browserId, tabId, 'status', body);
|
|
114
|
+
}
|
|
115
|
+
download(browserId, tabId, body) {
|
|
116
|
+
return this.action(browserId, tabId, 'download', body);
|
|
117
|
+
}
|
|
118
|
+
/** Live view URL for the tab. */
|
|
119
|
+
live(browserId, tabId, body = {}) {
|
|
120
|
+
return this.action(browserId, tabId, 'live', body);
|
|
121
|
+
}
|
|
122
|
+
focus(browserId, tabId) {
|
|
123
|
+
return this.action(browserId, tabId, 'focus');
|
|
124
|
+
}
|
|
125
|
+
move(browserId, tabId, body) {
|
|
126
|
+
return this.action(browserId, tabId, 'move', body);
|
|
127
|
+
}
|
|
128
|
+
/** Close the tab (DELETE /browsers/{id}/tabs/{tid}; POST .../close does the same). */
|
|
129
|
+
close(browserId, tabId) {
|
|
130
|
+
return this.http.json('DELETE', apiPath `/browsers/${browserId}/tabs/${tabId}`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type KazzleHttp } from './http';
|
|
2
|
+
import { ExecStream } from './sse';
|
|
3
|
+
import { FsApi } from './computers.fs';
|
|
4
|
+
import { TerminalsApi } from './computers.terminals';
|
|
5
|
+
import { DesktopApi } from './computers.desktop';
|
|
6
|
+
import type { ComputerCreateResponse, ComputerRow, ExecOptions, ListResponse, OkResponse } from './sdk.types';
|
|
7
|
+
export declare class ComputersApi {
|
|
8
|
+
private readonly http;
|
|
9
|
+
readonly fs: FsApi;
|
|
10
|
+
readonly terminals: TerminalsApi;
|
|
11
|
+
readonly desktop: DesktopApi;
|
|
12
|
+
constructor(http: KazzleHttp);
|
|
13
|
+
/** Create a cloud computer. It boots with a persistent disk; state is "offline" until it comes up. */
|
|
14
|
+
create(): Promise<ComputerCreateResponse>;
|
|
15
|
+
/** List the computers in the API key's space. */
|
|
16
|
+
list(): Promise<ListResponse<ComputerRow>>;
|
|
17
|
+
get(computerId: string): Promise<ComputerRow>;
|
|
18
|
+
/** Resume a suspended computer from its snapshot. Wakes take seconds; the disk is preserved. */
|
|
19
|
+
wake(computerId: string): Promise<OkResponse & {
|
|
20
|
+
id: string;
|
|
21
|
+
}>;
|
|
22
|
+
/** Suspend the computer. The disk is kept; wake it later to resume. */
|
|
23
|
+
stop(computerId: string): Promise<OkResponse>;
|
|
24
|
+
/** Re-provision a computer whose sandbox is missing or wedged. The persistent volume is reattached. */
|
|
25
|
+
repair(computerId: string): Promise<OkResponse>;
|
|
26
|
+
/** Destroy the computer and delete its disk. Permanent; use stop() to keep the files. */
|
|
27
|
+
destroy(computerId: string): Promise<OkResponse>;
|
|
28
|
+
/**
|
|
29
|
+
* Run one command and stream the result. Returns an ExecStream: iterate the
|
|
30
|
+
* SSE events (`stdout`/`error`/`exit`), or call `.text()` for the joined
|
|
31
|
+
* stdout and exit code. stderr is merged into stdout (PTY). For long-running
|
|
32
|
+
* processes use terminals instead.
|
|
33
|
+
*/
|
|
34
|
+
exec(computerId: string, options: ExecOptions): ExecStream;
|
|
35
|
+
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { type KazzleHttp } from './http';
|
|
2
|
+
import type { ActionResult, ListResponse } from './sdk.types';
|
|
3
|
+
declare class DesktopSessionsApi {
|
|
4
|
+
private readonly http;
|
|
5
|
+
constructor(http: KazzleHttp);
|
|
6
|
+
/** Create a live desktop session (virtual display) for input actions. */
|
|
7
|
+
create(computerId: string, options?: {
|
|
8
|
+
name?: string;
|
|
9
|
+
resolution?: string;
|
|
10
|
+
}): Promise<ActionResult>;
|
|
11
|
+
list(computerId: string): Promise<ListResponse<Record<string, unknown>> & ActionResult>;
|
|
12
|
+
close(computerId: string, sessionId: string): Promise<ActionResult>;
|
|
13
|
+
}
|
|
14
|
+
/** Mouse and keyboard input inside a live session. Every body carries the sessionId. */
|
|
15
|
+
declare class DesktopInputApi {
|
|
16
|
+
private readonly http;
|
|
17
|
+
constructor(http: KazzleHttp);
|
|
18
|
+
private post;
|
|
19
|
+
click(computerId: string, body: {
|
|
20
|
+
sessionId: string;
|
|
21
|
+
x: number;
|
|
22
|
+
y: number;
|
|
23
|
+
button?: string;
|
|
24
|
+
}): Promise<ActionResult>;
|
|
25
|
+
doubleClick(computerId: string, body: {
|
|
26
|
+
sessionId: string;
|
|
27
|
+
x: number;
|
|
28
|
+
y: number;
|
|
29
|
+
}): Promise<ActionResult>;
|
|
30
|
+
mouseDown(computerId: string, body: {
|
|
31
|
+
sessionId: string;
|
|
32
|
+
x: number;
|
|
33
|
+
y: number;
|
|
34
|
+
button?: string;
|
|
35
|
+
}): Promise<ActionResult>;
|
|
36
|
+
mouseUp(computerId: string, body: {
|
|
37
|
+
sessionId: string;
|
|
38
|
+
x: number;
|
|
39
|
+
y: number;
|
|
40
|
+
button?: string;
|
|
41
|
+
}): Promise<ActionResult>;
|
|
42
|
+
move(computerId: string, body: {
|
|
43
|
+
sessionId: string;
|
|
44
|
+
x: number;
|
|
45
|
+
y: number;
|
|
46
|
+
}): Promise<ActionResult>;
|
|
47
|
+
drag(computerId: string, body: {
|
|
48
|
+
sessionId: string;
|
|
49
|
+
x: number;
|
|
50
|
+
y: number;
|
|
51
|
+
toX: number;
|
|
52
|
+
toY: number;
|
|
53
|
+
}): Promise<ActionResult>;
|
|
54
|
+
scroll(computerId: string, body: {
|
|
55
|
+
sessionId: string;
|
|
56
|
+
deltaX?: number;
|
|
57
|
+
deltaY?: number;
|
|
58
|
+
x?: number;
|
|
59
|
+
y?: number;
|
|
60
|
+
}): Promise<ActionResult>;
|
|
61
|
+
type(computerId: string, body: {
|
|
62
|
+
sessionId: string;
|
|
63
|
+
text: string;
|
|
64
|
+
}): Promise<ActionResult>;
|
|
65
|
+
/** Press a key combo, e.g. "ctrl+c". */
|
|
66
|
+
key(computerId: string, body: {
|
|
67
|
+
sessionId: string;
|
|
68
|
+
key: string;
|
|
69
|
+
}): Promise<ActionResult>;
|
|
70
|
+
}
|
|
71
|
+
/** Structured control of applications (attach, inspect the UI tree, press elements). */
|
|
72
|
+
declare class DesktopAppsApi {
|
|
73
|
+
private readonly http;
|
|
74
|
+
constructor(http: KazzleHttp);
|
|
75
|
+
private post;
|
|
76
|
+
/** List the applications available on the computer with their bundle ids. */
|
|
77
|
+
list(computerId: string): Promise<ActionResult>;
|
|
78
|
+
/** Start (attach to) an application. The result row carries controlled_app_session_id. */
|
|
79
|
+
start(computerId: string, body: {
|
|
80
|
+
bundleId: string;
|
|
81
|
+
windowTitle?: string;
|
|
82
|
+
physicalInput?: boolean;
|
|
83
|
+
}): Promise<ActionResult>;
|
|
84
|
+
stop(computerId: string, body: {
|
|
85
|
+
controlledAppSessionId: string;
|
|
86
|
+
}): Promise<ActionResult>;
|
|
87
|
+
status(computerId: string, body: {
|
|
88
|
+
controlledAppSessionId: string;
|
|
89
|
+
}): Promise<ActionResult>;
|
|
90
|
+
/** Accessibility-tree inspection of the controlled application. */
|
|
91
|
+
inspect(computerId: string, body: {
|
|
92
|
+
controlledAppSessionId: string;
|
|
93
|
+
depth?: number;
|
|
94
|
+
}): Promise<ActionResult>;
|
|
95
|
+
press(computerId: string, body: {
|
|
96
|
+
controlledAppSessionId: string;
|
|
97
|
+
elementPath: string;
|
|
98
|
+
}): Promise<ActionResult>;
|
|
99
|
+
setValue(computerId: string, body: {
|
|
100
|
+
controlledAppSessionId: string;
|
|
101
|
+
elementPath: string;
|
|
102
|
+
value: string;
|
|
103
|
+
}): Promise<ActionResult>;
|
|
104
|
+
/** Screenshot the controlled application's window. Returns PNG bytes. */
|
|
105
|
+
capture(computerId: string, body: {
|
|
106
|
+
controlledAppSessionId: string;
|
|
107
|
+
}): Promise<Uint8Array>;
|
|
108
|
+
}
|
|
109
|
+
declare class DesktopWindowsApi {
|
|
110
|
+
private readonly http;
|
|
111
|
+
constructor(http: KazzleHttp);
|
|
112
|
+
/** The active window in a live session. */
|
|
113
|
+
active(computerId: string, body: {
|
|
114
|
+
sessionId: string;
|
|
115
|
+
}): Promise<ActionResult>;
|
|
116
|
+
/** Raise a window of a controlled application. */
|
|
117
|
+
raise(computerId: string, body: {
|
|
118
|
+
controlledAppSessionId: string;
|
|
119
|
+
windowPath: string;
|
|
120
|
+
}): Promise<ActionResult>;
|
|
121
|
+
/** Move/resize a window inside a live session. */
|
|
122
|
+
place(computerId: string, body: {
|
|
123
|
+
sessionId: string;
|
|
124
|
+
x: number;
|
|
125
|
+
y: number;
|
|
126
|
+
width: number;
|
|
127
|
+
height: number;
|
|
128
|
+
controlledAppSessionId?: string;
|
|
129
|
+
windowPath?: string;
|
|
130
|
+
}): Promise<ActionResult>;
|
|
131
|
+
}
|
|
132
|
+
export declare class DesktopApi {
|
|
133
|
+
private readonly http;
|
|
134
|
+
readonly sessions: DesktopSessionsApi;
|
|
135
|
+
readonly input: DesktopInputApi;
|
|
136
|
+
readonly apps: DesktopAppsApi;
|
|
137
|
+
readonly windows: DesktopWindowsApi;
|
|
138
|
+
constructor(http: KazzleHttp);
|
|
139
|
+
/** Screenshot a display. Omit displayId for the primary display. Returns PNG bytes. */
|
|
140
|
+
capture(computerId: string, options?: {
|
|
141
|
+
displayId?: string;
|
|
142
|
+
}): Promise<Uint8Array>;
|
|
143
|
+
/** List the computer's displays with ids for capture(). */
|
|
144
|
+
displays(computerId: string): Promise<ActionResult>;
|
|
145
|
+
/** Check screen-recording / input permissions on the computer. */
|
|
146
|
+
permissions(computerId: string): Promise<ActionResult>;
|
|
147
|
+
/** Screen geometry for a live session. */
|
|
148
|
+
screen(computerId: string, body: {
|
|
149
|
+
sessionId: string;
|
|
150
|
+
}): Promise<ActionResult>;
|
|
151
|
+
}
|
|
152
|
+
export {};
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
// kazzle.computers.desktop.* — screen capture, input, apps, and windows
|
|
2
|
+
// (/computers/{id}/desktop/*). Input actions target a live desktop session
|
|
3
|
+
// (virtual display) created with sessions.create().
|
|
4
|
+
import { apiPath } from './http';
|
|
5
|
+
class DesktopSessionsApi {
|
|
6
|
+
http;
|
|
7
|
+
constructor(http) {
|
|
8
|
+
this.http = http;
|
|
9
|
+
}
|
|
10
|
+
/** Create a live desktop session (virtual display) for input actions. */
|
|
11
|
+
create(computerId, options = {}) {
|
|
12
|
+
return this.http.json('POST', apiPath `/computers/${computerId}/desktop/sessions`, options);
|
|
13
|
+
}
|
|
14
|
+
list(computerId) {
|
|
15
|
+
return this.http.json('GET', apiPath `/computers/${computerId}/desktop/sessions`);
|
|
16
|
+
}
|
|
17
|
+
close(computerId, sessionId) {
|
|
18
|
+
return this.http.json('DELETE', apiPath `/computers/${computerId}/desktop/sessions/${sessionId}`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/** Mouse and keyboard input inside a live session. Every body carries the sessionId. */
|
|
22
|
+
class DesktopInputApi {
|
|
23
|
+
http;
|
|
24
|
+
constructor(http) {
|
|
25
|
+
this.http = http;
|
|
26
|
+
}
|
|
27
|
+
post(computerId, segment, body) {
|
|
28
|
+
return this.http.json('POST', `${apiPath `/computers/${computerId}/desktop/input/`}${segment}`, body);
|
|
29
|
+
}
|
|
30
|
+
click(computerId, body) {
|
|
31
|
+
return this.post(computerId, 'click', body);
|
|
32
|
+
}
|
|
33
|
+
doubleClick(computerId, body) {
|
|
34
|
+
return this.post(computerId, 'double_click', body);
|
|
35
|
+
}
|
|
36
|
+
mouseDown(computerId, body) {
|
|
37
|
+
return this.post(computerId, 'mouse_down', body);
|
|
38
|
+
}
|
|
39
|
+
mouseUp(computerId, body) {
|
|
40
|
+
return this.post(computerId, 'mouse_up', body);
|
|
41
|
+
}
|
|
42
|
+
move(computerId, body) {
|
|
43
|
+
return this.post(computerId, 'move', body);
|
|
44
|
+
}
|
|
45
|
+
drag(computerId, body) {
|
|
46
|
+
return this.post(computerId, 'drag', body);
|
|
47
|
+
}
|
|
48
|
+
scroll(computerId, body) {
|
|
49
|
+
return this.post(computerId, 'scroll', body);
|
|
50
|
+
}
|
|
51
|
+
type(computerId, body) {
|
|
52
|
+
return this.post(computerId, 'type', body);
|
|
53
|
+
}
|
|
54
|
+
/** Press a key combo, e.g. "ctrl+c". */
|
|
55
|
+
key(computerId, body) {
|
|
56
|
+
return this.post(computerId, 'key', body);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/** Structured control of applications (attach, inspect the UI tree, press elements). */
|
|
60
|
+
class DesktopAppsApi {
|
|
61
|
+
http;
|
|
62
|
+
constructor(http) {
|
|
63
|
+
this.http = http;
|
|
64
|
+
}
|
|
65
|
+
post(computerId, segment, body) {
|
|
66
|
+
return this.http.json('POST', `${apiPath `/computers/${computerId}/desktop/apps/`}${segment}`, body);
|
|
67
|
+
}
|
|
68
|
+
/** List the applications available on the computer with their bundle ids. */
|
|
69
|
+
list(computerId) {
|
|
70
|
+
return this.http.json('GET', apiPath `/computers/${computerId}/desktop/apps`);
|
|
71
|
+
}
|
|
72
|
+
/** Start (attach to) an application. The result row carries controlled_app_session_id. */
|
|
73
|
+
start(computerId, body) {
|
|
74
|
+
return this.post(computerId, 'start', body);
|
|
75
|
+
}
|
|
76
|
+
stop(computerId, body) {
|
|
77
|
+
return this.post(computerId, 'stop', body);
|
|
78
|
+
}
|
|
79
|
+
status(computerId, body) {
|
|
80
|
+
return this.post(computerId, 'status', body);
|
|
81
|
+
}
|
|
82
|
+
/** Accessibility-tree inspection of the controlled application. */
|
|
83
|
+
inspect(computerId, body) {
|
|
84
|
+
return this.post(computerId, 'inspect', body);
|
|
85
|
+
}
|
|
86
|
+
press(computerId, body) {
|
|
87
|
+
return this.post(computerId, 'press', body);
|
|
88
|
+
}
|
|
89
|
+
setValue(computerId, body) {
|
|
90
|
+
return this.post(computerId, 'set_value', body);
|
|
91
|
+
}
|
|
92
|
+
/** Screenshot the controlled application's window. Returns PNG bytes. */
|
|
93
|
+
capture(computerId, body) {
|
|
94
|
+
return this.http.binary(apiPath `/computers/${computerId}/desktop/apps/capture`, body);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
class DesktopWindowsApi {
|
|
98
|
+
http;
|
|
99
|
+
constructor(http) {
|
|
100
|
+
this.http = http;
|
|
101
|
+
}
|
|
102
|
+
/** The active window in a live session. */
|
|
103
|
+
active(computerId, body) {
|
|
104
|
+
return this.http.json('POST', apiPath `/computers/${computerId}/desktop/windows/active`, body);
|
|
105
|
+
}
|
|
106
|
+
/** Raise a window of a controlled application. */
|
|
107
|
+
raise(computerId, body) {
|
|
108
|
+
return this.http.json('POST', apiPath `/computers/${computerId}/desktop/windows/raise`, body);
|
|
109
|
+
}
|
|
110
|
+
/** Move/resize a window inside a live session. */
|
|
111
|
+
place(computerId, body) {
|
|
112
|
+
return this.http.json('POST', apiPath `/computers/${computerId}/desktop/windows/place`, body);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
export class DesktopApi {
|
|
116
|
+
http;
|
|
117
|
+
sessions;
|
|
118
|
+
input;
|
|
119
|
+
apps;
|
|
120
|
+
windows;
|
|
121
|
+
constructor(http) {
|
|
122
|
+
this.http = http;
|
|
123
|
+
this.sessions = new DesktopSessionsApi(http);
|
|
124
|
+
this.input = new DesktopInputApi(http);
|
|
125
|
+
this.apps = new DesktopAppsApi(http);
|
|
126
|
+
this.windows = new DesktopWindowsApi(http);
|
|
127
|
+
}
|
|
128
|
+
/** Screenshot a display. Omit displayId for the primary display. Returns PNG bytes. */
|
|
129
|
+
capture(computerId, options = {}) {
|
|
130
|
+
return this.http.binary(apiPath `/computers/${computerId}/desktop/capture`, options);
|
|
131
|
+
}
|
|
132
|
+
/** List the computer's displays with ids for capture(). */
|
|
133
|
+
displays(computerId) {
|
|
134
|
+
return this.http.json('GET', apiPath `/computers/${computerId}/desktop/displays`);
|
|
135
|
+
}
|
|
136
|
+
/** Check screen-recording / input permissions on the computer. */
|
|
137
|
+
permissions(computerId) {
|
|
138
|
+
return this.http.json('GET', apiPath `/computers/${computerId}/desktop/permissions`);
|
|
139
|
+
}
|
|
140
|
+
/** Screen geometry for a live session. */
|
|
141
|
+
screen(computerId, body) {
|
|
142
|
+
return this.http.json('POST', apiPath `/computers/${computerId}/desktop/screen`, body);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { type KazzleHttp } from './http';
|
|
2
|
+
import type { FsDeleteResponse, FsGlobResponse, FsGrepResponse, FsReadResponse, FsTransferResponse, FsWriteResponse } from './sdk.types';
|
|
3
|
+
export interface FsGrepOptions {
|
|
4
|
+
pattern: string;
|
|
5
|
+
path?: string;
|
|
6
|
+
include?: string;
|
|
7
|
+
caseSensitive?: boolean;
|
|
8
|
+
maxResults?: number;
|
|
9
|
+
}
|
|
10
|
+
export declare class FsApi {
|
|
11
|
+
private readonly http;
|
|
12
|
+
constructor(http: KazzleHttp);
|
|
13
|
+
/** Read a file. Text comes back as utf8; binary as base64 with `encoding: "base64"`. Reads are capped at 2 MB. */
|
|
14
|
+
read(computerId: string, options: {
|
|
15
|
+
path: string;
|
|
16
|
+
}): Promise<FsReadResponse>;
|
|
17
|
+
/** Write a file, creating parent directories as needed. Pass `encoding: "base64"` for binary payloads. */
|
|
18
|
+
write(computerId: string, options: {
|
|
19
|
+
path: string;
|
|
20
|
+
content: string;
|
|
21
|
+
encoding?: 'utf-8' | 'base64';
|
|
22
|
+
}): Promise<FsWriteResponse>;
|
|
23
|
+
/** Delete a file or directory. */
|
|
24
|
+
delete(computerId: string, options: {
|
|
25
|
+
path: string;
|
|
26
|
+
}): Promise<FsDeleteResponse>;
|
|
27
|
+
/** Move (rename) a file or directory. */
|
|
28
|
+
move(computerId: string, options: {
|
|
29
|
+
from: string;
|
|
30
|
+
to: string;
|
|
31
|
+
}): Promise<FsTransferResponse>;
|
|
32
|
+
/** Copy a file or directory. */
|
|
33
|
+
copy(computerId: string, options: {
|
|
34
|
+
from: string;
|
|
35
|
+
to: string;
|
|
36
|
+
}): Promise<FsTransferResponse>;
|
|
37
|
+
/** Search file contents (ripgrep semantics). */
|
|
38
|
+
grep(computerId: string, options: FsGrepOptions): Promise<FsGrepResponse>;
|
|
39
|
+
/** Find files by glob pattern, e.g. "**\/*.ts". */
|
|
40
|
+
glob(computerId: string, options: {
|
|
41
|
+
pattern: string;
|
|
42
|
+
maxResults?: number;
|
|
43
|
+
}): Promise<FsGlobResponse>;
|
|
44
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// kazzle.computers.fs.* — computer filesystem operations (/computers/{id}/fs/*).
|
|
2
|
+
// Paths are relative to the computer's space root.
|
|
3
|
+
import { apiPath } from './http';
|
|
4
|
+
export class FsApi {
|
|
5
|
+
http;
|
|
6
|
+
constructor(http) {
|
|
7
|
+
this.http = http;
|
|
8
|
+
}
|
|
9
|
+
/** Read a file. Text comes back as utf8; binary as base64 with `encoding: "base64"`. Reads are capped at 2 MB. */
|
|
10
|
+
read(computerId, options) {
|
|
11
|
+
return this.http.json('POST', apiPath `/computers/${computerId}/fs/read`, options);
|
|
12
|
+
}
|
|
13
|
+
/** Write a file, creating parent directories as needed. Pass `encoding: "base64"` for binary payloads. */
|
|
14
|
+
write(computerId, options) {
|
|
15
|
+
return this.http.json('POST', apiPath `/computers/${computerId}/fs/write`, options);
|
|
16
|
+
}
|
|
17
|
+
/** Delete a file or directory. */
|
|
18
|
+
delete(computerId, options) {
|
|
19
|
+
return this.http.json('POST', apiPath `/computers/${computerId}/fs/delete`, options);
|
|
20
|
+
}
|
|
21
|
+
/** Move (rename) a file or directory. */
|
|
22
|
+
move(computerId, options) {
|
|
23
|
+
return this.http.json('POST', apiPath `/computers/${computerId}/fs/move`, options);
|
|
24
|
+
}
|
|
25
|
+
/** Copy a file or directory. */
|
|
26
|
+
copy(computerId, options) {
|
|
27
|
+
return this.http.json('POST', apiPath `/computers/${computerId}/fs/copy`, options);
|
|
28
|
+
}
|
|
29
|
+
/** Search file contents (ripgrep semantics). */
|
|
30
|
+
grep(computerId, options) {
|
|
31
|
+
return this.http.json('POST', apiPath `/computers/${computerId}/fs/grep`, options);
|
|
32
|
+
}
|
|
33
|
+
/** Find files by glob pattern, e.g. "**\/*.ts". */
|
|
34
|
+
glob(computerId, options) {
|
|
35
|
+
return this.http.json('POST', apiPath `/computers/${computerId}/fs/glob`, options);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// kazzle.computers.* — cloud computer lifecycle plus the per-computer
|
|
2
|
+
// sub-surfaces: fs, exec (SSE), terminals, desktop.
|
|
3
|
+
import { apiPath } from './http';
|
|
4
|
+
import { ExecStream } from './sse';
|
|
5
|
+
import { FsApi } from './computers.fs';
|
|
6
|
+
import { TerminalsApi } from './computers.terminals';
|
|
7
|
+
import { DesktopApi } from './computers.desktop';
|
|
8
|
+
export class ComputersApi {
|
|
9
|
+
http;
|
|
10
|
+
fs;
|
|
11
|
+
terminals;
|
|
12
|
+
desktop;
|
|
13
|
+
constructor(http) {
|
|
14
|
+
this.http = http;
|
|
15
|
+
this.fs = new FsApi(http);
|
|
16
|
+
this.terminals = new TerminalsApi(http);
|
|
17
|
+
this.desktop = new DesktopApi(http);
|
|
18
|
+
}
|
|
19
|
+
/** Create a cloud computer. It boots with a persistent disk; state is "offline" until it comes up. */
|
|
20
|
+
create() {
|
|
21
|
+
return this.http.json('POST', '/computers', {});
|
|
22
|
+
}
|
|
23
|
+
/** List the computers in the API key's space. */
|
|
24
|
+
list() {
|
|
25
|
+
return this.http.json('GET', '/computers');
|
|
26
|
+
}
|
|
27
|
+
get(computerId) {
|
|
28
|
+
return this.http.json('GET', apiPath `/computers/${computerId}`);
|
|
29
|
+
}
|
|
30
|
+
/** Resume a suspended computer from its snapshot. Wakes take seconds; the disk is preserved. */
|
|
31
|
+
wake(computerId) {
|
|
32
|
+
return this.http.json('POST', apiPath `/computers/${computerId}/wake`, {});
|
|
33
|
+
}
|
|
34
|
+
/** Suspend the computer. The disk is kept; wake it later to resume. */
|
|
35
|
+
stop(computerId) {
|
|
36
|
+
return this.http.json('POST', apiPath `/computers/${computerId}/stop`, {});
|
|
37
|
+
}
|
|
38
|
+
/** Re-provision a computer whose sandbox is missing or wedged. The persistent volume is reattached. */
|
|
39
|
+
repair(computerId) {
|
|
40
|
+
return this.http.json('POST', apiPath `/computers/${computerId}/repair`, {});
|
|
41
|
+
}
|
|
42
|
+
/** Destroy the computer and delete its disk. Permanent; use stop() to keep the files. */
|
|
43
|
+
destroy(computerId) {
|
|
44
|
+
return this.http.json('DELETE', apiPath `/computers/${computerId}`);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Run one command and stream the result. Returns an ExecStream: iterate the
|
|
48
|
+
* SSE events (`stdout`/`error`/`exit`), or call `.text()` for the joined
|
|
49
|
+
* stdout and exit code. stderr is merged into stdout (PTY). For long-running
|
|
50
|
+
* processes use terminals instead.
|
|
51
|
+
*/
|
|
52
|
+
exec(computerId, options) {
|
|
53
|
+
return new ExecStream(this.http.request('POST', apiPath `/computers/${computerId}/exec`, options));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type KazzleHttp } from './http';
|
|
2
|
+
import type { ActionResult, TerminalCreateResponse } from './sdk.types';
|
|
3
|
+
export declare class TerminalsApi {
|
|
4
|
+
private readonly http;
|
|
5
|
+
constructor(http: KazzleHttp);
|
|
6
|
+
/** Open a persistent PTY session. The response's session_id is the id for the other calls. */
|
|
7
|
+
create(computerId: string, options?: {
|
|
8
|
+
shell?: string;
|
|
9
|
+
cwd?: string;
|
|
10
|
+
}): Promise<TerminalCreateResponse>;
|
|
11
|
+
/** List terminal sessions on this computer. */
|
|
12
|
+
list(computerId: string, options?: {
|
|
13
|
+
offset?: number;
|
|
14
|
+
limit?: number;
|
|
15
|
+
}): Promise<ActionResult>;
|
|
16
|
+
/** Send input to the session's stdin. Include \n to submit. */
|
|
17
|
+
write(computerId: string, sessionId: string, options: {
|
|
18
|
+
input: string;
|
|
19
|
+
}): Promise<ActionResult>;
|
|
20
|
+
/** Read buffered output (live or recently exited). Lines are 1-based; the response reports total_lines. */
|
|
21
|
+
read(computerId: string, sessionId: string, options?: {
|
|
22
|
+
startLine?: number;
|
|
23
|
+
endLine?: number;
|
|
24
|
+
}): Promise<ActionResult>;
|
|
25
|
+
/** Send a control signal: "interrupt", "eof", or "suspend". */
|
|
26
|
+
ctrl(computerId: string, sessionId: string, options: {
|
|
27
|
+
signal: 'interrupt' | 'eof' | 'suspend';
|
|
28
|
+
}): Promise<ActionResult>;
|
|
29
|
+
/** Block until a regex matches the session output or the timeout elapses. */
|
|
30
|
+
wait(computerId: string, sessionId: string, options: {
|
|
31
|
+
pattern: string;
|
|
32
|
+
timeoutMs?: number;
|
|
33
|
+
}): Promise<ActionResult>;
|
|
34
|
+
/** Kill the session's process and delete the session. */
|
|
35
|
+
kill(computerId: string, sessionId: string): Promise<ActionResult>;
|
|
36
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// kazzle.computers.terminals.* — persistent PTY sessions (/computers/{id}/terminals).
|
|
2
|
+
// Use these for long-running processes (dev servers, watchers); use exec() for
|
|
3
|
+
// one-shot commands.
|
|
4
|
+
import { apiPath } from './http';
|
|
5
|
+
export class TerminalsApi {
|
|
6
|
+
http;
|
|
7
|
+
constructor(http) {
|
|
8
|
+
this.http = http;
|
|
9
|
+
}
|
|
10
|
+
/** Open a persistent PTY session. The response's session_id is the id for the other calls. */
|
|
11
|
+
create(computerId, options = {}) {
|
|
12
|
+
return this.http.json('POST', apiPath `/computers/${computerId}/terminals`, options);
|
|
13
|
+
}
|
|
14
|
+
/** List terminal sessions on this computer. */
|
|
15
|
+
list(computerId, options = {}) {
|
|
16
|
+
return this.http.json('GET', apiPath `/computers/${computerId}/terminals`, undefined, options);
|
|
17
|
+
}
|
|
18
|
+
/** Send input to the session's stdin. Include \n to submit. */
|
|
19
|
+
write(computerId, sessionId, options) {
|
|
20
|
+
return this.http.json('POST', apiPath `/computers/${computerId}/terminals/${sessionId}/write`, options);
|
|
21
|
+
}
|
|
22
|
+
/** Read buffered output (live or recently exited). Lines are 1-based; the response reports total_lines. */
|
|
23
|
+
read(computerId, sessionId, options = {}) {
|
|
24
|
+
return this.http.json('POST', apiPath `/computers/${computerId}/terminals/${sessionId}/read`, options);
|
|
25
|
+
}
|
|
26
|
+
/** Send a control signal: "interrupt", "eof", or "suspend". */
|
|
27
|
+
ctrl(computerId, sessionId, options) {
|
|
28
|
+
return this.http.json('POST', apiPath `/computers/${computerId}/terminals/${sessionId}/ctrl`, options);
|
|
29
|
+
}
|
|
30
|
+
/** Block until a regex matches the session output or the timeout elapses. */
|
|
31
|
+
wait(computerId, sessionId, options) {
|
|
32
|
+
return this.http.json('POST', apiPath `/computers/${computerId}/terminals/${sessionId}/wait`, options);
|
|
33
|
+
}
|
|
34
|
+
/** Kill the session's process and delete the session. */
|
|
35
|
+
kill(computerId, sessionId) {
|
|
36
|
+
return this.http.json('DELETE', apiPath `/computers/${computerId}/terminals/${sessionId}`);
|
|
37
|
+
}
|
|
38
|
+
}
|