@pouchy_ai/companion-sdk 0.19.0 → 0.20.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 +22 -0
- package/README.md +26 -3
- package/dist/client.d.ts +23 -0
- package/dist/client.js +19 -0
- package/dist/index.d.ts +1 -1
- package/dist/protocol.d.ts +7 -1
- package/dist/protocol.js +10 -4
- package/dist/scopes.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -12,6 +12,28 @@ a protocol bump is always called out explicitly here.
|
|
|
12
12
|
|
|
13
13
|
## [Unreleased]
|
|
14
14
|
|
|
15
|
+
## [0.20.0] - 2026-07-11
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- `client.getWallet(): Promise<CompanionWallet>` and the `GET /api/companion/wallet`
|
|
20
|
+
endpoint — read the companion instance's OWN wallet (nonzero stablecoin
|
|
21
|
+
balances + total USD). Read-only and receive-only; requires the `wallet.read`
|
|
22
|
+
scope (or `wallet.spend`, which subsumes it). Shares its read path with the
|
|
23
|
+
conversational `get_wallet_balance` tool so the endpoint and the in-chat answer
|
|
24
|
+
can never diverge. New exported types `CompanionWallet` / `WalletBalance`.
|
|
25
|
+
|
|
26
|
+
## [0.19.1] - 2026-07-10
|
|
27
|
+
|
|
28
|
+
### Documentation
|
|
29
|
+
|
|
30
|
+
- README gains a client-method reference table (memory ingest, history,
|
|
31
|
+
setModalities, ping, pendingConfirms/confirmAction incl. the
|
|
32
|
+
exec_failed/retryable retry contract, endSession skipped reasons, close(),
|
|
33
|
+
startCall/connectCall, getAvatar/brandIconUrl) plus a note on
|
|
34
|
+
HOST_CONTROL_TOOLS and AVATAR_VISUAL_TOOLS (declare-or-silent-no-op).
|
|
35
|
+
No code change.
|
|
36
|
+
|
|
15
37
|
## [0.19.0] - 2026-07-10
|
|
16
38
|
|
|
17
39
|
### Added
|
package/README.md
CHANGED
|
@@ -72,11 +72,11 @@ Subscribe with `on(type, fn)` (or `'*'`), or these typed convenience helpers:
|
|
|
72
72
|
| `onInterfaceUpdate(fn)` | `companion.ui_update` | live `{key,value}` update to an already-rendered panel (no rebuild) |
|
|
73
73
|
| `onSocialMessage(fn)` | `companion.social_message` | inbound A2A friend message, delivered cross-app. Needs `social.message` |
|
|
74
74
|
| `onConfirmRequest(fn)` | `companion.confirm_request` | a sensitive-op approval request. **Platform session tokens** (your end users): show your own confirm card and resolve it with `confirmAction` — this is how confirm-gated custom skills (POST / credentialed) run. First-party user tokens: observe-only — approval stays first-party (where the `stepUp:true` biometric gate lives) |
|
|
75
|
-
| `onAudio(fn)` | `companion.audio` | TTS clip (non-call modality) |
|
|
76
|
-
| `onExpression(fn)` | `companion.expression` | avatar viseme / expression / gesture |
|
|
75
|
+
| `onAudio(fn)` | `companion.audio` | TTS clip (non-call modality). _(reserved — not emitted yet)_ |
|
|
76
|
+
| `onExpression(fn)` | `companion.expression` | avatar viseme / expression / gesture. _(reserved — not emitted yet)_ |
|
|
77
77
|
| `onVoiceInject(fn)` | `companion.voice_inject` | `fn({text, speak})` — a `voiceRelevant` world-state line to say aloud during a live call; route `text` to your voice session when `speak` |
|
|
78
78
|
| `onTyping(fn)` | `companion.typing` | activity indicator — `fn({active})` fires `true` when a turn starts working and `false` when it finishes / pauses, spanning the tool-loop / thinking phase before the first text delta. Drive a "typing…" state |
|
|
79
|
-
| `onUsage(fn)` | `control.usage` | per-token metering echo |
|
|
79
|
+
| `onUsage(fn)` | `control.usage` | per-token metering echo. _(reserved — not emitted yet)_ |
|
|
80
80
|
| `onError(fn)` | `control.error` | agent / stream errors |
|
|
81
81
|
|
|
82
82
|
### Instant UI
|
|
@@ -92,6 +92,29 @@ Reference renderers ship in [`examples/`](../../examples): `web-instant-ui` (van
|
|
|
92
92
|
`native-instant-ui` (SwiftUI + Jetpack Compose), and `cli-skills` (terminal +
|
|
93
93
|
local/device skills).
|
|
94
94
|
|
|
95
|
+
## Client methods (beyond the quickstart)
|
|
96
|
+
|
|
97
|
+
| Method | What it does |
|
|
98
|
+
|---|---|
|
|
99
|
+
| `recall(query)` / `remember(text)` | Read / write the token-scoped memory namespace. |
|
|
100
|
+
| `ingestKnowledge(text, opts?)` / `ingestFile(file)` | Push documents into the user's knowledge base ("My materials"); needs `memory.write:core`. |
|
|
101
|
+
| `history(limit?)` | Fetch the session transcript — restore chat on reload. |
|
|
102
|
+
| `setModalities([...])` | Switch active I/O mid-session (within the token's grant). |
|
|
103
|
+
| `ping()` | Keepalive for long-idle embeds. |
|
|
104
|
+
| `pendingConfirms()` / `confirmAction(id, approve)` | List / resolve pending sensitive-action confirms (platform session tokens). On `{ status: 'exec_failed', retryable: true }` you MAY re-call the same confirmId — idempotent actions only. |
|
|
105
|
+
| `endSession()` | Distill the session into durable memory now; returns `{ skipped?: 'no_session' \| 'no_content' \| 'throttled' }`. |
|
|
106
|
+
| `close()` | One-call teardown: `stop()` + `endSession()` — the text-session mirror of the call handle's `close()`. |
|
|
107
|
+
| `startCall(opts)` / `connectCall(opts)` | Voice plane: raw credentials / fully-wired call handle (`call.close()` ends + folds the transcript into memory). |
|
|
108
|
+
| `getAvatar()` / `brandIconUrl(size?)` | The user's avatar (VRM/portrait) and the Pouchy brand icon for your UI. |
|
|
109
|
+
| `getWallet()` | Read the instance's own wallet — `{ balances: [{ currency, amount }], totalUsd, currency }`. Read-only + receive-only; needs the `wallet.read` scope. |
|
|
110
|
+
|
|
111
|
+
Tool calling beyond your own declared tools: `HOST_CONTROL_TOOLS` (universal
|
|
112
|
+
verbs — `invoke_action`, `set_feature`, `set_value`, `navigate`, `highlight`)
|
|
113
|
+
are offered automatically once you declare `tools`/`handles`, and
|
|
114
|
+
`AVATAR_VISUAL_TOOLS` (`play_gesture` / `play_expression`) let avatar-rendering
|
|
115
|
+
embeds receive expression cues — declare them or they no-op silently. Full
|
|
116
|
+
contract: `docs/companion-host-control.md`.
|
|
117
|
+
|
|
95
118
|
## Scopes (typed)
|
|
96
119
|
|
|
97
120
|
The full capability-scope vocabulary ships as typed constants — no more
|
package/dist/client.d.ts
CHANGED
|
@@ -123,6 +123,23 @@ export interface CompanionAvatar {
|
|
|
123
123
|
* built-ins today (reserved for custom previews / server-rendered thumbs). */
|
|
124
124
|
imageUrl: string | null;
|
|
125
125
|
}
|
|
126
|
+
/** One nonzero stablecoin balance line. */
|
|
127
|
+
export interface WalletBalance {
|
|
128
|
+
/** Stablecoin code (USDT / USDC / DAI / USD1). */
|
|
129
|
+
currency: string;
|
|
130
|
+
/** Decimal amount as a string (not atomic units), e.g. "5.83". */
|
|
131
|
+
amount: string;
|
|
132
|
+
}
|
|
133
|
+
/** Read-only snapshot of the companion instance's OWN wallet (receive-only —
|
|
134
|
+
* there is no way to move funds via the SDK). Requires the `wallet.read` scope. */
|
|
135
|
+
export interface CompanionWallet {
|
|
136
|
+
/** Nonzero per-currency balances (empty when the wallet is empty). */
|
|
137
|
+
balances: WalletBalance[];
|
|
138
|
+
/** Total across the balances; the allowed stablecoins are USD-pegged 1:1. */
|
|
139
|
+
totalUsd: number;
|
|
140
|
+
/** Denomination of `totalUsd` (always "USD" today). */
|
|
141
|
+
currency: string;
|
|
142
|
+
}
|
|
126
143
|
/** Available sizes for the Pouchy brand icon (px). */
|
|
127
144
|
export type BrandIconSize = 256 | 512 | 1024;
|
|
128
145
|
/** Canonical URL of the official Pouchy brand icon at `size` px, derived from a
|
|
@@ -392,6 +409,12 @@ export declare class CompanionClient {
|
|
|
392
409
|
* and the /models asset is CORS-enabled, so a cross-origin renderer can fetch
|
|
393
410
|
* the VRM directly. Reflects the user's live choice (built-in or custom). */
|
|
394
411
|
getAvatar(): Promise<CompanionAvatar>;
|
|
412
|
+
/** Read the companion instance's OWN wallet — nonzero stablecoin balances +
|
|
413
|
+
* total USD. Read-only and receive-only (spends go through the confirm-gated
|
|
414
|
+
* pay tools, never here). Requires the `wallet.read` scope (or `wallet.spend`,
|
|
415
|
+
* which subsumes it). Same data the companion gives when asked "what's my
|
|
416
|
+
* balance?". */
|
|
417
|
+
getWallet(): Promise<CompanionWallet>;
|
|
395
418
|
/** Canonical URL of the official Pouchy brand icon (square PNG, transparent
|
|
396
419
|
* background) at the given size. Static + public — needs no token — so it's
|
|
397
420
|
* safe to drop straight into an `<img src>` for "powered by Pouchy" badges,
|
package/dist/client.js
CHANGED
|
@@ -593,6 +593,25 @@ export class CompanionClient {
|
|
|
593
593
|
imageUrl: json.imageUrl ?? null
|
|
594
594
|
};
|
|
595
595
|
}
|
|
596
|
+
/** Read the companion instance's OWN wallet — nonzero stablecoin balances +
|
|
597
|
+
* total USD. Read-only and receive-only (spends go through the confirm-gated
|
|
598
|
+
* pay tools, never here). Requires the `wallet.read` scope (or `wallet.spend`,
|
|
599
|
+
* which subsumes it). Same data the companion gives when asked "what's my
|
|
600
|
+
* balance?". */
|
|
601
|
+
async getWallet() {
|
|
602
|
+
const res = await this.doFetch(this.url('/api/companion/wallet'), {
|
|
603
|
+
headers: { Authorization: `Bearer ${this.opts.token}` }
|
|
604
|
+
});
|
|
605
|
+
const json = (await res.json().catch(() => null));
|
|
606
|
+
if (!res.ok || !json || json.ok === false) {
|
|
607
|
+
throw new CompanionError(json?.error || `wallet fetch failed (${res.status})`, res.status);
|
|
608
|
+
}
|
|
609
|
+
return {
|
|
610
|
+
balances: json.balances ?? [],
|
|
611
|
+
totalUsd: json.totalUsd ?? 0,
|
|
612
|
+
currency: json.currency ?? 'USD'
|
|
613
|
+
};
|
|
614
|
+
}
|
|
596
615
|
/** Canonical URL of the official Pouchy brand icon (square PNG, transparent
|
|
597
616
|
* background) at the given size. Static + public — needs no token — so it's
|
|
598
617
|
* safe to drop straight into an `<img src>` for "powered by Pouchy" badges,
|
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, WorldStateInput, CompanionAvatar, BrandIconSize, EndSessionResult } from './client.js';
|
|
3
|
+
export type { CompanionClientOptions, HelloAck, RecalledMemory, CompanionTurn, CallCredentials, CompanionToolDecl, WorldStateInput, CompanionAvatar, CompanionWallet, WalletBalance, BrandIconSize, EndSessionResult } 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/dist/protocol.d.ts
CHANGED
|
@@ -2,7 +2,13 @@ export declare const PROTOCOL_VERSION: 1;
|
|
|
2
2
|
/** App → Pouchy (control/data plane). */
|
|
3
3
|
export declare const INBOUND_TYPES: readonly ["hello", "input.text", "context.event", "context.snapshot", "tool.result", "control.start_call", "control.end_call", "control.set_modalities", "control.ping"];
|
|
4
4
|
export type InboundType = (typeof INBOUND_TYPES)[number];
|
|
5
|
-
/** Pouchy → app (control/data plane).
|
|
5
|
+
/** Pouchy → app (control/data plane).
|
|
6
|
+
* NOTE: three types are RESERVED — part of the vocabulary + typed handlers, but
|
|
7
|
+
* the server does NOT emit them yet, so `onAudio` / `onExpression` / `onUsage`
|
|
8
|
+
* are safe to register but won't fire until a producer ships. Don't build a UX
|
|
9
|
+
* that depends on them today. (companion.audio → non-call reply TTS;
|
|
10
|
+
* companion.expression → avatar viseme/expression cues; control.usage →
|
|
11
|
+
* per-turn usage-metering echo.) */
|
|
6
12
|
export declare const OUTBOUND_TYPES: readonly ["hello.ack", "companion.message", "companion.audio", "companion.tool_call", "companion.ui_action", "companion.ui_update", "companion.expression", "companion.voice_inject", "companion.confirm_request", "companion.social_message", "companion.typing", "control.call_ready", "control.error", "control.usage"];
|
|
7
13
|
export type OutboundType = (typeof OUTBOUND_TYPES)[number];
|
|
8
14
|
export type MessageType = InboundType | OutboundType;
|
package/dist/protocol.js
CHANGED
|
@@ -17,20 +17,26 @@ export const INBOUND_TYPES = [
|
|
|
17
17
|
'control.set_modalities',
|
|
18
18
|
'control.ping'
|
|
19
19
|
];
|
|
20
|
-
/** Pouchy → app (control/data plane).
|
|
20
|
+
/** Pouchy → app (control/data plane).
|
|
21
|
+
* NOTE: three types are RESERVED — part of the vocabulary + typed handlers, but
|
|
22
|
+
* the server does NOT emit them yet, so `onAudio` / `onExpression` / `onUsage`
|
|
23
|
+
* are safe to register but won't fire until a producer ships. Don't build a UX
|
|
24
|
+
* that depends on them today. (companion.audio → non-call reply TTS;
|
|
25
|
+
* companion.expression → avatar viseme/expression cues; control.usage →
|
|
26
|
+
* per-turn usage-metering echo.) */
|
|
21
27
|
export const OUTBOUND_TYPES = [
|
|
22
28
|
'hello.ack',
|
|
23
29
|
'companion.message',
|
|
24
|
-
'companion.audio',
|
|
30
|
+
'companion.audio', // reserved — not emitted yet
|
|
25
31
|
'companion.tool_call',
|
|
26
32
|
'companion.ui_action',
|
|
27
33
|
'companion.ui_update',
|
|
28
|
-
'companion.expression',
|
|
34
|
+
'companion.expression', // reserved — not emitted yet
|
|
29
35
|
'companion.voice_inject',
|
|
30
36
|
'companion.confirm_request',
|
|
31
37
|
'companion.social_message',
|
|
32
38
|
'companion.typing',
|
|
33
39
|
'control.call_ready',
|
|
34
40
|
'control.error',
|
|
35
|
-
'control.usage'
|
|
41
|
+
'control.usage' // reserved — not emitted yet
|
|
36
42
|
];
|
package/dist/scopes.js
CHANGED
|
@@ -21,7 +21,7 @@ export const COMPANION_SCOPES = [
|
|
|
21
21
|
'memory.read:core', // read the shared global brain (SENSITIVE)
|
|
22
22
|
'memory.write:core', // write into the shared global brain (SENSITIVE)
|
|
23
23
|
'skills.execute', // run the user's installed skills (SENSITIVE)
|
|
24
|
-
'wallet.read', // READ-ONLY wallet: balance + own deposit address (receive-only; not sensitive)
|
|
24
|
+
'wallet.read', // READ-ONLY wallet: balance + own deposit address (receive-only; not sensitive). Surfaced via the companion's wallet tools (ask it) — no standalone REST endpoint.
|
|
25
25
|
'wallet.spend', // spend from the Care Wallet (SENSITIVE)
|
|
26
26
|
'social.message', // message friends via A2A (SENSITIVE)
|
|
27
27
|
// ── Representative ("on-behalf-of") plane ─────────────────────────────
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pouchy_ai/companion-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
4
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",
|