@pouchy_ai/admin-sdk 0.9.0 → 0.11.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,47 @@
2
2
 
3
3
  All notable changes to `@pouchy_ai/admin-sdk` are documented here.
4
4
 
5
+ ## 0.11.0 — 2026-08-01
6
+
7
+ - **Data capabilities, headless.** Six new methods over the `/v1/admin/capabilities`
8
+ mirror: `listCapabilities` (heads + masked signing status — the `pcsk_`
9
+ plaintext is issued once on the owner plane and is never readable through any
10
+ API), `publishCapability` (immutable next version; idempotent on content),
11
+ `setCapabilityDisabled` (per-capability live revoke — live both directions,
12
+ pinned reconciliations unaffected), `listCapabilityVersions` (append-only
13
+ history; rollback = republishing an old declaration as the next version),
14
+ `testReadCapability`, and `testActionCapability` (the four-phase Action
15
+ protocol verifier; the server refuses without `confirmDuplicates: true`
16
+ because phases B/C intentionally re-deliver the same `actionId`).
17
+ - `POST /capabilities/{name}/test-action` joins `LONG_WORK_REQUESTS`: the
18
+ verifier makes real round-trips to YOUR endpoint, and aborting mid-test
19
+ cannot undo phase A's side effect — so the default deadline is the long one.
20
+
21
+ ## 0.10.0 — 2026-07-29
22
+
23
+ - **`AdminApiError.code` — the Admin API's machine-readable failure tag.** The
24
+ server has been sending `code` on ten failures across nineteen emit sites;
25
+ this package read `error` off the body and dropped `code` on the floor, so the
26
+ field was unreachable from the first-party client.
27
+ - **Why it matters more than it sounds: every one of those ten codes is a 409.**
28
+ On this plane the status line never disambiguates, and two of the durable-run
29
+ routes answer 409 for two different reasons each, with opposite recoveries —
30
+ `resumeRun` (`stale_token`: re-read and answer again / `run_not_parked`: stop,
31
+ someone already decided) and `signalRun` (`event_mismatch`: your event is early
32
+ or wrong, retry later / `run_not_waiting`: the wait ended, stop). This
33
+ package's own doc comments told callers to make exactly those distinctions,
34
+ which was not possible without string-matching English prose.
35
+ - **`ADMIN_ERROR_CODES` + `AdminErrorCode` are exported** so a `switch` is typed.
36
+ The type carries a `(string & {})` arm (same doctrine as the companion SDK's
37
+ `CompanionErrorCodeValue`), so a code newer than your installed build still
38
+ arrives as a readable string instead of being filtered out. The list is
39
+ drift-gated against the server's own vocabulary in both directions.
40
+ - Additive only — no method signature, request shape, status code or error
41
+ message changed. `code` is `undefined` on every failure the server did not tag
42
+ (400s, 404s, the 429, transport errors), and a non-string or empty `code` on
43
+ the wire leaves it `undefined` rather than stamping a falsy value a `switch`
44
+ would fall through on.
45
+
5
46
  ## 0.9.0 — 2026-07-28
6
47
 
7
48
  - **Channel CRUD is typed (CR-77).** `createChannel` takes
package/README.md CHANGED
@@ -100,6 +100,62 @@ try {
100
100
  }
101
101
  ```
102
102
 
103
+ ### Failure codes (409)
104
+
105
+ **Every machine-readable failure on this API is a 409**, so `status` separates
106
+ none of them. `AdminApiError.code` is the discriminator — switch on it rather
107
+ than string-matching `message`, which is prose and may be reworded:
108
+
109
+ ```ts
110
+ import { AdminApiError } from '@pouchy_ai/admin-sdk';
111
+
112
+ // `runId` and `token` come from the run you are answering — the
113
+ // `agent.run_awaiting` webhook carries both, or read them off `getRun`.
114
+ declare const runId: string;
115
+ declare const token: string;
116
+
117
+ try {
118
+ await admin.resumeRun(runId, { approved: true, token });
119
+ } catch (e) {
120
+ if (!(e instanceof AdminApiError)) throw e;
121
+ switch (e.code) {
122
+ case 'stale_token': {
123
+ // The run moved on to a different question. Re-read and answer the
124
+ // current one — this is the retryable branch.
125
+ const { run } = await admin.getRun(runId);
126
+ if (run.awaiting) await admin.resumeRun(runId, { approved: true, token: run.awaiting.token });
127
+ break;
128
+ }
129
+ case 'run_not_parked':
130
+ // Someone else decided, or the run was cancelled. Do NOT retry.
131
+ break;
132
+ default:
133
+ throw e;
134
+ }
135
+ }
136
+ ```
137
+
138
+ The vocabulary is exported as `ADMIN_ERROR_CODES` (and the `AdminErrorCode`
139
+ type), and is append-only:
140
+
141
+ | code | route | what to do |
142
+ |---|---|---|
143
+ | `schedule_limit_reached` | `createSchedule` | delete or disable a schedule, retry |
144
+ | `channel_limit_reached` | `createChannel` | delete an unused connector, retry |
145
+ | `webhook_limit_reached` | `createWebhook` | delete an unused endpoint, retry |
146
+ | `run_limit_reached` | `createRun` | wait for a run to finish, or `cancelRun` one |
147
+ | `reembed_required` | knowledge config | clear + re-ingest to switch embedding model |
148
+ | `run_terminal` | `cancelRun` | the run already finished — nothing to cancel |
149
+ | `run_not_parked` | `resumeRun` | already decided; stop retrying |
150
+ | `stale_token` | `resumeRun` | `getRun`, then answer the current `awaiting.token` |
151
+ | `run_not_waiting` | `signalRun` | the wait ended; stop retrying |
152
+ | `event_mismatch` | `signalRun` | the run wants a different key; your event is early or wrong |
153
+
154
+ `code` is `undefined` on every failure the server did not tag (400s, 404s, the
155
+ 429, transport errors), so always keep a `default` branch. The type has a
156
+ `(string & {})` arm on purpose: a code newer than your installed build still
157
+ arrives as a readable string. Available from **0.10.0**.
158
+
103
159
  ### Throttling (429)
104
160
 
105
161
  Writes are rate-limited per IP — 120 non-`GET` requests per minute across the
@@ -147,6 +203,7 @@ Channel types are checked at compile time: `createChannel` takes a
147
203
  `CreatableChannelType` (the platform's 31-transport union minus the adapterless
148
204
  `internal-a2a`), and `secret` is a named `ChannelSecretInput`. Per-transport
149
205
  `secret.extra` fields are listed in <https://pouchy.ai/docs/channel-setup>.
206
+ | Data capabilities | `listCapabilities` (heads + MASKED signing status) · `publishCapability` (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) |
150
207
  | Webhooks | `listWebhooks` · `createWebhook` · `updateWebhook` · `rotateWebhookSecret` · `deleteWebhook` · `testWebhook` · `redeliverWebhook` |
151
208
  | Reporting | `getUsage` · `getBilling` · `getTracesSummary` · `getRecentTraces` · `getLogs` · `getProject` · `updateProject` |
152
209
  | Escape hatch | `request(method, path, body?)` — any endpoint not yet typed |
@@ -175,6 +232,11 @@ const { run } = await admin.createRun({
175
232
  console.log(run.id, run.status); // → 'queued'
176
233
  ```
177
234
 
235
+ A `subtask_fanout` step runs at most **4** subtasks (`input.subtasks`).
236
+ Declaring more is a **400** naming the cap rather than a silent trim — split
237
+ the remainder into a second fan-out step. Entries without a non-empty `goal`
238
+ are ignored and do not count against the cap.
239
+
178
240
  When a run reaches a `human_approval` step it **parks**: it holds no lease and
179
241
  leaves the platform's due window, so nothing will move it until you answer.
180
242
  You learn about it either way — the `agent.run_awaiting` webhook pushes the
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export declare const ADMIN_SDK_VERSION = "0.9.0";
1
+ export declare const ADMIN_SDK_VERSION = "0.11.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
@@ -50,9 +50,33 @@ export interface AdminClientOptions {
50
50
  * failed with the self-contradicting `request timed out after 0ms`. */
51
51
  timeoutMs?: number;
52
52
  }
53
+ /** Machine-readable failure tags the Admin API puts on an error body, mirroring
54
+ * the server's own list (`src/lib/server/platform/api-error-codes.ts`) and
55
+ * drift-tested against it. APPEND-ONLY: these are documented as switchable, so
56
+ * renaming or removing one breaks integrators.
57
+ *
58
+ * Every member is a **409**. That is the whole reason this vocabulary is
59
+ * published: on this plane the status line never disambiguates, so two of the
60
+ * durable-run routes answer 409 for two entirely different reasons each, with
61
+ * different recoveries. `code` is the only thing that tells them apart. */
62
+ export declare const ADMIN_ERROR_CODES: readonly ["schedule_limit_reached", "channel_limit_reached", "webhook_limit_reached", "run_limit_reached", "reembed_required", "run_terminal", "run_not_parked", "stale_token", "run_not_waiting", "event_mismatch"];
63
+ /** `AdminApiError.code` values. The `(string & {})` arm keeps the type open for
64
+ * codes newer than this SDK build while preserving autocomplete — same
65
+ * doctrine as the companion SDK's `CompanionErrorCodeValue`. */
66
+ export type AdminErrorCode = (typeof ADMIN_ERROR_CODES)[number] | (string & {});
53
67
  /** Thrown on any non-2xx response. `status` is the HTTP status; `message` is the
54
68
  * server's `error` string when present; `retryAfter` is the throttle's own
55
- * backoff in SECONDS on a 429 (undefined on every other failure).
69
+ * backoff in SECONDS on a 429 (undefined on every other failure); `code` is the
70
+ * server's machine tag when it named one (undefined otherwise).
71
+ *
72
+ * Why `code` exists: the Admin API's ten machine-readable failures are ALL on
73
+ * 409, so `status` cannot separate them and this package used to discard the
74
+ * one field that can. Two routes are the point — `resumeRun` answers 409 for
75
+ * `run_not_parked` (someone already decided; re-read, do not retry) or
76
+ * `stale_token` (your token aged out; re-read for the current one and answer
77
+ * again), and `signalRun` answers 409 for `run_not_waiting` or
78
+ * `event_mismatch`. This package's own docs told callers to distinguish those,
79
+ * which was not possible without switching on prose.
56
80
  *
57
81
  * Why `retryAfter` exists: the entire write surface of this SDK sits behind one
58
82
  * per-IP throttle — `hooks.server.ts` runs a `v1-admin-write` bucket (120
@@ -69,7 +93,8 @@ export interface AdminClientOptions {
69
93
  export declare class AdminApiError extends Error {
70
94
  status: number;
71
95
  readonly retryAfter?: number;
72
- constructor(message: string, status: number, retryAfter?: number);
96
+ readonly code?: AdminErrorCode;
97
+ constructor(message: string, status: number, retryAfter?: number, code?: string);
73
98
  }
74
99
  export type Env = 'live' | 'test';
75
100
  export type AgentStatus = 'draft' | 'published';
@@ -598,7 +623,12 @@ export interface AdminClient {
598
623
  * turn carrying `goal`. Step ids must be unique and match
599
624
  * `[A-Za-z0-9_-]{1,64}`; `kind` is one of `agent_turn`, `subtask_fanout`,
600
625
  * `human_approval`, `await_event`. Answers **202**, not 201: the run is
601
- * accepted and has not run yet. */
626
+ * accepted and has not run yet.
627
+ *
628
+ * A `subtask_fanout` step runs at most **4** subtasks (`input.subtasks`).
629
+ * Declaring more is a **400** naming the cap, not a silent trim — split the
630
+ * remainder into a second fan-out step. Entries without a non-empty `goal`
631
+ * are ignored and do not count against the cap. */
602
632
  createRun(input: {
603
633
  agentId: string;
604
634
  externalUserId: string;
@@ -628,7 +658,13 @@ export interface AdminClient {
628
658
  * `awaiting.token` (also carried by the `agent.run_awaiting` webhook) and
629
659
  * fences the decision against a stale or replayed answer. Without this call
630
660
  * a parked run never resumes: it holds no lease and has left the platform's
631
- * due window by design. */
661
+ * due window by design.
662
+ *
663
+ * Both failures here are **409**; switch on `AdminApiError.code` to tell
664
+ * them apart. `stale_token` — the run has moved on to a different question:
665
+ * re-read it with `getRun` and answer the current `awaiting.token`.
666
+ * `run_not_parked` — it is no longer awaiting anyone (someone else decided,
667
+ * or it was cancelled): do NOT retry. */
632
668
  resumeRun(runId: string, input: {
633
669
  approved: boolean;
634
670
  token: string;
@@ -640,7 +676,13 @@ export interface AdminClient {
640
676
  }>;
641
677
  /** Deliver an external event to a run parked on one. `event` must equal the
642
678
  * key the run is waiting for — a mismatch answers 409 `event_mismatch`, so a
643
- * webhook retry can tell "too late" from "rejected". */
679
+ * webhook retry can tell "too late" from "rejected".
680
+ *
681
+ * Read that verdict off `AdminApiError.code` (0.10.0; before that the field
682
+ * was dropped and this advice was unfollowable). `event_mismatch` — the run
683
+ * wants a DIFFERENT key, so your event is early or wrong: safe to retry
684
+ * later. `run_not_waiting` — the run is not parked on an event at all, so
685
+ * the wait already ended: stop retrying. */
644
686
  signalRun(runId: string, input: {
645
687
  event: string;
646
688
  payload?: unknown;
@@ -649,6 +691,72 @@ export interface AdminClient {
649
691
  event: string;
650
692
  status: string;
651
693
  }>;
694
+ /** Capability heads + MASKED signing status (key IDs and rotation state
695
+ * only — the `pcsk_` plaintext is issued ONCE on the owner plane and is
696
+ * never readable through any API). */
697
+ listCapabilities(): Promise<{
698
+ capabilities: Array<{
699
+ capabilityId: string;
700
+ name: string;
701
+ kind: string;
702
+ latestVersion: number;
703
+ disabled?: boolean;
704
+ }>;
705
+ signing: {
706
+ activeKeyId: string;
707
+ previousKeyId: string | null;
708
+ } | null;
709
+ }>;
710
+ /** Publish the next IMMUTABLE revision. Idempotent on content: an unchanged
711
+ * manifest returns the existing version with `created: false`; different
712
+ * bytes mint version+1 and never rewrite an old one. Publishing is NOT
713
+ * revocation — the per-agent data flags and `setCapabilityDisabled` are
714
+ * the live levers. */
715
+ publishCapability(declaration: Record<string, unknown>): Promise<{
716
+ revision: {
717
+ capabilityId: string;
718
+ version: number;
719
+ revisionHash: string;
720
+ };
721
+ created: boolean;
722
+ }>;
723
+ /** Per-capability live revoke: flips the head's `disabled` bit. Live in
724
+ * BOTH directions on the next resolution — existing sessions lose it from
725
+ * their next turn, new plans/ingress see honest absence; a reconciliation
726
+ * pinned to a revision keeps reconciling. */
727
+ setCapabilityDisabled(name: string, disabled: boolean): Promise<{
728
+ name: string;
729
+ disabled: boolean;
730
+ }>;
731
+ /** Full version history, newest first, WITH declaration bodies. There is no
732
+ * rollback verb: restoring vN = `publishCapability(versions[i].declaration)`,
733
+ * which mints it as the NEXT version (history stays append-only). */
734
+ listCapabilityVersions(name: string): Promise<{
735
+ versions: Array<{
736
+ version: number;
737
+ revisionHash: string;
738
+ publishedAt: string;
739
+ declaration: Record<string, unknown>;
740
+ }>;
741
+ }>;
742
+ /** View integration test: real pinned revision + production signer; returns
743
+ * the curated rows exactly as an agent would see them, the menu/model
744
+ * bytes, and DECODED (never signed, never replayable) claims. */
745
+ testReadCapability(name: string, input?: {
746
+ externalUserId?: string;
747
+ filters?: Record<string, unknown>;
748
+ }): Promise<Record<string, unknown>>;
749
+ /** Action protocol verifier — four phases (connectivity, duplicate
750
+ * same-intent, mismatch, reconcile) against your REAL endpoint, including
751
+ * intentional duplicate deliveries of one actionId; the server refuses
752
+ * (428) without `confirmDuplicates: true`. Phase outcomes use production
753
+ * vocabulary (committed/rejected/unknown) SEPARATELY from protocol
754
+ * verdicts — "Protocol: PASS, outcome: unknown" is a valid result. */
755
+ testActionCapability(name: string, input: {
756
+ confirmDuplicates: true;
757
+ args?: Record<string, unknown>;
758
+ externalUserId?: string;
759
+ }): Promise<Record<string, unknown>>;
652
760
  listWebhooks(): Promise<{
653
761
  webhooks: unknown[];
654
762
  }>;
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.9.0';
11
+ export const ADMIN_SDK_VERSION = '0.11.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;
@@ -44,7 +44,12 @@ export const LONG_WORK_REQUESTS = [
44
44
  // GDPR erasure: recursive delete of the instance's whole users/** subtree
45
45
  // plus the top-level social graph. A client abort here is the worst of the
46
46
  // four — the operator is left not knowing whether the wipe completed.
47
- { method: 'DELETE', path: /^\/users\/[^/]+$/ }
47
+ { method: 'DELETE', path: /^\/users\/[^/]+$/ },
48
+ // The Action protocol verifier makes REAL deliveries to the developer's
49
+ // endpoint (four phases incl. reconcile) — network round-trips we don't
50
+ // control the latency of. An abort mid-test also cannot undo phase A's
51
+ // side effect, so waiting is strictly better than cutting.
52
+ { method: 'POST', path: /^\/capabilities\/[^/]+\/test-action$/ }
48
53
  ];
49
54
  /** The deadline a given request runs under when the host set no `timeoutMs`.
50
55
  * Exported so the contract is assertable without timing anything. */
@@ -55,9 +60,40 @@ export function requestDeadlineMs(method, path) {
55
60
  ? LONG_WORK_TIMEOUT_MS
56
61
  : DEFAULT_TIMEOUT_MS;
57
62
  }
63
+ /** Machine-readable failure tags the Admin API puts on an error body, mirroring
64
+ * the server's own list (`src/lib/server/platform/api-error-codes.ts`) and
65
+ * drift-tested against it. APPEND-ONLY: these are documented as switchable, so
66
+ * renaming or removing one breaks integrators.
67
+ *
68
+ * Every member is a **409**. That is the whole reason this vocabulary is
69
+ * published: on this plane the status line never disambiguates, so two of the
70
+ * durable-run routes answer 409 for two entirely different reasons each, with
71
+ * different recoveries. `code` is the only thing that tells them apart. */
72
+ export const ADMIN_ERROR_CODES = [
73
+ 'schedule_limit_reached',
74
+ 'channel_limit_reached',
75
+ 'webhook_limit_reached',
76
+ 'run_limit_reached',
77
+ 'reembed_required',
78
+ 'run_terminal',
79
+ 'run_not_parked',
80
+ 'stale_token',
81
+ 'run_not_waiting',
82
+ 'event_mismatch'
83
+ ];
58
84
  /** Thrown on any non-2xx response. `status` is the HTTP status; `message` is the
59
85
  * server's `error` string when present; `retryAfter` is the throttle's own
60
- * backoff in SECONDS on a 429 (undefined on every other failure).
86
+ * backoff in SECONDS on a 429 (undefined on every other failure); `code` is the
87
+ * server's machine tag when it named one (undefined otherwise).
88
+ *
89
+ * Why `code` exists: the Admin API's ten machine-readable failures are ALL on
90
+ * 409, so `status` cannot separate them and this package used to discard the
91
+ * one field that can. Two routes are the point — `resumeRun` answers 409 for
92
+ * `run_not_parked` (someone already decided; re-read, do not retry) or
93
+ * `stale_token` (your token aged out; re-read for the current one and answer
94
+ * again), and `signalRun` answers 409 for `run_not_waiting` or
95
+ * `event_mismatch`. This package's own docs told callers to distinguish those,
96
+ * which was not possible without switching on prose.
61
97
  *
62
98
  * Why `retryAfter` exists: the entire write surface of this SDK sits behind one
63
99
  * per-IP throttle — `hooks.server.ts` runs a `v1-admin-write` bucket (120
@@ -74,14 +110,27 @@ export function requestDeadlineMs(method, path) {
74
110
  export class AdminApiError extends Error {
75
111
  status;
76
112
  retryAfter;
77
- constructor(message, status, retryAfter) {
113
+ code;
114
+ constructor(message, status, retryAfter, code) {
78
115
  super(message);
79
116
  this.name = 'AdminApiError';
80
117
  this.status = status;
81
118
  if (retryAfter !== undefined)
82
119
  this.retryAfter = retryAfter;
120
+ // Only a non-empty string. A body carrying `code: null` or `code: 42`
121
+ // must leave the property ABSENT rather than stamping a falsy value that
122
+ // a `switch (e.code)` would fall through on in a way the caller can't see.
123
+ if (typeof code === 'string' && code)
124
+ this.code = code;
83
125
  }
84
126
  }
127
+ /** The `code` a non-2xx body named, or undefined. Kept beside `retryAfterFrom`
128
+ * and equally defensive: the body is parsed with a `.catch(() => ({}))`, so
129
+ * every field here is untrusted shape, not a typed response. */
130
+ function codeFrom(body) {
131
+ const v = body?.code;
132
+ return typeof v === 'string' && v ? v : undefined;
133
+ }
85
134
  /** Seconds to wait before retrying a throttled response, or undefined when the
86
135
  * server named neither a body field nor a header.
87
136
  *
@@ -165,7 +214,7 @@ export function createAdminClient(opts) {
165
214
  }
166
215
  const data = (await res.json().catch(() => ({})));
167
216
  if (!res.ok)
168
- throw new AdminApiError(data?.error ?? `HTTP ${res.status}`, res.status, retryAfterFrom(res, data));
217
+ throw new AdminApiError(data?.error ?? `HTTP ${res.status}`, res.status, retryAfterFrom(res, data), codeFrom(data));
169
218
  return data;
170
219
  }
171
220
  return {
@@ -237,6 +286,12 @@ export function createAdminClient(opts) {
237
286
  cancelRun: (id) => request('DELETE', `/runs/${encodeURIComponent(id)}`),
238
287
  resumeRun: (id, input) => request('POST', `/runs/${encodeURIComponent(id)}/resume`, input),
239
288
  signalRun: (id, input) => request('POST', `/runs/${encodeURIComponent(id)}/signal`, input),
289
+ listCapabilities: () => request('GET', '/capabilities'),
290
+ publishCapability: (declaration) => request('POST', '/capabilities', declaration),
291
+ setCapabilityDisabled: (name, disabled) => request('PATCH', `/capabilities/${encodeURIComponent(name)}`, { disabled }),
292
+ listCapabilityVersions: (name) => request('GET', `/capabilities/${encodeURIComponent(name)}/versions`),
293
+ testReadCapability: (name, input = {}) => request('POST', `/capabilities/${encodeURIComponent(name)}/test-read`, input),
294
+ testActionCapability: (name, input) => request('POST', `/capabilities/${encodeURIComponent(name)}/test-action`, input),
240
295
  listWebhooks: () => request('GET', '/webhooks'),
241
296
  createWebhook: (input) => request('POST', '/webhooks', input),
242
297
  deleteWebhook: (id) => request('DELETE', `/webhooks/${encodeURIComponent(id)}`),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pouchy_ai/admin-sdk",
3
- "version": "0.9.0",
3
+ "version": "0.11.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",