Skip to content

Commit 1449e80

Browse files
Ankit5467Ankit54671gemini-code-assist[bot]HenryHengZJ
authored
feature/extend AWS Bedrock node with full model catalog and custom model support (#6309)
* feat(bedrock): extend AWS Bedrock node with full model catalog and custom model support * Update packages/components/models.json fixed typo Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * fixed typo Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * Update packages/components/nodes/chatmodels/AWSBedrock/FlowiseAWSChatBedrockImported.ts Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * fix * lint fix * remove redundant readme implementation file --------- Co-authored-by: Ankit <pankitd@amazon.com> Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Co-authored-by: Henry <hzj94@hotmail.com>
1 parent aee37e1 commit 1449e80

15 files changed

Lines changed: 4836 additions & 1905 deletions

File tree

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,4 +118,5 @@ apps/*/
118118
# Claude - session/user specific files
119119
.claude/plans/
120120
.claude/settings.local.json
121-
.claude/agent-memory/*
121+
.claude/agent-memory/*
122+

packages/agentflow/README.md

Lines changed: 270 additions & 270 deletions
Large diffs are not rendered by default.

packages/agentflow/src/features/canvas/components/NodeModelConfigs.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { useApiContext, useConfigContext } from '@/infrastructure/store'
66

77
interface ModelConfig {
88
model?: string
9-
config?: { modelName?: string; model?: string }
9+
config?: { modelName?: string; model?: string; customModel?: string }
1010
}
1111

1212
export interface NodeModelConfigsProps {
@@ -54,7 +54,11 @@ function NodeModelConfigsComponent({ inputs }: NodeModelConfigsProps) {
5454
src={`${apiBaseUrl}/api/v1/node-icon/${item.model}`}
5555
alt={item.model as string}
5656
/>
57-
<Typography sx={{ fontSize: '0.7rem', ml: 0.5 }}>{item.config?.modelName || item.config?.model}</Typography>
57+
<Typography sx={{ fontSize: '0.7rem', ml: 0.5 }}>
58+
{item.config?.customModel
59+
? item.config.customModel.replace(/^arn:aws:bedrock:[^:]+:[^:]+:/, '')
60+
: item.config?.modelName || item.config?.model}
61+
</Typography>
5862
</Box>
5963
</Box>
6064
))}

packages/components/evaluation/EvaluationRunTracer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ export class EvaluationRunTracer extends RunCollectorCallbackHandler {
6666
onLLMEnd?(run: Run): void | Promise<void> {
6767
if (run.name) {
6868
let provider = run.name
69-
if (provider === 'BedrockChat') {
69+
if (provider === 'BedrockChat' || provider === 'bedrock-imported') {
7070
provider = 'awsChatBedrock'
7171
}
7272
EvaluationRunner.addMetrics(

packages/components/models.json

Lines changed: 1077 additions & 480 deletions
Large diffs are not rendered by default.
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import * as fs from 'fs'
2+
import * as path from 'path'
3+
4+
describe('AWS Bedrock model catalog (models.json)', () => {
5+
let bedrockChat: any
6+
7+
beforeAll(() => {
8+
const modelsPath = path.join(__dirname, '..', '..', '..', 'models.json')
9+
const raw = JSON.parse(fs.readFileSync(modelsPath, 'utf8'))
10+
bedrockChat = raw.chat.find((c: any) => c.name === 'awsChatBedrock')
11+
})
12+
13+
it('awsChatBedrock section exists', () => {
14+
expect(bedrockChat).toBeDefined()
15+
})
16+
17+
it('has a non-empty models array', () => {
18+
expect(bedrockChat.models.length).toBeGreaterThan(0)
19+
})
20+
21+
it('has a non-empty regions array', () => {
22+
expect(bedrockChat.regions.length).toBeGreaterThan(0)
23+
})
24+
25+
it('every model has label and name', () => {
26+
for (const m of bedrockChat.models) {
27+
expect(m.label).toBeTruthy()
28+
expect(m.name).toBeTruthy()
29+
}
30+
})
31+
32+
it('does not contain TwelveLabs Pegasus (not a chat model)', () => {
33+
const pegasus = bedrockChat.models.find((m: any) => m.name.includes('twelvelabs.pegasus'))
34+
expect(pegasus).toBeUndefined()
35+
})
36+
37+
it('contains models added from AWS API', () => {
38+
const names = bedrockChat.models.map((m: any) => m.name)
39+
expect(names).toContain('minimax.minimax-m2.5')
40+
expect(names).toContain('nvidia.nemotron-super-3-120b')
41+
expect(names).toContain('zai.glm-5')
42+
expect(names).toContain('writer.palmyra-vision-7b')
43+
})
44+
45+
it('legacy models are present with (Legacy) label', () => {
46+
const legacyModels = bedrockChat.models.filter((m: any) => m.label.includes('(Legacy)'))
47+
expect(legacyModels.length).toBeGreaterThan(0)
48+
49+
const legacyNames = legacyModels.map((m: any) => m.name)
50+
expect(legacyNames).toContain('anthropic.claude-3-haiku-20240307-v1:0')
51+
expect(legacyNames).toContain('meta.llama3-2-1b-instruct-v1:0')
52+
expect(legacyNames).toContain('cohere.command-r-v1:0')
53+
54+
for (const m of legacyModels) {
55+
expect(m.label).toContain('(Legacy)')
56+
expect(m.description).toMatch(/Legacy|deprecated/i)
57+
}
58+
})
59+
60+
it('does not contain stale/wrong model IDs', () => {
61+
const names = bedrockChat.models.map((m: any) => m.name)
62+
expect(names).not.toContain('deepseek.v3-v1:0')
63+
expect(names).not.toContain('meta.llama3-1-405b-instruct-v1:0')
64+
expect(names).not.toContain('mistral.mistral-large-2407-v1:0')
65+
expect(names).not.toContain('nvidia.nemotron-3-super-120b-a12b')
66+
expect(names).not.toContain('qwen.qwen3-235b-a22b-2507-v1:0')
67+
expect(names).not.toContain('qwen.qwen3-coder-480b-a35b-v1:0')
68+
})
69+
70+
it('contains Claude 4.6 Sonnet (auto-converted via code)', () => {
71+
const claude46 = bedrockChat.models.find((m: any) => m.name === 'anthropic.claude-sonnet-4-6')
72+
expect(claude46).toBeDefined()
73+
})
74+
75+
it('model names do not have leading/trailing whitespace', () => {
76+
for (const m of bedrockChat.models) {
77+
expect(m.name).toBe(m.name.trim())
78+
}
79+
})
80+
81+
it('marks correct models with stop_sequences: false', () => {
82+
const noStopSeq = bedrockChat.models.filter((m: any) => m.stop_sequences === false).map((m: any) => m.name)
83+
expect(noStopSeq).toContain('deepseek.v3.2')
84+
expect(noStopSeq).toContain('deepseek.r1-v1:0')
85+
expect(noStopSeq).toContain('openai.gpt-oss-20b-1:0')
86+
expect(noStopSeq).toContain('openai.gpt-oss-120b-1:0')
87+
expect(noStopSeq).toContain('openai.gpt-oss-safeguard-20b')
88+
expect(noStopSeq).toContain('openai.gpt-oss-safeguard-120b')
89+
expect(noStopSeq).toHaveLength(6)
90+
})
91+
92+
it('does not mark other models with stop_sequences: false', () => {
93+
const withStopSeq = bedrockChat.models.filter((m: any) => m.stop_sequences === false)
94+
const names = withStopSeq.map((m: any) => m.name)
95+
expect(names).not.toContain('anthropic.claude-sonnet-4-6')
96+
expect(names).not.toContain('amazon.nova-pro-v1:0')
97+
})
98+
99+
// --- Pricing ---
100+
101+
it('every model has input_cost and output_cost', () => {
102+
for (const m of bedrockChat.models) {
103+
expect(m.input_cost).toBeDefined()
104+
expect(m.output_cost).toBeDefined()
105+
expect(typeof m.input_cost).toBe('number')
106+
expect(typeof m.output_cost).toBe('number')
107+
expect(m.input_cost).toBeGreaterThan(0)
108+
expect(m.output_cost).toBeGreaterThan(0)
109+
}
110+
})
111+
})

0 commit comments

Comments
 (0)