@amplitude/ai 0.1.1 → 0.1.2
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/AGENTS.md +1 -1
- package/dist/providers/anthropic.d.ts.map +1 -1
- package/dist/providers/anthropic.js +4 -18
- package/dist/providers/anthropic.js.map +1 -1
- package/dist/providers/azure-openai.d.ts +3 -3
- package/dist/providers/azure-openai.d.ts.map +1 -1
- package/dist/providers/azure-openai.js +2 -2
- package/dist/providers/azure-openai.js.map +1 -1
- package/dist/providers/base.d.ts +11 -2
- package/dist/providers/base.d.ts.map +1 -1
- package/dist/providers/base.js +32 -14
- package/dist/providers/base.js.map +1 -1
- package/dist/providers/bedrock.d.ts.map +1 -1
- package/dist/providers/bedrock.js +13 -28
- package/dist/providers/bedrock.js.map +1 -1
- package/dist/providers/gemini.d.ts.map +1 -1
- package/dist/providers/gemini.js +8 -27
- package/dist/providers/gemini.js.map +1 -1
- package/dist/providers/mistral.d.ts.map +1 -1
- package/dist/providers/mistral.js +20 -24
- package/dist/providers/mistral.js.map +1 -1
- package/dist/providers/openai.d.ts.map +1 -1
- package/dist/providers/openai.js +23 -41
- package/dist/providers/openai.js.map +1 -1
- package/dist/types.d.ts +3 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/streaming.d.ts +2 -0
- package/dist/utils/streaming.d.ts.map +1 -1
- package/dist/utils/streaming.js +10 -0
- package/dist/utils/streaming.js.map +1 -1
- package/llms-full.txt +1 -1
- package/llms.txt +1 -1
- package/mcp.schema.json +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bedrock.js","names":["_BedrockModule: Record<string, unknown> | null","costUsd: number | null"],"sources":["../../src/providers/bedrock.ts"],"sourcesContent":["/**\n * AWS Bedrock provider wrapper with automatic tracking.\n *\n * Wraps the AWS SDK BedrockRuntimeClient's converse command.\n */\n\nimport type { PrivacyConfig } from '../core/privacy.js';\nimport type { AmplitudeOrAI, BedrockConverseResponse } from '../types.js';\nimport { calculateCost } from '../utils/costs.js';\nimport { tryRequire } from '../utils/resolve-module.js';\nimport { StreamingAccumulator } from '../utils/streaming.js';\nimport { applySessionContext, BaseAIProvider } from './base.js';\n\nconst _resolved = tryRequire('@aws-sdk/client-bedrock-runtime');\nexport const BEDROCK_AVAILABLE = _resolved != null;\nconst _BedrockModule: Record<string, unknown> | null = _resolved;\n\nexport { _BedrockModule };\n\nexport interface BedrockOptions {\n amplitude: AmplitudeOrAI;\n client: unknown;\n privacyConfig?: PrivacyConfig | null;\n /** Pass the `@aws-sdk/client-bedrock-runtime` module directly to bypass `tryRequire` (required in bundler environments). */\n bedrockModule?: unknown;\n}\n\nexport class Bedrock extends BaseAIProvider {\n private _client: unknown;\n private _bedrockMod: Record<string, unknown> | null;\n\n constructor(options: BedrockOptions) {\n super({\n amplitude: options.amplitude,\n privacyConfig: options.privacyConfig,\n providerName: 'bedrock',\n });\n this._client = options.client;\n this._bedrockMod =\n (options.bedrockModule as Record<string, unknown> | null) ??\n _BedrockModule;\n }\n\n async converse(params: Record<string, unknown>): Promise<unknown> {\n const client = this._client as {\n send: (command: unknown) => Promise<unknown>;\n };\n const modelId = String(params.modelId ?? 'unknown');\n\n if (this._bedrockMod == null) {\n throw new Error(\n '@aws-sdk/client-bedrock-runtime is required. Install it with: npm install @aws-sdk/client-bedrock-runtime — or pass the module directly via the bedrockModule option.',\n );\n }\n\n const ConverseCommand = this._bedrockMod.ConverseCommand as new (\n opts: Record<string, unknown>,\n ) => unknown;\n\n const command = new ConverseCommand(params);\n const startTime = performance.now();\n\n try {\n const response = await client.send(command);\n const latencyMs = performance.now() - startTime;\n\n const extracted = extractBedrockResponse(response);\n let costUsd: number | null = null;\n if (extracted.inputTokens != null && extracted.outputTokens != null) {\n try {\n costUsd = calculateCost({\n modelName: modelId,\n inputTokens: extracted.inputTokens,\n outputTokens: extracted.outputTokens,\n cacheReadInputTokens: extracted.cacheReadTokens ?? 0,\n cacheCreationInputTokens: extracted.cacheWriteTokens ?? 0,\n });\n } catch {\n // cost calculation is best-effort\n }\n }\n\n const ctx = applySessionContext();\n this._track({\n userId: ctx.userId ?? 'unknown',\n modelName: modelId,\n provider: 'bedrock',\n responseContent: extracted.text,\n latencyMs,\n sessionId: ctx.sessionId,\n traceId: ctx.traceId,\n turnId: ctx.turnId ?? undefined,\n agentId: ctx.agentId,\n env: ctx.env,\n inputTokens: extracted.inputTokens,\n outputTokens: extracted.outputTokens,\n totalTokens: extracted.totalTokens,\n totalCostUsd: costUsd,\n finishReason: extracted.stopReason,\n toolCalls:\n extracted.toolCalls.length > 0 ? extracted.toolCalls : undefined,\n systemPrompt: extracted.systemPrompt,\n temperature: extracted.temperature,\n topP: extracted.topP,\n maxOutputTokens: extracted.maxOutputTokens,\n isStreaming: false,\n });\n\n return response;\n } catch (error) {\n const latencyMs = performance.now() - startTime;\n const ctx = applySessionContext();\n\n this._track({\n userId: ctx.userId ?? 'unknown',\n modelName: modelId,\n provider: 'bedrock',\n responseContent: '',\n latencyMs,\n sessionId: ctx.sessionId,\n traceId: ctx.traceId,\n agentId: ctx.agentId,\n env: ctx.env,\n isError: true,\n errorMessage: error instanceof Error ? error.message : String(error),\n });\n\n throw error;\n }\n }\n\n async converseStream(params: Record<string, unknown>): Promise<unknown> {\n const modelId = String(params.modelId ?? 'unknown');\n const ctx = applySessionContext();\n const startTime = performance.now();\n try {\n const client = this._client as {\n send: (command: unknown) => Promise<unknown>;\n };\n if (this._bedrockMod == null) {\n throw new Error(\n '@aws-sdk/client-bedrock-runtime is required. Install it with: npm install @aws-sdk/client-bedrock-runtime — or pass the module directly via the bedrockModule option.',\n );\n }\n\n const ConverseStreamCommand = this._bedrockMod.ConverseStreamCommand as\n | (new (opts: Record<string, unknown>) => unknown)\n | undefined;\n if (ConverseStreamCommand == null) {\n throw new Error('Bedrock SDK does not expose ConverseStreamCommand');\n }\n\n const command = new ConverseStreamCommand(params);\n const response = (await client.send(command)) as Record<string, unknown>;\n const stream = response.stream as AsyncIterable<unknown> | undefined;\n if (!_isAsyncIterable(stream)) {\n throw new Error('Bedrock stream response is not AsyncIterable');\n }\n\n return {\n ...response,\n stream: this._wrapConverseStream(modelId, params, stream),\n };\n } catch (error) {\n this._track({\n userId: ctx.userId ?? 'unknown',\n modelName: modelId,\n provider: 'bedrock',\n responseContent: '',\n latencyMs: performance.now() - startTime,\n sessionId: ctx.sessionId,\n traceId: ctx.traceId,\n agentId: ctx.agentId,\n env: ctx.env,\n isError: true,\n errorMessage: error instanceof Error ? error.message : String(error),\n isStreaming: true,\n });\n throw error;\n }\n }\n\n get client(): unknown {\n return this._client;\n }\n\n private async *_wrapConverseStream(\n modelId: string,\n params: Record<string, unknown>,\n stream: AsyncIterable<unknown>,\n ): AsyncGenerator<unknown> {\n const accumulator = new StreamingAccumulator();\n accumulator.model = modelId;\n const ctx = applySessionContext();\n\n try {\n for await (const rawEvent of stream) {\n const event = rawEvent as Record<string, unknown>;\n const contentBlockDelta = event.contentBlockDelta as\n | Record<string, unknown>\n | undefined;\n const delta = contentBlockDelta?.delta as\n | Record<string, unknown>\n | undefined;\n if (delta?.text != null) {\n accumulator.addContent(String(delta.text));\n }\n\n const contentBlockStart = event.contentBlockStart as\n | Record<string, unknown>\n | undefined;\n const start = contentBlockStart?.start as\n | Record<string, unknown>\n | undefined;\n if (start?.toolUse != null) {\n accumulator.addToolCall(start.toolUse as Record<string, unknown>);\n }\n\n const messageStart = event.messageStart as\n | Record<string, unknown>\n | undefined;\n if (messageStart?.model != null) {\n accumulator.model = String(messageStart.model);\n }\n\n const messageStop = event.messageStop as\n | Record<string, unknown>\n | undefined;\n if (messageStop?.stopReason != null) {\n accumulator.finishReason = String(messageStop.stopReason);\n }\n\n const metadata = event.metadata as Record<string, unknown> | undefined;\n const usage = metadata?.usage as Record<string, unknown> | undefined;\n accumulator.setUsage({\n inputTokens: usage?.inputTokens as number | undefined,\n outputTokens: usage?.outputTokens as number | undefined,\n totalTokens: usage?.totalTokens as number | undefined,\n });\n\n yield rawEvent;\n }\n } catch (error) {\n accumulator.setError(\n error instanceof Error ? error.message : String(error),\n );\n throw error;\n } finally {\n const state = accumulator.getState();\n const modelName = String(accumulator.model ?? modelId);\n let costUsd: number | null = null;\n if (state.inputTokens != null && state.outputTokens != null) {\n try {\n costUsd = calculateCost({\n modelName,\n inputTokens: state.inputTokens,\n outputTokens: state.outputTokens,\n });\n } catch {\n // cost calculation is best-effort\n }\n }\n\n this._track({\n userId: ctx.userId ?? 'unknown',\n modelName,\n provider: 'bedrock',\n responseContent: state.content,\n latencyMs: accumulator.elapsedMs,\n sessionId: ctx.sessionId,\n traceId: ctx.traceId,\n turnId: ctx.turnId ?? undefined,\n agentId: ctx.agentId,\n env: ctx.env,\n inputTokens: state.inputTokens,\n outputTokens: state.outputTokens,\n totalTokens: state.totalTokens,\n totalCostUsd: costUsd,\n finishReason: state.finishReason,\n toolCalls: state.toolCalls.length > 0 ? state.toolCalls : undefined,\n systemPrompt: extractSystemPromptFromParams(params),\n temperature: (\n params.inferenceConfig as Record<string, unknown> | undefined\n )?.temperature as number | undefined,\n topP: (params.inferenceConfig as Record<string, unknown> | undefined)\n ?.topP as number | undefined,\n maxOutputTokens: (\n params.inferenceConfig as Record<string, unknown> | undefined\n )?.maxTokens as number | undefined,\n providerTtfbMs: state.ttfbMs,\n isStreaming: true,\n isError: state.isError,\n errorMessage: state.errorMessage,\n });\n }\n }\n}\n\nexport function extractBedrockResponse(response: unknown): {\n text: string;\n inputTokens?: number;\n outputTokens?: number;\n totalTokens?: number;\n cacheReadTokens?: number;\n cacheWriteTokens?: number;\n stopReason?: string;\n toolCalls: Array<Record<string, unknown>>;\n systemPrompt?: string;\n temperature?: number;\n topP?: number;\n maxOutputTokens?: number;\n} {\n const resp = response as BedrockConverseResponse;\n const content = resp.output?.message?.content;\n const textBlock = content?.find(\n (b) => (b as Record<string, unknown>).text != null,\n ) as { text?: string } | undefined;\n const toolCalls = content\n ?.filter((b) => (b as Record<string, unknown>).toolUse != null)\n .map(\n (b) => (b as Record<string, unknown>).toolUse as Record<string, unknown>,\n );\n const usage = resp.usage;\n const respAny = resp as Record<string, unknown>;\n const metrics = respAny.metrics as Record<string, unknown> | undefined;\n const additionalModelResponseFields =\n respAny.additionalModelResponseFields as\n | Record<string, unknown>\n | undefined;\n const inferenceConfig = respAny.inferenceConfig as\n | Record<string, unknown>\n | undefined;\n const system = respAny.system as Array<Record<string, unknown>> | undefined;\n const systemPrompt =\n Array.isArray(system) && system.length > 0\n ? system\n .map((s) => String((s as Record<string, unknown>).text ?? ''))\n .join('')\n : undefined;\n\n return {\n text: String(textBlock?.text ?? ''),\n inputTokens: usage?.inputTokens,\n outputTokens: usage?.outputTokens,\n totalTokens: usage?.totalTokens,\n cacheReadTokens: (usage as Record<string, unknown> | undefined)\n ?.cacheReadInputTokens as number | undefined,\n cacheWriteTokens: (usage as Record<string, unknown> | undefined)\n ?.cacheWriteInputTokens as number | undefined,\n stopReason: resp.stopReason,\n toolCalls: toolCalls ?? [],\n systemPrompt,\n temperature:\n (inferenceConfig?.temperature as number | undefined) ??\n (additionalModelResponseFields?.temperature as number | undefined),\n topP:\n (inferenceConfig?.topP as number | undefined) ??\n (additionalModelResponseFields?.topP as number | undefined),\n maxOutputTokens:\n (inferenceConfig?.maxTokens as number | undefined) ??\n (metrics?.maxOutputTokens as number | undefined),\n };\n}\n\nfunction extractSystemPromptFromParams(\n params: Record<string, unknown>,\n): string | undefined {\n const system = params.system as Array<Record<string, unknown>> | undefined;\n if (!Array.isArray(system) || system.length === 0) return undefined;\n return system.map((s) => String(s.text ?? '')).join('');\n}\n\nfunction _isAsyncIterable(value: unknown): value is AsyncIterable<unknown> {\n return (\n value != null &&\n typeof (value as Record<symbol, unknown>)[Symbol.asyncIterator] ===\n 'function'\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"bedrock.js","names":["_BedrockModule: Record<string, unknown> | null","costUsd: number | null"],"sources":["../../src/providers/bedrock.ts"],"sourcesContent":["/**\n * AWS Bedrock provider wrapper with automatic tracking.\n *\n * Wraps the AWS SDK BedrockRuntimeClient's converse command.\n */\n\nimport type { PrivacyConfig } from '../core/privacy.js';\nimport type { AmplitudeOrAI, BedrockConverseResponse } from '../types.js';\nimport { calculateCost } from '../utils/costs.js';\nimport { tryRequire } from '../utils/resolve-module.js';\nimport { StreamingAccumulator } from '../utils/streaming.js';\nimport { applySessionContext, BaseAIProvider, contextFields } from './base.js';\n\nconst _resolved = tryRequire('@aws-sdk/client-bedrock-runtime');\nexport const BEDROCK_AVAILABLE = _resolved != null;\nconst _BedrockModule: Record<string, unknown> | null = _resolved;\n\nexport { _BedrockModule };\n\nexport interface BedrockOptions {\n amplitude: AmplitudeOrAI;\n client: unknown;\n privacyConfig?: PrivacyConfig | null;\n /** Pass the `@aws-sdk/client-bedrock-runtime` module directly to bypass `tryRequire` (required in bundler environments). */\n bedrockModule?: unknown;\n}\n\nexport class Bedrock extends BaseAIProvider {\n private _client: unknown;\n private _bedrockMod: Record<string, unknown> | null;\n\n constructor(options: BedrockOptions) {\n super({\n amplitude: options.amplitude,\n privacyConfig: options.privacyConfig,\n providerName: 'bedrock',\n });\n this._client = options.client;\n this._bedrockMod =\n (options.bedrockModule as Record<string, unknown> | null) ??\n _BedrockModule;\n }\n\n async converse(params: Record<string, unknown>): Promise<unknown> {\n const client = this._client as {\n send: (command: unknown) => Promise<unknown>;\n };\n const modelId = String(params.modelId ?? 'unknown');\n\n if (this._bedrockMod == null) {\n throw new Error(\n '@aws-sdk/client-bedrock-runtime is required. Install it with: npm install @aws-sdk/client-bedrock-runtime — or pass the module directly via the bedrockModule option.',\n );\n }\n\n const ConverseCommand = this._bedrockMod.ConverseCommand as new (\n opts: Record<string, unknown>,\n ) => unknown;\n\n const command = new ConverseCommand(params);\n const startTime = performance.now();\n\n try {\n const response = await client.send(command);\n const latencyMs = performance.now() - startTime;\n\n const extracted = extractBedrockResponse(response);\n let costUsd: number | null = null;\n if (extracted.inputTokens != null && extracted.outputTokens != null) {\n try {\n costUsd = calculateCost({\n modelName: modelId,\n inputTokens: extracted.inputTokens,\n outputTokens: extracted.outputTokens,\n cacheReadInputTokens: extracted.cacheReadTokens ?? 0,\n cacheCreationInputTokens: extracted.cacheWriteTokens ?? 0,\n });\n } catch {\n // cost calculation is best-effort\n }\n }\n\n const ctx = applySessionContext();\n this._track({\n ...contextFields(ctx),\n modelName: modelId,\n provider: 'bedrock',\n responseContent: extracted.text,\n latencyMs,\n inputTokens: extracted.inputTokens,\n outputTokens: extracted.outputTokens,\n totalTokens: extracted.totalTokens,\n totalCostUsd: costUsd,\n finishReason: extracted.stopReason,\n toolCalls:\n extracted.toolCalls.length > 0 ? extracted.toolCalls : undefined,\n systemPrompt: extracted.systemPrompt,\n temperature: extracted.temperature,\n topP: extracted.topP,\n maxOutputTokens: extracted.maxOutputTokens,\n isStreaming: false,\n });\n\n return response;\n } catch (error) {\n const latencyMs = performance.now() - startTime;\n const ctx = applySessionContext();\n\n this._track({\n ...contextFields(ctx),\n modelName: modelId,\n provider: 'bedrock',\n responseContent: '',\n latencyMs,\n isError: true,\n errorMessage: error instanceof Error ? error.message : String(error),\n });\n\n throw error;\n }\n }\n\n async converseStream(params: Record<string, unknown>): Promise<unknown> {\n const modelId = String(params.modelId ?? 'unknown');\n const ctx = applySessionContext();\n const startTime = performance.now();\n try {\n const client = this._client as {\n send: (command: unknown) => Promise<unknown>;\n };\n if (this._bedrockMod == null) {\n throw new Error(\n '@aws-sdk/client-bedrock-runtime is required. Install it with: npm install @aws-sdk/client-bedrock-runtime — or pass the module directly via the bedrockModule option.',\n );\n }\n\n const ConverseStreamCommand = this._bedrockMod.ConverseStreamCommand as\n | (new (opts: Record<string, unknown>) => unknown)\n | undefined;\n if (ConverseStreamCommand == null) {\n throw new Error('Bedrock SDK does not expose ConverseStreamCommand');\n }\n\n const command = new ConverseStreamCommand(params);\n const response = (await client.send(command)) as Record<string, unknown>;\n const stream = response.stream as AsyncIterable<unknown> | undefined;\n if (!_isAsyncIterable(stream)) {\n throw new Error('Bedrock stream response is not AsyncIterable');\n }\n\n return {\n ...response,\n stream: this._wrapConverseStream(modelId, params, stream, ctx),\n };\n } catch (error) {\n this._track({\n ...contextFields(ctx),\n modelName: modelId,\n provider: 'bedrock',\n responseContent: '',\n latencyMs: performance.now() - startTime,\n isError: true,\n errorMessage: error instanceof Error ? error.message : String(error),\n isStreaming: true,\n });\n throw error;\n }\n }\n\n get client(): unknown {\n return this._client;\n }\n\n private async *_wrapConverseStream(\n modelId: string,\n params: Record<string, unknown>,\n stream: AsyncIterable<unknown>,\n ctx: ReturnType<typeof applySessionContext>,\n ): AsyncGenerator<unknown> {\n const accumulator = new StreamingAccumulator();\n accumulator.model = modelId;\n\n try {\n for await (const rawEvent of stream) {\n const event = rawEvent as Record<string, unknown>;\n const contentBlockDelta = event.contentBlockDelta as\n | Record<string, unknown>\n | undefined;\n const delta = contentBlockDelta?.delta as\n | Record<string, unknown>\n | undefined;\n if (delta?.text != null) {\n accumulator.addContent(String(delta.text));\n }\n\n const contentBlockStart = event.contentBlockStart as\n | Record<string, unknown>\n | undefined;\n const start = contentBlockStart?.start as\n | Record<string, unknown>\n | undefined;\n if (start?.toolUse != null) {\n accumulator.addToolCall(start.toolUse as Record<string, unknown>);\n }\n\n const messageStart = event.messageStart as\n | Record<string, unknown>\n | undefined;\n if (messageStart?.model != null) {\n accumulator.model = String(messageStart.model);\n }\n\n const messageStop = event.messageStop as\n | Record<string, unknown>\n | undefined;\n if (messageStop?.stopReason != null) {\n accumulator.finishReason = String(messageStop.stopReason);\n }\n\n const metadata = event.metadata as Record<string, unknown> | undefined;\n const usage = metadata?.usage as Record<string, unknown> | undefined;\n accumulator.setUsage({\n inputTokens: usage?.inputTokens as number | undefined,\n outputTokens: usage?.outputTokens as number | undefined,\n totalTokens: usage?.totalTokens as number | undefined,\n cacheReadTokens: usage?.cacheReadInputTokens as number | undefined,\n cacheCreationTokens: usage?.cacheWriteInputTokens as number | undefined,\n });\n\n yield rawEvent;\n }\n } catch (error) {\n accumulator.setError(\n error instanceof Error ? error.message : String(error),\n );\n throw error;\n } finally {\n const state = accumulator.getState();\n const modelName = String(accumulator.model ?? modelId);\n let costUsd: number | null = null;\n if (state.inputTokens != null && state.outputTokens != null) {\n try {\n costUsd = calculateCost({\n modelName,\n inputTokens: state.inputTokens,\n outputTokens: state.outputTokens,\n cacheReadInputTokens: state.cacheReadTokens ?? 0,\n cacheCreationInputTokens: state.cacheCreationTokens ?? 0,\n });\n } catch {\n // cost calculation is best-effort\n }\n }\n\n this._track({\n ...contextFields(ctx),\n modelName,\n provider: 'bedrock',\n responseContent: state.content,\n latencyMs: accumulator.elapsedMs,\n inputTokens: state.inputTokens,\n outputTokens: state.outputTokens,\n totalTokens: state.totalTokens,\n totalCostUsd: costUsd,\n finishReason: state.finishReason,\n toolCalls: state.toolCalls.length > 0 ? state.toolCalls : undefined,\n systemPrompt: extractSystemPromptFromParams(params),\n temperature: (\n params.inferenceConfig as Record<string, unknown> | undefined\n )?.temperature as number | undefined,\n topP: (params.inferenceConfig as Record<string, unknown> | undefined)\n ?.topP as number | undefined,\n maxOutputTokens: (\n params.inferenceConfig as Record<string, unknown> | undefined\n )?.maxTokens as number | undefined,\n providerTtfbMs: state.ttfbMs,\n isStreaming: true,\n isError: state.isError,\n errorMessage: state.errorMessage,\n });\n }\n }\n}\n\nexport function extractBedrockResponse(response: unknown): {\n text: string;\n inputTokens?: number;\n outputTokens?: number;\n totalTokens?: number;\n cacheReadTokens?: number;\n cacheWriteTokens?: number;\n stopReason?: string;\n toolCalls: Array<Record<string, unknown>>;\n systemPrompt?: string;\n temperature?: number;\n topP?: number;\n maxOutputTokens?: number;\n} {\n const resp = response as BedrockConverseResponse;\n const content = resp.output?.message?.content;\n const textBlock = content?.find(\n (b) => (b as Record<string, unknown>).text != null,\n ) as { text?: string } | undefined;\n const toolCalls = content\n ?.filter((b) => (b as Record<string, unknown>).toolUse != null)\n .map(\n (b) => (b as Record<string, unknown>).toolUse as Record<string, unknown>,\n );\n const usage = resp.usage;\n const respAny = resp as Record<string, unknown>;\n const metrics = respAny.metrics as Record<string, unknown> | undefined;\n const additionalModelResponseFields =\n respAny.additionalModelResponseFields as\n | Record<string, unknown>\n | undefined;\n const inferenceConfig = respAny.inferenceConfig as\n | Record<string, unknown>\n | undefined;\n const system = respAny.system as Array<Record<string, unknown>> | undefined;\n const systemPrompt =\n Array.isArray(system) && system.length > 0\n ? system\n .map((s) => String((s as Record<string, unknown>).text ?? ''))\n .join('')\n : undefined;\n\n return {\n text: String(textBlock?.text ?? ''),\n inputTokens: usage?.inputTokens,\n outputTokens: usage?.outputTokens,\n totalTokens: usage?.totalTokens,\n cacheReadTokens: (usage as Record<string, unknown> | undefined)\n ?.cacheReadInputTokens as number | undefined,\n cacheWriteTokens: (usage as Record<string, unknown> | undefined)\n ?.cacheWriteInputTokens as number | undefined,\n stopReason: resp.stopReason,\n toolCalls: toolCalls ?? [],\n systemPrompt,\n temperature:\n (inferenceConfig?.temperature as number | undefined) ??\n (additionalModelResponseFields?.temperature as number | undefined),\n topP:\n (inferenceConfig?.topP as number | undefined) ??\n (additionalModelResponseFields?.topP as number | undefined),\n maxOutputTokens:\n (inferenceConfig?.maxTokens as number | undefined) ??\n (metrics?.maxOutputTokens as number | undefined),\n };\n}\n\nfunction extractSystemPromptFromParams(\n params: Record<string, unknown>,\n): string | undefined {\n const system = params.system as Array<Record<string, unknown>> | undefined;\n if (!Array.isArray(system) || system.length === 0) return undefined;\n return system.map((s) => String(s.text ?? '')).join('');\n}\n\nfunction _isAsyncIterable(value: unknown): value is AsyncIterable<unknown> {\n return (\n value != null &&\n typeof (value as Record<symbol, unknown>)[Symbol.asyncIterator] ===\n 'function'\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gemini.d.ts","names":[],"sources":["../../src/providers/gemini.ts"],"sourcesContent":[],"mappings":";;;;;;AAaM,cADO,gBACQ,EAAA,OAAM;AAI3B,cAJM,aAIwB,EAJT,MAKR,CAAA,MAAA,EAAA,OAEK,CAAA,GAAA,IAAA;AAQK,UAXN,aAAA,CAWM;EAuBX,SAAA,EAjCC,aAiCD;EACP,MAAA,CAAA,EAAA,MAAA;
|
|
1
|
+
{"version":3,"file":"gemini.d.ts","names":[],"sources":["../../src/providers/gemini.ts"],"sourcesContent":[],"mappings":";;;;;;AAaM,cADO,gBACQ,EAAA,OAAM;AAI3B,cAJM,aAIwB,EAJT,MAKR,CAAA,MAAA,EAAA,OAEK,CAAA,GAAA,IAAA;AAQK,UAXN,aAAA,CAWM;EAuBX,SAAA,EAjCC,aAiCD;EACP,MAAA,CAAA,EAAA,MAAA;EAyEO,aAAA,CAAA,EAzGM,aAyGN,GAAA,IAAA;EACP;EArGuB,YAAA,CAAA,EAAA,OAAA;;AAwPZ,cAxPH,MAAA,SAAe,cAAA,CA8PV;;uBA3PK;yCAuBX,0BACP;+CAyEO,0BACP;;;;iBAmJW,qBAAA;;;;;;kBAME,MAAM"}
|
package/dist/providers/gemini.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { tryRequire } from "../utils/resolve-module.js";
|
|
2
2
|
import { calculateCost } from "../utils/costs.js";
|
|
3
3
|
import { StreamingAccumulator } from "../utils/streaming.js";
|
|
4
|
-
import { BaseAIProvider, applySessionContext } from "./base.js";
|
|
4
|
+
import { BaseAIProvider, applySessionContext, contextFields } from "./base.js";
|
|
5
5
|
|
|
6
6
|
//#region src/providers/gemini.ts
|
|
7
7
|
const _resolved = tryRequire("@google/generative-ai");
|
|
@@ -38,16 +38,11 @@ var Gemini = class extends BaseAIProvider {
|
|
|
38
38
|
} catch {}
|
|
39
39
|
const ctx = applySessionContext();
|
|
40
40
|
this._track({
|
|
41
|
-
|
|
41
|
+
...contextFields(ctx),
|
|
42
42
|
modelName: model,
|
|
43
43
|
provider: "gemini",
|
|
44
44
|
responseContent: extracted.text,
|
|
45
45
|
latencyMs,
|
|
46
|
-
sessionId: ctx.sessionId,
|
|
47
|
-
traceId: ctx.traceId,
|
|
48
|
-
turnId: ctx.turnId ?? void 0,
|
|
49
|
-
agentId: ctx.agentId,
|
|
50
|
-
env: ctx.env,
|
|
51
46
|
inputTokens: extracted.inputTokens,
|
|
52
47
|
outputTokens: extracted.outputTokens,
|
|
53
48
|
totalTokens: extracted.totalTokens,
|
|
@@ -65,15 +60,11 @@ var Gemini = class extends BaseAIProvider {
|
|
|
65
60
|
const latencyMs = performance.now() - startTime;
|
|
66
61
|
const ctx = applySessionContext();
|
|
67
62
|
this._track({
|
|
68
|
-
|
|
63
|
+
...contextFields(ctx),
|
|
69
64
|
modelName: model,
|
|
70
65
|
provider: "gemini",
|
|
71
66
|
responseContent: "",
|
|
72
67
|
latencyMs,
|
|
73
|
-
sessionId: ctx.sessionId,
|
|
74
|
-
traceId: ctx.traceId,
|
|
75
|
-
agentId: ctx.agentId,
|
|
76
|
-
env: ctx.env,
|
|
77
68
|
isError: true,
|
|
78
69
|
errorMessage: error instanceof Error ? error.message : String(error)
|
|
79
70
|
});
|
|
@@ -93,19 +84,15 @@ var Gemini = class extends BaseAIProvider {
|
|
|
93
84
|
if (!_isAsyncIterable(stream)) throw new Error("Gemini stream response is not AsyncIterable");
|
|
94
85
|
return {
|
|
95
86
|
...streamResponse,
|
|
96
|
-
stream: this._wrapStream(model, params, stream, finalResponse)
|
|
87
|
+
stream: this._wrapStream(model, params, stream, finalResponse, ctx)
|
|
97
88
|
};
|
|
98
89
|
} catch (error) {
|
|
99
90
|
this._track({
|
|
100
|
-
|
|
91
|
+
...contextFields(ctx),
|
|
101
92
|
modelName: model,
|
|
102
93
|
provider: "gemini",
|
|
103
94
|
responseContent: "",
|
|
104
95
|
latencyMs: performance.now() - startTime,
|
|
105
|
-
sessionId: ctx.sessionId,
|
|
106
|
-
traceId: ctx.traceId,
|
|
107
|
-
agentId: ctx.agentId,
|
|
108
|
-
env: ctx.env,
|
|
109
96
|
isError: true,
|
|
110
97
|
errorMessage: error instanceof Error ? error.message : String(error),
|
|
111
98
|
isStreaming: true
|
|
@@ -116,9 +103,8 @@ var Gemini = class extends BaseAIProvider {
|
|
|
116
103
|
get client() {
|
|
117
104
|
return this._client;
|
|
118
105
|
}
|
|
119
|
-
async *_wrapStream(model, params, stream, finalResponse) {
|
|
106
|
+
async *_wrapStream(model, params, stream, finalResponse, ctx) {
|
|
120
107
|
const accumulator = new StreamingAccumulator();
|
|
121
|
-
const ctx = applySessionContext();
|
|
122
108
|
try {
|
|
123
109
|
for await (const chunk of stream) {
|
|
124
110
|
const extracted = extractGeminiResponse(chunk);
|
|
@@ -144,7 +130,7 @@ var Gemini = class extends BaseAIProvider {
|
|
|
144
130
|
totalTokens: extractedFinal.totalTokens
|
|
145
131
|
});
|
|
146
132
|
if (extractedFinal.finishReason != null) accumulator.finishReason = String(extractedFinal.finishReason);
|
|
147
|
-
if (Array.isArray(extractedFinal.functionCalls)) for (const fc of extractedFinal.functionCalls) accumulator.addToolCall(fc);
|
|
133
|
+
if (Array.isArray(extractedFinal.functionCalls) && accumulator.toolCalls.length === 0) for (const fc of extractedFinal.functionCalls) accumulator.addToolCall(fc);
|
|
148
134
|
} catch {}
|
|
149
135
|
const state = accumulator.getState();
|
|
150
136
|
let costUsd = null;
|
|
@@ -156,16 +142,11 @@ var Gemini = class extends BaseAIProvider {
|
|
|
156
142
|
});
|
|
157
143
|
} catch {}
|
|
158
144
|
this._track({
|
|
159
|
-
|
|
145
|
+
...contextFields(ctx),
|
|
160
146
|
modelName: model,
|
|
161
147
|
provider: "gemini",
|
|
162
148
|
responseContent: state.content,
|
|
163
149
|
latencyMs: accumulator.elapsedMs,
|
|
164
|
-
sessionId: ctx.sessionId,
|
|
165
|
-
traceId: ctx.traceId,
|
|
166
|
-
turnId: ctx.turnId ?? void 0,
|
|
167
|
-
agentId: ctx.agentId,
|
|
168
|
-
env: ctx.env,
|
|
169
150
|
inputTokens: state.inputTokens,
|
|
170
151
|
outputTokens: state.outputTokens,
|
|
171
152
|
totalTokens: state.totalTokens,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gemini.js","names":["_GeminiModule: Record<string, unknown> | null","costUsd: number | null"],"sources":["../../src/providers/gemini.ts"],"sourcesContent":["/**\n * Google Gemini provider wrapper with automatic tracking.\n */\n\nimport type { PrivacyConfig } from '../core/privacy.js';\nimport type { AmplitudeOrAI, GeminiResponse } from '../types.js';\nimport { calculateCost } from '../utils/costs.js';\nimport { tryRequire } from '../utils/resolve-module.js';\nimport { StreamingAccumulator } from '../utils/streaming.js';\nimport { applySessionContext, BaseAIProvider } from './base.js';\n\nconst _resolved = tryRequire('@google/generative-ai');\nexport const GEMINI_AVAILABLE = _resolved != null;\nconst _GeminiModule: Record<string, unknown> | null = _resolved;\n\nexport { _GeminiModule };\n\nexport interface GeminiOptions {\n amplitude: AmplitudeOrAI;\n apiKey?: string;\n privacyConfig?: PrivacyConfig | null;\n /** Pass the `@google/generative-ai` module directly to bypass `tryRequire` (required in bundler environments). */\n geminiModule?: unknown;\n}\n\nexport class Gemini extends BaseAIProvider {\n private _client: unknown;\n\n constructor(options: GeminiOptions) {\n super({\n amplitude: options.amplitude,\n privacyConfig: options.privacyConfig,\n providerName: 'gemini',\n });\n\n const mod =\n (options.geminiModule as Record<string, unknown> | null) ?? _GeminiModule;\n if (mod == null) {\n throw new Error(\n '@google/generative-ai package is required. Install it with: npm install @google/generative-ai — or pass the module directly via the geminiModule option.',\n );\n }\n\n const GoogleGenAI = mod.GoogleGenerativeAI as new (\n apiKey: string,\n ) => unknown;\n this._client = new GoogleGenAI(options.apiKey ?? '');\n }\n\n async generateContent(\n model: string,\n params: Record<string, unknown>,\n ): Promise<unknown> {\n const clientObj = this._client as Record<string, unknown>;\n const getModel = clientObj.getGenerativeModel as (\n opts: Record<string, unknown>,\n ) => Record<string, unknown>;\n const genModel = getModel.call(this._client, { model });\n const generateFn = genModel.generateContent as (\n ...args: unknown[]\n ) => Promise<unknown>;\n\n const startTime = performance.now();\n\n try {\n const response = await generateFn.call(genModel, params);\n const latencyMs = performance.now() - startTime;\n\n const extracted = extractGeminiResponse(response);\n let costUsd: number | null = null;\n if (extracted.inputTokens != null && extracted.outputTokens != null) {\n try {\n costUsd = calculateCost({\n modelName: model,\n inputTokens: extracted.inputTokens,\n outputTokens: extracted.outputTokens,\n });\n } catch {\n // cost calculation is best-effort\n }\n }\n\n const ctx = applySessionContext();\n this._track({\n userId: ctx.userId ?? 'unknown',\n modelName: model,\n provider: 'gemini',\n responseContent: extracted.text,\n latencyMs,\n sessionId: ctx.sessionId,\n traceId: ctx.traceId,\n turnId: ctx.turnId ?? undefined,\n agentId: ctx.agentId,\n env: ctx.env,\n inputTokens: extracted.inputTokens,\n outputTokens: extracted.outputTokens,\n totalTokens: extracted.totalTokens,\n totalCostUsd: costUsd,\n finishReason: extracted.finishReason,\n toolCalls: extracted.functionCalls?.length\n ? extracted.functionCalls\n : undefined,\n systemPrompt: extractGeminiSystemPrompt(params),\n temperature: extractGeminiTemperature(params),\n topP: extractGeminiTopP(params),\n maxOutputTokens: extractGeminiMaxOutputTokens(params),\n isStreaming: false,\n });\n\n return response;\n } catch (error) {\n const latencyMs = performance.now() - startTime;\n const ctx = applySessionContext();\n\n this._track({\n userId: ctx.userId ?? 'unknown',\n modelName: model,\n provider: 'gemini',\n responseContent: '',\n latencyMs,\n sessionId: ctx.sessionId,\n traceId: ctx.traceId,\n agentId: ctx.agentId,\n env: ctx.env,\n isError: true,\n errorMessage: error instanceof Error ? error.message : String(error),\n });\n\n throw error;\n }\n }\n\n async generateContentStream(\n model: string,\n params: Record<string, unknown>,\n ): Promise<unknown> {\n const ctx = applySessionContext();\n const startTime = performance.now();\n try {\n const clientObj = this._client as Record<string, unknown>;\n const getModel = clientObj.getGenerativeModel as (\n opts: Record<string, unknown>,\n ) => Record<string, unknown>;\n const genModel = getModel.call(this._client, { model });\n const streamFn = genModel.generateContentStream as\n | ((...args: unknown[]) => Promise<unknown>)\n | undefined;\n if (typeof streamFn !== 'function') {\n throw new Error('Gemini SDK does not expose generateContentStream');\n }\n\n const response = await streamFn.call(genModel, params);\n const streamResponse = response as Record<string, unknown>;\n const stream = streamResponse.stream as\n | AsyncIterable<unknown>\n | undefined;\n const finalResponse = streamResponse.response as\n | Promise<unknown>\n | undefined;\n\n if (!_isAsyncIterable(stream)) {\n throw new Error('Gemini stream response is not AsyncIterable');\n }\n\n return {\n ...streamResponse,\n stream: this._wrapStream(model, params, stream, finalResponse),\n };\n } catch (error) {\n this._track({\n userId: ctx.userId ?? 'unknown',\n modelName: model,\n provider: 'gemini',\n responseContent: '',\n latencyMs: performance.now() - startTime,\n sessionId: ctx.sessionId,\n traceId: ctx.traceId,\n agentId: ctx.agentId,\n env: ctx.env,\n isError: true,\n errorMessage: error instanceof Error ? error.message : String(error),\n isStreaming: true,\n });\n throw error;\n }\n }\n\n get client(): unknown {\n return this._client;\n }\n\n private async *_wrapStream(\n model: string,\n params: Record<string, unknown>,\n stream: AsyncIterable<unknown>,\n finalResponse?: Promise<unknown>,\n ): AsyncGenerator<unknown> {\n const accumulator = new StreamingAccumulator();\n const ctx = applySessionContext();\n\n try {\n for await (const chunk of stream) {\n const extracted = extractGeminiResponse(chunk);\n if (extracted.text) accumulator.addContent(extracted.text);\n if (Array.isArray(extracted.functionCalls)) {\n for (const fc of extracted.functionCalls) accumulator.addToolCall(fc);\n }\n if (extracted.finishReason != null) {\n accumulator.finishReason = String(extracted.finishReason);\n }\n accumulator.setUsage({\n inputTokens: extracted.inputTokens,\n outputTokens: extracted.outputTokens,\n totalTokens: extracted.totalTokens,\n });\n yield chunk;\n }\n } catch (error) {\n accumulator.setError(\n error instanceof Error ? error.message : String(error),\n );\n throw error;\n } finally {\n if (finalResponse != null) {\n try {\n const extractedFinal = extractGeminiResponse(await finalResponse);\n accumulator.setUsage({\n inputTokens: extractedFinal.inputTokens,\n outputTokens: extractedFinal.outputTokens,\n totalTokens: extractedFinal.totalTokens,\n });\n if (extractedFinal.finishReason != null) {\n accumulator.finishReason = String(extractedFinal.finishReason);\n }\n if (Array.isArray(extractedFinal.functionCalls)) {\n for (const fc of extractedFinal.functionCalls) {\n accumulator.addToolCall(fc);\n }\n }\n } catch {\n // best-effort final response extraction\n }\n }\n\n const state = accumulator.getState();\n let costUsd: number | null = null;\n if (state.inputTokens != null && state.outputTokens != null) {\n try {\n costUsd = calculateCost({\n modelName: model,\n inputTokens: state.inputTokens,\n outputTokens: state.outputTokens,\n });\n } catch {\n // cost calculation is best-effort\n }\n }\n\n this._track({\n userId: ctx.userId ?? 'unknown',\n modelName: model,\n provider: 'gemini',\n responseContent: state.content,\n latencyMs: accumulator.elapsedMs,\n sessionId: ctx.sessionId,\n traceId: ctx.traceId,\n turnId: ctx.turnId ?? undefined,\n agentId: ctx.agentId,\n env: ctx.env,\n inputTokens: state.inputTokens,\n outputTokens: state.outputTokens,\n totalTokens: state.totalTokens,\n totalCostUsd: costUsd,\n finishReason: state.finishReason,\n toolCalls: state.toolCalls.length > 0 ? state.toolCalls : undefined,\n systemPrompt: extractGeminiSystemPrompt(params),\n temperature: extractGeminiTemperature(params),\n topP: extractGeminiTopP(params),\n maxOutputTokens: extractGeminiMaxOutputTokens(params),\n providerTtfbMs: state.ttfbMs,\n isStreaming: true,\n isError: state.isError,\n errorMessage: state.errorMessage,\n });\n }\n }\n}\n\nexport function extractGeminiResponse(response: unknown): {\n text: string;\n inputTokens?: number;\n outputTokens?: number;\n totalTokens?: number;\n finishReason?: string;\n functionCalls?: Array<Record<string, unknown>>;\n} {\n const resp = response as GeminiResponse;\n const respObj = resp.response ?? resp;\n let text = '';\n if (typeof respObj.text === 'function') {\n try {\n text = String(respObj.text());\n } catch {\n // text() throws when the response has no candidates (e.g. safety block)\n }\n }\n const usage = respObj.usageMetadata;\n\n const candidate = respObj.candidates?.[0];\n const finishReason = candidate?.finishReason;\n\n const parts = candidate?.content?.parts;\n const functionCalls = parts\n ?.filter((p) => p.functionCall != null)\n .map((p) => p.functionCall as Record<string, unknown>);\n\n return {\n text,\n inputTokens: usage?.promptTokenCount,\n outputTokens: usage?.candidatesTokenCount,\n totalTokens: usage?.totalTokenCount,\n finishReason,\n functionCalls: functionCalls?.length ? functionCalls : undefined,\n };\n}\n\nfunction extractGeminiSystemPrompt(\n params: Record<string, unknown>,\n): string | undefined {\n const systemInstruction =\n (params.systemInstruction as string | undefined) ??\n ((params.generationConfig as Record<string, unknown> | undefined)\n ?.systemInstruction as string | undefined);\n return systemInstruction;\n}\n\nfunction extractGeminiTemperature(\n params: Record<string, unknown>,\n): number | undefined {\n return (params.generationConfig as Record<string, unknown> | undefined)\n ?.temperature as number | undefined;\n}\n\nfunction extractGeminiTopP(\n params: Record<string, unknown>,\n): number | undefined {\n return (params.generationConfig as Record<string, unknown> | undefined)\n ?.topP as number | undefined;\n}\n\nfunction extractGeminiMaxOutputTokens(\n params: Record<string, unknown>,\n): number | undefined {\n return (params.generationConfig as Record<string, unknown> | undefined)\n ?.maxOutputTokens as number | undefined;\n}\n\nfunction _isAsyncIterable(value: unknown): value is AsyncIterable<unknown> {\n return (\n value != null &&\n typeof (value as Record<symbol, unknown>)[Symbol.asyncIterator] ===\n 'function'\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"gemini.js","names":["_GeminiModule: Record<string, unknown> | null","costUsd: number | null"],"sources":["../../src/providers/gemini.ts"],"sourcesContent":["/**\n * Google Gemini provider wrapper with automatic tracking.\n */\n\nimport type { PrivacyConfig } from '../core/privacy.js';\nimport type { AmplitudeOrAI, GeminiResponse } from '../types.js';\nimport { calculateCost } from '../utils/costs.js';\nimport { tryRequire } from '../utils/resolve-module.js';\nimport { StreamingAccumulator } from '../utils/streaming.js';\nimport { applySessionContext, BaseAIProvider, contextFields } from './base.js';\n\nconst _resolved = tryRequire('@google/generative-ai');\nexport const GEMINI_AVAILABLE = _resolved != null;\nconst _GeminiModule: Record<string, unknown> | null = _resolved;\n\nexport { _GeminiModule };\n\nexport interface GeminiOptions {\n amplitude: AmplitudeOrAI;\n apiKey?: string;\n privacyConfig?: PrivacyConfig | null;\n /** Pass the `@google/generative-ai` module directly to bypass `tryRequire` (required in bundler environments). */\n geminiModule?: unknown;\n}\n\nexport class Gemini extends BaseAIProvider {\n private _client: unknown;\n\n constructor(options: GeminiOptions) {\n super({\n amplitude: options.amplitude,\n privacyConfig: options.privacyConfig,\n providerName: 'gemini',\n });\n\n const mod =\n (options.geminiModule as Record<string, unknown> | null) ?? _GeminiModule;\n if (mod == null) {\n throw new Error(\n '@google/generative-ai package is required. Install it with: npm install @google/generative-ai — or pass the module directly via the geminiModule option.',\n );\n }\n\n const GoogleGenAI = mod.GoogleGenerativeAI as new (\n apiKey: string,\n ) => unknown;\n this._client = new GoogleGenAI(options.apiKey ?? '');\n }\n\n async generateContent(\n model: string,\n params: Record<string, unknown>,\n ): Promise<unknown> {\n const clientObj = this._client as Record<string, unknown>;\n const getModel = clientObj.getGenerativeModel as (\n opts: Record<string, unknown>,\n ) => Record<string, unknown>;\n const genModel = getModel.call(this._client, { model });\n const generateFn = genModel.generateContent as (\n ...args: unknown[]\n ) => Promise<unknown>;\n\n const startTime = performance.now();\n\n try {\n const response = await generateFn.call(genModel, params);\n const latencyMs = performance.now() - startTime;\n\n const extracted = extractGeminiResponse(response);\n let costUsd: number | null = null;\n if (extracted.inputTokens != null && extracted.outputTokens != null) {\n try {\n costUsd = calculateCost({\n modelName: model,\n inputTokens: extracted.inputTokens,\n outputTokens: extracted.outputTokens,\n });\n } catch {\n // cost calculation is best-effort\n }\n }\n\n const ctx = applySessionContext();\n this._track({\n ...contextFields(ctx),\n modelName: model,\n provider: 'gemini',\n responseContent: extracted.text,\n latencyMs,\n inputTokens: extracted.inputTokens,\n outputTokens: extracted.outputTokens,\n totalTokens: extracted.totalTokens,\n totalCostUsd: costUsd,\n finishReason: extracted.finishReason,\n toolCalls: extracted.functionCalls?.length\n ? extracted.functionCalls\n : undefined,\n systemPrompt: extractGeminiSystemPrompt(params),\n temperature: extractGeminiTemperature(params),\n topP: extractGeminiTopP(params),\n maxOutputTokens: extractGeminiMaxOutputTokens(params),\n isStreaming: false,\n });\n\n return response;\n } catch (error) {\n const latencyMs = performance.now() - startTime;\n const ctx = applySessionContext();\n\n this._track({\n ...contextFields(ctx),\n modelName: model,\n provider: 'gemini',\n responseContent: '',\n latencyMs,\n isError: true,\n errorMessage: error instanceof Error ? error.message : String(error),\n });\n\n throw error;\n }\n }\n\n async generateContentStream(\n model: string,\n params: Record<string, unknown>,\n ): Promise<unknown> {\n const ctx = applySessionContext();\n const startTime = performance.now();\n try {\n const clientObj = this._client as Record<string, unknown>;\n const getModel = clientObj.getGenerativeModel as (\n opts: Record<string, unknown>,\n ) => Record<string, unknown>;\n const genModel = getModel.call(this._client, { model });\n const streamFn = genModel.generateContentStream as\n | ((...args: unknown[]) => Promise<unknown>)\n | undefined;\n if (typeof streamFn !== 'function') {\n throw new Error('Gemini SDK does not expose generateContentStream');\n }\n\n const response = await streamFn.call(genModel, params);\n const streamResponse = response as Record<string, unknown>;\n const stream = streamResponse.stream as\n | AsyncIterable<unknown>\n | undefined;\n const finalResponse = streamResponse.response as\n | Promise<unknown>\n | undefined;\n\n if (!_isAsyncIterable(stream)) {\n throw new Error('Gemini stream response is not AsyncIterable');\n }\n\n return {\n ...streamResponse,\n stream: this._wrapStream(model, params, stream, finalResponse, ctx),\n };\n } catch (error) {\n this._track({\n ...contextFields(ctx),\n modelName: model,\n provider: 'gemini',\n responseContent: '',\n latencyMs: performance.now() - startTime,\n isError: true,\n errorMessage: error instanceof Error ? error.message : String(error),\n isStreaming: true,\n });\n throw error;\n }\n }\n\n get client(): unknown {\n return this._client;\n }\n\n private async *_wrapStream(\n model: string,\n params: Record<string, unknown>,\n stream: AsyncIterable<unknown>,\n finalResponse: Promise<unknown> | undefined,\n ctx: ReturnType<typeof applySessionContext>,\n ): AsyncGenerator<unknown> {\n const accumulator = new StreamingAccumulator();\n\n try {\n for await (const chunk of stream) {\n const extracted = extractGeminiResponse(chunk);\n if (extracted.text) accumulator.addContent(extracted.text);\n if (Array.isArray(extracted.functionCalls)) {\n for (const fc of extracted.functionCalls) accumulator.addToolCall(fc);\n }\n if (extracted.finishReason != null) {\n accumulator.finishReason = String(extracted.finishReason);\n }\n accumulator.setUsage({\n inputTokens: extracted.inputTokens,\n outputTokens: extracted.outputTokens,\n totalTokens: extracted.totalTokens,\n });\n yield chunk;\n }\n } catch (error) {\n accumulator.setError(\n error instanceof Error ? error.message : String(error),\n );\n throw error;\n } finally {\n if (finalResponse != null) {\n try {\n const extractedFinal = extractGeminiResponse(await finalResponse);\n accumulator.setUsage({\n inputTokens: extractedFinal.inputTokens,\n outputTokens: extractedFinal.outputTokens,\n totalTokens: extractedFinal.totalTokens,\n });\n if (extractedFinal.finishReason != null) {\n accumulator.finishReason = String(extractedFinal.finishReason);\n }\n if (\n Array.isArray(extractedFinal.functionCalls) &&\n accumulator.toolCalls.length === 0\n ) {\n for (const fc of extractedFinal.functionCalls) {\n accumulator.addToolCall(fc);\n }\n }\n } catch {\n // best-effort final response extraction\n }\n }\n\n const state = accumulator.getState();\n let costUsd: number | null = null;\n if (state.inputTokens != null && state.outputTokens != null) {\n try {\n costUsd = calculateCost({\n modelName: model,\n inputTokens: state.inputTokens,\n outputTokens: state.outputTokens,\n });\n } catch {\n // cost calculation is best-effort\n }\n }\n\n this._track({\n ...contextFields(ctx),\n modelName: model,\n provider: 'gemini',\n responseContent: state.content,\n latencyMs: accumulator.elapsedMs,\n inputTokens: state.inputTokens,\n outputTokens: state.outputTokens,\n totalTokens: state.totalTokens,\n totalCostUsd: costUsd,\n finishReason: state.finishReason,\n toolCalls: state.toolCalls.length > 0 ? state.toolCalls : undefined,\n systemPrompt: extractGeminiSystemPrompt(params),\n temperature: extractGeminiTemperature(params),\n topP: extractGeminiTopP(params),\n maxOutputTokens: extractGeminiMaxOutputTokens(params),\n providerTtfbMs: state.ttfbMs,\n isStreaming: true,\n isError: state.isError,\n errorMessage: state.errorMessage,\n });\n }\n }\n}\n\nexport function extractGeminiResponse(response: unknown): {\n text: string;\n inputTokens?: number;\n outputTokens?: number;\n totalTokens?: number;\n finishReason?: string;\n functionCalls?: Array<Record<string, unknown>>;\n} {\n const resp = response as GeminiResponse;\n const respObj = resp.response ?? resp;\n let text = '';\n if (typeof respObj.text === 'function') {\n try {\n text = String(respObj.text());\n } catch {\n // text() throws when the response has no candidates (e.g. safety block)\n }\n }\n const usage = respObj.usageMetadata;\n\n const candidate = respObj.candidates?.[0];\n const finishReason = candidate?.finishReason;\n\n const parts = candidate?.content?.parts;\n const functionCalls = parts\n ?.filter((p) => p.functionCall != null)\n .map((p) => p.functionCall as Record<string, unknown>);\n\n return {\n text,\n inputTokens: usage?.promptTokenCount,\n outputTokens: usage?.candidatesTokenCount,\n totalTokens: usage?.totalTokenCount,\n finishReason,\n functionCalls: functionCalls?.length ? functionCalls : undefined,\n };\n}\n\nfunction extractGeminiSystemPrompt(\n params: Record<string, unknown>,\n): string | undefined {\n const systemInstruction =\n (params.systemInstruction as string | undefined) ??\n ((params.generationConfig as Record<string, unknown> | undefined)\n ?.systemInstruction as string | undefined);\n return systemInstruction;\n}\n\nfunction extractGeminiTemperature(\n params: Record<string, unknown>,\n): number | undefined {\n return (params.generationConfig as Record<string, unknown> | undefined)\n ?.temperature as number | undefined;\n}\n\nfunction extractGeminiTopP(\n params: Record<string, unknown>,\n): number | undefined {\n return (params.generationConfig as Record<string, unknown> | undefined)\n ?.topP as number | undefined;\n}\n\nfunction extractGeminiMaxOutputTokens(\n params: Record<string, unknown>,\n): number | undefined {\n return (params.generationConfig as Record<string, unknown> | undefined)\n ?.maxOutputTokens as number | undefined;\n}\n\nfunction _isAsyncIterable(value: unknown): value is AsyncIterable<unknown> {\n return (\n value != null &&\n typeof (value as Record<symbol, unknown>)[Symbol.asyncIterator] ===\n 'function'\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mistral.d.ts","names":[],"sources":["../../src/providers/mistral.ts"],"sourcesContent":[],"mappings":";;;;;;AAaM,cADO,iBACS,EAAA,OAAM;AAI5B,cAJM,cAIyB,EAJT,MAKT,CAAA,MAAA,EAAA,OAEK,CAAA,GAAA,IAAA;AAOD,UAVA,cAAA,CAUA;EAEM,SAAA,EAXV,aAWU;EAJM,MAAA,CAAA,EAAA,MAAA;EAAc,aAAA,CAAA,EALzB,aAKyB,GAAA,IAAA;EAoC9B;EAI2B,aAAA,CAAA,EAAA,OAAA;;AAQW,cAhDtC,OAAA,SAAgB,cAAA,CAgDsB;
|
|
1
|
+
{"version":3,"file":"mistral.d.ts","names":[],"sources":["../../src/providers/mistral.ts"],"sourcesContent":[],"mappings":";;;;;;AAaM,cADO,iBACS,EAAA,OAAM;AAI5B,cAJM,cAIyB,EAJT,MAKT,CAAA,MAAA,EAAA,OAEK,CAAA,GAAA,IAAA;AAOD,UAVA,cAAA,CAUA;EAEM,SAAA,EAXV,aAWU;EAJM,MAAA,CAAA,EAAA,MAAA;EAAc,aAAA,CAAA,EALzB,aAKyB,GAAA,IAAA;EAoC9B;EAI2B,aAAA,CAAA,EAAA,OAAA;;AAQW,cAhDtC,OAAA,SAAgB,cAAA,CAgDsB;EAkF5B,QAAA,OAAA;EAA0B,SAAA,IAAA,EAhIhC,WAgIgC;EAAO,WAAA,CAAA,OAAA,EA9HjC,cA8HiC;;;cA9F3C,WAAA;;;wCAI2B;mBAQf,0BAA0B;iBAkF5B,0BAA0B"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { tryRequire } from "../utils/resolve-module.js";
|
|
2
2
|
import { calculateCost } from "../utils/costs.js";
|
|
3
3
|
import { StreamingAccumulator } from "../utils/streaming.js";
|
|
4
|
-
import { BaseAIProvider, applySessionContext } from "./base.js";
|
|
4
|
+
import { BaseAIProvider, applySessionContext, contextFields } from "./base.js";
|
|
5
5
|
|
|
6
6
|
//#region src/providers/mistral.ts
|
|
7
7
|
const _resolved = tryRequire("@mistralai/mistralai");
|
|
@@ -58,16 +58,11 @@ var WrappedChat = class {
|
|
|
58
58
|
});
|
|
59
59
|
} catch {}
|
|
60
60
|
this._trackFn({
|
|
61
|
-
|
|
61
|
+
...contextFields(ctx),
|
|
62
62
|
modelName,
|
|
63
63
|
provider: "mistral",
|
|
64
64
|
responseContent: extractMistralContent(choice?.message?.content),
|
|
65
65
|
latencyMs,
|
|
66
|
-
sessionId: ctx.sessionId,
|
|
67
|
-
traceId: ctx.traceId,
|
|
68
|
-
turnId: ctx.turnId ?? void 0,
|
|
69
|
-
agentId: ctx.agentId,
|
|
70
|
-
env: ctx.env,
|
|
71
66
|
inputTokens: usage?.prompt_tokens,
|
|
72
67
|
outputTokens: usage?.completion_tokens,
|
|
73
68
|
totalTokens: usage?.total_tokens,
|
|
@@ -84,15 +79,11 @@ var WrappedChat = class {
|
|
|
84
79
|
} catch (error) {
|
|
85
80
|
const latencyMs = performance.now() - startTime;
|
|
86
81
|
this._trackFn({
|
|
87
|
-
|
|
82
|
+
...contextFields(ctx),
|
|
88
83
|
modelName: String(params.model ?? "unknown"),
|
|
89
84
|
provider: "mistral",
|
|
90
85
|
responseContent: "",
|
|
91
86
|
latencyMs,
|
|
92
|
-
sessionId: ctx.sessionId,
|
|
93
|
-
traceId: ctx.traceId,
|
|
94
|
-
agentId: ctx.agentId,
|
|
95
|
-
env: ctx.env,
|
|
96
87
|
isError: true,
|
|
97
88
|
errorMessage: error instanceof Error ? error.message : String(error)
|
|
98
89
|
});
|
|
@@ -111,15 +102,11 @@ var WrappedChat = class {
|
|
|
111
102
|
return this._wrapStream(response, params, ctx);
|
|
112
103
|
} catch (error) {
|
|
113
104
|
this._trackFn({
|
|
114
|
-
|
|
105
|
+
...contextFields(ctx),
|
|
115
106
|
modelName: String(params.model ?? "unknown"),
|
|
116
107
|
provider: "mistral",
|
|
117
108
|
responseContent: "",
|
|
118
109
|
latencyMs: performance.now() - startTime,
|
|
119
|
-
sessionId: ctx.sessionId,
|
|
120
|
-
traceId: ctx.traceId,
|
|
121
|
-
agentId: ctx.agentId,
|
|
122
|
-
env: ctx.env,
|
|
123
110
|
isError: true,
|
|
124
111
|
errorMessage: error instanceof Error ? error.message : String(error),
|
|
125
112
|
isStreaming: true
|
|
@@ -139,7 +126,21 @@ var WrappedChat = class {
|
|
|
139
126
|
const content = delta?.content ?? message?.content;
|
|
140
127
|
if (typeof content === "string" && content.length > 0) accumulator.addContent(content);
|
|
141
128
|
const toolCalls = delta?.tool_calls ?? message?.tool_calls;
|
|
142
|
-
if (Array.isArray(toolCalls)) for (const call of toolCalls)
|
|
129
|
+
if (Array.isArray(toolCalls)) for (const call of toolCalls) {
|
|
130
|
+
const idx = call.index;
|
|
131
|
+
const id = call.id;
|
|
132
|
+
const fn = call.function;
|
|
133
|
+
if (idx != null && id && fn?.name != null) accumulator.setToolCallAt(idx, {
|
|
134
|
+
type: "function",
|
|
135
|
+
id,
|
|
136
|
+
function: {
|
|
137
|
+
name: fn.name,
|
|
138
|
+
arguments: fn.arguments ?? ""
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
else if (idx != null && fn?.arguments) accumulator.appendToolCallArgs(idx, fn.arguments);
|
|
142
|
+
else accumulator.addToolCall(call);
|
|
143
|
+
}
|
|
143
144
|
const finishReason = choices?.[0]?.finish_reason;
|
|
144
145
|
if (finishReason != null) accumulator.finishReason = String(finishReason);
|
|
145
146
|
const usage = c.usage;
|
|
@@ -165,16 +166,11 @@ var WrappedChat = class {
|
|
|
165
166
|
});
|
|
166
167
|
} catch {}
|
|
167
168
|
this._trackFn({
|
|
168
|
-
|
|
169
|
+
...contextFields(sessionCtx),
|
|
169
170
|
modelName,
|
|
170
171
|
provider: "mistral",
|
|
171
172
|
responseContent: state.content,
|
|
172
173
|
latencyMs: accumulator.elapsedMs,
|
|
173
|
-
sessionId: sessionCtx.sessionId,
|
|
174
|
-
traceId: sessionCtx.traceId,
|
|
175
|
-
turnId: sessionCtx.turnId ?? void 0,
|
|
176
|
-
agentId: sessionCtx.agentId,
|
|
177
|
-
env: sessionCtx.env,
|
|
178
174
|
inputTokens: state.inputTokens,
|
|
179
175
|
outputTokens: state.outputTokens,
|
|
180
176
|
totalTokens: state.totalTokens,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mistral.js","names":["_MistralModule: Record<string, unknown> | null","clientOpts: Record<string, unknown>","costUsd: number | null"],"sources":["../../src/providers/mistral.ts"],"sourcesContent":["/**\n * Mistral AI provider wrapper with automatic tracking.\n */\n\nimport type { PrivacyConfig } from '../core/privacy.js';\nimport type { AmplitudeOrAI, MistralChatResponse, TrackFn } from '../types.js';\nimport { calculateCost } from '../utils/costs.js';\nimport { tryRequire } from '../utils/resolve-module.js';\nimport { StreamingAccumulator } from '../utils/streaming.js';\nimport { applySessionContext, BaseAIProvider } from './base.js';\n\nconst _resolved = tryRequire('@mistralai/mistralai');\nexport const MISTRAL_AVAILABLE = _resolved != null;\nconst _MistralModule: Record<string, unknown> | null = _resolved;\n\nexport { _MistralModule };\n\nexport interface MistralOptions {\n amplitude: AmplitudeOrAI;\n apiKey?: string;\n privacyConfig?: PrivacyConfig | null;\n /** Pass the `@mistralai/mistralai` module directly to bypass `tryRequire` (required in bundler environments). */\n mistralModule?: unknown;\n}\n\nexport class Mistral extends BaseAIProvider {\n private _client: unknown;\n readonly chat: WrappedChat;\n\n constructor(options: MistralOptions) {\n super({\n amplitude: options.amplitude,\n privacyConfig: options.privacyConfig,\n providerName: 'mistral',\n });\n\n const mod =\n (options.mistralModule as Record<string, unknown> | null) ??\n _MistralModule;\n if (mod == null) {\n throw new Error(\n '@mistralai/mistralai package is required. Install it with: npm install @mistralai/mistralai — or pass the module directly via the mistralModule option.',\n );\n }\n\n const MistralSDK = (mod.Mistral ??\n mod.MistralClient ??\n mod.default) as new (opts: Record<string, unknown>) => unknown;\n\n const clientOpts: Record<string, unknown> = {};\n if (options.apiKey) clientOpts.apiKey = options.apiKey;\n\n this._client = new MistralSDK(clientOpts);\n this.chat = new WrappedChat(this._client, this.trackFn());\n }\n\n get client(): unknown {\n return this._client;\n }\n}\n\nexport class WrappedChat {\n private _client: unknown;\n private _trackFn: TrackFn;\n\n constructor(client: unknown, trackFn: TrackFn) {\n this._client = client;\n this._trackFn =\n typeof trackFn === 'function'\n ? trackFn\n : (trackFn as unknown as { trackFn(): TrackFn }).trackFn();\n }\n\n async complete(params: Record<string, unknown>): Promise<unknown> {\n const clientObj = this._client as Record<string, unknown>;\n const chat = clientObj.chat as Record<string, unknown>;\n const completeFn = chat.complete as (\n ...args: unknown[]\n ) => Promise<unknown>;\n\n const startTime = performance.now();\n const ctx = applySessionContext();\n\n try {\n const response = await completeFn.call(chat, params);\n if (\n (params.stream === true || chat.stream != null) &&\n _isAsyncIterable(response)\n ) {\n return this._wrapStream(\n response as AsyncIterable<unknown>,\n params,\n ctx,\n );\n }\n const latencyMs = performance.now() - startTime;\n\n const resp = response as MistralChatResponse;\n const choice = resp.choices?.[0];\n const usage = resp.usage;\n const modelName = String(resp.model ?? params.model ?? 'unknown');\n const toolCalls = (\n choice?.message as { tool_calls?: Array<Record<string, unknown>> }\n )?.tool_calls;\n\n let costUsd: number | null = null;\n if (usage?.prompt_tokens != null && usage?.completion_tokens != null) {\n try {\n costUsd = calculateCost({\n modelName,\n inputTokens: usage.prompt_tokens,\n outputTokens: usage.completion_tokens,\n });\n } catch {\n // cost calculation is best-effort\n }\n }\n\n this._trackFn({\n userId: ctx.userId ?? 'unknown',\n modelName,\n provider: 'mistral',\n responseContent: extractMistralContent(choice?.message?.content),\n latencyMs,\n sessionId: ctx.sessionId,\n traceId: ctx.traceId,\n turnId: ctx.turnId ?? undefined,\n agentId: ctx.agentId,\n env: ctx.env,\n inputTokens: usage?.prompt_tokens,\n outputTokens: usage?.completion_tokens,\n totalTokens: usage?.total_tokens,\n totalCostUsd: costUsd,\n finishReason: choice?.finish_reason,\n toolCalls: toolCalls ?? undefined,\n systemPrompt: extractMistralSystemPrompt(params),\n temperature: params.temperature as number | undefined,\n topP: params.top_p as number | undefined,\n maxOutputTokens: params.max_tokens as number | undefined,\n isStreaming: false,\n });\n\n return response;\n } catch (error) {\n const latencyMs = performance.now() - startTime;\n\n this._trackFn({\n userId: ctx.userId ?? 'unknown',\n modelName: String(params.model ?? 'unknown'),\n provider: 'mistral',\n responseContent: '',\n latencyMs,\n sessionId: ctx.sessionId,\n traceId: ctx.traceId,\n agentId: ctx.agentId,\n env: ctx.env,\n isError: true,\n errorMessage: error instanceof Error ? error.message : String(error),\n });\n\n throw error;\n }\n }\n\n async stream(params: Record<string, unknown>): Promise<unknown> {\n const ctx = applySessionContext();\n const startTime = performance.now();\n try {\n const clientObj = this._client as Record<string, unknown>;\n const chat = clientObj.chat as Record<string, unknown>;\n const streamFn = chat.stream as\n | ((...args: unknown[]) => Promise<unknown>)\n | undefined;\n if (typeof streamFn !== 'function') {\n throw new Error('Mistral SDK does not expose chat.stream');\n }\n\n const response = await streamFn.call(chat, params);\n if (!_isAsyncIterable(response)) {\n throw new Error('Mistral stream response is not AsyncIterable');\n }\n return this._wrapStream(response as AsyncIterable<unknown>, params, ctx);\n } catch (error) {\n this._trackFn({\n userId: ctx.userId ?? 'unknown',\n modelName: String(params.model ?? 'unknown'),\n provider: 'mistral',\n responseContent: '',\n latencyMs: performance.now() - startTime,\n sessionId: ctx.sessionId,\n traceId: ctx.traceId,\n agentId: ctx.agentId,\n env: ctx.env,\n isError: true,\n errorMessage: error instanceof Error ? error.message : String(error),\n isStreaming: true,\n });\n throw error;\n }\n }\n\n private async *_wrapStream(\n stream: AsyncIterable<unknown>,\n params: Record<string, unknown>,\n sessionCtx: ReturnType<typeof applySessionContext>,\n ): AsyncGenerator<unknown> {\n const accumulator = new StreamingAccumulator();\n accumulator.model = String(params.model ?? 'unknown');\n\n try {\n for await (const chunk of stream) {\n const c = chunk as Record<string, unknown>;\n const choices = c.choices as Array<Record<string, unknown>> | undefined;\n const delta = choices?.[0]?.delta as\n | Record<string, unknown>\n | undefined;\n const message = choices?.[0]?.message as\n | Record<string, unknown>\n | undefined;\n\n const content =\n (delta?.content as string | undefined) ??\n (message?.content as string | undefined);\n if (typeof content === 'string' && content.length > 0) {\n accumulator.addContent(content);\n }\n\n const toolCalls =\n (delta?.tool_calls as Array<Record<string, unknown>> | undefined) ??\n (message?.tool_calls as Array<Record<string, unknown>> | undefined);\n if (Array.isArray(toolCalls)) {\n for (const call of toolCalls) accumulator.addToolCall(call);\n }\n\n const finishReason = choices?.[0]?.finish_reason;\n if (finishReason != null)\n accumulator.finishReason = String(finishReason);\n\n const usage = c.usage as Record<string, unknown> | undefined;\n accumulator.setUsage({\n inputTokens: usage?.prompt_tokens as number | undefined,\n outputTokens: usage?.completion_tokens as number | undefined,\n totalTokens: usage?.total_tokens as number | undefined,\n });\n\n yield chunk;\n }\n } catch (error) {\n accumulator.setError(\n error instanceof Error ? error.message : String(error),\n );\n throw error;\n } finally {\n const state = accumulator.getState();\n const modelName = String(accumulator.model ?? params.model ?? 'unknown');\n let costUsd: number | null = null;\n if (state.inputTokens != null && state.outputTokens != null) {\n try {\n costUsd = calculateCost({\n modelName,\n inputTokens: state.inputTokens,\n outputTokens: state.outputTokens,\n });\n } catch {\n // cost calculation is best-effort\n }\n }\n\n this._trackFn({\n userId: sessionCtx.userId ?? 'unknown',\n modelName,\n provider: 'mistral',\n responseContent: state.content,\n latencyMs: accumulator.elapsedMs,\n sessionId: sessionCtx.sessionId,\n traceId: sessionCtx.traceId,\n turnId: sessionCtx.turnId ?? undefined,\n agentId: sessionCtx.agentId,\n env: sessionCtx.env,\n inputTokens: state.inputTokens,\n outputTokens: state.outputTokens,\n totalTokens: state.totalTokens,\n totalCostUsd: costUsd,\n finishReason: state.finishReason,\n toolCalls: state.toolCalls.length > 0 ? state.toolCalls : undefined,\n systemPrompt: extractMistralSystemPrompt(params),\n temperature: params.temperature as number | undefined,\n topP: params.top_p as number | undefined,\n maxOutputTokens: params.max_tokens as number | undefined,\n providerTtfbMs: state.ttfbMs,\n isStreaming: true,\n isError: state.isError,\n errorMessage: state.errorMessage,\n });\n }\n }\n}\n\nfunction extractMistralContent(content: unknown): string {\n if (typeof content === 'string') return content;\n if (content == null) return '';\n if (Array.isArray(content)) {\n return content\n .map((chunk) => {\n if (typeof chunk === 'string') return chunk;\n if (typeof chunk === 'object' && chunk != null) {\n return String((chunk as Record<string, unknown>).text ?? '');\n }\n return '';\n })\n .filter(Boolean)\n .join('');\n }\n return String(content);\n}\n\nfunction extractMistralSystemPrompt(\n params: Record<string, unknown>,\n): string | undefined {\n const messages = params.messages as\n | Array<Record<string, unknown>>\n | undefined;\n if (!Array.isArray(messages)) return undefined;\n const systemMessage = messages.find((m) => m.role === 'system');\n return typeof systemMessage?.content === 'string'\n ? systemMessage.content\n : undefined;\n}\n\nfunction _isAsyncIterable(value: unknown): value is AsyncIterable<unknown> {\n return (\n value != null &&\n typeof (value as Record<symbol, unknown>)[Symbol.asyncIterator] ===\n 'function'\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"mistral.js","names":["_MistralModule: Record<string, unknown> | null","clientOpts: Record<string, unknown>","costUsd: number | null"],"sources":["../../src/providers/mistral.ts"],"sourcesContent":["/**\n * Mistral AI provider wrapper with automatic tracking.\n */\n\nimport type { PrivacyConfig } from '../core/privacy.js';\nimport type { AmplitudeOrAI, MistralChatResponse, TrackFn } from '../types.js';\nimport { calculateCost } from '../utils/costs.js';\nimport { tryRequire } from '../utils/resolve-module.js';\nimport { StreamingAccumulator } from '../utils/streaming.js';\nimport { applySessionContext, BaseAIProvider, contextFields } from './base.js';\n\nconst _resolved = tryRequire('@mistralai/mistralai');\nexport const MISTRAL_AVAILABLE = _resolved != null;\nconst _MistralModule: Record<string, unknown> | null = _resolved;\n\nexport { _MistralModule };\n\nexport interface MistralOptions {\n amplitude: AmplitudeOrAI;\n apiKey?: string;\n privacyConfig?: PrivacyConfig | null;\n /** Pass the `@mistralai/mistralai` module directly to bypass `tryRequire` (required in bundler environments). */\n mistralModule?: unknown;\n}\n\nexport class Mistral extends BaseAIProvider {\n private _client: unknown;\n readonly chat: WrappedChat;\n\n constructor(options: MistralOptions) {\n super({\n amplitude: options.amplitude,\n privacyConfig: options.privacyConfig,\n providerName: 'mistral',\n });\n\n const mod =\n (options.mistralModule as Record<string, unknown> | null) ??\n _MistralModule;\n if (mod == null) {\n throw new Error(\n '@mistralai/mistralai package is required. Install it with: npm install @mistralai/mistralai — or pass the module directly via the mistralModule option.',\n );\n }\n\n const MistralSDK = (mod.Mistral ??\n mod.MistralClient ??\n mod.default) as new (opts: Record<string, unknown>) => unknown;\n\n const clientOpts: Record<string, unknown> = {};\n if (options.apiKey) clientOpts.apiKey = options.apiKey;\n\n this._client = new MistralSDK(clientOpts);\n this.chat = new WrappedChat(this._client, this.trackFn());\n }\n\n get client(): unknown {\n return this._client;\n }\n}\n\nexport class WrappedChat {\n private _client: unknown;\n private _trackFn: TrackFn;\n\n constructor(client: unknown, trackFn: TrackFn) {\n this._client = client;\n this._trackFn =\n typeof trackFn === 'function'\n ? trackFn\n : (trackFn as unknown as { trackFn(): TrackFn }).trackFn();\n }\n\n async complete(params: Record<string, unknown>): Promise<unknown> {\n const clientObj = this._client as Record<string, unknown>;\n const chat = clientObj.chat as Record<string, unknown>;\n const completeFn = chat.complete as (\n ...args: unknown[]\n ) => Promise<unknown>;\n\n const startTime = performance.now();\n const ctx = applySessionContext();\n\n try {\n const response = await completeFn.call(chat, params);\n if (\n (params.stream === true || chat.stream != null) &&\n _isAsyncIterable(response)\n ) {\n return this._wrapStream(\n response as AsyncIterable<unknown>,\n params,\n ctx,\n );\n }\n const latencyMs = performance.now() - startTime;\n\n const resp = response as MistralChatResponse;\n const choice = resp.choices?.[0];\n const usage = resp.usage;\n const modelName = String(resp.model ?? params.model ?? 'unknown');\n const toolCalls = (\n choice?.message as { tool_calls?: Array<Record<string, unknown>> }\n )?.tool_calls;\n\n let costUsd: number | null = null;\n if (usage?.prompt_tokens != null && usage?.completion_tokens != null) {\n try {\n costUsd = calculateCost({\n modelName,\n inputTokens: usage.prompt_tokens,\n outputTokens: usage.completion_tokens,\n });\n } catch {\n // cost calculation is best-effort\n }\n }\n\n this._trackFn({\n ...contextFields(ctx),\n modelName,\n provider: 'mistral',\n responseContent: extractMistralContent(choice?.message?.content),\n latencyMs,\n inputTokens: usage?.prompt_tokens,\n outputTokens: usage?.completion_tokens,\n totalTokens: usage?.total_tokens,\n totalCostUsd: costUsd,\n finishReason: choice?.finish_reason,\n toolCalls: toolCalls ?? undefined,\n systemPrompt: extractMistralSystemPrompt(params),\n temperature: params.temperature as number | undefined,\n topP: params.top_p as number | undefined,\n maxOutputTokens: params.max_tokens as number | undefined,\n isStreaming: false,\n });\n\n return response;\n } catch (error) {\n const latencyMs = performance.now() - startTime;\n\n this._trackFn({\n ...contextFields(ctx),\n modelName: String(params.model ?? 'unknown'),\n provider: 'mistral',\n responseContent: '',\n latencyMs,\n isError: true,\n errorMessage: error instanceof Error ? error.message : String(error),\n });\n\n throw error;\n }\n }\n\n async stream(params: Record<string, unknown>): Promise<unknown> {\n const ctx = applySessionContext();\n const startTime = performance.now();\n try {\n const clientObj = this._client as Record<string, unknown>;\n const chat = clientObj.chat as Record<string, unknown>;\n const streamFn = chat.stream as\n | ((...args: unknown[]) => Promise<unknown>)\n | undefined;\n if (typeof streamFn !== 'function') {\n throw new Error('Mistral SDK does not expose chat.stream');\n }\n\n const response = await streamFn.call(chat, params);\n if (!_isAsyncIterable(response)) {\n throw new Error('Mistral stream response is not AsyncIterable');\n }\n return this._wrapStream(response as AsyncIterable<unknown>, params, ctx);\n } catch (error) {\n this._trackFn({\n ...contextFields(ctx),\n modelName: String(params.model ?? 'unknown'),\n provider: 'mistral',\n responseContent: '',\n latencyMs: performance.now() - startTime,\n isError: true,\n errorMessage: error instanceof Error ? error.message : String(error),\n isStreaming: true,\n });\n throw error;\n }\n }\n\n private async *_wrapStream(\n stream: AsyncIterable<unknown>,\n params: Record<string, unknown>,\n sessionCtx: ReturnType<typeof applySessionContext>,\n ): AsyncGenerator<unknown> {\n const accumulator = new StreamingAccumulator();\n accumulator.model = String(params.model ?? 'unknown');\n\n try {\n for await (const chunk of stream) {\n const c = chunk as Record<string, unknown>;\n const choices = c.choices as Array<Record<string, unknown>> | undefined;\n const delta = choices?.[0]?.delta as\n | Record<string, unknown>\n | undefined;\n const message = choices?.[0]?.message as\n | Record<string, unknown>\n | undefined;\n\n const content =\n (delta?.content as string | undefined) ??\n (message?.content as string | undefined);\n if (typeof content === 'string' && content.length > 0) {\n accumulator.addContent(content);\n }\n\n const toolCalls =\n (delta?.tool_calls as Array<Record<string, unknown>> | undefined) ??\n (message?.tool_calls as Array<Record<string, unknown>> | undefined);\n if (Array.isArray(toolCalls)) {\n for (const call of toolCalls) {\n const idx = call.index as number | undefined;\n const id = call.id as string | undefined;\n const fn = call.function as Record<string, unknown> | undefined;\n if (idx != null && id && fn?.name != null) {\n accumulator.setToolCallAt(idx, {\n type: 'function',\n id,\n function: {\n name: fn.name,\n arguments: ((fn.arguments as string) ?? ''),\n },\n });\n } else if (idx != null && fn?.arguments) {\n accumulator.appendToolCallArgs(idx, fn.arguments as string);\n } else {\n accumulator.addToolCall(call);\n }\n }\n }\n\n const finishReason = choices?.[0]?.finish_reason;\n if (finishReason != null)\n accumulator.finishReason = String(finishReason);\n\n const usage = c.usage as Record<string, unknown> | undefined;\n accumulator.setUsage({\n inputTokens: usage?.prompt_tokens as number | undefined,\n outputTokens: usage?.completion_tokens as number | undefined,\n totalTokens: usage?.total_tokens as number | undefined,\n });\n\n yield chunk;\n }\n } catch (error) {\n accumulator.setError(\n error instanceof Error ? error.message : String(error),\n );\n throw error;\n } finally {\n const state = accumulator.getState();\n const modelName = String(accumulator.model ?? params.model ?? 'unknown');\n let costUsd: number | null = null;\n if (state.inputTokens != null && state.outputTokens != null) {\n try {\n costUsd = calculateCost({\n modelName,\n inputTokens: state.inputTokens,\n outputTokens: state.outputTokens,\n });\n } catch {\n // cost calculation is best-effort\n }\n }\n\n this._trackFn({\n ...contextFields(sessionCtx),\n modelName,\n provider: 'mistral',\n responseContent: state.content,\n latencyMs: accumulator.elapsedMs,\n inputTokens: state.inputTokens,\n outputTokens: state.outputTokens,\n totalTokens: state.totalTokens,\n totalCostUsd: costUsd,\n finishReason: state.finishReason,\n toolCalls: state.toolCalls.length > 0 ? state.toolCalls : undefined,\n systemPrompt: extractMistralSystemPrompt(params),\n temperature: params.temperature as number | undefined,\n topP: params.top_p as number | undefined,\n maxOutputTokens: params.max_tokens as number | undefined,\n providerTtfbMs: state.ttfbMs,\n isStreaming: true,\n isError: state.isError,\n errorMessage: state.errorMessage,\n });\n }\n }\n}\n\nfunction extractMistralContent(content: unknown): string {\n if (typeof content === 'string') return content;\n if (content == null) return '';\n if (Array.isArray(content)) {\n return content\n .map((chunk) => {\n if (typeof chunk === 'string') return chunk;\n if (typeof chunk === 'object' && chunk != null) {\n return String((chunk as Record<string, unknown>).text ?? '');\n }\n return '';\n })\n .filter(Boolean)\n .join('');\n }\n return String(content);\n}\n\nfunction extractMistralSystemPrompt(\n params: Record<string, unknown>,\n): string | undefined {\n const messages = params.messages as\n | Array<Record<string, unknown>>\n | undefined;\n if (!Array.isArray(messages)) return undefined;\n const systemMessage = messages.find((m) => m.role === 'system');\n return typeof systemMessage?.content === 'string'\n ? systemMessage.content\n : undefined;\n}\n\nfunction _isAsyncIterable(value: unknown): value is AsyncIterable<unknown> {\n return (\n value != null &&\n typeof (value as Record<symbol, unknown>)[Symbol.asyncIterator] ===\n 'function'\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openai.d.ts","names":[],"sources":["../../src/providers/openai.ts"],"sourcesContent":[],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"openai.d.ts","names":[],"sources":["../../src/providers/openai.ts"],"sourcesContent":[],"mappings":";;;;;;AAoDiB,cAnBJ,gBAmBI,EAAA,OAAA;cAlBX,aAmBgB,EAnBD,MAmBC,CAAA,MAAA,EAAA,OAAA,CAAA,GAAA,IAAA;AA6CN,UA5DC,aAAA,CA4DD;EAhDN,SAAA,EAXG,aAWH;EAAc,MAAA,CAAA,EAAA,MAAA;EAqDX,OAAA,CAAA,EAAA,MAAW;EACA,aAAA,CAAA,EA9DN,aA8DM,GAAA,IAAA;EAIX,gBAAA,CAAA,EAAA,OAAA;EACE;EACI,YAAA,CAAA,EAAA,OAAA;;AAeN,cA7EA,MA6EkB,CAAA,gBA5Eb,MA4Ea,CAAA,MAAA,EAAA,OAAA,CAAA,GA5Ea,MA4Eb,CAAA,MAAA,EAAA,OAAA,CAAA,CAAA,SA3ErB,cAAA,CA2EqB;EAClB,QAAA,OAAA;EAQI,SAAA,IAAA,EAlFA,WAkFA;EACJ,SAAA,SAAA,EAlFS,gBAkFT;EACE,QAAA,iBAAA;EACI,WAAA,CAAA,OAAA,EAjFI,aAiFJ;EAgBP,IAAA,MAAA,CAAA,CAAA,EAvDI,OAuDJ;;AAEC,cApDA,WAAA,CAoDA;EAAyB,SAAA,WAAA,EAnDd,kBAmDc;EAAjC,WAAA,CAAA,MAAA,EAAA,OAAA,EAAA,OAAA,EA/CQ,OA+CR,EAAA,SAAA,EA9CU,aA8CV,EAAA,aAAA,EA7Cc,aA6Cd,GAAA,IAAA,EAAA,gBAAA,EAAA,OAAA;;AAyGoB,cAvIZ,kBAAA,CAuIY;EACZ,SAAA,EAvIA,MAuIA,CAAA,MAAA,EAAA,OAAA,CAAA;EAAyB,QAAA,QAAA;EAAjC,QAAA,UAAA;EAAO,QAAA,cAAA;EA2LC,QAAA,iBAAgB;EAChB,QAAA,aAAA;EASA,WAAA,CAAA,WAAA,EApUI,MAoUJ,CAAA,MAAA,EAAA,OAAA,CAAA,EAAA,OAAA,EAnUA,OAmUA,EAAA,SAAA,EAlUE,aAkUF,EAAA,aAAA,EAjUM,aAiUN,GAAA,IAAA,EAAA,gBAAA,EAAA,OAAA,EAAA,YAAA,CAAA,EAAA,MAAA;EACE,MAAA,CAAA,MAAA,EAlTH,MAkTG,CAAA,MAAA,EAAA,OAAA,CAAA,EAAA,kBAAA,CAAA,EAjTU,oBAiTV,CAAA,EAhTV,OAgTU,CAhTF,sBAgTE,GAhTuB,aAgTvB,CAAA,OAAA,CAAA,CAAA;EACI,KAAA,CAAA,MAAA,EAzMP,MAyMO,CAAA,MAAA,EAAA,OAAA,CAAA,EAAA,kBAAA,CAAA,EAxMM,oBAwMN,CAAA,EAvMd,OAuMc,CAvMN,sBAuMM,GAvMmB,aAuMnB,CAAA,OAAA,CAAA,CAAA;EAkBP,QAAA,WAAA;EACa,QAAA,mBAAA;EACZ,QAAA,mBAAA;;AAAR,cAhCQ,gBAAA,CAgCR;EAkFO,SAAA,EAjHC,MAiHD,CAAA,MAAA,EAAA,OAAA,CAAA;EACa,QAAA,QAAA;EACZ,QAAA,UAAA;EAAR,QAAA,cAAA;EAAO,QAAA,iBAAA;EA2KI,QAAA,aAAA;wCArRH,oBACE,8BACI;iBAkBP,8CACa,uBACpB,QAAQ,iBAAiB;iBAkFlB,8CACa,uBACpB,QAAQ;;;;;iBA2KG,mBAAA,SACN"}
|
package/dist/providers/openai.js
CHANGED
|
@@ -3,7 +3,7 @@ import { getDefaultPropagateContext, injectContext } from "../propagation.js";
|
|
|
3
3
|
import { tryRequire } from "../utils/resolve-module.js";
|
|
4
4
|
import { calculateCost } from "../utils/costs.js";
|
|
5
5
|
import { StreamingAccumulator } from "../utils/streaming.js";
|
|
6
|
-
import { BaseAIProvider, applySessionContext } from "./base.js";
|
|
6
|
+
import { BaseAIProvider, applySessionContext, contextFields } from "./base.js";
|
|
7
7
|
|
|
8
8
|
//#region src/providers/openai.ts
|
|
9
9
|
const _resolved = tryRequire("openai");
|
|
@@ -91,16 +91,11 @@ var WrappedCompletions = class {
|
|
|
91
91
|
});
|
|
92
92
|
} catch {}
|
|
93
93
|
this._trackFn({
|
|
94
|
-
|
|
94
|
+
...contextFields(ctx),
|
|
95
95
|
modelName,
|
|
96
96
|
provider: this._providerName,
|
|
97
97
|
responseContent: String(choice?.message?.content ?? ""),
|
|
98
98
|
latencyMs,
|
|
99
|
-
sessionId: ctx.sessionId,
|
|
100
|
-
traceId: ctx.traceId,
|
|
101
|
-
turnId: ctx.turnId ?? void 0,
|
|
102
|
-
agentId: ctx.agentId,
|
|
103
|
-
env: ctx.env,
|
|
104
99
|
inputTokens: usage?.prompt_tokens,
|
|
105
100
|
outputTokens: usage?.completion_tokens,
|
|
106
101
|
totalTokens: usage?.total_tokens,
|
|
@@ -119,15 +114,11 @@ var WrappedCompletions = class {
|
|
|
119
114
|
} catch (error) {
|
|
120
115
|
const latencyMs = performance.now() - startTime;
|
|
121
116
|
this._trackFn({
|
|
122
|
-
|
|
117
|
+
...contextFields(ctx),
|
|
123
118
|
modelName: String(requestParams.model ?? "unknown"),
|
|
124
119
|
provider: this._providerName,
|
|
125
120
|
responseContent: "",
|
|
126
121
|
latencyMs,
|
|
127
|
-
sessionId: ctx.sessionId,
|
|
128
|
-
traceId: ctx.traceId,
|
|
129
|
-
agentId: ctx.agentId,
|
|
130
|
-
env: ctx.env,
|
|
131
122
|
isError: true,
|
|
132
123
|
errorMessage: error instanceof Error ? error.message : String(error)
|
|
133
124
|
});
|
|
@@ -156,7 +147,21 @@ var WrappedCompletions = class {
|
|
|
156
147
|
const delta = choices?.[0]?.delta;
|
|
157
148
|
if (delta?.content != null) accumulator.addContent(String(delta.content));
|
|
158
149
|
const deltaToolCalls = delta?.tool_calls;
|
|
159
|
-
if (Array.isArray(deltaToolCalls)) for (const call of deltaToolCalls)
|
|
150
|
+
if (Array.isArray(deltaToolCalls)) for (const call of deltaToolCalls) {
|
|
151
|
+
const idx = call.index;
|
|
152
|
+
const id = call.id;
|
|
153
|
+
const fn = call.function;
|
|
154
|
+
if (idx != null && id && fn?.name != null) accumulator.setToolCallAt(idx, {
|
|
155
|
+
type: "function",
|
|
156
|
+
id,
|
|
157
|
+
function: {
|
|
158
|
+
name: fn.name,
|
|
159
|
+
arguments: fn.arguments ?? ""
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
else if (idx != null && fn?.arguments) accumulator.appendToolCallArgs(idx, fn.arguments);
|
|
163
|
+
else accumulator.addToolCall(call);
|
|
164
|
+
}
|
|
160
165
|
if (delta?.reasoning_content != null) reasoningContent += String(delta.reasoning_content);
|
|
161
166
|
const finishReason = choices?.[0]?.finish_reason;
|
|
162
167
|
if (finishReason != null) accumulator.finishReason = String(finishReason);
|
|
@@ -191,16 +196,11 @@ var WrappedCompletions = class {
|
|
|
191
196
|
});
|
|
192
197
|
} catch {}
|
|
193
198
|
this._trackFn({
|
|
194
|
-
|
|
199
|
+
...contextFields(sessionCtx),
|
|
195
200
|
modelName,
|
|
196
201
|
provider: this._providerName,
|
|
197
202
|
responseContent: state.content,
|
|
198
203
|
latencyMs: accumulator.elapsedMs,
|
|
199
|
-
sessionId: sessionCtx.sessionId,
|
|
200
|
-
traceId: sessionCtx.traceId,
|
|
201
|
-
turnId: sessionCtx.turnId ?? void 0,
|
|
202
|
-
agentId: sessionCtx.agentId,
|
|
203
|
-
env: sessionCtx.env,
|
|
204
204
|
inputTokens: state.inputTokens,
|
|
205
205
|
outputTokens: state.outputTokens,
|
|
206
206
|
totalTokens: state.totalTokens,
|
|
@@ -294,16 +294,11 @@ var WrappedResponses = class {
|
|
|
294
294
|
});
|
|
295
295
|
} catch {}
|
|
296
296
|
this._trackFn({
|
|
297
|
-
|
|
297
|
+
...contextFields(ctx),
|
|
298
298
|
modelName,
|
|
299
299
|
provider: this._providerName,
|
|
300
300
|
responseContent: responseText,
|
|
301
301
|
latencyMs,
|
|
302
|
-
sessionId: ctx.sessionId,
|
|
303
|
-
traceId: ctx.traceId,
|
|
304
|
-
turnId: ctx.turnId ?? void 0,
|
|
305
|
-
agentId: ctx.agentId,
|
|
306
|
-
env: ctx.env,
|
|
307
302
|
inputTokens: usage?.input_tokens,
|
|
308
303
|
outputTokens: usage?.output_tokens,
|
|
309
304
|
totalTokens: usage?.total_tokens,
|
|
@@ -321,15 +316,11 @@ var WrappedResponses = class {
|
|
|
321
316
|
} catch (error) {
|
|
322
317
|
const latencyMs = performance.now() - startTime;
|
|
323
318
|
this._trackFn({
|
|
324
|
-
|
|
319
|
+
...contextFields(ctx),
|
|
325
320
|
modelName: String(requestParams.model ?? "unknown"),
|
|
326
321
|
provider: this._providerName,
|
|
327
322
|
responseContent: "",
|
|
328
323
|
latencyMs,
|
|
329
|
-
sessionId: ctx.sessionId,
|
|
330
|
-
traceId: ctx.traceId,
|
|
331
|
-
agentId: ctx.agentId,
|
|
332
|
-
env: ctx.env,
|
|
333
324
|
isError: true,
|
|
334
325
|
errorMessage: error instanceof Error ? error.message : String(error)
|
|
335
326
|
});
|
|
@@ -349,15 +340,11 @@ var WrappedResponses = class {
|
|
|
349
340
|
return this._wrapStream(response, requestParams, startTime, ctx);
|
|
350
341
|
} catch (error) {
|
|
351
342
|
this._trackFn({
|
|
352
|
-
|
|
343
|
+
...contextFields(ctx),
|
|
353
344
|
modelName: String(requestParams.model ?? "unknown"),
|
|
354
345
|
provider: this._providerName,
|
|
355
346
|
responseContent: "",
|
|
356
347
|
latencyMs: performance.now() - startTime,
|
|
357
|
-
sessionId: ctx.sessionId,
|
|
358
|
-
traceId: ctx.traceId,
|
|
359
|
-
agentId: ctx.agentId,
|
|
360
|
-
env: ctx.env,
|
|
361
348
|
isError: true,
|
|
362
349
|
errorMessage: error instanceof Error ? error.message : String(error),
|
|
363
350
|
isStreaming: true
|
|
@@ -408,16 +395,11 @@ var WrappedResponses = class {
|
|
|
408
395
|
});
|
|
409
396
|
} catch {}
|
|
410
397
|
this._trackFn({
|
|
411
|
-
|
|
398
|
+
...contextFields(sessionCtx),
|
|
412
399
|
modelName: String(accumulator.model ?? params.model ?? "unknown"),
|
|
413
400
|
provider: this._providerName,
|
|
414
401
|
responseContent: state.content,
|
|
415
402
|
latencyMs: accumulator.elapsedMs,
|
|
416
|
-
sessionId: sessionCtx.sessionId,
|
|
417
|
-
traceId: sessionCtx.traceId,
|
|
418
|
-
turnId: sessionCtx.turnId ?? void 0,
|
|
419
|
-
agentId: sessionCtx.agentId,
|
|
420
|
-
env: sessionCtx.env,
|
|
421
403
|
inputTokens: state.inputTokens,
|
|
422
404
|
outputTokens: state.outputTokens,
|
|
423
405
|
totalTokens: state.totalTokens,
|