@librechat/agents 3.4.5 → 3.4.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/common/enum.cjs +2 -0
- package/dist/cjs/common/enum.cjs.map +1 -1
- package/dist/cjs/graphs/Graph.cjs +268 -14
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/langfuseTraceShaping.cjs +9 -6
- package/dist/cjs/langfuseTraceShaping.cjs.map +1 -1
- package/dist/cjs/llm/google/utils/common.cjs +10 -5
- package/dist/cjs/llm/google/utils/common.cjs.map +1 -1
- package/dist/cjs/run.cjs +147 -14
- package/dist/cjs/run.cjs.map +1 -1
- package/dist/cjs/session/AgentSession.cjs +93 -31
- package/dist/cjs/session/AgentSession.cjs.map +1 -1
- package/dist/cjs/session/handlers.cjs +10 -0
- package/dist/cjs/session/handlers.cjs.map +1 -1
- package/dist/cjs/stream.cjs +17 -3
- package/dist/cjs/stream.cjs.map +1 -1
- package/dist/cjs/summarization/node.cjs +1 -0
- package/dist/cjs/summarization/node.cjs.map +1 -1
- package/dist/cjs/tools/ToolNode.cjs +4 -2
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/tools/handlers.cjs +1 -0
- package/dist/cjs/tools/handlers.cjs.map +1 -1
- package/dist/cjs/tools/subagent/SubagentExecutor.cjs +28 -0
- package/dist/cjs/tools/subagent/SubagentExecutor.cjs.map +1 -1
- package/dist/cjs/utils/handlers.cjs +3 -0
- package/dist/cjs/utils/handlers.cjs.map +1 -1
- package/dist/esm/common/enum.mjs +2 -0
- package/dist/esm/common/enum.mjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +268 -14
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/langfuseTraceShaping.mjs +9 -6
- package/dist/esm/langfuseTraceShaping.mjs.map +1 -1
- package/dist/esm/llm/google/utils/common.mjs +10 -5
- package/dist/esm/llm/google/utils/common.mjs.map +1 -1
- package/dist/esm/run.mjs +147 -14
- package/dist/esm/run.mjs.map +1 -1
- package/dist/esm/session/AgentSession.mjs +93 -31
- package/dist/esm/session/AgentSession.mjs.map +1 -1
- package/dist/esm/session/handlers.mjs +10 -0
- package/dist/esm/session/handlers.mjs.map +1 -1
- package/dist/esm/stream.mjs +17 -3
- package/dist/esm/stream.mjs.map +1 -1
- package/dist/esm/summarization/node.mjs +1 -0
- package/dist/esm/summarization/node.mjs.map +1 -1
- package/dist/esm/tools/ToolNode.mjs +4 -2
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/tools/handlers.mjs +1 -0
- package/dist/esm/tools/handlers.mjs.map +1 -1
- package/dist/esm/tools/subagent/SubagentExecutor.mjs +28 -0
- package/dist/esm/tools/subagent/SubagentExecutor.mjs.map +1 -1
- package/dist/esm/utils/handlers.mjs +3 -0
- package/dist/esm/utils/handlers.mjs.map +1 -1
- package/dist/types/common/enum.d.ts +2 -0
- package/dist/types/graphs/Graph.d.ts +87 -0
- package/dist/types/langfuseTraceShaping.d.ts +4 -3
- package/dist/types/run.d.ts +9 -1
- package/dist/types/session/types.d.ts +1 -1
- package/dist/types/summarization/node.d.ts +6 -0
- package/dist/types/types/graph.d.ts +3 -3
- package/dist/types/types/stream.d.ts +57 -0
- package/dist/types/utils/handlers.d.ts +1 -0
- package/package.json +1 -1
- package/src/aggregator.test.ts +127 -0
- package/src/common/enum.ts +2 -0
- package/src/graphs/Graph.ts +365 -7
- package/src/graphs/__tests__/Graph.closeRunStep.test.ts +385 -0
- package/src/langfuseTraceShaping.ts +14 -7
- package/src/llm/google/utils/common.test.ts +11 -0
- package/src/llm/google/utils/common.ts +6 -4
- package/src/run.ts +219 -41
- package/src/session/AgentSession.ts +105 -13
- package/src/session/handlers.ts +14 -2
- package/src/session/types.ts +1 -0
- package/src/specs/activity-label-observability.live.test.ts +262 -0
- package/src/specs/activity-label-observability.test.ts +167 -0
- package/src/specs/langfuse-trace-shaping.test.ts +32 -0
- package/src/specs/run-step-timestamps.test.ts +414 -0
- package/src/stream.ts +29 -6
- package/src/summarization/node.ts +11 -0
- package/src/tools/ToolNode.ts +2 -0
- package/src/tools/__tests__/SubagentExecutor.test.ts +52 -10
- package/src/tools/__tests__/handlers.test.ts +2 -0
- package/src/tools/handlers.ts +1 -0
- package/src/tools/subagent/SubagentExecutor.ts +46 -4
- package/src/types/graph.ts +9 -6
- package/src/types/stream.ts +65 -12
- package/src/utils/handlers.ts +13 -0
|
@@ -14,6 +14,8 @@ const CHAIN_OBSERVATION_TYPE = "chain";
|
|
|
14
14
|
const TOOL_OBSERVATION_TYPE = "tool";
|
|
15
15
|
const AGENT_TRACE_TAG = "agent";
|
|
16
16
|
const TITLE_TRACE_TAG = "title";
|
|
17
|
+
const ACTIVITY_PHASE_TRACE_TAG = "activity-phase";
|
|
18
|
+
const ACTIVITY_PHASE_ROOT_NAME = "summarize-activity-phase";
|
|
17
19
|
const EPHEMERAL_AGENT_SENDER_SEPARATOR = "___";
|
|
18
20
|
const EPHEMERAL_AGENT_INDEX_SEPARATOR = "____";
|
|
19
21
|
const OBSERVATION_METADATA_LANGGRAPH_NODE = `${_langfuse_tracing.LangfuseOtelSpanAttributes.OBSERVATION_METADATA}.langgraph_node`;
|
|
@@ -276,11 +278,11 @@ function hasTraceTag(span, expectedTag) {
|
|
|
276
278
|
}
|
|
277
279
|
function shapeRootObservationType(span) {
|
|
278
280
|
if (isGenerationSpan(span)) return;
|
|
279
|
-
if (hasTraceTag(span,
|
|
280
|
-
span.attributes[_langfuse_tracing.LangfuseOtelSpanAttributes.OBSERVATION_TYPE] =
|
|
281
|
+
if (hasTraceTag(span, TITLE_TRACE_TAG) || span.name === ACTIVITY_PHASE_ROOT_NAME && hasTraceTag(span, ACTIVITY_PHASE_TRACE_TAG)) {
|
|
282
|
+
span.attributes[_langfuse_tracing.LangfuseOtelSpanAttributes.OBSERVATION_TYPE] = CHAIN_OBSERVATION_TYPE;
|
|
281
283
|
return;
|
|
282
284
|
}
|
|
283
|
-
if (hasTraceTag(span,
|
|
285
|
+
if (hasTraceTag(span, AGENT_TRACE_TAG)) span.attributes[_langfuse_tracing.LangfuseOtelSpanAttributes.OBSERVATION_TYPE] = ROOT_OBSERVATION_TYPE;
|
|
284
286
|
}
|
|
285
287
|
/**
|
|
286
288
|
* Reshapes spans per Langfuse-team feedback before export:
|
|
@@ -295,9 +297,10 @@ function shapeRootObservationType(span) {
|
|
|
295
297
|
* - Agent nodes become `agent` observations, while tool-dispatch nodes become
|
|
296
298
|
* stable `chain` observations whose input is scoped to the pending calls.
|
|
297
299
|
* Individual child calls remain `tool` observations (items 3 & 4).
|
|
298
|
-
* - Agent trace roots become `agent` observations
|
|
299
|
-
* `chain` observations. Root and trace input/output are
|
|
300
|
-
* question and assistant response when chat messages are
|
|
300
|
+
* - Agent trace roots become `agent` observations, while title and activity
|
|
301
|
+
* summary roots become `chain` observations. Root and trace input/output are
|
|
302
|
+
* reduced to the user question and assistant response when chat messages are
|
|
303
|
+
* available (item 2).
|
|
301
304
|
*/
|
|
302
305
|
function shapeLangfuseSpan(span) {
|
|
303
306
|
const mutable = span;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"langfuseTraceShaping.cjs","names":["LangfuseOtelSpanAttributes"],"sources":["../../src/langfuseTraceShaping.ts"],"sourcesContent":["import { LangfuseOtelSpanAttributes } from '@langfuse/tracing';\nimport type { ReadableSpan } from '@opentelemetry/sdk-trace-base';\nimport { Constants } from '@/common';\n\nconst LANGGRAPH_START_NODE = '__start__';\nconst ANONYMOUS_LAMBDA_NAME = 'RunnableLambda';\nconst LANGGRAPH_AGENT_NODE_PREFIX = 'agent=';\nconst LANGGRAPH_TOOL_NODE_PREFIX = 'tools=';\nconst AGENT_NODE_SPAN_NAME = 'agent';\nconst TOOL_DISPATCH_SPAN_NAME = 'tool-dispatch';\nconst GENERATION_SPAN_NAME = 'llm';\nconst ROOT_OBSERVATION_TYPE = 'agent';\nconst CHAIN_OBSERVATION_TYPE = 'chain';\nconst TOOL_OBSERVATION_TYPE = 'tool';\nconst AGENT_TRACE_TAG = 'agent';\nconst TITLE_TRACE_TAG = 'title';\nconst EPHEMERAL_AGENT_SENDER_SEPARATOR = '___';\nconst EPHEMERAL_AGENT_INDEX_SEPARATOR = '____';\nconst OBSERVATION_METADATA_LANGGRAPH_NODE = `${LangfuseOtelSpanAttributes.OBSERVATION_METADATA}.langgraph_node`;\n\ntype MutableSpan = ReadableSpan & {\n name: string;\n attributes: Record<string, unknown>;\n};\n\ntype SerializedToolCall = {\n name: string;\n args: unknown;\n id?: string;\n};\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value != null && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction parseAttributeValue(value: unknown): unknown {\n if (typeof value !== 'string') {\n return value;\n }\n const trimmed = value.trim();\n if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) {\n return value;\n }\n try {\n return JSON.parse(value) as unknown;\n } catch {\n return value;\n }\n}\n\nfunction getMessageArray(\n value: unknown\n): Record<string, unknown>[] | undefined {\n if (Array.isArray(value)) {\n const records = value.filter(isRecord);\n return records.length > 0 ? records : undefined;\n }\n if (!isRecord(value)) {\n return undefined;\n }\n return (\n getMessageArray(value.messages) ??\n getMessageArray(value.input) ??\n getMessageArray(value.output)\n );\n}\n\nfunction getMessageRole(message: Record<string, unknown>): string | undefined {\n const id = message.id;\n if (Array.isArray(id)) {\n const className = id[id.length - 1];\n if (typeof className === 'string') {\n if (className.includes('Human')) {\n return 'user';\n }\n if (className.includes('AI')) {\n return 'assistant';\n }\n if (className.includes('System')) {\n return 'system';\n }\n if (className.includes('Tool')) {\n return 'tool';\n }\n }\n }\n const rawRole =\n message.type ?? message._type ?? message.role ?? message.sender;\n if (typeof rawRole !== 'string') {\n const kwargs = message.kwargs;\n return isRecord(kwargs) ? getMessageRole(kwargs) : undefined;\n }\n const normalized = rawRole.toLowerCase();\n if (normalized === 'human') {\n return 'user';\n }\n if (normalized === 'ai') {\n return 'assistant';\n }\n return normalized;\n}\n\nfunction getMessageText(message: Record<string, unknown>): string | undefined {\n const content =\n message.content ??\n (isRecord(message.kwargs) ? message.kwargs.content : undefined) ??\n (isRecord(message.data) ? message.data.content : undefined);\n if (typeof content === 'string') {\n return content;\n }\n if (!Array.isArray(content)) {\n return undefined;\n }\n const text = content\n .filter(isRecord)\n .map((part) => (typeof part.text === 'string' ? part.text : ''))\n .join('');\n return text === '' ? undefined : text;\n}\n\nfunction findLastMessageText(value: unknown, role: string): string | undefined {\n const messages = getMessageArray(value);\n if (messages == null) {\n return undefined;\n }\n for (let i = messages.length - 1; i >= 0; i--) {\n if (getMessageRole(messages[i]) !== role) {\n continue;\n }\n const text = getMessageText(messages[i]);\n if (text != null && text.trim() !== '') {\n return text;\n }\n }\n return undefined;\n}\n\nfunction normalizeToolCall(value: unknown): SerializedToolCall | undefined {\n if (!isRecord(value)) {\n return undefined;\n }\n const fn = value.function;\n if (isRecord(fn) && typeof fn.name === 'string') {\n return {\n name: fn.name,\n args: parseAttributeValue(fn.arguments),\n ...(typeof value.id === 'string' ? { id: value.id } : {}),\n };\n }\n if (typeof value.name !== 'string') {\n return undefined;\n }\n return {\n name: value.name,\n args: value.args ?? {},\n ...(typeof value.id === 'string' ? { id: value.id } : {}),\n };\n}\n\nfunction getMessageToolCalls(\n message: Record<string, unknown>\n): SerializedToolCall[] {\n const rawCalls =\n message.tool_calls ??\n (isRecord(message.kwargs) ? message.kwargs.tool_calls : undefined) ??\n (isRecord(message.additional_kwargs)\n ? message.additional_kwargs.tool_calls\n : undefined) ??\n (isRecord(message.data) ? message.data.tool_calls : undefined);\n if (!Array.isArray(rawCalls)) {\n return [];\n }\n const calls: SerializedToolCall[] = [];\n for (const rawCall of rawCalls) {\n const call = normalizeToolCall(rawCall);\n if (call != null) {\n calls.push(call);\n }\n }\n return calls;\n}\n\n/**\n * Id-bearing `invalid_tool_calls` on the assistant turn. ToolNode pairs these\n * with synthesized error results (and an invalid-only turn is routed on them\n * alone), so the tool-dispatch span must count them as part of the executing\n * batch — otherwise an invalid-only dispatch finds zero calls and the span\n * keeps the full serialized graph state as its input, and a mixed dispatch\n * silently omits the malformed call. `args` stays the raw unparsed string.\n */\n/** Tool-result ids present in the serialized state — ToolNode's\n * `!toolMessageIds.has(id)` execution filter, mirrored for the span. */\nfunction getToolResultIds(\n messages: Record<string, unknown>[]\n): Set<string> {\n const ids = new Set<string>();\n for (const message of messages) {\n if (getMessageRole(message) !== 'tool') {\n continue;\n }\n const rawId =\n message.tool_call_id ??\n (isRecord(message.kwargs) ? message.kwargs.tool_call_id : undefined) ??\n (isRecord(message.data) ? message.data.tool_call_id : undefined);\n if (typeof rawId === 'string' && rawId !== '') {\n ids.add(rawId);\n }\n }\n return ids;\n}\n\nfunction getMessageInvalidToolCalls(\n message: Record<string, unknown>,\n answeredIds: ReadonlySet<string>\n): SerializedToolCall[] {\n const rawCalls =\n message.invalid_tool_calls ??\n (isRecord(message.kwargs) ? message.kwargs.invalid_tool_calls : undefined) ??\n (isRecord(message.data) ? message.data.invalid_tool_calls : undefined);\n if (!Array.isArray(rawCalls)) {\n return [];\n }\n const calls: SerializedToolCall[] = [];\n for (const rawCall of rawCalls) {\n // Same attribution predicate ToolNode executes with (id-bearing,\n // non-server) so the span never claims calls the node deliberately skips.\n if (\n !isRecord(rawCall) ||\n typeof rawCall.id !== 'string' ||\n rawCall.id === '' ||\n answeredIds.has(rawCall.id) ||\n rawCall.id.startsWith(Constants.ANTHROPIC_SERVER_TOOL_PREFIX)\n ) {\n continue;\n }\n // Same name fallback ToolNode synthesizes with — a nameless attributable\n // call still gets a result, so it must still count in the span input.\n const call = normalizeToolCall(\n typeof rawCall.name === 'string' && rawCall.name !== ''\n ? rawCall\n : { ...rawCall, name: 'unknown' }\n );\n if (call != null) {\n calls.push(call);\n }\n }\n return calls;\n}\n\n/** The serialized message's own id (uuid), NOT the LC-serialization type id\n * array that `message.id` carries in constructor dumps. */\nfunction getSerializedMessageId(\n message: Record<string, unknown>\n): string | undefined {\n const kwargsId = isRecord(message.kwargs) ? message.kwargs.id : undefined;\n const dataId = isRecord(message.data) ? message.data.id : undefined;\n const rawId = message.id;\n const id = kwargsId ?? dataId ?? rawId;\n return typeof id === 'string' && id !== '' ? id : undefined;\n}\n\n/** Latest assistant turn's tool calls — the calls this tool node is executing. */\nfunction findPendingToolCalls(value: unknown): SerializedToolCall[] {\n const messages = getMessageArray(value);\n if (messages == null) {\n return [];\n }\n /**\n * Invalid calls count only where ToolNode's own gate lets them execute:\n * the messages-state form (a bare-array state means the node returns a\n * plain output list and skips invalid handling) with an id-bearing\n * assistant message (no id, no reducer upsert). Mirrors\n * `canPromoteInvalidCalls` so the span never reports skipped calls.\n */\n const invalidCallsApply = !Array.isArray(value);\n const answeredIds = invalidCallsApply\n ? getToolResultIds(messages)\n : undefined;\n for (let i = messages.length - 1; i >= 0; i--) {\n if (getMessageRole(messages[i]) !== 'assistant') {\n continue;\n }\n const calls = [\n ...getMessageToolCalls(messages[i]),\n ...(invalidCallsApply && getSerializedMessageId(messages[i]) != null\n ? getMessageInvalidToolCalls(messages[i], answeredIds!)\n : []),\n ];\n if (calls.length > 0) {\n return calls;\n }\n }\n return [];\n}\n\nfunction getRootSpanParentId(span: ReadableSpan): string | undefined {\n const legacyParent = (span as { parentSpanId?: string }).parentSpanId;\n if (typeof legacyParent === 'string' && legacyParent !== '') {\n return legacyParent;\n }\n const parentContext = (span as { parentSpanContext?: { spanId?: string } })\n .parentSpanContext;\n const spanId = parentContext?.spanId;\n return typeof spanId === 'string' && spanId !== '' ? spanId : undefined;\n}\n\nfunction isRootSpan(span: ReadableSpan): boolean {\n return getRootSpanParentId(span) == null;\n}\n\n/**\n * LangGraph plumbing observations that add noise without information:\n * the duplicated `__start__` channel-seed nodes and anonymous\n * `RunnableLambda` pass-throughs (Langfuse team feedback items 4 & 5).\n * Internal ToolNode batch spans are disabled at their source so traced child\n * tools retain an exported parent. Explicitly traced ToolNodes are preserved.\n */\nexport function shouldDropLangfuseSpan(spanName: string): boolean {\n return (\n spanName === LANGGRAPH_START_NODE || spanName === ANONYMOUS_LAMBDA_NAME\n );\n}\n\nfunction shapeToolNodeSpan(span: MutableSpan): void {\n const inputKey = LangfuseOtelSpanAttributes.OBSERVATION_INPUT;\n span.name = TOOL_DISPATCH_SPAN_NAME;\n span.attributes[LangfuseOtelSpanAttributes.OBSERVATION_TYPE] =\n CHAIN_OBSERVATION_TYPE;\n const calls = findPendingToolCalls(\n parseAttributeValue(span.attributes[inputKey])\n );\n if (calls.length === 0) {\n return;\n }\n span.attributes[inputKey] = JSON.stringify(\n calls.map(({ name, args }) => ({ name, args }))\n );\n}\n\nfunction shapeAgentNodeSpan(span: MutableSpan): void {\n span.name = AGENT_NODE_SPAN_NAME;\n span.attributes[LangfuseOtelSpanAttributes.OBSERVATION_TYPE] =\n ROOT_OBSERVATION_TYPE;\n}\n\nfunction shapeRootSpan(span: MutableSpan): void {\n const inputKey = LangfuseOtelSpanAttributes.OBSERVATION_INPUT;\n const outputKey = LangfuseOtelSpanAttributes.OBSERVATION_OUTPUT;\n const question = findLastMessageText(\n parseAttributeValue(span.attributes[inputKey]),\n 'user'\n );\n const answer = findLastMessageText(\n parseAttributeValue(span.attributes[outputKey]),\n 'assistant'\n );\n /** A generation that IS the trace root — a bare `model.invoke` with no\n * wrapping chain, i.e. the activity-label path — is also the only\n * observation carrying its own prompt: reducing its observation input\n * would discard the SystemMessage from the one place it is traced.\n * Chain/agent roots keep the full reduction; their child generations\n * still record the complete prompt. Trace-level input/output reduce\n * either way, so the trace list keeps showing question and answer. */\n if (!isGenerationSpan(span)) {\n if (question != null) {\n span.attributes[inputKey] = question;\n }\n if (answer != null) {\n span.attributes[outputKey] = answer;\n }\n }\n const traceInput = question ?? span.attributes[inputKey];\n const traceOutput = answer ?? span.attributes[outputKey];\n if (traceInput != null) {\n span.attributes[LangfuseOtelSpanAttributes.TRACE_INPUT] = traceInput;\n }\n if (traceOutput != null) {\n span.attributes[LangfuseOtelSpanAttributes.TRACE_OUTPUT] = traceOutput;\n }\n}\n\nfunction isGenerationSpan(span: MutableSpan): boolean {\n const type = span.attributes[LangfuseOtelSpanAttributes.OBSERVATION_TYPE];\n return typeof type === 'string' && type.toLowerCase() === 'generation';\n}\n\nfunction isToolSpan(span: MutableSpan): boolean {\n const type = span.attributes[LangfuseOtelSpanAttributes.OBSERVATION_TYPE];\n return (\n typeof type === 'string' && type.toLowerCase() === TOOL_OBSERVATION_TYPE\n );\n}\n\n/**\n * Whether the span is a LangGraph node execution whose node id is the span\n * name — the shape of the outer workflow-agent node. `@langfuse/tracing`\n * flattens object metadata to per-key attributes with string values stored\n * raw, so LangGraph's `langgraph_node` arrives directly comparable.\n */\nfunction isWorkflowNodeSpan(span: MutableSpan): boolean {\n return span.attributes[OBSERVATION_METADATA_LANGGRAPH_NODE] === span.name;\n}\n\n/**\n * LibreChat ephemeral agents are identified as\n * `endpoint__model___sender[____index]` (`__` encodes `:`; see LibreChat's\n * `encodeEphemeralAgentId`), and the outer workflow node carries that id as\n * its span name — so switching models renames the span (item 1). Returns the\n * stable human `sender` segment only when the name matches that encoding:\n * the `endpoint__model` prefix must contain both segments and — unlike\n * display names such as `LibreChat Agent: Ops___EU` — never contains\n * whitespace, so legitimate names that merely embed `___` are left alone.\n */\nfunction extractEphemeralAgentSender(name: string): string | undefined {\n let workingId = name;\n const indexSeparator = workingId.lastIndexOf(EPHEMERAL_AGENT_INDEX_SEPARATOR);\n if (\n indexSeparator !== -1 &&\n /^\\d+$/.test(\n workingId.slice(indexSeparator + EPHEMERAL_AGENT_INDEX_SEPARATOR.length)\n )\n ) {\n workingId = workingId.slice(0, indexSeparator);\n }\n const senderSeparator = workingId.indexOf(EPHEMERAL_AGENT_SENDER_SEPARATOR);\n if (senderSeparator <= 0) {\n return undefined;\n }\n const encodedPrefix = workingId.slice(0, senderSeparator);\n if (/\\s/.test(encodedPrefix)) {\n return undefined;\n }\n const prefixParts = encodedPrefix.split('__');\n if (prefixParts.length < 2 || prefixParts.some((part) => part === '')) {\n return undefined;\n }\n const sender = workingId\n .slice(senderSeparator + EPHEMERAL_AGENT_SENDER_SEPARATOR.length)\n .replace(/__/g, ':');\n return sender === '' ? undefined : sender;\n}\n\n/** Workflow-agent node spans are always children of the run's root chain and\n * always carry `langgraph_node` metadata equal to their name, so host-named\n * run roots (`LibreChat Agent: <name>`) and ordinary chains that merely look\n * like encoded ids (`pipeline__stage___EU`) are never rename candidates.\n * Successful decodes become `agent` observations, matching the inner\n * `agent=<id>` node shaping. */\nfunction shapeEphemeralAgentNodeSpan(span: MutableSpan): void {\n if (isToolSpan(span) || isRootSpan(span) || !isWorkflowNodeSpan(span)) {\n return;\n }\n const sender = extractEphemeralAgentSender(span.name);\n if (sender == null) {\n return;\n }\n span.name = sender;\n span.attributes[LangfuseOtelSpanAttributes.OBSERVATION_TYPE] =\n ROOT_OBSERVATION_TYPE;\n}\n\nfunction hasTraceTag(span: MutableSpan, expectedTag: string): boolean {\n const tags = parseAttributeValue(\n span.attributes[LangfuseOtelSpanAttributes.TRACE_TAGS]\n );\n return (\n Array.isArray(tags) &&\n tags.some((tag) => typeof tag === 'string' && tag === expectedTag)\n );\n}\n\nfunction shapeRootObservationType(span: MutableSpan): void {\n if (isGenerationSpan(span)) {\n return;\n }\n if (hasTraceTag(span, AGENT_TRACE_TAG)) {\n span.attributes[LangfuseOtelSpanAttributes.OBSERVATION_TYPE] =\n ROOT_OBSERVATION_TYPE;\n return;\n }\n if (hasTraceTag(span, TITLE_TRACE_TAG)) {\n span.attributes[LangfuseOtelSpanAttributes.OBSERVATION_TYPE] =\n CHAIN_OBSERVATION_TYPE;\n }\n}\n\n/**\n * Reshapes spans per Langfuse-team feedback before export:\n * - `agent=<id>` / `tools=<id>` node names carry the ephemeral agent id\n * (`provider__model`) — strip it so switching models doesn't break\n * name-based logic (item 1). The outer workflow node is named with the\n * bare agent id; ephemeral ids reduce to their stable sender name.\n * - LLM generation spans keep the provider client class name (`ChatOpenAI`,\n * `AzureChatOpenAI`, …); rename them to a provider-agnostic `llm` so the\n * name reflects the operation, not the model (the model stays on the\n * generation's model attribute).\n * - Agent nodes become `agent` observations, while tool-dispatch nodes become\n * stable `chain` observations whose input is scoped to the pending calls.\n * Individual child calls remain `tool` observations (items 3 & 4).\n * - Agent trace roots become `agent` observations and title trace roots become\n * `chain` observations. Root and trace input/output are reduced to the user\n * question and assistant response when chat messages are available (item 2).\n */\nexport function shapeLangfuseSpan(span: ReadableSpan): void {\n const mutable = span as MutableSpan;\n if (mutable.name.startsWith(LANGGRAPH_AGENT_NODE_PREFIX)) {\n shapeAgentNodeSpan(mutable);\n } else if (mutable.name.startsWith(LANGGRAPH_TOOL_NODE_PREFIX)) {\n shapeToolNodeSpan(mutable);\n } else if (isGenerationSpan(mutable)) {\n mutable.name = GENERATION_SPAN_NAME;\n } else {\n shapeEphemeralAgentNodeSpan(mutable);\n }\n if (!isRootSpan(span)) {\n return;\n }\n shapeRootObservationType(mutable);\n shapeRootSpan(mutable);\n}\n"],"mappings":";;;;AAIA,MAAM,uBAAuB;AAC7B,MAAM,wBAAwB;AAC9B,MAAM,8BAA8B;AACpC,MAAM,6BAA6B;AACnC,MAAM,uBAAuB;AAC7B,MAAM,0BAA0B;AAChC,MAAM,uBAAuB;AAC7B,MAAM,wBAAwB;AAC9B,MAAM,yBAAyB;AAC/B,MAAM,wBAAwB;AAC9B,MAAM,kBAAkB;AACxB,MAAM,kBAAkB;AACxB,MAAM,mCAAmC;AACzC,MAAM,kCAAkC;AACxC,MAAM,sCAAsC,GAAGA,kBAAAA,2BAA2B,qBAAqB;AAa/F,SAAS,SAAS,OAAkD;CAClE,OAAO,SAAS,QAAQ,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK;AAC3E;AAEA,SAAS,oBAAoB,OAAyB;CACpD,IAAI,OAAO,UAAU,UACnB,OAAO;CAET,MAAM,UAAU,MAAM,KAAK;CAC3B,IAAI,CAAC,QAAQ,WAAW,GAAG,KAAK,CAAC,QAAQ,WAAW,GAAG,GACrD,OAAO;CAET,IAAI;EACF,OAAO,KAAK,MAAM,KAAK;CACzB,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,gBACP,OACuC;CACvC,IAAI,MAAM,QAAQ,KAAK,GAAG;EACxB,MAAM,UAAU,MAAM,OAAO,QAAQ;EACrC,OAAO,QAAQ,SAAS,IAAI,UAAU,KAAA;CACxC;CACA,IAAI,CAAC,SAAS,KAAK,GACjB;CAEF,OACE,gBAAgB,MAAM,QAAQ,KAC9B,gBAAgB,MAAM,KAAK,KAC3B,gBAAgB,MAAM,MAAM;AAEhC;AAEA,SAAS,eAAe,SAAsD;CAC5E,MAAM,KAAK,QAAQ;CACnB,IAAI,MAAM,QAAQ,EAAE,GAAG;EACrB,MAAM,YAAY,GAAG,GAAG,SAAS;EACjC,IAAI,OAAO,cAAc,UAAU;GACjC,IAAI,UAAU,SAAS,OAAO,GAC5B,OAAO;GAET,IAAI,UAAU,SAAS,IAAI,GACzB,OAAO;GAET,IAAI,UAAU,SAAS,QAAQ,GAC7B,OAAO;GAET,IAAI,UAAU,SAAS,MAAM,GAC3B,OAAO;EAEX;CACF;CACA,MAAM,UACJ,QAAQ,QAAQ,QAAQ,SAAS,QAAQ,QAAQ,QAAQ;CAC3D,IAAI,OAAO,YAAY,UAAU;EAC/B,MAAM,SAAS,QAAQ;EACvB,OAAO,SAAS,MAAM,IAAI,eAAe,MAAM,IAAI,KAAA;CACrD;CACA,MAAM,aAAa,QAAQ,YAAY;CACvC,IAAI,eAAe,SACjB,OAAO;CAET,IAAI,eAAe,MACjB,OAAO;CAET,OAAO;AACT;AAEA,SAAS,eAAe,SAAsD;CAC5E,MAAM,UACJ,QAAQ,YACP,SAAS,QAAQ,MAAM,IAAI,QAAQ,OAAO,UAAU,KAAA,OACpD,SAAS,QAAQ,IAAI,IAAI,QAAQ,KAAK,UAAU,KAAA;CACnD,IAAI,OAAO,YAAY,UACrB,OAAO;CAET,IAAI,CAAC,MAAM,QAAQ,OAAO,GACxB;CAEF,MAAM,OAAO,QACV,OAAO,QAAQ,CAAC,CAChB,KAAK,SAAU,OAAO,KAAK,SAAS,WAAW,KAAK,OAAO,EAAG,CAAC,CAC/D,KAAK,EAAE;CACV,OAAO,SAAS,KAAK,KAAA,IAAY;AACnC;AAEA,SAAS,oBAAoB,OAAgB,MAAkC;CAC7E,MAAM,WAAW,gBAAgB,KAAK;CACtC,IAAI,YAAY,MACd;CAEF,KAAK,IAAI,IAAI,SAAS,SAAS,GAAG,KAAK,GAAG,KAAK;EAC7C,IAAI,eAAe,SAAS,EAAE,MAAM,MAClC;EAEF,MAAM,OAAO,eAAe,SAAS,EAAE;EACvC,IAAI,QAAQ,QAAQ,KAAK,KAAK,MAAM,IAClC,OAAO;CAEX;AAEF;AAEA,SAAS,kBAAkB,OAAgD;CACzE,IAAI,CAAC,SAAS,KAAK,GACjB;CAEF,MAAM,KAAK,MAAM;CACjB,IAAI,SAAS,EAAE,KAAK,OAAO,GAAG,SAAS,UACrC,OAAO;EACL,MAAM,GAAG;EACT,MAAM,oBAAoB,GAAG,SAAS;EACtC,GAAI,OAAO,MAAM,OAAO,WAAW,EAAE,IAAI,MAAM,GAAG,IAAI,CAAC;CACzD;CAEF,IAAI,OAAO,MAAM,SAAS,UACxB;CAEF,OAAO;EACL,MAAM,MAAM;EACZ,MAAM,MAAM,QAAQ,CAAC;EACrB,GAAI,OAAO,MAAM,OAAO,WAAW,EAAE,IAAI,MAAM,GAAG,IAAI,CAAC;CACzD;AACF;AAEA,SAAS,oBACP,SACsB;CACtB,MAAM,WACJ,QAAQ,eACP,SAAS,QAAQ,MAAM,IAAI,QAAQ,OAAO,aAAa,KAAA,OACvD,SAAS,QAAQ,iBAAiB,IAC/B,QAAQ,kBAAkB,aAC1B,KAAA,OACH,SAAS,QAAQ,IAAI,IAAI,QAAQ,KAAK,aAAa,KAAA;CACtD,IAAI,CAAC,MAAM,QAAQ,QAAQ,GACzB,OAAO,CAAC;CAEV,MAAM,QAA8B,CAAC;CACrC,KAAK,MAAM,WAAW,UAAU;EAC9B,MAAM,OAAO,kBAAkB,OAAO;EACtC,IAAI,QAAQ,MACV,MAAM,KAAK,IAAI;CAEnB;CACA,OAAO;AACT;;;;;;;;;;;AAYA,SAAS,iBACP,UACa;CACb,MAAM,sBAAM,IAAI,IAAY;CAC5B,KAAK,MAAM,WAAW,UAAU;EAC9B,IAAI,eAAe,OAAO,MAAM,QAC9B;EAEF,MAAM,QACJ,QAAQ,iBACP,SAAS,QAAQ,MAAM,IAAI,QAAQ,OAAO,eAAe,KAAA,OACzD,SAAS,QAAQ,IAAI,IAAI,QAAQ,KAAK,eAAe,KAAA;EACxD,IAAI,OAAO,UAAU,YAAY,UAAU,IACzC,IAAI,IAAI,KAAK;CAEjB;CACA,OAAO;AACT;AAEA,SAAS,2BACP,SACA,aACsB;CACtB,MAAM,WACJ,QAAQ,uBACP,SAAS,QAAQ,MAAM,IAAI,QAAQ,OAAO,qBAAqB,KAAA,OAC/D,SAAS,QAAQ,IAAI,IAAI,QAAQ,KAAK,qBAAqB,KAAA;CAC9D,IAAI,CAAC,MAAM,QAAQ,QAAQ,GACzB,OAAO,CAAC;CAEV,MAAM,QAA8B,CAAC;CACrC,KAAK,MAAM,WAAW,UAAU;EAG9B,IACE,CAAC,SAAS,OAAO,KACjB,OAAO,QAAQ,OAAO,YACtB,QAAQ,OAAO,MACf,YAAY,IAAI,QAAQ,EAAE,KAC1B,QAAQ,GAAG,WAAA,WAAiD,GAE5D;EAIF,MAAM,OAAO,kBACX,OAAO,QAAQ,SAAS,YAAY,QAAQ,SAAS,KACjD,UACA;GAAE,GAAG;GAAS,MAAM;EAAU,CACpC;EACA,IAAI,QAAQ,MACV,MAAM,KAAK,IAAI;CAEnB;CACA,OAAO;AACT;;;AAIA,SAAS,uBACP,SACoB;CACpB,MAAM,WAAW,SAAS,QAAQ,MAAM,IAAI,QAAQ,OAAO,KAAK,KAAA;CAChE,MAAM,SAAS,SAAS,QAAQ,IAAI,IAAI,QAAQ,KAAK,KAAK,KAAA;CAC1D,MAAM,QAAQ,QAAQ;CACtB,MAAM,KAAK,YAAY,UAAU;CACjC,OAAO,OAAO,OAAO,YAAY,OAAO,KAAK,KAAK,KAAA;AACpD;;AAGA,SAAS,qBAAqB,OAAsC;CAClE,MAAM,WAAW,gBAAgB,KAAK;CACtC,IAAI,YAAY,MACd,OAAO,CAAC;;;;;;;;CASV,MAAM,oBAAoB,CAAC,MAAM,QAAQ,KAAK;CAC9C,MAAM,cAAc,oBAChB,iBAAiB,QAAQ,IACzB,KAAA;CACJ,KAAK,IAAI,IAAI,SAAS,SAAS,GAAG,KAAK,GAAG,KAAK;EAC7C,IAAI,eAAe,SAAS,EAAE,MAAM,aAClC;EAEF,MAAM,QAAQ,CACZ,GAAG,oBAAoB,SAAS,EAAE,GAClC,GAAI,qBAAqB,uBAAuB,SAAS,EAAE,KAAK,OAC5D,2BAA2B,SAAS,IAAI,WAAY,IACpD,CAAC,CACP;EACA,IAAI,MAAM,SAAS,GACjB,OAAO;CAEX;CACA,OAAO,CAAC;AACV;AAEA,SAAS,oBAAoB,MAAwC;CACnE,MAAM,eAAgB,KAAmC;CACzD,IAAI,OAAO,iBAAiB,YAAY,iBAAiB,IACvD,OAAO;CAIT,MAAM,SAFiB,KACpB,mBAC2B;CAC9B,OAAO,OAAO,WAAW,YAAY,WAAW,KAAK,SAAS,KAAA;AAChE;AAEA,SAAS,WAAW,MAA6B;CAC/C,OAAO,oBAAoB,IAAI,KAAK;AACtC;;;;;;;;AASA,SAAgB,uBAAuB,UAA2B;CAChE,OACE,aAAa,wBAAwB,aAAa;AAEtD;AAEA,SAAS,kBAAkB,MAAyB;CAClD,MAAM,WAAWA,kBAAAA,2BAA2B;CAC5C,KAAK,OAAO;CACZ,KAAK,WAAWA,kBAAAA,2BAA2B,oBACzC;CACF,MAAM,QAAQ,qBACZ,oBAAoB,KAAK,WAAW,SAAS,CAC/C;CACA,IAAI,MAAM,WAAW,GACnB;CAEF,KAAK,WAAW,YAAY,KAAK,UAC/B,MAAM,KAAK,EAAE,MAAM,YAAY;EAAE;EAAM;CAAK,EAAE,CAChD;AACF;AAEA,SAAS,mBAAmB,MAAyB;CACnD,KAAK,OAAO;CACZ,KAAK,WAAWA,kBAAAA,2BAA2B,oBACzC;AACJ;AAEA,SAAS,cAAc,MAAyB;CAC9C,MAAM,WAAWA,kBAAAA,2BAA2B;CAC5C,MAAM,YAAYA,kBAAAA,2BAA2B;CAC7C,MAAM,WAAW,oBACf,oBAAoB,KAAK,WAAW,SAAS,GAC7C,MACF;CACA,MAAM,SAAS,oBACb,oBAAoB,KAAK,WAAW,UAAU,GAC9C,WACF;;;;;;;;CAQA,IAAI,CAAC,iBAAiB,IAAI,GAAG;EAC3B,IAAI,YAAY,MACd,KAAK,WAAW,YAAY;EAE9B,IAAI,UAAU,MACZ,KAAK,WAAW,aAAa;CAEjC;CACA,MAAM,aAAa,YAAY,KAAK,WAAW;CAC/C,MAAM,cAAc,UAAU,KAAK,WAAW;CAC9C,IAAI,cAAc,MAChB,KAAK,WAAWA,kBAAAA,2BAA2B,eAAe;CAE5D,IAAI,eAAe,MACjB,KAAK,WAAWA,kBAAAA,2BAA2B,gBAAgB;AAE/D;AAEA,SAAS,iBAAiB,MAA4B;CACpD,MAAM,OAAO,KAAK,WAAWA,kBAAAA,2BAA2B;CACxD,OAAO,OAAO,SAAS,YAAY,KAAK,YAAY,MAAM;AAC5D;AAEA,SAAS,WAAW,MAA4B;CAC9C,MAAM,OAAO,KAAK,WAAWA,kBAAAA,2BAA2B;CACxD,OACE,OAAO,SAAS,YAAY,KAAK,YAAY,MAAM;AAEvD;;;;;;;AAQA,SAAS,mBAAmB,MAA4B;CACtD,OAAO,KAAK,WAAW,yCAAyC,KAAK;AACvE;;;;;;;;;;;AAYA,SAAS,4BAA4B,MAAkC;CACrE,IAAI,YAAY;CAChB,MAAM,iBAAiB,UAAU,YAAY,+BAA+B;CAC5E,IACE,mBAAmB,MACnB,QAAQ,KACN,UAAU,MAAM,iBAAiB,CAAsC,CACzE,GAEA,YAAY,UAAU,MAAM,GAAG,cAAc;CAE/C,MAAM,kBAAkB,UAAU,QAAQ,gCAAgC;CAC1E,IAAI,mBAAmB,GACrB;CAEF,MAAM,gBAAgB,UAAU,MAAM,GAAG,eAAe;CACxD,IAAI,KAAK,KAAK,aAAa,GACzB;CAEF,MAAM,cAAc,cAAc,MAAM,IAAI;CAC5C,IAAI,YAAY,SAAS,KAAK,YAAY,MAAM,SAAS,SAAS,EAAE,GAClE;CAEF,MAAM,SAAS,UACZ,MAAM,kBAAkB,CAAuC,CAAC,CAChE,QAAQ,OAAO,GAAG;CACrB,OAAO,WAAW,KAAK,KAAA,IAAY;AACrC;;;;;;;AAQA,SAAS,4BAA4B,MAAyB;CAC5D,IAAI,WAAW,IAAI,KAAK,WAAW,IAAI,KAAK,CAAC,mBAAmB,IAAI,GAClE;CAEF,MAAM,SAAS,4BAA4B,KAAK,IAAI;CACpD,IAAI,UAAU,MACZ;CAEF,KAAK,OAAO;CACZ,KAAK,WAAWA,kBAAAA,2BAA2B,oBACzC;AACJ;AAEA,SAAS,YAAY,MAAmB,aAA8B;CACpE,MAAM,OAAO,oBACX,KAAK,WAAWA,kBAAAA,2BAA2B,WAC7C;CACA,OACE,MAAM,QAAQ,IAAI,KAClB,KAAK,MAAM,QAAQ,OAAO,QAAQ,YAAY,QAAQ,WAAW;AAErE;AAEA,SAAS,yBAAyB,MAAyB;CACzD,IAAI,iBAAiB,IAAI,GACvB;CAEF,IAAI,YAAY,MAAM,eAAe,GAAG;EACtC,KAAK,WAAWA,kBAAAA,2BAA2B,oBACzC;EACF;CACF;CACA,IAAI,YAAY,MAAM,eAAe,GACnC,KAAK,WAAWA,kBAAAA,2BAA2B,oBACzC;AAEN;;;;;;;;;;;;;;;;;;AAmBA,SAAgB,kBAAkB,MAA0B;CAC1D,MAAM,UAAU;CAChB,IAAI,QAAQ,KAAK,WAAW,2BAA2B,GACrD,mBAAmB,OAAO;MACrB,IAAI,QAAQ,KAAK,WAAW,0BAA0B,GAC3D,kBAAkB,OAAO;MACpB,IAAI,iBAAiB,OAAO,GACjC,QAAQ,OAAO;MAEf,4BAA4B,OAAO;CAErC,IAAI,CAAC,WAAW,IAAI,GAClB;CAEF,yBAAyB,OAAO;CAChC,cAAc,OAAO;AACvB"}
|
|
1
|
+
{"version":3,"file":"langfuseTraceShaping.cjs","names":["LangfuseOtelSpanAttributes"],"sources":["../../src/langfuseTraceShaping.ts"],"sourcesContent":["import { LangfuseOtelSpanAttributes } from '@langfuse/tracing';\nimport type { ReadableSpan } from '@opentelemetry/sdk-trace-base';\nimport { Constants } from '@/common';\n\nconst LANGGRAPH_START_NODE = '__start__';\nconst ANONYMOUS_LAMBDA_NAME = 'RunnableLambda';\nconst LANGGRAPH_AGENT_NODE_PREFIX = 'agent=';\nconst LANGGRAPH_TOOL_NODE_PREFIX = 'tools=';\nconst AGENT_NODE_SPAN_NAME = 'agent';\nconst TOOL_DISPATCH_SPAN_NAME = 'tool-dispatch';\nconst GENERATION_SPAN_NAME = 'llm';\nconst ROOT_OBSERVATION_TYPE = 'agent';\nconst CHAIN_OBSERVATION_TYPE = 'chain';\nconst TOOL_OBSERVATION_TYPE = 'tool';\nconst AGENT_TRACE_TAG = 'agent';\nconst TITLE_TRACE_TAG = 'title';\nconst ACTIVITY_PHASE_TRACE_TAG = 'activity-phase';\nconst ACTIVITY_PHASE_ROOT_NAME = 'summarize-activity-phase';\nconst EPHEMERAL_AGENT_SENDER_SEPARATOR = '___';\nconst EPHEMERAL_AGENT_INDEX_SEPARATOR = '____';\nconst OBSERVATION_METADATA_LANGGRAPH_NODE = `${LangfuseOtelSpanAttributes.OBSERVATION_METADATA}.langgraph_node`;\n\ntype MutableSpan = ReadableSpan & {\n name: string;\n attributes: Record<string, unknown>;\n};\n\ntype SerializedToolCall = {\n name: string;\n args: unknown;\n id?: string;\n};\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value != null && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction parseAttributeValue(value: unknown): unknown {\n if (typeof value !== 'string') {\n return value;\n }\n const trimmed = value.trim();\n if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) {\n return value;\n }\n try {\n return JSON.parse(value) as unknown;\n } catch {\n return value;\n }\n}\n\nfunction getMessageArray(\n value: unknown\n): Record<string, unknown>[] | undefined {\n if (Array.isArray(value)) {\n const records = value.filter(isRecord);\n return records.length > 0 ? records : undefined;\n }\n if (!isRecord(value)) {\n return undefined;\n }\n return (\n getMessageArray(value.messages) ??\n getMessageArray(value.input) ??\n getMessageArray(value.output)\n );\n}\n\nfunction getMessageRole(message: Record<string, unknown>): string | undefined {\n const id = message.id;\n if (Array.isArray(id)) {\n const className = id[id.length - 1];\n if (typeof className === 'string') {\n if (className.includes('Human')) {\n return 'user';\n }\n if (className.includes('AI')) {\n return 'assistant';\n }\n if (className.includes('System')) {\n return 'system';\n }\n if (className.includes('Tool')) {\n return 'tool';\n }\n }\n }\n const rawRole =\n message.type ?? message._type ?? message.role ?? message.sender;\n if (typeof rawRole !== 'string') {\n const kwargs = message.kwargs;\n return isRecord(kwargs) ? getMessageRole(kwargs) : undefined;\n }\n const normalized = rawRole.toLowerCase();\n if (normalized === 'human') {\n return 'user';\n }\n if (normalized === 'ai') {\n return 'assistant';\n }\n return normalized;\n}\n\nfunction getMessageText(message: Record<string, unknown>): string | undefined {\n const content =\n message.content ??\n (isRecord(message.kwargs) ? message.kwargs.content : undefined) ??\n (isRecord(message.data) ? message.data.content : undefined);\n if (typeof content === 'string') {\n return content;\n }\n if (!Array.isArray(content)) {\n return undefined;\n }\n const text = content\n .filter(isRecord)\n .map((part) => (typeof part.text === 'string' ? part.text : ''))\n .join('');\n return text === '' ? undefined : text;\n}\n\nfunction findLastMessageText(value: unknown, role: string): string | undefined {\n const messages = getMessageArray(value);\n if (messages == null) {\n return undefined;\n }\n for (let i = messages.length - 1; i >= 0; i--) {\n if (getMessageRole(messages[i]) !== role) {\n continue;\n }\n const text = getMessageText(messages[i]);\n if (text != null && text.trim() !== '') {\n return text;\n }\n }\n return undefined;\n}\n\nfunction normalizeToolCall(value: unknown): SerializedToolCall | undefined {\n if (!isRecord(value)) {\n return undefined;\n }\n const fn = value.function;\n if (isRecord(fn) && typeof fn.name === 'string') {\n return {\n name: fn.name,\n args: parseAttributeValue(fn.arguments),\n ...(typeof value.id === 'string' ? { id: value.id } : {}),\n };\n }\n if (typeof value.name !== 'string') {\n return undefined;\n }\n return {\n name: value.name,\n args: value.args ?? {},\n ...(typeof value.id === 'string' ? { id: value.id } : {}),\n };\n}\n\nfunction getMessageToolCalls(\n message: Record<string, unknown>\n): SerializedToolCall[] {\n const rawCalls =\n message.tool_calls ??\n (isRecord(message.kwargs) ? message.kwargs.tool_calls : undefined) ??\n (isRecord(message.additional_kwargs)\n ? message.additional_kwargs.tool_calls\n : undefined) ??\n (isRecord(message.data) ? message.data.tool_calls : undefined);\n if (!Array.isArray(rawCalls)) {\n return [];\n }\n const calls: SerializedToolCall[] = [];\n for (const rawCall of rawCalls) {\n const call = normalizeToolCall(rawCall);\n if (call != null) {\n calls.push(call);\n }\n }\n return calls;\n}\n\n/**\n * Id-bearing `invalid_tool_calls` on the assistant turn. ToolNode pairs these\n * with synthesized error results (and an invalid-only turn is routed on them\n * alone), so the tool-dispatch span must count them as part of the executing\n * batch — otherwise an invalid-only dispatch finds zero calls and the span\n * keeps the full serialized graph state as its input, and a mixed dispatch\n * silently omits the malformed call. `args` stays the raw unparsed string.\n */\n/** Tool-result ids present in the serialized state — ToolNode's\n * `!toolMessageIds.has(id)` execution filter, mirrored for the span. */\nfunction getToolResultIds(\n messages: Record<string, unknown>[]\n): Set<string> {\n const ids = new Set<string>();\n for (const message of messages) {\n if (getMessageRole(message) !== 'tool') {\n continue;\n }\n const rawId =\n message.tool_call_id ??\n (isRecord(message.kwargs) ? message.kwargs.tool_call_id : undefined) ??\n (isRecord(message.data) ? message.data.tool_call_id : undefined);\n if (typeof rawId === 'string' && rawId !== '') {\n ids.add(rawId);\n }\n }\n return ids;\n}\n\nfunction getMessageInvalidToolCalls(\n message: Record<string, unknown>,\n answeredIds: ReadonlySet<string>\n): SerializedToolCall[] {\n const rawCalls =\n message.invalid_tool_calls ??\n (isRecord(message.kwargs) ? message.kwargs.invalid_tool_calls : undefined) ??\n (isRecord(message.data) ? message.data.invalid_tool_calls : undefined);\n if (!Array.isArray(rawCalls)) {\n return [];\n }\n const calls: SerializedToolCall[] = [];\n for (const rawCall of rawCalls) {\n // Same attribution predicate ToolNode executes with (id-bearing,\n // non-server) so the span never claims calls the node deliberately skips.\n if (\n !isRecord(rawCall) ||\n typeof rawCall.id !== 'string' ||\n rawCall.id === '' ||\n answeredIds.has(rawCall.id) ||\n rawCall.id.startsWith(Constants.ANTHROPIC_SERVER_TOOL_PREFIX)\n ) {\n continue;\n }\n // Same name fallback ToolNode synthesizes with — a nameless attributable\n // call still gets a result, so it must still count in the span input.\n const call = normalizeToolCall(\n typeof rawCall.name === 'string' && rawCall.name !== ''\n ? rawCall\n : { ...rawCall, name: 'unknown' }\n );\n if (call != null) {\n calls.push(call);\n }\n }\n return calls;\n}\n\n/** The serialized message's own id (uuid), NOT the LC-serialization type id\n * array that `message.id` carries in constructor dumps. */\nfunction getSerializedMessageId(\n message: Record<string, unknown>\n): string | undefined {\n const kwargsId = isRecord(message.kwargs) ? message.kwargs.id : undefined;\n const dataId = isRecord(message.data) ? message.data.id : undefined;\n const rawId = message.id;\n const id = kwargsId ?? dataId ?? rawId;\n return typeof id === 'string' && id !== '' ? id : undefined;\n}\n\n/** Latest assistant turn's tool calls — the calls this tool node is executing. */\nfunction findPendingToolCalls(value: unknown): SerializedToolCall[] {\n const messages = getMessageArray(value);\n if (messages == null) {\n return [];\n }\n /**\n * Invalid calls count only where ToolNode's own gate lets them execute:\n * the messages-state form (a bare-array state means the node returns a\n * plain output list and skips invalid handling) with an id-bearing\n * assistant message (no id, no reducer upsert). Mirrors\n * `canPromoteInvalidCalls` so the span never reports skipped calls.\n */\n const invalidCallsApply = !Array.isArray(value);\n const answeredIds = invalidCallsApply\n ? getToolResultIds(messages)\n : undefined;\n for (let i = messages.length - 1; i >= 0; i--) {\n if (getMessageRole(messages[i]) !== 'assistant') {\n continue;\n }\n const calls = [\n ...getMessageToolCalls(messages[i]),\n ...(invalidCallsApply && getSerializedMessageId(messages[i]) != null\n ? getMessageInvalidToolCalls(messages[i], answeredIds!)\n : []),\n ];\n if (calls.length > 0) {\n return calls;\n }\n }\n return [];\n}\n\nfunction getRootSpanParentId(span: ReadableSpan): string | undefined {\n const legacyParent = (span as { parentSpanId?: string }).parentSpanId;\n if (typeof legacyParent === 'string' && legacyParent !== '') {\n return legacyParent;\n }\n const parentContext = (span as { parentSpanContext?: { spanId?: string } })\n .parentSpanContext;\n const spanId = parentContext?.spanId;\n return typeof spanId === 'string' && spanId !== '' ? spanId : undefined;\n}\n\nfunction isRootSpan(span: ReadableSpan): boolean {\n return getRootSpanParentId(span) == null;\n}\n\n/**\n * LangGraph plumbing observations that add noise without information:\n * the duplicated `__start__` channel-seed nodes and anonymous\n * `RunnableLambda` pass-throughs (Langfuse team feedback items 4 & 5).\n * Internal ToolNode batch spans are disabled at their source so traced child\n * tools retain an exported parent. Explicitly traced ToolNodes are preserved.\n */\nexport function shouldDropLangfuseSpan(spanName: string): boolean {\n return (\n spanName === LANGGRAPH_START_NODE || spanName === ANONYMOUS_LAMBDA_NAME\n );\n}\n\nfunction shapeToolNodeSpan(span: MutableSpan): void {\n const inputKey = LangfuseOtelSpanAttributes.OBSERVATION_INPUT;\n span.name = TOOL_DISPATCH_SPAN_NAME;\n span.attributes[LangfuseOtelSpanAttributes.OBSERVATION_TYPE] =\n CHAIN_OBSERVATION_TYPE;\n const calls = findPendingToolCalls(\n parseAttributeValue(span.attributes[inputKey])\n );\n if (calls.length === 0) {\n return;\n }\n span.attributes[inputKey] = JSON.stringify(\n calls.map(({ name, args }) => ({ name, args }))\n );\n}\n\nfunction shapeAgentNodeSpan(span: MutableSpan): void {\n span.name = AGENT_NODE_SPAN_NAME;\n span.attributes[LangfuseOtelSpanAttributes.OBSERVATION_TYPE] =\n ROOT_OBSERVATION_TYPE;\n}\n\nfunction shapeRootSpan(span: MutableSpan): void {\n const inputKey = LangfuseOtelSpanAttributes.OBSERVATION_INPUT;\n const outputKey = LangfuseOtelSpanAttributes.OBSERVATION_OUTPUT;\n const question = findLastMessageText(\n parseAttributeValue(span.attributes[inputKey]),\n 'user'\n );\n const answer = findLastMessageText(\n parseAttributeValue(span.attributes[outputKey]),\n 'assistant'\n );\n /** A generation that IS the trace root — a bare `model.invoke` with no\n * wrapping chain, i.e. the activity-label path — is also the only\n * observation carrying its own prompt: reducing its observation input\n * would discard the SystemMessage from the one place it is traced.\n * Chain/agent roots keep the full reduction; their child generations\n * still record the complete prompt. Trace-level input/output reduce\n * either way, so the trace list keeps showing question and answer. */\n if (!isGenerationSpan(span)) {\n if (question != null) {\n span.attributes[inputKey] = question;\n }\n if (answer != null) {\n span.attributes[outputKey] = answer;\n }\n }\n const traceInput = question ?? span.attributes[inputKey];\n const traceOutput = answer ?? span.attributes[outputKey];\n if (traceInput != null) {\n span.attributes[LangfuseOtelSpanAttributes.TRACE_INPUT] = traceInput;\n }\n if (traceOutput != null) {\n span.attributes[LangfuseOtelSpanAttributes.TRACE_OUTPUT] = traceOutput;\n }\n}\n\nfunction isGenerationSpan(span: MutableSpan): boolean {\n const type = span.attributes[LangfuseOtelSpanAttributes.OBSERVATION_TYPE];\n return typeof type === 'string' && type.toLowerCase() === 'generation';\n}\n\nfunction isToolSpan(span: MutableSpan): boolean {\n const type = span.attributes[LangfuseOtelSpanAttributes.OBSERVATION_TYPE];\n return (\n typeof type === 'string' && type.toLowerCase() === TOOL_OBSERVATION_TYPE\n );\n}\n\n/**\n * Whether the span is a LangGraph node execution whose node id is the span\n * name — the shape of the outer workflow-agent node. `@langfuse/tracing`\n * flattens object metadata to per-key attributes with string values stored\n * raw, so LangGraph's `langgraph_node` arrives directly comparable.\n */\nfunction isWorkflowNodeSpan(span: MutableSpan): boolean {\n return span.attributes[OBSERVATION_METADATA_LANGGRAPH_NODE] === span.name;\n}\n\n/**\n * LibreChat ephemeral agents are identified as\n * `endpoint__model___sender[____index]` (`__` encodes `:`; see LibreChat's\n * `encodeEphemeralAgentId`), and the outer workflow node carries that id as\n * its span name — so switching models renames the span (item 1). Returns the\n * stable human `sender` segment only when the name matches that encoding:\n * the `endpoint__model` prefix must contain both segments and — unlike\n * display names such as `LibreChat Agent: Ops___EU` — never contains\n * whitespace, so legitimate names that merely embed `___` are left alone.\n */\nfunction extractEphemeralAgentSender(name: string): string | undefined {\n let workingId = name;\n const indexSeparator = workingId.lastIndexOf(EPHEMERAL_AGENT_INDEX_SEPARATOR);\n if (\n indexSeparator !== -1 &&\n /^\\d+$/.test(\n workingId.slice(indexSeparator + EPHEMERAL_AGENT_INDEX_SEPARATOR.length)\n )\n ) {\n workingId = workingId.slice(0, indexSeparator);\n }\n const senderSeparator = workingId.indexOf(EPHEMERAL_AGENT_SENDER_SEPARATOR);\n if (senderSeparator <= 0) {\n return undefined;\n }\n const encodedPrefix = workingId.slice(0, senderSeparator);\n if (/\\s/.test(encodedPrefix)) {\n return undefined;\n }\n const prefixParts = encodedPrefix.split('__');\n if (prefixParts.length < 2 || prefixParts.some((part) => part === '')) {\n return undefined;\n }\n const sender = workingId\n .slice(senderSeparator + EPHEMERAL_AGENT_SENDER_SEPARATOR.length)\n .replace(/__/g, ':');\n return sender === '' ? undefined : sender;\n}\n\n/** Workflow-agent node spans are always children of the run's root chain and\n * always carry `langgraph_node` metadata equal to their name, so host-named\n * run roots (`LibreChat Agent: <name>`) and ordinary chains that merely look\n * like encoded ids (`pipeline__stage___EU`) are never rename candidates.\n * Successful decodes become `agent` observations, matching the inner\n * `agent=<id>` node shaping. */\nfunction shapeEphemeralAgentNodeSpan(span: MutableSpan): void {\n if (isToolSpan(span) || isRootSpan(span) || !isWorkflowNodeSpan(span)) {\n return;\n }\n const sender = extractEphemeralAgentSender(span.name);\n if (sender == null) {\n return;\n }\n span.name = sender;\n span.attributes[LangfuseOtelSpanAttributes.OBSERVATION_TYPE] =\n ROOT_OBSERVATION_TYPE;\n}\n\nfunction hasTraceTag(span: MutableSpan, expectedTag: string): boolean {\n const tags = parseAttributeValue(\n span.attributes[LangfuseOtelSpanAttributes.TRACE_TAGS]\n );\n return (\n Array.isArray(tags) &&\n tags.some((tag) => typeof tag === 'string' && tag === expectedTag)\n );\n}\n\nfunction shapeRootObservationType(span: MutableSpan): void {\n if (isGenerationSpan(span)) {\n return;\n }\n if (\n hasTraceTag(span, TITLE_TRACE_TAG) ||\n (span.name === ACTIVITY_PHASE_ROOT_NAME &&\n hasTraceTag(span, ACTIVITY_PHASE_TRACE_TAG))\n ) {\n span.attributes[LangfuseOtelSpanAttributes.OBSERVATION_TYPE] =\n CHAIN_OBSERVATION_TYPE;\n return;\n }\n if (hasTraceTag(span, AGENT_TRACE_TAG)) {\n span.attributes[LangfuseOtelSpanAttributes.OBSERVATION_TYPE] =\n ROOT_OBSERVATION_TYPE;\n }\n}\n\n/**\n * Reshapes spans per Langfuse-team feedback before export:\n * - `agent=<id>` / `tools=<id>` node names carry the ephemeral agent id\n * (`provider__model`) — strip it so switching models doesn't break\n * name-based logic (item 1). The outer workflow node is named with the\n * bare agent id; ephemeral ids reduce to their stable sender name.\n * - LLM generation spans keep the provider client class name (`ChatOpenAI`,\n * `AzureChatOpenAI`, …); rename them to a provider-agnostic `llm` so the\n * name reflects the operation, not the model (the model stays on the\n * generation's model attribute).\n * - Agent nodes become `agent` observations, while tool-dispatch nodes become\n * stable `chain` observations whose input is scoped to the pending calls.\n * Individual child calls remain `tool` observations (items 3 & 4).\n * - Agent trace roots become `agent` observations, while title and activity\n * summary roots become `chain` observations. Root and trace input/output are\n * reduced to the user question and assistant response when chat messages are\n * available (item 2).\n */\nexport function shapeLangfuseSpan(span: ReadableSpan): void {\n const mutable = span as MutableSpan;\n if (mutable.name.startsWith(LANGGRAPH_AGENT_NODE_PREFIX)) {\n shapeAgentNodeSpan(mutable);\n } else if (mutable.name.startsWith(LANGGRAPH_TOOL_NODE_PREFIX)) {\n shapeToolNodeSpan(mutable);\n } else if (isGenerationSpan(mutable)) {\n mutable.name = GENERATION_SPAN_NAME;\n } else {\n shapeEphemeralAgentNodeSpan(mutable);\n }\n if (!isRootSpan(span)) {\n return;\n }\n shapeRootObservationType(mutable);\n shapeRootSpan(mutable);\n}\n"],"mappings":"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"}
|
|
@@ -291,13 +291,18 @@ function convertBaseMessagesToContent(messages, isMultimodalModel, convertSystem
|
|
|
291
291
|
}
|
|
292
292
|
/**
|
|
293
293
|
* Gemini models that reject a request whose `contents` end with a `model`-role
|
|
294
|
-
* turn (a "prefill"). Google enforces this on newer generations (Gemini 3.
|
|
295
|
-
* Flash, Gemini 3.5 Flash-Lite) while older/sibling models
|
|
296
|
-
* trailing model turn, so the rule is model-scoped rather than
|
|
297
|
-
* Extend this list as Google applies the restriction to further
|
|
294
|
+
* turn (a "prefill"). Google enforces this on newer generations (Gemini 3.7
|
|
295
|
+
* Flash, Gemini 3.6 Flash, Gemini 3.5 Flash-Lite) while older/sibling models
|
|
296
|
+
* still accept a trailing model turn, so the rule is model-scoped rather than
|
|
297
|
+
* version-wide. Extend this list as Google applies the restriction to further
|
|
298
|
+
* models.
|
|
298
299
|
* @see https://ai.google.dev/gemini-api/docs/latest-model#api-changes-and-parameter-updates
|
|
299
300
|
*/
|
|
300
|
-
const NO_PREFILL_GEMINI_MODELS = [
|
|
301
|
+
const NO_PREFILL_GEMINI_MODELS = [
|
|
302
|
+
"gemini-3.7-flash",
|
|
303
|
+
"gemini-3.6-flash",
|
|
304
|
+
"gemini-3.5-flash-lite"
|
|
305
|
+
];
|
|
301
306
|
function rejectsModelTurnPrefill(model) {
|
|
302
307
|
if (model == null || model === "") return false;
|
|
303
308
|
const modelId = model.toLowerCase().split("/").pop() ?? "";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"common.cjs","names":["ChatMessage","toLangChainContent","STREAMED_TOOL_CALL_ADAPTER_METADATA_KEY","GOOGLE_STREAMED_TOOL_CALL_ADAPTER","STREAMED_TOOL_CALL_SEAL_METADATA_KEY","ChatGenerationChunk","AIMessageChunk","AIMessage"],"sources":["../../../../../src/llm/google/utils/common.ts"],"sourcesContent":["import { v4 as uuidv4 } from 'uuid';\nimport { ChatGenerationChunk } from '@langchain/core/outputs';\nimport { ToolCallChunk } from '@langchain/core/messages/tool';\nimport { isOpenAITool } from '@langchain/core/language_models/base';\nimport { isLangChainTool } from '@langchain/core/utils/function_calling';\nimport {\n AIMessage,\n AIMessageChunk,\n BaseMessage,\n ChatMessage,\n ToolMessage,\n ToolMessageChunk,\n MessageContent,\n MessageContentComplex,\n UsageMetadata,\n isAIMessage,\n isBaseMessage,\n isToolMessage,\n StandardContentBlockConverter,\n parseBase64DataUrl,\n convertToProviderContentBlock,\n isDataContentBlock,\n} from '@langchain/core/messages';\nimport {\n POSSIBLE_ROLES,\n type Part,\n type Content,\n type TextPart,\n type FileDataPart,\n type InlineDataPart,\n type FunctionCallPart,\n type GenerateContentCandidate,\n type EnhancedGenerateContentResponse,\n type FunctionDeclaration as GenerativeAIFunctionDeclaration,\n type FunctionDeclarationsTool as GoogleGenerativeAIFunctionDeclarationsTool,\n} from '@google/generative-ai';\nimport type { ChatGeneration, ChatResult } from '@langchain/core/outputs';\nimport {\n STREAMED_TOOL_CALL_SEAL_METADATA_KEY,\n STREAMED_TOOL_CALL_ADAPTER_METADATA_KEY,\n GOOGLE_STREAMED_TOOL_CALL_ADAPTER,\n} from '@/tools/streamedToolCallSeals';\nimport {\n jsonSchemaToGeminiParameters,\n schemaToGenerativeAIParameters,\n} from './zod_to_genai_parameters';\nimport { toLangChainContent } from '@/messages/langchain';\nimport { GoogleGenerativeAIToolType } from '../types';\n\nexport const _FUNCTION_CALL_THOUGHT_SIGNATURES_MAP_KEY =\n '__gemini_function_call_thought_signatures__';\n\nconst DUMMY_SIGNATURE =\n 'ErYCCrMCAdHtim9kOoOkrPiCNVsmlpMIKd7ZMxgiFbVQOkgp7nlLcDMzVsZwIzvuT7nQROivoXA72ccC2lSDvR0Gh7dkWaGuj7ctv6t7ZceHnecx0QYa+ix8tYpRfjhyWozQ49lWiws6+YGjCt10KRTyWsZ2h6O7iHTYJwKIRwGUHRKy/qK/6kFxJm5ML00gLq4D8s5Z6DBpp2ZlR+uF4G8jJgeWQgyHWVdx2wGYElaceVAc66tZdPQRdOHpWtgYSI1YdaXgVI8KHY3/EfNc2YqqMIulvkDBAnuMhkAjV9xmBa54Tq+ih3Im4+r3DzqhGqYdsSkhS0kZMwte4Hjs65dZzCw9lANxIqYi1DJ639WNPYihp/DCJCos7o+/EeSPJaio5sgWDyUnMGkY1atsJZ+m7pj7DD5tvQ==';\n\ntype GoogleServerSideToolPart = Part & {\n type?: 'toolCall' | 'toolResponse';\n toolCall?: object;\n toolResponse?: object;\n};\n\ntype GoogleServerSideToolPartMetadata = {\n thought?: boolean;\n thoughtSignature?: string;\n};\n\ntype GoogleFunctionCallWithId = FunctionCallPart['functionCall'] & {\n id?: string;\n};\n\ntype GoogleFunctionResponseWithId = {\n name: string;\n response: object;\n id?: string;\n};\n\nfunction getGoogleFunctionId(id?: string): string | undefined {\n return id != null && id !== '' ? id : undefined;\n}\n\nfunction createGoogleFunctionResponsePart({\n name,\n response,\n id,\n}: {\n name: string;\n response: object;\n id?: string;\n}): Part {\n const functionId = getGoogleFunctionId(id);\n const functionResponse: GoogleFunctionResponseWithId = {\n name,\n response,\n ...(functionId != null ? { id: functionId } : {}),\n };\n return { functionResponse };\n}\n\n/**\n * Executes a function immediately and returns its result.\n * Functional utility similar to an Immediately Invoked Function Expression (IIFE).\n * @param fn The function to execute.\n * @returns The result of invoking fn.\n */\nexport const iife = <T>(fn: () => T): T => fn();\n\nexport function getMessageAuthor(message: BaseMessage): string {\n const type = message._getType();\n if (ChatMessage.isInstance(message)) {\n return message.role;\n }\n if (type === 'tool') {\n return type;\n }\n return message.name ?? type;\n}\n\n/**\n * Maps a message type to a Google Generative AI chat author.\n * @param message The message to map.\n * @param model The model to use for mapping.\n * @returns The message type mapped to a Google Generative AI chat author.\n */\nexport function convertAuthorToRole(\n author: string\n): (typeof POSSIBLE_ROLES)[number] {\n switch (author) {\n /**\n * Note: Gemini currently is not supporting system messages\n * we will convert them to human messages and merge with following\n * */\n case 'supervisor':\n case 'ai':\n case 'model': // getMessageAuthor returns message.name. code ex.: return message.name ?? type;\n return 'model';\n case 'system':\n return 'system';\n case 'human':\n return 'user';\n case 'tool':\n case 'function':\n return 'function';\n default:\n throw new Error(`Unknown / unsupported author: ${author}`);\n }\n}\n\nfunction messageContentMedia(content: MessageContentComplex): Part {\n if ('mimeType' in content && 'data' in content) {\n return {\n inlineData: {\n mimeType: content.mimeType,\n data: content.data,\n },\n };\n }\n if ('mimeType' in content && 'fileUri' in content) {\n return {\n fileData: {\n mimeType: content.mimeType,\n fileUri: content.fileUri,\n },\n };\n }\n\n throw new Error('Invalid media content');\n}\n\nfunction isGoogleServerSideToolPart(\n content: MessageContentComplex\n): content is MessageContentComplex & GoogleServerSideToolPart {\n return (\n 'toolCall' in content ||\n 'toolResponse' in content ||\n content.type === 'toolCall' ||\n content.type === 'toolResponse'\n );\n}\n\nfunction convertGoogleServerSideToolPart(\n content: MessageContentComplex & GoogleServerSideToolPart\n): Part {\n const metadata: GoogleServerSideToolPartMetadata = {};\n if ('thought' in content && typeof content.thought === 'boolean') {\n metadata.thought = content.thought;\n }\n if (\n 'thoughtSignature' in content &&\n typeof content.thoughtSignature === 'string'\n ) {\n metadata.thoughtSignature = content.thoughtSignature;\n }\n if ('toolCall' in content && content.toolCall != null) {\n return { toolCall: content.toolCall, ...metadata } as unknown as Part;\n }\n if ('toolResponse' in content && content.toolResponse != null) {\n return {\n toolResponse: content.toolResponse,\n ...metadata,\n } as unknown as Part;\n }\n\n return content as Part;\n}\n\nfunction convertGoogleServerSideToolResponsePart(\n part: Part\n): GoogleServerSideToolPart | undefined {\n if (\n 'toolCall' in part &&\n typeof part.toolCall === 'object' &&\n part.toolCall != null\n ) {\n return { ...part, type: 'toolCall', toolCall: part.toolCall };\n }\n if (\n 'toolResponse' in part &&\n typeof part.toolResponse === 'object' &&\n part.toolResponse != null\n ) {\n return { ...part, type: 'toolResponse', toolResponse: part.toolResponse };\n }\n return undefined;\n}\n\nfunction inferToolNameFromPreviousMessages(\n message: ToolMessage | ToolMessageChunk,\n previousMessages: BaseMessage[]\n): string | undefined {\n return previousMessages\n .map((msg) => {\n if (isAIMessage(msg)) {\n return msg.tool_calls ?? [];\n }\n return [];\n })\n .flat()\n .find((toolCall) => {\n return toolCall.id === message.tool_call_id;\n })?.name;\n}\n\nfunction _getStandardContentBlockConverter(\n isMultimodalModel: boolean\n): StandardContentBlockConverter<{\n text: TextPart;\n image: FileDataPart | InlineDataPart;\n audio: FileDataPart | InlineDataPart;\n file: FileDataPart | InlineDataPart | TextPart;\n}> {\n const standardContentBlockConverter: StandardContentBlockConverter<{\n text: TextPart;\n image: FileDataPart | InlineDataPart;\n audio: FileDataPart | InlineDataPart;\n file: FileDataPart | InlineDataPart | TextPart;\n }> = {\n providerName: 'Google Gemini',\n\n fromStandardTextBlock(block) {\n return {\n text: block.text,\n };\n },\n\n fromStandardImageBlock(block): FileDataPart | InlineDataPart {\n if (!isMultimodalModel) {\n throw new Error('This model does not support images');\n }\n if (block.source_type === 'url') {\n const data = parseBase64DataUrl({ dataUrl: block.url });\n if (data) {\n return {\n inlineData: {\n mimeType: data.mime_type,\n data: data.data,\n },\n };\n } else {\n return {\n fileData: {\n mimeType: block.mime_type ?? '',\n fileUri: block.url,\n },\n };\n }\n }\n\n if (block.source_type === 'base64') {\n return {\n inlineData: {\n mimeType: block.mime_type ?? '',\n data: block.data,\n },\n };\n }\n\n throw new Error(`Unsupported source type: ${block.source_type}`);\n },\n\n fromStandardAudioBlock(block): FileDataPart | InlineDataPart {\n if (!isMultimodalModel) {\n throw new Error('This model does not support audio');\n }\n if (block.source_type === 'url') {\n const data = parseBase64DataUrl({ dataUrl: block.url });\n if (data) {\n return {\n inlineData: {\n mimeType: data.mime_type,\n data: data.data,\n },\n };\n } else {\n return {\n fileData: {\n mimeType: block.mime_type ?? '',\n fileUri: block.url,\n },\n };\n }\n }\n\n if (block.source_type === 'base64') {\n return {\n inlineData: {\n mimeType: block.mime_type ?? '',\n data: block.data,\n },\n };\n }\n\n throw new Error(`Unsupported source type: ${block.source_type}`);\n },\n\n fromStandardFileBlock(block): FileDataPart | InlineDataPart | TextPart {\n if (!isMultimodalModel) {\n throw new Error('This model does not support files');\n }\n if (block.source_type === 'text') {\n return {\n text: block.text,\n };\n }\n if (block.source_type === 'url') {\n const data = parseBase64DataUrl({ dataUrl: block.url });\n if (data) {\n return {\n inlineData: {\n mimeType: data.mime_type,\n data: data.data,\n },\n };\n } else {\n return {\n fileData: {\n mimeType: block.mime_type ?? '',\n fileUri: block.url,\n },\n };\n }\n }\n\n if (block.source_type === 'base64') {\n return {\n inlineData: {\n mimeType: block.mime_type ?? '',\n data: block.data,\n },\n };\n }\n throw new Error(`Unsupported source type: ${block.source_type}`);\n },\n };\n return standardContentBlockConverter;\n}\n\nfunction _convertLangChainContentToPart(\n content: MessageContentComplex,\n isMultimodalModel: boolean\n): Part | undefined {\n if (isDataContentBlock(content)) {\n return convertToProviderContentBlock(\n content,\n _getStandardContentBlockConverter(isMultimodalModel)\n );\n }\n\n if (isGoogleServerSideToolPart(content)) {\n return convertGoogleServerSideToolPart(content);\n }\n\n if (content.type === 'text') {\n return typeof content.text === 'string' && content.text !== ''\n ? { text: content.text }\n : undefined;\n } else if (content.type === 'executableCode') {\n return { executableCode: content.executableCode };\n } else if (content.type === 'codeExecutionResult') {\n return { codeExecutionResult: content.codeExecutionResult };\n } else if (content.type === 'image_url') {\n if (!isMultimodalModel) {\n throw new Error('This model does not support images');\n }\n let source: string;\n if (typeof content.image_url === 'string') {\n source = content.image_url;\n } else if (\n typeof content.image_url === 'object' &&\n 'url' in content.image_url\n ) {\n source = content.image_url.url;\n } else {\n throw new Error('Please provide image as base64 encoded data URL');\n }\n const [dm, data] = source.split(',');\n if (!dm.startsWith('data:')) {\n throw new Error('Please provide image as base64 encoded data URL');\n }\n\n const [mimeType, encoding] = dm.replace(/^data:/, '').split(';');\n if (encoding !== 'base64') {\n throw new Error('Please provide image as base64 encoded data URL');\n }\n\n return {\n inlineData: {\n data,\n mimeType,\n },\n };\n } else if (content.type === 'media') {\n return messageContentMedia(content);\n } else if (content.type === 'tool_use') {\n const functionId = getGoogleFunctionId(\n typeof content.id === 'string' ? content.id : undefined\n );\n return {\n functionCall: {\n name: content.name,\n args: content.input,\n ...(functionId != null ? { id: functionId } : {}),\n },\n };\n } else if (\n content.type?.includes('/') === true &&\n // Ensure it's a single slash.\n content.type.split('/').length === 2 &&\n 'data' in content &&\n typeof content.data === 'string'\n ) {\n return {\n inlineData: {\n mimeType: content.type,\n data: content.data,\n },\n };\n } else if ('functionCall' in content) {\n // No action needed here — function calls will be added later from message.tool_calls\n return undefined;\n } else {\n if ('type' in content) {\n throw new Error(`Unknown content type ${content.type}`);\n } else {\n throw new Error(`Unknown content ${JSON.stringify(content)}`);\n }\n }\n}\n\nexport function convertMessageContentToParts(\n message: BaseMessage,\n isMultimodalModel: boolean,\n previousMessages: BaseMessage[],\n model?: string\n): Part[] {\n if (isToolMessage(message)) {\n const messageName =\n message.name ??\n inferToolNameFromPreviousMessages(message, previousMessages);\n if (messageName === undefined) {\n throw new Error(\n `Google requires a tool name for each tool call response, and we could not infer a called tool name for ToolMessage \"${message.id}\" from your passed messages. Please populate a \"name\" field on that ToolMessage explicitly.`\n );\n }\n\n const result = Array.isArray(message.content)\n ? (message.content\n .map((c) => _convertLangChainContentToPart(c, isMultimodalModel))\n .filter((p) => p !== undefined) as Part[])\n : message.content;\n\n if (message.status === 'error') {\n return [\n createGoogleFunctionResponsePart({\n name: messageName,\n // The API expects an object with an `error` field if the function call fails.\n // `error` must be a valid object (not a string or array), so we wrap `message.content` here\n response: { error: { details: result } },\n id: message.tool_call_id,\n }),\n ];\n }\n\n return [\n createGoogleFunctionResponsePart({\n name: messageName,\n // again, can't have a string or array value for `response`, so we wrap it as an object here\n response: { result },\n id: message.tool_call_id,\n }),\n ];\n }\n\n let functionCalls: FunctionCallPart[] = [];\n const messageParts: Part[] = [];\n\n if (typeof message.content === 'string' && message.content) {\n messageParts.push({ text: message.content });\n }\n\n if (Array.isArray(message.content)) {\n messageParts.push(\n ...(message.content\n .map((c) => _convertLangChainContentToPart(c, isMultimodalModel))\n .filter((p) => p !== undefined) as Part[])\n );\n }\n\n const functionThoughtSignatures = (\n message.additional_kwargs as BaseMessage['additional_kwargs'] | undefined\n )?.[_FUNCTION_CALL_THOUGHT_SIGNATURES_MAP_KEY] as\n | Record<string, string>\n | undefined;\n\n if (isAIMessage(message) && (message.tool_calls?.length ?? 0) > 0) {\n functionCalls = (message.tool_calls ?? []).map((tc) => {\n const thoughtSignature = iife(() => {\n if (tc.id != null && tc.id !== '') {\n const signature = functionThoughtSignatures?.[tc.id];\n if (signature != null && signature !== '') {\n return signature;\n }\n }\n if (model?.includes('gemini-3') === true) {\n return DUMMY_SIGNATURE;\n }\n return '';\n });\n const functionId = getGoogleFunctionId(tc.id);\n const functionCall: GoogleFunctionCallWithId = {\n name: tc.name,\n args: tc.args,\n ...(functionId != null ? { id: functionId } : {}),\n };\n\n return {\n functionCall,\n ...(thoughtSignature ? { thoughtSignature } : {}),\n };\n });\n }\n\n const parsedFunctionCallIds = new Set(\n functionCalls.flatMap((part) => {\n const functionCall = part.functionCall as GoogleFunctionCallWithId;\n return functionCall.id != null ? [functionCall.id] : [];\n })\n );\n const parsedFunctionCallNames = new Set(\n functionCalls.map((part) => part.functionCall.name)\n );\n const contentWithoutParsedMirrors = messageParts.filter((part) => {\n if (!('functionCall' in part) || part.functionCall == null) {\n return true;\n }\n const functionCall = part.functionCall as GoogleFunctionCallWithId;\n return !(\n (functionCall.id != null && parsedFunctionCallIds.has(functionCall.id)) ||\n (functionCall.id == null &&\n parsedFunctionCallNames.has(functionCall.name))\n );\n });\n\n return [...contentWithoutParsedMirrors, ...functionCalls];\n}\n\nexport function convertBaseMessagesToContent(\n messages: BaseMessage[],\n isMultimodalModel: boolean,\n convertSystemMessageToHumanContent: boolean = false,\n\n model?: string\n): Content[] | undefined {\n return messages.reduce<{\n content: Content[] | undefined;\n mergeWithPreviousContent: boolean;\n }>(\n (acc, message, index) => {\n if (!isBaseMessage(message)) {\n throw new Error('Unsupported message input');\n }\n const author = getMessageAuthor(message);\n if (author === 'system' && index !== 0) {\n throw new Error('System message should be the first one');\n }\n const role = convertAuthorToRole(author);\n\n const prevContent = acc.content?.[acc.content.length];\n if (\n !acc.mergeWithPreviousContent &&\n prevContent &&\n prevContent.role === role\n ) {\n throw new Error(\n 'Google Generative AI requires alternate messages between authors'\n );\n }\n\n const parts = convertMessageContentToParts(\n message,\n isMultimodalModel,\n messages.slice(0, index),\n model\n );\n\n if (acc.mergeWithPreviousContent) {\n const prevContent = acc.content?.[acc.content.length - 1];\n if (!prevContent) {\n throw new Error(\n 'There was a problem parsing your system message. Please try a prompt without one.'\n );\n }\n prevContent.parts.push(...parts);\n\n return {\n mergeWithPreviousContent: false,\n content: acc.content,\n };\n }\n let actualRole = role;\n if (\n actualRole === 'function' ||\n (actualRole === 'system' && !convertSystemMessageToHumanContent)\n ) {\n // GenerativeAI API will throw an error if the role is not \"user\" or \"model.\"\n actualRole = 'user';\n }\n const content: Content = {\n role: actualRole,\n parts,\n };\n return {\n mergeWithPreviousContent:\n author === 'system' && !convertSystemMessageToHumanContent,\n content: [...(acc.content ?? []), content],\n };\n },\n { content: [], mergeWithPreviousContent: false }\n ).content;\n}\n\n/**\n * Gemini models that reject a request whose `contents` end with a `model`-role\n * turn (a \"prefill\"). Google enforces this on newer generations (Gemini 3.6\n * Flash, Gemini 3.5 Flash-Lite) while older/sibling models still accept a\n * trailing model turn, so the rule is model-scoped rather than version-wide.\n * Extend this list as Google applies the restriction to further models.\n * @see https://ai.google.dev/gemini-api/docs/latest-model#api-changes-and-parameter-updates\n */\nconst NO_PREFILL_GEMINI_MODELS = [\n 'gemini-3.6-flash',\n 'gemini-3.5-flash-lite',\n] as const;\n\nexport function rejectsModelTurnPrefill(model?: string): boolean {\n if (model == null || model === '') {\n return false;\n }\n const modelId = model.toLowerCase().split('/').pop() ?? '';\n return NO_PREFILL_GEMINI_MODELS.some(\n (id) => modelId === id || modelId.startsWith(`${id}-`)\n );\n}\n\n/**\n * Drops trailing `model`-role turns for models that reject prefill (see\n * {@link rejectsModelTurnPrefill}). Such a turn is only produced by prefill\n * flows (e.g. editing an assistant reply and resubmitting); these models return\n * HTTP 400 for it, so we drop it and let the model generate fresh from the\n * preceding user turn. No-op for every other model, preserving working prefill.\n */\nexport function dropUnsupportedModelTurnPrefill(\n contents: Content[] | undefined,\n model?: string\n): Content[] | undefined {\n if (\n contents == null ||\n contents.length === 0 ||\n !rejectsModelTurnPrefill(model)\n ) {\n return contents;\n }\n let end = contents.length;\n while (end > 1 && contents[end - 1]?.role === 'model') {\n end -= 1;\n }\n return end === contents.length ? contents : contents.slice(0, end);\n}\n\nexport function convertResponseContentToChatGenerationChunk(\n response: EnhancedGenerateContentResponse,\n extra: {\n usageMetadata?: UsageMetadata | undefined;\n index: number;\n }\n): ChatGenerationChunk | null {\n if (!response.candidates || response.candidates.length === 0) {\n return null;\n }\n const [candidate] = response.candidates as [\n Partial<GenerateContentCandidate> | undefined,\n ];\n const { content: candidateContent, ...generationInfo } = candidate ?? {};\n\n // Extract function calls directly from parts to preserve thoughtSignature\n const functionCalls =\n (candidateContent?.parts as Part[] | undefined)?.reduce(\n (acc, p) => {\n if ('functionCall' in p && p.functionCall) {\n acc.push({\n ...p,\n id:\n 'id' in p.functionCall && typeof p.functionCall.id === 'string'\n ? p.functionCall.id\n : uuidv4(),\n });\n }\n return acc;\n },\n [] as (\n | undefined\n | (FunctionCallPart & { id: string; thoughtSignature?: string })\n )[]\n ) ?? [];\n\n let content: MessageContent | undefined;\n // Checks if some parts do not have text. If false, it means that the content is a string.\n const reasoningParts: string[] = [];\n if (\n candidateContent != null &&\n Array.isArray(candidateContent.parts) &&\n candidateContent.parts.every((p) => 'text' in p)\n ) {\n // content = candidateContent.parts.map((p) => p.text).join('');\n const textParts: string[] = [];\n for (const part of candidateContent.parts) {\n if ('thought' in part && part.thought === true) {\n reasoningParts.push(part.text ?? '');\n continue;\n }\n textParts.push(part.text ?? '');\n }\n content = textParts.join('');\n } else if (candidateContent && Array.isArray(candidateContent.parts)) {\n content = toLangChainContent(\n candidateContent.parts\n .map((p) => {\n if ('text' in p && 'thought' in p && p.thought === true) {\n reasoningParts.push(p.text ?? '');\n return undefined;\n } else if ('text' in p) {\n return {\n type: 'text',\n text: p.text,\n };\n } else if ('executableCode' in p) {\n return {\n type: 'executableCode',\n executableCode: p.executableCode,\n };\n } else if ('codeExecutionResult' in p) {\n return {\n type: 'codeExecutionResult',\n codeExecutionResult: p.codeExecutionResult,\n };\n }\n const serverSideToolPart = convertGoogleServerSideToolResponsePart(p);\n if (serverSideToolPart !== undefined) {\n return serverSideToolPart;\n }\n return p;\n })\n .filter((p) => p !== undefined)\n );\n } else {\n // no content returned - likely due to abnormal stop reason, e.g. malformed function call\n content = [];\n }\n\n let text = '';\n if (typeof content === 'string' && content) {\n text = content;\n } else if (Array.isArray(content)) {\n const block = content.find((b) => 'text' in b) as\n | { text: string }\n | undefined;\n text = block?.text ?? '';\n }\n\n const toolCallChunks: ToolCallChunk[] = [];\n if (functionCalls.length > 0) {\n toolCallChunks.push(\n ...functionCalls.map((fc) => ({\n type: 'tool_call_chunk' as const,\n id: fc?.id,\n name: fc?.functionCall.name,\n args: JSON.stringify(fc?.functionCall.args),\n }))\n );\n }\n\n // Extract thought signatures from function calls for Gemini 3+\n const functionThoughtSignatures = functionCalls.reduce(\n (acc, fc) => {\n if (\n fc &&\n 'thoughtSignature' in fc &&\n typeof fc.thoughtSignature === 'string'\n ) {\n acc[fc.id] = fc.thoughtSignature;\n }\n return acc;\n },\n {} as Record<string, string>\n );\n\n const additional_kwargs: ChatGeneration['message']['additional_kwargs'] = {\n [_FUNCTION_CALL_THOUGHT_SIGNATURES_MAP_KEY]: functionThoughtSignatures,\n };\n\n if (reasoningParts.length > 0) {\n additional_kwargs.reasoning = reasoningParts.join('');\n }\n\n if (candidate?.groundingMetadata) {\n additional_kwargs.groundingMetadata = candidate.groundingMetadata;\n }\n\n const isFinalChunk =\n response.candidates[0]?.finishReason === 'STOP' ||\n response.candidates[0]?.finishReason === 'MAX_TOKENS' ||\n response.candidates[0]?.finishReason === 'SAFETY';\n\n // The GenAI API delivers function calls as complete objects (never partial\n // arg deltas), so every call on this chunk is sealed on arrival for eager\n // tool execution.\n const response_metadata: Record<string, unknown> | undefined =\n toolCallChunks.length > 0\n ? {\n [STREAMED_TOOL_CALL_ADAPTER_METADATA_KEY]:\n GOOGLE_STREAMED_TOOL_CALL_ADAPTER,\n [STREAMED_TOOL_CALL_SEAL_METADATA_KEY]: { kind: 'all' },\n }\n : undefined;\n\n return new ChatGenerationChunk({\n text,\n message: new AIMessageChunk({\n content: content,\n name: !candidateContent ? undefined : candidateContent.role,\n tool_call_chunks: toolCallChunks,\n // Each chunk can have unique \"generationInfo\", and merging strategy is unclear,\n // so leave blank for now.\n additional_kwargs,\n response_metadata,\n usage_metadata: isFinalChunk ? extra.usageMetadata : undefined,\n }),\n generationInfo,\n });\n}\n\n/**\n * Maps a Google GenerateContentResult to a LangChain ChatResult\n */\nexport function mapGenerateContentResultToChatResult(\n response: EnhancedGenerateContentResponse,\n extra?: {\n usageMetadata: UsageMetadata | undefined;\n }\n): ChatResult {\n if (!response.candidates || response.candidates.length === 0) {\n return {\n generations: [],\n llmOutput: {\n filters: response.promptFeedback,\n },\n };\n }\n const [candidate] = response.candidates as [\n Partial<GenerateContentCandidate> | undefined,\n ];\n const { content: candidateContent, ...generationInfo } = candidate ?? {};\n\n // Extract function calls directly from parts to preserve thoughtSignature\n const functionCalls =\n candidateContent?.parts.reduce(\n (acc, p) => {\n if ('functionCall' in p && p.functionCall) {\n acc.push({\n ...p,\n id:\n 'id' in p.functionCall && typeof p.functionCall.id === 'string'\n ? p.functionCall.id\n : uuidv4(),\n });\n }\n return acc;\n },\n [] as (FunctionCallPart & { id: string; thoughtSignature?: string })[]\n ) ?? [];\n\n let content: MessageContent | undefined;\n const reasoningParts: string[] = [];\n if (\n Array.isArray(candidateContent?.parts) &&\n candidateContent.parts.length === 1 &&\n (candidateContent.parts[0].text ?? '') !== '' &&\n !(\n 'thought' in candidateContent.parts[0] &&\n candidateContent.parts[0].thought === true\n )\n ) {\n content = candidateContent.parts[0].text;\n } else if (\n Array.isArray(candidateContent?.parts) &&\n candidateContent.parts.length > 0\n ) {\n content = toLangChainContent(\n candidateContent.parts\n .map((p) => {\n if ('text' in p && 'thought' in p && p.thought === true) {\n reasoningParts.push(p.text ?? '');\n return undefined;\n } else if ('text' in p) {\n return {\n type: 'text',\n text: p.text,\n };\n } else if ('executableCode' in p) {\n return {\n type: 'executableCode',\n executableCode: p.executableCode,\n };\n } else if ('codeExecutionResult' in p) {\n return {\n type: 'codeExecutionResult',\n codeExecutionResult: p.codeExecutionResult,\n };\n }\n const serverSideToolPart = convertGoogleServerSideToolResponsePart(p);\n if (serverSideToolPart !== undefined) {\n return serverSideToolPart;\n }\n return p;\n })\n .filter((p) => p !== undefined)\n );\n } else {\n content = [];\n }\n let text = '';\n if (typeof content === 'string') {\n text = content;\n } else if (Array.isArray(content) && content.length > 0) {\n const block = content.find((b) => 'text' in b) as\n | { text: string }\n | undefined;\n text = block?.text ?? text;\n }\n\n const additional_kwargs: ChatGeneration['message']['additional_kwargs'] = {\n ...generationInfo,\n };\n if (reasoningParts.length > 0) {\n additional_kwargs.reasoning = reasoningParts.join('');\n }\n\n // Extract thought signatures from function calls for Gemini 3+\n const functionThoughtSignatures = functionCalls.reduce(\n (acc, fc) => {\n if ('thoughtSignature' in fc && typeof fc.thoughtSignature === 'string') {\n acc[fc.id] = fc.thoughtSignature;\n }\n return acc;\n },\n {} as Record<string, string>\n );\n\n const tool_calls = functionCalls.map((fc) => ({\n type: 'tool_call' as const,\n id: fc.id,\n name: fc.functionCall.name,\n args: fc.functionCall.args,\n }));\n\n // Store thought signatures map for later retrieval\n additional_kwargs[_FUNCTION_CALL_THOUGHT_SIGNATURES_MAP_KEY] =\n functionThoughtSignatures;\n\n const generation: ChatGeneration = {\n text,\n message: new AIMessage({\n content,\n tool_calls,\n additional_kwargs,\n usage_metadata: extra?.usageMetadata,\n }),\n generationInfo,\n };\n return {\n generations: [generation],\n llmOutput: {\n tokenUsage: {\n promptTokens: extra?.usageMetadata?.input_tokens,\n completionTokens: extra?.usageMetadata?.output_tokens,\n totalTokens: extra?.usageMetadata?.total_tokens,\n },\n },\n };\n}\n\nexport function convertToGenerativeAITools(\n tools: GoogleGenerativeAIToolType[]\n): GoogleGenerativeAIFunctionDeclarationsTool[] {\n if (\n tools.every(\n (tool) =>\n 'functionDeclarations' in tool &&\n Array.isArray(tool.functionDeclarations)\n )\n ) {\n return tools as GoogleGenerativeAIFunctionDeclarationsTool[];\n }\n return [\n {\n functionDeclarations: tools.map(\n (tool): GenerativeAIFunctionDeclaration => {\n if (isLangChainTool(tool)) {\n const jsonSchema = schemaToGenerativeAIParameters(tool.schema);\n if (\n jsonSchema.type === 'object' &&\n 'properties' in jsonSchema &&\n Object.keys(jsonSchema.properties).length === 0\n ) {\n return {\n name: tool.name,\n description: tool.description,\n };\n }\n return {\n name: tool.name,\n description: tool.description,\n parameters: jsonSchema,\n };\n }\n if (isOpenAITool(tool)) {\n return {\n name: tool.function.name,\n description:\n tool.function.description ?? 'A function available to call.',\n parameters: jsonSchemaToGeminiParameters(\n tool.function.parameters\n ),\n };\n }\n return tool as unknown as GenerativeAIFunctionDeclaration;\n }\n ),\n },\n ];\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"common.cjs","names":["ChatMessage","toLangChainContent","STREAMED_TOOL_CALL_ADAPTER_METADATA_KEY","GOOGLE_STREAMED_TOOL_CALL_ADAPTER","STREAMED_TOOL_CALL_SEAL_METADATA_KEY","ChatGenerationChunk","AIMessageChunk","AIMessage"],"sources":["../../../../../src/llm/google/utils/common.ts"],"sourcesContent":["import { v4 as uuidv4 } from 'uuid';\nimport { ChatGenerationChunk } from '@langchain/core/outputs';\nimport { ToolCallChunk } from '@langchain/core/messages/tool';\nimport { isOpenAITool } from '@langchain/core/language_models/base';\nimport { isLangChainTool } from '@langchain/core/utils/function_calling';\nimport {\n AIMessage,\n AIMessageChunk,\n BaseMessage,\n ChatMessage,\n ToolMessage,\n ToolMessageChunk,\n MessageContent,\n MessageContentComplex,\n UsageMetadata,\n isAIMessage,\n isBaseMessage,\n isToolMessage,\n StandardContentBlockConverter,\n parseBase64DataUrl,\n convertToProviderContentBlock,\n isDataContentBlock,\n} from '@langchain/core/messages';\nimport {\n POSSIBLE_ROLES,\n type Part,\n type Content,\n type TextPart,\n type FileDataPart,\n type InlineDataPart,\n type FunctionCallPart,\n type GenerateContentCandidate,\n type EnhancedGenerateContentResponse,\n type FunctionDeclaration as GenerativeAIFunctionDeclaration,\n type FunctionDeclarationsTool as GoogleGenerativeAIFunctionDeclarationsTool,\n} from '@google/generative-ai';\nimport type { ChatGeneration, ChatResult } from '@langchain/core/outputs';\nimport {\n STREAMED_TOOL_CALL_SEAL_METADATA_KEY,\n STREAMED_TOOL_CALL_ADAPTER_METADATA_KEY,\n GOOGLE_STREAMED_TOOL_CALL_ADAPTER,\n} from '@/tools/streamedToolCallSeals';\nimport {\n jsonSchemaToGeminiParameters,\n schemaToGenerativeAIParameters,\n} from './zod_to_genai_parameters';\nimport { toLangChainContent } from '@/messages/langchain';\nimport { GoogleGenerativeAIToolType } from '../types';\n\nexport const _FUNCTION_CALL_THOUGHT_SIGNATURES_MAP_KEY =\n '__gemini_function_call_thought_signatures__';\n\nconst DUMMY_SIGNATURE =\n 'ErYCCrMCAdHtim9kOoOkrPiCNVsmlpMIKd7ZMxgiFbVQOkgp7nlLcDMzVsZwIzvuT7nQROivoXA72ccC2lSDvR0Gh7dkWaGuj7ctv6t7ZceHnecx0QYa+ix8tYpRfjhyWozQ49lWiws6+YGjCt10KRTyWsZ2h6O7iHTYJwKIRwGUHRKy/qK/6kFxJm5ML00gLq4D8s5Z6DBpp2ZlR+uF4G8jJgeWQgyHWVdx2wGYElaceVAc66tZdPQRdOHpWtgYSI1YdaXgVI8KHY3/EfNc2YqqMIulvkDBAnuMhkAjV9xmBa54Tq+ih3Im4+r3DzqhGqYdsSkhS0kZMwte4Hjs65dZzCw9lANxIqYi1DJ639WNPYihp/DCJCos7o+/EeSPJaio5sgWDyUnMGkY1atsJZ+m7pj7DD5tvQ==';\n\ntype GoogleServerSideToolPart = Part & {\n type?: 'toolCall' | 'toolResponse';\n toolCall?: object;\n toolResponse?: object;\n};\n\ntype GoogleServerSideToolPartMetadata = {\n thought?: boolean;\n thoughtSignature?: string;\n};\n\ntype GoogleFunctionCallWithId = FunctionCallPart['functionCall'] & {\n id?: string;\n};\n\ntype GoogleFunctionResponseWithId = {\n name: string;\n response: object;\n id?: string;\n};\n\nfunction getGoogleFunctionId(id?: string): string | undefined {\n return id != null && id !== '' ? id : undefined;\n}\n\nfunction createGoogleFunctionResponsePart({\n name,\n response,\n id,\n}: {\n name: string;\n response: object;\n id?: string;\n}): Part {\n const functionId = getGoogleFunctionId(id);\n const functionResponse: GoogleFunctionResponseWithId = {\n name,\n response,\n ...(functionId != null ? { id: functionId } : {}),\n };\n return { functionResponse };\n}\n\n/**\n * Executes a function immediately and returns its result.\n * Functional utility similar to an Immediately Invoked Function Expression (IIFE).\n * @param fn The function to execute.\n * @returns The result of invoking fn.\n */\nexport const iife = <T>(fn: () => T): T => fn();\n\nexport function getMessageAuthor(message: BaseMessage): string {\n const type = message._getType();\n if (ChatMessage.isInstance(message)) {\n return message.role;\n }\n if (type === 'tool') {\n return type;\n }\n return message.name ?? type;\n}\n\n/**\n * Maps a message type to a Google Generative AI chat author.\n * @param message The message to map.\n * @param model The model to use for mapping.\n * @returns The message type mapped to a Google Generative AI chat author.\n */\nexport function convertAuthorToRole(\n author: string\n): (typeof POSSIBLE_ROLES)[number] {\n switch (author) {\n /**\n * Note: Gemini currently is not supporting system messages\n * we will convert them to human messages and merge with following\n * */\n case 'supervisor':\n case 'ai':\n case 'model': // getMessageAuthor returns message.name. code ex.: return message.name ?? type;\n return 'model';\n case 'system':\n return 'system';\n case 'human':\n return 'user';\n case 'tool':\n case 'function':\n return 'function';\n default:\n throw new Error(`Unknown / unsupported author: ${author}`);\n }\n}\n\nfunction messageContentMedia(content: MessageContentComplex): Part {\n if ('mimeType' in content && 'data' in content) {\n return {\n inlineData: {\n mimeType: content.mimeType,\n data: content.data,\n },\n };\n }\n if ('mimeType' in content && 'fileUri' in content) {\n return {\n fileData: {\n mimeType: content.mimeType,\n fileUri: content.fileUri,\n },\n };\n }\n\n throw new Error('Invalid media content');\n}\n\nfunction isGoogleServerSideToolPart(\n content: MessageContentComplex\n): content is MessageContentComplex & GoogleServerSideToolPart {\n return (\n 'toolCall' in content ||\n 'toolResponse' in content ||\n content.type === 'toolCall' ||\n content.type === 'toolResponse'\n );\n}\n\nfunction convertGoogleServerSideToolPart(\n content: MessageContentComplex & GoogleServerSideToolPart\n): Part {\n const metadata: GoogleServerSideToolPartMetadata = {};\n if ('thought' in content && typeof content.thought === 'boolean') {\n metadata.thought = content.thought;\n }\n if (\n 'thoughtSignature' in content &&\n typeof content.thoughtSignature === 'string'\n ) {\n metadata.thoughtSignature = content.thoughtSignature;\n }\n if ('toolCall' in content && content.toolCall != null) {\n return { toolCall: content.toolCall, ...metadata } as unknown as Part;\n }\n if ('toolResponse' in content && content.toolResponse != null) {\n return {\n toolResponse: content.toolResponse,\n ...metadata,\n } as unknown as Part;\n }\n\n return content as Part;\n}\n\nfunction convertGoogleServerSideToolResponsePart(\n part: Part\n): GoogleServerSideToolPart | undefined {\n if (\n 'toolCall' in part &&\n typeof part.toolCall === 'object' &&\n part.toolCall != null\n ) {\n return { ...part, type: 'toolCall', toolCall: part.toolCall };\n }\n if (\n 'toolResponse' in part &&\n typeof part.toolResponse === 'object' &&\n part.toolResponse != null\n ) {\n return { ...part, type: 'toolResponse', toolResponse: part.toolResponse };\n }\n return undefined;\n}\n\nfunction inferToolNameFromPreviousMessages(\n message: ToolMessage | ToolMessageChunk,\n previousMessages: BaseMessage[]\n): string | undefined {\n return previousMessages\n .map((msg) => {\n if (isAIMessage(msg)) {\n return msg.tool_calls ?? [];\n }\n return [];\n })\n .flat()\n .find((toolCall) => {\n return toolCall.id === message.tool_call_id;\n })?.name;\n}\n\nfunction _getStandardContentBlockConverter(\n isMultimodalModel: boolean\n): StandardContentBlockConverter<{\n text: TextPart;\n image: FileDataPart | InlineDataPart;\n audio: FileDataPart | InlineDataPart;\n file: FileDataPart | InlineDataPart | TextPart;\n}> {\n const standardContentBlockConverter: StandardContentBlockConverter<{\n text: TextPart;\n image: FileDataPart | InlineDataPart;\n audio: FileDataPart | InlineDataPart;\n file: FileDataPart | InlineDataPart | TextPart;\n }> = {\n providerName: 'Google Gemini',\n\n fromStandardTextBlock(block) {\n return {\n text: block.text,\n };\n },\n\n fromStandardImageBlock(block): FileDataPart | InlineDataPart {\n if (!isMultimodalModel) {\n throw new Error('This model does not support images');\n }\n if (block.source_type === 'url') {\n const data = parseBase64DataUrl({ dataUrl: block.url });\n if (data) {\n return {\n inlineData: {\n mimeType: data.mime_type,\n data: data.data,\n },\n };\n } else {\n return {\n fileData: {\n mimeType: block.mime_type ?? '',\n fileUri: block.url,\n },\n };\n }\n }\n\n if (block.source_type === 'base64') {\n return {\n inlineData: {\n mimeType: block.mime_type ?? '',\n data: block.data,\n },\n };\n }\n\n throw new Error(`Unsupported source type: ${block.source_type}`);\n },\n\n fromStandardAudioBlock(block): FileDataPart | InlineDataPart {\n if (!isMultimodalModel) {\n throw new Error('This model does not support audio');\n }\n if (block.source_type === 'url') {\n const data = parseBase64DataUrl({ dataUrl: block.url });\n if (data) {\n return {\n inlineData: {\n mimeType: data.mime_type,\n data: data.data,\n },\n };\n } else {\n return {\n fileData: {\n mimeType: block.mime_type ?? '',\n fileUri: block.url,\n },\n };\n }\n }\n\n if (block.source_type === 'base64') {\n return {\n inlineData: {\n mimeType: block.mime_type ?? '',\n data: block.data,\n },\n };\n }\n\n throw new Error(`Unsupported source type: ${block.source_type}`);\n },\n\n fromStandardFileBlock(block): FileDataPart | InlineDataPart | TextPart {\n if (!isMultimodalModel) {\n throw new Error('This model does not support files');\n }\n if (block.source_type === 'text') {\n return {\n text: block.text,\n };\n }\n if (block.source_type === 'url') {\n const data = parseBase64DataUrl({ dataUrl: block.url });\n if (data) {\n return {\n inlineData: {\n mimeType: data.mime_type,\n data: data.data,\n },\n };\n } else {\n return {\n fileData: {\n mimeType: block.mime_type ?? '',\n fileUri: block.url,\n },\n };\n }\n }\n\n if (block.source_type === 'base64') {\n return {\n inlineData: {\n mimeType: block.mime_type ?? '',\n data: block.data,\n },\n };\n }\n throw new Error(`Unsupported source type: ${block.source_type}`);\n },\n };\n return standardContentBlockConverter;\n}\n\nfunction _convertLangChainContentToPart(\n content: MessageContentComplex,\n isMultimodalModel: boolean\n): Part | undefined {\n if (isDataContentBlock(content)) {\n return convertToProviderContentBlock(\n content,\n _getStandardContentBlockConverter(isMultimodalModel)\n );\n }\n\n if (isGoogleServerSideToolPart(content)) {\n return convertGoogleServerSideToolPart(content);\n }\n\n if (content.type === 'text') {\n return typeof content.text === 'string' && content.text !== ''\n ? { text: content.text }\n : undefined;\n } else if (content.type === 'executableCode') {\n return { executableCode: content.executableCode };\n } else if (content.type === 'codeExecutionResult') {\n return { codeExecutionResult: content.codeExecutionResult };\n } else if (content.type === 'image_url') {\n if (!isMultimodalModel) {\n throw new Error('This model does not support images');\n }\n let source: string;\n if (typeof content.image_url === 'string') {\n source = content.image_url;\n } else if (\n typeof content.image_url === 'object' &&\n 'url' in content.image_url\n ) {\n source = content.image_url.url;\n } else {\n throw new Error('Please provide image as base64 encoded data URL');\n }\n const [dm, data] = source.split(',');\n if (!dm.startsWith('data:')) {\n throw new Error('Please provide image as base64 encoded data URL');\n }\n\n const [mimeType, encoding] = dm.replace(/^data:/, '').split(';');\n if (encoding !== 'base64') {\n throw new Error('Please provide image as base64 encoded data URL');\n }\n\n return {\n inlineData: {\n data,\n mimeType,\n },\n };\n } else if (content.type === 'media') {\n return messageContentMedia(content);\n } else if (content.type === 'tool_use') {\n const functionId = getGoogleFunctionId(\n typeof content.id === 'string' ? content.id : undefined\n );\n return {\n functionCall: {\n name: content.name,\n args: content.input,\n ...(functionId != null ? { id: functionId } : {}),\n },\n };\n } else if (\n content.type?.includes('/') === true &&\n // Ensure it's a single slash.\n content.type.split('/').length === 2 &&\n 'data' in content &&\n typeof content.data === 'string'\n ) {\n return {\n inlineData: {\n mimeType: content.type,\n data: content.data,\n },\n };\n } else if ('functionCall' in content) {\n // No action needed here — function calls will be added later from message.tool_calls\n return undefined;\n } else {\n if ('type' in content) {\n throw new Error(`Unknown content type ${content.type}`);\n } else {\n throw new Error(`Unknown content ${JSON.stringify(content)}`);\n }\n }\n}\n\nexport function convertMessageContentToParts(\n message: BaseMessage,\n isMultimodalModel: boolean,\n previousMessages: BaseMessage[],\n model?: string\n): Part[] {\n if (isToolMessage(message)) {\n const messageName =\n message.name ??\n inferToolNameFromPreviousMessages(message, previousMessages);\n if (messageName === undefined) {\n throw new Error(\n `Google requires a tool name for each tool call response, and we could not infer a called tool name for ToolMessage \"${message.id}\" from your passed messages. Please populate a \"name\" field on that ToolMessage explicitly.`\n );\n }\n\n const result = Array.isArray(message.content)\n ? (message.content\n .map((c) => _convertLangChainContentToPart(c, isMultimodalModel))\n .filter((p) => p !== undefined) as Part[])\n : message.content;\n\n if (message.status === 'error') {\n return [\n createGoogleFunctionResponsePart({\n name: messageName,\n // The API expects an object with an `error` field if the function call fails.\n // `error` must be a valid object (not a string or array), so we wrap `message.content` here\n response: { error: { details: result } },\n id: message.tool_call_id,\n }),\n ];\n }\n\n return [\n createGoogleFunctionResponsePart({\n name: messageName,\n // again, can't have a string or array value for `response`, so we wrap it as an object here\n response: { result },\n id: message.tool_call_id,\n }),\n ];\n }\n\n let functionCalls: FunctionCallPart[] = [];\n const messageParts: Part[] = [];\n\n if (typeof message.content === 'string' && message.content) {\n messageParts.push({ text: message.content });\n }\n\n if (Array.isArray(message.content)) {\n messageParts.push(\n ...(message.content\n .map((c) => _convertLangChainContentToPart(c, isMultimodalModel))\n .filter((p) => p !== undefined) as Part[])\n );\n }\n\n const functionThoughtSignatures = (\n message.additional_kwargs as BaseMessage['additional_kwargs'] | undefined\n )?.[_FUNCTION_CALL_THOUGHT_SIGNATURES_MAP_KEY] as\n | Record<string, string>\n | undefined;\n\n if (isAIMessage(message) && (message.tool_calls?.length ?? 0) > 0) {\n functionCalls = (message.tool_calls ?? []).map((tc) => {\n const thoughtSignature = iife(() => {\n if (tc.id != null && tc.id !== '') {\n const signature = functionThoughtSignatures?.[tc.id];\n if (signature != null && signature !== '') {\n return signature;\n }\n }\n if (model?.includes('gemini-3') === true) {\n return DUMMY_SIGNATURE;\n }\n return '';\n });\n const functionId = getGoogleFunctionId(tc.id);\n const functionCall: GoogleFunctionCallWithId = {\n name: tc.name,\n args: tc.args,\n ...(functionId != null ? { id: functionId } : {}),\n };\n\n return {\n functionCall,\n ...(thoughtSignature ? { thoughtSignature } : {}),\n };\n });\n }\n\n const parsedFunctionCallIds = new Set(\n functionCalls.flatMap((part) => {\n const functionCall = part.functionCall as GoogleFunctionCallWithId;\n return functionCall.id != null ? [functionCall.id] : [];\n })\n );\n const parsedFunctionCallNames = new Set(\n functionCalls.map((part) => part.functionCall.name)\n );\n const contentWithoutParsedMirrors = messageParts.filter((part) => {\n if (!('functionCall' in part) || part.functionCall == null) {\n return true;\n }\n const functionCall = part.functionCall as GoogleFunctionCallWithId;\n return !(\n (functionCall.id != null && parsedFunctionCallIds.has(functionCall.id)) ||\n (functionCall.id == null &&\n parsedFunctionCallNames.has(functionCall.name))\n );\n });\n\n return [...contentWithoutParsedMirrors, ...functionCalls];\n}\n\nexport function convertBaseMessagesToContent(\n messages: BaseMessage[],\n isMultimodalModel: boolean,\n convertSystemMessageToHumanContent: boolean = false,\n\n model?: string\n): Content[] | undefined {\n return messages.reduce<{\n content: Content[] | undefined;\n mergeWithPreviousContent: boolean;\n }>(\n (acc, message, index) => {\n if (!isBaseMessage(message)) {\n throw new Error('Unsupported message input');\n }\n const author = getMessageAuthor(message);\n if (author === 'system' && index !== 0) {\n throw new Error('System message should be the first one');\n }\n const role = convertAuthorToRole(author);\n\n const prevContent = acc.content?.[acc.content.length];\n if (\n !acc.mergeWithPreviousContent &&\n prevContent &&\n prevContent.role === role\n ) {\n throw new Error(\n 'Google Generative AI requires alternate messages between authors'\n );\n }\n\n const parts = convertMessageContentToParts(\n message,\n isMultimodalModel,\n messages.slice(0, index),\n model\n );\n\n if (acc.mergeWithPreviousContent) {\n const prevContent = acc.content?.[acc.content.length - 1];\n if (!prevContent) {\n throw new Error(\n 'There was a problem parsing your system message. Please try a prompt without one.'\n );\n }\n prevContent.parts.push(...parts);\n\n return {\n mergeWithPreviousContent: false,\n content: acc.content,\n };\n }\n let actualRole = role;\n if (\n actualRole === 'function' ||\n (actualRole === 'system' && !convertSystemMessageToHumanContent)\n ) {\n // GenerativeAI API will throw an error if the role is not \"user\" or \"model.\"\n actualRole = 'user';\n }\n const content: Content = {\n role: actualRole,\n parts,\n };\n return {\n mergeWithPreviousContent:\n author === 'system' && !convertSystemMessageToHumanContent,\n content: [...(acc.content ?? []), content],\n };\n },\n { content: [], mergeWithPreviousContent: false }\n ).content;\n}\n\n/**\n * Gemini models that reject a request whose `contents` end with a `model`-role\n * turn (a \"prefill\"). Google enforces this on newer generations (Gemini 3.7\n * Flash, Gemini 3.6 Flash, Gemini 3.5 Flash-Lite) while older/sibling models\n * still accept a trailing model turn, so the rule is model-scoped rather than\n * version-wide. Extend this list as Google applies the restriction to further\n * models.\n * @see https://ai.google.dev/gemini-api/docs/latest-model#api-changes-and-parameter-updates\n */\nconst NO_PREFILL_GEMINI_MODELS = [\n 'gemini-3.7-flash',\n 'gemini-3.6-flash',\n 'gemini-3.5-flash-lite',\n] as const;\n\nexport function rejectsModelTurnPrefill(model?: string): boolean {\n if (model == null || model === '') {\n return false;\n }\n const modelId = model.toLowerCase().split('/').pop() ?? '';\n return NO_PREFILL_GEMINI_MODELS.some(\n (id) => modelId === id || modelId.startsWith(`${id}-`)\n );\n}\n\n/**\n * Drops trailing `model`-role turns for models that reject prefill (see\n * {@link rejectsModelTurnPrefill}). Such a turn is only produced by prefill\n * flows (e.g. editing an assistant reply and resubmitting); these models return\n * HTTP 400 for it, so we drop it and let the model generate fresh from the\n * preceding user turn. No-op for every other model, preserving working prefill.\n */\nexport function dropUnsupportedModelTurnPrefill(\n contents: Content[] | undefined,\n model?: string\n): Content[] | undefined {\n if (\n contents == null ||\n contents.length === 0 ||\n !rejectsModelTurnPrefill(model)\n ) {\n return contents;\n }\n let end = contents.length;\n while (end > 1 && contents[end - 1]?.role === 'model') {\n end -= 1;\n }\n return end === contents.length ? contents : contents.slice(0, end);\n}\n\nexport function convertResponseContentToChatGenerationChunk(\n response: EnhancedGenerateContentResponse,\n extra: {\n usageMetadata?: UsageMetadata | undefined;\n index: number;\n }\n): ChatGenerationChunk | null {\n if (!response.candidates || response.candidates.length === 0) {\n return null;\n }\n const [candidate] = response.candidates as [\n Partial<GenerateContentCandidate> | undefined,\n ];\n const { content: candidateContent, ...generationInfo } = candidate ?? {};\n\n // Extract function calls directly from parts to preserve thoughtSignature\n const functionCalls =\n (candidateContent?.parts as Part[] | undefined)?.reduce(\n (acc, p) => {\n if ('functionCall' in p && p.functionCall) {\n acc.push({\n ...p,\n id:\n 'id' in p.functionCall && typeof p.functionCall.id === 'string'\n ? p.functionCall.id\n : uuidv4(),\n });\n }\n return acc;\n },\n [] as (\n | undefined\n | (FunctionCallPart & { id: string; thoughtSignature?: string })\n )[]\n ) ?? [];\n\n let content: MessageContent | undefined;\n // Checks if some parts do not have text. If false, it means that the content is a string.\n const reasoningParts: string[] = [];\n if (\n candidateContent != null &&\n Array.isArray(candidateContent.parts) &&\n candidateContent.parts.every((p) => 'text' in p)\n ) {\n // content = candidateContent.parts.map((p) => p.text).join('');\n const textParts: string[] = [];\n for (const part of candidateContent.parts) {\n if ('thought' in part && part.thought === true) {\n reasoningParts.push(part.text ?? '');\n continue;\n }\n textParts.push(part.text ?? '');\n }\n content = textParts.join('');\n } else if (candidateContent && Array.isArray(candidateContent.parts)) {\n content = toLangChainContent(\n candidateContent.parts\n .map((p) => {\n if ('text' in p && 'thought' in p && p.thought === true) {\n reasoningParts.push(p.text ?? '');\n return undefined;\n } else if ('text' in p) {\n return {\n type: 'text',\n text: p.text,\n };\n } else if ('executableCode' in p) {\n return {\n type: 'executableCode',\n executableCode: p.executableCode,\n };\n } else if ('codeExecutionResult' in p) {\n return {\n type: 'codeExecutionResult',\n codeExecutionResult: p.codeExecutionResult,\n };\n }\n const serverSideToolPart = convertGoogleServerSideToolResponsePart(p);\n if (serverSideToolPart !== undefined) {\n return serverSideToolPart;\n }\n return p;\n })\n .filter((p) => p !== undefined)\n );\n } else {\n // no content returned - likely due to abnormal stop reason, e.g. malformed function call\n content = [];\n }\n\n let text = '';\n if (typeof content === 'string' && content) {\n text = content;\n } else if (Array.isArray(content)) {\n const block = content.find((b) => 'text' in b) as\n | { text: string }\n | undefined;\n text = block?.text ?? '';\n }\n\n const toolCallChunks: ToolCallChunk[] = [];\n if (functionCalls.length > 0) {\n toolCallChunks.push(\n ...functionCalls.map((fc) => ({\n type: 'tool_call_chunk' as const,\n id: fc?.id,\n name: fc?.functionCall.name,\n args: JSON.stringify(fc?.functionCall.args),\n }))\n );\n }\n\n // Extract thought signatures from function calls for Gemini 3+\n const functionThoughtSignatures = functionCalls.reduce(\n (acc, fc) => {\n if (\n fc &&\n 'thoughtSignature' in fc &&\n typeof fc.thoughtSignature === 'string'\n ) {\n acc[fc.id] = fc.thoughtSignature;\n }\n return acc;\n },\n {} as Record<string, string>\n );\n\n const additional_kwargs: ChatGeneration['message']['additional_kwargs'] = {\n [_FUNCTION_CALL_THOUGHT_SIGNATURES_MAP_KEY]: functionThoughtSignatures,\n };\n\n if (reasoningParts.length > 0) {\n additional_kwargs.reasoning = reasoningParts.join('');\n }\n\n if (candidate?.groundingMetadata) {\n additional_kwargs.groundingMetadata = candidate.groundingMetadata;\n }\n\n const isFinalChunk =\n response.candidates[0]?.finishReason === 'STOP' ||\n response.candidates[0]?.finishReason === 'MAX_TOKENS' ||\n response.candidates[0]?.finishReason === 'SAFETY';\n\n // The GenAI API delivers function calls as complete objects (never partial\n // arg deltas), so every call on this chunk is sealed on arrival for eager\n // tool execution.\n const response_metadata: Record<string, unknown> | undefined =\n toolCallChunks.length > 0\n ? {\n [STREAMED_TOOL_CALL_ADAPTER_METADATA_KEY]:\n GOOGLE_STREAMED_TOOL_CALL_ADAPTER,\n [STREAMED_TOOL_CALL_SEAL_METADATA_KEY]: { kind: 'all' },\n }\n : undefined;\n\n return new ChatGenerationChunk({\n text,\n message: new AIMessageChunk({\n content: content,\n name: !candidateContent ? undefined : candidateContent.role,\n tool_call_chunks: toolCallChunks,\n // Each chunk can have unique \"generationInfo\", and merging strategy is unclear,\n // so leave blank for now.\n additional_kwargs,\n response_metadata,\n usage_metadata: isFinalChunk ? extra.usageMetadata : undefined,\n }),\n generationInfo,\n });\n}\n\n/**\n * Maps a Google GenerateContentResult to a LangChain ChatResult\n */\nexport function mapGenerateContentResultToChatResult(\n response: EnhancedGenerateContentResponse,\n extra?: {\n usageMetadata: UsageMetadata | undefined;\n }\n): ChatResult {\n if (!response.candidates || response.candidates.length === 0) {\n return {\n generations: [],\n llmOutput: {\n filters: response.promptFeedback,\n },\n };\n }\n const [candidate] = response.candidates as [\n Partial<GenerateContentCandidate> | undefined,\n ];\n const { content: candidateContent, ...generationInfo } = candidate ?? {};\n\n // Extract function calls directly from parts to preserve thoughtSignature\n const functionCalls =\n candidateContent?.parts.reduce(\n (acc, p) => {\n if ('functionCall' in p && p.functionCall) {\n acc.push({\n ...p,\n id:\n 'id' in p.functionCall && typeof p.functionCall.id === 'string'\n ? p.functionCall.id\n : uuidv4(),\n });\n }\n return acc;\n },\n [] as (FunctionCallPart & { id: string; thoughtSignature?: string })[]\n ) ?? [];\n\n let content: MessageContent | undefined;\n const reasoningParts: string[] = [];\n if (\n Array.isArray(candidateContent?.parts) &&\n candidateContent.parts.length === 1 &&\n (candidateContent.parts[0].text ?? '') !== '' &&\n !(\n 'thought' in candidateContent.parts[0] &&\n candidateContent.parts[0].thought === true\n )\n ) {\n content = candidateContent.parts[0].text;\n } else if (\n Array.isArray(candidateContent?.parts) &&\n candidateContent.parts.length > 0\n ) {\n content = toLangChainContent(\n candidateContent.parts\n .map((p) => {\n if ('text' in p && 'thought' in p && p.thought === true) {\n reasoningParts.push(p.text ?? '');\n return undefined;\n } else if ('text' in p) {\n return {\n type: 'text',\n text: p.text,\n };\n } else if ('executableCode' in p) {\n return {\n type: 'executableCode',\n executableCode: p.executableCode,\n };\n } else if ('codeExecutionResult' in p) {\n return {\n type: 'codeExecutionResult',\n codeExecutionResult: p.codeExecutionResult,\n };\n }\n const serverSideToolPart = convertGoogleServerSideToolResponsePart(p);\n if (serverSideToolPart !== undefined) {\n return serverSideToolPart;\n }\n return p;\n })\n .filter((p) => p !== undefined)\n );\n } else {\n content = [];\n }\n let text = '';\n if (typeof content === 'string') {\n text = content;\n } else if (Array.isArray(content) && content.length > 0) {\n const block = content.find((b) => 'text' in b) as\n | { text: string }\n | undefined;\n text = block?.text ?? text;\n }\n\n const additional_kwargs: ChatGeneration['message']['additional_kwargs'] = {\n ...generationInfo,\n };\n if (reasoningParts.length > 0) {\n additional_kwargs.reasoning = reasoningParts.join('');\n }\n\n // Extract thought signatures from function calls for Gemini 3+\n const functionThoughtSignatures = functionCalls.reduce(\n (acc, fc) => {\n if ('thoughtSignature' in fc && typeof fc.thoughtSignature === 'string') {\n acc[fc.id] = fc.thoughtSignature;\n }\n return acc;\n },\n {} as Record<string, string>\n );\n\n const tool_calls = functionCalls.map((fc) => ({\n type: 'tool_call' as const,\n id: fc.id,\n name: fc.functionCall.name,\n args: fc.functionCall.args,\n }));\n\n // Store thought signatures map for later retrieval\n additional_kwargs[_FUNCTION_CALL_THOUGHT_SIGNATURES_MAP_KEY] =\n functionThoughtSignatures;\n\n const generation: ChatGeneration = {\n text,\n message: new AIMessage({\n content,\n tool_calls,\n additional_kwargs,\n usage_metadata: extra?.usageMetadata,\n }),\n generationInfo,\n };\n return {\n generations: [generation],\n llmOutput: {\n tokenUsage: {\n promptTokens: extra?.usageMetadata?.input_tokens,\n completionTokens: extra?.usageMetadata?.output_tokens,\n totalTokens: extra?.usageMetadata?.total_tokens,\n },\n },\n };\n}\n\nexport function convertToGenerativeAITools(\n tools: GoogleGenerativeAIToolType[]\n): GoogleGenerativeAIFunctionDeclarationsTool[] {\n if (\n tools.every(\n (tool) =>\n 'functionDeclarations' in tool &&\n Array.isArray(tool.functionDeclarations)\n )\n ) {\n return tools as GoogleGenerativeAIFunctionDeclarationsTool[];\n }\n return [\n {\n functionDeclarations: tools.map(\n (tool): GenerativeAIFunctionDeclaration => {\n if (isLangChainTool(tool)) {\n const jsonSchema = schemaToGenerativeAIParameters(tool.schema);\n if (\n jsonSchema.type === 'object' &&\n 'properties' in jsonSchema &&\n Object.keys(jsonSchema.properties).length === 0\n ) {\n return {\n name: tool.name,\n description: tool.description,\n };\n }\n return {\n name: tool.name,\n description: tool.description,\n parameters: jsonSchema,\n };\n }\n if (isOpenAITool(tool)) {\n return {\n name: tool.function.name,\n description:\n tool.function.description ?? 'A function available to call.',\n parameters: jsonSchemaToGeminiParameters(\n tool.function.parameters\n ),\n };\n }\n return tool as unknown as GenerativeAIFunctionDeclaration;\n }\n ),\n },\n ];\n}\n"],"mappings":"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"}
|