@sensu-ai/sdk 0.1.2 → 0.1.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sensu-ai/sdk",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "type": "module",
5
5
  "main": "./src/index.ts",
6
6
  "exports": {
package/src/client.ts CHANGED
@@ -8,6 +8,20 @@ import type {
8
8
  TrackToolOptions,
9
9
  RawLlmCallOptions,
10
10
  ContextBreakdown,
11
+ TrackRetrievalOptions,
12
+ RawRetrievalOptions,
13
+ TrackEmbeddingOptions,
14
+ RawEmbeddingOptions,
15
+ RecordFeedbackOptions,
16
+ RecordEvalScoreOptions,
17
+ HandoffOptions,
18
+ SpawnRunOptions,
19
+ TrackGuardrailOptions,
20
+ RawGuardrailOptions,
21
+ RecordPromptRenderOptions,
22
+ DeployPromptVersionOptions,
23
+ StartSessionOptions,
24
+ ResumeSessionOptions,
11
25
  } from './types.js';
12
26
 
13
27
  // ---------------------------------------------------------------------------
@@ -157,6 +171,171 @@ export class StepHandle {
157
171
  return result;
158
172
  }
159
173
 
174
+ /** Track a retrieval call — wraps fn(), measures latency, emits started + completed */
175
+ async trackRetrieval(opts: TrackRetrievalOptions): Promise<unknown> {
176
+ const startMs = Date.now();
177
+ const spanId = randomUUID();
178
+
179
+ this.client.enqueue({
180
+ ...this.base(),
181
+ span_id: spanId,
182
+ event_type: 'retrieval.started',
183
+ vector_store_id: opts.vectorStoreId,
184
+ top_k: opts.topK,
185
+ });
186
+
187
+ let result: unknown;
188
+ let status: 'success' | 'error' = 'success';
189
+ let err: unknown;
190
+
191
+ try {
192
+ result = await opts.fn();
193
+ } catch (e) {
194
+ status = 'error';
195
+ err = e;
196
+ }
197
+
198
+ const latencyMs = Date.now() - startMs;
199
+
200
+ this.client.enqueue({
201
+ ...this.base(),
202
+ span_id: spanId,
203
+ event_type: 'retrieval.completed',
204
+ vector_store_id: opts.vectorStoreId,
205
+ top_k: opts.topK,
206
+ latency_ms: latencyMs,
207
+ status,
208
+ });
209
+
210
+ if (err) throw err;
211
+ return result;
212
+ }
213
+
214
+ /** Emit a raw retrieval completed event (when you have the stats already) */
215
+ recordRetrieval(opts: RawRetrievalOptions): void {
216
+ this.client.enqueue({
217
+ ...this.base(),
218
+ event_type: 'retrieval.completed',
219
+ ...opts,
220
+ });
221
+ }
222
+
223
+ /** Track an embedding call — wraps fn(), measures latency */
224
+ async trackEmbedding(opts: TrackEmbeddingOptions): Promise<unknown> {
225
+ const startMs = Date.now();
226
+ let result: unknown;
227
+ let err: unknown;
228
+
229
+ try {
230
+ result = await opts.fn();
231
+ } catch (e) {
232
+ err = e;
233
+ }
234
+
235
+ const latencyMs = Date.now() - startMs;
236
+
237
+ this.client.enqueue({
238
+ ...this.base(),
239
+ event_type: 'embedding.created',
240
+ model: opts.model,
241
+ input_text_length: opts.inputTextLength,
242
+ batch_size: opts.batchSize,
243
+ latency_ms: latencyMs,
244
+ });
245
+
246
+ if (err) throw err;
247
+ return result;
248
+ }
249
+
250
+ /** Emit a raw embedding event */
251
+ recordEmbedding(opts: RawEmbeddingOptions): void {
252
+ this.client.enqueue({
253
+ ...this.base(),
254
+ event_type: 'embedding.created',
255
+ model: opts.model,
256
+ input_text_length: opts.inputTextLength,
257
+ token_count: opts.tokenCount,
258
+ latency_ms: opts.latencyMs,
259
+ cost_usd_estimate: opts.costUsdEstimate,
260
+ batch_size: opts.batchSize,
261
+ });
262
+ }
263
+
264
+ /** Track a guardrail check — wraps fn(), measures latency, handles block */
265
+ async trackGuardrail(opts: TrackGuardrailOptions): Promise<'pass' | 'fail' | 'modified'> {
266
+ const startMs = Date.now();
267
+
268
+ this.client.enqueue({
269
+ ...this.base(),
270
+ event_type: 'guardrail.check.started',
271
+ guardrail_id: opts.guardrailId,
272
+ guardrail_type: opts.guardrailType,
273
+ input_hash: opts.inputHash,
274
+ });
275
+
276
+ let result: 'pass' | 'fail' | 'modified' = 'pass';
277
+ let err: unknown;
278
+
279
+ try {
280
+ result = await opts.fn();
281
+ } catch (e) {
282
+ err = e;
283
+ }
284
+
285
+ const latencyMs = Date.now() - startMs;
286
+
287
+ this.client.enqueue({
288
+ ...this.base(),
289
+ event_type: 'guardrail.check.completed',
290
+ guardrail_id: opts.guardrailId,
291
+ guardrail_type: opts.guardrailType,
292
+ input_hash: opts.inputHash,
293
+ result,
294
+ latency_ms: latencyMs,
295
+ });
296
+
297
+ if (err) throw err;
298
+ return result;
299
+ }
300
+
301
+ /** Emit a raw guardrail result (check or block) */
302
+ recordGuardrail(opts: RawGuardrailOptions): void {
303
+ if (opts.blocked) {
304
+ this.client.enqueue({
305
+ ...this.base(),
306
+ event_type: 'guardrail.blocked',
307
+ guardrail_id: opts.guardrailId,
308
+ guardrail_type: opts.guardrailType,
309
+ input_hash: opts.inputHash,
310
+ block_reason: opts.blockReason,
311
+ severity: opts.severity,
312
+ });
313
+ } else {
314
+ this.client.enqueue({
315
+ ...this.base(),
316
+ event_type: 'guardrail.check.completed',
317
+ guardrail_id: opts.guardrailId,
318
+ guardrail_type: opts.guardrailType,
319
+ input_hash: opts.inputHash,
320
+ result: opts.result,
321
+ latency_ms: opts.latencyMs,
322
+ });
323
+ }
324
+ }
325
+
326
+ /** Record a prompt template render event */
327
+ recordPromptRender(opts: RecordPromptRenderOptions): void {
328
+ this.client.enqueue({
329
+ ...this.base(),
330
+ event_type: 'prompt.rendered',
331
+ template_id: opts.templateId,
332
+ template_version: opts.templateVersion,
333
+ rendered_token_count: opts.renderedTokenCount,
334
+ variable_count: opts.variableCount,
335
+ latency_ms: opts.latencyMs,
336
+ });
337
+ }
338
+
160
339
  async end(): Promise<void> {
161
340
  if (this.ended) return;
162
341
  this.ended = true;
@@ -243,6 +422,41 @@ export class RunHandle {
243
422
  });
244
423
  }
245
424
 
425
+ /** Record user feedback for this run */
426
+ recordFeedback(opts: RecordFeedbackOptions): void {
427
+ this.client.enqueue({
428
+ ...this.base(),
429
+ event_type: 'feedback.received',
430
+ type: opts.type,
431
+ score: opts.score,
432
+ comment: opts.comment,
433
+ end_user_id: opts.endUserId,
434
+ });
435
+ }
436
+
437
+ /** Record an automated eval score for this run */
438
+ recordEvalScore(opts: RecordEvalScoreOptions): void {
439
+ this.client.enqueue({
440
+ ...this.base(),
441
+ event_type: 'eval.score.recorded',
442
+ metric: opts.metric,
443
+ score: opts.score,
444
+ evaluator_id: opts.evaluatorId,
445
+ model_used_for_eval: opts.modelUsedForEval,
446
+ });
447
+ }
448
+
449
+ /** Emit an agent.handoff event from this run to another agent */
450
+ handoff(opts: HandoffOptions): void {
451
+ this.client.enqueue({
452
+ ...this.base(),
453
+ event_type: 'agent.handoff',
454
+ to_agent_id: opts.toAgentId,
455
+ reason: opts.reason,
456
+ context_tokens_transferred: opts.contextTokensTransferred,
457
+ });
458
+ }
459
+
246
460
  async end(status: 'completed' | 'failed' = 'completed'): Promise<void> {
247
461
  if (this.ended) return;
248
462
  this.ended = true;
@@ -363,6 +577,124 @@ export class SensuClient {
363
577
  });
364
578
  }
365
579
 
580
+ /**
581
+ * Spawn a child agent run from within a parent run.
582
+ * Emits `agent.spawned` on the parent and returns a RunHandle for the child.
583
+ */
584
+ spawnRun(parentRun: RunHandle, opts: SpawnRunOptions): RunHandle {
585
+ const childRunId = opts.childRunId ?? randomUUID();
586
+ const childAgentId = opts.childAgentId;
587
+ const sessionId = opts.sessionId ?? parentRun.sessionId;
588
+ const traceId = parentRun.traceId;
589
+ const spanId = randomUUID();
590
+
591
+ // Emit agent.spawned on the parent run
592
+ this.enqueue({
593
+ event_id: randomUUID(),
594
+ event_type: 'agent.spawned',
595
+ timestamp: new Date().toISOString(),
596
+ org_id: this.orgId,
597
+ agent_id: parentRun.agentId,
598
+ session_id: sessionId,
599
+ run_id: parentRun.runId,
600
+ trace_id: traceId,
601
+ span_id: spanId,
602
+ child_run_id: childRunId,
603
+ child_agent_id: childAgentId,
604
+ spawn_reason: opts.spawnReason,
605
+ });
606
+
607
+ // Emit agent.run.started for the child run (child agent emits this itself in practice,
608
+ // but the SDK can also do it on behalf of known child agents)
609
+ this.enqueue({
610
+ event_id: randomUUID(),
611
+ event_type: 'agent.run.started',
612
+ timestamp: new Date().toISOString(),
613
+ org_id: this.orgId,
614
+ agent_id: childAgentId,
615
+ session_id: sessionId,
616
+ run_id: childRunId,
617
+ trace_id: traceId,
618
+ span_id: randomUUID(),
619
+ run_type: opts.runType,
620
+ });
621
+
622
+ return new RunHandle(this, {
623
+ runId: childRunId,
624
+ sessionId,
625
+ agentId: childAgentId,
626
+ orgId: this.orgId,
627
+ traceId,
628
+ spanId,
629
+ });
630
+ }
631
+
632
+ /** Explicitly start a session (sets channel and end_user_id) */
633
+ startSession(opts: StartSessionOptions = {}): string {
634
+ const sessionId = opts.sessionId ?? randomUUID();
635
+ const traceId = randomUUID();
636
+ const spanId = randomUUID();
637
+
638
+ this.enqueue({
639
+ event_id: randomUUID(),
640
+ event_type: 'session.started',
641
+ timestamp: new Date().toISOString(),
642
+ org_id: this.orgId,
643
+ agent_id: this.agentId,
644
+ session_id: sessionId,
645
+ run_id: sessionId, // run_id required by base schema; reuse session_id as placeholder
646
+ trace_id: traceId,
647
+ span_id: spanId,
648
+ channel: opts.channel,
649
+ end_user_id: opts.endUserId,
650
+ });
651
+
652
+ return sessionId;
653
+ }
654
+
655
+ /** Resume a previous session */
656
+ resumeSession(opts: ResumeSessionOptions): string {
657
+ const sessionId = opts.sessionId ?? randomUUID();
658
+ const traceId = randomUUID();
659
+ const spanId = randomUUID();
660
+
661
+ this.enqueue({
662
+ event_id: randomUUID(),
663
+ event_type: 'session.resumed',
664
+ timestamp: new Date().toISOString(),
665
+ org_id: this.orgId,
666
+ agent_id: this.agentId,
667
+ session_id: sessionId,
668
+ run_id: sessionId,
669
+ trace_id: traceId,
670
+ span_id: spanId,
671
+ resumed_from_session_id: opts.resumedFromSessionId,
672
+ channel: opts.channel,
673
+ end_user_id: opts.endUserId,
674
+ });
675
+
676
+ return sessionId;
677
+ }
678
+
679
+ /** Record a prompt version deployment (org-level event, not tied to a run) */
680
+ deployPromptVersion(opts: DeployPromptVersionOptions): void {
681
+ this.enqueue({
682
+ event_id: randomUUID(),
683
+ event_type: 'prompt.version.deployed',
684
+ timestamp: new Date().toISOString(),
685
+ org_id: this.orgId,
686
+ agent_id: this.agentId,
687
+ session_id: 'system',
688
+ run_id: 'system',
689
+ trace_id: randomUUID(),
690
+ span_id: randomUUID(),
691
+ template_id: opts.templateId,
692
+ new_version: opts.newVersion,
693
+ old_version: opts.oldVersion,
694
+ deployed_by: opts.deployedBy,
695
+ });
696
+ }
697
+
366
698
  destroy(): void {
367
699
  if (this.flushTimer) clearInterval(this.flushTimer);
368
700
  }
package/src/index.ts CHANGED
@@ -7,4 +7,18 @@ export type {
7
7
  TrackToolOptions,
8
8
  RawLlmCallOptions,
9
9
  ContextBreakdown,
10
+ TrackRetrievalOptions,
11
+ RawRetrievalOptions,
12
+ TrackEmbeddingOptions,
13
+ RawEmbeddingOptions,
14
+ RecordFeedbackOptions,
15
+ RecordEvalScoreOptions,
16
+ SpawnRunOptions,
17
+ HandoffOptions,
18
+ TrackGuardrailOptions,
19
+ RawGuardrailOptions,
20
+ RecordPromptRenderOptions,
21
+ DeployPromptVersionOptions,
22
+ StartSessionOptions,
23
+ ResumeSessionOptions,
10
24
  } from './types.ts';
package/src/types.ts CHANGED
@@ -77,3 +77,137 @@ export interface RawLlmCallOptions {
77
77
  status?: 'success' | 'error' | 'timeout';
78
78
  contextBreakdown?: ContextBreakdown;
79
79
  }
80
+
81
+ // ---------------------------------------------------------------------------
82
+ // Retrieval & Embedding
83
+ // ---------------------------------------------------------------------------
84
+
85
+ export interface TrackRetrievalOptions {
86
+ /** Wraps the retrieval call and measures latency automatically */
87
+ fn: () => Promise<unknown>;
88
+ vectorStoreId?: string;
89
+ topK?: number;
90
+ }
91
+
92
+ export interface RawRetrievalOptions {
93
+ vectorStoreId?: string;
94
+ topK?: number;
95
+ latencyMs?: number;
96
+ chunksReturned?: number;
97
+ tokensInjected?: number;
98
+ similarityScoreAvg?: number;
99
+ status?: 'success' | 'error';
100
+ }
101
+
102
+ export interface TrackEmbeddingOptions {
103
+ model: string;
104
+ /** Wraps the embedding call and measures latency automatically */
105
+ fn: () => Promise<unknown>;
106
+ inputTextLength?: number;
107
+ batchSize?: number;
108
+ }
109
+
110
+ export interface RawEmbeddingOptions {
111
+ model: string;
112
+ inputTextLength?: number;
113
+ tokenCount?: number;
114
+ latencyMs?: number;
115
+ costUsdEstimate?: number;
116
+ batchSize?: number;
117
+ }
118
+
119
+ // ---------------------------------------------------------------------------
120
+ // Evaluation & Feedback
121
+ // ---------------------------------------------------------------------------
122
+
123
+ export interface RecordFeedbackOptions {
124
+ type: 'thumbs_up' | 'thumbs_down' | 'score' | 'correction';
125
+ score?: number;
126
+ comment?: string;
127
+ endUserId?: string;
128
+ }
129
+
130
+ export interface RecordEvalScoreOptions {
131
+ metric: string;
132
+ score: number;
133
+ evaluatorId?: string;
134
+ modelUsedForEval?: string;
135
+ }
136
+
137
+ // ---------------------------------------------------------------------------
138
+ // Multi-Agent
139
+ // ---------------------------------------------------------------------------
140
+
141
+ export interface SpawnRunOptions {
142
+ childAgentId: string;
143
+ childRunId?: string;
144
+ spawnReason?: string;
145
+ /** Options forwarded to the child RunHandle */
146
+ runType?: string;
147
+ sessionId?: string;
148
+ }
149
+
150
+ export interface HandoffOptions {
151
+ toAgentId: string;
152
+ reason?: string;
153
+ contextTokensTransferred?: number;
154
+ }
155
+
156
+ // ---------------------------------------------------------------------------
157
+ // Guardrails
158
+ // ---------------------------------------------------------------------------
159
+
160
+ export interface TrackGuardrailOptions {
161
+ guardrailId: string;
162
+ guardrailType?: 'content' | 'pii' | 'jailbreak' | 'custom';
163
+ inputHash?: string;
164
+ /** Wraps the guardrail check and measures latency automatically */
165
+ fn: () => Promise<'pass' | 'fail' | 'modified'>;
166
+ }
167
+
168
+ export interface RawGuardrailOptions {
169
+ guardrailId: string;
170
+ guardrailType?: 'content' | 'pii' | 'jailbreak' | 'custom';
171
+ inputHash?: string;
172
+ result?: 'pass' | 'fail' | 'modified';
173
+ blockReason?: string;
174
+ severity?: 'low' | 'medium' | 'high';
175
+ latencyMs?: number;
176
+ blocked?: boolean;
177
+ }
178
+
179
+ // ---------------------------------------------------------------------------
180
+ // Prompt Management
181
+ // ---------------------------------------------------------------------------
182
+
183
+ export interface RecordPromptRenderOptions {
184
+ templateId: string;
185
+ templateVersion?: string;
186
+ renderedTokenCount?: number;
187
+ variableCount?: number;
188
+ latencyMs?: number;
189
+ }
190
+
191
+ export interface DeployPromptVersionOptions {
192
+ templateId: string;
193
+ newVersion: string;
194
+ oldVersion?: string;
195
+ deployedBy?: string;
196
+ }
197
+
198
+ // ---------------------------------------------------------------------------
199
+ // Session Lifecycle
200
+ // ---------------------------------------------------------------------------
201
+
202
+ export interface StartSessionOptions {
203
+ sessionId?: string;
204
+ channel?: 'web' | 'api' | 'mobile';
205
+ endUserId?: string;
206
+ }
207
+
208
+ export interface ResumeSessionOptions {
209
+ sessionId?: string;
210
+ resumedFromSessionId: string;
211
+ channel?: 'web' | 'api' | 'mobile';
212
+ endUserId?: string;
213
+ }