@pyai/sdk 0.4.0 → 0.6.0

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/AGENT_GUIDE.md ADDED
@@ -0,0 +1,300 @@
1
+ # PyAI CLI integration guide for coding agents
2
+
3
+ Speech and calling decision tree: https://pyai.com/agents/speech-calling.md
4
+ Omni frame contract: https://api.pyai.com/omni-frames.json
5
+
6
+
7
+ Use this guide when building an application against PyAI, automating a file
8
+ workflow, or adding PyAI to an existing repository. It is readable as plain
9
+ Markdown and does not require the marketing website renderer.
10
+
11
+ ## Availability and sources of truth
12
+
13
+ The CLI is included in `@pyai/sdk` 0.6.0. Install it with
14
+ `npm install -g @pyai/sdk@0.6.0`. Browser login supports existing PyAI accounts;
15
+ unattended agents should use an authorized environment key. Inspect the
16
+ installed command schema before acting.
17
+
18
+ Use these sources in this order for the question they answer:
19
+
20
+ 1. `pyai schema [COMMAND OR GROUP] --json`: syntax supported by the installed CLI.
21
+ 2. `pyai schema --openapi --json`: API request/response contract on the configured deployment.
22
+ 3. https://docs.pyai.com: canonical guides and realtime protocols.
23
+ 4. https://pyai.com/cli.md: complete CLI handbook and troubleshooting.
24
+ 5. https://api.pyai.com/llms.txt: product and integration index.
25
+ 6. https://pyai.com/cli-schema.json: downloadable CLI schema snapshot for this
26
+ release. Your installed CLI schema wins if it differs.
27
+
28
+ The production API contract is https://api.pyai.com/openapi.json. If a CLI
29
+ shortcut is absent from the installed build, use a documented full command or
30
+ build the intended source revision. If a route is absent from the deployment,
31
+ do not invent an endpoint or present the feature as deployed.
32
+
33
+ ## Setup without hidden side effects
34
+
35
+ Install the published CLI with Node.js 22 or newer recommended:
36
+
37
+ ```bash
38
+ npm install -g @pyai/sdk@0.6.0
39
+ pyai --version
40
+ pyai schema --json
41
+ ```
42
+
43
+ For development from a source checkout, build with Node.js 22 or newer:
44
+
45
+ ```bash
46
+ cd sdk/typescript
47
+ npm ci
48
+ npm run build
49
+ node dist/cli.js schema --json
50
+ npm install -g .
51
+ ```
52
+
53
+ Alternatively install a supplied build with
54
+ `npm install -g /path/to/pyai-sdk-0.6.0.tgz`. The compiled executable supports
55
+ Node.js 18 or newer. Use `node dist/cli.js` explicitly when another package's
56
+ `pyai` shadows this executable.
57
+
58
+ Use `PYAI_API_KEY` supplied by the user's environment or secret store. Do not
59
+ print it, interpolate it into a prompt, commit it, or put it in a browser URL.
60
+ Keys are opaque strings; do not parse their components.
61
+
62
+ ```bash
63
+ pyai whoami --json
64
+ pyai schema speak --json
65
+ pyai schema agents create --json
66
+ pyai schema --openapi --json > openapi.json
67
+ ```
68
+
69
+ `whoami` is an authenticated network call. The local schema and recipes are
70
+ offline. Fetching OpenAPI is read-only and does not require a key. Inspect
71
+ `whoami` for the selected organization, environment, and scopes before changing
72
+ resources. An exported `PYAI_API_KEY` overrides profile credentials even if
73
+ `--profile` is present; do not assume changing the profile changes the key.
74
+
75
+ If a new isolated sandbox is appropriate for the requested task:
76
+
77
+ ```bash
78
+ pyai auth sandbox --profile sandbox --json
79
+ ```
80
+
81
+ This creates a new organization and persists a private local credential.
82
+ Reuse it instead of repeatedly minting new tenants. Review returned scopes and
83
+ expiry. Sandbox scope sets do not include every API; inspect for `dub:render`
84
+ before attempting dubbing. Existing account access uses an environment key or,
85
+ on a deployment supporting it, `pyai login --no-browser` with human approval.
86
+ Unattended automation should not wait on browser consent.
87
+
88
+ ## A reliable build loop
89
+
90
+ 1. Discover the exact command with filtered `schema`; fetch OpenAPI for API fields.
91
+ 2. Read current catalogs and resource state needed for the task.
92
+ 3. Write API payloads to reviewable JSON files. Keep secrets out of source control.
93
+ 4. Run `--dry-run --json` for intended mutations and inspect the plan.
94
+ 5. Execute the authorized mutation once, preserving its returned resource/job ID.
95
+ 6. Poll an existing job with a deadline; download output to a new path.
96
+ 7. Verify the artifact and report the result, command, and any deployment limitation.
97
+
98
+ `--dry-run` reads and validates local input and prints the planned operation.
99
+ It does not validate all server-side schema rules, permissions, billing, or
100
+ runtime capabilities. It is not a substitute for reading OpenAPI. Explicit
101
+ `delete` and `cancel` commands do not prompt for terminal confirmation.
102
+
103
+ ## Task-to-command map
104
+
105
+ | Task | Command pattern |
106
+ | --- | --- |
107
+ | Identify active key | `pyai whoami --json` |
108
+ | Browse voices | `pyai voices --language en --json` |
109
+ | Render text | `pyai speak "Your appointment is confirmed." -o prompt.wav --json` |
110
+ | Render a script | `pyai speak --text-file script.txt --format mp3 -o narration.mp3 --json` |
111
+ | Transcribe a file | `pyai transcribe call.wav --json` |
112
+ | Export plain text | `pyai hear call.wav --text-only` |
113
+ | Transcribe a hosted file | `pyai transcribe --url URL --wait --wait-timeout 300 --json` |
114
+ | Discover Dub languages | `pyai request GET /healthz/dub --json` |
115
+ | Dub a supported pair | `pyai dub input.wav --from SOURCE --to TARGET -o dubbed.wav --wait-timeout 600 --json` |
116
+ | Configure an Agent | `pyai agents create --data @agent.json --json` |
117
+ | Patch an Agent | `pyai agents update AGENT_ID --data @changes.json --json` |
118
+ | Inspect expressive voice options | `pyai cast capabilities --json` |
119
+ | Render a directed script | `pyai cast render --data @render.json --json` |
120
+ | Inspect a call | `pyai recap get CALL_ID --json` or `pyai trace get INTERACTION_ID --json` |
121
+ | Discover a missing dedicated command | `pyai schema --openapi --json`, then `pyai request METHOD /PATH` |
122
+ | Scaffold a new integration | `pyai init voice-project --template agent` |
123
+ | Read offline examples | `pyai recipes agent --json` |
124
+
125
+ Uppercase tokens are placeholders. Replace voice IDs, resource IDs, and
126
+ language codes with values from the target deployment. Do not fabricate a
127
+ voice ID or assume an output language is enabled. The `say` alias exists, but
128
+ `speak` is the primary speech command in examples and generated integrations.
129
+
130
+ ## Inputs, artifacts, and pipelines
131
+
132
+ - `speak` accepts one positional text string, `--text`, or `--text-file`. With
133
+ no explicit input it reads piped UTF-8 stdin; missing input on a terminal
134
+ returns an error. Quote text containing spaces or shell metacharacters.
135
+ - Local transcription uses a positional path or `--file`. A positional input
136
+ beginning with `http://` or `https://` selects a hosted URL and asynchronous
137
+ job. Use `--url` to select hosted input explicitly.
138
+ - `--data` accepts inline JSON, `@file.json`, or `@-`. Dedicated JSON mutations
139
+ require objects; `request` allows other JSON values when the API does.
140
+ - File uploads accept `--file -` for binary stdin and `--filename` for its name.
141
+ Do not consume stdin simultaneously for audio and `--data @-`.
142
+ - The CLI bounds stdin at 128 MiB. Server limits are independent and documented
143
+ in OpenAPI. Prefer files or hosted URLs for larger inputs.
144
+ - Audio output uses `--out PATH` and a receipt with `path`, `bytes`, and
145
+ `content_type`. It does not embed audio in JSON. The parent directory must
146
+ exist. Existing output files are refused unless `--force` is explicit.
147
+ - `--out -` writes raw bytes to stdout, requires a pipe, and conflicts with
148
+ `--json`. `--text-only` emits transcript text and conflicts with `--json`.
149
+ URL jobs require `--wait` for text-only output; large jobs may return only
150
+ `result_url`, so preserve normal JSON when consuming full results.
151
+ - Shell redirection has its own overwrite semantics. `> file.txt` is not
152
+ protected by the CLI's no-overwrite file handling.
153
+
154
+ ```bash
155
+ printf '%s\n' 'The build is ready.' | pyai speak -o build.wav --json
156
+ pyai hear build.wav --text-only > build.txt
157
+ pyai agents update AGENT_ID --data @changes.json --dry-run --json
158
+ ```
159
+
160
+ Speak defaults to `pyai-speak.wav`. `--format` chooses actual bytes: WAV, MP3,
161
+ Opus, AAC, FLAC, PCM, `g711_ulaw`, or `g711_alaw`. Changing the extension alone
162
+ never transcodes a response. G.711 is 8 kHz; its default extension is `.raw`.
163
+
164
+ ## Async lifecycle and retries
165
+
166
+ A submission response is not evidence that a job completed. Record its ID and
167
+ inspect the appropriate terminal status:
168
+
169
+ | Family | Success | Failure |
170
+ | --- | --- | --- |
171
+ | `jobs wait ID` | `completed` | `failed`, `cancelled` |
172
+ | `design wait ID` | `completed` | `failed` |
173
+ | `cast wait ID` | `done` | `error` |
174
+ | `dub wait ID` | `done` | `error` |
175
+
176
+ The top-level `dub INPUT --from LANG --to LANG --out PATH` performs submission,
177
+ wait, and audio download. Its JSON receipt includes `job_id`, `status`, `path`,
178
+ `bytes`, and `content_type`. Explicit `dub create`, `dub wait`, and `dub audio`
179
+ separate those stages. Cast uses `cast render`, `cast wait`, and `cast audio`.
180
+
181
+ HTTP `--timeout` defaults to 30 seconds, including response downloads.
182
+ `--wait-timeout` defaults to 120 seconds and `--poll-interval` to 2 seconds.
183
+ A polling timeout does not cancel a remote job. Error details include the job
184
+ path when available; inspect it before resubmitting. For long-running work,
185
+ resume with the relevant `wait` command.
186
+
187
+ Automatic retries apply only to reads. Mutations are not retried automatically.
188
+ Some mutations accept `--idempotency-key`; the endpoint must implement it for
189
+ it to be effective. Reuse an idempotency key only for the same intended request
190
+ and body. After an ambiguous network failure, reconcile remote state rather
191
+ than immediately creating another resource.
192
+
193
+ Paginated list commands return one page and accept `--limit 1..100` and
194
+ `--cursor`. Continue with the response's `next_cursor`; do not assume the first
195
+ page contains all resources. For additional filters use documented
196
+ `request --query name=value` options.
197
+
198
+ ## Machine-output contract
199
+
200
+ Use `--json` or `-j` for structured output. Normal success is one JSON result
201
+ on stdout, with no progress mixed in. Result shapes follow the API, except
202
+ local operations and artifact receipts. Do not assume all commands return a
203
+ `data` array or the same envelope.
204
+
205
+ Errors are JSON on stderr:
206
+
207
+ ```json
208
+ {"error":{"code":"unauthorized","message":"...","status":401}}
209
+ ```
210
+
211
+ `status`, `request_id`, and other detail fields are conditional. Branch on
212
+ `error.code` and process exit status, not the error's wording. Unknown response
213
+ fields may be added. Diagnostics return a JSON result with checks on stdout
214
+ and a nonzero exit when checks fail.
215
+
216
+ | Exit | Meaning | Handling |
217
+ | --- | --- | --- |
218
+ | `0` | Success | Consume result |
219
+ | `1` | API/job/operational failure | Inspect API code and remote state |
220
+ | `2` | Local input/configuration error | Correct flags, JSON, or filesystem paths |
221
+ | `3` | Authentication/permission failure | Fix key, scope, or membership |
222
+ | `4` | Network failure/timeout | Reconcile state before retrying a mutation |
223
+ | `130` | Interrupted | Resume existing work if needed |
224
+
225
+ Do not retry authorization failures. `402` requires checking account credit,
226
+ plan, or budget. `429` requires respecting delays and capacity/daily limits.
227
+ The CLI normalizes supported API error envelopes; preserve `request_id` in a
228
+ redacted issue report when available.
229
+
230
+ Browser login emits newline-delimited public JSON events on stderr, including
231
+ `authorization_required` and possibly `browser_unavailable`, before a final
232
+ stdout success receipt. Do not treat every stderr line during login as a fatal
233
+ error. The CLI saves a 30-day credential after explicit owner/admin consent;
234
+ logout only removes it locally, and revocation is performed in the console.
235
+
236
+ Terminal JSON redacts known credentials and secret-shaped fields. If an API
237
+ returns a token the application must retain, `request ... --out response.json`
238
+ saves the original response privately and prints only an artifact receipt.
239
+ Treat that file as sensitive; never commit it or paste it into a model prompt.
240
+
241
+ ## New projects and existing repositories
242
+
243
+ ```bash
244
+ pyai init voice-project
245
+ pyai init voice-ts --template typescript
246
+ pyai init voice-python --template python
247
+ pyai init voice-project --template agent --dry-run --json
248
+ ```
249
+
250
+ `agent` is the default. The destination must not exist and its parent must be
251
+ present. Scaffolding is offline; it creates `PYAI.md` and starter assets without
252
+ installing packages, minting credentials, or making API calls. Every template includes `README.md`, `PYAI.md`, `.env.example`, and
253
+ `.gitignore`. The agent template adds `agent.json`, `speech.json`, and
254
+ `job.json`; TypeScript adds `main.ts` and `package.json`; Python adds `main.py`.
255
+ Follow the created README. JSON output includes `directory`, `template`, `files`,
256
+ `created`, and `next_steps`.
257
+
258
+ For an existing repository, link this guide from its agent instructions and
259
+ add task-specific constraints. Keep application-specific instructions separate
260
+ from assumptions about the live API; fetch current contracts when implementing.
261
+
262
+ Suggested repository instruction:
263
+
264
+ > Use PyAI CLI for file workflows and REST resource setup. Before writing API
265
+ > payloads, inspect `pyai schema COMMAND --json` and the deployment's OpenAPI.
266
+ > Use PYAI_API_KEY from the environment without printing or committing it.
267
+ > Discover voice and language capabilities rather than guessing. Preview
268
+ > mutations, retain resource IDs, bound waits, and handle stable error codes.
269
+ > Use the official SDK for application code and realtime audio. Explain what
270
+ > was verified locally and what still requires deployment.
271
+
272
+ ## When to use the SDK or MCP
273
+
274
+ The CLI covers files, REST operations, configuration, and job lifecycles.
275
+ It does not capture live microphone input or run realtime Hear, Omni, or AMD
276
+ streams. Use the official TypeScript or Python SDK for that transport:
277
+ https://docs.pyai.com/guides/sdks. The MCP server is another integration when
278
+ an agent host works best with tools:
279
+ https://docs.pyai.com/guides/use-pyai-in-cursor.
280
+
281
+ For Omni, follow the canonical protocol rather than deriving it from CLI
282
+ commands: https://docs.pyai.com/realtime/omni-protocol. Managing an Agent profile
283
+ is separate from opening a realtime conversation. Do not infer unsupported
284
+ socket behavior, scopes, or endpoints from a REST resource name.
285
+
286
+ ## Verification checklist for a completed integration
287
+
288
+ - The installed CLI supports the commands used in scripts.
289
+ - API bodies and permissions match the target deployment's OpenAPI.
290
+ - Catalog-derived IDs and enabled language pairs are used.
291
+ - Secrets are absent from prompts, tracked files, and output logs.
292
+ - Artifacts are complete, in the intended format, and written to deliberate paths.
293
+ - Jobs are verified in their successful terminal state before outputs are used.
294
+ - Error handling covers local input, permission, network, and API/job failures.
295
+ - The handoff includes a runnable command and distinguishes local implementation
296
+ from published packages and deployed browser authentication.
297
+
298
+ `pyai doctor` and `pyai smoke` make real synthesis/transcription calls and
299
+ consume applicable usage quota. Use `--dry-run` to inspect their request plans,
300
+ and run them when that verification is appropriate to the task.