Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions scripts/run_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,26 @@ def arguments():
default="gpt-5-nano",
help="Model allowed by the OpenAI MPS selected in the configure CUJ.",
)
parser.add_argument(
"--codex-azure-provider",
default="main.ucode.ci_azure_openai_mps",
help="Existing Azure OpenAI MPS (reasoning-capable model) for the Codex azure_openai CUJ.",
)
parser.add_argument(
"--codex-azure-provider-model",
default="gpt-5-nano",
help="Reasoning-capable model allowed by the Azure OpenAI MPS.",
)
parser.add_argument(
"--codex-foundry-provider",
default="main.ucode.ci_foundry_mps",
help="Existing Microsoft Foundry MPS (reasoning-capable model) for the Codex foundry CUJ.",
)
parser.add_argument(
"--codex-foundry-provider-model",
default="gpt-5-nano",
help="Reasoning-capable model allowed by the Microsoft Foundry MPS.",
)
parser.add_argument(
"--parent-schema",
default="main.ucode",
Expand Down Expand Up @@ -355,6 +375,10 @@ def run(command, *, cwd=output, env=base_env, timeout=600) -> str:
"claude_bedrock_allow_all_model": args.claude_bedrock_allow_all_model,
"codex_provider": args.codex_provider,
"codex_provider_model": args.codex_provider_model,
"codex_azure_provider": args.codex_azure_provider,
"codex_azure_provider_model": args.codex_azure_provider_model,
"codex_foundry_provider": args.codex_foundry_provider,
"codex_foundry_provider_model": args.codex_foundry_provider_model,
"parent_schema": args.parent_schema,
"claude_parent_model": args.claude_parent_model,
"codex_parent_model": args.codex_parent_model,
Expand Down Expand Up @@ -611,6 +635,10 @@ def run(command, *, cwd=output, env=base_env, timeout=600) -> str:
"UG_INTEGRATION_CLAUDE_BEDROCK_ALLOW_ALL_MODEL": args.claude_bedrock_allow_all_model,
"UG_INTEGRATION_CODEX_PROVIDER": args.codex_provider,
"UG_INTEGRATION_CODEX_PROVIDER_MODEL": args.codex_provider_model,
"UG_INTEGRATION_CODEX_AZURE_PROVIDER": args.codex_azure_provider,
"UG_INTEGRATION_CODEX_AZURE_PROVIDER_MODEL": args.codex_azure_provider_model,
"UG_INTEGRATION_CODEX_FOUNDRY_PROVIDER": args.codex_foundry_provider,
"UG_INTEGRATION_CODEX_FOUNDRY_PROVIDER_MODEL": args.codex_foundry_provider_model,
"UG_INTEGRATION_PARENT_SCHEMA": args.parent_schema,
"UG_INTEGRATION_CLAUDE_PARENT_MODEL": args.claude_parent_model,
"UG_INTEGRATION_CODEX_PARENT_MODEL": args.codex_parent_model,
Expand Down
20 changes: 20 additions & 0 deletions tests/integration/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,26 @@ def codex_provider_model():
return os.environ["UG_INTEGRATION_CODEX_PROVIDER_MODEL"]


@pytest.fixture(scope="session")
def codex_azure_provider():
return os.environ["UG_INTEGRATION_CODEX_AZURE_PROVIDER"]


@pytest.fixture(scope="session")
def codex_azure_provider_model():
return os.environ["UG_INTEGRATION_CODEX_AZURE_PROVIDER_MODEL"]


@pytest.fixture(scope="session")
def codex_foundry_provider():
return os.environ["UG_INTEGRATION_CODEX_FOUNDRY_PROVIDER"]


@pytest.fixture(scope="session")
def codex_foundry_provider_model():
return os.environ["UG_INTEGRATION_CODEX_FOUNDRY_PROVIDER_MODEL"]


@pytest.fixture(scope="session")
def parent_schema():
return os.environ["UG_INTEGRATION_PARENT_SCHEMA"]
Expand Down
64 changes: 64 additions & 0 deletions tests/integration/test_ug_configure_codex.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,67 @@ def test_ug_configure_codex_openai_mps(
tui.exit_normally()
task.assert_completed(session, "codex")
session.assert_not_routed()


def _run_codex_openai_dialect_mps_cuj(session, workspace, provider, model, label):
"""Configure Codex through an OpenAI-dialect MPS, then complete a task on one of its models.

Azure OpenAI and Microsoft Foundry both speak the OpenAI dialect the gateway fronts for Codex,
so the CUJ is identical apart from which MPS the picker selects. Codex always sends
`reasoning.effort`, so a completed task also proves two things a plain routing check would miss:
the provider-type allowlist accepts the MPS's type for Codex, and the backing deployment is
reasoning-capable (a non-reasoning model 400s the request's `reasoning.effort`).
"""
task = FileTask(session)

command = [
str(session.binary),
"configure",
"--workspace",
workspace,
"--skip-upgrade",
"--disable-databricks-ai-tools",
]
with ConfigureTerminal(session, "codex", command, f"configure-{label}-provider") as configure:
configure.select_agent("Codex")
configure.choose("How should Codex get its models?", "External Models")
configure.choose("Select a model provider service:", provider)
configure.finish(timeout=240)
assert session.workspace_state()["provider_services"]["codex"] == provider
assert provider in session.run("status").stdout

command = [str(session.binary), "codex", "--", "--model", model]
with AgentTerminal(session, "codex", command, f"{label}-provider-session") as tui:
tui.boot()
tui.submit(task.prompt)
tui.wait_for_task(task, timeout=300)
tui.exit_normally()
task.assert_completed(session, "codex")
session.assert_not_routed()


def test_ug_configure_codex_azure_openai_mps(
live_session, workspace, codex_azure_provider, codex_azure_provider_model
):
"""Scenario: select an Azure OpenAI (`azure_openai`) MPS in ug configure's picker for Codex.

Expected: ug saves the provider and a real Codex session completes a file task on one of its
reasoning-capable models (see _run_codex_openai_dialect_mps_cuj).
"""
_run_codex_openai_dialect_mps_cuj(
live_session, workspace, codex_azure_provider, codex_azure_provider_model, "azure"
)


def test_ug_configure_codex_foundry_mps(
live_session, workspace, codex_foundry_provider, codex_foundry_provider_model
):
"""Scenario: select a Microsoft Foundry (`microsoft_foundry`) MPS in ug configure's picker.

Expected: ug saves the provider and a real Codex session completes a file task, exercising the
`microsoft_foundry` allowlist entry for Codex. Foundry speaks the same OpenAI dialect as Azure
OpenAI, so this reuses the Azure CUJ (see _run_codex_openai_dialect_mps_cuj).
"""
_run_codex_openai_dialect_mps_cuj(
live_session, workspace, codex_foundry_provider, codex_foundry_provider_model, "foundry"
)
Loading