@pyai/sdk 0.6.0 → 0.6.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.
- package/AGENT_GUIDE.md +4 -4
- package/CLI.md +4 -4
- package/README.md +28 -1
- package/dist/cli-dx.js +1 -1
- package/dist/cli-init.js +2 -2
- package/dist/cli.js +1 -1
- package/dist/index.d.ts +3 -0
- package/package.json +1 -1
- package/src/cli-dx.ts +1 -1
- package/src/cli-init.ts +2 -2
- package/src/cli.ts +1 -1
- package/src/index.ts +3 -0
package/AGENT_GUIDE.md
CHANGED
|
@@ -10,8 +10,8 @@ Markdown and does not require the marketing website renderer.
|
|
|
10
10
|
|
|
11
11
|
## Availability and sources of truth
|
|
12
12
|
|
|
13
|
-
The CLI is included in `@pyai/sdk` 0.6.
|
|
14
|
-
`npm install -g @pyai/sdk@0.6.
|
|
13
|
+
The CLI is included in `@pyai/sdk` 0.6.1. Install it with
|
|
14
|
+
`npm install -g @pyai/sdk@0.6.1`. Browser login supports existing PyAI accounts;
|
|
15
15
|
unattended agents should use an authorized environment key. Inspect the
|
|
16
16
|
installed command schema before acting.
|
|
17
17
|
|
|
@@ -35,7 +35,7 @@ do not invent an endpoint or present the feature as deployed.
|
|
|
35
35
|
Install the published CLI with Node.js 22 or newer recommended:
|
|
36
36
|
|
|
37
37
|
```bash
|
|
38
|
-
npm install -g @pyai/sdk@0.6.
|
|
38
|
+
npm install -g @pyai/sdk@0.6.1
|
|
39
39
|
pyai --version
|
|
40
40
|
pyai schema --json
|
|
41
41
|
```
|
|
@@ -51,7 +51,7 @@ npm install -g .
|
|
|
51
51
|
```
|
|
52
52
|
|
|
53
53
|
Alternatively install a supplied build with
|
|
54
|
-
`npm install -g /path/to/pyai-sdk-0.6.
|
|
54
|
+
`npm install -g /path/to/pyai-sdk-0.6.1.tgz`. The compiled executable supports
|
|
55
55
|
Node.js 18 or newer. Use `node dist/cli.js` explicitly when another package's
|
|
56
56
|
`pyai` shadows this executable.
|
|
57
57
|
|
package/CLI.md
CHANGED
|
@@ -6,8 +6,8 @@ scripts and in coding agents with shell access, including Cursor, Claude Code,
|
|
|
6
6
|
and Codex. `--json` provides structured results; `--help` and `schema` describe
|
|
7
7
|
the installed command surface.
|
|
8
8
|
|
|
9
|
-
**Version:** the expanded CLI is included in `@pyai/sdk` 0.6.
|
|
10
|
-
npm with `npm install -g @pyai/sdk@0.6.
|
|
9
|
+
**Version:** the expanded CLI is included in `@pyai/sdk` 0.6.1. Install it from
|
|
10
|
+
npm with `npm install -g @pyai/sdk@0.6.1`, then run `pyai login` for browser
|
|
11
11
|
sign-in or provide `PYAI_API_KEY` for unattended automation.
|
|
12
12
|
|
|
13
13
|
## Contents
|
|
@@ -31,7 +31,7 @@ sign-in or provide `PYAI_API_KEY` for unattended automation.
|
|
|
31
31
|
Install the published package (Node.js 22 or newer recommended):
|
|
32
32
|
|
|
33
33
|
```bash
|
|
34
|
-
npm install -g @pyai/sdk@0.6.
|
|
34
|
+
npm install -g @pyai/sdk@0.6.1
|
|
35
35
|
pyai --version
|
|
36
36
|
pyai login
|
|
37
37
|
pyai speak "Hello from PyAI." -o hello.wav
|
|
@@ -56,7 +56,7 @@ also be packaged and installed on another machine:
|
|
|
56
56
|
# In sdk/typescript after building
|
|
57
57
|
npm pack --ignore-scripts
|
|
58
58
|
# On the destination machine, using the actual tarball path
|
|
59
|
-
npm install -g /path/to/pyai-sdk-0.6.
|
|
59
|
+
npm install -g /path/to/pyai-sdk-0.6.1.tgz
|
|
60
60
|
pyai schema --json
|
|
61
61
|
```
|
|
62
62
|
|
package/README.md
CHANGED
|
@@ -78,9 +78,17 @@ the instant the socket opens and routes server frames to typed callbacks, so you
|
|
|
78
78
|
**can't** trip the #1 Omni integration bug (a hand-rolled `{"event":"configure"}`
|
|
79
79
|
is acked but silently dropped, giving you a connected session with zero turns):
|
|
80
80
|
|
|
81
|
-
|
|
81
|
+
For a Node 20 server, install `npm install ws` and inject its WebSocket constructor
|
|
82
|
+
as shown below. Use ESM imports. Node 22+ can omit the `ws` import and `webSocket`
|
|
83
|
+
option to use its global WebSocket. This SDK transport option does not change the
|
|
84
|
+
MCP server's Node 22+ requirement.
|
|
85
|
+
|
|
86
|
+
```js
|
|
87
|
+
import WebSocket from "ws";
|
|
88
|
+
|
|
82
89
|
// Omni is zero-state: the key's org authorizes the session, nothing to create.
|
|
83
90
|
const omni = pyai.omni.connect({
|
|
91
|
+
webSocket: WebSocket, // Supplies the transport on Node 20.
|
|
84
92
|
rate: 16000, // 24000 browser · 16000 wideband telephony · 8000 G.711/Twilio
|
|
85
93
|
configure: { voice_id: "stock_emma_en_gb", persona: "You are a receptionist." },
|
|
86
94
|
onAudio: (chunk) => speaker.write(chunk), // binary agent audio, play it out
|
|
@@ -109,6 +117,25 @@ Caller transcripts continue to require the `0x02` carrier.
|
|
|
109
117
|
agent audio; `rate: 8000` receives 8 kHz. Read `hello.audio_out` before playback.
|
|
110
118
|
Omni has no commit frame—keep streaming silence during caller pauses.
|
|
111
119
|
|
|
120
|
+
For a client-executed lookup, declare `side_effect: "read"` in its tool definition:
|
|
121
|
+
|
|
122
|
+
```js
|
|
123
|
+
const officeHoursTool = {
|
|
124
|
+
name: "lookup_office_hours",
|
|
125
|
+
description: "Read the office opening time.",
|
|
126
|
+
side_effect: "read",
|
|
127
|
+
parameters: { type: "object", properties: {} },
|
|
128
|
+
};
|
|
129
|
+
// Include officeHoursTool in configure.tools. In onToolCall, return the
|
|
130
|
+
// actual lookup result using session.toolResult(frame.call_id, { result }).
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
An omitted `side_effect` is treated as an action. Action results need a positive
|
|
134
|
+
completion acknowledgement, for example `{ ok: true, receipt_id: actualReceiptId }`,
|
|
135
|
+
returned inside `toolResult`'s `result`. Send that only after the operation has
|
|
136
|
+
completed; a queued request or transport acknowledgement is insufficient.
|
|
137
|
+
On failure, return `{ error: "Operation failed" }` instead of claiming success.
|
|
138
|
+
|
|
112
139
|
From the browser, mint an ephemeral token server-side with
|
|
113
140
|
`pyai.omni.createSession({ allowedOrigins })` and pass it as `token` so the page
|
|
114
141
|
never holds a secret key:
|
package/dist/cli-dx.js
CHANGED
|
@@ -34,5 +34,5 @@ export const recipes = [
|
|
|
34
34
|
notes: ["Local schema and recipes work without credentials. Live OpenAPI needs a network connection but no API key.", "The CLI manages Agent profiles; use the SDK or WebSocket API for a live Omni audio session."] },
|
|
35
35
|
{ name: "ci", title: "Use PyAI in a build", description: "Check access and produce an audio artifact with machine-readable output.",
|
|
36
36
|
commands: ["pyai whoami --json", 'pyai speak "Your build is ready" -o build.wav --json', "pyai doctor --json"],
|
|
37
|
-
notes: ["Set PYAI_API_KEY through the CI secret store; do not put it in source or shell arguments.", "doctor synthesizes and transcribes a sample, which consumes usage. Use whoami for an authentication-only check.", "Install the CLI with npm install -g @pyai/sdk@0.6.
|
|
37
|
+
notes: ["Set PYAI_API_KEY through the CI secret store; do not put it in source or shell arguments.", "doctor synthesizes and transcribes a sample, which consumes usage. Use whoami for an authentication-only check.", "Install the CLI with npm install -g @pyai/sdk@0.6.1 and pin that version in repeatable builds."] },
|
|
38
38
|
].map(recipe => ({ ...recipe, docs_url: "https://pyai.com/agents/speech-calling.md" }));
|
package/dist/cli-init.js
CHANGED
|
@@ -127,7 +127,7 @@ const install = `## Install the CLI
|
|
|
127
127
|
Install the published CLI with Node.js 22 or newer recommended:
|
|
128
128
|
|
|
129
129
|
\`\`\`bash
|
|
130
|
-
npm install -g @pyai/sdk@0.6.
|
|
130
|
+
npm install -g @pyai/sdk@0.6.1
|
|
131
131
|
pyai --version
|
|
132
132
|
\`\`\`
|
|
133
133
|
|
|
@@ -220,7 +220,7 @@ and product calls below are separate explicit steps. Read \`PYAI.md\` first.
|
|
|
220
220
|
Install the official SDK:
|
|
221
221
|
|
|
222
222
|
\`\`\`bash
|
|
223
|
-
npm install @pyai/sdk@0.6.
|
|
223
|
+
npm install @pyai/sdk@0.6.1
|
|
224
224
|
cp .env.example .env
|
|
225
225
|
\`\`\`
|
|
226
226
|
|
package/dist/cli.js
CHANGED
|
@@ -405,7 +405,7 @@ async function main() {
|
|
|
405
405
|
if (flags.json)
|
|
406
406
|
output({ name: "pyai", globals, aliases, short_flags: shortFlags, commands: visible }, flags, undefined, false);
|
|
407
407
|
else if (!spec && !group)
|
|
408
|
-
process.stdout.write(`PyAI CLI — speech, agents, and automation\n\nStart here\n pyai login Sign in through your browser\n pyai speak "Hello from PyAI" -o hello.wav Turn text into audio\n pyai hear call.wav --text-only Print a transcript\n pyai dub call.wav --from en --to hi -o hi.wav\n Submit, wait, and save dubbed audio\n pyai init voice-demo --template typescript Create a starter project offline\n\nDiscover\n pyai recipes [name] Copyable workflows\n pyai help <command> Command options and examples\n pyai help all Every command\n pyai schema [command] -j Machine-readable command definitions\n\nGroups\n auth profiles models voices agents jobs clones design\n cast dub recap trace tools vocabulary amd numbers calls omni\n\nShortcuts: login, logout, whoami, use, say (speak), hear (transcribe)\nOptions: -o FILE -f FILE -t TEXT -p PROFILE -j (JSON)\nGlobal: --base-url URL --api-key KEY --timeout SECONDS --retries N --dry-run\nCredentials: pyai login or PYAI_API_KEY. Run pyai doctor for a usage-consuming diagnostic.\n`);
|
|
408
|
+
process.stdout.write(`PyAI CLI — speech, agents, and automation\n\nStart here\n pyai login Sign in through your browser\n pyai speak "Hello from PyAI" -o hello.wav Turn text into audio\n pyai hear call.wav --text-only Print a transcript\n pyai dub call.wav --from en --to hi -o hi.wav\n Submit, wait, and save dubbed audio\n pyai init voice-demo --template typescript Create a starter project offline\n\nCalling\n pyai numbers list List owned phone numbers\n pyai numbers search --country US Find available numbers\n pyai calls list Inspect outbound calls\n pyai recipes calling --json Setup and preview examples\n pyai calls create --data @call.json --idempotency-key REQUEST_KEY --dry-run\n Preview a call without submitting it\n --dry-run previews a change without sending the request.\n Number purchases and outbound calls require --confirm and --idempotency-key.\n Use --confirm only after that purchase or call is authorized.\n\nDiscover\n pyai recipes [name] Copyable workflows\n pyai help <command> Command options and examples\n pyai help all Every command\n pyai schema [command] -j Machine-readable command definitions\n\nGroups\n auth profiles models voices agents jobs clones design\n cast dub recap trace tools vocabulary amd numbers calls omni\n\nShortcuts: login, logout, whoami, use, say (speak), hear (transcribe)\nOptions: -o FILE -f FILE -t TEXT -p PROFILE -j (JSON)\nGlobal: --base-url URL --api-key KEY --timeout SECONDS --retries N --dry-run\nCredentials: pyai login or PYAI_API_KEY. Run pyai doctor for a usage-consuming diagnostic.\n`);
|
|
409
409
|
else
|
|
410
410
|
process.stdout.write(`PyAI CLI — speech, agents, and automation\n\n${visible.map(c => ` pyai ${c.command}${(c.args ?? []).map(a => c.optionalArgs ? ` [${a}${c.variadic ? "..." : ""}]` : ` <${a}>`).join("")}\n ${c.description}${c.flags ? `\n Options: ${Object.keys(c.flags).map(k => `--${k}${c.flags[k] === "boolean" ? "" : " VALUE"}`).join(" ")}` : ""}${c.example ? `\n ${c.example}` : ""}`).join("\n")}\n\nGlobal: --profile NAME --json --timeout SECONDS --retries N --dry-run\n --base-url URL --api-key KEY --help --version\nShort flags: -o FILE -f FILE -t TEXT -p PROFILE -j (JSON)\nAuth: pyai login or PYAI_API_KEY. Discover: pyai schema --json\n`);
|
|
411
411
|
return;
|
package/dist/index.d.ts
CHANGED
|
@@ -594,6 +594,9 @@ export interface OmniToolDef {
|
|
|
594
594
|
name: string;
|
|
595
595
|
description?: string;
|
|
596
596
|
parameters?: Record<string, unknown>;
|
|
597
|
+
/** Declare lookups as read-only. Omitted tools are treated as actions and
|
|
598
|
+
* require a positive completion acknowledgement in their result. */
|
|
599
|
+
side_effect?: "read" | "action";
|
|
597
600
|
}
|
|
598
601
|
export interface OmniToolCallFrame {
|
|
599
602
|
event: "tool_call";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pyai/sdk",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "Official TypeScript/JavaScript SDK for PyAI, speech-to-text (Hear), text-to-speech (Speak), realtime voice agents (Omni), and call compliance (Trace).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
package/src/cli-dx.ts
CHANGED
|
@@ -35,5 +35,5 @@ export const recipes: Recipe[] = [
|
|
|
35
35
|
notes: ["Local schema and recipes work without credentials. Live OpenAPI needs a network connection but no API key.", "The CLI manages Agent profiles; use the SDK or WebSocket API for a live Omni audio session."] },
|
|
36
36
|
{ name: "ci", title: "Use PyAI in a build", description: "Check access and produce an audio artifact with machine-readable output.",
|
|
37
37
|
commands: ["pyai whoami --json", 'pyai speak "Your build is ready" -o build.wav --json', "pyai doctor --json"],
|
|
38
|
-
notes: ["Set PYAI_API_KEY through the CI secret store; do not put it in source or shell arguments.", "doctor synthesizes and transcribes a sample, which consumes usage. Use whoami for an authentication-only check.", "Install the CLI with npm install -g @pyai/sdk@0.6.
|
|
38
|
+
notes: ["Set PYAI_API_KEY through the CI secret store; do not put it in source or shell arguments.", "doctor synthesizes and transcribes a sample, which consumes usage. Use whoami for an authentication-only check.", "Install the CLI with npm install -g @pyai/sdk@0.6.1 and pin that version in repeatable builds."] },
|
|
39
39
|
].map(recipe => ({ ...recipe, docs_url: "https://pyai.com/agents/speech-calling.md" }));
|
package/src/cli-init.ts
CHANGED
|
@@ -149,7 +149,7 @@ const install = `## Install the CLI
|
|
|
149
149
|
Install the published CLI with Node.js 22 or newer recommended:
|
|
150
150
|
|
|
151
151
|
\`\`\`bash
|
|
152
|
-
npm install -g @pyai/sdk@0.6.
|
|
152
|
+
npm install -g @pyai/sdk@0.6.1
|
|
153
153
|
pyai --version
|
|
154
154
|
\`\`\`
|
|
155
155
|
|
|
@@ -242,7 +242,7 @@ and product calls below are separate explicit steps. Read \`PYAI.md\` first.
|
|
|
242
242
|
Install the official SDK:
|
|
243
243
|
|
|
244
244
|
\`\`\`bash
|
|
245
|
-
npm install @pyai/sdk@0.6.
|
|
245
|
+
npm install @pyai/sdk@0.6.1
|
|
246
246
|
cp .env.example .env
|
|
247
247
|
\`\`\`
|
|
248
248
|
|
package/src/cli.ts
CHANGED
|
@@ -270,7 +270,7 @@ async function main(): Promise<void> {
|
|
|
270
270
|
const grouped = group ? commands.filter(c => c.command.startsWith(`${group} `)) : commands;
|
|
271
271
|
const visible = spec ? [spec, ...commands.filter(c => c.command.startsWith(`${spec.command} `))] : grouped.length ? grouped : commands;
|
|
272
272
|
if (flags.json) output({ name: "pyai", globals, aliases, short_flags: shortFlags, commands: visible }, flags, undefined, false);
|
|
273
|
-
else if (!spec && !group) process.stdout.write(`PyAI CLI — speech, agents, and automation\n\nStart here\n pyai login Sign in through your browser\n pyai speak "Hello from PyAI" -o hello.wav Turn text into audio\n pyai hear call.wav --text-only Print a transcript\n pyai dub call.wav --from en --to hi -o hi.wav\n Submit, wait, and save dubbed audio\n pyai init voice-demo --template typescript Create a starter project offline\n\nDiscover\n pyai recipes [name] Copyable workflows\n pyai help <command> Command options and examples\n pyai help all Every command\n pyai schema [command] -j Machine-readable command definitions\n\nGroups\n auth profiles models voices agents jobs clones design\n cast dub recap trace tools vocabulary amd numbers calls omni\n\nShortcuts: login, logout, whoami, use, say (speak), hear (transcribe)\nOptions: -o FILE -f FILE -t TEXT -p PROFILE -j (JSON)\nGlobal: --base-url URL --api-key KEY --timeout SECONDS --retries N --dry-run\nCredentials: pyai login or PYAI_API_KEY. Run pyai doctor for a usage-consuming diagnostic.\n`);
|
|
273
|
+
else if (!spec && !group) process.stdout.write(`PyAI CLI — speech, agents, and automation\n\nStart here\n pyai login Sign in through your browser\n pyai speak "Hello from PyAI" -o hello.wav Turn text into audio\n pyai hear call.wav --text-only Print a transcript\n pyai dub call.wav --from en --to hi -o hi.wav\n Submit, wait, and save dubbed audio\n pyai init voice-demo --template typescript Create a starter project offline\n\nCalling\n pyai numbers list List owned phone numbers\n pyai numbers search --country US Find available numbers\n pyai calls list Inspect outbound calls\n pyai recipes calling --json Setup and preview examples\n pyai calls create --data @call.json --idempotency-key REQUEST_KEY --dry-run\n Preview a call without submitting it\n --dry-run previews a change without sending the request.\n Number purchases and outbound calls require --confirm and --idempotency-key.\n Use --confirm only after that purchase or call is authorized.\n\nDiscover\n pyai recipes [name] Copyable workflows\n pyai help <command> Command options and examples\n pyai help all Every command\n pyai schema [command] -j Machine-readable command definitions\n\nGroups\n auth profiles models voices agents jobs clones design\n cast dub recap trace tools vocabulary amd numbers calls omni\n\nShortcuts: login, logout, whoami, use, say (speak), hear (transcribe)\nOptions: -o FILE -f FILE -t TEXT -p PROFILE -j (JSON)\nGlobal: --base-url URL --api-key KEY --timeout SECONDS --retries N --dry-run\nCredentials: pyai login or PYAI_API_KEY. Run pyai doctor for a usage-consuming diagnostic.\n`);
|
|
274
274
|
else process.stdout.write(`PyAI CLI — speech, agents, and automation\n\n${visible.map(c => ` pyai ${c.command}${(c.args ?? []).map(a => c.optionalArgs ? ` [${a}${c.variadic ? "..." : ""}]` : ` <${a}>`).join("")}\n ${c.description}${c.flags ? `\n Options: ${Object.keys(c.flags).map(k => `--${k}${c.flags![k] === "boolean" ? "" : " VALUE"}`).join(" ")}` : ""}${c.example ? `\n ${c.example}` : ""}`).join("\n")}\n\nGlobal: --profile NAME --json --timeout SECONDS --retries N --dry-run\n --base-url URL --api-key KEY --help --version\nShort flags: -o FILE -f FILE -t TEXT -p PROFILE -j (JSON)\nAuth: pyai login or PYAI_API_KEY. Discover: pyai schema --json\n`);
|
|
275
275
|
return;
|
|
276
276
|
}
|
package/src/index.ts
CHANGED
|
@@ -887,6 +887,9 @@ export interface OmniToolDef {
|
|
|
887
887
|
name: string;
|
|
888
888
|
description?: string;
|
|
889
889
|
parameters?: Record<string, unknown>;
|
|
890
|
+
/** Declare lookups as read-only. Omitted tools are treated as actions and
|
|
891
|
+
* require a positive completion acknowledgement in their result. */
|
|
892
|
+
side_effect?: "read" | "action";
|
|
890
893
|
}
|
|
891
894
|
|
|
892
895
|
export interface OmniToolCallFrame {
|