@librechat/agents 3.1.97 → 3.1.99

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 (49) hide show
  1. package/dist/cjs/graphs/Graph.cjs +6 -0
  2. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  3. package/dist/cjs/langfuseToolOutputTracing.cjs +16 -5
  4. package/dist/cjs/langfuseToolOutputTracing.cjs.map +1 -1
  5. package/dist/cjs/llm/bedrock/index.cjs +10 -0
  6. package/dist/cjs/llm/bedrock/index.cjs.map +1 -1
  7. package/dist/cjs/llm/bedrock/toolCache.cjs +125 -0
  8. package/dist/cjs/llm/bedrock/toolCache.cjs.map +1 -0
  9. package/dist/cjs/messages/cache.cjs +17 -9
  10. package/dist/cjs/messages/cache.cjs.map +1 -1
  11. package/dist/cjs/messages/prune.cjs +45 -8
  12. package/dist/cjs/messages/prune.cjs.map +1 -1
  13. package/dist/cjs/tools/ToolNode.cjs +6 -1
  14. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  15. package/dist/esm/graphs/Graph.mjs +6 -0
  16. package/dist/esm/graphs/Graph.mjs.map +1 -1
  17. package/dist/esm/langfuseToolOutputTracing.mjs +16 -5
  18. package/dist/esm/langfuseToolOutputTracing.mjs.map +1 -1
  19. package/dist/esm/llm/bedrock/index.mjs +10 -0
  20. package/dist/esm/llm/bedrock/index.mjs.map +1 -1
  21. package/dist/esm/llm/bedrock/toolCache.mjs +122 -0
  22. package/dist/esm/llm/bedrock/toolCache.mjs.map +1 -0
  23. package/dist/esm/messages/cache.mjs +17 -9
  24. package/dist/esm/messages/cache.mjs.map +1 -1
  25. package/dist/esm/messages/prune.mjs +45 -8
  26. package/dist/esm/messages/prune.mjs.map +1 -1
  27. package/dist/esm/tools/ToolNode.mjs +6 -1
  28. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  29. package/dist/types/llm/bedrock/index.d.ts +16 -0
  30. package/dist/types/llm/bedrock/toolCache.d.ts +4 -0
  31. package/dist/types/messages/cache.d.ts +2 -2
  32. package/dist/types/types/llm.d.ts +2 -2
  33. package/package.json +1 -1
  34. package/src/agents/__tests__/AgentContext.anthropic.live.test.ts +332 -0
  35. package/src/agents/__tests__/AgentContext.bedrock.live.test.ts +504 -0
  36. package/src/graphs/Graph.ts +14 -0
  37. package/src/langfuseToolOutputTracing.ts +26 -7
  38. package/src/llm/bedrock/index.ts +32 -1
  39. package/src/llm/bedrock/llm.spec.ts +154 -1
  40. package/src/llm/bedrock/toolCache.test.ts +131 -0
  41. package/src/llm/bedrock/toolCache.ts +191 -0
  42. package/src/messages/cache.test.ts +97 -38
  43. package/src/messages/cache.ts +18 -10
  44. package/src/messages/prune.ts +55 -17
  45. package/src/specs/langfuse-tool-output-tracing.test.ts +28 -0
  46. package/src/specs/prune.test.ts +193 -0
  47. package/src/tools/ToolNode.ts +7 -1
  48. package/src/tools/__tests__/ToolNode.langfuse.test.ts +6 -0
  49. package/src/types/llm.ts +2 -2
@@ -10,6 +10,7 @@ const langfuseToolOutputTracingConfigKey = api.createContextKey('librechat.langf
10
10
  const langfuseConfigKey = api.createContextKey('librechat.langfuse.config');
11
11
  const toolOutputTracingStorage = new node_async_hooks.AsyncLocalStorage();
12
12
  const langfuseConfigStorage = new node_async_hooks.AsyncLocalStorage();
13
+ const LANGGRAPH_TOOL_NODE_PREFIX = 'tools=';
13
14
  const CHAT_ROLES = new Set([
14
15
  'assistant',
15
16
  'developer',
@@ -301,6 +302,17 @@ function isToolObservation(attributes) {
301
302
  const type = attributes[tracing.LangfuseOtelSpanAttributes.OBSERVATION_TYPE];
302
303
  return typeof type === 'string' && type.toLowerCase() === 'tool';
303
304
  }
305
+ function classifyLangGraphToolNodeSpan(attributes) {
306
+ const type = attributes[tracing.LangfuseOtelSpanAttributes.OBSERVATION_TYPE];
307
+ if (typeof type !== 'string' || type.toLowerCase() !== 'span') {
308
+ return;
309
+ }
310
+ const langGraphNode = attributes[`${tracing.LangfuseOtelSpanAttributes.OBSERVATION_METADATA}.langgraph_node`];
311
+ if (typeof langGraphNode === 'string' &&
312
+ langGraphNode.startsWith(LANGGRAPH_TOOL_NODE_PREFIX)) {
313
+ attributes[tracing.LangfuseOtelSpanAttributes.OBSERVATION_TYPE] = 'tool';
314
+ }
315
+ }
304
316
  function redactToolObservationOutput(span, attributes, config) {
305
317
  if (!(isToolObservation(attributes) &&
306
318
  shouldRedactTool(span.name, config) &&
@@ -311,10 +323,11 @@ function redactToolObservationOutput(span, attributes, config) {
311
323
  config.redactionText;
312
324
  }
313
325
  function redactLangfuseSpanToolOutputs(span, config) {
326
+ const attributes = span.attributes;
327
+ classifyLangGraphToolNodeSpan(attributes);
314
328
  if (!shouldApplyToolOutputRedaction(config)) {
315
329
  return;
316
330
  }
317
- const attributes = span.attributes;
318
331
  redactToolObservationOutput(span, attributes, config);
319
332
  for (const key of [
320
333
  tracing.LangfuseOtelSpanAttributes.OBSERVATION_INPUT,
@@ -412,8 +425,7 @@ function hasLangfuseConfigKeys(langfuse) {
412
425
  if (langfuse == null) {
413
426
  return false;
414
427
  }
415
- return (isPresent(langfuse.secretKey) &&
416
- isPresent(langfuse.publicKey));
428
+ return isPresent(langfuse.secretKey) && isPresent(langfuse.publicKey);
417
429
  }
418
430
  function shouldTraceToolNodeForLangfuse({ runLangfuse, agentLangfuse, }) {
419
431
  const langfuse = resolveLangfuseConfig(runLangfuse, agentLangfuse);
@@ -422,8 +434,7 @@ function shouldTraceToolNodeForLangfuse({ runLangfuse, agentLangfuse, }) {
422
434
  }
423
435
  const explicit = langfuse?.toolNodeTracing?.enabled;
424
436
  if (explicit != null) {
425
- return (explicit &&
426
- (hasLangfuseConfigKeys(langfuse) || hasLangfuseEnvKeys()));
437
+ return (explicit && (hasLangfuseConfigKeys(langfuse) || hasLangfuseEnvKeys()));
427
438
  }
428
439
  return hasLangfuseConfigKeys(langfuse) || hasLangfuseEnvKeys();
429
440
  }
@@ -1 +1 @@
1
- {"version":3,"file":"langfuseToolOutputTracing.cjs","sources":["../../src/langfuseToolOutputTracing.ts"],"sourcesContent":["import { context, createContextKey } from '@opentelemetry/api';\nimport { LangfuseSpanProcessor } from '@langfuse/otel';\nimport { LangfuseOtelSpanAttributes } from '@langfuse/tracing';\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport type {\n ReadableSpan,\n Span,\n SpanProcessor,\n} from '@opentelemetry/sdk-trace-base';\nimport type { LangfuseSpanProcessorParams } from '@langfuse/otel';\nimport type { Context } from '@opentelemetry/api';\nimport type * as t from '@/types';\n\nexport const LANGFUSE_TOOL_OUTPUT_REDACTION_TEXT = '[tool output redacted]';\n\nconst langfuseToolOutputTracingConfigKey = createContextKey(\n 'librechat.langfuse.tool-output-tracing'\n);\nconst langfuseConfigKey = createContextKey('librechat.langfuse.config');\nconst toolOutputTracingStorage =\n new AsyncLocalStorage<ResolvedLangfuseToolOutputTracingConfig>();\nconst langfuseConfigStorage = new AsyncLocalStorage<t.LangfuseConfig>();\n\nconst CHAT_ROLES = new Set([\n 'assistant',\n 'developer',\n 'human',\n 'system',\n 'user',\n]);\n\nexport type ResolvedLangfuseToolOutputTracingConfig = {\n enabled: boolean;\n redactedToolNames: Set<string>;\n redactedToolNameMatchMode: 'exact' | 'partial';\n redactionText: string;\n};\n\ntype SpanWithAttributes = ReadableSpan & {\n attributes: Record<string, unknown>;\n};\n\ntype RedactionResult = {\n value: unknown;\n changed: boolean;\n};\n\ntype RedactionContext = {\n toolNamesByCallId: Map<string, string>;\n};\n\nconst TOOL_OUTPUT_FIELD_KEYS = ['content', 'artifact'];\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value != null && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction isPresent(value: unknown): value is string {\n return typeof value === 'string' && value.trim() !== '';\n}\n\nfunction parseBoolean(value: string | undefined): boolean | undefined {\n if (value == null) {\n return undefined;\n }\n\n const normalized = value.trim().toLowerCase();\n if (['1', 'true', 'yes', 'on'].includes(normalized)) {\n return true;\n }\n if (['0', 'false', 'no', 'off'].includes(normalized)) {\n return false;\n }\n\n return undefined;\n}\n\nfunction normalizeToolName(name: string): string {\n return name.trim().toLowerCase();\n}\n\nfunction normalizeToolNames(names: string[] | undefined): Set<string> {\n const normalized = new Set<string>();\n for (const name of names ?? []) {\n if (isPresent(name)) {\n normalized.add(normalizeToolName(name));\n }\n }\n return normalized;\n}\n\nfunction parseToolNames(value: string | undefined): string[] | undefined {\n if (!isPresent(value)) {\n return undefined;\n }\n\n return value\n .split(',')\n .map((name) => name.trim())\n .filter((name) => name !== '');\n}\n\nfunction getEnvToolOutputTracingEnabled(): boolean | undefined {\n const traceToolOutputs = parseBoolean(\n process.env.LANGFUSE_TRACE_TOOL_OUTPUTS\n );\n if (traceToolOutputs != null) {\n return traceToolOutputs;\n }\n\n const redactToolOutputs = parseBoolean(\n process.env.LANGFUSE_REDACT_TOOL_OUTPUTS\n );\n if (redactToolOutputs != null) {\n return !redactToolOutputs;\n }\n\n return parseBoolean(process.env.LANGFUSE_TOOL_OUTPUT_TRACING_ENABLED);\n}\n\nfunction getEnvRedactedToolNames(): string[] | undefined {\n return (\n parseToolNames(process.env.LANGFUSE_REDACT_TOOL_OUTPUT_NAMES) ??\n parseToolNames(process.env.LANGFUSE_REDACT_TOOL_NAMES)\n );\n}\n\nfunction getEnvRedactionText(): string | undefined {\n return isPresent(process.env.LANGFUSE_TOOL_OUTPUT_REDACTION_TEXT)\n ? process.env.LANGFUSE_TOOL_OUTPUT_REDACTION_TEXT\n : undefined;\n}\n\nfunction getEnvToolNameMatchMode(): 'exact' | 'partial' | undefined {\n const mode = (\n process.env.LANGFUSE_REDACT_TOOL_OUTPUT_NAME_MATCH_MODE ??\n process.env.LANGFUSE_REDACT_TOOL_NAME_MATCH_MODE\n )\n ?.trim()\n .toLowerCase();\n if (mode === 'exact' || mode === 'partial') {\n return mode;\n }\n return undefined;\n}\n\nfunction resolveToolOutputTracingConfig(\n runLangfuse?: t.LangfuseConfig,\n agentLangfuse?: t.LangfuseConfig\n): ResolvedLangfuseToolOutputTracingConfig {\n const runConfig = runLangfuse?.toolOutputTracing;\n const agentConfig = agentLangfuse?.toolOutputTracing;\n\n return {\n enabled:\n agentConfig?.enabled ??\n runConfig?.enabled ??\n getEnvToolOutputTracingEnabled() ??\n true,\n redactedToolNames: normalizeToolNames(\n agentConfig?.redactedToolNames ??\n runConfig?.redactedToolNames ??\n getEnvRedactedToolNames()\n ),\n redactedToolNameMatchMode:\n agentConfig?.redactedToolNameMatchMode ??\n runConfig?.redactedToolNameMatchMode ??\n getEnvToolNameMatchMode() ??\n 'exact',\n redactionText:\n agentConfig?.redactionText ??\n runConfig?.redactionText ??\n getEnvRedactionText() ??\n LANGFUSE_TOOL_OUTPUT_REDACTION_TEXT,\n };\n}\n\nfunction shouldApplyToolOutputRedaction(\n config: ResolvedLangfuseToolOutputTracingConfig\n): boolean {\n return config.enabled === false || config.redactedToolNames.size > 0;\n}\n\nfunction toolNameMatches(\n toolName: string | undefined,\n config: ResolvedLangfuseToolOutputTracingConfig\n): boolean {\n if (!isPresent(toolName)) {\n return false;\n }\n\n const normalizedToolName = normalizeToolName(toolName);\n if (config.redactedToolNameMatchMode === 'partial') {\n for (const redactedToolName of config.redactedToolNames) {\n if (normalizedToolName.includes(redactedToolName)) {\n return true;\n }\n }\n return false;\n }\n\n return config.redactedToolNames.has(normalizedToolName);\n}\n\nfunction shouldRedactTool(\n toolName: string | undefined,\n config: ResolvedLangfuseToolOutputTracingConfig\n): boolean {\n return config.enabled === false || toolNameMatches(toolName, config);\n}\n\nfunction getStringField(\n value: Record<string, unknown>,\n key: string\n): string | undefined {\n const field = value[key];\n return typeof field === 'string' ? field : undefined;\n}\n\nfunction getNestedStringField(\n value: Record<string, unknown>,\n objectKey: string,\n fieldKey: string\n): string | undefined {\n const nested = value[objectKey];\n if (!isRecord(nested)) {\n return undefined;\n }\n return getStringField(nested, fieldKey);\n}\n\nfunction getSerializedToolCallId(\n value: Record<string, unknown>\n): string | undefined {\n return (\n getStringField(value, 'tool_call_id') ??\n getNestedStringField(value, 'kwargs', 'tool_call_id') ??\n getNestedStringField(value, 'additional_kwargs', 'tool_call_id') ??\n getNestedStringField(value, 'data', 'tool_call_id') ??\n (typeof value.id === 'string' ? value.id : undefined)\n );\n}\n\nfunction getSerializedToolName(\n value: Record<string, unknown>,\n redactionContext?: RedactionContext\n): string | undefined {\n const role = getStringField(value, 'role');\n const explicitName =\n getStringField(value, 'name') ??\n getStringField(value, 'tool_name') ??\n getNestedStringField(value, 'function', 'name') ??\n getNestedStringField(value, 'kwargs', 'name') ??\n getNestedStringField(value, 'additional_kwargs', 'name') ??\n getNestedStringField(value, 'data', 'name') ??\n (role != null && role.toLowerCase() !== 'tool' ? role : undefined);\n\n if (explicitName != null) {\n return explicitName;\n }\n\n const toolCallId = getSerializedToolCallId(value);\n return toolCallId != null\n ? redactionContext?.toolNamesByCallId.get(toolCallId)\n : undefined;\n}\n\nfunction hasToolMessageIdentity(value: Record<string, unknown>): boolean {\n const type = getStringField(value, 'type') ?? getStringField(value, '_type');\n if (type === 'tool' || type === 'tool_message') {\n return true;\n }\n\n const id = value.id;\n if (\n Array.isArray(id) &&\n id.some((part) => typeof part === 'string' && part.includes('ToolMessage'))\n ) {\n return true;\n }\n\n if (\n 'tool_call_id' in value ||\n getNestedStringField(value, 'kwargs', 'tool_call_id') != null ||\n getNestedStringField(value, 'additional_kwargs', 'tool_call_id') != null\n ) {\n return true;\n }\n\n const role = getStringField(value, 'role');\n return (\n role != null &&\n !CHAT_ROLES.has(role.toLowerCase()) &&\n ('content' in value || isRecord(value.kwargs) || isRecord(value.data))\n );\n}\n\nfunction redactToolContentFields(\n value: Record<string, unknown>,\n config: ResolvedLangfuseToolOutputTracingConfig\n): Record<string, unknown> {\n const next = { ...value };\n\n for (const outputKey of TOOL_OUTPUT_FIELD_KEYS) {\n if (outputKey in next) {\n next[outputKey] = config.redactionText;\n }\n }\n\n for (const nestedKey of ['kwargs', 'data', 'additional_kwargs']) {\n const nested = next[nestedKey];\n if (!isRecord(nested)) {\n continue;\n }\n const nextNested = { ...nested };\n let changed = false;\n for (const outputKey of TOOL_OUTPUT_FIELD_KEYS) {\n if (outputKey in nextNested) {\n nextNested[outputKey] = config.redactionText;\n changed = true;\n }\n }\n if (changed) {\n next[nestedKey] = nextNested;\n }\n }\n\n return next;\n}\n\nfunction collectToolCallNames(\n value: unknown,\n redactionContext: RedactionContext\n): void {\n if (Array.isArray(value)) {\n for (const item of value) {\n collectToolCallNames(item, redactionContext);\n }\n return;\n }\n\n if (!isRecord(value)) {\n return;\n }\n\n const toolCallId = getSerializedToolCallId(value);\n const toolName = getSerializedToolName(value);\n if (toolCallId != null && toolName != null) {\n redactionContext.toolNamesByCallId.set(toolCallId, toolName);\n }\n\n for (const child of Object.values(value)) {\n collectToolCallNames(child, redactionContext);\n }\n}\n\nfunction redactValue(\n value: unknown,\n config: ResolvedLangfuseToolOutputTracingConfig,\n redactionContext: RedactionContext\n): RedactionResult {\n if (Array.isArray(value)) {\n let changed = false;\n const next: unknown[] = [];\n for (const item of value) {\n const result = redactValue(item, config, redactionContext);\n if (result.changed) {\n changed = true;\n }\n next.push(result.value);\n }\n return changed ? { value: next, changed } : { value, changed };\n }\n\n if (!isRecord(value)) {\n return { value, changed: false };\n }\n\n const toolName = getSerializedToolName(value, redactionContext);\n if (hasToolMessageIdentity(value) && shouldRedactTool(toolName, config)) {\n return {\n value: redactToolContentFields(value, config),\n changed: true,\n };\n }\n\n let changed = false;\n const next: Record<string, unknown> = {};\n for (const [key, child] of Object.entries(value)) {\n const result = redactValue(child, config, redactionContext);\n if (result.changed) {\n changed = true;\n }\n next[key] = result.value;\n }\n\n return changed ? { value: next, changed } : { value, changed };\n}\n\nfunction redactSerializedValue(\n value: unknown,\n config: ResolvedLangfuseToolOutputTracingConfig\n): RedactionResult {\n const redactionContext: RedactionContext = {\n toolNamesByCallId: new Map(),\n };\n if (typeof value !== 'string') {\n collectToolCallNames(value, redactionContext);\n return redactValue(value, config, redactionContext);\n }\n\n const trimmed = value.trim();\n if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) {\n return { value, changed: false };\n }\n\n try {\n const parsed = JSON.parse(value) as unknown;\n collectToolCallNames(parsed, redactionContext);\n const result = redactValue(parsed, config, redactionContext);\n return result.changed\n ? { value: JSON.stringify(result.value), changed: true }\n : { value, changed: false };\n } catch {\n return { value, changed: false };\n }\n}\n\nfunction redactAttribute(\n attributes: Record<string, unknown>,\n key: string,\n config: ResolvedLangfuseToolOutputTracingConfig\n): void {\n if (!(key in attributes)) {\n return;\n }\n\n const result = redactSerializedValue(attributes[key], config);\n if (result.changed) {\n attributes[key] = result.value;\n }\n}\n\nfunction isToolObservation(attributes: Record<string, unknown>): boolean {\n const type = attributes[LangfuseOtelSpanAttributes.OBSERVATION_TYPE];\n return typeof type === 'string' && type.toLowerCase() === 'tool';\n}\n\nfunction redactToolObservationOutput(\n span: ReadableSpan,\n attributes: Record<string, unknown>,\n config: ResolvedLangfuseToolOutputTracingConfig\n): void {\n if (\n !(\n isToolObservation(attributes) &&\n shouldRedactTool(span.name, config) &&\n LangfuseOtelSpanAttributes.OBSERVATION_OUTPUT in attributes\n )\n ) {\n return;\n }\n\n attributes[LangfuseOtelSpanAttributes.OBSERVATION_OUTPUT] =\n config.redactionText;\n}\n\nexport function redactLangfuseSpanToolOutputs(\n span: ReadableSpan,\n config: ResolvedLangfuseToolOutputTracingConfig\n): void {\n if (!shouldApplyToolOutputRedaction(config)) {\n return;\n }\n\n const attributes = (span as SpanWithAttributes).attributes;\n redactToolObservationOutput(span, attributes, config);\n\n for (const key of [\n LangfuseOtelSpanAttributes.OBSERVATION_INPUT,\n LangfuseOtelSpanAttributes.OBSERVATION_OUTPUT,\n LangfuseOtelSpanAttributes.TRACE_INPUT,\n LangfuseOtelSpanAttributes.TRACE_OUTPUT,\n ]) {\n redactAttribute(attributes, key, config);\n }\n}\n\nfunction getContextToolOutputTracingConfig(\n activeContext: Context\n): ResolvedLangfuseToolOutputTracingConfig | undefined {\n const asyncConfig = toolOutputTracingStorage.getStore();\n if (asyncConfig != null) {\n return asyncConfig;\n }\n\n const value = activeContext.getValue(langfuseToolOutputTracingConfigKey);\n return isRecord(value)\n ? (value as ResolvedLangfuseToolOutputTracingConfig)\n : undefined;\n}\n\nexport function getContextLangfuseConfig(\n activeContext: Context\n): t.LangfuseConfig | undefined {\n const asyncConfig = langfuseConfigStorage.getStore();\n if (asyncConfig != null) {\n return asyncConfig;\n }\n\n const value = activeContext.getValue(langfuseConfigKey);\n return isRecord(value) ? (value as t.LangfuseConfig) : undefined;\n}\n\nclass ToolOutputRedactingLangfuseSpanProcessor implements SpanProcessor {\n private readonly processor: LangfuseSpanProcessor;\n private readonly fallbackConfig?: ResolvedLangfuseToolOutputTracingConfig;\n private readonly spanConfigs = new WeakMap<\n object,\n ResolvedLangfuseToolOutputTracingConfig\n >();\n\n constructor(\n params?: LangfuseSpanProcessorParams,\n fallbackConfig?: ResolvedLangfuseToolOutputTracingConfig\n ) {\n this.processor = new LangfuseSpanProcessor(params);\n this.fallbackConfig = fallbackConfig;\n }\n\n onStart(span: Span, parentContext: Context): void {\n const config =\n getContextToolOutputTracingConfig(parentContext) ?? this.fallbackConfig;\n if (config != null) {\n this.spanConfigs.set(span, config);\n }\n this.processor.onStart(span, parentContext);\n }\n\n onEnd(span: ReadableSpan): void {\n const config =\n this.spanConfigs.get(span) ??\n toolOutputTracingStorage.getStore() ??\n this.fallbackConfig ??\n resolveToolOutputTracingConfig();\n redactLangfuseSpanToolOutputs(span, config);\n this.processor.onEnd(span);\n }\n\n forceFlush(): Promise<void> {\n return this.processor.forceFlush();\n }\n\n shutdown(): Promise<void> {\n return this.processor.shutdown();\n }\n}\n\nexport function createLangfuseSpanProcessor(\n params?: LangfuseSpanProcessorParams,\n runLangfuse?: t.LangfuseConfig,\n agentLangfuse?: t.LangfuseConfig\n): SpanProcessor {\n const fallbackConfig =\n runLangfuse != null || agentLangfuse != null\n ? resolveToolOutputTracingConfig(runLangfuse, agentLangfuse)\n : undefined;\n return new ToolOutputRedactingLangfuseSpanProcessor(params, fallbackConfig);\n}\n\nexport function withLangfuseToolOutputTracingConfig<T>(\n runLangfuse: t.LangfuseConfig | undefined,\n action: () => T,\n agentLangfuse?: t.LangfuseConfig\n): T {\n const langfuse = resolveLangfuseConfig(runLangfuse, agentLangfuse);\n const hasNoToolOutputConfig =\n runLangfuse?.toolOutputTracing == null &&\n agentLangfuse?.toolOutputTracing == null;\n\n if (langfuse == null && hasNoToolOutputConfig) {\n return action();\n }\n\n const config = hasNoToolOutputConfig\n ? undefined\n : resolveToolOutputTracingConfig(runLangfuse, agentLangfuse);\n let activeContext = context.active();\n if (langfuse != null) {\n activeContext = activeContext.setValue(langfuseConfigKey, langfuse);\n }\n if (config != null) {\n activeContext = activeContext.setValue(\n langfuseToolOutputTracingConfigKey,\n config\n );\n }\n\n const runWithContext = (): T => context.with(activeContext, action);\n const runWithToolOutputConfig = (): T =>\n config != null\n ? toolOutputTracingStorage.run(config, runWithContext)\n : runWithContext();\n\n return langfuse != null\n ? langfuseConfigStorage.run(langfuse, runWithToolOutputConfig)\n : runWithToolOutputConfig();\n}\n\nfunction hasLangfuseEnvKeys(): boolean {\n return (\n isPresent(process.env.LANGFUSE_SECRET_KEY) &&\n isPresent(process.env.LANGFUSE_PUBLIC_KEY)\n );\n}\n\nfunction hasLangfuseConfigKeys(langfuse?: t.LangfuseConfig): boolean {\n if (langfuse == null) {\n return false;\n }\n return (\n isPresent(langfuse.secretKey) &&\n isPresent(langfuse.publicKey)\n );\n}\n\nexport function shouldTraceToolNodeForLangfuse({\n runLangfuse,\n agentLangfuse,\n}: {\n runLangfuse?: t.LangfuseConfig;\n agentLangfuse?: t.LangfuseConfig;\n}): boolean {\n const langfuse = resolveLangfuseConfig(runLangfuse, agentLangfuse);\n if (langfuse?.enabled === false) {\n return false;\n }\n\n const explicit = langfuse?.toolNodeTracing?.enabled;\n if (explicit != null) {\n return (\n explicit &&\n (hasLangfuseConfigKeys(langfuse) || hasLangfuseEnvKeys())\n );\n }\n\n return hasLangfuseConfigKeys(langfuse) || hasLangfuseEnvKeys();\n}\n\nexport function resolveLangfuseConfig(\n runLangfuse?: t.LangfuseConfig,\n agentLangfuse?: t.LangfuseConfig\n): t.LangfuseConfig | undefined {\n if (runLangfuse == null) {\n return agentLangfuse;\n }\n if (agentLangfuse == null) {\n return runLangfuse;\n }\n\n const toolNodeTracing =\n runLangfuse.toolNodeTracing != null || agentLangfuse.toolNodeTracing != null\n ? {\n ...runLangfuse.toolNodeTracing,\n ...agentLangfuse.toolNodeTracing,\n }\n : undefined;\n const toolOutputTracing =\n runLangfuse.toolOutputTracing != null ||\n agentLangfuse.toolOutputTracing != null\n ? {\n ...runLangfuse.toolOutputTracing,\n ...agentLangfuse.toolOutputTracing,\n }\n : undefined;\n\n return {\n ...runLangfuse,\n ...agentLangfuse,\n ...(toolNodeTracing != null ? { toolNodeTracing } : {}),\n ...(toolOutputTracing != null ? { toolOutputTracing } : {}),\n };\n}\n"],"names":["createContextKey","AsyncLocalStorage","LangfuseOtelSpanAttributes","LangfuseSpanProcessor","context"],"mappings":"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"}
1
+ {"version":3,"file":"langfuseToolOutputTracing.cjs","sources":["../../src/langfuseToolOutputTracing.ts"],"sourcesContent":["import { context, createContextKey } from '@opentelemetry/api';\nimport { LangfuseSpanProcessor } from '@langfuse/otel';\nimport { LangfuseOtelSpanAttributes } from '@langfuse/tracing';\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport type {\n ReadableSpan,\n Span,\n SpanProcessor,\n} from '@opentelemetry/sdk-trace-base';\nimport type { LangfuseSpanProcessorParams } from '@langfuse/otel';\nimport type { Context } from '@opentelemetry/api';\nimport type * as t from '@/types';\n\nexport const LANGFUSE_TOOL_OUTPUT_REDACTION_TEXT = '[tool output redacted]';\n\nconst langfuseToolOutputTracingConfigKey = createContextKey(\n 'librechat.langfuse.tool-output-tracing'\n);\nconst langfuseConfigKey = createContextKey('librechat.langfuse.config');\nconst toolOutputTracingStorage =\n new AsyncLocalStorage<ResolvedLangfuseToolOutputTracingConfig>();\nconst langfuseConfigStorage = new AsyncLocalStorage<t.LangfuseConfig>();\nconst LANGGRAPH_TOOL_NODE_PREFIX = 'tools=';\n\nconst CHAT_ROLES = new Set([\n 'assistant',\n 'developer',\n 'human',\n 'system',\n 'user',\n]);\n\nexport type ResolvedLangfuseToolOutputTracingConfig = {\n enabled: boolean;\n redactedToolNames: Set<string>;\n redactedToolNameMatchMode: 'exact' | 'partial';\n redactionText: string;\n};\n\ntype SpanWithAttributes = ReadableSpan & {\n attributes: Record<string, unknown>;\n};\n\ntype RedactionResult = {\n value: unknown;\n changed: boolean;\n};\n\ntype RedactionContext = {\n toolNamesByCallId: Map<string, string>;\n};\n\nconst TOOL_OUTPUT_FIELD_KEYS = ['content', 'artifact'];\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value != null && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction isPresent(value: unknown): value is string {\n return typeof value === 'string' && value.trim() !== '';\n}\n\nfunction parseBoolean(value: string | undefined): boolean | undefined {\n if (value == null) {\n return undefined;\n }\n\n const normalized = value.trim().toLowerCase();\n if (['1', 'true', 'yes', 'on'].includes(normalized)) {\n return true;\n }\n if (['0', 'false', 'no', 'off'].includes(normalized)) {\n return false;\n }\n\n return undefined;\n}\n\nfunction normalizeToolName(name: string): string {\n return name.trim().toLowerCase();\n}\n\nfunction normalizeToolNames(names: string[] | undefined): Set<string> {\n const normalized = new Set<string>();\n for (const name of names ?? []) {\n if (isPresent(name)) {\n normalized.add(normalizeToolName(name));\n }\n }\n return normalized;\n}\n\nfunction parseToolNames(value: string | undefined): string[] | undefined {\n if (!isPresent(value)) {\n return undefined;\n }\n\n return value\n .split(',')\n .map((name) => name.trim())\n .filter((name) => name !== '');\n}\n\nfunction getEnvToolOutputTracingEnabled(): boolean | undefined {\n const traceToolOutputs = parseBoolean(\n process.env.LANGFUSE_TRACE_TOOL_OUTPUTS\n );\n if (traceToolOutputs != null) {\n return traceToolOutputs;\n }\n\n const redactToolOutputs = parseBoolean(\n process.env.LANGFUSE_REDACT_TOOL_OUTPUTS\n );\n if (redactToolOutputs != null) {\n return !redactToolOutputs;\n }\n\n return parseBoolean(process.env.LANGFUSE_TOOL_OUTPUT_TRACING_ENABLED);\n}\n\nfunction getEnvRedactedToolNames(): string[] | undefined {\n return (\n parseToolNames(process.env.LANGFUSE_REDACT_TOOL_OUTPUT_NAMES) ??\n parseToolNames(process.env.LANGFUSE_REDACT_TOOL_NAMES)\n );\n}\n\nfunction getEnvRedactionText(): string | undefined {\n return isPresent(process.env.LANGFUSE_TOOL_OUTPUT_REDACTION_TEXT)\n ? process.env.LANGFUSE_TOOL_OUTPUT_REDACTION_TEXT\n : undefined;\n}\n\nfunction getEnvToolNameMatchMode(): 'exact' | 'partial' | undefined {\n const mode = (\n process.env.LANGFUSE_REDACT_TOOL_OUTPUT_NAME_MATCH_MODE ??\n process.env.LANGFUSE_REDACT_TOOL_NAME_MATCH_MODE\n )\n ?.trim()\n .toLowerCase();\n if (mode === 'exact' || mode === 'partial') {\n return mode;\n }\n return undefined;\n}\n\nfunction resolveToolOutputTracingConfig(\n runLangfuse?: t.LangfuseConfig,\n agentLangfuse?: t.LangfuseConfig\n): ResolvedLangfuseToolOutputTracingConfig {\n const runConfig = runLangfuse?.toolOutputTracing;\n const agentConfig = agentLangfuse?.toolOutputTracing;\n\n return {\n enabled:\n agentConfig?.enabled ??\n runConfig?.enabled ??\n getEnvToolOutputTracingEnabled() ??\n true,\n redactedToolNames: normalizeToolNames(\n agentConfig?.redactedToolNames ??\n runConfig?.redactedToolNames ??\n getEnvRedactedToolNames()\n ),\n redactedToolNameMatchMode:\n agentConfig?.redactedToolNameMatchMode ??\n runConfig?.redactedToolNameMatchMode ??\n getEnvToolNameMatchMode() ??\n 'exact',\n redactionText:\n agentConfig?.redactionText ??\n runConfig?.redactionText ??\n getEnvRedactionText() ??\n LANGFUSE_TOOL_OUTPUT_REDACTION_TEXT,\n };\n}\n\nfunction shouldApplyToolOutputRedaction(\n config: ResolvedLangfuseToolOutputTracingConfig\n): boolean {\n return config.enabled === false || config.redactedToolNames.size > 0;\n}\n\nfunction toolNameMatches(\n toolName: string | undefined,\n config: ResolvedLangfuseToolOutputTracingConfig\n): boolean {\n if (!isPresent(toolName)) {\n return false;\n }\n\n const normalizedToolName = normalizeToolName(toolName);\n if (config.redactedToolNameMatchMode === 'partial') {\n for (const redactedToolName of config.redactedToolNames) {\n if (normalizedToolName.includes(redactedToolName)) {\n return true;\n }\n }\n return false;\n }\n\n return config.redactedToolNames.has(normalizedToolName);\n}\n\nfunction shouldRedactTool(\n toolName: string | undefined,\n config: ResolvedLangfuseToolOutputTracingConfig\n): boolean {\n return config.enabled === false || toolNameMatches(toolName, config);\n}\n\nfunction getStringField(\n value: Record<string, unknown>,\n key: string\n): string | undefined {\n const field = value[key];\n return typeof field === 'string' ? field : undefined;\n}\n\nfunction getNestedStringField(\n value: Record<string, unknown>,\n objectKey: string,\n fieldKey: string\n): string | undefined {\n const nested = value[objectKey];\n if (!isRecord(nested)) {\n return undefined;\n }\n return getStringField(nested, fieldKey);\n}\n\nfunction getSerializedToolCallId(\n value: Record<string, unknown>\n): string | undefined {\n return (\n getStringField(value, 'tool_call_id') ??\n getNestedStringField(value, 'kwargs', 'tool_call_id') ??\n getNestedStringField(value, 'additional_kwargs', 'tool_call_id') ??\n getNestedStringField(value, 'data', 'tool_call_id') ??\n (typeof value.id === 'string' ? value.id : undefined)\n );\n}\n\nfunction getSerializedToolName(\n value: Record<string, unknown>,\n redactionContext?: RedactionContext\n): string | undefined {\n const role = getStringField(value, 'role');\n const explicitName =\n getStringField(value, 'name') ??\n getStringField(value, 'tool_name') ??\n getNestedStringField(value, 'function', 'name') ??\n getNestedStringField(value, 'kwargs', 'name') ??\n getNestedStringField(value, 'additional_kwargs', 'name') ??\n getNestedStringField(value, 'data', 'name') ??\n (role != null && role.toLowerCase() !== 'tool' ? role : undefined);\n\n if (explicitName != null) {\n return explicitName;\n }\n\n const toolCallId = getSerializedToolCallId(value);\n return toolCallId != null\n ? redactionContext?.toolNamesByCallId.get(toolCallId)\n : undefined;\n}\n\nfunction hasToolMessageIdentity(value: Record<string, unknown>): boolean {\n const type = getStringField(value, 'type') ?? getStringField(value, '_type');\n if (type === 'tool' || type === 'tool_message') {\n return true;\n }\n\n const id = value.id;\n if (\n Array.isArray(id) &&\n id.some((part) => typeof part === 'string' && part.includes('ToolMessage'))\n ) {\n return true;\n }\n\n if (\n 'tool_call_id' in value ||\n getNestedStringField(value, 'kwargs', 'tool_call_id') != null ||\n getNestedStringField(value, 'additional_kwargs', 'tool_call_id') != null\n ) {\n return true;\n }\n\n const role = getStringField(value, 'role');\n return (\n role != null &&\n !CHAT_ROLES.has(role.toLowerCase()) &&\n ('content' in value || isRecord(value.kwargs) || isRecord(value.data))\n );\n}\n\nfunction redactToolContentFields(\n value: Record<string, unknown>,\n config: ResolvedLangfuseToolOutputTracingConfig\n): Record<string, unknown> {\n const next = { ...value };\n\n for (const outputKey of TOOL_OUTPUT_FIELD_KEYS) {\n if (outputKey in next) {\n next[outputKey] = config.redactionText;\n }\n }\n\n for (const nestedKey of ['kwargs', 'data', 'additional_kwargs']) {\n const nested = next[nestedKey];\n if (!isRecord(nested)) {\n continue;\n }\n const nextNested = { ...nested };\n let changed = false;\n for (const outputKey of TOOL_OUTPUT_FIELD_KEYS) {\n if (outputKey in nextNested) {\n nextNested[outputKey] = config.redactionText;\n changed = true;\n }\n }\n if (changed) {\n next[nestedKey] = nextNested;\n }\n }\n\n return next;\n}\n\nfunction collectToolCallNames(\n value: unknown,\n redactionContext: RedactionContext\n): void {\n if (Array.isArray(value)) {\n for (const item of value) {\n collectToolCallNames(item, redactionContext);\n }\n return;\n }\n\n if (!isRecord(value)) {\n return;\n }\n\n const toolCallId = getSerializedToolCallId(value);\n const toolName = getSerializedToolName(value);\n if (toolCallId != null && toolName != null) {\n redactionContext.toolNamesByCallId.set(toolCallId, toolName);\n }\n\n for (const child of Object.values(value)) {\n collectToolCallNames(child, redactionContext);\n }\n}\n\nfunction redactValue(\n value: unknown,\n config: ResolvedLangfuseToolOutputTracingConfig,\n redactionContext: RedactionContext\n): RedactionResult {\n if (Array.isArray(value)) {\n let changed = false;\n const next: unknown[] = [];\n for (const item of value) {\n const result = redactValue(item, config, redactionContext);\n if (result.changed) {\n changed = true;\n }\n next.push(result.value);\n }\n return changed ? { value: next, changed } : { value, changed };\n }\n\n if (!isRecord(value)) {\n return { value, changed: false };\n }\n\n const toolName = getSerializedToolName(value, redactionContext);\n if (hasToolMessageIdentity(value) && shouldRedactTool(toolName, config)) {\n return {\n value: redactToolContentFields(value, config),\n changed: true,\n };\n }\n\n let changed = false;\n const next: Record<string, unknown> = {};\n for (const [key, child] of Object.entries(value)) {\n const result = redactValue(child, config, redactionContext);\n if (result.changed) {\n changed = true;\n }\n next[key] = result.value;\n }\n\n return changed ? { value: next, changed } : { value, changed };\n}\n\nfunction redactSerializedValue(\n value: unknown,\n config: ResolvedLangfuseToolOutputTracingConfig\n): RedactionResult {\n const redactionContext: RedactionContext = {\n toolNamesByCallId: new Map(),\n };\n if (typeof value !== 'string') {\n collectToolCallNames(value, redactionContext);\n return redactValue(value, config, redactionContext);\n }\n\n const trimmed = value.trim();\n if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) {\n return { value, changed: false };\n }\n\n try {\n const parsed = JSON.parse(value) as unknown;\n collectToolCallNames(parsed, redactionContext);\n const result = redactValue(parsed, config, redactionContext);\n return result.changed\n ? { value: JSON.stringify(result.value), changed: true }\n : { value, changed: false };\n } catch {\n return { value, changed: false };\n }\n}\n\nfunction redactAttribute(\n attributes: Record<string, unknown>,\n key: string,\n config: ResolvedLangfuseToolOutputTracingConfig\n): void {\n if (!(key in attributes)) {\n return;\n }\n\n const result = redactSerializedValue(attributes[key], config);\n if (result.changed) {\n attributes[key] = result.value;\n }\n}\n\nfunction isToolObservation(attributes: Record<string, unknown>): boolean {\n const type = attributes[LangfuseOtelSpanAttributes.OBSERVATION_TYPE];\n return typeof type === 'string' && type.toLowerCase() === 'tool';\n}\n\nfunction classifyLangGraphToolNodeSpan(\n attributes: Record<string, unknown>\n): void {\n const type = attributes[LangfuseOtelSpanAttributes.OBSERVATION_TYPE];\n if (typeof type !== 'string' || type.toLowerCase() !== 'span') {\n return;\n }\n\n const langGraphNode =\n attributes[\n `${LangfuseOtelSpanAttributes.OBSERVATION_METADATA}.langgraph_node`\n ];\n if (\n typeof langGraphNode === 'string' &&\n langGraphNode.startsWith(LANGGRAPH_TOOL_NODE_PREFIX)\n ) {\n attributes[LangfuseOtelSpanAttributes.OBSERVATION_TYPE] = 'tool';\n }\n}\n\nfunction redactToolObservationOutput(\n span: ReadableSpan,\n attributes: Record<string, unknown>,\n config: ResolvedLangfuseToolOutputTracingConfig\n): void {\n if (\n !(\n isToolObservation(attributes) &&\n shouldRedactTool(span.name, config) &&\n LangfuseOtelSpanAttributes.OBSERVATION_OUTPUT in attributes\n )\n ) {\n return;\n }\n\n attributes[LangfuseOtelSpanAttributes.OBSERVATION_OUTPUT] =\n config.redactionText;\n}\n\nexport function redactLangfuseSpanToolOutputs(\n span: ReadableSpan,\n config: ResolvedLangfuseToolOutputTracingConfig\n): void {\n const attributes = (span as SpanWithAttributes).attributes;\n classifyLangGraphToolNodeSpan(attributes);\n\n if (!shouldApplyToolOutputRedaction(config)) {\n return;\n }\n\n redactToolObservationOutput(span, attributes, config);\n\n for (const key of [\n LangfuseOtelSpanAttributes.OBSERVATION_INPUT,\n LangfuseOtelSpanAttributes.OBSERVATION_OUTPUT,\n LangfuseOtelSpanAttributes.TRACE_INPUT,\n LangfuseOtelSpanAttributes.TRACE_OUTPUT,\n ]) {\n redactAttribute(attributes, key, config);\n }\n}\n\nfunction getContextToolOutputTracingConfig(\n activeContext: Context\n): ResolvedLangfuseToolOutputTracingConfig | undefined {\n const asyncConfig = toolOutputTracingStorage.getStore();\n if (asyncConfig != null) {\n return asyncConfig;\n }\n\n const value = activeContext.getValue(langfuseToolOutputTracingConfigKey);\n return isRecord(value)\n ? (value as ResolvedLangfuseToolOutputTracingConfig)\n : undefined;\n}\n\nexport function getContextLangfuseConfig(\n activeContext: Context\n): t.LangfuseConfig | undefined {\n const asyncConfig = langfuseConfigStorage.getStore();\n if (asyncConfig != null) {\n return asyncConfig;\n }\n\n const value = activeContext.getValue(langfuseConfigKey);\n return isRecord(value) ? (value as t.LangfuseConfig) : undefined;\n}\n\nclass ToolOutputRedactingLangfuseSpanProcessor implements SpanProcessor {\n private readonly processor: LangfuseSpanProcessor;\n private readonly fallbackConfig?: ResolvedLangfuseToolOutputTracingConfig;\n private readonly spanConfigs = new WeakMap<\n object,\n ResolvedLangfuseToolOutputTracingConfig\n >();\n\n constructor(\n params?: LangfuseSpanProcessorParams,\n fallbackConfig?: ResolvedLangfuseToolOutputTracingConfig\n ) {\n this.processor = new LangfuseSpanProcessor(params);\n this.fallbackConfig = fallbackConfig;\n }\n\n onStart(span: Span, parentContext: Context): void {\n const config =\n getContextToolOutputTracingConfig(parentContext) ?? this.fallbackConfig;\n if (config != null) {\n this.spanConfigs.set(span, config);\n }\n this.processor.onStart(span, parentContext);\n }\n\n onEnd(span: ReadableSpan): void {\n const config =\n this.spanConfigs.get(span) ??\n toolOutputTracingStorage.getStore() ??\n this.fallbackConfig ??\n resolveToolOutputTracingConfig();\n redactLangfuseSpanToolOutputs(span, config);\n this.processor.onEnd(span);\n }\n\n forceFlush(): Promise<void> {\n return this.processor.forceFlush();\n }\n\n shutdown(): Promise<void> {\n return this.processor.shutdown();\n }\n}\n\nexport function createLangfuseSpanProcessor(\n params?: LangfuseSpanProcessorParams,\n runLangfuse?: t.LangfuseConfig,\n agentLangfuse?: t.LangfuseConfig\n): SpanProcessor {\n const fallbackConfig =\n runLangfuse != null || agentLangfuse != null\n ? resolveToolOutputTracingConfig(runLangfuse, agentLangfuse)\n : undefined;\n return new ToolOutputRedactingLangfuseSpanProcessor(params, fallbackConfig);\n}\n\nexport function withLangfuseToolOutputTracingConfig<T>(\n runLangfuse: t.LangfuseConfig | undefined,\n action: () => T,\n agentLangfuse?: t.LangfuseConfig\n): T {\n const langfuse = resolveLangfuseConfig(runLangfuse, agentLangfuse);\n const hasNoToolOutputConfig =\n runLangfuse?.toolOutputTracing == null &&\n agentLangfuse?.toolOutputTracing == null;\n\n if (langfuse == null && hasNoToolOutputConfig) {\n return action();\n }\n\n const config = hasNoToolOutputConfig\n ? undefined\n : resolveToolOutputTracingConfig(runLangfuse, agentLangfuse);\n let activeContext = context.active();\n if (langfuse != null) {\n activeContext = activeContext.setValue(langfuseConfigKey, langfuse);\n }\n if (config != null) {\n activeContext = activeContext.setValue(\n langfuseToolOutputTracingConfigKey,\n config\n );\n }\n\n const runWithContext = (): T => context.with(activeContext, action);\n const runWithToolOutputConfig = (): T =>\n config != null\n ? toolOutputTracingStorage.run(config, runWithContext)\n : runWithContext();\n\n return langfuse != null\n ? langfuseConfigStorage.run(langfuse, runWithToolOutputConfig)\n : runWithToolOutputConfig();\n}\n\nfunction hasLangfuseEnvKeys(): boolean {\n return (\n isPresent(process.env.LANGFUSE_SECRET_KEY) &&\n isPresent(process.env.LANGFUSE_PUBLIC_KEY)\n );\n}\n\nfunction hasLangfuseConfigKeys(langfuse?: t.LangfuseConfig): boolean {\n if (langfuse == null) {\n return false;\n }\n return isPresent(langfuse.secretKey) && isPresent(langfuse.publicKey);\n}\n\nexport function shouldTraceToolNodeForLangfuse({\n runLangfuse,\n agentLangfuse,\n}: {\n runLangfuse?: t.LangfuseConfig;\n agentLangfuse?: t.LangfuseConfig;\n}): boolean {\n const langfuse = resolveLangfuseConfig(runLangfuse, agentLangfuse);\n if (langfuse?.enabled === false) {\n return false;\n }\n\n const explicit = langfuse?.toolNodeTracing?.enabled;\n if (explicit != null) {\n return (\n explicit && (hasLangfuseConfigKeys(langfuse) || hasLangfuseEnvKeys())\n );\n }\n\n return hasLangfuseConfigKeys(langfuse) || hasLangfuseEnvKeys();\n}\n\nexport function resolveLangfuseConfig(\n runLangfuse?: t.LangfuseConfig,\n agentLangfuse?: t.LangfuseConfig\n): t.LangfuseConfig | undefined {\n if (runLangfuse == null) {\n return agentLangfuse;\n }\n if (agentLangfuse == null) {\n return runLangfuse;\n }\n\n const toolNodeTracing =\n runLangfuse.toolNodeTracing != null || agentLangfuse.toolNodeTracing != null\n ? {\n ...runLangfuse.toolNodeTracing,\n ...agentLangfuse.toolNodeTracing,\n }\n : undefined;\n const toolOutputTracing =\n runLangfuse.toolOutputTracing != null ||\n agentLangfuse.toolOutputTracing != null\n ? {\n ...runLangfuse.toolOutputTracing,\n ...agentLangfuse.toolOutputTracing,\n }\n : undefined;\n\n return {\n ...runLangfuse,\n ...agentLangfuse,\n ...(toolNodeTracing != null ? { toolNodeTracing } : {}),\n ...(toolOutputTracing != null ? { toolOutputTracing } : {}),\n };\n}\n"],"names":["createContextKey","AsyncLocalStorage","LangfuseOtelSpanAttributes","LangfuseSpanProcessor","context"],"mappings":"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"}
@@ -4,6 +4,7 @@ var aws = require('@langchain/aws');
4
4
  var clientBedrockRuntime = require('@aws-sdk/client-bedrock-runtime');
5
5
  var messages = require('@langchain/core/messages');
6
6
  var outputs = require('@langchain/core/outputs');
7
+ var toolCache = require('./toolCache.cjs');
7
8
  var message_inputs = require('./utils/message_inputs.cjs');
8
9
  var message_outputs = require('./utils/message_outputs.cjs');
9
10
 
@@ -30,6 +31,10 @@ var message_outputs = require('./utils/message_outputs.cjs');
30
31
  * the accumulated content is already an array.
31
32
  */
32
33
  class CustomChatBedrockConverse extends aws.ChatBedrockConverse {
34
+ /**
35
+ * Whether to insert Bedrock prompt cache checkpoints when available.
36
+ */
37
+ promptCache;
33
38
  /**
34
39
  * Application Inference Profile ARN to use instead of model ID.
35
40
  */
@@ -40,6 +45,7 @@ class CustomChatBedrockConverse extends aws.ChatBedrockConverse {
40
45
  serviceTier;
41
46
  constructor(fields) {
42
47
  super(fields);
48
+ this.promptCache = fields?.promptCache;
43
49
  this.applicationInferenceProfile = fields?.applicationInferenceProfile;
44
50
  this.serviceTier = fields?.serviceTier;
45
51
  }
@@ -58,10 +64,14 @@ class CustomChatBedrockConverse extends aws.ChatBedrockConverse {
58
64
  */
59
65
  invocationParams(options) {
60
66
  const baseParams = super.invocationParams(options);
67
+ const toolConfig = this.promptCache === true
68
+ ? toolCache.insertBedrockToolCachePoint(baseParams.toolConfig)
69
+ : baseParams.toolConfig;
61
70
  /** Service tier from options or fall back to class-level setting */
62
71
  const serviceTierType = options?.serviceTier ?? this.serviceTier;
63
72
  return {
64
73
  ...baseParams,
74
+ toolConfig,
65
75
  serviceTier: serviceTierType ? { type: serviceTierType } : undefined,
66
76
  };
67
77
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../../../../src/llm/bedrock/index.ts"],"sourcesContent":["/**\n * Optimized ChatBedrockConverse wrapper that fixes content block merging for\n * streaming responses and adds support for latest @langchain/aws features:\n *\n * - Application Inference Profiles (PR #9129)\n * - Service Tiers (Priority/Standard/Flex) (PR #9785) - requires AWS SDK 3.966.0+\n *\n * Bedrock's `@langchain/aws` library does not include an `index` property on content\n * blocks (unlike Anthropic/OpenAI), which causes LangChain's `_mergeLists` to append\n * each streaming chunk as a separate array entry instead of merging by index.\n *\n * This wrapper takes full ownership of the stream by directly interfacing with the\n * AWS SDK client (`this.client`) and using custom handlers from `./utils/` that\n * include `contentBlockIndex` in response_metadata for every delta type. It then\n * promotes `contentBlockIndex` to an `index` property on each content block\n * (mirroring Anthropic's pattern) and strips it from metadata to avoid\n * `_mergeDicts` conflicts.\n *\n * When multiple content block types are present (e.g. reasoning + text), text deltas\n * are promoted from strings to array form with `index` so they merge correctly once\n * the accumulated content is already an array.\n */\n\nimport { ChatBedrockConverse } from '@langchain/aws';\nimport { ConverseStreamCommand } from '@aws-sdk/client-bedrock-runtime';\nimport { AIMessageChunk } from '@langchain/core/messages';\nimport { ChatGenerationChunk, ChatResult } from '@langchain/core/outputs';\nimport type { CallbackManagerForLLMRun } from '@langchain/core/callbacks/manager';\nimport type { ChatBedrockConverseInput } from '@langchain/aws';\nimport type { BaseMessage, ResponseMetadata } from '@langchain/core/messages';\nimport {\n convertToConverseMessages,\n handleConverseStreamContentBlockStart,\n handleConverseStreamContentBlockDelta,\n handleConverseStreamMetadata,\n} from './utils';\n\n/**\n * Service tier type for Bedrock invocations.\n * Requires AWS SDK >= 3.966.0 to actually work.\n * @see https://docs.aws.amazon.com/bedrock/latest/userguide/service-tiers-inference.html\n */\nexport type ServiceTierType = 'priority' | 'default' | 'flex' | 'reserved';\n\n/**\n * Extended input interface with additional features:\n * - applicationInferenceProfile: Use an inference profile ARN instead of model ID\n * - serviceTier: Specify service tier (Priority, Standard, Flex, Reserved)\n */\nexport interface CustomChatBedrockConverseInput\n extends ChatBedrockConverseInput {\n /**\n * Application Inference Profile ARN to use for the model.\n * For example, \"arn:aws:bedrock:eu-west-1:123456789102:application-inference-profile/fm16bt65tzgx\"\n * When provided, this ARN will be used for the actual inference calls instead of the model ID.\n * Must still provide `model` as normal modelId to benefit from all the metadata.\n * @see https://docs.aws.amazon.com/bedrock/latest/userguide/inference-profiles-create.html\n */\n applicationInferenceProfile?: string;\n\n /**\n * Service tier for model invocation.\n * Specifies the processing tier type used for serving the request.\n * Supported values are 'priority', 'default', 'flex', and 'reserved'.\n *\n * - 'priority': Prioritized processing for lower latency\n * - 'default': Standard processing tier\n * - 'flex': Flexible processing tier with lower cost\n * - 'reserved': Reserved capacity for consistent performance\n *\n * If not provided, AWS uses the default tier.\n * Note: Requires AWS SDK >= 3.966.0 to work.\n * @see https://docs.aws.amazon.com/bedrock/latest/userguide/service-tiers-inference.html\n */\n serviceTier?: ServiceTierType;\n}\n\n/**\n * Extended call options with serviceTier override support.\n */\nexport interface CustomChatBedrockConverseCallOptions {\n serviceTier?: ServiceTierType;\n}\n\nexport class CustomChatBedrockConverse extends ChatBedrockConverse {\n /**\n * Application Inference Profile ARN to use instead of model ID.\n */\n applicationInferenceProfile?: string;\n\n /**\n * Service tier for model invocation.\n */\n serviceTier?: ServiceTierType;\n\n constructor(fields?: CustomChatBedrockConverseInput) {\n super(fields);\n this.applicationInferenceProfile = fields?.applicationInferenceProfile;\n this.serviceTier = fields?.serviceTier;\n }\n\n static lc_name(): string {\n return 'LibreChatBedrockConverse';\n }\n\n /**\n * Get the model ID to use for API calls.\n * Returns applicationInferenceProfile if set, otherwise returns this.model.\n */\n protected getModelId(): string {\n return this.applicationInferenceProfile ?? this.model;\n }\n\n /**\n * Override invocationParams to add serviceTier support.\n */\n override invocationParams(\n options?: this['ParsedCallOptions'] & CustomChatBedrockConverseCallOptions\n ): ReturnType<ChatBedrockConverse['invocationParams']> & {\n serviceTier?: { type: ServiceTierType };\n } {\n const baseParams = super.invocationParams(options);\n\n /** Service tier from options or fall back to class-level setting */\n const serviceTierType = options?.serviceTier ?? this.serviceTier;\n\n return {\n ...baseParams,\n serviceTier: serviceTierType ? { type: serviceTierType } : undefined,\n };\n }\n\n /**\n * Override _generateNonStreaming to use applicationInferenceProfile as modelId.\n * Uses the same model-swapping pattern as streaming for consistency.\n */\n override async _generateNonStreaming(\n messages: BaseMessage[],\n options: this['ParsedCallOptions'] & CustomChatBedrockConverseCallOptions,\n runManager?: CallbackManagerForLLMRun\n ): Promise<ChatResult> {\n const originalModel = this.model;\n if (\n this.applicationInferenceProfile != null &&\n this.applicationInferenceProfile !== ''\n ) {\n this.model = this.applicationInferenceProfile;\n }\n\n try {\n return await super._generateNonStreaming(messages, options, runManager);\n } finally {\n this.model = originalModel;\n }\n }\n\n /**\n * Own the stream end-to-end so we have direct access to every\n * `contentBlockDelta.contentBlockIndex` from the AWS SDK.\n *\n * This replaces the parent's implementation which strips contentBlockIndex\n * from text and reasoning deltas, making it impossible to merge correctly.\n */\n override async *_streamResponseChunks(\n messages: BaseMessage[],\n options: this['ParsedCallOptions'] & CustomChatBedrockConverseCallOptions,\n runManager?: CallbackManagerForLLMRun\n ): AsyncGenerator<ChatGenerationChunk> {\n const { converseMessages, converseSystem } =\n convertToConverseMessages(messages);\n const params = this.invocationParams(options);\n\n let { streamUsage } = this;\n if ((options as Record<string, unknown>).streamUsage !== undefined) {\n streamUsage = (options as Record<string, unknown>).streamUsage as boolean;\n }\n\n const modelId = this.getModelId();\n\n const command = new ConverseStreamCommand({\n modelId,\n messages: converseMessages,\n system: converseSystem,\n ...(params as Record<string, unknown>),\n });\n\n const response = await this.client.send(command, {\n abortSignal: options.signal,\n });\n\n if (!response.stream) {\n return;\n }\n\n const seenBlockIndices = new Set<number>();\n\n for await (const event of response.stream) {\n if (event.contentBlockStart != null) {\n const startChunk = handleConverseStreamContentBlockStart(\n event.contentBlockStart\n );\n if (startChunk != null) {\n const idx = event.contentBlockStart.contentBlockIndex;\n if (idx != null) {\n seenBlockIndices.add(idx);\n }\n yield this.enrichChunk(startChunk, seenBlockIndices);\n }\n } else if (event.contentBlockDelta != null) {\n const deltaChunk = handleConverseStreamContentBlockDelta(\n event.contentBlockDelta\n );\n\n const idx = event.contentBlockDelta.contentBlockIndex;\n if (idx != null) {\n seenBlockIndices.add(idx);\n }\n\n yield this.enrichChunk(deltaChunk, seenBlockIndices);\n\n await runManager?.handleLLMNewToken(\n deltaChunk.text,\n undefined,\n undefined,\n undefined,\n undefined,\n { chunk: deltaChunk }\n );\n } else if (event.metadata != null) {\n yield handleConverseStreamMetadata(event.metadata, { streamUsage });\n } else if (event.contentBlockStop != null) {\n const stopIdx = event.contentBlockStop.contentBlockIndex;\n if (stopIdx != null) {\n seenBlockIndices.add(stopIdx);\n }\n } else {\n yield new ChatGenerationChunk({\n text: '',\n message: new AIMessageChunk({\n content: '',\n response_metadata: { ...event } as ResponseMetadata,\n }),\n });\n }\n }\n }\n\n /**\n * Inject `index` on content blocks for proper merge behaviour, then strip\n * `contentBlockIndex` from response_metadata to prevent `_mergeDicts` conflicts.\n *\n * Text string content is promoted to array form only when the stream contains\n * multiple content block indices (e.g. reasoning at index 0, text at index 1),\n * ensuring text merges correctly with the already-array accumulated content.\n */\n private enrichChunk(\n chunk: ChatGenerationChunk,\n seenBlockIndices: Set<number>\n ): ChatGenerationChunk {\n const message = chunk.message;\n if (!(message instanceof AIMessageChunk)) {\n return chunk;\n }\n\n const metadata = message.response_metadata as Record<string, unknown>;\n const blockIndex = this.extractContentBlockIndex(metadata);\n const hasMetadataIndex = blockIndex != null;\n\n let content: AIMessageChunk['content'] = message.content;\n let contentModified = false;\n\n if (Array.isArray(content) && blockIndex != null) {\n content = content.map((block) =>\n typeof block === 'object' && !('index' in block)\n ? { ...block, index: blockIndex }\n : block\n );\n contentModified = true;\n } else if (\n typeof content === 'string' &&\n content !== '' &&\n blockIndex != null &&\n seenBlockIndices.size > 1\n ) {\n content = [{ type: 'text', text: content, index: blockIndex }];\n contentModified = true;\n }\n\n if (!contentModified && !hasMetadataIndex) {\n return chunk;\n }\n\n const cleanedMetadata = hasMetadataIndex\n ? (this.removeContentBlockIndex(metadata) as Record<string, unknown>)\n : metadata;\n\n return new ChatGenerationChunk({\n text: chunk.text,\n message: new AIMessageChunk({\n ...message,\n content,\n response_metadata: cleanedMetadata,\n }),\n generationInfo: chunk.generationInfo,\n });\n }\n\n /**\n * Extract `contentBlockIndex` from the top level of response_metadata.\n * Our custom handlers always place it at the top level.\n */\n private extractContentBlockIndex(\n metadata: Record<string, unknown>\n ): number | undefined {\n if (\n 'contentBlockIndex' in metadata &&\n typeof metadata.contentBlockIndex === 'number'\n ) {\n return metadata.contentBlockIndex;\n }\n return undefined;\n }\n\n private removeContentBlockIndex(obj: unknown): unknown {\n if (obj === null || obj === undefined) {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => this.removeContentBlockIndex(item));\n }\n\n if (typeof obj === 'object') {\n const cleaned: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n if (key !== 'contentBlockIndex') {\n cleaned[key] = this.removeContentBlockIndex(value);\n }\n }\n return cleaned;\n }\n\n return obj;\n }\n}\n\nexport type { ChatBedrockConverseInput };\n"],"names":["ChatBedrockConverse","messages","convertToConverseMessages","ConverseStreamCommand","handleConverseStreamContentBlockStart","handleConverseStreamContentBlockDelta","handleConverseStreamMetadata","ChatGenerationChunk","AIMessageChunk"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../../../../src/llm/bedrock/index.ts"],"sourcesContent":["/**\n * Optimized ChatBedrockConverse wrapper that fixes content block merging for\n * streaming responses and adds support for latest @langchain/aws features:\n *\n * - Application Inference Profiles (PR #9129)\n * - Service Tiers (Priority/Standard/Flex) (PR #9785) - requires AWS SDK 3.966.0+\n *\n * Bedrock's `@langchain/aws` library does not include an `index` property on content\n * blocks (unlike Anthropic/OpenAI), which causes LangChain's `_mergeLists` to append\n * each streaming chunk as a separate array entry instead of merging by index.\n *\n * This wrapper takes full ownership of the stream by directly interfacing with the\n * AWS SDK client (`this.client`) and using custom handlers from `./utils/` that\n * include `contentBlockIndex` in response_metadata for every delta type. It then\n * promotes `contentBlockIndex` to an `index` property on each content block\n * (mirroring Anthropic's pattern) and strips it from metadata to avoid\n * `_mergeDicts` conflicts.\n *\n * When multiple content block types are present (e.g. reasoning + text), text deltas\n * are promoted from strings to array form with `index` so they merge correctly once\n * the accumulated content is already an array.\n */\n\nimport { ChatBedrockConverse } from '@langchain/aws';\nimport {\n ConverseStreamCommand,\n type GuardrailConfiguration,\n type GuardrailStreamConfiguration,\n} from '@aws-sdk/client-bedrock-runtime';\nimport { AIMessageChunk } from '@langchain/core/messages';\nimport { ChatGenerationChunk, ChatResult } from '@langchain/core/outputs';\nimport type { CallbackManagerForLLMRun } from '@langchain/core/callbacks/manager';\nimport type { ChatBedrockConverseInput } from '@langchain/aws';\nimport type { BaseMessage, ResponseMetadata } from '@langchain/core/messages';\nimport { insertBedrockToolCachePoint } from './toolCache';\nimport {\n convertToConverseMessages,\n handleConverseStreamContentBlockStart,\n handleConverseStreamContentBlockDelta,\n handleConverseStreamMetadata,\n} from './utils';\n\n/**\n * Service tier type for Bedrock invocations.\n * Requires AWS SDK >= 3.966.0 to actually work.\n * @see https://docs.aws.amazon.com/bedrock/latest/userguide/service-tiers-inference.html\n */\nexport type ServiceTierType = 'priority' | 'default' | 'flex' | 'reserved';\n\nexport type CustomGuardrailConfiguration = GuardrailConfiguration &\n Pick<GuardrailStreamConfiguration, 'streamProcessingMode'>;\n\n/**\n * Extended input interface with additional features:\n * - applicationInferenceProfile: Use an inference profile ARN instead of model ID\n * - serviceTier: Specify service tier (Priority, Standard, Flex, Reserved)\n */\nexport interface CustomChatBedrockConverseInput\n extends ChatBedrockConverseInput {\n /**\n * Enables Bedrock prompt cache checkpoints for message and tool prefixes.\n */\n promptCache?: boolean;\n\n /**\n * Guardrail configuration for Converse and ConverseStream invocations.\n * `streamProcessingMode` is only used by ConverseStream.\n */\n guardrailConfig?: CustomGuardrailConfiguration;\n\n /**\n * Application Inference Profile ARN to use for the model.\n * For example, \"arn:aws:bedrock:eu-west-1:123456789102:application-inference-profile/fm16bt65tzgx\"\n * When provided, this ARN will be used for the actual inference calls instead of the model ID.\n * Must still provide `model` as normal modelId to benefit from all the metadata.\n * @see https://docs.aws.amazon.com/bedrock/latest/userguide/inference-profiles-create.html\n */\n applicationInferenceProfile?: string;\n\n /**\n * Service tier for model invocation.\n * Specifies the processing tier type used for serving the request.\n * Supported values are 'priority', 'default', 'flex', and 'reserved'.\n *\n * - 'priority': Prioritized processing for lower latency\n * - 'default': Standard processing tier\n * - 'flex': Flexible processing tier with lower cost\n * - 'reserved': Reserved capacity for consistent performance\n *\n * If not provided, AWS uses the default tier.\n * Note: Requires AWS SDK >= 3.966.0 to work.\n * @see https://docs.aws.amazon.com/bedrock/latest/userguide/service-tiers-inference.html\n */\n serviceTier?: ServiceTierType;\n}\n\n/**\n * Extended call options with serviceTier override support.\n */\nexport interface CustomChatBedrockConverseCallOptions {\n serviceTier?: ServiceTierType;\n guardrailConfig?: CustomGuardrailConfiguration;\n}\n\nexport class CustomChatBedrockConverse extends ChatBedrockConverse {\n /**\n * Whether to insert Bedrock prompt cache checkpoints when available.\n */\n promptCache?: boolean;\n\n /**\n * Application Inference Profile ARN to use instead of model ID.\n */\n applicationInferenceProfile?: string;\n\n /**\n * Service tier for model invocation.\n */\n serviceTier?: ServiceTierType;\n\n constructor(fields?: CustomChatBedrockConverseInput) {\n super(fields);\n this.promptCache = fields?.promptCache;\n this.applicationInferenceProfile = fields?.applicationInferenceProfile;\n this.serviceTier = fields?.serviceTier;\n }\n\n static lc_name(): string {\n return 'LibreChatBedrockConverse';\n }\n\n /**\n * Get the model ID to use for API calls.\n * Returns applicationInferenceProfile if set, otherwise returns this.model.\n */\n protected getModelId(): string {\n return this.applicationInferenceProfile ?? this.model;\n }\n\n /**\n * Override invocationParams to add serviceTier support.\n */\n override invocationParams(\n options?: this['ParsedCallOptions'] & CustomChatBedrockConverseCallOptions\n ): ReturnType<ChatBedrockConverse['invocationParams']> & {\n serviceTier?: { type: ServiceTierType };\n } {\n const baseParams = super.invocationParams(options);\n const toolConfig =\n this.promptCache === true\n ? insertBedrockToolCachePoint(baseParams.toolConfig, true)\n : baseParams.toolConfig;\n\n /** Service tier from options or fall back to class-level setting */\n const serviceTierType = options?.serviceTier ?? this.serviceTier;\n\n return {\n ...baseParams,\n toolConfig,\n serviceTier: serviceTierType ? { type: serviceTierType } : undefined,\n };\n }\n\n /**\n * Override _generateNonStreaming to use applicationInferenceProfile as modelId.\n * Uses the same model-swapping pattern as streaming for consistency.\n */\n override async _generateNonStreaming(\n messages: BaseMessage[],\n options: this['ParsedCallOptions'] & CustomChatBedrockConverseCallOptions,\n runManager?: CallbackManagerForLLMRun\n ): Promise<ChatResult> {\n const originalModel = this.model;\n if (\n this.applicationInferenceProfile != null &&\n this.applicationInferenceProfile !== ''\n ) {\n this.model = this.applicationInferenceProfile;\n }\n\n try {\n return await super._generateNonStreaming(messages, options, runManager);\n } finally {\n this.model = originalModel;\n }\n }\n\n /**\n * Own the stream end-to-end so we have direct access to every\n * `contentBlockDelta.contentBlockIndex` from the AWS SDK.\n *\n * This replaces the parent's implementation which strips contentBlockIndex\n * from text and reasoning deltas, making it impossible to merge correctly.\n */\n override async *_streamResponseChunks(\n messages: BaseMessage[],\n options: this['ParsedCallOptions'] & CustomChatBedrockConverseCallOptions,\n runManager?: CallbackManagerForLLMRun\n ): AsyncGenerator<ChatGenerationChunk> {\n const { converseMessages, converseSystem } =\n convertToConverseMessages(messages);\n const params = this.invocationParams(options);\n\n let { streamUsage } = this;\n if ((options as Record<string, unknown>).streamUsage !== undefined) {\n streamUsage = (options as Record<string, unknown>).streamUsage as boolean;\n }\n\n const modelId = this.getModelId();\n\n const command = new ConverseStreamCommand({\n modelId,\n messages: converseMessages,\n system: converseSystem,\n ...(params as Record<string, unknown>),\n });\n\n const response = await this.client.send(command, {\n abortSignal: options.signal,\n });\n\n if (!response.stream) {\n return;\n }\n\n const seenBlockIndices = new Set<number>();\n\n for await (const event of response.stream) {\n if (event.contentBlockStart != null) {\n const startChunk = handleConverseStreamContentBlockStart(\n event.contentBlockStart\n );\n if (startChunk != null) {\n const idx = event.contentBlockStart.contentBlockIndex;\n if (idx != null) {\n seenBlockIndices.add(idx);\n }\n yield this.enrichChunk(startChunk, seenBlockIndices);\n }\n } else if (event.contentBlockDelta != null) {\n const deltaChunk = handleConverseStreamContentBlockDelta(\n event.contentBlockDelta\n );\n\n const idx = event.contentBlockDelta.contentBlockIndex;\n if (idx != null) {\n seenBlockIndices.add(idx);\n }\n\n yield this.enrichChunk(deltaChunk, seenBlockIndices);\n\n await runManager?.handleLLMNewToken(\n deltaChunk.text,\n undefined,\n undefined,\n undefined,\n undefined,\n { chunk: deltaChunk }\n );\n } else if (event.metadata != null) {\n yield handleConverseStreamMetadata(event.metadata, { streamUsage });\n } else if (event.contentBlockStop != null) {\n const stopIdx = event.contentBlockStop.contentBlockIndex;\n if (stopIdx != null) {\n seenBlockIndices.add(stopIdx);\n }\n } else {\n yield new ChatGenerationChunk({\n text: '',\n message: new AIMessageChunk({\n content: '',\n response_metadata: { ...event } as ResponseMetadata,\n }),\n });\n }\n }\n }\n\n /**\n * Inject `index` on content blocks for proper merge behaviour, then strip\n * `contentBlockIndex` from response_metadata to prevent `_mergeDicts` conflicts.\n *\n * Text string content is promoted to array form only when the stream contains\n * multiple content block indices (e.g. reasoning at index 0, text at index 1),\n * ensuring text merges correctly with the already-array accumulated content.\n */\n private enrichChunk(\n chunk: ChatGenerationChunk,\n seenBlockIndices: Set<number>\n ): ChatGenerationChunk {\n const message = chunk.message;\n if (!(message instanceof AIMessageChunk)) {\n return chunk;\n }\n\n const metadata = message.response_metadata as Record<string, unknown>;\n const blockIndex = this.extractContentBlockIndex(metadata);\n const hasMetadataIndex = blockIndex != null;\n\n let content: AIMessageChunk['content'] = message.content;\n let contentModified = false;\n\n if (Array.isArray(content) && blockIndex != null) {\n content = content.map((block) =>\n typeof block === 'object' && !('index' in block)\n ? { ...block, index: blockIndex }\n : block\n );\n contentModified = true;\n } else if (\n typeof content === 'string' &&\n content !== '' &&\n blockIndex != null &&\n seenBlockIndices.size > 1\n ) {\n content = [{ type: 'text', text: content, index: blockIndex }];\n contentModified = true;\n }\n\n if (!contentModified && !hasMetadataIndex) {\n return chunk;\n }\n\n const cleanedMetadata = hasMetadataIndex\n ? (this.removeContentBlockIndex(metadata) as Record<string, unknown>)\n : metadata;\n\n return new ChatGenerationChunk({\n text: chunk.text,\n message: new AIMessageChunk({\n ...message,\n content,\n response_metadata: cleanedMetadata,\n }),\n generationInfo: chunk.generationInfo,\n });\n }\n\n /**\n * Extract `contentBlockIndex` from the top level of response_metadata.\n * Our custom handlers always place it at the top level.\n */\n private extractContentBlockIndex(\n metadata: Record<string, unknown>\n ): number | undefined {\n if (\n 'contentBlockIndex' in metadata &&\n typeof metadata.contentBlockIndex === 'number'\n ) {\n return metadata.contentBlockIndex;\n }\n return undefined;\n }\n\n private removeContentBlockIndex(obj: unknown): unknown {\n if (obj === null || obj === undefined) {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => this.removeContentBlockIndex(item));\n }\n\n if (typeof obj === 'object') {\n const cleaned: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n if (key !== 'contentBlockIndex') {\n cleaned[key] = this.removeContentBlockIndex(value);\n }\n }\n return cleaned;\n }\n\n return obj;\n }\n}\n\nexport type { ChatBedrockConverseInput };\n"],"names":["ChatBedrockConverse","insertBedrockToolCachePoint","messages","convertToConverseMessages","ConverseStreamCommand","handleConverseStreamContentBlockStart","handleConverseStreamContentBlockDelta","handleConverseStreamMetadata","ChatGenerationChunk","AIMessageChunk"],"mappings":";;;;;;;;;;AAAA;;;;;;;;;;;;;;;;;;;;;AAqBG;AAmFG,MAAO,yBAA0B,SAAQA,uBAAmB,CAAA;AAChE;;AAEG;AACH,IAAA,WAAW;AAEX;;AAEG;AACH,IAAA,2BAA2B;AAE3B;;AAEG;AACH,IAAA,WAAW;AAEX,IAAA,WAAA,CAAY,MAAuC,EAAA;QACjD,KAAK,CAAC,MAAM,CAAC;AACb,QAAA,IAAI,CAAC,WAAW,GAAG,MAAM,EAAE,WAAW;AACtC,QAAA,IAAI,CAAC,2BAA2B,GAAG,MAAM,EAAE,2BAA2B;AACtE,QAAA,IAAI,CAAC,WAAW,GAAG,MAAM,EAAE,WAAW;IACxC;AAEA,IAAA,OAAO,OAAO,GAAA;AACZ,QAAA,OAAO,0BAA0B;IACnC;AAEA;;;AAGG;IACO,UAAU,GAAA;AAClB,QAAA,OAAO,IAAI,CAAC,2BAA2B,IAAI,IAAI,CAAC,KAAK;IACvD;AAEA;;AAEG;AACM,IAAA,gBAAgB,CACvB,OAA0E,EAAA;QAI1E,MAAM,UAAU,GAAG,KAAK,CAAC,gBAAgB,CAAC,OAAO,CAAC;AAClD,QAAA,MAAM,UAAU,GACd,IAAI,CAAC,WAAW,KAAK;cACjBC,qCAA2B,CAAC,UAAU,CAAC,UAAgB;AACzD,cAAE,UAAU,CAAC,UAAU;;QAG3B,MAAM,eAAe,GAAG,OAAO,EAAE,WAAW,IAAI,IAAI,CAAC,WAAW;QAEhE,OAAO;AACL,YAAA,GAAG,UAAU;YACb,UAAU;AACV,YAAA,WAAW,EAAE,eAAe,GAAG,EAAE,IAAI,EAAE,eAAe,EAAE,GAAG,SAAS;SACrE;IACH;AAEA;;;AAGG;AACM,IAAA,MAAM,qBAAqB,CAClC,QAAuB,EACvB,OAAyE,EACzE,UAAqC,EAAA;AAErC,QAAA,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK;AAChC,QAAA,IACE,IAAI,CAAC,2BAA2B,IAAI,IAAI;AACxC,YAAA,IAAI,CAAC,2BAA2B,KAAK,EAAE,EACvC;AACA,YAAA,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,2BAA2B;QAC/C;AAEA,QAAA,IAAI;YACF,OAAO,MAAM,KAAK,CAAC,qBAAqB,CAAC,QAAQ,EAAE,OAAO,EAAE,UAAU,CAAC;QACzE;gBAAU;AACR,YAAA,IAAI,CAAC,KAAK,GAAG,aAAa;QAC5B;IACF;AAEA;;;;;;AAMG;IACM,OAAO,qBAAqB,CACnCC,UAAuB,EACvB,OAAyE,EACzE,UAAqC,EAAA;QAErC,MAAM,EAAE,gBAAgB,EAAE,cAAc,EAAE,GACxCC,wCAAyB,CAACD,UAAQ,CAAC;QACrC,MAAM,MAAM,GAAG,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC;AAE7C,QAAA,IAAI,EAAE,WAAW,EAAE,GAAG,IAAI;AAC1B,QAAA,IAAK,OAAmC,CAAC,WAAW,KAAK,SAAS,EAAE;AAClE,YAAA,WAAW,GAAI,OAAmC,CAAC,WAAsB;QAC3E;AAEA,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,EAAE;AAEjC,QAAA,MAAM,OAAO,GAAG,IAAIE,0CAAqB,CAAC;YACxC,OAAO;AACP,YAAA,QAAQ,EAAE,gBAAgB;AAC1B,YAAA,MAAM,EAAE,cAAc;AACtB,YAAA,GAAI,MAAkC;AACvC,SAAA,CAAC;QAEF,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE;YAC/C,WAAW,EAAE,OAAO,CAAC,MAAM;AAC5B,SAAA,CAAC;AAEF,QAAA,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE;YACpB;QACF;AAEA,QAAA,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAU;QAE1C,WAAW,MAAM,KAAK,IAAI,QAAQ,CAAC,MAAM,EAAE;AACzC,YAAA,IAAI,KAAK,CAAC,iBAAiB,IAAI,IAAI,EAAE;gBACnC,MAAM,UAAU,GAAGC,qDAAqC,CACtD,KAAK,CAAC,iBAAiB,CACxB;AACD,gBAAA,IAAI,UAAU,IAAI,IAAI,EAAE;AACtB,oBAAA,MAAM,GAAG,GAAG,KAAK,CAAC,iBAAiB,CAAC,iBAAiB;AACrD,oBAAA,IAAI,GAAG,IAAI,IAAI,EAAE;AACf,wBAAA,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC;oBAC3B;oBACA,MAAM,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,gBAAgB,CAAC;gBACtD;YACF;AAAO,iBAAA,IAAI,KAAK,CAAC,iBAAiB,IAAI,IAAI,EAAE;gBAC1C,MAAM,UAAU,GAAGC,qDAAqC,CACtD,KAAK,CAAC,iBAAiB,CACxB;AAED,gBAAA,MAAM,GAAG,GAAG,KAAK,CAAC,iBAAiB,CAAC,iBAAiB;AACrD,gBAAA,IAAI,GAAG,IAAI,IAAI,EAAE;AACf,oBAAA,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC;gBAC3B;gBAEA,MAAM,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,gBAAgB,CAAC;gBAEpD,MAAM,UAAU,EAAE,iBAAiB,CACjC,UAAU,CAAC,IAAI,EACf,SAAS,EACT,SAAS,EACT,SAAS,EACT,SAAS,EACT,EAAE,KAAK,EAAE,UAAU,EAAE,CACtB;YACH;AAAO,iBAAA,IAAI,KAAK,CAAC,QAAQ,IAAI,IAAI,EAAE;gBACjC,MAAMC,4CAA4B,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,WAAW,EAAE,CAAC;YACrE;AAAO,iBAAA,IAAI,KAAK,CAAC,gBAAgB,IAAI,IAAI,EAAE;AACzC,gBAAA,MAAM,OAAO,GAAG,KAAK,CAAC,gBAAgB,CAAC,iBAAiB;AACxD,gBAAA,IAAI,OAAO,IAAI,IAAI,EAAE;AACnB,oBAAA,gBAAgB,CAAC,GAAG,CAAC,OAAO,CAAC;gBAC/B;YACF;iBAAO;gBACL,MAAM,IAAIC,2BAAmB,CAAC;AAC5B,oBAAA,IAAI,EAAE,EAAE;oBACR,OAAO,EAAE,IAAIC,uBAAc,CAAC;AAC1B,wBAAA,OAAO,EAAE,EAAE;AACX,wBAAA,iBAAiB,EAAE,EAAE,GAAG,KAAK,EAAsB;qBACpD,CAAC;AACH,iBAAA,CAAC;YACJ;QACF;IACF;AAEA;;;;;;;AAOG;IACK,WAAW,CACjB,KAA0B,EAC1B,gBAA6B,EAAA;AAE7B,QAAA,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO;AAC7B,QAAA,IAAI,EAAE,OAAO,YAAYA,uBAAc,CAAC,EAAE;AACxC,YAAA,OAAO,KAAK;QACd;AAEA,QAAA,MAAM,QAAQ,GAAG,OAAO,CAAC,iBAA4C;QACrE,MAAM,UAAU,GAAG,IAAI,CAAC,wBAAwB,CAAC,QAAQ,CAAC;AAC1D,QAAA,MAAM,gBAAgB,GAAG,UAAU,IAAI,IAAI;AAE3C,QAAA,IAAI,OAAO,GAA8B,OAAO,CAAC,OAAO;QACxD,IAAI,eAAe,GAAG,KAAK;QAE3B,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,UAAU,IAAI,IAAI,EAAE;YAChD,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,KAC1B,OAAO,KAAK,KAAK,QAAQ,IAAI,EAAE,OAAO,IAAI,KAAK;kBAC3C,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,UAAU;kBAC7B,KAAK,CACV;YACD,eAAe,GAAG,IAAI;QACxB;aAAO,IACL,OAAO,OAAO,KAAK,QAAQ;AAC3B,YAAA,OAAO,KAAK,EAAE;AACd,YAAA,UAAU,IAAI,IAAI;AAClB,YAAA,gBAAgB,CAAC,IAAI,GAAG,CAAC,EACzB;AACA,YAAA,OAAO,GAAG,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;YAC9D,eAAe,GAAG,IAAI;QACxB;AAEA,QAAA,IAAI,CAAC,eAAe,IAAI,CAAC,gBAAgB,EAAE;AACzC,YAAA,OAAO,KAAK;QACd;QAEA,MAAM,eAAe,GAAG;AACtB,cAAG,IAAI,CAAC,uBAAuB,CAAC,QAAQ;cACtC,QAAQ;QAEZ,OAAO,IAAID,2BAAmB,CAAC;YAC7B,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,OAAO,EAAE,IAAIC,uBAAc,CAAC;AAC1B,gBAAA,GAAG,OAAO;gBACV,OAAO;AACP,gBAAA,iBAAiB,EAAE,eAAe;aACnC,CAAC;YACF,cAAc,EAAE,KAAK,CAAC,cAAc;AACrC,SAAA,CAAC;IACJ;AAEA;;;AAGG;AACK,IAAA,wBAAwB,CAC9B,QAAiC,EAAA;QAEjC,IACE,mBAAmB,IAAI,QAAQ;AAC/B,YAAA,OAAO,QAAQ,CAAC,iBAAiB,KAAK,QAAQ,EAC9C;YACA,OAAO,QAAQ,CAAC,iBAAiB;QACnC;AACA,QAAA,OAAO,SAAS;IAClB;AAEQ,IAAA,uBAAuB,CAAC,GAAY,EAAA;QAC1C,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,SAAS,EAAE;AACrC,YAAA,OAAO,GAAG;QACZ;AAEA,QAAA,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;AACtB,YAAA,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,CAAC;QAC9D;AAEA,QAAA,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE;YAC3B,MAAM,OAAO,GAA4B,EAAE;AAC3C,YAAA,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;AAC9C,gBAAA,IAAI,GAAG,KAAK,mBAAmB,EAAE;oBAC/B,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,uBAAuB,CAAC,KAAK,CAAC;gBACpD;YACF;AACA,YAAA,OAAO,OAAO;QAChB;AAEA,QAAA,OAAO,GAAG;IACZ;AACD;;;;"}
@@ -0,0 +1,125 @@
1
+ 'use strict';
2
+
3
+ var index = require('../openai/index.cjs');
4
+
5
+ const CACHE_POINT = {
6
+ cachePoint: { type: 'default' },
7
+ };
8
+ const BEDROCK_TOOL_CACHE_MARKER = '__lc_bedrock_cache_point_after';
9
+ const BEDROCK_TOOL_CACHE_DISABLED_MARKER = '__lc_bedrock_skip_tool_cache';
10
+ function isBedrockToolSpec(tool) {
11
+ return (typeof tool === 'object' &&
12
+ tool != null &&
13
+ 'toolSpec' in tool &&
14
+ typeof tool.toolSpec?.name === 'string');
15
+ }
16
+ function isBedrockCachePoint(tool) {
17
+ return 'cachePoint' in tool && tool.cachePoint != null;
18
+ }
19
+ function getToolName(tool) {
20
+ const candidate = tool;
21
+ if (typeof candidate.toolSpec?.name === 'string') {
22
+ return candidate.toolSpec.name;
23
+ }
24
+ if (typeof candidate.name === 'string') {
25
+ return candidate.name;
26
+ }
27
+ if (typeof candidate.function?.name === 'string') {
28
+ return candidate.function.name;
29
+ }
30
+ return undefined;
31
+ }
32
+ function openAIToBedrockTool(tool) {
33
+ return {
34
+ toolSpec: {
35
+ name: tool.function.name,
36
+ description: tool.function.description,
37
+ inputSchema: { json: tool.function.parameters },
38
+ },
39
+ };
40
+ }
41
+ function toBedrockTool(tool) {
42
+ if (isBedrockToolSpec(tool)) {
43
+ return { ...tool };
44
+ }
45
+ return openAIToBedrockTool(index._convertToOpenAITool(tool));
46
+ }
47
+ function markCachePointAfter(tool) {
48
+ return {
49
+ ...tool,
50
+ [BEDROCK_TOOL_CACHE_MARKER]: true,
51
+ };
52
+ }
53
+ function markToolCacheDisabled(tool) {
54
+ return {
55
+ ...tool,
56
+ [BEDROCK_TOOL_CACHE_DISABLED_MARKER]: true,
57
+ };
58
+ }
59
+ function stripCachePointMarker(tool) {
60
+ const { [BEDROCK_TOOL_CACHE_MARKER]: _marker, [BEDROCK_TOOL_CACHE_DISABLED_MARKER]: _disabled, ...rest } = tool;
61
+ return rest;
62
+ }
63
+ function partitionAndMarkBedrockToolCache(tools, isDeferred) {
64
+ if (tools == null || tools.length === 0) {
65
+ return tools;
66
+ }
67
+ const staticTools = [];
68
+ const deferredTools = [];
69
+ for (const tool of tools) {
70
+ const converted = toBedrockTool(tool);
71
+ const name = getToolName(converted) ?? getToolName(tool);
72
+ if (name != null && isDeferred(name)) {
73
+ deferredTools.push(converted);
74
+ continue;
75
+ }
76
+ staticTools.push(converted);
77
+ }
78
+ if (staticTools.length === 0) {
79
+ deferredTools[0] = markToolCacheDisabled(deferredTools[0]);
80
+ return [...deferredTools];
81
+ }
82
+ staticTools[staticTools.length - 1] = markCachePointAfter(staticTools[staticTools.length - 1]);
83
+ return [...staticTools, ...deferredTools];
84
+ }
85
+ function insertBedrockToolCachePoint(toolConfig, fallbackToEnd) {
86
+ const tools = toolConfig?.tools;
87
+ if (tools == null || tools.length === 0) {
88
+ return toolConfig;
89
+ }
90
+ let markerIndex = -1;
91
+ let hasCachePoint = false;
92
+ let hasDisabledMarker = false;
93
+ const cleanedTools = [];
94
+ for (let i = 0; i < tools.length; i++) {
95
+ const tool = tools[i];
96
+ if (isBedrockCachePoint(tool)) {
97
+ hasCachePoint = true;
98
+ cleanedTools.push(tool);
99
+ continue;
100
+ }
101
+ if (tool[BEDROCK_TOOL_CACHE_MARKER] === true) {
102
+ markerIndex = cleanedTools.length;
103
+ }
104
+ if (tool[BEDROCK_TOOL_CACHE_DISABLED_MARKER] === true) {
105
+ hasDisabledMarker = true;
106
+ }
107
+ cleanedTools.push(stripCachePointMarker(tool));
108
+ }
109
+ if (hasCachePoint || hasDisabledMarker) {
110
+ return { ...toolConfig, tools: cleanedTools };
111
+ }
112
+ const insertionIndex = markerIndex >= 0 ? markerIndex : tools.length - 1;
113
+ return {
114
+ ...toolConfig,
115
+ tools: [
116
+ ...cleanedTools.slice(0, insertionIndex + 1),
117
+ CACHE_POINT,
118
+ ...cleanedTools.slice(insertionIndex + 1),
119
+ ],
120
+ };
121
+ }
122
+
123
+ exports.insertBedrockToolCachePoint = insertBedrockToolCachePoint;
124
+ exports.partitionAndMarkBedrockToolCache = partitionAndMarkBedrockToolCache;
125
+ //# sourceMappingURL=toolCache.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolCache.cjs","sources":["../../../../src/llm/bedrock/toolCache.ts"],"sourcesContent":["import type { Tool, ToolConfiguration } from '@aws-sdk/client-bedrock-runtime';\nimport type { BindToolsInput } from '@langchain/core/language_models/chat_models';\nimport type { OpenAIClient } from '@langchain/openai';\nimport type { DocumentType } from '@smithy/types';\nimport type { GraphTools } from '@/types';\nimport { _convertToOpenAITool } from '@/llm/openai';\n\nconst CACHE_POINT: Tool.CachePointMember = {\n cachePoint: { type: 'default' },\n};\n\nconst BEDROCK_TOOL_CACHE_MARKER = '__lc_bedrock_cache_point_after';\nconst BEDROCK_TOOL_CACHE_DISABLED_MARKER = '__lc_bedrock_skip_tool_cache';\n\ntype BedrockToolWithCacheMarker = Tool & {\n [BEDROCK_TOOL_CACHE_MARKER]?: true;\n [BEDROCK_TOOL_CACHE_DISABLED_MARKER]?: true;\n};\n\ntype OpenAIFunctionTool = Extract<\n OpenAIClient.ChatCompletionTool,\n { type: 'function' }\n>;\n\ntype ToolNameCandidate = {\n name?: unknown;\n function?: {\n name?: unknown;\n };\n toolSpec?: {\n name?: unknown;\n };\n};\n\nfunction isBedrockToolSpec(tool: unknown): tool is Tool.ToolSpecMember {\n return (\n typeof tool === 'object' &&\n tool != null &&\n 'toolSpec' in tool &&\n typeof (tool as ToolNameCandidate).toolSpec?.name === 'string'\n );\n}\n\nfunction isBedrockCachePoint(tool: Tool): tool is Tool.CachePointMember {\n return 'cachePoint' in tool && tool.cachePoint != null;\n}\n\nfunction getToolName(tool: unknown): string | undefined {\n const candidate = tool as ToolNameCandidate;\n if (typeof candidate.toolSpec?.name === 'string') {\n return candidate.toolSpec.name;\n }\n if (typeof candidate.name === 'string') {\n return candidate.name;\n }\n if (typeof candidate.function?.name === 'string') {\n return candidate.function.name;\n }\n return undefined;\n}\n\nfunction openAIToBedrockTool(tool: OpenAIFunctionTool): Tool.ToolSpecMember {\n return {\n toolSpec: {\n name: tool.function.name,\n description: tool.function.description,\n inputSchema: { json: tool.function.parameters as DocumentType },\n },\n };\n}\n\nfunction toBedrockTool(tool: unknown): BedrockToolWithCacheMarker {\n if (isBedrockToolSpec(tool)) {\n return { ...tool };\n }\n\n return openAIToBedrockTool(\n _convertToOpenAITool(tool as BindToolsInput) as OpenAIFunctionTool\n ) as BedrockToolWithCacheMarker;\n}\n\nfunction markCachePointAfter(\n tool: BedrockToolWithCacheMarker\n): BedrockToolWithCacheMarker {\n return {\n ...tool,\n [BEDROCK_TOOL_CACHE_MARKER]: true,\n };\n}\n\nfunction markToolCacheDisabled(\n tool: BedrockToolWithCacheMarker\n): BedrockToolWithCacheMarker {\n return {\n ...tool,\n [BEDROCK_TOOL_CACHE_DISABLED_MARKER]: true,\n };\n}\n\nfunction stripCachePointMarker(tool: BedrockToolWithCacheMarker): Tool {\n const {\n [BEDROCK_TOOL_CACHE_MARKER]: _marker,\n [BEDROCK_TOOL_CACHE_DISABLED_MARKER]: _disabled,\n ...rest\n } = tool;\n return rest as Tool;\n}\n\nexport function partitionAndMarkBedrockToolCache(\n tools: GraphTools | undefined,\n isDeferred: (toolName: string) => boolean\n): GraphTools | undefined {\n if (tools == null || tools.length === 0) {\n return tools;\n }\n\n const staticTools: BedrockToolWithCacheMarker[] = [];\n const deferredTools: BedrockToolWithCacheMarker[] = [];\n\n for (const tool of tools as readonly unknown[]) {\n const converted = toBedrockTool(tool);\n const name = getToolName(converted) ?? getToolName(tool);\n\n if (name != null && isDeferred(name)) {\n deferredTools.push(converted);\n continue;\n }\n\n staticTools.push(converted);\n }\n\n if (staticTools.length === 0) {\n deferredTools[0] = markToolCacheDisabled(deferredTools[0]);\n return [...deferredTools] as GraphTools;\n }\n\n staticTools[staticTools.length - 1] = markCachePointAfter(\n staticTools[staticTools.length - 1]\n );\n\n return [...staticTools, ...deferredTools] as GraphTools;\n}\n\nexport function insertBedrockToolCachePoint(\n toolConfig: ToolConfiguration | undefined,\n fallbackToEnd: boolean\n): ToolConfiguration | undefined {\n const tools = toolConfig?.tools as BedrockToolWithCacheMarker[] | undefined;\n if (tools == null || tools.length === 0) {\n return toolConfig;\n }\n\n let markerIndex = -1;\n let hasCachePoint = false;\n let hasDisabledMarker = false;\n const cleanedTools: Tool[] = [];\n\n for (let i = 0; i < tools.length; i++) {\n const tool = tools[i];\n if (isBedrockCachePoint(tool)) {\n hasCachePoint = true;\n cleanedTools.push(tool);\n continue;\n }\n if (tool[BEDROCK_TOOL_CACHE_MARKER] === true) {\n markerIndex = cleanedTools.length;\n }\n if (tool[BEDROCK_TOOL_CACHE_DISABLED_MARKER] === true) {\n hasDisabledMarker = true;\n }\n cleanedTools.push(stripCachePointMarker(tool));\n }\n\n if (hasCachePoint || hasDisabledMarker) {\n return { ...toolConfig, tools: cleanedTools };\n }\n\n const insertionIndex = markerIndex >= 0 ? markerIndex : tools.length - 1;\n if (markerIndex < 0 && !fallbackToEnd) {\n return { ...toolConfig, tools: cleanedTools };\n }\n\n return {\n ...toolConfig,\n tools: [\n ...cleanedTools.slice(0, insertionIndex + 1),\n CACHE_POINT,\n ...cleanedTools.slice(insertionIndex + 1),\n ],\n };\n}\n"],"names":["_convertToOpenAITool"],"mappings":"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"}
@@ -336,22 +336,22 @@ function stripBedrockCacheControl(messages) {
336
336
  return updatedMessages;
337
337
  }
338
338
  /**
339
- * Adds Bedrock Converse API cache points to the last two messages.
339
+ * Adds Bedrock Converse API cache points to the latest two user messages.
340
340
  * Inserts `{ cachePoint: { type: 'default' } }` as a separate content block
341
341
  * immediately after the last text block in each targeted message.
342
342
  * Strips ALL existing cache control (both Bedrock and Anthropic formats) from all messages,
343
- * then adds fresh cache points to the last 2 messages in a single backward pass.
343
+ * then adds fresh cache points to the latest two non-tool user messages in a single backward pass.
344
344
  * This ensures we don't accumulate stale cache points across multiple turns.
345
345
  * Returns a new array - only clones messages that require modification.
346
346
  * @param messages - The array of message objects.
347
347
  * @returns - A new array of message objects with cache points added.
348
348
  */
349
349
  function addBedrockCacheControl(messages) {
350
- if (!Array.isArray(messages) || messages.length < 2) {
350
+ if (!Array.isArray(messages) || messages.length === 0) {
351
351
  return messages;
352
352
  }
353
353
  const updatedMessages = [...messages];
354
- let messagesModified = 0;
354
+ let cachePointsAdded = 0;
355
355
  for (let i = updatedMessages.length - 1; i >= 0; i--) {
356
356
  const originalMessage = updatedMessages[i];
357
357
  const messageType = 'getType' in originalMessage &&
@@ -367,18 +367,23 @@ function addBedrockCacheControl(messages) {
367
367
  continue;
368
368
  }
369
369
  const isToolMessage = messageType === 'tool' || messageRole === 'tool';
370
+ const isUserMessage = messageType === 'human' || messageRole === 'user';
370
371
  const content = originalMessage.content;
372
+ const hasSerializationProps = 'lc_kwargs' in originalMessage ||
373
+ 'lc_serializable' in originalMessage ||
374
+ 'lc_namespace' in originalMessage;
371
375
  const hasArrayContent = Array.isArray(content);
372
376
  const isEmptyString = typeof content === 'string' && content === '';
373
- const needsCacheAdd = messagesModified < 2 &&
377
+ const needsCacheAdd = cachePointsAdded < 2 &&
378
+ isUserMessage &&
374
379
  !isToolMessage &&
375
380
  !isEmptyString &&
376
381
  (typeof content === 'string' || hasArrayContent);
377
- if (!needsCacheAdd && !hasArrayContent) {
382
+ if (!needsCacheAdd && !hasArrayContent && !hasSerializationProps) {
378
383
  continue;
379
384
  }
380
385
  let workingContent;
381
- let modified = false;
386
+ let modified = hasSerializationProps;
382
387
  if (hasArrayContent) {
383
388
  // Single pass: clone blocks, strip cache markers, find last
384
389
  // non-empty text block for cache point insertion — all at once.
@@ -414,7 +419,7 @@ function addBedrockCacheControl(messages) {
414
419
  workingContent.splice(lastNonEmptyTextIndex + 1, 0, {
415
420
  cachePoint: { type: 'default' },
416
421
  });
417
- messagesModified++;
422
+ cachePointsAdded++;
418
423
  }
419
424
  }
420
425
  else if (typeof content === 'string' && needsCacheAdd) {
@@ -422,7 +427,10 @@ function addBedrockCacheControl(messages) {
422
427
  { type: _enum.ContentTypes.TEXT, text: content },
423
428
  { cachePoint: { type: 'default' } },
424
429
  ];
425
- messagesModified++;
430
+ cachePointsAdded++;
431
+ }
432
+ else if (typeof content === 'string' && hasSerializationProps) {
433
+ workingContent = content;
426
434
  }
427
435
  else {
428
436
  continue;