hypercli-sdk 0.9.2__tar.gz → 0.9.3__tar.gz

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 (88) hide show
  1. hypercli_sdk-0.9.3/.gitignore +33 -0
  2. hypercli_sdk-0.9.3/PKG-INFO +453 -0
  3. hypercli_sdk-0.9.3/README.md +415 -0
  4. hypercli_sdk-0.9.3/hypercli/__init__.py +360 -0
  5. hypercli_sdk-0.9.3/hypercli/acp.py +381 -0
  6. hypercli_sdk-0.9.3/hypercli/agent.py +1511 -0
  7. hypercli_sdk-0.9.3/hypercli/agents.py +4072 -0
  8. {hypercli_sdk-0.9.2 → hypercli_sdk-0.9.3}/hypercli/billing.py +13 -0
  9. hypercli_sdk-0.9.3/hypercli/chat_integrations.py +112 -0
  10. hypercli_sdk-0.9.3/hypercli/client.py +133 -0
  11. hypercli_sdk-0.9.3/hypercli/config.py +250 -0
  12. {hypercli_sdk-0.9.2 → hypercli_sdk-0.9.3}/hypercli/files.py +1 -156
  13. {hypercli_sdk-0.9.2 → hypercli_sdk-0.9.3}/hypercli/http.py +79 -17
  14. {hypercli_sdk-0.9.2 → hypercli_sdk-0.9.3}/hypercli/instances.py +2 -0
  15. {hypercli_sdk-0.9.2 → hypercli_sdk-0.9.3}/hypercli/job/base.py +8 -1
  16. hypercli_sdk-0.9.3/hypercli/jobs.py +555 -0
  17. hypercli_sdk-0.9.3/hypercli/keys.py +120 -0
  18. hypercli_sdk-0.9.3/hypercli/mcp.py +13 -0
  19. hypercli_sdk-0.9.3/hypercli/models.py +33 -0
  20. {hypercli_sdk-0.9.2 → hypercli_sdk-0.9.3}/hypercli/renders.py +143 -48
  21. hypercli_sdk-0.9.3/hypercli/routines.py +157 -0
  22. hypercli_sdk-0.9.3/hypercli/runners.py +126 -0
  23. hypercli_sdk-0.9.3/hypercli/sessions.py +55 -0
  24. hypercli_sdk-0.9.3/hypercli/shell.py +124 -0
  25. hypercli_sdk-0.9.3/hypercli/user.py +174 -0
  26. hypercli_sdk-0.9.3/hypercli/voice.py +109 -0
  27. hypercli_sdk-0.9.3/hypercli/voice_stream.py +251 -0
  28. hypercli_sdk-0.9.3/hypercli/voice_transcription.py +225 -0
  29. hypercli_sdk-0.9.3/hypercli/workspaces.py +1002 -0
  30. {hypercli_sdk-0.9.2 → hypercli_sdk-0.9.3}/hypercli/x402.py +16 -27
  31. {hypercli_sdk-0.9.2 → hypercli_sdk-0.9.3}/pyproject.toml +24 -6
  32. hypercli_sdk-0.9.3/tests/integration/conftest.py +49 -0
  33. hypercli_sdk-0.9.3/tests/integration/test_agents.py +120 -0
  34. hypercli_sdk-0.9.3/tests/integration/test_auth.py +13 -0
  35. hypercli_sdk-0.9.3/tests/integration/test_billing.py +10 -0
  36. hypercli_sdk-0.9.3/tests/integration/test_instances.py +21 -0
  37. hypercli_sdk-0.9.3/tests/integration/test_jobs_dryrun.py +57 -0
  38. hypercli_sdk-0.9.3/tests/integration/test_keys.py +83 -0
  39. hypercli_sdk-0.9.3/tests/integration/test_renders.py +11 -0
  40. hypercli_sdk-0.9.3/tests/test_acp.py +770 -0
  41. hypercli_sdk-0.9.3/tests/test_agent_files_source.py +60 -0
  42. hypercli_sdk-0.9.3/tests/test_agent_lifecycle.py +204 -0
  43. hypercli_sdk-0.9.3/tests/test_agents.py +2992 -0
  44. hypercli_sdk-0.9.3/tests/test_bootstrap_agents_e2e_user.py +243 -0
  45. hypercli_sdk-0.9.3/tests/test_bootstrap_console_test_key.py +99 -0
  46. hypercli_sdk-0.9.3/tests/test_bootstrap_dev_test_keys.py +256 -0
  47. hypercli_sdk-0.9.3/tests/test_chat_integrations.py +42 -0
  48. hypercli_sdk-0.9.3/tests/test_claw.py +1212 -0
  49. hypercli_sdk-0.9.3/tests/test_coding_agents.py +820 -0
  50. hypercli_sdk-0.9.3/tests/test_config.py +471 -0
  51. hypercli_sdk-0.9.3/tests/test_exec_shell_dryrun.py +503 -0
  52. hypercli_sdk-0.9.3/tests/test_file_transport.py +307 -0
  53. hypercli_sdk-0.9.3/tests/test_http.py +56 -0
  54. hypercli_sdk-0.9.3/tests/test_jobs.py +219 -0
  55. hypercli_sdk-0.9.3/tests/test_keys.py +238 -0
  56. hypercli_sdk-0.9.3/tests/test_models.py +27 -0
  57. hypercli_sdk-0.9.3/tests/test_parity_audit.py +469 -0
  58. hypercli_sdk-0.9.3/tests/test_public_surface.py +215 -0
  59. hypercli_sdk-0.9.3/tests/test_renders_subscription.py +204 -0
  60. hypercli_sdk-0.9.3/tests/test_repository_integrity.py +37 -0
  61. hypercli_sdk-0.9.3/tests/test_routines.py +319 -0
  62. hypercli_sdk-0.9.3/tests/test_runner_control_url.py +28 -0
  63. hypercli_sdk-0.9.3/tests/test_runner_placement.py +19 -0
  64. hypercli_sdk-0.9.3/tests/test_runners.py +171 -0
  65. hypercli_sdk-0.9.3/tests/test_sessions.py +132 -0
  66. hypercli_sdk-0.9.3/tests/test_status.py +27 -0
  67. hypercli_sdk-0.9.3/tests/test_voice.py +102 -0
  68. hypercli_sdk-0.9.3/tests/test_voice_stream.py +445 -0
  69. hypercli_sdk-0.9.3/tests/test_voice_transcription.py +128 -0
  70. hypercli_sdk-0.9.3/tests/test_workspaces.py +1009 -0
  71. hypercli_sdk-0.9.2/.gitignore +0 -51
  72. hypercli_sdk-0.9.2/PKG-INFO +0 -144
  73. hypercli_sdk-0.9.2/README.md +0 -114
  74. hypercli_sdk-0.9.2/hypercli/__init__.py +0 -77
  75. hypercli_sdk-0.9.2/hypercli/agents.py +0 -459
  76. hypercli_sdk-0.9.2/hypercli/claw.py +0 -303
  77. hypercli_sdk-0.9.2/hypercli/client.py +0 -66
  78. hypercli_sdk-0.9.2/hypercli/config.py +0 -70
  79. hypercli_sdk-0.9.2/hypercli/jobs.py +0 -293
  80. hypercli_sdk-0.9.2/hypercli/keys.py +0 -62
  81. hypercli_sdk-0.9.2/hypercli/user.py +0 -37
  82. hypercli_sdk-0.9.2/tests/test_claw.py +0 -153
  83. {hypercli_sdk-0.9.2 → hypercli_sdk-0.9.3}/hypercli/job/__init__.py +0 -0
  84. {hypercli_sdk-0.9.2 → hypercli_sdk-0.9.3}/hypercli/job/comfyui.py +0 -0
  85. {hypercli_sdk-0.9.2 → hypercli_sdk-0.9.3}/hypercli/job/gradio.py +0 -0
  86. {hypercli_sdk-0.9.2 → hypercli_sdk-0.9.3}/hypercli/logs.py +0 -0
  87. {hypercli_sdk-0.9.2 → hypercli_sdk-0.9.3}/tests/test_apply_params.py +0 -0
  88. {hypercli_sdk-0.9.2 → hypercli_sdk-0.9.3}/tests/test_graph_to_api.py +0 -0
@@ -0,0 +1,33 @@
1
+ # Build output
2
+ dist/
3
+ build/
4
+ target/
5
+ out/
6
+
7
+ # Caches
8
+ __pycache__/
9
+ .pytest_cache/
10
+ .mypy_cache/
11
+ .ruff_cache/
12
+ .turbo/
13
+ *.tsbuildinfo
14
+ *.pyc
15
+
16
+ # Dependencies
17
+ node_modules/
18
+ .venv/
19
+ venv/
20
+
21
+ # Test/coverage artifacts
22
+ coverage/
23
+ htmlcov/
24
+ .coverage*
25
+ coverage.xml
26
+
27
+ # Secrets & env
28
+ .env
29
+ .env.*
30
+ !.env.example
31
+
32
+ # OS junk
33
+ .DS_Store
@@ -0,0 +1,453 @@
1
+ Metadata-Version: 2.5
2
+ Name: hypercli-sdk
3
+ Version: 0.9.3
4
+ Summary: Python SDK for HyperCLI - GPU orchestration and HyperAgent API
5
+ Project-URL: Homepage, https://hypercli.com
6
+ Project-URL: Documentation, https://docs.hypercli.com
7
+ Project-URL: Repository, https://github.com/HyperCLI/hypercli
8
+ Author-email: HyperCLI <support@hypercli.com>
9
+ License-Expression: MIT
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Requires-Python: >=3.10
17
+ Requires-Dist: agent-client-protocol[http]==1.0.0rc2
18
+ Requires-Dist: httpx>=0.28.1
19
+ Requires-Dist: websockets>=15.0.1
20
+ Provides-Extra: all
21
+ Requires-Dist: comfyui-workflow-templates-media-image>=0.3.0; extra == 'all'
22
+ Requires-Dist: comfyui-workflow-templates>=0.7.0; extra == 'all'
23
+ Requires-Dist: eth-account>=0.13.0; extra == 'all'
24
+ Requires-Dist: httpx>=0.28.1; extra == 'all'
25
+ Requires-Dist: x402[evm]==2.21.0; extra == 'all'
26
+ Provides-Extra: comfyui
27
+ Requires-Dist: comfyui-workflow-templates-media-image>=0.3.0; extra == 'comfyui'
28
+ Requires-Dist: comfyui-workflow-templates>=0.7.0; extra == 'comfyui'
29
+ Provides-Extra: dev
30
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
31
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
32
+ Requires-Dist: ruff>=0.3.0; extra == 'dev'
33
+ Provides-Extra: wallet
34
+ Requires-Dist: eth-account>=0.13.0; extra == 'wallet'
35
+ Requires-Dist: httpx>=0.28.1; extra == 'wallet'
36
+ Requires-Dist: x402[evm]==2.21.0; extra == 'wallet'
37
+ Description-Content-Type: text/markdown
38
+
39
+ # HyperCLI SDK
40
+
41
+ Python SDK for [HyperCLI](https://hypercli.com) - GPU orchestration API.
42
+
43
+ ## Installation
44
+
45
+ ```bash
46
+ pip install hypercli-sdk
47
+ ```
48
+
49
+ ## Setup
50
+
51
+ Set your API key:
52
+
53
+ ```bash
54
+ export HYPER_API_KEY=your_api_key
55
+ ```
56
+
57
+ Or create `~/.hypercli/config`:
58
+ ```
59
+ HYPER_API_KEY=your_api_key
60
+ ```
61
+
62
+ Or pass directly:
63
+ ```python
64
+ client = HyperCLI(api_key="your_api_key")
65
+ ```
66
+
67
+ ## Usage
68
+
69
+ ```python
70
+ from hypercli import HyperCLI
71
+
72
+ client = HyperCLI()
73
+
74
+ # Check balance
75
+ balance = client.billing.balance()
76
+ print(f"Balance: ${balance.total:.2f}")
77
+ print(f"Rewards: ${balance.rewards:.2f}")
78
+
79
+ # List transactions
80
+ for tx in client.billing.transactions(limit=10):
81
+ print(f"{tx.transaction_type}: ${tx.amount_usd:.4f}")
82
+
83
+ # Create a job
84
+ job = client.jobs.create(
85
+ image="nvidia/cuda:12.0",
86
+ command="python train.py",
87
+ gpu_type="l40s",
88
+ gpu_count=1,
89
+ )
90
+ print(f"Job ID: {job.job_id}")
91
+ print(f"State: {job.state}")
92
+
93
+ # List jobs
94
+ for job in client.jobs.list():
95
+ print(f"{job.job_id}: {job.state}")
96
+
97
+ # Get job details
98
+ job = client.jobs.get("job_id")
99
+
100
+ # Get job logs
101
+ logs = client.jobs.logs("job_id")
102
+
103
+ # Get GPU metrics
104
+ metrics = client.jobs.metrics("job_id")
105
+ for gpu in metrics.gpus:
106
+ print(f"GPU {gpu.index}: {gpu.utilization}% util, {gpu.temperature}°C")
107
+
108
+ # Cancel a job
109
+ client.jobs.cancel("job_id")
110
+
111
+ # Extend runtime
112
+ client.jobs.extend("job_id", runtime=7200)
113
+
114
+ # Get user info
115
+ user = client.user.get()
116
+ print(f"User: {user.email}")
117
+ ```
118
+
119
+ ## Hosted Agents & Inference
120
+
121
+ Use `client.agent` for discovery and plan metadata, and point the OpenAI SDK at
122
+ the hosted inference base URL for chat completions:
123
+
124
+ ```python
125
+ from hypercli import HyperCLI
126
+ from openai import OpenAI
127
+
128
+ sdk = HyperCLI(api_key="hyper_api_key", agent_api_key="hyper_api_agent_key")
129
+ plans = sdk.agent.plans()
130
+ trial = sdk.agent.create_stripe_trial_checkout()
131
+ activation = sdk.deployments.redeem_grant_code("PROMO123")
132
+ renewal = sdk.deployments.redeem_grant_code("PROMO123", extend_existing=True)
133
+
134
+ client = OpenAI(
135
+ api_key="your_hyperagent_api_key",
136
+ base_url="https://api.agents.hypercli.com/v1"
137
+ )
138
+
139
+ response = client.chat.completions.create(
140
+ model="kimi-k3",
141
+ messages=[{"role": "user", "content": "Hello!"}]
142
+ )
143
+ ```
144
+
145
+ `create_stripe_trial_checkout()` creates the account's one-time Team trial checkout session. `claim_trial_entitlement()` (the former bodyless `POST /agents/plans/trial` claim) is deprecated: the route no longer exists in the backends. `deployments.redeem_grant_code()` applies a promo/activation code to the current agents account and returns the created entitlement. Codes create new entitlements by default; pass `extend_existing=True` only for renewal/extension behavior.
146
+
147
+ Plan IDs are open strings on the wire so future and historical plans continue
148
+ to parse. `plan.canonical_id` recognizes the current `solo`, `team`, and `pro`
149
+ IDs. Plan access comes from the agents summary, including direct grants:
150
+
151
+ ```python
152
+ summary = sdk.agent.subscription_summary()
153
+ if summary.has_active_plan: # active subscription OR direct entitlement
154
+ print(summary.agent_slots)
155
+ ```
156
+
157
+ Do not substitute the Orchestra `/api/auth/me` subscription flag. If the
158
+ summary request returns `401` or `403`, the selected key cannot establish plan
159
+ state; treat it as unknown rather than as no plan.
160
+
161
+ ## OpenClaw Agents
162
+
163
+ OpenClaw uses the generic deployment launch surface. `registry_url`,
164
+ `registry_auth`, and `sync_root` are generic deployment options. A nonblank
165
+ `sync_root` enables Reef persistence; no separate `sync_enabled` field is
166
+ serialized. On generic create, no include/exclude policy means the complete
167
+ root; `sync_exclude=[]` also excludes nothing. `sync_include=[]` and
168
+ root-wide excludes such as `sync_exclude=["*"]` are invalid.
169
+ Steady Reef synchronization
170
+ is PVC-to-object-storage upload/overwrite, not a two-way mirror: ordinary
171
+ filesystem deletes are not propagated, and remote-to-PVC copying occurs only
172
+ during explicit cold restore. Each SDK file operation obtains a fresh
173
+ files-scoped credential from Backend, then lists, reads, writes, or deletes
174
+ directly against the retained Reef server; Backend never carries file bytes.
175
+ Per-file writes are limited to 100 MiB (`AGENT_FILE_WRITE_MAX_BYTES`, the
176
+ Cloudflare edge request-body cap on the agent hostname); split larger data
177
+ across files or sync it via the agent's own tooling.
178
+ File paths are relative to `sync_root`, and
179
+ `files_list("")` lists the complete root, including dot-directories.
180
+ `build_openclaw_desktop_route()` builds the protected `desktop` route for pro
181
+ launches; there is no public `openclaw` gateway route (the pod gateway binds
182
+ loopback with auth mode `none` as an ACP hop only). The canonical images are
183
+ `ghcr.io/hypercli/hypercli-openclaw:prod` for regular OpenClaw and
184
+ the same image for desktop-enabled OpenClaw — pass
185
+ the image, `sync_root`, and exclusion choices explicitly in the launch config.
186
+ `create_agent` instead injects the runtime-specific include defaults documented in
187
+ [`coding-runtimes.mdx`](../docs/agents/coding-runtimes.mdx); pass an explicit
188
+ nullable policy at create time to select the whole root.
189
+ Workspaces boot sync defaults on through `build_openclaw_workspaces_sync_env()`
190
+ — applied automatically by `create_agent` — with
191
+ `HYPER_WORKSPACES_DIR` defaulting to `/home/node/shared` unless the launch
192
+ `env` supplies one.
193
+ `build_openclaw_trusted_proxies_env([...])` builds the comma-separated
194
+ `OPENCLAW_TRUSTED_PROXIES` env, a full replacement for OpenClaw
195
+ `gateway.trustedProxies`.
196
+
197
+ ```python
198
+ launch_config = build_agent_config(
199
+ image="ghcr.io/example/agent:latest",
200
+ registry_url="registry.example.com",
201
+ registry_auth={"username": "ci", "password": "token"},
202
+ )
203
+ agent = client.deployments.create(
204
+ name="docs-demo",
205
+ image=launch_config["image"],
206
+ registry_url=launch_config["registry_url"],
207
+ registry_auth=launch_config["registry_auth"],
208
+ )
209
+ agent = client.deployments.wait_for_state(agent.id, {"stopped"}, timeout=330)
210
+ client.deployments.update(agent.id, launch_config=launch_config)
211
+ agent = client.deployments.start(agent.id)
212
+ agent = client.deployments.wait_running(agent.id, timeout=300)
213
+
214
+ capacity = client.deployments.list_with_capacity()
215
+ print(capacity.max_agents_per_account, capacity.running_agents)
216
+ for slot in capacity.agent_slots:
217
+ print(slot.size, slot.plan_id, slot.agent_id)
218
+ ```
219
+
220
+ `start()` starts the Backend-stored launch config and does not accept launch
221
+ mutation options. Change launch settings through
222
+ `update(..., launch_config=...)` before starting.
223
+
224
+ `archive()` returns the accepted `ARCHIVING` Agent projection. `delete()` uses
225
+ HTTP 200 to accept a durable soft delete; cluster-local cleanup continues in
226
+ the background, so that response is not cleanup completion.
227
+
228
+ `list()` remains the compatibility list of agents. `list_with_capacity()`
229
+ preserves the full deployment envelope: saved/running account limits, pooled
230
+ TPD, aggregate slot inventory, and individual entitlement-backed agent slots.
231
+
232
+ For a long-lived UI, subscribe to thin invalidations and refresh REST in the
233
+ handler:
234
+
235
+ ```python
236
+ import asyncio
237
+
238
+ async def changed(_event):
239
+ agents = await asyncio.to_thread(client.deployments.list)
240
+ render(agents)
241
+
242
+ async def snapshot():
243
+ agents = await asyncio.to_thread(client.deployments.list)
244
+ render(agents)
245
+
246
+ stop = asyncio.Event()
247
+ await client.deployments.subscribe(changed, stop_event=stop, on_ready=snapshot)
248
+ ```
249
+
250
+ The `on_ready` callback runs after user-stream authentication and before event
251
+ frames are read; it repeats after reconnect so no transition can slip
252
+ between snapshot and subscription. Transition events carry `agent_id` for
253
+ local filtering plus `state`, `reason`, `error`, and `message`, but are not
254
+ resource snapshots and may be duplicated or coalesced; refresh REST for
255
+ authority.
256
+
257
+ Managed-agent lifecycle snapshots currently use `CREATING`, `STARTING`,
258
+ `RESTORING`, `RUNNING`, `STOPPING`, `STOPPED`, `ARCHIVING`, `ARCHIVED`,
259
+ `FAILED`, and `DELETED`. `CREATING` is fresh admission, `STARTING` resumes a
260
+ warm retained agent, and `RESTORING` hydrates a cold agent from its exact
261
+ archive checkpoint. `STOPPED` retains warm local storage. `ARCHIVING` is the
262
+ public transition to verified cold storage.
263
+ `ARCHIVED` is the Backend-persisted cold-restorable terminal projection after
264
+ Lagoon drops its agent task, namespace, PVC, and local S3 copy. `DELETED` is a
265
+ Backend-only terminal state and normally hidden from user lists. State values
266
+ remain open strings; use REST as authority instead of
267
+ recreating the server lifecycle machine in the client. Each snapshot may also
268
+ carry open-string diagnostics: `reason` is the stable cause such as `start`,
269
+ `api_stop`, `runtime_exit`, `timeout`, or `delete`, `error` is a failure code
270
+ when the transition failed, and `message` is human-readable context.
271
+
272
+ Persist desktop/browser configuration through `create(...)` or `update(..., launch_config=...)` (build the payload with `build_agent_config`). Use the standard OpenClaw image, a protected `desktop` route (the `desktop-<agent>.hypercli.app` host, port 3000, `auth=True`), and `HYPER_DESKTOP_ENABLED=1`.
273
+
274
+ Automatic memory indexing is off by default. Opt in by merging `build_openclaw_memory_index_env({"on_session_start": True, "on_search": True, "watch": True, "watch_debounce_ms": 30000, "interval_minutes": 0})` into the launch `env`.
275
+
276
+ ## Hosted Coding Agents
277
+
278
+ Native Buzz Agent, OpenCode, Codex, Claude Code, Goose, and Kimi Code use
279
+ canonical managed-runtime images.
280
+ They have no public runtime port: lifecycle, exec, shell, workspace sync, and
281
+ authentication all use the existing authenticated deployment APIs. OpenCode
282
+ and Goose default to HyperCLI's Anthropic-native `default-anthropic` route (currently `kimi-k3-anthropic`).
283
+ Kimi Code keeps Moonshot's upstream device login and service.
284
+ Claude Code, Codex, and Kimi Code are native-login-first. For Buzz-managed
285
+ launches, `HYPERCLI_RUNTIME_INFERENCE=hypercli` is an explicit compatibility
286
+ switch for Claude and Kimi. The gateway now exposes `/v1/responses`, and Buzz
287
+ compatibility mode renders Codex with `wire_api="responses"`; a successful
288
+ HyperCLI-model Codex Responses E2E remains unvalidated, so that path is not yet
289
+ advertised as supported. See the
290
+ [runtime and persistence matrix](../docs/agents/coding-runtimes.mdx).
291
+
292
+ All coding runtimes share one launch contract, `create_agent(runtime, ...)`;
293
+ `runtime` selects the default image, sync includes, and harness env. Permission
294
+ policy is native session configuration; no allow-all preset is injected. A
295
+ caller's standard `session/request_permission` handler may present the offered
296
+ choices or select `allow_once` per request without changing runtime modes.
297
+ The accepted runtimes are `buzz-agent`, `opencode`,
298
+ `codex`, `claude-code`, `goose`, `kimi-code`, and `pi`.
299
+ `create_coding_agent` survives only as a deprecated alias that warns and
300
+ forwards to `create_agent`.
301
+
302
+ **Breaking API change:** `build_permissions_json` and the custom permission
303
+ preset catalog have been removed. Explicit legacy `permission_mode` launch
304
+ arguments fail with a retirement error; use advertised ACP session config options
305
+ or explicit native runtime launch configuration instead.
306
+
307
+ ```python
308
+ buzz_agent = client.deployments.create_agent("buzz-agent", name="buzz-agent")
309
+ agent = client.deployments.create_agent("opencode", name="opencode")
310
+ codex = client.deployments.create_agent("codex", name="codex")
311
+ claude = client.deployments.create_agent("claude-code", name="claude")
312
+ goose = client.deployments.create_agent("goose", name="goose")
313
+ kimi = client.deployments.create_agent("kimi-code", name="kimi")
314
+
315
+ methods = codex.auth.methods()
316
+ status = codex.auth.status()
317
+
318
+ async with await codex.auth.login("device") as login:
319
+ print(login.verification_url, login.user_code)
320
+ await login.wait()
321
+ ```
322
+
323
+ The login helper opens a short-lived, agent-bound shell WebSocket and runs the
324
+ runtime's native login command inside the managed runtime. It never puts an API key on
325
+ the command line. Runtime credentials and state live under the persistent
326
+ `/home/node` sync root.
327
+
328
+ Authentication is runtime-specific rather than one universal login protocol.
329
+ Native Buzz Agent has no separate login step and uses its injected model and
330
+ provider configuration. `methods()` returns supported native commands: OpenCode
331
+ provider login, Codex device login, and Claude Code's Claude.ai, Console and SSO
332
+ login. Status uses the native OpenCode, Codex or Claude command. Buzz, Goose,
333
+ Kimi and Pi status discovery is unsupported through this SDK surface and raises
334
+ an error; use their native runtime authentication interface. No plugin probe or
335
+ fallback `authenticate` command is launched. Goose and Kimi expose no
336
+ noninteractive logout through this surface.
337
+
338
+ The images default to a long-lived direct shell/exec container. The managed
339
+ platform (runner/Lagoon) injects consistent defaults for `HYPER_API_BASE`
340
+ (product/inference), `HYPER_AGENTS_API_BASE` (direct Agent control), the
341
+ appropriate ACP URL, and agent-scoped `HYPER_AGENTS_API_KEY`.
342
+ Customers may override either base and supply canonical `HYPER_API_KEY`
343
+ through launch `env` or `secrets`, including for managing other agents. Clients
344
+ prefer an explicit canonical credential, environment `HYPER_API_KEY`, then the
345
+ configured canonical key before the platform runtime fallback. The launch
346
+ owner's auth key is never automatically forwarded.
347
+ The Agents base never selects inference. External inference URLs/keys must not
348
+ implicitly redirect platform callbacks or reconnects. Explicit `HYPER_ACP_WS_URL`
349
+ wins; otherwise derive from the Agents base, using the product base only when
350
+ no Agents base is supplied. ACP authentication uses the separate runtime key.
351
+
352
+ The typed Buzz launch contract (`BuzzLaunchConfig`) is TS-SDK-only:
353
+ `create_agent` accepts no `buzz=` option, and passing a `buzz` keyword raises
354
+ `TypeError`. Use the TS SDK's `createAgent(runtime, { buzz: ... })` for a
355
+ Buzz-managed identity launch, or render the raw contract yourself over the
356
+ generic launch surface: put `BUZZ_PRIVATE_KEY` (and optionally
357
+ `NOSTR_PRIVATE_KEY`) in `env` — `create_agent` promotes both to launch
358
+ secrets — and pass the remaining `BUZZ_*` keys as launch environment for the
359
+ managed image to parse at boot.
360
+
361
+ Caller environment becomes raw deployment environment values.
362
+ The agents backend currently persists them in `Agent.launch_config`, and
363
+ authenticated deployment read, environment, or exec surfaces may expose them.
364
+ The default `RUST_LOG` filter disables `acp::stream` content logging; overriding
365
+ it can expose generated text in container logs.
366
+
367
+ Persisted launch environment values can be changed one key at a time while an
368
+ agent is stopped:
369
+
370
+ ```python
371
+ agent.set_env("LOG_LEVEL", "debug")
372
+ agent.delete_env("LOG_LEVEL")
373
+ agent.set_secret("SERVICE_TOKEN", token)
374
+ agent.delete_secret("SERVICE_TOKEN")
375
+ ```
376
+
377
+ These methods return `AgentLaunchValueMutation` metadata. Secret writes never
378
+ echo the secret value in their response.
379
+
380
+ ## Platform session metadata
381
+
382
+ ```python
383
+ from hypercli import HyperCLI, SessionRecord
384
+
385
+ client = HyperCLI()
386
+ # Platform ID from /ws/acp session/new or deployments.list_sessions(), not a leg ID.
387
+ session: SessionRecord = client.deployments.get_session(platform_session_id)
388
+ print(session.source, session.summary_text, session.participants)
389
+ ```
390
+
391
+ `get_session()` calls `GET /agents/sessions/{id}` using the existing caller
392
+ credentials and the same `SessionRecord` decoder as `list_sessions()`, extended
393
+ with `import_outcome` and platform history state (`last_message_id`,
394
+ `message_count`, `head_seq`, per-message `receipts`). Nullable
395
+ source values are forward-compatible strings; the title is `summary_text`.
396
+ Timestamps and participant dictionaries retain the existing catalog shape.
397
+ Reads work offline without runtime connections. The backend advances the caller's
398
+ user read receipt to the session head on a best-effort basis. Platform history
399
+ and pagination remain separate from ACP attachment and live turns. HTTP
400
+ errors propagate as `APIError`: 404 unknown session, 403 outside participation
401
+ scope, 422 invalid UUID. No service impersonation or runtime-ID resolution occurs.
402
+
403
+ ## ACP v1 conversation client
404
+
405
+ `hypercli.acp.ACPClient` connects to the backend `/ws/acp` authority using the
406
+ pinned upstream `agent-client-protocol[http]==1.0.0rc2` from PyPI
407
+ (schema-v1.23.0). Its `acp/` package matches Git commit
408
+ `9d07d7871ef4b220b8507e15fc4b1560f0950a64` byte-for-byte.
409
+ Product ACP traffic targets vanilla v1 throughout.
410
+
411
+ ```python
412
+ from hypercli.acp import ACPClient, AmbiguousDeliveryError, RetryableACPError
413
+
414
+ async with await ACPClient.connect(proxy_url, token=api_key, on_update=handle_update) as acp:
415
+ session_id = await acp.new_session(cwd="/home/node")
416
+ result = await acp.prompt(session_id, "Summarize overnight mail")
417
+ print(result.stop_reason) # correlated native terminal response
418
+ ```
419
+
420
+ Use `resume_session(id, cwd=...)` for supported native attachment. It never
421
+ falls back to full load or resubmits a turn. There is no client-side full
422
+ history load: managed native reconciliation belongs to Backend, which drives
423
+ `session/load` on its own import leg.
424
+ `cancel(id)` sends the standard notification, never a replacement prompt.
425
+ There are no replay/window cursor arguments. Both `prompt` and `submit_prompt`
426
+ wait for the native terminal response. `submit_prompt` returns the upstream typed
427
+ `PromptResponse`; `prompt` returns `ACPPromptResult`. Neither requires a receipt
428
+ reader or infers completion from notifications. Inspect stored evidence separately
429
+ through the sessions REST API.
430
+
431
+ Known pre-write failures raise `RetryableACPError`; uncertain post-write/foreground
432
+ outcomes raise `AmbiguousDeliveryError`. Neither is automatically retried. Protocol
433
+ errors preserve code, message and data through `ACPRequestError`. Metadata and read
434
+ receipts stay on the existing platform REST APIs, not ACP fields or `_meta`.
435
+
436
+ Python is one-shot: it does not reconnect or replay submissions automatically.
437
+
438
+ ## Error Handling
439
+
440
+ ```python
441
+ from hypercli import HyperCLI, APIError
442
+
443
+ client = HyperCLI()
444
+
445
+ try:
446
+ job = client.jobs.get("invalid_id")
447
+ except APIError as e:
448
+ print(f"Error {e.status_code}: {e.detail}")
449
+ ```
450
+
451
+ ## License
452
+
453
+ MIT