@pouchy_ai/admin-sdk 0.34.0 → 0.38.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 +74 -0
- package/README.md +9 -2
- package/dist/index.d.ts +58 -6
- package/dist/index.js +11 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,80 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `@pouchy_ai/admin-sdk` are documented here.
|
|
4
4
|
|
|
5
|
+
## 0.38.0 — 2026-09-25
|
|
6
|
+
|
|
7
|
+
- **`ADMIN_ERROR_CODES` gains `subscription_exists`** (409). `POST
|
|
8
|
+
/v1/projects/{id}/billing/checkout` now refuses when the account already pays
|
|
9
|
+
through a live Stripe subscription. Before, a second checkout opened a SECOND
|
|
10
|
+
subscription: both billed, and each one's lifecycle events rewrote the
|
|
11
|
+
account's plan. Upgrade through `POST /v1/projects/{id}/billing/upgrade`
|
|
12
|
+
instead, which moves the existing subscription to the new price and charges
|
|
13
|
+
the prorated difference. Additive: the `AdminErrorCode` type was
|
|
14
|
+
already open to codes newer than the build.
|
|
15
|
+
|
|
16
|
+
## 0.37.0 — 2026-09-24
|
|
17
|
+
|
|
18
|
+
- **`getUsage()` now types the `credits` block** the server has returned since
|
|
19
|
+
admin API 1.14.0: `{ project, account, limit, scope: 'account', enforcement:
|
|
20
|
+
{ armed, plan, verdict, effect } }` (new exported types `UsageCredits` and
|
|
21
|
+
`UsageCreditEnforcement`). Additive: `usage` is unchanged, and `credits` is
|
|
22
|
+
optional because a server older than 1.14.0 does not send it.
|
|
23
|
+
|
|
24
|
+
`usage.credits / usage.creditLimit` is NOT a headroom ratio — `usage.credits`
|
|
25
|
+
is this project's slice and `creditLimit` is the ACCOUNT's pooled allowance,
|
|
26
|
+
so on a multi-project account it understates consumption. Until now the typed
|
|
27
|
+
client offered only that ratio (reading `res.credits` did not compile), and
|
|
28
|
+
this README's quickstart printed it. Read `credits.account / credits.limit`
|
|
29
|
+
instead; `account` is `null` when the pool could not be read, which means
|
|
30
|
+
unknown, never zero.
|
|
31
|
+
|
|
32
|
+
## 0.36.0 — 2026-09-12
|
|
33
|
+
|
|
34
|
+
- **`deleteChannel` reports what happened to the PROVIDER registration**, and
|
|
35
|
+
takes `{ deprovision: false }` to suppress it. Admin API 1.13.0. Additive:
|
|
36
|
+
the option is optional and the response field is new.
|
|
37
|
+
|
|
38
|
+
Create has registered telegram/discord connectors with their provider since
|
|
39
|
+
1.6.0 (`setWebhook` / the slash command). Delete never unregistered — and the
|
|
40
|
+
asymmetry was worse than an omission, because the delete also destroys the
|
|
41
|
+
stored bot token, so afterwards nothing on the server side could ever do it.
|
|
42
|
+
The bot kept pushing every message it could see to a dead inbound URL, which
|
|
43
|
+
on a fail-closed rate-limited prefix also keeps spending the project's
|
|
44
|
+
limiter quota.
|
|
45
|
+
|
|
46
|
+
Surfaced by an integrator asking whether `DELETE` called `deleteWebhook` —
|
|
47
|
+
the shape of question that is worth answering by reading the code.
|
|
48
|
+
|
|
49
|
+
- `ChannelProvisionCode` gains `webhook_deleted`, `command_deleted` and
|
|
50
|
+
`command_absent`. The union is closed and a published member is never removed,
|
|
51
|
+
so handle an unknown code as informational. `command_absent` is a **skip**,
|
|
52
|
+
not an ok: the Discord command was already gone, and "we removed it" versus
|
|
53
|
+
"there was nothing to remove" are different facts about the provider.
|
|
54
|
+
|
|
55
|
+
## 0.35.0 — 2026-09-10
|
|
56
|
+
|
|
57
|
+
### Added
|
|
58
|
+
|
|
59
|
+
- **Four story-package codes join `ADMIN_ERROR_CODES`**, and two of them were
|
|
60
|
+
already on the wire without being in it. `has_pins` and `pins_unknown` are
|
|
61
|
+
the two 409s of `DELETE …/story-packages/{packageId}` (world API 1.35.0):
|
|
62
|
+
an environment revision has pinned this package, versus the package predates
|
|
63
|
+
the pin stamp so whether one points at it is UNKNOWN and is not guessed. They
|
|
64
|
+
shipped through the same VARIABLE indirection that hid
|
|
65
|
+
`story_contract_v2_write_disabled` — the route forwarded `result.reason` as
|
|
66
|
+
`code`, so the vocabulary census could not see them; the route spells them
|
|
67
|
+
out now.
|
|
68
|
+
|
|
69
|
+
`story_package_limit` and `story_package_documents_limit` are the two ceiling
|
|
70
|
+
refusals, newly carrying a code at all. An integrator reported asserting on
|
|
71
|
+
the refusal SENTENCES because they were the only observation point for the
|
|
72
|
+
quota — which made a copy edit a breaking change for them and a number change
|
|
73
|
+
harmless, the exact inversion of what either should cost. The codes retire
|
|
74
|
+
the prose parsing.
|
|
75
|
+
|
|
76
|
+
Distinguishing the two delete refusals matters because their outs differ:
|
|
77
|
+
`has_pins` sends you to an environment, `pins_unknown` sends you to disable.
|
|
78
|
+
|
|
5
79
|
## 0.34.0 — 2026-09-08
|
|
6
80
|
|
|
7
81
|
### Fixed
|
package/README.md
CHANGED
|
@@ -38,9 +38,15 @@ const { key } = await admin.createKey({ label: 'prod-backend', env: 'live' });
|
|
|
38
38
|
console.log(key); // the plaintext token — shown ONCE
|
|
39
39
|
|
|
40
40
|
// Read this month's usage — MAU, tokens, and the credit meter (all typed)
|
|
41
|
-
const { usage } = await admin.getUsage();
|
|
41
|
+
const { usage, credits } = await admin.getUsage();
|
|
42
42
|
console.log(usage.mau, '/', usage.mauLimit, 'MAU');
|
|
43
|
-
|
|
43
|
+
// Credits pool across the ACCOUNT's projects: `usage.credits` is only this
|
|
44
|
+
// project's slice, so divide the ACCOUNT figure by the limit, never the slice.
|
|
45
|
+
// `account` is null when the pool could not be read — unknown, not zero.
|
|
46
|
+
if (credits) {
|
|
47
|
+
console.log(credits.project, 'credits here;', credits.account ?? '?', '/', credits.limit, 'account-wide');
|
|
48
|
+
console.log('next turn:', credits.enforcement.verdict ?? 'unknown', '—', credits.enforcement.effect);
|
|
49
|
+
}
|
|
44
50
|
// Voice is the priciest metered unit — watch its slice, not just the total
|
|
45
51
|
console.log(usage.creditsVoice, 'of those credits were', usage.voiceCalls, 'voice calls');
|
|
46
52
|
|
|
@@ -417,6 +423,7 @@ type), and is append-only:
|
|
|
417
423
|
| `event_mismatch` | `signalRun` | the run wants a different key; your event is early or wrong |
|
|
418
424
|
| `one_shot_spent` | `updateSchedule` | the one-shot already fired — create a new schedule instead of re-enabling |
|
|
419
425
|
| `ghost_row` | `updateSchedule` | a legacy fieldless row that can never run — delete it, create a new schedule |
|
|
426
|
+
| `subscription_exists` | `POST /v1/projects/{id}/billing/checkout` (console) | the account already pays through a live subscription — upgrade it with `POST …/billing/upgrade` |
|
|
420
427
|
|
|
421
428
|
`code` is `undefined` on every failure the server did not tag (400s, 404s, the
|
|
422
429
|
429, transport errors), so always keep a `default` branch. The type has a
|
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.38.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
|
|
@@ -60,7 +60,7 @@ export interface AdminClientOptions {
|
|
|
60
60
|
* published: on this plane the status line never disambiguates, so two of the
|
|
61
61
|
* durable-run routes answer 409 for two entirely different reasons each, with
|
|
62
62
|
* different recoveries. `code` is the only thing that tells them apart. */
|
|
63
|
-
export declare const ADMIN_ERROR_CODES: readonly ["story_contract_v2_write_disabled", "story_contract_v3_write_disabled", "story_contract_v4_write_disabled", "episode_history_incomplete", "episode_ended", "idempotency_key_reused", "stale_deliberation", "deliberation_disabled", "deliberation_uncalibrated", "deliberation_not_enabled", "deliberation_candidates_exceeded", "schedule_limit_reached", "one_shot_spent", "ghost_row", "channel_limit_reached", "webhook_limit_reached", "run_limit_reached", "reembed_required", "run_terminal", "run_not_parked", "stale_token", "run_not_waiting", "event_mismatch"];
|
|
63
|
+
export declare const ADMIN_ERROR_CODES: readonly ["story_contract_v2_write_disabled", "story_contract_v3_write_disabled", "story_contract_v4_write_disabled", "has_pins", "pins_unknown", "story_package_limit", "story_package_documents_limit", "episode_history_incomplete", "episode_ended", "idempotency_key_reused", "stale_deliberation", "deliberation_disabled", "deliberation_uncalibrated", "deliberation_not_enabled", "deliberation_candidates_exceeded", "schedule_limit_reached", "one_shot_spent", "ghost_row", "channel_limit_reached", "webhook_limit_reached", "run_limit_reached", "reembed_required", "run_terminal", "run_not_parked", "stale_token", "run_not_waiting", "event_mismatch", "subscription_exists"];
|
|
64
64
|
/** `AdminApiError.code` values. The `(string & {})` arm keeps the type open for
|
|
65
65
|
* codes newer than this SDK build while preserving autocomplete — same
|
|
66
66
|
* doctrine as the companion SDK's `CompanionErrorCodeValue`. */
|
|
@@ -312,6 +312,36 @@ export interface MonthUsage {
|
|
|
312
312
|
creditLimit?: number;
|
|
313
313
|
[k: string]: unknown;
|
|
314
314
|
}
|
|
315
|
+
/** What the credit gate would do on the NEXT turn of this account. */
|
|
316
|
+
export interface UsageCreditEnforcement {
|
|
317
|
+
/** Whether this deployment has the credit gate switched on at all. While
|
|
318
|
+
* false nothing is refused or downgraded at the ceiling. */
|
|
319
|
+
armed: boolean;
|
|
320
|
+
plan: string;
|
|
321
|
+
/** Computed on the ACCOUNT total, exactly as the gate does. `null` when the
|
|
322
|
+
* pool could not be read — unknown, not `allow`. */
|
|
323
|
+
verdict: 'allow' | 'downgrade' | 'deny' | null;
|
|
324
|
+
/** One line saying what `verdict` does (a paid-plan `downgrade` keeps turns
|
|
325
|
+
* running on `standard`; a free-plan ceiling refuses NEW sessions). */
|
|
326
|
+
effect: string;
|
|
327
|
+
}
|
|
328
|
+
/** The credit meter with both scopes named (admin API 1.14.0+). Read this, not
|
|
329
|
+
* `usage.credits / usage.creditLimit`: that divides THIS project's figure by
|
|
330
|
+
* the ACCOUNT's allowance and understates consumption on any multi-project
|
|
331
|
+
* account. */
|
|
332
|
+
export interface UsageCredits {
|
|
333
|
+
/** THIS project's consumption — the same number `usage.credits` carries. */
|
|
334
|
+
project: number;
|
|
335
|
+
/** The whole ACCOUNT's consumption: the numerator the gate compares to
|
|
336
|
+
* `limit`. `null` means it could not be read — never treat it as zero. */
|
|
337
|
+
account: number | null;
|
|
338
|
+
/** The ACCOUNT allowance (same value as `usage.creditLimit`). */
|
|
339
|
+
limit: number;
|
|
340
|
+
/** Which pool `limit` governs. Credits pool across the owner's projects, so
|
|
341
|
+
* a second project does NOT isolate a workload — a second account does. */
|
|
342
|
+
scope: 'account';
|
|
343
|
+
enforcement: UsageCreditEnforcement;
|
|
344
|
+
}
|
|
315
345
|
/** One month of the usage-history series. Unlike `MonthUsage` (the current
|
|
316
346
|
* month's full meter incl. day buckets and the cap), history rows are the
|
|
317
347
|
* compact per-month rollup the server keeps for every past month. */
|
|
@@ -401,13 +431,15 @@ export interface ChannelSecretInput {
|
|
|
401
431
|
extra?: Record<string, string>;
|
|
402
432
|
}
|
|
403
433
|
/** Outcome class of the provider registration the server performs on create,
|
|
404
|
-
*
|
|
405
|
-
*
|
|
434
|
+
* on a rotate / secret replacement, and — from admin API 1.13.0 — the
|
|
435
|
+
* UNregistration it performs on delete. Mirrors the server's
|
|
436
|
+
* `ProvisionStatus` (`channels/provision.ts`);
|
|
437
|
+
* `admin-sdk-provision.drift.test.ts` binds them. */
|
|
406
438
|
export type ChannelProvisionStatus = 'ok' | 'skipped' | 'failed';
|
|
407
439
|
/** Machine-readable reason for a `ChannelProvisionResult`. The server treats
|
|
408
440
|
* this vocabulary as part of the response contract (the dashboard keys its
|
|
409
441
|
* copy off it), so branch on `code`, never on `detail`. */
|
|
410
|
-
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';
|
|
442
|
+
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' | 'webhook_deleted' | 'command_deleted' | 'command_absent';
|
|
411
443
|
/** What the provider said when the server registered this connector for you.
|
|
412
444
|
*
|
|
413
445
|
* Registration is an enrichment on top of a durable write: the connector
|
|
@@ -1083,8 +1115,24 @@ export interface AdminClient {
|
|
|
1083
1115
|
* transport, when not suppressed with `autoProvision: false`. */
|
|
1084
1116
|
provision?: ChannelProvisionResult;
|
|
1085
1117
|
}>;
|
|
1086
|
-
|
|
1118
|
+
/** Delete a connector — and, for telegram/discord, UNREGISTER it with the
|
|
1119
|
+
* provider first (admin API 1.13.0).
|
|
1120
|
+
*
|
|
1121
|
+
* The ordering is the point: the delete also destroys the stored bot token,
|
|
1122
|
+
* so an unregistration skipped at that moment can never be done afterwards
|
|
1123
|
+
* from the server side — the bot would keep pushing every message it can see
|
|
1124
|
+
* to a dead inbound URL, and only whoever holds the token could stop it.
|
|
1125
|
+
*
|
|
1126
|
+
* Same contract as create-side registration: the connector is removed
|
|
1127
|
+
* whether or not the provider answers, and a `failed` outcome carries
|
|
1128
|
+
* `manualCommand`. Pass `deprovision: false` to keep the provider
|
|
1129
|
+
* registration (for a caller who manages the bot webhook themselves). */
|
|
1130
|
+
deleteChannel(channelId: string, options?: {
|
|
1131
|
+
deprovision?: false;
|
|
1132
|
+
}): Promise<{
|
|
1087
1133
|
ok: boolean;
|
|
1134
|
+
/** Absent for a transport with no provider registration. */
|
|
1135
|
+
deprovision?: ChannelProvisionResult;
|
|
1088
1136
|
}>;
|
|
1089
1137
|
listSchedules(): Promise<{
|
|
1090
1138
|
schedules: unknown[];
|
|
@@ -1344,8 +1392,12 @@ export interface AdminClient {
|
|
|
1344
1392
|
testWebhook(webhookId: string): Promise<DeliveryOutcome>;
|
|
1345
1393
|
/** Manually re-send a recorded delivery's original body, re-signed. */
|
|
1346
1394
|
redeliverWebhook(deliveryId: string): Promise<DeliveryOutcome>;
|
|
1395
|
+
/** Current-month usage. `credits` (admin API 1.14.0+; absent from an older
|
|
1396
|
+
* server) is the block to read for headroom — `account / limit` is the
|
|
1397
|
+
* ratio the gate enforces. */
|
|
1347
1398
|
getUsage(): Promise<{
|
|
1348
1399
|
usage: MonthUsage;
|
|
1400
|
+
credits?: UsageCredits;
|
|
1349
1401
|
}>;
|
|
1350
1402
|
/** Month-over-month usage series, oldest first; quiet months zero-fill
|
|
1351
1403
|
* rather than drop. `scope: 'account'` means the pooled account series —
|
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.38.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;
|
|
@@ -73,6 +73,10 @@ export const ADMIN_ERROR_CODES = [
|
|
|
73
73
|
'story_contract_v2_write_disabled',
|
|
74
74
|
'story_contract_v3_write_disabled',
|
|
75
75
|
'story_contract_v4_write_disabled',
|
|
76
|
+
'has_pins',
|
|
77
|
+
'pins_unknown',
|
|
78
|
+
'story_package_limit',
|
|
79
|
+
'story_package_documents_limit',
|
|
76
80
|
'episode_history_incomplete',
|
|
77
81
|
'episode_ended',
|
|
78
82
|
'idempotency_key_reused',
|
|
@@ -92,7 +96,11 @@ export const ADMIN_ERROR_CODES = [
|
|
|
92
96
|
'run_not_parked',
|
|
93
97
|
'stale_token',
|
|
94
98
|
'run_not_waiting',
|
|
95
|
-
'event_mismatch'
|
|
99
|
+
'event_mismatch',
|
|
100
|
+
// 0.38.0 — checkout on an account that already pays through a live
|
|
101
|
+
// subscription. Recovery: POST /v1/projects/{id}/billing/upgrade, which moves
|
|
102
|
+
// that subscription to the new price instead of opening a second one.
|
|
103
|
+
'subscription_exists'
|
|
96
104
|
];
|
|
97
105
|
/** Thrown on any non-2xx response AND on a transport failure that never reached
|
|
98
106
|
* the server (network / DNS / timeout), which carries `status: 0`. `status` is
|
|
@@ -330,7 +338,7 @@ export function createAdminClient(opts) {
|
|
|
330
338
|
createChannel: (input) => request('POST', '/channels', input),
|
|
331
339
|
getChannel: (id) => request('GET', `/channels/${encodeURIComponent(id)}`),
|
|
332
340
|
updateChannel: (id, patch) => request('PATCH', `/channels/${encodeURIComponent(id)}`, patch),
|
|
333
|
-
deleteChannel: (id) => request('DELETE', `/channels/${encodeURIComponent(id)}`),
|
|
341
|
+
deleteChannel: (id, options) => request('DELETE', `/channels/${encodeURIComponent(id)}${options?.deprovision === false ? '?deprovision=false' : ''}`),
|
|
334
342
|
listSchedules: () => request('GET', '/schedules'),
|
|
335
343
|
createSchedule: (input) => request('POST', '/schedules', input),
|
|
336
344
|
getSchedule: (id) => request('GET', `/schedules/${encodeURIComponent(id)}`),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pouchy_ai/admin-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.38.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",
|