@hypercli.com/sdk 0.9.1

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 (193) hide show
  1. package/README.md +629 -0
  2. package/dist/acp-driver.d.ts +72 -0
  3. package/dist/acp-driver.d.ts.map +1 -0
  4. package/dist/acp-driver.js +147 -0
  5. package/dist/acp-driver.js.map +1 -0
  6. package/dist/acp-pool.d.ts +70 -0
  7. package/dist/acp-pool.d.ts.map +1 -0
  8. package/dist/acp-pool.js +181 -0
  9. package/dist/acp-pool.js.map +1 -0
  10. package/dist/acp.d.ts +179 -0
  11. package/dist/acp.d.ts.map +1 -0
  12. package/dist/acp.js +487 -0
  13. package/dist/acp.js.map +1 -0
  14. package/dist/agent-persona.d.ts +68 -0
  15. package/dist/agent-persona.d.ts.map +1 -0
  16. package/dist/agent-persona.js +78 -0
  17. package/dist/agent-persona.js.map +1 -0
  18. package/dist/agent-slots.d.ts +18 -0
  19. package/dist/agent-slots.d.ts.map +1 -0
  20. package/dist/agent-slots.js +24 -0
  21. package/dist/agent-slots.js.map +1 -0
  22. package/dist/agent-urls.d.ts +47 -0
  23. package/dist/agent-urls.d.ts.map +1 -0
  24. package/dist/agent-urls.js +178 -0
  25. package/dist/agent-urls.js.map +1 -0
  26. package/dist/agent.d.ts +482 -0
  27. package/dist/agent.d.ts.map +1 -0
  28. package/dist/agent.js +926 -0
  29. package/dist/agent.js.map +1 -0
  30. package/dist/agents.d.ts +1452 -0
  31. package/dist/agents.d.ts.map +1 -0
  32. package/dist/agents.js +4022 -0
  33. package/dist/agents.js.map +1 -0
  34. package/dist/billing.d.ts +72 -0
  35. package/dist/billing.d.ts.map +1 -0
  36. package/dist/billing.js +93 -0
  37. package/dist/billing.js.map +1 -0
  38. package/dist/browser-jobs.d.ts +24 -0
  39. package/dist/browser-jobs.d.ts.map +1 -0
  40. package/dist/browser-jobs.js +209 -0
  41. package/dist/browser-jobs.js.map +1 -0
  42. package/dist/browser.d.ts +41 -0
  43. package/dist/browser.d.ts.map +1 -0
  44. package/dist/browser.js +57 -0
  45. package/dist/browser.js.map +1 -0
  46. package/dist/buzz-activity.d.ts +169 -0
  47. package/dist/buzz-activity.d.ts.map +1 -0
  48. package/dist/buzz-activity.js +844 -0
  49. package/dist/buzz-activity.js.map +1 -0
  50. package/dist/channels.d.ts +99 -0
  51. package/dist/channels.d.ts.map +1 -0
  52. package/dist/channels.js +27 -0
  53. package/dist/channels.js.map +1 -0
  54. package/dist/chat-integrations.d.ts +44 -0
  55. package/dist/chat-integrations.d.ts.map +1 -0
  56. package/dist/chat-integrations.js +138 -0
  57. package/dist/chat-integrations.js.map +1 -0
  58. package/dist/client.d.ts +88 -0
  59. package/dist/client.d.ts.map +1 -0
  60. package/dist/client.js +144 -0
  61. package/dist/client.js.map +1 -0
  62. package/dist/config.d.ts +44 -0
  63. package/dist/config.d.ts.map +1 -0
  64. package/dist/config.js +192 -0
  65. package/dist/config.js.map +1 -0
  66. package/dist/connectors.d.ts +80 -0
  67. package/dist/connectors.d.ts.map +1 -0
  68. package/dist/connectors.js +2 -0
  69. package/dist/connectors.js.map +1 -0
  70. package/dist/errors.d.ts +16 -0
  71. package/dist/errors.d.ts.map +1 -0
  72. package/dist/errors.js +26 -0
  73. package/dist/errors.js.map +1 -0
  74. package/dist/files.d.ts +60 -0
  75. package/dist/files.d.ts.map +1 -0
  76. package/dist/files.js +128 -0
  77. package/dist/files.js.map +1 -0
  78. package/dist/http.d.ts +56 -0
  79. package/dist/http.d.ts.map +1 -0
  80. package/dist/http.js +362 -0
  81. package/dist/http.js.map +1 -0
  82. package/dist/index.d.ts +49 -0
  83. package/dist/index.d.ts.map +1 -0
  84. package/dist/index.js +64 -0
  85. package/dist/index.js.map +1 -0
  86. package/dist/instances.d.ts +94 -0
  87. package/dist/instances.d.ts.map +1 -0
  88. package/dist/instances.js +197 -0
  89. package/dist/instances.js.map +1 -0
  90. package/dist/integrations.d.ts +111 -0
  91. package/dist/integrations.d.ts.map +1 -0
  92. package/dist/integrations.js +206 -0
  93. package/dist/integrations.js.map +1 -0
  94. package/dist/job/base.d.ts +86 -0
  95. package/dist/job/base.d.ts.map +1 -0
  96. package/dist/job/base.js +206 -0
  97. package/dist/job/base.js.map +1 -0
  98. package/dist/job/comfyui.d.ts +259 -0
  99. package/dist/job/comfyui.d.ts.map +1 -0
  100. package/dist/job/comfyui.js +1563 -0
  101. package/dist/job/comfyui.js.map +1 -0
  102. package/dist/job/gradio.d.ts +48 -0
  103. package/dist/job/gradio.d.ts.map +1 -0
  104. package/dist/job/gradio.js +90 -0
  105. package/dist/job/gradio.js.map +1 -0
  106. package/dist/job-codecs.d.ts +66 -0
  107. package/dist/job-codecs.d.ts.map +1 -0
  108. package/dist/job-codecs.js +132 -0
  109. package/dist/job-codecs.js.map +1 -0
  110. package/dist/jobs.d.ts +148 -0
  111. package/dist/jobs.d.ts.map +1 -0
  112. package/dist/jobs.js +480 -0
  113. package/dist/jobs.js.map +1 -0
  114. package/dist/keys.d.ts +99 -0
  115. package/dist/keys.d.ts.map +1 -0
  116. package/dist/keys.js +145 -0
  117. package/dist/keys.js.map +1 -0
  118. package/dist/logs.d.ts +54 -0
  119. package/dist/logs.d.ts.map +1 -0
  120. package/dist/logs.js +256 -0
  121. package/dist/logs.js.map +1 -0
  122. package/dist/managed-context.d.ts +20 -0
  123. package/dist/managed-context.d.ts.map +1 -0
  124. package/dist/managed-context.js +95 -0
  125. package/dist/managed-context.js.map +1 -0
  126. package/dist/mcp.d.ts +7 -0
  127. package/dist/mcp.d.ts.map +1 -0
  128. package/dist/mcp.js +8 -0
  129. package/dist/mcp.js.map +1 -0
  130. package/dist/memory.d.ts +87 -0
  131. package/dist/memory.d.ts.map +1 -0
  132. package/dist/memory.js +79 -0
  133. package/dist/memory.js.map +1 -0
  134. package/dist/models.d.ts +15 -0
  135. package/dist/models.d.ts.map +1 -0
  136. package/dist/models.js +19 -0
  137. package/dist/models.js.map +1 -0
  138. package/dist/openclaw-control-ui-origin.d.ts +23 -0
  139. package/dist/openclaw-control-ui-origin.d.ts.map +1 -0
  140. package/dist/openclaw-control-ui-origin.js +53 -0
  141. package/dist/openclaw-control-ui-origin.js.map +1 -0
  142. package/dist/renders.d.ts +187 -0
  143. package/dist/renders.d.ts.map +1 -0
  144. package/dist/renders.js +360 -0
  145. package/dist/renders.js.map +1 -0
  146. package/dist/routines.d.ts +59 -0
  147. package/dist/routines.d.ts.map +1 -0
  148. package/dist/routines.js +135 -0
  149. package/dist/routines.js.map +1 -0
  150. package/dist/runners.d.ts +61 -0
  151. package/dist/runners.d.ts.map +1 -0
  152. package/dist/runners.js +127 -0
  153. package/dist/runners.js.map +1 -0
  154. package/dist/sessions.d.ts +280 -0
  155. package/dist/sessions.d.ts.map +1 -0
  156. package/dist/sessions.js +292 -0
  157. package/dist/sessions.js.map +1 -0
  158. package/dist/skills.d.ts +170 -0
  159. package/dist/skills.d.ts.map +1 -0
  160. package/dist/skills.js +2 -0
  161. package/dist/skills.js.map +1 -0
  162. package/dist/user.d.ts +78 -0
  163. package/dist/user.d.ts.map +1 -0
  164. package/dist/user.js +143 -0
  165. package/dist/user.js.map +1 -0
  166. package/dist/version.d.ts +2 -0
  167. package/dist/version.d.ts.map +1 -0
  168. package/dist/version.js +3 -0
  169. package/dist/version.js.map +1 -0
  170. package/dist/voice-session.d.ts +66 -0
  171. package/dist/voice-session.d.ts.map +1 -0
  172. package/dist/voice-session.js +366 -0
  173. package/dist/voice-session.js.map +1 -0
  174. package/dist/voice-transcription-session.d.ts +64 -0
  175. package/dist/voice-transcription-session.d.ts.map +1 -0
  176. package/dist/voice-transcription-session.js +228 -0
  177. package/dist/voice-transcription-session.js.map +1 -0
  178. package/dist/voice.d.ts +62 -0
  179. package/dist/voice.d.ts.map +1 -0
  180. package/dist/voice.js +134 -0
  181. package/dist/voice.js.map +1 -0
  182. package/dist/workspace-tomd.d.ts +61 -0
  183. package/dist/workspace-tomd.d.ts.map +1 -0
  184. package/dist/workspace-tomd.js +177 -0
  185. package/dist/workspace-tomd.js.map +1 -0
  186. package/dist/workspaces.d.ts +255 -0
  187. package/dist/workspaces.d.ts.map +1 -0
  188. package/dist/workspaces.js +653 -0
  189. package/dist/workspaces.js.map +1 -0
  190. package/package.json +115 -0
  191. package/runtime/config-require.browser.js +4 -0
  192. package/runtime/config-require.d.ts +2 -0
  193. package/runtime/config-require.node.js +8 -0
package/README.md ADDED
@@ -0,0 +1,629 @@
1
+ # @hypercli.com/sdk
2
+
3
+ TypeScript SDK for HyperCLI API - GPU cloud compute made simple.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @hypercli.com/sdk
9
+ ```
10
+
11
+ **Dependencies:**
12
+ - `ws` - WebSocket client for log streaming
13
+ - Node.js 18+ (uses native `fetch`)
14
+
15
+ ## Vanilla ACP v1 (breaking API change)
16
+
17
+ ACP permission callbacks (`onPermissionRequest`, `setPermissionHandler`) and the
18
+ exported `RequestPermissionRequest` use the upstream v1 shape: `request.toolCall`.
19
+ All offered permission options reach the callback, including unfamiliar kinds.
20
+ Without a handler,
21
+ the SDK answers `cancelled`; it never chooses a permission automatically.
22
+
23
+ Session setup and configuration retain native v1 shapes, including
24
+ `configOptions[].id` and native `modes`. `setConfigOption(sessionId, option.id, value)`
25
+ sends the standard v1 request. Optional runtime capabilities are not guaranteed.
26
+
27
+ Concurrent `prompt` calls each own their correlated native terminal result.
28
+ They do not require REST receipts, and uncertain input is never resent.
29
+ Use `AcpTurnDriver` when the consumer wants serialized turns.
30
+
31
+ ## Quick Start
32
+
33
+ ```typescript
34
+ import { HyperCLI } from '@hypercli.com/sdk';
35
+
36
+ // Initialize client (uses HYPER_API_KEY from env or ~/.hypercli/config)
37
+ const client = new HyperCLI();
38
+
39
+ // Or pass API key directly
40
+ const client = new HyperCLI({ apiKey: 'your_key' });
41
+
42
+ // Check balance
43
+ const balance = await client.billing.balance();
44
+ console.log(`Balance: $${balance.total}`);
45
+
46
+ // Launch a GPU job
47
+ const job = await client.jobs.create({
48
+ image: 'nvidia/cuda:12.0-runtime-ubuntu22.04',
49
+ gpuType: 'l40s',
50
+ gpuCount: 1,
51
+ command: 'python train.py',
52
+ dryRun: true,
53
+ env: { MODEL: 'llama-3' },
54
+ });
55
+
56
+ console.log(`Job started: ${job.jobId}`);
57
+ console.log(`Hostname: ${job.hostname}`);
58
+ ```
59
+
60
+ ## Configuration
61
+
62
+ Set your API key via:
63
+ 1. Environment variable: `export HYPER_API_KEY=your_key`
64
+ 2. Config file: `~/.hypercli/config`
65
+ 3. Constructor: `new HyperCLI({ apiKey: 'your_key' })`
66
+
67
+ ```typescript
68
+ import { configure } from '@hypercli.com/sdk';
69
+
70
+ // Save to ~/.hypercli/config
71
+ configure('your_api_key');
72
+ ```
73
+
74
+ ## Examples
75
+
76
+ ### Platform session metadata
77
+
78
+ ```typescript
79
+ // The platform ID returned by /ws/acp session/new or the REST session catalog.
80
+ const session = await client.sessions.getSession(platformSessionId);
81
+ console.log(session.source, session.summaryText, session.participants);
82
+ ```
83
+
84
+ Returns the `AcpSessionState` shape — the `AcpSessionRecord` catalog record
85
+ extended with `importOutcome` and platform history state (`lastMessageId`,
86
+ `messageCount`, `headSeq`, per-message `receipts`). This calls
87
+ `GET /agents/sessions/{id}` with the current caller's credentials;
88
+ runtime/leg IDs are not resolved. `source` is `string | null` and unknown values
89
+ are preserved. It reads stored metadata even while the agent is offline, without
90
+ connecting to the runtime. It advances the caller's user read receipt to the
91
+ session head; transcript pages use `getMessages` independently of ACP.
92
+ HTTP errors propagate as
93
+ `APIError`: 404 unknown session, 403 outside participation scope, 422 invalid UUID.
94
+
95
+ ### Complete history pages
96
+
97
+ ```typescript
98
+ const page = await client.sessions.getMessages(platformSessionId, { limit: 20 });
99
+ // { items: AcpSessionMessage[], nextCursor: string | null,
100
+ // hasMore: boolean, importOutcome: SessionImportOutcome | null }
101
+ const older = page.hasMore
102
+ ? await client.sessions.getMessages(platformSessionId, { cursor: page.nextCursor })
103
+ : null;
104
+ ```
105
+
106
+ This canonical helper normalizes platform DTO fields only. Native v1 ACP payloads,
107
+ message/tool IDs, complete non-binary tool fields, and separate platform identities
108
+ are retained. Rows are descending by sequence; readers fold ascending. The default
109
+ limit is 20, a target the server may extend for chunk runs and transitive tool
110
+ creation dependencies. The opaque cursor reads strictly older rows.
111
+
112
+ A page is delivered as one coherent result; it is not a transaction with a live
113
+ subscription and promises no zero-gap boundary. Keep fetched history and live
114
+ notifications independently owned. No SDK renderer, compatibility decoder, replay
115
+ cache, or ACP pagination extension is involved.
116
+
117
+ ### Billing
118
+
119
+ ```typescript
120
+ const balance = await client.billing.balance();
121
+ const txs = await client.billing.transactions(limit: 10);
122
+ ```
123
+
124
+ ### Jobs
125
+
126
+ ```typescript
127
+ // List running jobs
128
+ const jobs = await client.jobs.list('running');
129
+
130
+ // Get job details
131
+ const job = await client.jobs.get(jobId);
132
+
133
+ // Cancel job
134
+ await client.jobs.cancel(jobId);
135
+
136
+ // Get logs
137
+ const logs = await client.jobs.logs(jobId);
138
+
139
+ // Get metrics
140
+ const metrics = await client.jobs.metrics(jobId);
141
+
142
+ // Non-interactive exec
143
+ const execResult = await client.jobs.exec(jobId, ['nvidia-smi']);
144
+
145
+ // Interactive shell WebSocket
146
+ const ws = await client.jobs.shellConnect(jobId, '/bin/bash');
147
+ ws.close();
148
+ ```
149
+
150
+ ### Agents Exec/Shell
151
+
152
+ ```typescript
153
+ const models = await client.agent.models();
154
+ const activation = await client.agent.redeemGrantCode('PROMO123');
155
+ const renewal = await client.agent.redeemGrantCode('PROMO123', { extendExisting: true });
156
+
157
+ // Execute command in a hypercli-openclaw agent container
158
+ const agentExec = await client.agents.exec(agentId, ['ls', '-la']);
159
+
160
+ // One live Reef metrics sample
161
+ const agentMetrics = await client.agents.metrics(agentId);
162
+
163
+ // Interactive shell for a hypercli-openclaw agent
164
+ const agentWs = await client.agents.shellConnect(agentId);
165
+ agentWs.close();
166
+ ```
167
+
168
+ ### Account Avatar and Per-Agent Usage
169
+
170
+ ```typescript
171
+ const currentAvatar = await client.user.getProfileImage();
172
+ const updatedAvatar = await client.user.uploadProfileImage(imageBlob);
173
+ await client.user.deleteProfileImage();
174
+
175
+ const dailyByAgent = await client.agent.agentUsage(1);
176
+ ```
177
+
178
+ Agent payloads also carry per-agent identity media: `Agent.avatarUrl` and, when
179
+ a voice reference has been uploaded, `Agent.avatarAudioUrl` (hydrated from the
180
+ backend's `avatar_audio_url`, mirroring `avatarUrl`; `null` when unset).
181
+
182
+ Plan IDs remain open strings so future and historical IDs keep parsing.
183
+ `plan.canonicalId` recognizes the current `solo`, `team`, and `pro` IDs.
184
+ Use the agents entitlement summary—not Orchestra `auth_me`—for plan access:
185
+
186
+ ```typescript
187
+ import { hasActivePlan } from '@hypercli.com/sdk';
188
+
189
+ const summary = await client.agent.subscriptionSummary();
190
+ if (hasActivePlan(summary)) { // subscription OR direct entitlement
191
+ console.log(summary.agentSlots);
192
+ }
193
+ ```
194
+
195
+ A `401` or `403` from the summary means the selected key cannot determine plan
196
+ state. Consumers should represent that as unknown, never as an explicit no.
197
+
198
+ ### OpenClaw Agents
199
+
200
+ OpenClaw uses the generic deployment launch surface. `registryUrl`,
201
+ `registryAuth`, and `syncRoot` are generic deployment options. A nonblank
202
+ `syncRoot` enables Reef persistence. On generic create, no include/exclude
203
+ policy means the complete root; `syncExclude: []` also excludes nothing.
204
+ `syncInclude: []` and root-wide excludes such as `syncExclude: ["*"]` are
205
+ invalid.
206
+ Steady Reef synchronization is PVC-to-object-storage upload/overwrite, not a
207
+ two-way mirror: ordinary filesystem deletes are not propagated, and
208
+ remote-to-PVC copying occurs only during explicit cold restore. Files API
209
+ operations obtain a fresh files-scoped credential from Backend and then call
210
+ the retained Reef server directly; Backend never carries file bytes.
211
+ Per-file writes are limited to 100 MiB (`AGENT_FILE_WRITE_MAX_BYTES`, the
212
+ Cloudflare edge request-body cap on the agent hostname); split larger data
213
+ across files or sync it via the agent's own tooling. File
214
+ paths are relative to `syncRoot`, and `filesList("")` lists the complete root, including
215
+ dot-directories. The OpenClaw helpers add concrete
216
+ image, `syncRoot: "/home/node"`, and cache/Workspace exclusions by default;
217
+ there is no public `openclaw` route (the pod gateway binds loopback with auth
218
+ mode `none` as an ACP hop only; desktop configuration adds the protected route).
219
+ Regular OpenClaw defaults to `ghcr.io/hypercli/hypercli-openclaw:prod`;
220
+ Desktop support uses the same OpenClaw image with explicit environment and routes.
221
+ Coding helpers instead inject the runtime-specific include defaults
222
+ documented in
223
+ [`coding-runtimes.mdx`](../docs/agents/coding-runtimes.mdx); pass an explicit
224
+ nullable policy at create time to select the whole root.
225
+ Both helper families default `HYPER_WORKSPACES_DIR` to `/home/node/shared` and
226
+ preserve an explicit value supplied in the launch `env`.
227
+
228
+ ```typescript
229
+ const launchConfig = buildAgentConfig({}, {
230
+ image: 'ghcr.io/example/agent:latest',
231
+ registryUrl: 'registry.example.com',
232
+ registryAuth: { username: 'ci', password: 'token' },
233
+ }).config;
234
+ const agent = await client.deployments.create({
235
+ name: 'docs-demo',
236
+ image: launchConfig.image,
237
+ registryUrl: launchConfig.registry_url,
238
+ registryAuth: launchConfig.registry_auth,
239
+ });
240
+ await client.deployments.waitForState(agent.id, ['STOPPED'], 330_000);
241
+ await client.deployments.update(agent.id, { launchConfig });
242
+ await client.deployments.start(agent.id);
243
+ const running = await client.deployments.waitForState(
244
+ agent.id,
245
+ ['RUNNING'],
246
+ 300_000,
247
+ ['FAILED'],
248
+ );
249
+
250
+ const capacity = await client.deployments.listWithCapacity();
251
+ console.log(capacity.maxAgentsPerAccount, capacity.runningAgents);
252
+ for (const slot of capacity.agentSlots) {
253
+ console.log(slot.size, slot.planId, slot.agentId);
254
+ }
255
+ ```
256
+
257
+ `start()` starts the Backend-stored launch config. Change
258
+ launch settings through `update(..., { launchConfig })` before starting.
259
+ `start()` does not accept launch mutation options such as
260
+ `launchConfig`, `controlUiAllowedOrigins`, or `trustedProxies`.
261
+
262
+ `archive()` returns the accepted `ARCHIVING` Agent projection. `delete()` uses
263
+ HTTP 200 to accept a durable soft delete; cluster-local cleanup continues in
264
+ the background, so that response is not cleanup completion.
265
+
266
+ `list()` remains the compatibility array. `listWithCapacity()` preserves the
267
+ full deployment response: saved/running account limits, pooled TPD, aggregate
268
+ slot inventory, and individual entitlement-backed agent slots.
269
+
270
+ Deployment lifecycle snapshots use an open-string `state`. `reason` is the
271
+ stable cause of a transition, such as `start`,
272
+ `api_stop`, `runtime_exit`, `timeout`, or `delete`; `error` is populated for a
273
+ failed transition, while `message` is human-readable context. Consumers should
274
+ not bind these strings to a closed client-side enum.
275
+
276
+ Canonical states are `CREATING`, `STARTING`, `RESTORING`, `RUNNING`, `STOPPING`,
277
+ `STOPPED`, `ARCHIVING`, `ARCHIVED`, `FAILED`, and `DELETED`. `CREATING` is fresh
278
+ admission, `STARTING` resumes a warm retained agent, and `RESTORING` hydrates a
279
+ cold agent from its exact archive checkpoint.
280
+ `STOPPED` is warm and `ARCHIVING` is transitional. `ARCHIVED` is the
281
+ Backend-persisted, cold-restorable terminal projection after Lagoon drops its
282
+ agent task, namespace, PVC, and local S3 copy. `DELETED` is a Backend-only
283
+ terminal state and normally absent from user reads.
284
+
285
+ For a long-lived UI, subscribe to thin invalidations and refresh REST in the
286
+ handler:
287
+
288
+ ```typescript
289
+ const controller = new AbortController();
290
+ const subscription = client.deployments.subscribe(async () => {
291
+ render(await client.deployments.list());
292
+ }, {
293
+ signal: controller.signal,
294
+ onReady: async () => render(await client.deployments.list()),
295
+ });
296
+
297
+ // During application teardown:
298
+ controller.abort();
299
+ await subscription;
300
+ ```
301
+
302
+ Abort during teardown. `onReady` runs after user-stream authentication and
303
+ before event frames are read; it repeats that order after reconnect.
304
+ Transition events carry `agent_id` for local filtering plus `state`, `reason`,
305
+ `error`, and `message`, but are not snapshots and may be duplicated or
306
+ coalesced; refresh REST for authority.
307
+
308
+ Use `createAgent('openclaw_acp', { env: { HYPER_DESKTOP_ENABLED: '1' }, openClawRoutes: { includeDesktop: true } })` to enable desktop/browser access on the standard image. The protected noVNC route is `desktop-<agent>.hypercli.app`.
309
+
310
+ For a running desktop-enabled agent, `client.deployments.desktopUrl(id)` returns
311
+ a JWT-signed URL that logs straight into the noVNC page: it builds
312
+ `<base>/_jwt_auth?jwt=…&redirect=vnc_lite.html`. `vnc_lite.html` is the default
313
+ redirect target (immediate RFB handoff, no connect screen); the builder accepts
314
+ any relative page via `BrowserDesktopUrlOptions.redirect`, and
315
+ `BrowserDesktopUrlOptions.resize` (default `'scale'`) renders as `scale=true`
316
+ for the lite pages (`vnc_lite.html`, `vnc_auto.html`) and as `resize=…` for
317
+ full-UI pages such as `vnc.html`. An already-minted token can be applied with
318
+ `agent.browserDesktopUrl(token, options)`; both resolve to `null`/`throw` when
319
+ the agent has no desktop route or is not running.
320
+
321
+ ```typescript
322
+ const { url, expiresAt } = await client.deployments.desktopUrl(agent.id);
323
+ // e.g. https://desktop-<agent>.hypercli.app/_jwt_auth?jwt=…&redirect=vnc_lite.html%3Fscale%3Dtrue
324
+ ```
325
+
326
+ ### OpenClaw control-UI allowed origins
327
+
328
+ An OpenClaw agent records the browser origins allowed to drive its control UI
329
+ in the `OPENCLAW_CONTROL_UI_ALLOWED_ORIGIN` launch env. OpenClaw treats this env
330
+ as a comma-separated full replacement for `gateway.controlUi.allowedOrigins`,
331
+ with `*` allowing any origin. Stored values predate a single canonical writer,
332
+ so the value can exist in three shapes (space-separated, comma-separated, JSON
333
+ array). The helpers in
334
+ `@hypercli.com/sdk/openclaw/control-ui-origin` are pure parsing/normalization:
335
+ `normalizeControlUiOrigin()`, `parseControlUiAllowedOrigins()`, and
336
+ `mergeControlUiAllowedOrigins()`. `normalizeControlUiOrigin()` is display-only;
337
+ the launch env is user-controlled and is not scheme-validated by the SDK.
338
+ The OpenClaw create path always writes the wildcard replacement
339
+ (`OPENCLAW_CONTROL_UI_ALLOWED_ORIGIN='*'`): every HyperCLI surface (desktop,
340
+ console) drives the control UI from dynamic origins, and the wildcard is the
341
+ only value that lands reliably. `resetRuntimeDefaults(...)` restores the same
342
+ wildcard.
343
+
344
+ `OPENCLAW_TRUSTED_PROXIES` is likewise a comma-separated full replacement for
345
+ OpenClaw `gateway.trustedProxies`. Use `buildOpenClawTrustedProxiesEnv([...])`
346
+ to build the launch env.
347
+
348
+ Automatic memory indexing is off by default. Opt in with `memoryIndex: { onSessionStart: true, onSearch: true, watch: true, watchDebounceMs: 30000, intervalMinutes: 0 }`.
349
+
350
+ ### ACP v1 conversation operations
351
+
352
+ The Backend `/ws/acp` surface and native runtime leg use vanilla v1.
353
+ The SDK uses `@agentclientprotocol/sdk` 1.5.0's v1 construction and types.
354
+
355
+ ```typescript
356
+ const acp = await agent.acpConnect({ onUpdate: handleSessionUpdate });
357
+ const { sessionId } = await acp.newSession({ cwd: '/home/node' });
358
+ const result = await acp.prompt(sessionId, [{ type: 'text', text: ' /plan\n' }]);
359
+ // result.stopReason is this native prompt's terminal result.
360
+ await acp.resumeSession(sessionId);
361
+ await acp.cancel(sessionId); // standard notification; never a replacement prompt
362
+ ```
363
+
364
+ `prompt()` remains outstanding through callbacks and updates until its real
365
+ terminal response. Native text/thought chunks, tool creation and patches, plans
366
+ and configuration notifications are delivered directly. Platform source/title,
367
+ history identities and reader receipts remain on REST.
368
+ Unknown legacy workspace setup is not guessed into ACP catalog entries.
369
+
370
+ History pages use `SessionsAPI.getMessages`; ACP has no custom history-window
371
+ options. Reconnect reattaches tracked sessions with supported `session/resume`
372
+ and never resends a turn. There is no client-side full history load: managed
373
+ native reconciliation belongs to Backend, which drives `session/load` on its
374
+ own import leg, and is never driven by scrolling.
375
+
376
+ `AcpTurnDriver` serializes one queued submission per prompt, preserving all
377
+ content blocks. Its commit hook runs after verified completion and before
378
+ settling the submission or sending the next one. Cancelled completion pauses
379
+ the queue until a new explicit submission. Prompt observation or commit failure
380
+ fences the driver: pending and later submissions reject without resending input.
381
+
382
+ ### Managed Coding Agents and Buzz ACP
383
+
384
+ Native Buzz Agent, OpenCode, Codex, Claude Code, Goose, and Kimi Code use
385
+ explicit managed runtime
386
+ discriminators while retaining the standard HyperCLI launch behavior: API-base
387
+ env injection, workspace boot sync, and persistent `/home/node` storage. They
388
+ do not receive an OpenClaw gateway token. OpenCode and Goose default to the
389
+ Anthropic-native `default-anthropic` route (currently `kimi-k3-anthropic`); Kimi Code uses Moonshot's
390
+ upstream login and service.
391
+ Claude Code, Codex, and Kimi Code are native-login-first. For Buzz-managed
392
+ launches, `HYPERCLI_RUNTIME_INFERENCE=hypercli` is an explicit compatibility
393
+ switch for Claude and Kimi. The gateway now exposes `/v1/responses`, and Buzz
394
+ compatibility mode renders Codex with `wire_api="responses"`; a successful
395
+ HyperCLI-model Codex Responses E2E remains unvalidated, so that path is not yet
396
+ advertised as supported. See the
397
+ [runtime and persistence matrix](../docs/agents/coding-runtimes.mdx).
398
+
399
+ ```typescript
400
+ const agent = await client.deployments.createCodingAgent('opencode', {
401
+ name: 'buzz-ci',
402
+ buzz: {
403
+ privateKeyNsec: agentNsec,
404
+ relayUrl,
405
+ authTag: ownerSignedAuthTag,
406
+ },
407
+ workspacesSync: { workspace: 'buzz' },
408
+ });
409
+
410
+ const methods = await agent.auth.methods();
411
+ const status = await agent.auth.status();
412
+ const login = await agent.auth.login({ method: 'device' });
413
+ // login.verificationUrl and login.userCode are populated from terminal output.
414
+ const authenticated = await login.wait();
415
+ await agent.auth.logout();
416
+ ```
417
+
418
+ Runner and Lagoon inject consistent defaults for `HYPER_API_BASE`
419
+ (product/inference), `HYPER_AGENTS_API_BASE` (direct Agent control), the
420
+ appropriate ACP URL, and agent-scoped `HYPER_AGENTS_API_KEY`.
421
+ Customers may override either base and supply canonical `HYPER_API_KEY`
422
+ through launch `env` or `secrets`, including for managing other agents. Clients
423
+ prefer an explicit canonical credential, environment `HYPER_API_KEY`, then the
424
+ configured canonical key before the platform runtime fallback. The launch
425
+ owner's auth key is never automatically forwarded.
426
+ The Agents base never selects inference. External inference URLs/keys must not
427
+ implicitly redirect platform callbacks or reconnects. Explicit `HYPER_ACP_WS_URL`
428
+ wins; otherwise derive from the Agents base, using the product base only when
429
+ no Agents base is supplied. ACP authentication uses the separate runtime key.
430
+
431
+ Authentication is runtime-specific rather than one universal login protocol.
432
+ Native Buzz Agent has no separate login step and uses its injected model and
433
+ provider configuration. `methods()` returns supported native commands: OpenCode
434
+ provider login, Codex device login, and Claude Code's Claude.ai, Console and SSO
435
+ login. Status uses the native OpenCode, Codex or Claude command. Buzz, Goose,
436
+ Kimi and Pi status discovery is unsupported through this SDK surface and raises
437
+ an error; use their native runtime authentication interface. No plugin probe or
438
+ fallback `authenticate` command is launched. Goose and Kimi expose no
439
+ noninteractive logout through this surface.
440
+
441
+ All seven runtimes launch through one helper, `createCodingAgent(runtime,
442
+ ...)` — `buzz-agent`, `opencode`, `codex`, `claude-code`, `goose`,
443
+ `kimi-code`, and `pi`. Set
444
+ the typed `buzz` object to derive the canonical child command, arguments,
445
+ native harness and Buzz-owned environment. `buzzEnabled`
446
+ remains as a deprecated raw-environment compatibility path. Both forms are
447
+ mutually exclusive with an explicit `command`.
448
+ Buzz launches keep the runtime's normal default image; only native Buzz
449
+ Agent's runtime image is already `hypercli-buzz-agent`. An explicit `image`
450
+ continues to override the default.
451
+
452
+ Buzz launches keep `/home/node` as the persistent Files API and credential
453
+ root, reserve `/home/node/shared` for Workspace projections, and run
454
+ `hyper-acp` from the specialized `/home/node/.buzz` nest. The image reconciles
455
+ the nest after the home mount. OpenCode and Codex consume its canonical
456
+ `AGENTS.md`; Claude Code receives `CLAUDE.md -> AGENTS.md`.
457
+ The Buzz plugin supplies no compiled prompt or context-injection asset.
458
+
459
+ The typed `buzz` renderer writes model and response-policy values but does not
460
+ duplicate the stock Desktop provider's validation; invalid combinations are
461
+ rejected later by `hyper-acp`. The Desktop provider also maps structured Goose
462
+ model/provider fields to `GOOSE_MODEL`/`GOOSE_PROVIDER`; direct TypeScript SDK
463
+ callers must set any Goose-specific environment themselves.
464
+
465
+ Buzz launches default `size` to `'large'` (only `'large'` or `'medium'` are
466
+ accepted) and force `restart: false`;
467
+ ordinary coding-agent launches preserve a caller-provided size or the backend
468
+ default. Stock Buzz provider agents do not
469
+ start on app launch and the current provider protocol has no stop callback.
470
+ Editing a running agent does not replace its HyperCLI launch environment: stop
471
+ the deployment through the authenticated HyperCLI API and deploy it again from
472
+ Buzz to apply changes. Hosted Buzz implements no chat shutdown command. Native
473
+ process exit follows the ordinary `restart: false` deployment cleanup lifecycle.
474
+
475
+ Stock Buzz expects ACP NDJSON. It skips non-JSON child stdout and there is no
476
+ plaintext fallback; the hosted connector auto-publishes completed assistant
477
+ text to the channel (see `docs/agents/buzz.mdx` → “Message behavior”). The
478
+ six-runtime SDK coverage validates request rendering, not live launches.
479
+
480
+ The agent nsec and caller environment become raw deployment environment values.
481
+ The agents backend currently persists them in `Agent.launch_config`, and
482
+ authenticated deployment read, environment, or exec surfaces may expose them.
483
+ The default `RUST_LOG` filter disables `acp::stream` content logging; overriding
484
+ it can expose generated text in container logs.
485
+
486
+ Persisted launch values can be changed one key at a time while an agent is
487
+ stopped:
488
+
489
+ ```typescript
490
+ await agent.setEnv('LOG_LEVEL', 'debug');
491
+ await agent.deleteEnv('LOG_LEVEL');
492
+ await agent.setSecret('SERVICE_TOKEN', token);
493
+ await agent.deleteSecret('SERVICE_TOKEN');
494
+ ```
495
+
496
+ Secret mutations return metadata only and never echo the secret value.
497
+
498
+ `client.agent.redeemGrantCode()` redeems a promo/activation code and returns the applied grant plus the resulting entitlement. Codes create new entitlements by default; pass `extendExisting: true` only for renewal/extension behavior.
499
+
500
+ ### Renders (Managed AI Workflows)
501
+
502
+ ```typescript
503
+ // Text to image
504
+ const render = await client.renders.textToImage({
505
+ prompt: 'a cat wearing sunglasses',
506
+ width: 1024,
507
+ height: 1024,
508
+ });
509
+
510
+ // Text to video
511
+ const video = await client.renders.textToVideo({
512
+ prompt: 'a cat walking through a garden',
513
+ });
514
+
515
+ // Check status
516
+ const status = await client.renders.status(render.renderId);
517
+ ```
518
+
519
+ ### File Uploads
520
+
521
+ ```typescript
522
+ // Upload local file
523
+ const file = await client.files.upload('./image.png');
524
+
525
+ // Upload from URL
526
+ const file = await client.files.uploadUrl('https://example.com/image.png');
527
+ await client.files.waitReady(file.id);
528
+
529
+ // Use in renders
530
+ const render = await client.renders.imageToVideo({
531
+ prompt: 'dancing',
532
+ fileIds: [file.id],
533
+ });
534
+ ```
535
+
536
+ ### Log Streaming
537
+
538
+ ```typescript
539
+ import { streamLogs } from '@hypercli.com/sdk';
540
+
541
+ await streamLogs(client, jobId, (line) => {
542
+ console.log(line);
543
+ });
544
+ ```
545
+
546
+ ### Captured Agent Logs
547
+
548
+ `client.deployments.getLogs(agentId, { source, generation, maxBytes, maxLines })`
549
+ returns the backend REST response. Runner responses preserve `captures`: exact
550
+ base64 bytes, source/storage generation, file generation, assignment, launch
551
+ epoch, truncation, capture health/drop counts, and runner/build/executable
552
+ provenance. `logs` is display text (stdout then stderr), not a chronological
553
+ merge. Empty captured bytes are distinct from unavailable files. If every
554
+ source is unavailable, `AgentCapturedLogsError.snapshot` retains the metadata
555
+ and `statusCode` retains the HTTP failure.
556
+
557
+ ```typescript
558
+ await client.deployments.subscribeLogs(agentId, appendClusterLine, {
559
+ source: 'both', generation: 'current', maxBytes: 65536, maxLines: 1000,
560
+ onCapturedLogs: snapshot => replaceRunnerLogView(snapshot),
561
+ follow: true,
562
+ signal: abortController.signal,
563
+ });
564
+ ```
565
+
566
+ `onCapturedLogs` receives `AgentCapturedLogsEvent` (`event: 'captured_logs'`).
567
+ These are overlapping **replacement snapshots**, never append-line callbacks.
568
+ Replace the view and display per-source truncation/unavailability even when
569
+ another source succeeded. SDK callbacks preserve metadata-only updates too;
570
+ they do not deduplicate by text or invent byte offsets. A runner subscription
571
+ requires this replacement handler. `follow: false` resolves after its first
572
+ snapshot callback completes; cluster logs still resolve at `history_end`.
573
+ Callback failures reject and clean up the subscription. Reconnect remains
574
+ caller-owned; no runner capability probing or runtime protocol is added here.
575
+
576
+ ### ComfyUI Workflows
577
+
578
+ ```typescript
579
+ import { ComfyUIJob, applyParams, graphToApi } from '@hypercli.com/sdk';
580
+
581
+ // Launch ComfyUI instance
582
+ const comfy = await ComfyUIJob.createForTemplate(client, 'flux-dev', {
583
+ gpuType: 'l40s',
584
+ lb: 8188, // HTTPS load balancer
585
+ auth: true,
586
+ });
587
+
588
+ // Wait for ready
589
+ await comfy.waitReady();
590
+
591
+ // Load and modify workflow
592
+ const workflow = JSON.parse(fs.readFileSync('workflow.json', 'utf-8'));
593
+ applyParams(workflow, {
594
+ prompt: 'a beautiful landscape',
595
+ seed: 42,
596
+ steps: 20,
597
+ });
598
+
599
+ // Execute workflow
600
+ const response = await fetch(`${comfy.baseUrl}/prompt`, {
601
+ method: 'POST',
602
+ headers: { ...comfy.authHeaders, 'Content-Type': 'application/json' },
603
+ body: JSON.stringify({ prompt: workflow }),
604
+ });
605
+ ```
606
+
607
+ ## API Reference
608
+
609
+ ### Client
610
+
611
+ - `client.billing` - Billing API
612
+ - `client.jobs` - Jobs API
613
+ - `client.user` - User API
614
+ - `client.instances` - GPU instances, types, regions, pricing
615
+ - `client.renders` - Render API
616
+ - `client.files` - File upload/download
617
+ - `client.keys` - API keys management
618
+ - `client.agent` - hosted inference API
619
+ - `client.agents` - hosted agents `hypercli-openclaw` exec/shell API
620
+
621
+ ### Job Helpers
622
+
623
+ - `BaseJob` - Base class for GPU jobs
624
+ - `ComfyUIJob` - ComfyUI-specific helpers
625
+ - `GradioJob` - Gradio-specific helpers
626
+
627
+ ## License
628
+
629
+ MIT