@boostecom/provider 0.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.
Files changed (70) hide show
  1. package/README.md +90 -0
  2. package/dist/index.cjs +2522 -0
  3. package/dist/index.cjs.map +1 -0
  4. package/dist/index.d.cts +848 -0
  5. package/dist/index.d.ts +848 -0
  6. package/dist/index.js +2484 -0
  7. package/dist/index.js.map +1 -0
  8. package/docs/content/README.md +337 -0
  9. package/docs/content/agent-teams.mdx +324 -0
  10. package/docs/content/api.mdx +757 -0
  11. package/docs/content/best-practices.mdx +624 -0
  12. package/docs/content/examples.mdx +675 -0
  13. package/docs/content/guide.mdx +516 -0
  14. package/docs/content/index.mdx +99 -0
  15. package/docs/content/installation.mdx +246 -0
  16. package/docs/content/skills.mdx +548 -0
  17. package/docs/content/troubleshooting.mdx +588 -0
  18. package/docs/examples/README.md +499 -0
  19. package/docs/examples/abort-signal.ts +125 -0
  20. package/docs/examples/agent-teams.ts +122 -0
  21. package/docs/examples/basic-usage.ts +73 -0
  22. package/docs/examples/check-cli.ts +51 -0
  23. package/docs/examples/conversation-history.ts +69 -0
  24. package/docs/examples/custom-config.ts +90 -0
  25. package/docs/examples/generate-object-constraints.ts +209 -0
  26. package/docs/examples/generate-object.ts +211 -0
  27. package/docs/examples/hooks-callbacks.ts +63 -0
  28. package/docs/examples/images.ts +76 -0
  29. package/docs/examples/integration-test.ts +241 -0
  30. package/docs/examples/limitations.ts +150 -0
  31. package/docs/examples/logging-custom-logger.ts +99 -0
  32. package/docs/examples/logging-default.ts +55 -0
  33. package/docs/examples/logging-disabled.ts +74 -0
  34. package/docs/examples/logging-verbose.ts +64 -0
  35. package/docs/examples/long-running-tasks.ts +179 -0
  36. package/docs/examples/message-injection.ts +210 -0
  37. package/docs/examples/mid-stream-injection.ts +126 -0
  38. package/docs/examples/run-all-examples.sh +48 -0
  39. package/docs/examples/sdk-tools-callbacks.ts +49 -0
  40. package/docs/examples/skills-discovery.ts +144 -0
  41. package/docs/examples/skills-management.ts +140 -0
  42. package/docs/examples/stream-object.ts +80 -0
  43. package/docs/examples/streaming.ts +52 -0
  44. package/docs/examples/structured-output-repro.ts +227 -0
  45. package/docs/examples/tool-management.ts +215 -0
  46. package/docs/examples/tool-streaming.ts +132 -0
  47. package/docs/examples/zod4-compatibility-test.ts +290 -0
  48. package/docs/src/claude-code-language-model.test.ts +3883 -0
  49. package/docs/src/claude-code-language-model.ts +2586 -0
  50. package/docs/src/claude-code-provider.test.ts +97 -0
  51. package/docs/src/claude-code-provider.ts +179 -0
  52. package/docs/src/convert-to-claude-code-messages.images.test.ts +104 -0
  53. package/docs/src/convert-to-claude-code-messages.test.ts +193 -0
  54. package/docs/src/convert-to-claude-code-messages.ts +419 -0
  55. package/docs/src/errors.test.ts +213 -0
  56. package/docs/src/errors.ts +216 -0
  57. package/docs/src/index.test.ts +49 -0
  58. package/docs/src/index.ts +98 -0
  59. package/docs/src/logger.integration.test.ts +164 -0
  60. package/docs/src/logger.test.ts +184 -0
  61. package/docs/src/logger.ts +65 -0
  62. package/docs/src/map-claude-code-finish-reason.test.ts +120 -0
  63. package/docs/src/map-claude-code-finish-reason.ts +60 -0
  64. package/docs/src/mcp-helpers.test.ts +71 -0
  65. package/docs/src/mcp-helpers.ts +123 -0
  66. package/docs/src/message-injection.test.ts +460 -0
  67. package/docs/src/types.ts +447 -0
  68. package/docs/src/validation.test.ts +558 -0
  69. package/docs/src/validation.ts +360 -0
  70. package/package.json +124 -0
@@ -0,0 +1,122 @@
1
+ import { claudeCode } from '../dist/index.js';
2
+ import { generateText } from 'ai';
3
+
4
+ /**
5
+ * Agent Teams Example with Claude Opus 4.6
6
+ *
7
+ * Demonstrates how to use multiple specialized subagents working together
8
+ * as a coordinated team to accomplish complex, multi-faceted tasks.
9
+ *
10
+ * This example showcases:
11
+ * - Multiple specialized agents (research, coding, testing)
12
+ * - Tool restrictions per agent
13
+ * - Coordination between agents
14
+ * - Extended context window usage (1M tokens in beta)
15
+ */
16
+
17
+ async function main() {
18
+ console.log('=== Agent Teams Example ===\n');
19
+
20
+ // Create a model with multiple specialized subagents
21
+ const model = claudeCode('opus', {
22
+ // Enable extended context window (1M tokens - beta feature)
23
+ maxThinkingTokens: 10000,
24
+
25
+ // Configure agent team with specialized roles
26
+ agents: {
27
+ // Research Agent - Specializes in information gathering
28
+ researcher: {
29
+ description: 'Expert at finding information, searching codebases, and analyzing documentation',
30
+ tools: ['Read', 'Grep', 'Glob', 'WebSearch', 'Skill'],
31
+ disallowedTools: ['Write', 'Edit', 'Bash'],
32
+ prompt: `You are a research specialist. Your role is to:
33
+ - Find and analyze relevant information
34
+ - Search through codebases systematically
35
+ - Provide comprehensive summaries
36
+ - Cite your sources clearly
37
+
38
+ When you find information, organize it clearly and pass it to the appropriate agent.`,
39
+ model: 'sonnet', // Use faster model for research
40
+ },
41
+
42
+ // Coding Agent - Specializes in implementation
43
+ developer: {
44
+ description: 'Expert at writing, editing, and refactoring code with best practices',
45
+ tools: ['Read', 'Write', 'Edit', 'Grep', 'Glob', 'Skill'],
46
+ disallowedTools: ['Bash(rm:*)', 'Bash(sudo:*)'],
47
+ prompt: `You are a senior software engineer. Your role is to:
48
+ - Write clean, maintainable code
49
+ - Follow best practices and design patterns
50
+ - Implement features based on research findings
51
+ - Create well-documented code
52
+
53
+ Always write tests for your implementations and coordinate with the testing agent.`,
54
+ model: 'opus', // Use most capable model for coding
55
+ },
56
+
57
+ // Testing Agent - Specializes in quality assurance
58
+ tester: {
59
+ description: 'Expert at writing tests, running test suites, and ensuring code quality',
60
+ tools: ['Read', 'Write', 'Bash', 'Grep', 'Skill'],
61
+ disallowedTools: ['Edit'],
62
+ prompt: `You are a QA engineer and testing specialist. Your role is to:
63
+ - Write comprehensive test suites
64
+ - Run tests and analyze results
65
+ - Identify edge cases and potential bugs
66
+ - Ensure code quality and coverage
67
+
68
+ Review implementations from the developer agent and provide feedback.`,
69
+ model: 'haiku', // Use fast model for testing
70
+ },
71
+ },
72
+
73
+ // Enable Skills for all agents
74
+ settingSources: ['user', 'project'],
75
+ allowedTools: ['Skill', 'Read', 'Write', 'Edit', 'Grep', 'Glob', 'Bash'],
76
+
77
+ // Enable extended features
78
+ betas: ['code-execution-tool'],
79
+
80
+ // Session management
81
+ persistSession: true,
82
+ maxTurns: 20,
83
+
84
+ verbose: true,
85
+ });
86
+
87
+ try {
88
+ const prompt = `I need to build a secure user authentication system for a Node.js API. Please:
89
+
90
+ 1. Research best practices for password hashing and session management
91
+ 2. Implement a complete auth module with:
92
+ - User registration with bcrypt password hashing
93
+ - Login with JWT tokens
94
+ - Session management with refresh tokens
95
+ - Rate limiting for security
96
+ 3. Write comprehensive tests covering all scenarios
97
+
98
+ Coordinate between the research, development, and testing agents to deliver a production-ready solution.`;
99
+
100
+ console.log('Prompt:', prompt);
101
+ console.log('\nGenerating with agent team...\n');
102
+
103
+ const { text, usage, finishReason } = await generateText({
104
+ model,
105
+ prompt,
106
+ });
107
+
108
+ console.log('\n=== Result ===');
109
+ console.log(text);
110
+
111
+ console.log('\n=== Usage ===');
112
+ console.log('Input tokens:', usage.inputTokens);
113
+ console.log('Output tokens:', usage.outputTokens);
114
+ console.log('Finish reason:', finishReason);
115
+
116
+ } catch (error) {
117
+ console.error('Error:', error);
118
+ throw error;
119
+ }
120
+ }
121
+
122
+ main().catch(console.error);
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Basic usage example for Claude Code AI SDK Provider
3
+ *
4
+ * This example demonstrates simple text generation with the provider
5
+ * and shows the metadata returned from each request.
6
+ */
7
+
8
+ import { streamText } from 'ai';
9
+ import { claudeCode } from '../dist/index.js';
10
+
11
+ async function main() {
12
+ try {
13
+ // Basic text generation - streamText returns immediately, not a promise
14
+ const result = streamText({
15
+ model: claudeCode('opus'),
16
+ prompt: 'Explain the concept of recursion in programming in 2-3 sentences.',
17
+ });
18
+
19
+ // Stream the response
20
+ console.log('Response:');
21
+ for await (const textPart of result.textStream) {
22
+ process.stdout.write(textPart);
23
+ }
24
+ console.log('\n');
25
+
26
+ // Get final results
27
+ const usage = await result.usage;
28
+ const providerMetadata = await result.providerMetadata;
29
+
30
+ console.log('\nToken usage:', usage);
31
+
32
+ // Display provider-specific metadata
33
+ const metadata = providerMetadata?.['claude-code'];
34
+ if (metadata) {
35
+ console.log('\nProvider metadata:');
36
+
37
+ // Session ID is assigned by the SDK for internal tracking
38
+ if (metadata.sessionId) {
39
+ console.log(`- Session ID: ${metadata.sessionId}`);
40
+ }
41
+
42
+ // Performance metrics
43
+ if (metadata.durationMs) {
44
+ console.log(`- Duration: ${metadata.durationMs}ms`);
45
+ }
46
+
47
+ // Cost information
48
+ if (typeof metadata.costUsd === 'number') {
49
+ console.log(`- Cost: ${metadata.costUsd.toFixed(4)}`);
50
+ console.log(' (Pro/Max subscribers: covered by subscription)');
51
+ }
52
+
53
+ // Raw usage breakdown (available in usage.raw in AI SDK v6 stable)
54
+ if (usage?.raw) {
55
+ console.log('- Raw usage:', JSON.stringify(usage.raw, null, 2));
56
+ }
57
+ }
58
+ } catch (error) {
59
+ console.error('Error:', error);
60
+ console.log('\n💡 Troubleshooting:');
61
+ console.log('1. Install Claude Code SDK: npm install -g @anthropic-ai/claude-code');
62
+ console.log('2. Authenticate: claude login');
63
+ console.log('3. Run check-cli.ts to verify setup');
64
+ }
65
+ }
66
+
67
+ main().catch(console.error);
68
+ // NOTE: Migrating to Claude Agent SDK:
69
+ // - System prompt is not applied by default
70
+ // - Filesystem settings (CLAUDE.md, settings.json) are not loaded by default
71
+ // To restore old behavior, set:
72
+ // systemPrompt: { type: 'preset', preset: 'claude_code' }
73
+ // settingSources: ['user', 'project', 'local']
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Check if the Claude Code SDK is properly installed and authenticated
3
+ * This example verifies the setup before running other examples
4
+ */
5
+
6
+ import { generateText } from 'ai';
7
+ import { createClaudeCode } from '../dist/index.js';
8
+
9
+ async function checkSetup() {
10
+ console.log('🔍 Checking Claude Code SDK setup...\n');
11
+
12
+ const claudeCode = createClaudeCode();
13
+
14
+ try {
15
+ // Try a simple generation to verify everything works
16
+ console.log('Testing SDK connection...');
17
+
18
+ const { text, usage } = await generateText({
19
+ model: claudeCode('opus'),
20
+ prompt: 'Say "Hello from Claude" and nothing else.',
21
+ });
22
+
23
+ console.log('✅ Claude Code SDK is working properly!');
24
+ console.log('Response:', text);
25
+ console.log('Tokens used:', usage.totalTokens);
26
+ console.log('\n🎉 You can run all the examples and integration tests!');
27
+ } catch (error: any) {
28
+ console.error('❌ Failed to connect to Claude Code');
29
+ console.error('Error:', error.message);
30
+
31
+ if (error.message?.includes('not found') || error.message?.includes('ENOENT')) {
32
+ console.log('\n💡 Make sure Claude Code SDK is installed:');
33
+ console.log(' npm install -g @anthropic-ai/claude-code');
34
+ } else if (error.message?.includes('authentication') || error.message?.includes('401')) {
35
+ console.log('\n🔐 Authentication required. Please run:');
36
+ console.log(' claude login');
37
+ } else {
38
+ console.log('\n🔧 Troubleshooting tips:');
39
+ console.log('1. Install Claude Code SDK: npm install -g @anthropic-ai/claude-code');
40
+ console.log('2. Authenticate: claude login');
41
+ console.log('3. Verify installation: claude --version');
42
+ }
43
+
44
+ process.exit(1);
45
+ }
46
+ }
47
+
48
+ checkSetup().catch((error) => {
49
+ console.error('Unexpected error:', error);
50
+ process.exit(1);
51
+ });
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Test conversation management with proper message history
3
+ */
4
+
5
+ import { generateText } from 'ai';
6
+ import { claudeCode } from '../dist/index.js';
7
+ // NOTE: Migrating to Claude Agent SDK:
8
+ // - System prompt is not applied by default
9
+ // - Filesystem settings (CLAUDE.md, settings.json) are not loaded by default
10
+ // To restore old behavior, set:
11
+ // systemPrompt: { type: 'preset', preset: 'claude_code' }
12
+ // settingSources: ['user', 'project', 'local']
13
+ import type { ModelMessage } from 'ai';
14
+
15
+ async function testConversation() {
16
+ console.log('🧪 Testing conversation with message history...');
17
+
18
+ const model = claudeCode('opus');
19
+ const messages: ModelMessage[] = [];
20
+
21
+ // First turn
22
+ console.log(`\n1️⃣ First turn...`);
23
+ messages.push({
24
+ role: 'user' as const,
25
+ content: "My name is Helen and I'm a data scientist. Remember this.",
26
+ });
27
+
28
+ const response1 = await generateText({
29
+ model,
30
+ messages,
31
+ });
32
+ console.log('Assistant:', response1.text);
33
+ messages.push({ role: 'assistant' as const, content: response1.text });
34
+
35
+ // Second turn - add to conversation
36
+ console.log(`\n2️⃣ Second turn...`);
37
+ messages.push({ role: 'user' as const, content: "What's my profession?" });
38
+
39
+ const response2 = await generateText({
40
+ model,
41
+ messages,
42
+ });
43
+ console.log('Assistant:', response2.text);
44
+
45
+ // Third turn - test memory
46
+ console.log(`\n3️⃣ Third turn...`);
47
+ messages.push({ role: 'assistant' as const, content: response2.text });
48
+ messages.push({ role: 'user' as const, content: 'And what was my name again?' });
49
+
50
+ const response3 = await generateText({
51
+ model,
52
+ messages,
53
+ });
54
+ console.log('Assistant:', response3.text);
55
+
56
+ // Check if context was maintained through message history
57
+ const contextMaintained = response3.text.toLowerCase().includes('helen');
58
+ console.log(`\n✅ Context maintained via message history:`, contextMaintained);
59
+ }
60
+
61
+ testConversation()
62
+ .then(() => {
63
+ console.log(`\n✅ Test completed`);
64
+ process.exit(0);
65
+ })
66
+ .catch((error) => {
67
+ console.error(`\n❌ Test failed:`, error);
68
+ process.exit(1);
69
+ });
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Custom configuration example for Claude Code AI SDK Provider
3
+ *
4
+ * This example shows how to configure the provider and models
5
+ * with specific settings for your use case.
6
+ */
7
+
8
+ import { generateText } from 'ai';
9
+ import { createClaudeCode } from '../dist/index.js';
10
+ // NOTE: Migrating to Claude Agent SDK:
11
+ // - System prompt is not applied by default
12
+ // - Filesystem settings (CLAUDE.md, settings.json) are not loaded by default
13
+ // To restore old behavior, set:
14
+ // systemPrompt: { type: 'preset', preset: 'claude_code' }
15
+ // settingSources: ['user', 'project', 'local']
16
+
17
+ async function main() {
18
+ console.log('🔧 Testing custom configurations...\n');
19
+
20
+ try {
21
+ // Example 1: Provider with default settings for all models
22
+ const customProvider = createClaudeCode({
23
+ defaultSettings: {
24
+ // Skip permission prompts for all operations
25
+ permissionMode: 'bypassPermissions',
26
+ // Set working directory for file operations
27
+ cwd: process.cwd(),
28
+ },
29
+ });
30
+
31
+ console.log('1️⃣ Using provider with default settings:');
32
+ const { text: response1 } = await generateText({
33
+ model: customProvider('opus'), // Uses default settings
34
+ prompt: 'What is the capital of France? Answer in one word.',
35
+ });
36
+ console.log('Response:', response1);
37
+
38
+ // Example 2: Override settings for specific model instance
39
+ console.log('\n2️⃣ Model with custom settings:');
40
+ const { text: response2 } = await generateText({
41
+ model: customProvider('opus', {
42
+ // These settings override the provider defaults
43
+ permissionMode: 'default', // Ask for permissions
44
+ maxTurns: 5, // Limit conversation turns
45
+ }),
46
+ prompt: 'Name three popular programming languages. Just list them.',
47
+ });
48
+ console.log('Response:', response2);
49
+
50
+ // Example 3: Using tool restrictions
51
+ console.log('\n3️⃣ Model with tool restrictions:');
52
+ const safeModel = customProvider('opus', {
53
+ // Only allow read operations
54
+ allowedTools: ['Read', 'LS', 'Grep', 'Glob'],
55
+ // Explicitly block write operations
56
+ disallowedTools: ['Write', 'Edit', 'Delete', 'Bash'],
57
+ });
58
+
59
+ const { text: response3 } = await generateText({
60
+ model: safeModel,
61
+ prompt: 'List the files in the current directory.',
62
+ });
63
+ console.log('Response:', response3);
64
+
65
+ // Example 4: Multiple model instances from same provider
66
+ console.log('\n4️⃣ Using multiple model instances:');
67
+ const opusModel1 = customProvider('opus');
68
+ const opusModel2 = customProvider('opus');
69
+
70
+ // Quick comparison
71
+ const prompt = 'Explain quantum computing in exactly 10 words.';
72
+
73
+ const { text: response4a } = await generateText({
74
+ model: opusModel1,
75
+ prompt,
76
+ });
77
+
78
+ const { text: response4b } = await generateText({
79
+ model: opusModel2,
80
+ prompt,
81
+ });
82
+
83
+ console.log('Instance 1:', response4a);
84
+ console.log('Instance 2:', response4b);
85
+ } catch (error) {
86
+ console.error('Error:', error);
87
+ }
88
+ }
89
+
90
+ main().catch(console.error);
@@ -0,0 +1,209 @@
1
+ #!/usr/bin/env tsx
2
+
3
+ /**
4
+ * Constrained Object Generation Examples
5
+ *
6
+ * Demonstrates validation constraints that the Claude Code CLI can enforce
7
+ * via constrained decoding: number ranges, simple regex patterns, array
8
+ * lengths, enums, and multipleOf.
9
+ *
10
+ * NOTE: Avoid Zod methods that produce unsupported JSON Schema annotations:
11
+ * .email(), .url(), .uuid(), .datetime() all emit `format` constraints that
12
+ * cause the Claude Code CLI to silently fall back to prose. Use .describe()
13
+ * with format hints instead, then validate client-side if strict format
14
+ * compliance is needed.
15
+ *
16
+ * Regex patterns WITHOUT lookaheads/lookbehinds work fine (e.g. /^\d{4}-\d{2}-\d{2}$/).
17
+ * Regex patterns WITH lookaheads ((?=...), (?!...)) cause silent fallback.
18
+ *
19
+ * See JSON_FIX.md for details.
20
+ */
21
+
22
+ import { createClaudeCode } from '../dist/index.js';
23
+ import { generateObject } from 'ai';
24
+ import { z } from 'zod';
25
+
26
+ const claudeCode = createClaudeCode();
27
+
28
+ console.log('=== Claude Code: Constrained Object Generation ===\n');
29
+
30
+ // ---------------------------------------------------------------------------
31
+ // Example 1: Number ranges and integer constraints
32
+ // ---------------------------------------------------------------------------
33
+ async function example1_numberConstraints() {
34
+ console.log('1. Number Ranges and Integer Constraints\n');
35
+
36
+ const { object } = await generateObject({
37
+ model: claudeCode('opus'),
38
+ schema: z.object({
39
+ character: z.object({
40
+ name: z.string().min(3).max(20).describe('Character name'),
41
+ level: z.number().int().min(1).max(100),
42
+ experience: z.number().int().min(0).max(1000000),
43
+ stats: z.object({
44
+ health: z.number().int().min(100).max(9999),
45
+ mana: z.number().int().min(0).max(9999),
46
+ strength: z.number().int().min(1).max(99),
47
+ defense: z.number().int().min(1).max(99),
48
+ speed: z.number().int().min(1).max(99),
49
+ luck: z.number().int().min(1).max(10).describe('Luck stat (1-10)'),
50
+ }),
51
+ inventory: z.object({
52
+ gold: z.number().int().min(0).max(999999),
53
+ items: z.number().int().min(0).max(50).describe('Number of items (max 50)'),
54
+ weight: z.number().min(0).max(100).describe('Inventory weight in kg'),
55
+ }),
56
+ position: z.object({
57
+ x: z.number().min(-1000).max(1000),
58
+ y: z.number().min(-1000).max(1000),
59
+ z: z.number().min(0).max(500).describe('Altitude'),
60
+ }),
61
+ }),
62
+ }),
63
+ prompt: 'Generate a level 45 warrior character with balanced stats and moderate inventory.',
64
+ });
65
+
66
+ console.log('Generated character:');
67
+ console.log(JSON.stringify(object, null, 2));
68
+ console.log();
69
+ }
70
+
71
+ // ---------------------------------------------------------------------------
72
+ // Example 2: String patterns, enums, and array constraints
73
+ // ---------------------------------------------------------------------------
74
+ async function example2_patternsAndArrays() {
75
+ console.log('2. String Patterns, Enums, and Array Constraints\n');
76
+
77
+ const { object } = await generateObject({
78
+ model: claudeCode('opus'),
79
+ schema: z.object({
80
+ registration: z.object({
81
+ // Simple regex (no lookaheads) — works with CLI constrained decoding
82
+ username: z
83
+ .string()
84
+ .min(3)
85
+ .max(20)
86
+ .regex(/^[a-zA-Z0-9_]+$/, 'Alphanumeric and underscore only'),
87
+ email: z.string().describe('Email address (e.g. user@example.com)'),
88
+ phone: z.string().regex(/^\+?[1-9]\d{1,14}$/, 'E.164 phone format'),
89
+ dateOfBirth: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, 'YYYY-MM-DD format'),
90
+ socialMedia: z.object({
91
+ twitter: z
92
+ .string()
93
+ .regex(/^@[a-zA-Z0-9_]{1,15}$/, 'Twitter handle format')
94
+ .optional(),
95
+ github: z
96
+ .string()
97
+ .describe('GitHub username (alphanumeric or hyphens, 1-39 characters)')
98
+ .optional(),
99
+ }),
100
+ preferences: z.object({
101
+ locale: z.string().regex(/^[a-z]{2}-[A-Z]{2}$/, 'Locale format like en-US'),
102
+ currency: z
103
+ .string()
104
+ .length(3)
105
+ .regex(/^[A-Z]{3}$/, 'ISO 4217 currency code'),
106
+ }),
107
+ }),
108
+ }),
109
+ prompt:
110
+ 'Generate a user registration for a software developer from San Francisco with a GitHub account.',
111
+ });
112
+
113
+ console.log('Generated registration:');
114
+ console.log(JSON.stringify(object, null, 2));
115
+ console.log();
116
+ }
117
+
118
+ // ---------------------------------------------------------------------------
119
+ // Example 3: Complex combined validations (invoice)
120
+ // ---------------------------------------------------------------------------
121
+ async function example3_complexCombined() {
122
+ console.log('3. Complex Combined Validations\n');
123
+
124
+ const { object } = await generateObject({
125
+ model: claudeCode('opus'),
126
+ schema: z.object({
127
+ invoice: z.object({
128
+ invoiceNumber: z.string().regex(/^INV-\d{4}-\d{6}$/, 'Format: INV-YYYY-XXXXXX'),
129
+ issueDate: z
130
+ .string()
131
+ .regex(/^\d{4}-\d{2}-\d{2}$/)
132
+ .describe('Issue date in YYYY-MM-DD format'),
133
+ dueDate: z
134
+ .string()
135
+ .regex(/^\d{4}-\d{2}-\d{2}$/)
136
+ .describe('Due date in YYYY-MM-DD format (after issue date)'),
137
+ status: z.enum(['draft', 'sent', 'paid', 'overdue', 'cancelled']),
138
+ client: z.object({
139
+ name: z.string().min(2).max(100),
140
+ taxId: z.string().regex(/^\d{2}-\d{7}$|^\d{3}-\d{2}-\d{4}$/, 'Tax ID format'),
141
+ email: z.string().describe('Client email address (e.g. billing@company.com)'),
142
+ address: z.object({
143
+ country: z
144
+ .string()
145
+ .length(2)
146
+ .regex(/^[A-Z]{2}$/, 'ISO country code'),
147
+ postalCode: z.string().min(3).max(10),
148
+ }),
149
+ }),
150
+ lineItems: z
151
+ .array(
152
+ z.object({
153
+ description: z.string().min(5).max(200),
154
+ quantity: z.number().positive().int().max(1000),
155
+ unitPrice: z.number().positive().multipleOf(0.01).max(10000),
156
+ taxRate: z.number().min(0).max(0.3).multipleOf(0.01),
157
+ discount: z.number().min(0).max(0.5).multipleOf(0.01).optional(),
158
+ })
159
+ )
160
+ .min(1)
161
+ .max(50),
162
+ payment: z.object({
163
+ terms: z.enum(['net-15', 'net-30', 'net-45', 'net-60', 'due-on-receipt']),
164
+ method: z.enum(['bank-transfer', 'credit-card', 'check', 'paypal', 'crypto']).optional(),
165
+ currency: z
166
+ .string()
167
+ .length(3)
168
+ .regex(/^[A-Z]{3}$/, 'ISO currency code'),
169
+ }),
170
+ totals: z.object({
171
+ subtotal: z.number().positive().multipleOf(0.01),
172
+ taxAmount: z.number().min(0).multipleOf(0.01),
173
+ discountAmount: z.number().min(0).multipleOf(0.01).optional(),
174
+ total: z.number().positive().multipleOf(0.01),
175
+ }),
176
+ }),
177
+ }),
178
+ prompt:
179
+ 'Generate an invoice for web development services with 3 line items, sent to a US company, due in 30 days. Use a recent issue date and set the due date 30 days later.',
180
+ });
181
+
182
+ console.log('Generated invoice:');
183
+ console.log(JSON.stringify(object, null, 2));
184
+ console.log();
185
+ }
186
+
187
+ // ---------------------------------------------------------------------------
188
+ // Main
189
+ // ---------------------------------------------------------------------------
190
+ async function main() {
191
+ try {
192
+ await example1_numberConstraints();
193
+ await example2_patternsAndArrays();
194
+ await example3_complexCombined();
195
+
196
+ console.log('All constraint examples completed!');
197
+ console.log('\nConstraint types demonstrated:');
198
+ console.log('- Number ranges with min/max/int/multipleOf');
199
+ console.log('- Simple regex patterns (no lookaheads)');
200
+ console.log('- String length constraints');
201
+ console.log('- Array length constraints (min/max)');
202
+ console.log('- Enums for fixed value sets');
203
+ console.log('- Complex combined validations');
204
+ } catch (error) {
205
+ console.error('Error:', error);
206
+ }
207
+ }
208
+
209
+ main().catch(console.error);