@anyway-sh/node-server-sdk 0.22.9 → 0.22.10
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/README.md +154 -0
- package/dist/index.d.ts +35 -2
- package/dist/index.js +94 -24
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +94 -25
- package/dist/src/lib/interfaces/initialize-options.interface.d.ts +10 -0
- package/dist/src/lib/pricing/calculator.d.ts +24 -0
- package/dist/src/lib/pricing/index.d.ts +4 -0
- package/dist/src/lib/pricing/loader.d.ts +3 -0
- package/dist/src/lib/tracing/span-processor.d.ts +2 -0
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -66,7 +66,7 @@ class PromptNotFoundError extends TraceloopError {
|
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
var version = "0.22.
|
|
69
|
+
var version = "0.22.10";
|
|
70
70
|
|
|
71
71
|
/**
|
|
72
72
|
* Base class for handling annotation operations with the Traceloop API.
|
|
@@ -3238,6 +3238,10 @@ function parseKeyPairsIntoRecord(keyPairs) {
|
|
|
3238
3238
|
}
|
|
3239
3239
|
|
|
3240
3240
|
const ALL_INSTRUMENTATION_LIBRARIES = "all";
|
|
3241
|
+
let _pricingCalculator = null;
|
|
3242
|
+
const setPricingCalculator = (calculator) => {
|
|
3243
|
+
_pricingCalculator = calculator;
|
|
3244
|
+
};
|
|
3241
3245
|
const spanAgentNames = new Map();
|
|
3242
3246
|
const SPAN_AGENT_NAME_TTL = 5 * 60 * 1000;
|
|
3243
3247
|
const AI_TELEMETRY_METADATA_AGENT = "ai.telemetry.metadata.agent";
|
|
@@ -3387,13 +3391,9 @@ const ensureSpanCompatibility = (span) => {
|
|
|
3387
3391
|
const onSpanEnd = (originalOnEnd, instrumentationLibraries) => {
|
|
3388
3392
|
return (span) => {
|
|
3389
3393
|
var _a, _b, _c;
|
|
3390
|
-
const libName = ((_a = span.instrumentationScope) === null || _a === void 0 ? void 0 : _a.name) ||
|
|
3391
|
-
((_b = span.instrumentationLibrary) === null || _b === void 0 ? void 0 : _b.name) ||
|
|
3392
|
-
"unknown";
|
|
3393
|
-
console.log(`[Anyway Debug] onSpanEnd: span="${span.name}" lib="${libName}"`);
|
|
3394
3394
|
if (instrumentationLibraries &&
|
|
3395
|
-
!instrumentationLibraries.includes(
|
|
3396
|
-
|
|
3395
|
+
!instrumentationLibraries.includes(((_a = span.instrumentationScope) === null || _a === void 0 ? void 0 : _a.name) ||
|
|
3396
|
+
((_b = span.instrumentationLibrary) === null || _b === void 0 ? void 0 : _b.name))) {
|
|
3397
3397
|
return;
|
|
3398
3398
|
}
|
|
3399
3399
|
transformAiSdkSpanAttributes(span);
|
|
@@ -3419,8 +3419,10 @@ const onSpanEnd = (originalOnEnd, instrumentationLibraries) => {
|
|
|
3419
3419
|
if (Math.random() < 0.01) {
|
|
3420
3420
|
cleanupExpiredSpanAgentNames();
|
|
3421
3421
|
}
|
|
3422
|
+
if (_pricingCalculator) {
|
|
3423
|
+
_pricingCalculator.addCostAttributes(span);
|
|
3424
|
+
}
|
|
3422
3425
|
const compatibleSpan = ensureSpanCompatibility(span);
|
|
3423
|
-
console.log(`[Anyway Debug] Span queued for export: "${span.name}" lib="${libName}"`);
|
|
3424
3426
|
originalOnEnd(compatibleSpan);
|
|
3425
3427
|
};
|
|
3426
3428
|
};
|
|
@@ -3706,19 +3708,6 @@ const startTracing = (options) => {
|
|
|
3706
3708
|
url: `${baseUrl}/v1/traces`,
|
|
3707
3709
|
headers,
|
|
3708
3710
|
}));
|
|
3709
|
-
// [Anyway Debug] Wrap exporter to log outgoing calls
|
|
3710
|
-
const origExport = traceExporter.export.bind(traceExporter);
|
|
3711
|
-
traceExporter.export = (spans, resultCallback) => {
|
|
3712
|
-
var _a, _b;
|
|
3713
|
-
console.log(`[Anyway Debug] Exporting ${spans.length} span(s) to ${baseUrl}/v1/traces`);
|
|
3714
|
-
for (const s of spans) {
|
|
3715
|
-
console.log(`[Anyway Debug] - ${s.name} (${((_a = s.instrumentationLibrary) === null || _a === void 0 ? void 0 : _a.name) || ((_b = s.instrumentationScope) === null || _b === void 0 ? void 0 : _b.name) || "unknown"})`);
|
|
3716
|
-
}
|
|
3717
|
-
return origExport(spans, (result) => {
|
|
3718
|
-
console.log(`[Anyway Debug] Export result: code=${result.code}${result.error ? ` error=${result.error.message}` : ""}`);
|
|
3719
|
-
resultCallback(result);
|
|
3720
|
-
});
|
|
3721
|
-
};
|
|
3722
3711
|
_spanProcessor = createSpanProcessor({
|
|
3723
3712
|
apiKey: options.apiKey,
|
|
3724
3713
|
baseUrl: options.baseUrl,
|
|
@@ -3856,6 +3845,80 @@ const initializeRegistry = (options) => {
|
|
|
3856
3845
|
});
|
|
3857
3846
|
};
|
|
3858
3847
|
|
|
3848
|
+
const DATE_SUFFIX_PATTERN = /-\d{4}-\d{2}-\d{2}$/;
|
|
3849
|
+
const DATE_COMPACT_SUFFIX_PATTERN = /-\d{8}$/;
|
|
3850
|
+
class PricingCalculator {
|
|
3851
|
+
constructor(pricingData) {
|
|
3852
|
+
var _a;
|
|
3853
|
+
this.chatModels = (_a = pricingData.chat) !== null && _a !== void 0 ? _a : {};
|
|
3854
|
+
}
|
|
3855
|
+
findPricing(modelName) {
|
|
3856
|
+
if (!modelName)
|
|
3857
|
+
return null;
|
|
3858
|
+
const models = this.chatModels;
|
|
3859
|
+
// 1. Exact match
|
|
3860
|
+
if (models[modelName]) {
|
|
3861
|
+
return this.normalize(models[modelName]);
|
|
3862
|
+
}
|
|
3863
|
+
// 2. Strip date suffix and retry
|
|
3864
|
+
let stripped = modelName.replace(DATE_SUFFIX_PATTERN, "");
|
|
3865
|
+
stripped = stripped.replace(DATE_COMPACT_SUFFIX_PATTERN, "");
|
|
3866
|
+
if (stripped !== modelName && models[stripped]) {
|
|
3867
|
+
return this.normalize(models[stripped]);
|
|
3868
|
+
}
|
|
3869
|
+
// 3. Prefix match (longest wins)
|
|
3870
|
+
let bestMatch = null;
|
|
3871
|
+
let bestLen = 0;
|
|
3872
|
+
for (const baseModel of Object.keys(models)) {
|
|
3873
|
+
if (modelName.startsWith(baseModel) && baseModel.length > bestLen) {
|
|
3874
|
+
bestMatch = baseModel;
|
|
3875
|
+
bestLen = baseModel.length;
|
|
3876
|
+
}
|
|
3877
|
+
}
|
|
3878
|
+
if (bestMatch) {
|
|
3879
|
+
return this.normalize(models[bestMatch]);
|
|
3880
|
+
}
|
|
3881
|
+
return null;
|
|
3882
|
+
}
|
|
3883
|
+
addCostAttributes(span) {
|
|
3884
|
+
const attrs = span.attributes;
|
|
3885
|
+
if (!attrs)
|
|
3886
|
+
return;
|
|
3887
|
+
const model = attrs[ATTR_GEN_AI_RESPONSE_MODEL] ||
|
|
3888
|
+
attrs[ATTR_GEN_AI_REQUEST_MODEL];
|
|
3889
|
+
if (!model)
|
|
3890
|
+
return;
|
|
3891
|
+
const inputTokens = attrs[ATTR_GEN_AI_USAGE_INPUT_TOKENS];
|
|
3892
|
+
const outputTokens = attrs[ATTR_GEN_AI_USAGE_OUTPUT_TOKENS];
|
|
3893
|
+
if (inputTokens == null && outputTokens == null)
|
|
3894
|
+
return;
|
|
3895
|
+
const pricing = this.findPricing(model);
|
|
3896
|
+
if (!pricing)
|
|
3897
|
+
return;
|
|
3898
|
+
const inputCost = (inputTokens !== null && inputTokens !== void 0 ? inputTokens : 0) * pricing.inputCostPerToken;
|
|
3899
|
+
const outputCost = (outputTokens !== null && outputTokens !== void 0 ? outputTokens : 0) * pricing.outputCostPerToken;
|
|
3900
|
+
span.attributes["gen_ai.usage.input_cost"] = inputCost;
|
|
3901
|
+
span.attributes["gen_ai.usage.output_cost"] = outputCost;
|
|
3902
|
+
span.attributes["gen_ai.usage.cost"] = inputCost + outputCost;
|
|
3903
|
+
}
|
|
3904
|
+
normalize(pricing) {
|
|
3905
|
+
var _a, _b;
|
|
3906
|
+
return {
|
|
3907
|
+
inputCostPerToken: ((_a = pricing.promptPrice) !== null && _a !== void 0 ? _a : 0) / 1000,
|
|
3908
|
+
outputCostPerToken: ((_b = pricing.completionPrice) !== null && _b !== void 0 ? _b : 0) / 1000,
|
|
3909
|
+
};
|
|
3910
|
+
}
|
|
3911
|
+
}
|
|
3912
|
+
|
|
3913
|
+
function loadPricing(pricingJsonPath) {
|
|
3914
|
+
if (pricingJsonPath) {
|
|
3915
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
3916
|
+
const fs = require("fs");
|
|
3917
|
+
return JSON.parse(fs.readFileSync(pricingJsonPath, "utf-8"));
|
|
3918
|
+
}
|
|
3919
|
+
return require("./data/default_pricing.json");
|
|
3920
|
+
}
|
|
3921
|
+
|
|
3859
3922
|
let _configuration;
|
|
3860
3923
|
let _client;
|
|
3861
3924
|
/**
|
|
@@ -3918,15 +3981,21 @@ const initialize = (options = {}) => {
|
|
|
3918
3981
|
if (!options.silenceInitializationMessage) {
|
|
3919
3982
|
console.log(`Traceloop exporting traces to ${_configuration.exporter ? "a custom exporter" : _configuration.baseUrl}`);
|
|
3920
3983
|
}
|
|
3921
|
-
console.log(`[Anyway Debug] Trace endpoint: ${_configuration.baseUrl}/v1/traces`);
|
|
3922
|
-
console.log(`[Anyway Debug] API key present: ${!!_configuration.apiKey}`);
|
|
3923
|
-
console.log(`[Anyway Debug] Using custom exporter: ${!!_configuration.exporter}`);
|
|
3924
3984
|
if (options.tracingEnabled === undefined || options.tracingEnabled) {
|
|
3925
3985
|
if (options.logLevel) {
|
|
3926
3986
|
diag.setLogger(new DiagConsoleLogger(), logLevelToOtelLogLevel(options.logLevel));
|
|
3927
3987
|
}
|
|
3928
3988
|
startTracing(_configuration);
|
|
3929
3989
|
}
|
|
3990
|
+
if (options.pricingEnabled !== false) {
|
|
3991
|
+
try {
|
|
3992
|
+
const pricingData = loadPricing(options.pricingJsonPath);
|
|
3993
|
+
setPricingCalculator(new PricingCalculator(pricingData));
|
|
3994
|
+
}
|
|
3995
|
+
catch (e) {
|
|
3996
|
+
console.warn(`[Traceloop] Failed to initialize pricing: ${e.message}`);
|
|
3997
|
+
}
|
|
3998
|
+
}
|
|
3930
3999
|
initializeRegistry(_configuration);
|
|
3931
4000
|
if (options.apiKey) {
|
|
3932
4001
|
_client = new TraceloopClient({
|
|
@@ -4399,5 +4468,5 @@ var AssociationProperty;
|
|
|
4399
4468
|
AssociationProperty["SESSION_ID"] = "session_id";
|
|
4400
4469
|
})(AssociationProperty || (AssociationProperty = {}));
|
|
4401
4470
|
|
|
4402
|
-
export { ALL_INSTRUMENTATION_LIBRARIES, ArgumentNotProvidedError, AssociationProperty, Attachment, AttachmentReference, AttachmentUploader, Column, Dataset, Datasets, Evaluator, EvaluatorMadeByTraceloop, Experiment, ExternalAttachment, ImageUploader, InitializationError, LLMSpan, NotInitializedError, PromptNotFoundError, Row, SEVERITY, TraceloopClient, TraceloopError, VectorSpan, agent, attachment, conversation, createEvaluator, createSpanProcessor, forceFlush, getAvailableEvaluatorSlugs, getClient, getEvaluatorSchemaInfo, getPrompt, getTraceloopTracer, initialize, isAnyAttachment, isAttachment, isAttachmentReference, isExternalAttachment, reportCustomMetric, task, tool, traceloopInstrumentationLibraries, validateEvaluatorInput, waitForInitialization, withAgent, withAssociationProperties, withConversation, withLLMCall, withTask, withTool, withVectorDBCall, withWorkflow, workflow };
|
|
4471
|
+
export { ALL_INSTRUMENTATION_LIBRARIES, ArgumentNotProvidedError, AssociationProperty, Attachment, AttachmentReference, AttachmentUploader, Column, Dataset, Datasets, Evaluator, EvaluatorMadeByTraceloop, Experiment, ExternalAttachment, ImageUploader, InitializationError, LLMSpan, NotInitializedError, PromptNotFoundError, Row, SEVERITY, TraceloopClient, TraceloopError, VectorSpan, agent, attachment, conversation, createEvaluator, createSpanProcessor, forceFlush, getAvailableEvaluatorSlugs, getClient, getEvaluatorSchemaInfo, getPrompt, getTraceloopTracer, initialize, isAnyAttachment, isAttachment, isAttachmentReference, isExternalAttachment, reportCustomMetric, setPricingCalculator, task, tool, traceloopInstrumentationLibraries, validateEvaluatorInput, waitForInitialization, withAgent, withAssociationProperties, withConversation, withLLMCall, withTask, withTool, withVectorDBCall, withWorkflow, workflow };
|
|
4403
4472
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -129,5 +129,15 @@ export interface InitializeOptions {
|
|
|
129
129
|
* This is used to configure the Google Cloud Trace Exporter.
|
|
130
130
|
*/
|
|
131
131
|
gcpProjectId?: string;
|
|
132
|
+
/**
|
|
133
|
+
* Whether to calculate and add cost attributes to spans. Optional.
|
|
134
|
+
* Defaults to true.
|
|
135
|
+
*/
|
|
136
|
+
pricingEnabled?: boolean;
|
|
137
|
+
/**
|
|
138
|
+
* Path to a custom pricing JSON file. Optional.
|
|
139
|
+
* If not set, uses the bundled default pricing data.
|
|
140
|
+
*/
|
|
141
|
+
pricingJsonPath?: string;
|
|
132
142
|
}
|
|
133
143
|
//# sourceMappingURL=initialize-options.interface.d.ts.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ReadableSpan } from "@opentelemetry/sdk-trace-base";
|
|
2
|
+
interface NormalizedPricing {
|
|
3
|
+
inputCostPerToken: number;
|
|
4
|
+
outputCostPerToken: number;
|
|
5
|
+
}
|
|
6
|
+
interface ModelPricing {
|
|
7
|
+
promptPrice: number;
|
|
8
|
+
completionPrice: number;
|
|
9
|
+
}
|
|
10
|
+
export interface PricingData {
|
|
11
|
+
chat?: Record<string, ModelPricing>;
|
|
12
|
+
embeddings?: Record<string, number>;
|
|
13
|
+
images?: Record<string, unknown>;
|
|
14
|
+
audio?: Record<string, unknown>;
|
|
15
|
+
}
|
|
16
|
+
export declare class PricingCalculator {
|
|
17
|
+
private chatModels;
|
|
18
|
+
constructor(pricingData: PricingData);
|
|
19
|
+
findPricing(modelName: string): NormalizedPricing | null;
|
|
20
|
+
addCostAttributes(span: ReadableSpan): void;
|
|
21
|
+
private normalize;
|
|
22
|
+
}
|
|
23
|
+
export {};
|
|
24
|
+
//# sourceMappingURL=calculator.d.ts.map
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { SpanProcessor } from "@opentelemetry/sdk-trace-node";
|
|
2
2
|
import { SpanExporter } from "@opentelemetry/sdk-trace-base";
|
|
3
|
+
import { PricingCalculator } from "../pricing";
|
|
3
4
|
export declare const ALL_INSTRUMENTATION_LIBRARIES: "all";
|
|
4
5
|
type AllInstrumentationLibraries = typeof ALL_INSTRUMENTATION_LIBRARIES;
|
|
6
|
+
export declare const setPricingCalculator: (calculator: PricingCalculator | null) => void;
|
|
5
7
|
export interface SpanProcessorOptions {
|
|
6
8
|
/**
|
|
7
9
|
* The API Key for sending traces data. Optional.
|