@juspay/neurolink 9.23.0 → 9.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (225) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +10 -13
  3. package/dist/adapters/tts/googleTTSHandler.js +26 -1
  4. package/dist/adapters/video/vertexVideoHandler.js +23 -17
  5. package/dist/cli/commands/config.d.ts +3 -3
  6. package/dist/cli/commands/observability.d.ts +53 -0
  7. package/dist/cli/commands/observability.js +453 -0
  8. package/dist/cli/commands/telemetry.d.ts +63 -0
  9. package/dist/cli/commands/telemetry.js +689 -0
  10. package/dist/cli/factories/commandFactory.d.ts +34 -0
  11. package/dist/cli/factories/commandFactory.js +321 -116
  12. package/dist/cli/parser.js +6 -9
  13. package/dist/cli/utils/formatters.d.ts +13 -0
  14. package/dist/cli/utils/formatters.js +23 -0
  15. package/dist/constants/contextWindows.js +6 -0
  16. package/dist/constants/enums.d.ts +6 -0
  17. package/dist/constants/enums.js +8 -2
  18. package/dist/context/budgetChecker.js +75 -48
  19. package/dist/context/contextCompactor.js +135 -127
  20. package/dist/core/baseProvider.d.ts +5 -0
  21. package/dist/core/baseProvider.js +158 -102
  22. package/dist/core/conversationMemoryInitializer.js +7 -4
  23. package/dist/core/conversationMemoryManager.d.ts +2 -0
  24. package/dist/core/conversationMemoryManager.js +6 -2
  25. package/dist/core/modules/GenerationHandler.d.ts +2 -2
  26. package/dist/core/modules/GenerationHandler.js +12 -12
  27. package/dist/evaluation/ragasEvaluator.js +39 -19
  28. package/dist/evaluation/scoring.js +46 -20
  29. package/dist/features/ppt/index.d.ts +1 -1
  30. package/dist/features/ppt/index.js +1 -1
  31. package/dist/features/ppt/presentationOrchestrator.js +23 -0
  32. package/dist/features/ppt/slideGenerator.js +13 -0
  33. package/dist/features/ppt/slideRenderers.d.ts +1 -1
  34. package/dist/features/ppt/slideRenderers.js +6 -4
  35. package/dist/features/ppt/slideTypeInference.d.ts +1 -1
  36. package/dist/features/ppt/slideTypeInference.js +75 -73
  37. package/dist/files/fileTools.d.ts +6 -6
  38. package/dist/index.d.ts +46 -12
  39. package/dist/index.js +79 -17
  40. package/dist/lib/adapters/tts/googleTTSHandler.js +26 -1
  41. package/dist/lib/adapters/video/vertexVideoHandler.js +23 -17
  42. package/dist/lib/constants/contextWindows.js +6 -0
  43. package/dist/lib/constants/enums.d.ts +6 -0
  44. package/dist/lib/constants/enums.js +8 -2
  45. package/dist/lib/context/budgetChecker.js +75 -48
  46. package/dist/lib/context/contextCompactor.js +135 -127
  47. package/dist/lib/core/baseProvider.d.ts +5 -0
  48. package/dist/lib/core/baseProvider.js +158 -102
  49. package/dist/lib/core/conversationMemoryInitializer.js +7 -4
  50. package/dist/lib/core/conversationMemoryManager.d.ts +2 -0
  51. package/dist/lib/core/conversationMemoryManager.js +6 -2
  52. package/dist/lib/core/modules/GenerationHandler.d.ts +2 -2
  53. package/dist/lib/core/modules/GenerationHandler.js +12 -12
  54. package/dist/lib/evaluation/ragasEvaluator.js +39 -19
  55. package/dist/lib/evaluation/scoring.js +46 -20
  56. package/dist/lib/features/ppt/index.d.ts +1 -1
  57. package/dist/lib/features/ppt/index.js +1 -1
  58. package/dist/lib/features/ppt/presentationOrchestrator.js +23 -0
  59. package/dist/lib/features/ppt/slideGenerator.js +13 -0
  60. package/dist/lib/features/ppt/slideRenderers.d.ts +1 -1
  61. package/dist/lib/features/ppt/slideRenderers.js +6 -4
  62. package/dist/lib/features/ppt/slideTypeInference.d.ts +1 -1
  63. package/dist/lib/features/ppt/slideTypeInference.js +75 -73
  64. package/dist/lib/files/fileTools.d.ts +6 -6
  65. package/dist/lib/index.d.ts +46 -12
  66. package/dist/lib/index.js +79 -17
  67. package/dist/lib/mcp/httpRateLimiter.js +39 -12
  68. package/dist/lib/mcp/httpRetryHandler.js +22 -1
  69. package/dist/lib/mcp/mcpClientFactory.js +13 -15
  70. package/dist/lib/memory/memoryRetrievalTools.js +22 -0
  71. package/dist/lib/neurolink.d.ts +64 -72
  72. package/dist/lib/neurolink.js +984 -566
  73. package/dist/lib/observability/exporterRegistry.d.ts +152 -0
  74. package/dist/lib/observability/exporterRegistry.js +414 -0
  75. package/dist/lib/observability/exporters/arizeExporter.d.ts +32 -0
  76. package/dist/lib/observability/exporters/arizeExporter.js +139 -0
  77. package/dist/lib/observability/exporters/baseExporter.d.ts +117 -0
  78. package/dist/lib/observability/exporters/baseExporter.js +191 -0
  79. package/dist/lib/observability/exporters/braintrustExporter.d.ts +30 -0
  80. package/dist/lib/observability/exporters/braintrustExporter.js +155 -0
  81. package/dist/lib/observability/exporters/datadogExporter.d.ts +37 -0
  82. package/dist/lib/observability/exporters/datadogExporter.js +197 -0
  83. package/dist/lib/observability/exporters/index.d.ts +13 -0
  84. package/dist/lib/observability/exporters/index.js +14 -0
  85. package/dist/lib/observability/exporters/laminarExporter.d.ts +48 -0
  86. package/dist/lib/observability/exporters/laminarExporter.js +303 -0
  87. package/dist/lib/observability/exporters/langfuseExporter.d.ts +47 -0
  88. package/dist/lib/observability/exporters/langfuseExporter.js +200 -0
  89. package/dist/lib/observability/exporters/langsmithExporter.d.ts +26 -0
  90. package/dist/lib/observability/exporters/langsmithExporter.js +124 -0
  91. package/dist/lib/observability/exporters/otelExporter.d.ts +39 -0
  92. package/dist/lib/observability/exporters/otelExporter.js +165 -0
  93. package/dist/lib/observability/exporters/posthogExporter.d.ts +48 -0
  94. package/dist/lib/observability/exporters/posthogExporter.js +288 -0
  95. package/dist/lib/observability/exporters/sentryExporter.d.ts +32 -0
  96. package/dist/lib/observability/exporters/sentryExporter.js +166 -0
  97. package/dist/lib/observability/index.d.ts +25 -0
  98. package/dist/lib/observability/index.js +32 -0
  99. package/dist/lib/observability/metricsAggregator.d.ts +260 -0
  100. package/dist/lib/observability/metricsAggregator.js +553 -0
  101. package/dist/lib/observability/otelBridge.d.ts +49 -0
  102. package/dist/lib/observability/otelBridge.js +132 -0
  103. package/dist/lib/observability/retryPolicy.d.ts +192 -0
  104. package/dist/lib/observability/retryPolicy.js +384 -0
  105. package/dist/lib/observability/sampling/index.d.ts +4 -0
  106. package/dist/lib/observability/sampling/index.js +5 -0
  107. package/dist/lib/observability/sampling/samplers.d.ts +116 -0
  108. package/dist/lib/observability/sampling/samplers.js +217 -0
  109. package/dist/lib/observability/spanProcessor.d.ts +129 -0
  110. package/dist/lib/observability/spanProcessor.js +288 -0
  111. package/dist/lib/observability/tokenTracker.d.ts +156 -0
  112. package/dist/lib/observability/tokenTracker.js +414 -0
  113. package/dist/lib/observability/types/exporterTypes.d.ts +250 -0
  114. package/dist/lib/observability/types/exporterTypes.js +6 -0
  115. package/dist/lib/observability/types/index.d.ts +6 -0
  116. package/dist/lib/observability/types/index.js +5 -0
  117. package/dist/lib/observability/types/spanTypes.d.ts +244 -0
  118. package/dist/lib/observability/types/spanTypes.js +93 -0
  119. package/dist/lib/observability/utils/index.d.ts +4 -0
  120. package/dist/lib/observability/utils/index.js +5 -0
  121. package/dist/lib/observability/utils/spanSerializer.d.ts +115 -0
  122. package/dist/lib/observability/utils/spanSerializer.js +287 -0
  123. package/dist/lib/providers/amazonSagemaker.d.ts +5 -4
  124. package/dist/lib/providers/amazonSagemaker.js +3 -4
  125. package/dist/lib/providers/googleVertex.d.ts +7 -0
  126. package/dist/lib/providers/googleVertex.js +80 -2
  127. package/dist/lib/rag/pipeline/RAGPipeline.d.ts +0 -5
  128. package/dist/lib/rag/pipeline/RAGPipeline.js +122 -87
  129. package/dist/lib/rag/ragIntegration.js +30 -0
  130. package/dist/lib/rag/retrieval/hybridSearch.js +22 -0
  131. package/dist/lib/server/abstract/baseServerAdapter.js +51 -19
  132. package/dist/lib/server/middleware/common.js +44 -12
  133. package/dist/lib/services/server/ai/observability/instrumentation.d.ts +2 -2
  134. package/dist/lib/services/server/ai/observability/instrumentation.js +10 -5
  135. package/dist/lib/types/cli.d.ts +18 -2
  136. package/dist/lib/types/conversationMemoryInterface.d.ts +2 -0
  137. package/dist/lib/types/generateTypes.d.ts +2 -2
  138. package/dist/lib/types/modelTypes.d.ts +18 -18
  139. package/dist/lib/types/providers.d.ts +5 -0
  140. package/dist/lib/utils/pricing.js +25 -1
  141. package/dist/lib/utils/ttsProcessor.js +74 -59
  142. package/dist/lib/workflow/config.d.ts +36 -36
  143. package/dist/lib/workflow/core/ensembleExecutor.js +10 -0
  144. package/dist/lib/workflow/core/judgeScorer.js +20 -2
  145. package/dist/lib/workflow/core/workflowRunner.js +34 -1
  146. package/dist/mcp/httpRateLimiter.js +39 -12
  147. package/dist/mcp/httpRetryHandler.js +22 -1
  148. package/dist/mcp/mcpClientFactory.js +13 -15
  149. package/dist/memory/memoryRetrievalTools.js +22 -0
  150. package/dist/neurolink.d.ts +64 -72
  151. package/dist/neurolink.js +984 -566
  152. package/dist/observability/FEATURE-STATUS.md +269 -0
  153. package/dist/observability/exporterRegistry.d.ts +152 -0
  154. package/dist/observability/exporterRegistry.js +413 -0
  155. package/dist/observability/exporters/arizeExporter.d.ts +32 -0
  156. package/dist/observability/exporters/arizeExporter.js +138 -0
  157. package/dist/observability/exporters/baseExporter.d.ts +117 -0
  158. package/dist/observability/exporters/baseExporter.js +190 -0
  159. package/dist/observability/exporters/braintrustExporter.d.ts +30 -0
  160. package/dist/observability/exporters/braintrustExporter.js +154 -0
  161. package/dist/observability/exporters/datadogExporter.d.ts +37 -0
  162. package/dist/observability/exporters/datadogExporter.js +196 -0
  163. package/dist/observability/exporters/index.d.ts +13 -0
  164. package/dist/observability/exporters/index.js +13 -0
  165. package/dist/observability/exporters/laminarExporter.d.ts +48 -0
  166. package/dist/observability/exporters/laminarExporter.js +302 -0
  167. package/dist/observability/exporters/langfuseExporter.d.ts +47 -0
  168. package/dist/observability/exporters/langfuseExporter.js +199 -0
  169. package/dist/observability/exporters/langsmithExporter.d.ts +26 -0
  170. package/dist/observability/exporters/langsmithExporter.js +123 -0
  171. package/dist/observability/exporters/otelExporter.d.ts +39 -0
  172. package/dist/observability/exporters/otelExporter.js +164 -0
  173. package/dist/observability/exporters/posthogExporter.d.ts +48 -0
  174. package/dist/observability/exporters/posthogExporter.js +287 -0
  175. package/dist/observability/exporters/sentryExporter.d.ts +32 -0
  176. package/dist/observability/exporters/sentryExporter.js +165 -0
  177. package/dist/observability/index.d.ts +25 -0
  178. package/dist/observability/index.js +31 -0
  179. package/dist/observability/metricsAggregator.d.ts +260 -0
  180. package/dist/observability/metricsAggregator.js +552 -0
  181. package/dist/observability/otelBridge.d.ts +49 -0
  182. package/dist/observability/otelBridge.js +131 -0
  183. package/dist/observability/retryPolicy.d.ts +192 -0
  184. package/dist/observability/retryPolicy.js +383 -0
  185. package/dist/observability/sampling/index.d.ts +4 -0
  186. package/dist/observability/sampling/index.js +4 -0
  187. package/dist/observability/sampling/samplers.d.ts +116 -0
  188. package/dist/observability/sampling/samplers.js +216 -0
  189. package/dist/observability/spanProcessor.d.ts +129 -0
  190. package/dist/observability/spanProcessor.js +287 -0
  191. package/dist/observability/tokenTracker.d.ts +156 -0
  192. package/dist/observability/tokenTracker.js +413 -0
  193. package/dist/observability/types/exporterTypes.d.ts +250 -0
  194. package/dist/observability/types/exporterTypes.js +5 -0
  195. package/dist/observability/types/index.d.ts +6 -0
  196. package/dist/observability/types/index.js +4 -0
  197. package/dist/observability/types/spanTypes.d.ts +244 -0
  198. package/dist/observability/types/spanTypes.js +92 -0
  199. package/dist/observability/utils/index.d.ts +4 -0
  200. package/dist/observability/utils/index.js +4 -0
  201. package/dist/observability/utils/spanSerializer.d.ts +115 -0
  202. package/dist/observability/utils/spanSerializer.js +286 -0
  203. package/dist/providers/amazonSagemaker.d.ts +5 -4
  204. package/dist/providers/amazonSagemaker.js +3 -4
  205. package/dist/providers/googleVertex.d.ts +7 -0
  206. package/dist/providers/googleVertex.js +80 -2
  207. package/dist/rag/pipeline/RAGPipeline.d.ts +0 -5
  208. package/dist/rag/pipeline/RAGPipeline.js +122 -87
  209. package/dist/rag/ragIntegration.js +30 -0
  210. package/dist/rag/retrieval/hybridSearch.js +22 -0
  211. package/dist/server/abstract/baseServerAdapter.js +51 -19
  212. package/dist/server/middleware/common.js +44 -12
  213. package/dist/services/server/ai/observability/instrumentation.d.ts +2 -2
  214. package/dist/services/server/ai/observability/instrumentation.js +10 -5
  215. package/dist/types/cli.d.ts +18 -2
  216. package/dist/types/conversationMemoryInterface.d.ts +2 -0
  217. package/dist/types/generateTypes.d.ts +2 -2
  218. package/dist/types/providers.d.ts +5 -0
  219. package/dist/utils/pricing.js +25 -1
  220. package/dist/utils/ttsProcessor.js +74 -59
  221. package/dist/workflow/config.d.ts +52 -52
  222. package/dist/workflow/core/ensembleExecutor.js +10 -0
  223. package/dist/workflow/core/judgeScorer.js +20 -2
  224. package/dist/workflow/core/workflowRunner.js +34 -1
  225. package/package.json +1 -1
@@ -0,0 +1,139 @@
1
+ /**
2
+ * Arize Exporter
3
+ * Exports spans to Arize ML monitoring platform
4
+ */
5
+ import { BaseExporter } from "./baseExporter.js";
6
+ /**
7
+ * Arize exporter for ML monitoring and prediction logs
8
+ * Supports feature tracking and model performance monitoring
9
+ */
10
+ export class ArizeExporter extends BaseExporter {
11
+ spaceKey;
12
+ apiKey;
13
+ modelId;
14
+ modelVersion;
15
+ endpoint = "https://api.arize.com/v1";
16
+ constructor(config) {
17
+ super("arize", config);
18
+ this.spaceKey = config.spaceKey;
19
+ this.apiKey = config.apiKey;
20
+ this.modelId = config.modelId ?? "neurolink-ai";
21
+ this.modelVersion = config.modelVersion ?? "1.0.0";
22
+ }
23
+ async initialize() {
24
+ if (this.initialized) {
25
+ return;
26
+ }
27
+ this.initialized = true;
28
+ this.startFlushInterval(this.config.flushIntervalMs ?? 10000);
29
+ }
30
+ async exportSpan(span) {
31
+ const startTime = Date.now();
32
+ try {
33
+ const prediction = this.convertToArizePrediction(span);
34
+ const response = await fetch(`${this.endpoint}/log`, {
35
+ method: "POST",
36
+ headers: {
37
+ "Content-Type": "application/json",
38
+ Authorization: `Bearer ${this.apiKey}`,
39
+ "space-key": this.spaceKey,
40
+ },
41
+ body: JSON.stringify(prediction),
42
+ });
43
+ if (!response.ok) {
44
+ throw new Error(`Export failed: ${response.statusText}`);
45
+ }
46
+ return this.createSuccessResult(1, Date.now() - startTime);
47
+ }
48
+ catch (error) {
49
+ return this.createFailureResult([span.spanId], error instanceof Error ? error.message : String(error), Date.now() - startTime);
50
+ }
51
+ }
52
+ async exportBatch(spans) {
53
+ // Arize's /v1/log endpoint does not support batch payloads, so we send
54
+ // individual requests in parallel. This is intentional — not a missed
55
+ // optimization.
56
+ const results = await Promise.all(spans.map((s) => this.exportSpan(s)));
57
+ const successful = results.filter((r) => r.success).length;
58
+ const failed = spans.length - successful;
59
+ return {
60
+ success: failed === 0,
61
+ exportedCount: successful,
62
+ failedCount: failed,
63
+ errors: results.flatMap((r) => r.errors ?? []),
64
+ durationMs: results.reduce((sum, r) => sum + r.durationMs, 0),
65
+ };
66
+ }
67
+ async flush() {
68
+ if (!this.initialized || this.buffer.length === 0) {
69
+ return;
70
+ }
71
+ const spans = [...this.buffer];
72
+ this.buffer = [];
73
+ await this.exportBatch(spans);
74
+ }
75
+ async shutdown() {
76
+ await this.flush();
77
+ this.stopFlushInterval();
78
+ this.initialized = false;
79
+ }
80
+ async healthCheck() {
81
+ try {
82
+ await this.withRetry(() => this.ping(), "health check");
83
+ return this.createHealthStatus(true);
84
+ }
85
+ catch {
86
+ return this.createHealthStatus(false, ["Health check failed"]);
87
+ }
88
+ }
89
+ /**
90
+ * Verify connectivity to Arize API
91
+ */
92
+ async ping() {
93
+ const response = await fetch(`${this.endpoint}/health`, {
94
+ method: "GET",
95
+ headers: {
96
+ Authorization: `Bearer ${this.apiKey}`,
97
+ "space-key": this.spaceKey,
98
+ },
99
+ });
100
+ if (!response.ok && response.status !== 404) {
101
+ // 404 is acceptable as health endpoint may not exist
102
+ throw new Error(`Arize API unreachable: ${response.status}`);
103
+ }
104
+ }
105
+ /**
106
+ * Convert span to Arize prediction log format
107
+ */
108
+ convertToArizePrediction(span) {
109
+ return {
110
+ space_key: this.spaceKey,
111
+ model_id: span.attributes["ai.model"] ?? this.modelId,
112
+ model_version: this.modelVersion,
113
+ prediction_id: span.spanId,
114
+ prediction_timestamp: new Date(span.startTime).getTime(),
115
+ features: {
116
+ provider: span.attributes["ai.provider"],
117
+ temperature: span.attributes["ai.temperature"],
118
+ max_tokens: span.attributes["ai.max_tokens"],
119
+ user_id: span.attributes["user.id"],
120
+ session_id: span.attributes["session.id"],
121
+ },
122
+ prediction: {
123
+ input: span.attributes["input"],
124
+ output: span.attributes["output"],
125
+ },
126
+ tags: {
127
+ span_type: span.type,
128
+ environment: this.config.environment,
129
+ },
130
+ latency_ms: span.durationMs,
131
+ token_count: {
132
+ prompt: span.attributes["ai.tokens.input"],
133
+ completion: span.attributes["ai.tokens.output"],
134
+ total: span.attributes["ai.tokens.total"],
135
+ },
136
+ };
137
+ }
138
+ }
139
+ //# sourceMappingURL=arizeExporter.js.map
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Abstract base class for all observability exporters
3
+ * Follows NeuroLink's factory pattern and Mastra's unified exporter interface
4
+ */
5
+ import type { ExporterConfig, ExporterHealthStatus, ExportResult, SpanData } from "../types/index.js";
6
+ /**
7
+ * Abstract base class for all observability exporters
8
+ * Provides common functionality: buffering, flush intervals, health checks, retry logic
9
+ */
10
+ export declare abstract class BaseExporter {
11
+ protected readonly name: string;
12
+ protected readonly config: ExporterConfig;
13
+ protected initialized: boolean;
14
+ protected buffer: SpanData[];
15
+ protected readonly maxBufferSize: number;
16
+ protected readonly retries: number;
17
+ protected flushInterval: ReturnType<typeof setInterval> | null;
18
+ protected lastExportTime: number;
19
+ constructor(name: string, config: ExporterConfig);
20
+ /**
21
+ * Initialize the exporter connection
22
+ * Must be called before exporting spans
23
+ */
24
+ abstract initialize(): Promise<void>;
25
+ /**
26
+ * Export a single span
27
+ * @param span - The span data to export
28
+ */
29
+ abstract exportSpan(span: SpanData): Promise<ExportResult>;
30
+ /**
31
+ * Export multiple spans in batch
32
+ * @param spans - Array of span data to export
33
+ */
34
+ abstract exportBatch(spans: SpanData[]): Promise<ExportResult>;
35
+ /**
36
+ * Flush all buffered spans
37
+ */
38
+ abstract flush(): Promise<void>;
39
+ /**
40
+ * Shutdown the exporter gracefully
41
+ * Should flush remaining spans before closing
42
+ */
43
+ abstract shutdown(): Promise<void>;
44
+ /**
45
+ * Check exporter health status
46
+ * Implementations should make an actual API call to verify connectivity
47
+ */
48
+ abstract healthCheck(): Promise<ExporterHealthStatus>;
49
+ /**
50
+ * Ping the exporter's backend to verify connectivity
51
+ * Override this in subclasses to provide backend-specific health check
52
+ */
53
+ protected ping(): Promise<void>;
54
+ /**
55
+ * Buffer a span for batch export
56
+ * Triggers flush if buffer is full
57
+ */
58
+ protected bufferSpan(span: SpanData): void;
59
+ /**
60
+ * Start automatic flush interval
61
+ * @param intervalMs - Interval in milliseconds between flushes
62
+ */
63
+ protected startFlushInterval(intervalMs: number): void;
64
+ /**
65
+ * Stop the automatic flush interval
66
+ */
67
+ protected stopFlushInterval(): void;
68
+ /**
69
+ * Get exporter name
70
+ */
71
+ getName(): string;
72
+ /**
73
+ * Check if exporter is initialized
74
+ */
75
+ isInitialized(): boolean;
76
+ /**
77
+ * Get number of pending spans in buffer
78
+ */
79
+ getPendingCount(): number;
80
+ /**
81
+ * Get last export timestamp
82
+ */
83
+ getLastExportTime(): number;
84
+ /**
85
+ * Create a standard export result for success
86
+ */
87
+ protected createSuccessResult(exportedCount: number, durationMs: number): ExportResult;
88
+ /**
89
+ * Create a standard export result for failure
90
+ */
91
+ protected createFailureResult(spanIds: string[], error: string, durationMs: number, retryable?: boolean): ExportResult;
92
+ /**
93
+ * Create a standard health status
94
+ */
95
+ protected createHealthStatus(healthy: boolean, errors?: string[]): ExporterHealthStatus;
96
+ /**
97
+ * Execute an operation with exponential backoff retry
98
+ * @param operation - The async operation to execute
99
+ * @param operationName - Name for logging purposes
100
+ * @returns The result of the operation
101
+ * @throws The last error if all retries fail
102
+ */
103
+ protected withRetry<T>(operation: () => Promise<T>, operationName: string): Promise<T>;
104
+ }
105
+ /**
106
+ * No-op exporter for when observability is disabled
107
+ * Provides zero-overhead behavior
108
+ */
109
+ export declare class NoOpExporter extends BaseExporter {
110
+ constructor();
111
+ initialize(): Promise<void>;
112
+ exportSpan(_span: SpanData): Promise<ExportResult>;
113
+ exportBatch(_spans: SpanData[]): Promise<ExportResult>;
114
+ flush(): Promise<void>;
115
+ shutdown(): Promise<void>;
116
+ healthCheck(): Promise<ExporterHealthStatus>;
117
+ }
@@ -0,0 +1,191 @@
1
+ /**
2
+ * Abstract base class for all observability exporters
3
+ * Follows NeuroLink's factory pattern and Mastra's unified exporter interface
4
+ */
5
+ import { logger } from "../../utils/logger.js";
6
+ /**
7
+ * Abstract base class for all observability exporters
8
+ * Provides common functionality: buffering, flush intervals, health checks, retry logic
9
+ */
10
+ export class BaseExporter {
11
+ name;
12
+ config;
13
+ initialized = false;
14
+ buffer = [];
15
+ maxBufferSize;
16
+ retries;
17
+ flushInterval = null;
18
+ lastExportTime = 0;
19
+ constructor(name, config) {
20
+ this.name = name;
21
+ this.config = config;
22
+ this.maxBufferSize = config.maxBufferSize ?? 100;
23
+ this.retries = config.retries ?? 3;
24
+ }
25
+ /**
26
+ * Ping the exporter's backend to verify connectivity
27
+ * Override this in subclasses to provide backend-specific health check
28
+ */
29
+ async ping() {
30
+ // Default implementation does nothing
31
+ // Subclasses should override this to make an actual API call
32
+ }
33
+ /**
34
+ * Buffer a span for batch export
35
+ * Triggers flush if buffer is full
36
+ */
37
+ bufferSpan(span) {
38
+ this.buffer.push(span);
39
+ if (this.buffer.length >= this.maxBufferSize) {
40
+ // Use void to explicitly ignore the promise
41
+ void this.flush();
42
+ }
43
+ }
44
+ /**
45
+ * Start automatic flush interval
46
+ * @param intervalMs - Interval in milliseconds between flushes
47
+ */
48
+ startFlushInterval(intervalMs) {
49
+ if (this.flushInterval) {
50
+ clearInterval(this.flushInterval);
51
+ }
52
+ this.flushInterval = setInterval(() => {
53
+ this.flush().catch((error) => {
54
+ logger.warn(`[${this.name}] Periodic flush failed`, {
55
+ error: error instanceof Error ? error.message : String(error),
56
+ });
57
+ });
58
+ }, intervalMs);
59
+ }
60
+ /**
61
+ * Stop the automatic flush interval
62
+ */
63
+ stopFlushInterval() {
64
+ if (this.flushInterval) {
65
+ clearInterval(this.flushInterval);
66
+ this.flushInterval = null;
67
+ }
68
+ }
69
+ /**
70
+ * Get exporter name
71
+ */
72
+ getName() {
73
+ return this.name;
74
+ }
75
+ /**
76
+ * Check if exporter is initialized
77
+ */
78
+ isInitialized() {
79
+ return this.initialized;
80
+ }
81
+ /**
82
+ * Get number of pending spans in buffer
83
+ */
84
+ getPendingCount() {
85
+ return this.buffer.length;
86
+ }
87
+ /**
88
+ * Get last export timestamp
89
+ */
90
+ getLastExportTime() {
91
+ return this.lastExportTime;
92
+ }
93
+ /**
94
+ * Create a standard export result for success
95
+ */
96
+ createSuccessResult(exportedCount, durationMs) {
97
+ this.lastExportTime = Date.now();
98
+ return {
99
+ success: true,
100
+ exportedCount,
101
+ failedCount: 0,
102
+ durationMs,
103
+ };
104
+ }
105
+ /**
106
+ * Create a standard export result for failure
107
+ */
108
+ createFailureResult(spanIds, error, durationMs, retryable = true) {
109
+ return {
110
+ success: false,
111
+ exportedCount: 0,
112
+ failedCount: spanIds.length,
113
+ errors: spanIds.map((spanId) => ({
114
+ spanId,
115
+ error,
116
+ retryable,
117
+ })),
118
+ durationMs,
119
+ };
120
+ }
121
+ /**
122
+ * Create a standard health status
123
+ */
124
+ createHealthStatus(healthy, errors) {
125
+ return {
126
+ healthy,
127
+ name: this.name,
128
+ pendingSpans: this.buffer.length,
129
+ lastExportTime: this.lastExportTime || undefined,
130
+ errors,
131
+ };
132
+ }
133
+ /**
134
+ * Execute an operation with exponential backoff retry
135
+ * @param operation - The async operation to execute
136
+ * @param operationName - Name for logging purposes
137
+ * @returns The result of the operation
138
+ * @throws The last error if all retries fail
139
+ */
140
+ async withRetry(operation, operationName) {
141
+ const maxRetries = this.retries;
142
+ const baseDelay = 1000;
143
+ let lastError;
144
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
145
+ try {
146
+ return await operation();
147
+ }
148
+ catch (error) {
149
+ lastError = error;
150
+ if (attempt < maxRetries) {
151
+ const delay = baseDelay * 2 ** attempt;
152
+ logger.warn(`[${this.name}] ${operationName} failed, retrying in ${delay}ms`, {
153
+ attempt: attempt + 1,
154
+ maxRetries,
155
+ error: lastError.message,
156
+ });
157
+ await new Promise((resolve) => setTimeout(resolve, delay));
158
+ }
159
+ }
160
+ }
161
+ throw lastError;
162
+ }
163
+ }
164
+ /**
165
+ * No-op exporter for when observability is disabled
166
+ * Provides zero-overhead behavior
167
+ */
168
+ export class NoOpExporter extends BaseExporter {
169
+ constructor() {
170
+ super("noop", { enabled: false });
171
+ }
172
+ async initialize() {
173
+ this.initialized = true;
174
+ }
175
+ async exportSpan(_span) {
176
+ return this.createSuccessResult(0, 0);
177
+ }
178
+ async exportBatch(_spans) {
179
+ return this.createSuccessResult(0, 0);
180
+ }
181
+ async flush() {
182
+ // No-op
183
+ }
184
+ async shutdown() {
185
+ this.initialized = false;
186
+ }
187
+ async healthCheck() {
188
+ return this.createHealthStatus(true);
189
+ }
190
+ }
191
+ //# sourceMappingURL=baseExporter.js.map
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Braintrust Exporter
3
+ * Exports spans to Braintrust AI evaluation platform
4
+ */
5
+ import type { BraintrustExporterConfig, ExporterHealthStatus, ExportResult, SpanData } from "../types/index.js";
6
+ import { BaseExporter } from "./baseExporter.js";
7
+ /**
8
+ * Braintrust exporter for AI evaluation and scoring
9
+ * Supports project logs and evaluation metrics
10
+ */
11
+ export declare class BraintrustExporter extends BaseExporter {
12
+ private readonly apiKey;
13
+ private readonly projectName;
14
+ private readonly endpoint;
15
+ constructor(config: BraintrustExporterConfig);
16
+ initialize(): Promise<void>;
17
+ exportSpan(span: SpanData): Promise<ExportResult>;
18
+ exportBatch(spans: SpanData[]): Promise<ExportResult>;
19
+ flush(): Promise<void>;
20
+ shutdown(): Promise<void>;
21
+ healthCheck(): Promise<ExporterHealthStatus>;
22
+ /**
23
+ * Verify connectivity to Braintrust API
24
+ */
25
+ protected ping(): Promise<void>;
26
+ /**
27
+ * Convert span to Braintrust log format
28
+ */
29
+ private convertToBraintrustLog;
30
+ }
@@ -0,0 +1,155 @@
1
+ /**
2
+ * Braintrust Exporter
3
+ * Exports spans to Braintrust AI evaluation platform
4
+ */
5
+ import { logger } from "../../utils/logger.js";
6
+ import { BaseExporter } from "./baseExporter.js";
7
+ /**
8
+ * Braintrust exporter for AI evaluation and scoring
9
+ * Supports project logs and evaluation metrics
10
+ */
11
+ export class BraintrustExporter extends BaseExporter {
12
+ apiKey;
13
+ projectName;
14
+ endpoint;
15
+ constructor(config) {
16
+ super("braintrust", config);
17
+ this.apiKey = config.apiKey;
18
+ this.projectName = config.projectName;
19
+ this.endpoint = config.endpoint ?? "https://api.braintrust.dev";
20
+ }
21
+ async initialize() {
22
+ if (this.initialized) {
23
+ return;
24
+ }
25
+ // Verify API key
26
+ try {
27
+ const response = await fetch(`${this.endpoint}/v1/project`, {
28
+ headers: { Authorization: `Bearer ${this.apiKey}` },
29
+ });
30
+ if (!response.ok) {
31
+ throw new Error(`Braintrust initialization failed: ${response.statusText}`);
32
+ }
33
+ }
34
+ catch (error) {
35
+ logger.warn("[Braintrust] Could not verify API connection:", error instanceof Error ? error.message : error);
36
+ }
37
+ this.initialized = true;
38
+ this.startFlushInterval(this.config.flushIntervalMs ?? 5000);
39
+ }
40
+ async exportSpan(span) {
41
+ const startTime = Date.now();
42
+ try {
43
+ const log = this.convertToBraintrustLog(span);
44
+ const response = await fetch(`${this.endpoint}/v1/project_logs/${this.projectName}/insert`, {
45
+ method: "POST",
46
+ headers: {
47
+ "Content-Type": "application/json",
48
+ Authorization: `Bearer ${this.apiKey}`,
49
+ },
50
+ body: JSON.stringify({ events: [log] }),
51
+ });
52
+ if (!response.ok) {
53
+ throw new Error(`Export failed: ${response.statusText}`);
54
+ }
55
+ return this.createSuccessResult(1, Date.now() - startTime);
56
+ }
57
+ catch (error) {
58
+ return this.createFailureResult([span.spanId], error instanceof Error ? error.message : String(error), Date.now() - startTime);
59
+ }
60
+ }
61
+ async exportBatch(spans) {
62
+ const startTime = Date.now();
63
+ try {
64
+ const events = spans.map((s) => this.convertToBraintrustLog(s));
65
+ const response = await fetch(`${this.endpoint}/v1/project_logs/${this.projectName}/insert`, {
66
+ method: "POST",
67
+ headers: {
68
+ "Content-Type": "application/json",
69
+ Authorization: `Bearer ${this.apiKey}`,
70
+ },
71
+ body: JSON.stringify({ events }),
72
+ });
73
+ if (!response.ok) {
74
+ throw new Error(`Batch export failed: ${response.statusText}`);
75
+ }
76
+ return this.createSuccessResult(spans.length, Date.now() - startTime);
77
+ }
78
+ catch (error) {
79
+ return this.createFailureResult(spans.map((s) => s.spanId), error instanceof Error ? error.message : String(error), Date.now() - startTime);
80
+ }
81
+ }
82
+ async flush() {
83
+ if (this.buffer.length > 0) {
84
+ const spans = [...this.buffer];
85
+ this.buffer = [];
86
+ await this.exportBatch(spans);
87
+ }
88
+ }
89
+ async shutdown() {
90
+ await this.flush();
91
+ this.stopFlushInterval();
92
+ this.initialized = false;
93
+ }
94
+ async healthCheck() {
95
+ try {
96
+ await this.withRetry(() => this.ping(), "health check");
97
+ return this.createHealthStatus(true);
98
+ }
99
+ catch {
100
+ return this.createHealthStatus(false, ["Health check failed"]);
101
+ }
102
+ }
103
+ /**
104
+ * Verify connectivity to Braintrust API
105
+ */
106
+ async ping() {
107
+ const response = await fetch(`${this.endpoint}/v1/project`, {
108
+ headers: { Authorization: `Bearer ${this.apiKey}` },
109
+ });
110
+ if (!response.ok) {
111
+ throw new Error(`Braintrust API unreachable: ${response.status}`);
112
+ }
113
+ }
114
+ /**
115
+ * Convert span to Braintrust log format
116
+ */
117
+ convertToBraintrustLog(span) {
118
+ return {
119
+ project_name: this.projectName,
120
+ id: span.spanId,
121
+ span_id: span.spanId,
122
+ root_span_id: span.parentSpanId ? undefined : span.spanId,
123
+ span_parents: span.parentSpanId ? [span.parentSpanId] : [],
124
+ input: span.attributes["input"],
125
+ output: span.attributes["output"],
126
+ expected: span.attributes["expected"],
127
+ scores: span.attributes["scores"],
128
+ metadata: {
129
+ // Pick only safe, non-PII attributes for metadata (avoid leaking input/output)
130
+ ...(span.attributes["ai.provider"] !== undefined && {
131
+ "ai.provider": span.attributes["ai.provider"],
132
+ }),
133
+ ...(span.attributes["ai.model"] !== undefined && {
134
+ "ai.model": span.attributes["ai.model"],
135
+ }),
136
+ // Explicit fields placed after spread so they always win
137
+ provider: span.attributes["ai.provider"],
138
+ model: span.attributes["ai.model"],
139
+ type: span.type,
140
+ status: span.status,
141
+ statusMessage: span.statusMessage,
142
+ },
143
+ metrics: {
144
+ tokens: span.attributes["ai.tokens.total"],
145
+ prompt_tokens: span.attributes["ai.tokens.input"],
146
+ completion_tokens: span.attributes["ai.tokens.output"],
147
+ cost: span.attributes["ai.cost.total"],
148
+ duration_ms: span.durationMs,
149
+ },
150
+ created: span.startTime,
151
+ end_time: span.endTime,
152
+ };
153
+ }
154
+ }
155
+ //# sourceMappingURL=braintrustExporter.js.map
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Datadog Exporter
3
+ * Exports spans to Datadog APM platform
4
+ */
5
+ import type { DatadogExporterConfig, ExporterHealthStatus, ExportResult, SpanData } from "../types/index.js";
6
+ import { BaseExporter } from "./baseExporter.js";
7
+ /**
8
+ * Datadog exporter for enterprise APM integration
9
+ * Supports trace correlation and AI-specific custom metrics
10
+ */
11
+ export declare class DatadogExporter extends BaseExporter {
12
+ private readonly apiKey;
13
+ private readonly appKey?;
14
+ private readonly site;
15
+ private readonly service;
16
+ private readonly source;
17
+ private readonly logsEndpoint;
18
+ constructor(config: DatadogExporterConfig);
19
+ initialize(): Promise<void>;
20
+ exportSpan(span: SpanData): Promise<ExportResult>;
21
+ exportBatch(spans: SpanData[]): Promise<ExportResult>;
22
+ flush(): Promise<void>;
23
+ shutdown(): Promise<void>;
24
+ healthCheck(): Promise<ExporterHealthStatus>;
25
+ /**
26
+ * Verify connectivity to Datadog API
27
+ */
28
+ protected ping(): Promise<void>;
29
+ /**
30
+ * Convert span to Datadog log format with trace correlation
31
+ */
32
+ private convertToDatadogLog;
33
+ /**
34
+ * Build Datadog tags from span attributes
35
+ */
36
+ private buildTags;
37
+ }