@librechat/agents 2.1.1 → 2.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/dist/cjs/common/enum.cjs +1 -0
  2. package/dist/cjs/common/enum.cjs.map +1 -1
  3. package/dist/cjs/graphs/Graph.cjs +11 -1
  4. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  5. package/dist/cjs/llm/anthropic/utils/message_inputs.cjs +25 -1
  6. package/dist/cjs/llm/anthropic/utils/message_inputs.cjs.map +1 -1
  7. package/dist/cjs/llm/anthropic/utils/message_outputs.cjs +52 -28
  8. package/dist/cjs/llm/anthropic/utils/message_outputs.cjs.map +1 -1
  9. package/dist/cjs/llm/openrouter/llm.cjs +25 -0
  10. package/dist/cjs/llm/openrouter/llm.cjs.map +1 -0
  11. package/dist/cjs/llm/providers.cjs +4 -2
  12. package/dist/cjs/llm/providers.cjs.map +1 -1
  13. package/dist/cjs/splitStream.cjs +8 -2
  14. package/dist/cjs/splitStream.cjs.map +1 -1
  15. package/dist/esm/common/enum.mjs +1 -0
  16. package/dist/esm/common/enum.mjs.map +1 -1
  17. package/dist/esm/graphs/Graph.mjs +11 -1
  18. package/dist/esm/graphs/Graph.mjs.map +1 -1
  19. package/dist/esm/llm/anthropic/utils/message_inputs.mjs +25 -1
  20. package/dist/esm/llm/anthropic/utils/message_inputs.mjs.map +1 -1
  21. package/dist/esm/llm/anthropic/utils/message_outputs.mjs +52 -28
  22. package/dist/esm/llm/anthropic/utils/message_outputs.mjs.map +1 -1
  23. package/dist/esm/llm/openrouter/llm.mjs +23 -0
  24. package/dist/esm/llm/openrouter/llm.mjs.map +1 -0
  25. package/dist/esm/llm/providers.mjs +2 -0
  26. package/dist/esm/llm/providers.mjs.map +1 -1
  27. package/dist/esm/splitStream.mjs +8 -2
  28. package/dist/esm/splitStream.mjs.map +1 -1
  29. package/dist/types/common/enum.d.ts +2 -1
  30. package/dist/types/llm/anthropic/types.d.ts +3 -0
  31. package/dist/types/llm/openrouter/llm.d.ts +10 -0
  32. package/dist/types/scripts/caching.d.ts +1 -0
  33. package/dist/types/splitStream.d.ts +2 -0
  34. package/dist/types/types/llm.d.ts +4 -0
  35. package/package.json +9 -8
  36. package/src/common/enum.ts +1 -0
  37. package/src/graphs/Graph.ts +14 -3
  38. package/src/llm/anthropic/types.ts +4 -0
  39. package/src/llm/anthropic/utils/message_inputs.ts +31 -1
  40. package/src/llm/anthropic/utils/message_outputs.ts +59 -34
  41. package/src/llm/openrouter/llm.ts +37 -0
  42. package/src/llm/providers.ts +2 -0
  43. package/src/scripts/caching.ts +124 -0
  44. package/src/scripts/simple.ts +1 -0
  45. package/src/scripts/tools.ts +2 -2
  46. package/src/splitStream.ts +8 -3
  47. package/src/types/llm.ts +4 -0
  48. package/src/utils/llmConfig.ts +16 -0
@@ -0,0 +1,23 @@
1
+ import { ChatOpenAI } from '@langchain/openai';
2
+
3
+ class ChatOpenRouter extends ChatOpenAI {
4
+ constructor(_fields) {
5
+ const { include_reasoning, ...fields } = _fields;
6
+ super({
7
+ ...fields,
8
+ modelKwargs: {
9
+ include_reasoning,
10
+ }
11
+ });
12
+ }
13
+ _convertOpenAIDeltaToBaseMessageChunk(
14
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
15
+ delta, rawResponse, defaultRole) {
16
+ const messageChunk = super._convertOpenAIDeltaToBaseMessageChunk(delta, rawResponse, defaultRole);
17
+ messageChunk.additional_kwargs.reasoning = delta.reasoning;
18
+ return messageChunk;
19
+ }
20
+ }
21
+
22
+ export { ChatOpenRouter };
23
+ //# sourceMappingURL=llm.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm.mjs","sources":["../../../../src/llm/openrouter/llm.ts"],"sourcesContent":["import { ChatOpenAI } from '@langchain/openai';\nimport type { ChatOpenAICallOptions, OpenAIClient } from '@langchain/openai';\nimport type { AIMessageChunk, HumanMessageChunk, SystemMessageChunk, FunctionMessageChunk, ToolMessageChunk, ChatMessageChunk} from '@langchain/core/messages';\nexport interface ChatOpenRouterCallOptions extends ChatOpenAICallOptions {\n include_reasoning?: boolean;\n}\nexport class ChatOpenRouter extends ChatOpenAI<ChatOpenRouterCallOptions> {\n constructor(_fields: Partial<ChatOpenRouterCallOptions>) {\n const { include_reasoning, ...fields } = _fields;\n super({\n ...fields,\n modelKwargs: {\n include_reasoning,\n }\n });\n }\n protected override _convertOpenAIDeltaToBaseMessageChunk(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n delta: Record<string, any>,\n rawResponse: OpenAIClient.ChatCompletionChunk,\n defaultRole?:\n | 'function'\n | 'user'\n | 'system'\n | 'developer'\n | 'assistant'\n | 'tool'\n ): AIMessageChunk | HumanMessageChunk | SystemMessageChunk | FunctionMessageChunk | ToolMessageChunk | ChatMessageChunk {\n const messageChunk = super._convertOpenAIDeltaToBaseMessageChunk(\n delta,\n rawResponse,\n defaultRole\n );\n messageChunk.additional_kwargs.reasoning = delta.reasoning;\n return messageChunk;\n }\n}"],"names":[],"mappings":";;AAMM,MAAO,cAAe,SAAQ,UAAqC,CAAA;AACvE,IAAA,WAAA,CAAY,OAA2C,EAAA;QACrD,MAAM,EAAE,iBAAiB,EAAE,GAAG,MAAM,EAAE,GAAG,OAAO;AAChD,QAAA,KAAK,CAAC;AACJ,YAAA,GAAG,MAAM;AACT,YAAA,WAAW,EAAE;gBACX,iBAAiB;AAClB;AACF,SAAA,CAAC;;IAEe,qCAAqC;;IAEtD,KAA0B,EAC1B,WAA6C,EAC7C,WAMQ,EAAA;AAER,QAAA,MAAM,YAAY,GAAG,KAAK,CAAC,qCAAqC,CAC9D,KAAK,EACL,WAAW,EACX,WAAW,CACZ;QACD,YAAY,CAAC,iBAAiB,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS;AAC1D,QAAA,OAAO,YAAY;;AAEtB;;;;"}
@@ -7,6 +7,7 @@ import { AzureChatOpenAI, ChatOpenAI } from '@langchain/openai';
7
7
  import { ChatGoogleGenerativeAI } from '@langchain/google-genai';
8
8
  import { BedrockChat } from '@langchain/community/chat_models/bedrock/web';
9
9
  import { CustomAnthropic } from './anthropic/llm.mjs';
10
+ import { ChatOpenRouter } from './openrouter/llm.mjs';
10
11
  import { Providers } from '../common/enum.mjs';
11
12
 
12
13
  // src/llm/providers.ts
@@ -18,6 +19,7 @@ const llmProviders = {
18
19
  [Providers.DEEPSEEK]: ChatDeepSeek,
19
20
  [Providers.MISTRALAI]: ChatMistralAI,
20
21
  [Providers.ANTHROPIC]: CustomAnthropic,
22
+ [Providers.OPENROUTER]: ChatOpenRouter,
21
23
  [Providers.BEDROCK_LEGACY]: BedrockChat,
22
24
  [Providers.BEDROCK]: ChatBedrockConverse,
23
25
  // [Providers.ANTHROPIC]: ChatAnthropic,
@@ -1 +1 @@
1
- {"version":3,"file":"providers.mjs","sources":["../../../src/llm/providers.ts"],"sourcesContent":["// src/llm/providers.ts\nimport { ChatOllama } from '@langchain/ollama';\nimport { ChatDeepSeek } from '@langchain/deepseek';\nimport { ChatMistralAI } from '@langchain/mistralai';\nimport { ChatBedrockConverse } from '@langchain/aws';\n// import { ChatAnthropic } from '@langchain/anthropic';\nimport { ChatVertexAI } from '@langchain/google-vertexai';\nimport { ChatOpenAI, AzureChatOpenAI } from '@langchain/openai';\nimport { ChatGoogleGenerativeAI } from '@langchain/google-genai';\nimport { BedrockChat } from '@langchain/community/chat_models/bedrock/web';\nimport type { ChatModelConstructorMap, ProviderOptionsMap, ChatModelMap } from '@/types';\nimport { CustomAnthropic } from '@/llm/anthropic/llm';\nimport { Providers } from '@/common';\n\nexport const llmProviders: Partial<ChatModelConstructorMap> = {\n [Providers.OPENAI]: ChatOpenAI,\n [Providers.OLLAMA]: ChatOllama,\n [Providers.AZURE]: AzureChatOpenAI,\n [Providers.VERTEXAI]: ChatVertexAI,\n [Providers.DEEPSEEK]: ChatDeepSeek,\n [Providers.MISTRALAI]: ChatMistralAI,\n [Providers.ANTHROPIC]: CustomAnthropic,\n [Providers.BEDROCK_LEGACY]: BedrockChat,\n [Providers.BEDROCK]: ChatBedrockConverse,\n // [Providers.ANTHROPIC]: ChatAnthropic,\n [Providers.GOOGLE]: ChatGoogleGenerativeAI,\n};\n\nexport const manualToolStreamProviders = new Set<Providers | string>([Providers.ANTHROPIC, Providers.BEDROCK, Providers.OLLAMA]);\n\nexport const getChatModelClass = <P extends Providers>(\n provider: P\n): new (config: ProviderOptionsMap[P]) => ChatModelMap[P] => {\n const ChatModelClass = llmProviders[provider];\n if (!ChatModelClass) {\n throw new Error(`Unsupported LLM provider: ${provider}`);\n }\n\n return ChatModelClass;\n};"],"names":[],"mappings":";;;;;;;;;;;AAAA;AAca,MAAA,YAAY,GAAqC;AAC5D,IAAA,CAAC,SAAS,CAAC,MAAM,GAAG,UAAU;AAC9B,IAAA,CAAC,SAAS,CAAC,MAAM,GAAG,UAAU;AAC9B,IAAA,CAAC,SAAS,CAAC,KAAK,GAAG,eAAe;AAClC,IAAA,CAAC,SAAS,CAAC,QAAQ,GAAG,YAAY;AAClC,IAAA,CAAC,SAAS,CAAC,QAAQ,GAAG,YAAY;AAClC,IAAA,CAAC,SAAS,CAAC,SAAS,GAAG,aAAa;AACpC,IAAA,CAAC,SAAS,CAAC,SAAS,GAAG,eAAe;AACtC,IAAA,CAAC,SAAS,CAAC,cAAc,GAAG,WAAW;AACvC,IAAA,CAAC,SAAS,CAAC,OAAO,GAAG,mBAAmB;;AAExC,IAAA,CAAC,SAAS,CAAC,MAAM,GAAG,sBAAsB;;MAG/B,yBAAyB,GAAG,IAAI,GAAG,CAAqB,CAAC,SAAS,CAAC,SAAS,EAAE,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,MAAM,CAAC;AAElH,MAAA,iBAAiB,GAAG,CAC/B,QAAW,KAC+C;AAC1D,IAAA,MAAM,cAAc,GAAG,YAAY,CAAC,QAAQ,CAAC;IAC7C,IAAI,CAAC,cAAc,EAAE;AACnB,QAAA,MAAM,IAAI,KAAK,CAAC,6BAA6B,QAAQ,CAAA,CAAE,CAAC;;AAG1D,IAAA,OAAO,cAAc;AACvB;;;;"}
1
+ {"version":3,"file":"providers.mjs","sources":["../../../src/llm/providers.ts"],"sourcesContent":["// src/llm/providers.ts\nimport { ChatOllama } from '@langchain/ollama';\nimport { ChatDeepSeek } from '@langchain/deepseek';\nimport { ChatMistralAI } from '@langchain/mistralai';\nimport { ChatBedrockConverse } from '@langchain/aws';\n// import { ChatAnthropic } from '@langchain/anthropic';\nimport { ChatVertexAI } from '@langchain/google-vertexai';\nimport { ChatOpenAI, AzureChatOpenAI } from '@langchain/openai';\nimport { ChatGoogleGenerativeAI } from '@langchain/google-genai';\nimport { BedrockChat } from '@langchain/community/chat_models/bedrock/web';\nimport type { ChatModelConstructorMap, ProviderOptionsMap, ChatModelMap } from '@/types';\nimport { CustomAnthropic } from '@/llm/anthropic/llm';\nimport { ChatOpenRouter } from '@/llm/openrouter/llm';\nimport { Providers } from '@/common';\n\nexport const llmProviders: Partial<ChatModelConstructorMap> = {\n [Providers.OPENAI]: ChatOpenAI,\n [Providers.OLLAMA]: ChatOllama,\n [Providers.AZURE]: AzureChatOpenAI,\n [Providers.VERTEXAI]: ChatVertexAI,\n [Providers.DEEPSEEK]: ChatDeepSeek,\n [Providers.MISTRALAI]: ChatMistralAI,\n [Providers.ANTHROPIC]: CustomAnthropic,\n [Providers.OPENROUTER]: ChatOpenRouter,\n [Providers.BEDROCK_LEGACY]: BedrockChat,\n [Providers.BEDROCK]: ChatBedrockConverse,\n // [Providers.ANTHROPIC]: ChatAnthropic,\n [Providers.GOOGLE]: ChatGoogleGenerativeAI,\n};\n\nexport const manualToolStreamProviders = new Set<Providers | string>([Providers.ANTHROPIC, Providers.BEDROCK, Providers.OLLAMA]);\n\nexport const getChatModelClass = <P extends Providers>(\n provider: P\n): new (config: ProviderOptionsMap[P]) => ChatModelMap[P] => {\n const ChatModelClass = llmProviders[provider];\n if (!ChatModelClass) {\n throw new Error(`Unsupported LLM provider: ${provider}`);\n }\n\n return ChatModelClass;\n};"],"names":[],"mappings":";;;;;;;;;;;;AAAA;AAea,MAAA,YAAY,GAAqC;AAC5D,IAAA,CAAC,SAAS,CAAC,MAAM,GAAG,UAAU;AAC9B,IAAA,CAAC,SAAS,CAAC,MAAM,GAAG,UAAU;AAC9B,IAAA,CAAC,SAAS,CAAC,KAAK,GAAG,eAAe;AAClC,IAAA,CAAC,SAAS,CAAC,QAAQ,GAAG,YAAY;AAClC,IAAA,CAAC,SAAS,CAAC,QAAQ,GAAG,YAAY;AAClC,IAAA,CAAC,SAAS,CAAC,SAAS,GAAG,aAAa;AACpC,IAAA,CAAC,SAAS,CAAC,SAAS,GAAG,eAAe;AACtC,IAAA,CAAC,SAAS,CAAC,UAAU,GAAG,cAAc;AACtC,IAAA,CAAC,SAAS,CAAC,cAAc,GAAG,WAAW;AACvC,IAAA,CAAC,SAAS,CAAC,OAAO,GAAG,mBAAmB;;AAExC,IAAA,CAAC,SAAS,CAAC,MAAM,GAAG,sBAAsB;;MAG/B,yBAAyB,GAAG,IAAI,GAAG,CAAqB,CAAC,SAAS,CAAC,SAAS,EAAE,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,MAAM,CAAC;AAElH,MAAA,iBAAiB,GAAG,CAC/B,QAAW,KAC+C;AAC1D,IAAA,MAAM,cAAc,GAAG,YAAY,CAAC,QAAQ,CAAC;IAC7C,IAAI,CAAC,cAAc,EAAE;AACnB,QAAA,MAAM,IAAI,KAAK,CAAC,6BAA6B,QAAQ,CAAA,CAAE,CAAC;;AAG1D,IAAA,OAAO,cAAc;AACvB;;;;"}
@@ -125,12 +125,18 @@ class SplitStreamHandler {
125
125
  });
126
126
  }
127
127
  };
128
+ getDeltaContent(chunk) {
129
+ return chunk.choices?.[0]?.delta.content ?? '';
130
+ }
131
+ getReasoningDelta(chunk) {
132
+ return chunk.choices?.[0]?.delta[this.reasoningKey] ?? '';
133
+ }
128
134
  handle(chunk) {
129
135
  if (!chunk) {
130
136
  return;
131
137
  }
132
- const content = chunk.choices?.[0]?.delta.content ?? '';
133
- const reasoning_content = chunk.choices?.[0]?.delta[this.reasoningKey] ?? '';
138
+ const content = this.getDeltaContent(chunk);
139
+ const reasoning_content = this.getReasoningDelta(chunk);
134
140
  if (!content.length && !reasoning_content.length) {
135
141
  return;
136
142
  }
@@ -1 +1 @@
1
- {"version":3,"file":"splitStream.mjs","sources":["../../src/splitStream.ts"],"sourcesContent":["import { nanoid } from 'nanoid';\nimport type * as t from '@/types';\nimport { ContentTypes, GraphEvents, StepTypes } from '@/common';\n\nexport const SEPARATORS = ['.', '?', '!', '۔', '。', '‥', ';', '¡', '¿', '\\n', '```'];\n\nexport class SplitStreamHandler {\n private inCodeBlock = false;\n private inThinkBlock = false;\n private accumulate: boolean;\n tokens: string[] = [];\n lastToken = '';\n reasoningTokens: string[] = [];\n currentStepId?: string;\n currentMessageId?: string;\n currentType?: ContentTypes.TEXT | ContentTypes.THINK;\n currentLength = 0;\n reasoningKey: 'reasoning_content' | 'reasoning' = 'reasoning_content';\n currentIndex = -1;\n blockThreshold = 4500;\n /** The run ID AKA the Message ID associated with the complete generation */\n runId: string;\n handlers?: t.SplitStreamHandlers;\n constructor({\n runId,\n handlers,\n accumulate,\n reasoningKey,\n blockThreshold,\n }: {\n runId: string,\n accumulate?: boolean,\n handlers: t.SplitStreamHandlers\n blockThreshold?: number,\n reasoningKey?: 'reasoning_content' | 'reasoning',\n }) {\n this.runId = runId;\n this.handlers = handlers;\n if (reasoningKey) {\n this.reasoningKey = reasoningKey;\n }\n if (blockThreshold != null) {\n this.blockThreshold = blockThreshold;\n }\n this.accumulate = accumulate ?? false;\n }\n getMessageId = (): string | undefined => {\n const messageId = this.currentMessageId;\n if (messageId != null && messageId) {\n return messageId;\n }\n return undefined;\n };\n createMessageStep = (type?: ContentTypes.TEXT | ContentTypes.THINK): [string, string] => {\n if (type != null && this.currentType !== type) {\n this.currentType = type;\n }\n this.currentLength = 0;\n this.currentIndex += 1;\n this.currentStepId = `step_${nanoid()}`;\n this.currentMessageId = `msg_${nanoid()}`;\n return [this.currentStepId, this.currentMessageId];\n };\n dispatchRunStep = (stepId: string, stepDetails: t.StepDetails): void => {\n const runStep: t.RunStep = {\n id: stepId,\n runId: this.runId,\n type: stepDetails.type,\n index: this.currentIndex,\n stepDetails,\n // usage: null,\n };\n this.handlers?.[GraphEvents.ON_RUN_STEP]?.({ event: GraphEvents.ON_RUN_STEP, data: runStep });\n };\n dispatchMessageDelta = (stepId: string, delta: t.MessageDelta): void => {\n const messageDelta: t.MessageDeltaEvent = {\n id: stepId,\n delta,\n };\n this.handlers?.[GraphEvents.ON_MESSAGE_DELTA]?.({ event: GraphEvents.ON_MESSAGE_DELTA, data: messageDelta });\n };\n dispatchReasoningDelta = (stepId: string, delta: t.ReasoningDelta): void => {\n const reasoningDelta: t.ReasoningDeltaEvent = {\n id: stepId,\n delta,\n };\n this.handlers?.[GraphEvents.ON_REASONING_DELTA]?.({ event: GraphEvents.ON_REASONING_DELTA, data: reasoningDelta });\n };\n handleContent = (content: string, _type: ContentTypes.TEXT | ContentTypes.THINK): void => {\n let type = _type;\n if (this.inThinkBlock && type === ContentTypes.TEXT) {\n type = ContentTypes.THINK;\n }\n if (this.accumulate) {\n if (type === ContentTypes.THINK) {\n this.reasoningTokens.push(content);\n } else {\n this.tokens.push(content);\n }\n }\n\n if (this.currentType !== type) {\n const [newStepId, newMessageId] = this.createMessageStep(type);\n this.dispatchRunStep(newStepId, {\n type: StepTypes.MESSAGE_CREATION,\n message_creation: {\n message_id: newMessageId,\n },\n });\n }\n\n const stepId = this.currentStepId ?? '';\n if (type === ContentTypes.THINK) {\n this.dispatchReasoningDelta(stepId, {\n content: [{\n type: ContentTypes.THINK,\n think: content,\n }],\n });\n } else {\n this.dispatchMessageDelta(stepId, {\n content: [{\n type: ContentTypes.TEXT,\n text: content,\n }],\n });\n }\n\n this.currentLength += content.length;\n if (this.inCodeBlock) {\n return;\n }\n\n if (this.currentLength > this.blockThreshold && SEPARATORS.some(sep => content.includes(sep))) {\n const [newStepId, newMessageId] = this.createMessageStep(type);\n this.dispatchRunStep(newStepId, {\n type: StepTypes.MESSAGE_CREATION,\n message_creation: {\n message_id: newMessageId,\n },\n });\n }\n };\n handle(chunk?: t.CustomChunk): void {\n if (!chunk) {\n return;\n }\n\n const content = chunk.choices?.[0]?.delta.content ?? '';\n const reasoning_content = chunk.choices?.[0]?.delta[this.reasoningKey] ?? '';\n\n if (!content.length && !reasoning_content.length) {\n return;\n }\n\n if (content.includes('```')) {\n this.inCodeBlock = !this.inCodeBlock;\n }\n\n if (content.includes('<think>') && !this.inCodeBlock) {\n this.inThinkBlock = true;\n } else if (this.lastToken.includes('</think>') && !this.inCodeBlock) {\n this.inThinkBlock = false;\n }\n\n this.lastToken = content;\n\n const message_id = this.getMessageId() ?? '';\n\n if (!message_id) {\n const initialContentType = this.inThinkBlock ? ContentTypes.THINK : ContentTypes.TEXT;\n const initialType = reasoning_content ? ContentTypes.THINK : initialContentType;\n const [stepId, message_id] = this.createMessageStep(initialType);\n this.dispatchRunStep(stepId, {\n type: StepTypes.MESSAGE_CREATION,\n message_creation: {\n message_id,\n },\n });\n }\n\n if (reasoning_content) {\n this.handleContent(reasoning_content, ContentTypes.THINK);\n } else {\n this.handleContent(content, ContentTypes.TEXT);\n }\n }\n}"],"names":[],"mappings":";;;AAIa,MAAA,UAAU,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK;MAEtE,kBAAkB,CAAA;IACrB,WAAW,GAAG,KAAK;IACnB,YAAY,GAAG,KAAK;AACpB,IAAA,UAAU;IAClB,MAAM,GAAa,EAAE;IACrB,SAAS,GAAG,EAAE;IACd,eAAe,GAAa,EAAE;AAC9B,IAAA,aAAa;AACb,IAAA,gBAAgB;AAChB,IAAA,WAAW;IACX,aAAa,GAAG,CAAC;IACjB,YAAY,GAAsC,mBAAmB;IACrE,YAAY,GAAG,EAAE;IACjB,cAAc,GAAG,IAAI;;AAErB,IAAA,KAAK;AACL,IAAA,QAAQ;IACR,WAAY,CAAA,EACV,KAAK,EACL,QAAQ,EACR,UAAU,EACV,YAAY,EACZ,cAAc,GAOb,EAAA;AACD,QAAA,IAAI,CAAC,KAAK,GAAG,KAAK;AAClB,QAAA,IAAI,CAAC,QAAQ,GAAG,QAAQ;QACxB,IAAI,YAAY,EAAE;AAChB,YAAA,IAAI,CAAC,YAAY,GAAG,YAAY;;AAElC,QAAA,IAAI,cAAc,IAAI,IAAI,EAAE;AAC1B,YAAA,IAAI,CAAC,cAAc,GAAG,cAAc;;AAEtC,QAAA,IAAI,CAAC,UAAU,GAAG,UAAU,IAAI,KAAK;;IAEvC,YAAY,GAAG,MAAyB;AACtC,QAAA,MAAM,SAAS,GAAG,IAAI,CAAC,gBAAgB;AACvC,QAAA,IAAI,SAAS,IAAI,IAAI,IAAI,SAAS,EAAE;AAClC,YAAA,OAAO,SAAS;;AAElB,QAAA,OAAO,SAAS;AAClB,KAAC;AACD,IAAA,iBAAiB,GAAG,CAAC,IAA6C,KAAsB;QACtF,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC,WAAW,KAAK,IAAI,EAAE;AAC7C,YAAA,IAAI,CAAC,WAAW,GAAG,IAAI;;AAEzB,QAAA,IAAI,CAAC,aAAa,GAAG,CAAC;AACtB,QAAA,IAAI,CAAC,YAAY,IAAI,CAAC;AACtB,QAAA,IAAI,CAAC,aAAa,GAAG,QAAQ,MAAM,EAAE,EAAE;AACvC,QAAA,IAAI,CAAC,gBAAgB,GAAG,OAAO,MAAM,EAAE,EAAE;QACzC,OAAO,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,gBAAgB,CAAC;AACpD,KAAC;AACD,IAAA,eAAe,GAAG,CAAC,MAAc,EAAE,WAA0B,KAAU;AACrE,QAAA,MAAM,OAAO,GAAc;AACzB,YAAA,EAAE,EAAE,MAAM;YACV,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,IAAI,EAAE,WAAW,CAAC,IAAI;YACtB,KAAK,EAAE,IAAI,CAAC,YAAY;YACxB,WAAW;;SAEZ;QACD,IAAI,CAAC,QAAQ,GAAG,WAAW,CAAC,WAAW,CAAC,GAAG,EAAE,KAAK,EAAE,WAAW,CAAC,WAAW,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAC/F,KAAC;AACD,IAAA,oBAAoB,GAAG,CAAC,MAAc,EAAE,KAAqB,KAAU;AACrE,QAAA,MAAM,YAAY,GAAwB;AACxC,YAAA,EAAE,EAAE,MAAM;YACV,KAAK;SACN;QACD,IAAI,CAAC,QAAQ,GAAG,WAAW,CAAC,gBAAgB,CAAC,GAAG,EAAE,KAAK,EAAE,WAAW,CAAC,gBAAgB,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;AAC9G,KAAC;AACD,IAAA,sBAAsB,GAAG,CAAC,MAAc,EAAE,KAAuB,KAAU;AACzE,QAAA,MAAM,cAAc,GAA0B;AAC5C,YAAA,EAAE,EAAE,MAAM;YACV,KAAK;SACN;QACD,IAAI,CAAC,QAAQ,GAAG,WAAW,CAAC,kBAAkB,CAAC,GAAG,EAAE,KAAK,EAAE,WAAW,CAAC,kBAAkB,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC;AACpH,KAAC;AACD,IAAA,aAAa,GAAG,CAAC,OAAe,EAAE,KAA6C,KAAU;QACvF,IAAI,IAAI,GAAG,KAAK;QAChB,IAAI,IAAI,CAAC,YAAY,IAAI,IAAI,KAAK,YAAY,CAAC,IAAI,EAAE;AACnD,YAAA,IAAI,GAAG,YAAY,CAAC,KAAK;;AAE3B,QAAA,IAAI,IAAI,CAAC,UAAU,EAAE;AACnB,YAAA,IAAI,IAAI,KAAK,YAAY,CAAC,KAAK,EAAE;AAC/B,gBAAA,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC;;iBAC7B;AACL,gBAAA,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC;;;AAI7B,QAAA,IAAI,IAAI,CAAC,WAAW,KAAK,IAAI,EAAE;AAC7B,YAAA,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC;AAC9D,YAAA,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE;gBAC9B,IAAI,EAAE,SAAS,CAAC,gBAAgB;AAChC,gBAAA,gBAAgB,EAAE;AAChB,oBAAA,UAAU,EAAE,YAAY;AACzB,iBAAA;AACF,aAAA,CAAC;;AAGJ,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,IAAI,EAAE;AACvC,QAAA,IAAI,IAAI,KAAK,YAAY,CAAC,KAAK,EAAE;AAC/B,YAAA,IAAI,CAAC,sBAAsB,CAAC,MAAM,EAAE;AAClC,gBAAA,OAAO,EAAE,CAAC;wBACR,IAAI,EAAE,YAAY,CAAC,KAAK;AACxB,wBAAA,KAAK,EAAE,OAAO;qBACf,CAAC;AACH,aAAA,CAAC;;aACG;AACL,YAAA,IAAI,CAAC,oBAAoB,CAAC,MAAM,EAAE;AAChC,gBAAA,OAAO,EAAE,CAAC;wBACR,IAAI,EAAE,YAAY,CAAC,IAAI;AACvB,wBAAA,IAAI,EAAE,OAAO;qBACd,CAAC;AACH,aAAA,CAAC;;AAGJ,QAAA,IAAI,CAAC,aAAa,IAAI,OAAO,CAAC,MAAM;AACpC,QAAA,IAAI,IAAI,CAAC,WAAW,EAAE;YACpB;;QAGF,IAAI,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,cAAc,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE;AAC7F,YAAA,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC;AAC9D,YAAA,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE;gBAC9B,IAAI,EAAE,SAAS,CAAC,gBAAgB;AAChC,gBAAA,gBAAgB,EAAE;AAChB,oBAAA,UAAU,EAAE,YAAY;AACzB,iBAAA;AACF,aAAA,CAAC;;AAEN,KAAC;AACD,IAAA,MAAM,CAAC,KAAqB,EAAA;QAC1B,IAAI,CAAC,KAAK,EAAE;YACV;;AAGF,QAAA,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,OAAO,IAAI,EAAE;AACvD,QAAA,MAAM,iBAAiB,GAAG,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE;QAE5E,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE;YAChD;;AAGF,QAAA,IAAI,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE;AAC3B,YAAA,IAAI,CAAC,WAAW,GAAG,CAAC,IAAI,CAAC,WAAW;;AAGtC,QAAA,IAAI,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE;AACpD,YAAA,IAAI,CAAC,YAAY,GAAG,IAAI;;AACnB,aAAA,IAAI,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE;AACnE,YAAA,IAAI,CAAC,YAAY,GAAG,KAAK;;AAG3B,QAAA,IAAI,CAAC,SAAS,GAAG,OAAO;QAExB,MAAM,UAAU,GAAG,IAAI,CAAC,YAAY,EAAE,IAAI,EAAE;QAE5C,IAAI,CAAC,UAAU,EAAE;AACf,YAAA,MAAM,kBAAkB,GAAG,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC,KAAK,GAAG,YAAY,CAAC,IAAI;AACrF,YAAA,MAAM,WAAW,GAAG,iBAAiB,GAAG,YAAY,CAAC,KAAK,GAAG,kBAAkB;AAC/E,YAAA,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG,IAAI,CAAC,iBAAiB,CAAC,WAAW,CAAC;AAChE,YAAA,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE;gBAC3B,IAAI,EAAE,SAAS,CAAC,gBAAgB;AAChC,gBAAA,gBAAgB,EAAE;oBAChB,UAAU;AACX,iBAAA;AACF,aAAA,CAAC;;QAGJ,IAAI,iBAAiB,EAAE;YACrB,IAAI,CAAC,aAAa,CAAC,iBAAiB,EAAE,YAAY,CAAC,KAAK,CAAC;;aACpD;YACL,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,YAAY,CAAC,IAAI,CAAC;;;AAGnD;;;;"}
1
+ {"version":3,"file":"splitStream.mjs","sources":["../../src/splitStream.ts"],"sourcesContent":["import { nanoid } from 'nanoid';\nimport type * as t from '@/types';\nimport { ContentTypes, GraphEvents, StepTypes } from '@/common';\n\nexport const SEPARATORS = ['.', '?', '!', '۔', '。', '‥', ';', '¡', '¿', '\\n', '```'];\n\nexport class SplitStreamHandler {\n private inCodeBlock = false;\n private inThinkBlock = false;\n private accumulate: boolean;\n tokens: string[] = [];\n lastToken = '';\n reasoningTokens: string[] = [];\n currentStepId?: string;\n currentMessageId?: string;\n currentType?: ContentTypes.TEXT | ContentTypes.THINK;\n currentLength = 0;\n reasoningKey: 'reasoning_content' | 'reasoning' = 'reasoning_content';\n currentIndex = -1;\n blockThreshold = 4500;\n /** The run ID AKA the Message ID associated with the complete generation */\n runId: string;\n handlers?: t.SplitStreamHandlers;\n constructor({\n runId,\n handlers,\n accumulate,\n reasoningKey,\n blockThreshold,\n }: {\n runId: string,\n accumulate?: boolean,\n handlers: t.SplitStreamHandlers\n blockThreshold?: number,\n reasoningKey?: 'reasoning_content' | 'reasoning',\n }) {\n this.runId = runId;\n this.handlers = handlers;\n if (reasoningKey) {\n this.reasoningKey = reasoningKey;\n }\n if (blockThreshold != null) {\n this.blockThreshold = blockThreshold;\n }\n this.accumulate = accumulate ?? false;\n }\n getMessageId = (): string | undefined => {\n const messageId = this.currentMessageId;\n if (messageId != null && messageId) {\n return messageId;\n }\n return undefined;\n };\n createMessageStep = (type?: ContentTypes.TEXT | ContentTypes.THINK): [string, string] => {\n if (type != null && this.currentType !== type) {\n this.currentType = type;\n }\n this.currentLength = 0;\n this.currentIndex += 1;\n this.currentStepId = `step_${nanoid()}`;\n this.currentMessageId = `msg_${nanoid()}`;\n return [this.currentStepId, this.currentMessageId];\n };\n dispatchRunStep = (stepId: string, stepDetails: t.StepDetails): void => {\n const runStep: t.RunStep = {\n id: stepId,\n runId: this.runId,\n type: stepDetails.type,\n index: this.currentIndex,\n stepDetails,\n // usage: null,\n };\n this.handlers?.[GraphEvents.ON_RUN_STEP]?.({ event: GraphEvents.ON_RUN_STEP, data: runStep });\n };\n dispatchMessageDelta = (stepId: string, delta: t.MessageDelta): void => {\n const messageDelta: t.MessageDeltaEvent = {\n id: stepId,\n delta,\n };\n this.handlers?.[GraphEvents.ON_MESSAGE_DELTA]?.({ event: GraphEvents.ON_MESSAGE_DELTA, data: messageDelta });\n };\n dispatchReasoningDelta = (stepId: string, delta: t.ReasoningDelta): void => {\n const reasoningDelta: t.ReasoningDeltaEvent = {\n id: stepId,\n delta,\n };\n this.handlers?.[GraphEvents.ON_REASONING_DELTA]?.({ event: GraphEvents.ON_REASONING_DELTA, data: reasoningDelta });\n };\n handleContent = (content: string, _type: ContentTypes.TEXT | ContentTypes.THINK): void => {\n let type = _type;\n if (this.inThinkBlock && type === ContentTypes.TEXT) {\n type = ContentTypes.THINK;\n }\n if (this.accumulate) {\n if (type === ContentTypes.THINK) {\n this.reasoningTokens.push(content);\n } else {\n this.tokens.push(content);\n }\n }\n\n if (this.currentType !== type) {\n const [newStepId, newMessageId] = this.createMessageStep(type);\n this.dispatchRunStep(newStepId, {\n type: StepTypes.MESSAGE_CREATION,\n message_creation: {\n message_id: newMessageId,\n },\n });\n }\n\n const stepId = this.currentStepId ?? '';\n if (type === ContentTypes.THINK) {\n this.dispatchReasoningDelta(stepId, {\n content: [{\n type: ContentTypes.THINK,\n think: content,\n }],\n });\n } else {\n this.dispatchMessageDelta(stepId, {\n content: [{\n type: ContentTypes.TEXT,\n text: content,\n }],\n });\n }\n\n this.currentLength += content.length;\n if (this.inCodeBlock) {\n return;\n }\n\n if (this.currentLength > this.blockThreshold && SEPARATORS.some(sep => content.includes(sep))) {\n const [newStepId, newMessageId] = this.createMessageStep(type);\n this.dispatchRunStep(newStepId, {\n type: StepTypes.MESSAGE_CREATION,\n message_creation: {\n message_id: newMessageId,\n },\n });\n }\n };\n getDeltaContent(chunk: t.CustomChunk): string {\n return chunk.choices?.[0]?.delta.content ?? '';\n }\n getReasoningDelta(chunk: t.CustomChunk): string {\n return chunk.choices?.[0]?.delta[this.reasoningKey] ?? '';\n }\n handle(chunk?: t.CustomChunk): void {\n if (!chunk) {\n return;\n }\n\n const content = this.getDeltaContent(chunk);\n const reasoning_content = this.getReasoningDelta(chunk);\n if (!content.length && !reasoning_content.length) {\n return;\n }\n\n if (content.includes('```')) {\n this.inCodeBlock = !this.inCodeBlock;\n }\n\n if (content.includes('<think>') && !this.inCodeBlock) {\n this.inThinkBlock = true;\n } else if (this.lastToken.includes('</think>') && !this.inCodeBlock) {\n this.inThinkBlock = false;\n }\n\n this.lastToken = content;\n\n const message_id = this.getMessageId() ?? '';\n\n if (!message_id) {\n const initialContentType = this.inThinkBlock ? ContentTypes.THINK : ContentTypes.TEXT;\n const initialType = reasoning_content ? ContentTypes.THINK : initialContentType;\n const [stepId, message_id] = this.createMessageStep(initialType);\n this.dispatchRunStep(stepId, {\n type: StepTypes.MESSAGE_CREATION,\n message_creation: {\n message_id,\n },\n });\n }\n\n if (reasoning_content) {\n this.handleContent(reasoning_content, ContentTypes.THINK);\n } else {\n this.handleContent(content, ContentTypes.TEXT);\n }\n }\n}"],"names":[],"mappings":"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"}
@@ -58,7 +58,8 @@ export declare enum Providers {
58
58
  OLLAMA = "ollama",
59
59
  GOOGLE = "google",
60
60
  AZURE = "azureOpenAI",
61
- DEEPSEEK = "deepseek"
61
+ DEEPSEEK = "deepseek",
62
+ OPENROUTER = "openrouter"
62
63
  }
63
64
  export declare enum GraphNodeKeys {
64
65
  TOOLS = "tools",
@@ -24,6 +24,9 @@ export type AnthropicTextBlockParam = Anthropic.Messages.TextBlockParam;
24
24
  export type AnthropicImageBlockParam = Anthropic.Messages.ImageBlockParam;
25
25
  export type AnthropicToolUseBlockParam = Anthropic.Messages.ToolUseBlockParam;
26
26
  export type AnthropicToolResultBlockParam = Anthropic.Messages.ToolResultBlockParam;
27
+ export type AnthropicDocumentBlockParam = Anthropic.Messages.DocumentBlockParam;
28
+ export type AnthropicThinkingBlockParam = Anthropic.Messages.ThinkingBlockParam;
29
+ export type AnthropicRedactedThinkingBlockParam = Anthropic.Messages.RedactedThinkingBlockParam;
27
30
  /**
28
31
  * Stream usage information for Anthropic API calls
29
32
  * @see https://docs.anthropic.com/en/docs/build-with-claude/prompt-caching#pricing
@@ -0,0 +1,10 @@
1
+ import { ChatOpenAI } from '@langchain/openai';
2
+ import type { ChatOpenAICallOptions, OpenAIClient } from '@langchain/openai';
3
+ import type { AIMessageChunk, HumanMessageChunk, SystemMessageChunk, FunctionMessageChunk, ToolMessageChunk, ChatMessageChunk } from '@langchain/core/messages';
4
+ export interface ChatOpenRouterCallOptions extends ChatOpenAICallOptions {
5
+ include_reasoning?: boolean;
6
+ }
7
+ export declare class ChatOpenRouter extends ChatOpenAI<ChatOpenRouterCallOptions> {
8
+ constructor(_fields: Partial<ChatOpenRouterCallOptions>);
9
+ protected _convertOpenAIDeltaToBaseMessageChunk(delta: Record<string, any>, rawResponse: OpenAIClient.ChatCompletionChunk, defaultRole?: 'function' | 'user' | 'system' | 'developer' | 'assistant' | 'tool'): AIMessageChunk | HumanMessageChunk | SystemMessageChunk | FunctionMessageChunk | ToolMessageChunk | ChatMessageChunk;
10
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -31,5 +31,7 @@ export declare class SplitStreamHandler {
31
31
  dispatchMessageDelta: (stepId: string, delta: t.MessageDelta) => void;
32
32
  dispatchReasoningDelta: (stepId: string, delta: t.ReasoningDelta) => void;
33
33
  handleContent: (content: string, _type: ContentTypes.TEXT | ContentTypes.THINK) => void;
34
+ getDeltaContent(chunk: t.CustomChunk): string;
35
+ getReasoningDelta(chunk: t.CustomChunk): string;
34
36
  handle(chunk?: t.CustomChunk): void;
35
37
  }
@@ -20,6 +20,8 @@ import type { AnthropicInput } from '@langchain/anthropic';
20
20
  import type { Runnable } from '@langchain/core/runnables';
21
21
  import type { ChatOllamaInput } from '@langchain/ollama';
22
22
  import type { OpenAI as OpenAIClient } from 'openai';
23
+ import type { ChatOpenRouterCallOptions } from '@/llm/openrouter/llm';
24
+ import { ChatOpenRouter } from '@/llm/openrouter/llm';
23
25
  import { Providers } from '@/common';
24
26
  export type AzureClientOptions = (Partial<OpenAIChatInput> & Partial<AzureOpenAIInput> & {
25
27
  openAIApiKey?: string;
@@ -53,6 +55,7 @@ export type ProviderOptionsMap = {
53
55
  [Providers.DEEPSEEK]: DeepSeekClientOptions;
54
56
  [Providers.ANTHROPIC]: AnthropicClientOptions;
55
57
  [Providers.MISTRALAI]: MistralAIClientOptions;
58
+ [Providers.OPENROUTER]: ChatOpenRouterCallOptions;
56
59
  [Providers.BEDROCK_LEGACY]: BedrockClientOptions;
57
60
  [Providers.BEDROCK]: BedrockConverseClientOptions;
58
61
  };
@@ -64,6 +67,7 @@ export type ChatModelMap = {
64
67
  [Providers.VERTEXAI]: ChatVertexAI;
65
68
  [Providers.ANTHROPIC]: ChatAnthropic;
66
69
  [Providers.MISTRALAI]: ChatMistralAI;
70
+ [Providers.OPENROUTER]: ChatOpenRouter;
67
71
  [Providers.BEDROCK_LEGACY]: BedrockChat;
68
72
  [Providers.BEDROCK]: ChatBedrockConverse;
69
73
  [Providers.GOOGLE]: ChatGoogleGenerativeAI;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@librechat/agents",
3
- "version": "2.1.1",
3
+ "version": "2.1.3",
4
4
  "main": "./dist/cjs/main.cjs",
5
5
  "module": "./dist/esm/main.mjs",
6
6
  "types": "./dist/types/index.d.ts",
@@ -45,7 +45,8 @@
45
45
  "code_exec": "node -r dotenv/config --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/code_exec.ts --provider 'google' --name 'Jo' --location 'New York, NY'",
46
46
  "image": "node -r dotenv/config --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/image.ts --provider 'vertexai' --name 'Jo' --location 'New York, NY'",
47
47
  "code_exec_simple": "node -r dotenv/config --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/code_exec_simple.ts --provider 'vertexai' --name 'Jo' --location 'New York, NY'",
48
- "simple": "node -r dotenv/config --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/simple.ts --provider 'deepseek' --name 'Jo' --location 'New York, NY'",
48
+ "simple": "node -r dotenv/config --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/simple.ts --provider 'openrouter' --name 'Jo' --location 'New York, NY'",
49
+ "caching": "node -r dotenv/config --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/caching.ts --name 'Jo' --location 'New York, NY'",
49
50
  "memory": "node -r dotenv/config --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/memory.ts --provider 'openAI' --name 'Jo' --location 'New York, NY'",
50
51
  "tool-test": "node -r dotenv/config --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/tools.ts --provider 'alibaba' --name 'Jo' --location 'New York, NY'",
51
52
  "abort": "node -r dotenv/config --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/abort.ts --provider 'openAI' --name 'Jo' --location 'New York, NY'",
@@ -70,14 +71,14 @@
70
71
  "@aws-crypto/sha256-js": "^5.2.0",
71
72
  "@aws-sdk/credential-provider-node": "^3.613.0",
72
73
  "@aws-sdk/types": "^3.609.0",
73
- "@langchain/anthropic": "^0.3.12",
74
- "@langchain/aws": "^0.1.3",
74
+ "@langchain/anthropic": "^0.3.14",
75
+ "@langchain/aws": "^0.1.4",
75
76
  "@langchain/community": "^0.3.27",
76
- "@langchain/core": "^0.3.37",
77
+ "@langchain/core": "^0.3.40",
77
78
  "@langchain/deepseek": "^0.0.1",
78
- "@langchain/google-genai": "^0.1.7",
79
- "@langchain/google-vertexai": "^0.1.8",
80
- "@langchain/langgraph": "^0.2.41",
79
+ "@langchain/google-genai": "^0.1.9",
80
+ "@langchain/google-vertexai": "^0.2.0",
81
+ "@langchain/langgraph": "^0.2.49",
81
82
  "@langchain/mistralai": "^0.0.26",
82
83
  "@langchain/ollama": "^0.1.5",
83
84
  "@langchain/openai": "^0.4.2",
@@ -79,6 +79,7 @@ export enum Providers {
79
79
  GOOGLE = 'google',
80
80
  AZURE = 'azureOpenAI',
81
81
  DEEPSEEK = 'deepseek',
82
+ OPENROUTER = 'openrouter',
82
83
  }
83
84
 
84
85
  export enum GraphNodeKeys {
@@ -8,7 +8,7 @@ import { ChatOpenAI, AzureChatOpenAI } from '@langchain/openai';
8
8
  import { Runnable, RunnableConfig } from '@langchain/core/runnables';
9
9
  import { dispatchCustomEvent } from '@langchain/core/callbacks/dispatch';
10
10
  import { AIMessageChunk, ToolMessage, SystemMessage } from '@langchain/core/messages';
11
- import type { BaseMessage } from '@langchain/core/messages';
11
+ import type { BaseMessage, BaseMessageFields } from '@langchain/core/messages';
12
12
  import type * as t from '@/types';
13
13
  import { Providers, GraphEvents, GraphNodeKeys, StepTypes, Callback, ContentTypes } from '@/common';
14
14
  import { getChatModelClass, manualToolStreamProviders } from '@/llm/providers';
@@ -127,11 +127,23 @@ export class StandardGraph extends Graph<
127
127
  this.reasoningKey = reasoningKey;
128
128
  }
129
129
 
130
- let finalInstructions = instructions ?? '';
130
+ let finalInstructions: string | BaseMessageFields = instructions ?? '';
131
131
  if (additional_instructions) {
132
132
  finalInstructions = finalInstructions ? `${finalInstructions}\n\n${additional_instructions}` : additional_instructions;
133
133
  }
134
134
 
135
+ if (finalInstructions && provider === Providers.ANTHROPIC && (clientOptions as t.AnthropicClientOptions)?.clientOptions?.defaultHeaders?.['anthropic-beta']?.includes('prompt-caching')) {
136
+ finalInstructions = {
137
+ content: [
138
+ {
139
+ type: "text",
140
+ text: instructions,
141
+ cache_control: { type: "ephemeral" },
142
+ },
143
+ ],
144
+ };
145
+ }
146
+
135
147
  if (finalInstructions) {
136
148
  this.systemMessage = new SystemMessage(finalInstructions);
137
149
  }
@@ -151,7 +163,6 @@ export class StandardGraph extends Graph<
151
163
  this.messageIdsByStepKey = resetIfNotEmpty(this.messageIdsByStepKey, new Map());
152
164
  this.messageStepHasToolCalls = resetIfNotEmpty(this.prelimMessageIdsByStepKey, new Map());
153
165
  this.prelimMessageIdsByStepKey = resetIfNotEmpty(this.prelimMessageIdsByStepKey, new Map());
154
- this.reasoningKey = resetIfNotEmpty(this.reasoningKey, 'reasoning_content');
155
166
  this.currentTokenType = resetIfNotEmpty(this.currentTokenType, ContentTypes.TEXT);
156
167
  this.lastToken = resetIfNotEmpty(this.lastToken, undefined);
157
168
  this.tokenTypeSwitch = resetIfNotEmpty(this.tokenTypeSwitch, undefined);
@@ -38,6 +38,10 @@ export type AnthropicImageBlockParam = Anthropic.Messages.ImageBlockParam;
38
38
  export type AnthropicToolUseBlockParam = Anthropic.Messages.ToolUseBlockParam;
39
39
  export type AnthropicToolResultBlockParam =
40
40
  Anthropic.Messages.ToolResultBlockParam;
41
+ export type AnthropicDocumentBlockParam = Anthropic.Messages.DocumentBlockParam;
42
+ export type AnthropicThinkingBlockParam = Anthropic.Messages.ThinkingBlockParam;
43
+ export type AnthropicRedactedThinkingBlockParam =
44
+ Anthropic.Messages.RedactedThinkingBlockParam;
41
45
 
42
46
  /**
43
47
  * Stream usage information for Anthropic API calls
@@ -20,6 +20,9 @@ import type {
20
20
  AnthropicToolUseBlockParam,
21
21
  AnthropicMessageCreateParams,
22
22
  AnthropicToolResultBlockParam,
23
+ AnthropicDocumentBlockParam,
24
+ AnthropicThinkingBlockParam,
25
+ AnthropicRedactedThinkingBlockParam,
23
26
  } from '@/llm/anthropic/types';
24
27
 
25
28
  function _formatImage(imageUrl: string): { type: string; media_type: string; data: string } {
@@ -135,6 +138,27 @@ function _formatContent(content: MessageContent): string | Record<string, any>[]
135
138
  source,
136
139
  ...(cacheControl ? { cache_control: cacheControl } : {}),
137
140
  };
141
+ } else if (contentPart.type === "document") {
142
+ // PDF
143
+ return {
144
+ ...contentPart,
145
+ ...(cacheControl ? { cache_control: cacheControl } : {}),
146
+ };
147
+ } else if (contentPart.type === "thinking") {
148
+ const block: AnthropicThinkingBlockParam = {
149
+ type: "thinking" as const, // Explicitly setting the type as "thinking"
150
+ thinking: contentPart.thinking,
151
+ signature: contentPart.signature,
152
+ ...(cacheControl ? { cache_control: cacheControl } : {}),
153
+ };
154
+ return block;
155
+ } else if (contentPart.type === "redacted_thinking") {
156
+ const block: AnthropicRedactedThinkingBlockParam = {
157
+ type: "redacted_thinking" as const, // Explicitly setting the type as "redacted_thinking"
158
+ data: contentPart.data,
159
+ ...(cacheControl ? { cache_control: cacheControl } : {}),
160
+ };
161
+ return block;
138
162
  } else if (
139
163
  textTypes.find((t) => t === contentPart.type) != null &&
140
164
  'text' in contentPart
@@ -279,14 +303,20 @@ function mergeMessages(messages?: AnthropicMessageCreateParams['messages']): Ant
279
303
  | AnthropicImageBlockParam
280
304
  | AnthropicToolUseBlockParam
281
305
  | AnthropicToolResultBlockParam
306
+ | AnthropicDocumentBlockParam
307
+ | AnthropicThinkingBlockParam
308
+ | AnthropicRedactedThinkingBlockParam
282
309
  >
283
310
  ): Array<
284
311
  | AnthropicTextBlockParam
285
312
  | AnthropicImageBlockParam
286
313
  | AnthropicToolUseBlockParam
287
314
  | AnthropicToolResultBlockParam
315
+ | AnthropicDocumentBlockParam
316
+ | AnthropicThinkingBlockParam
317
+ | AnthropicRedactedThinkingBlockParam
288
318
  > => {
289
- if (typeof content === 'string') {
319
+ if (typeof content === "string") {
290
320
  return [
291
321
  {
292
322
  type: 'text',
@@ -7,6 +7,7 @@ import {
7
7
  UsageMetadata,
8
8
  AIMessageChunk,
9
9
  } from '@langchain/core/messages';
10
+ import type { ToolCallChunk } from "@langchain/core/messages/tool";
10
11
  import { ToolCall } from '@langchain/core/messages/tool';
11
12
  import { ChatGeneration } from '@langchain/core/outputs';
12
13
  import { AnthropicMessageResponse } from '../types.js';
@@ -73,56 +74,80 @@ export function _makeMessageChunkFromAnthropicEvent(
73
74
  }),
74
75
  };
75
76
  } else if (
76
- data.type === 'content_block_start' &&
77
- data.content_block.type === 'tool_use'
77
+ data.type === "content_block_start" &&
78
+ ["tool_use", "document"].includes(data.content_block.type)
78
79
  ) {
79
- const toolCallContentBlock =
80
- data.content_block as Anthropic.Messages.ToolUseBlock;
80
+ const contentBlock = data.content_block;
81
+ let toolCallChunks: ToolCallChunk[];
82
+ if (contentBlock.type === "tool_use") {
83
+ toolCallChunks = [
84
+ {
85
+ id: contentBlock.id,
86
+ index: data.index,
87
+ name: contentBlock.name,
88
+ args: "",
89
+ },
90
+ ];
91
+ } else {
92
+ toolCallChunks = [];
93
+ }
81
94
  return {
82
95
  chunk: new AIMessageChunk({
83
96
  content: fields.coerceContentToString
84
- ? ''
97
+ ? ""
85
98
  : [
86
- {
87
- index: data.index,
88
- ...data.content_block,
89
- input: '',
90
- },
91
- ],
99
+ {
100
+ index: data.index,
101
+ ...data.content_block,
102
+ input: "",
103
+ },
104
+ ],
92
105
  additional_kwargs: {},
93
- tool_call_chunks: [
94
- {
95
- id: toolCallContentBlock.id,
96
- index: data.index,
97
- name: toolCallContentBlock.name,
98
- args: '',
99
- },
100
- ],
106
+ tool_call_chunks: toolCallChunks,
101
107
  }),
102
108
  };
103
109
  } else if (
104
- data.type === 'content_block_delta' &&
105
- data.delta.type === 'text_delta'
110
+ data.type === "content_block_delta" &&
111
+ [
112
+ "text_delta",
113
+ "citations_delta",
114
+ "thinking_delta",
115
+ "signature_delta",
116
+ ].includes(data.delta.type)
106
117
  ) {
107
- const content = data.delta.text;
108
- if (content !== undefined) {
118
+ if (fields.coerceContentToString && "text" in data.delta) {
109
119
  return {
110
120
  chunk: new AIMessageChunk({
111
- content: fields.coerceContentToString
112
- ? content
113
- : [
114
- {
115
- index: data.index,
116
- ...data.delta,
117
- },
118
- ],
119
- additional_kwargs: {},
121
+ content: data.delta.text,
122
+ }),
123
+ };
124
+ } else {
125
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
126
+ const contentBlock: Record<string, any> = data.delta;
127
+ if ("citation" in contentBlock) {
128
+ contentBlock.citations = [contentBlock.citation];
129
+ delete contentBlock.citation;
130
+ }
131
+ if (
132
+ contentBlock.type === "thinking_delta" ||
133
+ contentBlock.type === "signature_delta"
134
+ ) {
135
+ return {
136
+ chunk: new AIMessageChunk({
137
+ content: [{ index: data.index, ...contentBlock, type: "thinking" }],
138
+ }),
139
+ };
140
+ }
141
+
142
+ return {
143
+ chunk: new AIMessageChunk({
144
+ content: [{ index: data.index, ...contentBlock, type: "text" }],
120
145
  }),
121
146
  };
122
147
  }
123
148
  } else if (
124
- data.type === 'content_block_delta' &&
125
- data.delta.type === 'input_json_delta'
149
+ data.type === "content_block_delta" &&
150
+ data.delta.type === "input_json_delta"
126
151
  ) {
127
152
  return {
128
153
  chunk: new AIMessageChunk({
@@ -0,0 +1,37 @@
1
+ import { ChatOpenAI } from '@langchain/openai';
2
+ import type { ChatOpenAICallOptions, OpenAIClient } from '@langchain/openai';
3
+ import type { AIMessageChunk, HumanMessageChunk, SystemMessageChunk, FunctionMessageChunk, ToolMessageChunk, ChatMessageChunk} from '@langchain/core/messages';
4
+ export interface ChatOpenRouterCallOptions extends ChatOpenAICallOptions {
5
+ include_reasoning?: boolean;
6
+ }
7
+ export class ChatOpenRouter extends ChatOpenAI<ChatOpenRouterCallOptions> {
8
+ constructor(_fields: Partial<ChatOpenRouterCallOptions>) {
9
+ const { include_reasoning, ...fields } = _fields;
10
+ super({
11
+ ...fields,
12
+ modelKwargs: {
13
+ include_reasoning,
14
+ }
15
+ });
16
+ }
17
+ protected override _convertOpenAIDeltaToBaseMessageChunk(
18
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
19
+ delta: Record<string, any>,
20
+ rawResponse: OpenAIClient.ChatCompletionChunk,
21
+ defaultRole?:
22
+ | 'function'
23
+ | 'user'
24
+ | 'system'
25
+ | 'developer'
26
+ | 'assistant'
27
+ | 'tool'
28
+ ): AIMessageChunk | HumanMessageChunk | SystemMessageChunk | FunctionMessageChunk | ToolMessageChunk | ChatMessageChunk {
29
+ const messageChunk = super._convertOpenAIDeltaToBaseMessageChunk(
30
+ delta,
31
+ rawResponse,
32
+ defaultRole
33
+ );
34
+ messageChunk.additional_kwargs.reasoning = delta.reasoning;
35
+ return messageChunk;
36
+ }
37
+ }
@@ -10,6 +10,7 @@ import { ChatGoogleGenerativeAI } from '@langchain/google-genai';
10
10
  import { BedrockChat } from '@langchain/community/chat_models/bedrock/web';
11
11
  import type { ChatModelConstructorMap, ProviderOptionsMap, ChatModelMap } from '@/types';
12
12
  import { CustomAnthropic } from '@/llm/anthropic/llm';
13
+ import { ChatOpenRouter } from '@/llm/openrouter/llm';
13
14
  import { Providers } from '@/common';
14
15
 
15
16
  export const llmProviders: Partial<ChatModelConstructorMap> = {
@@ -20,6 +21,7 @@ export const llmProviders: Partial<ChatModelConstructorMap> = {
20
21
  [Providers.DEEPSEEK]: ChatDeepSeek,
21
22
  [Providers.MISTRALAI]: ChatMistralAI,
22
23
  [Providers.ANTHROPIC]: CustomAnthropic,
24
+ [Providers.OPENROUTER]: ChatOpenRouter,
23
25
  [Providers.BEDROCK_LEGACY]: BedrockChat,
24
26
  [Providers.BEDROCK]: ChatBedrockConverse,
25
27
  // [Providers.ANTHROPIC]: ChatAnthropic,