diff --git a/.github/ci-coverage-allowlist.yml b/.github/ci-coverage-allowlist.yml index b6ec08bd295..f7a785b3b80 100644 --- a/.github/ci-coverage-allowlist.yml +++ b/.github/ci-coverage-allowlist.yml @@ -89,17 +89,6 @@ test_paths: - tests/integration/sandbox/test_e2b_sandbox.py - tests/integration/test_oci_integration.py - tests/integration/test_oci_proxy_integration.py - - reason: >- - A unit test for the proxy-extras package that no job invokes, while the package's other - tests live under tests/proxy_migration_tests. Measured 2026-08-20: 24 of its 28 tests pass - and the 4 in TestMigrationSQLIdempotency fail, because 13 migrations from 2026-03 onward use - bare CREATE TABLE, ADD COLUMN, CREATE INDEX and ADD CONSTRAINT rather than the guarded forms - this file requires. It also matches those keywords inside SQL comments, so two further - migrations are reported that are in fact fine. Wiring it up means deciding what to do about - the 13 first, and they cannot simply be edited: Prisma checksums an applied migration, so a - changed one breaks migrate deploy for existing installs - paths: - - tests/litellm-proxy-extras/test_litellm_proxy_extras_utils.py dockerfiles: - reason: >- diff --git a/.github/workflows/test-unit.yml b/.github/workflows/test-unit.yml index 5a75b4af7db..368680d9ec2 100644 --- a/.github/workflows/test-unit.yml +++ b/.github/workflows/test-unit.yml @@ -213,6 +213,14 @@ jobs: timeout-minutes: 20 job-timeout-minutes: 55 + - shard: proxy-extras + artifact-name: proxy-extras + test-path: "tests/litellm-proxy-extras" + workers: 2 + reruns: 2 + timeout-minutes: 20 + job-timeout-minutes: 55 + - shard: responses-caching-types artifact-name: responses-caching-types test-path: >- diff --git a/tests/litellm-proxy-extras/test_litellm_proxy_extras_utils.py b/tests/litellm-proxy-extras/test_litellm_proxy_extras_utils.py index 6f4979b9b84..09f3e0ba34f 100644 --- a/tests/litellm-proxy-extras/test_litellm_proxy_extras_utils.py +++ b/tests/litellm-proxy-extras/test_litellm_proxy_extras_utils.py @@ -161,6 +161,58 @@ def _get_all_migrations(): return results +_LINE_COMMENT = re.compile(r"--.*$") +_BLOCK_COMMENT = re.compile(r"/\*.*?\*/", re.DOTALL) + +_PRE_GUARD_MIGRATIONS = frozenset({ + "20260331000000_add_prompt_environment_and_created_by", + "20260418000000_add_adaptive_router_tables", + "20260429161855_workflow_runs_tables", + "20260605182307_add_timeout_to_mcp_server_table", + "20260626120000_add_mcp_tool_search_enabled", + "20260629000000_add_max_concurrent_requests_to_mcp_server_table", + "20260710000000_add_dcr_bridge_to_mcp_server_table", + "20260713230852_add_key_type_to_litellm_verification_token", + "20260811172448_add_shadow_eval", + "20260813180408_add_shadow_eval_direction", + "20260814000000_add_proxy_worker_heartbeat", + "20260817143646_add_daily_guardrail_usage_units", + "20260818224500_add_shadow_eval_stopped_by", + "20260819000000_shadow_eval_max_budget", +}) + + +def _blanked_block_comments(sql): + """`sql` with every `/* ... */` body blanked out, newlines kept so lines still count. + + Prisma opens a destructive migration with a `/* Warnings: You are about to drop the + column ... */` header, which is prose about the statement rather than the statement. + """ + return _BLOCK_COMMENT.sub(lambda m: re.sub(r"[^\n]", " ", m.group(0)), sql) + + +def _statements(sql): + """(line_number, sql) for each line, with comments removed. + + Prisma writes its own explanations as `-- CREATE INDEX CONCURRENTLY ...`, which a + raw-line scan reads as the statement it is describing. + """ + return [ + (number, _LINE_COMMENT.sub("", line)) + for number, line in enumerate(_blanked_block_comments(sql).splitlines(), 1) + ] + + +def _guarded_migrations(all_migrations): + """Migrations the DDL rules apply to. Prisma checksums an applied migration, so the + ones that predate these rules cannot be edited without breaking `migrate deploy` + for existing installs; they are named once, and the rules bind everything after. + """ + return [ + (name, sql) for name, sql in all_migrations if name not in _PRE_GUARD_MIGRATIONS + ] + + class TestMigrationSQLIdempotency: """Ensure all migration SQL files use idempotent DDL (IF [NOT] EXISTS). @@ -181,8 +233,8 @@ class TestMigrationSQLIdempotency: def test_create_table_uses_if_not_exists(self, all_migrations): """CREATE TABLE statements must use IF NOT EXISTS""" violations = [] - for migration_name, sql in all_migrations: - for line_num, line in enumerate(sql.splitlines(), 1): + for migration_name, sql in _guarded_migrations(all_migrations): + for line_num, line in _statements(sql): if re.search( r"CREATE\s+TABLE\s+", line, re.IGNORECASE ) and not re.search( @@ -198,8 +250,8 @@ class TestMigrationSQLIdempotency: def test_add_column_uses_if_not_exists(self, all_migrations): """ADD COLUMN statements must use IF NOT EXISTS""" violations = [] - for migration_name, sql in all_migrations: - for line_num, line in enumerate(sql.splitlines(), 1): + for migration_name, sql in _guarded_migrations(all_migrations): + for line_num, line in _statements(sql): if re.search(r"ADD\s+COLUMN\s+", line, re.IGNORECASE) and not re.search( r"ADD\s+COLUMN\s+IF\s+NOT\s+EXISTS", line, re.IGNORECASE ): @@ -212,8 +264,8 @@ class TestMigrationSQLIdempotency: def test_drop_column_uses_if_exists(self, all_migrations): """DROP COLUMN statements must use IF EXISTS""" violations = [] - for migration_name, sql in all_migrations: - for line_num, line in enumerate(sql.splitlines(), 1): + for migration_name, sql in _guarded_migrations(all_migrations): + for line_num, line in _statements(sql): if re.search( r"DROP\s+COLUMN\s+", line, re.IGNORECASE ) and not re.search( @@ -239,7 +291,7 @@ class TestMigrationSQLIdempotency: for migration_name, sql in all_migrations: if migration_name in self._DROP_COLUMN_ALLOWLIST: continue - for line_num, line in enumerate(sql.splitlines(), 1): + for line_num, line in _statements(sql): if re.search(r"DROP\s+COLUMN", line, re.IGNORECASE): violations.append(f" {migration_name}:{line_num}: {line.strip()}") assert ( @@ -251,8 +303,8 @@ class TestMigrationSQLIdempotency: def test_drop_index_uses_if_exists(self, all_migrations): """DROP INDEX statements must use IF EXISTS""" violations = [] - for migration_name, sql in all_migrations: - for line_num, line in enumerate(sql.splitlines(), 1): + for migration_name, sql in _guarded_migrations(all_migrations): + for line_num, line in _statements(sql): if re.search(r"DROP\s+INDEX\s+", line, re.IGNORECASE) and not re.search( r"DROP\s+INDEX\s+IF\s+EXISTS", line, re.IGNORECASE ): @@ -266,8 +318,8 @@ class TestMigrationSQLIdempotency: def test_create_index_uses_if_not_exists(self, all_migrations): """CREATE INDEX statements must use IF NOT EXISTS""" violations = [] - for migration_name, sql in all_migrations: - for line_num, line in enumerate(sql.splitlines(), 1): + for migration_name, sql in _guarded_migrations(all_migrations): + for line_num, line in _statements(sql): if re.search( r"CREATE\s+(?:UNIQUE\s+)?INDEX\s+", line, re.IGNORECASE ) and not re.search( @@ -284,10 +336,9 @@ class TestMigrationSQLIdempotency: def test_rename_column_is_guarded(self, all_migrations): """RENAME COLUMN must be inside a DO $$ IF EXISTS block""" violations = [] - for migration_name, sql in all_migrations: - lines = sql.splitlines() + for migration_name, sql in _guarded_migrations(all_migrations): in_do_block = False - for line_num, line in enumerate(lines, 1): + for line_num, line in _statements(sql): if re.search(r"DO\s+\$\$", line, re.IGNORECASE): in_do_block = True if re.search(r"END\s+\$\$", line, re.IGNORECASE): @@ -305,10 +356,9 @@ class TestMigrationSQLIdempotency: def test_add_constraint_is_guarded(self, all_migrations): """ADD CONSTRAINT must be inside a DO $$ IF NOT EXISTS block""" violations = [] - for migration_name, sql in all_migrations: - lines = sql.splitlines() + for migration_name, sql in _guarded_migrations(all_migrations): in_do_block = False - for line_num, line in enumerate(lines, 1): + for line_num, line in _statements(sql): if re.search(r"DO\s+\$\$", line, re.IGNORECASE): in_do_block = True if re.search(r"END\s+\$\$", line, re.IGNORECASE): @@ -326,10 +376,9 @@ class TestMigrationSQLIdempotency: def test_drop_constraint_is_guarded(self, all_migrations): """DROP CONSTRAINT must be inside a DO $$ IF EXISTS block""" violations = [] - for migration_name, sql in all_migrations: - lines = sql.splitlines() + for migration_name, sql in _guarded_migrations(all_migrations): in_do_block = False - for line_num, line in enumerate(lines, 1): + for line_num, line in _statements(sql): if re.search(r"DO\s+\$\$", line, re.IGNORECASE): in_do_block = True if re.search(r"END\s+\$\$", line, re.IGNORECASE): @@ -343,3 +392,86 @@ class TestMigrationSQLIdempotency: "DROP CONSTRAINT without DO $$ IF EXISTS guard found in migrations:\n" + "\n".join(violations) ) + + +class TestMigrationGuardScope: + """The guard must ignore SQL comments, exempt only the named pre-guard migrations, + and still fail on a new migration that uses bare DDL.""" + + _NEW = "20990101000000_a_new_migration" + + def _run_rules(self, migrations): + suite = TestMigrationSQLIdempotency() + failures = [] + for name in ( + "test_create_table_uses_if_not_exists", + "test_add_column_uses_if_not_exists", + "test_create_index_uses_if_not_exists", + "test_add_constraint_is_guarded", + ): + try: + getattr(suite, name)(migrations) + except AssertionError: + failures.append(name) + return failures + + def test_a_comment_describing_ddl_is_not_the_ddl(self): + sql = '-- CREATE TABLE "Foo" (id TEXT);\n-- ADD COLUMN "bar" TEXT;\n' + assert self._run_rules([(self._NEW, sql)]) == [] + + def test_a_prisma_warning_block_is_not_the_ddl_it_describes(self): + sql = ( + "/*\n" + " Warnings:\n" + "\n" + " - You are about to CREATE TABLE \"Foo\" and ADD COLUMN \"bar\".\n" + "\n" + "*/\n" + 'CREATE TABLE IF NOT EXISTS "Foo" (id TEXT);\n' + ) + assert self._run_rules([(self._NEW, sql)]) == [] + + def test_a_block_comment_does_not_shift_the_reported_line(self): + sql = "/* filler\nfiller */\n" + 'CREATE TABLE "Foo" (id TEXT);\n' + suite = TestMigrationSQLIdempotency() + with pytest.raises(AssertionError) as failure: + suite.test_create_table_uses_if_not_exists([(self._NEW, sql)]) + assert f"{self._NEW}:3:" in str(failure.value) + + def test_a_new_migration_with_bare_create_table_fails(self): + assert "test_create_table_uses_if_not_exists" in self._run_rules( + [(self._NEW, 'CREATE TABLE "Foo" (id TEXT);\n')] + ) + + def test_a_new_migration_with_bare_add_column_fails(self): + assert "test_add_column_uses_if_not_exists" in self._run_rules( + [(self._NEW, 'ALTER TABLE "Foo" ADD COLUMN "bar" TEXT;\n')] + ) + + def test_the_guarded_forms_pass(self): + sql = ( + 'CREATE TABLE IF NOT EXISTS "Foo" (id TEXT);\n' + 'ALTER TABLE "Foo" ADD COLUMN IF NOT EXISTS "bar" TEXT;\n' + 'CREATE INDEX IF NOT EXISTS "Foo_bar_idx" ON "Foo"("bar");\n' + ) + assert self._run_rules([(self._NEW, sql)]) == [] + + def test_a_pre_guard_migration_is_exempt_but_a_new_one_is_not(self): + bare = 'CREATE TABLE "Foo" (id TEXT);\n' + exempt = sorted(_PRE_GUARD_MIGRATIONS)[0] + assert self._run_rules([(exempt, bare)]) == [] + assert self._run_rules([(self._NEW, bare)]) != [] + + def test_every_pre_guard_migration_still_exists_on_disk(self): + present = {name for name, _ in _get_all_migrations()} + missing = _PRE_GUARD_MIGRATIONS - present + assert not missing, f"pre-guard entries naming no migration: {sorted(missing)}" + + def test_no_pre_guard_entry_is_already_clean(self): + by_name = dict(_get_all_migrations()) + redundant = [ + name + for name in sorted(_PRE_GUARD_MIGRATIONS) + if not self._run_rules([(TestMigrationGuardScope._NEW, by_name[name])]) + ] + assert not redundant, f"these no longer violate and should be removed: {redundant}" diff --git a/whitelisted_bedrock_models.txt b/whitelisted_bedrock_models.txt new file mode 100644 index 00000000000..7e20081988d --- /dev/null +++ b/whitelisted_bedrock_models.txt @@ -0,0 +1,219 @@ +ai21.j2-mid-v1 +ai21.j2-ultra-v1 +ai21.jamba-1-5-large-v1:0 +ai21.jamba-1-5-mini-v1:0 +ai21.jamba-instruct-v1:0 +twelvelabs.pegasus-1-2-v1:0 +us.twelvelabs.pegasus-1-2-v1:0 +eu.twelvelabs.pegasus-1-2-v1:0 +amazon.titan-text-express-v1 +amazon.titan-text-lite-v1 +amazon.titan-text-premier-v1:0 +anthropic.claude-3-5-haiku-20241022-v1:0 +anthropic.claude-3-5-sonnet-20240620-v1:0 +anthropic.claude-3-5-sonnet-20241022-v2:0 +anthropic.claude-3-7-sonnet-20240620-v1:0 +anthropic.claude-3-haiku-20240307-v1:0 +anthropic.claude-3-opus-20240229-v1:0 +anthropic.claude-3-sonnet-20240229-v1:0 +anthropic.claude-instant-v1 +anthropic.claude-mythos-preview +anthropic.claude-v1 +anthropic.claude-v2:1 +apac.anthropic.claude-3-5-sonnet-20240620-v1:0 +apac.anthropic.claude-3-5-sonnet-20241022-v2:0 +apac.anthropic.claude-3-haiku-20240307-v1:0 +apac.anthropic.claude-3-sonnet-20240229-v1:0 +bedrock/*/1-month-commitment/cohere.command-light-text-v14 +bedrock/*/1-month-commitment/cohere.command-text-v14 +bedrock/*/6-month-commitment/cohere.command-light-text-v14 +bedrock/*/6-month-commitment/cohere.command-text-v14 +bedrock/ap-northeast-1/1-month-commitment/anthropic.claude-instant-v1 +bedrock/ap-northeast-1/1-month-commitment/anthropic.claude-v1 +bedrock/ap-northeast-1/1-month-commitment/anthropic.claude-v2:1 +bedrock/ap-northeast-1/6-month-commitment/anthropic.claude-instant-v1 +bedrock/ap-northeast-1/6-month-commitment/anthropic.claude-v1 +bedrock/ap-northeast-1/6-month-commitment/anthropic.claude-v2:1 +bedrock/ap-northeast-1/anthropic.claude-instant-v1 +bedrock/ap-northeast-1/anthropic.claude-v1 +bedrock/ap-northeast-1/anthropic.claude-v2:1 +bedrock/ap-northeast-1/deepseek.v3.2 +bedrock/ap-northeast-1/minimax.minimax-m2.1 +bedrock/ap-northeast-1/minimax.minimax-m2.5 +bedrock/ap-northeast-1/moonshotai.kimi-k2-thinking +bedrock/ap-northeast-1/moonshotai.kimi-k2.5 +bedrock/ap-northeast-1/qwen.qwen3-coder-next +bedrock/moonshotai.kimi-k2-thinking +bedrock/moonshotai.kimi-k2.5 +bedrock/ap-south-1/meta.llama3-70b-instruct-v1:0 +bedrock/ap-south-1/meta.llama3-8b-instruct-v1:0 +bedrock/ap-south-1/deepseek.v3.2 +bedrock/ap-south-1/minimax.minimax-m2.1 +bedrock/ap-south-1/minimax.minimax-m2.5 +bedrock/ap-south-1/moonshotai.kimi-k2-thinking +bedrock/ap-south-1/moonshotai.kimi-k2.5 +bedrock/ap-south-1/qwen.qwen3-coder-next +bedrock/ap-southeast-2/minimax.minimax-m2.5 +bedrock/ap-southeast-3/deepseek.v3.2 +bedrock/ap-southeast-3/minimax.minimax-m2.1 +bedrock/ap-southeast-3/minimax.minimax-m2.5 +bedrock/ap-southeast-3/moonshotai.kimi-k2.5 +bedrock/ap-southeast-3/qwen.qwen3-coder-next +bedrock/ca-central-1/meta.llama3-70b-instruct-v1:0 +bedrock/ca-central-1/meta.llama3-8b-instruct-v1:0 +bedrock/eu-north-1/deepseek.v3.2 +bedrock/eu-north-1/minimax.minimax-m2.1 +bedrock/eu-north-1/minimax.minimax-m2.5 +bedrock/eu-north-1/moonshotai.kimi-k2.5 +bedrock/eu-central-1/1-month-commitment/anthropic.claude-instant-v1 +bedrock/eu-central-1/1-month-commitment/anthropic.claude-v1 +bedrock/eu-central-1/1-month-commitment/anthropic.claude-v2:1 +bedrock/eu-central-1/6-month-commitment/anthropic.claude-instant-v1 +bedrock/eu-central-1/6-month-commitment/anthropic.claude-v1 +bedrock/eu-central-1/6-month-commitment/anthropic.claude-v2:1 +bedrock/eu-central-1/anthropic.claude-instant-v1 +bedrock/eu-central-1/anthropic.claude-v1 +bedrock/eu-central-1/anthropic.claude-v2:1 +bedrock/eu-central-1/minimax.minimax-m2.1 +bedrock/eu-central-1/minimax.minimax-m2.5 +bedrock/eu-central-1/qwen.qwen3-coder-next +bedrock/eu-west-1/meta.llama3-70b-instruct-v1:0 +bedrock/eu-west-1/meta.llama3-8b-instruct-v1:0 +bedrock/eu-west-1/minimax.minimax-m2.1 +bedrock/eu-west-1/minimax.minimax-m2.5 +bedrock/eu-west-1/qwen.qwen3-coder-next +bedrock/eu-west-2/meta.llama3-70b-instruct-v1:0 +bedrock/eu-west-2/meta.llama3-8b-instruct-v1:0 +bedrock/eu-west-2/minimax.minimax-m2.1 +bedrock/eu-west-2/minimax.minimax-m2.5 +bedrock/eu-west-2/qwen.qwen3-coder-next +bedrock/eu-west-3/mistral.mistral-7b-instruct-v0:2 +bedrock/eu-west-3/mistral.mistral-large-2402-v1:0 +bedrock/eu-west-3/mistral.mixtral-8x7b-instruct-v0:1 +bedrock/eu-south-1/minimax.minimax-m2.1 +bedrock/eu-south-1/minimax.minimax-m2.5 +bedrock/eu-south-1/qwen.qwen3-coder-next +bedrock/invoke/anthropic.claude-3-5-sonnet-20240620-v1:0 +bedrock/sa-east-1/meta.llama3-70b-instruct-v1:0 +bedrock/sa-east-1/meta.llama3-8b-instruct-v1:0 +bedrock/sa-east-1/deepseek.v3.2 +bedrock/sa-east-1/minimax.minimax-m2.1 +bedrock/sa-east-1/minimax.minimax-m2.5 +bedrock/sa-east-1/moonshotai.kimi-k2-thinking +bedrock/sa-east-1/moonshotai.kimi-k2.5 +bedrock/sa-east-1/qwen.qwen3-coder-next +bedrock/us-east-1/1-month-commitment/anthropic.claude-instant-v1 +bedrock/us-east-1/1-month-commitment/anthropic.claude-v1 +bedrock/us-east-1/1-month-commitment/anthropic.claude-v2:1 +bedrock/us-east-1/6-month-commitment/anthropic.claude-instant-v1 +bedrock/us-east-1/6-month-commitment/anthropic.claude-v1 +bedrock/us-east-1/6-month-commitment/anthropic.claude-v2:1 +bedrock/us-east-1/anthropic.claude-instant-v1 +bedrock/us-east-1/anthropic.claude-v1 +bedrock/us-east-1/anthropic.claude-v2:1 +bedrock/us-east-1/meta.llama3-70b-instruct-v1:0 +bedrock/us-east-1/meta.llama3-8b-instruct-v1:0 +bedrock/us-east-1/mistral.mistral-7b-instruct-v0:2 +bedrock/us-east-1/mistral.mistral-large-2402-v1:0 +bedrock/us-east-1/mistral.mixtral-8x7b-instruct-v0:1 +bedrock/us-east-1/deepseek.v3.2 +bedrock/us-east-1/minimax.minimax-m2.1 +bedrock/us-east-1/minimax.minimax-m2.5 +bedrock/us-east-1/moonshotai.kimi-k2-thinking +bedrock/us-east-1/moonshotai.kimi-k2.5 +bedrock/us-east-1/qwen.qwen3-coder-next +bedrock/us-east-2/deepseek.v3.2 +bedrock/us-east-2/minimax.minimax-m2.1 +bedrock/us-east-2/minimax.minimax-m2.5 +bedrock/us-east-2/moonshotai.kimi-k2-thinking +bedrock/us-east-2/moonshotai.kimi-k2.5 +bedrock/us-east-2/qwen.qwen3-coder-next +bedrock/us-gov-east-1/amazon.nova-pro-v1:0 +bedrock/us-gov-east-1/amazon.titan-text-express-v1 +bedrock/us-gov-east-1/amazon.titan-text-lite-v1 +bedrock/us-gov-east-1/amazon.titan-text-premier-v1:0 +bedrock/us-gov-east-1/anthropic.claude-3-5-sonnet-20240620-v1:0 +bedrock/us-gov-east-1/anthropic.claude-3-haiku-20240307-v1:0 +bedrock/us-gov-east-1/anthropic.claude-sonnet-4-5-20250929-v1:0 +bedrock/us-gov-east-1/claude-sonnet-4-5-20250929-v1:0 +bedrock/us-gov-east-1/meta.llama3-70b-instruct-v1:0 +bedrock/us-gov-east-1/meta.llama3-8b-instruct-v1:0 +bedrock/us-gov-west-1/amazon.nova-pro-v1:0 +bedrock/us-gov-west-1/amazon.titan-text-express-v1 +bedrock/us-gov-west-1/amazon.titan-text-lite-v1 +bedrock/us-gov-west-1/amazon.titan-text-premier-v1:0 +bedrock/us-gov-west-1/anthropic.claude-3-7-sonnet-20250219-v1:0 +bedrock/us-gov-west-1/anthropic.claude-3-5-sonnet-20240620-v1:0 +bedrock/us-gov-west-1/anthropic.claude-3-haiku-20240307-v1:0 +bedrock/us-gov-west-1/anthropic.claude-sonnet-4-5-20250929-v1:0 +bedrock/us-gov-west-1/claude-sonnet-4-5-20250929-v1:0 +bedrock/us-gov-west-1/meta.llama3-70b-instruct-v1:0 +bedrock/us-gov-west-1/meta.llama3-8b-instruct-v1:0 +bedrock/us-west-1/meta.llama3-70b-instruct-v1:0 +bedrock/us-west-1/meta.llama3-8b-instruct-v1:0 +bedrock/us-west-2/1-month-commitment/anthropic.claude-instant-v1 +bedrock/us-west-2/1-month-commitment/anthropic.claude-v1 +bedrock/us-west-2/1-month-commitment/anthropic.claude-v2:1 +bedrock/us-west-2/6-month-commitment/anthropic.claude-instant-v1 +bedrock/us-west-2/6-month-commitment/anthropic.claude-v1 +bedrock/us-west-2/6-month-commitment/anthropic.claude-v2:1 +bedrock/us-west-2/anthropic.claude-instant-v1 +bedrock/us-west-2/anthropic.claude-v1 +bedrock/us-west-2/anthropic.claude-v2:1 +bedrock/us-west-2/mistral.mistral-7b-instruct-v0:2 +bedrock/us-west-2/mistral.mistral-large-2402-v1:0 +bedrock/us-west-2/mistral.mixtral-8x7b-instruct-v0:1 +bedrock/us-west-2/deepseek.v3.2 +bedrock/us-west-2/minimax.minimax-m2.1 +bedrock/us-west-2/minimax.minimax-m2.5 +bedrock/us-west-2/moonshotai.kimi-k2-thinking +bedrock/us-west-2/moonshotai.kimi-k2.5 +bedrock/us-west-2/qwen.qwen3-coder-next +bedrock/us.anthropic.claude-3-5-haiku-20241022-v1:0 +claude-sonnet-4-5-20250929-v1:0 +cohere.command-light-text-v14 +cohere.command-r-plus-v1:0 +cohere.command-r-v1:0 +cohere.command-text-v14 +eu.anthropic.claude-3-5-haiku-20241022-v1:0 +eu.anthropic.claude-3-5-sonnet-20240620-v1:0 +eu.anthropic.claude-3-5-sonnet-20241022-v2:0 +eu.anthropic.claude-3-7-sonnet-20250219-v1:0 +eu.anthropic.claude-3-haiku-20240307-v1:0 +eu.anthropic.claude-3-opus-20240229-v1:0 +eu.anthropic.claude-3-sonnet-20240229-v1:0 +eu.meta.llama3-2-1b-instruct-v1:0 +eu.meta.llama3-2-3b-instruct-v1:0 +meta.llama2-13b-chat-v1 +meta.llama2-70b-chat-v1 +meta.llama3-1-405b-instruct-v1:0 +meta.llama3-1-70b-instruct-v1:0 +meta.llama3-1-8b-instruct-v1:0 +meta.llama3-2-11b-instruct-v1:0 +meta.llama3-2-1b-instruct-v1:0 +meta.llama3-2-3b-instruct-v1:0 +meta.llama3-2-90b-instruct-v1:0 +meta.llama3-70b-instruct-v1:0 +meta.llama3-8b-instruct-v1:0 +mistral.mistral-7b-instruct-v0:2 +mistral.mistral-large-2402-v1:0 +mistral.mistral-large-2407-v1:0 +mistral.mistral-small-2402-v1:0 +mistral.mixtral-8x7b-instruct-v0:1 +us.anthropic.claude-3-5-haiku-20241022-v1:0 +us.anthropic.claude-3-5-sonnet-20240620-v1:0 +us.anthropic.claude-3-5-sonnet-20241022-v2:0 +us.anthropic.claude-3-haiku-20240307-v1:0 +us.anthropic.claude-3-opus-20240229-v1:0 +us.anthropic.claude-3-sonnet-20240229-v1:0 +us.meta.llama3-1-405b-instruct-v1:0 +us.meta.llama3-1-70b-instruct-v1:0 +us.meta.llama3-1-8b-instruct-v1:0 +us.meta.llama3-2-11b-instruct-v1:0 +us.meta.llama3-2-1b-instruct-v1:0 +us.meta.llama3-2-3b-instruct-v1:0 +us.meta.llama3-2-90b-instruct-v1:0 +bedrock/us-east-1/zai.glm-5 +bedrock/us-west-2/zai.glm-5 +bedrock/us-gov-east-1/anthropic.claude-haiku-4-5-20251001-v1:0 +bedrock/us-gov-west-1/anthropic.claude-haiku-4-5-20251001-v1:0