@adcp/client 4.21.0 → 4.22.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 (160) hide show
  1. package/AGENTS.md +278 -0
  2. package/README.md +96 -61
  3. package/bin/adcp.js +342 -4
  4. package/dist/lib/agents/index.generated.d.ts +9 -1
  5. package/dist/lib/agents/index.generated.d.ts.map +1 -1
  6. package/dist/lib/agents/index.generated.js +12 -0
  7. package/dist/lib/agents/index.generated.js.map +1 -1
  8. package/dist/lib/core/AgentClient.d.ts.map +1 -1
  9. package/dist/lib/core/SingleAgentClient.d.ts +2 -1
  10. package/dist/lib/core/SingleAgentClient.d.ts.map +1 -1
  11. package/dist/lib/core/SingleAgentClient.js +10 -1
  12. package/dist/lib/core/SingleAgentClient.js.map +1 -1
  13. package/dist/lib/discovery/property-crawler.d.ts +4 -0
  14. package/dist/lib/discovery/property-crawler.d.ts.map +1 -1
  15. package/dist/lib/discovery/property-crawler.js +10 -2
  16. package/dist/lib/discovery/property-crawler.js.map +1 -1
  17. package/dist/lib/index.d.ts +4 -4
  18. package/dist/lib/index.d.ts.map +1 -1
  19. package/dist/lib/index.js +6 -4
  20. package/dist/lib/index.js.map +1 -1
  21. package/dist/lib/protocols/index.d.ts.map +1 -1
  22. package/dist/lib/protocols/index.js +8 -6
  23. package/dist/lib/protocols/index.js.map +1 -1
  24. package/dist/lib/protocols/mcp.d.ts.map +1 -1
  25. package/dist/lib/protocols/mcp.js +24 -11
  26. package/dist/lib/protocols/mcp.js.map +1 -1
  27. package/dist/lib/server/index.d.ts +2 -0
  28. package/dist/lib/server/index.d.ts.map +1 -1
  29. package/dist/lib/server/index.js +3 -1
  30. package/dist/lib/server/index.js.map +1 -1
  31. package/dist/lib/server/serve.d.ts +73 -0
  32. package/dist/lib/server/serve.d.ts.map +1 -0
  33. package/dist/lib/server/serve.js +94 -0
  34. package/dist/lib/server/serve.js.map +1 -0
  35. package/dist/lib/testing/client.d.ts.map +1 -1
  36. package/dist/lib/testing/client.js +1 -0
  37. package/dist/lib/testing/client.js.map +1 -1
  38. package/dist/lib/testing/compliance/comply.d.ts.map +1 -1
  39. package/dist/lib/testing/compliance/comply.js +48 -63
  40. package/dist/lib/testing/compliance/comply.js.map +1 -1
  41. package/dist/lib/testing/compliance/storyboard-tracks.d.ts +24 -0
  42. package/dist/lib/testing/compliance/storyboard-tracks.d.ts.map +1 -0
  43. package/dist/lib/testing/compliance/storyboard-tracks.js +157 -0
  44. package/dist/lib/testing/compliance/storyboard-tracks.js.map +1 -0
  45. package/dist/lib/testing/compliance/types.d.ts +1 -1
  46. package/dist/lib/testing/compliance/types.d.ts.map +1 -1
  47. package/dist/lib/testing/index.d.ts +1 -0
  48. package/dist/lib/testing/index.d.ts.map +1 -1
  49. package/dist/lib/testing/index.js +23 -1
  50. package/dist/lib/testing/index.js.map +1 -1
  51. package/dist/lib/testing/orchestrator.d.ts +8 -0
  52. package/dist/lib/testing/orchestrator.d.ts.map +1 -1
  53. package/dist/lib/testing/orchestrator.js +8 -0
  54. package/dist/lib/testing/orchestrator.js.map +1 -1
  55. package/dist/lib/testing/storyboard/context.d.ts +34 -0
  56. package/dist/lib/testing/storyboard/context.d.ts.map +1 -0
  57. package/dist/lib/testing/storyboard/context.js +257 -0
  58. package/dist/lib/testing/storyboard/context.js.map +1 -0
  59. package/dist/lib/testing/storyboard/index.d.ts +15 -0
  60. package/dist/lib/testing/storyboard/index.d.ts.map +1 -0
  61. package/dist/lib/testing/storyboard/index.js +48 -0
  62. package/dist/lib/testing/storyboard/index.js.map +1 -0
  63. package/dist/lib/testing/storyboard/loader.d.ts +53 -0
  64. package/dist/lib/testing/storyboard/loader.d.ts.map +1 -0
  65. package/dist/lib/testing/storyboard/loader.js +114 -0
  66. package/dist/lib/testing/storyboard/loader.js.map +1 -0
  67. package/dist/lib/testing/storyboard/path.d.ts +29 -0
  68. package/dist/lib/testing/storyboard/path.d.ts.map +1 -0
  69. package/dist/lib/testing/storyboard/path.js +121 -0
  70. package/dist/lib/testing/storyboard/path.js.map +1 -0
  71. package/dist/lib/testing/storyboard/request-builder.d.ts +28 -0
  72. package/dist/lib/testing/storyboard/request-builder.d.ts.map +1 -0
  73. package/dist/lib/testing/storyboard/request-builder.js +410 -0
  74. package/dist/lib/testing/storyboard/request-builder.js.map +1 -0
  75. package/dist/lib/testing/storyboard/runner.d.ts +24 -0
  76. package/dist/lib/testing/storyboard/runner.d.ts.map +1 -0
  77. package/dist/lib/testing/storyboard/runner.js +280 -0
  78. package/dist/lib/testing/storyboard/runner.js.map +1 -0
  79. package/dist/lib/testing/storyboard/task-map.d.ts +21 -0
  80. package/dist/lib/testing/storyboard/task-map.d.ts.map +1 -0
  81. package/dist/lib/testing/storyboard/task-map.js +84 -0
  82. package/dist/lib/testing/storyboard/task-map.js.map +1 -0
  83. package/dist/lib/testing/storyboard/types.d.ts +156 -0
  84. package/dist/lib/testing/storyboard/types.d.ts.map +1 -0
  85. package/dist/lib/testing/storyboard/types.js +10 -0
  86. package/dist/lib/testing/storyboard/types.js.map +1 -0
  87. package/dist/lib/testing/storyboard/validations.d.ts +17 -0
  88. package/dist/lib/testing/storyboard/validations.d.ts.map +1 -0
  89. package/dist/lib/testing/storyboard/validations.js +166 -0
  90. package/dist/lib/testing/storyboard/validations.js.map +1 -0
  91. package/dist/lib/testing/types.d.ts +2 -0
  92. package/dist/lib/testing/types.d.ts.map +1 -1
  93. package/dist/lib/types/core.generated.d.ts +2 -2
  94. package/dist/lib/types/core.generated.d.ts.map +1 -1
  95. package/dist/lib/types/core.generated.js +1 -1
  96. package/dist/lib/types/schemas.generated.d.ts +193 -34
  97. package/dist/lib/types/schemas.generated.d.ts.map +1 -1
  98. package/dist/lib/types/schemas.generated.js +87 -5
  99. package/dist/lib/types/schemas.generated.js.map +1 -1
  100. package/dist/lib/types/tools.generated.d.ts +280 -3
  101. package/dist/lib/types/tools.generated.d.ts.map +1 -1
  102. package/dist/lib/utils/response-schemas.d.ts.map +1 -1
  103. package/dist/lib/utils/response-schemas.js +34 -3
  104. package/dist/lib/utils/response-schemas.js.map +1 -1
  105. package/dist/lib/utils/validate-user-agent.d.ts +8 -0
  106. package/dist/lib/utils/validate-user-agent.d.ts.map +1 -0
  107. package/dist/lib/utils/validate-user-agent.js +15 -0
  108. package/dist/lib/utils/validate-user-agent.js.map +1 -0
  109. package/dist/lib/version.d.ts +6 -0
  110. package/dist/lib/version.d.ts.map +1 -1
  111. package/dist/lib/version.js +7 -1
  112. package/dist/lib/version.js.map +1 -1
  113. package/docs/README.md +42 -0
  114. package/docs/guides/BUILD-AN-AGENT.md +294 -0
  115. package/docs/llms.txt +634 -0
  116. package/examples/README.md +106 -0
  117. package/examples/adcp.config.json +30 -0
  118. package/examples/basic-a2a.ts +76 -0
  119. package/examples/basic-mcp.ts +50 -0
  120. package/examples/batch-preview-test.ts +266 -0
  121. package/examples/conversation-client.ts +291 -0
  122. package/examples/debug-preview-response.ts +73 -0
  123. package/examples/debug-preview-with-logging.ts +50 -0
  124. package/examples/easy-config-demo.ts +242 -0
  125. package/examples/env-config.ts +51 -0
  126. package/examples/error-compliant-server.ts +237 -0
  127. package/examples/generative-creative-demo.ts +205 -0
  128. package/examples/inspect-card-formats.ts +161 -0
  129. package/examples/logger-usage.ts +165 -0
  130. package/examples/oauth-cli-example.ts +154 -0
  131. package/examples/pr78-async-patterns-demo.ts +247 -0
  132. package/examples/signals-agent.ts +163 -0
  133. package/examples/simple-getting-started.ts +225 -0
  134. package/examples/simple-protocol-demo.ts +75 -0
  135. package/examples/test-helpers-demo.ts +239 -0
  136. package/examples/zod-validation-example.ts +126 -0
  137. package/package.json +12 -2
  138. package/skills/adcp/SKILL.md +13 -2
  139. package/storyboards/audience_sync.yaml +199 -0
  140. package/storyboards/behavioral_analysis.yaml +244 -0
  141. package/storyboards/brand_rights.yaml +131 -0
  142. package/storyboards/creative_ad_server.yaml +171 -0
  143. package/storyboards/creative_sales_agent.yaml +169 -0
  144. package/storyboards/creative_template.yaml +306 -0
  145. package/storyboards/deterministic_testing.yaml +925 -0
  146. package/storyboards/error_compliance.yaml +231 -0
  147. package/storyboards/governance_content_standards.yaml +213 -0
  148. package/storyboards/governance_property_lists.yaml +372 -0
  149. package/storyboards/media_buy_catalog_creative.yaml +457 -0
  150. package/storyboards/media_buy_governance_escalation.yaml +467 -0
  151. package/storyboards/media_buy_guaranteed_approval.yaml +396 -0
  152. package/storyboards/media_buy_non_guaranteed.yaml +288 -0
  153. package/storyboards/media_buy_proposal_mode.yaml +369 -0
  154. package/storyboards/media_buy_seller.yaml +560 -0
  155. package/storyboards/media_buy_state_machine.yaml +254 -0
  156. package/storyboards/schema.yaml +65 -0
  157. package/storyboards/schema_validation.yaml +166 -0
  158. package/storyboards/si_session.yaml +384 -0
  159. package/storyboards/signal_marketplace.yaml +283 -0
  160. package/storyboards/signal_owned.yaml +211 -0
@@ -0,0 +1,165 @@
1
+ /**
2
+ * Logger Usage Examples
3
+ *
4
+ * Demonstrates how to use the structured logger in AdCP Client
5
+ */
6
+
7
+ import { logger, createLogger } from '../src/lib/utils/logger';
8
+
9
+ // ====== BASIC USAGE ======
10
+
11
+ console.log('\n=== Basic Usage ===\n');
12
+
13
+ logger.debug('Debugging info (only visible if LOG_LEVEL=debug)');
14
+ logger.info('General information');
15
+ logger.warn('Warning message');
16
+ logger.error('Error message');
17
+
18
+ // ====== LOGGING WITH METADATA ======
19
+
20
+ console.log('\n=== Logging with Metadata ===\n');
21
+
22
+ logger.info('Task completed', {
23
+ taskId: 'task_123',
24
+ duration: 1250,
25
+ status: 'success',
26
+ });
27
+
28
+ logger.error('Connection failed', {
29
+ agentId: 'agent_xyz',
30
+ error: 'ECONNREFUSED',
31
+ retryCount: 3,
32
+ });
33
+
34
+ // ====== CONTEXT-AWARE LOGGING ======
35
+
36
+ console.log('\n=== Context-Aware Logging ===\n');
37
+
38
+ // Create protocol-specific logger
39
+ const mcpLogger = logger.child('MCP');
40
+ mcpLogger.info('Connecting to agent', { url: 'https://agent.example.com' });
41
+ mcpLogger.debug('Sending initialize request');
42
+
43
+ // Create nested context
44
+ const toolLogger = mcpLogger.child('get_products');
45
+ toolLogger.info('Calling tool', { params: { brief: 'Coffee products' } });
46
+ toolLogger.debug('Parsing response');
47
+
48
+ // ====== CUSTOM LOGGER INSTANCES ======
49
+
50
+ console.log('\n=== Custom Logger Instances ===\n');
51
+
52
+ // Create a debug-level logger for development
53
+ const devLogger = createLogger({
54
+ level: 'debug',
55
+ enabled: true,
56
+ });
57
+
58
+ devLogger.debug('This message is visible with debug level');
59
+ devLogger.info('Standard info message');
60
+
61
+ // Create a production logger (warn level only)
62
+ const prodLogger = createLogger({
63
+ level: 'warn',
64
+ enabled: true,
65
+ });
66
+
67
+ prodLogger.debug('This will NOT be logged');
68
+ prodLogger.info('This will NOT be logged');
69
+ prodLogger.warn('This WILL be logged');
70
+ prodLogger.error('This WILL be logged');
71
+
72
+ // ====== CUSTOM LOG HANDLERS ======
73
+
74
+ console.log('\n=== Custom Log Handlers ===\n');
75
+
76
+ // Example: Send logs to external service
77
+ const externalLogger = createLogger({
78
+ level: 'info',
79
+ handler: {
80
+ debug: (msg, meta) => console.log(`[EXT-DEBUG] ${msg}`, meta || ''),
81
+ info: (msg, meta) => console.log(`[EXT-INFO] ${msg}`, meta || ''),
82
+ warn: (msg, meta) => console.log(`[EXT-WARN] ${msg}`, meta || ''),
83
+ error: (msg, meta) => console.log(`[EXT-ERROR] ${msg}`, meta || ''),
84
+ },
85
+ });
86
+
87
+ externalLogger.info('Using custom handler', { service: 'external' });
88
+
89
+ // ====== RUNTIME CONFIGURATION ======
90
+
91
+ console.log('\n=== Runtime Configuration ===\n');
92
+
93
+ // Start with info level
94
+ logger.configure({ level: 'info' });
95
+ logger.debug('This will NOT be logged');
96
+ logger.info('This will be logged');
97
+
98
+ // Change to debug level
99
+ logger.configure({ level: 'debug' });
100
+ logger.debug('Now this WILL be logged');
101
+
102
+ // Disable logging temporarily
103
+ logger.configure({ enabled: false });
104
+ logger.error('This will NOT be logged (disabled)');
105
+
106
+ // Re-enable
107
+ logger.configure({ enabled: true });
108
+ logger.info('Logging re-enabled');
109
+
110
+ // ====== PRACTICAL EXAMPLES ======
111
+
112
+ console.log('\n=== Practical Examples ===\n');
113
+
114
+ // Example 1: Component-specific logging
115
+ class MediaBuyService {
116
+ private logger = logger.child('MediaBuyService');
117
+
118
+ async createMediaBuy(params: any) {
119
+ this.logger.info('Creating media buy', { params });
120
+
121
+ try {
122
+ // Simulate API call
123
+ this.logger.debug('Calling agent API');
124
+ // ...
125
+ this.logger.info('Media buy created', { buyId: 'mb_123' });
126
+ } catch (error) {
127
+ this.logger.error('Failed to create media buy', {
128
+ error: error instanceof Error ? error.message : String(error),
129
+ params,
130
+ });
131
+ throw error;
132
+ }
133
+ }
134
+ }
135
+
136
+ const service = new MediaBuyService();
137
+ service.createMediaBuy({ brief: 'Coffee campaign' });
138
+
139
+ // Example 2: Protocol client logging
140
+ class ProtocolClient {
141
+ private logger = logger.child('ProtocolClient');
142
+
143
+ async connect(protocol: string, url: string) {
144
+ const protocolLogger = this.logger.child(protocol.toUpperCase());
145
+
146
+ protocolLogger.info('Connecting to agent', { url });
147
+
148
+ try {
149
+ // Simulate connection
150
+ protocolLogger.debug('Sending initialize request');
151
+ protocolLogger.info('Connected successfully');
152
+ } catch (error) {
153
+ protocolLogger.error('Connection failed', {
154
+ url,
155
+ error: error instanceof Error ? error.message : String(error),
156
+ });
157
+ throw error;
158
+ }
159
+ }
160
+ }
161
+
162
+ const client = new ProtocolClient();
163
+ client.connect('mcp', 'https://agent.example.com');
164
+
165
+ console.log('\n=== Examples Complete ===\n');
@@ -0,0 +1,154 @@
1
+ /**
2
+ * Example: Using OAuth with the ADCP client
3
+ *
4
+ * OAuth tokens are stored directly in the AgentConfig,
5
+ * same place as static auth tokens.
6
+ */
7
+
8
+ import { Client as MCPClient } from '@modelcontextprotocol/sdk/client/index.js';
9
+ import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
10
+ import { UnauthorizedError } from '@modelcontextprotocol/sdk/client/auth.js';
11
+ import {
12
+ createCLIOAuthProvider,
13
+ hasValidOAuthTokens,
14
+ clearOAuthTokens,
15
+ getEffectiveAuthToken,
16
+ } from '../src/lib/auth/oauth';
17
+ import type { AgentConfig } from '../src/lib/types/adcp';
18
+
19
+ // Example: Agent configured for OAuth
20
+ const agent: AgentConfig = {
21
+ id: 'scope3-snapadcp',
22
+ name: 'Scope3 SnapAdCP',
23
+ agent_uri: process.argv[2] || 'https://snapadcp.scope3.com/mcp',
24
+ protocol: 'mcp',
25
+ // Static token alternative (uncomment to use instead of OAuth):
26
+ // auth_token: 'your-api-key-here',
27
+ //
28
+ // After OAuth flow completes, these fields are populated:
29
+ // oauth_tokens: { access_token: '...', refresh_token: '...' }
30
+ // oauth_client: { client_id: '...' }
31
+ };
32
+
33
+ async function main() {
34
+ console.log('ADCP OAuth Example');
35
+ console.log('==================');
36
+ console.log(`Agent: ${agent.name}`);
37
+ console.log(`URI: ${agent.agent_uri}`);
38
+ console.log(`Has OAuth tokens: ${hasValidOAuthTokens(agent)}`);
39
+ console.log(`Has static token: ${!!agent.auth_token}`);
40
+ console.log('');
41
+
42
+ // Create OAuth provider - tokens stored in agent config
43
+ const provider = createCLIOAuthProvider(agent);
44
+
45
+ // Create MCP client
46
+ const client = new MCPClient({
47
+ name: 'adcp-oauth-example',
48
+ version: '1.0.0',
49
+ });
50
+
51
+ // Helper to create transport with OAuth provider
52
+ const createTransport = () =>
53
+ new StreamableHTTPClientTransport(new URL(agent.agent_uri), {
54
+ authProvider: provider,
55
+ });
56
+
57
+ let transport = createTransport();
58
+
59
+ try {
60
+ console.log('Connecting...');
61
+ await client.connect(transport);
62
+ console.log('Connected!');
63
+ } catch (error) {
64
+ if (error instanceof UnauthorizedError) {
65
+ console.log('');
66
+ console.log('OAuth authorization required.');
67
+ console.log('Opening browser...');
68
+
69
+ try {
70
+ // Wait for user to complete OAuth in browser
71
+ const code = await provider.waitForCallback();
72
+ console.log('Authorization received!');
73
+
74
+ // Finish OAuth flow to exchange code for tokens
75
+ await transport.finishAuth(code);
76
+
77
+ // Show that tokens are now in agent config
78
+ console.log('');
79
+ console.log('OAuth tokens saved to agent config:');
80
+ console.log(` access_token: ${agent.oauth_tokens?.access_token ? '***' : 'none'}`);
81
+ console.log(` refresh_token: ${agent.oauth_tokens?.refresh_token ? '***' : 'none'}`);
82
+ console.log(` expires_at: ${agent.oauth_tokens?.expires_at || 'unknown'}`);
83
+
84
+ // Create new transport and reconnect (tokens are now available)
85
+ console.log('');
86
+ console.log('Reconnecting with tokens...');
87
+ transport = createTransport();
88
+ await client.connect(transport);
89
+ console.log('Connected!');
90
+ } catch (authError) {
91
+ console.error('OAuth failed:', authError);
92
+ await provider.cleanup();
93
+ process.exit(1);
94
+ }
95
+ } else {
96
+ console.error('Connection failed:', error);
97
+ await provider.cleanup();
98
+ process.exit(1);
99
+ }
100
+ }
101
+
102
+ // List available tools
103
+ try {
104
+ console.log('');
105
+ console.log('Listing tools...');
106
+ const result = await client.request({ method: 'tools/list', params: {} }, { tools: [] } as any);
107
+
108
+ console.log('Available tools:');
109
+ for (const tool of (result as any).tools || []) {
110
+ console.log(` - ${tool.name}`);
111
+ }
112
+ } catch (error) {
113
+ console.error('Failed to list tools:', error);
114
+ }
115
+
116
+ // Clean up
117
+ await provider.cleanup();
118
+ await client.close();
119
+
120
+ // Show final agent config (for saving to file/db)
121
+ console.log('');
122
+ console.log('Final agent config (save this to persist OAuth tokens):');
123
+ console.log(JSON.stringify(agent, null, 2));
124
+ }
125
+
126
+ // Utility: clear tokens and re-auth
127
+ async function clearAndReauth() {
128
+ console.log('Clearing OAuth tokens...');
129
+ clearOAuthTokens(agent);
130
+ console.log('Tokens cleared. Run again to re-authenticate.');
131
+ }
132
+
133
+ // Entry point
134
+ const command = process.argv[2];
135
+ if (command === '--clear') {
136
+ clearAndReauth();
137
+ } else if (command === '--help' || command === '-h') {
138
+ console.log(`
139
+ Usage: npx ts-node examples/oauth-cli-example.ts [options] [server-url]
140
+
141
+ Options:
142
+ <server-url> Connect to a specific MCP server (default: https://snapadcp.scope3.com/mcp)
143
+ --clear Clear OAuth tokens and exit
144
+ --help, -h Show this help
145
+
146
+ The OAuth flow:
147
+ 1. Browser opens for authorization
148
+ 2. User logs in and approves
149
+ 3. Tokens are saved to agent.oauth_tokens
150
+ 4. Save agent config to persist tokens for future use
151
+ `);
152
+ } else {
153
+ main().catch(console.error);
154
+ }
@@ -0,0 +1,247 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * PR #78 Async Patterns Demo
5
+ *
6
+ * Demonstrates the new handler-controlled async execution patterns
7
+ * that align with ADCP spec PR #78
8
+ */
9
+
10
+ import {
11
+ ADCPMultiAgentClient,
12
+ ADCP_STATUS,
13
+ autoApproveHandler,
14
+ deferAllHandler,
15
+ createFieldHandler,
16
+ InputRequiredError,
17
+ type TaskResult,
18
+ type DeferredContinuation,
19
+ type SubmittedContinuation,
20
+ } from '../src/lib/index';
21
+
22
+ async function main() {
23
+ console.log('šŸš€ PR #78 Async Patterns Demo\n');
24
+
25
+ // Example 1: Immediate completion (status: completed)
26
+ console.log('šŸ“‹ Example 1: Immediate Task Completion');
27
+ console.log('─'.repeat(50));
28
+
29
+ const client = ADCPMultiAgentClient.simple('https://demo.example.com', {
30
+ agentId: 'demo-agent',
31
+ agentName: 'Demo Agent',
32
+ protocol: 'mcp',
33
+ });
34
+
35
+ // Simulate immediate completion
36
+ console.log('• Calling getProducts with auto-approve handler...');
37
+ try {
38
+ // This would complete immediately if server returns status: 'completed'
39
+ const result = await simulateTaskResult('completed', {
40
+ products: ['Product A', 'Product B', 'Product C'],
41
+ });
42
+
43
+ console.log('āœ… Task completed immediately!');
44
+ console.log(` Status: ${result.status}`);
45
+ console.log(` Products: ${JSON.stringify(result.data?.products || [])}`);
46
+ } catch (error) {
47
+ console.log(`ā„¹ļø Note: ${error.message} (expected in demo)`);
48
+ }
49
+
50
+ console.log('\nšŸ“‹ Example 2: Working Status (keep connection open)');
51
+ console.log('─'.repeat(50));
52
+
53
+ // Simulate server processing (status: working)
54
+ console.log('• Server is processing (working status)...');
55
+ console.log('• Client keeps connection open for up to 120 seconds');
56
+ try {
57
+ const result = await simulateWorkingTask();
58
+ console.log('āœ… Task completed after server processing!');
59
+ console.log(` Status: ${result.status}`);
60
+ } catch (error) {
61
+ console.log(`ā„¹ļø Note: ${error.message} (expected in demo)`);
62
+ }
63
+
64
+ console.log('\nšŸ“‹ Example 3: Input Required with Handler');
65
+ console.log('─'.repeat(50));
66
+
67
+ // Handler provides input immediately
68
+ const fieldHandler = createFieldHandler({
69
+ budget: 50000,
70
+ targeting: ['US', 'CA'],
71
+ approval: true,
72
+ });
73
+
74
+ console.log('• Server needs input, handler provides it...');
75
+ try {
76
+ const result = await simulateInputRequired(fieldHandler);
77
+ console.log('āœ… Handler provided input, task continued!');
78
+ console.log(` Status: ${result.status}`);
79
+ } catch (error) {
80
+ console.log(`ā„¹ļø Note: ${error.message} (expected in demo)`);
81
+ }
82
+
83
+ console.log('\nšŸ“‹ Example 4: Input Required without Handler (ERROR)');
84
+ console.log('─'.repeat(50));
85
+
86
+ console.log('• Server needs input, but no handler provided...');
87
+ try {
88
+ const result = await simulateInputRequired(); // No handler
89
+ console.log('āŒ This should not happen');
90
+ } catch (error) {
91
+ if (error instanceof InputRequiredError) {
92
+ console.log('āœ… Correctly threw InputRequiredError!');
93
+ console.log(` Error: ${error.message}`);
94
+ } else {
95
+ console.log(`ā„¹ļø Note: ${error.message} (expected in demo)`);
96
+ }
97
+ }
98
+
99
+ console.log('\nšŸ“‹ Example 5: Client Deferral (Human-in-the-Loop)');
100
+ console.log('─'.repeat(50));
101
+
102
+ // Handler chooses to defer for human approval
103
+ const humanApprovalHandler = (context: any) => {
104
+ if (context.inputRequest.field === 'final_approval') {
105
+ console.log('• Handler choosing to defer for human approval...');
106
+ return { defer: true, token: `approval-${Date.now()}` };
107
+ }
108
+ return 'auto-approved';
109
+ };
110
+
111
+ try {
112
+ const result = await simulateClientDeferral(humanApprovalHandler);
113
+
114
+ if (result.status === 'deferred' && result.deferred) {
115
+ console.log('āœ… Task successfully deferred!');
116
+ console.log(` Token: ${result.deferred.token}`);
117
+ console.log(` Question: ${result.deferred.question}`);
118
+
119
+ // Later, when human provides input...
120
+ console.log('• Human provides approval, resuming task...');
121
+ const finalResult = await result.deferred.resume('APPROVED');
122
+ console.log('āœ… Task resumed and completed!');
123
+ console.log(` Final status: ${finalResult.status}`);
124
+ }
125
+ } catch (error) {
126
+ console.log(`ā„¹ļø Note: ${error.message} (expected in demo)`);
127
+ }
128
+
129
+ console.log('\nšŸ“‹ Example 6: Server Async (Submitted Status)');
130
+ console.log('─'.repeat(50));
131
+
132
+ // Server says task will take hours/days
133
+ console.log('• Server submitting long-running task...');
134
+ try {
135
+ const result = await simulateSubmittedTask();
136
+
137
+ if (result.status === 'submitted' && result.submitted) {
138
+ console.log('āœ… Task submitted for async processing!');
139
+ console.log(` Task ID: ${result.submitted.taskId}`);
140
+ console.log(` Webhook: ${result.submitted.webhookUrl || 'not provided'}`);
141
+
142
+ // User can track progress
143
+ console.log('• Tracking task progress...');
144
+ const status = await result.submitted.track();
145
+ console.log(` Current status: ${status.status}`);
146
+
147
+ // Or wait for completion (with polling)
148
+ console.log('• Waiting for completion (polling every 30s)...');
149
+ // In real usage: const final = await result.submitted.waitForCompletion(30000);
150
+ console.log(' (Would poll until completed)');
151
+ }
152
+ } catch (error) {
153
+ console.log(`ā„¹ļø Note: ${error.message} (expected in demo)`);
154
+ }
155
+
156
+ console.log('\nšŸŽÆ Key Takeaways:');
157
+ console.log('─'.repeat(50));
158
+ console.log('• āœ… Working status: Client keeps connection open (≤120s)');
159
+ console.log('• āœ… Input-required: Handler is MANDATORY');
160
+ console.log('• āœ… Client deferral: Handler returns { defer: true, token }');
161
+ console.log('• āœ… Server async: Returns { status: "submitted", submitted: { ... } }');
162
+ console.log('• āœ… Completed: Returns { success: true, data: ... }');
163
+ console.log('• āœ… No complex config needed - handler controls the flow!');
164
+
165
+ console.log('\nšŸŽ‰ Demo Complete!');
166
+ }
167
+
168
+ // Demo helper functions (simulate different response patterns)
169
+
170
+ async function simulateTaskResult(status: string, data: any): Promise<TaskResult<any>> {
171
+ // In real usage, this would be a real agent call
172
+ throw new Error('Demo simulation - would call real agent');
173
+ }
174
+
175
+ async function simulateWorkingTask(): Promise<TaskResult<any>> {
176
+ throw new Error('Demo simulation - would poll tasks/get endpoint');
177
+ }
178
+
179
+ async function simulateInputRequired(handler?: any): Promise<TaskResult<any>> {
180
+ if (!handler) {
181
+ throw new InputRequiredError('What is your budget for this campaign?');
182
+ }
183
+ throw new Error('Demo simulation - would call handler and continue');
184
+ }
185
+
186
+ async function simulateClientDeferral(handler: any): Promise<TaskResult<any>> {
187
+ // Simulate the handler being called and choosing to defer
188
+ const mockContext = {
189
+ inputRequest: {
190
+ field: 'final_approval',
191
+ question: 'Do you approve this $50,000 media buy?',
192
+ },
193
+ };
194
+
195
+ const response = handler(mockContext);
196
+
197
+ if (response.defer) {
198
+ return {
199
+ success: false,
200
+ status: 'deferred',
201
+ deferred: {
202
+ token: response.token,
203
+ question: mockContext.inputRequest.question,
204
+ resume: async (input: any) => {
205
+ console.log(` Resumed with input: ${input}`);
206
+ return {
207
+ success: true,
208
+ status: 'completed',
209
+ data: { approved: input === 'APPROVED' },
210
+ };
211
+ },
212
+ },
213
+ };
214
+ }
215
+
216
+ throw new Error('Demo simulation - handler did not defer');
217
+ }
218
+
219
+ async function simulateSubmittedTask(): Promise<TaskResult<any>> {
220
+ return {
221
+ success: false,
222
+ status: 'submitted',
223
+ submitted: {
224
+ taskId: `task-${Date.now()}`,
225
+ webhookUrl: 'https://yourapp.com/webhooks/adcp/xyz123',
226
+ track: async () => ({
227
+ taskId: `task-${Date.now()}`,
228
+ status: 'working',
229
+ taskType: 'create_media_buy',
230
+ createdAt: Date.now(),
231
+ updatedAt: Date.now(),
232
+ }),
233
+ waitForCompletion: async (pollInterval = 60000) => {
234
+ console.log(` Polling every ${pollInterval}ms...`);
235
+ return {
236
+ success: true,
237
+ status: 'completed',
238
+ data: { mediaBuyId: 'mb-12345' },
239
+ };
240
+ },
241
+ },
242
+ };
243
+ }
244
+
245
+ if (require.main === module) {
246
+ main().catch(console.error);
247
+ }