@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,150 @@
1
+ import { generateText, streamText } from 'ai';
2
+ import { generateObject } from 'ai';
3
+ import { claudeCode } from '../dist/index.js';
4
+ import { z } from 'zod';
5
+
6
+ /**
7
+ * Example: Provider Limitations and Unsupported Features
8
+ *
9
+ * This example explicitly demonstrates which AI SDK features are NOT supported
10
+ * by the Claude Code provider due to CLI limitations. It shows what happens
11
+ * when you try to use these features and suggests workarounds where possible.
12
+ */
13
+
14
+ async function main() {
15
+ console.log('🚧 Claude Code Provider Limitations\n');
16
+ console.log(
17
+ 'This example demonstrates features that are NOT supported by the Claude Code SDK.\n'
18
+ );
19
+
20
+ // 1. Parameters that are silently ignored
21
+ console.log('1. Parameters that are silently ignored:');
22
+ console.log(' The following AI SDK parameters have no effect with Claude Code SDK:\n');
23
+
24
+ try {
25
+ const { text, usage } = await generateText({
26
+ model: claudeCode('opus'),
27
+ prompt: 'Write exactly 5 words.',
28
+ // These parameters are part of the AI SDK spec but are ignored by Claude Code SDK
29
+ temperature: 0.1, // āŒ Ignored - CLI doesn't support temperature control
30
+ maxOutputTokens: 10, // āŒ Ignored - CLI doesn't support output length limits
31
+ topP: 0.9, // āŒ Ignored - CLI doesn't support nucleus sampling
32
+ topK: 50, // āŒ Ignored - CLI doesn't support top-k sampling
33
+ presencePenalty: 0.5, // āŒ Ignored - CLI doesn't support repetition penalties
34
+ frequencyPenalty: 0.5, // āŒ Ignored - CLI doesn't support repetition penalties
35
+ stopSequences: ['END'], // āŒ Ignored - CLI doesn't support custom stop sequences
36
+ seed: 12345, // āŒ Ignored - CLI doesn't support deterministic output
37
+ });
38
+
39
+ console.log(' Result:', text);
40
+ console.log(' Tokens used:', usage.totalTokens);
41
+ console.log(
42
+ '\n āš ļø Note: Despite setting maxTokens:10, the response used',
43
+ usage.totalTokens,
44
+ 'tokens'
45
+ );
46
+ console.log(' āš ļø All the above parameters were silently ignored by the CLI\n');
47
+ } catch (error) {
48
+ console.error(' Error:', error);
49
+ }
50
+
51
+ // 2. Object generation - native SDK support with caveats
52
+ console.log('2. Object generation (supported with native SDK, with caveats):');
53
+
54
+ const PersonSchema = z.object({
55
+ name: z.string(),
56
+ age: z.number(),
57
+ occupation: z.string(),
58
+ });
59
+
60
+ try {
61
+ console.log(' Attempting generateObject()...');
62
+ const { object } = await generateObject({
63
+ model: claudeCode('opus'),
64
+ schema: PersonSchema,
65
+ prompt: 'Generate a person who is a software developer',
66
+ });
67
+ console.log(' āœ… Object generated:', object);
68
+ console.log(' Note: Uses native SDK constrained decoding (outputFormat)');
69
+ console.log(' Schema compliance for supported JSON Schema features');
70
+ console.log(' Some constraints (e.g., format: "email"/"uri", complex regex) can');
71
+ console.log(' cause the CLI to fall back to prose with no structured_output.');
72
+ console.log(' See examples/structured-output-repro.ts for details.');
73
+ } catch (error: any) {
74
+ console.log(' āŒ Error:', error.message);
75
+ }
76
+
77
+ // 3. Tool/Function calling - not supported
78
+ console.log('\n3. Tool/Function calling:');
79
+ console.log(' āŒ Not supported - Claude Code SDK has no function calling capability');
80
+ console.log(' ā„¹ļø While MCP servers can be configured, they cannot control output format\n');
81
+
82
+ // 4. Image inputs - not supported
83
+ console.log('4. Image inputs:');
84
+ console.log(' āŒ Not supported - Claude Code SDK cannot process images');
85
+ console.log(' ā„¹ļø The supportsImageUrls property is set to false\n');
86
+
87
+ // 5. Streaming with unsupported parameters
88
+ console.log('5. Streaming with ignored parameters:');
89
+ try {
90
+ const { textStream } = streamText({
91
+ model: claudeCode('opus'),
92
+ prompt: 'Count to 3',
93
+ temperature: 0, // āŒ Still ignored in streaming mode
94
+ maxOutputTokens: 5, // āŒ Still ignored in streaming mode
95
+ });
96
+
97
+ console.log(' Streaming: ');
98
+ for await (const chunk of textStream) {
99
+ process.stdout.write(chunk);
100
+ }
101
+ console.log('\n āš ļø Parameters were ignored in streaming mode too\n');
102
+ } catch (error) {
103
+ console.error(' Error:', error);
104
+ }
105
+
106
+ // 6. Workarounds and recommendations
107
+ console.log('šŸ“ Workarounds and Recommendations:\n');
108
+ console.log('1. For temperature control:');
109
+ console.log(' - Adjust your prompts to be more specific');
110
+ console.log(' - Use phrases like "be creative" or "be precise"\n');
111
+
112
+ console.log('2. For output length control:');
113
+ console.log(' - Specify length in your prompt: "Write exactly 50 words"');
114
+ console.log(' - Use explicit instructions: "Keep your response brief"\n');
115
+
116
+ console.log('3. For structured output:');
117
+ console.log(' - āœ… Supported via native SDK constrained decoding (outputFormat)');
118
+ console.log(' - Use generateObject/streamObject with Zod schemas');
119
+ console.log(' - Prefer a simplified generation schema, then validate client-side');
120
+ console.log(' - See structured-output-repro.ts for known CLI limitations\n');
121
+
122
+ console.log('4. For deterministic output:');
123
+ console.log(' - Not possible with Claude Code SDK');
124
+ console.log(' - Each request will produce different results\n');
125
+
126
+ console.log('5. For function calling:');
127
+ console.log(' - Implement your own prompt-based routing');
128
+ console.log(" - Parse Claude's response to determine actions\n");
129
+
130
+ console.log('šŸ” Why these limitations exist:');
131
+ console.log('- Claude Code SDK/CLI is mainly designed for interactive coding assistance');
132
+ console.log("- It lacks the API's fine-grained control parameters");
133
+ console.log('- The provider accurately reflects what the CLI can do\n');
134
+
135
+ console.log('āœ… What DOES work well:');
136
+ console.log('- Basic text generation and streaming');
137
+ console.log('- Native structured outputs for supported schema features');
138
+ console.log('- Conversation context via message history');
139
+ console.log('- Custom timeouts and session management');
140
+ console.log('- Abort signals for cancellation');
141
+ console.log('- System messages for context setting');
142
+ }
143
+
144
+ main().catch(console.error);
145
+ // NOTE: Migrating to Claude Agent SDK:
146
+ // - System prompt is not applied by default
147
+ // - Filesystem settings (CLAUDE.md, settings.json) are not loaded by default
148
+ // To restore old behavior, set:
149
+ // systemPrompt: { type: 'preset', preset: 'claude_code' }
150
+ // settingSources: ['user', 'project', 'local']
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Custom Logger Example
3
+ *
4
+ * Run: npx tsx examples/logging-custom-logger.ts
5
+ *
6
+ * This example demonstrates how to integrate a custom logger with Claude Code.
7
+ * This is useful when you want to:
8
+ * - Route logs to an external logging service
9
+ * - Format logs in a specific way
10
+ * - Filter or transform log messages
11
+ * - Integrate with existing logging infrastructure
12
+ *
13
+ * Expected output:
14
+ * - Custom prefixed log messages (e.g., "[CUSTOM-DEBUG]")
15
+ * - All log levels when verbose: true
16
+ * - Full control over log formatting and routing
17
+ */
18
+
19
+ import { streamText } from 'ai';
20
+ import { claudeCode } from '../dist/index.js';
21
+ import type { Logger } from '../dist/index.js';
22
+
23
+ // Custom logger that prefixes each level and adds timestamps
24
+ const customLogger: Logger = {
25
+ debug: (message: string) => {
26
+ const timestamp = new Date().toISOString();
27
+ console.log(`[CUSTOM-DEBUG] ${timestamp} - ${message}`);
28
+ },
29
+ info: (message: string) => {
30
+ const timestamp = new Date().toISOString();
31
+ console.log(`[CUSTOM-INFO] ${timestamp} - ${message}`);
32
+ },
33
+ warn: (message: string) => {
34
+ const timestamp = new Date().toISOString();
35
+ console.warn(`[CUSTOM-WARN] ${timestamp} - ${message}`);
36
+ },
37
+ error: (message: string) => {
38
+ const timestamp = new Date().toISOString();
39
+ console.error(`[CUSTOM-ERROR] ${timestamp} - ${message}`);
40
+ },
41
+ };
42
+
43
+ async function main() {
44
+ console.log('=== Custom Logger Example ===\n');
45
+ console.log('This example shows how to integrate your own logging system.');
46
+ console.log('All logs will be prefixed with [CUSTOM-*] and include timestamps.\n');
47
+
48
+ try {
49
+ // Use custom logger with verbose mode enabled
50
+ const result = streamText({
51
+ model: claudeCode('opus', {
52
+ verbose: true, // Enable verbose logging to see debug/info
53
+ logger: customLogger, // Use our custom logger
54
+ }),
55
+ prompt: 'Say hello in 5 words',
56
+ });
57
+
58
+ // Stream the response
59
+ console.log('\nResponse:');
60
+ for await (const textPart of result.textStream) {
61
+ process.stdout.write(textPart);
62
+ }
63
+ console.log('\n');
64
+
65
+ // Get usage info
66
+ const usage = await result.usage;
67
+ console.log('Token usage:', usage);
68
+
69
+ console.log('\nāœ“ Custom logger successfully integrated!');
70
+ console.log(' All logs above are formatted with custom prefixes and timestamps');
71
+ console.log(' You can route these to any logging service (Datadog, Sentry, etc.)');
72
+ } catch (error) {
73
+ console.error('Error:', error);
74
+ console.log('\nšŸ’” Troubleshooting:');
75
+ console.log('1. Install Claude Code SDK: npm install -g @anthropic-ai/claude-code');
76
+ console.log('2. Authenticate: claude login');
77
+ console.log('3. Run check-cli.ts to verify setup');
78
+ }
79
+ }
80
+
81
+ main().catch(console.error);
82
+
83
+ // Example: Integration with popular logging libraries
84
+ console.log('\nšŸ“š Integration Examples:\n');
85
+ console.log('// Winston integration:');
86
+ console.log('const logger: Logger = {');
87
+ console.log(' debug: (msg) => winston.debug(msg),');
88
+ console.log(' info: (msg) => winston.info(msg),');
89
+ console.log(' warn: (msg) => winston.warn(msg),');
90
+ console.log(' error: (msg) => winston.error(msg),');
91
+ console.log('};\n');
92
+
93
+ console.log('// Pino integration:');
94
+ console.log('const logger: Logger = {');
95
+ console.log(' debug: (msg) => pino.debug(msg),');
96
+ console.log(' info: (msg) => pino.info(msg),');
97
+ console.log(' warn: (msg) => pino.warn(msg),');
98
+ console.log(' error: (msg) => pino.error(msg),');
99
+ console.log('};\n');
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Default Logging Example
3
+ *
4
+ * Run: npx tsx examples/logging-default.ts
5
+ *
6
+ * This example demonstrates the default logging behavior of Claude Code.
7
+ * By default, only warn and error messages are logged.
8
+ * Debug and info messages are suppressed unless verbose mode is enabled.
9
+ *
10
+ * Expected output:
11
+ * - No debug or info logs
12
+ * - Only warn/error logs if something goes wrong
13
+ * - Clean output focused on the actual response
14
+ */
15
+
16
+ import { streamText } from 'ai';
17
+ import { claudeCode } from '../dist/index.js';
18
+
19
+ async function main() {
20
+ console.log('=== Default Logging (Non-Verbose Mode) ===\n');
21
+ console.log('Expected behavior:');
22
+ console.log('- No debug or info logs');
23
+ console.log('- Only warn/error logs appear if needed');
24
+ console.log('- Clean output showing just the response\n');
25
+
26
+ try {
27
+ // Default logging - only warn/error messages will appear
28
+ const result = streamText({
29
+ model: claudeCode('opus'),
30
+ prompt: 'Say hello in 5 words',
31
+ });
32
+
33
+ // Stream the response
34
+ console.log('Response:');
35
+ for await (const textPart of result.textStream) {
36
+ process.stdout.write(textPart);
37
+ }
38
+ console.log('\n');
39
+
40
+ // Get usage info
41
+ const usage = await result.usage;
42
+ console.log('Token usage:', usage);
43
+
44
+ console.log('\nāœ“ Notice: No debug or info logs appeared above');
45
+ console.log(' This is the default behavior - only essential output is shown');
46
+ } catch (error) {
47
+ console.error('Error:', error);
48
+ console.log('\nšŸ’” Troubleshooting:');
49
+ console.log('1. Install Claude Code SDK: npm install -g @anthropic-ai/claude-code');
50
+ console.log('2. Authenticate: claude login');
51
+ console.log('3. Run check-cli.ts to verify setup');
52
+ }
53
+ }
54
+
55
+ main().catch(console.error);
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Disabled Logging Example
3
+ *
4
+ * Run: npx tsx examples/logging-disabled.ts
5
+ *
6
+ * This example demonstrates how to completely disable all logging.
7
+ * When logger: false is set, no logs will be emitted at all.
8
+ *
9
+ * Use this when:
10
+ * - You want completely silent operation
11
+ * - Logs might interfere with output processing
12
+ * - Running in production with external monitoring
13
+ * - You don't need any diagnostic information
14
+ *
15
+ * Expected output:
16
+ * - Zero log messages (no debug, info, warn, or error)
17
+ * - Only explicit console.log statements from your code
18
+ * - Completely silent provider operation
19
+ *
20
+ * āš ļø Warning: With logging disabled, you won't see:
21
+ * - Warning messages about misconfigurations
22
+ * - Error messages from the provider
23
+ * - Any diagnostic information
24
+ */
25
+
26
+ import { streamText } from 'ai';
27
+ import { claudeCode } from '../dist/index.js';
28
+
29
+ async function main() {
30
+ console.log('=== Logging Disabled Example ===\n');
31
+ console.log('Expected behavior:');
32
+ console.log('- No logs from the provider at all');
33
+ console.log('- Completely silent operation');
34
+ console.log('- Only application output is shown\n');
35
+
36
+ try {
37
+ // Disable all logging
38
+ const result = streamText({
39
+ model: claudeCode('opus', {
40
+ logger: false, // Disable all logging
41
+ }),
42
+ prompt: 'Say hello in 5 words',
43
+ });
44
+
45
+ // Stream the response
46
+ console.log('Response:');
47
+ for await (const textPart of result.textStream) {
48
+ process.stdout.write(textPart);
49
+ }
50
+ console.log('\n');
51
+
52
+ // Get usage info
53
+ const usage = await result.usage;
54
+ console.log('Token usage:', usage);
55
+
56
+ console.log('\nāœ“ Notice: Zero logs from the provider appeared above');
57
+ console.log(' The provider operated completely silently');
58
+ console.log(' Only our explicit console.log statements were shown');
59
+
60
+ console.log('\nāš ļø Important:');
61
+ console.log(" With logging disabled, you won't see warnings or errors");
62
+ console.log(' from the provider. Use this mode carefully!');
63
+ } catch (error) {
64
+ // Even with logging disabled, you can still catch and handle errors
65
+ console.error('Error:', error);
66
+ console.log('\nšŸ’” Troubleshooting:');
67
+ console.log('1. Install Claude Code SDK: npm install -g @anthropic-ai/claude-code');
68
+ console.log('2. Authenticate: claude login');
69
+ console.log('3. Run check-cli.ts to verify setup');
70
+ console.log('4. Try running without logger: false to see diagnostic logs');
71
+ }
72
+ }
73
+
74
+ main().catch(console.error);
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Verbose Logging Example
3
+ *
4
+ * Run: npx tsx examples/logging-verbose.ts
5
+ *
6
+ * This example demonstrates verbose logging mode.
7
+ * When verbose: true is set, you'll see detailed debug and info logs
8
+ * that help you understand what's happening under the hood.
9
+ *
10
+ * Expected output:
11
+ * - Debug logs showing detailed execution trace
12
+ * - Info logs about request/response flow
13
+ * - Warn/error logs if issues occur
14
+ * - Much more detailed output for troubleshooting
15
+ *
16
+ * Use verbose mode when:
17
+ * - Debugging issues
18
+ * - Understanding the provider's behavior
19
+ * - Developing and testing
20
+ */
21
+
22
+ import { streamText } from 'ai';
23
+ import { claudeCode } from '../dist/index.js';
24
+
25
+ async function main() {
26
+ console.log('=== Verbose Logging Mode ===\n');
27
+ console.log('Expected behavior:');
28
+ console.log('- Debug logs showing internal details');
29
+ console.log('- Info logs about execution flow');
30
+ console.log('- Full visibility into what the provider is doing\n');
31
+
32
+ try {
33
+ // Enable verbose logging to see debug and info messages
34
+ const result = streamText({
35
+ model: claudeCode('opus', {
36
+ verbose: true, // Enable verbose logging
37
+ }),
38
+ prompt: 'Say hello in 5 words',
39
+ });
40
+
41
+ // Stream the response
42
+ console.log('\nResponse:');
43
+ for await (const textPart of result.textStream) {
44
+ process.stdout.write(textPart);
45
+ }
46
+ console.log('\n');
47
+
48
+ // Get usage info
49
+ const usage = await result.usage;
50
+ console.log('Token usage:', usage);
51
+
52
+ console.log('\nāœ“ Notice: Debug and info logs appeared above');
53
+ console.log(' Verbose mode provides detailed execution information');
54
+ console.log(' This is helpful for development and troubleshooting');
55
+ } catch (error) {
56
+ console.error('Error:', error);
57
+ console.log('\nšŸ’” Troubleshooting:');
58
+ console.log('1. Install Claude Code SDK: npm install -g @anthropic-ai/claude-code');
59
+ console.log('2. Authenticate: claude login');
60
+ console.log('3. Run check-cli.ts to verify setup');
61
+ }
62
+ }
63
+
64
+ main().catch(console.error);
@@ -0,0 +1,179 @@
1
+ #!/usr/bin/env tsx
2
+
3
+ /**
4
+ * Example: Handling Long-Running Tasks
5
+ *
6
+ * Shows how to implement custom timeouts using AbortSignal
7
+ * for complex tasks that may take longer than usual.
8
+ */
9
+
10
+ import { generateText } from 'ai';
11
+ import { claudeCode } from '../../dist/index.js';
12
+ // NOTE: Migrating to Claude Agent SDK:
13
+ // - System prompt is not applied by default
14
+ // - Filesystem settings (CLAUDE.md, settings.json) are not loaded by default
15
+ // To restore old behavior, set:
16
+ // systemPrompt: { type: 'preset', preset: 'claude_code' }
17
+ // settingSources: ['user', 'project', 'local']
18
+
19
+ async function withTimeout() {
20
+ console.log('šŸ• Example 1: Custom timeout for long task\n');
21
+
22
+ // Create an AbortController with a 5-minute timeout
23
+ const controller = new AbortController();
24
+ const timeoutId = setTimeout(() => {
25
+ controller.abort(new Error('Request timeout after 5 minutes'));
26
+ }, 300000); // 5 minutes
27
+
28
+ try {
29
+ const { text } = await generateText({
30
+ model: claudeCode('opus'),
31
+ prompt: 'Analyze the implications of quantum computing on cryptography...',
32
+ abortSignal: controller.signal,
33
+ });
34
+
35
+ clearTimeout(timeoutId); // Clear timeout on success
36
+ console.log('Response:', text);
37
+ } catch (error: any) {
38
+ clearTimeout(timeoutId);
39
+
40
+ if (error.name === 'AbortError' || error.message?.includes('timeout')) {
41
+ console.log('āŒ Request timed out after 5 minutes');
42
+ console.log('Consider breaking the task into smaller parts');
43
+ } else {
44
+ console.error('Error:', error);
45
+ }
46
+ }
47
+ }
48
+
49
+ async function withUserCancellation() {
50
+ console.log('\nšŸ›‘ Example 2: User-cancellable request\n');
51
+
52
+ const controller = new AbortController();
53
+
54
+ // Simulate user cancellation after 2 seconds
55
+ setTimeout(() => {
56
+ console.log('User clicked cancel...');
57
+ controller.abort(new Error('User cancelled the request'));
58
+ }, 2000);
59
+
60
+ try {
61
+ console.log('Starting long task (will be cancelled in 2 seconds)...');
62
+
63
+ const { text } = await generateText({
64
+ model: claudeCode('opus'),
65
+ prompt: 'Write a comprehensive guide to machine learning...',
66
+ abortSignal: controller.signal,
67
+ });
68
+
69
+ console.log('Response:', text);
70
+ } catch (error: any) {
71
+ // Check for various abort/cancel error patterns
72
+ const isAborted =
73
+ error.name === 'AbortError' ||
74
+ error.message?.includes('cancelled') ||
75
+ error.message?.includes('aborted');
76
+
77
+ if (isAborted) {
78
+ console.log('āœ… Request successfully cancelled by user');
79
+ } else {
80
+ console.error('Error:', error);
81
+ }
82
+ }
83
+ }
84
+
85
+ async function withGracefulTimeout() {
86
+ console.log('\nā° Example 3: Graceful timeout with retry option\n');
87
+
88
+ async function attemptWithTimeout(timeoutMs: number) {
89
+ const controller = new AbortController();
90
+ const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
91
+
92
+ try {
93
+ const { text } = await generateText({
94
+ model: claudeCode('opus'),
95
+ prompt: 'Explain the theory of relativity',
96
+ abortSignal: controller.signal,
97
+ });
98
+
99
+ clearTimeout(timeoutId);
100
+ return { success: true, text };
101
+ } catch (error: any) {
102
+ clearTimeout(timeoutId);
103
+
104
+ if (error.name === 'AbortError') {
105
+ return { success: false, timeout: true };
106
+ }
107
+ throw error;
108
+ }
109
+ }
110
+
111
+ // Try with 30-second timeout first
112
+ console.log('Attempting with 30-second timeout...');
113
+ let result = await attemptWithTimeout(30000);
114
+
115
+ if (!result.success && result.timeout) {
116
+ console.log('ā±ļø First attempt timed out, trying with longer timeout...');
117
+
118
+ // Retry with 2-minute timeout
119
+ result = await attemptWithTimeout(120000);
120
+ }
121
+
122
+ if (result.success) {
123
+ console.log('āœ… Success!', result.text);
124
+ } else {
125
+ console.log('āŒ Failed even with extended timeout');
126
+ }
127
+ }
128
+
129
+ // Helper function for creating timeout controllers
130
+ function createTimeoutController(ms: number, reason = 'Request timeout'): AbortController {
131
+ const controller = new AbortController();
132
+ const timeoutId = setTimeout(() => {
133
+ controller.abort(new Error(`${reason} after ${ms}ms`));
134
+ }, ms);
135
+
136
+ // Add cleanup method
137
+ (controller as any).clearTimeout = () => clearTimeout(timeoutId);
138
+
139
+ return controller;
140
+ }
141
+
142
+ async function withHelper() {
143
+ console.log('\nšŸ”§ Example 4: Using timeout helper\n');
144
+
145
+ const controller = createTimeoutController(60000, 'Complex analysis timeout');
146
+
147
+ try {
148
+ const { text } = await generateText({
149
+ model: claudeCode('opus'),
150
+ prompt: 'Analyze this code for security vulnerabilities...',
151
+ abortSignal: controller.signal,
152
+ });
153
+
154
+ (controller as any).clearTimeout();
155
+ console.log('Analysis complete:', text);
156
+ } catch (error: any) {
157
+ console.error('Analysis failed:', error.message);
158
+ }
159
+ }
160
+
161
+ async function main() {
162
+ console.log('=== Long-Running Task Examples ===\n');
163
+ console.log('These examples show how to handle timeouts using AbortSignal');
164
+ console.log('following Vercel AI SDK patterns.\n');
165
+
166
+ await withTimeout();
167
+ await withUserCancellation();
168
+ await withGracefulTimeout();
169
+ await withHelper();
170
+
171
+ console.log('\nšŸ“ Key Takeaways:');
172
+ console.log('- Use AbortController for all cancellation needs');
173
+ console.log('- Set custom timeouts based on task complexity');
174
+ console.log('- Always clear timeouts on success');
175
+ console.log('- Consider retry logic for timeout scenarios');
176
+ console.log('- More complex tasks may need longer timeouts (5-10 minutes)');
177
+ }
178
+
179
+ main().catch(console.error);