@datatamer.ai/agentdev 1.0.6 → 1.0.7

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,1382 @@
1
+ # API Integration Guide — Step-by-Step Playbook
2
+
3
+ A comprehensive guide for integrating new APIs into the agentdev platform, based on the LinkedIn integration process.
4
+
5
+ ## Overview
6
+
7
+ This guide provides a proven, repeatable process for integrating third-party APIs into agentdev. Follow these steps to add support for any OAuth-based API (Twitter, GitHub, Slack, etc.) or API-key-based services.
8
+
9
+ **Time Estimate:** 20-40 hours depending on API complexity
10
+ **Difficulty:** Medium to Advanced
11
+ **Prerequisites:** Node.js, ES modules, OAuth 2.0 knowledge
12
+
13
+ ---
14
+
15
+ ## Phase 1: Research & Planning (2-4 hours)
16
+
17
+ ### Step 1.1: API Research
18
+
19
+ **Objective:** Understand the API capabilities, limitations, and requirements.
20
+
21
+ **Tasks:**
22
+ 1. **Review API Documentation**
23
+ - Read official API docs thoroughly
24
+ - Identify API version (e.g., LinkedIn uses v2, Twitter uses v2)
25
+ - Note API base URL (e.g., `https://api.linkedin.com`)
26
+ - Document rate limits and quotas
27
+ - Understand authentication method (OAuth 2.0, API keys, etc.)
28
+
29
+ 2. **Identify Core Endpoints**
30
+ - List all available endpoints
31
+ - Categorize by functionality (e.g., posts, analytics, users)
32
+ - Note request/response formats
33
+ - Document required vs. optional parameters
34
+
35
+ 3. **Understand OAuth Scopes**
36
+ - List all available OAuth scopes
37
+ - Map scopes to features you want to implement
38
+ - Note scope dependencies (some scopes require others)
39
+ - Check for special permissions (e.g., LinkedIn org admin)
40
+
41
+ **Example (LinkedIn):**
42
+ ```
43
+ API Base: https://api.linkedin.com
44
+ Version: 202501
45
+ Auth: OAuth 2.0
46
+
47
+ Core Endpoints:
48
+ - POST /rest/posts - Create posts (scope: w_member_social)
49
+ - GET /rest/posts - List posts (scope: r_member_social)
50
+ - GET /rest/socialMetadata/{urn} - Get analytics (scope: r_member_social)
51
+ - GET /v2/connections - List connections (scope: r_1st_connections)
52
+
53
+ Rate Limits:
54
+ - 150 posts/day per user
55
+ - 100,000 API requests/day per app
56
+ ```
57
+
58
+ ### Step 1.2: Feature Prioritization
59
+
60
+ **Objective:** Decide what features to implement first.
61
+
62
+ **Process:**
63
+ 1. **List Potential Features**
64
+ - Write down all possible features
65
+ - Group by complexity (simple, medium, complex)
66
+ - Estimate implementation time for each
67
+
68
+ 2. **Create Implementation Phases**
69
+ - Phase 1: Quick wins (basic functionality)
70
+ - Phase 2: Medium features (analytics, advanced reads)
71
+ - Phase 3: Complex features (video uploads, webhooks)
72
+
73
+ 3. **Define MVP (Minimum Viable Product)**
74
+ - Choose 3-5 core features for initial release
75
+ - Ensure features provide immediate value
76
+ - Keep scope manageable (1-2 weeks max)
77
+
78
+ **Example (LinkedIn):**
79
+ ```
80
+ MVP Features (Week 1):
81
+ ✅ Create text posts
82
+ ✅ Create article posts (with URL)
83
+ ✅ Create image posts
84
+ ✅ View user profile
85
+ ✅ Check auth status
86
+
87
+ Phase 2 (Week 2):
88
+ ✅ Post management (list, view, edit, delete)
89
+ ✅ Analytics (stats, reactions, comments)
90
+ ✅ Connections management
91
+
92
+ Phase 3 (Week 3):
93
+ ✅ Organization pages
94
+ ✅ Video uploads
95
+ ❌ Messages API (requires special approval)
96
+ ```
97
+
98
+ ### Step 1.3: Create Implementation Plan
99
+
100
+ **Objective:** Document the implementation strategy.
101
+
102
+ **Create:** `IMPLEMENTATION_PLAN.md`
103
+
104
+ **Template:**
105
+ ```markdown
106
+ # [API Name] Integration Plan
107
+
108
+ ## Context
109
+ - Current state: [What exists now]
110
+ - Problem: [What's missing]
111
+ - Solution: [What we're building]
112
+
113
+ ## Features
114
+ ### Phase 1: MVP
115
+ - Feature 1: [Description]
116
+ - Feature 2: [Description]
117
+
118
+ ### Phase 2: Advanced
119
+ - Feature 3: [Description]
120
+
121
+ ## Technical Approach
122
+ - OAuth provider: [Name]
123
+ - Scopes needed: [List]
124
+ - API endpoints: [List]
125
+
126
+ ## Files to Create/Modify
127
+ - `/agentdev-webui/lib/[api].js` - OAuth handler
128
+ - `/packages/agentdev-client/src/[api]/api.js` - API client
129
+ - `/packages/agentdev-client/src/cli/[api].js` - CLI commands
130
+ - `/packages/agentdev-client/skills/agentdev-[api].md` - Documentation
131
+
132
+ ## Timeline
133
+ - Week 1: OAuth + Basic API
134
+ - Week 2: Advanced features
135
+ - Week 3: Testing + Documentation
136
+ ```
137
+
138
+ ---
139
+
140
+ ## Phase 2: OAuth Setup (3-5 hours)
141
+
142
+ ### Step 2.1: Register OAuth Application
143
+
144
+ **Objective:** Get OAuth credentials from the API provider.
145
+
146
+ **Tasks:**
147
+ 1. **Create Developer Account**
148
+ - Sign up for developer access
149
+ - Verify email/identity if required
150
+ - Accept developer terms
151
+
152
+ 2. **Create OAuth Application**
153
+ - Go to API provider's developer portal
154
+ - Create new app/project
155
+ - Fill in application details:
156
+ - Name: "AgentDev Integration"
157
+ - Description: "AI agent platform integration"
158
+ - Website: Your agentdev URL
159
+ - Redirect URI: `https://your-domain.com/api/auth/callback/[provider]`
160
+
161
+ 3. **Save Credentials**
162
+ - Copy Client ID
163
+ - Copy Client Secret
164
+ - Store securely (never commit to git)
165
+ - Add to password manager
166
+
167
+ **Example (LinkedIn):**
168
+ ```
169
+ Portal: https://www.linkedin.com/developers/apps
170
+ Redirect URI: https://agentdev.datatamer.ai/api/auth/callback/linkedin
171
+ Scopes: openid profile email w_member_social r_member_social...
172
+ ```
173
+
174
+ ### Step 2.2: Create Server-Side OAuth Handler
175
+
176
+ **Objective:** Implement OAuth flow in the backend.
177
+
178
+ **File:** `/agentdev-webui/lib/[api-name].js`
179
+
180
+ **Template:**
181
+ ```javascript
182
+ const db = require('./database');
183
+ const encryption = require('./encryption');
184
+
185
+ const AUTH_URL = 'https://provider.com/oauth/authorize';
186
+ const TOKEN_URL = 'https://provider.com/oauth/token';
187
+ const API_BASE = 'https://api.provider.com';
188
+ const SCOPES = 'scope1 scope2 scope3';
189
+
190
+ /**
191
+ * Build authorization URL
192
+ */
193
+ async function getAuthorizationUrl(state, redirectUri) {
194
+ const config = await db.getOAuthProviderConfig('[provider]');
195
+ if (!config || !config.client_id) {
196
+ throw new Error('[Provider] OAuth not configured');
197
+ }
198
+
199
+ const clientId = encryption.decrypt(config.client_id);
200
+ const params = new URLSearchParams({
201
+ response_type: 'code',
202
+ client_id: clientId,
203
+ redirect_uri: redirectUri,
204
+ state: state,
205
+ scope: SCOPES
206
+ });
207
+
208
+ return `${AUTH_URL}?${params.toString()}`;
209
+ }
210
+
211
+ /**
212
+ * Exchange authorization code for access token
213
+ */
214
+ async function exchangeCodeForToken(code, redirectUri) {
215
+ const config = await db.getOAuthProviderConfig('[provider]');
216
+ const clientId = encryption.decrypt(config.client_id);
217
+ const clientSecret = encryption.decrypt(config.client_secret);
218
+
219
+ const res = await fetch(TOKEN_URL, {
220
+ method: 'POST',
221
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
222
+ body: new URLSearchParams({
223
+ grant_type: 'authorization_code',
224
+ code,
225
+ redirect_uri: redirectUri,
226
+ client_id: clientId,
227
+ client_secret: clientSecret
228
+ }).toString()
229
+ });
230
+
231
+ if (!res.ok) {
232
+ const text = await res.text();
233
+ throw new Error(`Token exchange failed (${res.status}): ${text}`);
234
+ }
235
+
236
+ const data = await res.json();
237
+ return {
238
+ accessToken: data.access_token,
239
+ refreshToken: data.refresh_token || null,
240
+ expiresIn: data.expires_in
241
+ };
242
+ }
243
+
244
+ /**
245
+ * Refresh an expired access token
246
+ */
247
+ async function refreshAccessToken(refreshToken) {
248
+ const config = await db.getOAuthProviderConfig('[provider]');
249
+ const clientId = encryption.decrypt(config.client_id);
250
+ const clientSecret = encryption.decrypt(config.client_secret);
251
+
252
+ const res = await fetch(TOKEN_URL, {
253
+ method: 'POST',
254
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
255
+ body: new URLSearchParams({
256
+ grant_type: 'refresh_token',
257
+ refresh_token: refreshToken,
258
+ client_id: clientId,
259
+ client_secret: clientSecret
260
+ }).toString()
261
+ });
262
+
263
+ if (!res.ok) {
264
+ const text = await res.text();
265
+ throw new Error(`Token refresh failed (${res.status}): ${text}`);
266
+ }
267
+
268
+ const data = await res.json();
269
+ return {
270
+ accessToken: data.access_token,
271
+ refreshToken: data.refresh_token || refreshToken,
272
+ expiresIn: data.expires_in
273
+ };
274
+ }
275
+
276
+ /**
277
+ * Fetch user profile
278
+ */
279
+ async function fetchProfile(accessToken) {
280
+ const res = await fetch(`${API_BASE}/v1/user`, {
281
+ headers: {
282
+ 'Authorization': `Bearer ${accessToken}`
283
+ }
284
+ });
285
+
286
+ if (!res.ok) {
287
+ const text = await res.text();
288
+ throw new Error(`Profile fetch failed (${res.status}): ${text}`);
289
+ }
290
+
291
+ const data = await res.json();
292
+ return {
293
+ id: data.id,
294
+ name: data.name,
295
+ email: data.email,
296
+ picture: data.avatar_url
297
+ };
298
+ }
299
+
300
+ module.exports = {
301
+ getAuthorizationUrl,
302
+ exchangeCodeForToken,
303
+ refreshAccessToken,
304
+ fetchProfile,
305
+ AUTH_URL,
306
+ TOKEN_URL,
307
+ SCOPES
308
+ };
309
+ ```
310
+
311
+ ### Step 2.3: Configure OAuth in Admin Panel
312
+
313
+ **Objective:** Add OAuth credentials to database.
314
+
315
+ **Tasks:**
316
+ 1. **Access Admin Panel**
317
+ - Navigate to `/admin/oauth` (or create this page)
318
+ - Add new provider section
319
+
320
+ 2. **Add Provider Configuration**
321
+ ```sql
322
+ INSERT INTO oauth_providers (
323
+ provider_name,
324
+ client_id,
325
+ client_secret,
326
+ enabled
327
+ ) VALUES (
328
+ '[provider]',
329
+ '[encrypted_client_id]',
330
+ '[encrypted_client_secret]',
331
+ true
332
+ );
333
+ ```
334
+
335
+ 3. **Test OAuth Flow**
336
+ - Visit `/profile` page
337
+ - Click "Connect [Provider]"
338
+ - Complete authorization
339
+ - Verify token is saved
340
+
341
+ ---
342
+
343
+ ## Phase 3: API Client Implementation (8-12 hours)
344
+
345
+ ### Step 3.1: Create Modular API Structure
346
+
347
+ **Objective:** Build a well-organized API client.
348
+
349
+ **Directory Structure:**
350
+ ```
351
+ /packages/agentdev-client/src/[api-name]/
352
+ ├── api.js (re-export wrapper)
353
+ └── api/
354
+ ├── index.js (main entry point)
355
+ ├── core.js (HTTP client)
356
+ ├── [feature1].js (e.g., posts.js)
357
+ ├── [feature2].js (e.g., analytics.js)
358
+ └── [feature3].js (e.g., users.js)
359
+ ```
360
+
361
+ ### Step 3.2: Create Core HTTP Client
362
+
363
+ **File:** `/packages/agentdev-client/src/[api]/api/core.js`
364
+
365
+ **Template:**
366
+ ```javascript
367
+ /**
368
+ * [API Name] API Core - Base HTTP client and utilities
369
+ */
370
+
371
+ export const API_BASE = 'https://api.provider.com';
372
+ export const API_VERSION = 'v1';
373
+
374
+ /**
375
+ * Core REST API helper
376
+ * Handles authentication, error responses, and standard headers
377
+ */
378
+ export async function apiRequest(method, path, token, body = null, extraHeaders = {}) {
379
+ const opts = {
380
+ method,
381
+ headers: {
382
+ 'Authorization': `Bearer ${token}`,
383
+ 'Accept': 'application/json',
384
+ ...extraHeaders
385
+ }
386
+ };
387
+
388
+ if (body) {
389
+ opts.headers['Content-Type'] = 'application/json';
390
+ opts.body = JSON.stringify(body);
391
+ }
392
+
393
+ const res = await fetch(`${API_BASE}${path}`, opts);
394
+
395
+ if (!res.ok) {
396
+ const text = await res.text();
397
+
398
+ // Handle token expiration
399
+ if (res.status === 401) {
400
+ throw new Error('TOKEN_EXPIRED');
401
+ }
402
+
403
+ // Handle rate limiting
404
+ if (res.status === 429) {
405
+ const retryAfter = res.headers.get('Retry-After');
406
+ throw new Error(`API rate limit exceeded. Retry after: ${retryAfter || 'unknown'}`);
407
+ }
408
+
409
+ // Handle forbidden
410
+ if (res.status === 403) {
411
+ throw new Error('Insufficient permissions. Check OAuth scopes.');
412
+ }
413
+
414
+ throw new Error(`API ${method} ${path} failed (${res.status}): ${text}`);
415
+ }
416
+
417
+ // Handle No Content responses
418
+ if (res.status === 204) {
419
+ return { success: true };
420
+ }
421
+
422
+ // Handle Created responses
423
+ if (res.status === 201) {
424
+ const location = res.headers.get('Location');
425
+ if (location) {
426
+ return { id: location, success: true };
427
+ }
428
+ }
429
+
430
+ return res.json();
431
+ }
432
+
433
+ /**
434
+ * Resolve token from CLI argument or environment variable
435
+ */
436
+ export function resolveToken(cliToken) {
437
+ return cliToken || process.env.[PROVIDER]_TOKEN || null;
438
+ }
439
+ ```
440
+
441
+ ### Step 3.3: Implement Feature Modules
442
+
443
+ **Pattern:** One module per feature category
444
+
445
+ **Example - Posts Module:**
446
+
447
+ **File:** `/packages/agentdev-client/src/[api]/api/posts.js`
448
+
449
+ ```javascript
450
+ /**
451
+ * [API Name] - Posts Operations
452
+ */
453
+
454
+ import { apiRequest } from './core.js';
455
+
456
+ /**
457
+ * Create a text post
458
+ */
459
+ export async function createPost(token, text, options = {}) {
460
+ const body = {
461
+ text: text,
462
+ visibility: options.visibility || 'public'
463
+ };
464
+
465
+ return apiRequest('POST', '/v1/posts', token, body);
466
+ }
467
+
468
+ /**
469
+ * List user's posts
470
+ */
471
+ export async function listPosts(token, userId, options = {}) {
472
+ const params = new URLSearchParams({
473
+ user_id: userId,
474
+ limit: options.limit || 10,
475
+ offset: options.offset || 0
476
+ });
477
+
478
+ return apiRequest('GET', `/v1/posts?${params}`, token);
479
+ }
480
+
481
+ /**
482
+ * Get post details
483
+ */
484
+ export async function getPost(token, postId) {
485
+ return apiRequest('GET', `/v1/posts/${postId}`, token);
486
+ }
487
+
488
+ /**
489
+ * Delete a post
490
+ */
491
+ export async function deletePost(token, postId) {
492
+ return apiRequest('DELETE', `/v1/posts/${postId}`, token);
493
+ }
494
+
495
+ /**
496
+ * Update a post
497
+ */
498
+ export async function updatePost(token, postId, updates) {
499
+ return apiRequest('PATCH', `/v1/posts/${postId}`, token, updates);
500
+ }
501
+ ```
502
+
503
+ ### Step 3.4: Create Main Index
504
+
505
+ **File:** `/packages/agentdev-client/src/[api]/api/index.js`
506
+
507
+ ```javascript
508
+ /**
509
+ * [API Name] - Main Entry Point
510
+ * Re-exports all API functions from modular structure
511
+ */
512
+
513
+ // Core utilities
514
+ export { apiRequest, resolveToken, API_BASE, API_VERSION } from './core.js';
515
+
516
+ // Feature modules
517
+ export {
518
+ createPost,
519
+ listPosts,
520
+ getPost,
521
+ deletePost,
522
+ updatePost
523
+ } from './posts.js';
524
+
525
+ export {
526
+ getUserProfile,
527
+ updateUserProfile
528
+ } from './users.js';
529
+
530
+ // Add more exports as you create modules
531
+ ```
532
+
533
+ ### Step 3.5: Create Re-export Wrapper
534
+
535
+ **File:** `/packages/agentdev-client/src/[api]/api.js`
536
+
537
+ ```javascript
538
+ /**
539
+ * [API Name] REST API module (ESM)
540
+ * Provides programmatic access to [Provider] APIs for agents.
541
+ *
542
+ * This file maintains backward compatibility by re-exporting
543
+ * from the modular structure in ./api/
544
+ */
545
+
546
+ export * from './api/index.js';
547
+ ```
548
+
549
+ ---
550
+
551
+ ## Phase 4: CLI Commands Implementation (6-10 hours)
552
+
553
+ ### Step 4.1: Create Modular CLI Structure
554
+
555
+ **Directory Structure:**
556
+ ```
557
+ /packages/agentdev-client/src/cli/[api-name]/
558
+ ├── index.js (main registration)
559
+ ├── helpers.js (shared utilities)
560
+ ├── [feature1].js (e.g., posts.js)
561
+ ├── [feature2].js (e.g., analytics.js)
562
+ └── [feature3].js (e.g., users.js)
563
+ ```
564
+
565
+ ### Step 4.2: Create CLI Helpers
566
+
567
+ **File:** `/packages/agentdev-client/src/cli/[api]/helpers.js`
568
+
569
+ ```javascript
570
+ /**
571
+ * [API Name] CLI - Shared Helpers
572
+ */
573
+
574
+ import chalk from 'chalk';
575
+ import { getConfig } from '../../config/config.js';
576
+
577
+ /**
578
+ * Fetch [Provider] access token from server OAuth endpoint
579
+ */
580
+ export async function getProviderToken() {
581
+ const config = getConfig();
582
+ const apiUrl = config.apiUrl || 'https://agentdev.datatamer.ai';
583
+ const agentToken = config.token;
584
+
585
+ if (!agentToken) {
586
+ throw new Error('Agent not registered. Run "agentdev register" first.');
587
+ }
588
+
589
+ try {
590
+ const res = await fetch(`${apiUrl}/api/agent/oauth?provider=[provider]`, {
591
+ headers: {
592
+ 'Authorization': `Bearer ${agentToken}`,
593
+ 'Content-Type': 'application/json'
594
+ }
595
+ });
596
+
597
+ if (!res.ok) {
598
+ if (res.status === 404) {
599
+ throw new Error('[Provider] not connected. Connect at ' + apiUrl + '/profile');
600
+ }
601
+ const text = await res.text();
602
+ throw new Error(`Failed to fetch token (${res.status}): ${text}`);
603
+ }
604
+
605
+ const data = await res.json();
606
+ return data.[provider].access_token;
607
+ } catch (error) {
608
+ if (error.message.includes('not connected')) {
609
+ throw error;
610
+ }
611
+ throw new Error(`Failed to fetch token: ${error.message}`);
612
+ }
613
+ }
614
+
615
+ /**
616
+ * Centralized error handler
617
+ */
618
+ export function handleProviderError(error) {
619
+ if (error.message === 'TOKEN_EXPIRED') {
620
+ console.error(chalk.red('✗ Token expired. Please reconnect at /profile'));
621
+ } else if (error.message.includes('not connected')) {
622
+ console.error(chalk.red('✗ ' + error.message));
623
+ } else if (error.message.includes('rate limit')) {
624
+ console.error(chalk.red('✗ ' + error.message));
625
+ } else if (error.message.includes('permissions')) {
626
+ console.error(chalk.red('✗ ' + error.message));
627
+ console.error(chalk.yellow('Please reconnect to grant new permissions'));
628
+ } else {
629
+ console.error(chalk.red('✗ Operation failed:'), error.message);
630
+ }
631
+ process.exit(1);
632
+ }
633
+ ```
634
+
635
+ ### Step 4.3: Create Feature Command Handlers
636
+
637
+ **File:** `/packages/agentdev-client/src/cli/[api]/posts.js`
638
+
639
+ ```javascript
640
+ /**
641
+ * [API Name] CLI - Post Commands
642
+ */
643
+
644
+ import chalk from 'chalk';
645
+ import {
646
+ resolveToken,
647
+ createPost,
648
+ listPosts,
649
+ getPost,
650
+ deletePost,
651
+ updatePost
652
+ } from '../../[api]/api.js';
653
+ import { getProviderToken, handleProviderError } from './helpers.js';
654
+
655
+ /**
656
+ * Handle post creation
657
+ */
658
+ export async function handlePostCreate(opts) {
659
+ try {
660
+ const token = resolveToken() || await getProviderToken();
661
+
662
+ const result = await createPost(token, opts.text, {
663
+ visibility: opts.visibility || 'public'
664
+ });
665
+
666
+ console.log(chalk.green('✓ Post created successfully'));
667
+ if (result.id) {
668
+ console.log(chalk.gray(`Post ID: ${result.id}`));
669
+ }
670
+ } catch (error) {
671
+ handleProviderError(error);
672
+ }
673
+ }
674
+
675
+ /**
676
+ * Handle post listing
677
+ */
678
+ export async function handlePostList(opts) {
679
+ try {
680
+ const token = resolveToken() || await getProviderToken();
681
+
682
+ const result = await listPosts(token, opts.userId, {
683
+ limit: opts.limit || 10
684
+ });
685
+
686
+ if (!result.posts || result.posts.length === 0) {
687
+ console.log(chalk.yellow('No posts found'));
688
+ return;
689
+ }
690
+
691
+ console.log(chalk.bold(`\nPosts (${result.posts.length} shown)`));
692
+ console.log(chalk.gray('─'.repeat(80)));
693
+
694
+ result.posts.forEach((post, index) => {
695
+ console.log(`${chalk.cyan(`${index + 1}.`)} ${post.text.substring(0, 100)}...`);
696
+ console.log(` ${chalk.gray('ID:')} ${post.id}`);
697
+ console.log();
698
+ });
699
+
700
+ console.log(chalk.gray('─'.repeat(80)));
701
+ } catch (error) {
702
+ handleProviderError(error);
703
+ }
704
+ }
705
+
706
+ /**
707
+ * Handle post deletion
708
+ */
709
+ export async function handlePostDelete(postId, opts) {
710
+ try {
711
+ const token = resolveToken() || await getProviderToken();
712
+
713
+ if (!opts.confirm) {
714
+ console.log(chalk.yellow('⚠ Add --confirm flag to proceed'));
715
+ process.exit(0);
716
+ }
717
+
718
+ await deletePost(token, postId);
719
+ console.log(chalk.green('✓ Post deleted successfully'));
720
+ } catch (error) {
721
+ handleProviderError(error);
722
+ }
723
+ }
724
+
725
+ /**
726
+ * Register post commands
727
+ */
728
+ export function registerPostCommands(api) {
729
+ const post = api
730
+ .command('post')
731
+ .description('[Provider] post operations');
732
+
733
+ post
734
+ .command('create')
735
+ .description('Create a post')
736
+ .requiredOption('--text <text>', 'Post text')
737
+ .option('--visibility <type>', 'Visibility: public or private', 'public')
738
+ .action(handlePostCreate);
739
+
740
+ post
741
+ .command('list')
742
+ .description('List posts')
743
+ .option('--user-id <id>', 'User ID')
744
+ .option('--limit <number>', 'Number of posts', '10')
745
+ .action(handlePostList);
746
+
747
+ post
748
+ .command('delete <post-id>')
749
+ .description('Delete a post')
750
+ .option('--confirm', 'Confirm deletion')
751
+ .action(handlePostDelete);
752
+ }
753
+ ```
754
+
755
+ ### Step 4.4: Create Main CLI Index
756
+
757
+ **File:** `/packages/agentdev-client/src/cli/[api]/index.js`
758
+
759
+ ```javascript
760
+ /**
761
+ * [API Name] CLI - Main Entry Point
762
+ */
763
+
764
+ import { registerPostCommands } from './posts.js';
765
+ import { registerUserCommands } from './users.js';
766
+ // Import other command modules
767
+
768
+ /**
769
+ * Register [Provider] command group with Commander
770
+ */
771
+ export function register[Provider]Command(program) {
772
+ const api = program
773
+ .command('[provider]')
774
+ .description('[Provider] operations');
775
+
776
+ // Register all command groups
777
+ registerPostCommands(api);
778
+ registerUserCommands(api);
779
+ // Register other command groups
780
+
781
+ return api;
782
+ }
783
+ ```
784
+
785
+ ### Step 4.5: Create CLI Re-export Wrapper
786
+
787
+ **File:** `/packages/agentdev-client/src/cli/[api].js`
788
+
789
+ ```javascript
790
+ /**
791
+ * `agentdev [provider]` subcommand group
792
+ *
793
+ * This file maintains backward compatibility by re-exporting
794
+ * from the modular structure in ./[api]/
795
+ */
796
+
797
+ export { register[Provider]Command } from './[api]/index.js';
798
+ ```
799
+
800
+ ---
801
+
802
+ ## Phase 5: Skill Documentation (2-4 hours)
803
+
804
+ ### Step 5.1: Create Skill File
805
+
806
+ **File:** `/packages/agentdev-client/skills/agentdev-[provider].md`
807
+
808
+ **Template:**
809
+ ```markdown
810
+ # agentdev [provider] — [Provider] CLI
811
+
812
+ Use `agentdev [provider]` for ALL [Provider] operations. Do NOT attempt to use [Provider] APIs directly.
813
+
814
+ ## Prerequisites
815
+
816
+ User must connect their [Provider] account first:
817
+ 1. Visit /profile page on AgentDev
818
+ 2. Click "Connect [Provider]"
819
+ 3. Complete OAuth authorization flow
820
+
821
+ If [Provider] is not connected, all commands will fail with instructions to connect.
822
+
823
+ ## Commands
824
+
825
+ ### Create Post
826
+
827
+ ```bash
828
+ agentdev [provider] post create --text "Hello world!"
829
+ ```
830
+
831
+ ### List Posts
832
+
833
+ ```bash
834
+ agentdev [provider] post list --limit 10
835
+ ```
836
+
837
+ ### Delete Post
838
+
839
+ ```bash
840
+ agentdev [provider] post delete <post-id> --confirm
841
+ ```
842
+
843
+ ## Rate Limits
844
+
845
+ - **[X] requests per hour** per user
846
+ - **[Y] posts per day** per user
847
+
848
+ If rate limit is exceeded, you'll receive a clear error message.
849
+
850
+ ## Error Handling
851
+
852
+ | Error | Meaning | Action |
853
+ |-------|---------|--------|
854
+ | "[Provider] not connected" | User hasn't connected account | Direct user to /profile |
855
+ | "Token expired" | OAuth token expired | User must reconnect at /profile |
856
+ | "Rate limit exceeded" | Hit API rate limits | Wait for retry period |
857
+
858
+ ## Agent Task Examples
859
+
860
+ ### Example 1: Post update
861
+
862
+ When asked to "post to [Provider] about completing task":
863
+
864
+ ```bash
865
+ agentdev [provider] post create --text "✅ Completed task #123"
866
+ ```
867
+
868
+ ### Example 2: Check recent posts
869
+
870
+ When asked to "show my recent [Provider] posts":
871
+
872
+ ```bash
873
+ agentdev [provider] post list --limit 5
874
+ ```
875
+
876
+ ## Required OAuth Scopes
877
+
878
+ The following scopes are automatically requested during OAuth flow:
879
+ - `scope1` - Description
880
+ - `scope2` - Description
881
+ - `scope3` - Description
882
+
883
+ ## Notes
884
+
885
+ - All posts are created as the authenticated user
886
+ - Post IDs are returned on successful creation
887
+ - Token refresh is handled automatically
888
+ ```
889
+
890
+ ---
891
+
892
+ ## Phase 6: Testing & Validation (4-6 hours)
893
+
894
+ ### Step 6.1: Manual Testing Checklist
895
+
896
+ **OAuth Flow:**
897
+ - [ ] Visit /profile page
898
+ - [ ] Click "Connect [Provider]"
899
+ - [ ] Complete authorization
900
+ - [ ] Verify token is saved in database
901
+ - [ ] Verify token works for API calls
902
+
903
+ **CLI Commands:**
904
+ - [ ] Test `agentdev [provider] auth` - Check connection status
905
+ - [ ] Test `agentdev [provider] post create --text "test"` - Create post
906
+ - [ ] Test `agentdev [provider] post list` - List posts
907
+ - [ ] Test `agentdev [provider] post delete <id> --confirm` - Delete post
908
+ - [ ] Test error handling (invalid token, missing scopes, rate limits)
909
+
910
+ **Error Cases:**
911
+ - [ ] Test with expired token
912
+ - [ ] Test with missing OAuth scopes
913
+ - [ ] Test with invalid post ID
914
+ - [ ] Test rate limit handling
915
+ - [ ] Test network errors
916
+
917
+ ### Step 6.2: Create Unit Tests
918
+
919
+ **File:** `/packages/agentdev-client/src/[api]/api/core.test.js`
920
+
921
+ ```javascript
922
+ import { apiRequest } from './core.js';
923
+
924
+ describe('[Provider] API Core', () => {
925
+ test('apiRequest handles 401 errors', async () => {
926
+ global.fetch = jest.fn(() =>
927
+ Promise.resolve({
928
+ ok: false,
929
+ status: 401,
930
+ text: () => Promise.resolve('Unauthorized')
931
+ })
932
+ );
933
+
934
+ await expect(
935
+ apiRequest('GET', '/test', 'invalid-token')
936
+ ).rejects.toThrow('TOKEN_EXPIRED');
937
+ });
938
+
939
+ test('apiRequest handles 429 rate limits', async () => {
940
+ global.fetch = jest.fn(() =>
941
+ Promise.resolve({
942
+ ok: false,
943
+ status: 429,
944
+ headers: new Map([['Retry-After', '60']]),
945
+ text: () => Promise.resolve('Rate limit')
946
+ })
947
+ );
948
+
949
+ await expect(
950
+ apiRequest('GET', '/test', 'token')
951
+ ).rejects.toThrow('rate limit');
952
+ });
953
+ });
954
+ ```
955
+
956
+ ### Step 6.3: Integration Testing
957
+
958
+ **Create:** `/packages/agentdev-client/src/[api]/integration.test.js`
959
+
960
+ ```javascript
961
+ /**
962
+ * Integration tests for [Provider] API
963
+ * These tests require valid OAuth credentials
964
+ */
965
+
966
+ import {
967
+ createPost,
968
+ listPosts,
969
+ deletePost
970
+ } from './api.js';
971
+
972
+ // Only run if token is available
973
+ const TOKEN = process.env.[PROVIDER]_TOKEN;
974
+ const runIntegrationTests = TOKEN && process.env.RUN_INTEGRATION_TESTS;
975
+
976
+ describe.skipIf(!runIntegrationTests)('[Provider] Integration Tests', () => {
977
+ let testPostId;
978
+
979
+ test('Create post', async () => {
980
+ const result = await createPost(TOKEN, 'Test post from integration tests');
981
+ expect(result.id).toBeDefined();
982
+ testPostId = result.id;
983
+ });
984
+
985
+ test('List posts', async () => {
986
+ const result = await listPosts(TOKEN, 'me');
987
+ expect(result.posts).toBeDefined();
988
+ expect(Array.isArray(result.posts)).toBe(true);
989
+ });
990
+
991
+ test('Delete post', async () => {
992
+ if (testPostId) {
993
+ const result = await deletePost(TOKEN, testPostId);
994
+ expect(result.success).toBe(true);
995
+ }
996
+ });
997
+ });
998
+ ```
999
+
1000
+ ---
1001
+
1002
+ ## Phase 7: Deployment & Documentation (2-3 hours)
1003
+
1004
+ ### Step 7.1: Update Main CLI Entry Point
1005
+
1006
+ **File:** `/packages/agentdev-client/src/cli/index.js`
1007
+
1008
+ Add your new command:
1009
+
1010
+ ```javascript
1011
+ import { register[Provider]Command } from './cli/[provider].js';
1012
+
1013
+ export function registerCommands(program) {
1014
+ // ... existing commands
1015
+ register[Provider]Command(program);
1016
+ }
1017
+ ```
1018
+
1019
+ ### Step 7.2: Build & Test
1020
+
1021
+ ```bash
1022
+ cd /packages/agentdev-client
1023
+ npm run build
1024
+ npm test
1025
+
1026
+ # Test CLI locally
1027
+ node dist/cli/index.js [provider] auth
1028
+ node dist/cli/index.js [provider] post create --text "Test"
1029
+ ```
1030
+
1031
+ ### Step 7.3: Create Migration Guide
1032
+
1033
+ **File:** `MIGRATION_GUIDE_[PROVIDER].md`
1034
+
1035
+ ```markdown
1036
+ # [Provider] Integration - Migration Guide
1037
+
1038
+ ## For Users
1039
+
1040
+ ### Step 1: Connect Your Account
1041
+ 1. Visit https://agentdev.datatamer.ai/profile
1042
+ 2. Click "Connect [Provider]"
1043
+ 3. Authorize the application
1044
+ 4. Verify connection with: `agentdev [provider] auth`
1045
+
1046
+ ### Step 2: Update CLI (if needed)
1047
+ ```bash
1048
+ npm install -g agentdev-client@latest
1049
+ ```
1050
+
1051
+ ### Step 3: Start Using
1052
+ ```bash
1053
+ agentdev [provider] post create --text "Hello from AgentDev!"
1054
+ ```
1055
+
1056
+ ## For Developers
1057
+
1058
+ ### New Files Added
1059
+ - `/agentdev-webui/lib/[provider].js` - OAuth handler
1060
+ - `/packages/agentdev-client/src/[provider]/api/` - API modules
1061
+ - `/packages/agentdev-client/src/cli/[provider]/` - CLI modules
1062
+ - `/packages/agentdev-client/skills/agentdev-[provider].md` - Documentation
1063
+
1064
+ ### OAuth Scopes
1065
+ The following scopes are requested:
1066
+ - scope1, scope2, scope3
1067
+
1068
+ ### Environment Variables (optional)
1069
+ ```bash
1070
+ export [PROVIDER]_TOKEN="your-token-here"
1071
+ ```
1072
+ ```
1073
+
1074
+ ### Step 7.4: Create README Section
1075
+
1076
+ Add to main README:
1077
+
1078
+ ```markdown
1079
+ ## [Provider] Integration
1080
+
1081
+ AgentDev supports [Provider] integration for [brief description].
1082
+
1083
+ ### Setup
1084
+ 1. Connect your [Provider] account at `/profile`
1085
+ 2. Use CLI: `agentdev [provider] --help`
1086
+ 3. See full docs: [Link to skill doc]
1087
+
1088
+ ### Examples
1089
+ ```bash
1090
+ # Create a post
1091
+ agentdev [provider] post create --text "Hello!"
1092
+
1093
+ # List posts
1094
+ agentdev [provider] post list --limit 10
1095
+ ```
1096
+
1097
+ ### Rate Limits
1098
+ - X posts per day
1099
+ - Y API requests per hour
1100
+ ```
1101
+
1102
+ ---
1103
+
1104
+ ## Phase 8: Monitoring & Iteration (Ongoing)
1105
+
1106
+ ### Step 8.1: Add Logging
1107
+
1108
+ **Update API client to log important events:**
1109
+
1110
+ ```javascript
1111
+ export async function apiRequest(method, path, token, body, extraHeaders) {
1112
+ console.log(`[${new Date().toISOString()}] ${method} ${path}`);
1113
+
1114
+ try {
1115
+ const result = await fetch(/* ... */);
1116
+ console.log(`[${new Date().toISOString()}] ${method} ${path} - ${result.status}`);
1117
+ return result;
1118
+ } catch (error) {
1119
+ console.error(`[${new Date().toISOString()}] ${method} ${path} - ERROR:`, error.message);
1120
+ throw error;
1121
+ }
1122
+ }
1123
+ ```
1124
+
1125
+ ### Step 8.2: Monitor Usage
1126
+
1127
+ **Track:**
1128
+ - Number of API calls per day
1129
+ - Error rates
1130
+ - Most used commands
1131
+ - Token refresh frequency
1132
+ - Rate limit hits
1133
+
1134
+ ### Step 8.3: Gather Feedback
1135
+
1136
+ **Create feedback channels:**
1137
+ - GitHub issues for bug reports
1138
+ - Discord/Slack for questions
1139
+ - Usage analytics for feature requests
1140
+
1141
+ ### Step 8.4: Iterate
1142
+
1143
+ **Based on feedback:**
1144
+ 1. Add missing features
1145
+ 2. Fix bugs
1146
+ 3. Improve error messages
1147
+ 4. Optimize performance
1148
+ 5. Update documentation
1149
+
1150
+ ---
1151
+
1152
+ ## Common Patterns & Best Practices
1153
+
1154
+ ### OAuth Best Practices
1155
+
1156
+ 1. **Always Encrypt Credentials**
1157
+ ```javascript
1158
+ const encrypted = encryption.encrypt(clientSecret);
1159
+ ```
1160
+
1161
+ 2. **Handle Token Refresh**
1162
+ ```javascript
1163
+ if (isTokenExpired(token)) {
1164
+ token = await refreshAccessToken(refreshToken);
1165
+ }
1166
+ ```
1167
+
1168
+ 3. **Store Tokens Securely**
1169
+ - Never log tokens
1170
+ - Encrypt in database
1171
+ - Don't commit to git
1172
+
1173
+ ### API Client Best Practices
1174
+
1175
+ 1. **Use Modular Structure**
1176
+ - One module per feature category
1177
+ - Core module for shared logic
1178
+ - Index for re-exports
1179
+
1180
+ 2. **Handle Errors Gracefully**
1181
+ ```javascript
1182
+ if (res.status === 401) throw new Error('TOKEN_EXPIRED');
1183
+ if (res.status === 429) throw new Error('RATE_LIMIT');
1184
+ if (res.status === 403) throw new Error('FORBIDDEN');
1185
+ ```
1186
+
1187
+ 3. **Validate Input**
1188
+ ```javascript
1189
+ if (!text || text.length > 280) {
1190
+ throw new Error('Text must be 1-280 characters');
1191
+ }
1192
+ ```
1193
+
1194
+ 4. **Provide Clear Error Messages**
1195
+ ```javascript
1196
+ throw new Error('Post not found. Check the post ID and try again.');
1197
+ ```
1198
+
1199
+ ### CLI Best Practices
1200
+
1201
+ 1. **Use Chalk for Colors**
1202
+ ```javascript
1203
+ console.log(chalk.green('✓ Success'));
1204
+ console.error(chalk.red('✗ Error'));
1205
+ console.log(chalk.yellow('⚠ Warning'));
1206
+ console.log(chalk.gray('Additional info'));
1207
+ ```
1208
+
1209
+ 2. **Require Confirmation for Destructive Actions**
1210
+ ```javascript
1211
+ if (!opts.confirm) {
1212
+ console.log(chalk.yellow('Add --confirm to proceed'));
1213
+ process.exit(0);
1214
+ }
1215
+ ```
1216
+
1217
+ 3. **Show Progress for Long Operations**
1218
+ ```javascript
1219
+ console.log('Uploading video...');
1220
+ for (let i = 0; i < parts.length; i++) {
1221
+ console.log(` Part ${i+1}/${parts.length} uploaded`);
1222
+ }
1223
+ ```
1224
+
1225
+ 4. **Provide Examples in Help**
1226
+ ```javascript
1227
+ .command('create')
1228
+ .description('Create a post')
1229
+ .example('agentdev [provider] post create --text "Hello"')
1230
+ ```
1231
+
1232
+ ### Documentation Best Practices
1233
+
1234
+ 1. **Include Examples**
1235
+ - Show common use cases
1236
+ - Provide copy-paste commands
1237
+ - Explain expected output
1238
+
1239
+ 2. **Document Errors**
1240
+ - List common errors
1241
+ - Explain what they mean
1242
+ - Provide solutions
1243
+
1244
+ 3. **Keep Updated**
1245
+ - Update when adding features
1246
+ - Document breaking changes
1247
+ - Maintain changelog
1248
+
1249
+ ---
1250
+
1251
+ ## Quick Reference Checklist
1252
+
1253
+ Use this checklist for every new API integration:
1254
+
1255
+ ### Pre-Implementation
1256
+ - [ ] Research API documentation
1257
+ - [ ] Identify OAuth scopes needed
1258
+ - [ ] List core endpoints
1259
+ - [ ] Document rate limits
1260
+ - [ ] Create implementation plan
1261
+
1262
+ ### OAuth Setup
1263
+ - [ ] Register OAuth application
1264
+ - [ ] Get client ID and secret
1265
+ - [ ] Create `/lib/[provider].js`
1266
+ - [ ] Implement authorization URL
1267
+ - [ ] Implement token exchange
1268
+ - [ ] Implement token refresh
1269
+ - [ ] Test OAuth flow
1270
+
1271
+ ### API Client
1272
+ - [ ] Create `/src/[api]/api/core.js`
1273
+ - [ ] Create feature modules (posts, users, etc.)
1274
+ - [ ] Create `/src/[api]/api/index.js`
1275
+ - [ ] Create `/src/[api]/api.js` wrapper
1276
+ - [ ] Write unit tests
1277
+ - [ ] Test API calls
1278
+
1279
+ ### CLI Commands
1280
+ - [ ] Create `/src/cli/[api]/helpers.js`
1281
+ - [ ] Create feature command modules
1282
+ - [ ] Create `/src/cli/[api]/index.js`
1283
+ - [ ] Create `/src/cli/[api].js` wrapper
1284
+ - [ ] Register with main CLI
1285
+ - [ ] Test all commands
1286
+
1287
+ ### Documentation
1288
+ - [ ] Create skill file `/skills/agentdev-[api].md`
1289
+ - [ ] Document all commands
1290
+ - [ ] Add examples
1291
+ - [ ] Document errors
1292
+ - [ ] Add to main README
1293
+
1294
+ ### Testing & Deployment
1295
+ - [ ] Manual testing
1296
+ - [ ] Integration testing
1297
+ - [ ] Build and verify
1298
+ - [ ] Create migration guide
1299
+ - [ ] Deploy to production
1300
+ - [ ] Monitor for issues
1301
+
1302
+ ---
1303
+
1304
+ ## Example Integrations
1305
+
1306
+ This pattern has been successfully used for:
1307
+
1308
+ 1. **LinkedIn** (Implemented)
1309
+ - OAuth 2.0
1310
+ - Posts, analytics, connections
1311
+ - Organization pages
1312
+ - Video uploads
1313
+
1314
+ 2. **Twitter/X** (Future)
1315
+ - OAuth 2.0
1316
+ - Tweets, timelines, DMs
1317
+ - Media uploads
1318
+ - Analytics
1319
+
1320
+ 3. **GitHub** (Future)
1321
+ - OAuth 2.0
1322
+ - Repos, issues, PRs
1323
+ - Actions, releases
1324
+ - Webhooks
1325
+
1326
+ 4. **Slack** (Future)
1327
+ - OAuth 2.0
1328
+ - Messages, channels
1329
+ - File uploads
1330
+ - Slash commands
1331
+
1332
+ ---
1333
+
1334
+ ## Troubleshooting
1335
+
1336
+ ### OAuth Issues
1337
+
1338
+ **Problem:** "Invalid redirect URI"
1339
+ **Solution:** Ensure redirect URI matches exactly in OAuth app settings
1340
+
1341
+ **Problem:** "Invalid scopes"
1342
+ **Solution:** Check scopes are supported and spelled correctly
1343
+
1344
+ **Problem:** "Token expired immediately"
1345
+ **Solution:** Check token expiration handling and refresh logic
1346
+
1347
+ ### API Issues
1348
+
1349
+ **Problem:** 401 Unauthorized
1350
+ **Solution:** Verify token is valid and not expired
1351
+
1352
+ **Problem:** 403 Forbidden
1353
+ **Solution:** Check OAuth scopes include required permissions
1354
+
1355
+ **Problem:** 429 Rate Limited
1356
+ **Solution:** Implement exponential backoff and respect rate limits
1357
+
1358
+ ### CLI Issues
1359
+
1360
+ **Problem:** Command not found
1361
+ **Solution:** Rebuild CLI with `npm run build`
1362
+
1363
+ **Problem:** "Not connected" error
1364
+ **Solution:** Direct user to connect account at /profile
1365
+
1366
+ **Problem:** Module import errors
1367
+ **Solution:** Check file paths and ensure proper ES module syntax
1368
+
1369
+ ---
1370
+
1371
+ ## Conclusion
1372
+
1373
+ This guide provides a complete, battle-tested process for integrating any API into agentdev. Follow these steps and you'll have a production-ready integration in 2-4 weeks.
1374
+
1375
+ **Key Takeaways:**
1376
+ 1. ✅ Start with research and planning
1377
+ 2. ✅ Use modular architecture
1378
+ 3. ✅ Test thoroughly before deployment
1379
+ 4. ✅ Document everything
1380
+ 5. ✅ Monitor and iterate
1381
+
1382
+ For questions or help with integration, refer to this guide or ask the team!