@pouchy_ai/admin-sdk 0.13.0 → 0.14.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 CHANGED
@@ -2,6 +2,32 @@
2
2
 
3
3
  All notable changes to `@pouchy_ai/admin-sdk` are documented here.
4
4
 
5
+ ## 0.14.0 — 2026-08-02
6
+
7
+ - **Channel provider registration is now typed.** The server registers
8
+ `telegram`/`discord` connectors with their provider on create (Telegram
9
+ `setWebhook`, Discord slash command) and re-registers on a `rotate` or a
10
+ secret replacement, reporting the outcome as a `provision` object. The
11
+ package typed neither half, so the opt-out was unreachable and the outcome
12
+ unreadable:
13
+ - `createChannel` takes **`autoProvision?: boolean`**. This is the half that
14
+ mattered: `setWebhook` REPLACES rather than adds, so an integrator who
15
+ already owns their bot's webhook had no typed way to say "don't touch it"
16
+ — the closed input type made the flag an excess-property error, leaving
17
+ `request()` or a cast as the only route.
18
+ - `createChannel` / `updateChannel` return **`provision?:
19
+ ChannelProvisionResult`**, and `updateChannel` returns the rotate-only
20
+ `inboundUrl?`. A `failed` outcome on a rotate is the one that bites — the
21
+ provider still points at the URL the rotate just invalidated, and
22
+ `manualCommand` is the fix.
23
+ - `ChannelProvisionResult`, `ChannelProvisionStatus` and
24
+ `ChannelProvisionCode` are exported. Branch on `code` (a stable contract
25
+ vocabulary), never on `detail` (provider prose).
26
+
27
+ Purely additive: no existing signature narrowed, so 0.13.x code compiles
28
+ unchanged. `admin-sdk-provision.drift.test.ts` now binds both unions to
29
+ `channels/provision.ts` so the two copies cannot drift again.
30
+
5
31
  ## 0.13.0 — 2026-08-02
6
32
 
7
33
  - **`getUsageHistory({ months? })`** over `GET /v1/admin/usage/history` —
package/README.md CHANGED
@@ -208,6 +208,40 @@ Channel types are checked at compile time: `createChannel` takes a
208
208
  `internal-a2a`), and `secret` is a named `ChannelSecretInput`. Per-transport
209
209
  `secret.extra` fields are listed in <https://pouchy.ai/docs/channel-setup>.
210
210
 
211
+ **Telegram and Discord register themselves.** On create — and again on a
212
+ `rotate: true` or a secret replacement, which invalidate what the provider
213
+ holds — the server calls Telegram's `setWebhook` / registers Discord's slash
214
+ command with `secret.token`, and reports the outcome as a
215
+ `ChannelProvisionResult` on `provision`. Two things to know:
216
+
217
+ - `setWebhook` **replaces** rather than adds. If you already manage your bot's
218
+ webhook, pass `autoProvision: false` or the create will overwrite it.
219
+ - The connector is durable before any provider call, so this never fails the
220
+ request — a `failed` outcome is reported, not thrown. Branch on `code` (a
221
+ stable vocabulary, `ChannelProvisionCode`), never on `detail`; `manualCommand`
222
+ is the equivalent curl with secrets left as `<PLACEHOLDER>`.
223
+
224
+ ```ts
225
+ import { createAdminClient } from '@pouchy_ai/admin-sdk';
226
+
227
+ const admin = createAdminClient({ adminKey: process.env.POUCHY_ADMIN_KEY! });
228
+
229
+ const { connector, provision } = await admin.createChannel({
230
+ type: 'telegram',
231
+ agentId: process.env.AGENT_ID!,
232
+ secret: {
233
+ token: process.env.TELEGRAM_BOT_TOKEN!,
234
+ inboundSecret: process.env.TELEGRAM_SECRET_TOKEN!
235
+ }
236
+ });
237
+
238
+ if (provision?.status === 'failed') {
239
+ // The connector exists — only the webhook registration didn't land.
240
+ console.warn('register by hand:', provision.detail, provision.manualCommand);
241
+ }
242
+ console.log(connector.id);
243
+ ```
244
+
211
245
  Capability **signing-key management is deliberately not mirrored** here: the
212
246
  one-time `pcsk_`/`pesk_` plaintext reveal stays a human act on the owner
213
247
  plane (dashboard / owner API). `listCapabilities` returns masked key status
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export declare const ADMIN_SDK_VERSION = "0.13.0";
1
+ export declare const ADMIN_SDK_VERSION = "0.14.0";
2
2
  export declare const DEFAULT_BASE_URL = "https://pouchy.ai/v1/admin";
3
3
  /** Deadline for the routes whose server handler declares `maxDuration: 300` —
4
4
  * the server's own ceiling plus headroom, so a client abort can only ever mean
@@ -307,6 +307,32 @@ export interface ChannelSecretInput {
307
307
  /** Extra named credentials for transports whose auth needs more than the pair above. */
308
308
  extra?: Record<string, string>;
309
309
  }
310
+ /** Outcome class of the provider registration the server performs on create,
311
+ * and on a rotate / secret replacement. Mirrors the server's `ProvisionStatus`
312
+ * (`channels/provision.ts`); `admin-sdk-provision.drift.test.ts` binds them. */
313
+ export type ChannelProvisionStatus = 'ok' | 'skipped' | 'failed';
314
+ /** Machine-readable reason for a `ChannelProvisionResult`. The server treats
315
+ * this vocabulary as part of the response contract (the dashboard keys its
316
+ * copy off it), so branch on `code`, never on `detail`. */
317
+ export type ChannelProvisionCode = 'webhook_set' | 'command_registered' | 'unsupported_type' | 'no_token' | 'no_inbound_url' | 'not_requested' | 'invalid_command_name' | 'app_lookup_failed' | 'upstream_rejected' | 'upstream_unreachable';
318
+ /** What the provider said when the server registered this connector for you.
319
+ *
320
+ * Registration is an enrichment on top of a durable write: the connector
321
+ * exists whether or not the provider answered, so this NEVER turns a
322
+ * successful create into an error — a non-ok outcome is reported here instead.
323
+ * A `failed` result always carries `manualCommand`, the equivalent curl with
324
+ * every credential left as a `<PLACEHOLDER>`, so the fallback is the manual
325
+ * registration this feature replaced rather than a dead end. `detail` is built
326
+ * from the provider's own message and never contains a credential. */
327
+ export interface ChannelProvisionResult {
328
+ status: ChannelProvisionStatus;
329
+ code: ChannelProvisionCode;
330
+ /** Operator-facing detail, from the provider's message. Never a credential. */
331
+ detail?: string;
332
+ /** The equivalent command to run by hand, secrets left as `<PLACEHOLDER>`.
333
+ * Present on every non-ok outcome a human can act on. */
334
+ manualCommand?: string;
335
+ }
310
336
  /** A durable run as the API returns it. Typed rather than `unknown` because
311
337
  * the parked-run flow — read `status`, read `awaiting.token`, answer — is the
312
338
  * SDK's most important interaction, and forcing a cast there would put the
@@ -659,17 +685,44 @@ export interface AdminClient {
659
685
  /** Connector credentials (bot token, signing secret, …) — stored
660
686
  * encrypted, never returned. */
661
687
  secret?: ChannelSecretInput;
688
+ /** Default **true**. For `telegram`/`discord` the server registers the
689
+ * connector with the provider on create — Telegram `setWebhook(inboundUrl)`,
690
+ * Discord a slash command — using `secret.token`, and reports the outcome
691
+ * on `provision`. Set `false` if you already manage that registration:
692
+ * otherwise the create OVERWRITES your bot's existing webhook, since
693
+ * `setWebhook` replaces rather than adds. Every other transport ignores
694
+ * this (`provision.code: 'unsupported_type'`). */
695
+ autoProvision?: boolean;
662
696
  }): Promise<{
663
697
  connector: {
664
698
  id: string;
665
699
  };
666
700
  inboundUrl: string;
701
+ /** Absent for transports that need no provider registration. */
702
+ provision?: ChannelProvisionResult;
667
703
  }>;
668
704
  getChannel(channelId: string): Promise<{
669
705
  connector: unknown;
670
706
  }>;
707
+ /** Patch a connector. Accepts `agentId`, `enabled`, `config`, `secret`,
708
+ * `rotate` and `autoProvision` (see `createChannel`).
709
+ *
710
+ * `rotate: true` re-signs the inbound URL and returns it ONCE on
711
+ * `inboundUrl` — which also invalidates the old one, so a telegram/discord
712
+ * connector is RE-REGISTERED with the provider on a rotate or a secret
713
+ * replacement (without that, the provider would keep delivering to a dead
714
+ * endpoint while the connector still looked healthy). Check `provision` on
715
+ * those two patches: a `failed` outcome means the provider still points at
716
+ * the old URL, and `manualCommand` is the fix. Pass `autoProvision: false`
717
+ * to suppress. Every other patch — enable/disable, rebind, config — leaves
718
+ * both fields absent. */
671
719
  updateChannel(channelId: string, patch: Record<string, unknown>): Promise<{
672
720
  connector: unknown;
721
+ /** Present only when the patch carried `rotate: true`. */
722
+ inboundUrl?: string;
723
+ /** Present only on a rotate or a secret replacement, for a provisionable
724
+ * transport, when not suppressed with `autoProvision: false`. */
725
+ provision?: ChannelProvisionResult;
673
726
  }>;
674
727
  deleteChannel(channelId: string): Promise<{
675
728
  ok: boolean;
package/dist/index.js CHANGED
@@ -8,7 +8,7 @@
8
8
  // import { createAdminClient } from '@pouchy_ai/admin-sdk';
9
9
  // const admin = createAdminClient({ adminKey: process.env.POUCHY_ADMIN_KEY! });
10
10
  // const { agents } = await admin.listAgents();
11
- export const ADMIN_SDK_VERSION = '0.13.0';
11
+ export const ADMIN_SDK_VERSION = '0.14.0';
12
12
  export const DEFAULT_BASE_URL = 'https://pouchy.ai/v1/admin';
13
13
  /** Default per-request timeout (ms). A hung upstream otherwise never rejects. */
14
14
  const DEFAULT_TIMEOUT_MS = 30_000;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pouchy_ai/admin-sdk",
3
- "version": "0.13.0",
3
+ "version": "0.14.0",
4
4
  "description": "Typed TypeScript client for the Pouchy Admin API \u2014 manage agents, keys, end users, knowledge, skills, channels, schedules, webhooks and credentials headlessly, with a project Admin key.",
5
5
  "type": "module",
6
6
  "license": "SEE LICENSE IN LICENSE",