diff --git a/frontend/snapshots.yml b/frontend/snapshots.yml index 37e3ea912c44..5e31971962e4 100644 --- a/frontend/snapshots.yml +++ b/frontend/snapshots.yml @@ -5395,13 +5395,13 @@ snapshots: scenes-app-customer-analytics-dashboard--b-2-c-mode--light: hash: v1.k794b7964.ff25e11868464e00df352180254dbe0a1017cd1d8c7c4f4c7d6995068e80e2dc.m0XFOZVPCdSaCLaPQ6XTePvkZJ1I11QI2KARZi9QpWs scenes-app-customer-analytics-dashboard--gated-with-feature-toggle--dark: - hash: v1.k794b7964.f07be6c5a9a602a1b2de2e07ff8329cf79022a86359c8592ec0ffa997e06815e.4p0ObyV8dflPFp4eV8-iGtIyPw-H4rNRImtZ98MUaq0 + hash: v1.k794b7964.731394bccab76141d6dc494f99dd56cc85e18b3f787977f8edd5c1a50c5564c8.9z2bNOo-dAM0tEyxcqStccQSV7X6iHbKnJdqAgvNapU scenes-app-customer-analytics-dashboard--gated-with-feature-toggle--light: - hash: v1.k794b7964.c08ac439ce99c1885784bb01585643983c42e334ee9b66dc4fdca3a200f49aa8.1nfQJfx8u9E46SodXwq0FKkEXnMgRERGpZ3LrS7lsgk + hash: v1.k794b7964.d4a3f7e666d9788b86e4e35e6e976dc048f50189129b316352f60e389916e740.XNraHFrJz2oo-ioKjtSG3b53aSd7SUozc4GkGnRUVPw scenes-app-customer-analytics-dashboard--gated-without-matching-early-access-feature--dark: - hash: v1.k794b7964.df78ad055d2df40bd8f7291c6be67f5186e055f66f8d642e54f4493bfea8dee4.ZN0UYUnaFqZlJQb_8eCa8a74QdPPt4v9VBEQNfMT5Dw + hash: v1.k794b7964.212105add8f003ebda9493c4f1324aa86a9ea9d4f078a9202f746125bc188ee0.mcCJ4cjTJAjHr9-eqJV3Vki9l2-kPcGcbCkwbnXGGNI scenes-app-customer-analytics-dashboard--gated-without-matching-early-access-feature--light: - hash: v1.k794b7964.261496c85d5d04af3eb5e766063ec3e1783ea9ba2d54f82bb9c7d4b0f1cc28a0.5Gacg7ZDoAp-d35eiCG9-Jp2vYDw-4uvGAJsL5U4uiI + hash: v1.k794b7964.c17e8855ba266d7d7732b79d59cbe6996e34469b95aaf820146a2ec098d4c1cd.xHHIXeNzT7uaxywPDDglLPD96SXg9n66LgqmXi677J0 scenes-app-customer-analytics-journey-builder--new-journey--dark: hash: v1.k794b7964.5e2f6c51e7e4db5d5d8bed07edeb90f8e71b6dbe9e4aa7042ce9337e407ff3bb.qbiM7NeFkMfNbY374tsbc_nZloshk9lmHLFgIPx5-ow scenes-app-customer-analytics-journey-builder--new-journey--light: diff --git a/products/posthog_ai/frontend/utils/composerModels.ts b/products/posthog_ai/frontend/utils/composerModels.ts index b1a039e558cd..1e31d6094e21 100644 --- a/products/posthog_ai/frontend/utils/composerModels.ts +++ b/products/posthog_ai/frontend/utils/composerModels.ts @@ -27,6 +27,7 @@ const EFFORT_LABELS: Record = { [ReasoningEffortEnumApi.High]: 'High', [ReasoningEffortEnumApi.Xhigh]: 'Extra high', [ReasoningEffortEnumApi.Max]: 'Max', + [ReasoningEffortEnumApi.Ultracode]: 'Ultracode', } // Mirrors backend CLAUDE_REASONING_EFFORTS_BY_MODEL (products/tasks/backend/temporal/process_task/utils.py): @@ -38,6 +39,7 @@ const EFFORTS_BY_MODEL: Record = { ReasoningEffortEnumApi.High, ReasoningEffortEnumApi.Xhigh, ReasoningEffortEnumApi.Max, + ReasoningEffortEnumApi.Ultracode, ], 'claude-opus-5': [ ReasoningEffortEnumApi.Low, @@ -45,8 +47,16 @@ const EFFORTS_BY_MODEL: Record = { ReasoningEffortEnumApi.High, ReasoningEffortEnumApi.Xhigh, ReasoningEffortEnumApi.Max, + ReasoningEffortEnumApi.Ultracode, + ], + 'claude-sonnet-5': [ + ReasoningEffortEnumApi.Low, + ReasoningEffortEnumApi.Medium, + ReasoningEffortEnumApi.High, + ReasoningEffortEnumApi.Xhigh, + ReasoningEffortEnumApi.Max, + ReasoningEffortEnumApi.Ultracode, ], - 'claude-sonnet-5': [ReasoningEffortEnumApi.Low, ReasoningEffortEnumApi.Medium, ReasoningEffortEnumApi.High], } const FALLBACK_EFFORTS: ReasoningEffortEnumApi[] = [ diff --git a/products/tasks/backend/facade/api.py b/products/tasks/backend/facade/api.py index b17fcdb525d2..a7199e03d551 100644 --- a/products/tasks/backend/facade/api.py +++ b/products/tasks/backend/facade/api.py @@ -3086,6 +3086,8 @@ def bootstrap_task_run( runtime_adapter = validated_data.get("runtime_adapter") model = validated_data.get("model") reasoning_effort = validated_data.get("reasoning_effort") + context_window = validated_data.get("context_window") + fast_mode = validated_data.get("fast_mode") github_user_token = validated_data.get("github_user_token") initial_permission_mode = validated_data.get("initial_permission_mode") imported_mcp_servers = validated_data.get("imported_mcp_servers") @@ -3108,6 +3110,8 @@ def bootstrap_task_run( "provider": provider, "model": model, "reasoning_effort": reasoning_effort, + "context_window": context_window, + "fast_mode": fast_mode, "rtk_enabled": validated_data.get("rtk_enabled"), }.items(): if value is not None: @@ -4399,12 +4403,16 @@ def run_task( warm_state.get("runtime_adapter") or None, warm_state.get("model") or None, warm_state.get("reasoning_effort") or None, + warm_state.get("context_window") or None, + warm_state.get("fast_mode") or None, warm_state.get("sandbox_environment_id") or None, warm_state.get("custom_image_id") or None, ) == ( validated_data.get("runtime_adapter") or None, validated_data.get("model") or None, validated_data.get("reasoning_effort") or None, + validated_data.get("context_window") or None, + validated_data.get("fast_mode") or None, str(validated_data["sandbox_environment_id"]) if validated_data.get("sandbox_environment_id") else None, str(validated_data["custom_image_id"]) if validated_data.get("custom_image_id") else None, ) @@ -4448,6 +4456,8 @@ def run_task( runtime_adapter = validated_data.get("runtime_adapter") model = validated_data.get("model") reasoning_effort = validated_data.get("reasoning_effort") + context_window = validated_data.get("context_window") + fast_mode = validated_data.get("fast_mode") github_user_token = validated_data.get("github_user_token") initial_permission_mode = validated_data.get("initial_permission_mode") imported_mcp_servers = validated_data.get("imported_mcp_servers") @@ -4463,6 +4473,8 @@ def run_task( "runtime_adapter": runtime_adapter, "model": model, "reasoning_effort": reasoning_effort, + "context_window": context_window, + "fast_mode": fast_mode, } extra_state: dict | None = None @@ -4521,6 +4533,8 @@ def run_task( runtime_adapter = runtime_state_fields["runtime_adapter"] model = runtime_state_fields["model"] reasoning_effort = runtime_state_fields["reasoning_effort"] + context_window = runtime_state_fields["context_window"] + fast_mode = runtime_state_fields["fast_mode"] if branch is None and prev_state.pr_base_branch is not None: branch = prev_state.pr_base_branch @@ -4536,6 +4550,8 @@ def run_task( "provider": provider, "model": model, "reasoning_effort": reasoning_effort, + "context_window": context_window, + "fast_mode": fast_mode, }.items(): if value is not None: extra_state = extra_state or {} diff --git a/products/tasks/backend/facade/run_config.py b/products/tasks/backend/facade/run_config.py index 3d70641ea5a1..c1af3db7cb15 100644 --- a/products/tasks/backend/facade/run_config.py +++ b/products/tasks/backend/facade/run_config.py @@ -21,6 +21,7 @@ # so presentation builds serializer choices without importing the ORM model directly. from products.tasks.backend.models import TaskArtifact as _TaskArtifact from products.tasks.backend.temporal.process_task.utils import ( + CONTEXT_WINDOW_CHOICES, PUBLIC_REASONING_EFFORTS, GitHubCredentialSource, LLMProvider, @@ -44,6 +45,7 @@ __all__ = [ "ALL_INITIAL_PERMISSION_MODE_CHOICES", "CODEX_INITIAL_PERMISSION_MODE_CHOICES", + "CONTEXT_WINDOW_CHOICES", "INITIAL_PERMISSION_MODE_CHOICES", "InitialPermissionMode", "PUBLIC_REASONING_EFFORTS", diff --git a/products/tasks/backend/logic/services/docker_sandbox.py b/products/tasks/backend/logic/services/docker_sandbox.py index 3fe76eac06e8..d782e55ce551 100644 --- a/products/tasks/backend/logic/services/docker_sandbox.py +++ b/products/tasks/backend/logic/services/docker_sandbox.py @@ -794,6 +794,8 @@ def _build_agent_server_command( provider: str | None = None, model: str | None = None, reasoning_effort: str | None = None, + context_window: str | None = None, + fast_mode: bool | None = None, initial_permission_mode: str | None = None, mcp_servers_arg: str = "", relay_mcp_servers_arg: str = "", @@ -815,6 +817,8 @@ def _build_agent_server_command( provider=provider, model=model, reasoning_effort=reasoning_effort, + context_window=context_window, + fast_mode=fast_mode, initial_permission_mode=initial_permission_mode, event_ingest_token=event_ingest_token, event_ingest_url=event_ingest_url, @@ -899,6 +903,8 @@ def start_agent_server( provider: str | None = None, model: str | None = None, reasoning_effort: str | None = None, + context_window: str | None = None, + fast_mode: bool | None = None, initial_permission_mode: str | None = None, mcp_configs: list[McpServerConfig] | None = None, relayed_mcp_servers: list[str] | None = None, @@ -970,9 +976,11 @@ def start_agent_server( provider, model, reasoning_effort, - initial_permission_mode, - mcp_servers_arg, - relay_mcp_servers_arg, + context_window=context_window, + fast_mode=fast_mode, + initial_permission_mode=initial_permission_mode, + mcp_servers_arg=mcp_servers_arg, + relay_mcp_servers_arg=relay_mcp_servers_arg, allowed_domains=allowed_domains, event_ingest_token=event_ingest_token, event_ingest_url=event_ingest_url, @@ -1021,6 +1029,8 @@ def start_agent_server( provider=provider, model=model, reasoning_effort=reasoning_effort, + context_window=context_window, + fast_mode=fast_mode, initial_permission_mode=initial_permission_mode, mcp_servers_arg=mcp_servers_arg, relay_mcp_servers_arg=relay_mcp_servers_arg, diff --git a/products/tasks/backend/logic/services/modal_sandbox.py b/products/tasks/backend/logic/services/modal_sandbox.py index 9ef32c2b8674..69ca7cfdaf7b 100644 --- a/products/tasks/backend/logic/services/modal_sandbox.py +++ b/products/tasks/backend/logic/services/modal_sandbox.py @@ -949,6 +949,8 @@ def _build_agent_server_command( provider: str | None = None, model: str | None = None, reasoning_effort: str | None = None, + context_window: str | None = None, + fast_mode: bool | None = None, initial_permission_mode: str | None = None, mcp_servers_arg: str = "", relay_mcp_servers_arg: str = "", @@ -966,6 +968,8 @@ def _build_agent_server_command( provider=provider, model=model, reasoning_effort=reasoning_effort, + context_window=context_window, + fast_mode=fast_mode, initial_permission_mode=initial_permission_mode, event_ingest_token=event_ingest_token, event_ingest_url=event_ingest_url, @@ -1076,6 +1080,8 @@ def start_agent_server( provider: str | None = None, model: str | None = None, reasoning_effort: str | None = None, + context_window: str | None = None, + fast_mode: bool | None = None, initial_permission_mode: str | None = None, mcp_configs: list[McpServerConfig] | None = None, relayed_mcp_servers: list[str] | None = None, @@ -1150,9 +1156,11 @@ def start_agent_server( provider, model, reasoning_effort, - initial_permission_mode, - mcp_servers_arg, - relay_mcp_servers_arg, + context_window=context_window, + fast_mode=fast_mode, + initial_permission_mode=initial_permission_mode, + mcp_servers_arg=mcp_servers_arg, + relay_mcp_servers_arg=relay_mcp_servers_arg, allowed_domains=allowed_domains, event_ingest_token=event_ingest_token, event_ingest_url=event_ingest_url, diff --git a/products/tasks/backend/logic/services/sandbox.py b/products/tasks/backend/logic/services/sandbox.py index 7503f439e97f..2dbd31c63da6 100644 --- a/products/tasks/backend/logic/services/sandbox.py +++ b/products/tasks/backend/logic/services/sandbox.py @@ -171,6 +171,8 @@ def build_agent_runtime_env_prefix( provider: str | None = None, model: str | None = None, reasoning_effort: str | None = None, + context_window: str | None = None, + fast_mode: bool | None = None, initial_permission_mode: str | None = None, event_ingest_token: str | None = None, event_ingest_url: str | None = None, @@ -183,6 +185,9 @@ def build_agent_runtime_env_prefix( "POSTHOG_CODE_PROVIDER": provider, "POSTHOG_CODE_MODEL": model, "POSTHOG_CODE_REASONING_EFFORT": reasoning_effort, + "POSTHOG_CODE_CONTEXT_WINDOW": context_window, + # Explicit false pins fast mode off even if a stale env value survives in a resumed sandbox. + "POSTHOG_CODE_FAST_MODE": None if fast_mode is None else ("true" if fast_mode else "false"), "POSTHOG_CODE_INITIAL_PERMISSION_MODE": initial_permission_mode, "POSTHOG_TASK_RUN_EVENT_INGEST_TOKEN": event_ingest_token, "POSTHOG_TASK_RUN_EVENT_INGEST_URL": event_ingest_url, @@ -333,6 +338,8 @@ def start_agent_server( provider: str | None = None, model: str | None = None, reasoning_effort: str | None = None, + context_window: str | None = None, + fast_mode: bool | None = None, initial_permission_mode: str | None = None, mcp_configs: list[McpServerConfig] | None = None, relayed_mcp_servers: list[str] | None = None, diff --git a/products/tasks/backend/logic/services/test_docker_sandbox.py b/products/tasks/backend/logic/services/test_docker_sandbox.py index a9c9eae4be08..6eac741cd9eb 100644 --- a/products/tasks/backend/logic/services/test_docker_sandbox.py +++ b/products/tasks/backend/logic/services/test_docker_sandbox.py @@ -590,6 +590,8 @@ def test_start_agent_server_includes_runtime_environment_variables(self): provider="openai", model="gpt-5.3-codex", reasoning_effort="medium", + context_window="1m", + fast_mode=True, initial_permission_mode="plan", event_ingest_token="ingest-token", event_ingest_url="http://localhost:8003", @@ -600,11 +602,44 @@ def test_start_agent_server_includes_runtime_environment_variables(self): assert "POSTHOG_CODE_PROVIDER=openai" in command assert "POSTHOG_CODE_MODEL=gpt-5.3-codex" in command assert "POSTHOG_CODE_REASONING_EFFORT=medium" in command + assert "POSTHOG_CODE_CONTEXT_WINDOW=1m" in command + assert "POSTHOG_CODE_FAST_MODE=true" in command assert "POSTHOG_CODE_INITIAL_PERMISSION_MODE=plan" in command assert "POSTHOG_TASK_RUN_EVENT_INGEST_TOKEN=ingest-token" in command # The host proxy URL is rewritten so it resolves from inside the container. assert "POSTHOG_TASK_RUN_EVENT_INGEST_URL=http://host.docker.internal:8003" in command + @pytest.mark.parametrize( + "fast_mode, expected_env", + [ + (False, "POSTHOG_CODE_FAST_MODE=false"), + (None, None), + ], + ) + def test_start_agent_server_fast_mode_env(self, fast_mode, expected_env): + sandbox = DockerSandbox.__new__(DockerSandbox) + sandbox._container_id = "abc123" + sandbox.id = "abc123" + sandbox.config = SandboxConfig(name="test") + sandbox._host_port = 12345 + + with patch.object(sandbox, "is_running", return_value=True): + with patch.object(sandbox, "execute") as mock_execute: + mock_execute.return_value = ExecutionResult(stdout="ok:1", stderr="", exit_code=0, error=None) + sandbox.start_agent_server( + "posthog/posthog", + "task-123", + "run-456", + "background", + fast_mode=fast_mode, + ) + + command = _agent_server_launch_command(mock_execute) + if expected_env is not None: + assert expected_env in command + else: + assert "POSTHOG_CODE_FAST_MODE" not in command + @pytest.mark.parametrize( "keep_stream_open, expected_env_present", [ diff --git a/products/tasks/backend/logic/services/tests/test_modal_sandbox.py b/products/tasks/backend/logic/services/tests/test_modal_sandbox.py index 898ae7340135..6dd6a863a370 100644 --- a/products/tasks/backend/logic/services/tests/test_modal_sandbox.py +++ b/products/tasks/backend/logic/services/tests/test_modal_sandbox.py @@ -549,6 +549,8 @@ def test_start_agent_server_includes_runtime_environment_variables(self, mock_sa provider="openai", model="gpt-5.3-codex", reasoning_effort="high", + context_window="1m", + fast_mode=True, initial_permission_mode="plan", event_ingest_token="ingest-token", event_ingest_url="https://agent-proxy.example.com", @@ -559,12 +561,40 @@ def test_start_agent_server_includes_runtime_environment_variables(self, mock_sa assert "POSTHOG_CODE_PROVIDER=openai" in command assert "POSTHOG_CODE_MODEL=gpt-5.3-codex" in command assert "POSTHOG_CODE_REASONING_EFFORT=high" in command + assert "POSTHOG_CODE_CONTEXT_WINDOW=1m" in command + assert "POSTHOG_CODE_FAST_MODE=true" in command assert "POSTHOG_CODE_INITIAL_PERMISSION_MODE=plan" in command assert "POSTHOG_TASK_RUN_EVENT_INGEST_TOKEN=ingest-token" in command # Modal sandboxes reach the proxy by its real URL, no Docker-host rewrite. assert "POSTHOG_TASK_RUN_EVENT_INGEST_URL=https://agent-proxy.example.com" in command assert "POSTHOG_RTK=1" in command + @pytest.mark.parametrize( + "fast_mode, expected_env", + [ + (False, "POSTHOG_CODE_FAST_MODE=false"), + (None, None), + ], + ) + def test_start_agent_server_fast_mode_env(self, mock_sandbox: Any, fast_mode, expected_env): + mock_sandbox.execute = MagicMock( + return_value=ExecutionResult(stdout="ok:1", stderr="", exit_code=0, error=None), + ) + + mock_sandbox.start_agent_server( + repository="posthog/posthog", + task_id="task-123", + run_id="run-456", + mode="background", + fast_mode=fast_mode, + ) + + command = _agent_server_launch_command(mock_sandbox.execute) + if expected_env is not None: + assert expected_env in command + else: + assert "POSTHOG_CODE_FAST_MODE" not in command + @pytest.mark.parametrize( "rtk_enabled, expected_env", [ diff --git a/products/tasks/backend/presentation/serializers.py b/products/tasks/backend/presentation/serializers.py index 6a6aaca41a3f..2d8b56bfbc05 100644 --- a/products/tasks/backend/presentation/serializers.py +++ b/products/tasks/backend/presentation/serializers.py @@ -41,6 +41,7 @@ from products.tasks.backend.facade.run_config import ( ALL_INITIAL_PERMISSION_MODE_CHOICES, CODEX_INITIAL_PERMISSION_MODE_CHOICES, + CONTEXT_WINDOW_CHOICES, INITIAL_PERMISSION_MODE_CHOICES, PUBLIC_REASONING_EFFORTS, LLMProvider, @@ -1890,6 +1891,18 @@ class TaskRunCreateRequestSerializer(ImportedMcpServersFieldMixin, RelayedMcpSer default=None, help_text="Reasoning effort to request for models that expose an effort control.", ) + context_window = serializers.ChoiceField( + choices=CONTEXT_WINDOW_CHOICES, + required=False, + default=None, + help_text="Context window size for models that support the 1M window.", + ) + fast_mode = serializers.BooleanField( + required=False, + allow_null=True, + default=None, + help_text="Enable fast mode for models that support it.", + ) github_user_token = serializers.CharField( required=False, default=None, @@ -1953,7 +1966,10 @@ def validate(self, attrs): attrs.pop("pending_user_message", None) runtime_fields = ("runtime_adapter", "model") - has_runtime_selection = any(attrs.get(field) is not None for field in (*runtime_fields, "reasoning_effort")) + has_runtime_selection = any( + attrs.get(field) is not None + for field in (*runtime_fields, "reasoning_effort", "context_window", "fast_mode") + ) if not has_runtime_selection: if errors: @@ -2070,6 +2086,18 @@ class TaskRunBootstrapCreateRequestSerializer( default=None, help_text="Reasoning effort to request for models that expose an effort control.", ) + context_window = serializers.ChoiceField( + choices=CONTEXT_WINDOW_CHOICES, + required=False, + default=None, + help_text="Context window size for models that support the 1M window.", + ) + fast_mode = serializers.BooleanField( + required=False, + allow_null=True, + default=None, + help_text="Enable fast mode for models that support it.", + ) github_user_token = serializers.CharField( required=False, default=None, @@ -2121,7 +2149,10 @@ def validate(self, attrs): ) runtime_fields = ("runtime_adapter", "model") - has_runtime_selection = any(attrs.get(field) is not None for field in (*runtime_fields, "reasoning_effort")) + has_runtime_selection = any( + attrs.get(field) is not None + for field in (*runtime_fields, "reasoning_effort", "context_window", "fast_mode") + ) if not has_runtime_selection: if errors: raise serializers.ValidationError(errors) diff --git a/products/tasks/backend/temporal/process_task/activities/get_task_processing_context.py b/products/tasks/backend/temporal/process_task/activities/get_task_processing_context.py index d5da4c9457ad..e7e7f3210de2 100644 --- a/products/tasks/backend/temporal/process_task/activities/get_task_processing_context.py +++ b/products/tasks/backend/temporal/process_task/activities/get_task_processing_context.py @@ -158,6 +158,16 @@ def reasoning_effort(self) -> str | None: value = (self.state or {}).get("reasoning_effort") return value if isinstance(value, str) else None + @property + def context_window(self) -> str | None: + value = (self.state or {}).get("context_window") + return value if isinstance(value, str) else None + + @property + def fast_mode(self) -> bool | None: + value = (self.state or {}).get("fast_mode") + return value if isinstance(value, bool) else None + @property def initial_permission_mode(self) -> str | None: value = (self.state or {}).get("initial_permission_mode") diff --git a/products/tasks/backend/temporal/process_task/activities/start_agent_server.py b/products/tasks/backend/temporal/process_task/activities/start_agent_server.py index e2f86ba16cdf..cbd2be5df441 100644 --- a/products/tasks/backend/temporal/process_task/activities/start_agent_server.py +++ b/products/tasks/backend/temporal/process_task/activities/start_agent_server.py @@ -334,6 +334,8 @@ def _invoke_start_agent_server( provider=ctx.provider, model=ctx.model, reasoning_effort=ctx.reasoning_effort, + context_window=ctx.context_window, + fast_mode=ctx.fast_mode, initial_permission_mode=ctx.initial_permission_mode, mcp_configs=params.mcp_configs or None, relayed_mcp_servers=params.relayed_mcp_servers or None, diff --git a/products/tasks/backend/temporal/process_task/utils.py b/products/tasks/backend/temporal/process_task/utils.py index 4a17297762ac..bc880c99cd0b 100644 --- a/products/tasks/backend/temporal/process_task/utils.py +++ b/products/tasks/backend/temporal/process_task/utils.py @@ -81,6 +81,7 @@ class ReasoningEffort(StrEnum): HIGH = "high" XHIGH = "xhigh" MAX = "max" + ULTRACODE = "ultracode" PUBLIC_REASONING_EFFORTS: tuple[ReasoningEffort, ...] = ( @@ -89,9 +90,13 @@ class ReasoningEffort(StrEnum): ReasoningEffort.HIGH, ReasoningEffort.XHIGH, ReasoningEffort.MAX, + ReasoningEffort.ULTRACODE, ) +CONTEXT_WINDOW_CHOICES: tuple[str, ...] = ("200k", "1m") + + RUNTIME_PROVIDER_BY_ADAPTER: dict[RuntimeAdapter, LLMProvider] = { RuntimeAdapter.CLAUDE: LLMProvider.ANTHROPIC, RuntimeAdapter.CODEX: LLMProvider.OPENAI, @@ -124,6 +129,7 @@ class ReasoningEffort(StrEnum): ReasoningEffort.HIGH, ReasoningEffort.XHIGH, ReasoningEffort.MAX, + ReasoningEffort.ULTRACODE, ), "claude-opus-4-8": ( ReasoningEffort.LOW, @@ -131,6 +137,7 @@ class ReasoningEffort(StrEnum): ReasoningEffort.HIGH, ReasoningEffort.XHIGH, ReasoningEffort.MAX, + ReasoningEffort.ULTRACODE, ), "claude-opus-5": ( ReasoningEffort.LOW, @@ -138,6 +145,7 @@ class ReasoningEffort(StrEnum): ReasoningEffort.HIGH, ReasoningEffort.XHIGH, ReasoningEffort.MAX, + ReasoningEffort.ULTRACODE, ), "claude-fable-5": ( ReasoningEffort.LOW, @@ -145,6 +153,7 @@ class ReasoningEffort(StrEnum): ReasoningEffort.HIGH, ReasoningEffort.XHIGH, ReasoningEffort.MAX, + ReasoningEffort.ULTRACODE, ), "claude-sonnet-5": ( ReasoningEffort.LOW, @@ -152,6 +161,7 @@ class ReasoningEffort(StrEnum): ReasoningEffort.HIGH, ReasoningEffort.XHIGH, ReasoningEffort.MAX, + ReasoningEffort.ULTRACODE, ), "claude-sonnet-4-6": ( ReasoningEffort.LOW, @@ -308,6 +318,8 @@ class RunState(BaseModel, extra="allow"): provider: LLMProvider | None = None model: str | None = None reasoning_effort: ReasoningEffort | None = None + context_window: str | None = None + fast_mode: bool | None = None resume_from_run_id: str | None = None handoff_resumed: bool = False snapshot_external_id: str | None = None diff --git a/products/tasks/backend/tests/test_api.py b/products/tasks/backend/tests/test_api.py index fbf566c3204d..fb5fa4ab19ec 100644 --- a/products/tasks/backend/tests/test_api.py +++ b/products/tasks/backend/tests/test_api.py @@ -2557,6 +2557,52 @@ def test_run_endpoint_persists_runtime_metadata( assert latest_run["reasoning_effort"] == reasoning_effort mock_workflow.assert_called_once() + @patch("products.tasks.backend.temporal.client.execute_task_processing_workflow") + def test_run_endpoint_persists_context_window_and_fast_mode(self, mock_workflow): + task = self.create_task() + + response = self.client.post( + f"/api/projects/@current/tasks/{task.id}/run/", + { + "mode": "interactive", + "runtime_adapter": "claude", + "model": "claude-sonnet-5", + "context_window": "200k", + "fast_mode": False, + }, + format="json", + ) + + assert response.status_code == status.HTTP_200_OK + latest_run = response.json()["latest_run"] + task_run = TaskRun.objects.get(id=latest_run["id"]) + assert task_run.state["context_window"] == "200k" + assert task_run.state["fast_mode"] is False + mock_workflow.assert_called_once() + + @patch("products.tasks.backend.temporal.client.execute_task_processing_workflow") + def test_run_endpoint_rejects_unsupported_context_window(self, mock_workflow): + task = self.create_task() + + response = self.client.post( + f"/api/projects/@current/tasks/{task.id}/run/", + { + "runtime_adapter": "claude", + "model": "claude-sonnet-5", + "context_window": "500k", + }, + format="json", + ) + + assert response.status_code == status.HTTP_400_BAD_REQUEST + assert response.json() == { + "type": "validation_error", + "code": "invalid_choice", + "detail": '"500k" is not a valid choice.', + "attr": "context_window", + } + mock_workflow.assert_not_called() + @parameterized.expand([("plan",), ("auto",), ("read-only",), ("full-access",)]) @patch("products.tasks.backend.temporal.client.execute_task_processing_workflow") def test_run_endpoint_preserves_codex_initial_permission_mode(self, initial_permission_mode, mock_workflow): @@ -2874,6 +2920,7 @@ def test_run_endpoint_accepts_fable_reasoning_effort(self, reasoning_effort, moc ("high",), # xhigh is load-bearing: ReviewHog pins it for its one-shot and review runs. ("xhigh",), + ("ultracode",), ] ) @patch("products.tasks.backend.temporal.client.execute_task_processing_workflow") @@ -2899,13 +2946,21 @@ def test_run_endpoint_accepts_claude_sonnet_5_reasoning_effort(self, reasoning_e assert task_run.state["reasoning_effort"] == reasoning_effort mock_workflow.assert_called_once() + @parameterized.expand( + [ + ("xhigh",), + ("ultracode",), + ] + ) @patch("products.tasks.backend.presentation.serializers.posthoganalytics.capture") @patch("products.tasks.backend.temporal.client.execute_task_processing_workflow") - def test_run_endpoint_rejects_unsupported_claude_sonnet_4_6_reasoning_effort(self, mock_workflow, mock_capture): - # claude-sonnet-4-6 supports low/medium/high but not xhigh (claude-sonnet-5 accepts the - # full set, ReviewHog pins its xhigh) - this pins the "Supported values: " - # message and confirms the rejection capture also fires for a model with some supported - # efforts. + def test_run_endpoint_rejects_unsupported_claude_sonnet_4_6_reasoning_effort( + self, reasoning_effort, mock_workflow, mock_capture + ): + # claude-sonnet-4-6 supports low/medium/high but not xhigh/ultracode (claude-sonnet-5 + # accepts the full set, ReviewHog pins its xhigh) - this pins the "Supported values: + # " message and confirms the rejection capture also fires for a model + # with some supported efforts. task = self.create_task() response = self.client.post( @@ -2913,7 +2968,7 @@ def test_run_endpoint_rejects_unsupported_claude_sonnet_4_6_reasoning_effort(sel { "runtime_adapter": "claude", "model": "claude-sonnet-4-6", - "reasoning_effort": "xhigh", + "reasoning_effort": reasoning_effort, }, format="json", ) @@ -2923,7 +2978,7 @@ def test_run_endpoint_rejects_unsupported_claude_sonnet_4_6_reasoning_effort(sel "type": "validation_error", "code": "invalid_input", "detail": ( - "Reasoning effort 'xhigh' is not supported for runtime_adapter 'claude' " + f"Reasoning effort '{reasoning_effort}' is not supported for runtime_adapter 'claude' " "and model 'claude-sonnet-4-6'. Supported values: low, medium, high." ), "attr": "reasoning_effort", @@ -2937,9 +2992,9 @@ def test_run_endpoint_rejects_unsupported_claude_sonnet_4_6_reasoning_effort(sel properties={ "runtime_adapter": "claude", "model": "claude-sonnet-4-6", - "reasoning_effort": "xhigh", + "reasoning_effort": reasoning_effort, "error": ( - "Reasoning effort 'xhigh' is not supported for runtime_adapter 'claude' " + f"Reasoning effort '{reasoning_effort}' is not supported for runtime_adapter 'claude' " "and model 'claude-sonnet-4-6'. Supported values: low, medium, high." ), }, @@ -3043,6 +3098,8 @@ def test_run_endpoint_resume_carries_forward_pr_authorship_metadata(self, mock_w "runtime_adapter": "codex", "model": "gpt-5.3-codex", "reasoning_effort": "medium", + "context_window": "1m", + "fast_mode": True, "snapshot_external_id": "snap-1", }, ) @@ -3069,6 +3126,8 @@ def test_run_endpoint_resume_carries_forward_pr_authorship_metadata(self, mock_w assert task_run.state["provider"] == "openai" assert task_run.state["model"] == "gpt-5.3-codex" assert task_run.state["reasoning_effort"] == "medium" + assert task_run.state["context_window"] == "1m" + assert task_run.state["fast_mode"] is True # Token passed on a BOT resume must not be cached — only USER mode runs use it. assert get_cached_github_user_token(str(task_run.id)) is None diff --git a/products/tasks/backend/tests/test_warm_facade.py b/products/tasks/backend/tests/test_warm_facade.py index 146bba3db529..5db7e7852321 100644 --- a/products/tasks/backend/tests/test_warm_facade.py +++ b/products/tasks/backend/tests/test_warm_facade.py @@ -647,6 +647,72 @@ def test_sandbox_environment_mismatch_does_not_activate_warm_run(self): run.refresh_from_db() assert run.state.get("await_user_message") is True + def test_context_window_mismatch_does_not_activate_warm_run(self): + task, run = self._warm_run() + with ( + patch(f"{FACADE}.signal_task_run_user_message") as mock_signal, + patch(f"{FACADE}._trigger_task_processing_workflow") as mock_trigger, + ): + facade.run_task( + task.id, + self.team.id, + self.user.id, + validated_data={ + "mode": "interactive", + "branch": "main", + "pending_user_message": "do it", + "context_window": "1m", + }, + ) + + mock_signal.assert_not_called() + mock_trigger.assert_called_once() + run.refresh_from_db() + assert run.state.get("await_user_message") is True + + def test_fast_mode_mismatch_does_not_activate_warm_run(self): + task, run = self._warm_run() + with ( + patch(f"{FACADE}.signal_task_run_user_message") as mock_signal, + patch(f"{FACADE}._trigger_task_processing_workflow") as mock_trigger, + ): + facade.run_task( + task.id, + self.team.id, + self.user.id, + validated_data={ + "mode": "interactive", + "branch": "main", + "pending_user_message": "do it", + "fast_mode": True, + }, + ) + + mock_signal.assert_not_called() + mock_trigger.assert_called_once() + run.refresh_from_db() + assert run.state.get("await_user_message") is True + + def test_matching_context_window_and_fast_mode_activates_warm_run(self): + task, run = self._warm_run(extra_state={"context_window": "1m", "fast_mode": True}) + with patch(f"{FACADE}.signal_task_run_user_message", return_value=True) as m_signal: + facade.run_task( + task.id, + self.team.id, + self.user.id, + validated_data={ + "mode": "interactive", + "branch": "main", + "pending_user_message": "do it", + "context_window": "1m", + "fast_mode": True, + }, + ) + + m_signal.assert_called_once() + run.refresh_from_db() + assert "await_user_message" not in run.state + def test_unready_custom_image_does_not_activate_warm_run(self): custom_image = SandboxCustomImage.objects.for_team(self.team.id).create( team_id=self.team.id, diff --git a/products/tasks/frontend/generated/api.schemas.ts b/products/tasks/frontend/generated/api.schemas.ts index ff01a2d6950b..f818c6f1dc2d 100644 --- a/products/tasks/frontend/generated/api.schemas.ts +++ b/products/tasks/frontend/generated/api.schemas.ts @@ -210,6 +210,7 @@ export const RuntimeAdapterEnumApi = { * * `high` - high * * `xhigh` - xhigh * * `max` - max + * * `ultracode` - ultracode */ export type ReasoningEffortEnumApi = (typeof ReasoningEffortEnumApi)[keyof typeof ReasoningEffortEnumApi] @@ -219,6 +220,7 @@ export const ReasoningEffortEnumApi = { High: 'high', Xhigh: 'xhigh', Max: 'max', + Ultracode: 'ultracode', } as const export interface LoopRepositoryEntryApi { @@ -404,7 +406,8 @@ export interface LoopWriteApi { * * `medium` - medium * * `high` - high * * `xhigh` - xhigh - * * `max` - max */ + * * `max` - max + * * `ultracode` - ultracode */ reasoning_effort?: ReasoningEffortEnumApi | null /** * Repositories this loop operates on, ordered. Capped at 1 until multi-repo execution ships. May be empty for report-only loops. @@ -470,7 +473,8 @@ export interface PatchedLoopWriteApi { * * `medium` - medium * * `high` - high * * `xhigh` - xhigh - * * `max` - max */ + * * `max` - max + * * `ultracode` - ultracode */ reasoning_effort?: ReasoningEffortEnumApi | null /** * Repositories this loop operates on, ordered. Capped at 1 until multi-repo execution ships. May be empty for report-only loops. @@ -1355,7 +1359,8 @@ export interface TaskRunDetailDTOApi { * * `medium` - medium * * `high` - high * * `xhigh` - xhigh - * * `max` - max */ + * * `max` - max + * * `ultracode` - ultracode */ reasoning_effort?: ReasoningEffortEnumApi | null /** * Presigned S3 URL for log access (valid for 1 hour). @@ -1578,7 +1583,8 @@ export interface TaskCreateApi { * * `medium` - medium * * `high` - high * * `xhigh` - xhigh - * * `max` - max */ + * * `max` - max + * * `ultracode` - ultracode */ reasoning_effort?: ReasoningEffortEnumApi | null /** * First user message to forward when creation reuses a pre-warmed Run. Write-only and not persisted on the task: lets clients deliver a message that differs from `description` (e.g. a resolved skill invocation with channel context folded in). Ignored when no warm Run is reused — cold creation takes the first message via the run start endpoint instead. @@ -1714,7 +1720,8 @@ export interface TaskWriteApi { * * `medium` - medium * * `high` - high * * `xhigh` - xhigh - * * `max` - max */ + * * `max` - max + * * `ultracode` - ultracode */ reasoning_effort?: ReasoningEffortEnumApi | null /** * First user message to forward when creation reuses a pre-warmed Run. Write-only and not persisted on the task: lets clients deliver a message that differs from `description` (e.g. a resolved skill invocation with channel context folded in). Ignored when no warm Run is reused — cold creation takes the first message via the run start endpoint instead. @@ -1835,7 +1842,8 @@ export interface PatchedTaskWriteApi { * * `medium` - medium * * `high` - high * * `xhigh` - xhigh - * * `max` - max */ + * * `max` - max + * * `ultracode` - ultracode */ reasoning_effort?: ReasoningEffortEnumApi | null /** * First user message to forward when creation reuses a pre-warmed Run. Write-only and not persisted on the task: lets clients deliver a message that differs from `description` (e.g. a resolved skill invocation with channel context folded in). Ignored when no warm Run is reused — cold creation takes the first message via the run start endpoint instead. @@ -1955,6 +1963,17 @@ export const ClaudeRuntimeAdapterEnumApi = { Claude: 'claude', } as const +/** + * * `200k` - 200k + * * `1m` - 1m + */ +export type ContextWindowEnumApi = (typeof ContextWindowEnumApi)[keyof typeof ContextWindowEnumApi] + +export const ContextWindowEnumApi = { + '200k': '200k', + '1m': '1m', +} as const + /** * * `default` - default * * `acceptEdits` - acceptEdits @@ -2040,8 +2059,19 @@ export interface ClaudeTaskRunCreateSchemaApi { * * `medium` - medium * * `high` - high * * `xhigh` - xhigh - * * `max` - max */ + * * `max` - max + * * `ultracode` - ultracode */ reasoning_effort?: ReasoningEffortEnumApi + /** Context window size for models that support the 1M window. + * + * * `200k` - 200k + * * `1m` - 1m */ + context_window?: ContextWindowEnumApi + /** + * Enable fast mode for models that support it. + * @nullable + */ + fast_mode?: boolean | null /** Optional GitHub user token from PostHog Desktop for user-authored cloud pull requests. Prefer linking GitHub from Settings → Linked accounts so the server can manage tokens; this field remains supported for callers that still manage their own tokens. */ github_user_token?: string /** Initial permission mode for Claude runtimes. @@ -2151,8 +2181,19 @@ export interface CodexTaskRunCreateSchemaApi { * * `medium` - medium * * `high` - high * * `xhigh` - xhigh - * * `max` - max */ + * * `max` - max + * * `ultracode` - ultracode */ reasoning_effort?: ReasoningEffortEnumApi + /** Context window size for models that support the 1M window. + * + * * `200k` - 200k + * * `1m` - 1m */ + context_window?: ContextWindowEnumApi + /** + * Enable fast mode for models that support it. + * @nullable + */ + fast_mode?: boolean | null /** Optional GitHub user token from PostHog Desktop for user-authored cloud pull requests. Prefer linking GitHub from Settings → Linked accounts so the server can manage tokens; this field remains supported for callers that still manage their own tokens. */ github_user_token?: string /** Initial permission mode for Codex runtimes. @@ -2470,8 +2511,19 @@ export interface TaskRunBootstrapCreateRequestApi { * * `medium` - medium * * `high` - high * * `xhigh` - xhigh - * * `max` - max */ + * * `max` - max + * * `ultracode` - ultracode */ reasoning_effort?: ReasoningEffortEnumApi + /** Context window size for models that support the 1M window. + * + * * `200k` - 200k + * * `1m` - 1m */ + context_window?: ContextWindowEnumApi + /** + * Enable fast mode for models that support it. + * @nullable + */ + fast_mode?: boolean | null /** Ephemeral GitHub user token from PostHog Desktop for user-authored cloud pull requests. */ github_user_token?: string /** Initial permission mode for the agent session. Claude runtimes accept PostHog permission presets like 'plan'. Codex runtimes accept native Codex modes like 'plan', 'auto', and 'read-only'. @@ -3558,7 +3610,8 @@ export interface WarmTaskRequestApi { * * `medium` - medium * * `high` - high * * `xhigh` - xhigh - * * `max` - max */ + * * `max` - max + * * `ultracode` - ultracode */ reasoning_effort?: ReasoningEffortEnumApi | null /** * Optional sandbox environment to provision before the task is submitted. diff --git a/products/tasks/frontend/generated/api.zod.ts b/products/tasks/frontend/generated/api.zod.ts index b53da5877760..eec19c31c0e6 100644 --- a/products/tasks/frontend/generated/api.zod.ts +++ b/products/tasks/frontend/generated/api.zod.ts @@ -87,15 +87,15 @@ export const LoopsCreateBody = /* @__PURE__ */ zod reasoning_effort: zod .union([ zod - .enum(['low', 'medium', 'high', 'xhigh', 'max']) + .enum(['low', 'medium', 'high', 'xhigh', 'max', 'ultracode']) .describe( - '\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max' + '\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max\n\* `ultracode` - ultracode' ), zod.null(), ]) .optional() .describe( - "Reasoning effort, validated against `runtime_adapter`\/`model`'s supported set.\n\n\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max" + "Reasoning effort, validated against `runtime_adapter`\/`model`'s supported set.\n\n\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max\n\* `ultracode` - ultracode" ), repositories: zod .array( @@ -388,15 +388,15 @@ export const LoopsPartialUpdateBody = /* @__PURE__ */ zod reasoning_effort: zod .union([ zod - .enum(['low', 'medium', 'high', 'xhigh', 'max']) + .enum(['low', 'medium', 'high', 'xhigh', 'max', 'ultracode']) .describe( - '\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max' + '\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max\n\* `ultracode` - ultracode' ), zod.null(), ]) .optional() .describe( - "Reasoning effort, validated against `runtime_adapter`\/`model`'s supported set.\n\n\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max" + "Reasoning effort, validated against `runtime_adapter`\/`model`'s supported set.\n\n\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max\n\* `ultracode` - ultracode" ), repositories: zod .array( @@ -1163,15 +1163,15 @@ export const TasksCreateBody = /* @__PURE__ */ zod reasoning_effort: zod .union([ zod - .enum(['low', 'medium', 'high', 'xhigh', 'max']) + .enum(['low', 'medium', 'high', 'xhigh', 'max', 'ultracode']) .describe( - '\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max' + '\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max\n\* `ultracode` - ultracode' ), zod.null(), ]) .optional() .describe( - 'Selected reasoning effort. Write-only; used only to reuse a warm Run started on the same effort.\n\n\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max' + 'Selected reasoning effort. Write-only; used only to reuse a warm Run started on the same effort.\n\n\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max\n\* `ultracode` - ultracode' ), pending_user_message: zod .string() @@ -1318,15 +1318,15 @@ export const TasksUpdateBody = /* @__PURE__ */ zod reasoning_effort: zod .union([ zod - .enum(['low', 'medium', 'high', 'xhigh', 'max']) + .enum(['low', 'medium', 'high', 'xhigh', 'max', 'ultracode']) .describe( - '\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max' + '\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max\n\* `ultracode` - ultracode' ), zod.null(), ]) .optional() .describe( - 'Selected reasoning effort. Write-only; used only to reuse a warm Run started on the same effort.\n\n\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max' + 'Selected reasoning effort. Write-only; used only to reuse a warm Run started on the same effort.\n\n\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max\n\* `ultracode` - ultracode' ), pending_user_message: zod .string() @@ -1458,15 +1458,15 @@ export const TasksPartialUpdateBody = /* @__PURE__ */ zod reasoning_effort: zod .union([ zod - .enum(['low', 'medium', 'high', 'xhigh', 'max']) + .enum(['low', 'medium', 'high', 'xhigh', 'max', 'ultracode']) .describe( - '\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max' + '\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max\n\* `ultracode` - ultracode' ), zod.null(), ]) .optional() .describe( - 'Selected reasoning effort. Write-only; used only to reuse a warm Run started on the same effort.\n\n\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max' + 'Selected reasoning effort. Write-only; used only to reuse a warm Run started on the same effort.\n\n\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max\n\* `ultracode` - ultracode' ), pending_user_message: zod .string() @@ -1654,12 +1654,22 @@ export const TasksRunCreateBody = /* @__PURE__ */ zod.union([ ), model: zod.string().describe('LLM model identifier to run in the Claude runtime.'), reasoning_effort: zod - .enum(['low', 'medium', 'high', 'xhigh', 'max']) - .describe('\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max') + .enum(['low', 'medium', 'high', 'xhigh', 'max', 'ultracode']) + .describe( + '\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max\n\* `ultracode` - ultracode' + ) .optional() .describe( - 'Reasoning effort to request for models that expose an effort control.\n\n\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max' + 'Reasoning effort to request for models that expose an effort control.\n\n\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max\n\* `ultracode` - ultracode' ), + context_window: zod + .enum(['200k', '1m']) + .describe('\* `200k` - 200k\n\* `1m` - 1m') + .optional() + .describe( + 'Context window size for models that support the 1M window.\n\n\* `200k` - 200k\n\* `1m` - 1m' + ), + fast_mode: zod.boolean().nullish().describe('Enable fast mode for models that support it.'), github_user_token: zod .string() .optional() @@ -1791,12 +1801,22 @@ export const TasksRunCreateBody = /* @__PURE__ */ zod.union([ ), model: zod.string().describe('LLM model identifier to run in the Codex runtime.'), reasoning_effort: zod - .enum(['low', 'medium', 'high', 'xhigh', 'max']) - .describe('\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max') + .enum(['low', 'medium', 'high', 'xhigh', 'max', 'ultracode']) + .describe( + '\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max\n\* `ultracode` - ultracode' + ) .optional() .describe( - 'Reasoning effort to request for models that expose an effort control.\n\n\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max' + 'Reasoning effort to request for models that expose an effort control.\n\n\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max\n\* `ultracode` - ultracode' ), + context_window: zod + .enum(['200k', '1m']) + .describe('\* `200k` - 200k\n\* `1m` - 1m') + .optional() + .describe( + 'Context window size for models that support the 1M window.\n\n\* `200k` - 200k\n\* `1m` - 1m' + ), + fast_mode: zod.boolean().nullish().describe('Enable fast mode for models that support it.'), github_user_token: zod .string() .optional() @@ -2186,12 +2206,20 @@ export const TasksRunsCreateBody = /* @__PURE__ */ zod ), model: zod.string().optional().describe('LLM model identifier to run in the selected runtime.'), reasoning_effort: zod - .enum(['low', 'medium', 'high', 'xhigh', 'max']) - .describe('\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max') + .enum(['low', 'medium', 'high', 'xhigh', 'max', 'ultracode']) + .describe( + '\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max\n\* `ultracode` - ultracode' + ) .optional() .describe( - 'Reasoning effort to request for models that expose an effort control.\n\n\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max' + 'Reasoning effort to request for models that expose an effort control.\n\n\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max\n\* `ultracode` - ultracode' ), + context_window: zod + .enum(['200k', '1m']) + .describe('\* `200k` - 200k\n\* `1m` - 1m') + .optional() + .describe('Context window size for models that support the 1M window.\n\n\* `200k` - 200k\n\* `1m` - 1m'), + fast_mode: zod.boolean().nullish().describe('Enable fast mode for models that support it.'), github_user_token: zod .string() .optional() @@ -2888,15 +2916,15 @@ export const TasksWarmCreateBody = /* @__PURE__ */ zod reasoning_effort: zod .union([ zod - .enum(['low', 'medium', 'high', 'xhigh', 'max']) + .enum(['low', 'medium', 'high', 'xhigh', 'max', 'ultracode']) .describe( - '\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max' + '\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max\n\* `ultracode` - ultracode' ), zod.null(), ]) .optional() .describe( - 'Reasoning effort to warm the sandbox on for models that expose an effort control.\n\n\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max' + 'Reasoning effort to warm the sandbox on for models that expose an effort control.\n\n\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max\n\* `ultracode` - ultracode' ), sandbox_environment_id: zod .uuid() diff --git a/services/mcp/src/api/generated.ts b/services/mcp/src/api/generated.ts index 838d116a7b59..78c2ef8f1c8a 100644 --- a/services/mcp/src/api/generated.ts +++ b/services/mcp/src/api/generated.ts @@ -14171,6 +14171,7 @@ export namespace Schemas { * * `high` - high * * `xhigh` - xhigh * * `max` - max + * * `ultracode` - ultracode */ export type ReasoningEffortEnum = typeof ReasoningEffortEnum[keyof typeof ReasoningEffortEnum]; @@ -14181,6 +14182,19 @@ export namespace Schemas { High: 'high', Xhigh: 'xhigh', Max: 'max', + Ultracode: 'ultracode', + } as const; + + /** + * * `200k` - 200k + * * `1m` - 1m + */ + export type ContextWindowEnum = typeof ContextWindowEnum[keyof typeof ContextWindowEnum]; + + + export const ContextWindowEnum = { + '200k': '200k', + '1m': '1m', } as const; /** @@ -14268,8 +14282,19 @@ export namespace Schemas { * * `medium` - medium * * `high` - high * * `xhigh` - xhigh - * * `max` - max */ + * * `max` - max + * * `ultracode` - ultracode */ reasoning_effort?: ReasoningEffortEnum; + /** Context window size for models that support the 1M window. + * + * * `200k` - 200k + * * `1m` - 1m */ + context_window?: ContextWindowEnum; + /** + * Enable fast mode for models that support it. + * @nullable + */ + fast_mode?: boolean | null; /** Optional GitHub user token from PostHog Desktop for user-authored cloud pull requests. Prefer linking GitHub from Settings → Linked accounts so the server can manage tokens; this field remains supported for callers that still manage their own tokens. */ github_user_token?: string; /** Initial permission mode for Claude runtimes. @@ -14639,8 +14664,19 @@ export namespace Schemas { * * `medium` - medium * * `high` - high * * `xhigh` - xhigh - * * `max` - max */ + * * `max` - max + * * `ultracode` - ultracode */ reasoning_effort?: ReasoningEffortEnum; + /** Context window size for models that support the 1M window. + * + * * `200k` - 200k + * * `1m` - 1m */ + context_window?: ContextWindowEnum; + /** + * Enable fast mode for models that support it. + * @nullable + */ + fast_mode?: boolean | null; /** Optional GitHub user token from PostHog Desktop for user-authored cloud pull requests. Prefer linking GitHub from Settings → Linked accounts so the server can manage tokens; this field remains supported for callers that still manage their own tokens. */ github_user_token?: string; /** Initial permission mode for Codex runtimes. @@ -38309,7 +38345,8 @@ export namespace Schemas { * * `medium` - medium * * `high` - high * * `xhigh` - xhigh - * * `max` - max */ + * * `max` - max + * * `ultracode` - ultracode */ reasoning_effort?: ReasoningEffortEnum | null; /** * Repositories this loop operates on, ordered. Capped at 1 until multi-repo execution ships. May be empty for report-only loops. @@ -44945,7 +44982,8 @@ export namespace Schemas { * * `medium` - medium * * `high` - high * * `xhigh` - xhigh - * * `max` - max */ + * * `max` - max + * * `ultracode` - ultracode */ reasoning_effort?: ReasoningEffortEnum | null; /** * Presigned S3 URL for log access (valid for 1 hour). @@ -49858,7 +49896,8 @@ export namespace Schemas { * * `medium` - medium * * `high` - high * * `xhigh` - xhigh - * * `max` - max */ + * * `max` - max + * * `ultracode` - ultracode */ reasoning_effort?: ReasoningEffortEnum | null; /** * Repositories this loop operates on, ordered. Capped at 1 until multi-repo execution ships. May be empty for report-only loops. @@ -53051,7 +53090,8 @@ export namespace Schemas { * * `medium` - medium * * `high` - high * * `xhigh` - xhigh - * * `max` - max */ + * * `max` - max + * * `ultracode` - ultracode */ reasoning_effort?: ReasoningEffortEnum | null; /** * First user message to forward when creation reuses a pre-warmed Run. Write-only and not persisted on the task: lets clients deliver a message that differs from `description` (e.g. a resolved skill invocation with channel context folded in). Ignored when no warm Run is reused — cold creation takes the first message via the run start endpoint instead. @@ -67389,7 +67429,8 @@ export namespace Schemas { * * `medium` - medium * * `high` - high * * `xhigh` - xhigh - * * `max` - max */ + * * `max` - max + * * `ultracode` - ultracode */ reasoning_effort?: ReasoningEffortEnum | null; /** * First user message to forward when creation reuses a pre-warmed Run. Write-only and not persisted on the task: lets clients deliver a message that differs from `description` (e.g. a resolved skill invocation with channel context folded in). Ignored when no warm Run is reused — cold creation takes the first message via the run start endpoint instead. @@ -67758,8 +67799,19 @@ export namespace Schemas { * * `medium` - medium * * `high` - high * * `xhigh` - xhigh - * * `max` - max */ + * * `max` - max + * * `ultracode` - ultracode */ reasoning_effort?: ReasoningEffortEnum; + /** Context window size for models that support the 1M window. + * + * * `200k` - 200k + * * `1m` - 1m */ + context_window?: ContextWindowEnum; + /** + * Enable fast mode for models that support it. + * @nullable + */ + fast_mode?: boolean | null; /** Ephemeral GitHub user token from PostHog Desktop for user-authored cloud pull requests. */ github_user_token?: string; /** Initial permission mode for the agent session. Claude runtimes accept PostHog permission presets like 'plan'. Codex runtimes accept native Codex modes like 'plan', 'auto', and 'read-only'. @@ -68371,7 +68423,8 @@ export namespace Schemas { * * `medium` - medium * * `high` - high * * `xhigh` - xhigh - * * `max` - max */ + * * `max` - max + * * `ultracode` - ultracode */ reasoning_effort?: ReasoningEffortEnum | null; /** * First user message to forward when creation reuses a pre-warmed Run. Write-only and not persisted on the task: lets clients deliver a message that differs from `description` (e.g. a resolved skill invocation with channel context folded in). Ignored when no warm Run is reused — cold creation takes the first message via the run start endpoint instead. @@ -69588,7 +69641,8 @@ export namespace Schemas { * * `medium` - medium * * `high` - high * * `xhigh` - xhigh - * * `max` - max */ + * * `max` - max + * * `ultracode` - ultracode */ reasoning_effort?: ReasoningEffortEnum | null; /** * Optional sandbox environment to provision before the task is submitted. diff --git a/services/mcp/src/generated/tasks/api.ts b/services/mcp/src/generated/tasks/api.ts index 3ae46ca526b8..91714eab68d4 100644 --- a/services/mcp/src/generated/tasks/api.ts +++ b/services/mcp/src/generated/tasks/api.ts @@ -101,15 +101,15 @@ export const LoopsCreateBody = /* @__PURE__ */ zod reasoning_effort: zod .union([ zod - .enum(['low', 'medium', 'high', 'xhigh', 'max']) + .enum(['low', 'medium', 'high', 'xhigh', 'max', 'ultracode']) .describe( - '\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max' + '\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max\n\* `ultracode` - ultracode' ), zod.null(), ]) .optional() .describe( - "Reasoning effort, validated against `runtime_adapter`\/`model`'s supported set.\n\n\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max" + "Reasoning effort, validated against `runtime_adapter`\/`model`'s supported set.\n\n\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max\n\* `ultracode` - ultracode" ), repositories: zod .array( @@ -416,15 +416,15 @@ export const LoopsPartialUpdateBody = /* @__PURE__ */ zod reasoning_effort: zod .union([ zod - .enum(['low', 'medium', 'high', 'xhigh', 'max']) + .enum(['low', 'medium', 'high', 'xhigh', 'max', 'ultracode']) .describe( - '\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max' + '\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max\n\* `ultracode` - ultracode' ), zod.null(), ]) .optional() .describe( - "Reasoning effort, validated against `runtime_adapter`\/`model`'s supported set.\n\n\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max" + "Reasoning effort, validated against `runtime_adapter`\/`model`'s supported set.\n\n\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max\n\* `ultracode` - ultracode" ), repositories: zod .array( @@ -920,15 +920,15 @@ export const TasksCreateBody = /* @__PURE__ */ zod reasoning_effort: zod .union([ zod - .enum(['low', 'medium', 'high', 'xhigh', 'max']) + .enum(['low', 'medium', 'high', 'xhigh', 'max', 'ultracode']) .describe( - '\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max' + '\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max\n\* `ultracode` - ultracode' ), zod.null(), ]) .optional() .describe( - 'Selected reasoning effort. Write-only; used only to reuse a warm Run started on the same effort.\n\n\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max' + 'Selected reasoning effort. Write-only; used only to reuse a warm Run started on the same effort.\n\n\* `low` - low\n\* `medium` - medium\n\* `high` - high\n\* `xhigh` - xhigh\n\* `max` - max\n\* `ultracode` - ultracode' ), pending_user_message: zod .string() diff --git a/services/mcp/tests/unit/__snapshots__/tool-schemas/loops-create-prepare.json b/services/mcp/tests/unit/__snapshots__/tool-schemas/loops-create-prepare.json index cca47d2ab54b..72677cfd261c 100644 --- a/services/mcp/tests/unit/__snapshots__/tool-schemas/loops-create-prepare.json +++ b/services/mcp/tests/unit/__snapshots__/tool-schemas/loops-create-prepare.json @@ -222,15 +222,15 @@ "reasoning_effort": { "anyOf": [ { - "description": "* `low` - low\n* `medium` - medium\n* `high` - high\n* `xhigh` - xhigh\n* `max` - max", - "enum": ["low", "medium", "high", "xhigh", "max"], + "description": "* `low` - low\n* `medium` - medium\n* `high` - high\n* `xhigh` - xhigh\n* `max` - max\n* `ultracode` - ultracode", + "enum": ["low", "medium", "high", "xhigh", "max", "ultracode"], "type": "string" }, { "type": "null" } ], - "description": "Reasoning effort, validated against `runtime_adapter`/`model`'s supported set.\n\n* `low` - low\n* `medium` - medium\n* `high` - high\n* `xhigh` - xhigh\n* `max` - max" + "description": "Reasoning effort, validated against `runtime_adapter`/`model`'s supported set.\n\n* `low` - low\n* `medium` - medium\n* `high` - high\n* `xhigh` - xhigh\n* `max` - max\n* `ultracode` - ultracode" }, "repositories": { "description": "Repositories this loop operates on, ordered. Capped at 1 until multi-repo execution ships. May be empty for report-only loops.", diff --git a/services/mcp/tests/unit/__snapshots__/tool-schemas/loops-partial-update.json b/services/mcp/tests/unit/__snapshots__/tool-schemas/loops-partial-update.json index ca953575d316..4c7b3e5c5545 100644 --- a/services/mcp/tests/unit/__snapshots__/tool-schemas/loops-partial-update.json +++ b/services/mcp/tests/unit/__snapshots__/tool-schemas/loops-partial-update.json @@ -220,15 +220,15 @@ "reasoning_effort": { "anyOf": [ { - "description": "* `low` - low\n* `medium` - medium\n* `high` - high\n* `xhigh` - xhigh\n* `max` - max", - "enum": ["low", "medium", "high", "xhigh", "max"], + "description": "* `low` - low\n* `medium` - medium\n* `high` - high\n* `xhigh` - xhigh\n* `max` - max\n* `ultracode` - ultracode", + "enum": ["low", "medium", "high", "xhigh", "max", "ultracode"], "type": "string" }, { "type": "null" } ], - "description": "Reasoning effort, validated against `runtime_adapter`/`model`'s supported set.\n\n* `low` - low\n* `medium` - medium\n* `high` - high\n* `xhigh` - xhigh\n* `max` - max" + "description": "Reasoning effort, validated against `runtime_adapter`/`model`'s supported set.\n\n* `low` - low\n* `medium` - medium\n* `high` - high\n* `xhigh` - xhigh\n* `max` - max\n* `ultracode` - ultracode" }, "repositories": { "description": "Repositories this loop operates on, ordered. Capped at 1 until multi-repo execution ships. May be empty for report-only loops.", diff --git a/services/mcp/tests/unit/__snapshots__/tool-schemas/loops-review.json b/services/mcp/tests/unit/__snapshots__/tool-schemas/loops-review.json index cca47d2ab54b..72677cfd261c 100644 --- a/services/mcp/tests/unit/__snapshots__/tool-schemas/loops-review.json +++ b/services/mcp/tests/unit/__snapshots__/tool-schemas/loops-review.json @@ -222,15 +222,15 @@ "reasoning_effort": { "anyOf": [ { - "description": "* `low` - low\n* `medium` - medium\n* `high` - high\n* `xhigh` - xhigh\n* `max` - max", - "enum": ["low", "medium", "high", "xhigh", "max"], + "description": "* `low` - low\n* `medium` - medium\n* `high` - high\n* `xhigh` - xhigh\n* `max` - max\n* `ultracode` - ultracode", + "enum": ["low", "medium", "high", "xhigh", "max", "ultracode"], "type": "string" }, { "type": "null" } ], - "description": "Reasoning effort, validated against `runtime_adapter`/`model`'s supported set.\n\n* `low` - low\n* `medium` - medium\n* `high` - high\n* `xhigh` - xhigh\n* `max` - max" + "description": "Reasoning effort, validated against `runtime_adapter`/`model`'s supported set.\n\n* `low` - low\n* `medium` - medium\n* `high` - high\n* `xhigh` - xhigh\n* `max` - max\n* `ultracode` - ultracode" }, "repositories": { "description": "Repositories this loop operates on, ordered. Capped at 1 until multi-repo execution ships. May be empty for report-only loops.",