@kaiban/sdk 0.1.9 → 0.3.0

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 (93) hide show
  1. package/README.md +187 -21
  2. package/dist/cjs/index.js +21 -0
  3. package/dist/cjs/lib/client.js +56 -0
  4. package/dist/cjs/lib/http/HttpClient.js +243 -0
  5. package/dist/cjs/lib/http/errors.js +143 -0
  6. package/dist/cjs/lib/http/types.js +2 -0
  7. package/dist/cjs/lib/resources/ActivitiesClient.js +164 -0
  8. package/dist/cjs/lib/resources/AgentsClient.js +224 -0
  9. package/dist/cjs/lib/resources/BoardsClient.js +120 -0
  10. package/dist/cjs/lib/resources/CardsClient.js +352 -0
  11. package/dist/cjs/lib/resources/ExternalChannelsClient.js +78 -0
  12. package/dist/cjs/lib/resources/ModelCost.js +87 -0
  13. package/dist/cjs/lib/resources/ResourcesClient.js +78 -0
  14. package/dist/cjs/lib/resources/TeamMembersClient.js +102 -0
  15. package/dist/cjs/lib/resources/TeamsClient.js +96 -0
  16. package/dist/cjs/package.json +3 -0
  17. package/dist/cjs/test/helpers/mockFetch.js +27 -0
  18. package/dist/cjs/types/entities/a2a-dataparts.js +17 -0
  19. package/dist/cjs/types/entities/activities.js +72 -0
  20. package/dist/cjs/types/entities/agent.js +28 -0
  21. package/dist/cjs/types/entities/board.js +2 -0
  22. package/dist/cjs/types/entities/card.js +29 -0
  23. package/dist/cjs/types/entities/costs.js +2 -0
  24. package/dist/cjs/types/entities/external-channel.js +19 -0
  25. package/dist/cjs/types/entities/index.js +25 -0
  26. package/dist/cjs/types/entities/resource.js +10 -0
  27. package/dist/cjs/types/entities/shared.js +3 -0
  28. package/dist/cjs/types/entities/team.js +2 -0
  29. package/dist/cjs/types/entities.js +17 -0
  30. package/dist/cjs/types/responses.js +2 -0
  31. package/dist/esm/index.js +5 -0
  32. package/dist/{lib → esm/lib}/client.js +11 -9
  33. package/dist/{lib → esm/lib}/http/HttpClient.js +1 -1
  34. package/dist/{lib → esm/lib}/resources/AgentsClient.js +28 -0
  35. package/dist/{lib → esm/lib}/resources/BoardsClient.js +42 -0
  36. package/dist/{lib → esm/lib}/resources/CardsClient.js +1 -1
  37. package/dist/esm/lib/resources/TeamMembersClient.js +98 -0
  38. package/dist/{types → esm/types}/entities/activities.js +9 -13
  39. package/dist/esm/types/entities/index.js +9 -0
  40. package/dist/esm/types/entities.js +1 -0
  41. package/dist/esm/types/requests.js +19 -0
  42. package/dist/{lib → types/lib}/client.d.ts +3 -0
  43. package/dist/{lib → types/lib}/resources/AgentsClient.d.ts +26 -0
  44. package/dist/{lib → types/lib}/resources/BoardsClient.d.ts +34 -1
  45. package/dist/types/lib/resources/TeamMembersClient.d.ts +89 -0
  46. package/dist/types/{entities → types/entities}/activities.d.ts +14 -3
  47. package/dist/types/{entities → types/entities}/agent.d.ts +18 -10
  48. package/dist/types/{entities → types/entities}/board.d.ts +16 -5
  49. package/dist/types/{entities → types/entities}/card.d.ts +22 -13
  50. package/dist/types/{entities → types/entities}/external-channel.d.ts +1 -1
  51. package/dist/types/{entities → types/entities}/team.d.ts +4 -2
  52. package/package.json +18 -9
  53. package/dist/index.js +0 -5
  54. package/dist/types/entities/index.js +0 -9
  55. package/dist/types/entities.js +0 -1
  56. /package/dist/{types → cjs/types}/requests.js +0 -0
  57. /package/dist/{lib → esm/lib}/http/errors.js +0 -0
  58. /package/dist/{lib → esm/lib}/http/types.js +0 -0
  59. /package/dist/{lib → esm/lib}/resources/ActivitiesClient.js +0 -0
  60. /package/dist/{lib → esm/lib}/resources/ExternalChannelsClient.js +0 -0
  61. /package/dist/{lib → esm/lib}/resources/ModelCost.js +0 -0
  62. /package/dist/{lib → esm/lib}/resources/ResourcesClient.js +0 -0
  63. /package/dist/{lib → esm/lib}/resources/TeamsClient.js +0 -0
  64. /package/dist/{test → esm/test}/helpers/mockFetch.js +0 -0
  65. /package/dist/{types → esm/types}/entities/a2a-dataparts.js +0 -0
  66. /package/dist/{types → esm/types}/entities/agent.js +0 -0
  67. /package/dist/{types → esm/types}/entities/board.js +0 -0
  68. /package/dist/{types → esm/types}/entities/card.js +0 -0
  69. /package/dist/{types → esm/types}/entities/costs.js +0 -0
  70. /package/dist/{types → esm/types}/entities/external-channel.js +0 -0
  71. /package/dist/{types → esm/types}/entities/resource.js +0 -0
  72. /package/dist/{types → esm/types}/entities/shared.js +0 -0
  73. /package/dist/{types → esm/types}/entities/team.js +0 -0
  74. /package/dist/{types → esm/types}/responses.js +0 -0
  75. /package/dist/{index.d.ts → types/index.d.ts} +0 -0
  76. /package/dist/{lib → types/lib}/http/HttpClient.d.ts +0 -0
  77. /package/dist/{lib → types/lib}/http/errors.d.ts +0 -0
  78. /package/dist/{lib → types/lib}/http/types.d.ts +0 -0
  79. /package/dist/{lib → types/lib}/resources/ActivitiesClient.d.ts +0 -0
  80. /package/dist/{lib → types/lib}/resources/CardsClient.d.ts +0 -0
  81. /package/dist/{lib → types/lib}/resources/ExternalChannelsClient.d.ts +0 -0
  82. /package/dist/{lib → types/lib}/resources/ModelCost.d.ts +0 -0
  83. /package/dist/{lib → types/lib}/resources/ResourcesClient.d.ts +0 -0
  84. /package/dist/{lib → types/lib}/resources/TeamsClient.d.ts +0 -0
  85. /package/dist/{test → types/test}/helpers/mockFetch.d.ts +0 -0
  86. /package/dist/types/{entities → types/entities}/a2a-dataparts.d.ts +0 -0
  87. /package/dist/types/{entities → types/entities}/costs.d.ts +0 -0
  88. /package/dist/types/{entities → types/entities}/index.d.ts +0 -0
  89. /package/dist/types/{entities → types/entities}/resource.d.ts +0 -0
  90. /package/dist/types/{entities → types/entities}/shared.d.ts +0 -0
  91. /package/dist/types/{entities.d.ts → types/entities.d.ts} +0 -0
  92. /package/dist/types/{requests.d.ts → types/requests.d.ts} +0 -0
  93. /package/dist/types/{responses.d.ts → types/responses.d.ts} +0 -0
package/README.md CHANGED
@@ -14,7 +14,7 @@ npm install @kaiban/sdk
14
14
  import { createKaibanClient } from '@kaiban/sdk';
15
15
 
16
16
  const client = createKaibanClient({
17
- tenant: 'agi',
17
+ tenant: 'your-tenant',
18
18
  token: process.env.KAIBAN_TOKEN,
19
19
  });
20
20
 
@@ -22,11 +22,12 @@ const result = await client.agents.list({ limit: 10 });
22
22
  console.log(result.data); // Array of agents
23
23
  ```
24
24
 
25
- ## Auth and tenancy
25
+ ## Auth and Tenancy
26
26
 
27
27
  - Uses `Authorization: Bearer <token>` automatically when provided
28
- - Sends `x-tenant` with the configured tenant
28
+ - Sends `x-tenant` header with the configured tenant
29
29
  - Default base URL: `https://{tenant}.kaiban.io`
30
+ - Custom base URL can be configured via `baseUrl` option
30
31
 
31
32
  ## Resources
32
33
 
@@ -34,20 +35,22 @@ The SDK provides clients for the following API resources:
34
35
 
35
36
  ### Available Resource Clients
36
37
 
37
- - **agents**: `list`, `listAll`, `get`, `update`, `createFeedback`, `listSupervisorFeedback`
38
+ - **agents**: `list`, `listAll`, `get`, `create`, `update`, `createFeedback`, `listSupervisorFeedback`
39
+ - **teamMembers**: `list`, `listAll`, `get`
38
40
  - **cards**: `list`, `listAll`, `get`, `create`, `update`, `delete`, `moveToColumn`, `createActivity`, `createBatchActivities`, `listActivities`, `listAllActivities`
39
41
  - **activities**: `list`, `listAll`, `create`, `createBatch`
40
42
  - **teams**: `list`, `listAll`, `get`
41
- - **boards**: `list`, `listAll`, `get`
43
+ - **boards**: `list`, `listAll`, `get`, `create`
42
44
  - **resources**: `list`, `listAll`, `get`
43
45
  - **external_channels**: `list`, `listAll`, `get`
46
+ - **costs**: `calculateCosts` (offline utility for model cost calculations)
44
47
 
45
48
  ### Pagination
46
49
 
47
50
  All `list` methods return paginated results with cursor-based navigation:
48
51
 
49
52
  ```ts
50
- import { type Paginated, type Agent, type ListParams } from '@kaiban/sdk';
53
+ import { type Paginated, type Agent, type Card, type ListParams } from '@kaiban/sdk';
51
54
 
52
55
  // Basic pagination
53
56
  const params: ListParams = {
@@ -76,6 +79,13 @@ if (result.pagination.prev_cursor) {
76
79
  before: result.pagination.prev_cursor,
77
80
  });
78
81
  }
82
+
83
+ // Filter cards by metadata (cards only)
84
+ const cardsResult: Paginated<Card> = await client.cards.list({
85
+ limit: 20,
86
+ metadata: { thread_id: 'thread-123', user_id: 'user-456' },
87
+ });
88
+ // This becomes: ?metadata.thread_id=thread-123&metadata.user_id=user-456
79
89
  ```
80
90
 
81
91
  All `listAll` methods return async generators that automatically handle pagination:
@@ -91,13 +101,19 @@ for await (const agent of client.agents.listAll({ limit: 100 })) {
91
101
 
92
102
  All types are published and re-exported from `@kaiban/sdk`. Available types include:
93
103
 
94
- - **Entities**: `Agent`, `Card`, `Activity`, `Team`, `Board`, `Resource`, `ExternalChannel`
95
- - **Request/Response**: `ActivityCreate`, `ListParams`, `Paginated`, `PaginationMeta`
96
- - **Configuration**: `KaibanClientConfig`, `RequestOptions`
97
- - **Actors & Changes**: `ActivityActor`, `ActivityChange`
104
+ - **Entities**: `Agent`, `Card`, `Activity`, `Team`, `Board`, `Resource`, `ExternalChannel`, `TeamMember`, `Column`
105
+ - **Agent Types**: `AgentFeedback`, `AgentSupervisorFeedback`, `AgentType`, `AgentStatus`, `AgentFeedbackStatus`, `AgentFeedbackType`, `AgentFeedbackEvaluation`
106
+ - **Activity Types**: `ActivityCreate`, `ActivityActor`, `ActivityChange`, `ActivityType`
98
107
  - **Card Types**: `CardStatus`, `CardPart`
99
- - **Enums/Constants**: `AgentType`, `AgentStatus`, `ActivityType`, `ResourceStatus`, `ExternalChannelType`, `ExternalChannelStatus`, `AgentFeedbackType`, `AgentFeedbackEvaluation`
100
- - **Error classes**: `ApiError`, `NotFoundError`, `BadRequestError`, `UnauthorizedError`, `ForbiddenError`, `ConflictError`, `TooManyRequestsError`, `InternalServerError`, `TimeoutError`, `AbortedError`
108
+ - **Board Types**: `Column`
109
+ - **Resource Types**: `ResourceStatus`
110
+ - **External Channel Types**: `ExternalChannelType`, `ExternalChannelStatus`, `ExternalChannelPriority`
111
+ - **Cost Types**: `ModelCostInput`, `ModelCostOutput`
112
+ - **A2A Data Parts**: `A2ADataPartType`, `ToolCallStartPart`, `ToolCallArgsPart`, `ToolCallEndPart`, `ToolCallResultPart`, `TaskInfoMessagePart`, `TaskStepOutputPart`, `UserEvaluationPart`, `UserThreadFeedbackPart`, `UserCloseThreadPart`, `GenerateReportPart`, `KaibanActivityPart`, `AgentStatusPart`
113
+ - **Request/Response**: `ListParams`, `Paginated`, `PaginationMeta`
114
+ - **Configuration**: `KaibanClientConfig`, `RequestOptions`
115
+ - **Shared Types**: `ISODate`
116
+ - **Error classes**: `HttpError`, `ApiError`, `BadRequestError`, `ValidationError`, `UnauthorizedError`, `ForbiddenError`, `NotFoundError`, `ConflictError`, `RateLimitError`, `UnavailableError`, `ServerError`, `TimeoutError`, `AbortedError`
101
117
 
102
118
  ### Example: Using Types
103
119
 
@@ -207,21 +223,36 @@ import { createKaibanClient, type KaibanClientConfig } from '@kaiban/sdk';
207
223
  const config: KaibanClientConfig = {
208
224
  tenant: 'your-tenant', // Required: Your tenant identifier
209
225
  token: 'your-api-token', // Required: Your API authentication token
210
- baseUrl: 'https://custom-host', // Optional: Custom API base URL
226
+ baseUrl: 'https://custom-host', // Optional: Custom API base URL (default: https://{tenant}.kaiban.io)
211
227
  timeoutMs: 30000, // Optional: Request timeout in milliseconds (default: 30000)
212
228
  retry: {
213
229
  // Optional: Retry configuration
214
230
  maxAttempts: 3, // Maximum number of retry attempts (default: 3)
215
- backoffMs: 1000, // Initial backoff delay (default: 1000)
216
- maxBackoffMs: 30000, // Maximum backoff delay (default: 30000)
231
+ backoffMs: 1000, // Initial backoff delay in ms (default: 1000)
232
+ maxBackoffMs: 30000, // Maximum backoff delay in ms (default: 30000)
217
233
  jitter: true, // Add randomness to backoff (default: true)
234
+ retryOn: [429, 502, 503, 504], // Optional: HTTP status codes to retry on
235
+ retryMethods: ['GET', 'PUT', 'DELETE'], // Optional: HTTP methods to retry
236
+ },
237
+ fetch: globalThis.fetch, // Optional: Custom fetch implementation
238
+ onRequest: ({ method, url, init }) => {
239
+ // Optional: Hook called before each request
240
+ console.log(`Making ${method} request to ${url}`);
241
+ },
242
+ onResponse: ({ status, url, response }) => {
243
+ // Optional: Hook called after each response
244
+ console.log(`Received ${status} from ${url}`);
218
245
  },
219
246
  };
220
247
 
221
248
  const client = createKaibanClient(config);
249
+
250
+ // You can also update the token dynamically after client creation
251
+ client.setToken('new-token'); // Set a new token
252
+ client.setToken(); // Clear the token
222
253
  ```
223
254
 
224
- ## Per-call options
255
+ ## Per-call Options
225
256
 
226
257
  All resource methods accept an optional `RequestOptions` parameter for per-call overrides:
227
258
 
@@ -242,29 +273,70 @@ await client.cards.list({ limit: 20 }, options);
242
273
  await client.agents.get('agent-123', options);
243
274
  ```
244
275
 
245
- ## Error handling
276
+ ## Error Handling
246
277
 
247
- The SDK provides typed error classes for different HTTP status codes:
278
+ The SDK provides typed error classes for different HTTP status codes and network errors:
248
279
 
249
280
  ```ts
250
- import { createKaibanClient, ApiError, NotFoundError, BadRequestError } from '@kaiban/sdk';
281
+ import {
282
+ createKaibanClient,
283
+ ApiError,
284
+ NotFoundError,
285
+ BadRequestError,
286
+ ValidationError,
287
+ UnauthorizedError,
288
+ RateLimitError,
289
+ TimeoutError,
290
+ AbortedError,
291
+ } from '@kaiban/sdk';
292
+
293
+ const client = createKaibanClient({
294
+ tenant: 'your-tenant',
295
+ token: process.env.KAIBAN_TOKEN!,
296
+ });
251
297
 
252
298
  try {
253
299
  await client.cards.get('non-existent-id');
254
300
  } catch (err) {
255
301
  if (err instanceof NotFoundError) {
256
302
  console.error('Card not found:', err.message);
303
+ console.error('Error code:', err.code); // Optional error code from API
304
+ } else if (err instanceof ValidationError) {
305
+ console.error('Validation failed:', err.message);
306
+ console.error('Details:', err.details); // Additional error details from API
257
307
  } else if (err instanceof BadRequestError) {
258
308
  console.error('Invalid request:', err.message);
309
+ } else if (err instanceof UnauthorizedError) {
310
+ console.error('Authentication required:', err.message);
311
+ } else if (err instanceof RateLimitError) {
312
+ console.error('Rate limit exceeded:', err.message);
313
+ } else if (err instanceof TimeoutError) {
314
+ console.error('Request timed out');
315
+ } else if (err instanceof AbortedError) {
316
+ console.error('Request was cancelled');
259
317
  } else if (err instanceof ApiError) {
260
- console.error('API error:', err.status, err.message);
318
+ console.error('API error:', err.message);
261
319
  } else {
262
320
  console.error('Unexpected error:', err);
263
321
  }
264
322
  }
265
323
  ```
266
324
 
267
- Available error classes: `ApiError`, `BadRequestError`, `UnauthorizedError`, `ForbiddenError`, `NotFoundError`, `ConflictError`, `TooManyRequestsError`, `InternalServerError`, `TimeoutError`, `AbortedError`.
325
+ ### Available Error Classes
326
+
327
+ - **`ApiError`**: Base class for all API errors (includes `code`, `message`, `details` properties)
328
+ - **`BadRequestError`**: 400 - Invalid request format or parameters
329
+ - **`ValidationError`**: 422 - Request validation failed
330
+ - **`UnauthorizedError`**: 401 - Authentication required or failed
331
+ - **`ForbiddenError`**: 403 - Insufficient permissions
332
+ - **`NotFoundError`**: 404 - Resource not found
333
+ - **`ConflictError`**: 409 - Resource conflict
334
+ - **`RateLimitError`**: 429 - Too many requests
335
+ - **`UnavailableError`**: 502, 503, 504 - Service temporarily unavailable
336
+ - **`ServerError`**: 500 or other server errors
337
+ - **`TimeoutError`**: Request exceeded configured timeout
338
+ - **`AbortedError`**: Request was cancelled via AbortSignal
339
+ - **`HttpError`**: Low-level HTTP error (includes `status`, `url`, `body` properties)
268
340
 
269
341
  ## Examples by resource
270
342
 
@@ -287,6 +359,19 @@ for await (const agent of client.agents.listAll({ limit: 100 })) {
287
359
  // Get agent by id
288
360
  const agent = await client.agents.get('agent-123');
289
361
 
362
+ // Create a new agent
363
+ const newAgent = await client.agents.create({
364
+ name: 'SupportAgent',
365
+ description: 'Handles support tickets',
366
+ team_id: 'team_123',
367
+ owner_id: 'user_123',
368
+ created_by: 'user_123',
369
+ type: 'a2a',
370
+ status: 'active',
371
+ monthly_budget: 200,
372
+ examples: [],
373
+ });
374
+
290
375
  // Update agent
291
376
  const updated = await client.agents.update('agent-123', {
292
377
  name: 'Updated Name',
@@ -329,6 +414,24 @@ for await (const team of client.teams.listAll()) {
329
414
  const team = await client.teams.get('team-123');
330
415
  ```
331
416
 
417
+ ### Team Members
418
+
419
+ ```ts
420
+ // List team members with pagination
421
+ const result = await client.teamMembers.list({
422
+ limit: 20,
423
+ order_by: '-joined_at',
424
+ });
425
+
426
+ // Iterate through all team members
427
+ for await (const member of client.teamMembers.listAll({ limit: 100 })) {
428
+ console.log(member.id, member.user_id, member.role);
429
+ }
430
+
431
+ // Get a specific team member
432
+ const member = await client.teamMembers.get('tm-123');
433
+ ```
434
+
332
435
  ### Boards
333
436
 
334
437
  ```ts
@@ -342,6 +445,17 @@ for await (const board of client.boards.listAll()) {
342
445
 
343
446
  // Get a specific board
344
447
  const board = await client.boards.get('board-123');
448
+
449
+ // Create a new board
450
+ const newBoard = await client.boards.create({
451
+ name: 'Sales',
452
+ team_id: 'team_123',
453
+ owner_id: 'user_123',
454
+ created_by: 'user_123',
455
+ description: 'Manage pipeline',
456
+ columns: [],
457
+ // agent_ids, member_ids, and allowed_roles are optional (default to [])
458
+ });
345
459
  ```
346
460
 
347
461
  ### Cards
@@ -519,3 +633,55 @@ for await (const channel of client.external_channels.listAll()) {
519
633
  // Get a specific channel
520
634
  const channel = await client.external_channels.get('channel-123');
521
635
  ```
636
+
637
+ ### Model Costs
638
+
639
+ The `costs` client provides an offline utility to calculate costs for LLM usage based on token counts:
640
+
641
+ ```ts
642
+ import { type ModelCostInput } from '@kaiban/sdk';
643
+
644
+ // Calculate costs for multiple model usages
645
+ const usages: ModelCostInput[] = [
646
+ {
647
+ model: 'gpt-4o',
648
+ inputTokens: 1500,
649
+ outputTokens: 500,
650
+ reasoningTokens: 200, // Optional: reasoning tokens for models that support it
651
+ },
652
+ {
653
+ model: 'gpt-4o-mini',
654
+ inputTokens: 3000,
655
+ outputTokens: 1000,
656
+ },
657
+ ];
658
+
659
+ const result = client.costs.calculateCosts(usages);
660
+
661
+ console.log('Total cost:', result.totalCost); // Total cost in dollars
662
+ console.log('Total tokens:', result.totalTokens); // Total tokens used
663
+
664
+ // Get detailed costs per model
665
+ result.costsByModel.forEach((modelCost) => {
666
+ console.log(`Model: ${modelCost.model}`);
667
+ console.log(` Input tokens: ${modelCost.inputTokens}`);
668
+ console.log(` Output tokens: ${modelCost.outputTokens}`);
669
+ console.log(` Reasoning tokens: ${modelCost.reasoningTokens}`);
670
+ console.log(` Charged output tokens: ${modelCost.chargedOutputTokens}`); // output + reasoning
671
+ console.log(` Total tokens: ${modelCost.totalTokens}`);
672
+ console.log(` Input cost: $${modelCost.inputCost.toFixed(6)}`);
673
+ console.log(` Output cost: $${modelCost.outputCost.toFixed(6)}`);
674
+ console.log(` Total cost: $${modelCost.totalCost.toFixed(6)}`);
675
+ });
676
+ ```
677
+
678
+ Supported models and their pricing (per 1M tokens):
679
+
680
+ - **gpt-4o**: $5.00 input, $20.00 output
681
+ - **gpt-4o-mini**: $0.60 input, $2.40 output
682
+ - **gpt-5**: $1.50 input, $10.00 output
683
+ - **gpt-5-mini**: $0.25 input, $2.00 output
684
+ - **gpt-5-nano**: $0.05 input, $0.40 output
685
+ - **text-embedding-3-small**: $0.02 input, $0.00 output
686
+
687
+ **Note:** Reasoning tokens (when provided) are billed as output tokens.
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./lib/client"), exports);
18
+ __exportStar(require("./lib/http/errors"), exports);
19
+ __exportStar(require("./lib/http/types"), exports);
20
+ __exportStar(require("./types/entities"), exports);
21
+ __exportStar(require("./types/responses"), exports);
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createKaibanClient = createKaibanClient;
4
+ const HttpClient_1 = require("./http/HttpClient");
5
+ const ActivitiesClient_1 = require("./resources/ActivitiesClient");
6
+ const AgentsClient_1 = require("./resources/AgentsClient");
7
+ const BoardsClient_1 = require("./resources/BoardsClient");
8
+ const CardsClient_1 = require("./resources/CardsClient");
9
+ const ExternalChannelsClient_1 = require("./resources/ExternalChannelsClient");
10
+ const ModelCost_1 = require("./resources/ModelCost");
11
+ const ResourcesClient_1 = require("./resources/ResourcesClient");
12
+ const TeamMembersClient_1 = require("./resources/TeamMembersClient");
13
+ const TeamsClient_1 = require("./resources/TeamsClient");
14
+ /**
15
+ * Create a Kaiban SDK client instance
16
+ *
17
+ * @param config - Client configuration object
18
+ * @param config.tenant - The tenant identifier for your Kaiban instance
19
+ * @param config.token - Optional bearer token for authentication
20
+ * @param config.baseUrl - Optional custom base URL for the API
21
+ * @param config.maxRetries - Optional maximum number of request retries (default: 3)
22
+ * @param config.timeout - Optional request timeout in milliseconds (default: 30000)
23
+ *
24
+ * @returns A configured Kaiban client instance
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * import { createKaibanClient } from 'kaiban-sdk';
29
+ *
30
+ * const client = createKaibanClient({
31
+ * tenant: 'my-tenant',
32
+ * token: 'my-auth-token',
33
+ * baseUrl: 'https://api.kaiban.ai'
34
+ * });
35
+ *
36
+ * // List all agents
37
+ * const agents = await client.agents.list();
38
+ * ```
39
+ *
40
+ * @category Client
41
+ */
42
+ function createKaibanClient(config) {
43
+ const http = new HttpClient_1.HttpClient(config);
44
+ return {
45
+ setToken: (t) => http.setToken(t),
46
+ agents: new AgentsClient_1.AgentsClient(http),
47
+ cards: new CardsClient_1.CardsClient(http),
48
+ activities: new ActivitiesClient_1.ActivitiesClient(http),
49
+ teams: new TeamsClient_1.TeamsClient(http),
50
+ teamMembers: new TeamMembersClient_1.TeamMembersClient(http),
51
+ boards: new BoardsClient_1.BoardsClient(http),
52
+ resources: new ResourcesClient_1.ResourcesClient(http),
53
+ external_channels: new ExternalChannelsClient_1.ExternalChannelsClient(http),
54
+ costs: new ModelCost_1.ModelCost(),
55
+ };
56
+ }
@@ -0,0 +1,243 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HttpClient = void 0;
4
+ const errors_1 = require("./errors");
5
+ function buildQuery(query) {
6
+ if (!query)
7
+ return '';
8
+ const params = new URLSearchParams();
9
+ for (const [k, v] of Object.entries(query)) {
10
+ if (v !== undefined && v !== null)
11
+ params.append(k, String(v));
12
+ }
13
+ const qs = params.toString();
14
+ return qs ? `?${qs}` : '';
15
+ }
16
+ function sleep(ms) {
17
+ return new Promise((r) => setTimeout(r, ms));
18
+ }
19
+ class HttpClient {
20
+ constructor(config) {
21
+ const defaultRetry = {
22
+ maxAttempts: 3,
23
+ backoffMs: 250,
24
+ maxBackoffMs: 4000,
25
+ jitter: true,
26
+ retryOn: [429, 500, 502, 503, 504],
27
+ retryMethods: ['GET', 'PUT', 'DELETE'],
28
+ };
29
+ const baseUrl = config.baseUrl || `https://${config.tenant}.kaiban.io/api`;
30
+ this.config = {
31
+ tenant: config.tenant,
32
+ token: config.token,
33
+ baseUrl,
34
+ timeoutMs: config.timeoutMs ?? 30000,
35
+ retry: {
36
+ ...defaultRetry,
37
+ ...(config.retry || {}),
38
+ retryOn: [
39
+ ...(Array.isArray((config.retry || {}).retryOn)
40
+ ? (config.retry || {}).retryOn
41
+ : defaultRetry.retryOn),
42
+ ],
43
+ retryMethods: [
44
+ ...(Array.isArray((config.retry || {}).retryMethods)
45
+ ? (config.retry || {}).retryMethods
46
+ : defaultRetry.retryMethods),
47
+ ],
48
+ },
49
+ fetch: config.fetch || fetch,
50
+ onRequest: config.onRequest || (() => { }),
51
+ onResponse: config.onResponse || (() => { }),
52
+ };
53
+ this._token = config.token;
54
+ // Normalize retry config with required fields for internal use
55
+ const r = this.config.retry;
56
+ this.retryCfg = {
57
+ maxAttempts: r.maxAttempts ?? defaultRetry.maxAttempts,
58
+ backoffMs: r.backoffMs ?? defaultRetry.backoffMs,
59
+ maxBackoffMs: r.maxBackoffMs ?? defaultRetry.maxBackoffMs,
60
+ jitter: r.jitter ?? defaultRetry.jitter,
61
+ retryOn: Array.isArray(r.retryOn) ? r.retryOn : defaultRetry.retryOn,
62
+ retryMethods: Array.isArray(r.retryMethods) ? r.retryMethods : defaultRetry.retryMethods,
63
+ };
64
+ }
65
+ setToken(token) {
66
+ this._token = token;
67
+ }
68
+ async attempt(fn, retryCfg) {
69
+ const { maxAttempts = 3, backoffMs = 250, maxBackoffMs = 4000, jitter = true } = retryCfg;
70
+ let attempt = 0;
71
+ let delay = backoffMs;
72
+ while (true) {
73
+ try {
74
+ return await fn();
75
+ }
76
+ catch (err) {
77
+ attempt++;
78
+ if (attempt >= maxAttempts)
79
+ throw err;
80
+ const wait = jitter ? Math.min(maxBackoffMs, delay * (1 + Math.random())) : delay;
81
+ await sleep(wait);
82
+ delay = Math.min(maxBackoffMs, delay * 2);
83
+ }
84
+ }
85
+ }
86
+ async request(method, path, body, options) {
87
+ const normalizedPath = path.startsWith('/v1') ? path : `/v1${path}`;
88
+ const url = `${this.config.baseUrl}${normalizedPath}${buildQuery(options?.query)}`;
89
+ const headers = {
90
+ 'content-type': 'application/json',
91
+ 'x-tenant': this.config.tenant,
92
+ ...(this._token ? { authorization: `Bearer ${this._token}` } : {}),
93
+ ...(options?.headers || {}),
94
+ };
95
+ // Compose abort signals: user-provided and timeout
96
+ const combinedController = new AbortController();
97
+ const userSignal = options?.signal;
98
+ let timedOut = false;
99
+ const timeout = setTimeout(() => {
100
+ timedOut = true;
101
+ combinedController.abort();
102
+ }, options?.timeoutMs ?? this.config.timeoutMs);
103
+ const onUserAbort = () => combinedController.abort();
104
+ if (userSignal) {
105
+ if (userSignal.aborted) {
106
+ // propagate immediately
107
+ combinedController.abort();
108
+ }
109
+ else {
110
+ userSignal.addEventListener('abort', onUserAbort);
111
+ }
112
+ }
113
+ const init = {
114
+ method,
115
+ headers,
116
+ body: body !== undefined ? JSON.stringify(body) : undefined,
117
+ signal: combinedController.signal,
118
+ };
119
+ this.config.onRequest({ method, url, init });
120
+ const doFetch = async () => {
121
+ try {
122
+ const res = await this.config.fetch(url, init);
123
+ this.config.onResponse({ status: res.status, url, response: res });
124
+ let parsed;
125
+ const contentType = res.headers.get('content-type') || '';
126
+ if (contentType.includes('application/json')) {
127
+ try {
128
+ parsed = await res.json();
129
+ }
130
+ catch {
131
+ parsed = undefined;
132
+ }
133
+ }
134
+ else {
135
+ parsed = await res.text();
136
+ }
137
+ if (!res.ok) {
138
+ throw (0, errors_1.mapHttpToSdkError)(res.status, parsed);
139
+ }
140
+ return parsed;
141
+ }
142
+ catch (e) {
143
+ if (isAbortError(e)) {
144
+ if (timedOut)
145
+ throw new errors_1.TimeoutError();
146
+ throw new errors_1.AbortedError();
147
+ }
148
+ throw e;
149
+ }
150
+ finally {
151
+ clearTimeout(timeout);
152
+ if (userSignal)
153
+ userSignal.removeEventListener('abort', onUserAbort);
154
+ }
155
+ };
156
+ const retryCfg = mergeRetryConfig(this.retryCfg, options?.retry);
157
+ const shouldRetry = (err) => {
158
+ const methodUpper = method.toUpperCase();
159
+ const retryableByMethod = retryCfg.retryMethods?.includes(methodUpper);
160
+ if (!retryableByMethod)
161
+ return false;
162
+ if (err instanceof errors_1.TimeoutError)
163
+ return true;
164
+ // Retry on known transient SDK errors
165
+ if (err instanceof errors_1.RateLimitError)
166
+ return retryCfg.retryOn?.includes(429) ?? false;
167
+ if (err instanceof errors_1.UnavailableError)
168
+ return retryCfg.retryOn?.some((c) => c === 502 || c === 503 || c === 504) ?? false;
169
+ if (err instanceof errors_1.ServerError)
170
+ return retryCfg.retryOn?.includes(500) ?? false;
171
+ return false;
172
+ };
173
+ return await this.attempt(async () => {
174
+ try {
175
+ return await doFetch();
176
+ }
177
+ catch (err) {
178
+ if (shouldRetry(err))
179
+ throw err;
180
+ throw err;
181
+ }
182
+ }, retryCfg);
183
+ }
184
+ get(path, options) {
185
+ return this.request('GET', path, undefined, options);
186
+ }
187
+ post(path, body, options) {
188
+ return this.request('POST', path, body, options);
189
+ }
190
+ put(path, body, options) {
191
+ return this.request('PUT', path, body, options);
192
+ }
193
+ delete(path, options) {
194
+ return this.request('DELETE', path, undefined, options);
195
+ }
196
+ list(path, listParams, options) {
197
+ const queryParams = {};
198
+ if (listParams) {
199
+ // Handle pagination
200
+ if (listParams.limit)
201
+ queryParams.limit = listParams.limit;
202
+ if (listParams.before)
203
+ queryParams.before = listParams.before;
204
+ if (listParams.after)
205
+ queryParams.after = listParams.after;
206
+ // Handle sorting (already a string)
207
+ if (listParams.order_by)
208
+ queryParams.order_by = listParams.order_by;
209
+ // Handle filters
210
+ if (listParams.filters) {
211
+ Object.entries(listParams.filters).forEach(([key, value]) => {
212
+ queryParams[key] = value;
213
+ });
214
+ }
215
+ // Handle metadata filters for cards
216
+ if (listParams.metadata) {
217
+ Object.entries(listParams.metadata).forEach(([key, value]) => {
218
+ queryParams[`metadata.${key}`] = value;
219
+ });
220
+ }
221
+ }
222
+ return this.request('GET', path, undefined, { ...options, query: queryParams });
223
+ }
224
+ }
225
+ exports.HttpClient = HttpClient;
226
+ function isAbortError(e) {
227
+ if (!e)
228
+ return false;
229
+ const anyErr = e;
230
+ return anyErr && anyErr.name === 'AbortError';
231
+ }
232
+ function mergeRetryConfig(base, override) {
233
+ if (!override)
234
+ return base;
235
+ return {
236
+ maxAttempts: override.maxAttempts ?? base.maxAttempts,
237
+ backoffMs: override.backoffMs ?? base.backoffMs,
238
+ maxBackoffMs: override.maxBackoffMs ?? base.maxBackoffMs,
239
+ jitter: override.jitter ?? base.jitter,
240
+ retryOn: override.retryOn ? [...override.retryOn] : base.retryOn,
241
+ retryMethods: override.retryMethods ? [...override.retryMethods] : base.retryMethods,
242
+ };
243
+ }