@rustrak/client 0.3.13 → 0.3.15

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