scorecard-ai 2.3.0 → 2.4.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.4.0 (2025-10-31)
4
+
5
+ Full Changelog: [v2.3.0...v2.4.0](https://github.com/scorecard-ai/scorecard-node/compare/v2.3.0...v2.4.0)
6
+
3
7
  ## 2.3.0 (2025-10-31)
4
8
 
5
9
  Full Changelog: [v2.2.0...v2.3.0](https://github.com/scorecard-ai/scorecard-node/compare/v2.2.0...v2.3.0)
package/index.d.mts CHANGED
@@ -5,4 +5,5 @@ export { Scorecard, type ClientOptions } from "./client.mjs";
5
5
  export { PagePromise } from "./core/pagination.mjs";
6
6
  export { ScorecardError, APIError, APIConnectionError, APIConnectionTimeoutError, APIUserAbortError, NotFoundError, ConflictError, RateLimitError, BadRequestError, AuthenticationError, InternalServerError, PermissionDeniedError, UnprocessableEntityError, } from "./core/error.mjs";
7
7
  export { runAndEvaluate } from "./lib/runAndEvaluate.mjs";
8
+ export { wrapAISDK } from "./lib/wrapAISDK.mjs";
8
9
  //# sourceMappingURL=index.d.mts.map
package/index.d.mts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":"OAEO,EAAE,SAAS,IAAI,OAAO,EAAE;OAExB,EAAE,KAAK,UAAU,EAAE,MAAM,EAAE;OAC3B,EAAE,UAAU,EAAE;OACd,EAAE,SAAS,EAAE,KAAK,aAAa,EAAE;OACjC,EAAE,WAAW,EAAE;OACf,EACL,cAAc,EACd,QAAQ,EACR,kBAAkB,EAClB,yBAAyB,EACzB,iBAAiB,EACjB,aAAa,EACb,aAAa,EACb,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,EACrB,wBAAwB,GACzB;OAEM,EAAE,cAAc,EAAE"}
1
+ {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":"OAEO,EAAE,SAAS,IAAI,OAAO,EAAE;OAExB,EAAE,KAAK,UAAU,EAAE,MAAM,EAAE;OAC3B,EAAE,UAAU,EAAE;OACd,EAAE,SAAS,EAAE,KAAK,aAAa,EAAE;OACjC,EAAE,WAAW,EAAE;OACf,EACL,cAAc,EACd,QAAQ,EACR,kBAAkB,EAClB,yBAAyB,EACzB,iBAAiB,EACjB,aAAa,EACb,aAAa,EACb,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,EACrB,wBAAwB,GACzB;OAEM,EAAE,cAAc,EAAE;OAClB,EAAE,SAAS,EAAE"}
package/index.d.ts CHANGED
@@ -5,4 +5,5 @@ export { Scorecard, type ClientOptions } from "./client.js";
5
5
  export { PagePromise } from "./core/pagination.js";
6
6
  export { ScorecardError, APIError, APIConnectionError, APIConnectionTimeoutError, APIUserAbortError, NotFoundError, ConflictError, RateLimitError, BadRequestError, AuthenticationError, InternalServerError, PermissionDeniedError, UnprocessableEntityError, } from "./core/error.js";
7
7
  export { runAndEvaluate } from "./lib/runAndEvaluate.js";
8
+ export { wrapAISDK } from "./lib/wrapAISDK.js";
8
9
  //# sourceMappingURL=index.d.ts.map
package/index.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":"OAEO,EAAE,SAAS,IAAI,OAAO,EAAE;OAExB,EAAE,KAAK,UAAU,EAAE,MAAM,EAAE;OAC3B,EAAE,UAAU,EAAE;OACd,EAAE,SAAS,EAAE,KAAK,aAAa,EAAE;OACjC,EAAE,WAAW,EAAE;OACf,EACL,cAAc,EACd,QAAQ,EACR,kBAAkB,EAClB,yBAAyB,EACzB,iBAAiB,EACjB,aAAa,EACb,aAAa,EACb,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,EACrB,wBAAwB,GACzB;OAEM,EAAE,cAAc,EAAE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":"OAEO,EAAE,SAAS,IAAI,OAAO,EAAE;OAExB,EAAE,KAAK,UAAU,EAAE,MAAM,EAAE;OAC3B,EAAE,UAAU,EAAE;OACd,EAAE,SAAS,EAAE,KAAK,aAAa,EAAE;OACjC,EAAE,WAAW,EAAE;OACf,EACL,cAAc,EACd,QAAQ,EACR,kBAAkB,EAClB,yBAAyB,EACzB,iBAAiB,EACjB,aAAa,EACb,aAAa,EACb,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,EACrB,wBAAwB,GACzB;OAEM,EAAE,cAAc,EAAE;OAClB,EAAE,SAAS,EAAE"}
package/index.js CHANGED
@@ -4,7 +4,7 @@ exports = module.exports = function (...args) {
4
4
  return new exports.default(...args)
5
5
  }
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.runAndEvaluate = exports.UnprocessableEntityError = exports.PermissionDeniedError = exports.InternalServerError = exports.AuthenticationError = exports.BadRequestError = exports.RateLimitError = exports.ConflictError = exports.NotFoundError = exports.APIUserAbortError = exports.APIConnectionTimeoutError = exports.APIConnectionError = exports.APIError = exports.ScorecardError = exports.PagePromise = exports.Scorecard = exports.APIPromise = exports.toFile = exports.default = void 0;
7
+ exports.wrapAISDK = exports.runAndEvaluate = exports.UnprocessableEntityError = exports.PermissionDeniedError = exports.InternalServerError = exports.AuthenticationError = exports.BadRequestError = exports.RateLimitError = exports.ConflictError = exports.NotFoundError = exports.APIUserAbortError = exports.APIConnectionTimeoutError = exports.APIConnectionError = exports.APIError = exports.ScorecardError = exports.PagePromise = exports.Scorecard = exports.APIPromise = exports.toFile = exports.default = void 0;
8
8
  var client_1 = require("./client.js");
9
9
  Object.defineProperty(exports, "default", { enumerable: true, get: function () { return client_1.Scorecard; } });
10
10
  var uploads_1 = require("./core/uploads.js");
@@ -31,4 +31,6 @@ Object.defineProperty(exports, "PermissionDeniedError", { enumerable: true, get:
31
31
  Object.defineProperty(exports, "UnprocessableEntityError", { enumerable: true, get: function () { return error_1.UnprocessableEntityError; } });
32
32
  var runAndEvaluate_1 = require("./lib/runAndEvaluate.js");
33
33
  Object.defineProperty(exports, "runAndEvaluate", { enumerable: true, get: function () { return runAndEvaluate_1.runAndEvaluate; } });
34
+ var wrapAISDK_1 = require("./lib/wrapAISDK.js");
35
+ Object.defineProperty(exports, "wrapAISDK", { enumerable: true, get: function () { return wrapAISDK_1.wrapAISDK; } });
34
36
  //# sourceMappingURL=index.js.map
package/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":";AAAA,sFAAsF;;;AAEtF,sCAAgD;AAAvC,iGAAA,SAAS,OAAW;AAE7B,6CAAyD;AAA/B,iGAAA,MAAM,OAAA;AAChC,qDAAgD;AAAvC,yGAAA,UAAU,OAAA;AACnB,sCAAyD;AAAhD,mGAAA,SAAS,OAAA;AAClB,mDAAgD;AAAvC,yGAAA,WAAW,OAAA;AACpB,yCAcsB;AAbpB,uGAAA,cAAc,OAAA;AACd,iGAAA,QAAQ,OAAA;AACR,2GAAA,kBAAkB,OAAA;AAClB,kHAAA,yBAAyB,OAAA;AACzB,0GAAA,iBAAiB,OAAA;AACjB,sGAAA,aAAa,OAAA;AACb,sGAAA,aAAa,OAAA;AACb,uGAAA,cAAc,OAAA;AACd,wGAAA,eAAe,OAAA;AACf,4GAAA,mBAAmB,OAAA;AACnB,4GAAA,mBAAmB,OAAA;AACnB,8GAAA,qBAAqB,OAAA;AACrB,iHAAA,wBAAwB,OAAA;AAG1B,0DAAsD;AAA7C,gHAAA,cAAc,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":";AAAA,sFAAsF;;;AAEtF,sCAAgD;AAAvC,iGAAA,SAAS,OAAW;AAE7B,6CAAyD;AAA/B,iGAAA,MAAM,OAAA;AAChC,qDAAgD;AAAvC,yGAAA,UAAU,OAAA;AACnB,sCAAyD;AAAhD,mGAAA,SAAS,OAAA;AAClB,mDAAgD;AAAvC,yGAAA,WAAW,OAAA;AACpB,yCAcsB;AAbpB,uGAAA,cAAc,OAAA;AACd,iGAAA,QAAQ,OAAA;AACR,2GAAA,kBAAkB,OAAA;AAClB,kHAAA,yBAAyB,OAAA;AACzB,0GAAA,iBAAiB,OAAA;AACjB,sGAAA,aAAa,OAAA;AACb,sGAAA,aAAa,OAAA;AACb,uGAAA,cAAc,OAAA;AACd,wGAAA,eAAe,OAAA;AACf,4GAAA,mBAAmB,OAAA;AACnB,4GAAA,mBAAmB,OAAA;AACnB,8GAAA,qBAAqB,OAAA;AACrB,iHAAA,wBAAwB,OAAA;AAG1B,0DAAsD;AAA7C,gHAAA,cAAc,OAAA;AACvB,gDAA4C;AAAnC,sGAAA,SAAS,OAAA"}
package/index.mjs CHANGED
@@ -6,4 +6,5 @@ export { Scorecard } from "./client.mjs";
6
6
  export { PagePromise } from "./core/pagination.mjs";
7
7
  export { ScorecardError, APIError, APIConnectionError, APIConnectionTimeoutError, APIUserAbortError, NotFoundError, ConflictError, RateLimitError, BadRequestError, AuthenticationError, InternalServerError, PermissionDeniedError, UnprocessableEntityError, } from "./core/error.mjs";
8
8
  export { runAndEvaluate } from "./lib/runAndEvaluate.mjs";
9
+ export { wrapAISDK } from "./lib/wrapAISDK.mjs";
9
10
  //# sourceMappingURL=index.mjs.map
package/index.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":"AAAA,sFAAsF;OAE/E,EAAE,SAAS,IAAI,OAAO,EAAE;OAExB,EAAmB,MAAM,EAAE;OAC3B,EAAE,UAAU,EAAE;OACd,EAAE,SAAS,EAAsB;OACjC,EAAE,WAAW,EAAE;OACf,EACL,cAAc,EACd,QAAQ,EACR,kBAAkB,EAClB,yBAAyB,EACzB,iBAAiB,EACjB,aAAa,EACb,aAAa,EACb,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,EACrB,wBAAwB,GACzB;OAEM,EAAE,cAAc,EAAE"}
1
+ {"version":3,"file":"index.mjs","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":"AAAA,sFAAsF;OAE/E,EAAE,SAAS,IAAI,OAAO,EAAE;OAExB,EAAmB,MAAM,EAAE;OAC3B,EAAE,UAAU,EAAE;OACd,EAAE,SAAS,EAAsB;OACjC,EAAE,WAAW,EAAE;OACf,EACL,cAAc,EACd,QAAQ,EACR,kBAAkB,EAClB,yBAAyB,EACzB,iBAAiB,EACjB,aAAa,EACb,aAAa,EACb,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,EACrB,wBAAwB,GACzB;OAEM,EAAE,cAAc,EAAE;OAClB,EAAE,SAAS,EAAE"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Configuration for the Scorecard AI SDK wrapper
3
+ */
4
+ interface ScorecardConfig {
5
+ /**
6
+ * ID of the Scorecard project that traces should be associated with.
7
+ * Defaults to SCORECARD_PROJECT_ID environment variable.
8
+ */
9
+ projectId?: string;
10
+ /**
11
+ * Metrics to score the traces against.
12
+ * It can be a list of metric IDs, descriptions of what you want the metric to do, or a mix of both.
13
+ * For example: ['123', 'Check if the response is concise'].
14
+ * If it's a description, the metric will be created if it doesn't exist.
15
+ * Defaults to empty array.
16
+ */
17
+ metrics?: string[];
18
+ /**
19
+ * Scorecard API key for authentication.
20
+ * Defaults to SCORECARD_API_KEY environment variable.
21
+ */
22
+ apiKey?: string;
23
+ /**
24
+ * Service name for telemetry.
25
+ * Defaults to "ai-sdk-app".
26
+ */
27
+ serviceName?: string;
28
+ /**
29
+ * Service version for telemetry.
30
+ * Defaults to undefined.
31
+ */
32
+ serviceVersion?: string;
33
+ /**
34
+ * Max export batch size for the batch span processor.
35
+ * Defaults to 1 so the traces are exported immediately.
36
+ */
37
+ maxExportBatchSize?: number;
38
+ }
39
+ /**
40
+ * Wraps the AI SDK module to automatically inject telemetry configuration.
41
+ *
42
+ * @param aiSDKModule - The AI SDK module (e.g., import('ai'))
43
+ * @param config - Optional Scorecard configuration
44
+ * @returns Proxied AI SDK module with automatic telemetry injection
45
+ *
46
+ * @example
47
+ * ```typescript
48
+ * import ai from 'ai';
49
+ * import { wrapAISDK } from 'scorecard-ai';
50
+ *
51
+ * const aiSDK = await wrapAISDK(ai);
52
+ *
53
+ * // Now all AI SDK calls will automatically send traces to Scorecard.
54
+ * const { text } = await aiSDK.generateText({
55
+ * model: openai('gpt-4o-mini'),
56
+ * prompt: 'What is the capital of France? Answer in one sentence.',
57
+ * });
58
+ * ```
59
+ */
60
+ export declare function wrapAISDK<T extends Record<string, unknown>>(aiSDKModule: T, config?: ScorecardConfig): T;
61
+ export {};
62
+ //# sourceMappingURL=wrapAISDK.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wrapAISDK.d.mts","sourceRoot":"","sources":["../src/lib/wrapAISDK.ts"],"names":[],"mappings":"AASA;;GAEG;AACH,UAAU,eAAe;IACvB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IAEnB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAyED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACzD,WAAW,EAAE,CAAC,EACd,MAAM,GAAE,eAAoB,GAC3B,CAAC,CAmFH"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Configuration for the Scorecard AI SDK wrapper
3
+ */
4
+ interface ScorecardConfig {
5
+ /**
6
+ * ID of the Scorecard project that traces should be associated with.
7
+ * Defaults to SCORECARD_PROJECT_ID environment variable.
8
+ */
9
+ projectId?: string;
10
+ /**
11
+ * Metrics to score the traces against.
12
+ * It can be a list of metric IDs, descriptions of what you want the metric to do, or a mix of both.
13
+ * For example: ['123', 'Check if the response is concise'].
14
+ * If it's a description, the metric will be created if it doesn't exist.
15
+ * Defaults to empty array.
16
+ */
17
+ metrics?: string[];
18
+ /**
19
+ * Scorecard API key for authentication.
20
+ * Defaults to SCORECARD_API_KEY environment variable.
21
+ */
22
+ apiKey?: string;
23
+ /**
24
+ * Service name for telemetry.
25
+ * Defaults to "ai-sdk-app".
26
+ */
27
+ serviceName?: string;
28
+ /**
29
+ * Service version for telemetry.
30
+ * Defaults to undefined.
31
+ */
32
+ serviceVersion?: string;
33
+ /**
34
+ * Max export batch size for the batch span processor.
35
+ * Defaults to 1 so the traces are exported immediately.
36
+ */
37
+ maxExportBatchSize?: number;
38
+ }
39
+ /**
40
+ * Wraps the AI SDK module to automatically inject telemetry configuration.
41
+ *
42
+ * @param aiSDKModule - The AI SDK module (e.g., import('ai'))
43
+ * @param config - Optional Scorecard configuration
44
+ * @returns Proxied AI SDK module with automatic telemetry injection
45
+ *
46
+ * @example
47
+ * ```typescript
48
+ * import ai from 'ai';
49
+ * import { wrapAISDK } from 'scorecard-ai';
50
+ *
51
+ * const aiSDK = await wrapAISDK(ai);
52
+ *
53
+ * // Now all AI SDK calls will automatically send traces to Scorecard.
54
+ * const { text } = await aiSDK.generateText({
55
+ * model: openai('gpt-4o-mini'),
56
+ * prompt: 'What is the capital of France? Answer in one sentence.',
57
+ * });
58
+ * ```
59
+ */
60
+ export declare function wrapAISDK<T extends Record<string, unknown>>(aiSDKModule: T, config?: ScorecardConfig): T;
61
+ export {};
62
+ //# sourceMappingURL=wrapAISDK.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wrapAISDK.d.ts","sourceRoot":"","sources":["../src/lib/wrapAISDK.ts"],"names":[],"mappings":"AASA;;GAEG;AACH,UAAU,eAAe;IACvB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IAEnB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAyED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACzD,WAAW,EAAE,CAAC,EACd,MAAM,GAAE,eAAoB,GAC3B,CAAC,CAmFH"}
@@ -0,0 +1,154 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.wrapAISDK = wrapAISDK;
4
+ const sdk_trace_node_1 = require("@opentelemetry/sdk-trace-node");
5
+ const exporter_trace_otlp_http_1 = require("@opentelemetry/exporter-trace-otlp-http");
6
+ const resources_1 = require("@opentelemetry/resources");
7
+ const semantic_conventions_1 = require("@opentelemetry/semantic-conventions");
8
+ const utils_1 = require("../internal/utils.js");
9
+ const error_1 = require("../error.js");
10
+ const client_1 = require("../client.js");
11
+ const DEFAULT_SERVICE_NAME = 'ai-sdk-app';
12
+ const AI_SDK_FUNCTIONS_WITH_TELEMETRY = new Set([
13
+ 'embed',
14
+ 'embedMany',
15
+ 'generateObject',
16
+ 'generateText',
17
+ 'streamObject',
18
+ 'streamText',
19
+ ]);
20
+ /**
21
+ * Initialize the OpenTelemetry tracer with Scorecard configuration.
22
+ */
23
+ function initializeTracer(config = {}) {
24
+ const { projectId = (0, utils_1.readEnv)('SCORECARD_PROJECT_ID'), apiKey = (0, utils_1.readEnv)('SCORECARD_API_KEY'), serviceName = DEFAULT_SERVICE_NAME, serviceVersion, maxExportBatchSize = 1, } = config;
25
+ // Create resource with service information
26
+ const resource = (0, resources_1.defaultResource)().merge((0, resources_1.resourceFromAttributes)({
27
+ [semantic_conventions_1.ATTR_SERVICE_NAME]: serviceName,
28
+ ...(serviceVersion != null ? { [semantic_conventions_1.ATTR_SERVICE_VERSION]: serviceVersion } : null),
29
+ ...(projectId != null ? { 'scorecard.project_id': projectId } : null),
30
+ }));
31
+ // Create span processors
32
+ const spanProcessors = [];
33
+ try {
34
+ const tracingUrl = (0, utils_1.readEnv)('SCORECARD_TRACING_URL') || 'https://tracing.scorecard.io/otel/v1/traces';
35
+ // Create OTLP exporter for Scorecard
36
+ const otlpExporter = new exporter_trace_otlp_http_1.OTLPTraceExporter({
37
+ url: tracingUrl,
38
+ headers: apiKey ?
39
+ {
40
+ Authorization: `Bearer ${apiKey}`,
41
+ }
42
+ : {},
43
+ });
44
+ // Add batch span processor with OTLP exporter
45
+ spanProcessors.push(new sdk_trace_node_1.BatchSpanProcessor(otlpExporter, {
46
+ maxExportBatchSize,
47
+ }));
48
+ }
49
+ catch (error) {
50
+ // Handle initialization errors
51
+ console.error(error);
52
+ throw new error_1.ScorecardError('Failed to initialize Scorecard telemetry');
53
+ }
54
+ // Create tracer provider with span processors
55
+ const tracerProvider = new sdk_trace_node_1.NodeTracerProvider({
56
+ resource,
57
+ spanProcessors,
58
+ });
59
+ // Register the provider
60
+ tracerProvider.register();
61
+ // Return the tracer instance
62
+ return tracerProvider.getTracer('ai-sdk-wrapper');
63
+ }
64
+ /**
65
+ * Wraps the AI SDK module to automatically inject telemetry configuration.
66
+ *
67
+ * @param aiSDKModule - The AI SDK module (e.g., import('ai'))
68
+ * @param config - Optional Scorecard configuration
69
+ * @returns Proxied AI SDK module with automatic telemetry injection
70
+ *
71
+ * @example
72
+ * ```typescript
73
+ * import ai from 'ai';
74
+ * import { wrapAISDK } from 'scorecard-ai';
75
+ *
76
+ * const aiSDK = await wrapAISDK(ai);
77
+ *
78
+ * // Now all AI SDK calls will automatically send traces to Scorecard.
79
+ * const { text } = await aiSDK.generateText({
80
+ * model: openai('gpt-4o-mini'),
81
+ * prompt: 'What is the capital of France? Answer in one sentence.',
82
+ * });
83
+ * ```
84
+ */
85
+ function wrapAISDK(aiSDKModule, config = {}) {
86
+ const projectId = config.projectId || (0, utils_1.readEnv)('SCORECARD_PROJECT_ID');
87
+ const apiKey = config.apiKey || (0, utils_1.readEnv)('SCORECARD_API_KEY');
88
+ const serviceName = config.serviceName || DEFAULT_SERVICE_NAME;
89
+ if (!apiKey) {
90
+ throw new error_1.ScorecardError('The SCORECARD_API_KEY environment variable is missing or empty; either provide it, or instantiate the AI SDK wrapper client with an apiKey option, like wrapAISDK(ai, { apiKey: "My API Key" }).');
91
+ }
92
+ const client = new client_1.Scorecard({ apiKey });
93
+ if (config.metrics && config.metrics.length > 0 && !projectId) {
94
+ throw new error_1.ScorecardError("The SCORECARD_PROJECT_ID environment variable is missing or empty; either provide it, or instantiate the AI SDK wrapper with a projectId option, like wrapAISDK(ai, { projectId: '123' }).");
95
+ }
96
+ // Create metrics and monitor if needed
97
+ if (config.metrics && config.metrics.length > 0 && projectId) {
98
+ client
99
+ .put(`/api/v2/projects/${projectId}/monitors`, {
100
+ body: {
101
+ description: serviceName,
102
+ metrics: config.metrics,
103
+ filter: {
104
+ serviceName,
105
+ },
106
+ },
107
+ })
108
+ // we use .catch instead of try/catch to avoid needing async/await in the wrapper
109
+ // otherwise the code would await here before giving back the wrapped AI SDK module
110
+ .catch((error) => {
111
+ console.error('Failed to create a Scorecard monitor for your AI SDK traces. The most common case is that the projectId is incorrect.', error);
112
+ });
113
+ }
114
+ // Initialize tracer
115
+ const tracerInstance = initializeTracer(config);
116
+ // Create telemetry configuration to inject
117
+ const telemetryConfig = {
118
+ isEnabled: true,
119
+ recordInputs: true,
120
+ recordOutputs: true,
121
+ tracer: tracerInstance,
122
+ };
123
+ // Create a proxy to intercept function calls
124
+ return new Proxy(aiSDKModule, {
125
+ get(target, prop) {
126
+ const originalValue = target[prop];
127
+ // Only wrap functions that support telemetry
128
+ if (typeof prop === 'string' &&
129
+ AI_SDK_FUNCTIONS_WITH_TELEMETRY.has(prop) &&
130
+ typeof originalValue === 'function') {
131
+ return function (...args) {
132
+ try {
133
+ // The first argument is typically the options object
134
+ if (args.length > 0 && args[0] && typeof args[0] === 'object') {
135
+ args[0].experimental_telemetry = {
136
+ ...telemetryConfig,
137
+ ...(args[0].experimental_telemetry || {}),
138
+ };
139
+ }
140
+ }
141
+ catch (error) {
142
+ // Silently handle any errors during injection
143
+ console.error('Failed to inject telemetry config:', error);
144
+ }
145
+ // Call the original function
146
+ return originalValue.apply(this, args);
147
+ };
148
+ }
149
+ // Return original value for non-function properties or non-telemetry functions
150
+ return originalValue;
151
+ },
152
+ });
153
+ }
154
+ //# sourceMappingURL=wrapAISDK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wrapAISDK.js","sourceRoot":"","sources":["../src/lib/wrapAISDK.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,151 @@
1
+ import { NodeTracerProvider, BatchSpanProcessor } from '@opentelemetry/sdk-trace-node';
2
+ import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
3
+ import { defaultResource, resourceFromAttributes } from '@opentelemetry/resources';
4
+ import { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } from '@opentelemetry/semantic-conventions';
5
+ import { readEnv } from "../internal/utils.mjs";
6
+ import { ScorecardError } from "../error.mjs";
7
+ import { Scorecard } from "../client.mjs";
8
+ const DEFAULT_SERVICE_NAME = 'ai-sdk-app';
9
+ const AI_SDK_FUNCTIONS_WITH_TELEMETRY = new Set([
10
+ 'embed',
11
+ 'embedMany',
12
+ 'generateObject',
13
+ 'generateText',
14
+ 'streamObject',
15
+ 'streamText',
16
+ ]);
17
+ /**
18
+ * Initialize the OpenTelemetry tracer with Scorecard configuration.
19
+ */
20
+ function initializeTracer(config = {}) {
21
+ const { projectId = readEnv('SCORECARD_PROJECT_ID'), apiKey = readEnv('SCORECARD_API_KEY'), serviceName = DEFAULT_SERVICE_NAME, serviceVersion, maxExportBatchSize = 1, } = config;
22
+ // Create resource with service information
23
+ const resource = defaultResource().merge(resourceFromAttributes({
24
+ [ATTR_SERVICE_NAME]: serviceName,
25
+ ...(serviceVersion != null ? { [ATTR_SERVICE_VERSION]: serviceVersion } : null),
26
+ ...(projectId != null ? { 'scorecard.project_id': projectId } : null),
27
+ }));
28
+ // Create span processors
29
+ const spanProcessors = [];
30
+ try {
31
+ const tracingUrl = readEnv('SCORECARD_TRACING_URL') || 'https://tracing.scorecard.io/otel/v1/traces';
32
+ // Create OTLP exporter for Scorecard
33
+ const otlpExporter = new OTLPTraceExporter({
34
+ url: tracingUrl,
35
+ headers: apiKey ?
36
+ {
37
+ Authorization: `Bearer ${apiKey}`,
38
+ }
39
+ : {},
40
+ });
41
+ // Add batch span processor with OTLP exporter
42
+ spanProcessors.push(new BatchSpanProcessor(otlpExporter, {
43
+ maxExportBatchSize,
44
+ }));
45
+ }
46
+ catch (error) {
47
+ // Handle initialization errors
48
+ console.error(error);
49
+ throw new ScorecardError('Failed to initialize Scorecard telemetry');
50
+ }
51
+ // Create tracer provider with span processors
52
+ const tracerProvider = new NodeTracerProvider({
53
+ resource,
54
+ spanProcessors,
55
+ });
56
+ // Register the provider
57
+ tracerProvider.register();
58
+ // Return the tracer instance
59
+ return tracerProvider.getTracer('ai-sdk-wrapper');
60
+ }
61
+ /**
62
+ * Wraps the AI SDK module to automatically inject telemetry configuration.
63
+ *
64
+ * @param aiSDKModule - The AI SDK module (e.g., import('ai'))
65
+ * @param config - Optional Scorecard configuration
66
+ * @returns Proxied AI SDK module with automatic telemetry injection
67
+ *
68
+ * @example
69
+ * ```typescript
70
+ * import ai from 'ai';
71
+ * import { wrapAISDK } from 'scorecard-ai';
72
+ *
73
+ * const aiSDK = await wrapAISDK(ai);
74
+ *
75
+ * // Now all AI SDK calls will automatically send traces to Scorecard.
76
+ * const { text } = await aiSDK.generateText({
77
+ * model: openai('gpt-4o-mini'),
78
+ * prompt: 'What is the capital of France? Answer in one sentence.',
79
+ * });
80
+ * ```
81
+ */
82
+ export function wrapAISDK(aiSDKModule, config = {}) {
83
+ const projectId = config.projectId || readEnv('SCORECARD_PROJECT_ID');
84
+ const apiKey = config.apiKey || readEnv('SCORECARD_API_KEY');
85
+ const serviceName = config.serviceName || DEFAULT_SERVICE_NAME;
86
+ if (!apiKey) {
87
+ throw new ScorecardError('The SCORECARD_API_KEY environment variable is missing or empty; either provide it, or instantiate the AI SDK wrapper client with an apiKey option, like wrapAISDK(ai, { apiKey: "My API Key" }).');
88
+ }
89
+ const client = new Scorecard({ apiKey });
90
+ if (config.metrics && config.metrics.length > 0 && !projectId) {
91
+ throw new ScorecardError("The SCORECARD_PROJECT_ID environment variable is missing or empty; either provide it, or instantiate the AI SDK wrapper with a projectId option, like wrapAISDK(ai, { projectId: '123' }).");
92
+ }
93
+ // Create metrics and monitor if needed
94
+ if (config.metrics && config.metrics.length > 0 && projectId) {
95
+ client
96
+ .put(`/api/v2/projects/${projectId}/monitors`, {
97
+ body: {
98
+ description: serviceName,
99
+ metrics: config.metrics,
100
+ filter: {
101
+ serviceName,
102
+ },
103
+ },
104
+ })
105
+ // we use .catch instead of try/catch to avoid needing async/await in the wrapper
106
+ // otherwise the code would await here before giving back the wrapped AI SDK module
107
+ .catch((error) => {
108
+ console.error('Failed to create a Scorecard monitor for your AI SDK traces. The most common case is that the projectId is incorrect.', error);
109
+ });
110
+ }
111
+ // Initialize tracer
112
+ const tracerInstance = initializeTracer(config);
113
+ // Create telemetry configuration to inject
114
+ const telemetryConfig = {
115
+ isEnabled: true,
116
+ recordInputs: true,
117
+ recordOutputs: true,
118
+ tracer: tracerInstance,
119
+ };
120
+ // Create a proxy to intercept function calls
121
+ return new Proxy(aiSDKModule, {
122
+ get(target, prop) {
123
+ const originalValue = target[prop];
124
+ // Only wrap functions that support telemetry
125
+ if (typeof prop === 'string' &&
126
+ AI_SDK_FUNCTIONS_WITH_TELEMETRY.has(prop) &&
127
+ typeof originalValue === 'function') {
128
+ return function (...args) {
129
+ try {
130
+ // The first argument is typically the options object
131
+ if (args.length > 0 && args[0] && typeof args[0] === 'object') {
132
+ args[0].experimental_telemetry = {
133
+ ...telemetryConfig,
134
+ ...(args[0].experimental_telemetry || {}),
135
+ };
136
+ }
137
+ }
138
+ catch (error) {
139
+ // Silently handle any errors during injection
140
+ console.error('Failed to inject telemetry config:', error);
141
+ }
142
+ // Call the original function
143
+ return originalValue.apply(this, args);
144
+ };
145
+ }
146
+ // Return original value for non-function properties or non-telemetry functions
147
+ return originalValue;
148
+ },
149
+ });
150
+ }
151
+ //# sourceMappingURL=wrapAISDK.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wrapAISDK.mjs","sourceRoot":"","sources":["../src/lib/wrapAISDK.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "scorecard-ai",
3
- "version": "2.3.0",
3
+ "version": "2.4.0",
4
4
  "description": "The official TypeScript library for the Scorecard API",
5
5
  "author": "Scorecard <team@scorecard.io>",
6
6
  "types": "./index.d.ts",
@@ -24,7 +24,13 @@
24
24
  "lint": "./scripts/lint",
25
25
  "fix": "./scripts/format"
26
26
  },
27
- "dependencies": {},
27
+ "dependencies": {
28
+ "@opentelemetry/api": "^1.9.0",
29
+ "@opentelemetry/exporter-trace-otlp-http": "^0.207.0",
30
+ "@opentelemetry/resources": "^2.2.0",
31
+ "@opentelemetry/sdk-trace-node": "^2.2.0",
32
+ "@opentelemetry/semantic-conventions": "^1.37.0"
33
+ },
28
34
  "exports": {
29
35
  ".": {
30
36
  "require": {
package/src/index.ts CHANGED
@@ -23,3 +23,4 @@ export {
23
23
  } from './core/error';
24
24
 
25
25
  export { runAndEvaluate } from './lib/runAndEvaluate';
26
+ export { wrapAISDK } from './lib/wrapAISDK';
@@ -0,0 +1,232 @@
1
+ import { NodeTracerProvider, BatchSpanProcessor } from '@opentelemetry/sdk-trace-node';
2
+ import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
3
+ import { defaultResource, resourceFromAttributes } from '@opentelemetry/resources';
4
+ import { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } from '@opentelemetry/semantic-conventions';
5
+ import { Tracer } from '@opentelemetry/api';
6
+ import { readEnv } from '../internal/utils';
7
+ import { ScorecardError } from '../error';
8
+ import { Scorecard } from '../client';
9
+
10
+ /**
11
+ * Configuration for the Scorecard AI SDK wrapper
12
+ */
13
+ interface ScorecardConfig {
14
+ /**
15
+ * ID of the Scorecard project that traces should be associated with.
16
+ * Defaults to SCORECARD_PROJECT_ID environment variable.
17
+ */
18
+ projectId?: string;
19
+
20
+ /**
21
+ * Metrics to score the traces against.
22
+ * It can be a list of metric IDs, descriptions of what you want the metric to do, or a mix of both.
23
+ * For example: ['123', 'Check if the response is concise'].
24
+ * If it's a description, the metric will be created if it doesn't exist.
25
+ * Defaults to empty array.
26
+ */
27
+ metrics?: string[];
28
+
29
+ /**
30
+ * Scorecard API key for authentication.
31
+ * Defaults to SCORECARD_API_KEY environment variable.
32
+ */
33
+ apiKey?: string;
34
+
35
+ /**
36
+ * Service name for telemetry.
37
+ * Defaults to "ai-sdk-app".
38
+ */
39
+ serviceName?: string;
40
+
41
+ /**
42
+ * Service version for telemetry.
43
+ * Defaults to undefined.
44
+ */
45
+ serviceVersion?: string;
46
+
47
+ /**
48
+ * Max export batch size for the batch span processor.
49
+ * Defaults to 1 so the traces are exported immediately.
50
+ */
51
+ maxExportBatchSize?: number;
52
+ }
53
+
54
+ const DEFAULT_SERVICE_NAME = 'ai-sdk-app';
55
+ const AI_SDK_FUNCTIONS_WITH_TELEMETRY = new Set([
56
+ 'embed',
57
+ 'embedMany',
58
+ 'generateObject',
59
+ 'generateText',
60
+ 'streamObject',
61
+ 'streamText',
62
+ ]);
63
+ /**
64
+ * Initialize the OpenTelemetry tracer with Scorecard configuration.
65
+ */
66
+ function initializeTracer(config: ScorecardConfig = {}): Tracer {
67
+ const {
68
+ projectId = readEnv('SCORECARD_PROJECT_ID'),
69
+ apiKey = readEnv('SCORECARD_API_KEY'),
70
+ serviceName = DEFAULT_SERVICE_NAME,
71
+ serviceVersion,
72
+ maxExportBatchSize = 1,
73
+ } = config;
74
+
75
+ // Create resource with service information
76
+ const resource = defaultResource().merge(
77
+ resourceFromAttributes({
78
+ [ATTR_SERVICE_NAME]: serviceName,
79
+ ...(serviceVersion != null ? { [ATTR_SERVICE_VERSION]: serviceVersion } : null),
80
+ ...(projectId != null ? { 'scorecard.project_id': projectId } : null),
81
+ }),
82
+ );
83
+
84
+ // Create span processors
85
+ const spanProcessors = [];
86
+
87
+ try {
88
+ const tracingUrl = readEnv('SCORECARD_TRACING_URL') || 'https://tracing.scorecard.io/otel/v1/traces';
89
+ // Create OTLP exporter for Scorecard
90
+ const otlpExporter = new OTLPTraceExporter({
91
+ url: tracingUrl,
92
+ headers:
93
+ apiKey ?
94
+ {
95
+ Authorization: `Bearer ${apiKey}`,
96
+ }
97
+ : {},
98
+ });
99
+
100
+ // Add batch span processor with OTLP exporter
101
+ spanProcessors.push(
102
+ new BatchSpanProcessor(otlpExporter, {
103
+ maxExportBatchSize,
104
+ }),
105
+ );
106
+ } catch (error) {
107
+ // Handle initialization errors
108
+ console.error(error);
109
+ throw new ScorecardError('Failed to initialize Scorecard telemetry');
110
+ }
111
+
112
+ // Create tracer provider with span processors
113
+ const tracerProvider = new NodeTracerProvider({
114
+ resource,
115
+ spanProcessors,
116
+ });
117
+
118
+ // Register the provider
119
+ tracerProvider.register();
120
+
121
+ // Return the tracer instance
122
+ return tracerProvider.getTracer('ai-sdk-wrapper');
123
+ }
124
+
125
+ /**
126
+ * Wraps the AI SDK module to automatically inject telemetry configuration.
127
+ *
128
+ * @param aiSDKModule - The AI SDK module (e.g., import('ai'))
129
+ * @param config - Optional Scorecard configuration
130
+ * @returns Proxied AI SDK module with automatic telemetry injection
131
+ *
132
+ * @example
133
+ * ```typescript
134
+ * import ai from 'ai';
135
+ * import { wrapAISDK } from 'scorecard-ai';
136
+ *
137
+ * const aiSDK = await wrapAISDK(ai);
138
+ *
139
+ * // Now all AI SDK calls will automatically send traces to Scorecard.
140
+ * const { text } = await aiSDK.generateText({
141
+ * model: openai('gpt-4o-mini'),
142
+ * prompt: 'What is the capital of France? Answer in one sentence.',
143
+ * });
144
+ * ```
145
+ */
146
+ export function wrapAISDK<T extends Record<string, unknown>>(
147
+ aiSDKModule: T,
148
+ config: ScorecardConfig = {},
149
+ ): T {
150
+ const projectId = config.projectId || readEnv('SCORECARD_PROJECT_ID');
151
+ const apiKey = config.apiKey || readEnv('SCORECARD_API_KEY');
152
+ const serviceName = config.serviceName || DEFAULT_SERVICE_NAME;
153
+ if (!apiKey) {
154
+ throw new ScorecardError(
155
+ 'The SCORECARD_API_KEY environment variable is missing or empty; either provide it, or instantiate the AI SDK wrapper client with an apiKey option, like wrapAISDK(ai, { apiKey: "My API Key" }).',
156
+ );
157
+ }
158
+ const client = new Scorecard({ apiKey });
159
+
160
+ if (config.metrics && config.metrics.length > 0 && !projectId) {
161
+ throw new ScorecardError(
162
+ "The SCORECARD_PROJECT_ID environment variable is missing or empty; either provide it, or instantiate the AI SDK wrapper with a projectId option, like wrapAISDK(ai, { projectId: '123' }).",
163
+ );
164
+ }
165
+
166
+ // Create metrics and monitor if needed
167
+ if (config.metrics && config.metrics.length > 0 && projectId) {
168
+ client
169
+ .put(`/api/v2/projects/${projectId}/monitors`, {
170
+ body: {
171
+ description: serviceName,
172
+ metrics: config.metrics,
173
+ filter: {
174
+ serviceName,
175
+ },
176
+ },
177
+ })
178
+ // we use .catch instead of try/catch to avoid needing async/await in the wrapper
179
+ // otherwise the code would await here before giving back the wrapped AI SDK module
180
+ .catch((error) => {
181
+ console.error(
182
+ 'Failed to create a Scorecard monitor for your AI SDK traces. The most common case is that the projectId is incorrect.',
183
+ error,
184
+ );
185
+ });
186
+ }
187
+ // Initialize tracer
188
+ const tracerInstance = initializeTracer(config);
189
+
190
+ // Create telemetry configuration to inject
191
+ const telemetryConfig = {
192
+ isEnabled: true,
193
+ recordInputs: true,
194
+ recordOutputs: true,
195
+ tracer: tracerInstance,
196
+ };
197
+
198
+ // Create a proxy to intercept function calls
199
+ return new Proxy(aiSDKModule, {
200
+ get(target, prop: string | symbol) {
201
+ const originalValue = target[prop as keyof T];
202
+
203
+ // Only wrap functions that support telemetry
204
+ if (
205
+ typeof prop === 'string' &&
206
+ AI_SDK_FUNCTIONS_WITH_TELEMETRY.has(prop) &&
207
+ typeof originalValue === 'function'
208
+ ) {
209
+ return function (this: any, ...args: any[]) {
210
+ try {
211
+ // The first argument is typically the options object
212
+ if (args.length > 0 && args[0] && typeof args[0] === 'object') {
213
+ args[0].experimental_telemetry = {
214
+ ...telemetryConfig,
215
+ ...(args[0].experimental_telemetry || {}),
216
+ };
217
+ }
218
+ } catch (error) {
219
+ // Silently handle any errors during injection
220
+ console.error('Failed to inject telemetry config:', error);
221
+ }
222
+
223
+ // Call the original function
224
+ return originalValue.apply(this, args);
225
+ };
226
+ }
227
+
228
+ // Return original value for non-function properties or non-telemetry functions
229
+ return originalValue;
230
+ },
231
+ });
232
+ }
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const VERSION = '2.3.0'; // x-release-please-version
1
+ export const VERSION = '2.4.0'; // x-release-please-version
package/version.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "2.3.0";
1
+ export declare const VERSION = "2.4.0";
2
2
  //# sourceMappingURL=version.d.mts.map
package/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "2.3.0";
1
+ export declare const VERSION = "2.4.0";
2
2
  //# sourceMappingURL=version.d.ts.map
package/version.js CHANGED
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.VERSION = void 0;
4
- exports.VERSION = '2.3.0'; // x-release-please-version
4
+ exports.VERSION = '2.4.0'; // x-release-please-version
5
5
  //# sourceMappingURL=version.js.map
package/version.mjs CHANGED
@@ -1,2 +1,2 @@
1
- export const VERSION = '2.3.0'; // x-release-please-version
1
+ export const VERSION = '2.4.0'; // x-release-please-version
2
2
  //# sourceMappingURL=version.mjs.map