@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
package/AGENTS.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  # AGENTS.md
4
4
 
5
- Package: `@amplitude/ai` v0.1.1
5
+ Package: `@amplitude/ai` v0.2.0
6
6
 
7
7
  ## Install
8
8
 
@@ -13,6 +13,7 @@ Package: `@amplitude/ai` v0.1.1
13
13
  - Need zero-code coverage: use `patch()`.
14
14
  - Already have a provider client: use `wrap()` or provider wrappers.
15
15
  - Need user/session lineage: use `ai.agent(...).session(...)`.
16
+ - Multiple agents collaborating: use `session.runAs(childAgent, fn)` for automatic identity propagation.
16
17
  - Need tool telemetry: use `tool()`.
17
18
  - Need agent-assistant guidance: run MCP prompt `instrument_app`.
18
19
 
@@ -21,6 +22,7 @@ Package: `@amplitude/ai` v0.1.1
21
22
  - zero-code patching
22
23
  - wrap-openai
23
24
  - bound-agent-session
25
+ - multi-agent-runas
24
26
  - tool-decorator
25
27
  - express-middleware
26
28
 
package/README.md CHANGED
@@ -715,6 +715,15 @@ s.trackAiMessage(response.content, 'gpt-4o', 'openai', latencyMs, {
715
715
  });
716
716
  ```
717
717
 
718
+ > **Note — pricing data freshness.** Cost calculation relies on pricing data bundled in the installed `@pydantic/genai-prices` package. Newly released models may return `$0` until the package is updated. To get the latest pricing between package releases, opt in to live updates at startup:
719
+ >
720
+ > ```typescript
721
+ > import { enableLivePriceUpdates } from '@amplitude/ai';
722
+ > enableLivePriceUpdates(); // fetches latest prices from genai-prices GitHub repo hourly
723
+ > ```
724
+ >
725
+ > This makes periodic HTTPS requests to `raw.githubusercontent.com` (~26 KB each). Only enable in environments where outbound network access is permitted.
726
+
718
727
  ## Semantic Cache Tracking
719
728
 
720
729
  Track full-response semantic cache hits (distinct from token-level prompt caching above):
@@ -1693,45 +1702,65 @@ await session.run(async (s) => {
1693
1702
 
1694
1703
  ### Pattern C: Multi-Agent Orchestration
1695
1704
 
1696
- For architectures where a parent agent delegates to specialized child agents. Each child inherits context from the parent:
1705
+ For architectures where a parent agent delegates to specialized child agents. Use `session.runAs()` to automatically propagate the child agent's identity to **both** manual tracking calls and provider wrappers:
1697
1706
 
1698
1707
  ```typescript
1699
1708
  const ai = new AmplitudeAI({ apiKey: process.env.AMPLITUDE_AI_API_KEY! });
1709
+ const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY!, amplitude: ai });
1710
+
1700
1711
  const orchestrator = ai.agent('orchestrator', {
1701
1712
  userId: 'user-123',
1702
1713
  env: 'production',
1703
1714
  });
1704
-
1705
1715
  const researcher = orchestrator.child('researcher');
1706
1716
  const writer = orchestrator.child('writer');
1707
- const reviewer = orchestrator.child('reviewer');
1708
1717
 
1709
1718
  const session = orchestrator.session({ userId: 'user-123' });
1710
1719
 
1711
1720
  await session.run(async (s) => {
1712
1721
  s.trackUserMessage('Write a blog post about TypeScript generics');
1713
1722
 
1714
- // Research phase
1715
- const researchResult = await doResearch(researcher, s);
1716
-
1717
- // Writing phase
1718
- const draft = await writeDraft(writer, s, researchResult);
1723
+ // Research phase — provider calls automatically tagged with agentId='researcher'
1724
+ const researchResult = await s.runAs(researcher, async (rs) => {
1725
+ const completion = await openai.chat.completions.create({
1726
+ model: 'gpt-4o',
1727
+ messages: [{ role: 'user', content: 'Research TypeScript generics' }],
1728
+ });
1729
+ return completion.choices[0].message.content;
1730
+ });
1719
1731
 
1720
- // Review phase
1721
- const finalPost = await reviewDraft(reviewer, s, draft);
1732
+ // Writing phase — provider calls automatically tagged with agentId='writer'
1733
+ const draft = await s.runAs(writer, async (ws) => {
1734
+ const completion = await openai.chat.completions.create({
1735
+ model: 'gpt-4o',
1736
+ messages: [{ role: 'user', content: `Write a post using: ${researchResult}` }],
1737
+ });
1738
+ return completion.choices[0].message.content;
1739
+ });
1722
1740
 
1723
- s.trackAiMessage(finalPost, 'gpt-4o', 'openai', totalLatencyMs, {
1741
+ s.trackAiMessage(draft ?? '', 'gpt-4o', 'openai', totalLatencyMs, {
1724
1742
  inputTokens: totalInput,
1725
1743
  outputTokens: totalOutput,
1726
1744
  });
1727
1745
  });
1728
1746
 
1729
- // Each child agent's events include:
1730
- // [Agent] Agent ID = "researcher" | "writer" | "reviewer"
1731
- // [Agent] Parent Agent ID = "orchestrator"
1732
- // [Agent] Agent Chain (on enrichments) = ["orchestrator", "researcher", "writer", "reviewer"]
1747
+ // Events emitted:
1748
+ // [Agent] User Message → agentId='orchestrator'
1749
+ // [Agent] AI Response → agentId='researcher', parentAgentId='orchestrator'
1750
+ // [Agent] AI Response → agentId='writer', parentAgentId='orchestrator'
1751
+ // [Agent] AI Response → agentId='orchestrator'
1752
+ // [Agent] Session End → agentId='orchestrator' (one session end, not per-child)
1733
1753
  ```
1734
1754
 
1755
+ **How `runAs` works:**
1756
+
1757
+ - Shares the parent session's `sessionId`, `traceId`, and turn counter
1758
+ - Overrides `agentId` and `parentAgentId` in `AsyncLocalStorage` for the callback's duration
1759
+ - Provider wrappers automatically read the child's identity — no `amplitudeOverrides` needed
1760
+ - Does **not** emit `[Agent] Session End` (the child operates within the parent session)
1761
+ - Restores the parent context when the callback completes, even on errors
1762
+ - Supports nesting: `s.runAs(child, (cs) => cs.runAs(grandchild, ...))`
1763
+
1735
1764
  ## Serverless Environments
1736
1765
 
1737
1766
  **Critical**: Always `await ai.flush()` before your handler returns. Without this, events buffered in memory are lost when the runtime freezes or terminates:
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","names":[],"sources":["../src/client.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;AA+CA;;;;;;;;;;;;;;;;AAsMkB,cAtML,WAAA,CAsMK;EACL,UAAA,UAAA,EAtMW,mBAsMX;EAQC,UAAA,WAAA,EAAA,OAAA;EAKQ,UAAA,OAAA,EAjND,QAiNC;EACT,UAAA,cAAA,EAjNe,aAiNf;EACO,UAAA,oBAAA,EAjNc,GAiNd,CAAA,MAAA,EAAA,MAAA,CAAA;EA2FN,WAAA,CAAA,OAAA,EAAA;IAGQ,SAAA,CAAA,EA5SN,mBA4SM;IACT,MAAA,CAAA,EAAA,MAAA;IA2CC,MAAA,CAAA,EAtVD,QAsVC;EAEQ,CAAA;EACT,QAAA,iBAAA;EA+BI,IAAA,SAAA,CAAA,CAAA,EAhSE,mBAgSF;EACC,IAAA,MAAA,CAAA,CAAA,EA7RF,QA6RE;EAUJ,WAAA,CAAA,SAAA,EAAA,MAAA,CAAA,EAAA,MAAA;EAEQ,gBAAA,CAAA,IAAA,EAAA;IACT,MAAA,EAAA,MAAA;IAkCK,OAAA,EAAA,MAAA;IAOJ,SAAA,EAAA,MAAA;IAIQ,OAAA,CAAA,EAAA,MAAA,GAAA,IAAA;IACT,MAAA,CAAA,EAAA,MAAA,GAAA,IAAA;IA2BI,SAAA,CAAA,EAAA,MAAA,GAAA,IAAA;IAOH,OAAA,CAAA,EAAA,MAAA,GAAA,IAAA;IAEQ,aAAA,CAAA,EAAA,MAAA,GAAA,IAAA;IACT,aAAA,CAAA,EAAA,MAAA,GAAA,IAAA;IAwCC,YAAA,CAAA,EAAA,MAAA,GAAA,IAAA;IAEQ,OAAA,CAAA,EArYR,MAqYQ,CAAA,MAAA,EAAA,OAAA,CAAA,GAAA,IAAA;IACT,GAAA,CAAA,EAAA,MAAA,GAAA,IAAA;IAqCG,cAAA,CAAA,EAAA,OAAA;IAID,MAAA,CAAA,EAAA,OAAA;IAIV,eAAA,CAAA,EAAA,MAAA,GAAA,IAAA;IAUgB,WAAA,CAAA,EAxbH,UAwbG,EAAA,GAAA,IAAA;IAChB,MAAA,CAAA,EAxbQ,YAwbR,EAAA,GAAA,IAAA;IAQO,eAAA,CAAA,EA/bU,MA+bV,CAAA,MAAA,EAAA,OAAA,CAAA,GAAA,IAAA;IAAM,MAAA,CAAA,EA9bL,MA8bK,CAAA,MAAA,EAAA,OAAA,CAAA,GAAA,IAAA;;;;;;;;;;;;;;;;;gBAnZF,MAAM;;;;;;;;;;;kBAWJ;aACL;;;;;;;;cAQC;;;;;sBAKQ;aACT;oBACO;;;;;;;;;;;;;;;;;;cA2FN;;;sBAGQ;aACT;;;;;;;;;;;;;;;;;cA2CC;;sBAEQ;aACT;;;;;;;iBA+BI;kBACC;;;;;;;;;;cAUJ;;sBAEQ;aACT;;;;;kBAkCK;;;;;;;cAOJ;;;;sBAIQ;aACT;;;;;iBA2BI;;;;;;;cAOH;;sBAEQ;aACT;;;;;;;;;;;;;;;;;cAwCC;;sBAEQ;aACT;;;;;;;cAqCG;;;;aAID;;;MAIV;;aAUgB;;MAChB;YAQO"}
1
+ {"version":3,"file":"client.d.ts","names":[],"sources":["../src/client.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;AA+CA;;;;;;;;;;;;;;;;AAsMkB,cAtML,WAAA,CAsMK;EACL,UAAA,UAAA,EAtMW,mBAsMX;EAQC,UAAA,WAAA,EAAA,OAAA;EAKQ,UAAA,OAAA,EAjND,QAiNC;EACT,UAAA,cAAA,EAjNe,aAiNf;EACO,UAAA,oBAAA,EAjNc,GAiNd,CAAA,MAAA,EAAA,MAAA,CAAA;EA4FN,WAAA,CAAA,OAAA,EAAA;IAGQ,SAAA,CAAA,EA7SN,mBA6SM;IACT,MAAA,CAAA,EAAA,MAAA;IA2CC,MAAA,CAAA,EAvVD,QAuVC;EAEQ,CAAA;EACT,QAAA,iBAAA;EA+BI,IAAA,SAAA,CAAA,CAAA,EAjSE,mBAiSF;EACC,IAAA,MAAA,CAAA,CAAA,EA9RF,QA8RE;EAUJ,WAAA,CAAA,SAAA,EAAA,MAAA,CAAA,EAAA,MAAA;EAEQ,gBAAA,CAAA,IAAA,EAAA;IACT,MAAA,EAAA,MAAA;IAkCK,OAAA,EAAA,MAAA;IAOJ,SAAA,EAAA,MAAA;IAIQ,OAAA,CAAA,EAAA,MAAA,GAAA,IAAA;IACT,MAAA,CAAA,EAAA,MAAA,GAAA,IAAA;IA2BI,SAAA,CAAA,EAAA,MAAA,GAAA,IAAA;IAOH,OAAA,CAAA,EAAA,MAAA,GAAA,IAAA;IAEQ,aAAA,CAAA,EAAA,MAAA,GAAA,IAAA;IACT,aAAA,CAAA,EAAA,MAAA,GAAA,IAAA;IAwCC,YAAA,CAAA,EAAA,MAAA,GAAA,IAAA;IAEQ,OAAA,CAAA,EAtYR,MAsYQ,CAAA,MAAA,EAAA,OAAA,CAAA,GAAA,IAAA;IACT,GAAA,CAAA,EAAA,MAAA,GAAA,IAAA;IAqCG,cAAA,CAAA,EAAA,OAAA;IAID,MAAA,CAAA,EAAA,OAAA;IAIV,eAAA,CAAA,EAAA,MAAA,GAAA,IAAA;IAUgB,WAAA,CAAA,EAzbH,UAybG,EAAA,GAAA,IAAA;IAChB,MAAA,CAAA,EAzbQ,YAybR,EAAA,GAAA,IAAA;IAQO,eAAA,CAAA,EAhcU,MAgcV,CAAA,MAAA,EAAA,OAAA,CAAA,GAAA,IAAA;IAAM,MAAA,CAAA,EA/bL,MA+bK,CAAA,MAAA,EAAA,OAAA,CAAA,GAAA,IAAA;;;;;;;;;;;;;;;;;gBApZF,MAAM;;;;;;;;;;;kBAWJ;aACL;;;;;;;;cAQC;;;;;sBAKQ;aACT;oBACO;;;;;;;;;;;;;;;;;;cA4FN;;;sBAGQ;aACT;;;;;;;;;;;;;;;;;cA2CC;;sBAEQ;aACT;;;;;;;iBA+BI;kBACC;;;;;;;;;;cAUJ;;sBAEQ;aACT;;;;;kBAkCK;;;;;;;cAOJ;;;;sBAIQ;aACT;;;;;iBA2BI;;;;;;;cAOH;;sBAEQ;aACT;;;;;;;;;;;;;;;;;cAwCC;;sBAEQ;aACT;;;;;;;cAqCG;;;;aAID;;;MAIV;;aAUgB;;MAChB;YAQO"}
package/dist/client.js CHANGED
@@ -133,7 +133,8 @@ var AmplitudeAI = class {
133
133
  outputTokens: opts.outputTokens,
134
134
  reasoningTokens: opts.reasoningTokens ?? 0,
135
135
  cacheReadInputTokens: opts.cacheReadTokens ?? 0,
136
- cacheCreationInputTokens: opts.cacheCreationTokens ?? 0
136
+ cacheCreationInputTokens: opts.cacheCreationTokens ?? 0,
137
+ defaultProvider: opts.provider || void 0
137
138
  });
138
139
  } catch {}
139
140
  return trackAiMessage({
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","names":["availableProviders: string[]"],"sources":["../src/client.ts"],"sourcesContent":["import { BoundAgent } from './bound-agent.js';\nimport { AIConfig } from './config.js';\nimport type { MessageLabel, SessionEnrichments } from './core/enrichments.js';\nimport type { PrivacyConfig } from './core/privacy.js';\nimport {\n trackAiMessage,\n trackEmbedding,\n trackScore,\n trackSessionEnd,\n trackSessionEnrichment,\n trackSpan,\n trackToolCall,\n trackUserMessage,\n} from './core/tracking.js';\nimport { ConfigurationError } from './exceptions.js';\nimport { patchedProviders } from './patching.js';\nimport { setDefaultPropagateContext } from './propagation.js';\nimport { TenantHandle } from './tenant.js';\nimport type {\n AmplitudeClientLike,\n AmplitudeEvent,\n Attachment,\n} from './types.js';\nimport { calculateCost } from './utils/costs.js';\nimport { formatDebugLine, formatDryRunLine } from './utils/debug.js';\nimport { tryRequire } from './utils/resolve-module.js';\n\nconst _MAX_SESSION_TURN_COUNTERS = 10_000;\n\n/**\n * Main Amplitude AI client for tracking LLM interactions.\n *\n * Create an instance with an API key or an existing Amplitude client,\n * then use `.agent()` to create bound agents and `.session()` to\n * manage session context.\n *\n * @example\n * ```typescript\n * const ai = new AmplitudeAI({ apiKey: 'YOUR_KEY' });\n * const agent = ai.agent('my-chatbot', { userId: 'user-1' });\n * const session = agent.session();\n * await session.run(async (s) => {\n * s.trackUserMessage('Hello');\n * s.trackAiMessage('Hi there!', 'gpt-4', 'openai', 150);\n * });\n * ```\n */\nexport class AmplitudeAI {\n protected _amplitude: AmplitudeClientLike;\n protected _ownsClient: boolean;\n protected _config: AIConfig;\n protected _privacyConfig: PrivacyConfig;\n protected _sessionTurnCounters: Map<string, number> = new Map();\n\n constructor(options: {\n amplitude?: AmplitudeClientLike;\n apiKey?: string;\n config?: AIConfig;\n }) {\n if (options.amplitude != null) {\n this._amplitude = options.amplitude;\n this._ownsClient = false;\n } else if (options.apiKey != null) {\n const amplitudeNode = tryRequire('@amplitude/analytics-node') as\n | (AmplitudeClientLike & { init?: (apiKey: string) => unknown })\n | null;\n if (amplitudeNode == null || typeof amplitudeNode.init !== 'function') {\n throw new ConfigurationError(\n '@amplitude/analytics-node is required. Install it as a dependency.',\n );\n }\n amplitudeNode.init(options.apiKey);\n this._amplitude = amplitudeNode;\n this._ownsClient = true;\n } else {\n throw new ConfigurationError(\n \"Provide either an existing Amplitude instance via 'amplitude' or an API key via 'apiKey'.\",\n );\n }\n\n this._config = options.config ?? new AIConfig();\n this._privacyConfig = this._config.toPrivacyConfig();\n setDefaultPropagateContext(this._config.propagateContext);\n\n if (\n this._config.debug ||\n this._config.dryRun ||\n this._config.onEventCallback != null\n ) {\n this._installTrackHook();\n }\n }\n\n private _installTrackHook(): void {\n const originalTrack = this._amplitude.track.bind(this._amplitude);\n const debug = this._config.debug;\n const dryRun = this._config.dryRun;\n const onEvent = this._config.onEventCallback;\n const clientWithConfig = this._amplitude as AmplitudeClientLike & {\n configuration?: { callback?: (...args: unknown[]) => void };\n };\n const existingCallback = clientWithConfig.configuration?.callback;\n let callbackHandledByTransport = false;\n\n if (onEvent != null && clientWithConfig.configuration != null) {\n clientWithConfig.configuration.callback = (...args: unknown[]) => {\n const event = args[0];\n const statusCode = typeof args[1] === 'number' ? args[1] : 0;\n const message = args[2] == null ? null : String(args[2]);\n if (typeof existingCallback === 'function') {\n try {\n existingCallback(...args);\n } catch {\n // preserve hook behavior even if customer callback throws\n }\n }\n try {\n onEvent(event, statusCode, message);\n } catch {\n // swallow callback errors to avoid disrupting tracking\n }\n };\n callbackHandledByTransport = true;\n }\n\n this._amplitude.track = (event: AmplitudeEvent) => {\n if (debug) {\n console.error(formatDebugLine(event));\n }\n if (dryRun) {\n console.error(formatDryRunLine(event));\n }\n if (!dryRun) {\n originalTrack(event);\n }\n if (onEvent != null && (!callbackHandledByTransport || dryRun)) {\n try {\n onEvent(event, dryRun ? -1 : 0, dryRun ? 'dry-run' : null);\n } catch {\n // swallow callback errors to avoid disrupting tracking\n }\n }\n };\n }\n\n get amplitude(): AmplitudeClientLike {\n return this._amplitude;\n }\n\n get config(): AIConfig {\n return this._config;\n }\n\n _nextTurnId(sessionId: string): number {\n if (\n !this._sessionTurnCounters.has(sessionId) &&\n this._sessionTurnCounters.size >= _MAX_SESSION_TURN_COUNTERS\n ) {\n const oldestKey = this._sessionTurnCounters.keys().next().value;\n if (oldestKey != null) this._sessionTurnCounters.delete(oldestKey);\n }\n\n const current = this._sessionTurnCounters.get(sessionId) ?? 0;\n const next = current + 1;\n this._sessionTurnCounters.set(sessionId, next);\n return next;\n }\n\n // ---------------------------------------------------------------\n // Message Tracking\n // ---------------------------------------------------------------\n\n trackUserMessage(opts: {\n userId: string;\n content: string;\n sessionId: string;\n traceId?: string | null;\n turnId?: number | null;\n messageId?: string | 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 isRegeneration?: boolean;\n isEdit?: boolean;\n editedMessageId?: string | null;\n attachments?: Attachment[] | null;\n labels?: MessageLabel[] | null;\n eventProperties?: Record<string, unknown> | null;\n groups?: Record<string, unknown> | null;\n }): string {\n const effectiveTurnId = opts.turnId ?? this._nextTurnId(opts.sessionId);\n return trackUserMessage({\n amplitude: this._amplitude,\n userId: opts.userId,\n messageContent: opts.content,\n sessionId: opts.sessionId,\n traceId: opts.traceId,\n turnId: effectiveTurnId,\n messageId: opts.messageId,\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 isRegeneration: opts.isRegeneration,\n isEdit: opts.isEdit,\n editedMessageId: opts.editedMessageId,\n attachments: opts.attachments,\n labels: opts.labels,\n eventProperties: opts.eventProperties,\n groups: opts.groups,\n privacyConfig: this._privacyConfig,\n });\n }\n\n trackAiMessage(opts: {\n userId: string;\n content: string;\n sessionId: string;\n model: string;\n provider: string;\n latencyMs: number;\n inputTokens?: number | null;\n outputTokens?: number | null;\n reasoningTokens?: number | null;\n cacheReadTokens?: number | null;\n cacheCreationTokens?: number | null;\n totalTokens?: number | null;\n totalCostUsd?: number | null;\n finishReason?: string | null;\n toolCalls?: Array<Record<string, unknown>> | null;\n reasoningContent?: string | null;\n systemPrompt?: string | null;\n temperature?: number | null;\n maxOutputTokens?: number | null;\n topP?: number | null;\n isStreaming?: boolean | null;\n promptId?: string | null;\n wasCopied?: boolean;\n wasCached?: boolean;\n modelTier?: string | null;\n attachments?: Attachment[] | null;\n labels?: MessageLabel[] | null;\n traceId?: string | null;\n turnId?: number | null;\n messageId?: string | 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 isError?: boolean;\n errorMessage?: string | null;\n ttfbMs?: number | null;\n eventProperties?: Record<string, unknown> | null;\n groups?: Record<string, unknown> | null;\n privacyConfig?: PrivacyConfig | null;\n }): string {\n const effectiveTurnId = opts.turnId ?? this._nextTurnId(opts.sessionId);\n\n let effectiveCost = opts.totalCostUsd ?? null;\n if (\n effectiveCost == null &&\n opts.inputTokens != null &&\n opts.outputTokens != null\n ) {\n try {\n effectiveCost = calculateCost({\n modelName: opts.model,\n inputTokens: opts.inputTokens,\n outputTokens: opts.outputTokens,\n reasoningTokens: opts.reasoningTokens ?? 0,\n cacheReadInputTokens: opts.cacheReadTokens ?? 0,\n cacheCreationInputTokens: opts.cacheCreationTokens ?? 0,\n });\n } catch {\n // cost calculation is best-effort\n }\n }\n\n return trackAiMessage({\n amplitude: this._amplitude,\n userId: opts.userId,\n modelName: opts.model,\n provider: opts.provider,\n responseContent: opts.content,\n latencyMs: opts.latencyMs,\n sessionId: opts.sessionId,\n traceId: opts.traceId,\n turnId: effectiveTurnId,\n messageId: opts.messageId,\n inputTokens: opts.inputTokens,\n outputTokens: opts.outputTokens,\n reasoningTokens: opts.reasoningTokens,\n cacheReadInputTokens: opts.cacheReadTokens,\n cacheCreationInputTokens: opts.cacheCreationTokens,\n totalTokens: opts.totalTokens,\n totalCostUsd: effectiveCost,\n finishReason: opts.finishReason,\n toolCalls: opts.toolCalls,\n reasoningContent: opts.reasoningContent,\n systemPrompt: opts.systemPrompt,\n temperature: opts.temperature,\n maxOutputTokens: opts.maxOutputTokens,\n topP: opts.topP,\n isStreaming: opts.isStreaming,\n promptId: opts.promptId,\n wasCopied: opts.wasCopied,\n wasCached: opts.wasCached,\n modelTier: opts.modelTier,\n attachments: opts.attachments,\n labels: opts.labels,\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 isError: opts.isError,\n errorMessage: opts.errorMessage,\n providerTtfbMs: opts.ttfbMs,\n eventProperties: opts.eventProperties,\n groups: opts.groups,\n privacyConfig: opts.privacyConfig ?? this._privacyConfig,\n });\n }\n\n // ---------------------------------------------------------------\n // Operation Tracking\n // ---------------------------------------------------------------\n\n trackToolCall(opts: {\n userId: string;\n toolName: string;\n latencyMs: number;\n success: boolean;\n sessionId?: string | null;\n traceId?: string | null;\n turnId?: number | null;\n invocationId?: string | null;\n input?: unknown;\n output?: unknown;\n parentMessageId?: string | 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 errorMessage?: string | null;\n eventProperties?: Record<string, unknown> | null;\n groups?: Record<string, unknown> | null;\n }): string {\n return trackToolCall({\n amplitude: this._amplitude,\n userId: opts.userId,\n toolName: opts.toolName,\n success: opts.success,\n latencyMs: opts.latencyMs,\n sessionId: opts.sessionId,\n traceId: opts.traceId,\n turnId: opts.turnId ?? undefined,\n invocationId: opts.invocationId,\n toolInput: opts.input,\n toolOutput: opts.output,\n parentMessageId: opts.parentMessageId,\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 errorMessage: opts.errorMessage,\n eventProperties: opts.eventProperties,\n groups: opts.groups,\n privacyConfig: this._privacyConfig,\n });\n }\n\n trackEmbedding(opts: {\n userId: string;\n model: string;\n provider: string;\n latencyMs: number;\n inputTokens?: number | null;\n dimensions?: number | null;\n totalCostUsd?: number | 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 eventProperties?: Record<string, unknown> | null;\n groups?: Record<string, unknown> | null;\n }): string {\n return trackEmbedding({\n amplitude: this._amplitude,\n userId: opts.userId,\n model: opts.model,\n provider: opts.provider,\n latencyMs: opts.latencyMs,\n inputTokens: opts.inputTokens,\n dimensions: opts.dimensions,\n totalCostUsd: opts.totalCostUsd,\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 eventProperties: opts.eventProperties,\n groups: opts.groups,\n privacyConfig: this._privacyConfig,\n });\n }\n\n trackSpan(opts: {\n userId: string;\n spanName: string;\n traceId: string;\n latencyMs: number;\n inputState?: Record<string, unknown> | null;\n outputState?: Record<string, unknown> | null;\n parentSpanId?: string | null;\n isError?: boolean;\n errorMessage?: string | null;\n sessionId?: 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 eventProperties?: Record<string, unknown> | null;\n groups?: Record<string, unknown> | null;\n }): string {\n return trackSpan({\n amplitude: this._amplitude,\n userId: opts.userId,\n spanName: opts.spanName,\n traceId: opts.traceId,\n latencyMs: opts.latencyMs,\n inputState: opts.inputState,\n outputState: opts.outputState,\n parentSpanId: opts.parentSpanId,\n isError: opts.isError,\n errorMessage: opts.errorMessage,\n sessionId: opts.sessionId,\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 eventProperties: opts.eventProperties,\n groups: opts.groups,\n privacyConfig: this._privacyConfig,\n });\n }\n\n // ---------------------------------------------------------------\n // Session Management\n // ---------------------------------------------------------------\n\n trackSessionEnd(opts: {\n userId: string;\n sessionId: string;\n enrichments?: SessionEnrichments | 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 abandonmentTurn?: number | null;\n idleTimeoutMinutes?: number | null;\n eventProperties?: Record<string, unknown> | null;\n groups?: Record<string, unknown> | null;\n }): void {\n trackSessionEnd({\n amplitude: this._amplitude,\n userId: opts.userId,\n sessionId: opts.sessionId,\n enrichments: opts.enrichments,\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 abandonmentTurn: opts.abandonmentTurn,\n idleTimeoutMinutes: opts.idleTimeoutMinutes,\n eventProperties: opts.eventProperties,\n groups: opts.groups,\n privacyConfig: this._privacyConfig,\n });\n this._sessionTurnCounters.delete(opts.sessionId);\n }\n\n trackSessionEnrichment(opts: {\n userId: string;\n sessionId: string;\n enrichments: SessionEnrichments;\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 eventProperties?: Record<string, unknown> | null;\n groups?: Record<string, unknown> | null;\n }): void {\n trackSessionEnrichment({\n amplitude: this._amplitude,\n userId: opts.userId,\n sessionId: opts.sessionId,\n enrichments: opts.enrichments,\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 eventProperties: opts.eventProperties,\n groups: opts.groups,\n privacyConfig: this._privacyConfig,\n });\n }\n\n // ---------------------------------------------------------------\n // Scoring\n // ---------------------------------------------------------------\n\n score(opts: {\n userId: string;\n name: string;\n value: number;\n targetId: string;\n targetType?: string;\n source?: string;\n comment?: 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 eventProperties?: Record<string, unknown> | null;\n groups?: Record<string, unknown> | null;\n }): void {\n trackScore({\n amplitude: this._amplitude,\n userId: opts.userId,\n name: opts.name,\n value: opts.value,\n targetId: opts.targetId,\n targetType: opts.targetType,\n source: opts.source,\n comment: opts.comment,\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 eventProperties: opts.eventProperties,\n groups: opts.groups,\n privacyConfig: this._privacyConfig,\n });\n }\n\n // ---------------------------------------------------------------\n // Bound Agent Factory\n // ---------------------------------------------------------------\n\n agent(\n agentId: string,\n opts: {\n userId?: 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 sessionId?: string | null;\n traceId?: string | null;\n groups?: Record<string, unknown> | null;\n deviceId?: string | null;\n browserSessionId?: string | null;\n } = {},\n ): BoundAgent {\n return new BoundAgent(this, { agentId, ...opts });\n }\n\n // ---------------------------------------------------------------\n // Tenant Factory\n // ---------------------------------------------------------------\n\n tenant(\n customerOrgId: string,\n opts: { groups?: Record<string, unknown> | null; env?: string | null } = {},\n ): TenantHandle {\n return new TenantHandle(this, { customerOrgId, ...opts });\n }\n\n // ---------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------\n\n status(): Record<string, unknown> {\n const availableProviders: string[] = [];\n for (const mod of [\n 'openai',\n '@anthropic-ai/sdk',\n '@google/generative-ai',\n '@aws-sdk/client-bedrock-runtime',\n '@mistralai/mistralai',\n ]) {\n if (tryRequire(mod) != null) {\n const name =\n mod === '@anthropic-ai/sdk'\n ? 'anthropic'\n : mod === '@google/generative-ai'\n ? 'gemini'\n : mod === '@aws-sdk/client-bedrock-runtime'\n ? 'bedrock'\n : mod === '@mistralai/mistralai'\n ? 'mistral'\n : mod;\n availableProviders.push(name);\n if (mod === 'openai') {\n availableProviders.push('azure-openai');\n }\n }\n }\n\n return {\n content_mode: this._config.contentMode,\n debug: this._config.debug,\n dry_run: this._config.dryRun,\n redact_pii: this._config.redactPii,\n providers_available: availableProviders,\n patched_providers: patchedProviders(),\n };\n }\n\n flush(): unknown {\n return this._amplitude.flush();\n }\n\n shutdown(): void {\n if (this._ownsClient) {\n this._amplitude.shutdown?.();\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"client.js","names":["availableProviders: string[]"],"sources":["../src/client.ts"],"sourcesContent":["import { BoundAgent } from './bound-agent.js';\nimport { AIConfig } from './config.js';\nimport type { MessageLabel, SessionEnrichments } from './core/enrichments.js';\nimport type { PrivacyConfig } from './core/privacy.js';\nimport {\n trackAiMessage,\n trackEmbedding,\n trackScore,\n trackSessionEnd,\n trackSessionEnrichment,\n trackSpan,\n trackToolCall,\n trackUserMessage,\n} from './core/tracking.js';\nimport { ConfigurationError } from './exceptions.js';\nimport { patchedProviders } from './patching.js';\nimport { setDefaultPropagateContext } from './propagation.js';\nimport { TenantHandle } from './tenant.js';\nimport type {\n AmplitudeClientLike,\n AmplitudeEvent,\n Attachment,\n} from './types.js';\nimport { calculateCost } from './utils/costs.js';\nimport { formatDebugLine, formatDryRunLine } from './utils/debug.js';\nimport { tryRequire } from './utils/resolve-module.js';\n\nconst _MAX_SESSION_TURN_COUNTERS = 10_000;\n\n/**\n * Main Amplitude AI client for tracking LLM interactions.\n *\n * Create an instance with an API key or an existing Amplitude client,\n * then use `.agent()` to create bound agents and `.session()` to\n * manage session context.\n *\n * @example\n * ```typescript\n * const ai = new AmplitudeAI({ apiKey: 'YOUR_KEY' });\n * const agent = ai.agent('my-chatbot', { userId: 'user-1' });\n * const session = agent.session();\n * await session.run(async (s) => {\n * s.trackUserMessage('Hello');\n * s.trackAiMessage('Hi there!', 'gpt-4', 'openai', 150);\n * });\n * ```\n */\nexport class AmplitudeAI {\n protected _amplitude: AmplitudeClientLike;\n protected _ownsClient: boolean;\n protected _config: AIConfig;\n protected _privacyConfig: PrivacyConfig;\n protected _sessionTurnCounters: Map<string, number> = new Map();\n\n constructor(options: {\n amplitude?: AmplitudeClientLike;\n apiKey?: string;\n config?: AIConfig;\n }) {\n if (options.amplitude != null) {\n this._amplitude = options.amplitude;\n this._ownsClient = false;\n } else if (options.apiKey != null) {\n const amplitudeNode = tryRequire('@amplitude/analytics-node') as\n | (AmplitudeClientLike & { init?: (apiKey: string) => unknown })\n | null;\n if (amplitudeNode == null || typeof amplitudeNode.init !== 'function') {\n throw new ConfigurationError(\n '@amplitude/analytics-node is required. Install it as a dependency.',\n );\n }\n amplitudeNode.init(options.apiKey);\n this._amplitude = amplitudeNode;\n this._ownsClient = true;\n } else {\n throw new ConfigurationError(\n \"Provide either an existing Amplitude instance via 'amplitude' or an API key via 'apiKey'.\",\n );\n }\n\n this._config = options.config ?? new AIConfig();\n this._privacyConfig = this._config.toPrivacyConfig();\n setDefaultPropagateContext(this._config.propagateContext);\n\n if (\n this._config.debug ||\n this._config.dryRun ||\n this._config.onEventCallback != null\n ) {\n this._installTrackHook();\n }\n }\n\n private _installTrackHook(): void {\n const originalTrack = this._amplitude.track.bind(this._amplitude);\n const debug = this._config.debug;\n const dryRun = this._config.dryRun;\n const onEvent = this._config.onEventCallback;\n const clientWithConfig = this._amplitude as AmplitudeClientLike & {\n configuration?: { callback?: (...args: unknown[]) => void };\n };\n const existingCallback = clientWithConfig.configuration?.callback;\n let callbackHandledByTransport = false;\n\n if (onEvent != null && clientWithConfig.configuration != null) {\n clientWithConfig.configuration.callback = (...args: unknown[]) => {\n const event = args[0];\n const statusCode = typeof args[1] === 'number' ? args[1] : 0;\n const message = args[2] == null ? null : String(args[2]);\n if (typeof existingCallback === 'function') {\n try {\n existingCallback(...args);\n } catch {\n // preserve hook behavior even if customer callback throws\n }\n }\n try {\n onEvent(event, statusCode, message);\n } catch {\n // swallow callback errors to avoid disrupting tracking\n }\n };\n callbackHandledByTransport = true;\n }\n\n this._amplitude.track = (event: AmplitudeEvent) => {\n if (debug) {\n console.error(formatDebugLine(event));\n }\n if (dryRun) {\n console.error(formatDryRunLine(event));\n }\n if (!dryRun) {\n originalTrack(event);\n }\n if (onEvent != null && (!callbackHandledByTransport || dryRun)) {\n try {\n onEvent(event, dryRun ? -1 : 0, dryRun ? 'dry-run' : null);\n } catch {\n // swallow callback errors to avoid disrupting tracking\n }\n }\n };\n }\n\n get amplitude(): AmplitudeClientLike {\n return this._amplitude;\n }\n\n get config(): AIConfig {\n return this._config;\n }\n\n _nextTurnId(sessionId: string): number {\n if (\n !this._sessionTurnCounters.has(sessionId) &&\n this._sessionTurnCounters.size >= _MAX_SESSION_TURN_COUNTERS\n ) {\n const oldestKey = this._sessionTurnCounters.keys().next().value;\n if (oldestKey != null) this._sessionTurnCounters.delete(oldestKey);\n }\n\n const current = this._sessionTurnCounters.get(sessionId) ?? 0;\n const next = current + 1;\n this._sessionTurnCounters.set(sessionId, next);\n return next;\n }\n\n // ---------------------------------------------------------------\n // Message Tracking\n // ---------------------------------------------------------------\n\n trackUserMessage(opts: {\n userId: string;\n content: string;\n sessionId: string;\n traceId?: string | null;\n turnId?: number | null;\n messageId?: string | 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 isRegeneration?: boolean;\n isEdit?: boolean;\n editedMessageId?: string | null;\n attachments?: Attachment[] | null;\n labels?: MessageLabel[] | null;\n eventProperties?: Record<string, unknown> | null;\n groups?: Record<string, unknown> | null;\n }): string {\n const effectiveTurnId = opts.turnId ?? this._nextTurnId(opts.sessionId);\n return trackUserMessage({\n amplitude: this._amplitude,\n userId: opts.userId,\n messageContent: opts.content,\n sessionId: opts.sessionId,\n traceId: opts.traceId,\n turnId: effectiveTurnId,\n messageId: opts.messageId,\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 isRegeneration: opts.isRegeneration,\n isEdit: opts.isEdit,\n editedMessageId: opts.editedMessageId,\n attachments: opts.attachments,\n labels: opts.labels,\n eventProperties: opts.eventProperties,\n groups: opts.groups,\n privacyConfig: this._privacyConfig,\n });\n }\n\n trackAiMessage(opts: {\n userId: string;\n content: string;\n sessionId: string;\n model: string;\n provider: string;\n latencyMs: number;\n inputTokens?: number | null;\n outputTokens?: number | null;\n reasoningTokens?: number | null;\n cacheReadTokens?: number | null;\n cacheCreationTokens?: number | null;\n totalTokens?: number | null;\n totalCostUsd?: number | null;\n finishReason?: string | null;\n toolCalls?: Array<Record<string, unknown>> | null;\n reasoningContent?: string | null;\n systemPrompt?: string | null;\n temperature?: number | null;\n maxOutputTokens?: number | null;\n topP?: number | null;\n isStreaming?: boolean | null;\n promptId?: string | null;\n wasCopied?: boolean;\n wasCached?: boolean;\n modelTier?: string | null;\n attachments?: Attachment[] | null;\n labels?: MessageLabel[] | null;\n traceId?: string | null;\n turnId?: number | null;\n messageId?: string | 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 isError?: boolean;\n errorMessage?: string | null;\n ttfbMs?: number | null;\n eventProperties?: Record<string, unknown> | null;\n groups?: Record<string, unknown> | null;\n privacyConfig?: PrivacyConfig | null;\n }): string {\n const effectiveTurnId = opts.turnId ?? this._nextTurnId(opts.sessionId);\n\n let effectiveCost = opts.totalCostUsd ?? null;\n if (\n effectiveCost == null &&\n opts.inputTokens != null &&\n opts.outputTokens != null\n ) {\n try {\n effectiveCost = calculateCost({\n modelName: opts.model,\n inputTokens: opts.inputTokens,\n outputTokens: opts.outputTokens,\n reasoningTokens: opts.reasoningTokens ?? 0,\n cacheReadInputTokens: opts.cacheReadTokens ?? 0,\n cacheCreationInputTokens: opts.cacheCreationTokens ?? 0,\n defaultProvider: opts.provider || undefined,\n });\n } catch {\n // cost calculation is best-effort\n }\n }\n\n return trackAiMessage({\n amplitude: this._amplitude,\n userId: opts.userId,\n modelName: opts.model,\n provider: opts.provider,\n responseContent: opts.content,\n latencyMs: opts.latencyMs,\n sessionId: opts.sessionId,\n traceId: opts.traceId,\n turnId: effectiveTurnId,\n messageId: opts.messageId,\n inputTokens: opts.inputTokens,\n outputTokens: opts.outputTokens,\n reasoningTokens: opts.reasoningTokens,\n cacheReadInputTokens: opts.cacheReadTokens,\n cacheCreationInputTokens: opts.cacheCreationTokens,\n totalTokens: opts.totalTokens,\n totalCostUsd: effectiveCost,\n finishReason: opts.finishReason,\n toolCalls: opts.toolCalls,\n reasoningContent: opts.reasoningContent,\n systemPrompt: opts.systemPrompt,\n temperature: opts.temperature,\n maxOutputTokens: opts.maxOutputTokens,\n topP: opts.topP,\n isStreaming: opts.isStreaming,\n promptId: opts.promptId,\n wasCopied: opts.wasCopied,\n wasCached: opts.wasCached,\n modelTier: opts.modelTier,\n attachments: opts.attachments,\n labels: opts.labels,\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 isError: opts.isError,\n errorMessage: opts.errorMessage,\n providerTtfbMs: opts.ttfbMs,\n eventProperties: opts.eventProperties,\n groups: opts.groups,\n privacyConfig: opts.privacyConfig ?? this._privacyConfig,\n });\n }\n\n // ---------------------------------------------------------------\n // Operation Tracking\n // ---------------------------------------------------------------\n\n trackToolCall(opts: {\n userId: string;\n toolName: string;\n latencyMs: number;\n success: boolean;\n sessionId?: string | null;\n traceId?: string | null;\n turnId?: number | null;\n invocationId?: string | null;\n input?: unknown;\n output?: unknown;\n parentMessageId?: string | 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 errorMessage?: string | null;\n eventProperties?: Record<string, unknown> | null;\n groups?: Record<string, unknown> | null;\n }): string {\n return trackToolCall({\n amplitude: this._amplitude,\n userId: opts.userId,\n toolName: opts.toolName,\n success: opts.success,\n latencyMs: opts.latencyMs,\n sessionId: opts.sessionId,\n traceId: opts.traceId,\n turnId: opts.turnId ?? undefined,\n invocationId: opts.invocationId,\n toolInput: opts.input,\n toolOutput: opts.output,\n parentMessageId: opts.parentMessageId,\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 errorMessage: opts.errorMessage,\n eventProperties: opts.eventProperties,\n groups: opts.groups,\n privacyConfig: this._privacyConfig,\n });\n }\n\n trackEmbedding(opts: {\n userId: string;\n model: string;\n provider: string;\n latencyMs: number;\n inputTokens?: number | null;\n dimensions?: number | null;\n totalCostUsd?: number | 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 eventProperties?: Record<string, unknown> | null;\n groups?: Record<string, unknown> | null;\n }): string {\n return trackEmbedding({\n amplitude: this._amplitude,\n userId: opts.userId,\n model: opts.model,\n provider: opts.provider,\n latencyMs: opts.latencyMs,\n inputTokens: opts.inputTokens,\n dimensions: opts.dimensions,\n totalCostUsd: opts.totalCostUsd,\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 eventProperties: opts.eventProperties,\n groups: opts.groups,\n privacyConfig: this._privacyConfig,\n });\n }\n\n trackSpan(opts: {\n userId: string;\n spanName: string;\n traceId: string;\n latencyMs: number;\n inputState?: Record<string, unknown> | null;\n outputState?: Record<string, unknown> | null;\n parentSpanId?: string | null;\n isError?: boolean;\n errorMessage?: string | null;\n sessionId?: 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 eventProperties?: Record<string, unknown> | null;\n groups?: Record<string, unknown> | null;\n }): string {\n return trackSpan({\n amplitude: this._amplitude,\n userId: opts.userId,\n spanName: opts.spanName,\n traceId: opts.traceId,\n latencyMs: opts.latencyMs,\n inputState: opts.inputState,\n outputState: opts.outputState,\n parentSpanId: opts.parentSpanId,\n isError: opts.isError,\n errorMessage: opts.errorMessage,\n sessionId: opts.sessionId,\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 eventProperties: opts.eventProperties,\n groups: opts.groups,\n privacyConfig: this._privacyConfig,\n });\n }\n\n // ---------------------------------------------------------------\n // Session Management\n // ---------------------------------------------------------------\n\n trackSessionEnd(opts: {\n userId: string;\n sessionId: string;\n enrichments?: SessionEnrichments | 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 abandonmentTurn?: number | null;\n idleTimeoutMinutes?: number | null;\n eventProperties?: Record<string, unknown> | null;\n groups?: Record<string, unknown> | null;\n }): void {\n trackSessionEnd({\n amplitude: this._amplitude,\n userId: opts.userId,\n sessionId: opts.sessionId,\n enrichments: opts.enrichments,\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 abandonmentTurn: opts.abandonmentTurn,\n idleTimeoutMinutes: opts.idleTimeoutMinutes,\n eventProperties: opts.eventProperties,\n groups: opts.groups,\n privacyConfig: this._privacyConfig,\n });\n this._sessionTurnCounters.delete(opts.sessionId);\n }\n\n trackSessionEnrichment(opts: {\n userId: string;\n sessionId: string;\n enrichments: SessionEnrichments;\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 eventProperties?: Record<string, unknown> | null;\n groups?: Record<string, unknown> | null;\n }): void {\n trackSessionEnrichment({\n amplitude: this._amplitude,\n userId: opts.userId,\n sessionId: opts.sessionId,\n enrichments: opts.enrichments,\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 eventProperties: opts.eventProperties,\n groups: opts.groups,\n privacyConfig: this._privacyConfig,\n });\n }\n\n // ---------------------------------------------------------------\n // Scoring\n // ---------------------------------------------------------------\n\n score(opts: {\n userId: string;\n name: string;\n value: number;\n targetId: string;\n targetType?: string;\n source?: string;\n comment?: 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 eventProperties?: Record<string, unknown> | null;\n groups?: Record<string, unknown> | null;\n }): void {\n trackScore({\n amplitude: this._amplitude,\n userId: opts.userId,\n name: opts.name,\n value: opts.value,\n targetId: opts.targetId,\n targetType: opts.targetType,\n source: opts.source,\n comment: opts.comment,\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 eventProperties: opts.eventProperties,\n groups: opts.groups,\n privacyConfig: this._privacyConfig,\n });\n }\n\n // ---------------------------------------------------------------\n // Bound Agent Factory\n // ---------------------------------------------------------------\n\n agent(\n agentId: string,\n opts: {\n userId?: 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 sessionId?: string | null;\n traceId?: string | null;\n groups?: Record<string, unknown> | null;\n deviceId?: string | null;\n browserSessionId?: string | null;\n } = {},\n ): BoundAgent {\n return new BoundAgent(this, { agentId, ...opts });\n }\n\n // ---------------------------------------------------------------\n // Tenant Factory\n // ---------------------------------------------------------------\n\n tenant(\n customerOrgId: string,\n opts: { groups?: Record<string, unknown> | null; env?: string | null } = {},\n ): TenantHandle {\n return new TenantHandle(this, { customerOrgId, ...opts });\n }\n\n // ---------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------\n\n status(): Record<string, unknown> {\n const availableProviders: string[] = [];\n for (const mod of [\n 'openai',\n '@anthropic-ai/sdk',\n '@google/generative-ai',\n '@aws-sdk/client-bedrock-runtime',\n '@mistralai/mistralai',\n ]) {\n if (tryRequire(mod) != null) {\n const name =\n mod === '@anthropic-ai/sdk'\n ? 'anthropic'\n : mod === '@google/generative-ai'\n ? 'gemini'\n : mod === '@aws-sdk/client-bedrock-runtime'\n ? 'bedrock'\n : mod === '@mistralai/mistralai'\n ? 'mistral'\n : mod;\n availableProviders.push(name);\n if (mod === 'openai') {\n availableProviders.push('azure-openai');\n }\n }\n }\n\n return {\n content_mode: this._config.contentMode,\n debug: this._config.debug,\n dry_run: this._config.dryRun,\n redact_pii: this._config.redactPii,\n providers_available: availableProviders,\n patched_providers: patchedProviders(),\n };\n }\n\n flush(): unknown {\n return this._amplitude.flush();\n }\n\n shutdown(): void {\n if (this._ownsClient) {\n this._amplitude.shutdown?.();\n }\n }\n}\n"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -31,7 +31,7 @@ import { AmplitudeTracingProcessor } from "./integrations/openai-agents.js";
31
31
  import { AmplitudeToolLoop } from "./integrations/anthropic-tools.js";
32
32
  import { AmplitudeCrewAIHooks } from "./integrations/crewai.js";
33
33
  import { inferProviderFromModel } from "./utils/providers.js";
34
- import { calculateCost, getGenaiPriceLookupCandidates, inferProvider, stripProviderPrefix } from "./utils/costs.js";
34
+ import { calculateCost, enableLivePriceUpdates, getGenaiPriceLookupCandidates, inferProvider, stripProviderPrefix } from "./utils/costs.js";
35
35
  import { countMessageTokens, countTokens, estimateTokens } from "./utils/tokens.js";
36
36
  import { TIER_FAST, TIER_REASONING, TIER_STANDARD, inferModelTier } from "./utils/model-tiers.js";
37
- export { AIConfig, type AIConfigOptions, ANTHROPIC_AVAILABLE, OPENAI_AVAILABLE as AZURE_OPENAI_AVAILABLE, type AiMessageOpts, AmplitudeAI, AmplitudeAIError, type AmplitudeAILike, AmplitudeAIWrapError, AmplitudeAgentExporter, AmplitudeCallbackHandler, type AmplitudeClientLike, AmplitudeCrewAIHooks, type AmplitudeEvent, AmplitudeGenAIExporter, type AmplitudeLike, AmplitudeLlamaIndexHandler, type AmplitudeOrAI, AmplitudeSpanExporter, AmplitudeToolLoop, AmplitudeTracingProcessor, Anthropic, type AnthropicParams, type AnthropicResponse, type Attachment, AzureOpenAI, BEDROCK_AVAILABLE, Bedrock, type BedrockConverseParams, type BedrockConverseResponse, BoundAgent, type ChatCompletionParams, type ChatCompletionResponse, type ChatMessage, ConfigurationError, type ContentBlock, ContentMode, EVENT_AI_RESPONSE, EVENT_EMBEDDING, EVENT_SCORE, EVENT_SESSION_END, EVENT_SESSION_ENRICHMENT, EVENT_SPAN, EVENT_TOOL_CALL, EVENT_USER_MESSAGE, type EmbeddingOpts, EvidenceQuote, GEMINI_AVAILABLE, GENERATED_FILES, Gemini, MAX_SERIALIZED_LENGTH, MCP_PROMPTS, MCP_RESOURCES, MCP_SERVER_NAME, MCP_TOOLS, MISTRAL_AVAILABLE, MessageLabel, type MiddlewareOptions, Mistral, type MistralChatParams, type MistralChatResponse, MockAmplitudeAI, OPENAI_AVAILABLE, type ObserveWrapped, OpenAI, PROP_ABANDONMENT_TURN, PROP_AGENT_CHAIN, PROP_AGENT_ID, PROP_AGENT_VERSION, PROP_ATTACHMENTS, PROP_ATTACHMENT_COUNT, PROP_ATTACHMENT_TYPES, PROP_CACHE_CREATION_TOKENS, PROP_CACHE_READ_TOKENS, PROP_COMMENT, PROP_COMPONENT_TYPE, PROP_CONTEXT, PROP_COST_USD, PROP_CUSTOMER_ORG_ID, PROP_EDITED_MESSAGE_ID, PROP_EMBEDDING_DIMENSIONS, PROP_ENRICHMENTS, PROP_ENV, PROP_ERROR_MESSAGE, PROP_EVALUATION_SOURCE, PROP_FINISH_REASON, PROP_HAS_ATTACHMENTS, PROP_HAS_REASONING, PROP_IDLE_TIMEOUT_MINUTES, PROP_INPUT_STATE, PROP_INPUT_TOKENS, PROP_INVOCATION_ID, PROP_IS_EDIT, PROP_IS_ERROR, PROP_IS_REGENERATION, PROP_IS_STREAMING, PROP_LATENCY_MS, PROP_LOCALE, PROP_MAX_OUTPUT_TOKENS, PROP_MESSAGE_ID, PROP_MESSAGE_LABELS, PROP_MESSAGE_LABEL_MAP, PROP_MODEL_NAME, PROP_MODEL_TIER, PROP_OUTPUT_STATE, PROP_OUTPUT_TOKENS, PROP_PARENT_AGENT_ID, PROP_PARENT_MESSAGE_ID, PROP_PARENT_SPAN_ID, PROP_PROMPT_ID, PROP_PROVIDER, PROP_QUALITY_SCORE, PROP_REASONING_CONTENT, PROP_REASONING_TOKENS, PROP_REQUEST_COMPLEXITY, PROP_ROOT_AGENT_NAME, PROP_RUNTIME, PROP_SCORE_NAME, PROP_SCORE_VALUE, PROP_SDK_VERSION, PROP_SENTIMENT_SCORE, PROP_SESSION_ID, PROP_SESSION_REPLAY_ID, PROP_SPAN_ID, PROP_SPAN_KIND, PROP_SPAN_NAME, PROP_SYSTEM_PROMPT, PROP_SYSTEM_PROMPT_LENGTH, PROP_TARGET_ID, PROP_TARGET_TYPE, PROP_TASK_FAILURE_REASON, PROP_TASK_FAILURE_TYPE, PROP_TEMPERATURE, PROP_TOOL_CALLS, PROP_TOOL_INPUT, PROP_TOOL_NAME, PROP_TOOL_OUTPUT, PROP_TOOL_SUCCESS, PROP_TOP_P, PROP_TOTAL_ATTACHMENT_SIZE, PROP_TOTAL_TOKENS, PROP_TRACE_ID, PROP_TTFB_MS, PROP_TURN_ID, PROP_WAS_CACHED, PROP_WAS_COPIED, PrivacyConfig, ProviderError, RubricScore, SDK_RUNTIME, SDK_VERSION, type ScoreOpts, Session, SessionContext, type SessionEndOpts, type SessionEnrichmentOpts, SessionEnrichments, type SpanOpts, StreamingAccumulator, TIER_FAST, TIER_REASONING, TIER_STANDARD, TenantHandle, type ToolCallOpts, type ToolCallShape, ToolCallTracker, type ToolWrapped, TopicClassification, type TrackCallOptions, type TrackFn, TrackingError, type UserMessageOpts, ValidationError, WrappedResponses, calculateCost, countMessageTokens, countTokens, createAmplitudeAIMiddleware, createAmplitudeCallback, createAmplitudeLlamaIndexHandler, estimateTokens, extractAnthropicContent, extractAnthropicSystemPrompt, extractBedrockResponse, extractContext, extractGeminiResponse, extractSystemPrompt, getActiveContext, getGenaiPriceLookupCandidates, inferModelTier, inferProvider, inferProviderFromModel, injectContext, observe, patch, patchAnthropic, patchAzureOpenAI, patchBedrock, patchGemini, patchMistral, patchOpenAI, patchedProviders, resolveAmplitude, runWithContext, runWithContextAsync, serializeToJsonString, stripProviderPrefix, tool, trackAiMessage, trackConversation, trackEmbedding, trackScore, trackSessionEnd, trackSessionEnrichment, trackSpan, trackToolCall, trackUserMessage, unpatch, unpatchAnthropic, unpatchAzureOpenAI, unpatchBedrock, unpatchGemini, unpatchMistral, unpatchOpenAI, wrap };
37
+ export { AIConfig, type AIConfigOptions, ANTHROPIC_AVAILABLE, OPENAI_AVAILABLE as AZURE_OPENAI_AVAILABLE, type AiMessageOpts, AmplitudeAI, AmplitudeAIError, type AmplitudeAILike, AmplitudeAIWrapError, AmplitudeAgentExporter, AmplitudeCallbackHandler, type AmplitudeClientLike, AmplitudeCrewAIHooks, type AmplitudeEvent, AmplitudeGenAIExporter, type AmplitudeLike, AmplitudeLlamaIndexHandler, type AmplitudeOrAI, AmplitudeSpanExporter, AmplitudeToolLoop, AmplitudeTracingProcessor, Anthropic, type AnthropicParams, type AnthropicResponse, type Attachment, AzureOpenAI, BEDROCK_AVAILABLE, Bedrock, type BedrockConverseParams, type BedrockConverseResponse, BoundAgent, type ChatCompletionParams, type ChatCompletionResponse, type ChatMessage, ConfigurationError, type ContentBlock, ContentMode, EVENT_AI_RESPONSE, EVENT_EMBEDDING, EVENT_SCORE, EVENT_SESSION_END, EVENT_SESSION_ENRICHMENT, EVENT_SPAN, EVENT_TOOL_CALL, EVENT_USER_MESSAGE, type EmbeddingOpts, EvidenceQuote, GEMINI_AVAILABLE, GENERATED_FILES, Gemini, MAX_SERIALIZED_LENGTH, MCP_PROMPTS, MCP_RESOURCES, MCP_SERVER_NAME, MCP_TOOLS, MISTRAL_AVAILABLE, MessageLabel, type MiddlewareOptions, Mistral, type MistralChatParams, type MistralChatResponse, MockAmplitudeAI, OPENAI_AVAILABLE, type ObserveWrapped, OpenAI, PROP_ABANDONMENT_TURN, PROP_AGENT_CHAIN, PROP_AGENT_ID, PROP_AGENT_VERSION, PROP_ATTACHMENTS, PROP_ATTACHMENT_COUNT, PROP_ATTACHMENT_TYPES, PROP_CACHE_CREATION_TOKENS, PROP_CACHE_READ_TOKENS, PROP_COMMENT, PROP_COMPONENT_TYPE, PROP_CONTEXT, PROP_COST_USD, PROP_CUSTOMER_ORG_ID, PROP_EDITED_MESSAGE_ID, PROP_EMBEDDING_DIMENSIONS, PROP_ENRICHMENTS, PROP_ENV, PROP_ERROR_MESSAGE, PROP_EVALUATION_SOURCE, PROP_FINISH_REASON, PROP_HAS_ATTACHMENTS, PROP_HAS_REASONING, PROP_IDLE_TIMEOUT_MINUTES, PROP_INPUT_STATE, PROP_INPUT_TOKENS, PROP_INVOCATION_ID, PROP_IS_EDIT, PROP_IS_ERROR, PROP_IS_REGENERATION, PROP_IS_STREAMING, PROP_LATENCY_MS, PROP_LOCALE, PROP_MAX_OUTPUT_TOKENS, PROP_MESSAGE_ID, PROP_MESSAGE_LABELS, PROP_MESSAGE_LABEL_MAP, PROP_MODEL_NAME, PROP_MODEL_TIER, PROP_OUTPUT_STATE, PROP_OUTPUT_TOKENS, PROP_PARENT_AGENT_ID, PROP_PARENT_MESSAGE_ID, PROP_PARENT_SPAN_ID, PROP_PROMPT_ID, PROP_PROVIDER, PROP_QUALITY_SCORE, PROP_REASONING_CONTENT, PROP_REASONING_TOKENS, PROP_REQUEST_COMPLEXITY, PROP_ROOT_AGENT_NAME, PROP_RUNTIME, PROP_SCORE_NAME, PROP_SCORE_VALUE, PROP_SDK_VERSION, PROP_SENTIMENT_SCORE, PROP_SESSION_ID, PROP_SESSION_REPLAY_ID, PROP_SPAN_ID, PROP_SPAN_KIND, PROP_SPAN_NAME, PROP_SYSTEM_PROMPT, PROP_SYSTEM_PROMPT_LENGTH, PROP_TARGET_ID, PROP_TARGET_TYPE, PROP_TASK_FAILURE_REASON, PROP_TASK_FAILURE_TYPE, PROP_TEMPERATURE, PROP_TOOL_CALLS, PROP_TOOL_INPUT, PROP_TOOL_NAME, PROP_TOOL_OUTPUT, PROP_TOOL_SUCCESS, PROP_TOP_P, PROP_TOTAL_ATTACHMENT_SIZE, PROP_TOTAL_TOKENS, PROP_TRACE_ID, PROP_TTFB_MS, PROP_TURN_ID, PROP_WAS_CACHED, PROP_WAS_COPIED, PrivacyConfig, ProviderError, RubricScore, SDK_RUNTIME, SDK_VERSION, type ScoreOpts, Session, SessionContext, type SessionEndOpts, type SessionEnrichmentOpts, SessionEnrichments, type SpanOpts, StreamingAccumulator, TIER_FAST, TIER_REASONING, TIER_STANDARD, TenantHandle, type ToolCallOpts, type ToolCallShape, ToolCallTracker, type ToolWrapped, TopicClassification, type TrackCallOptions, type TrackFn, TrackingError, type UserMessageOpts, ValidationError, WrappedResponses, calculateCost, countMessageTokens, countTokens, createAmplitudeAIMiddleware, createAmplitudeCallback, createAmplitudeLlamaIndexHandler, enableLivePriceUpdates, estimateTokens, extractAnthropicContent, extractAnthropicSystemPrompt, extractBedrockResponse, extractContext, extractGeminiResponse, extractSystemPrompt, getActiveContext, getGenaiPriceLookupCandidates, inferModelTier, inferProvider, inferProviderFromModel, injectContext, observe, patch, patchAnthropic, patchAzureOpenAI, patchBedrock, patchGemini, patchMistral, patchOpenAI, patchedProviders, resolveAmplitude, runWithContext, runWithContextAsync, serializeToJsonString, stripProviderPrefix, tool, trackAiMessage, trackConversation, trackEmbedding, trackScore, trackSessionEnd, trackSessionEnrichment, trackSpan, trackToolCall, trackUserMessage, unpatch, unpatchAnthropic, unpatchAzureOpenAI, unpatchBedrock, unpatchGemini, unpatchMistral, unpatchOpenAI, wrap };
package/dist/index.js CHANGED
@@ -9,7 +9,7 @@ import { BoundAgent } from "./bound-agent.js";
9
9
  import { AIConfig, ContentMode } from "./config.js";
10
10
  import { extractContext, injectContext } from "./propagation.js";
11
11
  import { inferProviderFromModel } from "./utils/providers.js";
12
- import { calculateCost, getGenaiPriceLookupCandidates, inferProvider, stripProviderPrefix } from "./utils/costs.js";
12
+ import { calculateCost, enableLivePriceUpdates, getGenaiPriceLookupCandidates, inferProvider, stripProviderPrefix } from "./utils/costs.js";
13
13
  import { StreamingAccumulator } from "./utils/streaming.js";
14
14
  import { resolveAmplitude } from "./types.js";
15
15
  import { ANTHROPIC_AVAILABLE, Anthropic, extractAnthropicContent, extractAnthropicSystemPrompt } from "./providers/anthropic.js";
@@ -35,4 +35,4 @@ import { AmplitudeToolLoop } from "./integrations/anthropic-tools.js";
35
35
  import { AmplitudeCrewAIHooks } from "./integrations/crewai.js";
36
36
  import { countMessageTokens, countTokens, estimateTokens } from "./utils/tokens.js";
37
37
 
38
- export { AIConfig, ANTHROPIC_AVAILABLE, OPENAI_AVAILABLE as AZURE_OPENAI_AVAILABLE, AmplitudeAI, AmplitudeAIError, AmplitudeAIWrapError, AmplitudeAgentExporter, AmplitudeCallbackHandler, AmplitudeCrewAIHooks, AmplitudeGenAIExporter, AmplitudeLlamaIndexHandler, AmplitudeSpanExporter, AmplitudeToolLoop, AmplitudeTracingProcessor, Anthropic, AzureOpenAI, BEDROCK_AVAILABLE, Bedrock, BoundAgent, ConfigurationError, ContentMode, EVENT_AI_RESPONSE, EVENT_EMBEDDING, EVENT_SCORE, EVENT_SESSION_END, EVENT_SESSION_ENRICHMENT, EVENT_SPAN, EVENT_TOOL_CALL, EVENT_USER_MESSAGE, EvidenceQuote, GEMINI_AVAILABLE, GENERATED_FILES, Gemini, MAX_SERIALIZED_LENGTH, MCP_PROMPTS, MCP_RESOURCES, MCP_SERVER_NAME, MCP_TOOLS, MISTRAL_AVAILABLE, MessageLabel, Mistral, MockAmplitudeAI, OPENAI_AVAILABLE, OpenAI, PROP_ABANDONMENT_TURN, PROP_AGENT_CHAIN, PROP_AGENT_ID, PROP_AGENT_VERSION, PROP_ATTACHMENTS, PROP_ATTACHMENT_COUNT, PROP_ATTACHMENT_TYPES, PROP_CACHE_CREATION_TOKENS, PROP_CACHE_READ_TOKENS, PROP_COMMENT, PROP_COMPONENT_TYPE, PROP_CONTEXT, PROP_COST_USD, PROP_CUSTOMER_ORG_ID, PROP_EDITED_MESSAGE_ID, PROP_EMBEDDING_DIMENSIONS, PROP_ENRICHMENTS, PROP_ENV, PROP_ERROR_MESSAGE, PROP_EVALUATION_SOURCE, PROP_FINISH_REASON, PROP_HAS_ATTACHMENTS, PROP_HAS_REASONING, PROP_IDLE_TIMEOUT_MINUTES, PROP_INPUT_STATE, PROP_INPUT_TOKENS, PROP_INVOCATION_ID, PROP_IS_EDIT, PROP_IS_ERROR, PROP_IS_REGENERATION, PROP_IS_STREAMING, PROP_LATENCY_MS, PROP_LOCALE, PROP_MAX_OUTPUT_TOKENS, PROP_MESSAGE_ID, PROP_MESSAGE_LABELS, PROP_MESSAGE_LABEL_MAP, PROP_MODEL_NAME, PROP_MODEL_TIER, PROP_OUTPUT_STATE, PROP_OUTPUT_TOKENS, PROP_PARENT_AGENT_ID, PROP_PARENT_MESSAGE_ID, PROP_PARENT_SPAN_ID, PROP_PROMPT_ID, PROP_PROVIDER, PROP_QUALITY_SCORE, PROP_REASONING_CONTENT, PROP_REASONING_TOKENS, PROP_REQUEST_COMPLEXITY, PROP_ROOT_AGENT_NAME, PROP_RUNTIME, PROP_SCORE_NAME, PROP_SCORE_VALUE, PROP_SDK_VERSION, PROP_SENTIMENT_SCORE, PROP_SESSION_ID, PROP_SESSION_REPLAY_ID, PROP_SPAN_ID, PROP_SPAN_KIND, PROP_SPAN_NAME, PROP_SYSTEM_PROMPT, PROP_SYSTEM_PROMPT_LENGTH, PROP_TARGET_ID, PROP_TARGET_TYPE, PROP_TASK_FAILURE_REASON, PROP_TASK_FAILURE_TYPE, PROP_TEMPERATURE, PROP_TOOL_CALLS, PROP_TOOL_INPUT, PROP_TOOL_NAME, PROP_TOOL_OUTPUT, PROP_TOOL_SUCCESS, PROP_TOP_P, PROP_TOTAL_ATTACHMENT_SIZE, PROP_TOTAL_TOKENS, PROP_TRACE_ID, PROP_TTFB_MS, PROP_TURN_ID, PROP_WAS_CACHED, PROP_WAS_COPIED, PrivacyConfig, ProviderError, RubricScore, SDK_RUNTIME, SDK_VERSION, Session, SessionContext, SessionEnrichments, StreamingAccumulator, TIER_FAST, TIER_REASONING, TIER_STANDARD, TenantHandle, ToolCallTracker, TopicClassification, TrackingError, ValidationError, WrappedResponses, calculateCost, countMessageTokens, countTokens, createAmplitudeAIMiddleware, createAmplitudeCallback, createAmplitudeLlamaIndexHandler, estimateTokens, extractAnthropicContent, extractAnthropicSystemPrompt, extractBedrockResponse, extractContext, extractGeminiResponse, extractSystemPrompt, getActiveContext, getGenaiPriceLookupCandidates, inferModelTier, inferProvider, inferProviderFromModel, injectContext, observe, patch, patchAnthropic, patchAzureOpenAI, patchBedrock, patchGemini, patchMistral, patchOpenAI, patchedProviders, resolveAmplitude, runWithContext, runWithContextAsync, serializeToJsonString, stripProviderPrefix, tool, trackAiMessage, trackConversation, trackEmbedding, trackScore, trackSessionEnd, trackSessionEnrichment, trackSpan, trackToolCall, trackUserMessage, unpatch, unpatchAnthropic, unpatchAzureOpenAI, unpatchBedrock, unpatchGemini, unpatchMistral, unpatchOpenAI, wrap };
38
+ export { AIConfig, ANTHROPIC_AVAILABLE, OPENAI_AVAILABLE as AZURE_OPENAI_AVAILABLE, AmplitudeAI, AmplitudeAIError, AmplitudeAIWrapError, AmplitudeAgentExporter, AmplitudeCallbackHandler, AmplitudeCrewAIHooks, AmplitudeGenAIExporter, AmplitudeLlamaIndexHandler, AmplitudeSpanExporter, AmplitudeToolLoop, AmplitudeTracingProcessor, Anthropic, AzureOpenAI, BEDROCK_AVAILABLE, Bedrock, BoundAgent, ConfigurationError, ContentMode, EVENT_AI_RESPONSE, EVENT_EMBEDDING, EVENT_SCORE, EVENT_SESSION_END, EVENT_SESSION_ENRICHMENT, EVENT_SPAN, EVENT_TOOL_CALL, EVENT_USER_MESSAGE, EvidenceQuote, GEMINI_AVAILABLE, GENERATED_FILES, Gemini, MAX_SERIALIZED_LENGTH, MCP_PROMPTS, MCP_RESOURCES, MCP_SERVER_NAME, MCP_TOOLS, MISTRAL_AVAILABLE, MessageLabel, Mistral, MockAmplitudeAI, OPENAI_AVAILABLE, OpenAI, PROP_ABANDONMENT_TURN, PROP_AGENT_CHAIN, PROP_AGENT_ID, PROP_AGENT_VERSION, PROP_ATTACHMENTS, PROP_ATTACHMENT_COUNT, PROP_ATTACHMENT_TYPES, PROP_CACHE_CREATION_TOKENS, PROP_CACHE_READ_TOKENS, PROP_COMMENT, PROP_COMPONENT_TYPE, PROP_CONTEXT, PROP_COST_USD, PROP_CUSTOMER_ORG_ID, PROP_EDITED_MESSAGE_ID, PROP_EMBEDDING_DIMENSIONS, PROP_ENRICHMENTS, PROP_ENV, PROP_ERROR_MESSAGE, PROP_EVALUATION_SOURCE, PROP_FINISH_REASON, PROP_HAS_ATTACHMENTS, PROP_HAS_REASONING, PROP_IDLE_TIMEOUT_MINUTES, PROP_INPUT_STATE, PROP_INPUT_TOKENS, PROP_INVOCATION_ID, PROP_IS_EDIT, PROP_IS_ERROR, PROP_IS_REGENERATION, PROP_IS_STREAMING, PROP_LATENCY_MS, PROP_LOCALE, PROP_MAX_OUTPUT_TOKENS, PROP_MESSAGE_ID, PROP_MESSAGE_LABELS, PROP_MESSAGE_LABEL_MAP, PROP_MODEL_NAME, PROP_MODEL_TIER, PROP_OUTPUT_STATE, PROP_OUTPUT_TOKENS, PROP_PARENT_AGENT_ID, PROP_PARENT_MESSAGE_ID, PROP_PARENT_SPAN_ID, PROP_PROMPT_ID, PROP_PROVIDER, PROP_QUALITY_SCORE, PROP_REASONING_CONTENT, PROP_REASONING_TOKENS, PROP_REQUEST_COMPLEXITY, PROP_ROOT_AGENT_NAME, PROP_RUNTIME, PROP_SCORE_NAME, PROP_SCORE_VALUE, PROP_SDK_VERSION, PROP_SENTIMENT_SCORE, PROP_SESSION_ID, PROP_SESSION_REPLAY_ID, PROP_SPAN_ID, PROP_SPAN_KIND, PROP_SPAN_NAME, PROP_SYSTEM_PROMPT, PROP_SYSTEM_PROMPT_LENGTH, PROP_TARGET_ID, PROP_TARGET_TYPE, PROP_TASK_FAILURE_REASON, PROP_TASK_FAILURE_TYPE, PROP_TEMPERATURE, PROP_TOOL_CALLS, PROP_TOOL_INPUT, PROP_TOOL_NAME, PROP_TOOL_OUTPUT, PROP_TOOL_SUCCESS, PROP_TOP_P, PROP_TOTAL_ATTACHMENT_SIZE, PROP_TOTAL_TOKENS, PROP_TRACE_ID, PROP_TTFB_MS, PROP_TURN_ID, PROP_WAS_CACHED, PROP_WAS_COPIED, PrivacyConfig, ProviderError, RubricScore, SDK_RUNTIME, SDK_VERSION, Session, SessionContext, SessionEnrichments, StreamingAccumulator, TIER_FAST, TIER_REASONING, TIER_STANDARD, TenantHandle, ToolCallTracker, TopicClassification, TrackingError, ValidationError, WrappedResponses, calculateCost, countMessageTokens, countTokens, createAmplitudeAIMiddleware, createAmplitudeCallback, createAmplitudeLlamaIndexHandler, enableLivePriceUpdates, estimateTokens, extractAnthropicContent, extractAnthropicSystemPrompt, extractBedrockResponse, extractContext, extractGeminiResponse, extractSystemPrompt, getActiveContext, getGenaiPriceLookupCandidates, inferModelTier, inferProvider, inferProviderFromModel, injectContext, observe, patch, patchAnthropic, patchAzureOpenAI, patchBedrock, patchGemini, patchMistral, patchOpenAI, patchedProviders, resolveAmplitude, runWithContext, runWithContextAsync, serializeToJsonString, stripProviderPrefix, tool, trackAiMessage, trackConversation, trackEmbedding, trackScore, trackSessionEnd, trackSessionEnrichment, trackSpan, trackToolCall, trackUserMessage, unpatch, unpatchAnthropic, unpatchAzureOpenAI, unpatchBedrock, unpatchGemini, unpatchMistral, unpatchOpenAI, wrap };
@@ -73,7 +73,8 @@ var AmplitudeToolLoop = class {
73
73
  inputTokens: normalizedInput,
74
74
  outputTokens: usage.output_tokens,
75
75
  cacheReadInputTokens: cacheRead,
76
- cacheCreationInputTokens: cacheCreation
76
+ cacheCreationInputTokens: cacheCreation,
77
+ defaultProvider: "anthropic"
77
78
  });
78
79
  if (cost > 0) costUsd = cost;
79
80
  } catch {}
@@ -1 +1 @@
1
- {"version":3,"file":"anthropic-tools.js","names":["allResponses: Array<Record<string, unknown>>","costUsd: number | undefined","toolResults: Array<Record<string, unknown>>"],"sources":["../../src/integrations/anthropic-tools.ts"],"sourcesContent":["/**\n * Anthropic tool loop integration.\n *\n * Runs Anthropic's multi-turn tool_use loop and tracks each turn.\n */\n\nimport type { AmplitudeAI } from '../client.js';\nimport { getActiveContext } from '../context.js';\nimport { calculateCost } from '../utils/costs.js';\n\nexport interface ToolLoopOptions {\n amplitudeAI: AmplitudeAI;\n userId?: string;\n sessionId?: string;\n agentId?: string;\n env?: string;\n maxTurns?: number;\n}\n\nexport class AmplitudeToolLoop {\n private _ai: AmplitudeAI;\n private _userId: string | null;\n private _sessionId: string | null;\n private _agentId: string | null;\n private _env: string | null;\n private _maxTurns: number;\n\n constructor(options: ToolLoopOptions) {\n this._ai = options.amplitudeAI;\n this._userId = options.userId ?? null;\n this._sessionId = options.sessionId ?? null;\n this._agentId = options.agentId ?? null;\n this._env = options.env ?? null;\n this._maxTurns = options.maxTurns ?? 10;\n }\n\n /**\n * Run a tool loop with the Anthropic API.\n *\n * This method orchestrates multi-turn tool_use conversations,\n * tracking each AI response and tool call along the way.\n */\n async run(options: {\n client: unknown;\n model: string;\n messages: Array<Record<string, unknown>>;\n tools: Array<Record<string, unknown>>;\n system?: string;\n toolExecutor: (\n name: string,\n input: Record<string, unknown>,\n ) => Promise<unknown>;\n }): Promise<Array<Record<string, unknown>>> {\n const ctx = getActiveContext();\n const userId = this._userId ?? ctx?.userId ?? 'unknown';\n const sessionId = this._sessionId ?? ctx?.sessionId ?? 'tool-loop-session';\n const agentId = this._agentId ?? ctx?.agentId ?? undefined;\n const env = this._env ?? ctx?.env ?? undefined;\n\n const messages = [...options.messages];\n const allResponses: Array<Record<string, unknown>> = [];\n let currentTurnId = 1;\n\n for (const msg of messages) {\n const userText = _extractUserText(msg);\n if (msg.role === 'user' && userText.length > 0) {\n this._ai.trackUserMessage({\n userId,\n content: userText,\n sessionId,\n agentId,\n env,\n turnId: currentTurnId,\n });\n currentTurnId += 1;\n }\n }\n\n for (let turn = 0; turn < this._maxTurns; turn++) {\n const clientObj = options.client as Record<string, unknown>;\n const messagesApi = clientObj.messages as Record<string, unknown>;\n const createFn = messagesApi.create as (\n ...args: unknown[]\n ) => Promise<unknown>;\n\n const startTime = performance.now();\n const response = (await createFn.call(messagesApi, {\n model: options.model,\n messages,\n tools: options.tools,\n system: options.system,\n })) as Record<string, unknown>;\n\n const latencyMs = performance.now() - startTime;\n allResponses.push(response);\n\n const content = _normalizeContentBlocks(response.content);\n const responseText = _extractAssistantText(content);\n const toolUseBlocks = content.filter((b) => b.type === 'tool_use');\n const usage = response.usage as Record<string, number> | undefined;\n\n const cacheRead = usage?.cache_read_input_tokens ?? 0;\n const cacheCreation = usage?.cache_creation_input_tokens ?? 0;\n const rawInput = usage?.input_tokens ?? 0;\n const normalizedInput =\n cacheRead || cacheCreation\n ? rawInput + cacheRead + cacheCreation\n : rawInput;\n\n let costUsd: number | undefined;\n if (usage?.input_tokens != null && usage?.output_tokens != null) {\n try {\n const cost = calculateCost({\n modelName: options.model,\n inputTokens: normalizedInput,\n outputTokens: usage.output_tokens,\n cacheReadInputTokens: cacheRead,\n cacheCreationInputTokens: cacheCreation,\n });\n if (cost > 0) costUsd = cost;\n } catch {\n // cost calculation is best-effort\n }\n }\n\n this._ai.trackAiMessage({\n userId,\n content: responseText,\n sessionId,\n model: options.model,\n provider: 'anthropic',\n latencyMs,\n turnId: currentTurnId,\n agentId,\n env,\n inputTokens: normalizedInput || undefined,\n outputTokens: usage?.output_tokens,\n cacheReadTokens: cacheRead || undefined,\n cacheCreationTokens: cacheCreation || undefined,\n totalCostUsd: costUsd,\n });\n currentTurnId += 1;\n\n if (response.stop_reason !== 'tool_use' || toolUseBlocks.length === 0) {\n break;\n }\n\n messages.push({ role: 'assistant', content });\n\n const toolResults: Array<Record<string, unknown>> = [];\n for (const toolUse of toolUseBlocks) {\n const toolName = String(toolUse.name);\n const toolInput = toolUse.input as Record<string, unknown>;\n const toolStartTime = performance.now();\n\n try {\n const output = await options.toolExecutor(toolName, toolInput);\n const toolLatencyMs = performance.now() - toolStartTime;\n\n this._ai.trackToolCall({\n userId,\n toolName,\n latencyMs: toolLatencyMs,\n success: true,\n sessionId,\n agentId,\n env,\n input: toolInput,\n output: output == null ? undefined : String(output),\n });\n\n toolResults.push({\n type: 'tool_result',\n tool_use_id: toolUse.id,\n content: output == null ? '' : String(output),\n });\n } catch (error) {\n const toolLatencyMs = performance.now() - toolStartTime;\n\n this._ai.trackToolCall({\n userId,\n toolName,\n latencyMs: toolLatencyMs,\n success: false,\n sessionId,\n agentId,\n env,\n input: toolInput,\n errorMessage:\n error instanceof Error ? error.message : String(error),\n });\n\n toolResults.push({\n type: 'tool_result',\n tool_use_id: toolUse.id,\n content: `Error: ${error instanceof Error ? error.message : String(error)}`,\n is_error: true,\n });\n }\n }\n\n messages.push({ role: 'user', content: toolResults });\n }\n\n return allResponses;\n }\n}\n\nfunction _extractUserText(msg: Record<string, unknown>): string {\n if (typeof msg.content === 'string') return msg.content;\n if (!Array.isArray(msg.content)) return '';\n return msg.content\n .map((block) => {\n if (typeof block === 'string') return block;\n const item = block as Record<string, unknown>;\n return typeof item.text === 'string' ? item.text : '';\n })\n .join('');\n}\n\nfunction _extractAssistantText(\n content: Array<Record<string, unknown>> | undefined,\n): string {\n if (!Array.isArray(content)) return '';\n return content\n .filter((b) => b.type === 'text')\n .map((b) => String(b.text ?? ''))\n .join('');\n}\n\nfunction _normalizeContentBlocks(\n value: unknown,\n): Array<Record<string, unknown>> {\n if (!Array.isArray(value)) return [];\n return value.filter((v) => v != null && typeof v === 'object') as Array<\n Record<string, unknown>\n >;\n}\n"],"mappings":";;;;AAmBA,IAAa,oBAAb,MAA+B;CAC7B,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;CAER,YAAY,SAA0B;AACpC,OAAK,MAAM,QAAQ;AACnB,OAAK,UAAU,QAAQ,UAAU;AACjC,OAAK,aAAa,QAAQ,aAAa;AACvC,OAAK,WAAW,QAAQ,WAAW;AACnC,OAAK,OAAO,QAAQ,OAAO;AAC3B,OAAK,YAAY,QAAQ,YAAY;;;;;;;;CASvC,MAAM,IAAI,SAUkC;EAC1C,MAAM,MAAM,kBAAkB;EAC9B,MAAM,SAAS,KAAK,WAAW,KAAK,UAAU;EAC9C,MAAM,YAAY,KAAK,cAAc,KAAK,aAAa;EACvD,MAAM,UAAU,KAAK,YAAY,KAAK,WAAW;EACjD,MAAM,MAAM,KAAK,QAAQ,KAAK,OAAO;EAErC,MAAM,WAAW,CAAC,GAAG,QAAQ,SAAS;EACtC,MAAMA,eAA+C,EAAE;EACvD,IAAI,gBAAgB;AAEpB,OAAK,MAAM,OAAO,UAAU;GAC1B,MAAM,WAAW,iBAAiB,IAAI;AACtC,OAAI,IAAI,SAAS,UAAU,SAAS,SAAS,GAAG;AAC9C,SAAK,IAAI,iBAAiB;KACxB;KACA,SAAS;KACT;KACA;KACA;KACA,QAAQ;KACT,CAAC;AACF,qBAAiB;;;AAIrB,OAAK,IAAI,OAAO,GAAG,OAAO,KAAK,WAAW,QAAQ;GAEhD,MAAM,cADY,QAAQ,OACI;GAC9B,MAAM,WAAW,YAAY;GAI7B,MAAM,YAAY,YAAY,KAAK;GACnC,MAAM,WAAY,MAAM,SAAS,KAAK,aAAa;IACjD,OAAO,QAAQ;IACf;IACA,OAAO,QAAQ;IACf,QAAQ,QAAQ;IACjB,CAAC;GAEF,MAAM,YAAY,YAAY,KAAK,GAAG;AACtC,gBAAa,KAAK,SAAS;GAE3B,MAAM,UAAU,wBAAwB,SAAS,QAAQ;GACzD,MAAM,eAAe,sBAAsB,QAAQ;GACnD,MAAM,gBAAgB,QAAQ,QAAQ,MAAM,EAAE,SAAS,WAAW;GAClE,MAAM,QAAQ,SAAS;GAEvB,MAAM,YAAY,OAAO,2BAA2B;GACpD,MAAM,gBAAgB,OAAO,+BAA+B;GAC5D,MAAM,WAAW,OAAO,gBAAgB;GACxC,MAAM,kBACJ,aAAa,gBACT,WAAW,YAAY,gBACvB;GAEN,IAAIC;AACJ,OAAI,OAAO,gBAAgB,QAAQ,OAAO,iBAAiB,KACzD,KAAI;IACF,MAAM,OAAO,cAAc;KACzB,WAAW,QAAQ;KACnB,aAAa;KACb,cAAc,MAAM;KACpB,sBAAsB;KACtB,0BAA0B;KAC3B,CAAC;AACF,QAAI,OAAO,EAAG,WAAU;WAClB;AAKV,QAAK,IAAI,eAAe;IACtB;IACA,SAAS;IACT;IACA,OAAO,QAAQ;IACf,UAAU;IACV;IACA,QAAQ;IACR;IACA;IACA,aAAa,mBAAmB;IAChC,cAAc,OAAO;IACrB,iBAAiB,aAAa;IAC9B,qBAAqB,iBAAiB;IACtC,cAAc;IACf,CAAC;AACF,oBAAiB;AAEjB,OAAI,SAAS,gBAAgB,cAAc,cAAc,WAAW,EAClE;AAGF,YAAS,KAAK;IAAE,MAAM;IAAa;IAAS,CAAC;GAE7C,MAAMC,cAA8C,EAAE;AACtD,QAAK,MAAM,WAAW,eAAe;IACnC,MAAM,WAAW,OAAO,QAAQ,KAAK;IACrC,MAAM,YAAY,QAAQ;IAC1B,MAAM,gBAAgB,YAAY,KAAK;AAEvC,QAAI;KACF,MAAM,SAAS,MAAM,QAAQ,aAAa,UAAU,UAAU;KAC9D,MAAM,gBAAgB,YAAY,KAAK,GAAG;AAE1C,UAAK,IAAI,cAAc;MACrB;MACA;MACA,WAAW;MACX,SAAS;MACT;MACA;MACA;MACA,OAAO;MACP,QAAQ,UAAU,OAAO,SAAY,OAAO,OAAO;MACpD,CAAC;AAEF,iBAAY,KAAK;MACf,MAAM;MACN,aAAa,QAAQ;MACrB,SAAS,UAAU,OAAO,KAAK,OAAO,OAAO;MAC9C,CAAC;aACK,OAAO;KACd,MAAM,gBAAgB,YAAY,KAAK,GAAG;AAE1C,UAAK,IAAI,cAAc;MACrB;MACA;MACA,WAAW;MACX,SAAS;MACT;MACA;MACA;MACA,OAAO;MACP,cACE,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;MACzD,CAAC;AAEF,iBAAY,KAAK;MACf,MAAM;MACN,aAAa,QAAQ;MACrB,SAAS,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;MACzE,UAAU;MACX,CAAC;;;AAIN,YAAS,KAAK;IAAE,MAAM;IAAQ,SAAS;IAAa,CAAC;;AAGvD,SAAO;;;AAIX,SAAS,iBAAiB,KAAsC;AAC9D,KAAI,OAAO,IAAI,YAAY,SAAU,QAAO,IAAI;AAChD,KAAI,CAAC,MAAM,QAAQ,IAAI,QAAQ,CAAE,QAAO;AACxC,QAAO,IAAI,QACR,KAAK,UAAU;AACd,MAAI,OAAO,UAAU,SAAU,QAAO;EACtC,MAAM,OAAO;AACb,SAAO,OAAO,KAAK,SAAS,WAAW,KAAK,OAAO;GACnD,CACD,KAAK,GAAG;;AAGb,SAAS,sBACP,SACQ;AACR,KAAI,CAAC,MAAM,QAAQ,QAAQ,CAAE,QAAO;AACpC,QAAO,QACJ,QAAQ,MAAM,EAAE,SAAS,OAAO,CAChC,KAAK,MAAM,OAAO,EAAE,QAAQ,GAAG,CAAC,CAChC,KAAK,GAAG;;AAGb,SAAS,wBACP,OACgC;AAChC,KAAI,CAAC,MAAM,QAAQ,MAAM,CAAE,QAAO,EAAE;AACpC,QAAO,MAAM,QAAQ,MAAM,KAAK,QAAQ,OAAO,MAAM,SAAS"}
1
+ {"version":3,"file":"anthropic-tools.js","names":["allResponses: Array<Record<string, unknown>>","costUsd: number | undefined","toolResults: Array<Record<string, unknown>>"],"sources":["../../src/integrations/anthropic-tools.ts"],"sourcesContent":["/**\n * Anthropic tool loop integration.\n *\n * Runs Anthropic's multi-turn tool_use loop and tracks each turn.\n */\n\nimport type { AmplitudeAI } from '../client.js';\nimport { getActiveContext } from '../context.js';\nimport { calculateCost } from '../utils/costs.js';\n\nexport interface ToolLoopOptions {\n amplitudeAI: AmplitudeAI;\n userId?: string;\n sessionId?: string;\n agentId?: string;\n env?: string;\n maxTurns?: number;\n}\n\nexport class AmplitudeToolLoop {\n private _ai: AmplitudeAI;\n private _userId: string | null;\n private _sessionId: string | null;\n private _agentId: string | null;\n private _env: string | null;\n private _maxTurns: number;\n\n constructor(options: ToolLoopOptions) {\n this._ai = options.amplitudeAI;\n this._userId = options.userId ?? null;\n this._sessionId = options.sessionId ?? null;\n this._agentId = options.agentId ?? null;\n this._env = options.env ?? null;\n this._maxTurns = options.maxTurns ?? 10;\n }\n\n /**\n * Run a tool loop with the Anthropic API.\n *\n * This method orchestrates multi-turn tool_use conversations,\n * tracking each AI response and tool call along the way.\n */\n async run(options: {\n client: unknown;\n model: string;\n messages: Array<Record<string, unknown>>;\n tools: Array<Record<string, unknown>>;\n system?: string;\n toolExecutor: (\n name: string,\n input: Record<string, unknown>,\n ) => Promise<unknown>;\n }): Promise<Array<Record<string, unknown>>> {\n const ctx = getActiveContext();\n const userId = this._userId ?? ctx?.userId ?? 'unknown';\n const sessionId = this._sessionId ?? ctx?.sessionId ?? 'tool-loop-session';\n const agentId = this._agentId ?? ctx?.agentId ?? undefined;\n const env = this._env ?? ctx?.env ?? undefined;\n\n const messages = [...options.messages];\n const allResponses: Array<Record<string, unknown>> = [];\n let currentTurnId = 1;\n\n for (const msg of messages) {\n const userText = _extractUserText(msg);\n if (msg.role === 'user' && userText.length > 0) {\n this._ai.trackUserMessage({\n userId,\n content: userText,\n sessionId,\n agentId,\n env,\n turnId: currentTurnId,\n });\n currentTurnId += 1;\n }\n }\n\n for (let turn = 0; turn < this._maxTurns; turn++) {\n const clientObj = options.client as Record<string, unknown>;\n const messagesApi = clientObj.messages as Record<string, unknown>;\n const createFn = messagesApi.create as (\n ...args: unknown[]\n ) => Promise<unknown>;\n\n const startTime = performance.now();\n const response = (await createFn.call(messagesApi, {\n model: options.model,\n messages,\n tools: options.tools,\n system: options.system,\n })) as Record<string, unknown>;\n\n const latencyMs = performance.now() - startTime;\n allResponses.push(response);\n\n const content = _normalizeContentBlocks(response.content);\n const responseText = _extractAssistantText(content);\n const toolUseBlocks = content.filter((b) => b.type === 'tool_use');\n const usage = response.usage as Record<string, number> | undefined;\n\n const cacheRead = usage?.cache_read_input_tokens ?? 0;\n const cacheCreation = usage?.cache_creation_input_tokens ?? 0;\n const rawInput = usage?.input_tokens ?? 0;\n const normalizedInput =\n cacheRead || cacheCreation\n ? rawInput + cacheRead + cacheCreation\n : rawInput;\n\n let costUsd: number | undefined;\n if (usage?.input_tokens != null && usage?.output_tokens != null) {\n try {\n const cost = calculateCost({\n modelName: options.model,\n inputTokens: normalizedInput,\n outputTokens: usage.output_tokens,\n cacheReadInputTokens: cacheRead,\n cacheCreationInputTokens: cacheCreation,\n defaultProvider: 'anthropic',\n });\n if (cost > 0) costUsd = cost;\n } catch {\n // cost calculation is best-effort\n }\n }\n\n this._ai.trackAiMessage({\n userId,\n content: responseText,\n sessionId,\n model: options.model,\n provider: 'anthropic',\n latencyMs,\n turnId: currentTurnId,\n agentId,\n env,\n inputTokens: normalizedInput || undefined,\n outputTokens: usage?.output_tokens,\n cacheReadTokens: cacheRead || undefined,\n cacheCreationTokens: cacheCreation || undefined,\n totalCostUsd: costUsd,\n });\n currentTurnId += 1;\n\n if (response.stop_reason !== 'tool_use' || toolUseBlocks.length === 0) {\n break;\n }\n\n messages.push({ role: 'assistant', content });\n\n const toolResults: Array<Record<string, unknown>> = [];\n for (const toolUse of toolUseBlocks) {\n const toolName = String(toolUse.name);\n const toolInput = toolUse.input as Record<string, unknown>;\n const toolStartTime = performance.now();\n\n try {\n const output = await options.toolExecutor(toolName, toolInput);\n const toolLatencyMs = performance.now() - toolStartTime;\n\n this._ai.trackToolCall({\n userId,\n toolName,\n latencyMs: toolLatencyMs,\n success: true,\n sessionId,\n agentId,\n env,\n input: toolInput,\n output: output == null ? undefined : String(output),\n });\n\n toolResults.push({\n type: 'tool_result',\n tool_use_id: toolUse.id,\n content: output == null ? '' : String(output),\n });\n } catch (error) {\n const toolLatencyMs = performance.now() - toolStartTime;\n\n this._ai.trackToolCall({\n userId,\n toolName,\n latencyMs: toolLatencyMs,\n success: false,\n sessionId,\n agentId,\n env,\n input: toolInput,\n errorMessage:\n error instanceof Error ? error.message : String(error),\n });\n\n toolResults.push({\n type: 'tool_result',\n tool_use_id: toolUse.id,\n content: `Error: ${error instanceof Error ? error.message : String(error)}`,\n is_error: true,\n });\n }\n }\n\n messages.push({ role: 'user', content: toolResults });\n }\n\n return allResponses;\n }\n}\n\nfunction _extractUserText(msg: Record<string, unknown>): string {\n if (typeof msg.content === 'string') return msg.content;\n if (!Array.isArray(msg.content)) return '';\n return msg.content\n .map((block) => {\n if (typeof block === 'string') return block;\n const item = block as Record<string, unknown>;\n return typeof item.text === 'string' ? item.text : '';\n })\n .join('');\n}\n\nfunction _extractAssistantText(\n content: Array<Record<string, unknown>> | undefined,\n): string {\n if (!Array.isArray(content)) return '';\n return content\n .filter((b) => b.type === 'text')\n .map((b) => String(b.text ?? ''))\n .join('');\n}\n\nfunction _normalizeContentBlocks(\n value: unknown,\n): Array<Record<string, unknown>> {\n if (!Array.isArray(value)) return [];\n return value.filter((v) => v != null && typeof v === 'object') as Array<\n Record<string, unknown>\n >;\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"langchain.d.ts","names":[],"sources":["../../src/integrations/langchain.ts"],"sourcesContent":[],"mappings":";;;;;AA6FuB,UAjFN,sBAAA,CAiFM;EAgEP,WAAA,EAhJD,WAgJC;EAAM,MAAA,CAAA,EAAA,MAAA;EAoFN,SAAA,CAAA,EAAA,MAAA;;;kBA/NE;;cAGL,wBAAA;;;;;;;;;;;uBAYU;;6BAqBP;uBAuCO;8BAgEP;;;;;iBAoFA,uBAAA,UACL,yBACR"}
1
+ {"version":3,"file":"langchain.d.ts","names":[],"sources":["../../src/integrations/langchain.ts"],"sourcesContent":[],"mappings":";;;;;AAgGuB,UApFN,sBAAA,CAoFM;EAiEP,WAAA,EApJD,WAoJC;EAAM,MAAA,CAAA,EAAA,MAAA;EAoFN,SAAA,CAAA,EAAA,MAAA;;;kBAnOE;;cAGL,wBAAA;;;;;;;;;;;uBAYU;;6BAqBP;uBA0CO;8BAiEP;;;;;iBAoFA,uBAAA,UACL,yBACR"}
@@ -1,5 +1,5 @@
1
1
  import { getActiveContext } from "../context.js";
2
- import { calculateCost } from "../utils/costs.js";
2
+ import { calculateCost, inferProvider } from "../utils/costs.js";
3
3
 
4
4
  //#region src/integrations/langchain.ts
5
5
  var AmplitudeCallbackHandler = class {
@@ -34,7 +34,7 @@ var AmplitudeCallbackHandler = class {
34
34
  handleLLMStart(serialized, prompts, runId) {
35
35
  this._runStartTimes.set(runId, performance.now());
36
36
  const kwargs = serialized.kwargs;
37
- const idModel = Array.isArray(serialized.id) ? serialized.id.find((v) => typeof v === "string" && (v.includes("gpt") || v.includes("claude") || v.includes("gemini"))) : void 0;
37
+ const idModel = Array.isArray(serialized.id) ? serialized.id.find((v) => typeof v === "string" && (/\d/.test(v) || v.includes("."))) : void 0;
38
38
  const modelName = String(kwargs?.model ?? kwargs?.modelName ?? kwargs?.model_name ?? idModel ?? "");
39
39
  if (modelName) this._runModelNames.set(runId, modelName);
40
40
  const trackUserMessage = this._ai.trackUserMessage;
@@ -65,14 +65,16 @@ var AmplitudeCallbackHandler = class {
65
65
  this._runModelNames.delete(runId);
66
66
  const ctx = this._getContext();
67
67
  const modelName = String(llmOutput?.modelName ?? modelFromStart ?? "unknown");
68
- const inputTokens = _safeNumber(usage?.promptTokens ?? usage?.prompt_tokens ?? usage?.input_tokens);
69
- const outputTokens = _safeNumber(usage?.completionTokens ?? usage?.completion_tokens ?? usage?.output_tokens);
68
+ const { inputTokens, outputTokens, cacheReadTokens, cacheCreationTokens } = _extractLangchainUsage(usage);
70
69
  let costUsd;
71
70
  if (modelName !== "unknown" && inputTokens != null && outputTokens != null) try {
72
71
  const cost = calculateCost({
73
72
  modelName,
74
73
  inputTokens,
75
- outputTokens
74
+ outputTokens,
75
+ cacheReadInputTokens: cacheReadTokens,
76
+ cacheCreationInputTokens: cacheCreationTokens,
77
+ defaultProvider: inferProvider(modelName)
76
78
  });
77
79
  if (cost > 0) costUsd = cost;
78
80
  } catch {}
@@ -169,6 +171,34 @@ function createAmplitudeCallback(options) {
169
171
  function _safeNumber(value) {
170
172
  return typeof value === "number" ? value : void 0;
171
173
  }
174
+ function _extractLangchainUsage(usage) {
175
+ if (!usage) return {
176
+ inputTokens: void 0,
177
+ outputTokens: void 0,
178
+ cacheReadTokens: 0,
179
+ cacheCreationTokens: 0
180
+ };
181
+ const outputTokens = _safeNumber(usage.completionTokens ?? usage.completion_tokens ?? usage.output_tokens);
182
+ const promptTokens = _safeNumber(usage.promptTokens ?? usage.prompt_tokens);
183
+ if (promptTokens != null) {
184
+ const details = usage.prompt_tokens_details;
185
+ return {
186
+ inputTokens: promptTokens,
187
+ outputTokens,
188
+ cacheReadTokens: _safeNumber(details?.cached_tokens ?? details?.cachedTokens) ?? 0,
189
+ cacheCreationTokens: 0
190
+ };
191
+ }
192
+ const rawInput = _safeNumber(usage.input_tokens);
193
+ const cacheRead = _safeNumber(usage.cache_read_input_tokens) ?? 0;
194
+ const cacheCreation = _safeNumber(usage.cache_creation_input_tokens) ?? 0;
195
+ return {
196
+ inputTokens: rawInput != null ? rawInput + cacheRead + cacheCreation : void 0,
197
+ outputTokens,
198
+ cacheReadTokens: cacheRead,
199
+ cacheCreationTokens: cacheCreation
200
+ };
201
+ }
172
202
  function _extractLangchainText(generation) {
173
203
  if (generation == null || typeof generation !== "object") return "";
174
204
  const gen = generation;
@@ -1 +1 @@
1
- {"version":3,"file":"langchain.js","names":["costUsd: number | undefined"],"sources":["../../src/integrations/langchain.ts"],"sourcesContent":["/**\n * LangChain integration — AmplitudeCallbackHandler.\n *\n * Tracks LLM calls, tool calls, and chain events via LangChain's\n * callback system.\n */\n\nimport type { AmplitudeAI } from '../client.js';\nimport { getActiveContext } from '../context.js';\nimport type { PrivacyConfig } from '../core/privacy.js';\nimport { calculateCost } from '../utils/costs.js';\n\nexport interface CallbackHandlerOptions {\n amplitudeAI: AmplitudeAI;\n userId?: string;\n sessionId?: string;\n agentId?: string;\n env?: string;\n privacyConfig?: PrivacyConfig | null;\n}\n\nexport class AmplitudeCallbackHandler {\n private _ai: AmplitudeAI;\n private _userId: string | null;\n private _sessionId: string | null;\n private _agentId: string | null;\n private _env: string | null;\n private _privacyConfig: PrivacyConfig | null;\n private _runStartTimes: Map<string, number> = new Map();\n private _runModelNames: Map<string, string> = new Map();\n private _toolInputs: Map<string, unknown> = new Map();\n private _toolNames: Map<string, string> = new Map();\n\n constructor(options: CallbackHandlerOptions) {\n this._ai = options.amplitudeAI;\n this._userId = options.userId ?? null;\n this._sessionId = options.sessionId ?? null;\n this._agentId = options.agentId ?? null;\n this._env = options.env ?? null;\n this._privacyConfig = options.privacyConfig ?? null;\n }\n\n private _getContext() {\n const ctx = getActiveContext();\n return {\n userId: this._userId ?? ctx?.userId ?? 'unknown',\n sessionId: this._sessionId ?? ctx?.sessionId ?? undefined,\n agentId: this._agentId ?? ctx?.agentId ?? undefined,\n env: this._env ?? ctx?.env ?? undefined,\n traceId: ctx?.traceId ?? undefined,\n };\n }\n\n handleLLMStart(\n serialized: Record<string, unknown>,\n prompts: string[],\n runId: string,\n ): void {\n this._runStartTimes.set(runId, performance.now());\n const kwargs = serialized.kwargs as Record<string, unknown> | undefined;\n const idModel = Array.isArray(serialized.id)\n ? serialized.id.find(\n (v) =>\n typeof v === 'string' &&\n (v.includes('gpt') || v.includes('claude') || v.includes('gemini')),\n )\n : undefined;\n const modelName = String(\n kwargs?.model ?? kwargs?.modelName ?? kwargs?.model_name ?? idModel ?? '',\n );\n if (modelName) this._runModelNames.set(runId, modelName);\n\n const trackUserMessage = (\n this._ai as unknown as {\n trackUserMessage?: (opts: Record<string, unknown>) => void;\n }\n ).trackUserMessage;\n if (typeof trackUserMessage === 'function') {\n const ctx = this._getContext();\n for (const prompt of prompts) {\n if (!prompt) continue;\n trackUserMessage({\n userId: ctx.userId,\n content: prompt,\n sessionId: ctx.sessionId ?? 'langchain-session',\n traceId: ctx.traceId,\n agentId: ctx.agentId,\n env: ctx.env,\n });\n }\n }\n }\n\n handleLLMEnd(output: Record<string, unknown>, runId: string): void {\n const startTime = this._runStartTimes.get(runId) ?? performance.now();\n this._runStartTimes.delete(runId);\n const latencyMs = performance.now() - startTime;\n\n const generations = output.generations as\n | Array<Array<Record<string, unknown>>>\n | undefined;\n const firstGen = generations?.[0]?.[0];\n const content = _extractLangchainText(firstGen);\n const llmOutput = output.llmOutput as Record<string, unknown> | undefined;\n const usage =\n (llmOutput?.tokenUsage as Record<string, unknown> | undefined) ??\n (llmOutput?.usage as Record<string, unknown> | undefined) ??\n (llmOutput?.usage_metadata as Record<string, unknown> | undefined);\n const modelFromStart = this._runModelNames.get(runId);\n this._runModelNames.delete(runId);\n\n const ctx = this._getContext();\n const modelName = String(\n llmOutput?.modelName ?? modelFromStart ?? 'unknown',\n );\n const inputTokens = _safeNumber(\n usage?.promptTokens ?? usage?.prompt_tokens ?? usage?.input_tokens,\n );\n const outputTokens = _safeNumber(\n usage?.completionTokens ??\n usage?.completion_tokens ??\n usage?.output_tokens,\n );\n\n let costUsd: number | undefined;\n if (\n modelName !== 'unknown' &&\n inputTokens != null &&\n outputTokens != null\n ) {\n try {\n const cost = calculateCost({ modelName, inputTokens, outputTokens });\n if (cost > 0) costUsd = cost;\n } catch {\n // cost calculation is best-effort\n }\n }\n\n this._ai.trackAiMessage({\n userId: ctx.userId,\n content,\n sessionId: ctx.sessionId ?? 'langchain-session',\n model: modelName,\n provider: 'langchain',\n latencyMs,\n traceId: ctx.traceId,\n agentId: ctx.agentId,\n env: ctx.env,\n inputTokens,\n outputTokens,\n totalTokens: _safeNumber(usage?.totalTokens ?? usage?.total_tokens),\n totalCostUsd: costUsd,\n privacyConfig: this._privacyConfig,\n });\n }\n\n handleToolStart(\n serialized: Record<string, unknown>,\n input: string,\n runId: string,\n ): void {\n this._runStartTimes.set(runId, performance.now());\n this._toolInputs.set(runId, input);\n const name = String(\n serialized.name ??\n (serialized.id as string[] | undefined)?.slice(-1)[0] ??\n 'langchain-tool',\n );\n this._toolNames.set(runId, name);\n }\n\n handleToolEnd(output: string, runId: string): void {\n const startTime = this._runStartTimes.get(runId) ?? performance.now();\n this._runStartTimes.delete(runId);\n const latencyMs = performance.now() - startTime;\n const toolInput = this._toolInputs.get(runId);\n this._toolInputs.delete(runId);\n const toolName = this._toolNames.get(runId) ?? 'langchain-tool';\n this._toolNames.delete(runId);\n\n const ctx = this._getContext();\n this._ai.trackToolCall({\n userId: ctx.userId,\n toolName,\n latencyMs,\n success: true,\n sessionId: ctx.sessionId,\n traceId: ctx.traceId,\n agentId: ctx.agentId,\n env: ctx.env,\n input: toolInput,\n output,\n });\n }\n\n handleToolError(error: unknown, runId: string): void {\n const startTime = this._runStartTimes.get(runId) ?? performance.now();\n this._runStartTimes.delete(runId);\n const latencyMs = performance.now() - startTime;\n const toolInput = this._toolInputs.get(runId);\n this._toolInputs.delete(runId);\n const toolName = this._toolNames.get(runId) ?? 'langchain-tool';\n this._toolNames.delete(runId);\n\n const ctx = this._getContext();\n this._ai.trackToolCall({\n userId: ctx.userId,\n toolName,\n latencyMs,\n success: false,\n sessionId: ctx.sessionId,\n traceId: ctx.traceId,\n agentId: ctx.agentId,\n env: ctx.env,\n input: toolInput,\n errorMessage: error instanceof Error ? error.message : String(error),\n });\n }\n\n handleLLMError(error: unknown, runId: string): void {\n const startTime = this._runStartTimes.get(runId) ?? performance.now();\n this._runStartTimes.delete(runId);\n const latencyMs = performance.now() - startTime;\n\n const ctx = this._getContext();\n this._ai.trackAiMessage({\n userId: ctx.userId,\n content: '',\n sessionId: ctx.sessionId ?? 'langchain-session',\n model: 'unknown',\n provider: 'langchain',\n latencyMs,\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}\n\nexport function createAmplitudeCallback(\n options: CallbackHandlerOptions,\n): AmplitudeCallbackHandler {\n return new AmplitudeCallbackHandler(options);\n}\n\nfunction _safeNumber(value: unknown): number | undefined {\n return typeof value === 'number' ? value : undefined;\n}\n\nfunction _extractLangchainText(generation: unknown): string {\n if (generation == null || typeof generation !== 'object') return '';\n const gen = generation as Record<string, unknown>;\n if (typeof gen.text === 'string') return gen.text;\n const message = gen.message as Record<string, unknown> | undefined;\n if (message == null) return '';\n if (typeof message.content === 'string') return message.content;\n if (!Array.isArray(message.content)) return '';\n return message.content\n .map((part) => {\n if (typeof part === 'string') return part;\n const item = part as Record<string, unknown>;\n return typeof item.text === 'string' ? item.text : '';\n })\n .join('');\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"langchain.js","names":["costUsd: number | undefined"],"sources":["../../src/integrations/langchain.ts"],"sourcesContent":["/**\n * LangChain integration — AmplitudeCallbackHandler.\n *\n * Tracks LLM calls, tool calls, and chain events via LangChain's\n * callback system.\n */\n\nimport type { AmplitudeAI } from '../client.js';\nimport { getActiveContext } from '../context.js';\nimport type { PrivacyConfig } from '../core/privacy.js';\nimport { calculateCost, inferProvider } from '../utils/costs.js';\n\nexport interface CallbackHandlerOptions {\n amplitudeAI: AmplitudeAI;\n userId?: string;\n sessionId?: string;\n agentId?: string;\n env?: string;\n privacyConfig?: PrivacyConfig | null;\n}\n\nexport class AmplitudeCallbackHandler {\n private _ai: AmplitudeAI;\n private _userId: string | null;\n private _sessionId: string | null;\n private _agentId: string | null;\n private _env: string | null;\n private _privacyConfig: PrivacyConfig | null;\n private _runStartTimes: Map<string, number> = new Map();\n private _runModelNames: Map<string, string> = new Map();\n private _toolInputs: Map<string, unknown> = new Map();\n private _toolNames: Map<string, string> = new Map();\n\n constructor(options: CallbackHandlerOptions) {\n this._ai = options.amplitudeAI;\n this._userId = options.userId ?? null;\n this._sessionId = options.sessionId ?? null;\n this._agentId = options.agentId ?? null;\n this._env = options.env ?? null;\n this._privacyConfig = options.privacyConfig ?? null;\n }\n\n private _getContext() {\n const ctx = getActiveContext();\n return {\n userId: this._userId ?? ctx?.userId ?? 'unknown',\n sessionId: this._sessionId ?? ctx?.sessionId ?? undefined,\n agentId: this._agentId ?? ctx?.agentId ?? undefined,\n env: this._env ?? ctx?.env ?? undefined,\n traceId: ctx?.traceId ?? undefined,\n };\n }\n\n handleLLMStart(\n serialized: Record<string, unknown>,\n prompts: string[],\n runId: string,\n ): void {\n this._runStartTimes.set(runId, performance.now());\n const kwargs = serialized.kwargs as Record<string, unknown> | undefined;\n const idModel = Array.isArray(serialized.id)\n ? serialized.id.find(\n (v) =>\n typeof v === 'string' &&\n // Accept any id segment that looks like a model name: contains a\n // digit (version) or a dot (vendor.model). Avoids hardcoding\n // specific model families that would need updating over time.\n (/\\d/.test(v) || v.includes('.')),\n )\n : undefined;\n const modelName = String(\n kwargs?.model ?? kwargs?.modelName ?? kwargs?.model_name ?? idModel ?? '',\n );\n if (modelName) this._runModelNames.set(runId, modelName);\n\n const trackUserMessage = (\n this._ai as unknown as {\n trackUserMessage?: (opts: Record<string, unknown>) => void;\n }\n ).trackUserMessage;\n if (typeof trackUserMessage === 'function') {\n const ctx = this._getContext();\n for (const prompt of prompts) {\n if (!prompt) continue;\n trackUserMessage({\n userId: ctx.userId,\n content: prompt,\n sessionId: ctx.sessionId ?? 'langchain-session',\n traceId: ctx.traceId,\n agentId: ctx.agentId,\n env: ctx.env,\n });\n }\n }\n }\n\n handleLLMEnd(output: Record<string, unknown>, runId: string): void {\n const startTime = this._runStartTimes.get(runId) ?? performance.now();\n this._runStartTimes.delete(runId);\n const latencyMs = performance.now() - startTime;\n\n const generations = output.generations as\n | Array<Array<Record<string, unknown>>>\n | undefined;\n const firstGen = generations?.[0]?.[0];\n const content = _extractLangchainText(firstGen);\n const llmOutput = output.llmOutput as Record<string, unknown> | undefined;\n const usage =\n (llmOutput?.tokenUsage as Record<string, unknown> | undefined) ??\n (llmOutput?.usage as Record<string, unknown> | undefined) ??\n (llmOutput?.usage_metadata as Record<string, unknown> | undefined);\n const modelFromStart = this._runModelNames.get(runId);\n this._runModelNames.delete(runId);\n\n const ctx = this._getContext();\n const modelName = String(\n llmOutput?.modelName ?? modelFromStart ?? 'unknown',\n );\n const { inputTokens, outputTokens, cacheReadTokens, cacheCreationTokens } =\n _extractLangchainUsage(usage);\n\n let costUsd: number | undefined;\n if (\n modelName !== 'unknown' &&\n inputTokens != null &&\n outputTokens != null\n ) {\n try {\n const cost = calculateCost({\n modelName,\n inputTokens,\n outputTokens,\n cacheReadInputTokens: cacheReadTokens,\n cacheCreationInputTokens: cacheCreationTokens,\n defaultProvider: inferProvider(modelName),\n });\n if (cost > 0) costUsd = cost;\n } catch {\n // cost calculation is best-effort\n }\n }\n\n this._ai.trackAiMessage({\n userId: ctx.userId,\n content,\n sessionId: ctx.sessionId ?? 'langchain-session',\n model: modelName,\n provider: 'langchain',\n latencyMs,\n traceId: ctx.traceId,\n agentId: ctx.agentId,\n env: ctx.env,\n inputTokens,\n outputTokens,\n totalTokens: _safeNumber(usage?.totalTokens ?? usage?.total_tokens),\n totalCostUsd: costUsd,\n privacyConfig: this._privacyConfig,\n });\n }\n\n handleToolStart(\n serialized: Record<string, unknown>,\n input: string,\n runId: string,\n ): void {\n this._runStartTimes.set(runId, performance.now());\n this._toolInputs.set(runId, input);\n const name = String(\n serialized.name ??\n (serialized.id as string[] | undefined)?.slice(-1)[0] ??\n 'langchain-tool',\n );\n this._toolNames.set(runId, name);\n }\n\n handleToolEnd(output: string, runId: string): void {\n const startTime = this._runStartTimes.get(runId) ?? performance.now();\n this._runStartTimes.delete(runId);\n const latencyMs = performance.now() - startTime;\n const toolInput = this._toolInputs.get(runId);\n this._toolInputs.delete(runId);\n const toolName = this._toolNames.get(runId) ?? 'langchain-tool';\n this._toolNames.delete(runId);\n\n const ctx = this._getContext();\n this._ai.trackToolCall({\n userId: ctx.userId,\n toolName,\n latencyMs,\n success: true,\n sessionId: ctx.sessionId,\n traceId: ctx.traceId,\n agentId: ctx.agentId,\n env: ctx.env,\n input: toolInput,\n output,\n });\n }\n\n handleToolError(error: unknown, runId: string): void {\n const startTime = this._runStartTimes.get(runId) ?? performance.now();\n this._runStartTimes.delete(runId);\n const latencyMs = performance.now() - startTime;\n const toolInput = this._toolInputs.get(runId);\n this._toolInputs.delete(runId);\n const toolName = this._toolNames.get(runId) ?? 'langchain-tool';\n this._toolNames.delete(runId);\n\n const ctx = this._getContext();\n this._ai.trackToolCall({\n userId: ctx.userId,\n toolName,\n latencyMs,\n success: false,\n sessionId: ctx.sessionId,\n traceId: ctx.traceId,\n agentId: ctx.agentId,\n env: ctx.env,\n input: toolInput,\n errorMessage: error instanceof Error ? error.message : String(error),\n });\n }\n\n handleLLMError(error: unknown, runId: string): void {\n const startTime = this._runStartTimes.get(runId) ?? performance.now();\n this._runStartTimes.delete(runId);\n const latencyMs = performance.now() - startTime;\n\n const ctx = this._getContext();\n this._ai.trackAiMessage({\n userId: ctx.userId,\n content: '',\n sessionId: ctx.sessionId ?? 'langchain-session',\n model: 'unknown',\n provider: 'langchain',\n latencyMs,\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}\n\nexport function createAmplitudeCallback(\n options: CallbackHandlerOptions,\n): AmplitudeCallbackHandler {\n return new AmplitudeCallbackHandler(options);\n}\n\nfunction _safeNumber(value: unknown): number | undefined {\n return typeof value === 'number' ? value : undefined;\n}\n\nfunction _extractLangchainUsage(usage: Record<string, unknown> | undefined): {\n inputTokens: number | undefined;\n outputTokens: number | undefined;\n cacheReadTokens: number;\n cacheCreationTokens: number;\n} {\n if (!usage) {\n return { inputTokens: undefined, outputTokens: undefined, cacheReadTokens: 0, cacheCreationTokens: 0 };\n }\n\n const outputTokens = _safeNumber(\n usage.completionTokens ?? usage.completion_tokens ?? usage.output_tokens,\n );\n\n // OpenAI format: promptTokens / prompt_tokens (already total, includes cached)\n const promptTokens = _safeNumber(usage.promptTokens ?? usage.prompt_tokens);\n if (promptTokens != null) {\n const details = usage.prompt_tokens_details as Record<string, unknown> | undefined;\n const cached = _safeNumber(details?.cached_tokens ?? details?.cachedTokens) ?? 0;\n return { inputTokens: promptTokens, outputTokens, cacheReadTokens: cached, cacheCreationTokens: 0 };\n }\n\n // Anthropic format: input_tokens is non-cached only; normalize to total\n const rawInput = _safeNumber(usage.input_tokens);\n const cacheRead = _safeNumber(usage.cache_read_input_tokens) ?? 0;\n const cacheCreation = _safeNumber(usage.cache_creation_input_tokens) ?? 0;\n const totalInput = rawInput != null ? rawInput + cacheRead + cacheCreation : undefined;\n return { inputTokens: totalInput, outputTokens, cacheReadTokens: cacheRead, cacheCreationTokens: cacheCreation };\n}\n\nfunction _extractLangchainText(generation: unknown): string {\n if (generation == null || typeof generation !== 'object') return '';\n const gen = generation as Record<string, unknown>;\n if (typeof gen.text === 'string') return gen.text;\n const message = gen.message as Record<string, unknown> | undefined;\n if (message == null) return '';\n if (typeof message.content === 'string') return message.content;\n if (!Array.isArray(message.content)) return '';\n return message.content\n .map((part) => {\n if (typeof part === 'string') return part;\n const item = part as Record<string, unknown>;\n return typeof item.text === 'string' ? item.text : '';\n })\n .join('');\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"llamaindex.d.ts","names":[],"sources":["../../src/integrations/llamaindex.ts"],"sourcesContent":[],"mappings":";;;;UAWiB,wBAAA;eACF;;;;;;cAOF,0BAAA;;;;;;;uBAQU;;;;;;;;;;;;;;;;;;;;;;iBAiIP,gCAAA,UACL,2BACR"}
1
+ {"version":3,"file":"llamaindex.d.ts","names":[],"sources":["../../src/integrations/llamaindex.ts"],"sourcesContent":[],"mappings":";;;;UAWiB,wBAAA;eACF;;;;;;cAOF,0BAAA;;;;;;;uBAQU;;;;;;;;;;;;;;;;;;;;;;iBAoIP,gCAAA,UACL,2BACR"}
@@ -1,5 +1,5 @@
1
1
  import { getActiveContext } from "../context.js";
2
- import { calculateCost } from "../utils/costs.js";
2
+ import { calculateCost, inferProvider } from "../utils/costs.js";
3
3
 
4
4
  //#region src/integrations/llamaindex.ts
5
5
  var AmplitudeLlamaIndexHandler = class {
@@ -40,7 +40,10 @@ var AmplitudeLlamaIndexHandler = class {
40
40
  const cost = calculateCost({
41
41
  modelName: normalized.model,
42
42
  inputTokens: normalized.inputTokens,
43
- outputTokens: normalized.outputTokens
43
+ outputTokens: normalized.outputTokens,
44
+ cacheReadInputTokens: normalized.cacheReadTokens,
45
+ cacheCreationInputTokens: normalized.cacheCreationTokens,
46
+ defaultProvider: inferProvider(normalized.model)
44
47
  });
45
48
  if (cost > 0) costUsd = cost;
46
49
  } catch {}
@@ -111,11 +114,31 @@ function _normalizeLlamaLlmResponse(response) {
111
114
  const message = resp.message;
112
115
  const content = (typeof resp.content === "string" ? resp.content : void 0) ?? (typeof message?.content === "string" ? message.content : "") ?? "";
113
116
  const usage = resp.usage ?? {};
117
+ const outputTokens = _toNumber(resp.outputTokens ?? usage.output_tokens ?? usage.completion_tokens);
118
+ const promptTokens = _toNumber(usage.prompt_tokens);
119
+ if (promptTokens != null) {
120
+ const details = usage.prompt_tokens_details;
121
+ const cached = _toNumber(details?.cached_tokens) ?? 0;
122
+ return {
123
+ content,
124
+ model: String(resp.model ?? message?.model ?? "unknown"),
125
+ inputTokens: _toNumber(resp.inputTokens) ?? promptTokens,
126
+ outputTokens,
127
+ cacheReadTokens: cached,
128
+ cacheCreationTokens: 0
129
+ };
130
+ }
131
+ const rawInput = _toNumber(usage.input_tokens);
132
+ const cacheRead = _toNumber(usage.cache_read_input_tokens) ?? 0;
133
+ const cacheCreation = _toNumber(usage.cache_creation_input_tokens) ?? 0;
134
+ const totalInput = rawInput != null && (cacheRead > 0 || cacheCreation > 0) ? rawInput + cacheRead + cacheCreation : _toNumber(resp.inputTokens) ?? rawInput;
114
135
  return {
115
136
  content,
116
137
  model: String(resp.model ?? message?.model ?? "unknown"),
117
- inputTokens: _toNumber(resp.inputTokens ?? usage.input_tokens ?? usage.prompt_tokens),
118
- outputTokens: _toNumber(resp.outputTokens ?? usage.output_tokens ?? usage.completion_tokens)
138
+ inputTokens: totalInput,
139
+ outputTokens,
140
+ cacheReadTokens: cacheRead,
141
+ cacheCreationTokens: cacheCreation
119
142
  };
120
143
  }
121
144
  function _normalizeLlamaEmbeddingResponse(response) {