@dialgem/sdk 0.1.0-beta.0 → 0.1.0-beta.2
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/CHANGELOG.md +36 -0
- package/README.md +182 -23
- package/dist/index.cjs +735 -54
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2256 -150
- package/dist/index.d.ts +2256 -150
- package/dist/index.js +732 -54
- package/dist/index.js.map +1 -1
- package/examples/export-calls.ts +11 -14
- package/examples/webhook-express.ts +22 -8
- package/examples/webhook-fastify.ts +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,41 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.0-beta.2
|
|
4
|
+
|
|
5
|
+
### Not in this SDK, on purpose
|
|
6
|
+
Campaigns, webhook endpoint management, usage, billing, analytics, and contact erasure / do-not-call are dashboard-only. See the surface policy in the Python SDK's `docs/api-surface.md`.
|
|
7
|
+
|
|
8
|
+
### Breaking changes
|
|
9
|
+
- **The API address is fixed at `https://api.dialgem.com`.** The `baseURL` option and the `DIALGEM_BASE_URL` environment variable are gone. Passing `baseURL` now throws rather than being ignored, so a leftover staging or local URL cannot quietly send your key to production. `DEFAULT_BASE_URL` is renamed `BASE_URL`.
|
|
10
|
+
- **Webhook signatures are timestamped.** `x-dialgem-signature` is now `v=<timestamp_ms>,d=<hex>`, where the HMAC covers the raw body plus the timestamp. `verify` and `constructEvent` also reject signatures more than 5 minutes old; set `toleranceMs` or `now` to change that. Signatures from 0.1.0-beta.0 no longer verify.
|
|
11
|
+
- **Webhook payloads carry the full call record.** Every event is `{ event, call_id, agent_id, call }`. The flat fields (`status`, `duration_s`, `analysis`) now live under `call`.
|
|
12
|
+
- **`calls.list` pages are cursor-based.** A page is `{ data, has_more, pagination_key }`. `page`, `page_size` and `total` are gone; use `limit`.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
- `sessions.say(sessionId, { text, interrupt? })` and `sessions.release(sessionId)`: make the agent speak a line on a live call, and hand a taken-over call back. Off unless the deployment enables live control (`live_control_disabled`). Listening in and taking over run over a WebSocket this SDK does not wrap. `sessions.update` now reaches a call on any service instance.
|
|
16
|
+
|
|
17
|
+
- `sessions.update(sessionId, { system_prompt?, dynamic_variables? })`: change a live call's prompt and/or variables from the agent's next turn. `sessionId` is the session's id or the call's `call_id`. Only that call changes and it is not saved.
|
|
18
|
+
- **Saved LLMs.** `llms` (`create`, `list`, `retrieve`, `update`, `delete`): a prompt and model set up once, attached with `llm_id` on `agents.create` / `agents.update`. Attaching copies the values; later edits or deletion do not change the agent, and `llm_id` cannot be sent with the fields it carries.
|
|
19
|
+
- `agents.mcpServers.listTools(agentId, serverId)`: the server's tools with descriptions and argument schemas, from a live connection; stores nothing.
|
|
20
|
+
- **Saved flows.** `flows` (`create`, `list`, `retrieve`, `update`, `delete`): build and check a conversation flow once, then attach it with `flow_id` on `agents.create` / `agents.update`. Attaching copies the flow; later edits or deletion do not change the agent.
|
|
21
|
+
- **Chats.** `chats` (`create`, `list`, `retrieve`, `update`, `delete`, `sendMessage`, `end`, `rerunAnalysis`): text conversations with a prompt agent, with the agent's own prompt, model and functions.
|
|
22
|
+
- Chats are billed per agent reply (a spent balance is a 402 `insufficient_credit`); `Chat.chat_cost` shows the spend (`null` for a team-member session). Webhook events `chat_started`, `chat_ended` and `chat_analyzed` are in the `WebhookEvent` union (`ChatStartedEvent`, `ChatEndedEvent`, `ChatAnalyzedEvent`); they carry `chat_id` and `chat`, not `call_id`, so narrow on `event` before reading `call`.
|
|
23
|
+
- `calls.rerunAnalysis(callId)`, `contacts.retrieveByPhone(phone, { default_country })` and `apiKey.retrieve()` (who this key is; works for any scope).
|
|
24
|
+
- **Agent simulations.** `simulations.createSuite`, `createCase`, `run` and `retrieveRun` (with the rest of `listSuites`, `retrieveSuite`, `updateSuite`, `deleteSuite`, `updateCase`, `deleteCase`, `listRuns`, `cancelRun`): save conversations a simulated caller has with your agent, run them in text against the draft or a published version, and check what it said and did. A suite's `publish_gate` can warn or block publishing a version until the draft has passed. Nothing is dialled or billed and the agent's tools are never really called.
|
|
25
|
+
- **Inbound routing webhook.** `phoneNumbers.update(id, { inbound_webhook_url })` sets (or, with `null`, removes) a URL Dialgem asks, before an inbound call is answered, which agent should take it, with variables or metadata, or to reject it. `phoneNumbers.testInboundWebhook(id)` sends one signed test request; `phoneNumbers.rotateInboundWebhookSecret(id)` replaces the signing secret. `PhoneNumber` gains `inbound_webhook_url` and `inbound_webhook_secret_hint`, and `inbound_webhook_secret` in the one response that creates or rotates it.
|
|
26
|
+
- `calls.update` (replace metadata), `calls.delete` and `calls.stop`.
|
|
27
|
+
- `metadata` on `createPhoneCall` and `register`.
|
|
28
|
+
- New call record fields: `metadata`, `dynamic_variables`, `start_timestamp`, `end_timestamp`, `ended_at`, `duration_ms`, `transcript_text`, `in_voicemail` and `latency` (per-stage p50/p90/p95/p99). Post-call analysis gains `call_summary` and `in_voicemail`.
|
|
29
|
+
- `calls.list` filters: `agent_id`, `status` (one or several), `direction`, `call_type`, `disconnection_reason`, `from_number`, `to_number`, `user_sentiment`, `call_successful`, `start_after`, `start_before`, `metadata`, `sort_order`.
|
|
30
|
+
- `webhooks.constructFunctionCall` verifies and parses signed requests to your custom functions (`{ name, call, args }`).
|
|
31
|
+
- `AgentFunction.args_at_root`.
|
|
32
|
+
- **Voice cloning.** `voices.clone({ name, files, consent_confirmed: true })` uploads audio and returns a voice private to your organization; `voices.delete(voiceId)` removes it at the provider and here. `Voice` gains `is_custom` and `created_by`. The upload is never retried, whatever `maxRetries` says.
|
|
33
|
+
- `phoneNumbers.retrieve(phoneNumber)` looks a number up by its E.164 value.
|
|
34
|
+
- **`agent_version: "latest_published"`** on a phone number and on `createPhoneCall` / `register`: a pointer that follows the newest publish rather than naming a version. A call still reports the concrete version it ran.
|
|
35
|
+
- **Contacts.** `contacts` (`create`, `list`, `retrieve`, `update`, `delete`, `calls`), `contactLists` (`list`, `create`, `retrieve`, `update`, `delete`, `addContacts`, `removeContact`) and CSV import under `contacts.imports` (`inspect`, `create`, `list`, `retrieve`, `errors`, `commit`, `cancel`). A contact is keyed on its phone number, stored in E.164 however it is written (pass `default_country` for numbers without a `+`). `do_not_call` on a contact is read from your do-not-call list, not stored on it. Imports run in the background: start one with `dry_run: true`, poll `retrieve` until it is `previewed`, then `commit`. `contacts.list` pages by cursor like `calls.list`. CSV downloads (the export, and the rejected-rows report) are available over the REST API only.
|
|
36
|
+
- **Browser calls.** `webCalls.create({ agent_id, metadata, dialgem_llm_dynamic_variables })` creates a call for one visitor and returns a one-use `access_token` (60 seconds) for `@dialgem/client`, so a web page can talk to an agent without your API key ever reaching the browser. Allow the pages that may start calls with `webCalls.updateSettings({ allowed_origins })` (`retrieveSettings` reads them back); `create` answers 409 `web_origins_not_configured` until at least one is set.
|
|
37
|
+
- **Agent versions.** `agents.versions.publish` freezes an agent — its configuration, functions and MCP servers — as an immutable numbered snapshot; `list` and `retrieve` read them back. Pin one with `inbound_agent_version` / `outbound_agent_version` on a phone number, or `agent_version` on `createPhoneCall` and `register`. The version a call ran is reported as `agent_version` on the call record and in every webhook. The agent itself is the draft, version 0, and stays what every unpinned call runs.
|
|
38
|
+
|
|
3
39
|
## 0.1.0-beta.0 (unreleased)
|
|
4
40
|
|
|
5
41
|
The first release.
|
package/README.md
CHANGED
|
@@ -1,11 +1,45 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
# Dialgem for TypeScript
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
**The official TypeScript SDK for the [Dialgem](https://dialgem.com) voice AI API.**
|
|
6
|
+
|
|
7
|
+
Build voice agents, put them on phone numbers, place calls, steer them live, and read transcripts, all from your backend.
|
|
8
|
+
|
|
9
|
+
[](https://www.npmjs.com/package/@dialgem/sdk)
|
|
10
|
+
[](https://www.npmjs.com/package/@dialgem/sdk)
|
|
11
|
+
[](https://github.com/DialgemAI/dialgem-sdk-typescript/actions/workflows/ci.yml)
|
|
12
|
+
[](LICENSE)
|
|
13
|
+
[](https://www.typescriptlang.org/)
|
|
14
|
+
[](https://github.com/DialgemAI/dialgem-sdk-typescript/stargazers)
|
|
15
|
+
|
|
16
|
+
[Website](https://dialgem.com) · [Issues](https://github.com/DialgemAI/dialgem-sdk-typescript/issues) · [Changelog](CHANGELOG.md) · [Python SDK](https://github.com/DialgemAI/dialgem-sdk-python)
|
|
17
|
+
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
import { Dialgem } from "@dialgem/sdk"
|
|
24
|
+
|
|
25
|
+
const dialgem = new Dialgem() // reads DIALGEM_API_KEY
|
|
26
|
+
|
|
27
|
+
const agent = await dialgem.agents.create({ name: "Front desk", system_prompt: "You answer for Acme Dental." })
|
|
28
|
+
const { call_id } = await dialgem.calls.createPhoneCall({ from_: "+14155550100", to: "+14155550123", agent_id: agent.id })
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Why this SDK
|
|
32
|
+
|
|
33
|
+
- **Typed end to end.** Request bodies are typed from the API's own schema, including the full conversation-flow node union, and webhook events are a discriminated union you can `switch` on.
|
|
34
|
+
- **Zero runtime dependencies.** ESM and CommonJS builds, so it works from any Node project.
|
|
35
|
+
- **Runs anywhere with `fetch`.** Node.js 20+, Bun, Deno and serverless runtimes that provide `fetch` and Web Crypto.
|
|
36
|
+
- **Safe by default.** `POST` is never retried (a retry could ring someone twice), other requests retry with backoff and `Retry-After`, and redirects are never followed so your key can't be sent elsewhere.
|
|
37
|
+
- **Everything a backend needs.** Agents (with tools, knowledge, MCP servers and versions), phone numbers, calls and chats, saved flows and LLMs, voices, contacts, live call control, and webhook signature verification.
|
|
38
|
+
- **Server-side only.** Your API key grants full access to your organization. To talk to an agent from a web page, use [`@dialgem/client`](https://github.com/DialgemAI/dialgem-client-sdk).
|
|
39
|
+
|
|
40
|
+
## Contents
|
|
41
|
+
|
|
42
|
+
[Install](#install) · [Quickstart](#quickstart) · [Recipes](#recipes) · [Live call control](#live-call-control) · [Errors](#errors) · [Retries](#retries) · [Coverage](#coverage) · [Development](#development) · [License](#license)
|
|
9
43
|
|
|
10
44
|
## Install
|
|
11
45
|
|
|
@@ -37,7 +71,6 @@ const agent = await dialgem.agents.create({
|
|
|
37
71
|
| Option | Default | |
|
|
38
72
|
|---|---|---|
|
|
39
73
|
| `apiKey` | `process.env.DIALGEM_API_KEY` | Organization API key. |
|
|
40
|
-
| `baseURL` | `process.env.DIALGEM_BASE_URL`, then `https://api.dialgem.com` | Point at a self-hosted or local stack. |
|
|
41
74
|
| `timeout` | `60000` | Milliseconds per attempt. |
|
|
42
75
|
| `maxRetries` | `2` | See [Retries](#retries). |
|
|
43
76
|
| `fetch` | global `fetch` | Custom implementation (proxy agent, instrumentation). |
|
|
@@ -94,9 +127,18 @@ const { call_id } = await dialgem.calls.createPhoneCall({
|
|
|
94
127
|
to: "+14155550199",
|
|
95
128
|
agent_id: agent.id,
|
|
96
129
|
dialgem_llm_dynamic_variables: { customer_name: "Sam" },
|
|
130
|
+
metadata: { crm_id: "42" }, // your own data; returned on the call and in every webhook
|
|
97
131
|
})
|
|
98
132
|
```
|
|
99
133
|
|
|
134
|
+
Manage it afterwards:
|
|
135
|
+
|
|
136
|
+
```ts
|
|
137
|
+
await dialgem.calls.update(call_id, { metadata: { crm_id: "42", campaign: "renewals" } })
|
|
138
|
+
await dialgem.calls.stop(call_id) // end it now; disconnection_reason becomes "manual_stopped"
|
|
139
|
+
await dialgem.calls.delete(call_id) // a finished call: record, transcript and recording
|
|
140
|
+
```
|
|
141
|
+
|
|
100
142
|
### 3. Bring your own Twilio number
|
|
101
143
|
|
|
102
144
|
Point your Twilio number's Voice webhook at your backend. Register the call there, then return TwiML that connects Twilio's media stream to Dialgem:
|
|
@@ -118,7 +160,13 @@ Your Twilio credentials are never shared with Dialgem. `stream_url` is signed an
|
|
|
118
160
|
|
|
119
161
|
### 4. Verify webhooks
|
|
120
162
|
|
|
121
|
-
Set `webhook_url`, `webhook_events` and `webhook_signing_secret` on the agent. Dialgem then POSTs `call_started`, `call_ended` and `
|
|
163
|
+
Set `webhook_url`, `webhook_events` and `webhook_signing_secret` on the agent (and, optionally, `webhook_timeout_ms`, 1000–30000, default 10000, to bound how long each delivery attempt waits for your server). Dialgem then POSTs the events you subscribe to: `call_started`, `call_ended`, `call_analyzed`, `transcript_updated`, `transfer_started`, `transfer_bridged`, `transfer_cancelled` and `transfer_ended`. Each body is `{ event, call_id, agent_id, call }`, where `call` is the full call record; `transcript_updated` also carries `role`, `turn_index` and the `transcript` so far, and the transfer events carry `transfer: { target?, mode?, reason? }`. Each request is signed:
|
|
164
|
+
|
|
165
|
+
```
|
|
166
|
+
x-dialgem-signature: v=<timestamp_ms>,d=<hex> hex = HMAC-SHA256(secret, raw_body + timestamp_ms)
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
`constructEvent` and `verify` check the HMAC and reject signatures more than 5 minutes old, so a captured request cannot be replayed. `call_ended` arrives as soon as the call ends; `call_analyzed` follows once the summary, sentiment and your extracted variables are ready. `transcript_updated` is sent per turn and may be retried out of order, so keep the highest `turn_index`. For a cold transfer, `transfer_bridged` is sent when the transferred leg finishes, followed by `transfer_ended`.
|
|
122
170
|
|
|
123
171
|
> **Verify the raw body.** The signature covers the exact bytes Dialgem sent. A body that was parsed and re-serialized, for example by `express.json()`, will never verify, even when the JSON is identical.
|
|
124
172
|
|
|
@@ -130,7 +178,7 @@ import { Dialgem, WebhookVerificationError } from "@dialgem/sdk"
|
|
|
130
178
|
app.post("/webhooks/dialgem", express.raw({ type: "application/json" }), async (req, res) => {
|
|
131
179
|
try {
|
|
132
180
|
const event = await Dialgem.webhooks.constructEvent(req.body, req.header("x-dialgem-signature"), SECRET)
|
|
133
|
-
if (event.event === "call_analyzed") await crm.update(event.
|
|
181
|
+
if (event.event === "call_analyzed") await crm.update(event.call.metadata.crm_id, event.call.analysis?.variables)
|
|
134
182
|
res.sendStatus(204)
|
|
135
183
|
} catch (err) {
|
|
136
184
|
if (err instanceof WebhookVerificationError) return res.status(400).send(err.message)
|
|
@@ -155,26 +203,109 @@ export async function POST(request: Request) {
|
|
|
155
203
|
|
|
156
204
|
**Fastify**: register a buffer parser for `application/json` on the webhook route. See `examples/webhook-fastify.ts`.
|
|
157
205
|
|
|
158
|
-
`event` is a discriminated union, so `switch (event.event)` narrows the payload type. A failed delivery is retried
|
|
206
|
+
`event` is a discriminated union, so `switch (event.event)` narrows the payload type. A failed delivery is retried up to three times; every attempt carries the same `x-dialgem-delivery` header, so drop an id you have already processed. Respond within 10 seconds and queue any slow work. `webhooks.verify(body, signature, secret)` returns a boolean if you prefer to handle rejection yourself.
|
|
207
|
+
|
|
208
|
+
**Verifying your custom functions.** When the agent calls one of your functions, the request is signed the same way, and its body is `{ name, call, args }`:
|
|
209
|
+
|
|
210
|
+
```ts
|
|
211
|
+
app.post("/functions/lookup-order", express.raw({ type: "application/json" }), async (req, res) => {
|
|
212
|
+
const { args, call } = await Dialgem.webhooks.constructFunctionCall<{ order_id: string }>(
|
|
213
|
+
req.body, req.header("x-dialgem-signature"), SECRET,
|
|
214
|
+
)
|
|
215
|
+
res.json(await orders.find(args.order_id, call.metadata.crm_id))
|
|
216
|
+
})
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
A function created with `args_at_root: true` receives the arguments object alone instead.
|
|
159
220
|
|
|
160
221
|
### 5. Export calls and transcripts
|
|
161
222
|
|
|
162
223
|
`calls.list()` returns one page when you `await` it. Iterate over it with `for await` to walk every page:
|
|
163
224
|
|
|
164
225
|
```ts
|
|
165
|
-
const
|
|
166
|
-
for await (const call of dialgem.calls.list({
|
|
167
|
-
|
|
168
|
-
console.log(call.id, call.duration_s, call.analysis?.call_successful, call.transcript)
|
|
226
|
+
const since = Date.parse("2026-09-01T00:00:00Z")
|
|
227
|
+
for await (const call of dialgem.calls.list({ start_after: since, status: "completed", limit: 50 })) {
|
|
228
|
+
console.log(call.id, call.duration_ms, call.analysis?.call_summary, call.transcript_text)
|
|
169
229
|
}
|
|
170
230
|
|
|
171
|
-
const page = await dialgem.calls.list({
|
|
231
|
+
const page = await dialgem.calls.list({ agent_id: agent.id, metadata: { crm_id: "42" }, limit: 50 })
|
|
172
232
|
page.data // Call[]
|
|
173
|
-
page.total // number
|
|
174
233
|
if (page.hasNextPage()) await page.getNextPage()
|
|
175
234
|
```
|
|
176
235
|
|
|
177
|
-
|
|
236
|
+
Filters: `agent_id`, `status`, `direction`, `call_type`, `disconnection_reason`, `from_number`, `to_number`, `user_sentiment`, `call_successful`, `start_after` / `start_before` (epoch ms), `metadata`, `search` and `sort_order`. Pages are cursor-based, so walking them is stable while new calls arrive.
|
|
237
|
+
|
|
238
|
+
### 6. Ship a change without touching live calls
|
|
239
|
+
|
|
240
|
+
The agent you edit is the **draft**. Publishing freezes it — configuration, functions and MCP servers — as a numbered version that never changes afterwards:
|
|
241
|
+
|
|
242
|
+
```ts
|
|
243
|
+
const v1 = await dialgem.agents.versions.publish(agent.id, { title: "Refund flow" })
|
|
244
|
+
v1.version // 1
|
|
245
|
+
|
|
246
|
+
// Point production at the frozen copy, then keep editing the draft freely.
|
|
247
|
+
await dialgem.phoneNumbers.assign(number.id, { agent_id: agent.id, agent_version: v1.version })
|
|
248
|
+
await dialgem.agents.update(agent.id, { system_prompt: "…work in progress…" })
|
|
249
|
+
|
|
250
|
+
await dialgem.agents.versions.list(agent.id) // one page, newest first
|
|
251
|
+
await dialgem.agents.versions.retrieve(agent.id, 1) // with its snapshot
|
|
252
|
+
|
|
253
|
+
// Nothing prunes versions, so the list is paged. `listPage` keeps `has_more`.
|
|
254
|
+
const { versions, has_more } = await dialgem.agents.versions.listPage(agent.id, { limit: 20 })
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
A number can also follow the newest publish instead of naming a version, so shipping moves it with nothing to update:
|
|
258
|
+
|
|
259
|
+
```ts
|
|
260
|
+
await dialgem.phoneNumbers.assign(number.id, {
|
|
261
|
+
agent_id: agent.id,
|
|
262
|
+
agent_version: "latest_published",
|
|
263
|
+
})
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
A version is also pinnable per call — `createPhoneCall({ …, agent_id, agent_version: 1 })` and `register({ …, agent_version: 1 })` — and the version a call ran comes back on the call record as `agent_version`, so a recording, its transcript and its analysis all name the configuration that produced them. Version `0` everywhere means the draft, which is what an unpinned call runs.
|
|
267
|
+
|
|
268
|
+
### 7. Give an agent a cloned voice
|
|
269
|
+
|
|
270
|
+
```ts
|
|
271
|
+
import { readFile } from "node:fs/promises"
|
|
272
|
+
|
|
273
|
+
const voice = await dialgem.voices.clone({
|
|
274
|
+
name: "Ada",
|
|
275
|
+
files: [new Blob([await readFile("./sample.mp3")], { type: "audio/mpeg" })],
|
|
276
|
+
// You are asserting that you hold the rights to this audio and have the
|
|
277
|
+
// speaker's consent. It is recorded against your API identity.
|
|
278
|
+
consent_confirmed: true,
|
|
279
|
+
})
|
|
280
|
+
|
|
281
|
+
await dialgem.agents.update(agent.id, { voice_id: voice.provider_voice_id })
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
The new voice is private to your organization — it never appears in another
|
|
285
|
+
one's catalog, and `voices.list()` puts yours first. ElevenLabs (the default)
|
|
286
|
+
takes up to 25 files; **Cartesia takes exactly one** and refuses more rather
|
|
287
|
+
than quietly picking one.
|
|
288
|
+
|
|
289
|
+
`voices.delete(voice.id)` removes it at the provider and here. It refuses with a
|
|
290
|
+
409 while an agent still uses it, rather than leaving that agent without a voice.
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
## Live call control
|
|
294
|
+
|
|
295
|
+
Steer a call while it is happening. `sessionId` is the session's id from `sessions.list()` or the call's own `call_id`, and the call can be on any service instance.
|
|
296
|
+
|
|
297
|
+
```ts
|
|
298
|
+
// Change this call's prompt or variables from the agent's next turn (not saved, only this call).
|
|
299
|
+
await dialgem.sessions.update(call_id, { dynamic_variables: { plan: "pro" } })
|
|
300
|
+
|
|
301
|
+
// Make the agent say a line in its own voice; interrupt: true cuts in now.
|
|
302
|
+
await dialgem.sessions.say(call_id, { text: "One moment while I check that." })
|
|
303
|
+
|
|
304
|
+
// Give a taken-over call back to the agent.
|
|
305
|
+
await dialgem.sessions.release(call_id)
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
`say` and `release` are **off unless your deployment enables live control** (`PermissionDeniedError` with `errCode` `live_control_disabled`), and are for owners, admins and API keys only. Listening in and taking a call over run over a WebSocket (`/v1/agent/sessions/{id}/live`), which this SDK does not wrap.
|
|
178
309
|
|
|
179
310
|
## Errors
|
|
180
311
|
|
|
@@ -223,13 +354,20 @@ The SDK never follows redirects. The API does not issue them, and following one
|
|
|
223
354
|
| `agents.functions` | `list`, `create`, `update`, `delete`, `reorder` |
|
|
224
355
|
| `agents.knowledge` | `list`, `create`, `delete` |
|
|
225
356
|
| `agents.mcpServers` | `list`, `create`, `update`, `delete`, `test` |
|
|
226
|
-
| `
|
|
227
|
-
| `
|
|
228
|
-
| `
|
|
357
|
+
| `agents.versions` | `publish`, `list`, `listPage`, `retrieve` |
|
|
358
|
+
| `calls` | `list`, `retrieve`, `update`, `delete`, `stop`, `rerunAnalysis`, `createPhoneCall`, `register` |
|
|
359
|
+
| `phoneNumbers` | `create`, `list`, `retrieve`, `update`, `assign`, `delete` |
|
|
360
|
+
| `voices` | `list`, `clone`, `delete` |
|
|
229
361
|
| `flowTemplates`, `promptTemplates` | `list`, `retrieve` |
|
|
230
|
-
| `
|
|
362
|
+
| `llms` | `create`, `list`, `retrieve`, `update`, `delete` |
|
|
363
|
+
| `flows` | `create`, `list`, `retrieve`, `update`, `delete` |
|
|
364
|
+
| `chats` | `create`, `list`, `retrieve`, `update`, `delete`, `sendMessage`, `end`, `rerunAnalysis` |
|
|
365
|
+
| `sessions` | `list`, `update`, `say`, `release` |
|
|
366
|
+
| `apiKey` | `retrieve` |
|
|
367
|
+
| `contacts` | `retrieveByPhone` (and the rest: see the reference) |
|
|
368
|
+
| `webhooks` | `verify`, `constructEvent`, `constructFunctionCall` |
|
|
231
369
|
|
|
232
|
-
In-browser web calls are not part of this package.
|
|
370
|
+
In-browser web calls are not part of this package: see [`@dialgem/client`](https://github.com/DialgemAI/dialgem-client-sdk).
|
|
233
371
|
|
|
234
372
|
## Development
|
|
235
373
|
|
|
@@ -245,7 +383,20 @@ pnpm sync:openapi --from https://api.dialgem.com/openapi.json
|
|
|
245
383
|
pnpm gen:types
|
|
246
384
|
|
|
247
385
|
# Against a running API, with an organization key:
|
|
248
|
-
DIALGEM_API_KEY=zk_…
|
|
386
|
+
DIALGEM_API_KEY=zk_… pnpm test:live # runs against api.dialgem.com — use a test org's key
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
The API address is fixed at `https://api.dialgem.com` and `baseURL` is refused,
|
|
390
|
+
so a key can never start hitting production by accident. To exercise the SDK
|
|
391
|
+
against a local or staging stack, pass a `fetch` that rewrites the origin — it
|
|
392
|
+
is explicit, it stays in your test setup, and it cannot be switched on by an
|
|
393
|
+
environment variable someone forgot to unset:
|
|
394
|
+
|
|
395
|
+
```ts
|
|
396
|
+
const local = new Dialgem({
|
|
397
|
+
apiKey: "zk_local",
|
|
398
|
+
fetch: (url, init) => fetch(String(url).replace("https://api.dialgem.com", "http://localhost:8002"), init),
|
|
399
|
+
})
|
|
249
400
|
```
|
|
250
401
|
|
|
251
402
|
Request-body types are generated from `openapi/openapi.json`. Response types in `src/types/` are written by hand, so a change to a response shape needs a matching edit there.
|
|
@@ -255,3 +406,11 @@ To release, bump `version` in `package.json` and `src/version.ts`, add a CHANGEL
|
|
|
255
406
|
## License
|
|
256
407
|
|
|
257
408
|
Apache-2.0
|
|
409
|
+
|
|
410
|
+
---
|
|
411
|
+
|
|
412
|
+
<div align="center">
|
|
413
|
+
|
|
414
|
+
If this SDK saves you time, a ⭐ on [GitHub](https://github.com/DialgemAI/dialgem-sdk-typescript) helps other developers find it.
|
|
415
|
+
|
|
416
|
+
</div>
|