@openkeyai/sdk 0.1.0 → 0.2.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/dist/index.d.cts CHANGED
@@ -9,6 +9,19 @@
9
9
  */
10
10
  /** Scopes a tool may request and a JWT may carry. */
11
11
  type ToolJwtScope = "keys.read" | "user.read" | "billing.read";
12
+ /**
13
+ * Issuance mode (Phase 13.4 / Phase 19).
14
+ *
15
+ * production — normal user launches an approved tool through the catalog
16
+ * owner_test — the tool's owner launching their own pre-approval scaffold
17
+ * to dogfood the build. Subscription gate waived; only the
18
+ * owner can mint these
19
+ *
20
+ * Tools that want to render a TEST MODE banner read this claim and check
21
+ * for `'owner_test'`. Backwards-compatible: tokens minted before Phase 13.4
22
+ * default to `'production'` on verify.
23
+ */
24
+ type ToolJwtMode = "production" | "owner_test";
12
25
  /** Decoded + verified claim payload. */
13
26
  type ToolJwtClaims = {
14
27
  /** Always exactly "https://openkeyai.com". */
@@ -21,6 +34,8 @@ type ToolJwtClaims = {
21
34
  scopes: ToolJwtScope[];
22
35
  /** Whether the user has an active subscription at issuance time. */
23
36
  subscription_active: boolean;
37
+ /** Mode the JWT was issued under (Phase 13.4). Defaults to 'production'. */
38
+ mode: ToolJwtMode;
24
39
  /** Unix seconds. */
25
40
  iat: number;
26
41
  /** Unix seconds. Tokens default to iat + 900 (15 min). */
@@ -49,6 +64,33 @@ type HubCallOptions = {
49
64
  */
50
65
  signal?: AbortSignal;
51
66
  };
67
+ /**
68
+ * Generic proxy call options. The proxy is the Phase 19 endpoint that
69
+ * forwards arbitrary requests to upstream providers with the user's key
70
+ * injected by the hub — the tool never sees the plaintext key.
71
+ */
72
+ type ProxyCallOptions = HubCallOptions & {
73
+ /** Provider slug — matches the hub's provider registry. */
74
+ provider: ProviderSlug;
75
+ /** HTTP method to use against the upstream. */
76
+ method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
77
+ /**
78
+ * Path portion of the upstream URL. Must start with `/`. The hub appends
79
+ * this to the provider's baseUrl. Example: `/v1/chat/completions`.
80
+ */
81
+ path: string;
82
+ /**
83
+ * Request body. If an object, sent as JSON. If a string / Blob /
84
+ * FormData / ReadableStream / ArrayBuffer, sent as-is. Omit for
85
+ * GET / DELETE.
86
+ */
87
+ body?: Record<string, unknown> | unknown[] | string | Blob | FormData | ArrayBuffer | ReadableStream<Uint8Array> | null;
88
+ /**
89
+ * Extra headers to forward upstream. The hub will strip a few it
90
+ * controls (authorization, host, cookie); the rest pass through.
91
+ */
92
+ headers?: Record<string, string>;
93
+ };
52
94
 
53
95
  /**
54
96
  * `session.verify(jwt, opts?)`
@@ -163,6 +205,422 @@ declare class SecureKey {
163
205
  */
164
206
  declare function get(jwt: string, provider: ProviderSlug, opts?: HubCallOptions): Promise<SecureKey>;
165
207
 
208
+ /**
209
+ * Generic proxy call — JSON in, JSON out. Most tools want this.
210
+ *
211
+ * const completion = await proxy.call<ChatCompletionResponse>(token, {
212
+ * provider: "openai",
213
+ * method: "POST",
214
+ * path: "/v1/chat/completions",
215
+ * body: { model: "gpt-4o-mini", messages: [{ role: "user", content: "hi" }] },
216
+ * });
217
+ *
218
+ * Throws typed HubSdkError subclasses for hub-side failures (missing
219
+ * scope, rate limited, etc.) and `ProviderError` for upstream non-2xx
220
+ * (wrong key, model gone, provider 5xx, etc.).
221
+ */
222
+ declare function call<T = unknown>(token: string, opts: ProxyCallOptions): Promise<T>;
223
+ /**
224
+ * Raw-response proxy call. Used when the upstream returns non-JSON —
225
+ * binary audio (TTS), image bytes (DALL-E with response_format=url is
226
+ * JSON, but other endpoints may stream binary), multipart, etc.
227
+ *
228
+ * const response = await proxy.callRaw(token, {
229
+ * provider: "openai",
230
+ * method: "POST",
231
+ * path: "/v1/audio/speech",
232
+ * body: { model: "tts-1", input: "Hello", voice: "alloy" },
233
+ * });
234
+ * const audio = await response.arrayBuffer();
235
+ *
236
+ * Returns the upstream Response with status / headers intact — the tool
237
+ * decides how to consume the body. Throws on hub-side errors before the
238
+ * Response is returned.
239
+ */
240
+ declare function callRaw(token: string, opts: ProxyCallOptions): Promise<Response>;
241
+ /**
242
+ * Streaming proxy call — returns a ReadableStream of the upstream
243
+ * response body. Used for SSE (chat completion streaming), chunked
244
+ * downloads, large response bodies you want to process as they arrive.
245
+ *
246
+ * const stream = await proxy.callStream(token, {
247
+ * provider: "openai",
248
+ * method: "POST",
249
+ * path: "/v1/chat/completions",
250
+ * body: { model: "gpt-4o", messages: [...], stream: true },
251
+ * });
252
+ * const reader = stream.getReader();
253
+ * while (true) {
254
+ * const { value, done } = await reader.read();
255
+ * if (done) break;
256
+ * // parse SSE chunks here — typed SSE iterator comes in M1.5
257
+ * }
258
+ *
259
+ * Hub-side errors (auth, rate-limit) still throw before the stream is
260
+ * returned. Upstream errors are surfaced via the stream itself — the
261
+ * caller should check `response.status` before reading if a provider 4xx
262
+ * matters; in M1.5 we'll wrap this in `ProviderError` if the upstream
263
+ * status is non-2xx before any chunks are read.
264
+ */
265
+ declare function callStream(token: string, opts: ProxyCallOptions): Promise<ReadableStream<Uint8Array>>;
266
+
267
+ /**
268
+ * Typed convenience wrappers for OpenAI's most-used endpoints. Thin
269
+ * wrappers around `proxy.call(token, opts)` — same gates, same errors,
270
+ * just better DX for the common cases.
271
+ *
272
+ * Tools that need an endpoint not covered here can drop to the generic
273
+ * `proxy.call(token, { provider: "openai", method, path, body })`. The
274
+ * proxy supports every OpenAI endpoint without us shipping wrappers for
275
+ * each one.
276
+ *
277
+ * Types here are pragmatic, not exhaustive — we hit the fields the YT
278
+ * thumbnail tool and other early reference tools need. As more tools land
279
+ * we'll grow these. The escape hatch (`proxy.call`) means tools never wait
280
+ * on the SDK to update types when a new model ships.
281
+ */
282
+ type OpenaiImageModel = "gpt-image-1" | "dall-e-3" | "dall-e-2" | (string & {});
283
+ type OpenaiImageSize = "1024x1024" | "1024x1536" | "1536x1024" | "1792x1024" | "1024x1792" | "256x256" | "512x512" | "auto" | (string & {});
284
+ type OpenaiImageQuality = "high" | "medium" | "low" | "auto" | "hd" | "standard" | (string & {});
285
+ type OpenaiImageStyle = "vivid" | "natural" | (string & {});
286
+ type OpenaiImageGenerateParams = {
287
+ model?: OpenaiImageModel;
288
+ prompt: string;
289
+ n?: number;
290
+ size?: OpenaiImageSize;
291
+ quality?: OpenaiImageQuality;
292
+ style?: OpenaiImageStyle;
293
+ /**
294
+ * `b64_json` returns base64-encoded image bytes inline in the response.
295
+ * `url` returns a hosted URL the client can fetch. gpt-image-1 always
296
+ * returns b64.
297
+ */
298
+ response_format?: "url" | "b64_json";
299
+ user?: string;
300
+ background?: "transparent" | "opaque" | "auto" | (string & {});
301
+ moderation?: "low" | "auto" | (string & {});
302
+ output_compression?: number;
303
+ output_format?: "png" | "jpeg" | "webp" | (string & {});
304
+ };
305
+ type OpenaiImageData = {
306
+ url?: string;
307
+ b64_json?: string;
308
+ revised_prompt?: string;
309
+ };
310
+ type OpenaiImageGenerateResponse = {
311
+ created: number;
312
+ data: OpenaiImageData[];
313
+ usage?: {
314
+ total_tokens?: number;
315
+ input_tokens?: number;
316
+ output_tokens?: number;
317
+ input_tokens_details?: {
318
+ text_tokens?: number;
319
+ image_tokens?: number;
320
+ };
321
+ };
322
+ };
323
+ type OpenaiChatRole = "system" | "user" | "assistant" | "tool";
324
+ type OpenaiChatMessageContentPart = {
325
+ type: "text";
326
+ text: string;
327
+ } | {
328
+ type: "image_url";
329
+ image_url: {
330
+ url: string;
331
+ detail?: "low" | "high" | "auto";
332
+ };
333
+ };
334
+ type OpenaiChatMessage = {
335
+ role: OpenaiChatRole;
336
+ content: string | OpenaiChatMessageContentPart[];
337
+ name?: string;
338
+ tool_call_id?: string;
339
+ };
340
+ type OpenaiChatCompletionParams = {
341
+ model: string;
342
+ messages: OpenaiChatMessage[];
343
+ temperature?: number;
344
+ top_p?: number;
345
+ n?: number;
346
+ max_tokens?: number;
347
+ max_completion_tokens?: number;
348
+ stream?: boolean;
349
+ stop?: string | string[];
350
+ presence_penalty?: number;
351
+ frequency_penalty?: number;
352
+ seed?: number;
353
+ response_format?: {
354
+ type: "text" | "json_object" | "json_schema";
355
+ };
356
+ tools?: Array<{
357
+ type: "function";
358
+ function: {
359
+ name: string;
360
+ description?: string;
361
+ parameters?: unknown;
362
+ };
363
+ }>;
364
+ tool_choice?: "none" | "auto" | "required" | {
365
+ type: "function";
366
+ function: {
367
+ name: string;
368
+ };
369
+ };
370
+ user?: string;
371
+ };
372
+ type OpenaiChatCompletionResponse = {
373
+ id: string;
374
+ object: "chat.completion";
375
+ created: number;
376
+ model: string;
377
+ choices: Array<{
378
+ index: number;
379
+ message: {
380
+ role: "assistant";
381
+ content: string | null;
382
+ tool_calls?: unknown[];
383
+ };
384
+ finish_reason: "stop" | "length" | "tool_calls" | "content_filter" | string;
385
+ }>;
386
+ usage?: {
387
+ prompt_tokens: number;
388
+ completion_tokens: number;
389
+ total_tokens: number;
390
+ };
391
+ };
392
+ type OpenaiEmbeddingsParams = {
393
+ model: string;
394
+ input: string | string[];
395
+ dimensions?: number;
396
+ encoding_format?: "float" | "base64";
397
+ user?: string;
398
+ };
399
+ type OpenaiEmbeddingsResponse = {
400
+ object: "list";
401
+ data: Array<{
402
+ object: "embedding";
403
+ index: number;
404
+ embedding: number[];
405
+ }>;
406
+ model: string;
407
+ usage: {
408
+ prompt_tokens: number;
409
+ total_tokens: number;
410
+ };
411
+ };
412
+ type OpenaiTranscriptionParams = {
413
+ file: Blob;
414
+ model: string;
415
+ language?: string;
416
+ prompt?: string;
417
+ response_format?: "json" | "text" | "srt" | "verbose_json" | "vtt";
418
+ temperature?: number;
419
+ /** Filename to attach to the multipart upload. Defaults to "audio.webm". */
420
+ filename?: string;
421
+ };
422
+ type OpenaiTranscriptionResponse = {
423
+ text: string;
424
+ language?: string;
425
+ duration?: number;
426
+ segments?: Array<{
427
+ id: number;
428
+ start: number;
429
+ end: number;
430
+ text: string;
431
+ }>;
432
+ };
433
+ type OpenaiSpeechParams = {
434
+ model: string;
435
+ input: string;
436
+ voice: "alloy" | "echo" | "fable" | "onyx" | "nova" | "shimmer" | (string & {});
437
+ response_format?: "mp3" | "opus" | "aac" | "flac" | "wav" | "pcm";
438
+ speed?: number;
439
+ instructions?: string;
440
+ };
441
+ /**
442
+ * The OpenAI typed convenience surface. Wraps `proxy.call` / `callRaw` /
443
+ * `callStream` with provider="openai" pre-set and per-endpoint typings.
444
+ *
445
+ * const result = await openai.images.generate(token, {
446
+ * model: "gpt-image-1",
447
+ * prompt: "...",
448
+ * n: 4,
449
+ * });
450
+ */
451
+ declare const openai: {
452
+ readonly images: {
453
+ readonly generate: (token: string, params: OpenaiImageGenerateParams, opts?: HubCallOptions) => Promise<OpenaiImageGenerateResponse>;
454
+ };
455
+ readonly chat: {
456
+ readonly completions: {
457
+ readonly create: (token: string, params: OpenaiChatCompletionParams, opts?: HubCallOptions) => Promise<OpenaiChatCompletionResponse>;
458
+ readonly stream: (token: string, params: Omit<OpenaiChatCompletionParams, "stream">, opts?: HubCallOptions) => Promise<ReadableStream<Uint8Array>>;
459
+ };
460
+ };
461
+ readonly embeddings: {
462
+ readonly create: (token: string, params: OpenaiEmbeddingsParams, opts?: HubCallOptions) => Promise<OpenaiEmbeddingsResponse>;
463
+ };
464
+ readonly audio: {
465
+ readonly transcriptions: {
466
+ readonly create: (token: string, params: OpenaiTranscriptionParams, opts?: HubCallOptions) => Promise<OpenaiTranscriptionResponse>;
467
+ };
468
+ readonly speech: {
469
+ readonly create: (token: string, params: OpenaiSpeechParams, opts?: HubCallOptions) => Promise<Response>;
470
+ };
471
+ };
472
+ };
473
+
474
+ /**
475
+ * Typed convenience wrappers for Anthropic's Messages API.
476
+ *
477
+ * Hub-side handles the per-provider auth quirk (Anthropic uses `x-api-key`
478
+ * not `Authorization: Bearer`) and injects the required
479
+ * `anthropic-version: 2023-06-01` header automatically — see
480
+ * `src/lib/proxy/providers.ts` on the hub for the config.
481
+ */
482
+ type AnthropicTextBlock = {
483
+ type: "text";
484
+ text: string;
485
+ };
486
+ type AnthropicImageBlock = {
487
+ type: "image";
488
+ source: {
489
+ type: "base64";
490
+ media_type: string;
491
+ data: string;
492
+ } | {
493
+ type: "url";
494
+ url: string;
495
+ };
496
+ };
497
+ type AnthropicToolUseBlock = {
498
+ type: "tool_use";
499
+ id: string;
500
+ name: string;
501
+ input: Record<string, unknown>;
502
+ };
503
+ type AnthropicToolResultBlock = {
504
+ type: "tool_result";
505
+ tool_use_id: string;
506
+ content: string | AnthropicTextBlock[];
507
+ is_error?: boolean;
508
+ };
509
+ type AnthropicContentBlock = AnthropicTextBlock | AnthropicImageBlock | AnthropicToolUseBlock | AnthropicToolResultBlock;
510
+ type AnthropicMessage = {
511
+ role: "user" | "assistant";
512
+ content: string | AnthropicContentBlock[];
513
+ };
514
+ type AnthropicMessagesParams = {
515
+ model: string;
516
+ messages: AnthropicMessage[];
517
+ max_tokens: number;
518
+ system?: string | AnthropicTextBlock[];
519
+ temperature?: number;
520
+ top_p?: number;
521
+ top_k?: number;
522
+ stop_sequences?: string[];
523
+ stream?: boolean;
524
+ tools?: Array<{
525
+ name: string;
526
+ description?: string;
527
+ input_schema: Record<string, unknown>;
528
+ }>;
529
+ tool_choice?: {
530
+ type: "auto";
531
+ } | {
532
+ type: "any";
533
+ } | {
534
+ type: "tool";
535
+ name: string;
536
+ };
537
+ metadata?: {
538
+ user_id?: string;
539
+ };
540
+ };
541
+ type AnthropicMessagesResponse = {
542
+ id: string;
543
+ type: "message";
544
+ role: "assistant";
545
+ model: string;
546
+ content: AnthropicContentBlock[];
547
+ stop_reason: "end_turn" | "max_tokens" | "stop_sequence" | "tool_use" | string;
548
+ stop_sequence: string | null;
549
+ usage: {
550
+ input_tokens: number;
551
+ output_tokens: number;
552
+ cache_creation_input_tokens?: number;
553
+ cache_read_input_tokens?: number;
554
+ };
555
+ };
556
+ declare const anthropic: {
557
+ readonly messages: {
558
+ readonly create: (token: string, params: AnthropicMessagesParams, opts?: HubCallOptions) => Promise<AnthropicMessagesResponse>;
559
+ readonly stream: (token: string, params: Omit<AnthropicMessagesParams, "stream">, opts?: HubCallOptions) => Promise<ReadableStream<Uint8Array>>;
560
+ };
561
+ };
562
+
563
+ /**
564
+ * Typed convenience wrappers for Replicate's Predictions API.
565
+ *
566
+ * Replicate uses an async lifecycle: POST to create a prediction, GET to
567
+ * poll its status, optionally cancel. We surface all three plus a small
568
+ * `predictions.run()` helper that polls until the prediction is final.
569
+ *
570
+ * For per-model deployments (Replicate's hosted models with stable URLs),
571
+ * use `proxy.call(token, { provider: "replicate", path: "/v1/models/.../predictions", ... })`
572
+ * directly — the generic passthrough handles every Replicate endpoint we
573
+ * haven't typed here yet.
574
+ */
575
+ type ReplicatePredictionStatus = "starting" | "processing" | "succeeded" | "failed" | "canceled";
576
+ type ReplicatePrediction<TOutput = unknown> = {
577
+ id: string;
578
+ version: string;
579
+ status: ReplicatePredictionStatus;
580
+ input: Record<string, unknown>;
581
+ output: TOutput | null;
582
+ error: string | null;
583
+ logs: string;
584
+ created_at: string;
585
+ started_at: string | null;
586
+ completed_at: string | null;
587
+ urls: {
588
+ get: string;
589
+ cancel: string;
590
+ stream?: string;
591
+ };
592
+ metrics?: {
593
+ predict_time?: number;
594
+ };
595
+ };
596
+ type ReplicateCreatePredictionParams = {
597
+ /** Model version hash. Mutually exclusive with the model-deployment URL form. */
598
+ version: string;
599
+ input: Record<string, unknown>;
600
+ webhook?: string;
601
+ webhook_events_filter?: Array<"start" | "output" | "logs" | "completed">;
602
+ stream?: boolean;
603
+ };
604
+ declare const replicate: {
605
+ readonly predictions: {
606
+ readonly create: <TOutput = unknown>(token: string, params: ReplicateCreatePredictionParams, opts?: HubCallOptions) => Promise<ReplicatePrediction<TOutput>>;
607
+ readonly get: <TOutput = unknown>(token: string, predictionId: string, opts?: HubCallOptions) => Promise<ReplicatePrediction<TOutput>>;
608
+ readonly cancel: <TOutput = unknown>(token: string, predictionId: string, opts?: HubCallOptions) => Promise<ReplicatePrediction<TOutput>>;
609
+ /**
610
+ * Convenience: create + poll until the prediction reaches a terminal
611
+ * status. Polls every `pollIntervalMs` (default 1000ms) with the
612
+ * provided AbortSignal honoured.
613
+ *
614
+ * For long-running predictions consider using webhooks via
615
+ * `create({ webhook, webhook_events_filter })` instead so you're not
616
+ * holding open a long fetch.
617
+ */
618
+ readonly run: <TOutput = unknown>(token: string, params: ReplicateCreatePredictionParams, opts?: HubCallOptions & {
619
+ pollIntervalMs?: number;
620
+ }) => Promise<ReplicatePrediction<TOutput>>;
621
+ };
622
+ };
623
+
166
624
  /**
167
625
  * Typed errors.
168
626
  *
@@ -183,7 +641,7 @@ declare function get(jwt: string, provider: ProviderSlug, opts?: HubCallOptions)
183
641
  * else throw e;
184
642
  * }
185
643
  */
186
- type HubSdkErrorCode = "missing_token" | "bad_token" | "missing_scope" | "subscription_inactive" | "tool_not_found" | "not_subscribed" | "provider_not_granted" | "rate_limited" | "key_not_found" | "internal" | "network" | "secure_key_consumed";
644
+ type HubSdkErrorCode = "missing_token" | "bad_token" | "missing_scope" | "subscription_inactive" | "tool_not_found" | "not_subscribed" | "provider_not_granted" | "rate_limited" | "key_not_found" | "internal" | "network" | "secure_key_consumed" | "provider_error" | "provider_not_configured";
187
645
  /** Base class for every typed error in the SDK. */
188
646
  declare class HubSdkError extends Error {
189
647
  readonly code: HubSdkErrorCode;
@@ -228,28 +686,75 @@ declare class NetworkError extends HubSdkError {
228
686
  declare class SecureKeyConsumedError extends HubSdkError {
229
687
  constructor();
230
688
  }
689
+ /**
690
+ * The proxy was asked to forward to a provider the hub doesn't have
691
+ * configured. Distinct from `provider_not_granted` (which means the tool
692
+ * isn't permitted to use a known provider). Fix: add the provider to
693
+ * `src/lib/proxy/providers.ts` on the hub, or use a registered slug.
694
+ */
695
+ declare class ProviderNotConfiguredError extends HubSdkError {
696
+ constructor(provider: string);
697
+ }
698
+ /**
699
+ * The upstream provider (OpenAI / Anthropic / etc.) returned a non-2xx
700
+ * response. The hub relays it unchanged — `body` holds the parsed JSON
701
+ * body if the response was JSON, or the raw text otherwise, so the tool
702
+ * can inspect the provider's native error shape.
703
+ *
704
+ * This is the catch-all for "the platform did its job correctly; the
705
+ * upstream rejected the request" — wrong key (relayed 401), model not
706
+ * available (provider 400), upstream rate limit (provider 429), etc.
707
+ *
708
+ * Distinguish from `RateLimitedError` (hub-side rate limit) by checking
709
+ * `instanceof` first; the typed hub errors take precedence.
710
+ */
711
+ declare class ProviderError extends HubSdkError {
712
+ /** The provider slug we tried to call. */
713
+ readonly provider: string;
714
+ /** The path on the provider that returned non-2xx. */
715
+ readonly path: string;
716
+ /**
717
+ * The upstream response body. Parsed as JSON when the upstream's
718
+ * content-type was JSON; raw text otherwise.
719
+ */
720
+ readonly body: unknown;
721
+ /** The upstream response status code (relayed unchanged). */
722
+ readonly upstreamStatus: number;
723
+ constructor(provider: string, path: string, upstreamStatus: number, body: unknown);
724
+ }
231
725
 
232
726
  /**
233
727
  * `@openkeyai/sdk` — public entry.
234
728
  *
235
729
  * Tools install this and import only from the package root:
236
730
  *
237
- * import { session, keys, SecureKey, SubscriptionInactiveError } from "@openkeyai/sdk";
731
+ * import { session, openai, anthropic, proxy, ProviderError } from "@openkeyai/sdk";
238
732
  *
239
- * The five-module surface (session / keys / user / billing / webhooks) is
240
- * defined in
733
+ * The seven-module surface (session / keys / proxy / openai / anthropic /
734
+ * replicate / webhooks) is defined in
241
735
  * https://github.com/Scott-Builds-AI/hub/blob/main/docs/TOOL_SDK.md
242
736
  *
243
- * Status by module in 0.1.0:
737
+ * Status by module in 0.2.0:
244
738
  * - session.verify ✓
245
- * - keys.get → SecureKey ✓
246
- * - user — deferred until the hub ships /api/me (issue TBD)
739
+ * - keys.get → SecureKey ✓ (kept for endpoints the proxy doesn't typeset yet)
740
+ * - proxy.call / .callRaw / .callStream ✓ ← Phase 19 universal passthrough
741
+ * - openai.{images,chat,embeddings,audio} ✓ ← typed convenience
742
+ * - anthropic.messages ✓ ← typed convenience
743
+ * - replicate.predictions ✓ ← typed convenience
744
+ * - user — deferred until the hub ships /api/me
247
745
  * - billing — deferred until the hub ships /api/billing/status
248
- * - webhooks — deferred until Phase 16 (the hub's webhook delivery layer)
746
+ * - webhooks — deferred until Phase 16 (hub's webhook delivery layer)
249
747
  *
250
748
  * Internal helpers live under `_internal/`. They are NOT part of the
251
749
  * public API and may change without notice — the tool-manifest scanner
252
750
  * (Phase 9) treats `@openkeyai/sdk/_internal` imports as a CI failure.
751
+ *
752
+ * Migration note (Phase 19):
753
+ * The `keys.get(jwt, provider).use(callback)` SecureKey pattern still
754
+ * works and is the only path for endpoints we haven't typed in the
755
+ * proxy yet. For canonical model calls (images.generate, chat,
756
+ * embeddings, etc.) prefer the proxy — the plaintext key never enters
757
+ * your Worker process.
253
758
  */
254
759
 
255
760
  /** session module — JWT verification + (future) refresh. */
@@ -260,8 +765,18 @@ declare const session: {
260
765
  declare const keys: {
261
766
  readonly get: typeof get;
262
767
  };
768
+ /**
769
+ * proxy module — Phase 19 zero-trust universal forwarder. Plaintext keys
770
+ * never leave the hub. Supports any HTTP method, any path on any
771
+ * registered provider, any body shape, streaming and binary responses.
772
+ */
773
+ declare const proxy: {
774
+ readonly call: typeof call;
775
+ readonly callRaw: typeof callRaw;
776
+ readonly callStream: typeof callStream;
777
+ };
263
778
 
264
779
  /** Bumped on each release. Tools log this on boot. */
265
- declare const SDK_VERSION = "0.1.0";
780
+ declare const SDK_VERSION = "0.2.0";
266
781
 
267
- export { BadTokenError, type HubCallOptions, HubSdkError, type HubSdkErrorCode, InternalError, KeyNotFoundError, MissingScopeError, MissingTokenError, NetworkError, NotSubscribedError, ProviderNotGrantedError, type ProviderSlug, RateLimitedError, SDK_VERSION, SecureKey, SecureKeyConsumedError, SubscriptionInactiveError, type ToolJwtClaims, type ToolJwtScope, ToolNotFoundError, keys, session };
782
+ export { type AnthropicContentBlock, type AnthropicImageBlock, type AnthropicMessage, type AnthropicMessagesParams, type AnthropicMessagesResponse, type AnthropicTextBlock, type AnthropicToolResultBlock, type AnthropicToolUseBlock, BadTokenError, type HubCallOptions, HubSdkError, type HubSdkErrorCode, InternalError, KeyNotFoundError, MissingScopeError, MissingTokenError, NetworkError, NotSubscribedError, type OpenaiChatCompletionParams, type OpenaiChatCompletionResponse, type OpenaiChatMessage, type OpenaiChatMessageContentPart, type OpenaiChatRole, type OpenaiEmbeddingsParams, type OpenaiEmbeddingsResponse, type OpenaiImageData, type OpenaiImageGenerateParams, type OpenaiImageGenerateResponse, type OpenaiImageModel, type OpenaiImageQuality, type OpenaiImageSize, type OpenaiImageStyle, type OpenaiSpeechParams, type OpenaiTranscriptionParams, type OpenaiTranscriptionResponse, ProviderError, ProviderNotConfiguredError, ProviderNotGrantedError, type ProviderSlug, type ProxyCallOptions, RateLimitedError, type ReplicateCreatePredictionParams, type ReplicatePrediction, type ReplicatePredictionStatus, SDK_VERSION, SecureKey, SecureKeyConsumedError, SubscriptionInactiveError, type ToolJwtClaims, type ToolJwtMode, type ToolJwtScope, ToolNotFoundError, anthropic, keys, openai, proxy, replicate, session };