From ed7b652f69148097bc1ce467fc14bbc5883f548b Mon Sep 17 00:00:00 2001 From: jsonbailey Date: Thu, 6 Nov 2025 17:18:17 +0000 Subject: [PATCH 1/4] feat: Include AI sdk version in tracking information --- packages/sdk/server-ai/src/LDAIConfigTrackerImpl.ts | 4 ++++ packages/sdk/server-ai/src/api/config/LDAIConfigTracker.ts | 3 +++ packages/sdk/server-ai/tsconfig.json | 2 +- packages/sdk/server-ai/tsconfig.ref.json | 2 +- 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/sdk/server-ai/src/LDAIConfigTrackerImpl.ts b/packages/sdk/server-ai/src/LDAIConfigTrackerImpl.ts index 9990c8505e..6755421dd1 100644 --- a/packages/sdk/server-ai/src/LDAIConfigTrackerImpl.ts +++ b/packages/sdk/server-ai/src/LDAIConfigTrackerImpl.ts @@ -13,6 +13,8 @@ import { } from './api/metrics'; import { LDClientMin } from './LDClientMin'; +const { version } = require('../package.json'); + export class LDAIConfigTrackerImpl implements LDAIConfigTracker { private _trackedMetrics: LDAIMetricSummary = {}; @@ -32,6 +34,7 @@ export class LDAIConfigTrackerImpl implements LDAIConfigTracker { version: number; modelName: string; providerName: string; + aiSdkVersion: string; } { return { variationKey: this._variationKey, @@ -39,6 +42,7 @@ export class LDAIConfigTrackerImpl implements LDAIConfigTracker { version: this._version, modelName: this._modelName, providerName: this._providerName, + aiSdkVersion: version, }; } diff --git a/packages/sdk/server-ai/src/api/config/LDAIConfigTracker.ts b/packages/sdk/server-ai/src/api/config/LDAIConfigTracker.ts index 130a8d041e..2f39aa4ef4 100644 --- a/packages/sdk/server-ai/src/api/config/LDAIConfigTracker.ts +++ b/packages/sdk/server-ai/src/api/config/LDAIConfigTracker.ts @@ -42,6 +42,9 @@ export interface LDAIConfigTracker { variationKey: string; configKey: string; version: number; + modelName: string; + providerName: string; + aiSdkVersion: string; }; /** * Track the duration of generation. diff --git a/packages/sdk/server-ai/tsconfig.json b/packages/sdk/server-ai/tsconfig.json index 2d1f62a18a..b175e70077 100644 --- a/packages/sdk/server-ai/tsconfig.json +++ b/packages/sdk/server-ai/tsconfig.json @@ -16,6 +16,6 @@ "stripInternal": true, "moduleResolution": "node" }, - "include": ["src"], + "include": ["src/**/*"], "exclude": ["**/*.test.ts", "dist", "node_modules", "__tests__"] } diff --git a/packages/sdk/server-ai/tsconfig.ref.json b/packages/sdk/server-ai/tsconfig.ref.json index 0c86b2c554..34a1cb607a 100644 --- a/packages/sdk/server-ai/tsconfig.ref.json +++ b/packages/sdk/server-ai/tsconfig.ref.json @@ -1,6 +1,6 @@ { "extends": "./tsconfig.json", - "include": ["src/**/*"], + "include": ["src/**/*", "package.json"], "compilerOptions": { "composite": true } From 2c68f5f4733d4716bd5032840ef9150604791a4c Mon Sep 17 00:00:00 2001 From: jsonbailey Date: Thu, 6 Nov 2025 17:32:47 +0000 Subject: [PATCH 2/4] fix failing tests --- .../__tests__/LDAIConfigTrackerImpl.test.ts | 90 +++++++++++-------- 1 file changed, 51 insertions(+), 39 deletions(-) diff --git a/packages/sdk/server-ai/__tests__/LDAIConfigTrackerImpl.test.ts b/packages/sdk/server-ai/__tests__/LDAIConfigTrackerImpl.test.ts index 1cf9f839bd..ea776dfd42 100644 --- a/packages/sdk/server-ai/__tests__/LDAIConfigTrackerImpl.test.ts +++ b/packages/sdk/server-ai/__tests__/LDAIConfigTrackerImpl.test.ts @@ -4,6 +4,9 @@ import { LDFeedbackKind } from '../src/api/metrics'; import { LDAIConfigTrackerImpl } from '../src/LDAIConfigTrackerImpl'; import { LDClientMin } from '../src/LDClientMin'; +// eslint-disable-next-line @typescript-eslint/no-var-requires +const { version: aiSdkVersion } = require('../package.json'); + const mockTrack = jest.fn(); const mockVariation = jest.fn(); const mockLdClient: LDClientMin = { @@ -18,6 +21,15 @@ const version = 1; const modelName = 'test-model'; const providerName = 'test-provider'; +const getExpectedTrackData = () => ({ + configKey, + variationKey, + version, + modelName, + providerName, + aiSdkVersion, +}); + beforeEach(() => { jest.clearAllMocks(); }); @@ -37,7 +49,7 @@ it('tracks duration', () => { expect(mockTrack).toHaveBeenCalledWith( '$ld:ai:duration:total', testContext, - { configKey, variationKey, version, modelName, providerName }, + getExpectedTrackData(), 1000, ); }); @@ -60,7 +72,7 @@ it('tracks duration of async function', async () => { expect(mockTrack).toHaveBeenCalledWith( '$ld:ai:duration:total', testContext, - { configKey, variationKey, version, modelName, providerName }, + getExpectedTrackData(), 1000, ); }); @@ -80,7 +92,7 @@ it('tracks time to first token', () => { expect(mockTrack).toHaveBeenCalledWith( '$ld:ai:tokens:ttf', testContext, - { configKey, variationKey, version, modelName, providerName }, + getExpectedTrackData(), 1000, ); }); @@ -100,7 +112,7 @@ it('tracks positive feedback', () => { expect(mockTrack).toHaveBeenCalledWith( '$ld:ai:feedback:user:positive', testContext, - { configKey, variationKey, version, modelName, providerName }, + getExpectedTrackData(), 1, ); }); @@ -120,7 +132,7 @@ it('tracks negative feedback', () => { expect(mockTrack).toHaveBeenCalledWith( '$ld:ai:feedback:user:negative', testContext, - { configKey, variationKey, version, modelName, providerName }, + getExpectedTrackData(), 1, ); }); @@ -140,7 +152,7 @@ it('tracks success', () => { expect(mockTrack).toHaveBeenCalledWith( '$ld:ai:generation:success', testContext, - { configKey, variationKey, version, modelName, providerName }, + getExpectedTrackData(), 1, ); }); @@ -172,14 +184,14 @@ it('tracks OpenAI usage', async () => { expect(mockTrack).toHaveBeenCalledWith( '$ld:ai:duration:total', testContext, - { configKey, variationKey, version, modelName, providerName }, + getExpectedTrackData(), 1000, ); expect(mockTrack).toHaveBeenCalledWith( '$ld:ai:generation:success', testContext, - { configKey, variationKey, version, modelName, providerName }, + getExpectedTrackData(), 1, ); @@ -193,21 +205,21 @@ it('tracks OpenAI usage', async () => { expect(mockTrack).toHaveBeenCalledWith( '$ld:ai:tokens:total', testContext, - { configKey, variationKey, version, modelName, providerName }, + getExpectedTrackData(), TOTAL_TOKENS, ); expect(mockTrack).toHaveBeenCalledWith( '$ld:ai:tokens:input', testContext, - { configKey, variationKey, version, modelName, providerName }, + getExpectedTrackData(), PROMPT_TOKENS, ); expect(mockTrack).toHaveBeenCalledWith( '$ld:ai:tokens:output', testContext, - { configKey, variationKey, version, modelName, providerName }, + getExpectedTrackData(), COMPLETION_TOKENS, ); }); @@ -234,14 +246,14 @@ it('tracks error when OpenAI metrics function throws', async () => { expect(mockTrack).toHaveBeenCalledWith( '$ld:ai:duration:total', testContext, - { configKey, variationKey, version, modelName, providerName }, + getExpectedTrackData(), 1000, ); expect(mockTrack).toHaveBeenCalledWith( '$ld:ai:generation:error', testContext, - { configKey, variationKey, version, modelName, providerName }, + getExpectedTrackData(), 1, ); @@ -283,7 +295,7 @@ it('tracks Bedrock conversation with successful response', () => { expect(mockTrack).toHaveBeenCalledWith( '$ld:ai:generation:success', testContext, - { configKey, variationKey, version, modelName, providerName }, + getExpectedTrackData(), 1, ); @@ -297,28 +309,28 @@ it('tracks Bedrock conversation with successful response', () => { expect(mockTrack).toHaveBeenCalledWith( '$ld:ai:duration:total', testContext, - { configKey, variationKey, version, modelName, providerName }, + getExpectedTrackData(), 500, ); expect(mockTrack).toHaveBeenCalledWith( '$ld:ai:tokens:total', testContext, - { configKey, variationKey, version, modelName, providerName }, + getExpectedTrackData(), TOTAL_TOKENS, ); expect(mockTrack).toHaveBeenCalledWith( '$ld:ai:tokens:input', testContext, - { configKey, variationKey, version, modelName, providerName }, + getExpectedTrackData(), PROMPT_TOKENS, ); expect(mockTrack).toHaveBeenCalledWith( '$ld:ai:tokens:output', testContext, - { configKey, variationKey, version, modelName, providerName }, + getExpectedTrackData(), COMPLETION_TOKENS, ); }); @@ -345,7 +357,7 @@ it('tracks Bedrock conversation with error response', () => { expect(mockTrack).toHaveBeenCalledWith( '$ld:ai:generation:error', testContext, - { configKey, variationKey, version, modelName, providerName }, + getExpectedTrackData(), 1, ); @@ -385,14 +397,14 @@ describe('Vercel AI SDK generateText', () => { expect(mockTrack).toHaveBeenCalledWith( '$ld:ai:duration:total', testContext, - { configKey, variationKey, version, modelName, providerName }, + getExpectedTrackData(), 1000, ); expect(mockTrack).toHaveBeenCalledWith( '$ld:ai:generation:success', testContext, - { configKey, variationKey, version, modelName, providerName }, + getExpectedTrackData(), 1, ); @@ -406,21 +418,21 @@ describe('Vercel AI SDK generateText', () => { expect(mockTrack).toHaveBeenCalledWith( '$ld:ai:tokens:total', testContext, - { configKey, variationKey, version, modelName, providerName }, + getExpectedTrackData(), TOTAL_TOKENS, ); expect(mockTrack).toHaveBeenCalledWith( '$ld:ai:tokens:input', testContext, - { configKey, variationKey, version, modelName, providerName }, + getExpectedTrackData(), PROMPT_TOKENS, ); expect(mockTrack).toHaveBeenCalledWith( '$ld:ai:tokens:output', testContext, - { configKey, variationKey, version, modelName, providerName }, + getExpectedTrackData(), COMPLETION_TOKENS, ); }); @@ -447,14 +459,14 @@ describe('Vercel AI SDK generateText', () => { expect(mockTrack).toHaveBeenCalledWith( '$ld:ai:duration:total', testContext, - { configKey, variationKey, version, modelName, providerName }, + getExpectedTrackData(), 1000, ); expect(mockTrack).toHaveBeenCalledWith( '$ld:ai:generation:error', testContext, - { configKey, variationKey, version, modelName, providerName }, + getExpectedTrackData(), 1, ); @@ -491,21 +503,21 @@ it('tracks tokens', () => { expect(mockTrack).toHaveBeenCalledWith( '$ld:ai:tokens:total', testContext, - { configKey, variationKey, version, modelName, providerName }, + getExpectedTrackData(), TOTAL_TOKENS, ); expect(mockTrack).toHaveBeenCalledWith( '$ld:ai:tokens:input', testContext, - { configKey, variationKey, version, modelName, providerName }, + getExpectedTrackData(), PROMPT_TOKENS, ); expect(mockTrack).toHaveBeenCalledWith( '$ld:ai:tokens:output', testContext, - { configKey, variationKey, version, modelName, providerName }, + getExpectedTrackData(), COMPLETION_TOKENS, ); }); @@ -537,7 +549,7 @@ it('only tracks non-zero token counts', () => { expect(mockTrack).toHaveBeenCalledWith( '$ld:ai:tokens:input', testContext, - { configKey, variationKey, version, modelName, providerName }, + getExpectedTrackData(), 50, ); @@ -623,7 +635,7 @@ it('tracks duration when async function throws', async () => { expect(mockTrack).toHaveBeenCalledWith( '$ld:ai:duration:total', testContext, - { configKey, variationKey, version, modelName, providerName }, + getExpectedTrackData(), 1000, ); }); @@ -643,7 +655,7 @@ it('tracks error', () => { expect(mockTrack).toHaveBeenCalledWith( '$ld:ai:generation:error', testContext, - { configKey, variationKey, version, modelName, providerName }, + getExpectedTrackData(), 1, ); }); @@ -679,7 +691,7 @@ describe('trackMetricsOf', () => { expect(mockTrack).toHaveBeenCalledWith( '$ld:ai:generation:success', testContext, - { configKey, variationKey, version, modelName, providerName }, + getExpectedTrackData(), 1, ); @@ -687,19 +699,19 @@ describe('trackMetricsOf', () => { expect(mockTrack).toHaveBeenCalledWith( '$ld:ai:tokens:total', testContext, - { configKey, variationKey, version, modelName, providerName }, + getExpectedTrackData(), 100, ); expect(mockTrack).toHaveBeenCalledWith( '$ld:ai:tokens:input', testContext, - { configKey, variationKey, version, modelName, providerName }, + getExpectedTrackData(), 50, ); expect(mockTrack).toHaveBeenCalledWith( '$ld:ai:tokens:output', testContext, - { configKey, variationKey, version, modelName, providerName }, + getExpectedTrackData(), 50, ); }); @@ -729,7 +741,7 @@ describe('trackMetricsOf', () => { expect(mockTrack).toHaveBeenCalledWith( '$ld:ai:generation:error', testContext, - { configKey, variationKey, version, modelName, providerName }, + getExpectedTrackData(), 1, ); }); @@ -755,7 +767,7 @@ describe('trackMetricsOf', () => { expect(mockTrack).toHaveBeenCalledWith( '$ld:ai:generation:error', testContext, - { configKey, variationKey, version, modelName, providerName }, + getExpectedTrackData(), 1, ); @@ -789,7 +801,7 @@ describe('trackMetricsOf', () => { expect(mockTrack).toHaveBeenCalledWith( '$ld:ai:generation:success', testContext, - { configKey, variationKey, version, modelName, providerName }, + getExpectedTrackData(), 1, ); From de613db466083515b8882451fc15abd0cdf526ff Mon Sep 17 00:00:00 2001 From: jsonbailey Date: Thu, 6 Nov 2025 18:13:03 +0000 Subject: [PATCH 3/4] include sdk name and prefer import over require --- .../sdk/server-ai/__tests__/LDAIConfigTrackerImpl.test.ts | 5 ++--- packages/sdk/server-ai/src/LDAIConfigTrackerImpl.ts | 7 ++++--- packages/sdk/server-ai/src/api/config/LDAIConfigTracker.ts | 1 + packages/sdk/server-ai/tsconfig.json | 6 +++--- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/packages/sdk/server-ai/__tests__/LDAIConfigTrackerImpl.test.ts b/packages/sdk/server-ai/__tests__/LDAIConfigTrackerImpl.test.ts index ea776dfd42..33ec018cac 100644 --- a/packages/sdk/server-ai/__tests__/LDAIConfigTrackerImpl.test.ts +++ b/packages/sdk/server-ai/__tests__/LDAIConfigTrackerImpl.test.ts @@ -1,12 +1,10 @@ import { LDContext } from '@launchdarkly/js-server-sdk-common'; +import { name as aiSdkName, version as aiSdkVersion } from '../package.json'; import { LDFeedbackKind } from '../src/api/metrics'; import { LDAIConfigTrackerImpl } from '../src/LDAIConfigTrackerImpl'; import { LDClientMin } from '../src/LDClientMin'; -// eslint-disable-next-line @typescript-eslint/no-var-requires -const { version: aiSdkVersion } = require('../package.json'); - const mockTrack = jest.fn(); const mockVariation = jest.fn(); const mockLdClient: LDClientMin = { @@ -27,6 +25,7 @@ const getExpectedTrackData = () => ({ version, modelName, providerName, + aiSdkName, aiSdkVersion, }); diff --git a/packages/sdk/server-ai/src/LDAIConfigTrackerImpl.ts b/packages/sdk/server-ai/src/LDAIConfigTrackerImpl.ts index 6755421dd1..f4e6624a79 100644 --- a/packages/sdk/server-ai/src/LDAIConfigTrackerImpl.ts +++ b/packages/sdk/server-ai/src/LDAIConfigTrackerImpl.ts @@ -1,5 +1,6 @@ import { LDContext } from '@launchdarkly/js-server-sdk-common'; +import { name as aiSdkName, version as aiSdkVersion } from '../package.json'; import { LDAIConfigTracker } from './api/config'; import { LDAIMetricSummary } from './api/config/LDAIConfigTracker'; import { EvalScore } from './api/judge/types'; @@ -13,8 +14,6 @@ import { } from './api/metrics'; import { LDClientMin } from './LDClientMin'; -const { version } = require('../package.json'); - export class LDAIConfigTrackerImpl implements LDAIConfigTracker { private _trackedMetrics: LDAIMetricSummary = {}; @@ -34,6 +33,7 @@ export class LDAIConfigTrackerImpl implements LDAIConfigTracker { version: number; modelName: string; providerName: string; + aiSdkName: string; aiSdkVersion: string; } { return { @@ -42,7 +42,8 @@ export class LDAIConfigTrackerImpl implements LDAIConfigTracker { version: this._version, modelName: this._modelName, providerName: this._providerName, - aiSdkVersion: version, + aiSdkName, + aiSdkVersion, }; } diff --git a/packages/sdk/server-ai/src/api/config/LDAIConfigTracker.ts b/packages/sdk/server-ai/src/api/config/LDAIConfigTracker.ts index 2f39aa4ef4..eb9beb258a 100644 --- a/packages/sdk/server-ai/src/api/config/LDAIConfigTracker.ts +++ b/packages/sdk/server-ai/src/api/config/LDAIConfigTracker.ts @@ -44,6 +44,7 @@ export interface LDAIConfigTracker { version: number; modelName: string; providerName: string; + aiSdkName: string; aiSdkVersion: string; }; /** diff --git a/packages/sdk/server-ai/tsconfig.json b/packages/sdk/server-ai/tsconfig.json index b175e70077..19ba2bdc20 100644 --- a/packages/sdk/server-ai/tsconfig.json +++ b/packages/sdk/server-ai/tsconfig.json @@ -1,6 +1,7 @@ { "compilerOptions": { - "rootDir": "src", + // Uses "." so it can load package.json. + "rootDir": ".", "outDir": "dist", "target": "es2017", "lib": ["es6"], @@ -16,6 +17,5 @@ "stripInternal": true, "moduleResolution": "node" }, - "include": ["src/**/*"], - "exclude": ["**/*.test.ts", "dist", "node_modules", "__tests__"] + "exclude": ["**/*.test.ts", "dist", "node_modules", "__tests__", "examples"] } From 8475ca6928cedfe77a7073677fb230a2b3e33ae9 Mon Sep 17 00:00:00 2001 From: jsonbailey Date: Thu, 6 Nov 2025 18:31:14 +0000 Subject: [PATCH 4/4] fix package based on updated root --- packages/sdk/server-ai/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/sdk/server-ai/package.json b/packages/sdk/server-ai/package.json index 99b5e773af..b29317b3d0 100644 --- a/packages/sdk/server-ai/package.json +++ b/packages/sdk/server-ai/package.json @@ -7,8 +7,8 @@ "type": "git", "url": "https://github.com/launchdarkly/js-core.git" }, - "main": "dist/index.js", - "types": "dist/index.d.ts", + "main": "dist/src/index.js", + "types": "dist/src/index.d.ts", "type": "commonjs", "scripts": { "build": "npx tsc",