@providerprotocol/ai 0.0.39 → 0.0.40

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.
Files changed (130) hide show
  1. package/README.md +269 -34
  2. package/dist/anthropic/index.d.ts +3 -3
  3. package/dist/anthropic/index.js +7 -5
  4. package/dist/anthropic/index.js.map +1 -1
  5. package/dist/cerebras/index.d.ts +3 -3
  6. package/dist/cerebras/index.js +7 -5
  7. package/dist/cerebras/index.js.map +1 -1
  8. package/dist/{chunk-WU4U6IHF.js → chunk-6QCV4WXF.js} +4 -13
  9. package/dist/chunk-6QCV4WXF.js.map +1 -0
  10. package/dist/{chunk-5XPRVUOK.js → chunk-AC3VHSZJ.js} +2 -2
  11. package/dist/{chunk-5XPRVUOK.js.map → chunk-AC3VHSZJ.js.map} +1 -1
  12. package/dist/{chunk-ZDYEDI2A.js → chunk-CWGTARDE.js} +2 -2
  13. package/dist/{chunk-KNBODIQU.js → chunk-DI47UY2H.js} +2 -2
  14. package/dist/{chunk-KNBODIQU.js.map → chunk-DI47UY2H.js.map} +1 -1
  15. package/dist/{chunk-IDZR4ROP.js → chunk-EHR3LIPS.js} +2 -2
  16. package/dist/{chunk-IDZR4ROP.js.map → chunk-EHR3LIPS.js.map} +1 -1
  17. package/dist/chunk-EY2LLDGY.js +94 -0
  18. package/dist/chunk-EY2LLDGY.js.map +1 -0
  19. package/dist/{chunk-MJI74VEJ.js → chunk-F5ENANMJ.js} +18 -2
  20. package/dist/chunk-F5ENANMJ.js.map +1 -0
  21. package/dist/chunk-IKJH5ZSJ.js +1 -0
  22. package/dist/chunk-IKJH5ZSJ.js.map +1 -0
  23. package/dist/{chunk-IIMTP3XC.js → chunk-KBI45OXI.js} +2 -2
  24. package/dist/{chunk-SAMIK4WZ.js → chunk-KVUOTFYZ.js} +2 -2
  25. package/dist/{chunk-U6M3MXNI.js → chunk-L6QWKFGE.js} +3 -2
  26. package/dist/chunk-L6QWKFGE.js.map +1 -0
  27. package/dist/{chunk-RDC5GYST.js → chunk-N4LAFGLX.js} +7 -7
  28. package/dist/{chunk-ZKNPQBIE.js → chunk-R3T2IYOU.js} +5 -3
  29. package/dist/{chunk-ZKNPQBIE.js.map → chunk-R3T2IYOU.js.map} +1 -1
  30. package/dist/chunk-U2G5PHHL.js +25 -0
  31. package/dist/chunk-U2G5PHHL.js.map +1 -0
  32. package/dist/{chunk-SBGZJVTJ.js → chunk-VQZPADW6.js} +100 -33
  33. package/dist/chunk-VQZPADW6.js.map +1 -0
  34. package/dist/{chunk-O32SBS6S.js → chunk-XTWBAL42.js} +2 -2
  35. package/dist/{chunk-O32SBS6S.js.map → chunk-XTWBAL42.js.map} +1 -1
  36. package/dist/{chunk-WNB5PSY6.js → chunk-ZMESKGUY.js} +2 -2
  37. package/dist/{chunk-7ULSRWDH.js → chunk-ZSZVWLGE.js} +2 -2
  38. package/dist/{embedding-iNQCeXfk.d.ts → embedding-ts1npsDg.d.ts} +1 -1
  39. package/dist/google/index.d.ts +38 -4
  40. package/dist/google/index.js +5 -4
  41. package/dist/google/index.js.map +1 -1
  42. package/dist/groq/index.d.ts +3 -3
  43. package/dist/groq/index.js +7 -5
  44. package/dist/groq/index.js.map +1 -1
  45. package/dist/http/index.d.ts +5 -5
  46. package/dist/http/index.js +19 -22
  47. package/dist/{image-stream-ARno6XlS.d.ts → image-stream-BPml2YZZ.d.ts} +1 -1
  48. package/dist/index.d.ts +8 -8
  49. package/dist/index.js +306 -112
  50. package/dist/index.js.map +1 -1
  51. package/dist/{llm-CZqlijjK.d.ts → llm-BWLaTzzY.d.ts} +75 -29
  52. package/dist/middleware/logging/index.d.ts +3 -3
  53. package/dist/middleware/logging/index.js +3 -0
  54. package/dist/middleware/logging/index.js.map +1 -1
  55. package/dist/middleware/parsed-object/index.d.ts +3 -3
  56. package/dist/middleware/parsed-object/index.js +5 -1
  57. package/dist/middleware/parsed-object/index.js.map +1 -1
  58. package/dist/middleware/persistence/index.d.ts +3 -3
  59. package/dist/middleware/persistence/index.js +3 -2
  60. package/dist/middleware/persistence/index.js.map +1 -1
  61. package/dist/middleware/pipeline/index.d.ts +195 -0
  62. package/dist/middleware/pipeline/index.js +61 -0
  63. package/dist/middleware/pipeline/index.js.map +1 -0
  64. package/dist/middleware/pubsub/index.d.ts +13 -11
  65. package/dist/middleware/pubsub/index.js +31 -5
  66. package/dist/middleware/pubsub/index.js.map +1 -1
  67. package/dist/middleware/pubsub/server/express/index.d.ts +3 -3
  68. package/dist/middleware/pubsub/server/express/index.js +2 -2
  69. package/dist/middleware/pubsub/server/fastify/index.d.ts +3 -3
  70. package/dist/middleware/pubsub/server/fastify/index.js +2 -2
  71. package/dist/middleware/pubsub/server/h3/index.d.ts +3 -3
  72. package/dist/middleware/pubsub/server/h3/index.js +2 -2
  73. package/dist/middleware/pubsub/server/index.d.ts +50 -9
  74. package/dist/middleware/pubsub/server/index.js +5 -5
  75. package/dist/middleware/pubsub/server/index.js.map +1 -1
  76. package/dist/middleware/pubsub/server/webapi/index.d.ts +3 -3
  77. package/dist/middleware/pubsub/server/webapi/index.js +2 -2
  78. package/dist/moonshot/index.d.ts +3 -3
  79. package/dist/moonshot/index.js +7 -5
  80. package/dist/moonshot/index.js.map +1 -1
  81. package/dist/ollama/index.d.ts +24 -4
  82. package/dist/ollama/index.js +5 -4
  83. package/dist/ollama/index.js.map +1 -1
  84. package/dist/openai/index.d.ts +65 -4
  85. package/dist/openai/index.js +7 -5
  86. package/dist/openai/index.js.map +1 -1
  87. package/dist/openrouter/index.d.ts +4 -4
  88. package/dist/openrouter/index.js +7 -5
  89. package/dist/openrouter/index.js.map +1 -1
  90. package/dist/proxy/index.d.ts +5 -5
  91. package/dist/proxy/index.js +16 -15
  92. package/dist/proxy/index.js.map +1 -1
  93. package/dist/proxy/server/express/index.d.ts +8 -9
  94. package/dist/proxy/server/express/index.js +4 -3
  95. package/dist/proxy/server/fastify/index.d.ts +8 -9
  96. package/dist/proxy/server/fastify/index.js +4 -3
  97. package/dist/proxy/server/h3/index.d.ts +8 -9
  98. package/dist/proxy/server/h3/index.js +4 -3
  99. package/dist/proxy/server/index.d.ts +5 -5
  100. package/dist/proxy/server/index.js +14 -13
  101. package/dist/proxy/server/webapi/index.d.ts +8 -9
  102. package/dist/proxy/server/webapi/index.js +4 -3
  103. package/dist/responses/index.d.ts +3 -3
  104. package/dist/responses/index.js +7 -5
  105. package/dist/responses/index.js.map +1 -1
  106. package/dist/retry-DVfdPLIB.d.ts +322 -0
  107. package/dist/{stream-DVVUIKpz.d.ts → stream-bBd_4Ipu.d.ts} +27 -4
  108. package/dist/{tool-D22EhP5F.d.ts → tool-BmAfKNBq.d.ts} +1 -1
  109. package/dist/{types-CyXF0J7C.d.ts → types-nTwlpyJE.d.ts} +13 -1
  110. package/dist/utils/index.d.ts +66 -2
  111. package/dist/utils/index.js +13 -0
  112. package/dist/xai/index.d.ts +3 -3
  113. package/dist/xai/index.js +7 -5
  114. package/dist/xai/index.js.map +1 -1
  115. package/package.json +6 -1
  116. package/dist/chunk-ARVM24K2.js +0 -128
  117. package/dist/chunk-ARVM24K2.js.map +0 -1
  118. package/dist/chunk-MJI74VEJ.js.map +0 -1
  119. package/dist/chunk-SBGZJVTJ.js.map +0 -1
  120. package/dist/chunk-U6M3MXNI.js.map +0 -1
  121. package/dist/chunk-WU4U6IHF.js.map +0 -1
  122. package/dist/chunk-Y5H7C5J4.js +0 -263
  123. package/dist/chunk-Y5H7C5J4.js.map +0 -1
  124. package/dist/retry-C1eJbEMV.d.ts +0 -531
  125. /package/dist/{chunk-ZDYEDI2A.js.map → chunk-CWGTARDE.js.map} +0 -0
  126. /package/dist/{chunk-IIMTP3XC.js.map → chunk-KBI45OXI.js.map} +0 -0
  127. /package/dist/{chunk-SAMIK4WZ.js.map → chunk-KVUOTFYZ.js.map} +0 -0
  128. /package/dist/{chunk-RDC5GYST.js.map → chunk-N4LAFGLX.js.map} +0 -0
  129. /package/dist/{chunk-WNB5PSY6.js.map → chunk-ZMESKGUY.js.map} +0 -0
  130. /package/dist/{chunk-7ULSRWDH.js.map → chunk-ZSZVWLGE.js.map} +0 -0
package/README.md CHANGED
@@ -29,9 +29,10 @@ console.log(turn.response.text);
29
29
  | OpenRouter | `@providerprotocol/ai/openrouter` | ✓ | ✓ | ✓ |
30
30
  | Groq | `@providerprotocol/ai/groq` | ✓ | | |
31
31
  | Cerebras | `@providerprotocol/ai/cerebras` | ✓ | | |
32
+ | Moonshot | `@providerprotocol/ai/moonshot` | ✓ | | |
32
33
  | OpenResponses | `@providerprotocol/ai/responses` | ✓ | | |
33
34
 
34
- API keys are loaded automatically from environment variables (`ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `GROQ_API_KEY`, `CEREBRAS_API_KEY`, etc.).
35
+ API keys are loaded automatically from environment variables (`ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `GROQ_API_KEY`, `CEREBRAS_API_KEY`, `MOONSHOT_API_KEY`, etc.).
35
36
 
36
37
  ## LLM
37
38
 
@@ -229,6 +230,9 @@ const videoTurn = await gemini.generate([video.toBlock(), 'Describe this video']
229
230
  | OpenRouter | ✓ | PDF, Text | ✓ | ✓ |
230
231
  | xAI | ✓ | | | |
231
232
  | Groq | ✓ | | | |
233
+ | Moonshot | ✓ | | | ✓* |
234
+
235
+ \* Moonshot video input is experimental.
232
236
 
233
237
  ## Anthropic Beta Features
234
238
 
@@ -502,16 +506,15 @@ const result = await editor.edit({
502
506
  ## Configuration
503
507
 
504
508
  ```typescript
505
- import { llm } from '@providerprotocol/ai';
509
+ import { llm, exponentialBackoff, roundRobinKeys } from '@providerprotocol/ai';
506
510
  import { openai } from '@providerprotocol/ai/openai';
507
- import { ExponentialBackoff, RoundRobinKeys } from '@providerprotocol/ai/http';
508
511
 
509
512
  const instance = llm({
510
513
  model: openai('gpt-4o'),
511
514
  config: {
512
- apiKey: new RoundRobinKeys(['sk-key1', 'sk-key2']),
515
+ apiKey: roundRobinKeys(['sk-key1', 'sk-key2']),
513
516
  timeout: 30000,
514
- retryStrategy: new ExponentialBackoff({ maxAttempts: 3 }),
517
+ retryStrategy: exponentialBackoff({ maxAttempts: 3 }),
515
518
  },
516
519
  params: {
517
520
  temperature: 0.7,
@@ -569,34 +572,33 @@ interface ProviderConfig {
569
572
  ### Key Strategies
570
573
 
571
574
  ```typescript
572
- import { RoundRobinKeys, WeightedKeys, DynamicKey } from '@providerprotocol/ai/http';
575
+ import { roundRobinKeys, weightedKeys, dynamicKey } from '@providerprotocol/ai/http';
573
576
 
574
577
  // Cycle through keys evenly
575
- new RoundRobinKeys(['sk-1', 'sk-2', 'sk-3'])
578
+ roundRobinKeys(['sk-1', 'sk-2', 'sk-3'])
576
579
 
577
580
  // Weighted selection (70% key1, 30% key2)
578
- new WeightedKeys([
581
+ weightedKeys([
579
582
  { key: 'sk-1', weight: 70 },
580
583
  { key: 'sk-2', weight: 30 },
581
584
  ])
582
585
 
583
586
  // Dynamic fetching (secrets manager, etc.)
584
- new DynamicKey(async () => fetchKeyFromVault())
587
+ dynamicKey(async () => fetchKeyFromVault())
585
588
  ```
586
589
 
587
590
  ### Retry Strategies
588
591
 
589
592
  ```typescript
590
593
  import {
591
- ExponentialBackoff,
592
- LinearBackoff,
593
- NoRetry,
594
- TokenBucket,
595
- RetryAfterStrategy,
596
- } from '@providerprotocol/ai/http';
594
+ exponentialBackoff,
595
+ linearBackoff,
596
+ noRetry,
597
+ retryAfterStrategy,
598
+ } from '@providerprotocol/ai';
597
599
 
598
600
  // Exponential: 1s, 2s, 4s...
599
- new ExponentialBackoff({
601
+ exponentialBackoff({
600
602
  maxAttempts: 5,
601
603
  baseDelay: 1000,
602
604
  maxDelay: 30000,
@@ -604,20 +606,19 @@ new ExponentialBackoff({
604
606
  })
605
607
 
606
608
  // Linear: 1s, 2s, 3s...
607
- new LinearBackoff({ maxAttempts: 3, delay: 1000 })
608
-
609
- // Rate limiting with token bucket
610
- new TokenBucket({ maxTokens: 10, refillRate: 1 })
609
+ linearBackoff({ maxAttempts: 3, delay: 1000 })
611
610
 
612
611
  // Respect server Retry-After headers
613
- new RetryAfterStrategy({ maxAttempts: 3, fallbackDelay: 5000 })
612
+ retryAfterStrategy({ maxAttempts: 3, fallbackDelay: 5000 })
614
613
 
615
614
  // No retries
616
- new NoRetry()
615
+ noRetry()
617
616
  ```
618
617
 
619
618
  **Retryable Errors:** `RATE_LIMITED`, `NETWORK_ERROR`, `TIMEOUT`, `PROVIDER_ERROR`
620
619
 
620
+ **Streaming Retry:** Retry strategies work with both `.generate()` and `.stream()`. During streaming, `stream_retry` events are emitted to notify consumers of retry attempts, and middleware can use the `onRetry` hook to reset accumulated state.
621
+
621
622
  ## Tool Execution Control
622
623
 
623
624
  ```typescript
@@ -786,22 +787,55 @@ Bun.serve({
786
787
  ```typescript
787
788
  // Express
788
789
  import { express } from '@providerprotocol/ai/middleware/pubsub/server';
789
- app.post('/api/ai/reconnect', (req, res) => {
790
- const { streamId } = req.body;
790
+
791
+ app.post('/api/ai', async (req, res) => {
792
+ const { messages, streamId } = req.body;
793
+
794
+ // Guard: prevent duplicate generations on reconnect
795
+ if (!await adapter.exists(streamId)) {
796
+ const model = llm({
797
+ model: anthropic('claude-sonnet-4-20250514'),
798
+ middleware: [pubsubMiddleware({ adapter, streamId })],
799
+ });
800
+ model.stream(messages).then(turn => { /* save to DB */ });
801
+ }
802
+
791
803
  express.streamSubscriber(streamId, adapter, res);
792
804
  });
793
805
 
794
806
  // Fastify
795
807
  import { fastify } from '@providerprotocol/ai/middleware/pubsub/server';
796
- app.post('/api/ai/reconnect', (request, reply) => {
797
- const { streamId } = request.body;
808
+
809
+ app.post('/api/ai', async (request, reply) => {
810
+ const { messages, streamId } = request.body;
811
+
812
+ // Guard: prevent duplicate generations on reconnect
813
+ if (!await adapter.exists(streamId)) {
814
+ const model = llm({
815
+ model: anthropic('claude-sonnet-4-20250514'),
816
+ middleware: [pubsubMiddleware({ adapter, streamId })],
817
+ });
818
+ model.stream(messages).then(turn => { /* save to DB */ });
819
+ }
820
+
798
821
  return fastify.streamSubscriber(streamId, adapter, reply);
799
822
  });
800
823
 
801
824
  // H3/Nuxt
802
825
  import { h3 } from '@providerprotocol/ai/middleware/pubsub/server';
826
+
803
827
  export default defineEventHandler(async (event) => {
804
- const { streamId } = await readBody(event);
828
+ const { messages, streamId } = await readBody(event);
829
+
830
+ // Guard: prevent duplicate generations on reconnect
831
+ if (!await adapter.exists(streamId)) {
832
+ const model = llm({
833
+ model: anthropic('claude-sonnet-4-20250514'),
834
+ middleware: [pubsubMiddleware({ adapter, streamId })],
835
+ });
836
+ model.stream(messages).then(turn => { /* save to DB */ });
837
+ }
838
+
805
839
  return h3.streamSubscriber(streamId, adapter, event);
806
840
  });
807
841
  ```
@@ -842,6 +876,89 @@ const model = llm({
842
876
  });
843
877
  ```
844
878
 
879
+ ### Pipeline Middleware (Post-Turn Processing)
880
+
881
+ Run async tasks (image generation, embeddings, slug creation, etc.) after the LLM completes, with progress events streamed to connected clients:
882
+
883
+ ```typescript
884
+ import { llm } from '@providerprotocol/ai';
885
+ import { anthropic } from '@providerprotocol/ai/anthropic';
886
+ import { pubsubMiddleware, memoryAdapter } from '@providerprotocol/ai/middleware/pubsub';
887
+ import { pipelineMiddleware, isPipelineStageEvent } from '@providerprotocol/ai/middleware/pipeline';
888
+
889
+ const adapter = memoryAdapter();
890
+
891
+ const model = llm({
892
+ model: anthropic('claude-sonnet-4-20250514'),
893
+ structure: BlogPostSchema,
894
+ middleware: [
895
+ pubsubMiddleware({ adapter, streamId: postId }),
896
+ pipelineMiddleware<BlogPost>({
897
+ stages: [
898
+ {
899
+ type: 'slug',
900
+ run: (turn, emit) => {
901
+ const slug = turn.data!.title.toLowerCase().replace(/\s+/g, '-');
902
+ (turn as { slug?: string }).slug = slug;
903
+ emit({ slug });
904
+ },
905
+ },
906
+ {
907
+ type: 'embedding',
908
+ run: async (turn, emit) => {
909
+ await vectorize(turn.data!);
910
+ emit({ embedded: true });
911
+ },
912
+ },
913
+ ],
914
+ parallel: false, // Run stages sequentially (default)
915
+ continueOnError: false, // Stop on first error (default)
916
+ onStageError: ({ stage, error }) => {
917
+ console.error(`Stage ${stage.type} failed:`, error);
918
+ },
919
+ }),
920
+ ],
921
+ });
922
+
923
+ // Stages run after streaming completes
924
+ model.stream(prompt).then(turn => {
925
+ const extended = turn as typeof turn & { slug?: string };
926
+ console.log(extended.slug);
927
+ });
928
+ ```
929
+
930
+ **Consuming Pipeline Events:**
931
+
932
+ ```typescript
933
+ for await (const event of model.stream(prompt)) {
934
+ if (isPipelineStageEvent(event)) {
935
+ console.log(event.delta.stage, event.delta.payload);
936
+ // 'slug' { slug: 'my-blog-post' }
937
+ // 'embedding' { embedded: true }
938
+ }
939
+ }
940
+ ```
941
+
942
+ **Middleware Order:** Place `pipelineMiddleware` after `pubsubMiddleware` in the array:
943
+
944
+ ```typescript
945
+ middleware: [
946
+ pubsubMiddleware({ ... }), // Setup runs first in onStart
947
+ pipelineMiddleware({ ... }), // Events run first in onTurn (reverse order)
948
+ ]
949
+ ```
950
+
951
+ This ensures pubsub sets up before pipeline stages execute, and pipeline events emit before pubsub cleanup.
952
+
953
+ **Pipeline Configuration:**
954
+
955
+ | Option | Type | Default | Description |
956
+ |--------|------|---------|-------------|
957
+ | `stages` | `PipelineStage[]` | required | Stages to run after turn completion |
958
+ | `parallel` | `boolean` | `false` | Run stages in parallel instead of sequential |
959
+ | `continueOnError` | `boolean` | `false` | Continue running subsequent stages if one fails |
960
+ | `onStageError` | `function` | - | Called when a stage throws an error |
961
+
845
962
  ## Error Handling
846
963
 
847
964
  All errors are normalized to `UPPError` with consistent error codes:
@@ -888,17 +1005,16 @@ Build AI API gateways with your own authentication. Users authenticate with your
888
1005
  ### Server (Bun/Deno/Cloudflare Workers)
889
1006
 
890
1007
  ```typescript
891
- import { llm } from '@providerprotocol/ai';
1008
+ import { llm, exponentialBackoff, roundRobinKeys } from '@providerprotocol/ai';
892
1009
  import { anthropic } from '@providerprotocol/ai/anthropic';
893
- import { ExponentialBackoff, RoundRobinKeys } from '@providerprotocol/ai/http';
894
1010
  import { parseBody, toJSON, toSSE, toError } from '@providerprotocol/ai/proxy';
895
1011
 
896
1012
  // Server manages AI provider keys - users never see them
897
1013
  const claude = llm({
898
1014
  model: anthropic('claude-sonnet-4-20250514'),
899
1015
  config: {
900
- apiKey: new RoundRobinKeys([process.env.ANTHROPIC_KEY_1!, process.env.ANTHROPIC_KEY_2!]),
901
- retryStrategy: new ExponentialBackoff({ maxAttempts: 3 }),
1016
+ apiKey: roundRobinKeys([process.env.ANTHROPIC_KEY_1!, process.env.ANTHROPIC_KEY_2!]),
1017
+ retryStrategy: exponentialBackoff({ maxAttempts: 3 }),
902
1018
  },
903
1019
  });
904
1020
 
@@ -928,15 +1044,14 @@ Bun.serve({
928
1044
  Clients authenticate with your platform token. They get automatic retry on network failures to your proxy.
929
1045
 
930
1046
  ```typescript
931
- import { llm } from '@providerprotocol/ai';
1047
+ import { llm, exponentialBackoff } from '@providerprotocol/ai';
932
1048
  import { proxy } from '@providerprotocol/ai/proxy';
933
- import { ExponentialBackoff } from '@providerprotocol/ai/http';
934
1049
 
935
1050
  const claude = llm({
936
1051
  model: proxy('https://api.yourplatform.com/ai'),
937
1052
  config: {
938
1053
  headers: { 'Authorization': 'Bearer user-platform-token' },
939
- retryStrategy: new ExponentialBackoff({ maxAttempts: 3 }),
1054
+ retryStrategy: exponentialBackoff({ maxAttempts: 3 }),
940
1055
  timeout: 30000,
941
1056
  },
942
1057
  });
@@ -1153,6 +1268,85 @@ const model = llm({
1153
1268
 
1154
1269
  **Environment:** `CEREBRAS_API_KEY`
1155
1270
 
1271
+ ## Moonshot
1272
+
1273
+ Kimi K2.5 with 256K context, thinking mode, vision, and server-side builtin tools:
1274
+
1275
+ ```typescript
1276
+ import { llm } from '@providerprotocol/ai';
1277
+ import { moonshot, tools } from '@providerprotocol/ai/moonshot';
1278
+
1279
+ const model = llm({
1280
+ model: moonshot('kimi-k2.5'),
1281
+ params: { max_tokens: 1000 },
1282
+ });
1283
+
1284
+ const turn = await model.generate('Hello!');
1285
+ ```
1286
+
1287
+ **With thinking mode (default for K2.5):**
1288
+
1289
+ ```typescript
1290
+ const model = llm({
1291
+ model: moonshot('kimi-k2.5'),
1292
+ params: {
1293
+ max_tokens: 2000,
1294
+ temperature: 1.0,
1295
+ thinking: { type: 'enabled' },
1296
+ },
1297
+ });
1298
+
1299
+ // Response includes reasoning in turn.response.reasoning
1300
+ const turn = await model.generate('Solve step by step: 2x + 5 = 13');
1301
+ ```
1302
+
1303
+ **With instant mode (disabled thinking):**
1304
+
1305
+ ```typescript
1306
+ const model = llm({
1307
+ model: moonshot('kimi-k2.5'),
1308
+ params: {
1309
+ temperature: 0.6,
1310
+ thinking: { type: 'disabled' },
1311
+ },
1312
+ });
1313
+ ```
1314
+
1315
+ **With builtin tools:**
1316
+
1317
+ ```typescript
1318
+ const model = llm({
1319
+ model: moonshot('kimi-k2.5'),
1320
+ params: {
1321
+ tools: [
1322
+ tools.webSearch(),
1323
+ tools.codeRunner(),
1324
+ tools.date(),
1325
+ ],
1326
+ },
1327
+ });
1328
+ ```
1329
+
1330
+ **Available Builtin Tools:**
1331
+
1332
+ | Tool | Description |
1333
+ |------|-------------|
1334
+ | `tools.webSearch()` | Real-time internet search |
1335
+ | `tools.codeRunner()` | Python code execution with matplotlib/pandas |
1336
+ | `tools.quickjs()` | JavaScript execution via QuickJS engine |
1337
+ | `tools.fetch()` | URL content fetching with markdown extraction |
1338
+ | `tools.convert()` | Unit conversion (length, mass, temperature, currency) |
1339
+ | `tools.date()` | Date/time processing and timezone conversion |
1340
+ | `tools.base64Encode()` | Base64 encoding |
1341
+ | `tools.base64Decode()` | Base64 decoding |
1342
+ | `tools.memory()` | Memory storage and retrieval system |
1343
+ | `tools.rethink()` | Intelligent reasoning/reflection tool |
1344
+ | `tools.randomChoice()` | Random selection with optional weights |
1345
+
1346
+ **Capabilities:** Streaming, tool calling, structured output, thinking mode, image input, video input (experimental).
1347
+
1348
+ **Environment:** `MOONSHOT_API_KEY` or `KIMI_API_KEY`
1349
+
1156
1350
  ## OpenResponses Provider
1157
1351
 
1158
1352
  Connect to any server implementing the [OpenResponses specification](https://www.openresponses.org):
@@ -1209,8 +1403,10 @@ Full type safety with no `any` types. All provider parameters are typed:
1209
1403
  import type {
1210
1404
  // Core types
1211
1405
  Turn,
1406
+ TurnJSON,
1212
1407
  Message,
1213
1408
  Tool,
1409
+ ToolInput,
1214
1410
  TokenUsage,
1215
1411
 
1216
1412
  // Streaming
@@ -1268,6 +1464,45 @@ if (isZodSchema(schema)) {
1268
1464
  }
1269
1465
  ```
1270
1466
 
1467
+ **Error & ID Utilities:**
1468
+
1469
+ ```typescript
1470
+ import {
1471
+ toError,
1472
+ isCancelledError,
1473
+ generateId,
1474
+ generateShortId,
1475
+ } from '@providerprotocol/ai/utils';
1476
+
1477
+ // Convert unknown thrown values to Error instances
1478
+ const error = toError(unknownValue);
1479
+
1480
+ // Check if an error is a cancellation/abort error
1481
+ if (isCancelledError(error)) {
1482
+ console.log('Request was cancelled');
1483
+ }
1484
+
1485
+ // Generate IDs
1486
+ const uuid = generateId(); // UUID v4: "a1b2c3d4-..."
1487
+ const shortId = generateShortId('req'); // "req_abc123xyz789"
1488
+ ```
1489
+
1490
+ **Provider-Specific Types:**
1491
+
1492
+ ```typescript
1493
+ // OpenAI
1494
+ import type { OpenAIHeaders, OpenAIImageParams } from '@providerprotocol/ai/openai';
1495
+
1496
+ // Google
1497
+ import type { GoogleImagenParams } from '@providerprotocol/ai/google';
1498
+
1499
+ // Ollama
1500
+ import type { OllamaHeaders } from '@providerprotocol/ai/ollama';
1501
+
1502
+ // OpenRouter
1503
+ import type { OpenRouterProviderOptions } from '@providerprotocol/ai/openrouter';
1504
+ ```
1505
+
1271
1506
  **Type-Safe Enums:**
1272
1507
 
1273
1508
  ```typescript
@@ -1,6 +1,6 @@
1
- import { e as Provider } from '../llm-CZqlijjK.js';
2
- import '../stream-DVVUIKpz.js';
3
- import '../tool-D22EhP5F.js';
1
+ import { e as Provider } from '../llm-BWLaTzzY.js';
2
+ import '../stream-bBd_4Ipu.js';
3
+ import '../tool-BmAfKNBq.js';
4
4
 
5
5
  /**
6
6
  * @fileoverview Anthropic API type definitions.
@@ -6,7 +6,7 @@ import {
6
6
  } from "../chunk-TUTYMOBL.js";
7
7
  import {
8
8
  resolveApiKey
9
- } from "../chunk-ARVM24K2.js";
9
+ } from "../chunk-EY2LLDGY.js";
10
10
  import {
11
11
  createProvider
12
12
  } from "../chunk-JA3UZALR.js";
@@ -14,18 +14,20 @@ import {
14
14
  doFetch,
15
15
  doStreamFetch,
16
16
  normalizeHttpError
17
- } from "../chunk-SBGZJVTJ.js";
17
+ } from "../chunk-VQZPADW6.js";
18
18
  import {
19
19
  StreamEventType,
20
20
  objectDelta
21
- } from "../chunk-MJI74VEJ.js";
21
+ } from "../chunk-F5ENANMJ.js";
22
22
  import {
23
23
  AssistantMessage,
24
- generateId,
25
24
  isAssistantMessage,
26
25
  isToolResultMessage,
27
26
  isUserMessage
28
- } from "../chunk-WU4U6IHF.js";
27
+ } from "../chunk-6QCV4WXF.js";
28
+ import {
29
+ generateId
30
+ } from "../chunk-U2G5PHHL.js";
29
31
  import {
30
32
  toError
31
33
  } from "../chunk-GIDT7C6I.js";