@aglit-ai/sdk 0.1.9 → 0.1.11
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 +236 -58
- package/browser.d.ts +1 -0
- package/browser.js +2 -0
- package/dist/browser.d.ts +7503 -0
- package/dist/browser.js +1 -0
- package/dist/index.d.ts +17648 -5
- package/dist/index.js +1 -1
- package/dist/schema/api.openapi.yaml +8202 -0
- package/dist/schema/tools-api.openapi.yaml +1665 -0
- package/package.json +12 -35
- package/site-worker.js +221 -0
- package/dist/.tsbuildinfo +0 -1
- package/dist/create-chat.d.ts +0 -36
- package/dist/create-chat.js +0 -1
- package/dist/desktop-client.d.ts +0 -76
- package/dist/desktop-client.js +0 -1
- package/dist/http.d.ts +0 -20
- package/dist/http.js +0 -1
- package/dist/ipc-client.d.ts +0 -87
- package/dist/ipc-client.js +0 -1
- package/dist/openapi-paths.d.ts +0 -2
- package/dist/openapi-paths.js +0 -1
- package/dist/tools-execute.d.ts +0 -66
- package/dist/tools-execute.js +0 -1
- package/examples/app.js +0 -66
- package/examples/browser.js +0 -72
- package/examples/chat.js +0 -43
- package/examples/mcp.js +0 -74
- package/examples/openai-sdk.js +0 -39
- package/examples/run-all.js +0 -63
- package/examples/shared.js +0 -101
- package/examples/terminal.js +0 -74
package/README.md
CHANGED
|
@@ -9,6 +9,188 @@ MIT-licensed SDK for building against the Aglit AI desktop API and tool runtime.
|
|
|
9
9
|
|
|
10
10
|
> You must have the Aglit AI desktop app/API running locally (localhost). Set `SERVER_PORT`/`PORT`/`AGLIT_DESKTOP_BASE_URL` as needed.
|
|
11
11
|
|
|
12
|
+
## Encrypted private website content
|
|
13
|
+
|
|
14
|
+
The trusted `/_sites/bootstrap` shell can render a normal device-local website
|
|
15
|
+
without exposing its HTML, scripts, assets or HTTP API bodies to the gateway:
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { createAuthenticatedSiteRuntimeFetch, mountEncryptedSite } from '@aglit-ai/sdk/browser';
|
|
19
|
+
|
|
20
|
+
const response = await fetch('/_sites/context', { credentials: 'same-origin', cache: 'no-store' });
|
|
21
|
+
if (!response.ok) throw new Error('Sign in to this site’s team');
|
|
22
|
+
const context = await response.json();
|
|
23
|
+
const runtimeFetch = await createAuthenticatedSiteRuntimeFetch({
|
|
24
|
+
deviceId: context.site.deviceId,
|
|
25
|
+
authenticatedEmail: context.user.email,
|
|
26
|
+
});
|
|
27
|
+
const surface = await mountEncryptedSite(document.querySelector('#site')!, {
|
|
28
|
+
siteName: context.site.name,
|
|
29
|
+
deviceId: context.site.deviceId,
|
|
30
|
+
agentId: context.site.agentId,
|
|
31
|
+
initialPath: new URLSearchParams(location.hash.slice(1)).get('path') ?? '/',
|
|
32
|
+
runtimeFetch,
|
|
33
|
+
});
|
|
34
|
+
// On teardown: await surface.destroy();
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Serve the SDK's standalone `site-worker.js` as the trusted, authenticated
|
|
38
|
+
`/_sites/worker.js`, with `Service-Worker-Allowed: /` and a JavaScript content type.
|
|
39
|
+
Serve the bundled shell code at `/_sites/bootstrap.js`. The shell, worker,
|
|
40
|
+
context and existing `/remote-access/api/...` endpoints remain protected by their
|
|
41
|
+
canonical server authentication and route allowlists. All other site content is
|
|
42
|
+
requested only through the generated `proxyPrivateSiteRequest` operation inside
|
|
43
|
+
the existing signed and encrypted runtime channel. A bare site cookie never
|
|
44
|
+
replaces that channel.
|
|
45
|
+
|
|
46
|
+
The page holds the canonical endpoint crypto; the worker receives no keys. An
|
|
47
|
+
in-memory MessageChannel binds the exact top-level shell, one-use initial iframe
|
|
48
|
+
navigation, and browser-owned child client IDs. It returns decrypted responses
|
|
49
|
+
locally to the iframe. It never fetches site content directly or stores content
|
|
50
|
+
or keys in CacheStorage, IndexedDB, or a service-worker cache. Responses use
|
|
51
|
+
`no-store` and a same-origin CSP; external content requests fail closed. The
|
|
52
|
+
worker leaves only gateway-reserved `/_sites/*` and `/remote-access/api/*`
|
|
53
|
+
requests to their existing authenticated handlers.
|
|
54
|
+
|
|
55
|
+
The persistent shell must stay alive. A closed shell, rejected membership,
|
|
56
|
+
missing endpoint verification, or unavailable crypto returns an error rather
|
|
57
|
+
than plaintext fallback. A worker restart loses client custody, so the shell
|
|
58
|
+
reconnects and reloads a newly owned iframe. Site documents share their site's
|
|
59
|
+
origin and code trust; the iframe is a rendering surface, **not** an isolation
|
|
60
|
+
boundary between the site's own scripts and its Aglit SDK capabilities.
|
|
61
|
+
|
|
62
|
+
Shell links use `/_sites/bootstrap#path=<encoded-local-path>` so application
|
|
63
|
+
paths and queries stay browser-local during worker navigation. Keep secrets out
|
|
64
|
+
of ordinary URLs entered before the worker controls the page, as those initial
|
|
65
|
+
network URLs are necessarily routing metadata.
|
|
66
|
+
|
|
67
|
+
The first version supports bounded HTTP request bodies up to 1 MiB and individual
|
|
68
|
+
responses up to 8 MiB. Open-ended media ranges are bounded to 1 MiB segments.
|
|
69
|
+
Site cookies, worker registrations, external resources, WebSockets and unbounded
|
|
70
|
+
HTTP streams are not forwarded by the content bridge. Use the direct WebRTC
|
|
71
|
+
primitive below for live app/desktop video and input.
|
|
72
|
+
|
|
73
|
+
## Private-site app and desktop streams
|
|
74
|
+
|
|
75
|
+
Browser applications can import `@aglit-ai/sdk/browser` without loading local
|
|
76
|
+
credential-file or IPC helpers. The default SDK entrypoint remains for local
|
|
77
|
+
desktop/server integration.
|
|
78
|
+
|
|
79
|
+
`createDirectRemoteStreamTransport(binding, { baseUrl, runtimeFetch })` connects
|
|
80
|
+
to the existing authenticated direct WebRTC runtime. `mountAppStream`,
|
|
81
|
+
`mountDesktopStream`, and `mountRemoteStream` provide framework-neutral video,
|
|
82
|
+
connection status, and optional pointer/keyboard controls. They use the existing
|
|
83
|
+
OpenAPI-generated signaling routes and direct ICE/TURN media, with the same
|
|
84
|
+
`aglit-input-reliable` and `aglit-input-volatile` input channels as Aglit.
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
import { createAuthenticatedSiteRuntimeFetch, createDirectRemoteStreamTransport, mountAppStream } from '@aglit-ai/sdk/browser';
|
|
88
|
+
|
|
89
|
+
// binding comes from your authorized backend's exact persisted game chat/window:
|
|
90
|
+
// binding: { agentId, deviceId, sessionId, streamId,
|
|
91
|
+
// target: { streamType: 'app', appId, windowId } }
|
|
92
|
+
const response = await fetch('/_sites/context', { credentials: 'same-origin', cache: 'no-store' });
|
|
93
|
+
if (!response.ok) throw new Error('Sign in to this site’s team');
|
|
94
|
+
const context = await response.json();
|
|
95
|
+
if (context.site.deviceId !== binding.deviceId) throw new Error('Game device changed');
|
|
96
|
+
const encryptedRuntimeFetch = await createAuthenticatedSiteRuntimeFetch({
|
|
97
|
+
deviceId: context.site.deviceId,
|
|
98
|
+
authenticatedEmail: context.user.email,
|
|
99
|
+
runtimeSessionId: binding.sessionId,
|
|
100
|
+
});
|
|
101
|
+
const surface = mountAppStream(document.querySelector('#game')!, {
|
|
102
|
+
title: "slurp's up!",
|
|
103
|
+
interactive: true,
|
|
104
|
+
transport: createDirectRemoteStreamTransport(binding, {
|
|
105
|
+
baseUrl: window.location.origin,
|
|
106
|
+
runtimeFetch: encryptedRuntimeFetch,
|
|
107
|
+
captureSpeakerAudio: true,
|
|
108
|
+
}),
|
|
109
|
+
});
|
|
110
|
+
await surface.connect();
|
|
111
|
+
// During component/page cleanup:
|
|
112
|
+
await surface.destroy();
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
For a desktop, use `mountDesktopStream` with
|
|
116
|
+
`target: { streamType: 'desktop', displayId }` and omit `interactive`.
|
|
117
|
+
Desktop streams are view-only in this version: interactive desktop mounting is
|
|
118
|
+
rejected, and the direct transport rejects desktop control/input. Display video
|
|
119
|
+
pixels can differ from logical native coordinates on Retina or scaled captures;
|
|
120
|
+
desktop control requires the canonical verified logical display-bounds mapping.
|
|
121
|
+
Supply a real persisted chat
|
|
122
|
+
session, the original registered device, and an exact enumerated app window or
|
|
123
|
+
display authorized by the backend. IDs select a target; they never grant access.
|
|
124
|
+
The primitive does not launch apps or create account, team, or device grants.
|
|
125
|
+
|
|
126
|
+
`createAuthenticatedSiteRuntimeFetch` enrolls this browser through the existing
|
|
127
|
+
runtime auth/key flow. Obtain its account and device from authenticated
|
|
128
|
+
`/_sites/context`, never a URL claim. It reuses canonical nonextractable browser
|
|
129
|
+
keys, device identity verification and existing managed pins or fingerprint
|
|
130
|
+
confirmation UI. A configured computer verification code is requested through
|
|
131
|
+
a real code dialog; denied access and API-key requirements remain failures.
|
|
132
|
+
The separate site cookie stays HttpOnly. No cookie or device key is copied into
|
|
133
|
+
application JavaScript. The optional `runtimeSessionId` is an existing task/chat
|
|
134
|
+
used to select the serving runtime generation; the auth flow allocates its own
|
|
135
|
+
separate crypto session.
|
|
136
|
+
|
|
137
|
+
The resulting **authenticated, encrypted runtime fetch** receives the unchanged
|
|
138
|
+
generated `/remote-access/api/...` URLs on the site
|
|
139
|
+
origin. The site gateway preserves their exact paths and queries, including
|
|
140
|
+
URL-bound encryption proofs; it never rewrites them behind another API prefix.
|
|
141
|
+
Passing ordinary `fetch` with a site cookie does not establish that runtime
|
|
142
|
+
session. No broad local SDK token, browser cookie export, or provider-terminated
|
|
143
|
+
media fallback is introduced.
|
|
144
|
+
|
|
145
|
+
The adapter signs exact encrypted bytes and URLs with the canonical v2 proof,
|
|
146
|
+
then accepts only authenticated nonce-bound successful responses. It has one
|
|
147
|
+
account/device scope per page; reload after account, device or credential changes.
|
|
148
|
+
|
|
149
|
+
App input is off by default. With `interactive: true`, the user explicitly selects
|
|
150
|
+
**Take control** after the authorized direct input channel opens. Pointer input
|
|
151
|
+
is mapped to the contained video rather than its letterbox. The default mode
|
|
152
|
+
sends the canonical complete `keyEvent: press` gestures, including
|
|
153
|
+
browser keyboard repeats, and complete clicks or left-button drags on pointer
|
|
154
|
+
release. Interrupted pointer gestures are cancelled locally. It never leaves a
|
|
155
|
+
native key or button waiting for a later release from a vanished viewer.
|
|
156
|
+
|
|
157
|
+
For games that need continuous movement, explicitly set `keyboardMode: 'hold'`.
|
|
158
|
+
Connection then requires the actual packaged native helper's advertised app
|
|
159
|
+
held-key capability. It sends existing `down`/`up` events with one `keyHoldId`
|
|
160
|
+
per physical hold; `keyHoldRenew: true` renewals preserve that identity and never repeat key-down
|
|
161
|
+
callbacks. Simultaneous keys remain down together. Renewal runs every 250 ms
|
|
162
|
+
only while the video has focus, the page is visible, and this surface has control.
|
|
163
|
+
Blur, hidden pages, key-up and teardown stop renewal before sending releases.
|
|
164
|
+
Queued down/renew packets expire before native admission; a renewal cannot
|
|
165
|
+
create a hold. Native down/renew also requires the captured window to remain
|
|
166
|
+
the foreground app's exact focused window, without focusing or changing that window.
|
|
167
|
+
|
|
168
|
+
The native helper holds one exclusive app-keyboard owner per process,
|
|
169
|
+
bound to its process birth and admitted exact window. App input and global
|
|
170
|
+
keyboard events from another viewer cannot release or interrupt those keys.
|
|
171
|
+
Existing authorized desktop pointer control may change focus; that stops app
|
|
172
|
+
key renewal. A missing renewal expires its two-second native
|
|
173
|
+
lease, checked every 100 ms; helper EOF/orderly shutdown also releases them. Cleanup uses the
|
|
174
|
+
captured process identity and never focuses or resolves a replacement app.
|
|
175
|
+
Expired/released hold IDs cannot be renewed into a new hold. Older runtimes
|
|
176
|
+
reject held mode; they continue to support viewing and complete presses.
|
|
177
|
+
Native activation and real game acceptance still require the new signed helper.
|
|
178
|
+
An abrupt helper crash, SIGKILL or a suspended native process cannot run cleanup;
|
|
179
|
+
the expiry guarantee requires the native helper to remain scheduled and healthy.
|
|
180
|
+
Live button-held dragging and standalone modifier holds remain unsupported.
|
|
181
|
+
Audio starts muted to respect browser playback requirements; a site can expose
|
|
182
|
+
its own sound control using `surface.video.muted`. All viewers currently share
|
|
183
|
+
the same running app and player state. Native held mode admits one input owner while
|
|
184
|
+
keys are held; the Take control button itself grants no additional authority.
|
|
185
|
+
|
|
186
|
+
Call `surface.destroy()` on unmount to abort signaling, cancel pending input, and
|
|
187
|
+
delete only this exact viewer session. An auth/signaling failure closes the
|
|
188
|
+
peer; create a new surface after restoring the authorized runtime session.
|
|
189
|
+
Offer creation and local SDP readiness are bounded separately inside the full
|
|
190
|
+
60-second startup deadline, matching the web viewer's browser compatibility path.
|
|
191
|
+
|
|
192
|
+
See `examples/site-game.ts` for the minimal game wrapper.
|
|
193
|
+
|
|
12
194
|
## Install
|
|
13
195
|
|
|
14
196
|
```bash
|
|
@@ -94,6 +276,10 @@ socket config.
|
|
|
94
276
|
|
|
95
277
|
Always include `x_aglit_ai_tool_reason` and pass structured arguments rather than raw shell strings. The IPC broker
|
|
96
278
|
also enforces the same tool policies you see in the UI, including approval flows and logging.
|
|
279
|
+
Scripts started from an Aglit chat terminal inherit `AGLIT_AGENT_ID`, `AGLIT_SESSION_ID`, and
|
|
280
|
+
`AGLIT_SDK_MODULE_PATH`. Load the bundled SDK with `require(process.env.AGLIT_SDK_MODULE_PATH)`
|
|
281
|
+
to avoid an older workspace copy. `executeTool` uses the inherited session ID automatically; an
|
|
282
|
+
explicit request `_meta.sessionId` takes precedence.
|
|
97
283
|
|
|
98
284
|
## Examples
|
|
99
285
|
|
|
@@ -140,67 +326,23 @@ await executeTool({
|
|
|
140
326
|
|
|
141
327
|
### Browser Automation
|
|
142
328
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
request: {
|
|
148
|
-
jsonrpc: '2.0',
|
|
149
|
-
id: 'browser-nav',
|
|
150
|
-
params: {
|
|
151
|
-
name: 'p1_browser',
|
|
152
|
-
arguments: {
|
|
153
|
-
action: 'navigate',
|
|
154
|
-
url: 'https://example.com',
|
|
155
|
-
x_aglit_ai_tool_reason: 'SDK example: warm up page',
|
|
156
|
-
},
|
|
157
|
-
},
|
|
158
|
-
context: { sessionId: 'sdk-browser', agentId: 'root-agent' },
|
|
159
|
-
},
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
const windowId = (nav.data?.result as any)?.windowId as string;
|
|
163
|
-
|
|
164
|
-
// Inject JavaScript in that session
|
|
165
|
-
await executeTool({
|
|
166
|
-
agentId: 'root-agent',
|
|
167
|
-
request: {
|
|
168
|
-
jsonrpc: '2.0',
|
|
169
|
-
id: 'browser-js',
|
|
170
|
-
params: {
|
|
171
|
-
name: 'p1_browser',
|
|
172
|
-
arguments: {
|
|
173
|
-
action: 'execute_javascript',
|
|
174
|
-
windowId,
|
|
175
|
-
code: 'document.title',
|
|
176
|
-
x_aglit_ai_tool_reason: 'SDK example: read page title',
|
|
177
|
-
},
|
|
178
|
-
},
|
|
179
|
-
context: { sessionId: 'sdk-browser', agentId: 'root-agent' },
|
|
180
|
-
},
|
|
181
|
-
});
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
### Office App Automations (macOS)
|
|
329
|
+
Use the SDK compatibility adapter for structured browser actions. The adapter executes
|
|
330
|
+
only `p1_codex_browser` registry calls, preserves chat authorization and approvals,
|
|
331
|
+
and returns the exact native tab ID. Page evaluation is read-only; use native
|
|
332
|
+
click/fill actions to change a page.
|
|
185
333
|
|
|
186
334
|
```ts
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
id: 'app-01',
|
|
192
|
-
params: {
|
|
193
|
-
name: 'p1_office',
|
|
194
|
-
arguments: {
|
|
195
|
-
tool: 'app',
|
|
196
|
-
app: 'calendar',
|
|
197
|
-
action: 'list',
|
|
198
|
-
x_aglit_ai_tool_reason: 'SDK example: list calendar events',
|
|
199
|
-
},
|
|
200
|
-
},
|
|
201
|
-
context: { sessionId: 'sdk-app', agentId: 'root-agent' },
|
|
202
|
-
},
|
|
335
|
+
import { executeNativeControl, unwrapNativeControlResult } from '@aglit-ai/sdk';
|
|
336
|
+
|
|
337
|
+
const call = (args: Record<string, unknown>, reason: string) => executeNativeControl({
|
|
338
|
+
toolName: 'p1_codex_browser', agentId: 'root-agent', sessionId: 'sdk-browser', args, reason,
|
|
203
339
|
});
|
|
340
|
+
const nav = unwrapNativeControlResult(await call(
|
|
341
|
+
{ action: 'navigate', url: 'https://example.com' }, 'Open example.com'
|
|
342
|
+
));
|
|
343
|
+
if (!nav?.tabId) throw new Error('Native browser returned no exact tab ID');
|
|
344
|
+
await call({ action: 'execute_javascript', tabId: nav.tabId, code: 'document.title' },
|
|
345
|
+
'Read the page title');
|
|
204
346
|
```
|
|
205
347
|
|
|
206
348
|
### Create Chat Sessions
|
|
@@ -240,3 +382,39 @@ The SDK resolves the current OpenAPI source files from `@aglit-ai/types`:
|
|
|
240
382
|
- Desktop API: `@aglit-ai/types/schema/api.openapi.yaml`
|
|
241
383
|
- Tool Builder API: `@aglit-ai/types/schema/tools-api.openapi.yaml`
|
|
242
384
|
- Provider SPI API: `@aglit-ai/types/schema/provider-spi.openapi.yaml`
|
|
385
|
+
|
|
386
|
+
## Native control migration
|
|
387
|
+
|
|
388
|
+
`executeNativeControl({toolName, args, reason, agentId, sessionId})` adapts structured
|
|
389
|
+
custom-tool browser/app actions to `p1_codex_browser` and `p1_codex_computer`. Existing
|
|
390
|
+
native execute/capture/stream/focus calls pass through. The retired IDs remain rejected.
|
|
391
|
+
|
|
392
|
+
```ts
|
|
393
|
+
import { executeNativeControl } from '@aglit-ai/sdk';
|
|
394
|
+
const result = await executeNativeControl({
|
|
395
|
+
toolName: 'p1_codex_browser',
|
|
396
|
+
args: {action: 'navigate', url: 'https://example.com'},
|
|
397
|
+
reason: 'Open the requested example page',
|
|
398
|
+
agentId, sessionId,
|
|
399
|
+
});
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
The adapter keeps exact native targets, preserves typing/submit flags, returns original
|
|
403
|
+
proof and familiar result fields, and never replays an uncertain mutation. Page evaluation
|
|
404
|
+
is read-only. Authored DOM input plans use `aglitNativeClick(element)` and
|
|
405
|
+
`aglitNativeFill(element, text)` during inspection; the adapter performs those actions
|
|
406
|
+
through native input APIs afterward. No page mutation, CDP or terminal fallback is used.
|
|
407
|
+
Custom runtimes package this same SDK adapter locally, so they need no new SDK dependency.
|
|
408
|
+
|
|
409
|
+
Native control still requires the agent's existing unrestricted profiles and explicit
|
|
410
|
+
access. Upload/file permissions remain separate native grants. Downloads return a saved
|
|
411
|
+
path directly; old download progress stream IDs are unsupported. App window requests are
|
|
412
|
+
verified against the private capture receipt before input; ambiguous/mismatched targets
|
|
413
|
+
fail. Encoded recording and some legacy desktop-only APIs have no native equivalent.
|
|
414
|
+
|
|
415
|
+
## Build and deployment
|
|
416
|
+
|
|
417
|
+
Run `pnpm run build` before `pnpm run deploy`. Deploy requires the compiled
|
|
418
|
+
entrypoints and bundled OpenAPI schemas, then publishes the already built SDK
|
|
419
|
+
using the version committed in `package.json` and existing registry credentials.
|
|
420
|
+
Deploy does not rebuild, bump versions or launch an interactive registry login.
|
package/browser.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './dist/browser';
|
package/browser.js
ADDED