@pouchy_ai/admin-sdk 0.12.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 +37 -0
- package/README.md +35 -1
- package/dist/index.d.ts +80 -3
- package/dist/index.js +2 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,43 @@
|
|
|
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
|
+
|
|
31
|
+
## 0.13.0 — 2026-08-02
|
|
32
|
+
|
|
33
|
+
- **`getUsageHistory({ months? })`** over `GET /v1/admin/usage/history` —
|
|
34
|
+
month-over-month `{ months: MonthUsageHistoryEntry[], scope }`, oldest
|
|
35
|
+
first, quiet months zero-filled. The route shipped with the 1.4.x history
|
|
36
|
+
work; this closes the package's own "new mirror ⇒ new method" convention
|
|
37
|
+
gap (a headless operator could read this month but not the history).
|
|
38
|
+
`scope: 'account'` is the pooled series the plan cap compares;
|
|
39
|
+
`'project'` is the fallback when the account can't be resolved.
|
|
40
|
+
`MonthUsageHistoryEntry` is exported.
|
|
41
|
+
|
|
5
42
|
## 0.12.0 — 2026-08-01
|
|
6
43
|
|
|
7
44
|
- **Typed capability declarations.** `publishCapability` now takes a
|
package/README.md
CHANGED
|
@@ -200,7 +200,7 @@ Reads (`GET`) are not covered by that bucket. `retryAfter` is available from
|
|
|
200
200
|
| Durable runs | `listRuns` · `createRun` · `getRun` · `cancelRun` · `resumeRun` · `signalRun` |
|
|
201
201
|
| Data capabilities | `listCapabilities` (heads + MASKED signing status) · `publishCapability` (TYPED `CapabilityDeclaration`; immutable next version, idempotent on content) · `setCapabilityDisabled` (per-capability live revoke) · `listCapabilityVersions` (history; rollback = republish an old declaration) · `testReadCapability` · `testActionCapability({ confirmDuplicates: true, … })` (REAL deliveries incl. intentional duplicates — 428 without consent) · `listActionExecutions` (the durable Action journal, incl. `authorizedBy: 'automation'`) · `listEventReceipts` (receipts + wake trail) |
|
|
202
202
|
| Webhooks | `listWebhooks` · `createWebhook` · `updateWebhook` · `rotateWebhookSecret` · `deleteWebhook` · `testWebhook` · `redeliverWebhook` |
|
|
203
|
-
| Reporting | `getUsage` · `getBilling` · `getTracesSummary` · `getRecentTraces` · `getLogs` · `getProject` · `updateProject` |
|
|
203
|
+
| Reporting | `getUsage` · `getUsageHistory` · `getBilling` · `getTracesSummary` · `getRecentTraces` · `getLogs` · `getProject` · `updateProject` |
|
|
204
204
|
| Escape hatch | `request(method, path, body?)` — any endpoint not yet typed |
|
|
205
205
|
|
|
206
206
|
Channel types are checked at compile time: `createChannel` takes a
|
|
@@ -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.
|
|
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
|
|
@@ -220,6 +220,16 @@ export interface MonthUsage {
|
|
|
220
220
|
tokensOut: number;
|
|
221
221
|
[k: string]: unknown;
|
|
222
222
|
}
|
|
223
|
+
/** One month of the usage-history series. Unlike `MonthUsage` (the current
|
|
224
|
+
* month's full meter incl. day buckets and the cap), history rows are the
|
|
225
|
+
* compact per-month rollup the server keeps for every past month. */
|
|
226
|
+
export interface MonthUsageHistoryEntry {
|
|
227
|
+
month: string;
|
|
228
|
+
mau: number;
|
|
229
|
+
mauTest: number;
|
|
230
|
+
sessions: number;
|
|
231
|
+
[k: string]: unknown;
|
|
232
|
+
}
|
|
223
233
|
export interface AuditRow {
|
|
224
234
|
at: string;
|
|
225
235
|
type: string;
|
|
@@ -297,6 +307,32 @@ export interface ChannelSecretInput {
|
|
|
297
307
|
/** Extra named credentials for transports whose auth needs more than the pair above. */
|
|
298
308
|
extra?: Record<string, string>;
|
|
299
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
|
+
}
|
|
300
336
|
/** A durable run as the API returns it. Typed rather than `unknown` because
|
|
301
337
|
* the parked-run flow — read `status`, read `awaiting.token`, answer — is the
|
|
302
338
|
* SDK's most important interaction, and forcing a cast there would put the
|
|
@@ -649,17 +685,44 @@ export interface AdminClient {
|
|
|
649
685
|
/** Connector credentials (bot token, signing secret, …) — stored
|
|
650
686
|
* encrypted, never returned. */
|
|
651
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;
|
|
652
696
|
}): Promise<{
|
|
653
697
|
connector: {
|
|
654
698
|
id: string;
|
|
655
699
|
};
|
|
656
700
|
inboundUrl: string;
|
|
701
|
+
/** Absent for transports that need no provider registration. */
|
|
702
|
+
provision?: ChannelProvisionResult;
|
|
657
703
|
}>;
|
|
658
704
|
getChannel(channelId: string): Promise<{
|
|
659
705
|
connector: unknown;
|
|
660
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. */
|
|
661
719
|
updateChannel(channelId: string, patch: Record<string, unknown>): Promise<{
|
|
662
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;
|
|
663
726
|
}>;
|
|
664
727
|
deleteChannel(channelId: string): Promise<{
|
|
665
728
|
ok: boolean;
|
|
@@ -670,8 +733,10 @@ export interface AdminClient {
|
|
|
670
733
|
/** Create a schedule. `externalUserId` and `prompt` are required alongside
|
|
671
734
|
* `agentId`; the schedule fires by `intervalMinutes` (recurring, >=5) or
|
|
672
735
|
* `runAt` (one-shot **epoch milliseconds** — an ISO string is silently
|
|
673
|
-
* ignored by the server
|
|
674
|
-
*
|
|
736
|
+
* ignored by the server; must be in the future — a past `runAt` is a 400,
|
|
737
|
+
* with a 60s clock-skew grace) — there is NO cron field. A storage outage
|
|
738
|
+
* answers 503, not a validation 400. Returns the stored record, whose id
|
|
739
|
+
* lives on `.id`. */
|
|
675
740
|
createSchedule(input: {
|
|
676
741
|
agentId: string;
|
|
677
742
|
externalUserId: string;
|
|
@@ -918,6 +983,18 @@ export interface AdminClient {
|
|
|
918
983
|
getUsage(): Promise<{
|
|
919
984
|
usage: MonthUsage;
|
|
920
985
|
}>;
|
|
986
|
+
/** Month-over-month usage series, oldest first; quiet months zero-fill
|
|
987
|
+
* rather than drop. `scope: 'account'` means the pooled account series —
|
|
988
|
+
* the figure the plan cap actually compares (a multi-project account's
|
|
989
|
+
* pooled number differs from any one project's slice); `'project'` is the
|
|
990
|
+
* fallback when the account can't be resolved. */
|
|
991
|
+
getUsageHistory(params?: {
|
|
992
|
+
/** Window size in months, clamped server-side to 1..24 (default 12). */
|
|
993
|
+
months?: number;
|
|
994
|
+
}): Promise<{
|
|
995
|
+
months: MonthUsageHistoryEntry[];
|
|
996
|
+
scope: 'account' | 'project';
|
|
997
|
+
}>;
|
|
921
998
|
getBilling(): Promise<{
|
|
922
999
|
billing: {
|
|
923
1000
|
plan: string;
|
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.
|
|
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;
|
|
@@ -302,6 +302,7 @@ export function createAdminClient(opts) {
|
|
|
302
302
|
testWebhook: (id) => request('POST', `/webhooks/${encodeURIComponent(id)}/test`),
|
|
303
303
|
redeliverWebhook: (id) => request('POST', `/webhooks/deliveries/${encodeURIComponent(id)}/redeliver`),
|
|
304
304
|
getUsage: () => request('GET', '/usage'),
|
|
305
|
+
getUsageHistory: (params = {}) => request('GET', `/usage/history${qs(params)}`),
|
|
305
306
|
getBilling: () => request('GET', '/billing'),
|
|
306
307
|
getTracesSummary: (params) => request('GET', `/traces/summary${qs(params)}`),
|
|
307
308
|
getRecentTraces: (params = {}) => request('GET', `/traces/recent${qs({ ...params, errorsOnly: params.errorsOnly ? '1' : undefined })}`),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pouchy_ai/admin-sdk",
|
|
3
|
-
"version": "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",
|