@juspay/neurolink 9.24.0 → 9.25.1
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/CHANGELOG.md +12 -0
- package/dist/adapters/tts/googleTTSHandler.js +26 -1
- package/dist/adapters/video/vertexVideoHandler.js +23 -17
- package/dist/cli/commands/config.d.ts +3 -3
- package/dist/cli/commands/observability.d.ts +53 -0
- package/dist/cli/commands/observability.js +453 -0
- package/dist/cli/commands/telemetry.d.ts +63 -0
- package/dist/cli/commands/telemetry.js +689 -0
- package/dist/cli/factories/commandFactory.js +29 -15
- package/dist/cli/parser.js +6 -9
- package/dist/cli/utils/formatters.d.ts +13 -0
- package/dist/cli/utils/formatters.js +23 -0
- package/dist/constants/contextWindows.js +6 -0
- package/dist/constants/enums.d.ts +6 -0
- package/dist/constants/enums.js +8 -2
- package/dist/context/budgetChecker.js +75 -48
- package/dist/context/contextCompactor.js +135 -127
- package/dist/core/baseProvider.d.ts +5 -0
- package/dist/core/baseProvider.js +117 -110
- package/dist/core/conversationMemoryInitializer.js +7 -4
- package/dist/core/conversationMemoryManager.d.ts +2 -0
- package/dist/core/conversationMemoryManager.js +6 -2
- package/dist/core/modules/GenerationHandler.d.ts +2 -2
- package/dist/core/modules/GenerationHandler.js +12 -12
- package/dist/evaluation/ragasEvaluator.js +39 -19
- package/dist/evaluation/scoring.js +46 -20
- package/dist/features/ppt/presentationOrchestrator.js +23 -0
- package/dist/features/ppt/slideGenerator.js +13 -0
- package/dist/features/ppt/slideRenderers.d.ts +1 -1
- package/dist/features/ppt/slideRenderers.js +6 -4
- package/dist/features/ppt/slideTypeInference.d.ts +1 -1
- package/dist/features/ppt/slideTypeInference.js +75 -73
- package/dist/files/fileTools.d.ts +6 -6
- package/dist/index.d.ts +46 -12
- package/dist/index.js +79 -17
- package/dist/lib/adapters/tts/googleTTSHandler.js +26 -1
- package/dist/lib/adapters/video/vertexVideoHandler.js +23 -17
- package/dist/lib/constants/contextWindows.js +6 -0
- package/dist/lib/constants/enums.d.ts +6 -0
- package/dist/lib/constants/enums.js +8 -2
- package/dist/lib/context/budgetChecker.js +75 -48
- package/dist/lib/context/contextCompactor.js +135 -127
- package/dist/lib/core/baseProvider.d.ts +5 -0
- package/dist/lib/core/baseProvider.js +117 -110
- package/dist/lib/core/conversationMemoryInitializer.js +7 -4
- package/dist/lib/core/conversationMemoryManager.d.ts +2 -0
- package/dist/lib/core/conversationMemoryManager.js +6 -2
- package/dist/lib/core/modules/GenerationHandler.d.ts +2 -2
- package/dist/lib/core/modules/GenerationHandler.js +12 -12
- package/dist/lib/evaluation/ragasEvaluator.js +39 -19
- package/dist/lib/evaluation/scoring.js +46 -20
- package/dist/lib/features/ppt/presentationOrchestrator.js +23 -0
- package/dist/lib/features/ppt/slideGenerator.js +13 -0
- package/dist/lib/features/ppt/slideRenderers.d.ts +1 -1
- package/dist/lib/features/ppt/slideRenderers.js +6 -4
- package/dist/lib/features/ppt/slideTypeInference.d.ts +1 -1
- package/dist/lib/features/ppt/slideTypeInference.js +75 -73
- package/dist/lib/files/fileTools.d.ts +6 -6
- package/dist/lib/index.d.ts +46 -12
- package/dist/lib/index.js +79 -17
- package/dist/lib/mcp/httpRateLimiter.js +39 -12
- package/dist/lib/mcp/httpRetryHandler.js +22 -1
- package/dist/lib/mcp/mcpClientFactory.js +13 -15
- package/dist/lib/memory/memoryRetrievalTools.js +22 -0
- package/dist/lib/neurolink.d.ts +64 -72
- package/dist/lib/neurolink.js +1007 -564
- package/dist/lib/observability/exporterRegistry.d.ts +152 -0
- package/dist/lib/observability/exporterRegistry.js +414 -0
- package/dist/lib/observability/exporters/arizeExporter.d.ts +32 -0
- package/dist/lib/observability/exporters/arizeExporter.js +139 -0
- package/dist/lib/observability/exporters/baseExporter.d.ts +117 -0
- package/dist/lib/observability/exporters/baseExporter.js +191 -0
- package/dist/lib/observability/exporters/braintrustExporter.d.ts +30 -0
- package/dist/lib/observability/exporters/braintrustExporter.js +155 -0
- package/dist/lib/observability/exporters/datadogExporter.d.ts +37 -0
- package/dist/lib/observability/exporters/datadogExporter.js +197 -0
- package/dist/lib/observability/exporters/index.d.ts +13 -0
- package/dist/lib/observability/exporters/index.js +14 -0
- package/dist/lib/observability/exporters/laminarExporter.d.ts +48 -0
- package/dist/lib/observability/exporters/laminarExporter.js +303 -0
- package/dist/lib/observability/exporters/langfuseExporter.d.ts +47 -0
- package/dist/lib/observability/exporters/langfuseExporter.js +204 -0
- package/dist/lib/observability/exporters/langsmithExporter.d.ts +26 -0
- package/dist/lib/observability/exporters/langsmithExporter.js +124 -0
- package/dist/lib/observability/exporters/otelExporter.d.ts +39 -0
- package/dist/lib/observability/exporters/otelExporter.js +165 -0
- package/dist/lib/observability/exporters/posthogExporter.d.ts +48 -0
- package/dist/lib/observability/exporters/posthogExporter.js +288 -0
- package/dist/lib/observability/exporters/sentryExporter.d.ts +32 -0
- package/dist/lib/observability/exporters/sentryExporter.js +166 -0
- package/dist/lib/observability/index.d.ts +25 -0
- package/dist/lib/observability/index.js +32 -0
- package/dist/lib/observability/metricsAggregator.d.ts +260 -0
- package/dist/lib/observability/metricsAggregator.js +557 -0
- package/dist/lib/observability/otelBridge.d.ts +49 -0
- package/dist/lib/observability/otelBridge.js +132 -0
- package/dist/lib/observability/retryPolicy.d.ts +192 -0
- package/dist/lib/observability/retryPolicy.js +384 -0
- package/dist/lib/observability/sampling/index.d.ts +4 -0
- package/dist/lib/observability/sampling/index.js +5 -0
- package/dist/lib/observability/sampling/samplers.d.ts +116 -0
- package/dist/lib/observability/sampling/samplers.js +217 -0
- package/dist/lib/observability/spanProcessor.d.ts +129 -0
- package/dist/lib/observability/spanProcessor.js +304 -0
- package/dist/lib/observability/tokenTracker.d.ts +156 -0
- package/dist/lib/observability/tokenTracker.js +414 -0
- package/dist/lib/observability/types/exporterTypes.d.ts +250 -0
- package/dist/lib/observability/types/exporterTypes.js +6 -0
- package/dist/lib/observability/types/index.d.ts +6 -0
- package/dist/lib/observability/types/index.js +5 -0
- package/dist/lib/observability/types/spanTypes.d.ts +244 -0
- package/dist/lib/observability/types/spanTypes.js +93 -0
- package/dist/lib/observability/utils/index.d.ts +4 -0
- package/dist/lib/observability/utils/index.js +5 -0
- package/dist/lib/observability/utils/safeMetadata.d.ts +10 -0
- package/dist/lib/observability/utils/safeMetadata.js +26 -0
- package/dist/lib/observability/utils/spanSerializer.d.ts +115 -0
- package/dist/lib/observability/utils/spanSerializer.js +291 -0
- package/dist/lib/providers/amazonSagemaker.d.ts +5 -4
- package/dist/lib/providers/amazonSagemaker.js +3 -4
- package/dist/lib/providers/googleVertex.d.ts +7 -0
- package/dist/lib/providers/googleVertex.js +76 -2
- package/dist/lib/rag/pipeline/RAGPipeline.d.ts +0 -5
- package/dist/lib/rag/pipeline/RAGPipeline.js +122 -87
- package/dist/lib/rag/ragIntegration.js +30 -0
- package/dist/lib/rag/retrieval/hybridSearch.js +22 -0
- package/dist/lib/server/abstract/baseServerAdapter.js +51 -19
- package/dist/lib/server/middleware/common.js +44 -12
- package/dist/lib/services/server/ai/observability/instrumentation.d.ts +2 -2
- package/dist/lib/services/server/ai/observability/instrumentation.js +10 -5
- package/dist/lib/types/conversationMemoryInterface.d.ts +2 -0
- package/dist/lib/types/modelTypes.d.ts +18 -18
- package/dist/lib/types/providers.d.ts +5 -0
- package/dist/lib/utils/pricing.js +25 -1
- package/dist/lib/utils/ttsProcessor.js +74 -59
- package/dist/lib/workflow/config.d.ts +36 -36
- package/dist/lib/workflow/core/ensembleExecutor.js +10 -0
- package/dist/lib/workflow/core/judgeScorer.js +20 -2
- package/dist/lib/workflow/core/workflowRunner.js +34 -1
- package/dist/mcp/httpRateLimiter.js +39 -12
- package/dist/mcp/httpRetryHandler.js +22 -1
- package/dist/mcp/mcpClientFactory.js +13 -15
- package/dist/memory/memoryRetrievalTools.js +22 -0
- package/dist/neurolink.d.ts +64 -72
- package/dist/neurolink.js +1007 -564
- package/dist/observability/FEATURE-STATUS.md +269 -0
- package/dist/observability/exporterRegistry.d.ts +152 -0
- package/dist/observability/exporterRegistry.js +413 -0
- package/dist/observability/exporters/arizeExporter.d.ts +32 -0
- package/dist/observability/exporters/arizeExporter.js +138 -0
- package/dist/observability/exporters/baseExporter.d.ts +117 -0
- package/dist/observability/exporters/baseExporter.js +190 -0
- package/dist/observability/exporters/braintrustExporter.d.ts +30 -0
- package/dist/observability/exporters/braintrustExporter.js +154 -0
- package/dist/observability/exporters/datadogExporter.d.ts +37 -0
- package/dist/observability/exporters/datadogExporter.js +196 -0
- package/dist/observability/exporters/index.d.ts +13 -0
- package/dist/observability/exporters/index.js +13 -0
- package/dist/observability/exporters/laminarExporter.d.ts +48 -0
- package/dist/observability/exporters/laminarExporter.js +302 -0
- package/dist/observability/exporters/langfuseExporter.d.ts +47 -0
- package/dist/observability/exporters/langfuseExporter.js +203 -0
- package/dist/observability/exporters/langsmithExporter.d.ts +26 -0
- package/dist/observability/exporters/langsmithExporter.js +123 -0
- package/dist/observability/exporters/otelExporter.d.ts +39 -0
- package/dist/observability/exporters/otelExporter.js +164 -0
- package/dist/observability/exporters/posthogExporter.d.ts +48 -0
- package/dist/observability/exporters/posthogExporter.js +287 -0
- package/dist/observability/exporters/sentryExporter.d.ts +32 -0
- package/dist/observability/exporters/sentryExporter.js +165 -0
- package/dist/observability/index.d.ts +25 -0
- package/dist/observability/index.js +31 -0
- package/dist/observability/metricsAggregator.d.ts +260 -0
- package/dist/observability/metricsAggregator.js +556 -0
- package/dist/observability/otelBridge.d.ts +49 -0
- package/dist/observability/otelBridge.js +131 -0
- package/dist/observability/retryPolicy.d.ts +192 -0
- package/dist/observability/retryPolicy.js +383 -0
- package/dist/observability/sampling/index.d.ts +4 -0
- package/dist/observability/sampling/index.js +4 -0
- package/dist/observability/sampling/samplers.d.ts +116 -0
- package/dist/observability/sampling/samplers.js +216 -0
- package/dist/observability/spanProcessor.d.ts +129 -0
- package/dist/observability/spanProcessor.js +303 -0
- package/dist/observability/tokenTracker.d.ts +156 -0
- package/dist/observability/tokenTracker.js +413 -0
- package/dist/observability/types/exporterTypes.d.ts +250 -0
- package/dist/observability/types/exporterTypes.js +5 -0
- package/dist/observability/types/index.d.ts +6 -0
- package/dist/observability/types/index.js +4 -0
- package/dist/observability/types/spanTypes.d.ts +244 -0
- package/dist/observability/types/spanTypes.js +92 -0
- package/dist/observability/utils/index.d.ts +4 -0
- package/dist/observability/utils/index.js +4 -0
- package/dist/observability/utils/safeMetadata.d.ts +10 -0
- package/dist/observability/utils/safeMetadata.js +25 -0
- package/dist/observability/utils/spanSerializer.d.ts +115 -0
- package/dist/observability/utils/spanSerializer.js +290 -0
- package/dist/providers/amazonSagemaker.d.ts +5 -4
- package/dist/providers/amazonSagemaker.js +3 -4
- package/dist/providers/googleVertex.d.ts +7 -0
- package/dist/providers/googleVertex.js +76 -2
- package/dist/rag/pipeline/RAGPipeline.d.ts +0 -5
- package/dist/rag/pipeline/RAGPipeline.js +122 -87
- package/dist/rag/ragIntegration.js +30 -0
- package/dist/rag/retrieval/hybridSearch.js +22 -0
- package/dist/server/abstract/baseServerAdapter.js +51 -19
- package/dist/server/middleware/common.js +44 -12
- package/dist/services/server/ai/observability/instrumentation.d.ts +2 -2
- package/dist/services/server/ai/observability/instrumentation.js +10 -5
- package/dist/types/conversationMemoryInterface.d.ts +2 -0
- package/dist/types/providers.d.ts +5 -0
- package/dist/utils/pricing.js +25 -1
- package/dist/utils/ttsProcessor.js +74 -59
- package/dist/workflow/config.d.ts +52 -52
- package/dist/workflow/core/ensembleExecutor.js +10 -0
- package/dist/workflow/core/judgeScorer.js +20 -2
- package/dist/workflow/core/workflowRunner.js +34 -1
- package/package.json +1 -1
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Langfuse Exporter
|
|
3
|
+
* Exports spans to Langfuse observability platform
|
|
4
|
+
*/
|
|
5
|
+
import { SpanType } from "../types/spanTypes.js";
|
|
6
|
+
import { SpanSerializer } from "../utils/spanSerializer.js";
|
|
7
|
+
import { BaseExporter } from "./baseExporter.js";
|
|
8
|
+
/**
|
|
9
|
+
* Langfuse exporter for LLM observability
|
|
10
|
+
* Supports traces, generations, spans, and scores
|
|
11
|
+
*/
|
|
12
|
+
export class LangfuseExporter extends BaseExporter {
|
|
13
|
+
publicKey;
|
|
14
|
+
secretKey;
|
|
15
|
+
baseUrl;
|
|
16
|
+
release;
|
|
17
|
+
constructor(config) {
|
|
18
|
+
super("langfuse", config);
|
|
19
|
+
this.publicKey = config.publicKey;
|
|
20
|
+
this.secretKey = config.secretKey;
|
|
21
|
+
this.baseUrl = config.baseUrl ?? "https://cloud.langfuse.com";
|
|
22
|
+
this.release = config.release;
|
|
23
|
+
}
|
|
24
|
+
async initialize() {
|
|
25
|
+
if (this.initialized) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
// Verify credentials with a simple check
|
|
29
|
+
if (!this.publicKey || !this.secretKey) {
|
|
30
|
+
throw new Error("Langfuse publicKey and secretKey are required");
|
|
31
|
+
}
|
|
32
|
+
this.initialized = true;
|
|
33
|
+
this.startFlushInterval(this.config.flushIntervalMs ?? 5000);
|
|
34
|
+
}
|
|
35
|
+
async exportSpan(span) {
|
|
36
|
+
const startTime = Date.now();
|
|
37
|
+
try {
|
|
38
|
+
// Create trace if this is a root span
|
|
39
|
+
if (!span.parentSpanId) {
|
|
40
|
+
await this.createTrace(span);
|
|
41
|
+
}
|
|
42
|
+
// Create span/generation based on type
|
|
43
|
+
if (span.type === SpanType.MODEL_GENERATION) {
|
|
44
|
+
await this.createGeneration(span);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
await this.createSpan(span);
|
|
48
|
+
}
|
|
49
|
+
return this.createSuccessResult(1, Date.now() - startTime);
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
return this.createFailureResult([span.spanId], error instanceof Error ? error.message : String(error), Date.now() - startTime);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
async exportBatch(spans) {
|
|
56
|
+
const startTime = Date.now();
|
|
57
|
+
const results = await Promise.allSettled(spans.map((s) => this.exportSpan(s)));
|
|
58
|
+
const successful = results.filter((r) => r.status === "fulfilled" && r.value.success).length;
|
|
59
|
+
const failed = spans.length - successful;
|
|
60
|
+
return {
|
|
61
|
+
success: failed === 0,
|
|
62
|
+
exportedCount: successful,
|
|
63
|
+
failedCount: failed,
|
|
64
|
+
errors: results
|
|
65
|
+
.filter((r) => r.status === "rejected" ||
|
|
66
|
+
(r.status === "fulfilled" && !r.value.success))
|
|
67
|
+
.map((r, i) => ({
|
|
68
|
+
spanId: spans[i].spanId,
|
|
69
|
+
error: r.status === "rejected" ? String(r.reason) : "Export failed",
|
|
70
|
+
retryable: true,
|
|
71
|
+
})),
|
|
72
|
+
durationMs: Date.now() - startTime,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
async flush() {
|
|
76
|
+
if (this.buffer.length > 0) {
|
|
77
|
+
const spans = [...this.buffer];
|
|
78
|
+
this.buffer = [];
|
|
79
|
+
await this.exportBatch(spans);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
async shutdown() {
|
|
83
|
+
await this.flush();
|
|
84
|
+
this.stopFlushInterval();
|
|
85
|
+
this.initialized = false;
|
|
86
|
+
}
|
|
87
|
+
async healthCheck() {
|
|
88
|
+
try {
|
|
89
|
+
await this.withRetry(() => this.ping(), "health check");
|
|
90
|
+
return this.createHealthStatus(true);
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
return this.createHealthStatus(false, ["Health check failed"]);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Verify connectivity to Langfuse API
|
|
98
|
+
*/
|
|
99
|
+
async ping() {
|
|
100
|
+
const credentials = Buffer.from(`${this.publicKey}:${this.secretKey}`).toString("base64");
|
|
101
|
+
const response = await fetch(`${this.baseUrl}/api/public/health`, {
|
|
102
|
+
method: "GET",
|
|
103
|
+
headers: {
|
|
104
|
+
Authorization: `Basic ${credentials}`,
|
|
105
|
+
},
|
|
106
|
+
});
|
|
107
|
+
if (!response.ok && response.status !== 404) {
|
|
108
|
+
// 404 is acceptable as health endpoint may not exist
|
|
109
|
+
throw new Error(`Langfuse API unreachable: ${response.status}`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Create a Langfuse trace
|
|
114
|
+
*/
|
|
115
|
+
async createTrace(span) {
|
|
116
|
+
const body = {
|
|
117
|
+
id: span.traceId,
|
|
118
|
+
name: span.name,
|
|
119
|
+
userId: span.attributes["user.id"],
|
|
120
|
+
sessionId: span.attributes["session.id"],
|
|
121
|
+
// Only pick safe, non-PII attributes for metadata — intentionally excludes
|
|
122
|
+
// input, output, error.stack, and other user content to match Braintrust exporter
|
|
123
|
+
metadata: filterSafeMetadata(span.attributes),
|
|
124
|
+
release: this.release,
|
|
125
|
+
tags: this.extractTags(span),
|
|
126
|
+
};
|
|
127
|
+
await this.apiCall("/api/public/traces", body);
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Create a Langfuse span
|
|
131
|
+
*/
|
|
132
|
+
async createSpan(span) {
|
|
133
|
+
const langfuseSpan = SpanSerializer.toLangfuseFormat(span);
|
|
134
|
+
const body = {
|
|
135
|
+
...langfuseSpan,
|
|
136
|
+
traceId: span.traceId,
|
|
137
|
+
};
|
|
138
|
+
await this.apiCall("/api/public/spans", body);
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Create a Langfuse generation (for LLM calls)
|
|
142
|
+
*/
|
|
143
|
+
async createGeneration(span) {
|
|
144
|
+
const langfuseSpan = SpanSerializer.toLangfuseFormat(span);
|
|
145
|
+
const body = {
|
|
146
|
+
traceId: span.traceId,
|
|
147
|
+
id: langfuseSpan.id,
|
|
148
|
+
parentObservationId: langfuseSpan.parentObservationId,
|
|
149
|
+
name: langfuseSpan.name,
|
|
150
|
+
startTime: langfuseSpan.startTime,
|
|
151
|
+
endTime: langfuseSpan.endTime,
|
|
152
|
+
model: span.attributes["ai.model"],
|
|
153
|
+
modelParameters: {
|
|
154
|
+
temperature: span.attributes["ai.temperature"],
|
|
155
|
+
maxTokens: span.attributes["ai.max_tokens"],
|
|
156
|
+
topP: span.attributes["ai.top_p"],
|
|
157
|
+
},
|
|
158
|
+
input: langfuseSpan.input,
|
|
159
|
+
output: langfuseSpan.output,
|
|
160
|
+
usage: langfuseSpan.usage,
|
|
161
|
+
metadata: langfuseSpan.metadata,
|
|
162
|
+
level: langfuseSpan.level,
|
|
163
|
+
statusMessage: langfuseSpan.statusMessage,
|
|
164
|
+
};
|
|
165
|
+
await this.apiCall("/api/public/generations", body);
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Make API call to Langfuse
|
|
169
|
+
*/
|
|
170
|
+
async apiCall(path, body) {
|
|
171
|
+
const credentials = Buffer.from(`${this.publicKey}:${this.secretKey}`).toString("base64");
|
|
172
|
+
const response = await fetch(`${this.baseUrl}${path}`, {
|
|
173
|
+
method: "POST",
|
|
174
|
+
headers: {
|
|
175
|
+
"Content-Type": "application/json",
|
|
176
|
+
Authorization: `Basic ${credentials}`,
|
|
177
|
+
},
|
|
178
|
+
body: JSON.stringify(body),
|
|
179
|
+
});
|
|
180
|
+
if (!response.ok) {
|
|
181
|
+
const text = await response.text();
|
|
182
|
+
throw new Error(`Langfuse API error: ${response.status} - ${text}`);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Extract tags from span attributes
|
|
187
|
+
*/
|
|
188
|
+
extractTags(span) {
|
|
189
|
+
const tags = [];
|
|
190
|
+
if (span.attributes["ai.provider"]) {
|
|
191
|
+
tags.push(`provider:${span.attributes["ai.provider"]}`);
|
|
192
|
+
}
|
|
193
|
+
if (span.attributes["ai.model"]) {
|
|
194
|
+
tags.push(`model:${span.attributes["ai.model"]}`);
|
|
195
|
+
}
|
|
196
|
+
if (span.attributes["deployment.environment"]) {
|
|
197
|
+
tags.push(`env:${span.attributes["deployment.environment"]}`);
|
|
198
|
+
}
|
|
199
|
+
return tags;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
// Safe metadata filtering imported from shared module to avoid duplication
|
|
203
|
+
import { filterSafeMetadata } from "../utils/safeMetadata.js";
|
|
204
|
+
//# sourceMappingURL=langfuseExporter.js.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LangSmith Exporter
|
|
3
|
+
* Exports spans to LangSmith observability platform
|
|
4
|
+
*/
|
|
5
|
+
import type { ExporterHealthStatus, ExportResult, LangSmithExporterConfig, SpanData } from "../types/index.js";
|
|
6
|
+
import { BaseExporter } from "./baseExporter.js";
|
|
7
|
+
/**
|
|
8
|
+
* LangSmith exporter for LangChain ecosystem observability
|
|
9
|
+
* Supports runs with proper type mapping
|
|
10
|
+
*/
|
|
11
|
+
export declare class LangSmithExporter extends BaseExporter {
|
|
12
|
+
private readonly apiKey;
|
|
13
|
+
private readonly projectName;
|
|
14
|
+
private readonly endpoint;
|
|
15
|
+
constructor(config: LangSmithExporterConfig);
|
|
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 LangSmith API
|
|
24
|
+
*/
|
|
25
|
+
protected ping(): Promise<void>;
|
|
26
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LangSmith Exporter
|
|
3
|
+
* Exports spans to LangSmith observability platform
|
|
4
|
+
*/
|
|
5
|
+
import { logger } from "../../utils/logger.js";
|
|
6
|
+
import { SpanSerializer } from "../utils/spanSerializer.js";
|
|
7
|
+
import { BaseExporter } from "./baseExporter.js";
|
|
8
|
+
/**
|
|
9
|
+
* LangSmith exporter for LangChain ecosystem observability
|
|
10
|
+
* Supports runs with proper type mapping
|
|
11
|
+
*/
|
|
12
|
+
export class LangSmithExporter extends BaseExporter {
|
|
13
|
+
apiKey;
|
|
14
|
+
projectName;
|
|
15
|
+
endpoint;
|
|
16
|
+
constructor(config) {
|
|
17
|
+
super("langsmith", config);
|
|
18
|
+
this.apiKey = config.apiKey;
|
|
19
|
+
this.projectName = config.projectName ?? "default";
|
|
20
|
+
this.endpoint = config.endpoint ?? "https://api.smith.langchain.com";
|
|
21
|
+
}
|
|
22
|
+
async initialize() {
|
|
23
|
+
if (this.initialized) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
// Verify API key with a test request
|
|
27
|
+
try {
|
|
28
|
+
const response = await fetch(`${this.endpoint}/api/v1/info`, {
|
|
29
|
+
headers: { "x-api-key": this.apiKey },
|
|
30
|
+
});
|
|
31
|
+
if (!response.ok) {
|
|
32
|
+
throw new Error(`LangSmith initialization failed: ${response.statusText}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
// Allow initialization to proceed even if API is unreachable
|
|
37
|
+
// This enables offline/test scenarios
|
|
38
|
+
logger.warn("[LangSmith] Could not verify API connection:", error instanceof Error ? error.message : error);
|
|
39
|
+
}
|
|
40
|
+
this.initialized = true;
|
|
41
|
+
this.startFlushInterval(this.config.flushIntervalMs ?? 5000);
|
|
42
|
+
}
|
|
43
|
+
async exportSpan(span) {
|
|
44
|
+
const startTime = Date.now();
|
|
45
|
+
try {
|
|
46
|
+
const langsmithRun = SpanSerializer.toLangSmithFormat(span);
|
|
47
|
+
const response = await fetch(`${this.endpoint}/api/v1/runs`, {
|
|
48
|
+
method: "POST",
|
|
49
|
+
headers: {
|
|
50
|
+
"Content-Type": "application/json",
|
|
51
|
+
"x-api-key": this.apiKey,
|
|
52
|
+
},
|
|
53
|
+
body: JSON.stringify({
|
|
54
|
+
...langsmithRun,
|
|
55
|
+
session_name: this.projectName,
|
|
56
|
+
}),
|
|
57
|
+
});
|
|
58
|
+
if (!response.ok) {
|
|
59
|
+
throw new Error(`Export failed: ${response.statusText}`);
|
|
60
|
+
}
|
|
61
|
+
return this.createSuccessResult(1, Date.now() - startTime);
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
return this.createFailureResult([span.spanId], error instanceof Error ? error.message : String(error), Date.now() - startTime);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
async exportBatch(spans) {
|
|
68
|
+
const startTime = Date.now();
|
|
69
|
+
try {
|
|
70
|
+
const runs = spans.map((s) => ({
|
|
71
|
+
...SpanSerializer.toLangSmithFormat(s),
|
|
72
|
+
session_name: this.projectName,
|
|
73
|
+
}));
|
|
74
|
+
const response = await fetch(`${this.endpoint}/api/v1/runs/batch`, {
|
|
75
|
+
method: "POST",
|
|
76
|
+
headers: {
|
|
77
|
+
"Content-Type": "application/json",
|
|
78
|
+
"x-api-key": this.apiKey,
|
|
79
|
+
},
|
|
80
|
+
body: JSON.stringify({ runs }),
|
|
81
|
+
});
|
|
82
|
+
if (!response.ok) {
|
|
83
|
+
throw new Error(`Batch export failed: ${response.statusText}`);
|
|
84
|
+
}
|
|
85
|
+
return this.createSuccessResult(spans.length, Date.now() - startTime);
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
return this.createFailureResult(spans.map((s) => s.spanId), error instanceof Error ? error.message : String(error), Date.now() - startTime);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
async flush() {
|
|
92
|
+
if (this.buffer.length > 0) {
|
|
93
|
+
const spans = [...this.buffer];
|
|
94
|
+
this.buffer = [];
|
|
95
|
+
await this.exportBatch(spans);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
async shutdown() {
|
|
99
|
+
await this.flush();
|
|
100
|
+
this.stopFlushInterval();
|
|
101
|
+
this.initialized = false;
|
|
102
|
+
}
|
|
103
|
+
async healthCheck() {
|
|
104
|
+
try {
|
|
105
|
+
await this.withRetry(() => this.ping(), "health check");
|
|
106
|
+
return this.createHealthStatus(true);
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
return this.createHealthStatus(false, ["Health check failed"]);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Verify connectivity to LangSmith API
|
|
114
|
+
*/
|
|
115
|
+
async ping() {
|
|
116
|
+
const response = await fetch(`${this.endpoint}/api/v1/info`, {
|
|
117
|
+
headers: { "x-api-key": this.apiKey },
|
|
118
|
+
});
|
|
119
|
+
if (!response.ok) {
|
|
120
|
+
throw new Error(`LangSmith API unreachable: ${response.status}`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=langsmithExporter.js.map
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenTelemetry Exporter
|
|
3
|
+
* Exports spans to OTLP-compatible backends
|
|
4
|
+
*/
|
|
5
|
+
import type { ExporterHealthStatus, ExportResult, OtelExporterConfig, SpanData } from "../types/index.js";
|
|
6
|
+
import { BaseExporter } from "./baseExporter.js";
|
|
7
|
+
/**
|
|
8
|
+
* OpenTelemetry exporter for OTLP-compatible backends
|
|
9
|
+
* Supports HTTP, gRPC, and Zipkin protocols
|
|
10
|
+
*/
|
|
11
|
+
export declare class OtelExporter extends BaseExporter {
|
|
12
|
+
private readonly endpoint;
|
|
13
|
+
private readonly protocol;
|
|
14
|
+
private readonly serviceName;
|
|
15
|
+
private readonly serviceVersion;
|
|
16
|
+
private readonly resourceAttributes;
|
|
17
|
+
private readonly compression;
|
|
18
|
+
constructor(config: OtelExporterConfig);
|
|
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 OTLP endpoint
|
|
27
|
+
*/
|
|
28
|
+
protected ping(): Promise<void>;
|
|
29
|
+
/**
|
|
30
|
+
* Get the export URL based on protocol
|
|
31
|
+
*/
|
|
32
|
+
private getExportUrl;
|
|
33
|
+
/**
|
|
34
|
+
* Send request with optional gzip compression
|
|
35
|
+
* @param endpoint - The URL to send to
|
|
36
|
+
* @param body - The payload to send
|
|
37
|
+
*/
|
|
38
|
+
private sendRequest;
|
|
39
|
+
}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenTelemetry Exporter
|
|
3
|
+
* Exports spans to OTLP-compatible backends
|
|
4
|
+
*/
|
|
5
|
+
import { gzipSync } from "zlib";
|
|
6
|
+
import { SpanSerializer } from "../utils/spanSerializer.js";
|
|
7
|
+
import { BaseExporter } from "./baseExporter.js";
|
|
8
|
+
/**
|
|
9
|
+
* OpenTelemetry exporter for OTLP-compatible backends
|
|
10
|
+
* Supports HTTP, gRPC, and Zipkin protocols
|
|
11
|
+
*/
|
|
12
|
+
export class OtelExporter extends BaseExporter {
|
|
13
|
+
endpoint;
|
|
14
|
+
protocol;
|
|
15
|
+
serviceName;
|
|
16
|
+
serviceVersion;
|
|
17
|
+
resourceAttributes;
|
|
18
|
+
compression;
|
|
19
|
+
constructor(config) {
|
|
20
|
+
super("opentelemetry", config);
|
|
21
|
+
this.endpoint = config.endpoint;
|
|
22
|
+
this.protocol = config.protocol ?? "http";
|
|
23
|
+
this.serviceName = config.serviceName ?? "neurolink-ai";
|
|
24
|
+
this.serviceVersion = config.serviceVersion ?? "1.0.0";
|
|
25
|
+
this.resourceAttributes = config.resourceAttributes ?? {};
|
|
26
|
+
this.compression = config.compression ?? "none";
|
|
27
|
+
}
|
|
28
|
+
async initialize() {
|
|
29
|
+
if (this.initialized) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
this.initialized = true;
|
|
33
|
+
this.startFlushInterval(this.config.flushIntervalMs ?? 5000);
|
|
34
|
+
}
|
|
35
|
+
async exportSpan(span) {
|
|
36
|
+
// Intentionally buffer spans rather than exporting immediately.
|
|
37
|
+
// OTLP is designed for batch export (resourceSpans envelope), so we
|
|
38
|
+
// accumulate spans and flush them together via exportBatch() on the
|
|
39
|
+
// configured flushInterval or when the buffer reaches maxBufferSize.
|
|
40
|
+
this.bufferSpan(span);
|
|
41
|
+
return this.createSuccessResult(0, 0);
|
|
42
|
+
}
|
|
43
|
+
async exportBatch(spans) {
|
|
44
|
+
const startTime = Date.now();
|
|
45
|
+
try {
|
|
46
|
+
const otelSpans = spans.map((s) => SpanSerializer.toOtelFormat(s));
|
|
47
|
+
const payload = {
|
|
48
|
+
resourceSpans: [
|
|
49
|
+
{
|
|
50
|
+
resource: {
|
|
51
|
+
attributes: [
|
|
52
|
+
{
|
|
53
|
+
key: "service.name",
|
|
54
|
+
value: { stringValue: this.serviceName },
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
key: "service.version",
|
|
58
|
+
value: { stringValue: this.serviceVersion },
|
|
59
|
+
},
|
|
60
|
+
...Object.entries(this.resourceAttributes).map(([key, value]) => ({
|
|
61
|
+
key,
|
|
62
|
+
value: { stringValue: value },
|
|
63
|
+
})),
|
|
64
|
+
],
|
|
65
|
+
},
|
|
66
|
+
scopeSpans: [
|
|
67
|
+
{
|
|
68
|
+
scope: {
|
|
69
|
+
name: "neurolink-observability",
|
|
70
|
+
version: "1.0.0",
|
|
71
|
+
},
|
|
72
|
+
spans: otelSpans,
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
};
|
|
78
|
+
const url = this.getExportUrl();
|
|
79
|
+
await this.sendRequest(url, payload);
|
|
80
|
+
return this.createSuccessResult(spans.length, Date.now() - startTime);
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
return this.createFailureResult(spans.map((s) => s.spanId), error instanceof Error ? error.message : String(error), Date.now() - startTime);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
async flush() {
|
|
87
|
+
if (this.buffer.length > 0) {
|
|
88
|
+
const spans = [...this.buffer];
|
|
89
|
+
this.buffer = [];
|
|
90
|
+
await this.exportBatch(spans);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
async shutdown() {
|
|
94
|
+
await this.flush();
|
|
95
|
+
this.stopFlushInterval();
|
|
96
|
+
this.initialized = false;
|
|
97
|
+
}
|
|
98
|
+
async healthCheck() {
|
|
99
|
+
try {
|
|
100
|
+
await this.withRetry(() => this.ping(), "health check");
|
|
101
|
+
return this.createHealthStatus(true);
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
return this.createHealthStatus(false, ["Endpoint unreachable"]);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Verify connectivity to OTLP endpoint
|
|
109
|
+
*/
|
|
110
|
+
async ping() {
|
|
111
|
+
const response = await fetch(this.endpoint, { method: "HEAD" });
|
|
112
|
+
// 405 (Method Not Allowed) is acceptable for HEAD requests
|
|
113
|
+
if (!response.ok && response.status !== 405) {
|
|
114
|
+
throw new Error(`OTLP endpoint unreachable: ${response.status}`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Get the export URL based on protocol
|
|
119
|
+
*/
|
|
120
|
+
getExportUrl() {
|
|
121
|
+
switch (this.protocol) {
|
|
122
|
+
case "http":
|
|
123
|
+
return `${this.endpoint}/v1/traces`;
|
|
124
|
+
case "zipkin":
|
|
125
|
+
return `${this.endpoint}/api/v2/spans`;
|
|
126
|
+
case "grpc":
|
|
127
|
+
// For gRPC, this would use @grpc/grpc-js
|
|
128
|
+
return this.endpoint;
|
|
129
|
+
default:
|
|
130
|
+
return `${this.endpoint}/v1/traces`;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Send request with optional gzip compression
|
|
135
|
+
* @param endpoint - The URL to send to
|
|
136
|
+
* @param body - The payload to send
|
|
137
|
+
*/
|
|
138
|
+
async sendRequest(endpoint, body) {
|
|
139
|
+
const jsonBody = JSON.stringify(body);
|
|
140
|
+
let bodyData = jsonBody;
|
|
141
|
+
const headers = {
|
|
142
|
+
"Content-Type": "application/json",
|
|
143
|
+
};
|
|
144
|
+
// Apply gzip compression if configured
|
|
145
|
+
if (this.compression === "gzip") {
|
|
146
|
+
const compressed = gzipSync(Buffer.from(jsonBody));
|
|
147
|
+
// Convert Buffer to Uint8Array for fetch compatibility
|
|
148
|
+
bodyData = new Uint8Array(compressed);
|
|
149
|
+
headers["Content-Encoding"] = "gzip";
|
|
150
|
+
}
|
|
151
|
+
// Add any custom headers from config
|
|
152
|
+
if (this.config.headers) {
|
|
153
|
+
Object.assign(headers, this.config.headers);
|
|
154
|
+
}
|
|
155
|
+
const response = await fetch(endpoint, {
|
|
156
|
+
method: "POST",
|
|
157
|
+
headers,
|
|
158
|
+
body: bodyData,
|
|
159
|
+
});
|
|
160
|
+
if (!response.ok) {
|
|
161
|
+
throw new Error(`OTLP export failed: ${response.statusText}`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
//# sourceMappingURL=otelExporter.js.map
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PostHog Exporter
|
|
3
|
+
* Exports spans to PostHog product analytics platform
|
|
4
|
+
* @see https://posthog.com/docs/api
|
|
5
|
+
*/
|
|
6
|
+
import type { ExporterHealthStatus, ExportResult, PostHogExporterConfig, SpanData } from "../types/index.js";
|
|
7
|
+
import { BaseExporter } from "./baseExporter.js";
|
|
8
|
+
/**
|
|
9
|
+
* PostHog exporter for product analytics and LLM event tracking
|
|
10
|
+
* Supports capturing LLM interactions as events with properties
|
|
11
|
+
*/
|
|
12
|
+
export declare class PostHogExporter extends BaseExporter {
|
|
13
|
+
private readonly apiKey;
|
|
14
|
+
private readonly host;
|
|
15
|
+
private readonly personalApiKey?;
|
|
16
|
+
constructor(config: PostHogExporterConfig);
|
|
17
|
+
initialize(): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Get authorization headers
|
|
20
|
+
*/
|
|
21
|
+
private getHeaders;
|
|
22
|
+
exportSpan(span: SpanData): Promise<ExportResult>;
|
|
23
|
+
exportBatch(spans: SpanData[]): Promise<ExportResult>;
|
|
24
|
+
flush(): Promise<void>;
|
|
25
|
+
shutdown(): Promise<void>;
|
|
26
|
+
healthCheck(): Promise<ExporterHealthStatus>;
|
|
27
|
+
/**
|
|
28
|
+
* Verify connectivity to PostHog API
|
|
29
|
+
*/
|
|
30
|
+
protected ping(): Promise<void>;
|
|
31
|
+
/**
|
|
32
|
+
* Convert span to PostHog event format
|
|
33
|
+
*/
|
|
34
|
+
private convertToPostHogEvent;
|
|
35
|
+
/**
|
|
36
|
+
* Get event name based on span type
|
|
37
|
+
*/
|
|
38
|
+
private getEventName;
|
|
39
|
+
/**
|
|
40
|
+
* Convert span status to string
|
|
41
|
+
*/
|
|
42
|
+
private getStatusString;
|
|
43
|
+
/**
|
|
44
|
+
* Extract custom properties from span attributes
|
|
45
|
+
* Filters out standard attributes that are already handled
|
|
46
|
+
*/
|
|
47
|
+
private extractCustomProperties;
|
|
48
|
+
}
|