@rustrak/client 0.3.13 → 0.3.14

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/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { z } from 'zod';
2
2
  import ky, { isHTTPError } from 'ky';
3
3
 
4
- // src/resources/alert-integrations.ts
4
+ // src/resources/agents.ts
5
5
  var paginatedResponseSchema = (itemSchema) => z.object({
6
6
  items: z.array(itemSchema),
7
7
  next_cursor: z.string().optional(),
@@ -32,7 +32,29 @@ z.object({
32
32
  message: z.string().optional()
33
33
  });
34
34
 
35
- // src/schemas/alert.ts
35
+ // src/schemas/agent.ts
36
+ var agentTimeseriesPointSchema = z.object({
37
+ bucket: dateTimeSchema,
38
+ value: z.number()
39
+ });
40
+ var agentDurationPointSchema = z.object({
41
+ bucket: dateTimeSchema,
42
+ avg_ms: z.number(),
43
+ p95_ms: z.number()
44
+ });
45
+ var genAiBreakdownRowSchema = z.object({
46
+ label: z.string(),
47
+ value: z.number()
48
+ });
49
+ var agentTraceSummarySchema = z.object({
50
+ trace_id: z.string(),
51
+ /** Every distinct agent that ran in this trace, earliest first. */
52
+ agent_names: z.array(z.string()),
53
+ duration_ms: z.number().nullable(),
54
+ total_tokens: z.number(),
55
+ tool_call_count: z.number().int(),
56
+ started_at: dateTimeSchema
57
+ });
36
58
  var providerTypeSchema = z.enum(["webhook", "email", "slack"]);
37
59
  var alertTypeSchema = z.enum(["new_issue", "regression", "unmute"]);
38
60
  var alertStatusSchema = z.enum([
@@ -48,451 +70,81 @@ var alertIntegrationSchema = z.object({
48
70
  credentials: z.record(z.string(), z.unknown()),
49
71
  is_enabled: z.boolean(),
50
72
  failure_count: z.number().int(),
51
- last_failure_at: dateTimeSchema.nullable(),
52
- last_failure_message: z.string().nullable(),
53
- last_success_at: dateTimeSchema.nullable(),
54
- created_at: dateTimeSchema,
55
- updated_at: dateTimeSchema
56
- });
57
- var createAlertIntegrationSchema = z.object({
58
- name: z.string().min(1),
59
- provider_type: providerTypeSchema,
60
- credentials: z.record(z.string(), z.unknown()),
61
- is_enabled: z.boolean().optional()
62
- });
63
- var updateAlertIntegrationSchema = z.object({
64
- name: z.string().min(1).optional(),
65
- credentials: z.record(z.string(), z.unknown()).optional(),
66
- is_enabled: z.boolean().optional()
67
- });
68
- var alertRuleChannelInputSchema = z.object({
69
- integration_id: z.number().int(),
70
- routing_override: z.record(z.string(), z.unknown()).default({})
71
- });
72
- var alertRuleSchema = z.object({
73
- id: z.number().int(),
74
- project_id: z.number().int(),
75
- name: z.string(),
76
- alert_type: alertTypeSchema,
77
- is_enabled: z.boolean(),
78
- conditions: z.record(z.string(), z.unknown()),
79
- cooldown_minutes: z.number().int(),
80
- last_triggered_at: dateTimeSchema.nullable(),
81
- created_at: dateTimeSchema,
82
- updated_at: dateTimeSchema,
83
- channels: z.array(alertRuleChannelInputSchema).default([]),
84
- integration_ids: z.array(z.number().int())
85
- });
86
- var createAlertRuleSchema = z.object({
87
- name: z.string().min(1),
88
- alert_type: alertTypeSchema,
89
- channels: z.array(alertRuleChannelInputSchema).default([]),
90
- is_enabled: z.boolean().optional(),
91
- conditions: z.record(z.string(), z.unknown()).optional(),
92
- cooldown_minutes: z.number().int().min(0).optional()
93
- });
94
- var updateAlertRuleSchema = z.object({
95
- name: z.string().min(1).optional(),
96
- is_enabled: z.boolean().optional(),
97
- conditions: z.record(z.string(), z.unknown()).optional(),
98
- cooldown_minutes: z.number().int().min(0).optional(),
99
- channels: z.array(alertRuleChannelInputSchema).optional()
100
- });
101
- var alertHistorySchema = z.object({
102
- id: z.number().int(),
103
- alert_rule_id: z.number().int().nullable(),
104
- integration_id: z.number().int().nullable(),
105
- issue_id: z.string().uuid().nullable(),
106
- project_id: z.number().int().nullable(),
107
- alert_type: z.string(),
108
- channel_type: z.string(),
109
- channel_name: z.string(),
110
- status: alertStatusSchema,
111
- attempt_count: z.number().int(),
112
- next_retry_at: dateTimeSchema.nullable(),
113
- error_message: z.string().nullable(),
114
- http_status_code: z.number().int().nullable(),
115
- idempotency_key: z.string(),
116
- created_at: dateTimeSchema,
117
- sent_at: dateTimeSchema.nullable()
118
- });
119
- var testChannelResponseSchema = z.object({
120
- success: z.boolean(),
121
- message: z.string()
122
- });
123
- var testIntegrationBodySchema = z.object({
124
- routing_override: z.record(z.string(), z.unknown()).optional()
125
- });
126
-
127
- // src/errors/base.ts
128
- var RustrakError = class extends Error {
129
- /**
130
- * Whether this error is safe to retry
131
- */
132
- retryable;
133
- /**
134
- * HTTP status code if applicable
135
- */
136
- statusCode;
137
- /**
138
- * Original error cause
139
- */
140
- cause;
141
- constructor(message, options) {
142
- super(message);
143
- this.name = this.constructor.name;
144
- this.retryable = options?.retryable ?? false;
145
- this.statusCode = options?.statusCode;
146
- this.cause = options?.cause;
147
- if (Error.captureStackTrace) {
148
- Error.captureStackTrace(this, this.constructor);
149
- }
150
- }
151
- };
152
-
153
- // src/errors/http.ts
154
- var NetworkError = class extends RustrakError {
155
- constructor(message, cause) {
156
- super(message, { retryable: true, cause });
157
- }
158
- };
159
- var AuthenticationError = class extends RustrakError {
160
- constructor(message = "Authentication failed") {
161
- super(message, { retryable: false, statusCode: 401 });
162
- }
163
- };
164
- var AuthorizationError = class extends RustrakError {
165
- constructor(message = "Insufficient permissions") {
166
- super(message, { retryable: false, statusCode: 403 });
167
- }
168
- };
169
- var NotFoundError = class extends RustrakError {
170
- constructor(resource) {
171
- super(`Resource not found: ${resource}`, {
172
- retryable: false,
173
- statusCode: 404
174
- });
175
- }
176
- };
177
- var RateLimitError = class extends RustrakError {
178
- /**
179
- * Number of seconds to wait before retrying (from Retry-After header)
180
- */
181
- retryAfter;
182
- constructor(message = "Rate limit exceeded", retryAfter) {
183
- super(message, { retryable: true, statusCode: 429 });
184
- if (retryAfter !== void 0) {
185
- this.retryAfter = typeof retryAfter === "string" ? parseInt(retryAfter, 10) : retryAfter;
186
- }
187
- }
188
- };
189
- var ServerError = class extends RustrakError {
190
- constructor(message, statusCode = 500) {
191
- super(message, { retryable: true, statusCode });
192
- }
193
- };
194
- var BadRequestError = class extends RustrakError {
195
- constructor(message) {
196
- super(message, { retryable: false, statusCode: 400 });
197
- }
198
- };
199
-
200
- // src/errors/validation.ts
201
- var ValidationError = class extends RustrakError {
202
- /**
203
- * Zod validation errors
204
- */
205
- validationErrors;
206
- constructor(message, validationErrors) {
207
- super(message, { retryable: false });
208
- this.validationErrors = validationErrors;
209
- }
210
- /**
211
- * Get a formatted string of validation errors
212
- */
213
- getValidationDetails() {
214
- if (!this.validationErrors) {
215
- return this.message;
216
- }
217
- const errors = this.validationErrors.issues.map((err) => `${err.path.map(String).join(".")}: ${err.message}`).join(", ");
218
- return `${this.message} - ${errors}`;
219
- }
220
- };
221
-
222
- // src/resources/base.ts
223
- var BaseResource = class {
224
- http;
225
- constructor(http) {
226
- this.http = http;
227
- }
228
- /**
229
- * Validate API response against Zod schema
230
- * @throws {ValidationError} if validation fails
231
- */
232
- validate(data, schema) {
233
- const result = schema.safeParse(data);
234
- if (!result.success) {
235
- throw new ValidationError("API response validation failed", result.error);
236
- }
237
- return result.data;
238
- }
239
- };
240
-
241
- // src/resources/alert-integrations.ts
242
- var AlertIntegrationsResource = class extends BaseResource {
243
- /**
244
- * List all alert integrations
245
- */
246
- async list() {
247
- const data = await this.http.get("api/integrations").json();
248
- return this.validate(data, z.array(alertIntegrationSchema));
249
- }
250
- /**
251
- * Get a single alert integration by ID
252
- */
253
- async get(id) {
254
- const data = await this.http.get(`api/integrations/${id}`).json();
255
- return this.validate(data, alertIntegrationSchema);
256
- }
257
- /**
258
- * Create a new alert integration
259
- */
260
- async create(input) {
261
- const validatedInput = this.validate(input, createAlertIntegrationSchema);
262
- const data = await this.http.post("api/integrations", { json: validatedInput }).json();
263
- return this.validate(data, alertIntegrationSchema);
264
- }
265
- /**
266
- * Update an existing alert integration
267
- */
268
- async update(id, input) {
269
- const validatedInput = this.validate(input, updateAlertIntegrationSchema);
270
- const data = await this.http.patch(`api/integrations/${id}`, { json: validatedInput }).json();
271
- return this.validate(data, alertIntegrationSchema);
272
- }
273
- /**
274
- * Delete an alert integration
275
- */
276
- async delete(id) {
277
- await this.http.delete(`api/integrations/${id}`);
278
- }
279
- /**
280
- * Send a test notification to verify integration configuration.
281
- * For Slack bot_token integrations, routingOverride must include `channel`.
282
- */
283
- async test(id, routingOverride) {
284
- const body = routingOverride !== void 0 ? this.validate(
285
- { routing_override: routingOverride },
286
- testIntegrationBodySchema
287
- ) : void 0;
288
- const data = await this.http.post(
289
- `api/integrations/${id}/test`,
290
- body !== void 0 ? { json: body } : void 0
291
- ).json();
292
- return this.validate(data, testChannelResponseSchema);
293
- }
294
- };
295
- var AlertRulesResource = class extends BaseResource {
296
- /**
297
- * List all alert rules for a project
298
- */
299
- async list(projectId) {
300
- const data = await this.http.get(`api/projects/${projectId}/alert-rules`).json();
301
- return this.validate(data, z.array(alertRuleSchema));
302
- }
303
- /**
304
- * Get a single alert rule by ID
305
- */
306
- async get(projectId, ruleId) {
307
- const data = await this.http.get(`api/projects/${projectId}/alert-rules/${ruleId}`).json();
308
- return this.validate(data, alertRuleSchema);
309
- }
310
- /**
311
- * Create a new alert rule for a project
312
- */
313
- async create(projectId, input) {
314
- const validatedInput = this.validate(input, createAlertRuleSchema);
315
- const data = await this.http.post(`api/projects/${projectId}/alert-rules`, { json: validatedInput }).json();
316
- return this.validate(data, alertRuleSchema);
317
- }
318
- /**
319
- * Update an existing alert rule
320
- */
321
- async update(projectId, ruleId, input) {
322
- const validatedInput = this.validate(input, updateAlertRuleSchema);
323
- const data = await this.http.patch(`api/projects/${projectId}/alert-rules/${ruleId}`, {
324
- json: validatedInput
325
- }).json();
326
- return this.validate(data, alertRuleSchema);
327
- }
328
- /**
329
- * Delete an alert rule
330
- */
331
- async delete(projectId, ruleId) {
332
- await this.http.delete(`api/projects/${projectId}/alert-rules/${ruleId}`);
333
- }
334
- /**
335
- * List alert history for a project
336
- */
337
- async listHistory(projectId, options) {
338
- const searchParams = new URLSearchParams();
339
- if (options?.limit !== void 0) {
340
- searchParams.set("limit", options.limit.toString());
341
- }
342
- const query = searchParams.toString();
343
- const url = query ? `api/projects/${projectId}/alert-history?${query}` : `api/projects/${projectId}/alert-history`;
344
- const data = await this.http.get(url).json();
345
- return this.validate(data, z.array(alertHistorySchema));
346
- }
347
- };
348
- var globalRoleSchema = z.enum(["admin", "member"]);
349
- var teamMemberSchema = z.object({
350
- id: z.number().int(),
351
- email: z.string().email(),
352
- role: globalRoleSchema,
353
- is_active: z.boolean(),
354
- /** True for the first-registered account, which cannot be demoted or deleted. */
355
- is_primary: z.boolean().optional(),
356
- created_at: dateTimeSchema,
357
- last_login: dateTimeSchema.nullable().optional()
358
- });
359
- var updateUserRoleSchema = z.object({
360
- role: globalRoleSchema
361
- });
362
-
363
- // src/schemas/invitation.ts
364
- var invitationStatusSchema = z.string();
365
- var invitationSchema = z.object({
366
- token: z.string(),
367
- email: z.string().email(),
368
- role: globalRoleSchema,
369
- status: invitationStatusSchema,
370
- expires_at: dateTimeSchema,
371
- created_at: dateTimeSchema
372
- });
373
- var invitationInfoSchema = z.object({
374
- email: z.string().email(),
375
- role: globalRoleSchema,
376
- status: invitationStatusSchema,
377
- expires_at: dateTimeSchema
378
- });
379
- var createInvitationSchema = z.object({
380
- email: z.string().email(),
381
- role: globalRoleSchema
382
- });
383
- var acceptInvitationSchema = z.object({
384
- token: z.string().min(1),
385
- password: z.string().min(1)
386
- });
387
- var userSchema = z.object({
388
- id: z.number().int().positive(),
389
- email: z.string().email(),
390
- role: globalRoleSchema,
391
- is_admin: z.boolean()
392
- });
393
- var authResponseSchema = z.object({
394
- user: userSchema
395
- });
396
- z.object({
397
- user: userSchema,
398
- cookies: z.array(z.string())
399
- });
400
- var loginRequestSchema = z.object({
401
- email: z.string().email(),
402
- password: z.string().min(1)
403
- });
404
- var registerRequestSchema = z.object({
405
- email: z.string().email(),
406
- password: z.string().min(1)
407
- });
408
-
409
- // src/resources/auth.ts
410
- var AuthResource = class extends BaseResource {
411
- /**
412
- * Register a new user account
413
- * Creates a new user and automatically logs them in (sets session cookie)
414
- * @param credentials - Email and password for the new account
415
- * @returns LoginResult with user information and session cookies
416
- */
417
- async register(credentials) {
418
- const validatedInput = this.validate(credentials, registerRequestSchema);
419
- const response = await this.http.post("auth/register", {
420
- json: validatedInput
421
- });
422
- const cookies = response.headers.getSetCookie();
423
- const data = await response.json();
424
- const authResponse = this.validate(data, authResponseSchema);
425
- return {
426
- user: authResponse.user,
427
- cookies
428
- };
429
- }
430
- /**
431
- * Login with email and password
432
- * Authenticates the user and sets a session cookie
433
- * @param credentials - Email and password
434
- * @returns LoginResult with user information and session cookies
435
- */
436
- async login(credentials) {
437
- const validatedInput = this.validate(credentials, loginRequestSchema);
438
- const response = await this.http.post("auth/login", {
439
- json: validatedInput
440
- });
441
- const cookies = response.headers.getSetCookie();
442
- const data = await response.json();
443
- const authResponse = this.validate(data, authResponseSchema);
444
- return {
445
- user: authResponse.user,
446
- cookies
447
- };
448
- }
449
- /**
450
- * Logout the current user
451
- * Clears the session cookie
452
- * @returns Array of Set-Cookie headers (typically clearing cookies)
453
- */
454
- async logout() {
455
- const response = await this.http.post("auth/logout");
456
- return response.headers.getSetCookie();
457
- }
458
- /**
459
- * Get current authenticated user
460
- * Requires a valid session cookie
461
- * @returns User information
462
- */
463
- async getCurrentUser() {
464
- const data = await this.http.get("auth/me").json();
465
- return this.validate(data, userSchema);
466
- }
467
- /**
468
- * Get the details of a pending invitation by its token (public endpoint)
469
- * Used by the accept-invitation page before the user has an account
470
- * @param token - Invitation token
471
- * @returns Invitation info (email, role, status, expiry)
472
- */
473
- async getInvitation(token) {
474
- const data = await this.http.get(`auth/invitation/${token}`).json();
475
- return this.validate(data, invitationInfoSchema);
476
- }
477
- /**
478
- * Accept a pending invitation, creating the user account and logging in
479
- * @param input - Invitation token and the new account's password
480
- * @returns LoginResult with user information and session cookies
481
- */
482
- async acceptInvitation(input) {
483
- const validatedInput = this.validate(input, acceptInvitationSchema);
484
- const response = await this.http.post("auth/accept-invitation", {
485
- json: validatedInput
486
- });
487
- const cookies = response.headers.getSetCookie();
488
- const data = await response.json();
489
- const authResponse = this.validate(data, authResponseSchema);
490
- return {
491
- user: authResponse.user,
492
- cookies
493
- };
494
- }
495
- };
73
+ last_failure_at: dateTimeSchema.nullable(),
74
+ last_failure_message: z.string().nullable(),
75
+ last_success_at: dateTimeSchema.nullable(),
76
+ created_at: dateTimeSchema,
77
+ updated_at: dateTimeSchema
78
+ });
79
+ var createAlertIntegrationSchema = z.object({
80
+ name: z.string().min(1),
81
+ provider_type: providerTypeSchema,
82
+ credentials: z.record(z.string(), z.unknown()),
83
+ is_enabled: z.boolean().optional()
84
+ });
85
+ var updateAlertIntegrationSchema = z.object({
86
+ name: z.string().min(1).optional(),
87
+ credentials: z.record(z.string(), z.unknown()).optional(),
88
+ is_enabled: z.boolean().optional()
89
+ });
90
+ var alertRuleChannelInputSchema = z.object({
91
+ integration_id: z.number().int(),
92
+ routing_override: z.record(z.string(), z.unknown()).default({})
93
+ });
94
+ var alertRuleSchema = z.object({
95
+ id: z.number().int(),
96
+ project_id: z.number().int(),
97
+ name: z.string(),
98
+ alert_type: alertTypeSchema,
99
+ is_enabled: z.boolean(),
100
+ conditions: z.record(z.string(), z.unknown()),
101
+ cooldown_minutes: z.number().int(),
102
+ last_triggered_at: dateTimeSchema.nullable(),
103
+ created_at: dateTimeSchema,
104
+ updated_at: dateTimeSchema,
105
+ channels: z.array(alertRuleChannelInputSchema).default([]),
106
+ integration_ids: z.array(z.number().int())
107
+ });
108
+ var createAlertRuleSchema = z.object({
109
+ name: z.string().min(1),
110
+ alert_type: alertTypeSchema,
111
+ channels: z.array(alertRuleChannelInputSchema).default([]),
112
+ is_enabled: z.boolean().optional(),
113
+ conditions: z.record(z.string(), z.unknown()).optional(),
114
+ cooldown_minutes: z.number().int().min(0).optional()
115
+ });
116
+ var updateAlertRuleSchema = z.object({
117
+ name: z.string().min(1).optional(),
118
+ is_enabled: z.boolean().optional(),
119
+ conditions: z.record(z.string(), z.unknown()).optional(),
120
+ cooldown_minutes: z.number().int().min(0).optional(),
121
+ channels: z.array(alertRuleChannelInputSchema).optional()
122
+ });
123
+ var alertHistorySchema = z.object({
124
+ id: z.number().int(),
125
+ alert_rule_id: z.number().int().nullable(),
126
+ integration_id: z.number().int().nullable(),
127
+ issue_id: z.string().uuid().nullable(),
128
+ project_id: z.number().int().nullable(),
129
+ alert_type: z.string(),
130
+ channel_type: z.string(),
131
+ channel_name: z.string(),
132
+ status: alertStatusSchema,
133
+ attempt_count: z.number().int(),
134
+ next_retry_at: dateTimeSchema.nullable(),
135
+ error_message: z.string().nullable(),
136
+ http_status_code: z.number().int().nullable(),
137
+ idempotency_key: z.string(),
138
+ created_at: dateTimeSchema,
139
+ sent_at: dateTimeSchema.nullable()
140
+ });
141
+ var testChannelResponseSchema = z.object({
142
+ success: z.boolean(),
143
+ message: z.string()
144
+ });
145
+ var testIntegrationBodySchema = z.object({
146
+ routing_override: z.record(z.string(), z.unknown()).optional()
147
+ });
496
148
  var eventSchema = z.object({
497
149
  id: uuidSchema,
498
150
  event_id: eventIdSchema,
@@ -523,6 +175,45 @@ var eventDetailSchema = z.object({
523
175
  data: z.record(z.string(), z.any())
524
176
  // Full Sentry event JSON
525
177
  });
178
+ var globalRoleSchema = z.enum(["admin", "member"]);
179
+ var teamMemberSchema = z.object({
180
+ id: z.number().int(),
181
+ email: z.string().email(),
182
+ role: globalRoleSchema,
183
+ is_active: z.boolean(),
184
+ /** True for the first-registered account, which cannot be demoted or deleted. */
185
+ is_primary: z.boolean().optional(),
186
+ created_at: dateTimeSchema,
187
+ last_login: dateTimeSchema.nullable().optional()
188
+ });
189
+ var updateUserRoleSchema = z.object({
190
+ role: globalRoleSchema
191
+ });
192
+
193
+ // src/schemas/invitation.ts
194
+ var invitationStatusSchema = z.string();
195
+ var invitationSchema = z.object({
196
+ token: z.string(),
197
+ email: z.string().email(),
198
+ role: globalRoleSchema,
199
+ status: invitationStatusSchema,
200
+ expires_at: dateTimeSchema,
201
+ created_at: dateTimeSchema
202
+ });
203
+ var invitationInfoSchema = z.object({
204
+ email: z.string().email(),
205
+ role: globalRoleSchema,
206
+ status: invitationStatusSchema,
207
+ expires_at: dateTimeSchema
208
+ });
209
+ var createInvitationSchema = z.object({
210
+ email: z.string().email(),
211
+ role: globalRoleSchema
212
+ });
213
+ var acceptInvitationSchema = z.object({
214
+ token: z.string().min(1),
215
+ password: z.string().min(1)
216
+ });
526
217
  var issueStatusSchema = z.enum(["unresolved", "resolved", "ignored"]);
527
218
  var issuePrioritySchema = z.enum(["low", "medium", "high"]);
528
219
  var issueSchema = z.object({
@@ -826,6 +517,8 @@ var transactionDetailSchema = z.object({
826
517
  });
827
518
  var spanSchema = z.object({
828
519
  id: uuidSchema,
520
+ /** Parent transaction, if this span was extracted from one. `null` for a standalone span. */
521
+ transaction_id: uuidSchema.nullable(),
829
522
  span_id: z.string().nullable(),
830
523
  trace_id: z.string().nullable(),
831
524
  parent_span_id: z.string().nullable(),
@@ -837,7 +530,21 @@ var spanSchema = z.object({
837
530
  duration_ms: z.number().nullable(),
838
531
  exclusive_time_ms: z.number().nullable(),
839
532
  is_segment: z.boolean(),
840
- segment_id: z.string().nullable()
533
+ segment_id: z.string().nullable(),
534
+ /** Only ever set for standalone spans — a transaction-embedded span has no parent row to inherit these from. */
535
+ platform: z.string().nullable(),
536
+ release: z.string().nullable(),
537
+ environment: z.string().nullable(),
538
+ /** gen_ai.* denormalized fields — all null unless recognized as an AI span. */
539
+ gen_ai_operation_type: z.string().nullable(),
540
+ gen_ai_agent_name: z.string().nullable(),
541
+ gen_ai_request_model: z.string().nullable(),
542
+ gen_ai_response_model: z.string().nullable(),
543
+ gen_ai_tool_name: z.string().nullable(),
544
+ gen_ai_conversation_id: z.string().nullable(),
545
+ gen_ai_usage_input_tokens: z.number().nullable(),
546
+ gen_ai_usage_output_tokens: z.number().nullable(),
547
+ gen_ai_usage_total_tokens: z.number().nullable()
841
548
  });
842
549
  var transactionStatsSchema = z.object({
843
550
  transaction_name: z.string(),
@@ -848,6 +555,422 @@ var transactionStatsSchema = z.object({
848
555
  p99_ms: z.number(),
849
556
  failure_rate: z.number()
850
557
  });
558
+ var userSchema = z.object({
559
+ id: z.number().int().positive(),
560
+ email: z.string().email(),
561
+ role: globalRoleSchema,
562
+ is_admin: z.boolean()
563
+ });
564
+ var authResponseSchema = z.object({
565
+ user: userSchema
566
+ });
567
+ z.object({
568
+ user: userSchema,
569
+ cookies: z.array(z.string())
570
+ });
571
+ var loginRequestSchema = z.object({
572
+ email: z.string().email(),
573
+ password: z.string().min(1)
574
+ });
575
+ var registerRequestSchema = z.object({
576
+ email: z.string().email(),
577
+ password: z.string().min(1)
578
+ });
579
+
580
+ // src/errors/base.ts
581
+ var RustrakError = class extends Error {
582
+ /**
583
+ * Whether this error is safe to retry
584
+ */
585
+ retryable;
586
+ /**
587
+ * HTTP status code if applicable
588
+ */
589
+ statusCode;
590
+ /**
591
+ * Original error cause
592
+ */
593
+ cause;
594
+ constructor(message, options) {
595
+ super(message);
596
+ this.name = this.constructor.name;
597
+ this.retryable = options?.retryable ?? false;
598
+ this.statusCode = options?.statusCode;
599
+ this.cause = options?.cause;
600
+ if (Error.captureStackTrace) {
601
+ Error.captureStackTrace(this, this.constructor);
602
+ }
603
+ }
604
+ };
605
+
606
+ // src/errors/http.ts
607
+ var NetworkError = class extends RustrakError {
608
+ constructor(message, cause) {
609
+ super(message, { retryable: true, cause });
610
+ }
611
+ };
612
+ var AuthenticationError = class extends RustrakError {
613
+ constructor(message = "Authentication failed") {
614
+ super(message, { retryable: false, statusCode: 401 });
615
+ }
616
+ };
617
+ var AuthorizationError = class extends RustrakError {
618
+ constructor(message = "Insufficient permissions") {
619
+ super(message, { retryable: false, statusCode: 403 });
620
+ }
621
+ };
622
+ var NotFoundError = class extends RustrakError {
623
+ constructor(resource) {
624
+ super(`Resource not found: ${resource}`, {
625
+ retryable: false,
626
+ statusCode: 404
627
+ });
628
+ }
629
+ };
630
+ var RateLimitError = class extends RustrakError {
631
+ /**
632
+ * Number of seconds to wait before retrying (from Retry-After header)
633
+ */
634
+ retryAfter;
635
+ constructor(message = "Rate limit exceeded", retryAfter) {
636
+ super(message, { retryable: true, statusCode: 429 });
637
+ if (retryAfter !== void 0) {
638
+ this.retryAfter = typeof retryAfter === "string" ? parseInt(retryAfter, 10) : retryAfter;
639
+ }
640
+ }
641
+ };
642
+ var ServerError = class extends RustrakError {
643
+ constructor(message, statusCode = 500) {
644
+ super(message, { retryable: true, statusCode });
645
+ }
646
+ };
647
+ var BadRequestError = class extends RustrakError {
648
+ constructor(message) {
649
+ super(message, { retryable: false, statusCode: 400 });
650
+ }
651
+ };
652
+
653
+ // src/errors/validation.ts
654
+ var ValidationError = class extends RustrakError {
655
+ /**
656
+ * Zod validation errors
657
+ */
658
+ validationErrors;
659
+ constructor(message, validationErrors) {
660
+ super(message, { retryable: false });
661
+ this.validationErrors = validationErrors;
662
+ }
663
+ /**
664
+ * Get a formatted string of validation errors
665
+ */
666
+ getValidationDetails() {
667
+ if (!this.validationErrors) {
668
+ return this.message;
669
+ }
670
+ const errors = this.validationErrors.issues.map((err) => `${err.path.map(String).join(".")}: ${err.message}`).join(", ");
671
+ return `${this.message} - ${errors}`;
672
+ }
673
+ };
674
+
675
+ // src/resources/base.ts
676
+ var BaseResource = class {
677
+ http;
678
+ constructor(http) {
679
+ this.http = http;
680
+ }
681
+ /**
682
+ * Validate API response against Zod schema
683
+ * @throws {ValidationError} if validation fails
684
+ */
685
+ validate(data, schema) {
686
+ const result = schema.safeParse(data);
687
+ if (!result.success) {
688
+ throw new ValidationError("API response validation failed", result.error);
689
+ }
690
+ return result.data;
691
+ }
692
+ };
693
+
694
+ // src/resources/agents.ts
695
+ function timeseriesSearchParams(options) {
696
+ const searchParams = {};
697
+ if (options?.period_hours) {
698
+ searchParams.period_hours = String(options.period_hours);
699
+ }
700
+ if (options?.interval_hours) {
701
+ searchParams.interval_hours = String(options.interval_hours);
702
+ }
703
+ return searchParams;
704
+ }
705
+ function breakdownSearchParams(options) {
706
+ const searchParams = {};
707
+ if (options?.period_hours) {
708
+ searchParams.period_hours = String(options.period_hours);
709
+ }
710
+ if (options?.limit) {
711
+ searchParams.limit = String(options.limit);
712
+ }
713
+ return searchParams;
714
+ }
715
+ var AgentsResource = class extends BaseResource {
716
+ /**
717
+ * Time-bucketed count of agent-run spans (`gen_ai.operation.type:agent`).
718
+ */
719
+ async getRuns(projectId, options) {
720
+ const data = await this.http.get(`api/projects/${projectId}/agents/runs`, {
721
+ searchParams: timeseriesSearchParams(options)
722
+ }).json();
723
+ return this.validate(data, z.array(agentTimeseriesPointSchema));
724
+ }
725
+ /**
726
+ * Time-bucketed avg/p95 duration for `agent`/`ai_client` spans.
727
+ */
728
+ async getDuration(projectId, options) {
729
+ const data = await this.http.get(`api/projects/${projectId}/agents/duration`, {
730
+ searchParams: timeseriesSearchParams(options)
731
+ }).json();
732
+ return this.validate(data, z.array(agentDurationPointSchema));
733
+ }
734
+ /**
735
+ * Top models by LLM call count (`gen_ai.operation.type:ai_client`).
736
+ */
737
+ async getModelsByCalls(projectId, options) {
738
+ const data = await this.http.get(`api/projects/${projectId}/agents/models/calls`, {
739
+ searchParams: breakdownSearchParams(options)
740
+ }).json();
741
+ return this.validate(data, z.array(genAiBreakdownRowSchema));
742
+ }
743
+ /**
744
+ * Top models by total tokens used (`gen_ai.operation.type:ai_client`).
745
+ */
746
+ async getModelsByTokens(projectId, options) {
747
+ const data = await this.http.get(`api/projects/${projectId}/agents/models/tokens`, {
748
+ searchParams: breakdownSearchParams(options)
749
+ }).json();
750
+ return this.validate(data, z.array(genAiBreakdownRowSchema));
751
+ }
752
+ /**
753
+ * Top tools by call count (`gen_ai.operation.type:tool`).
754
+ */
755
+ async getTools(projectId, options) {
756
+ const data = await this.http.get(`api/projects/${projectId}/agents/tools`, {
757
+ searchParams: breakdownSearchParams(options)
758
+ }).json();
759
+ return this.validate(data, z.array(genAiBreakdownRowSchema));
760
+ }
761
+ /**
762
+ * Paginated per-trace_id aggregate (duration, tokens, tool usage) across
763
+ * all AI spans sharing that trace, regardless of origin.
764
+ */
765
+ async getTraces(projectId, options) {
766
+ const searchParams = {};
767
+ if (options?.page) {
768
+ searchParams.page = String(options.page);
769
+ }
770
+ if (options?.per_page) {
771
+ searchParams.per_page = String(options.per_page);
772
+ }
773
+ const data = await this.http.get(`api/projects/${projectId}/agents/traces`, { searchParams }).json();
774
+ return this.validate(
775
+ data,
776
+ offsetPaginatedResponseSchema(agentTraceSummarySchema)
777
+ );
778
+ }
779
+ };
780
+ var AlertIntegrationsResource = class extends BaseResource {
781
+ /**
782
+ * List all alert integrations
783
+ */
784
+ async list() {
785
+ const data = await this.http.get("api/integrations").json();
786
+ return this.validate(data, z.array(alertIntegrationSchema));
787
+ }
788
+ /**
789
+ * Get a single alert integration by ID
790
+ */
791
+ async get(id) {
792
+ const data = await this.http.get(`api/integrations/${id}`).json();
793
+ return this.validate(data, alertIntegrationSchema);
794
+ }
795
+ /**
796
+ * Create a new alert integration
797
+ */
798
+ async create(input) {
799
+ const validatedInput = this.validate(input, createAlertIntegrationSchema);
800
+ const data = await this.http.post("api/integrations", { json: validatedInput }).json();
801
+ return this.validate(data, alertIntegrationSchema);
802
+ }
803
+ /**
804
+ * Update an existing alert integration
805
+ */
806
+ async update(id, input) {
807
+ const validatedInput = this.validate(input, updateAlertIntegrationSchema);
808
+ const data = await this.http.patch(`api/integrations/${id}`, { json: validatedInput }).json();
809
+ return this.validate(data, alertIntegrationSchema);
810
+ }
811
+ /**
812
+ * Delete an alert integration
813
+ */
814
+ async delete(id) {
815
+ await this.http.delete(`api/integrations/${id}`);
816
+ }
817
+ /**
818
+ * Send a test notification to verify integration configuration.
819
+ * For Slack bot_token integrations, routingOverride must include `channel`.
820
+ */
821
+ async test(id, routingOverride) {
822
+ const body = routingOverride !== void 0 ? this.validate(
823
+ { routing_override: routingOverride },
824
+ testIntegrationBodySchema
825
+ ) : void 0;
826
+ const data = await this.http.post(
827
+ `api/integrations/${id}/test`,
828
+ body !== void 0 ? { json: body } : void 0
829
+ ).json();
830
+ return this.validate(data, testChannelResponseSchema);
831
+ }
832
+ };
833
+ var AlertRulesResource = class extends BaseResource {
834
+ /**
835
+ * List all alert rules for a project
836
+ */
837
+ async list(projectId) {
838
+ const data = await this.http.get(`api/projects/${projectId}/alert-rules`).json();
839
+ return this.validate(data, z.array(alertRuleSchema));
840
+ }
841
+ /**
842
+ * Get a single alert rule by ID
843
+ */
844
+ async get(projectId, ruleId) {
845
+ const data = await this.http.get(`api/projects/${projectId}/alert-rules/${ruleId}`).json();
846
+ return this.validate(data, alertRuleSchema);
847
+ }
848
+ /**
849
+ * Create a new alert rule for a project
850
+ */
851
+ async create(projectId, input) {
852
+ const validatedInput = this.validate(input, createAlertRuleSchema);
853
+ const data = await this.http.post(`api/projects/${projectId}/alert-rules`, { json: validatedInput }).json();
854
+ return this.validate(data, alertRuleSchema);
855
+ }
856
+ /**
857
+ * Update an existing alert rule
858
+ */
859
+ async update(projectId, ruleId, input) {
860
+ const validatedInput = this.validate(input, updateAlertRuleSchema);
861
+ const data = await this.http.patch(`api/projects/${projectId}/alert-rules/${ruleId}`, {
862
+ json: validatedInput
863
+ }).json();
864
+ return this.validate(data, alertRuleSchema);
865
+ }
866
+ /**
867
+ * Delete an alert rule
868
+ */
869
+ async delete(projectId, ruleId) {
870
+ await this.http.delete(`api/projects/${projectId}/alert-rules/${ruleId}`);
871
+ }
872
+ /**
873
+ * List alert history for a project
874
+ */
875
+ async listHistory(projectId, options) {
876
+ const searchParams = new URLSearchParams();
877
+ if (options?.limit !== void 0) {
878
+ searchParams.set("limit", options.limit.toString());
879
+ }
880
+ const query = searchParams.toString();
881
+ const url = query ? `api/projects/${projectId}/alert-history?${query}` : `api/projects/${projectId}/alert-history`;
882
+ const data = await this.http.get(url).json();
883
+ return this.validate(data, z.array(alertHistorySchema));
884
+ }
885
+ };
886
+
887
+ // src/resources/auth.ts
888
+ var AuthResource = class extends BaseResource {
889
+ /**
890
+ * Register a new user account
891
+ * Creates a new user and automatically logs them in (sets session cookie)
892
+ * @param credentials - Email and password for the new account
893
+ * @returns LoginResult with user information and session cookies
894
+ */
895
+ async register(credentials) {
896
+ const validatedInput = this.validate(credentials, registerRequestSchema);
897
+ const response = await this.http.post("auth/register", {
898
+ json: validatedInput
899
+ });
900
+ const cookies = response.headers.getSetCookie();
901
+ const data = await response.json();
902
+ const authResponse = this.validate(data, authResponseSchema);
903
+ return {
904
+ user: authResponse.user,
905
+ cookies
906
+ };
907
+ }
908
+ /**
909
+ * Login with email and password
910
+ * Authenticates the user and sets a session cookie
911
+ * @param credentials - Email and password
912
+ * @returns LoginResult with user information and session cookies
913
+ */
914
+ async login(credentials) {
915
+ const validatedInput = this.validate(credentials, loginRequestSchema);
916
+ const response = await this.http.post("auth/login", {
917
+ json: validatedInput
918
+ });
919
+ const cookies = response.headers.getSetCookie();
920
+ const data = await response.json();
921
+ const authResponse = this.validate(data, authResponseSchema);
922
+ return {
923
+ user: authResponse.user,
924
+ cookies
925
+ };
926
+ }
927
+ /**
928
+ * Logout the current user
929
+ * Clears the session cookie
930
+ * @returns Array of Set-Cookie headers (typically clearing cookies)
931
+ */
932
+ async logout() {
933
+ const response = await this.http.post("auth/logout");
934
+ return response.headers.getSetCookie();
935
+ }
936
+ /**
937
+ * Get current authenticated user
938
+ * Requires a valid session cookie
939
+ * @returns User information
940
+ */
941
+ async getCurrentUser() {
942
+ const data = await this.http.get("auth/me").json();
943
+ return this.validate(data, userSchema);
944
+ }
945
+ /**
946
+ * Get the details of a pending invitation by its token (public endpoint)
947
+ * Used by the accept-invitation page before the user has an account
948
+ * @param token - Invitation token
949
+ * @returns Invitation info (email, role, status, expiry)
950
+ */
951
+ async getInvitation(token) {
952
+ const data = await this.http.get(`auth/invitation/${token}`).json();
953
+ return this.validate(data, invitationInfoSchema);
954
+ }
955
+ /**
956
+ * Accept a pending invitation, creating the user account and logging in
957
+ * @param input - Invitation token and the new account's password
958
+ * @returns LoginResult with user information and session cookies
959
+ */
960
+ async acceptInvitation(input) {
961
+ const validatedInput = this.validate(input, acceptInvitationSchema);
962
+ const response = await this.http.post("auth/accept-invitation", {
963
+ json: validatedInput
964
+ });
965
+ const cookies = response.headers.getSetCookie();
966
+ const data = await response.json();
967
+ const authResponse = this.validate(data, authResponseSchema);
968
+ return {
969
+ user: authResponse.user,
970
+ cookies
971
+ };
972
+ }
973
+ };
851
974
 
852
975
  // src/resources/events.ts
853
976
  var EventsResource = class extends BaseResource {
@@ -1324,6 +1447,37 @@ var SourceMapsResource = class extends BaseResource {
1324
1447
  return this.validate(data, listSourceMapsResponseSchema);
1325
1448
  }
1326
1449
  };
1450
+
1451
+ // src/resources/spans.ts
1452
+ var SpansResource = class extends BaseResource {
1453
+ /**
1454
+ * List spans for a project with offset-based pagination (newest first),
1455
+ * optionally filtered by op/status/trace_id/operation_type.
1456
+ */
1457
+ async list(projectId, options) {
1458
+ const searchParams = {};
1459
+ if (options?.page) {
1460
+ searchParams.page = String(options.page);
1461
+ }
1462
+ if (options?.per_page) {
1463
+ searchParams.per_page = String(options.per_page);
1464
+ }
1465
+ if (options?.op) {
1466
+ searchParams.op = options.op;
1467
+ }
1468
+ if (options?.status) {
1469
+ searchParams.status = options.status;
1470
+ }
1471
+ if (options?.trace_id) {
1472
+ searchParams.trace_id = options.trace_id;
1473
+ }
1474
+ if (options?.operation_type) {
1475
+ searchParams.operation_type = options.operation_type;
1476
+ }
1477
+ const data = await this.http.get(`api/projects/${projectId}/spans`, { searchParams }).json();
1478
+ return this.validate(data, offsetPaginatedResponseSchema(spanSchema));
1479
+ }
1480
+ };
1327
1481
  var StorageResource = class extends BaseResource {
1328
1482
  /**
1329
1483
  * Get the instance-wide storage summary: row counts per data category, the
@@ -1652,6 +1806,14 @@ var RustrakClient = class {
1652
1806
  * Logs API resource (standalone logs)
1653
1807
  */
1654
1808
  logs;
1809
+ /**
1810
+ * Spans API resource (standalone + transaction-embedded spans, shared table)
1811
+ */
1812
+ spans;
1813
+ /**
1814
+ * AI Agent Monitoring dashboard API resource
1815
+ */
1816
+ agents;
1655
1817
  /**
1656
1818
  * Storage API resource (usage + retention cleanup, admin only)
1657
1819
  */
@@ -1682,6 +1844,8 @@ var RustrakClient = class {
1682
1844
  this.releases = new ReleasesResource(this.http);
1683
1845
  this.transactions = new TransactionsResource(this.http);
1684
1846
  this.logs = new LogsResource(this.http);
1847
+ this.spans = new SpansResource(this.http);
1848
+ this.agents = new AgentsResource(this.http);
1685
1849
  this.storage = new StorageResource(this.http);
1686
1850
  this.health = new HealthResource(this.http);
1687
1851
  }