@amplitude/ai 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/AGENTS.md +3 -1
  2. package/README.md +44 -15
  3. package/dist/client.d.ts.map +1 -1
  4. package/dist/client.js +2 -1
  5. package/dist/client.js.map +1 -1
  6. package/dist/index.d.ts +2 -2
  7. package/dist/index.js +2 -2
  8. package/dist/integrations/anthropic-tools.js +2 -1
  9. package/dist/integrations/anthropic-tools.js.map +1 -1
  10. package/dist/integrations/langchain.d.ts.map +1 -1
  11. package/dist/integrations/langchain.js +35 -5
  12. package/dist/integrations/langchain.js.map +1 -1
  13. package/dist/integrations/llamaindex.d.ts.map +1 -1
  14. package/dist/integrations/llamaindex.js +27 -4
  15. package/dist/integrations/llamaindex.js.map +1 -1
  16. package/dist/integrations/openai-agents.js +5 -1
  17. package/dist/integrations/openai-agents.js.map +1 -1
  18. package/dist/integrations/opentelemetry.d.ts.map +1 -1
  19. package/dist/integrations/opentelemetry.js +2 -1
  20. package/dist/integrations/opentelemetry.js.map +1 -1
  21. package/dist/mcp/patterns.d.ts.map +1 -1
  22. package/dist/mcp/patterns.js +6 -0
  23. package/dist/mcp/patterns.js.map +1 -1
  24. package/dist/mcp/server.d.ts.map +1 -1
  25. package/dist/mcp/validate-file.js +1 -1
  26. package/dist/mcp/validate-file.js.map +1 -1
  27. package/dist/patching.d.ts.map +1 -1
  28. package/dist/patching.js +7 -1
  29. package/dist/patching.js.map +1 -1
  30. package/dist/providers/anthropic.d.ts.map +1 -1
  31. package/dist/providers/anthropic.js +11 -20
  32. package/dist/providers/anthropic.js.map +1 -1
  33. package/dist/providers/azure-openai.d.ts +3 -3
  34. package/dist/providers/azure-openai.d.ts.map +1 -1
  35. package/dist/providers/azure-openai.js +2 -2
  36. package/dist/providers/azure-openai.js.map +1 -1
  37. package/dist/providers/base.d.ts +11 -2
  38. package/dist/providers/base.d.ts.map +1 -1
  39. package/dist/providers/base.js +32 -14
  40. package/dist/providers/base.js.map +1 -1
  41. package/dist/providers/bedrock.d.ts.map +1 -1
  42. package/dist/providers/bedrock.js +16 -29
  43. package/dist/providers/bedrock.js.map +1 -1
  44. package/dist/providers/gemini.d.ts.map +1 -1
  45. package/dist/providers/gemini.js +12 -29
  46. package/dist/providers/gemini.js.map +1 -1
  47. package/dist/providers/mistral.d.ts.map +1 -1
  48. package/dist/providers/mistral.js +24 -26
  49. package/dist/providers/mistral.js.map +1 -1
  50. package/dist/providers/openai.d.ts.map +1 -1
  51. package/dist/providers/openai.js +37 -45
  52. package/dist/providers/openai.js.map +1 -1
  53. package/dist/session.d.ts +23 -0
  54. package/dist/session.d.ts.map +1 -1
  55. package/dist/session.js +44 -1
  56. package/dist/session.js.map +1 -1
  57. package/dist/types.d.ts +3 -0
  58. package/dist/types.d.ts.map +1 -1
  59. package/dist/types.js.map +1 -1
  60. package/dist/utils/costs.d.ts +46 -5
  61. package/dist/utils/costs.d.ts.map +1 -1
  62. package/dist/utils/costs.js +115 -26
  63. package/dist/utils/costs.js.map +1 -1
  64. package/dist/utils/providers.d.ts +6 -1
  65. package/dist/utils/providers.d.ts.map +1 -1
  66. package/dist/utils/providers.js +9 -3
  67. package/dist/utils/providers.js.map +1 -1
  68. package/dist/utils/streaming.d.ts +2 -0
  69. package/dist/utils/streaming.d.ts.map +1 -1
  70. package/dist/utils/streaming.js +10 -0
  71. package/dist/utils/streaming.js.map +1 -1
  72. package/llms-full.txt +17 -1
  73. package/llms.txt +1 -1
  74. package/mcp.schema.json +1 -1
  75. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  import { PrivacyConfig } from "../core/privacy.js";
2
- import { AmplitudeLike, AmplitudeOrAI, TrackFn } from "../types.js";
2
+ import { AmplitudeLike, AmplitudeOrAI, TrackCallOptions, TrackFn } from "../types.js";
3
3
  import { TrackAiMessageOptions } from "../core/tracking.js";
4
4
  import { StreamingAccumulator } from "../utils/streaming.js";
5
5
 
@@ -22,6 +22,8 @@ interface ProviderTrackOptions {
22
22
  agentId?: string | null;
23
23
  parentAgentId?: string | null;
24
24
  customerOrgId?: string | null;
25
+ agentVersion?: string | null;
26
+ context?: Record<string, unknown> | null;
25
27
  env?: string | null;
26
28
  groups?: Record<string, unknown> | null;
27
29
  eventProperties?: Record<string, unknown> | null;
@@ -39,6 +41,13 @@ interface ProviderTrackOptions {
39
41
  declare function applySessionContext(overrides?: ProviderTrackOptions): ProviderTrackOptions & {
40
42
  userId: string;
41
43
  };
44
+ /**
45
+ * Extract all context fields from a resolved ProviderTrackOptions into a
46
+ * flat object suitable for spreading into _trackFn() / _track() calls.
47
+ * Ensures all 13 context fields propagate consistently.
48
+ */
49
+ type TrackContextFields = Pick<TrackCallOptions, 'userId' | 'sessionId' | 'traceId' | 'turnId' | 'agentId' | 'parentAgentId' | 'customerOrgId' | 'agentVersion' | 'context' | 'env' | 'groups' | 'eventProperties'>;
50
+ declare function contextFields(ctx: ProviderTrackOptions): TrackContextFields;
42
51
  declare abstract class BaseAIProvider {
43
52
  protected _amplitude: AmplitudeLike;
44
53
  protected _privacyConfig: PrivacyConfig | null;
@@ -66,5 +75,5 @@ declare class SimpleStreamingTracker {
66
75
  finalize(overrides?: ProviderTrackOptions): string;
67
76
  }
68
77
  //#endregion
69
- export { BaseAIProvider, ProviderTrackOptions, SimpleStreamingTracker, applySessionContext };
78
+ export { BaseAIProvider, ProviderTrackOptions, SimpleStreamingTracker, TrackContextFields, applySessionContext, contextFields };
70
79
  //# sourceMappingURL=base.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"base.d.ts","names":[],"sources":["../../src/providers/base.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;;;AAsJa,UApHI,oBAAA,CAoHkB;EAEX,MAAA,CAAA,EAAA,MAAA,GAAA,IAAA;EAIA,SAAA,CAAA,EAAA,MAAA,GAAA,IAAA;EAeK,OAAA,CAAA,EAAA,MAAA,GAAA,IAAA;EAAX,MAAA,CAAA,EAAA,MAAA,GAAA,IAAA;EAQM,OAAA,CAAA,EAAA,MAAA,GAAA,IAAA;EAIF,aAAA,CAAA,EAAA,MAAA,GAAA,IAAA;EAAyB,aAAA,CAAA,EAAA,MAAA,GAAA,IAAA;;WA5IpC;oBACS;;;;;;;;;;;;iBAaJ,mBAAA,aACH,uBACV;;;uBAqCmB,cAAA;wBACE;4BACI;;;eAIb;oBACK;;;yBAQK,KAAK;aA6BjB;4BAKe;;cAKf,sBAAA;;wBAEW;;;wBAIA;;;kBAeN,WAAW;;wBAQL;uBAIF"}
1
+ {"version":3,"file":"base.d.ts","names":[],"sources":["../../src/providers/base.ts"],"sourcesContent":[],"mappings":";;;;;;;;;AA2DA;AAgDA;AAgBA;AAiBA;;;;AAOoB,UAjHH,oBAAA,CAiHG;EAQU,MAAA,CAAA,EAAA,MAAA,GAAA,IAAA;EAAL,SAAA,CAAA,EAAA,MAAA,GAAA,IAAA;EAmCZ,OAAA,CAAA,EAAA,MAAA,GAAA,IAAA;EAKe,MAAA,CAAA,EAAA,MAAA,GAAA,IAAA;EAAsB,OAAA,CAAA,EAAA,MAAA,GAAA,IAAA;EAKrC,aAAA,CAAA,EAAA,MAAA,GAAsB,IAAA;EAEX,aAAA,CAAA,EAAA,MAAA,GAAA,IAAA;EAIA,YAAA,CAAA,EAAA,MAAA,GAAA,IAAA;EAeK,OAAA,CAAA,EAlLjB,MAkLiB,CAAA,MAAA,EAAA,OAAA,CAAA,GAAA,IAAA;EAAX,GAAA,CAAA,EAAA,MAAA,GAAA,IAAA;EAQM,MAAA,CAAA,EAxLb,MAwLa,CAAA,MAAA,EAAA,OAAA,CAAA,GAAA,IAAA;EAIF,eAAA,CAAA,EA3LF,MA2LE,CAAA,MAAA,EAAA,OAAA,CAAA,GAAA,IAAA;EAAyB;;;;;;;;;;;iBA9K/B,mBAAA,aACH,uBACV;;;;;;;;KA8CS,kBAAA,GAAqB,KAC/B;iBAec,aAAA,MAAmB,uBAAuB;uBAiBpC,cAAA;wBACE;4BACI;;;eAIb;oBACK;;;yBAQK,KAAK;aAmCjB;4BAKe;;cAKf,sBAAA;;wBAEW;;;wBAIA;;;kBAeN,WAAW;;wBAQL;uBAIF"}
@@ -25,10 +25,14 @@ function applySessionContext(overrides = {}) {
25
25
  if (!result.agentId) result.agentId = ctx.agentId;
26
26
  if (!result.parentAgentId) result.parentAgentId = ctx.parentAgentId;
27
27
  if (!result.customerOrgId) result.customerOrgId = ctx.customerOrgId;
28
+ if (!result.agentVersion) result.agentVersion = ctx.agentVersion;
29
+ if (!result.context) result.context = ctx.context;
28
30
  if (!result.env) result.env = ctx.env;
29
31
  if (!result.groups) result.groups = ctx.groups;
30
- const turnId = ctx.nextTurnId();
31
- if (turnId != null && result.turnId == null) result.turnId = turnId;
32
+ if (result.turnId == null) {
33
+ const turnId = ctx.nextTurnId();
34
+ if (turnId != null) result.turnId = turnId;
35
+ }
32
36
  const existingEp = result.eventProperties;
33
37
  const ep = existingEp != null ? { ...existingEp } : {};
34
38
  if (ctx.idleTimeoutMinutes != null && !(PROP_IDLE_TIMEOUT_MINUTES in ep)) ep[PROP_IDLE_TIMEOUT_MINUTES] = ctx.idleTimeoutMinutes;
@@ -37,6 +41,22 @@ function applySessionContext(overrides = {}) {
37
41
  }
38
42
  return result;
39
43
  }
44
+ function contextFields(ctx) {
45
+ return {
46
+ userId: ctx.userId ?? "unknown",
47
+ sessionId: ctx.sessionId,
48
+ traceId: ctx.traceId,
49
+ turnId: ctx.turnId ?? void 0,
50
+ agentId: ctx.agentId,
51
+ parentAgentId: ctx.parentAgentId,
52
+ customerOrgId: ctx.customerOrgId,
53
+ agentVersion: ctx.agentVersion,
54
+ context: ctx.context,
55
+ env: ctx.env,
56
+ groups: ctx.groups,
57
+ eventProperties: ctx.eventProperties
58
+ };
59
+ }
40
60
  var BaseAIProvider = class {
41
61
  _amplitude;
42
62
  _privacyConfig;
@@ -55,8 +75,11 @@ var BaseAIProvider = class {
55
75
  agentId: opts.agentId,
56
76
  parentAgentId: opts.parentAgentId,
57
77
  customerOrgId: opts.customerOrgId,
78
+ agentVersion: opts.agentVersion,
79
+ context: opts.context,
58
80
  env: opts.env,
59
- groups: opts.groups
81
+ groups: opts.groups,
82
+ eventProperties: opts.eventProperties
60
83
  });
61
84
  return trackAiMessage({
62
85
  ...opts,
@@ -68,8 +91,11 @@ var BaseAIProvider = class {
68
91
  agentId: merged.agentId ?? opts.agentId,
69
92
  parentAgentId: merged.parentAgentId ?? opts.parentAgentId,
70
93
  customerOrgId: merged.customerOrgId ?? opts.customerOrgId,
94
+ agentVersion: merged.agentVersion ?? opts.agentVersion,
95
+ context: merged.context ?? opts.context,
71
96
  env: merged.env ?? opts.env,
72
97
  groups: merged.groups ?? opts.groups,
98
+ eventProperties: merged.eventProperties ?? opts.eventProperties,
73
99
  privacyConfig: this._privacyConfig
74
100
  });
75
101
  }
@@ -109,7 +135,7 @@ var SimpleStreamingTracker = class {
109
135
  finalize(overrides = {}) {
110
136
  const state = this.accumulator.getState();
111
137
  return this._trackFn({
112
- userId: overrides.userId ?? "unknown",
138
+ ...contextFields(overrides),
113
139
  modelName: this._modelName,
114
140
  provider: this._providerName,
115
141
  responseContent: state.content,
@@ -123,19 +149,11 @@ var SimpleStreamingTracker = class {
123
149
  finishReason: state.finishReason,
124
150
  toolCalls: state.toolCalls.length > 0 ? state.toolCalls : null,
125
151
  providerTtfbMs: state.ttfbMs,
126
- isStreaming: true,
127
- sessionId: overrides.sessionId,
128
- traceId: overrides.traceId,
129
- turnId: overrides.turnId ?? void 0,
130
- agentId: overrides.agentId,
131
- parentAgentId: overrides.parentAgentId,
132
- customerOrgId: overrides.customerOrgId,
133
- env: overrides.env,
134
- groups: overrides.groups
152
+ isStreaming: true
135
153
  });
136
154
  }
137
155
  };
138
156
 
139
157
  //#endregion
140
- export { BaseAIProvider, SimpleStreamingTracker, applySessionContext };
158
+ export { BaseAIProvider, SimpleStreamingTracker, applySessionContext, contextFields };
141
159
  //# sourceMappingURL=base.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"base.js","names":["result: Record<string, unknown>"],"sources":["../../src/providers/base.ts"],"sourcesContent":["/**\n * Base class for AI provider wrappers.\n *\n * Provides shared tracking logic and session context integration.\n */\n\nimport { getActiveContext } from '../context.js';\nimport {\n PROP_IDLE_TIMEOUT_MINUTES,\n PROP_SESSION_REPLAY_ID,\n} from '../core/constants.js';\nimport type { PrivacyConfig } from '../core/privacy.js';\nimport {\n trackAiMessage,\n type TrackAiMessageOptions,\n} from '../core/tracking.js';\nimport {\n resolveAmplitude,\n type AmplitudeLike,\n type AmplitudeOrAI,\n type TrackCallOptions,\n type TrackFn,\n} from '../types.js';\nimport { StreamingAccumulator } from '../utils/streaming.js';\n\n/**\n * Per-call context overrides for provider wrappers.\n *\n * Pass as the second argument to wrapped provider methods\n * (e.g., `openai.chat.completions.create(params, overrides)`)\n * to set Amplitude tracking context for that specific call.\n * Any fields left `null`/`undefined` are filled from the\n * active `SessionContext` via `AsyncLocalStorage`.\n */\nexport interface ProviderTrackOptions {\n userId?: string | null;\n sessionId?: string | null;\n traceId?: string | null;\n turnId?: number | null;\n agentId?: string | null;\n parentAgentId?: string | null;\n customerOrgId?: string | null;\n env?: string | null;\n groups?: Record<string, unknown> | null;\n eventProperties?: Record<string, unknown> | null;\n /**\n * Controls whether provider wrappers auto-track user input payloads.\n * Set to false when you already call `trackUserMessage()` explicitly.\n */\n trackInputMessages?: boolean;\n}\n\n/**\n * Apply session context fields from AsyncLocalStorage to tracking options.\n * Returns a merged set of fields with explicit values taking precedence.\n * Also injects idle_timeout_minutes and session_replay_id from the context.\n */\nexport function applySessionContext(\n overrides: ProviderTrackOptions = {},\n): ProviderTrackOptions & { userId: string } {\n const ctx = getActiveContext();\n const result: Record<string, unknown> = { ...overrides };\n\n if (ctx != null) {\n if (!result.userId) result.userId = ctx.userId;\n if (!result.sessionId) result.sessionId = ctx.sessionId;\n if (!result.traceId) result.traceId = ctx.traceId;\n if (!result.agentId) result.agentId = ctx.agentId;\n if (!result.parentAgentId) result.parentAgentId = ctx.parentAgentId;\n if (!result.customerOrgId) result.customerOrgId = ctx.customerOrgId;\n if (!result.env) result.env = ctx.env;\n if (!result.groups) result.groups = ctx.groups;\n\n const turnId = ctx.nextTurnId();\n if (turnId != null && result.turnId == null) result.turnId = turnId;\n\n const existingEp = result.eventProperties as Record<string, unknown> | null;\n const ep = existingEp != null ? { ...existingEp } : {};\n if (ctx.idleTimeoutMinutes != null && !(PROP_IDLE_TIMEOUT_MINUTES in ep)) {\n ep[PROP_IDLE_TIMEOUT_MINUTES] = ctx.idleTimeoutMinutes;\n }\n if (\n ctx.deviceId &&\n ctx.browserSessionId &&\n !(PROP_SESSION_REPLAY_ID in ep)\n ) {\n ep[PROP_SESSION_REPLAY_ID] = `${ctx.deviceId}/${ctx.browserSessionId}`;\n }\n if (Object.keys(ep).length > 0) {\n result.eventProperties = ep;\n }\n }\n\n return result as unknown as ProviderTrackOptions & { userId: string };\n}\n\nexport abstract class BaseAIProvider {\n protected _amplitude: AmplitudeLike;\n protected _privacyConfig: PrivacyConfig | null;\n readonly _providerName: string;\n\n constructor(options: {\n amplitude: AmplitudeOrAI;\n privacyConfig?: PrivacyConfig | null;\n providerName: string;\n }) {\n this._amplitude = resolveAmplitude(options.amplitude);\n this._privacyConfig = options.privacyConfig ?? null;\n this._providerName = options.providerName;\n }\n\n protected _track(opts: Omit<TrackAiMessageOptions, 'amplitude'>): string {\n const merged = applySessionContext({\n userId: opts.userId,\n sessionId: opts.sessionId,\n traceId: opts.traceId,\n turnId: opts.turnId,\n agentId: opts.agentId,\n parentAgentId: opts.parentAgentId,\n customerOrgId: opts.customerOrgId,\n env: opts.env,\n groups: opts.groups,\n });\n\n return trackAiMessage({\n ...opts,\n amplitude: this._amplitude,\n userId: merged.userId ?? opts.userId,\n sessionId: merged.sessionId ?? opts.sessionId,\n traceId: merged.traceId ?? opts.traceId,\n turnId: merged.turnId ?? opts.turnId,\n agentId: merged.agentId ?? opts.agentId,\n parentAgentId: merged.parentAgentId ?? opts.parentAgentId,\n customerOrgId: merged.customerOrgId ?? opts.customerOrgId,\n env: merged.env ?? opts.env,\n groups: merged.groups ?? opts.groups,\n privacyConfig: this._privacyConfig,\n });\n }\n\n trackFn(): TrackFn {\n return (opts: TrackCallOptions) =>\n this._track(opts as Omit<TrackAiMessageOptions, 'amplitude'>);\n }\n\n createStreamingTracker(): SimpleStreamingTracker {\n return new SimpleStreamingTracker(this);\n }\n}\n\nexport class SimpleStreamingTracker {\n private _trackFn: TrackFn;\n readonly accumulator: StreamingAccumulator;\n private _modelName = 'unknown';\n private _providerName: string;\n\n constructor(provider: BaseAIProvider) {\n this._trackFn = provider.trackFn();\n this._providerName = provider._providerName;\n this.accumulator = new StreamingAccumulator();\n }\n\n setModel(model: string): void {\n this._modelName = model;\n this.accumulator.model = model;\n }\n\n addContent(chunk: string): void {\n this.accumulator.addContent(chunk);\n }\n\n setUsage(usage: Parameters<StreamingAccumulator['setUsage']>[0]): void {\n this.accumulator.setUsage(usage);\n }\n\n setFinishReason(reason: string): void {\n this.accumulator.finishReason = reason;\n }\n\n addToolCall(toolCall: Record<string, unknown>): void {\n this.accumulator.addToolCall(toolCall);\n }\n\n finalize(overrides: ProviderTrackOptions = {}): string {\n const state = this.accumulator.getState();\n\n return this._trackFn({\n userId: overrides.userId ?? 'unknown',\n modelName: this._modelName,\n provider: this._providerName,\n responseContent: state.content,\n latencyMs: this.accumulator.elapsedMs,\n inputTokens: state.inputTokens,\n outputTokens: state.outputTokens,\n totalTokens: state.totalTokens,\n reasoningTokens: state.reasoningTokens,\n cacheReadInputTokens: state.cacheReadTokens,\n cacheCreationInputTokens: state.cacheCreationTokens,\n finishReason: state.finishReason,\n toolCalls: state.toolCalls.length > 0 ? state.toolCalls : null,\n providerTtfbMs: state.ttfbMs,\n isStreaming: true,\n sessionId: overrides.sessionId,\n traceId: overrides.traceId,\n turnId: overrides.turnId ?? undefined,\n agentId: overrides.agentId,\n parentAgentId: overrides.parentAgentId,\n customerOrgId: overrides.customerOrgId,\n env: overrides.env,\n groups: overrides.groups,\n });\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"base.js","names":["result: Record<string, unknown>"],"sources":["../../src/providers/base.ts"],"sourcesContent":["/**\n * Base class for AI provider wrappers.\n *\n * Provides shared tracking logic and session context integration.\n */\n\nimport { getActiveContext } from '../context.js';\nimport {\n PROP_IDLE_TIMEOUT_MINUTES,\n PROP_SESSION_REPLAY_ID,\n} from '../core/constants.js';\nimport type { PrivacyConfig } from '../core/privacy.js';\nimport {\n trackAiMessage,\n type TrackAiMessageOptions,\n} from '../core/tracking.js';\nimport {\n resolveAmplitude,\n type AmplitudeLike,\n type AmplitudeOrAI,\n type TrackCallOptions,\n type TrackFn,\n} from '../types.js';\nimport { StreamingAccumulator } from '../utils/streaming.js';\n\n/**\n * Per-call context overrides for provider wrappers.\n *\n * Pass as the second argument to wrapped provider methods\n * (e.g., `openai.chat.completions.create(params, overrides)`)\n * to set Amplitude tracking context for that specific call.\n * Any fields left `null`/`undefined` are filled from the\n * active `SessionContext` via `AsyncLocalStorage`.\n */\nexport interface ProviderTrackOptions {\n userId?: string | null;\n sessionId?: string | null;\n traceId?: string | null;\n turnId?: number | null;\n agentId?: string | null;\n parentAgentId?: string | null;\n customerOrgId?: string | null;\n agentVersion?: string | null;\n context?: Record<string, unknown> | null;\n env?: string | null;\n groups?: Record<string, unknown> | null;\n eventProperties?: Record<string, unknown> | null;\n /**\n * Controls whether provider wrappers auto-track user input payloads.\n * Set to false when you already call `trackUserMessage()` explicitly.\n */\n trackInputMessages?: boolean;\n}\n\n/**\n * Apply session context fields from AsyncLocalStorage to tracking options.\n * Returns a merged set of fields with explicit values taking precedence.\n * Also injects idle_timeout_minutes and session_replay_id from the context.\n */\nexport function applySessionContext(\n overrides: ProviderTrackOptions = {},\n): ProviderTrackOptions & { userId: string } {\n const ctx = getActiveContext();\n const result: Record<string, unknown> = { ...overrides };\n\n if (ctx != null) {\n if (!result.userId) result.userId = ctx.userId;\n if (!result.sessionId) result.sessionId = ctx.sessionId;\n if (!result.traceId) result.traceId = ctx.traceId;\n if (!result.agentId) result.agentId = ctx.agentId;\n if (!result.parentAgentId) result.parentAgentId = ctx.parentAgentId;\n if (!result.customerOrgId) result.customerOrgId = ctx.customerOrgId;\n if (!result.agentVersion) result.agentVersion = ctx.agentVersion;\n if (!result.context) result.context = ctx.context;\n if (!result.env) result.env = ctx.env;\n if (!result.groups) result.groups = ctx.groups;\n\n if (result.turnId == null) {\n const turnId = ctx.nextTurnId();\n if (turnId != null) result.turnId = turnId;\n }\n\n const existingEp = result.eventProperties as Record<string, unknown> | null;\n const ep = existingEp != null ? { ...existingEp } : {};\n if (ctx.idleTimeoutMinutes != null && !(PROP_IDLE_TIMEOUT_MINUTES in ep)) {\n ep[PROP_IDLE_TIMEOUT_MINUTES] = ctx.idleTimeoutMinutes;\n }\n if (\n ctx.deviceId &&\n ctx.browserSessionId &&\n !(PROP_SESSION_REPLAY_ID in ep)\n ) {\n ep[PROP_SESSION_REPLAY_ID] = `${ctx.deviceId}/${ctx.browserSessionId}`;\n }\n if (Object.keys(ep).length > 0) {\n result.eventProperties = ep;\n }\n }\n\n return result as unknown as ProviderTrackOptions & { userId: string };\n}\n\n/**\n * Extract all context fields from a resolved ProviderTrackOptions into a\n * flat object suitable for spreading into _trackFn() / _track() calls.\n * Ensures all 13 context fields propagate consistently.\n */\nexport type TrackContextFields = Pick<\n TrackCallOptions,\n | 'userId'\n | 'sessionId'\n | 'traceId'\n | 'turnId'\n | 'agentId'\n | 'parentAgentId'\n | 'customerOrgId'\n | 'agentVersion'\n | 'context'\n | 'env'\n | 'groups'\n | 'eventProperties'\n>;\n\nexport function contextFields(ctx: ProviderTrackOptions): TrackContextFields {\n return {\n userId: ctx.userId ?? 'unknown',\n sessionId: ctx.sessionId,\n traceId: ctx.traceId,\n turnId: ctx.turnId ?? undefined,\n agentId: ctx.agentId,\n parentAgentId: ctx.parentAgentId,\n customerOrgId: ctx.customerOrgId,\n agentVersion: ctx.agentVersion,\n context: ctx.context,\n env: ctx.env,\n groups: ctx.groups,\n eventProperties: ctx.eventProperties,\n };\n}\n\nexport abstract class BaseAIProvider {\n protected _amplitude: AmplitudeLike;\n protected _privacyConfig: PrivacyConfig | null;\n readonly _providerName: string;\n\n constructor(options: {\n amplitude: AmplitudeOrAI;\n privacyConfig?: PrivacyConfig | null;\n providerName: string;\n }) {\n this._amplitude = resolveAmplitude(options.amplitude);\n this._privacyConfig = options.privacyConfig ?? null;\n this._providerName = options.providerName;\n }\n\n protected _track(opts: Omit<TrackAiMessageOptions, 'amplitude'>): string {\n const merged = applySessionContext({\n userId: opts.userId,\n sessionId: opts.sessionId,\n traceId: opts.traceId,\n turnId: opts.turnId,\n agentId: opts.agentId,\n parentAgentId: opts.parentAgentId,\n customerOrgId: opts.customerOrgId,\n agentVersion: opts.agentVersion,\n context: opts.context,\n env: opts.env,\n groups: opts.groups,\n eventProperties: opts.eventProperties,\n });\n\n return trackAiMessage({\n ...opts,\n amplitude: this._amplitude,\n userId: merged.userId ?? opts.userId,\n sessionId: merged.sessionId ?? opts.sessionId,\n traceId: merged.traceId ?? opts.traceId,\n turnId: merged.turnId ?? opts.turnId,\n agentId: merged.agentId ?? opts.agentId,\n parentAgentId: merged.parentAgentId ?? opts.parentAgentId,\n customerOrgId: merged.customerOrgId ?? opts.customerOrgId,\n agentVersion: merged.agentVersion ?? opts.agentVersion,\n context: merged.context ?? opts.context,\n env: merged.env ?? opts.env,\n groups: merged.groups ?? opts.groups,\n eventProperties: merged.eventProperties ?? opts.eventProperties,\n privacyConfig: this._privacyConfig,\n });\n }\n\n trackFn(): TrackFn {\n return (opts: TrackCallOptions) =>\n this._track(opts as Omit<TrackAiMessageOptions, 'amplitude'>);\n }\n\n createStreamingTracker(): SimpleStreamingTracker {\n return new SimpleStreamingTracker(this);\n }\n}\n\nexport class SimpleStreamingTracker {\n private _trackFn: TrackFn;\n readonly accumulator: StreamingAccumulator;\n private _modelName = 'unknown';\n private _providerName: string;\n\n constructor(provider: BaseAIProvider) {\n this._trackFn = provider.trackFn();\n this._providerName = provider._providerName;\n this.accumulator = new StreamingAccumulator();\n }\n\n setModel(model: string): void {\n this._modelName = model;\n this.accumulator.model = model;\n }\n\n addContent(chunk: string): void {\n this.accumulator.addContent(chunk);\n }\n\n setUsage(usage: Parameters<StreamingAccumulator['setUsage']>[0]): void {\n this.accumulator.setUsage(usage);\n }\n\n setFinishReason(reason: string): void {\n this.accumulator.finishReason = reason;\n }\n\n addToolCall(toolCall: Record<string, unknown>): void {\n this.accumulator.addToolCall(toolCall);\n }\n\n finalize(overrides: ProviderTrackOptions = {}): string {\n const state = this.accumulator.getState();\n\n return this._trackFn({\n ...contextFields(overrides),\n modelName: this._modelName,\n provider: this._providerName,\n responseContent: state.content,\n latencyMs: this.accumulator.elapsedMs,\n inputTokens: state.inputTokens,\n outputTokens: state.outputTokens,\n totalTokens: state.totalTokens,\n reasoningTokens: state.reasoningTokens,\n cacheReadInputTokens: state.cacheReadTokens,\n cacheCreationInputTokens: state.cacheCreationTokens,\n finishReason: state.finishReason,\n toolCalls: state.toolCalls.length > 0 ? state.toolCalls : null,\n providerTtfbMs: state.ttfbMs,\n isStreaming: true,\n });\n }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"bedrock.d.ts","names":[],"sources":["../../src/providers/bedrock.ts"],"sourcesContent":[],"mappings":";;;;;;AA2Ba,cAbA,iBAaQ,EAAA,OAAA;cAZf,cAgBiB,EAhBD,MAgBC,CAAA,MAAA,EAAA,OAAA,CAAA,GAAA,IAAA;AAY4B,UAxBlC,cAAA,CAwBkC;EAwFpB,SAAA,EA/GlB,aA+GkB;EAA0B,MAAA,EAAA,OAAA;EAxG5B,aAAA,CAAA,EALX,aAKW,GAAA,IAAA;EAAc;EA+Q3B,aAAA,CAAA,EAAA,OAAA;;cA/QH,OAAA,SAAgB,cAAA;;;uBAIN;mBAYE,0BAA0B;yBAwFpB,0BAA0B;;;;iBAuKzC,sBAAA;;;;;;;;aAQH,MAAM"}
1
+ {"version":3,"file":"bedrock.d.ts","names":[],"sources":["../../src/providers/bedrock.ts"],"sourcesContent":[],"mappings":";;;;;;AA2Ba,cAbA,iBAaQ,EAAA,OAAA;cAZf,cAgBiB,EAhBD,MAgBC,CAAA,MAAA,EAAA,OAAA,CAAA,GAAA,IAAA;AAY4B,UAxBlC,cAAA,CAwBkC;EAgFpB,SAAA,EAvGlB,aAuGkB;EAA0B,MAAA,EAAA,OAAA;EAhG5B,aAAA,CAAA,EALX,aAKW,GAAA,IAAA;EAAc;EAmQ3B,aAAA,CAAA,EAAA,OAAA;;cAnQH,OAAA,SAAgB,cAAA;;;uBAIN;mBAYE,0BAA0B;yBAgFpB,0BAA0B;;;;iBAmKzC,sBAAA;;;;;;;;aAQH,MAAM"}
@@ -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/bedrock.ts
7
7
  const _resolved = tryRequire("@aws-sdk/client-bedrock-runtime");
@@ -37,21 +37,17 @@ var Bedrock = class extends BaseAIProvider {
37
37
  inputTokens: extracted.inputTokens,
38
38
  outputTokens: extracted.outputTokens,
39
39
  cacheReadInputTokens: extracted.cacheReadTokens ?? 0,
40
- cacheCreationInputTokens: extracted.cacheWriteTokens ?? 0
40
+ cacheCreationInputTokens: extracted.cacheWriteTokens ?? 0,
41
+ defaultProvider: "bedrock"
41
42
  });
42
43
  } catch {}
43
44
  const ctx = applySessionContext();
44
45
  this._track({
45
- userId: ctx.userId ?? "unknown",
46
+ ...contextFields(ctx),
46
47
  modelName: modelId,
47
48
  provider: "bedrock",
48
49
  responseContent: extracted.text,
49
50
  latencyMs,
50
- sessionId: ctx.sessionId,
51
- traceId: ctx.traceId,
52
- turnId: ctx.turnId ?? void 0,
53
- agentId: ctx.agentId,
54
- env: ctx.env,
55
51
  inputTokens: extracted.inputTokens,
56
52
  outputTokens: extracted.outputTokens,
57
53
  totalTokens: extracted.totalTokens,
@@ -69,15 +65,11 @@ var Bedrock = class extends BaseAIProvider {
69
65
  const latencyMs = performance.now() - startTime;
70
66
  const ctx = applySessionContext();
71
67
  this._track({
72
- userId: ctx.userId ?? "unknown",
68
+ ...contextFields(ctx),
73
69
  modelName: modelId,
74
70
  provider: "bedrock",
75
71
  responseContent: "",
76
72
  latencyMs,
77
- sessionId: ctx.sessionId,
78
- traceId: ctx.traceId,
79
- agentId: ctx.agentId,
80
- env: ctx.env,
81
73
  isError: true,
82
74
  errorMessage: error instanceof Error ? error.message : String(error)
83
75
  });
@@ -99,19 +91,15 @@ var Bedrock = class extends BaseAIProvider {
99
91
  if (!_isAsyncIterable(stream)) throw new Error("Bedrock stream response is not AsyncIterable");
100
92
  return {
101
93
  ...response,
102
- stream: this._wrapConverseStream(modelId, params, stream)
94
+ stream: this._wrapConverseStream(modelId, params, stream, ctx)
103
95
  };
104
96
  } catch (error) {
105
97
  this._track({
106
- userId: ctx.userId ?? "unknown",
98
+ ...contextFields(ctx),
107
99
  modelName: modelId,
108
100
  provider: "bedrock",
109
101
  responseContent: "",
110
102
  latencyMs: performance.now() - startTime,
111
- sessionId: ctx.sessionId,
112
- traceId: ctx.traceId,
113
- agentId: ctx.agentId,
114
- env: ctx.env,
115
103
  isError: true,
116
104
  errorMessage: error instanceof Error ? error.message : String(error),
117
105
  isStreaming: true
@@ -122,10 +110,9 @@ var Bedrock = class extends BaseAIProvider {
122
110
  get client() {
123
111
  return this._client;
124
112
  }
125
- async *_wrapConverseStream(modelId, params, stream) {
113
+ async *_wrapConverseStream(modelId, params, stream, ctx) {
126
114
  const accumulator = new StreamingAccumulator();
127
115
  accumulator.model = modelId;
128
- const ctx = applySessionContext();
129
116
  try {
130
117
  for await (const rawEvent of stream) {
131
118
  const event = rawEvent;
@@ -141,7 +128,9 @@ var Bedrock = class extends BaseAIProvider {
141
128
  accumulator.setUsage({
142
129
  inputTokens: usage?.inputTokens,
143
130
  outputTokens: usage?.outputTokens,
144
- totalTokens: usage?.totalTokens
131
+ totalTokens: usage?.totalTokens,
132
+ cacheReadTokens: usage?.cacheReadInputTokens,
133
+ cacheCreationTokens: usage?.cacheWriteInputTokens
145
134
  });
146
135
  yield rawEvent;
147
136
  }
@@ -156,20 +145,18 @@ var Bedrock = class extends BaseAIProvider {
156
145
  costUsd = calculateCost({
157
146
  modelName,
158
147
  inputTokens: state.inputTokens,
159
- outputTokens: state.outputTokens
148
+ outputTokens: state.outputTokens,
149
+ cacheReadInputTokens: state.cacheReadTokens ?? 0,
150
+ cacheCreationInputTokens: state.cacheCreationTokens ?? 0,
151
+ defaultProvider: "bedrock"
160
152
  });
161
153
  } catch {}
162
154
  this._track({
163
- userId: ctx.userId ?? "unknown",
155
+ ...contextFields(ctx),
164
156
  modelName,
165
157
  provider: "bedrock",
166
158
  responseContent: state.content,
167
159
  latencyMs: accumulator.elapsedMs,
168
- sessionId: ctx.sessionId,
169
- traceId: ctx.traceId,
170
- turnId: ctx.turnId ?? void 0,
171
- agentId: ctx.agentId,
172
- env: ctx.env,
173
160
  inputTokens: state.inputTokens,
174
161
  outputTokens: state.outputTokens,
175
162
  totalTokens: state.totalTokens,
@@ -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 defaultProvider: 'bedrock',\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 defaultProvider: 'bedrock',\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;EAkFO,aAAA,CAAA,EAlHM,aAkHN,GAAA,IAAA;EACP;EA9GuB,YAAA,CAAA,EAAA,OAAA;;AAuQZ,cAvQH,MAAA,SAAe,cAAA,CA6QV;;uBA1QK;yCAuBX,0BACP;+CAkFO,0BACP;;;;iBAyJW,qBAAA;;;;;;kBAME,MAAM"}
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;EA0EO,aAAA,CAAA,EA1GM,aA0GN,GAAA,IAAA;EACP;EAtGuB,YAAA,CAAA,EAAA,OAAA;;AA0PZ,cA1PH,MAAA,SAAe,cAAA,CAgQV;;uBA7PK;yCAuBX,0BACP;+CA0EO,0BACP;;;;iBAoJW,qBAAA;;;;;;kBAME,MAAM"}
@@ -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");
@@ -33,21 +33,17 @@ var Gemini = class extends BaseAIProvider {
33
33
  costUsd = calculateCost({
34
34
  modelName: model,
35
35
  inputTokens: extracted.inputTokens,
36
- outputTokens: extracted.outputTokens
36
+ outputTokens: extracted.outputTokens,
37
+ defaultProvider: "google"
37
38
  });
38
39
  } catch {}
39
40
  const ctx = applySessionContext();
40
41
  this._track({
41
- userId: ctx.userId ?? "unknown",
42
+ ...contextFields(ctx),
42
43
  modelName: model,
43
44
  provider: "gemini",
44
45
  responseContent: extracted.text,
45
46
  latencyMs,
46
- sessionId: ctx.sessionId,
47
- traceId: ctx.traceId,
48
- turnId: ctx.turnId ?? void 0,
49
- agentId: ctx.agentId,
50
- env: ctx.env,
51
47
  inputTokens: extracted.inputTokens,
52
48
  outputTokens: extracted.outputTokens,
53
49
  totalTokens: extracted.totalTokens,
@@ -65,15 +61,11 @@ var Gemini = class extends BaseAIProvider {
65
61
  const latencyMs = performance.now() - startTime;
66
62
  const ctx = applySessionContext();
67
63
  this._track({
68
- userId: ctx.userId ?? "unknown",
64
+ ...contextFields(ctx),
69
65
  modelName: model,
70
66
  provider: "gemini",
71
67
  responseContent: "",
72
68
  latencyMs,
73
- sessionId: ctx.sessionId,
74
- traceId: ctx.traceId,
75
- agentId: ctx.agentId,
76
- env: ctx.env,
77
69
  isError: true,
78
70
  errorMessage: error instanceof Error ? error.message : String(error)
79
71
  });
@@ -93,19 +85,15 @@ var Gemini = class extends BaseAIProvider {
93
85
  if (!_isAsyncIterable(stream)) throw new Error("Gemini stream response is not AsyncIterable");
94
86
  return {
95
87
  ...streamResponse,
96
- stream: this._wrapStream(model, params, stream, finalResponse)
88
+ stream: this._wrapStream(model, params, stream, finalResponse, ctx)
97
89
  };
98
90
  } catch (error) {
99
91
  this._track({
100
- userId: ctx.userId ?? "unknown",
92
+ ...contextFields(ctx),
101
93
  modelName: model,
102
94
  provider: "gemini",
103
95
  responseContent: "",
104
96
  latencyMs: performance.now() - startTime,
105
- sessionId: ctx.sessionId,
106
- traceId: ctx.traceId,
107
- agentId: ctx.agentId,
108
- env: ctx.env,
109
97
  isError: true,
110
98
  errorMessage: error instanceof Error ? error.message : String(error),
111
99
  isStreaming: true
@@ -116,9 +104,8 @@ var Gemini = class extends BaseAIProvider {
116
104
  get client() {
117
105
  return this._client;
118
106
  }
119
- async *_wrapStream(model, params, stream, finalResponse) {
107
+ async *_wrapStream(model, params, stream, finalResponse, ctx) {
120
108
  const accumulator = new StreamingAccumulator();
121
- const ctx = applySessionContext();
122
109
  try {
123
110
  for await (const chunk of stream) {
124
111
  const extracted = extractGeminiResponse(chunk);
@@ -144,7 +131,7 @@ var Gemini = class extends BaseAIProvider {
144
131
  totalTokens: extractedFinal.totalTokens
145
132
  });
146
133
  if (extractedFinal.finishReason != null) accumulator.finishReason = String(extractedFinal.finishReason);
147
- if (Array.isArray(extractedFinal.functionCalls)) for (const fc of extractedFinal.functionCalls) accumulator.addToolCall(fc);
134
+ if (Array.isArray(extractedFinal.functionCalls) && accumulator.toolCalls.length === 0) for (const fc of extractedFinal.functionCalls) accumulator.addToolCall(fc);
148
135
  } catch {}
149
136
  const state = accumulator.getState();
150
137
  let costUsd = null;
@@ -152,20 +139,16 @@ var Gemini = class extends BaseAIProvider {
152
139
  costUsd = calculateCost({
153
140
  modelName: model,
154
141
  inputTokens: state.inputTokens,
155
- outputTokens: state.outputTokens
142
+ outputTokens: state.outputTokens,
143
+ defaultProvider: "google"
156
144
  });
157
145
  } catch {}
158
146
  this._track({
159
- userId: ctx.userId ?? "unknown",
147
+ ...contextFields(ctx),
160
148
  modelName: model,
161
149
  provider: "gemini",
162
150
  responseContent: state.content,
163
151
  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
152
  inputTokens: state.inputTokens,
170
153
  outputTokens: state.outputTokens,
171
154
  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 defaultProvider: 'google',\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 defaultProvider: 'google',\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;EA2F5B,QAAA,OAAA;EAA0B,SAAA,IAAA,EAzIhC,WAyIgC;EAAO,WAAA,CAAA,OAAA,EAvIjC,cAuIiC;;;cAvG3C,WAAA;;;wCAI2B;mBAQf,0BAA0B;iBA2F5B,0BAA0B"}
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;EAmF5B,QAAA,OAAA;EAA0B,SAAA,IAAA,EAjIhC,WAiIgC;EAAO,WAAA,CAAA,OAAA,EA/HjC,cA+HiC;;;cA/F3C,WAAA;;;wCAI2B;mBAQf,0BAA0B;iBAmF5B,0BAA0B"}