@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.
- package/README.md +187 -21
- package/dist/cjs/index.js +21 -0
- package/dist/cjs/lib/client.js +56 -0
- package/dist/cjs/lib/http/HttpClient.js +243 -0
- package/dist/cjs/lib/http/errors.js +143 -0
- package/dist/cjs/lib/http/types.js +2 -0
- package/dist/cjs/lib/resources/ActivitiesClient.js +164 -0
- package/dist/cjs/lib/resources/AgentsClient.js +224 -0
- package/dist/cjs/lib/resources/BoardsClient.js +120 -0
- package/dist/cjs/lib/resources/CardsClient.js +352 -0
- package/dist/cjs/lib/resources/ExternalChannelsClient.js +78 -0
- package/dist/cjs/lib/resources/ModelCost.js +87 -0
- package/dist/cjs/lib/resources/ResourcesClient.js +78 -0
- package/dist/cjs/lib/resources/TeamMembersClient.js +102 -0
- package/dist/cjs/lib/resources/TeamsClient.js +96 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/test/helpers/mockFetch.js +27 -0
- package/dist/cjs/types/entities/a2a-dataparts.js +17 -0
- package/dist/cjs/types/entities/activities.js +72 -0
- package/dist/cjs/types/entities/agent.js +28 -0
- package/dist/cjs/types/entities/board.js +2 -0
- package/dist/cjs/types/entities/card.js +29 -0
- package/dist/cjs/types/entities/costs.js +2 -0
- package/dist/cjs/types/entities/external-channel.js +19 -0
- package/dist/cjs/types/entities/index.js +25 -0
- package/dist/cjs/types/entities/resource.js +10 -0
- package/dist/cjs/types/entities/shared.js +3 -0
- package/dist/cjs/types/entities/team.js +2 -0
- package/dist/cjs/types/entities.js +17 -0
- package/dist/cjs/types/responses.js +2 -0
- package/dist/esm/index.js +5 -0
- package/dist/{lib → esm/lib}/client.js +11 -9
- package/dist/{lib → esm/lib}/http/HttpClient.js +1 -1
- package/dist/{lib → esm/lib}/resources/AgentsClient.js +28 -0
- package/dist/{lib → esm/lib}/resources/BoardsClient.js +42 -0
- package/dist/{lib → esm/lib}/resources/CardsClient.js +1 -1
- package/dist/esm/lib/resources/TeamMembersClient.js +98 -0
- package/dist/{types → esm/types}/entities/activities.js +9 -13
- package/dist/esm/types/entities/index.js +9 -0
- package/dist/esm/types/entities.js +1 -0
- package/dist/esm/types/requests.js +19 -0
- package/dist/{lib → types/lib}/client.d.ts +3 -0
- package/dist/{lib → types/lib}/resources/AgentsClient.d.ts +26 -0
- package/dist/{lib → types/lib}/resources/BoardsClient.d.ts +34 -1
- package/dist/types/lib/resources/TeamMembersClient.d.ts +89 -0
- package/dist/types/{entities → types/entities}/activities.d.ts +14 -3
- package/dist/types/{entities → types/entities}/agent.d.ts +18 -10
- package/dist/types/{entities → types/entities}/board.d.ts +16 -5
- package/dist/types/{entities → types/entities}/card.d.ts +22 -13
- package/dist/types/{entities → types/entities}/external-channel.d.ts +1 -1
- package/dist/types/{entities → types/entities}/team.d.ts +4 -2
- package/package.json +18 -9
- package/dist/index.js +0 -5
- package/dist/types/entities/index.js +0 -9
- package/dist/types/entities.js +0 -1
- /package/dist/{types → cjs/types}/requests.js +0 -0
- /package/dist/{lib → esm/lib}/http/errors.js +0 -0
- /package/dist/{lib → esm/lib}/http/types.js +0 -0
- /package/dist/{lib → esm/lib}/resources/ActivitiesClient.js +0 -0
- /package/dist/{lib → esm/lib}/resources/ExternalChannelsClient.js +0 -0
- /package/dist/{lib → esm/lib}/resources/ModelCost.js +0 -0
- /package/dist/{lib → esm/lib}/resources/ResourcesClient.js +0 -0
- /package/dist/{lib → esm/lib}/resources/TeamsClient.js +0 -0
- /package/dist/{test → esm/test}/helpers/mockFetch.js +0 -0
- /package/dist/{types → esm/types}/entities/a2a-dataparts.js +0 -0
- /package/dist/{types → esm/types}/entities/agent.js +0 -0
- /package/dist/{types → esm/types}/entities/board.js +0 -0
- /package/dist/{types → esm/types}/entities/card.js +0 -0
- /package/dist/{types → esm/types}/entities/costs.js +0 -0
- /package/dist/{types → esm/types}/entities/external-channel.js +0 -0
- /package/dist/{types → esm/types}/entities/resource.js +0 -0
- /package/dist/{types → esm/types}/entities/shared.js +0 -0
- /package/dist/{types → esm/types}/entities/team.js +0 -0
- /package/dist/{types → esm/types}/responses.js +0 -0
- /package/dist/{index.d.ts → types/index.d.ts} +0 -0
- /package/dist/{lib → types/lib}/http/HttpClient.d.ts +0 -0
- /package/dist/{lib → types/lib}/http/errors.d.ts +0 -0
- /package/dist/{lib → types/lib}/http/types.d.ts +0 -0
- /package/dist/{lib → types/lib}/resources/ActivitiesClient.d.ts +0 -0
- /package/dist/{lib → types/lib}/resources/CardsClient.d.ts +0 -0
- /package/dist/{lib → types/lib}/resources/ExternalChannelsClient.d.ts +0 -0
- /package/dist/{lib → types/lib}/resources/ModelCost.d.ts +0 -0
- /package/dist/{lib → types/lib}/resources/ResourcesClient.d.ts +0 -0
- /package/dist/{lib → types/lib}/resources/TeamsClient.d.ts +0 -0
- /package/dist/{test → types/test}/helpers/mockFetch.d.ts +0 -0
- /package/dist/types/{entities → types/entities}/a2a-dataparts.d.ts +0 -0
- /package/dist/types/{entities → types/entities}/costs.d.ts +0 -0
- /package/dist/types/{entities → types/entities}/index.d.ts +0 -0
- /package/dist/types/{entities → types/entities}/resource.d.ts +0 -0
- /package/dist/types/{entities → types/entities}/shared.d.ts +0 -0
- /package/dist/types/{entities.d.ts → types/entities.d.ts} +0 -0
- /package/dist/types/{requests.d.ts → types/requests.d.ts} +0 -0
- /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: '
|
|
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
|
|
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
|
-
- **
|
|
96
|
-
- **
|
|
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
|
-
- **
|
|
100
|
-
- **
|
|
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
|
|
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
|
|
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 {
|
|
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.
|
|
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
|
|
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
|
+
}
|