@pouchy_ai/companion-sdk 0.24.0 → 0.26.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/CHANGELOG.md +51 -0
- package/README.md +8 -1
- package/dist/call.js +7 -6
- package/dist/client.d.ts +39 -8
- package/dist/client.js +49 -24
- package/dist/errors.d.ts +9 -0
- package/dist/errors.js +20 -0
- package/dist/index.d.ts +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -12,6 +12,57 @@ a protocol bump is always called out explicitly here.
|
|
|
12
12
|
|
|
13
13
|
## [Unreleased]
|
|
14
14
|
|
|
15
|
+
## [0.26.0] - 2026-07-11
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- **Voice-call connect failures now honor the typed-error contract.** The
|
|
20
|
+
call helpers (`connectCall` / `startCall` / `openCompanionCall`) used to
|
|
21
|
+
reject with plain `Error`s for the connect-step failures, so they carried
|
|
22
|
+
no `.code` and couldn't be `switch`ed like every other SDK rejection.
|
|
23
|
+
They now reject with `CompanionError` and three new client-synthesized
|
|
24
|
+
codes: `call_unsupported` (non-browser environment — no WebRTC/mic),
|
|
25
|
+
`call_connect_failed` (mic-permission timeout, SDP exchange failed or
|
|
26
|
+
timed out; `status` carries the HTTP status when the exchange answered
|
|
27
|
+
non-2xx), and `call_dependency_missing` (the optional
|
|
28
|
+
`@elevenlabs/client` peer dependency isn't installed). Like
|
|
29
|
+
`reply_timeout`/`stream_unauthorized` these are SDK-synthesized and
|
|
30
|
+
deliberately NOT part of the server-mirrored `COMPANION_ERROR_CODES`
|
|
31
|
+
HTTP vocabulary. Browser-native `getUserMedia` rejections (e.g.
|
|
32
|
+
`NotAllowedError` on permission denial) still propagate untouched.
|
|
33
|
+
`CompanionError` itself is unchanged and keeps its import path.
|
|
34
|
+
|
|
35
|
+
## [0.25.0] - 2026-07-11
|
|
36
|
+
|
|
37
|
+
### Added
|
|
38
|
+
|
|
39
|
+
- **`sendText(text, { awaitReply: true })` — await the reply as the return
|
|
40
|
+
value.** Resolves with `{ seq, text, envelope }` (a new exported
|
|
41
|
+
`SendTextReply` type) once the turn completes: `text` is the authoritative
|
|
42
|
+
final assistant text (the same value `onMessage` receives), `envelope` the
|
|
43
|
+
full `companion.message` envelope. Request/response hosts — a CLI REPL, an
|
|
44
|
+
HTTP handler, a test — no longer hand-roll the resolve-on-message +
|
|
45
|
+
timeout gate every integration was writing. It rides the same streaming
|
|
46
|
+
request (the terminal `done` frame carries the envelope), so it works
|
|
47
|
+
without `start()`; `onMessage`/`onDelta` subscribers still fire as usual.
|
|
48
|
+
With `stream: false` (or an old server that answers plain JSON) it falls
|
|
49
|
+
back to the event stream — which then does need `start()` — resolving with
|
|
50
|
+
the next `companion.message` or rejecting with a client-side
|
|
51
|
+
`CompanionError` `code: 'reply_timeout'` after `replyTimeoutMs`
|
|
52
|
+
(default 60 000 ms).
|
|
53
|
+
|
|
54
|
+
### Docs
|
|
55
|
+
|
|
56
|
+
- OpenAPI spec corrections (served at `/api/companion/openapi.json`): the
|
|
57
|
+
memory-write body field is `content` (was wrongly documented as `text`),
|
|
58
|
+
knowledge ingest takes `name`/`kind`/`locale` (was `title`), the
|
|
59
|
+
modalities enum is `text|voice|call|files` (`avatar` never existed),
|
|
60
|
+
`GET …/confirm` (pending confirmations) is now documented, the session
|
|
61
|
+
handshake body documents `handles`/`contextKinds`/`visitor`, and memory
|
|
62
|
+
scopes use the real namespaced strings (`memory.read:app` …).
|
|
63
|
+
- The `/sdk` reference described the call handle as having `.end()` — the
|
|
64
|
+
method is `close()`.
|
|
65
|
+
|
|
15
66
|
## [0.24.0] - 2026-07-11
|
|
16
67
|
|
|
17
68
|
### Added
|
package/README.md
CHANGED
|
@@ -96,6 +96,7 @@ local/device skills).
|
|
|
96
96
|
|
|
97
97
|
| Method | What it does |
|
|
98
98
|
|---|---|
|
|
99
|
+
| `sendText(text, { awaitReply: true, replyTimeoutMs? })` | Request/response mode: the promise resolves with the completed turn's reply `{ seq, text, envelope }` (`SendTextReply`) — no `onMessage` wiring or hand-rolled turn gate. Works without `start()` (the reply rides the same streaming request); only the `stream: false` / old-server fallback needs the event stream, and it rejects with `code: 'reply_timeout'` after `replyTimeoutMs` (default 60s). |
|
|
99
100
|
| `recall({ query?, limit? })` / `remember({ content, … })` | Read / write the token-scoped memory namespace. `query` runs SEMANTIC search over the facts server-side (embedding-based, ranked fallback); omit it for the plain importance/recency ranking. |
|
|
100
101
|
| `ingestKnowledge({ text, name, … })` / `ingestFile(file)` | Push documents into the user's knowledge base ("My materials"); needs `memory.write:core`. |
|
|
101
102
|
| `history({ limit? })` | Fetch the session transcript — restore chat on reload. |
|
|
@@ -146,7 +147,13 @@ HTTP `code` vocabulary behind `CompanionError.code`, e.g. `missing_scope` /
|
|
|
146
147
|
`session_not_found` / `turn_pending`) — so you can assert the version, validate
|
|
147
148
|
the event vocabulary, or switch on error codes without hard-coding strings.
|
|
148
149
|
Every helper populates `CompanionError.code` when the server names a cause
|
|
149
|
-
(0.24.0 — previously only the POST-backed calls did).
|
|
150
|
+
(0.24.0 — previously only the POST-backed calls did). The SDK also synthesizes
|
|
151
|
+
a few client-side codes outside that HTTP vocabulary: `reply_timeout`
|
|
152
|
+
(awaitReply fallback gave up), `stream_unauthorized` (event-stream 401
|
|
153
|
+
exhausted reconnects), and — 0.26.0 — the voice connect-step codes
|
|
154
|
+
`call_unsupported` (no WebRTC/mic in this environment), `call_connect_failed`
|
|
155
|
+
(mic timeout / SDP exchange failed) and `call_dependency_missing`
|
|
156
|
+
(`@elevenlabs/client` not installed). Every
|
|
150
157
|
outbound payload has a named type; `ToolCallPayload` (`{ id, name, args }`) types
|
|
151
158
|
the `companion.tool_call` event, and `onToolCall`'s callback receives
|
|
152
159
|
`ToolCallEvent` — the payload plus `argsJson` (pre-parsed args).
|
package/dist/call.js
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
//
|
|
11
11
|
// Browser-only (needs WebRTC + getUserMedia). Returns a handle to hang up and to
|
|
12
12
|
// inject live context mid-call (the bridge the server uses for voiceRelevant).
|
|
13
|
+
import { CompanionError } from './errors.js';
|
|
13
14
|
/** Universal "host control" verbs the companion can call on ANY surface (web /
|
|
14
15
|
* game / app / hardware), regardless of provider. They're generic on purpose —
|
|
15
16
|
* the SPECIFIC intent rides in the string params, which YOUR surface interprets
|
|
@@ -147,7 +148,7 @@ const OPENAI_REALTIME_CALLS = 'https://api.openai.com/v1/realtime/calls';
|
|
|
147
148
|
/** Open a live call from pre-minted credentials. */
|
|
148
149
|
export async function openCompanionCall(creds, opts = {}, bridge) {
|
|
149
150
|
if (typeof navigator === 'undefined' || !navigator.mediaDevices) {
|
|
150
|
-
throw new
|
|
151
|
+
throw new CompanionError('connectCall is browser-only (needs WebRTC + microphone access)', 0, 'call_unsupported');
|
|
151
152
|
}
|
|
152
153
|
return creds.provider === 'openai-realtime'
|
|
153
154
|
? openOpenAICall(creds, opts, bridge)
|
|
@@ -176,7 +177,7 @@ async function getMicWithTimeout() {
|
|
|
176
177
|
.catch(() => { });
|
|
177
178
|
const timeout = new Promise((_, reject) => setTimeout(() => {
|
|
178
179
|
timedOut = true;
|
|
179
|
-
reject(new
|
|
180
|
+
reject(new CompanionError('microphone request timed out', 0, 'call_connect_failed'));
|
|
180
181
|
}, GUM_TIMEOUT_MS));
|
|
181
182
|
return Promise.race([micPromise, timeout]);
|
|
182
183
|
}
|
|
@@ -343,14 +344,14 @@ async function openOpenAICall(creds, opts, bridge) {
|
|
|
343
344
|
catch {
|
|
344
345
|
clearTimeout(sdpTimer);
|
|
345
346
|
cleanupPartial();
|
|
346
|
-
throw new
|
|
347
|
+
throw new CompanionError(sdpAbort.signal.aborted
|
|
347
348
|
? 'OpenAI Realtime SDP exchange timed out'
|
|
348
|
-
: 'OpenAI Realtime SDP exchange failed');
|
|
349
|
+
: 'OpenAI Realtime SDP exchange failed', 0, 'call_connect_failed');
|
|
349
350
|
}
|
|
350
351
|
clearTimeout(sdpTimer);
|
|
351
352
|
if (!res.ok) {
|
|
352
353
|
cleanupPartial();
|
|
353
|
-
throw new
|
|
354
|
+
throw new CompanionError(`OpenAI Realtime SDP exchange failed (${res.status})`, res.status, 'call_connect_failed');
|
|
354
355
|
}
|
|
355
356
|
await pc.setRemoteDescription({ type: 'answer', sdp: await res.text() });
|
|
356
357
|
let closed = false;
|
|
@@ -458,7 +459,7 @@ async function openConvaiCall(creds, opts, bridge) {
|
|
|
458
459
|
mod = await import('@elevenlabs/client');
|
|
459
460
|
}
|
|
460
461
|
catch {
|
|
461
|
-
throw new
|
|
462
|
+
throw new CompanionError("elevenlabs-convai call needs the optional peer dependency '@elevenlabs/client' — install it (npm i @elevenlabs/client)", 0, 'call_dependency_missing');
|
|
462
463
|
}
|
|
463
464
|
// App tools → EL client tools. NOTE: ElevenLabs only CALLS a client tool the
|
|
464
465
|
// agent already knows (declared on the agent config); a shared Convai agent
|
package/dist/client.d.ts
CHANGED
|
@@ -166,12 +166,10 @@ export declare function pouchyBrandIconUrl(baseUrl: string, size?: BrandIconSize
|
|
|
166
166
|
* a method before `connect()`). `code` is a stable machine-readable tag you can
|
|
167
167
|
* switch on, shared with the `control.error` stream event vocabulary:
|
|
168
168
|
* `'not_connected'`, `'missing_option'`, `'not_representative'`, or the server's
|
|
169
|
-
* own error code for an HTTP failure (when it sends one).
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
constructor(message: string, status: number, code?: string);
|
|
174
|
-
}
|
|
169
|
+
* own error code for an HTTP failure (when it sends one). Defined in errors.ts
|
|
170
|
+
* (so call.ts shares it cycle-free); re-exported here so the public import
|
|
171
|
+
* path is unchanged. */
|
|
172
|
+
export { CompanionError } from './errors.js';
|
|
175
173
|
/** The server's memory-consolidation diagnostic from `endSession()` / `close()`.
|
|
176
174
|
* `ok` is whether consolidation ran; `facts` is how many memories it wrote;
|
|
177
175
|
* `skipped` (when present) says why nothing was written
|
|
@@ -181,6 +179,15 @@ export interface EndSessionResult {
|
|
|
181
179
|
facts?: number;
|
|
182
180
|
skipped?: string;
|
|
183
181
|
}
|
|
182
|
+
/** What `sendText(text, { awaitReply: true })` resolves with: the completed
|
|
183
|
+
* turn's reply. `text` is the authoritative final assistant text (same value
|
|
184
|
+
* onMessage receives); `envelope` is the full `companion.message` envelope
|
|
185
|
+
* for hosts that want the id/ts. */
|
|
186
|
+
export interface SendTextReply {
|
|
187
|
+
seq: number | null;
|
|
188
|
+
text: string;
|
|
189
|
+
envelope: CompanionEnvelope;
|
|
190
|
+
}
|
|
184
191
|
type Handler = (envelope: CompanionEnvelope) => void;
|
|
185
192
|
/** Token-streaming subscriber (P1-2). `chunk` is a raw text delta of the reply
|
|
186
193
|
* being generated; `meta.reset` (with an empty chunk) tells the renderer to
|
|
@@ -244,13 +251,38 @@ export declare class CompanionClient {
|
|
|
244
251
|
* request — delta subscribers fire as chunks arrive, and onMessage still
|
|
245
252
|
* fires exactly ONCE with the authoritative final text (the streamed copy
|
|
246
253
|
* is emitted locally; the event-stream replay of the same envelope is
|
|
247
|
-
* deduplicated by id). Pass `stream: false` to force the buffered path.
|
|
254
|
+
* deduplicated by id). Pass `stream: false` to force the buffered path.
|
|
255
|
+
*
|
|
256
|
+
* AWAIT THE REPLY (request/response hosts — a REPL, an HTTP handler, a
|
|
257
|
+
* test): pass `awaitReply: true` and the promise resolves with the final
|
|
258
|
+
* reply `{ seq, text, envelope }` — no onMessage wiring, no hand-rolled
|
|
259
|
+
* turn gate. It rides the same streaming request (the terminal `done`
|
|
260
|
+
* frame carries the authoritative envelope), so it works without start();
|
|
261
|
+
* onMessage/onDelta subscribers still fire as usual. Only when the reply
|
|
262
|
+
* can't ride the request (`stream: false`, or an old server) does it fall
|
|
263
|
+
* back to the event stream — which then DOES need start() — resolving with
|
|
264
|
+
* the next `companion.message`, or rejecting with code `reply_timeout`
|
|
265
|
+
* after `replyTimeoutMs` (default 60s). */
|
|
266
|
+
sendText(text: string, opts: {
|
|
267
|
+
awaitReply: true;
|
|
268
|
+
images?: string[];
|
|
269
|
+
stream?: boolean;
|
|
270
|
+
replyTimeoutMs?: number;
|
|
271
|
+
}): Promise<SendTextReply>;
|
|
248
272
|
sendText(text: string, opts?: {
|
|
249
273
|
images?: string[];
|
|
250
274
|
stream?: boolean;
|
|
275
|
+
awaitReply?: boolean;
|
|
276
|
+
replyTimeoutMs?: number;
|
|
251
277
|
}): Promise<{
|
|
252
278
|
seq: number | null;
|
|
253
279
|
}>;
|
|
280
|
+
/** The awaitReply leg of sendText. Prefers the in-request answer (the
|
|
281
|
+
* streaming `done` frame's envelope); falls back to the next
|
|
282
|
+
* `companion.message` off the event stream, bounded by a timeout. The
|
|
283
|
+
* fallback subscription opens BEFORE the POST so a fast event-stream reply
|
|
284
|
+
* can't slip through the gap. */
|
|
285
|
+
private sendTextAwaitingReply;
|
|
254
286
|
/** The streaming leg of sendText: parse the POST response's SSE frames —
|
|
255
287
|
* `delta` / `reset` → delta subscribers, `done` → resolve (emitting the
|
|
256
288
|
* final envelope locally so onMessage fires immediately and the log replay
|
|
@@ -547,4 +579,3 @@ export declare class CompanionClient {
|
|
|
547
579
|
private consume;
|
|
548
580
|
private sleep;
|
|
549
581
|
}
|
|
550
|
-
export {};
|
package/dist/client.js
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
// kept in lockstep by protocol.drift.test.ts.
|
|
15
15
|
import { PROTOCOL_VERSION } from './protocol.js';
|
|
16
16
|
import { parseSse } from './sse.js';
|
|
17
|
+
import { CompanionError } from './errors.js';
|
|
17
18
|
import { openCompanionCall, HOST_CONTROL_TOOLS, HOST_CONTROL_TOOL_NAMES, AVATAR_VISUAL_TOOLS, AVATAR_VISUAL_TOOL_NAMES } from './call.js';
|
|
18
19
|
/** Model tool arguments are model output — tolerate junk without throwing. */
|
|
19
20
|
function parseArgsJson(args) {
|
|
@@ -37,18 +38,10 @@ export function pouchyBrandIconUrl(baseUrl, size = 512) {
|
|
|
37
38
|
* a method before `connect()`). `code` is a stable machine-readable tag you can
|
|
38
39
|
* switch on, shared with the `control.error` stream event vocabulary:
|
|
39
40
|
* `'not_connected'`, `'missing_option'`, `'not_representative'`, or the server's
|
|
40
|
-
* own error code for an HTTP failure (when it sends one).
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
constructor(message, status, code) {
|
|
45
|
-
super(message);
|
|
46
|
-
this.name = 'CompanionError';
|
|
47
|
-
this.status = status;
|
|
48
|
-
if (code)
|
|
49
|
-
this.code = code;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
41
|
+
* own error code for an HTTP failure (when it sends one). Defined in errors.ts
|
|
42
|
+
* (so call.ts shares it cycle-free); re-exported here so the public import
|
|
43
|
+
* path is unchanged. */
|
|
44
|
+
export { CompanionError } from './errors.js';
|
|
52
45
|
const SEEN_CAP = 512;
|
|
53
46
|
export class CompanionClient {
|
|
54
47
|
opts;
|
|
@@ -177,26 +170,58 @@ export class CompanionClient {
|
|
|
177
170
|
});
|
|
178
171
|
return { pairId: json.pairId ?? null };
|
|
179
172
|
}
|
|
180
|
-
/** Send a user text turn, optionally with images (data URLs) for a multimodal
|
|
181
|
-
* turn — images need the `files` scope. The reply arrives on the event stream
|
|
182
|
-
* as a `companion.message` — subscribe via onMessage()/start() to receive it.
|
|
183
|
-
*
|
|
184
|
-
* TOKEN STREAMING (P1-2): when any onDelta() subscriber is registered (or
|
|
185
|
-
* `opts.stream` is true), the reply streams token-by-token on this very
|
|
186
|
-
* request — delta subscribers fire as chunks arrive, and onMessage still
|
|
187
|
-
* fires exactly ONCE with the authoritative final text (the streamed copy
|
|
188
|
-
* is emitted locally; the event-stream replay of the same envelope is
|
|
189
|
-
* deduplicated by id). Pass `stream: false` to force the buffered path. */
|
|
190
173
|
async sendText(text, opts) {
|
|
191
174
|
const id = this.requireSession();
|
|
192
|
-
const wantStream = opts?.stream ?? this.deltaHandlers.size > 0;
|
|
193
175
|
const body = { text, ...(opts?.images?.length ? { images: opts.images } : {}) };
|
|
176
|
+
if (opts?.awaitReply)
|
|
177
|
+
return this.sendTextAwaitingReply(id, body, opts);
|
|
178
|
+
const wantStream = opts?.stream ?? this.deltaHandlers.size > 0;
|
|
194
179
|
if (!wantStream) {
|
|
195
180
|
const json = await this.postJson(`/api/companion/session/${id}/input`, body);
|
|
196
181
|
return { seq: json.seq ?? null };
|
|
197
182
|
}
|
|
198
183
|
return this.sendTextStreaming(id, body);
|
|
199
184
|
}
|
|
185
|
+
/** The awaitReply leg of sendText. Prefers the in-request answer (the
|
|
186
|
+
* streaming `done` frame's envelope); falls back to the next
|
|
187
|
+
* `companion.message` off the event stream, bounded by a timeout. The
|
|
188
|
+
* fallback subscription opens BEFORE the POST so a fast event-stream reply
|
|
189
|
+
* can't slip through the gap. */
|
|
190
|
+
async sendTextAwaitingReply(sessionId, body, opts) {
|
|
191
|
+
const timeoutMs = opts?.replyTimeoutMs ?? 60_000;
|
|
192
|
+
let resolveFallback;
|
|
193
|
+
const fallback = new Promise((res) => (resolveFallback = res));
|
|
194
|
+
const off = this.on('companion.message', (env) => resolveFallback(env));
|
|
195
|
+
let timer;
|
|
196
|
+
try {
|
|
197
|
+
let seq = null;
|
|
198
|
+
let envelope;
|
|
199
|
+
if (opts?.stream === false) {
|
|
200
|
+
const json = await this.postJson(`/api/companion/session/${sessionId}/input`, body);
|
|
201
|
+
seq = json.seq ?? null;
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
const r = await this.sendTextStreaming(sessionId, body);
|
|
205
|
+
seq = r.seq;
|
|
206
|
+
envelope = r.envelope;
|
|
207
|
+
}
|
|
208
|
+
if (!envelope) {
|
|
209
|
+
envelope = await Promise.race([
|
|
210
|
+
fallback,
|
|
211
|
+
new Promise((_, reject) => {
|
|
212
|
+
timer = setTimeout(() => reject(new CompanionError(`timed out after ${timeoutMs}ms waiting for the reply — buffered mode needs start() polling the event stream`, 0, 'reply_timeout')), timeoutMs);
|
|
213
|
+
})
|
|
214
|
+
]);
|
|
215
|
+
}
|
|
216
|
+
const replyText = envelope.payload?.text;
|
|
217
|
+
return { seq, text: typeof replyText === 'string' ? replyText : '', envelope };
|
|
218
|
+
}
|
|
219
|
+
finally {
|
|
220
|
+
off();
|
|
221
|
+
if (timer !== undefined)
|
|
222
|
+
clearTimeout(timer);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
200
225
|
/** The streaming leg of sendText: parse the POST response's SSE frames —
|
|
201
226
|
* `delta` / `reset` → delta subscribers, `done` → resolve (emitting the
|
|
202
227
|
* final envelope locally so onMessage fires immediately and the log replay
|
|
@@ -256,7 +281,7 @@ export class CompanionClient {
|
|
|
256
281
|
// latency; the event-stream replay of the same id is deduped.
|
|
257
282
|
if (d.envelope && typeof d.envelope === 'object')
|
|
258
283
|
this.emit(d.envelope);
|
|
259
|
-
return { seq: d.seq ?? null };
|
|
284
|
+
return { seq: d.seq ?? null, envelope: d.envelope ?? undefined };
|
|
260
285
|
}
|
|
261
286
|
}
|
|
262
287
|
if (done)
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Thrown by every helper on an HTTP or client-side failure. `status` is the
|
|
2
|
+
* HTTP status (0 for client-synthesized failures — timeouts, unsupported
|
|
3
|
+
* environments, missing optional deps); `code` is machine-switchable when
|
|
4
|
+
* the server (or the SDK itself) names a cause. */
|
|
5
|
+
export declare class CompanionError extends Error {
|
|
6
|
+
status: number;
|
|
7
|
+
code?: string;
|
|
8
|
+
constructor(message: string, status: number, code?: string);
|
|
9
|
+
}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// CompanionError — the one error type every SDK helper rejects with (README
|
|
2
|
+
// contract: consumers `switch` on `.code` instead of string-matching prose).
|
|
3
|
+
// Lives in its own module so call.ts can use it without a runtime cycle
|
|
4
|
+
// through client.ts (client.ts re-exports it, keeping the public import path
|
|
5
|
+
// `@pouchy_ai/companion-sdk` → `CompanionError` unchanged).
|
|
6
|
+
/** Thrown by every helper on an HTTP or client-side failure. `status` is the
|
|
7
|
+
* HTTP status (0 for client-synthesized failures — timeouts, unsupported
|
|
8
|
+
* environments, missing optional deps); `code` is machine-switchable when
|
|
9
|
+
* the server (or the SDK itself) names a cause. */
|
|
10
|
+
export class CompanionError extends Error {
|
|
11
|
+
status;
|
|
12
|
+
code;
|
|
13
|
+
constructor(message, status, code) {
|
|
14
|
+
super(message);
|
|
15
|
+
this.name = 'CompanionError';
|
|
16
|
+
this.status = status;
|
|
17
|
+
if (code)
|
|
18
|
+
this.code = code;
|
|
19
|
+
}
|
|
20
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CompanionClient, type CompanionClientOptions } from './client.js';
|
|
2
2
|
export { CompanionClient, CompanionError, pouchyBrandIconUrl } from './client.js';
|
|
3
|
-
export type { CompanionClientOptions, HelloAck, RecalledMemory, CompanionTurn, CallCredentials, CompanionToolDecl, ToolCallEvent, WorldStateInput, CompanionAvatar, CompanionWallet, WalletBalance, BrandIconSize, EndSessionResult } from './client.js';
|
|
3
|
+
export type { CompanionClientOptions, HelloAck, RecalledMemory, CompanionTurn, CallCredentials, CompanionToolDecl, ToolCallEvent, WorldStateInput, CompanionAvatar, CompanionWallet, WalletBalance, BrandIconSize, EndSessionResult, SendTextReply } from './client.js';
|
|
4
4
|
export { openCompanionCall, HOST_CONTROL_TOOLS, HOST_CONTROL_TOOL_NAMES, AVATAR_VISUAL_TOOLS, AVATAR_VISUAL_TOOL_NAMES } from './call.js';
|
|
5
5
|
export type { CompanionCall, CompanionCallOptions, VoiceToolBridge } from './call.js';
|
|
6
6
|
export { COMPANION_SCOPES, COMPANION_MODALITIES, SENSITIVE_SCOPES, REPRESENT_SCOPES, DEFAULT_SCOPES, DEFAULT_MODALITIES, isSensitiveScope, isRepresentScope, hasScope } from './scopes.js';
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pouchy_ai/companion-sdk",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Embed the Pouchy companion
|
|
3
|
+
"version": "0.26.0",
|
|
4
|
+
"description": "Embed the Pouchy companion — chat, voice, tools, memory, live world-state, instant UI, and agent-to-agent messaging — in any app, game, or site.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|
|
7
7
|
"homepage": "https://pouchy.ai",
|