Skip to content

feat: namespaced SDK (client.agent / client.tts) + realtime connect layer#3

Closed
luke-speechify wants to merge 6 commits into
masterfrom
realtime-connect
Closed

feat: namespaced SDK (client.agent / client.tts) + realtime connect layer#3
luke-speechify wants to merge 6 commits into
masterfrom
realtime-connect

Conversation

@luke-speechify

Copy link
Copy Markdown
Collaborator

What

Regenerates the SDK from the updated OpenAPI spec and adds a hand-written realtime voice-agent connect layer.

1. Namespaced surface (spec-driven)

Operations are now grouped so the client reads as the product does:

  • client.tts.audio.*, client.tts.voices.*
  • client.agent.* — core agent CRUD flattened onto agent (create, get, list, update, delete, createConversation, …)
  • client.agent.{conversations, tools, knowledgeBases, tests, phoneNumbers, …} — 14 sub-resources

Spec-only change (x-fern-sdk-group-name); no wire/field renames.

2. @livekit/rtc-node dependency

Added via generators.yml extraDependencies so the realtime transport ships with the package.

3. Realtime connect layer — @speechify/api/realtime

Hand-written, .fernignore'd (src/realtime/). Exposes a realtime voice-agent session from the { url, token } returned by client.agent.createConversation(...):

import { connectConversation } from "@speechify/api/realtime";

const convo = await client.agent.createConversation(agentId, { /* ... */ });
const session = await connectConversation(convo);

session.onText((ev) => console.log(ev.role, ev.text, ev.final));
for await (const chunk of session.outputAudio()) { /* PCM16 LE */ }
await session.sendAudio(callerPcm, { sampleRate: 48000, channels: 1 });
await session.disconnect();
  • Audio is exposed as raw PCM byte streams (input + output) — no microphone/speaker capture; device handling is the application's job.
  • Transcripts via onText ({ role, text, final }).
  • The realtime transport is an internal implementation detail and never named in the public surface.

Verification

  • fern generate --group typescript --local → builds clean (tsc, 0 errors)
  • Structure smoke: tts.audio/voices present, tts has no agents, flat agent.* + 14/14 sub-resources
  • Realtime layer proven end-to-end against a live agent (caller WAV in → agent reply audio + transcripts out)
  • @speechify/api/realtime subpath resolves to the compiled module after prepack

Draft until the sibling api-repo generators.yml PR lands.

fern-api Bot and others added 6 commits June 17, 2026 10:07
Generated by Fern
CLI Version: unknown
Generators:
  - fernapi/fern-typescript-node-sdk: 0.49.1
Hand-written, .fernignore'd module exposing realtime voice-agent sessions
as raw PCM audio streams + transcript events. Connect from the { url, token }
returned by client.agent.createConversation(...).

Imported as @speechify/api/realtime. No microphone/speaker capture — audio
device handling is the application's job.
Lets pre-release consumers install @speechify/api directly from a branch
(e.g. github:...#realtime-connect) before the npm release — npm runs
`prepare` on git-dependency installs, building dist/ and copying it to the
package root like prepack does at publish time.
Unanchored `tests` also matched the generated `tests` SDK-group dir
(api/resources/agent/resources/tests), stripping it from the packed
tarball -> 'Cannot find module ./tests' at runtime. Anchor to /src and
/tests so only the top-level source + test suite are excluded.
NodeNext/Bundler consumers can't resolve @speechify/api/realtime without
an exports entry. Declares the root and the realtime subpath (and
package.json) so the hand-written realtime layer is a first-class,
typed import.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant