illuma-agents 1.0.8 → 1.0.10
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/LICENSE +1 -5
- package/dist/cjs/common/enum.cjs +1 -2
- package/dist/cjs/common/enum.cjs.map +1 -1
- package/dist/cjs/events.cjs +11 -0
- package/dist/cjs/events.cjs.map +1 -1
- package/dist/cjs/graphs/Graph.cjs +2 -1
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/instrumentation.cjs +3 -1
- package/dist/cjs/instrumentation.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/types.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/utils/message_inputs.cjs +79 -2
- package/dist/cjs/llm/anthropic/utils/message_inputs.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/utils/tools.cjs.map +1 -1
- package/dist/cjs/llm/bedrock/index.cjs +99 -0
- package/dist/cjs/llm/bedrock/index.cjs.map +1 -0
- package/dist/cjs/llm/fake.cjs.map +1 -1
- package/dist/cjs/llm/openai/index.cjs +102 -0
- package/dist/cjs/llm/openai/index.cjs.map +1 -1
- package/dist/cjs/llm/openai/utils/index.cjs +87 -1
- package/dist/cjs/llm/openai/utils/index.cjs.map +1 -1
- package/dist/cjs/llm/openrouter/index.cjs +175 -1
- package/dist/cjs/llm/openrouter/index.cjs.map +1 -1
- package/dist/cjs/llm/providers.cjs +13 -16
- package/dist/cjs/llm/providers.cjs.map +1 -1
- package/dist/cjs/llm/text.cjs.map +1 -1
- package/dist/cjs/messages/core.cjs +14 -14
- package/dist/cjs/messages/core.cjs.map +1 -1
- package/dist/cjs/messages/ids.cjs.map +1 -1
- package/dist/cjs/messages/prune.cjs.map +1 -1
- package/dist/cjs/run.cjs +18 -1
- package/dist/cjs/run.cjs.map +1 -1
- package/dist/cjs/splitStream.cjs.map +1 -1
- package/dist/cjs/stream.cjs +24 -1
- package/dist/cjs/stream.cjs.map +1 -1
- package/dist/cjs/tools/ToolNode.cjs +20 -1
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/tools/handlers.cjs +29 -25
- package/dist/cjs/tools/handlers.cjs.map +1 -1
- package/dist/cjs/tools/search/anthropic.cjs.map +1 -1
- package/dist/cjs/tools/search/content.cjs.map +1 -1
- package/dist/cjs/tools/search/firecrawl.cjs.map +1 -1
- package/dist/cjs/tools/search/format.cjs.map +1 -1
- package/dist/cjs/tools/search/highlights.cjs.map +1 -1
- package/dist/cjs/tools/search/rerankers.cjs.map +1 -1
- package/dist/cjs/tools/search/schema.cjs +27 -25
- package/dist/cjs/tools/search/schema.cjs.map +1 -1
- package/dist/cjs/tools/search/search.cjs +6 -1
- package/dist/cjs/tools/search/search.cjs.map +1 -1
- package/dist/cjs/tools/search/serper-scraper.cjs.map +1 -1
- package/dist/cjs/tools/search/tool.cjs +182 -35
- package/dist/cjs/tools/search/tool.cjs.map +1 -1
- package/dist/cjs/tools/search/utils.cjs.map +1 -1
- package/dist/cjs/utils/graph.cjs.map +1 -1
- package/dist/cjs/utils/llm.cjs +0 -1
- package/dist/cjs/utils/llm.cjs.map +1 -1
- package/dist/cjs/utils/misc.cjs.map +1 -1
- package/dist/cjs/utils/run.cjs.map +1 -1
- package/dist/cjs/utils/title.cjs +7 -7
- package/dist/cjs/utils/title.cjs.map +1 -1
- package/dist/esm/common/enum.mjs +1 -2
- package/dist/esm/common/enum.mjs.map +1 -1
- package/dist/esm/events.mjs +11 -0
- package/dist/esm/events.mjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +2 -1
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/instrumentation.mjs +3 -1
- package/dist/esm/instrumentation.mjs.map +1 -1
- package/dist/esm/llm/anthropic/types.mjs.map +1 -1
- package/dist/esm/llm/anthropic/utils/message_inputs.mjs +79 -2
- package/dist/esm/llm/anthropic/utils/message_inputs.mjs.map +1 -1
- package/dist/esm/llm/anthropic/utils/tools.mjs.map +1 -1
- package/dist/esm/llm/bedrock/index.mjs +97 -0
- package/dist/esm/llm/bedrock/index.mjs.map +1 -0
- package/dist/esm/llm/fake.mjs.map +1 -1
- package/dist/esm/llm/openai/index.mjs +103 -1
- package/dist/esm/llm/openai/index.mjs.map +1 -1
- package/dist/esm/llm/openai/utils/index.mjs +88 -2
- package/dist/esm/llm/openai/utils/index.mjs.map +1 -1
- package/dist/esm/llm/openrouter/index.mjs +175 -1
- package/dist/esm/llm/openrouter/index.mjs.map +1 -1
- package/dist/esm/llm/providers.mjs +2 -5
- package/dist/esm/llm/providers.mjs.map +1 -1
- package/dist/esm/llm/text.mjs.map +1 -1
- package/dist/esm/messages/core.mjs +14 -14
- package/dist/esm/messages/core.mjs.map +1 -1
- package/dist/esm/messages/ids.mjs.map +1 -1
- package/dist/esm/messages/prune.mjs.map +1 -1
- package/dist/esm/run.mjs +18 -1
- package/dist/esm/run.mjs.map +1 -1
- package/dist/esm/splitStream.mjs.map +1 -1
- package/dist/esm/stream.mjs +24 -1
- package/dist/esm/stream.mjs.map +1 -1
- package/dist/esm/tools/ToolNode.mjs +20 -1
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/tools/handlers.mjs +30 -26
- package/dist/esm/tools/handlers.mjs.map +1 -1
- package/dist/esm/tools/search/anthropic.mjs.map +1 -1
- package/dist/esm/tools/search/content.mjs.map +1 -1
- package/dist/esm/tools/search/firecrawl.mjs.map +1 -1
- package/dist/esm/tools/search/format.mjs.map +1 -1
- package/dist/esm/tools/search/highlights.mjs.map +1 -1
- package/dist/esm/tools/search/rerankers.mjs.map +1 -1
- package/dist/esm/tools/search/schema.mjs +27 -25
- package/dist/esm/tools/search/schema.mjs.map +1 -1
- package/dist/esm/tools/search/search.mjs +6 -1
- package/dist/esm/tools/search/search.mjs.map +1 -1
- package/dist/esm/tools/search/serper-scraper.mjs.map +1 -1
- package/dist/esm/tools/search/tool.mjs +182 -35
- package/dist/esm/tools/search/tool.mjs.map +1 -1
- package/dist/esm/tools/search/utils.mjs.map +1 -1
- package/dist/esm/utils/graph.mjs.map +1 -1
- package/dist/esm/utils/llm.mjs +0 -1
- package/dist/esm/utils/llm.mjs.map +1 -1
- package/dist/esm/utils/misc.mjs.map +1 -1
- package/dist/esm/utils/run.mjs.map +1 -1
- package/dist/esm/utils/title.mjs +7 -7
- package/dist/esm/utils/title.mjs.map +1 -1
- package/dist/types/common/enum.d.ts +1 -2
- package/dist/types/llm/bedrock/index.d.ts +36 -0
- package/dist/types/llm/openai/index.d.ts +1 -0
- package/dist/types/llm/openai/utils/index.d.ts +10 -1
- package/dist/types/llm/openrouter/index.d.ts +4 -1
- package/dist/types/tools/search/types.d.ts +2 -0
- package/dist/types/types/llm.d.ts +3 -8
- package/package.json +16 -12
- package/src/common/enum.ts +1 -2
- package/src/common/index.ts +1 -1
- package/src/events.ts +11 -0
- package/src/graphs/Graph.ts +2 -1
- package/src/instrumentation.ts +25 -22
- package/src/llm/anthropic/llm.spec.ts +1442 -1442
- package/src/llm/anthropic/types.ts +140 -140
- package/src/llm/anthropic/utils/message_inputs.ts +757 -660
- package/src/llm/anthropic/utils/output_parsers.ts +133 -133
- package/src/llm/anthropic/utils/tools.ts +29 -29
- package/src/llm/bedrock/index.ts +128 -0
- package/src/llm/fake.ts +133 -133
- package/src/llm/google/llm.spec.ts +3 -1
- package/src/llm/google/utils/tools.ts +160 -160
- package/src/llm/openai/index.ts +126 -0
- package/src/llm/openai/types.ts +24 -24
- package/src/llm/openai/utils/index.ts +116 -1
- package/src/llm/openai/utils/isReasoningModel.test.ts +90 -90
- package/src/llm/openrouter/index.ts +222 -1
- package/src/llm/providers.ts +2 -7
- package/src/llm/text.ts +94 -94
- package/src/messages/core.ts +463 -463
- package/src/messages/formatAgentMessages.tools.test.ts +400 -400
- package/src/messages/formatMessage.test.ts +693 -693
- package/src/messages/ids.ts +26 -26
- package/src/messages/prune.ts +567 -567
- package/src/messages/shiftIndexTokenCountMap.test.ts +81 -81
- package/src/mockStream.ts +98 -98
- package/src/prompts/collab.ts +5 -5
- package/src/prompts/index.ts +1 -1
- package/src/prompts/taskmanager.ts +61 -61
- package/src/run.ts +22 -4
- package/src/scripts/ant_web_search_edge_case.ts +162 -0
- package/src/scripts/ant_web_search_error_edge_case.ts +148 -0
- package/src/scripts/args.ts +48 -48
- package/src/scripts/caching.ts +123 -123
- package/src/scripts/code_exec_files.ts +193 -193
- package/src/scripts/empty_input.ts +137 -137
- package/src/scripts/memory.ts +97 -97
- package/src/scripts/test-tools-before-handoff.ts +1 -5
- package/src/scripts/thinking.ts +149 -149
- package/src/scripts/tools.ts +1 -4
- package/src/specs/anthropic.simple.test.ts +67 -0
- package/src/specs/spec.utils.ts +3 -3
- package/src/specs/token-distribution-edge-case.test.ts +316 -316
- package/src/specs/tool-error.test.ts +193 -193
- package/src/splitStream.test.ts +691 -691
- package/src/splitStream.ts +234 -234
- package/src/stream.test.ts +94 -94
- package/src/stream.ts +30 -1
- package/src/tools/ToolNode.ts +24 -1
- package/src/tools/handlers.ts +32 -28
- package/src/tools/search/anthropic.ts +51 -51
- package/src/tools/search/content.test.ts +173 -173
- package/src/tools/search/content.ts +147 -147
- package/src/tools/search/direct-url.test.ts +530 -0
- package/src/tools/search/firecrawl.ts +210 -210
- package/src/tools/search/format.ts +250 -250
- package/src/tools/search/highlights.ts +320 -320
- package/src/tools/search/index.ts +2 -2
- package/src/tools/search/jina-reranker.test.ts +126 -126
- package/src/tools/search/output.md +2775 -2775
- package/src/tools/search/rerankers.ts +242 -242
- package/src/tools/search/schema.ts +65 -63
- package/src/tools/search/search.ts +766 -759
- package/src/tools/search/serper-scraper.ts +155 -155
- package/src/tools/search/test.html +883 -883
- package/src/tools/search/test.md +642 -642
- package/src/tools/search/test.ts +159 -159
- package/src/tools/search/tool.ts +641 -471
- package/src/tools/search/types.ts +689 -687
- package/src/tools/search/utils.ts +79 -79
- package/src/types/index.ts +6 -6
- package/src/types/llm.ts +2 -8
- package/src/utils/graph.ts +10 -10
- package/src/utils/llm.ts +26 -27
- package/src/utils/llmConfig.ts +13 -5
- package/src/utils/logging.ts +48 -48
- package/src/utils/misc.ts +57 -57
- package/src/utils/run.ts +100 -100
- package/src/utils/title.ts +165 -165
- package/dist/cjs/llm/ollama/index.cjs +0 -70
- package/dist/cjs/llm/ollama/index.cjs.map +0 -1
- package/dist/cjs/llm/ollama/utils.cjs +0 -158
- package/dist/cjs/llm/ollama/utils.cjs.map +0 -1
- package/dist/esm/llm/ollama/index.mjs +0 -68
- package/dist/esm/llm/ollama/index.mjs.map +0 -1
- package/dist/esm/llm/ollama/utils.mjs +0 -155
- package/dist/esm/llm/ollama/utils.mjs.map +0 -1
- package/dist/types/llm/ollama/index.d.ts +0 -8
- package/dist/types/llm/ollama/utils.d.ts +0 -7
- package/src/llm/ollama/index.ts +0 -92
- package/src/llm/ollama/utils.ts +0 -193
- package/src/proto/CollabGraph.ts +0 -269
- package/src/proto/TaskManager.ts +0 -243
- package/src/proto/collab.ts +0 -200
- package/src/proto/collab_design.ts +0 -184
- package/src/proto/collab_design_v2.ts +0 -224
- package/src/proto/collab_design_v3.ts +0 -255
- package/src/proto/collab_design_v4.ts +0 -220
- package/src/proto/collab_design_v5.ts +0 -251
- package/src/proto/collab_graph.ts +0 -181
- package/src/proto/collab_original.ts +0 -123
- package/src/proto/example.ts +0 -93
- package/src/proto/example_new.ts +0 -68
- package/src/proto/example_old.ts +0 -201
- package/src/proto/example_test.ts +0 -152
- package/src/proto/example_test_anthropic.ts +0 -100
- package/src/proto/log_stream.ts +0 -202
- package/src/proto/main_collab_community_event.ts +0 -133
- package/src/proto/main_collab_design_v2.ts +0 -96
- package/src/proto/main_collab_design_v4.ts +0 -100
- package/src/proto/main_collab_design_v5.ts +0 -135
- package/src/proto/main_collab_global_analysis.ts +0 -122
- package/src/proto/main_collab_hackathon_event.ts +0 -153
- package/src/proto/main_collab_space_mission.ts +0 -153
- package/src/proto/main_philosophy.ts +0 -210
- package/src/proto/original_script.ts +0 -126
- package/src/proto/standard.ts +0 -100
- package/src/proto/stream.ts +0 -56
- package/src/proto/tasks.ts +0 -118
- package/src/proto/tools/global_analysis_tools.ts +0 -86
- package/src/proto/tools/space_mission_tools.ts +0 -60
- package/src/proto/vertexai.ts +0 -54
- package/src/scripts/image.ts +0 -178
package/src/llm/openai/index.ts
CHANGED
|
@@ -643,6 +643,132 @@ export class ChatDeepSeek extends OriginalChatDeepSeek {
|
|
|
643
643
|
} as OpenAICoreRequestOptions;
|
|
644
644
|
return requestOptions;
|
|
645
645
|
}
|
|
646
|
+
|
|
647
|
+
async *_streamResponseChunks(
|
|
648
|
+
messages: BaseMessage[],
|
|
649
|
+
options: this['ParsedCallOptions'],
|
|
650
|
+
runManager?: CallbackManagerForLLMRun
|
|
651
|
+
): AsyncGenerator<ChatGenerationChunk> {
|
|
652
|
+
const messagesMapped: OpenAICompletionParam[] =
|
|
653
|
+
_convertMessagesToOpenAIParams(messages, this.model, {
|
|
654
|
+
includeReasoningContent: true,
|
|
655
|
+
});
|
|
656
|
+
|
|
657
|
+
const params = {
|
|
658
|
+
...this.invocationParams(options, {
|
|
659
|
+
streaming: true,
|
|
660
|
+
}),
|
|
661
|
+
messages: messagesMapped,
|
|
662
|
+
stream: true as const,
|
|
663
|
+
};
|
|
664
|
+
let defaultRole: OpenAIRoleEnum | undefined;
|
|
665
|
+
|
|
666
|
+
const streamIterable = await this.completionWithRetry(params, options);
|
|
667
|
+
let usage: OpenAIClient.Completions.CompletionUsage | undefined;
|
|
668
|
+
for await (const data of streamIterable) {
|
|
669
|
+
const choice = data.choices[0] as
|
|
670
|
+
| Partial<OpenAIClient.Chat.Completions.ChatCompletionChunk.Choice>
|
|
671
|
+
| undefined;
|
|
672
|
+
if (data.usage) {
|
|
673
|
+
usage = data.usage;
|
|
674
|
+
}
|
|
675
|
+
if (!choice) {
|
|
676
|
+
continue;
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
const { delta } = choice;
|
|
680
|
+
if (!delta) {
|
|
681
|
+
continue;
|
|
682
|
+
}
|
|
683
|
+
const chunk = this._convertOpenAIDeltaToBaseMessageChunk(
|
|
684
|
+
delta,
|
|
685
|
+
data,
|
|
686
|
+
defaultRole
|
|
687
|
+
);
|
|
688
|
+
if ('reasoning_content' in delta) {
|
|
689
|
+
chunk.additional_kwargs.reasoning_content = delta.reasoning_content;
|
|
690
|
+
}
|
|
691
|
+
defaultRole = delta.role ?? defaultRole;
|
|
692
|
+
const newTokenIndices = {
|
|
693
|
+
prompt: (options as OpenAIChatCallOptions).promptIndex ?? 0,
|
|
694
|
+
completion: choice.index ?? 0,
|
|
695
|
+
};
|
|
696
|
+
if (typeof chunk.content !== 'string') {
|
|
697
|
+
// eslint-disable-next-line no-console
|
|
698
|
+
console.log(
|
|
699
|
+
'[WARNING]: Received non-string content from OpenAI. This is currently not supported.'
|
|
700
|
+
);
|
|
701
|
+
continue;
|
|
702
|
+
}
|
|
703
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
704
|
+
const generationInfo: Record<string, any> = { ...newTokenIndices };
|
|
705
|
+
if (choice.finish_reason != null) {
|
|
706
|
+
generationInfo.finish_reason = choice.finish_reason;
|
|
707
|
+
generationInfo.system_fingerprint = data.system_fingerprint;
|
|
708
|
+
generationInfo.model_name = data.model;
|
|
709
|
+
generationInfo.service_tier = data.service_tier;
|
|
710
|
+
}
|
|
711
|
+
if (this.logprobs == true) {
|
|
712
|
+
generationInfo.logprobs = choice.logprobs;
|
|
713
|
+
}
|
|
714
|
+
const generationChunk = new ChatGenerationChunk({
|
|
715
|
+
message: chunk,
|
|
716
|
+
text: chunk.content,
|
|
717
|
+
generationInfo,
|
|
718
|
+
});
|
|
719
|
+
yield generationChunk;
|
|
720
|
+
await runManager?.handleLLMNewToken(
|
|
721
|
+
generationChunk.text || '',
|
|
722
|
+
newTokenIndices,
|
|
723
|
+
undefined,
|
|
724
|
+
undefined,
|
|
725
|
+
undefined,
|
|
726
|
+
{ chunk: generationChunk }
|
|
727
|
+
);
|
|
728
|
+
}
|
|
729
|
+
if (usage) {
|
|
730
|
+
const inputTokenDetails = {
|
|
731
|
+
...(usage.prompt_tokens_details?.audio_tokens != null && {
|
|
732
|
+
audio: usage.prompt_tokens_details.audio_tokens,
|
|
733
|
+
}),
|
|
734
|
+
...(usage.prompt_tokens_details?.cached_tokens != null && {
|
|
735
|
+
cache_read: usage.prompt_tokens_details.cached_tokens,
|
|
736
|
+
}),
|
|
737
|
+
};
|
|
738
|
+
const outputTokenDetails = {
|
|
739
|
+
...(usage.completion_tokens_details?.audio_tokens != null && {
|
|
740
|
+
audio: usage.completion_tokens_details.audio_tokens,
|
|
741
|
+
}),
|
|
742
|
+
...(usage.completion_tokens_details?.reasoning_tokens != null && {
|
|
743
|
+
reasoning: usage.completion_tokens_details.reasoning_tokens,
|
|
744
|
+
}),
|
|
745
|
+
};
|
|
746
|
+
const generationChunk = new ChatGenerationChunk({
|
|
747
|
+
message: new AIMessageChunk({
|
|
748
|
+
content: '',
|
|
749
|
+
response_metadata: {
|
|
750
|
+
usage: { ...usage },
|
|
751
|
+
},
|
|
752
|
+
usage_metadata: {
|
|
753
|
+
input_tokens: usage.prompt_tokens,
|
|
754
|
+
output_tokens: usage.completion_tokens,
|
|
755
|
+
total_tokens: usage.total_tokens,
|
|
756
|
+
...(Object.keys(inputTokenDetails).length > 0 && {
|
|
757
|
+
input_token_details: inputTokenDetails,
|
|
758
|
+
}),
|
|
759
|
+
...(Object.keys(outputTokenDetails).length > 0 && {
|
|
760
|
+
output_token_details: outputTokenDetails,
|
|
761
|
+
}),
|
|
762
|
+
},
|
|
763
|
+
}),
|
|
764
|
+
text: '',
|
|
765
|
+
});
|
|
766
|
+
yield generationChunk;
|
|
767
|
+
}
|
|
768
|
+
if (options.signal?.aborted === true) {
|
|
769
|
+
throw new Error('AbortError');
|
|
770
|
+
}
|
|
771
|
+
}
|
|
646
772
|
}
|
|
647
773
|
|
|
648
774
|
/** xAI-specific usage metadata type */
|
package/src/llm/openai/types.ts
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
import type { OpenAICallOptions } from '@langchain/openai';
|
|
2
|
-
|
|
3
|
-
export interface OpenAIChatCallOptions extends OpenAICallOptions {
|
|
4
|
-
promptIndex?: number;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
// TODO import from SDK when available
|
|
8
|
-
export type OpenAIRoleEnum =
|
|
9
|
-
| 'system'
|
|
10
|
-
| 'developer'
|
|
11
|
-
| 'assistant'
|
|
12
|
-
| 'user'
|
|
13
|
-
| 'function'
|
|
14
|
-
| 'tool';
|
|
15
|
-
|
|
16
|
-
export type HeaderValue = string | undefined | null;
|
|
17
|
-
export type HeadersLike =
|
|
18
|
-
| Headers
|
|
19
|
-
| readonly HeaderValue[][]
|
|
20
|
-
| Record<string, HeaderValue | readonly HeaderValue[]>
|
|
21
|
-
| undefined
|
|
22
|
-
| null
|
|
23
|
-
// NullableHeaders
|
|
24
|
-
| { values: Headers; [key: string]: unknown };
|
|
1
|
+
import type { OpenAICallOptions } from '@langchain/openai';
|
|
2
|
+
|
|
3
|
+
export interface OpenAIChatCallOptions extends OpenAICallOptions {
|
|
4
|
+
promptIndex?: number;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
// TODO import from SDK when available
|
|
8
|
+
export type OpenAIRoleEnum =
|
|
9
|
+
| 'system'
|
|
10
|
+
| 'developer'
|
|
11
|
+
| 'assistant'
|
|
12
|
+
| 'user'
|
|
13
|
+
| 'function'
|
|
14
|
+
| 'tool';
|
|
15
|
+
|
|
16
|
+
export type HeaderValue = string | undefined | null;
|
|
17
|
+
export type HeadersLike =
|
|
18
|
+
| Headers
|
|
19
|
+
| readonly HeaderValue[][]
|
|
20
|
+
| Record<string, HeaderValue | readonly HeaderValue[]>
|
|
21
|
+
| undefined
|
|
22
|
+
| null
|
|
23
|
+
// NullableHeaders
|
|
24
|
+
| { values: Headers; [key: string]: unknown };
|
|
@@ -286,10 +286,21 @@ const completionsApiContentBlockConverter: StandardContentBlockConverter<{
|
|
|
286
286
|
},
|
|
287
287
|
};
|
|
288
288
|
|
|
289
|
+
/** Options for converting messages to OpenAI params */
|
|
290
|
+
export interface ConvertMessagesOptions {
|
|
291
|
+
/** Include reasoning_content field for DeepSeek thinking mode with tool calls */
|
|
292
|
+
includeReasoningContent?: boolean;
|
|
293
|
+
/** Include reasoning_details field for OpenRouter/Gemini thinking mode with tool calls */
|
|
294
|
+
includeReasoningDetails?: boolean;
|
|
295
|
+
/** Convert reasoning_details to content blocks for Claude (requires content array format) */
|
|
296
|
+
convertReasoningDetailsToContent?: boolean;
|
|
297
|
+
}
|
|
298
|
+
|
|
289
299
|
// Used in LangSmith, export is important here
|
|
290
300
|
export function _convertMessagesToOpenAIParams(
|
|
291
301
|
messages: BaseMessage[],
|
|
292
|
-
model?: string
|
|
302
|
+
model?: string,
|
|
303
|
+
options?: ConvertMessagesOptions
|
|
293
304
|
): OpenAICompletionParam[] {
|
|
294
305
|
// TODO: Function messages do not support array content, fix cast
|
|
295
306
|
return messages.flatMap((message) => {
|
|
@@ -333,9 +344,113 @@ export function _convertMessagesToOpenAIParams(
|
|
|
333
344
|
convertLangChainToolCallToOpenAI
|
|
334
345
|
);
|
|
335
346
|
completionParam.content = hasAnthropicThinkingBlock ? content : '';
|
|
347
|
+
if (
|
|
348
|
+
options?.includeReasoningContent === true &&
|
|
349
|
+
message.additional_kwargs.reasoning_content != null
|
|
350
|
+
) {
|
|
351
|
+
completionParam.reasoning_content =
|
|
352
|
+
message.additional_kwargs.reasoning_content;
|
|
353
|
+
}
|
|
354
|
+
if (
|
|
355
|
+
options?.includeReasoningDetails === true &&
|
|
356
|
+
message.additional_kwargs.reasoning_details != null
|
|
357
|
+
) {
|
|
358
|
+
// For Claude via OpenRouter, convert reasoning_details to content blocks
|
|
359
|
+
const isClaudeModel =
|
|
360
|
+
model?.includes('claude') === true ||
|
|
361
|
+
model?.includes('anthropic') === true;
|
|
362
|
+
if (
|
|
363
|
+
options.convertReasoningDetailsToContent === true &&
|
|
364
|
+
isClaudeModel
|
|
365
|
+
) {
|
|
366
|
+
const reasoningDetails = message.additional_kwargs
|
|
367
|
+
.reasoning_details as Record<string, unknown>[];
|
|
368
|
+
const contentBlocks = [];
|
|
369
|
+
|
|
370
|
+
// Add thinking blocks from reasoning_details
|
|
371
|
+
for (const detail of reasoningDetails) {
|
|
372
|
+
if (detail.type === 'reasoning.text' && detail.text != null) {
|
|
373
|
+
contentBlocks.push({
|
|
374
|
+
type: 'thinking',
|
|
375
|
+
thinking: detail.text,
|
|
376
|
+
});
|
|
377
|
+
} else if (
|
|
378
|
+
detail.type === 'reasoning.encrypted' &&
|
|
379
|
+
detail.data != null
|
|
380
|
+
) {
|
|
381
|
+
contentBlocks.push({
|
|
382
|
+
type: 'redacted_thinking',
|
|
383
|
+
data: detail.data,
|
|
384
|
+
id: detail.id,
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// Set content to array with thinking blocks
|
|
390
|
+
if (contentBlocks.length > 0) {
|
|
391
|
+
completionParam.content = contentBlocks;
|
|
392
|
+
}
|
|
393
|
+
} else {
|
|
394
|
+
// For non-Claude models, pass as separate field
|
|
395
|
+
completionParam.reasoning_details =
|
|
396
|
+
message.additional_kwargs.reasoning_details;
|
|
397
|
+
}
|
|
398
|
+
}
|
|
336
399
|
} else {
|
|
337
400
|
if (message.additional_kwargs.tool_calls != null) {
|
|
338
401
|
completionParam.tool_calls = message.additional_kwargs.tool_calls;
|
|
402
|
+
if (
|
|
403
|
+
options?.includeReasoningContent === true &&
|
|
404
|
+
message.additional_kwargs.reasoning_content != null
|
|
405
|
+
) {
|
|
406
|
+
completionParam.reasoning_content =
|
|
407
|
+
message.additional_kwargs.reasoning_content;
|
|
408
|
+
}
|
|
409
|
+
if (
|
|
410
|
+
options?.includeReasoningDetails === true &&
|
|
411
|
+
message.additional_kwargs.reasoning_details != null
|
|
412
|
+
) {
|
|
413
|
+
// For Claude via OpenRouter, convert reasoning_details to content blocks
|
|
414
|
+
const isClaudeModel =
|
|
415
|
+
model?.includes('claude') === true ||
|
|
416
|
+
model?.includes('anthropic') === true;
|
|
417
|
+
if (
|
|
418
|
+
options.convertReasoningDetailsToContent === true &&
|
|
419
|
+
isClaudeModel
|
|
420
|
+
) {
|
|
421
|
+
const reasoningDetails = message.additional_kwargs
|
|
422
|
+
.reasoning_details as Record<string, unknown>[];
|
|
423
|
+
const contentBlocks = [];
|
|
424
|
+
|
|
425
|
+
// Add thinking blocks from reasoning_details
|
|
426
|
+
for (const detail of reasoningDetails) {
|
|
427
|
+
if (detail.type === 'reasoning.text' && detail.text != null) {
|
|
428
|
+
contentBlocks.push({
|
|
429
|
+
type: 'thinking',
|
|
430
|
+
thinking: detail.text,
|
|
431
|
+
});
|
|
432
|
+
} else if (
|
|
433
|
+
detail.type === 'reasoning.encrypted' &&
|
|
434
|
+
detail.data != null
|
|
435
|
+
) {
|
|
436
|
+
contentBlocks.push({
|
|
437
|
+
type: 'redacted_thinking',
|
|
438
|
+
data: detail.data,
|
|
439
|
+
id: detail.id,
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// Set content to array with thinking blocks
|
|
445
|
+
if (contentBlocks.length > 0) {
|
|
446
|
+
completionParam.content = contentBlocks;
|
|
447
|
+
}
|
|
448
|
+
} else {
|
|
449
|
+
// For non-Claude models, pass as separate field
|
|
450
|
+
completionParam.reasoning_details =
|
|
451
|
+
message.additional_kwargs.reasoning_details;
|
|
452
|
+
}
|
|
453
|
+
}
|
|
339
454
|
}
|
|
340
455
|
if ((message as ToolMessage).tool_call_id != null) {
|
|
341
456
|
completionParam.tool_call_id = (message as ToolMessage).tool_call_id;
|
|
@@ -1,90 +1,90 @@
|
|
|
1
|
-
import { isReasoningModel } from './index';
|
|
2
|
-
|
|
3
|
-
describe('isReasoningModel', () => {
|
|
4
|
-
describe('should return true for reasoning models', () => {
|
|
5
|
-
test('basic o-series models', () => {
|
|
6
|
-
expect(isReasoningModel('o1')).toBe(true);
|
|
7
|
-
expect(isReasoningModel('o2')).toBe(true);
|
|
8
|
-
expect(isReasoningModel('o9')).toBe(true);
|
|
9
|
-
expect(isReasoningModel('o1-preview')).toBe(true);
|
|
10
|
-
expect(isReasoningModel('o1-mini')).toBe(true);
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
test('gpt-5+ models', () => {
|
|
14
|
-
expect(isReasoningModel('gpt-5')).toBe(true);
|
|
15
|
-
expect(isReasoningModel('gpt-6')).toBe(true);
|
|
16
|
-
expect(isReasoningModel('gpt-7')).toBe(true);
|
|
17
|
-
expect(isReasoningModel('gpt-8')).toBe(true);
|
|
18
|
-
expect(isReasoningModel('gpt-9')).toBe(true);
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
test('with provider prefixes', () => {
|
|
22
|
-
expect(isReasoningModel('azure/o1')).toBe(true);
|
|
23
|
-
expect(isReasoningModel('azure/gpt-5')).toBe(true);
|
|
24
|
-
expect(isReasoningModel('openai/o1')).toBe(true);
|
|
25
|
-
expect(isReasoningModel('openai/gpt-5')).toBe(true);
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
test('with custom prefixes', () => {
|
|
29
|
-
expect(isReasoningModel('custom-provider/o1')).toBe(true);
|
|
30
|
-
expect(isReasoningModel('my-deployment/gpt-5')).toBe(true);
|
|
31
|
-
expect(isReasoningModel('company/azure/gpt-5')).toBe(true);
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
test('case insensitive', () => {
|
|
35
|
-
expect(isReasoningModel('O1')).toBe(true);
|
|
36
|
-
expect(isReasoningModel('GPT-5')).toBe(true);
|
|
37
|
-
expect(isReasoningModel('gPt-6')).toBe(true);
|
|
38
|
-
expect(isReasoningModel('Azure/O1')).toBe(true);
|
|
39
|
-
});
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
describe('should return false for non-reasoning models', () => {
|
|
43
|
-
test('older GPT models', () => {
|
|
44
|
-
expect(isReasoningModel('gpt-3.5-turbo')).toBe(false);
|
|
45
|
-
expect(isReasoningModel('gpt-4')).toBe(false);
|
|
46
|
-
expect(isReasoningModel('gpt-4-turbo')).toBe(false);
|
|
47
|
-
expect(isReasoningModel('gpt-4o')).toBe(false);
|
|
48
|
-
expect(isReasoningModel('gpt-4o-mini')).toBe(false);
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
test('other model families', () => {
|
|
52
|
-
expect(isReasoningModel('claude-3')).toBe(false);
|
|
53
|
-
expect(isReasoningModel('claude-3-opus')).toBe(false);
|
|
54
|
-
expect(isReasoningModel('llama-2')).toBe(false);
|
|
55
|
-
expect(isReasoningModel('gemini-pro')).toBe(false);
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
test('partial matches that should not match', () => {
|
|
59
|
-
expect(isReasoningModel('proto1')).toBe(false);
|
|
60
|
-
expect(isReasoningModel('version-o1')).toBe(true);
|
|
61
|
-
expect(isReasoningModel('gpt-40')).toBe(false);
|
|
62
|
-
expect(isReasoningModel('gpt-3.5')).toBe(false);
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
test('empty, null, and undefined', () => {
|
|
66
|
-
expect(isReasoningModel('')).toBe(false);
|
|
67
|
-
expect(isReasoningModel()).toBe(false);
|
|
68
|
-
expect(isReasoningModel(undefined)).toBe(false);
|
|
69
|
-
});
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
describe('edge cases', () => {
|
|
73
|
-
test('with special characters', () => {
|
|
74
|
-
expect(isReasoningModel('deployment_o1_model')).toBe(false);
|
|
75
|
-
expect(isReasoningModel('gpt-5-deployment')).toBe(true);
|
|
76
|
-
expect(isReasoningModel('o1@latest')).toBe(true);
|
|
77
|
-
expect(isReasoningModel('gpt-5.0')).toBe(true);
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
test('word boundary behavior', () => {
|
|
81
|
-
// These should match because o1 and gpt-5 are whole words
|
|
82
|
-
expect(isReasoningModel('use-o1-model')).toBe(true);
|
|
83
|
-
expect(isReasoningModel('model-gpt-5-latest')).toBe(true);
|
|
84
|
-
|
|
85
|
-
// These should not match because o1/gpt-5 are not whole words
|
|
86
|
-
expect(isReasoningModel('proto1model')).toBe(false);
|
|
87
|
-
expect(isReasoningModel('supergpt-50')).toBe(false);
|
|
88
|
-
});
|
|
89
|
-
});
|
|
90
|
-
});
|
|
1
|
+
import { isReasoningModel } from './index';
|
|
2
|
+
|
|
3
|
+
describe('isReasoningModel', () => {
|
|
4
|
+
describe('should return true for reasoning models', () => {
|
|
5
|
+
test('basic o-series models', () => {
|
|
6
|
+
expect(isReasoningModel('o1')).toBe(true);
|
|
7
|
+
expect(isReasoningModel('o2')).toBe(true);
|
|
8
|
+
expect(isReasoningModel('o9')).toBe(true);
|
|
9
|
+
expect(isReasoningModel('o1-preview')).toBe(true);
|
|
10
|
+
expect(isReasoningModel('o1-mini')).toBe(true);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
test('gpt-5+ models', () => {
|
|
14
|
+
expect(isReasoningModel('gpt-5')).toBe(true);
|
|
15
|
+
expect(isReasoningModel('gpt-6')).toBe(true);
|
|
16
|
+
expect(isReasoningModel('gpt-7')).toBe(true);
|
|
17
|
+
expect(isReasoningModel('gpt-8')).toBe(true);
|
|
18
|
+
expect(isReasoningModel('gpt-9')).toBe(true);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test('with provider prefixes', () => {
|
|
22
|
+
expect(isReasoningModel('azure/o1')).toBe(true);
|
|
23
|
+
expect(isReasoningModel('azure/gpt-5')).toBe(true);
|
|
24
|
+
expect(isReasoningModel('openai/o1')).toBe(true);
|
|
25
|
+
expect(isReasoningModel('openai/gpt-5')).toBe(true);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test('with custom prefixes', () => {
|
|
29
|
+
expect(isReasoningModel('custom-provider/o1')).toBe(true);
|
|
30
|
+
expect(isReasoningModel('my-deployment/gpt-5')).toBe(true);
|
|
31
|
+
expect(isReasoningModel('company/azure/gpt-5')).toBe(true);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test('case insensitive', () => {
|
|
35
|
+
expect(isReasoningModel('O1')).toBe(true);
|
|
36
|
+
expect(isReasoningModel('GPT-5')).toBe(true);
|
|
37
|
+
expect(isReasoningModel('gPt-6')).toBe(true);
|
|
38
|
+
expect(isReasoningModel('Azure/O1')).toBe(true);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
describe('should return false for non-reasoning models', () => {
|
|
43
|
+
test('older GPT models', () => {
|
|
44
|
+
expect(isReasoningModel('gpt-3.5-turbo')).toBe(false);
|
|
45
|
+
expect(isReasoningModel('gpt-4')).toBe(false);
|
|
46
|
+
expect(isReasoningModel('gpt-4-turbo')).toBe(false);
|
|
47
|
+
expect(isReasoningModel('gpt-4o')).toBe(false);
|
|
48
|
+
expect(isReasoningModel('gpt-4o-mini')).toBe(false);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
test('other model families', () => {
|
|
52
|
+
expect(isReasoningModel('claude-3')).toBe(false);
|
|
53
|
+
expect(isReasoningModel('claude-3-opus')).toBe(false);
|
|
54
|
+
expect(isReasoningModel('llama-2')).toBe(false);
|
|
55
|
+
expect(isReasoningModel('gemini-pro')).toBe(false);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test('partial matches that should not match', () => {
|
|
59
|
+
expect(isReasoningModel('proto1')).toBe(false);
|
|
60
|
+
expect(isReasoningModel('version-o1')).toBe(true);
|
|
61
|
+
expect(isReasoningModel('gpt-40')).toBe(false);
|
|
62
|
+
expect(isReasoningModel('gpt-3.5')).toBe(false);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
test('empty, null, and undefined', () => {
|
|
66
|
+
expect(isReasoningModel('')).toBe(false);
|
|
67
|
+
expect(isReasoningModel()).toBe(false);
|
|
68
|
+
expect(isReasoningModel(undefined)).toBe(false);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
describe('edge cases', () => {
|
|
73
|
+
test('with special characters', () => {
|
|
74
|
+
expect(isReasoningModel('deployment_o1_model')).toBe(false);
|
|
75
|
+
expect(isReasoningModel('gpt-5-deployment')).toBe(true);
|
|
76
|
+
expect(isReasoningModel('o1@latest')).toBe(true);
|
|
77
|
+
expect(isReasoningModel('gpt-5.0')).toBe(true);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test('word boundary behavior', () => {
|
|
81
|
+
// These should match because o1 and gpt-5 are whole words
|
|
82
|
+
expect(isReasoningModel('use-o1-model')).toBe(true);
|
|
83
|
+
expect(isReasoningModel('model-gpt-5-latest')).toBe(true);
|
|
84
|
+
|
|
85
|
+
// These should not match because o1/gpt-5 are not whole words
|
|
86
|
+
expect(isReasoningModel('proto1model')).toBe(false);
|
|
87
|
+
expect(isReasoningModel('supergpt-50')).toBe(false);
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
});
|