@kaiban/sdk 0.4.0 → 0.4.2

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.
package/README.md CHANGED
@@ -35,11 +35,12 @@ The SDK provides clients for the following API resources:
35
35
 
36
36
  ### Available Resource Clients
37
37
 
38
- - **agents**: `list`, `listAll`, `get`, `update`, `createFeedback`, `listSupervisorFeedback`
38
+ - **agents**: `list`, `listAll`, `get`, `create`, `update`, `createFeedback`, `listSupervisorFeedback`
39
+ - **teamMembers**: `list`, `listAll`, `get`
39
40
  - **cards**: `list`, `listAll`, `get`, `create`, `update`, `delete`, `moveToColumn`, `createActivity`, `createBatchActivities`, `listActivities`, `listAllActivities`
40
41
  - **activities**: `list`, `listAll`, `create`, `createBatch`
41
42
  - **teams**: `list`, `listAll`, `get`
42
- - **boards**: `list`, `listAll`, `get`
43
+ - **boards**: `list`, `listAll`, `get`, `create`
43
44
  - **resources**: `list`, `listAll`, `get`
44
45
  - **external_channels**: `list`, `listAll`, `get`
45
46
  - **costs**: `calculateCosts` (offline utility for model cost calculations)
@@ -285,6 +286,9 @@ import {
285
286
  ValidationError,
286
287
  UnauthorizedError,
287
288
  RateLimitError,
289
+ BadGatewayError,
290
+ GatewayTimeoutError,
291
+ UnavailableError,
288
292
  TimeoutError,
289
293
  AbortedError,
290
294
  } from '@kaiban/sdk';
@@ -299,22 +303,44 @@ try {
299
303
  } catch (err) {
300
304
  if (err instanceof NotFoundError) {
301
305
  console.error('Card not found:', err.message);
302
- console.error('Error code:', err.code); // Optional error code from API
306
+ console.error('Error code:', err.code); // 'not_found'
307
+ console.error('Request ID:', err.meta?.request_id);
308
+ console.error('Timestamp:', err.meta?.timestamp);
303
309
  } else if (err instanceof ValidationError) {
304
310
  console.error('Validation failed:', err.message);
305
- console.error('Details:', err.details); // Additional error details from API
311
+ console.error('Error code:', err.code); // 'validation_error'
312
+ // ValidationError.details includes issues array
313
+ if (err.details?.issues) {
314
+ err.details.issues.forEach((issue) => {
315
+ console.error(` - ${issue.path.join('.')}: ${issue.message}`);
316
+ });
317
+ }
306
318
  } else if (err instanceof BadRequestError) {
307
319
  console.error('Invalid request:', err.message);
320
+ console.error('Error code:', err.code); // 'invalid_argument'
308
321
  } else if (err instanceof UnauthorizedError) {
309
322
  console.error('Authentication required:', err.message);
323
+ console.error('Error code:', err.code); // 'unauthenticated'
310
324
  } else if (err instanceof RateLimitError) {
311
325
  console.error('Rate limit exceeded:', err.message);
326
+ console.error('Error code:', err.code); // 'rate_limit_exceeded'
327
+ } else if (err instanceof BadGatewayError) {
328
+ console.error('Bad gateway:', err.message);
329
+ console.error('Error code:', err.code); // 'bad_gateway'
330
+ } else if (err instanceof GatewayTimeoutError) {
331
+ console.error('Gateway timeout:', err.message);
332
+ console.error('Error code:', err.code); // 'gateway_timeout'
333
+ } else if (err instanceof UnavailableError) {
334
+ console.error('Service unavailable:', err.message);
335
+ console.error('Error code:', err.code); // 'service_unavailable'
312
336
  } else if (err instanceof TimeoutError) {
313
337
  console.error('Request timed out');
314
338
  } else if (err instanceof AbortedError) {
315
339
  console.error('Request was cancelled');
316
340
  } else if (err instanceof ApiError) {
317
341
  console.error('API error:', err.message);
342
+ console.error('Error code:', err.code);
343
+ console.error('Details:', err.details);
318
344
  } else {
319
345
  console.error('Unexpected error:', err);
320
346
  }
@@ -323,20 +349,29 @@ try {
323
349
 
324
350
  ### Available Error Classes
325
351
 
326
- - **`ApiError`**: Base class for all API errors (includes `code`, `message`, `details` properties)
327
- - **`BadRequestError`**: 400 - Invalid request format or parameters
328
- - **`ValidationError`**: 422 - Request validation failed
329
- - **`UnauthorizedError`**: 401 - Authentication required or failed
330
- - **`ForbiddenError`**: 403 - Insufficient permissions
331
- - **`NotFoundError`**: 404 - Resource not found
332
- - **`ConflictError`**: 409 - Resource conflict
333
- - **`RateLimitError`**: 429 - Too many requests
334
- - **`UnavailableError`**: 502, 503, 504 - Service temporarily unavailable
335
- - **`ServerError`**: 500 or other server errors
352
+ - **`ApiError`**: Base class for all API errors (includes `code`, `message`, `details`, `meta` properties)
353
+ - **`BadRequestError`**: 400 - Invalid request format or parameters (`invalid_argument`)
354
+ - **`ValidationError`**: 422 - Request validation failed (`validation_error`, includes `details.issues[]`)
355
+ - **`UnauthorizedError`**: 401 - Authentication required or failed (`unauthenticated`)
356
+ - **`ForbiddenError`**: 403 - Insufficient permissions (`permission_denied`)
357
+ - **`NotFoundError`**: 404 - Resource not found (`not_found`)
358
+ - **`ConflictError`**: 409 - Resource conflict (`conflict`)
359
+ - **`RateLimitError`**: 429 - Too many requests (`rate_limit_exceeded`)
360
+ - **`BadGatewayError`**: 502 - Bad gateway (`bad_gateway`)
361
+ - **`UnavailableError`**: 503 - Service temporarily unavailable (`service_unavailable`)
362
+ - **`GatewayTimeoutError`**: 504 - Gateway timeout (`gateway_timeout`)
363
+ - **`ServerError`**: 500 - Internal server error (`internal`)
336
364
  - **`TimeoutError`**: Request exceeded configured timeout
337
365
  - **`AbortedError`**: Request was cancelled via AbortSignal
338
366
  - **`HttpError`**: Low-level HTTP error (includes `status`, `url`, `body` properties)
339
367
 
368
+ All API errors include:
369
+
370
+ - `code`: Backend error code (e.g., `validation_error`, `not_found`)
371
+ - `message`: Human-readable error message
372
+ - `details`: Optional error details (for `ValidationError`, includes `issues[]` array)
373
+ - `meta`: Request metadata with `request_id?` and `timestamp`
374
+
340
375
  ## Examples by resource
341
376
 
342
377
  ### Agents
@@ -358,6 +393,19 @@ for await (const agent of client.agents.listAll({ limit: 100 })) {
358
393
  // Get agent by id
359
394
  const agent = await client.agents.get('agent-123');
360
395
 
396
+ // Create a new agent
397
+ const newAgent = await client.agents.create({
398
+ name: 'SupportAgent',
399
+ description: 'Handles support tickets',
400
+ team_id: 'team_123',
401
+ owner_id: 'user_123',
402
+ created_by: 'user_123',
403
+ type: 'a2a',
404
+ status: 'active',
405
+ monthly_budget: 200,
406
+ examples: [],
407
+ });
408
+
361
409
  // Update agent
362
410
  const updated = await client.agents.update('agent-123', {
363
411
  name: 'Updated Name',
@@ -400,6 +448,24 @@ for await (const team of client.teams.listAll()) {
400
448
  const team = await client.teams.get('team-123');
401
449
  ```
402
450
 
451
+ ### Team Members
452
+
453
+ ```ts
454
+ // List team members with pagination
455
+ const result = await client.teamMembers.list({
456
+ limit: 20,
457
+ order_by: '-joined_at',
458
+ });
459
+
460
+ // Iterate through all team members
461
+ for await (const member of client.teamMembers.listAll({ limit: 100 })) {
462
+ console.log(member.id, member.user_id, member.role);
463
+ }
464
+
465
+ // Get a specific team member
466
+ const member = await client.teamMembers.get('tm-123');
467
+ ```
468
+
403
469
  ### Boards
404
470
 
405
471
  ```ts
@@ -413,6 +479,17 @@ for await (const board of client.boards.listAll()) {
413
479
 
414
480
  // Get a specific board
415
481
  const board = await client.boards.get('board-123');
482
+
483
+ // Create a new board
484
+ const newBoard = await client.boards.create({
485
+ name: 'Sales',
486
+ team_id: 'team_123',
487
+ owner_id: 'user_123',
488
+ created_by: 'user_123',
489
+ description: 'Manage pipeline',
490
+ columns: [],
491
+ // agent_ids, member_ids, and allowed_roles are optional (default to [])
492
+ });
416
493
  ```
417
494
 
418
495
  ### Cards
@@ -9,6 +9,7 @@ const CardsClient_1 = require("./resources/CardsClient");
9
9
  const ExternalChannelsClient_1 = require("./resources/ExternalChannelsClient");
10
10
  const ModelCost_1 = require("./resources/ModelCost");
11
11
  const ResourcesClient_1 = require("./resources/ResourcesClient");
12
+ const TeamMembersClient_1 = require("./resources/TeamMembersClient");
12
13
  const TeamsClient_1 = require("./resources/TeamsClient");
13
14
  /**
14
15
  * Create a Kaiban SDK client instance
@@ -46,9 +47,10 @@ function createKaibanClient(config) {
46
47
  cards: new CardsClient_1.CardsClient(http),
47
48
  activities: new ActivitiesClient_1.ActivitiesClient(http),
48
49
  teams: new TeamsClient_1.TeamsClient(http),
50
+ teamMembers: new TeamMembersClient_1.TeamMembersClient(http),
49
51
  boards: new BoardsClient_1.BoardsClient(http),
50
52
  resources: new ResourcesClient_1.ResourcesClient(http),
51
- external_channels: new ExternalChannelsClient_1.ExternalChannelsClient(http),
53
+ externalChannels: new ExternalChannelsClient_1.ExternalChannelsClient(http),
52
54
  costs: new ModelCost_1.ModelCost(),
53
55
  };
54
56
  }
@@ -165,7 +165,11 @@ class HttpClient {
165
165
  if (err instanceof errors_1.RateLimitError)
166
166
  return retryCfg.retryOn?.includes(429) ?? false;
167
167
  if (err instanceof errors_1.UnavailableError)
168
- return retryCfg.retryOn?.some((c) => c === 502 || c === 503 || c === 504) ?? false;
168
+ return retryCfg.retryOn?.includes(503) ?? false;
169
+ if (err instanceof errors_1.BadGatewayError)
170
+ return retryCfg.retryOn?.includes(502) ?? false;
171
+ if (err instanceof errors_1.GatewayTimeoutError)
172
+ return retryCfg.retryOn?.includes(504) ?? false;
169
173
  if (err instanceof errors_1.ServerError)
170
174
  return retryCfg.retryOn?.includes(500) ?? false;
171
175
  return false;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ServerError = exports.UnavailableError = exports.RateLimitError = exports.ConflictError = exports.NotFoundError = exports.ForbiddenError = exports.UnauthorizedError = exports.ValidationError = exports.BadRequestError = exports.ApiError = exports.AbortedError = exports.TimeoutError = exports.HttpError = void 0;
3
+ exports.ServerError = exports.GatewayTimeoutError = exports.BadGatewayError = exports.UnavailableError = exports.RateLimitError = exports.ConflictError = exports.NotFoundError = exports.ForbiddenError = exports.UnauthorizedError = exports.ValidationError = exports.BadRequestError = exports.ApiError = exports.AbortedError = exports.TimeoutError = exports.HttpError = void 0;
4
4
  exports.mapHttpToSdkError = mapHttpToSdkError;
5
5
  class HttpError extends Error {
6
6
  constructor(message, status, url, body) {
@@ -32,6 +32,7 @@ class ApiError extends Error {
32
32
  this.name = 'ApiError';
33
33
  this.code = shape.code;
34
34
  this.details = shape.details;
35
+ this.meta = shape.meta;
35
36
  }
36
37
  }
37
38
  exports.ApiError = ApiError;
@@ -46,6 +47,7 @@ class ValidationError extends ApiError {
46
47
  constructor(shape) {
47
48
  super(shape);
48
49
  this.name = 'ValidationError';
50
+ this.details = shape.details;
49
51
  }
50
52
  }
51
53
  exports.ValidationError = ValidationError;
@@ -91,6 +93,20 @@ class UnavailableError extends ApiError {
91
93
  }
92
94
  }
93
95
  exports.UnavailableError = UnavailableError;
96
+ class BadGatewayError extends ApiError {
97
+ constructor(shape) {
98
+ super(shape);
99
+ this.name = 'BadGatewayError';
100
+ }
101
+ }
102
+ exports.BadGatewayError = BadGatewayError;
103
+ class GatewayTimeoutError extends ApiError {
104
+ constructor(shape) {
105
+ super(shape);
106
+ this.name = 'GatewayTimeoutError';
107
+ }
108
+ }
109
+ exports.GatewayTimeoutError = GatewayTimeoutError;
94
110
  class ServerError extends ApiError {
95
111
  constructor(shape) {
96
112
  super(shape);
@@ -99,8 +115,38 @@ class ServerError extends ApiError {
99
115
  }
100
116
  exports.ServerError = ServerError;
101
117
  // Map HTTP response status and body to human-friendly SDK errors
118
+ // Uses backend error code when available, falls back to HTTP status mapping
102
119
  function mapHttpToSdkError(status, body) {
103
120
  const shape = normalizeBody(body);
121
+ // If backend provided an explicit error code, use it to determine error type
122
+ if (shape.code) {
123
+ switch (shape.code) {
124
+ case 'invalid_argument':
125
+ return new BadRequestError(shape);
126
+ case 'unauthenticated':
127
+ return new UnauthorizedError(shape);
128
+ case 'permission_denied':
129
+ return new ForbiddenError(shape);
130
+ case 'not_found':
131
+ return new NotFoundError(shape);
132
+ case 'conflict':
133
+ return new ConflictError(shape);
134
+ case 'validation_error':
135
+ return new ValidationError(shape);
136
+ case 'rate_limit_exceeded':
137
+ return new RateLimitError(shape);
138
+ case 'bad_gateway':
139
+ return new BadGatewayError(shape);
140
+ case 'service_unavailable':
141
+ return new UnavailableError(shape);
142
+ case 'gateway_timeout':
143
+ return new GatewayTimeoutError(shape);
144
+ case 'internal':
145
+ default:
146
+ return new ServerError(shape);
147
+ }
148
+ }
149
+ // Fallback to HTTP status code mapping if no backend code provided
104
150
  switch (status) {
105
151
  case 400:
106
152
  return new BadRequestError(shape);
@@ -117,14 +163,20 @@ function mapHttpToSdkError(status, body) {
117
163
  case 429:
118
164
  return new RateLimitError(shape);
119
165
  case 502:
166
+ return new BadGatewayError(shape);
120
167
  case 503:
121
- case 504:
122
168
  return new UnavailableError(shape);
169
+ case 504:
170
+ return new GatewayTimeoutError(shape);
123
171
  case 500:
124
172
  default:
125
173
  return new ServerError(shape);
126
174
  }
127
175
  }
176
+ /**
177
+ * Normalizes error response body to ApiErrorShape
178
+ * Backend returns: { error: { code, message, details? }, meta: { request_id?, timestamp } }
179
+ */
128
180
  function normalizeBody(body) {
129
181
  if (!body)
130
182
  return { message: 'Unknown error' };
@@ -132,12 +184,26 @@ function normalizeBody(body) {
132
184
  return { message: body };
133
185
  if (typeof body === 'object') {
134
186
  const anyBody = body;
135
- const code = anyBody['code'] || anyBody['error'];
187
+ // Backend structure: { error: { code, message, details? }, meta: { request_id?, timestamp } }
188
+ if (anyBody['error'] && typeof anyBody['error'] === 'object') {
189
+ const errorObj = anyBody['error'];
190
+ const meta = anyBody['meta'];
191
+ return {
192
+ code: errorObj['code'],
193
+ message: errorObj['message'] || 'Request failed',
194
+ details: errorObj['details'],
195
+ meta,
196
+ };
197
+ }
198
+ // Fallback: try to extract from flat structure (legacy support)
199
+ const code = anyBody['code'] ||
200
+ anyBody['error'];
136
201
  const message = anyBody['message'] ||
137
202
  anyBody['error_description'] ||
138
203
  'Request failed';
139
204
  const details = anyBody['details'];
140
- return { code, message, details };
205
+ const meta = anyBody['meta'];
206
+ return { code, message, details, meta };
141
207
  }
142
208
  return { message: 'Request failed' };
143
209
  }
@@ -105,6 +105,34 @@ class AgentsClient {
105
105
  get(id, options) {
106
106
  return this.http.get(`/agent/${encodeURIComponent(id)}`, options);
107
107
  }
108
+ /**
109
+ * Create a new agent
110
+ *
111
+ * @param data - Agent creation data
112
+ * @param options - Optional request configuration
113
+ *
114
+ * @returns The newly created agent object
115
+ *
116
+ * @throws {Error} If creation fails
117
+ *
118
+ * @example
119
+ * ```typescript
120
+ * const agent = await client.agents.create({
121
+ * name: 'SupportAgent',
122
+ * description: 'Handles support tickets',
123
+ * team_id: 'team_123',
124
+ * owner_id: 'user_123',
125
+ * created_by: 'user_123',
126
+ * type: 'a2a',
127
+ * status: 'active',
128
+ * monthly_budget: 200,
129
+ * examples: []
130
+ * });
131
+ * ```
132
+ */
133
+ create(data, options) {
134
+ return this.http.post('/agents', data, options);
135
+ }
108
136
  /**
109
137
  * Update an agent's properties
110
138
  *
@@ -74,5 +74,47 @@ class BoardsClient {
74
74
  get(id, options) {
75
75
  return this.http.get(`/board/${encodeURIComponent(id)}`, options);
76
76
  }
77
+ /**
78
+ * Create a new board
79
+ *
80
+ * @param data - Board creation data
81
+ * @param data.name - The board name
82
+ * @param data.team_id - The team this board belongs to
83
+ * @param data.owner_id - The owner of the board
84
+ * @param data.created_by - The user creating the board
85
+ * @param data.description - Board description
86
+ * @param data.agent_ids - Array of agent IDs
87
+ * @param data.member_ids - Array of member IDs
88
+ * @param data.allowed_roles - Array of allowed roles
89
+ * @param data.columns - Array of columns
90
+ * @param options - Optional request configuration
91
+ *
92
+ * @returns The newly created board
93
+ *
94
+ * @throws {Error} If creation fails
95
+ *
96
+ * @example
97
+ * ```typescript
98
+ * const board = await client.boards.create({
99
+ * name: 'Sales',
100
+ * team_id: 'team_123',
101
+ * owner_id: 'user_123',
102
+ * created_by: 'user_123',
103
+ * description: 'Manage pipeline',
104
+ * columns: []
105
+ * // agent_ids, member_ids, and allowed_roles are optional (default to [])
106
+ * });
107
+ * ```
108
+ */
109
+ create(data, options) {
110
+ // Default empty arrays for optional fields
111
+ const payload = {
112
+ ...data,
113
+ agent_ids: data.agent_ids ?? [],
114
+ member_ids: data.member_ids ?? [],
115
+ allowed_roles: data.allowed_roles ?? [],
116
+ };
117
+ return this.http.post('/boards', payload, options);
118
+ }
77
119
  }
78
120
  exports.BoardsClient = BoardsClient;
@@ -0,0 +1,102 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TeamMembersClient = void 0;
4
+ /**
5
+ * Client for managing team members in the Kaiban platform
6
+ * @category Resources
7
+ */
8
+ class TeamMembersClient {
9
+ constructor(http) {
10
+ this.http = http;
11
+ }
12
+ /**
13
+ * List team members with pagination, filters, and sorting
14
+ *
15
+ * @param params - Optional query parameters for filtering and pagination
16
+ * @param params.limit - Number of items per page (default: 50, max: 100)
17
+ * @param params.after - Cursor to navigate forwards (get items after this cursor)
18
+ * @param params.before - Cursor to navigate backwards (get items before this cursor)
19
+ * @param params.order_by - Fields to sort by (prefix with - for descending order)
20
+ * @param params.filters - Filter parameters to narrow results
21
+ * @param options - Optional request configuration
22
+ *
23
+ * @returns A paginated list of team members
24
+ *
25
+ * @example
26
+ * ```typescript
27
+ * // List first page of team members
28
+ * const result = await client.teamMembers.list({ limit: 10 });
29
+ * console.log(result.data); // Array of TeamMember objects
30
+ * console.log(result.pagination.next_cursor); // Cursor for next page
31
+ *
32
+ * // Get next page using cursor
33
+ * if (result.pagination.next_cursor) {
34
+ * const nextPage = await client.teamMembers.list({
35
+ * limit: 10,
36
+ * after: result.pagination.next_cursor
37
+ * });
38
+ * }
39
+ * ```
40
+ */
41
+ list(params, options) {
42
+ return this.http.list('/team-members', params, options);
43
+ }
44
+ /**
45
+ * Iterate through all team members using async generator
46
+ * Automatically handles pagination by following next_cursor
47
+ *
48
+ * @param params - Optional query parameters (excluding after/before cursors)
49
+ * @param params.limit - Number of items per page (used internally for pagination)
50
+ * @param params.order_by - Fields to sort by (prefix with - for descending order)
51
+ * @param params.filters - Filter parameters to narrow results
52
+ * @param options - Optional request configuration
53
+ *
54
+ * @yields Individual TeamMember objects
55
+ *
56
+ * @example
57
+ * ```typescript
58
+ * // Iterate through all team members
59
+ * for await (const member of client.teamMembers.listAll()) {
60
+ * console.log(member.id, member.user_id, member.role);
61
+ * }
62
+ *
63
+ * // With custom page size and sorting
64
+ * for await (const member of client.teamMembers.listAll({
65
+ * limit: 100,
66
+ * order_by: '-joined_at',
67
+ * filters: { team_id: 'team_123' }
68
+ * })) {
69
+ * console.log(member);
70
+ * }
71
+ * ```
72
+ */
73
+ async *listAll(params, options) {
74
+ let cursor = undefined;
75
+ do {
76
+ const page = await this.list({ ...(params || {}), after: cursor }, options);
77
+ for (const item of page.data)
78
+ yield item;
79
+ cursor = page.pagination.next_cursor;
80
+ } while (cursor);
81
+ }
82
+ /**
83
+ * Get a single team member by ID
84
+ *
85
+ * @param id - The unique identifier of the team member
86
+ * @param options - Optional request configuration
87
+ *
88
+ * @returns The team member object
89
+ *
90
+ * @throws {Error} If the team member is not found or request fails
91
+ *
92
+ * @example
93
+ * ```typescript
94
+ * const member = await client.teamMembers.get('tm-123');
95
+ * console.log(member.user_id, member.role);
96
+ * ```
97
+ */
98
+ get(id, options) {
99
+ return this.http.get(`/team-member/${encodeURIComponent(id)}`, options);
100
+ }
101
+ }
102
+ exports.TeamMembersClient = TeamMembersClient;
@@ -24,8 +24,6 @@ exports.ActivityType = {
24
24
  CARD_CLONED: 'card_cloned',
25
25
  CARD_COLUMN_CHANGED: 'card_column_changed',
26
26
  // A2A task status activities
27
- // "submitted" | "working" | "input-required" | "completed" | "canceled" | "failed" | "rejected"
28
- // | "auth-required" | "unknown"
29
27
  A2A_TASK_STATUS_SUBMITTED: 'submitted',
30
28
  A2A_TASK_STATUS_WORKING: 'working',
31
29
  A2A_TASK_STATUS_INPUT_REQUIRED: 'required',
@@ -6,6 +6,7 @@ import { CardsClient } from './resources/CardsClient.js';
6
6
  import { ExternalChannelsClient } from './resources/ExternalChannelsClient.js';
7
7
  import { ModelCost } from './resources/ModelCost.js';
8
8
  import { ResourcesClient } from './resources/ResourcesClient.js';
9
+ import { TeamMembersClient } from './resources/TeamMembersClient.js';
9
10
  import { TeamsClient } from './resources/TeamsClient.js';
10
11
  /**
11
12
  * Create a Kaiban SDK client instance
@@ -43,9 +44,10 @@ export function createKaibanClient(config) {
43
44
  cards: new CardsClient(http),
44
45
  activities: new ActivitiesClient(http),
45
46
  teams: new TeamsClient(http),
47
+ teamMembers: new TeamMembersClient(http),
46
48
  boards: new BoardsClient(http),
47
49
  resources: new ResourcesClient(http),
48
- external_channels: new ExternalChannelsClient(http),
50
+ externalChannels: new ExternalChannelsClient(http),
49
51
  costs: new ModelCost(),
50
52
  };
51
53
  }
@@ -1,4 +1,4 @@
1
- import { AbortedError, RateLimitError, ServerError, TimeoutError, UnavailableError, mapHttpToSdkError, } from './errors.js';
1
+ import { AbortedError, BadGatewayError, GatewayTimeoutError, RateLimitError, ServerError, TimeoutError, UnavailableError, mapHttpToSdkError, } from './errors.js';
2
2
  function buildQuery(query) {
3
3
  if (!query)
4
4
  return '';
@@ -162,7 +162,11 @@ export class HttpClient {
162
162
  if (err instanceof RateLimitError)
163
163
  return retryCfg.retryOn?.includes(429) ?? false;
164
164
  if (err instanceof UnavailableError)
165
- return retryCfg.retryOn?.some((c) => c === 502 || c === 503 || c === 504) ?? false;
165
+ return retryCfg.retryOn?.includes(503) ?? false;
166
+ if (err instanceof BadGatewayError)
167
+ return retryCfg.retryOn?.includes(502) ?? false;
168
+ if (err instanceof GatewayTimeoutError)
169
+ return retryCfg.retryOn?.includes(504) ?? false;
166
170
  if (err instanceof ServerError)
167
171
  return retryCfg.retryOn?.includes(500) ?? false;
168
172
  return false;