@observyze/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.
@@ -0,0 +1,440 @@
1
+ import { SpanType, TokenUsage, Span as Span$1, TraceStatus, Trace as Trace$1 } from '@observyze/types';
2
+
3
+ /**
4
+ * SDK Configuration and Types
5
+ */
6
+
7
+ /**
8
+ * Configuration for Observyze SDK client
9
+ */
10
+ interface ClientConfig {
11
+ /**
12
+ * API key for authentication with Observyze Ingestion Service
13
+ */
14
+ apiKey: string;
15
+ /**
16
+ * Endpoint URL for the Ingestion Service
17
+ * @default 'http://localhost:3001'
18
+ */
19
+ endpoint?: string;
20
+ /**
21
+ * Maximum number of traces to buffer before flushing
22
+ * @default 100
23
+ */
24
+ batchSize?: number;
25
+ /**
26
+ * Time in milliseconds to wait before auto-flushing buffered traces
27
+ * @default 5000
28
+ */
29
+ flushInterval?: number;
30
+ /**
31
+ * Enable automatic instrumentation of popular LLM libraries
32
+ * @default true
33
+ */
34
+ enableAutoInstrumentation?: boolean;
35
+ /**
36
+ * Organization ID (optional, can be extracted from API key)
37
+ */
38
+ organizationId?: string;
39
+ /**
40
+ * Project ID for trace attribution
41
+ */
42
+ projectId?: string;
43
+ /**
44
+ * Enable debug logging
45
+ * @default false
46
+ */
47
+ debug?: boolean;
48
+ /**
49
+ * Dry run mode - don't send traces to server (useful for testing)
50
+ * @default false
51
+ */
52
+ dryRun?: boolean;
53
+ /**
54
+ * Phase 5: Automatically scrub PII from trace output before network transmission
55
+ * @default true
56
+ */
57
+ enablePiiRedaction?: boolean;
58
+ /**
59
+ * Phase 4: Autonomous Circuit Breaker
60
+ * Hallucination score threshold (0-1) above which execution is blocked
61
+ * @default 0.8
62
+ */
63
+ hallucinationThreshold?: number;
64
+ /**
65
+ * Phase 4: Autonomous Circuit Breaker
66
+ * Safety score threshold (0-1) above which execution is blocked
67
+ * @default 0.9
68
+ */
69
+ safetyThreshold?: number;
70
+ /**
71
+ * Minimum confidence threshold for circuit breaker blocking (0-1).
72
+ * If confidence is below this threshold, high scores trigger alert-only instead of halt.
73
+ * @default 0.4
74
+ */
75
+ confidenceThreshold?: number;
76
+ /**
77
+ * Evaluation service URL for real-time guardrail checks
78
+ * In production, this should be https://api.observyze.com
79
+ * @default 'http://localhost:3000'
80
+ */
81
+ evalEndpoint?: string;
82
+ /**
83
+ * Enable circuit breaker - block execution on high hallucination/safety scores
84
+ * @default true
85
+ */
86
+ enableCircuitBreaker?: boolean;
87
+ /**
88
+ * Fail closed when evaluation service is unreachable.
89
+ * If true, guardrail checks will block execution on errors (safe default).
90
+ * If false, guardrail checks will allow execution on errors (fail open).
91
+ * @default true
92
+ */
93
+ failClosed?: boolean;
94
+ /**
95
+ * Automatically redirect LLM client (OpenAI, Anthropic) base URLs to Observyze proxy gateway
96
+ * to ensure Redis-backed circuit breakers are enforced.
97
+ * @default true
98
+ */
99
+ enableProxyRedirect?: boolean;
100
+ }
101
+ /**
102
+ * Internal configuration with defaults applied
103
+ */
104
+ interface ResolvedClientConfig extends Required<ClientConfig> {
105
+ }
106
+ /**
107
+ * Result of a guardrail evaluation check.
108
+ * score is null when evaluation could not be performed.
109
+ */
110
+ interface GuardrailResult {
111
+ pass: boolean;
112
+ /** The hallucination score (0-1), or null if evaluation failed */
113
+ score: number | null;
114
+ /** Confidence in the evaluation score (0-1), null if unavailable */
115
+ confidence?: number | null;
116
+ /** The safety score (0-1), or null if evaluation failed */
117
+ safetyScore?: number | null;
118
+ /** Human-readable reason for the result */
119
+ reason?: string;
120
+ /** How the evaluation was performed */
121
+ evaluationSource?: 'live' | 'consensus' | 'nli_fast_path' | 'error' | 'disabled' | 'fallback';
122
+ /** Why a live evaluation didn't happen (only set when evaluationSource is 'error' or 'fallback') */
123
+ fallbackReason?: string;
124
+ }
125
+
126
+ /**
127
+ * Trace and Span classes for capturing AI workflow execution
128
+ */
129
+
130
+ /**
131
+ * Represents an individual operation within a trace
132
+ */
133
+ declare class Span {
134
+ private data;
135
+ private startTime;
136
+ constructor(name: string, type: SpanType, parentSpanId?: string);
137
+ /**
138
+ * Set the input data for this span
139
+ */
140
+ setInput(input: any): this;
141
+ /**
142
+ * Set the output data for this span
143
+ */
144
+ setOutput(output: any): this;
145
+ /**
146
+ * Record an error that occurred during span execution
147
+ */
148
+ setError(error: Error): this;
149
+ /**
150
+ * Set metadata for this span
151
+ */
152
+ setMetadata(key: string, value: any): this;
153
+ /**
154
+ * Set multiple metadata fields at once
155
+ */
156
+ setMetadataAll(metadata: Record<string, any>): this;
157
+ /**
158
+ * Set token usage information
159
+ */
160
+ setTokens(tokens: TokenUsage): this;
161
+ /**
162
+ * End the span and calculate duration
163
+ */
164
+ end(): void;
165
+ /**
166
+ * Get the span ID
167
+ */
168
+ get id(): string;
169
+ /**
170
+ * Get the span data for serialization
171
+ */
172
+ toJSON(): Span$1;
173
+ }
174
+ /**
175
+ * Represents a complete AI workflow execution
176
+ */
177
+ declare class Trace {
178
+ private data;
179
+ private startTime;
180
+ private spans;
181
+ private ended;
182
+ constructor(name: string, organizationId: string, projectId?: string);
183
+ /**
184
+ * Start a new span within this trace
185
+ */
186
+ startSpan(name: string, type: SpanType, parentSpanId?: string): Span;
187
+ /**
188
+ * Add metadata to the trace
189
+ */
190
+ setMetadata(key: string, value: any): this;
191
+ /**
192
+ * Set multiple metadata fields at once
193
+ */
194
+ setMetadataAll(metadata: Record<string, any>): this;
195
+ /**
196
+ * Add tags to the trace
197
+ */
198
+ addTag(tag: string): this;
199
+ /**
200
+ * Add multiple tags at once
201
+ */
202
+ addTags(tags: string[]): this;
203
+ /**
204
+ * Set the user ID associated with this trace
205
+ */
206
+ setUserId(userId: string): this;
207
+ /**
208
+ * Set the session ID associated with this trace
209
+ */
210
+ setSessionId(sessionId: string): this;
211
+ /**
212
+ * End the trace with a final status
213
+ */
214
+ end(status?: TraceStatus): void;
215
+ /**
216
+ * Get the trace ID
217
+ */
218
+ get id(): string;
219
+ /**
220
+ * Check if the trace has ended
221
+ */
222
+ get isEnded(): boolean;
223
+ /**
224
+ * Get the trace data for serialization
225
+ */
226
+ toJSON(): Omit<Trace$1, '_id' | 'created_at' | 'updated_at'>;
227
+ }
228
+
229
+ /**
230
+ * Auto-Instrumentation API
231
+ * Provides nw.wrap() API for instrumenting LLM clients
232
+ */
233
+
234
+ /**
235
+ * Supported client types for auto-instrumentation
236
+ */
237
+ type SupportedClient = {
238
+ chat: {
239
+ completions: {
240
+ create: Function;
241
+ };
242
+ };
243
+ } | {
244
+ messages: {
245
+ create: Function;
246
+ };
247
+ };
248
+ /**
249
+ * Detect the type of LLM client and apply appropriate instrumentation
250
+ */
251
+ declare function wrap<T extends SupportedClient>(client: T, nwClient: ObservyzeClient): T;
252
+
253
+ /**
254
+ * Observyze SDK Client
255
+ * Main entry point for instrumenting AI applications
256
+ */
257
+
258
+ /**
259
+ * Main SDK client for Observyze
260
+ */
261
+ declare class ObservyzeClient {
262
+ private config;
263
+ private traceBuffer;
264
+ private flushTimer;
265
+ private isShuttingDown;
266
+ private readonly MAX_QUEUE_SIZE;
267
+ private readonly RETRY_DELAYS;
268
+ /**
269
+ * Parse a JSON API error response and extract trace_id, error code, and message.
270
+ * The api-gateway error handler includes these fields in every error response.
271
+ */
272
+ private static parseApiError;
273
+ /**
274
+ * Format an API error into a user-friendly message with trace_id for correlation.
275
+ * Example output:
276
+ * "Observyze API error (401 [ref: err_a1b2c3d4]): MISSING_PROVIDER_KEY — No API key configured..."
277
+ */
278
+ private static formatApiError;
279
+ constructor(config: ClientConfig);
280
+ /**
281
+ * Start a new trace
282
+ */
283
+ startTrace(name: string, metadata?: Record<string, any>): Trace;
284
+ /**
285
+ * Buffer a completed trace for batch sending
286
+ */
287
+ private bufferTrace;
288
+ /**
289
+ * Start the auto-flush timer
290
+ */
291
+ private startFlushTimer;
292
+ /**
293
+ * Flush all buffered traces to the Ingestion Service
294
+ */
295
+ flush(): Promise<void>;
296
+ /**
297
+ * Send traces with exponential backoff retry
298
+ */
299
+ private sendWithRetry;
300
+ /**
301
+ * Shutdown the SDK and flush remaining traces
302
+ */
303
+ shutdown(): Promise<void>;
304
+ /**
305
+ * Get current buffer size
306
+ */
307
+ get bufferSize(): number;
308
+ /**
309
+ * Get SDK configuration
310
+ */
311
+ getConfig(): Readonly<ResolvedClientConfig>;
312
+ /**
313
+ * Wrap an LLM client (OpenAI, Anthropic) to enable auto-instrumentation
314
+ *
315
+ * @example
316
+ * ```typescript
317
+ * import OpenAI from 'openai'
318
+ * import { ObservyzeClient } from '@observyze/sdk'
319
+ *
320
+ * const nw = new ObservyzeClient({ apiKey: 'your-api-key' })
321
+ * const openai = new OpenAI({ apiKey: 'openai-key' })
322
+ *
323
+ * // Wrap the client to enable auto-instrumentation
324
+ * nw.wrap(openai)
325
+ *
326
+ * // All calls are now automatically traced
327
+ * const response = await openai.chat.completions.create({
328
+ * model: 'gpt-4',
329
+ * messages: [{ role: 'user', content: 'Hello!' }]
330
+ * })
331
+ * ```
332
+ */
333
+ wrap<T extends SupportedClient>(client: T): T;
334
+ /**
335
+ * Sync local agent .history file to Observyze cloud
336
+ * Parses JSON/NDJSON agent history and sends to ingestion endpoint.
337
+ */
338
+ syncLocalHistory(filePath: string): Promise<void>;
339
+ /**
340
+ * Industry-grade PII Redaction (Compliance & RBAC)
341
+ *
342
+ * Recursively scrubs PII from trace data before transmission to the cloud.
343
+ * Coverage: emails, JWTs, bearer tokens, AWS/API keys, SSNs, credit cards,
344
+ * phone numbers (US + E.164), IPv4/IPv6, passport numbers, ZIP codes, plus
345
+ * key-based redaction for sensitive JSON fields (password, token, api_key, etc.).
346
+ *
347
+ * Design:
348
+ * - Pure function, never mutates the original object
349
+ * - Depth-limited to 16 levels to prevent stack overflow on deep agent outputs
350
+ * - Key-aware: sensitive key names are fully redacted regardless of value format
351
+ */
352
+ private static readonly PII_PATTERNS;
353
+ private static readonly SENSITIVE_KEYS;
354
+ private static isSensitiveKey;
355
+ private sanitizePII;
356
+ /**
357
+ * Phase 4: Autonomous Circuit Breakers (Requirement 4.1)
358
+ * Evaluate a trace or text for hallucination in real-time.
359
+ * If hallucination score > hallucinationThreshold, the SDK blocks execution.
360
+ *
361
+ * Returns GuardrailResult with score: null when evaluation couldn't be performed.
362
+ * In failClosed mode, null scores result in blocked execution.
363
+ * In failOpen mode, null scores allow execution through.
364
+ */
365
+ checkGuardrails(content: string | any): Promise<GuardrailResult>;
366
+ /**
367
+ * Phase 4: Autonomous Circuit Breakers
368
+ * Execute an agent action wrapped with the Circuit Breaker.
369
+ * Pauses execution if hallucination score >= hallucinationThreshold and requests human review.
370
+ * @throws Error when execution is blocked by circuit breaker
371
+ */
372
+ executeWithCircuitBreaker<T>(agentExecution: () => Promise<T>, traceContext?: any): Promise<T>;
373
+ /**
374
+ * Phase 4: Bug Bounty Protocol (Automated) (Requirement 4.2)
375
+ * Automatically shard persistent failure cases to external security researcher endpoints (e.g. HackerOne wrapper)
376
+ */
377
+ reportBugBounty(traceId: string, securityEndpoint: string, failureContext: any): Promise<void>;
378
+ }
379
+
380
+ /**
381
+ * Observyze OpenTelemetry Span Exporter
382
+ *
383
+ * Implements `@opentelemetry/sdk-trace-base`'s `SpanExporter` interface
384
+ * so users can use the standard OTel Node.js SDK and export spans to
385
+ * the Observyze platform.
386
+ *
387
+ * Usage:
388
+ * ```typescript
389
+ * import { ObservyzeClient } from '@observyze/sdk'
390
+ * import { ObservyzeSpanExporter } from '@observyze/sdk/opentelemetry'
391
+ * import { NodeSDK } from '@opentelemetry/sdk-node'
392
+ * import { BatchSpanProcessor } from '@opentelemetry/sdk-trace-base'
393
+ *
394
+ * const nw = new ObservyzeClient({ apiKey: 'nw_...' })
395
+ *
396
+ * const sdk = new NodeSDK({
397
+ * spanProcessor: new BatchSpanProcessor(
398
+ * new ObservyzeSpanExporter(nw, { serviceName: 'my-app' })
399
+ * )
400
+ * })
401
+ * sdk.start()
402
+ * ```
403
+ */
404
+
405
+ /**
406
+ * Exporter configuration
407
+ */
408
+ interface ObservyzeExporterConfig {
409
+ serviceName?: string;
410
+ projectId?: string;
411
+ defaultSpanType?: SpanType | 'llm' | 'tool' | 'agent' | 'chain' | 'retrieval';
412
+ headers?: Record<string, string>;
413
+ }
414
+ /**
415
+ * Observyze OpenTelemetry Span Exporter
416
+ */
417
+ declare class ObservyzeSpanExporter {
418
+ private client;
419
+ private config;
420
+ constructor(client: ObservyzeClient, config?: ObservyzeExporterConfig);
421
+ /**
422
+ * Export spans — called by OTel SDK when spans are ready.
423
+ * Converts OTel spans to Observyze traces and buffers them.
424
+ */
425
+ export(spans: any[], resultCallback: (result: {
426
+ code: number;
427
+ error?: Error;
428
+ }) => void): Promise<void>;
429
+ /**
430
+ * Called when the exporter is shut down.
431
+ * Flushes any remaining buffered traces via the SDK client.
432
+ */
433
+ shutdown(): Promise<void>;
434
+ /**
435
+ * Called by the OTel SDK to force-export buffered spans.
436
+ */
437
+ forceFlush(): Promise<void>;
438
+ }
439
+
440
+ export { type ClientConfig as C, ObservyzeClient as O, type ResolvedClientConfig as R, Span as S, Trace as T, type ObservyzeExporterConfig as a, ObservyzeSpanExporter as b, type SupportedClient as c, wrap as w };