ai-pro-sdk 2.0.1

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.
@@ -0,0 +1,894 @@
1
+ # Usage Guide
2
+
3
+ > **Historical:** Covers legacy provider versions 0.x (AI SDK v4). See the [main README](../../README.md) for current documentation.
4
+
5
+ ## Essential Examples
6
+
7
+ ### Streaming Responses
8
+
9
+ ```typescript
10
+ import { streamText } from 'ai';
11
+ import { claudeCode } from 'ai-sdk-provider-claude-code';
12
+
13
+ const result = await streamText({
14
+ model: claudeCode('sonnet'),
15
+ prompt: 'Write a haiku about programming',
16
+ });
17
+
18
+ for await (const chunk of result.textStream) {
19
+ process.stdout.write(chunk);
20
+ }
21
+ ```
22
+
23
+ ### Multi-turn Conversations
24
+
25
+ ```typescript
26
+ import { generateText } from 'ai';
27
+ import { claudeCode } from 'ai-sdk-provider-claude-code';
28
+
29
+ const messages = [];
30
+
31
+ // First turn
32
+ messages.push({ role: 'user', content: 'My name is Alice' });
33
+ const { text: response1 } = await generateText({
34
+ model: claudeCode('sonnet'),
35
+ messages,
36
+ });
37
+ messages.push({ role: 'assistant', content: response1 });
38
+
39
+ // Second turn - remembers context
40
+ messages.push({ role: 'user', content: 'What is my name?' });
41
+ const { text: response2 } = await generateText({
42
+ model: claudeCode('sonnet'),
43
+ messages,
44
+ });
45
+ console.log(response2); // "Alice"
46
+ ```
47
+
48
+ ### Object Generation with JSON Schema
49
+
50
+ ```typescript
51
+ import { generateObject } from 'ai';
52
+ import { claudeCode } from 'ai-sdk-provider-claude-code';
53
+ import { z } from 'zod';
54
+
55
+ const { object } = await generateObject({
56
+ model: claudeCode('sonnet'),
57
+ schema: z.object({
58
+ name: z.string().describe('Full name'),
59
+ age: z.number().describe('Age in years'),
60
+ email: z.string().email().describe('Email address'),
61
+ interests: z.array(z.string()).describe('List of hobbies'),
62
+ }),
63
+ prompt: 'Generate a profile for a software developer',
64
+ });
65
+
66
+ console.log(object);
67
+ // {
68
+ // name: "Alex Chen",
69
+ // age: 28,
70
+ // email: "alex.chen@example.com",
71
+ // interests: ["coding", "open source", "machine learning"]
72
+ // }
73
+ ```
74
+
75
+ ### Handling Long-Running Tasks
76
+
77
+ For complex tasks with Claude Opus 4's extended thinking, use AbortSignal with custom timeouts:
78
+
79
+ ```typescript
80
+ import { generateText } from 'ai';
81
+ import { claudeCode } from 'ai-sdk-provider-claude-code';
82
+
83
+ // Create a custom timeout
84
+ const controller = new AbortController();
85
+ const timeoutId = setTimeout(() => {
86
+ controller.abort(new Error('Request timeout after 10 minutes'));
87
+ }, 600000); // 10 minutes
88
+
89
+ try {
90
+ const { text } = await generateText({
91
+ model: claudeCode('opus'),
92
+ prompt: 'Analyze this complex problem in detail...',
93
+ abortSignal: controller.signal,
94
+ });
95
+
96
+ clearTimeout(timeoutId);
97
+ console.log(text);
98
+ } catch (error) {
99
+ if (error.name === 'AbortError') {
100
+ console.log('Request was cancelled');
101
+ }
102
+ }
103
+ ```
104
+
105
+ ### Session Management (Experimental)
106
+
107
+ ```typescript
108
+ import { generateText } from 'ai';
109
+ import { claudeCode } from 'ai-sdk-provider-claude-code';
110
+
111
+ // First message
112
+ const { text, providerMetadata } = await generateText({
113
+ model: claudeCode('sonnet'),
114
+ messages: [{ role: 'user', content: 'My name is Bob.' }],
115
+ });
116
+
117
+ // Resume using the session ID
118
+ const sessionId = providerMetadata?.['claude-code']?.sessionId;
119
+
120
+ const { text: response } = await generateText({
121
+ model: claudeCode('sonnet', { resume: sessionId }),
122
+ messages: [{ role: 'user', content: 'What is my name?' }],
123
+ });
124
+ ```
125
+
126
+ `resume` continues a previous CLI session instead of starting a new one.
127
+
128
+ ---
129
+
130
+ ## Detailed Configuration
131
+
132
+ ### AbortSignal Support
133
+
134
+ The provider fully supports the standard AbortSignal for request cancellation, following Vercel AI SDK patterns:
135
+
136
+ ```typescript
137
+ import { generateText } from 'ai';
138
+ import { claudeCode } from 'ai-sdk-provider-claude-code';
139
+
140
+ // Using AbortController for cancellation
141
+ const controller = new AbortController();
142
+
143
+ // Cancel after user action
144
+ button.addEventListener('click', () => {
145
+ controller.abort();
146
+ });
147
+
148
+ const { text } = await generateText({
149
+ model: claudeCode('opus'),
150
+ prompt: 'Write a story...',
151
+ abortSignal: controller.signal,
152
+ });
153
+ ```
154
+
155
+ **For Long-Running Tasks**: Claude Opus 4's extended thinking may require longer timeouts than typical HTTP requests. See the "Handling Long-Running Tasks" section above for implementing custom timeouts using AbortSignal.
156
+
157
+ ### Configuration Options
158
+
159
+ | Option | Type | Default | Description |
160
+ | ---------------------------- | -------------------- | ----------- | ----------------------------- |
161
+ | `model` | `'opus' \| 'sonnet'` | `'opus'` | Model to use |
162
+ | `pathToClaudeCodeExecutable` | `string` | `'claude'` | Path to Claude CLI executable |
163
+ | `customSystemPrompt` | `string` | `undefined` | Custom system prompt |
164
+ | `appendSystemPrompt` | `string` | `undefined` | Append to system prompt |
165
+ | `maxTurns` | `number` | `undefined` | Maximum conversation turns |
166
+ | `maxThinkingTokens` | `number` | `undefined` | Maximum thinking tokens |
167
+ | `permissionMode` | `string` | `'default'` | Permission mode for tools |
168
+ | `allowedTools` | `string[]` | `undefined` | Tools to explicitly allow |
169
+ | `disallowedTools` | `string[]` | `undefined` | Tools to restrict |
170
+ | `mcpServers` | `object` | `undefined` | MCP server configuration |
171
+ | `resume` | `string` | `undefined` | Resume an existing session |
172
+
173
+ ### Custom Configuration
174
+
175
+ ```typescript
176
+ import { createClaudeCode } from 'ai-sdk-provider-claude-code';
177
+
178
+ const claude = createClaudeCode({
179
+ defaultSettings: {
180
+ pathToClaudeCodeExecutable: '/usr/local/bin/claude',
181
+ permissionMode: 'default', // Ask for permissions
182
+ customSystemPrompt: 'You are a helpful coding assistant.',
183
+ },
184
+ });
185
+
186
+ const { text } = await generateText({
187
+ model: claude('opus'),
188
+ prompt: 'Hello, Claude!',
189
+ });
190
+ ```
191
+
192
+ ### Logging Configuration
193
+
194
+ Control how warnings and errors are logged:
195
+
196
+ ```typescript
197
+ import { createClaudeCode } from 'ai-sdk-provider-claude-code';
198
+
199
+ // Default: logs to console
200
+ const defaultClaude = createClaudeCode();
201
+
202
+ // Disable all logging
203
+ const silentClaude = createClaudeCode({
204
+ defaultSettings: {
205
+ logger: false,
206
+ },
207
+ });
208
+
209
+ // Custom logger
210
+ const customClaude = createClaudeCode({
211
+ defaultSettings: {
212
+ logger: {
213
+ warn: (message) => myLogger.warn('Claude:', message),
214
+ error: (message) => myLogger.error('Claude:', message),
215
+ },
216
+ },
217
+ });
218
+
219
+ // Model-specific logger override
220
+ const model = customClaude('opus', {
221
+ logger: false, // Disable logging for this model only
222
+ });
223
+ ```
224
+
225
+ Logger options:
226
+
227
+ - `undefined` (default): Uses `console.warn` and `console.error`
228
+ - `false`: Disables all logging
229
+ - Custom `Logger` object: Must implement `warn` and `error` methods
230
+
231
+ ### Tool Management
232
+
233
+ Control which tools Claude Code can use with either `allowedTools` (allowlist) or `disallowedTools` (denylist). These flags work for **both built-in Claude tools and MCP tools**, providing session-only permission overrides.
234
+
235
+ #### Tool Types
236
+
237
+ - **Built-in tools**: `Bash`, `Edit`, `Read`, `Write`, `LS`, `Grep`, etc.
238
+ - **MCP tools**: `mcp__serverName__toolName` format
239
+
240
+ #### Using allowedTools (Allowlist)
241
+
242
+ ```typescript
243
+ import { createClaudeCode } from 'ai-sdk-provider-claude-code';
244
+
245
+ // Only allow specific built-in tools
246
+ const readOnlyClaude = createClaudeCode({
247
+ allowedTools: ['Read', 'LS', 'Grep'],
248
+ });
249
+
250
+ // Allow specific Bash commands using specifiers
251
+ const gitOnlyClaude = createClaudeCode({
252
+ allowedTools: ['Bash(git log:*)', 'Bash(git diff:*)', 'Bash(git status)'],
253
+ });
254
+
255
+ // Mix built-in and MCP tools
256
+ const mixedClaude = createClaudeCode({
257
+ allowedTools: ['Read', 'Bash(npm test:*)', 'mcp__filesystem__read_text_file', 'mcp__git__status'],
258
+ });
259
+ ```
260
+
261
+ #### Using disallowedTools (Denylist)
262
+
263
+ ```typescript
264
+ // Block dangerous operations
265
+ const safeClaude = createClaudeCode({
266
+ disallowedTools: ['Write', 'Edit', 'Delete', 'Bash(rm:*)', 'Bash(sudo:*)'],
267
+ });
268
+
269
+ // Block all Bash and MCP write operations
270
+ const restrictedClaude = createClaudeCode({
271
+ disallowedTools: ['Bash', 'mcp__filesystem__write_file', 'mcp__git__commit', 'mcp__git__push'],
272
+ });
273
+ ```
274
+
275
+ #### Model-Specific Overrides
276
+
277
+ ```typescript
278
+ const baseClaude = createClaudeCode({
279
+ disallowedTools: ['Write', 'Edit'],
280
+ });
281
+
282
+ // Override for a specific call
283
+ const { text } = await generateText({
284
+ model: baseClaude('opus', {
285
+ disallowedTools: [], // Allow everything for this call
286
+ }),
287
+ prompt: 'Create a simple config file...',
288
+ });
289
+ ```
290
+
291
+ **Key Points**:
292
+
293
+ - These are **session-only permission overrides** (same syntax as settings.json)
294
+ - Higher priority than settings files
295
+ - Works for both built-in tools AND MCP tools
296
+ - Cannot use both `allowedTools` and `disallowedTools` together
297
+ - Empty `allowedTools: []` = Explicit empty allowlist (no tools allowed)
298
+ - Omitting the flags entirely = Falls back to normal permission system
299
+ - Use `/permissions` in Claude to see all available tool names
300
+
301
+ **Common Patterns**:
302
+
303
+ - Read-only mode: `disallowedTools: ['Write', 'Edit', 'Delete']`
304
+ - No shell access: `disallowedTools: ['Bash']`
305
+ - Safe git: `allowedTools: ['Bash(git log:*)', 'Bash(git diff:*)']`
306
+ - No MCP: `disallowedTools: ['mcp__*']`
307
+
308
+ **Permission Behavior**:
309
+ | Configuration | CLI Flag Behavior | Result |
310
+ |--------------|-------------------|---------|
311
+ | No config | No `--allowedTools` or `--disallowedTools` | Falls back to settings.json and interactive prompts |
312
+ | `allowedTools: []` | `--allowedTools` (empty) | Explicit empty allowlist - blocks all tools |
313
+ | `allowedTools: ['Read']` | `--allowedTools Read` | Only allows Read tool |
314
+ | `disallowedTools: []` | `--disallowedTools` (empty) | No effect - normal permissions apply |
315
+ | `disallowedTools: ['Write']` | `--disallowedTools Write` | Blocks Write tool, others follow normal permissions |
316
+
317
+ ## Advanced Configuration
318
+
319
+ ### MCP Server Support
320
+
321
+ The provider supports Model Context Protocol (MCP) servers for extended functionality:
322
+
323
+ ```typescript
324
+ const claude = createClaudeCode({
325
+ mcpServers: {
326
+ filesystem: {
327
+ command: 'npx',
328
+ args: ['-y', '@modelcontextprotocol/server-filesystem'],
329
+ },
330
+ github: {
331
+ type: 'sse',
332
+ url: 'https://mcp.github.com/api',
333
+ headers: { Authorization: 'Bearer YOUR_TOKEN' },
334
+ },
335
+ },
336
+ });
337
+ ```
338
+
339
+ ### Permission Modes
340
+
341
+ Control how Claude Code handles tool permissions:
342
+
343
+ ```typescript
344
+ const claude = createClaudeCode({
345
+ permissionMode: 'bypassPermissions', // Skip all permission prompts
346
+ // Other options: 'default', 'acceptEdits', 'plan'
347
+ });
348
+ ```
349
+
350
+ ### Custom System Prompts
351
+
352
+ ```typescript
353
+ const claude = createClaudeCode({
354
+ customSystemPrompt: 'You are an expert Python developer.',
355
+ // Or append to existing prompt:
356
+ appendSystemPrompt: 'Always use type hints in Python code.',
357
+ });
358
+ ```
359
+
360
+ ## Request Cancellation
361
+
362
+ The provider supports request cancellation through the standard AbortController API:
363
+
364
+ ```typescript
365
+ import { generateText } from 'ai';
366
+ import { claudeCode } from 'ai-sdk-provider-claude-code';
367
+
368
+ // Create abort controller
369
+ const controller = new AbortController();
370
+
371
+ // Start request
372
+ const promise = generateText({
373
+ model: claudeCode('opus'),
374
+ prompt: 'Write a long story...',
375
+ abortSignal: controller.signal,
376
+ });
377
+
378
+ // Cancel the request
379
+ controller.abort();
380
+
381
+ // The promise rejects with AbortError
382
+ try {
383
+ await promise;
384
+ } catch (error) {
385
+ if (error.name === 'AbortError') {
386
+ console.log('Request was cancelled');
387
+ }
388
+ }
389
+ ```
390
+
391
+ This is especially useful in UI scenarios where users might cancel requests or navigate away.
392
+
393
+ ## Implementation Details
394
+
395
+ ### SDK Message Types
396
+
397
+ The SDK provides structured message types for different events:
398
+
399
+ #### Assistant Message
400
+
401
+ ```typescript
402
+ {
403
+ type: 'assistant',
404
+ message: {
405
+ content: [{ type: 'text', text: 'Hello!' }],
406
+ // ... other fields
407
+ },
408
+ session_id: 'abc-123-def'
409
+ }
410
+ ```
411
+
412
+ #### Result Message
413
+
414
+ ```typescript
415
+ {
416
+ type: 'result',
417
+ subtype: 'success' | 'error_max_turns' | 'error_during_execution',
418
+ session_id: 'abc-123-def',
419
+ usage: { /* token counts */ },
420
+ total_cost_usd: 0.001,
421
+ duration_ms: 1500
422
+ }
423
+ ```
424
+
425
+ #### System Message
426
+
427
+ ```typescript
428
+ {
429
+ type: 'system',
430
+ subtype: 'init',
431
+ session_id: 'abc-123-def',
432
+ tools: ['Read', 'Write', 'Bash'],
433
+ model: 'opus'
434
+ }
435
+ ```
436
+
437
+ ### SDK Implementation
438
+
439
+ The provider uses the official `@anthropic-ai/claude-code` SDK which provides:
440
+
441
+ - **AsyncGenerator pattern**: Native streaming support with `query()` function
442
+ - **Structured messages**: Rich message types (assistant, result, system, error)
443
+ - **Built-in features**: AbortController, session management, MCP servers
444
+ - **Automatic handling**: Process management, error handling, and output parsing
445
+
446
+ ### Provider Metadata
447
+
448
+ The provider returns rich metadata including token usage, timing, and cost information:
449
+
450
+ ```typescript
451
+ const { text, usage, providerMetadata } = await generateText({
452
+ model: claudeCode('sonnet'),
453
+ prompt: 'Hello!',
454
+ });
455
+
456
+ console.log(providerMetadata);
457
+ // {
458
+ // "claude-code": {
459
+ // "sessionId": "abc-123-def",
460
+ // "costUsd": 0.0285561, // Note: Always non-zero for tracking
461
+ // "durationMs": 3056,
462
+ // "rawUsage": {
463
+ // "inputTokens": 4,
464
+ // "outputTokens": 7,
465
+ // "cacheCreationInputTokens": 5924,
466
+ // "cacheReadInputTokens": 10075
467
+ // }
468
+ // }
469
+ // }
470
+ ```
471
+
472
+ **Important Note about Costs**: The `costUsd` field shows the cost of the API usage:
473
+
474
+ - **For Pro/Max subscribers**: This is informational only - usage is covered by your monthly subscription
475
+ - **For API key users**: This represents actual charges that will be billed to your account
476
+
477
+ ## Object Generation
478
+
479
+ The provider supports object generation through prompt engineering, allowing you to generate structured data with JSON schema validation:
480
+
481
+ ```typescript
482
+ import { generateObject, streamObject } from 'ai';
483
+ import { claudeCode } from 'ai-sdk-provider-claude-code';
484
+ import { z } from 'zod';
485
+
486
+ // Generate a complete object
487
+ const { object } = await generateObject({
488
+ model: claudeCode('sonnet'),
489
+ schema: z.object({
490
+ recipe: z.object({
491
+ name: z.string(),
492
+ ingredients: z.array(z.string()),
493
+ instructions: z.array(z.string()),
494
+ prepTime: z.number(),
495
+ servings: z.number(),
496
+ }),
497
+ }),
498
+ prompt: 'Generate a recipe for chocolate chip cookies',
499
+ });
500
+
501
+ // Note: streamObject waits for complete response before parsing
502
+ // Use generateObject for clarity since streaming doesn't provide benefits
503
+ const { object: analysis } = await generateObject({
504
+ model: claudeCode('sonnet'),
505
+ schema: z.object({
506
+ analysis: z.string(),
507
+ sentiment: z.enum(['positive', 'negative', 'neutral']),
508
+ score: z.number(),
509
+ }),
510
+ prompt: 'Analyze this review: "Great product!"',
511
+ });
512
+
513
+ console.log(analysis);
514
+ ```
515
+
516
+ **How it works**: The provider appends JSON generation instructions to your prompt and uses a tolerant JSON parser to extract valid output from Claude's response. Minor issues like trailing commas or comments are automatically handled, though this is still not as strict as native JSON mode.
517
+
518
+ **Important notes**:
519
+
520
+ - **Object mode support**: Only `object-json` mode is supported (via `generateObject`/`streamObject`). The provider uses prompt engineering and JSON extraction to ensure reliable object generation.
521
+ - **Streaming behavior**: While `streamObject` is supported, it accumulates the full response before extracting JSON to ensure validity. Regular text streaming works in real-time.
522
+
523
+ ## Object Generation Cookbook
524
+
525
+ ### Quick Start Examples
526
+
527
+ #### Basic Objects
528
+
529
+ Start with simple schemas and clear prompts:
530
+
531
+ ```typescript
532
+ const { object } = await generateObject({
533
+ model: claudeCode('sonnet'),
534
+ schema: z.object({
535
+ name: z.string(),
536
+ age: z.number(),
537
+ email: z.string().email(),
538
+ }),
539
+ prompt: 'Generate a developer profile',
540
+ });
541
+ ```
542
+
543
+ [Full example](../examples/generate-object-basic.ts)
544
+
545
+ #### Nested Structures
546
+
547
+ Build complex hierarchical data:
548
+
549
+ ```typescript
550
+ const { object } = await generateObject({
551
+ model: claudeCode('sonnet'),
552
+ schema: z.object({
553
+ company: z.object({
554
+ departments: z.array(
555
+ z.object({
556
+ name: z.string(),
557
+ teams: z.array(
558
+ z.object({
559
+ name: z.string(),
560
+ members: z.number(),
561
+ })
562
+ ),
563
+ })
564
+ ),
565
+ }),
566
+ }),
567
+ prompt: 'Generate a company org structure',
568
+ });
569
+ ```
570
+
571
+ [Full example](../examples/generate-object-nested.ts)
572
+
573
+ #### Constrained Generation
574
+
575
+ Use Zod's validation features:
576
+
577
+ ```typescript
578
+ const { object } = await generateObject({
579
+ model: claudeCode('sonnet'),
580
+ schema: z.object({
581
+ status: z.enum(['pending', 'active', 'completed']),
582
+ priority: z.number().min(1).max(5),
583
+ tags: z.array(z.string()).min(1).max(3),
584
+ }),
585
+ prompt: 'Generate a task with medium priority',
586
+ });
587
+ ```
588
+
589
+ [Full example](../examples/generate-object-constraints.ts)
590
+
591
+ ### Best Practices
592
+
593
+ 1. **Start Simple**: Begin with basic schemas and add complexity gradually
594
+ 2. **Clear Prompts**: Be specific about what you want generated
595
+ 3. **Use Descriptions**: Add `.describe()` to schema fields for better results
596
+ 4. **Handle Errors**: Implement retry logic for production use
597
+ 5. **Test Schemas**: Validate your schemas work before deployment
598
+
599
+ ### Common Patterns
600
+
601
+ - **Data Models**: [User profiles, products, orders](../examples/generate-object-nested.ts)
602
+ - **Validation**: [Enums, constraints, regex patterns](../examples/generate-object-constraints.ts)
603
+ - **Basic Objects**: [Simple schemas and arrays](../examples/generate-object-basic.ts)
604
+ - **Note**: For object generation, use `generateObject` instead of `streamObject` as streaming provides no benefits
605
+
606
+ ## Object Generation Troubleshooting
607
+
608
+ ### Common Issues and Solutions
609
+
610
+ #### 1. Invalid JSON Response
611
+
612
+ **Problem**: Claude returns text instead of valid JSON
613
+
614
+ **Solutions**:
615
+
616
+ - Simplify your schema - start with fewer fields
617
+ - Make your prompt more explicit: "Generate only valid JSON"
618
+ - Check the schema for overly complex constraints
619
+ - Use the retry pattern:
620
+
621
+ ```typescript
622
+ async function generateWithRetry(schema, prompt, maxRetries = 3) {
623
+ for (let i = 0; i < maxRetries; i++) {
624
+ try {
625
+ return await generateObject({ model, schema, prompt });
626
+ } catch (error) {
627
+ if (i === maxRetries - 1) throw error;
628
+ await new Promise((r) => setTimeout(r, 1000 * Math.pow(2, i)));
629
+ }
630
+ }
631
+ }
632
+ ```
633
+
634
+ #### 2. Missing Required Fields
635
+
636
+ **Problem**: Generated objects missing required properties
637
+
638
+ **Solutions**:
639
+
640
+ - Emphasize requirements in your prompt
641
+ - Use descriptive field names
642
+ - Add field descriptions with `.describe()`
643
+ - Example:
644
+
645
+ ```typescript
646
+ z.object({
647
+ // Bad: vague field name
648
+ val: z.number(),
649
+
650
+ // Good: clear field name with description
651
+ totalPrice: z.number().describe('Total price in USD'),
652
+ });
653
+ ```
654
+
655
+ #### 3. Type Mismatches
656
+
657
+ **Problem**: String when expecting number, wrong date format, etc.
658
+
659
+ **Solutions**:
660
+
661
+ - Be explicit in descriptions: "age as a number" not just "age"
662
+ - For dates, specify format: `.describe('Date in YYYY-MM-DD format')`
663
+ - Use regex patterns for strings: `z.string().regex(/^\d{4}-\d{2}-\d{2}$/)`
664
+
665
+ #### 4. Schema Too Complex
666
+
667
+ **Problem**: Very complex schemas fail or timeout
668
+
669
+ **Solutions**:
670
+
671
+ - Break into smaller parts and combine:
672
+
673
+ ```typescript
674
+ // Instead of one huge schema, compose smaller ones
675
+ const userSchema = z.object({
676
+ /* user fields */
677
+ });
678
+ const settingsSchema = z.object({
679
+ /* settings */
680
+ });
681
+ const profileSchema = z.object({
682
+ user: userSchema,
683
+ settings: settingsSchema,
684
+ });
685
+ ```
686
+
687
+ - Generate in steps and merge results
688
+ - Increase timeout for complex generations
689
+
690
+ #### 5. Inconsistent Results
691
+
692
+ **Problem**: Same prompt gives different structure each time
693
+
694
+ **Solutions**:
695
+
696
+ - Make schemas more constrained (use enums, min/max)
697
+ - Provide example in prompt
698
+ - Use consistent field naming conventions
699
+ - Consider using `opus` model for complex schemas
700
+
701
+ ### Debugging Tips
702
+
703
+ 1. **Enable Debug Logging**:
704
+
705
+ ```typescript
706
+ const { object, usage, warnings } = await generateObject({
707
+ model: claudeCode('sonnet'),
708
+ schema: yourSchema,
709
+ prompt: yourPrompt,
710
+ });
711
+ console.log('Tokens used:', usage);
712
+ console.log('Warnings:', warnings);
713
+ ```
714
+
715
+ 2. **Test Schema Separately**:
716
+
717
+ ```typescript
718
+ // Validate your schema works
719
+ const testData = {
720
+ /* your test object */
721
+ };
722
+ try {
723
+ schema.parse(testData);
724
+ console.log('Schema is valid');
725
+ } catch (e) {
726
+ console.log('Schema errors:', e.errors);
727
+ }
728
+ ```
729
+
730
+ 3. **Progressive Enhancement**:
731
+ Start with minimal schema, test, then add fields one by one
732
+
733
+ 4. **Check Examples**:
734
+ Review our examples for implementation patterns
735
+
736
+ ## Limitations
737
+
738
+ - **No image support**: The Claude Code SDK doesn't support image inputs (provider sets `supportsImageUrls = false`)
739
+ - **No embedding support**: Text embeddings are not available through this provider
740
+ - **Object-tool mode not supported**: Only `object-json` mode works via `generateObject`/`streamObject`. The AI SDK's tool calling interface is not implemented
741
+ - **Text-only responses**: No support for file generation or other modalities
742
+ - **Session management**: While sessions are supported, message history is the recommended approach
743
+ - **Unsupported generation settings**: The following AI SDK settings are ignored and will generate warnings:
744
+ - `temperature` - Claude Code SDK doesn't expose temperature control
745
+ - `maxTokens` - Token limits aren't configurable via CLI
746
+ - `topP`, `topK` - Sampling parameters aren't available
747
+ - `presencePenalty`, `frequencyPenalty` - Penalty parameters aren't supported
748
+ - `stopSequences` - Custom stop sequences aren't available
749
+ - `seed` - Deterministic generation isn't supported
750
+
751
+ ## Error Handling
752
+
753
+ The provider uses standard AI SDK error classes for better ecosystem compatibility:
754
+
755
+ ```typescript
756
+ import { generateText } from 'ai';
757
+ import { APICallError, LoadAPIKeyError } from '@ai-sdk/provider';
758
+ import {
759
+ claudeCode,
760
+ isAuthenticationError,
761
+ isTimeoutError,
762
+ getErrorMetadata,
763
+ } from 'ai-sdk-provider-claude-code';
764
+
765
+ try {
766
+ const { text } = await generateText({
767
+ model: claudeCode('opus'),
768
+ prompt: 'Hello!',
769
+ });
770
+ } catch (error) {
771
+ if (isAuthenticationError(error)) {
772
+ console.error('Please run "claude login" to authenticate');
773
+ } else if (isTimeoutError(error)) {
774
+ console.error('Request timed out. Consider using AbortController with a custom timeout.');
775
+ } else if (error instanceof APICallError) {
776
+ // Get CLI-specific metadata
777
+ const metadata = getErrorMetadata(error);
778
+ console.error('CLI error:', {
779
+ message: error.message,
780
+ isRetryable: error.isRetryable,
781
+ exitCode: metadata?.exitCode,
782
+ stderr: metadata?.stderr,
783
+ });
784
+ } else {
785
+ console.error('Error:', error);
786
+ }
787
+ }
788
+ ```
789
+
790
+ ### Error Types
791
+
792
+ - **`LoadAPIKeyError`**: Authentication failures (exit code 401)
793
+ - **`APICallError`**: All other CLI failures
794
+ - `isRetryable: true` for timeouts
795
+ - `isRetryable: false` for SDK errors, authentication failures, etc.
796
+ - Contains metadata with `exitCode`, `stderr`, `promptExcerpt`
797
+
798
+ ## Troubleshooting
799
+
800
+ See [TROUBLESHOOTING.md](TROUBLESHOOTING.md) for solutions to common issues including:
801
+
802
+ - Authentication problems
803
+ - SDK installation issues
804
+ - Session management
805
+ - Platform-specific issues
806
+ - Timeout handling with AbortSignal
807
+
808
+ ## Project Structure
809
+
810
+ ```
811
+ ai-sdk-provider-claude-code/
812
+ ├── src/ # Source code
813
+ │ ├── index.ts # Main exports
814
+ │ ├── claude-code-provider.ts # Provider factory
815
+ │ ├── claude-code-language-model.ts # AI SDK implementation using SDK
816
+ │ ├── convert-to-claude-code-messages.ts # Message format converter
817
+ │ ├── extract-json.ts # JSON extraction for object generation
818
+ │ ├── errors.ts # Error handling utilities
819
+ │ ├── logger.ts # Configurable logger support
820
+ │ ├── map-claude-code-finish-reason.ts # Finish reason mapping utilities
821
+ │ ├── types.ts # TypeScript types and interfaces
822
+ │ ├── validation.ts # Input validation utilities
823
+ │ ├── *.test.ts # Test files for each module
824
+ │ └── logger.integration.test.ts # Logger integration tests
825
+ ├── examples/ # Example usage scripts
826
+ │ ├── README.md # Examples documentation
827
+ │ ├── abort-signal.ts # Request cancellation examples
828
+ │ ├── basic-usage.ts # Simple text generation with metadata
829
+ │ ├── check-cli.ts # CLI installation verification
830
+ │ ├── conversation-history.ts # Multi-turn conversation with message history
831
+ │ ├── custom-config.ts # Provider configuration options
832
+ │ ├── generate-object.ts # Original object generation example
833
+ │ ├── generate-object-basic.ts # Basic object generation patterns
834
+ │ ├── generate-object-constraints.ts # Validation and constraints
835
+ │ ├── generate-object-nested.ts # Complex nested structures
836
+ │ ├── integration-test.ts # Comprehensive integration tests
837
+ │ ├── limitations.ts # Provider limitations demo
838
+ │ ├── long-running-tasks.ts # Timeout handling with AbortSignal
839
+ │ ├── streaming.ts # Streaming response demo
840
+ │ ├── test-session.ts # Session management testing
841
+ │ └── tool-management.ts # Tool access control (allow/disallow)
842
+ ├── docs/ # Documentation
843
+ │ ├── GUIDE.md # Comprehensive guide (this file)
844
+ │ ├── DEVELOPMENT-STATUS.md # Development status and roadmap
845
+ │ └── TROUBLESHOOTING.md # Common issues and solutions
846
+ ├── CHANGELOG.md # Version history
847
+ ├── CODE_REVIEW_PLAN.md # Development planning documentation
848
+ ├── LICENSE # MIT License
849
+ ├── README.md # Main project documentation
850
+ ├── eslint.config.js # ESLint configuration
851
+ ├── package.json # Project metadata and dependencies
852
+ ├── package-lock.json # Dependency lock file
853
+ ├── run-all-examples.sh # Script to run all examples
854
+ ├── tsconfig.json # TypeScript configuration
855
+ ├── tsup.config.ts # Build configuration
856
+ └── vitest.config.ts # Test runner configuration
857
+ ```
858
+
859
+ ## Known Limitations
860
+
861
+ 1. **No image support**: The CLI doesn't accept image inputs
862
+ 2. **Authentication required**: Requires separate Claude Code SDK authentication (`claude login`)
863
+ 3. **Session IDs change**: Each request gets a new session ID, even when using `--resume`
864
+ 4. **No AI SDK tool calling interface**: The AI SDK's function/tool calling interface is not implemented, but Claude can use tools via MCP servers and built-in CLI tools
865
+
866
+ ## Contributing
867
+
868
+ Contributions are welcome! Please read our contributing guidelines before submitting a PR.
869
+
870
+ **Alpha Focus Areas:**
871
+
872
+ - Code structure improvements (AI-generated code cleanup)
873
+ - Performance optimizations
874
+ - Better error handling patterns
875
+ - TypeScript type improvements
876
+ - Additional example use cases
877
+
878
+ ### Dependency Management
879
+
880
+ This project uses exact dependency versions to ensure consistent behavior across all installations. When updating dependencies:
881
+
882
+ 1. Update the exact version in `package.json`
883
+ 2. Run `npm install` to update the lock file
884
+ 3. Test thoroughly before committing
885
+
886
+ Note: Peer dependencies (like `zod`) use version ranges as per npm best practices.
887
+
888
+ ## License
889
+
890
+ MIT - see [LICENSE](../LICENSE) for details.
891
+
892
+ ## Acknowledgments
893
+
894
+ This provider is built for the [Vercel AI SDK](https://sdk.vercel.ai/) and uses the [Claude Code SDK](https://docs.anthropic.com/claude-code/cli) by Anthropic.