@oneciel-ai/ciel-runtime 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +132 -0
- package/ciel-runtime-menu.py +56 -6
- package/ciel_runtime.py +9379 -35909
- package/ciel_runtime_support/advisor_client.py +193 -0
- package/ciel_runtime_support/advisor_policy.py +320 -0
- package/ciel_runtime_support/advisor_refinement.py +160 -0
- package/ciel_runtime_support/advisor_request_builder.py +261 -0
- package/ciel_runtime_support/agy_installer.py +169 -0
- package/ciel_runtime_support/agy_mcp_restore.py +182 -0
- package/ciel_runtime_support/anthropic_model_policy.py +186 -0
- package/ciel_runtime_support/anthropic_response_writer.py +255 -0
- package/ciel_runtime_support/anthropic_tool_turns.py +130 -0
- package/ciel_runtime_support/api_key_cooldown.py +159 -0
- package/ciel_runtime_support/architecture.py +488 -1
- package/ciel_runtime_support/architecture_budget.py +42 -0
- package/ciel_runtime_support/channel_backlog.py +90 -0
- package/ciel_runtime_support/channel_cli.py +119 -0
- package/ciel_runtime_support/channel_compact_injection.py +82 -0
- package/ciel_runtime_support/channel_compact_poll.py +67 -0
- package/ciel_runtime_support/channel_compact_request_repository.py +113 -0
- package/ciel_runtime_support/channel_config_service.py +281 -0
- package/ciel_runtime_support/channel_connection_lifecycle.py +180 -0
- package/ciel_runtime_support/channel_connection_registry.py +128 -0
- package/ciel_runtime_support/channel_connection_worker.py +284 -0
- package/ciel_runtime_support/channel_cursor_recovery.py +92 -0
- package/ciel_runtime_support/channel_cursor_repository.py +89 -0
- package/ciel_runtime_support/channel_cursor_service.py +178 -0
- package/ciel_runtime_support/channel_event_identity.py +212 -0
- package/ciel_runtime_support/channel_event_projection.py +315 -0
- package/ciel_runtime_support/channel_inflight.py +127 -0
- package/ciel_runtime_support/channel_injection.py +115 -0
- package/ciel_runtime_support/channel_launch_guard_repository.py +58 -0
- package/ciel_runtime_support/channel_launch_policy.py +180 -0
- package/ciel_runtime_support/channel_llm_context.py +156 -0
- package/ciel_runtime_support/channel_mcp_discovery.py +186 -0
- package/ciel_runtime_support/channel_mcp_http_controller.py +239 -0
- package/ciel_runtime_support/channel_mcp_ownership.py +148 -0
- package/ciel_runtime_support/channel_mcp_tools.py +240 -0
- package/ciel_runtime_support/channel_mcp_transport.py +394 -0
- package/ciel_runtime_support/channel_message_dedupe.py +65 -0
- package/ciel_runtime_support/channel_message_policy.py +256 -0
- package/ciel_runtime_support/channel_message_prompt.py +305 -0
- package/ciel_runtime_support/channel_message_repository.py +234 -0
- package/ciel_runtime_support/channel_notification_projection.py +217 -0
- package/ciel_runtime_support/channel_panel.py +162 -0
- package/ciel_runtime_support/channel_pending_injection.py +209 -0
- package/ciel_runtime_support/channel_pending_poll.py +109 -0
- package/ciel_runtime_support/channel_probe_cache.py +433 -0
- package/ciel_runtime_support/channel_probe_report.py +101 -0
- package/ciel_runtime_support/channel_runtime_environment.py +181 -0
- package/ciel_runtime_support/channel_session_lifecycle.py +114 -0
- package/ciel_runtime_support/channel_session_repository.py +90 -0
- package/ciel_runtime_support/channel_terminal_dispatch.py +115 -0
- package/ciel_runtime_support/channel_terminal_input.py +277 -0
- package/ciel_runtime_support/channel_terminal_proxy.py +447 -0
- package/ciel_runtime_support/channel_tool_context.py +166 -0
- package/ciel_runtime_support/channel_transcript.py +414 -0
- package/ciel_runtime_support/channel_transcript_repository.py +96 -0
- package/ciel_runtime_support/channel_wake_claim_repository.py +126 -0
- package/ciel_runtime_support/channel_wake_delivery_repository.py +88 -0
- package/ciel_runtime_support/chat_files.py +138 -0
- package/ciel_runtime_support/chat_http_controller.py +235 -0
- package/ciel_runtime_support/claude_environment.py +375 -0
- package/ciel_runtime_support/claude_router.py +247 -193
- package/ciel_runtime_support/cli_dispatch.py +792 -0
- package/ciel_runtime_support/cli_parser.py +165 -0
- package/ciel_runtime_support/cli_usage.py +100 -0
- package/ciel_runtime_support/codex_app_server.py +20 -5
- package/ciel_runtime_support/codex_channel_sse_launch.py +87 -0
- package/ciel_runtime_support/codex_cli.py +42 -6
- package/ciel_runtime_support/codex_config.py +323 -0
- package/ciel_runtime_support/codex_launch_configuration.py +240 -0
- package/ciel_runtime_support/codex_launch_policy.py +66 -0
- package/ciel_runtime_support/codex_mcp_integration.py +195 -0
- package/ciel_runtime_support/codex_mcp_restore.py +304 -0
- package/ciel_runtime_support/codex_model_catalog.py +133 -0
- package/ciel_runtime_support/codex_process_lifecycle.py +271 -0
- package/ciel_runtime_support/codex_router.py +147 -1
- package/ciel_runtime_support/codex_session_repository.py +115 -0
- package/ciel_runtime_support/codex_session_selection.py +114 -0
- package/ciel_runtime_support/command_asset_installer.py +103 -0
- package/ciel_runtime_support/compatibility_probe.py +295 -0
- package/ciel_runtime_support/compatibility_protocol.py +251 -0
- package/ciel_runtime_support/compatibility_runtime.py +166 -0
- package/ciel_runtime_support/compatibility_test.py +370 -0
- package/ciel_runtime_support/config_migrations.py +307 -0
- package/ciel_runtime_support/config_repository.py +175 -0
- package/ciel_runtime_support/config_value_codec.py +64 -0
- package/ciel_runtime_support/configuration_cli.py +374 -0
- package/ciel_runtime_support/context_compaction.py +280 -0
- package/ciel_runtime_support/context_setup.py +208 -0
- package/ciel_runtime_support/context_summary_policy.py +392 -0
- package/ciel_runtime_support/credential_cli.py +104 -0
- package/ciel_runtime_support/credential_management.py +261 -0
- package/ciel_runtime_support/credentials.py +269 -0
- package/ciel_runtime_support/executable_discovery.py +141 -0
- package/ciel_runtime_support/github_copilot_oauth.py +335 -0
- package/ciel_runtime_support/github_copilot_oauth_runtime.py +213 -0
- package/ciel_runtime_support/header_forwarding.py +73 -0
- package/ciel_runtime_support/headless_config.py +221 -0
- package/ciel_runtime_support/http_response.py +129 -0
- package/ciel_runtime_support/install_diagnostics.py +149 -0
- package/ciel_runtime_support/kimi_identity.py +123 -0
- package/ciel_runtime_support/launch_diagnostics.py +204 -0
- package/ciel_runtime_support/launch_state.py +127 -0
- package/ciel_runtime_support/live_api_key_controller.py +58 -0
- package/ciel_runtime_support/llm_config_http.py +148 -0
- package/ciel_runtime_support/llm_option_config.py +259 -0
- package/ciel_runtime_support/llm_presentation_data.py +447 -0
- package/ciel_runtime_support/llm_presets.py +773 -0
- package/ciel_runtime_support/lm_studio_runtime.py +401 -0
- package/ciel_runtime_support/managed_mcp_config.py +144 -0
- package/ciel_runtime_support/managed_mcp_discovery.py +151 -0
- package/ciel_runtime_support/managed_service_cleanup.py +89 -0
- package/ciel_runtime_support/mcp_config_reader.py +230 -0
- package/ciel_runtime_support/mcp_http_proxy.py +607 -0
- package/ciel_runtime_support/mcp_inventory.py +59 -0
- package/ciel_runtime_support/mcp_notification_wait_policy.py +159 -0
- package/ciel_runtime_support/mcp_probe_codec.py +136 -0
- package/ciel_runtime_support/mcp_probe_transport.py +328 -0
- package/ciel_runtime_support/mcp_proxy_codec.py +345 -0
- package/ciel_runtime_support/mcp_proxy_config.py +107 -0
- package/ciel_runtime_support/mcp_proxy_notifications.py +261 -0
- package/ciel_runtime_support/mcp_proxy_process.py +560 -0
- package/ciel_runtime_support/mcp_split_proxy_http.py +165 -0
- package/ciel_runtime_support/mcp_stdio_probe.py +240 -0
- package/ciel_runtime_support/mcp_transport.py +146 -0
- package/ciel_runtime_support/model_cache_lifecycle.py +78 -0
- package/ciel_runtime_support/model_catalog_projection.py +61 -0
- package/ciel_runtime_support/model_context_hints.py +109 -0
- package/ciel_runtime_support/model_panel.py +147 -0
- package/ciel_runtime_support/model_registry_repository.py +231 -0
- package/ciel_runtime_support/npm_runtime.py +191 -0
- package/ciel_runtime_support/ollama_catalog.py +462 -0
- package/ciel_runtime_support/ollama_catalog_cli.py +41 -0
- package/ciel_runtime_support/ollama_catalog_repository.py +75 -0
- package/ciel_runtime_support/ollama_context_sync.py +87 -0
- package/ciel_runtime_support/ollama_forwarding.py +449 -0
- package/ciel_runtime_support/openai_chat_passthrough.py +67 -0
- package/ciel_runtime_support/openai_chat_router.py +64 -0
- package/ciel_runtime_support/openai_forwarding.py +194 -0
- package/ciel_runtime_support/openai_responses_router.py +291 -0
- package/ciel_runtime_support/openai_responses_stream.py +135 -0
- package/ciel_runtime_support/output_budget.py +89 -0
- package/ciel_runtime_support/package_lifecycle.py +217 -0
- package/ciel_runtime_support/plan_artifact_controller.py +104 -0
- package/ciel_runtime_support/prelaunch.py +959 -0
- package/ciel_runtime_support/prelaunch_launch_preference.py +75 -0
- package/ciel_runtime_support/prelaunch_panel_projection.py +396 -0
- package/ciel_runtime_support/prelaunch_terminal.py +764 -0
- package/ciel_runtime_support/process_control.py +708 -0
- package/ciel_runtime_support/prompt_compaction.py +322 -0
- package/ciel_runtime_support/prompt_injection.py +176 -0
- package/ciel_runtime_support/protocols/__init__.py +24 -0
- package/ciel_runtime_support/protocols/anthropic_content.py +29 -0
- package/ciel_runtime_support/protocols/anthropic_thinking_policy.py +336 -0
- package/ciel_runtime_support/protocols/chat_projection.py +315 -0
- package/ciel_runtime_support/protocols/conversation_policy.py +217 -0
- package/ciel_runtime_support/protocols/conversation_turn_policy.py +972 -0
- package/ciel_runtime_support/protocols/ollama_chat.py +111 -0
- package/ciel_runtime_support/protocols/ollama_response.py +231 -0
- package/ciel_runtime_support/protocols/openai_reasoning.py +75 -0
- package/ciel_runtime_support/protocols/openai_responses.py +271 -0
- package/ciel_runtime_support/protocols/pseudo_tool_history.py +248 -0
- package/ciel_runtime_support/protocols/tool_result_projection.py +112 -0
- package/ciel_runtime_support/provider_adapters.py +160 -0
- package/ciel_runtime_support/provider_catalog_sources.py +316 -0
- package/ciel_runtime_support/provider_choice.py +201 -0
- package/ciel_runtime_support/provider_compatibility.py +165 -0
- package/ciel_runtime_support/provider_config_mutations.py +361 -0
- package/ciel_runtime_support/provider_configuration_service.py +162 -0
- package/ciel_runtime_support/provider_context.py +308 -0
- package/ciel_runtime_support/provider_contract_projection.py +73 -0
- package/ciel_runtime_support/provider_descriptor.py +82 -0
- package/ciel_runtime_support/provider_endpoint_policy.py +130 -0
- package/ciel_runtime_support/provider_endpoint_probe.py +165 -0
- package/ciel_runtime_support/provider_launch_endpoint.py +109 -0
- package/ciel_runtime_support/provider_limits.py +457 -0
- package/ciel_runtime_support/provider_model_identity.py +139 -0
- package/ciel_runtime_support/provider_model_selection.py +431 -0
- package/ciel_runtime_support/provider_model_specs.py +142 -0
- package/ciel_runtime_support/provider_models.py +263 -0
- package/ciel_runtime_support/provider_network.py +176 -0
- package/ciel_runtime_support/provider_option_cli.py +238 -0
- package/ciel_runtime_support/provider_option_panel.py +275 -0
- package/ciel_runtime_support/provider_option_status.py +192 -0
- package/ciel_runtime_support/provider_policy.py +101 -0
- package/ciel_runtime_support/provider_query_policy.py +67 -0
- package/ciel_runtime_support/provider_readiness.py +112 -0
- package/ciel_runtime_support/provider_request_access.py +131 -0
- package/ciel_runtime_support/provider_request_builder.py +250 -0
- package/ciel_runtime_support/provider_responses_passthrough.py +81 -0
- package/ciel_runtime_support/provider_runtime_info.py +113 -0
- package/ciel_runtime_support/provider_runtime_modes.py +150 -0
- package/ciel_runtime_support/provider_sampling_policy.py +46 -0
- package/ciel_runtime_support/provider_status.py +145 -0
- package/ciel_runtime_support/provider_timeout_policy.py +184 -0
- package/ciel_runtime_support/provider_tool_policy.py +145 -0
- package/ciel_runtime_support/providers/__init__.py +65 -0
- package/ciel_runtime_support/providers/anthropic.py +160 -0
- package/ciel_runtime_support/providers/anthropic_catalog.py +119 -0
- package/ciel_runtime_support/providers/base.py +232 -0
- package/ciel_runtime_support/providers/catalog.py +326 -0
- package/ciel_runtime_support/providers/cloud.py +194 -0
- package/ciel_runtime_support/providers/constants.py +54 -0
- package/ciel_runtime_support/providers/deepseek.py +115 -0
- package/ciel_runtime_support/providers/fireworks.py +158 -0
- package/ciel_runtime_support/providers/github_copilot_oauth.py +199 -0
- package/ciel_runtime_support/providers/kimi.py +297 -0
- package/ciel_runtime_support/providers/lm_studio.py +76 -0
- package/ciel_runtime_support/providers/meta.py +257 -0
- package/ciel_runtime_support/providers/native.py +194 -0
- package/ciel_runtime_support/providers/nim.py +69 -0
- package/ciel_runtime_support/providers/nvidia.py +158 -0
- package/ciel_runtime_support/providers/nvidia_runtime.py +285 -0
- package/ciel_runtime_support/providers/ollama.py +181 -0
- package/ciel_runtime_support/providers/ollama_context.py +195 -0
- package/ciel_runtime_support/providers/ollama_runtime.py +213 -0
- package/ciel_runtime_support/providers/opencode.py +220 -0
- package/ciel_runtime_support/providers/opencode_go.py +37 -0
- package/ciel_runtime_support/providers/openrouter.py +57 -0
- package/ciel_runtime_support/providers/vllm.py +65 -0
- package/ciel_runtime_support/providers/zai.py +119 -0
- package/ciel_runtime_support/pseudo_tool_parser.py +115 -0
- package/ciel_runtime_support/rate_limit_policy.py +117 -0
- package/ciel_runtime_support/rate_limit_repository.py +154 -0
- package/ciel_runtime_support/registry.py +46 -0
- package/ciel_runtime_support/request_shortcuts.py +253 -0
- package/ciel_runtime_support/request_trace.py +323 -0
- package/ciel_runtime_support/response_collection.py +209 -0
- package/ciel_runtime_support/router_access.py +238 -0
- package/ciel_runtime_support/router_client_lifecycle.py +366 -0
- package/ciel_runtime_support/router_health_policy.py +101 -0
- package/ciel_runtime_support/router_http.py +513 -0
- package/ciel_runtime_support/router_process_lifecycle.py +401 -0
- package/ciel_runtime_support/router_rate_limit_service.py +285 -0
- package/ciel_runtime_support/router_server_runtime.py +103 -0
- package/ciel_runtime_support/router_shortcuts.py +201 -0
- package/ciel_runtime_support/routing_fallback.py +73 -0
- package/ciel_runtime_support/runtime_activity_repository.py +143 -0
- package/ciel_runtime_support/runtime_adapters.py +104 -0
- package/ciel_runtime_support/runtime_command_factory.py +73 -0
- package/ciel_runtime_support/runtime_compatibility.py +50 -0
- package/ciel_runtime_support/runtime_constants.py +178 -0
- package/ciel_runtime_support/runtime_launch.py +1602 -0
- package/ciel_runtime_support/runtime_llm_options.py +312 -0
- package/ciel_runtime_support/runtime_logging.py +161 -0
- package/ciel_runtime_support/runtime_paths.py +157 -0
- package/ciel_runtime_support/runtime_restart.py +84 -0
- package/ciel_runtime_support/runtime_upgrade.py +149 -0
- package/ciel_runtime_support/secure_json_repository.py +55 -0
- package/ciel_runtime_support/session_import.py +356 -0
- package/ciel_runtime_support/settings_repository.py +8 -0
- package/ciel_runtime_support/slash_command_assets.py +211 -0
- package/ciel_runtime_support/sse_stream.py +57 -0
- package/ciel_runtime_support/sse_trace.py +225 -0
- package/ciel_runtime_support/statusline_script.py +593 -0
- package/ciel_runtime_support/statusline_settings.py +53 -0
- package/ciel_runtime_support/stream_chunk_policy.py +18 -0
- package/ciel_runtime_support/streaming_anthropic.py +1955 -0
- package/ciel_runtime_support/synthetic_tool_policy.py +105 -0
- package/ciel_runtime_support/terminal_platform_io.py +127 -0
- package/ciel_runtime_support/timeout_profile.py +196 -0
- package/ciel_runtime_support/tool_dialects.py +85 -0
- package/ciel_runtime_support/tool_exposure_policy.py +63 -0
- package/ciel_runtime_support/tool_guard_hooks.py +218 -0
- package/ciel_runtime_support/tool_request_projection.py +96 -0
- package/ciel_runtime_support/tool_schema.py +483 -0
- package/ciel_runtime_support/tool_side_effect_dedupe.py +95 -0
- package/ciel_runtime_support/ui_text.py +266 -0
- package/ciel_runtime_support/upstream_error_policy.py +104 -0
- package/ciel_runtime_support/upstream_retry.py +419 -0
- package/ciel_runtime_support/upstream_stream_io.py +106 -0
- package/ciel_runtime_support/usage_events.py +96 -0
- package/ciel_runtime_support/visible_stream_filters.py +130 -0
- package/ciel_runtime_support/web_endpoints.py +447 -0
- package/ciel_runtime_support/web_ui.py +915 -0
- package/ciel_runtime_support/web_ui_controller.py +189 -0
- package/ciel_runtime_support/windows_console_input.py +137 -0
- package/ciel_runtime_support/windows_console_mode.py +112 -0
- package/docs/Architecture.md +54 -0
- package/docs/Configuration.md +17 -0
- package/docs/Module-Map.md +1093 -26
- package/docs/Providers.md +46 -1
- package/docs/adr/0001-runtime-bounded-contexts.md +295 -0
- package/npm-bin/run-ciel-runtime.js +22 -2
- package/package.json +9 -2
|
@@ -0,0 +1,1602 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import subprocess
|
|
5
|
+
import uuid
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Any, Callable
|
|
8
|
+
from dataclasses import dataclass
|
|
9
|
+
|
|
10
|
+
from ciel_runtime_support.channel_message_prompt import NATIVE_ROUTER_CHANNEL_NAMES
|
|
11
|
+
from ciel_runtime_support.runtime_constants import (
|
|
12
|
+
CLAUDE_SERVER_SIDE_WEB_TOOLS,
|
|
13
|
+
CODEX_RUNTIME_API_KEY_ENV,
|
|
14
|
+
PRELAUNCH_CANCEL,
|
|
15
|
+
PRELAUNCH_LAUNCH_AGY,
|
|
16
|
+
PRELAUNCH_LAUNCH_CLAUDE,
|
|
17
|
+
PRELAUNCH_LAUNCH_CODEX,
|
|
18
|
+
PRELAUNCH_LAUNCH_CODEX_APP_SERVER,
|
|
19
|
+
ROUTED_COMPAT_PROMPT,
|
|
20
|
+
)
|
|
21
|
+
from ciel_runtime_support.runtime_paths import CONFIG_DIR, LOG_PATH
|
|
22
|
+
from ciel_runtime_support.web_endpoints import web_backend_settings
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
CLAUDE_CODE_GENERATED_GREEDY_OPTIONS = frozenset(
|
|
26
|
+
{"--mcp-config", "--dangerously-load-development-channels"}
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def web_backend_start_requested(config: dict[str, Any]) -> bool:
|
|
31
|
+
if str(os.environ.get("CIEL_RUNTIME_WEB_START_REQUESTED") or "").lower() in {
|
|
32
|
+
"1", "true", "yes", "on"
|
|
33
|
+
}:
|
|
34
|
+
return True
|
|
35
|
+
return web_backend_settings(config).enabled
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@dataclass(frozen=True, slots=True)
|
|
39
|
+
class ClaudeLaunchConstants:
|
|
40
|
+
CLAUDE_SERVER_SIDE_WEB_TOOLS: Any
|
|
41
|
+
LOG_PATH: Any
|
|
42
|
+
PRELAUNCH_CANCEL: Any
|
|
43
|
+
PRELAUNCH_LAUNCH_AGY: Any
|
|
44
|
+
PRELAUNCH_LAUNCH_CLAUDE: Any
|
|
45
|
+
PRELAUNCH_LAUNCH_CODEX: Any
|
|
46
|
+
PRELAUNCH_LAUNCH_CODEX_APP_SERVER: Any
|
|
47
|
+
ROUTED_COMPAT_PROMPT: Any
|
|
48
|
+
_NATIVE_ROUTER_CHANNEL_NAMES: Any
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def build_default_claude_launch_constants() -> ClaudeLaunchConstants:
|
|
52
|
+
"""Build immutable Claude launch policy constants at their owner boundary."""
|
|
53
|
+
return ClaudeLaunchConstants(
|
|
54
|
+
CLAUDE_SERVER_SIDE_WEB_TOOLS=CLAUDE_SERVER_SIDE_WEB_TOOLS,
|
|
55
|
+
LOG_PATH=LOG_PATH,
|
|
56
|
+
PRELAUNCH_CANCEL=PRELAUNCH_CANCEL,
|
|
57
|
+
PRELAUNCH_LAUNCH_AGY=PRELAUNCH_LAUNCH_AGY,
|
|
58
|
+
PRELAUNCH_LAUNCH_CLAUDE=PRELAUNCH_LAUNCH_CLAUDE,
|
|
59
|
+
PRELAUNCH_LAUNCH_CODEX=PRELAUNCH_LAUNCH_CODEX,
|
|
60
|
+
PRELAUNCH_LAUNCH_CODEX_APP_SERVER=PRELAUNCH_LAUNCH_CODEX_APP_SERVER,
|
|
61
|
+
ROUTED_COMPAT_PROMPT=ROUTED_COMPAT_PROMPT,
|
|
62
|
+
_NATIVE_ROUTER_CHANNEL_NAMES=NATIVE_ROUTER_CHANNEL_NAMES,
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@dataclass(frozen=True, slots=True)
|
|
67
|
+
class ClaudeLaunchProcess:
|
|
68
|
+
_log_claude_command_for_diagnostics: Callable[..., Any]
|
|
69
|
+
_subprocess_call_capturing_stderr: Callable[..., Any]
|
|
70
|
+
env_bool: Callable[..., Any]
|
|
71
|
+
env_vars: Callable[..., Any]
|
|
72
|
+
file_size_or_zero: Callable[..., Any]
|
|
73
|
+
path_with_ciel_runtime_user_dirs: Callable[..., Any]
|
|
74
|
+
print_routed_claude_exit_diagnostics: Callable[..., Any]
|
|
75
|
+
subprocess_call_with_channel_wake_proxy: Callable[..., Any]
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
@dataclass(frozen=True, slots=True)
|
|
79
|
+
class ClaudeLaunchInstallation:
|
|
80
|
+
find_executable: Callable[..., Any]
|
|
81
|
+
install_ciel_runtime_slash_commands: Callable[..., Any]
|
|
82
|
+
install_ciel_runtime_statusline: Callable[..., Any]
|
|
83
|
+
install_claude_code_if_missing: Callable[..., Any]
|
|
84
|
+
install_tool_guard_hooks: Callable[..., Any]
|
|
85
|
+
disable_ciel_runtime_slash_commands_for_native: Callable[..., Any]
|
|
86
|
+
launch_readiness_errors: Callable[..., Any]
|
|
87
|
+
warn_if_multiple_ciel_runtime_installs: Callable[..., Any]
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
@dataclass(frozen=True, slots=True)
|
|
91
|
+
class ClaudeLaunchDispatch:
|
|
92
|
+
launch_agy: Callable[..., Any]
|
|
93
|
+
launch_codex: Callable[..., Any]
|
|
94
|
+
launch_codex_app_server: Callable[..., Any]
|
|
95
|
+
materialize_runtime_command: Callable[..., Any]
|
|
96
|
+
run_ciel_runtime_update_check: Callable[..., Any]
|
|
97
|
+
run_claude_update_check: Callable[..., Any]
|
|
98
|
+
run_prelaunch_menu: Callable[..., Any]
|
|
99
|
+
claude_launch_enabled_for_provider: Callable[..., Any]
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
@dataclass(frozen=True, slots=True)
|
|
103
|
+
class ClaudeLaunchConfig:
|
|
104
|
+
load_config: Callable[..., Any]
|
|
105
|
+
save_config: Callable[..., Any]
|
|
106
|
+
get_current_provider: Callable[..., Any]
|
|
107
|
+
ensure_current_model_from_provider_list: Callable[..., Any]
|
|
108
|
+
ensure_model_cache_for_launch: Callable[..., Any]
|
|
109
|
+
apply_launch_endpoint_policy: Callable[..., Any]
|
|
110
|
+
provider_menu_label: Callable[..., Any]
|
|
111
|
+
launch_mode_name: Callable[..., Any]
|
|
112
|
+
current_launch_cwd_key: Callable[..., Any]
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
@dataclass(frozen=True, slots=True)
|
|
116
|
+
class ClaudeLaunchRouting:
|
|
117
|
+
anthropic_routed_enabled: Callable[..., Any]
|
|
118
|
+
direct_native_anthropic_enabled: Callable[..., Any]
|
|
119
|
+
cleanup_managed_services_for_provider: Callable[..., Any]
|
|
120
|
+
ensure_managed_router_running_for_client: Callable[..., Any]
|
|
121
|
+
reset_zai_mcp_config_if_inactive: Callable[..., Any]
|
|
122
|
+
router_health_summary: Callable[..., Any]
|
|
123
|
+
router_log: Callable[..., Any]
|
|
124
|
+
start_router_if_needed: Callable[..., Any]
|
|
125
|
+
run_with_router_lifetime: Callable[..., Any]
|
|
126
|
+
record_launch_state_for_cwd: Callable[..., Any]
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
@dataclass(frozen=True, slots=True)
|
|
130
|
+
class ClaudeLaunchPolicy:
|
|
131
|
+
append_claude_code_runtime_settings_args: Callable[..., Any]
|
|
132
|
+
claude_supports_permission_mode_arg: Callable[..., Any]
|
|
133
|
+
has_noninteractive_claude_args: Callable[..., Any]
|
|
134
|
+
has_passthrough_option: Callable[..., Any]
|
|
135
|
+
should_append_compat_prompt: Callable[..., Any]
|
|
136
|
+
should_attach_web_search: Callable[..., Any]
|
|
137
|
+
should_disallow_claude_server_side_web_tools: Callable[..., Any]
|
|
138
|
+
should_fork_native_session_after_mode_switch: Callable[..., Any]
|
|
139
|
+
should_insert_passthrough_option_boundary: Callable[..., Any]
|
|
140
|
+
strip_mcp_config_passthrough: Callable[..., Any]
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
@dataclass(frozen=True, slots=True)
|
|
144
|
+
class ClaudeLaunchChannelDiscovery:
|
|
145
|
+
auto_import_passthrough_channels: Callable[..., Any]
|
|
146
|
+
cached_channel_capable_server_names: Callable[..., Any]
|
|
147
|
+
cached_channel_source_paths_for_specs: Callable[..., Any]
|
|
148
|
+
channel_candidate_server_names_for_launch: Callable[..., Any]
|
|
149
|
+
channel_specs_for_launch: Callable[..., Any]
|
|
150
|
+
claude_channels_requested: Callable[..., Any]
|
|
151
|
+
claude_code_channels_auth_available: Callable[..., Any]
|
|
152
|
+
ensure_channel_probe_cache_for_launch: Callable[..., Any]
|
|
153
|
+
external_mcp_channel_server_names_from_configs: Callable[..., Any]
|
|
154
|
+
read_channel_probe_cache: Callable[..., Any]
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
@dataclass(frozen=True, slots=True)
|
|
158
|
+
class ClaudeLaunchChannelDelivery:
|
|
159
|
+
auto_start_sse_channels_from_mcp_configs: Callable[..., Any]
|
|
160
|
+
claude_channel_args: Callable[..., Any]
|
|
161
|
+
native_channel_passthrough_requested: Callable[..., Any]
|
|
162
|
+
normalize_channel_passthrough: Callable[..., Any]
|
|
163
|
+
prepare_channel_llm_delivery_for_launch: Callable[..., Any]
|
|
164
|
+
should_launch_process_start_channel_sse: Callable[..., Any]
|
|
165
|
+
should_use_channel_llm_delivery: Callable[..., Any]
|
|
166
|
+
should_use_channel_stdin_proxy: Callable[..., Any]
|
|
167
|
+
should_use_native_channel_bridge: Callable[..., Any]
|
|
168
|
+
write_channel_mcp_config: Callable[..., Any]
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
@dataclass(frozen=True, slots=True)
|
|
172
|
+
class ClaudeLaunchMcpConfig:
|
|
173
|
+
write_duckduckgo_mcp_config: Callable[..., Any]
|
|
174
|
+
write_mcp_proxy_config: Callable[..., Any]
|
|
175
|
+
write_native_mcp_config_from_discovery: Callable[..., Any]
|
|
176
|
+
write_zai_mcp_config: Callable[..., Any]
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
@dataclass(frozen=True, slots=True)
|
|
180
|
+
class ClaudeLaunchServices:
|
|
181
|
+
constants: ClaudeLaunchConstants
|
|
182
|
+
process: ClaudeLaunchProcess
|
|
183
|
+
installation: ClaudeLaunchInstallation
|
|
184
|
+
dispatch: ClaudeLaunchDispatch
|
|
185
|
+
config: ClaudeLaunchConfig
|
|
186
|
+
routing: ClaudeLaunchRouting
|
|
187
|
+
policy: ClaudeLaunchPolicy
|
|
188
|
+
channel_discovery: ClaudeLaunchChannelDiscovery
|
|
189
|
+
channel_delivery: ClaudeLaunchChannelDelivery
|
|
190
|
+
mcp_config: ClaudeLaunchMcpConfig
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def run_claude(
|
|
194
|
+
passthrough: list[str],
|
|
195
|
+
skip_menu: bool = False,
|
|
196
|
+
force_menu: bool = False,
|
|
197
|
+
web_search_override: bool | None = None,
|
|
198
|
+
update_check: bool = True,
|
|
199
|
+
self_update_check: bool = True,
|
|
200
|
+
*,
|
|
201
|
+
services: ClaudeLaunchServices,
|
|
202
|
+
) -> int:
|
|
203
|
+
CLAUDE_SERVER_SIDE_WEB_TOOLS = services.constants.CLAUDE_SERVER_SIDE_WEB_TOOLS
|
|
204
|
+
LOG_PATH = services.constants.LOG_PATH
|
|
205
|
+
PRELAUNCH_CANCEL = services.constants.PRELAUNCH_CANCEL
|
|
206
|
+
PRELAUNCH_LAUNCH_AGY = services.constants.PRELAUNCH_LAUNCH_AGY
|
|
207
|
+
PRELAUNCH_LAUNCH_CLAUDE = services.constants.PRELAUNCH_LAUNCH_CLAUDE
|
|
208
|
+
PRELAUNCH_LAUNCH_CODEX = services.constants.PRELAUNCH_LAUNCH_CODEX
|
|
209
|
+
PRELAUNCH_LAUNCH_CODEX_APP_SERVER = services.constants.PRELAUNCH_LAUNCH_CODEX_APP_SERVER
|
|
210
|
+
ROUTED_COMPAT_PROMPT = services.constants.ROUTED_COMPAT_PROMPT
|
|
211
|
+
_NATIVE_ROUTER_CHANNEL_NAMES = services.constants._NATIVE_ROUTER_CHANNEL_NAMES
|
|
212
|
+
_log_claude_command_for_diagnostics = services.process._log_claude_command_for_diagnostics
|
|
213
|
+
_subprocess_call_capturing_stderr = services.process._subprocess_call_capturing_stderr
|
|
214
|
+
anthropic_routed_enabled = services.routing.anthropic_routed_enabled
|
|
215
|
+
append_claude_code_runtime_settings_args = services.policy.append_claude_code_runtime_settings_args
|
|
216
|
+
apply_launch_endpoint_policy = services.config.apply_launch_endpoint_policy
|
|
217
|
+
auto_import_passthrough_channels = services.channel_discovery.auto_import_passthrough_channels
|
|
218
|
+
auto_start_sse_channels_from_mcp_configs = services.channel_delivery.auto_start_sse_channels_from_mcp_configs
|
|
219
|
+
cached_channel_capable_server_names = services.channel_discovery.cached_channel_capable_server_names
|
|
220
|
+
cached_channel_source_paths_for_specs = services.channel_discovery.cached_channel_source_paths_for_specs
|
|
221
|
+
channel_candidate_server_names_for_launch = services.channel_discovery.channel_candidate_server_names_for_launch
|
|
222
|
+
channel_specs_for_launch = services.channel_discovery.channel_specs_for_launch
|
|
223
|
+
claude_channel_args = services.channel_delivery.claude_channel_args
|
|
224
|
+
claude_channels_requested = services.channel_discovery.claude_channels_requested
|
|
225
|
+
claude_code_channels_auth_available = services.channel_discovery.claude_code_channels_auth_available
|
|
226
|
+
claude_launch_enabled_for_provider = services.dispatch.claude_launch_enabled_for_provider
|
|
227
|
+
claude_supports_permission_mode_arg = services.policy.claude_supports_permission_mode_arg
|
|
228
|
+
cleanup_managed_services_for_provider = services.routing.cleanup_managed_services_for_provider
|
|
229
|
+
current_launch_cwd_key = services.config.current_launch_cwd_key
|
|
230
|
+
direct_native_anthropic_enabled = services.routing.direct_native_anthropic_enabled
|
|
231
|
+
disable_ciel_runtime_slash_commands_for_native = services.installation.disable_ciel_runtime_slash_commands_for_native
|
|
232
|
+
ensure_channel_probe_cache_for_launch = services.channel_discovery.ensure_channel_probe_cache_for_launch
|
|
233
|
+
ensure_current_model_from_provider_list = services.config.ensure_current_model_from_provider_list
|
|
234
|
+
ensure_managed_router_running_for_client = services.routing.ensure_managed_router_running_for_client
|
|
235
|
+
ensure_model_cache_for_launch = services.config.ensure_model_cache_for_launch
|
|
236
|
+
env_bool = services.process.env_bool
|
|
237
|
+
env_vars = services.process.env_vars
|
|
238
|
+
external_mcp_channel_server_names_from_configs = services.channel_discovery.external_mcp_channel_server_names_from_configs
|
|
239
|
+
file_size_or_zero = services.process.file_size_or_zero
|
|
240
|
+
find_executable = services.installation.find_executable
|
|
241
|
+
get_current_provider = services.config.get_current_provider
|
|
242
|
+
has_noninteractive_claude_args = services.policy.has_noninteractive_claude_args
|
|
243
|
+
has_passthrough_option = services.policy.has_passthrough_option
|
|
244
|
+
install_ciel_runtime_slash_commands = services.installation.install_ciel_runtime_slash_commands
|
|
245
|
+
install_ciel_runtime_statusline = services.installation.install_ciel_runtime_statusline
|
|
246
|
+
install_claude_code_if_missing = services.installation.install_claude_code_if_missing
|
|
247
|
+
install_tool_guard_hooks = services.installation.install_tool_guard_hooks
|
|
248
|
+
launch_agy = services.dispatch.launch_agy
|
|
249
|
+
launch_codex = services.dispatch.launch_codex
|
|
250
|
+
launch_codex_app_server = services.dispatch.launch_codex_app_server
|
|
251
|
+
launch_mode_name = services.config.launch_mode_name
|
|
252
|
+
launch_readiness_errors = services.installation.launch_readiness_errors
|
|
253
|
+
load_config = services.config.load_config
|
|
254
|
+
materialize_runtime_command = services.dispatch.materialize_runtime_command
|
|
255
|
+
native_channel_passthrough_requested = services.channel_delivery.native_channel_passthrough_requested
|
|
256
|
+
normalize_channel_passthrough = services.channel_delivery.normalize_channel_passthrough
|
|
257
|
+
path_with_ciel_runtime_user_dirs = services.process.path_with_ciel_runtime_user_dirs
|
|
258
|
+
prepare_channel_llm_delivery_for_launch = services.channel_delivery.prepare_channel_llm_delivery_for_launch
|
|
259
|
+
print_routed_claude_exit_diagnostics = services.process.print_routed_claude_exit_diagnostics
|
|
260
|
+
provider_menu_label = services.config.provider_menu_label
|
|
261
|
+
read_channel_probe_cache = services.channel_discovery.read_channel_probe_cache
|
|
262
|
+
record_launch_state_for_cwd = services.routing.record_launch_state_for_cwd
|
|
263
|
+
reset_zai_mcp_config_if_inactive = services.routing.reset_zai_mcp_config_if_inactive
|
|
264
|
+
router_health_summary = services.routing.router_health_summary
|
|
265
|
+
router_log = services.routing.router_log
|
|
266
|
+
run_ciel_runtime_update_check = services.dispatch.run_ciel_runtime_update_check
|
|
267
|
+
run_claude_update_check = services.dispatch.run_claude_update_check
|
|
268
|
+
run_prelaunch_menu = services.dispatch.run_prelaunch_menu
|
|
269
|
+
run_with_router_lifetime = services.routing.run_with_router_lifetime
|
|
270
|
+
save_config = services.config.save_config
|
|
271
|
+
should_append_compat_prompt = services.policy.should_append_compat_prompt
|
|
272
|
+
should_attach_web_search = services.policy.should_attach_web_search
|
|
273
|
+
should_disallow_claude_server_side_web_tools = services.policy.should_disallow_claude_server_side_web_tools
|
|
274
|
+
should_fork_native_session_after_mode_switch = services.policy.should_fork_native_session_after_mode_switch
|
|
275
|
+
should_insert_passthrough_option_boundary = services.policy.should_insert_passthrough_option_boundary
|
|
276
|
+
should_launch_process_start_channel_sse = services.channel_delivery.should_launch_process_start_channel_sse
|
|
277
|
+
should_use_channel_llm_delivery = services.channel_delivery.should_use_channel_llm_delivery
|
|
278
|
+
should_use_channel_stdin_proxy = services.channel_delivery.should_use_channel_stdin_proxy
|
|
279
|
+
should_use_native_channel_bridge = services.channel_delivery.should_use_native_channel_bridge
|
|
280
|
+
start_router_if_needed = services.routing.start_router_if_needed
|
|
281
|
+
strip_mcp_config_passthrough = services.policy.strip_mcp_config_passthrough
|
|
282
|
+
subprocess_call_with_channel_wake_proxy = services.process.subprocess_call_with_channel_wake_proxy
|
|
283
|
+
warn_if_multiple_ciel_runtime_installs = services.installation.warn_if_multiple_ciel_runtime_installs
|
|
284
|
+
write_channel_mcp_config = services.channel_delivery.write_channel_mcp_config
|
|
285
|
+
write_duckduckgo_mcp_config = services.mcp_config.write_duckduckgo_mcp_config
|
|
286
|
+
write_mcp_proxy_config = services.mcp_config.write_mcp_proxy_config
|
|
287
|
+
write_native_mcp_config_from_discovery = services.mcp_config.write_native_mcp_config_from_discovery
|
|
288
|
+
write_zai_mcp_config = services.mcp_config.write_zai_mcp_config
|
|
289
|
+
if has_noninteractive_claude_args(passthrough):
|
|
290
|
+
self_update_check = False
|
|
291
|
+
warn_if_multiple_ciel_runtime_installs()
|
|
292
|
+
run_ciel_runtime_update_check(enabled=self_update_check)
|
|
293
|
+
auto_import_passthrough_channels(passthrough)
|
|
294
|
+
rc = run_prelaunch_menu(passthrough, skip_menu=skip_menu, force_menu=force_menu)
|
|
295
|
+
if rc == PRELAUNCH_LAUNCH_CODEX:
|
|
296
|
+
return launch_codex(
|
|
297
|
+
passthrough,
|
|
298
|
+
skip_menu=True,
|
|
299
|
+
force_menu=False,
|
|
300
|
+
update_check=update_check,
|
|
301
|
+
self_update_check=False,
|
|
302
|
+
)
|
|
303
|
+
if rc == PRELAUNCH_LAUNCH_AGY:
|
|
304
|
+
return launch_agy(
|
|
305
|
+
passthrough,
|
|
306
|
+
skip_menu=True,
|
|
307
|
+
force_menu=False,
|
|
308
|
+
update_check=update_check,
|
|
309
|
+
self_update_check=False,
|
|
310
|
+
)
|
|
311
|
+
if rc == PRELAUNCH_LAUNCH_CODEX_APP_SERVER:
|
|
312
|
+
return launch_codex_app_server(
|
|
313
|
+
passthrough,
|
|
314
|
+
skip_menu=True,
|
|
315
|
+
force_menu=False,
|
|
316
|
+
update_check=update_check,
|
|
317
|
+
self_update_check=False,
|
|
318
|
+
)
|
|
319
|
+
if rc == PRELAUNCH_CANCEL:
|
|
320
|
+
return 0
|
|
321
|
+
if rc not in (0, PRELAUNCH_LAUNCH_CLAUDE):
|
|
322
|
+
return rc
|
|
323
|
+
cfg = load_config()
|
|
324
|
+
provider, pcfg = get_current_provider(cfg)
|
|
325
|
+
for line in apply_launch_endpoint_policy(cfg, "claude"):
|
|
326
|
+
print(line, flush=True)
|
|
327
|
+
provider, pcfg = get_current_provider(cfg)
|
|
328
|
+
if not claude_launch_enabled_for_provider(provider):
|
|
329
|
+
print(f"Ciel Runtime launch blocked: Launch Claude Code is disabled while {provider_menu_label(provider, pcfg)} provider is selected.", flush=True)
|
|
330
|
+
print("Use the matching Launch menu item or --ca-runtime agy|codex|codex-app-server.", flush=True)
|
|
331
|
+
return 2
|
|
332
|
+
blockers = launch_readiness_errors(cfg)
|
|
333
|
+
if blockers:
|
|
334
|
+
print("Ciel Runtime launch blocked:", flush=True)
|
|
335
|
+
for line in blockers:
|
|
336
|
+
print(f"- {line}", flush=True)
|
|
337
|
+
return 2
|
|
338
|
+
use_native_anthropic = direct_native_anthropic_enabled(provider, pcfg)
|
|
339
|
+
use_router_mode = not use_native_anthropic
|
|
340
|
+
launch_cwd_key = current_launch_cwd_key()
|
|
341
|
+
fork_native_session, previous_launch_mode = should_fork_native_session_after_mode_switch(
|
|
342
|
+
provider,
|
|
343
|
+
pcfg,
|
|
344
|
+
use_native_anthropic,
|
|
345
|
+
passthrough,
|
|
346
|
+
launch_cwd_key,
|
|
347
|
+
)
|
|
348
|
+
cleanup_managed_services_for_provider(provider, pcfg, cfg, quiet=True)
|
|
349
|
+
env = os.environ.copy()
|
|
350
|
+
env["PATH"] = path_with_ciel_runtime_user_dirs(env)
|
|
351
|
+
launch_passthrough = normalize_channel_passthrough(passthrough)
|
|
352
|
+
native_channel_bridge = should_use_native_channel_bridge(use_router_mode, cfg, launch_passthrough)
|
|
353
|
+
stdin_channel_proxy = should_use_channel_stdin_proxy(use_router_mode, launch_passthrough, cfg)
|
|
354
|
+
llm_channel_delivery = should_use_channel_llm_delivery(use_router_mode, launch_passthrough, cfg)
|
|
355
|
+
native_auto_channel_specs: list[str] = []
|
|
356
|
+
if use_native_anthropic and not native_channel_bridge and not native_channel_passthrough_requested(launch_passthrough):
|
|
357
|
+
try:
|
|
358
|
+
auto_channel_names = external_mcp_channel_server_names_from_configs(launch_passthrough)
|
|
359
|
+
native_auto_channel_specs = [f"server:{name}" for name in auto_channel_names]
|
|
360
|
+
if native_auto_channel_specs:
|
|
361
|
+
router_log(
|
|
362
|
+
"INFO",
|
|
363
|
+
"channel_native_auto_specs servers=%s" % ",".join(auto_channel_names),
|
|
364
|
+
)
|
|
365
|
+
except Exception as exc:
|
|
366
|
+
router_log("WARN", f"channel_native_auto_probe_failed error={type(exc).__name__}: {exc}")
|
|
367
|
+
manage_router_lifetime = False
|
|
368
|
+
if use_router_mode or llm_channel_delivery:
|
|
369
|
+
manage_router_lifetime = bool(start_router_if_needed())
|
|
370
|
+
elif web_backend_start_requested(cfg):
|
|
371
|
+
manage_router_lifetime = bool(
|
|
372
|
+
start_router_if_needed(replace_active_clients=False)
|
|
373
|
+
)
|
|
374
|
+
if not use_native_anthropic:
|
|
375
|
+
ensure_model_cache_for_launch(provider, pcfg)
|
|
376
|
+
selected, selection_lines = ensure_current_model_from_provider_list(provider, pcfg)
|
|
377
|
+
if selection_lines:
|
|
378
|
+
for line in selection_lines:
|
|
379
|
+
print(line)
|
|
380
|
+
save_config(cfg)
|
|
381
|
+
if not selected:
|
|
382
|
+
raise RuntimeError(
|
|
383
|
+
f"No concrete model is selected for provider {provider}; choose a model from the provider model list before launching Claude Code."
|
|
384
|
+
)
|
|
385
|
+
launch_env = env_vars(cfg)
|
|
386
|
+
if claude_channels_requested(cfg, launch_passthrough) or native_channel_bridge or llm_channel_delivery or native_auto_channel_specs:
|
|
387
|
+
env.pop("CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS", None)
|
|
388
|
+
launch_env.pop("CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS", None)
|
|
389
|
+
if use_native_anthropic:
|
|
390
|
+
# Claude Native guarantee — strip every env var ciel-runtime (or a
|
|
391
|
+
# prior ciel-runtime session) might have left behind that would change
|
|
392
|
+
# Claude Code's default model selection, backend, advisor flow, or
|
|
393
|
+
# other behavior. See env_vars() docstring for the contract.
|
|
394
|
+
for key in (
|
|
395
|
+
"ANTHROPIC_BASE_URL",
|
|
396
|
+
"ANTHROPIC_MODEL",
|
|
397
|
+
"ANTHROPIC_CUSTOM_MODEL_OPTION",
|
|
398
|
+
"ANTHROPIC_CUSTOM_MODEL_OPTION_SUPPORTED_CAPABILITIES",
|
|
399
|
+
"ANTHROPIC_DEFAULT_HAIKU_MODEL",
|
|
400
|
+
"ANTHROPIC_DEFAULT_HAIKU_MODEL_SUPPORTS",
|
|
401
|
+
"ANTHROPIC_DEFAULT_HAIKU_MODEL_SUPPORTED_CAPABILITIES",
|
|
402
|
+
"ANTHROPIC_DEFAULT_OPUS_MODEL",
|
|
403
|
+
"ANTHROPIC_DEFAULT_OPUS_MODEL_SUPPORTS",
|
|
404
|
+
"ANTHROPIC_DEFAULT_OPUS_MODEL_SUPPORTED_CAPABILITIES",
|
|
405
|
+
"ANTHROPIC_DEFAULT_SONNET_MODEL",
|
|
406
|
+
"ANTHROPIC_DEFAULT_SONNET_MODEL_SUPPORTS",
|
|
407
|
+
"ANTHROPIC_DEFAULT_SONNET_MODEL_SUPPORTED_CAPABILITIES",
|
|
408
|
+
"CLAUDE_CODE_SUBAGENT_MODEL",
|
|
409
|
+
"CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY",
|
|
410
|
+
"CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS",
|
|
411
|
+
"CLAUDE_CODE_MAX_OUTPUT_TOKENS",
|
|
412
|
+
"CLAUDE_CODE_AUTO_COMPACT_WINDOW",
|
|
413
|
+
"CLAUDE_CODE_MAX_CONTEXT_TOKENS",
|
|
414
|
+
"CLAUDE_CODE_EFFORT_LEVEL",
|
|
415
|
+
"CLAUDE_CODE_DISABLE_TERMINAL_TITLE",
|
|
416
|
+
"CLAUDE_CODE_ATTRIBUTION_HEADER",
|
|
417
|
+
"CIEL_RUNTIME_ADVISOR_MODEL",
|
|
418
|
+
"CIEL_RUNTIME_BYPASS_PERMISSIONS",
|
|
419
|
+
"CIEL_RUNTIME_MODEL_ALIAS",
|
|
420
|
+
):
|
|
421
|
+
env.pop(key, None)
|
|
422
|
+
launch_env.pop(key, None)
|
|
423
|
+
if "ANTHROPIC_API_KEY" in launch_env:
|
|
424
|
+
env.pop("ANTHROPIC_AUTH_TOKEN", None)
|
|
425
|
+
router_log(
|
|
426
|
+
"INFO",
|
|
427
|
+
"claude_native_launch model=<defer-to-claude-code> advisor=off backend=<default-anthropic>",
|
|
428
|
+
)
|
|
429
|
+
disable_ciel_runtime_slash_commands_for_native()
|
|
430
|
+
elif anthropic_routed_enabled(provider, pcfg):
|
|
431
|
+
router_log(
|
|
432
|
+
"INFO",
|
|
433
|
+
"claude_anthropic_routed_launch backend=ciel-runtime-router upstream=anthropic",
|
|
434
|
+
)
|
|
435
|
+
env.update(launch_env)
|
|
436
|
+
if not use_native_anthropic:
|
|
437
|
+
preserve_anthropic_auth = anthropic_routed_enabled(provider, pcfg)
|
|
438
|
+
for key in ("ANTHROPIC_API_KEY", "ANTHROPIC_AUTH_TOKEN"):
|
|
439
|
+
if key not in launch_env and not preserve_anthropic_auth:
|
|
440
|
+
env.pop(key, None)
|
|
441
|
+
install_ciel_runtime_slash_commands(include_advisor=provider != "anthropic")
|
|
442
|
+
install_tool_guard_hooks()
|
|
443
|
+
install_ciel_runtime_statusline()
|
|
444
|
+
claude = install_claude_code_if_missing()
|
|
445
|
+
if not claude:
|
|
446
|
+
raise RuntimeError(
|
|
447
|
+
"claude executable was not found in PATH or the Ciel Runtime user bin directories, "
|
|
448
|
+
"and automatic install of @anthropic-ai/claude-code did not make it available"
|
|
449
|
+
)
|
|
450
|
+
updated_claude = run_claude_update_check(claude, enabled=update_check)
|
|
451
|
+
if isinstance(updated_claude, str) and updated_claude:
|
|
452
|
+
claude = updated_claude
|
|
453
|
+
claude = find_executable("claude") or claude
|
|
454
|
+
if native_channel_bridge or native_auto_channel_specs:
|
|
455
|
+
auth_ok, auth_reason = claude_code_channels_auth_available(claude)
|
|
456
|
+
if not auth_ok:
|
|
457
|
+
if native_channel_bridge:
|
|
458
|
+
router_log("WARN", f"channel_native_unavailable_fallback reason={auth_reason} delivery=llm")
|
|
459
|
+
native_channel_bridge = False
|
|
460
|
+
llm_channel_delivery = True
|
|
461
|
+
else:
|
|
462
|
+
router_log("WARN", f"channel_native_auto_disabled reason={auth_reason}")
|
|
463
|
+
native_auto_channel_specs = []
|
|
464
|
+
extra_args: list[str] = []
|
|
465
|
+
mcp_config_paths: list[str] = []
|
|
466
|
+
reset_zai_mcp_config_if_inactive(provider)
|
|
467
|
+
zai_mcp_config = write_zai_mcp_config(provider, pcfg)
|
|
468
|
+
if zai_mcp_config:
|
|
469
|
+
mcp_config_paths.append(str(zai_mcp_config))
|
|
470
|
+
if should_attach_web_search(provider, cfg, web_search_override):
|
|
471
|
+
mcp_config_paths.append(str(write_duckduckgo_mcp_config(cfg)))
|
|
472
|
+
if llm_channel_delivery:
|
|
473
|
+
mcp_config_paths.append(str(write_channel_mcp_config()))
|
|
474
|
+
native_direct_mcp_config_paths: list[str] = []
|
|
475
|
+
if use_native_anthropic:
|
|
476
|
+
native_mcp_config = write_native_mcp_config_from_discovery(launch_passthrough)
|
|
477
|
+
if native_mcp_config:
|
|
478
|
+
native_direct_mcp_config_paths = [str(native_mcp_config)]
|
|
479
|
+
detected_channel_specs: list[str] = []
|
|
480
|
+
detected_channel_capable_names: list[str] = []
|
|
481
|
+
channel_probe_source_paths: list[Path] = []
|
|
482
|
+
if stdin_channel_proxy or llm_channel_delivery:
|
|
483
|
+
try:
|
|
484
|
+
candidate_channel_names = channel_candidate_server_names_for_launch(cfg, launch_passthrough)
|
|
485
|
+
ensure_channel_probe_cache_for_launch(cfg, launch_passthrough)
|
|
486
|
+
capable_names = cached_channel_capable_server_names()
|
|
487
|
+
capable_name_set = set(capable_names)
|
|
488
|
+
detected_channel_capable_names = [
|
|
489
|
+
name for name in candidate_channel_names
|
|
490
|
+
if name in capable_name_set and name.strip().lower() not in _NATIVE_ROUTER_CHANNEL_NAMES
|
|
491
|
+
]
|
|
492
|
+
detected_channel_specs = [f"server:{name}" for name in detected_channel_capable_names]
|
|
493
|
+
channel_launch_specs = channel_specs_for_launch(cfg, launch_passthrough, detected_channel_specs)
|
|
494
|
+
channel_probe_source_paths = cached_channel_source_paths_for_specs(channel_launch_specs)
|
|
495
|
+
if channel_probe_source_paths:
|
|
496
|
+
mcp_config_paths.extend(str(path) for path in channel_probe_source_paths)
|
|
497
|
+
cache_age = read_channel_probe_cache().get("probed_at") or 0
|
|
498
|
+
router_log(
|
|
499
|
+
"INFO",
|
|
500
|
+
"channel_probe_loaded source=cache cache_age_ts=%d count=%d servers=%s sources=%s"
|
|
501
|
+
% (
|
|
502
|
+
int(cache_age),
|
|
503
|
+
len(detected_channel_capable_names),
|
|
504
|
+
",".join(detected_channel_capable_names) or "-",
|
|
505
|
+
",".join(str(path) for path in channel_probe_source_paths) or "-",
|
|
506
|
+
),
|
|
507
|
+
)
|
|
508
|
+
except Exception as exc:
|
|
509
|
+
router_log("WARN", f"channel_probe_cache_load_failed error={type(exc).__name__}: {exc}")
|
|
510
|
+
claude_passthrough = list(launch_passthrough)
|
|
511
|
+
if use_native_anthropic:
|
|
512
|
+
if native_direct_mcp_config_paths:
|
|
513
|
+
mcp_config_paths.extend(native_direct_mcp_config_paths)
|
|
514
|
+
claude_passthrough = strip_mcp_config_passthrough(launch_passthrough)
|
|
515
|
+
elif stdin_channel_proxy or llm_channel_delivery or native_auto_channel_specs:
|
|
516
|
+
if llm_channel_delivery:
|
|
517
|
+
prepare_channel_llm_delivery_for_launch()
|
|
518
|
+
if should_launch_process_start_channel_sse(stdin_channel_proxy, native_channel_bridge, llm_channel_delivery):
|
|
519
|
+
auto_start_sse_channels_from_mcp_configs(
|
|
520
|
+
launch_passthrough,
|
|
521
|
+
extra_config_paths=[Path(path) for path in mcp_config_paths],
|
|
522
|
+
)
|
|
523
|
+
else:
|
|
524
|
+
router_log("INFO", "channel_sse_auto_start_skipped reason=router_managed_llm_delivery")
|
|
525
|
+
# Channel-capable streamable-HTTP backends (e.g. ai-net-http) are forced
|
|
526
|
+
# through ciel-runtime's own mcp-proxy so there is exactly ONE backend
|
|
527
|
+
# connection: the proxy serves Claude Code's tool calls AND owns the
|
|
528
|
+
# notification stream + idle-death wake handling. Because the proxy now
|
|
529
|
+
# OWNS the stream, it must NOT also be in the disable set -- forcing a
|
|
530
|
+
# server while disabling its stream would leave zero notification owners
|
|
531
|
+
# and the agent would never wake. force and disable are mutually
|
|
532
|
+
# exclusive per server, so the disable set excludes anything we force.
|
|
533
|
+
forced_channel_names = (
|
|
534
|
+
set(detected_channel_capable_names)
|
|
535
|
+
if (stdin_channel_proxy or llm_channel_delivery)
|
|
536
|
+
else set()
|
|
537
|
+
)
|
|
538
|
+
proxy_config = write_mcp_proxy_config(
|
|
539
|
+
launch_passthrough,
|
|
540
|
+
extra_config_paths=[Path(path) for path in mcp_config_paths],
|
|
541
|
+
force_proxy_server_names=forced_channel_names or None,
|
|
542
|
+
disable_proxy_notification_stream_names=None,
|
|
543
|
+
)
|
|
544
|
+
if proxy_config:
|
|
545
|
+
mcp_config_paths = [str(proxy_config)]
|
|
546
|
+
claude_passthrough = strip_mcp_config_passthrough(launch_passthrough)
|
|
547
|
+
if mcp_config_paths:
|
|
548
|
+
extra_args.extend(["--mcp-config", *mcp_config_paths])
|
|
549
|
+
if should_append_compat_prompt(provider, pcfg, cfg) and not has_passthrough_option(launch_passthrough, "--system-prompt"):
|
|
550
|
+
extra_args.extend(["--append-system-prompt", ROUTED_COMPAT_PROMPT])
|
|
551
|
+
extra_args.extend(
|
|
552
|
+
claude_channel_args(
|
|
553
|
+
cfg,
|
|
554
|
+
launch_passthrough,
|
|
555
|
+
extra_specs=native_auto_channel_specs if native_auto_channel_specs else detected_channel_specs,
|
|
556
|
+
native_channel_bridge=bool(native_channel_bridge or native_auto_channel_specs),
|
|
557
|
+
)
|
|
558
|
+
)
|
|
559
|
+
append_claude_code_runtime_settings_args(extra_args, launch_passthrough, provider, pcfg)
|
|
560
|
+
if fork_native_session:
|
|
561
|
+
session_id = str(uuid.uuid4())
|
|
562
|
+
extra_args.extend(["--session-id", session_id])
|
|
563
|
+
router_log(
|
|
564
|
+
"INFO",
|
|
565
|
+
f"claude_native_session_boundary previous_mode={previous_launch_mode} cwd={launch_cwd_key} session_id={session_id}",
|
|
566
|
+
)
|
|
567
|
+
bypass_permission_mode = (
|
|
568
|
+
not use_native_anthropic
|
|
569
|
+
and not has_passthrough_option([*extra_args, *claude_passthrough], "--permission-mode")
|
|
570
|
+
and claude_supports_permission_mode_arg(claude)
|
|
571
|
+
)
|
|
572
|
+
disallowed_tools = ""
|
|
573
|
+
if (
|
|
574
|
+
should_disallow_claude_server_side_web_tools(provider, pcfg, use_native_anthropic)
|
|
575
|
+
and not has_passthrough_option([*extra_args, *claude_passthrough], "--disallowedTools", "--disallowed-tools")
|
|
576
|
+
):
|
|
577
|
+
disallowed_tools = ",".join(CLAUDE_SERVER_SIDE_WEB_TOOLS)
|
|
578
|
+
model = env.get("CIEL_RUNTIME_MODEL_ALIAS")
|
|
579
|
+
cmd, env = materialize_runtime_command(
|
|
580
|
+
"claude",
|
|
581
|
+
claude,
|
|
582
|
+
env,
|
|
583
|
+
provider,
|
|
584
|
+
pcfg,
|
|
585
|
+
mode="native" if use_native_anthropic else "routed",
|
|
586
|
+
protocol="anthropic_messages",
|
|
587
|
+
cwd=Path.cwd(),
|
|
588
|
+
enable_channels=bool(stdin_channel_proxy or native_channel_bridge or llm_channel_delivery),
|
|
589
|
+
passthrough=claude_passthrough,
|
|
590
|
+
options={
|
|
591
|
+
"bypass_permission_mode": bypass_permission_mode,
|
|
592
|
+
"disallowed_tools": disallowed_tools,
|
|
593
|
+
"model": model or "",
|
|
594
|
+
"extra_args": tuple(extra_args),
|
|
595
|
+
"passthrough_boundary": should_insert_passthrough_option_boundary(extra_args, claude_passthrough),
|
|
596
|
+
},
|
|
597
|
+
)
|
|
598
|
+
_log_claude_command_for_diagnostics(cmd, env)
|
|
599
|
+
record_launch_state_for_cwd(
|
|
600
|
+
launch_cwd_key,
|
|
601
|
+
provider,
|
|
602
|
+
launch_mode_name(provider, pcfg, use_native_anthropic),
|
|
603
|
+
str(pcfg.get("current_model") or env.get("CIEL_RUNTIME_MODEL_ALIAS") or ""),
|
|
604
|
+
)
|
|
605
|
+
launch_log_offset = file_size_or_zero(LOG_PATH)
|
|
606
|
+
capture_stderr = env_bool(os.environ.get("CIEL_RUNTIME_CAPTURE_CC_STDERR"), False)
|
|
607
|
+
def run_claude_process() -> int:
|
|
608
|
+
rc = 1
|
|
609
|
+
try:
|
|
610
|
+
if use_router_mode and not ensure_managed_router_running_for_client():
|
|
611
|
+
print(
|
|
612
|
+
"Ciel Runtime warning: local router health check failed immediately before launching Claude Code.",
|
|
613
|
+
flush=True,
|
|
614
|
+
)
|
|
615
|
+
print(f" {router_health_summary()}", flush=True)
|
|
616
|
+
if stdin_channel_proxy:
|
|
617
|
+
rc = subprocess_call_with_channel_wake_proxy(cmd, env, wake_for_llm_delivery=llm_channel_delivery)
|
|
618
|
+
elif capture_stderr:
|
|
619
|
+
rc = _subprocess_call_capturing_stderr(cmd, env)
|
|
620
|
+
else:
|
|
621
|
+
rc = subprocess.call(cmd, env=env)
|
|
622
|
+
return rc
|
|
623
|
+
finally:
|
|
624
|
+
if use_router_mode:
|
|
625
|
+
print_routed_claude_exit_diagnostics(rc, provider, pcfg, log_offset=launch_log_offset)
|
|
626
|
+
|
|
627
|
+
return run_with_router_lifetime(run_claude_process, manage_router_lifetime)
|
|
628
|
+
|
|
629
|
+
|
|
630
|
+
|
|
631
|
+
@dataclass(frozen=True, slots=True)
|
|
632
|
+
class CodexLaunchConstants:
|
|
633
|
+
CODEX_RUNTIME_API_KEY_ENV: Any
|
|
634
|
+
CONFIG_DIR: Any
|
|
635
|
+
PRELAUNCH_CANCEL: Any
|
|
636
|
+
PRELAUNCH_LAUNCH_AGY: Any
|
|
637
|
+
PRELAUNCH_LAUNCH_CLAUDE: Any
|
|
638
|
+
PRELAUNCH_LAUNCH_CODEX: Any
|
|
639
|
+
PRELAUNCH_LAUNCH_CODEX_APP_SERVER: Any
|
|
640
|
+
|
|
641
|
+
|
|
642
|
+
def build_default_codex_launch_constants() -> CodexLaunchConstants:
|
|
643
|
+
"""Build immutable Codex and App Server launch constants."""
|
|
644
|
+
return CodexLaunchConstants(
|
|
645
|
+
CODEX_RUNTIME_API_KEY_ENV=CODEX_RUNTIME_API_KEY_ENV,
|
|
646
|
+
CONFIG_DIR=CONFIG_DIR,
|
|
647
|
+
PRELAUNCH_CANCEL=PRELAUNCH_CANCEL,
|
|
648
|
+
PRELAUNCH_LAUNCH_AGY=PRELAUNCH_LAUNCH_AGY,
|
|
649
|
+
PRELAUNCH_LAUNCH_CLAUDE=PRELAUNCH_LAUNCH_CLAUDE,
|
|
650
|
+
PRELAUNCH_LAUNCH_CODEX=PRELAUNCH_LAUNCH_CODEX,
|
|
651
|
+
PRELAUNCH_LAUNCH_CODEX_APP_SERVER=PRELAUNCH_LAUNCH_CODEX_APP_SERVER,
|
|
652
|
+
)
|
|
653
|
+
|
|
654
|
+
|
|
655
|
+
@dataclass(frozen=True, slots=True)
|
|
656
|
+
class CodexLaunchProcess:
|
|
657
|
+
_channel_wake_enter_env_is_fixed: Callable[..., Any]
|
|
658
|
+
_codex_channel_wake_submit_delay_seconds: Callable[..., Any]
|
|
659
|
+
_codex_channel_wake_submit_retries: Callable[..., Any]
|
|
660
|
+
_log_codex_command_for_diagnostics: Callable[..., Any]
|
|
661
|
+
_set_channel_transcript_scope: Callable[..., Any]
|
|
662
|
+
codex_process_record_path: Callable[..., Any]
|
|
663
|
+
path_with_ciel_runtime_user_dirs: Callable[..., Any]
|
|
664
|
+
subprocess_call_with_channel_wake_proxy: Callable[..., Any]
|
|
665
|
+
terminate_existing_codex_processes_for_launch: Callable[..., Any]
|
|
666
|
+
terminate_existing_router_clients_for_launch: Callable[..., Any]
|
|
667
|
+
|
|
668
|
+
|
|
669
|
+
@dataclass(frozen=True, slots=True)
|
|
670
|
+
class CodexLaunchCliPolicy:
|
|
671
|
+
codex_alternate_screen_compat_args: Callable[..., Any]
|
|
672
|
+
codex_current_model_cli_args: Callable[..., Any]
|
|
673
|
+
codex_help_requested: Callable[..., Any]
|
|
674
|
+
codex_native_routed_config_args: Callable[..., Any]
|
|
675
|
+
codex_passthrough_args_for_launch: Callable[..., Any]
|
|
676
|
+
codex_passthrough_has_command: Callable[..., Any]
|
|
677
|
+
codex_resume_picker_requested: Callable[..., Any]
|
|
678
|
+
codex_resume_with_session_id: Callable[..., Any]
|
|
679
|
+
codex_runtime_config_args: Callable[..., Any]
|
|
680
|
+
codex_yolo_launch_args: Callable[..., Any]
|
|
681
|
+
|
|
682
|
+
|
|
683
|
+
@dataclass(frozen=True, slots=True)
|
|
684
|
+
class CodexLaunchConfig:
|
|
685
|
+
apply_launch_endpoint_policy: Callable[..., Any]
|
|
686
|
+
current_alias: Callable[..., Any]
|
|
687
|
+
current_launch_cwd_key: Callable[..., Any]
|
|
688
|
+
ensure_model_cache_for_launch: Callable[..., Any]
|
|
689
|
+
get_current_provider: Callable[..., Any]
|
|
690
|
+
load_config: Callable[..., Any]
|
|
691
|
+
provider_mode_label: Callable[..., Any]
|
|
692
|
+
record_launch_state_for_cwd: Callable[..., Any]
|
|
693
|
+
codex_runtime_model_catalog_args: Callable[..., Any]
|
|
694
|
+
|
|
695
|
+
|
|
696
|
+
@dataclass(frozen=True, slots=True)
|
|
697
|
+
class CodexLaunchInstallation:
|
|
698
|
+
disable_ciel_runtime_codex_prompts_for_native: Callable[..., Any]
|
|
699
|
+
find_executable: Callable[..., Any]
|
|
700
|
+
has_passthrough_option: Callable[..., Any]
|
|
701
|
+
install_ciel_runtime_codex_prompts: Callable[..., Any]
|
|
702
|
+
install_codex_if_missing: Callable[..., Any]
|
|
703
|
+
warn_if_multiple_ciel_runtime_installs: Callable[..., Any]
|
|
704
|
+
|
|
705
|
+
|
|
706
|
+
@dataclass(frozen=True, slots=True)
|
|
707
|
+
class CodexLaunchDispatch:
|
|
708
|
+
launch_agy: Callable[..., Any]
|
|
709
|
+
launch_claude: Callable[..., Any]
|
|
710
|
+
launch_codex_app_server: Callable[..., Any]
|
|
711
|
+
log_codex_passthrough_mapping: Callable[..., Any]
|
|
712
|
+
materialize_runtime_command: Callable[..., Any]
|
|
713
|
+
run_ciel_runtime_update_check: Callable[..., Any]
|
|
714
|
+
run_codex_update_check: Callable[..., Any]
|
|
715
|
+
run_prelaunch_menu: Callable[..., Any]
|
|
716
|
+
|
|
717
|
+
|
|
718
|
+
@dataclass(frozen=True, slots=True)
|
|
719
|
+
class CodexLaunchRouting:
|
|
720
|
+
cleanup_managed_services_for_provider: Callable[..., Any]
|
|
721
|
+
codex_routed_enabled: Callable[..., Any]
|
|
722
|
+
direct_native_codex_enabled: Callable[..., Any]
|
|
723
|
+
launch_readiness_errors: Callable[..., Any]
|
|
724
|
+
native_codex_enabled: Callable[..., Any]
|
|
725
|
+
run_with_router_lifetime: Callable[..., Any]
|
|
726
|
+
start_router_if_needed: Callable[..., Any]
|
|
727
|
+
|
|
728
|
+
|
|
729
|
+
@dataclass(frozen=True, slots=True)
|
|
730
|
+
class CodexLaunchChannel:
|
|
731
|
+
auto_import_passthrough_channels: Callable[..., Any]
|
|
732
|
+
channel_delivery_mode: Callable[..., Any]
|
|
733
|
+
codex_channel_capable_mcp_server_names: Callable[..., Any]
|
|
734
|
+
codex_mcp_native_http_compat_args: Callable[..., Any]
|
|
735
|
+
codex_mcp_split_proxy_enabled: Callable[..., Any]
|
|
736
|
+
restore_codex_mcp_config_from_managed: Callable[..., Any]
|
|
737
|
+
select_codex_resume_session: Callable[..., Any]
|
|
738
|
+
start_codex_mcp_channel_sse_for_launch: Callable[..., Any]
|
|
739
|
+
write_codex_mcp_config_for_channel_discovery: Callable[..., Any]
|
|
740
|
+
|
|
741
|
+
|
|
742
|
+
@dataclass(frozen=True, slots=True)
|
|
743
|
+
class CodexLaunchServices:
|
|
744
|
+
constants: CodexLaunchConstants
|
|
745
|
+
process: CodexLaunchProcess
|
|
746
|
+
cli_policy: CodexLaunchCliPolicy
|
|
747
|
+
config: CodexLaunchConfig
|
|
748
|
+
installation: CodexLaunchInstallation
|
|
749
|
+
dispatch: CodexLaunchDispatch
|
|
750
|
+
routing: CodexLaunchRouting
|
|
751
|
+
channel: CodexLaunchChannel
|
|
752
|
+
|
|
753
|
+
|
|
754
|
+
def run_codex(
|
|
755
|
+
passthrough: list[str],
|
|
756
|
+
skip_menu: bool = False,
|
|
757
|
+
force_menu: bool = False,
|
|
758
|
+
update_check: bool = True,
|
|
759
|
+
self_update_check: bool = True,
|
|
760
|
+
*,
|
|
761
|
+
services: CodexLaunchServices,
|
|
762
|
+
) -> int:
|
|
763
|
+
CODEX_RUNTIME_API_KEY_ENV = services.constants.CODEX_RUNTIME_API_KEY_ENV
|
|
764
|
+
CONFIG_DIR = services.constants.CONFIG_DIR
|
|
765
|
+
PRELAUNCH_CANCEL = services.constants.PRELAUNCH_CANCEL
|
|
766
|
+
PRELAUNCH_LAUNCH_AGY = services.constants.PRELAUNCH_LAUNCH_AGY
|
|
767
|
+
PRELAUNCH_LAUNCH_CLAUDE = services.constants.PRELAUNCH_LAUNCH_CLAUDE
|
|
768
|
+
PRELAUNCH_LAUNCH_CODEX = services.constants.PRELAUNCH_LAUNCH_CODEX
|
|
769
|
+
PRELAUNCH_LAUNCH_CODEX_APP_SERVER = services.constants.PRELAUNCH_LAUNCH_CODEX_APP_SERVER
|
|
770
|
+
_channel_wake_enter_env_is_fixed = services.process._channel_wake_enter_env_is_fixed
|
|
771
|
+
_codex_channel_wake_submit_delay_seconds = services.process._codex_channel_wake_submit_delay_seconds
|
|
772
|
+
_codex_channel_wake_submit_retries = services.process._codex_channel_wake_submit_retries
|
|
773
|
+
_log_codex_command_for_diagnostics = services.process._log_codex_command_for_diagnostics
|
|
774
|
+
_set_channel_transcript_scope = services.process._set_channel_transcript_scope
|
|
775
|
+
apply_launch_endpoint_policy = services.config.apply_launch_endpoint_policy
|
|
776
|
+
auto_import_passthrough_channels = services.channel.auto_import_passthrough_channels
|
|
777
|
+
channel_delivery_mode = services.channel.channel_delivery_mode
|
|
778
|
+
cleanup_managed_services_for_provider = services.routing.cleanup_managed_services_for_provider
|
|
779
|
+
codex_alternate_screen_compat_args = services.cli_policy.codex_alternate_screen_compat_args
|
|
780
|
+
codex_channel_capable_mcp_server_names = services.channel.codex_channel_capable_mcp_server_names
|
|
781
|
+
codex_current_model_cli_args = services.cli_policy.codex_current_model_cli_args
|
|
782
|
+
codex_help_requested = services.cli_policy.codex_help_requested
|
|
783
|
+
codex_mcp_native_http_compat_args = services.channel.codex_mcp_native_http_compat_args
|
|
784
|
+
codex_mcp_split_proxy_enabled = services.channel.codex_mcp_split_proxy_enabled
|
|
785
|
+
restore_codex_mcp_config_from_managed = services.channel.restore_codex_mcp_config_from_managed
|
|
786
|
+
codex_native_routed_config_args = services.cli_policy.codex_native_routed_config_args
|
|
787
|
+
codex_passthrough_args_for_launch = services.cli_policy.codex_passthrough_args_for_launch
|
|
788
|
+
codex_passthrough_has_command = services.cli_policy.codex_passthrough_has_command
|
|
789
|
+
codex_process_record_path = services.process.codex_process_record_path
|
|
790
|
+
codex_resume_picker_requested = services.cli_policy.codex_resume_picker_requested
|
|
791
|
+
codex_resume_with_session_id = services.cli_policy.codex_resume_with_session_id
|
|
792
|
+
codex_routed_enabled = services.routing.codex_routed_enabled
|
|
793
|
+
codex_runtime_config_args = services.cli_policy.codex_runtime_config_args
|
|
794
|
+
codex_runtime_model_catalog_args = services.config.codex_runtime_model_catalog_args
|
|
795
|
+
codex_yolo_launch_args = services.cli_policy.codex_yolo_launch_args
|
|
796
|
+
current_alias = services.config.current_alias
|
|
797
|
+
current_launch_cwd_key = services.config.current_launch_cwd_key
|
|
798
|
+
direct_native_codex_enabled = services.routing.direct_native_codex_enabled
|
|
799
|
+
disable_ciel_runtime_codex_prompts_for_native = services.installation.disable_ciel_runtime_codex_prompts_for_native
|
|
800
|
+
ensure_model_cache_for_launch = services.config.ensure_model_cache_for_launch
|
|
801
|
+
find_executable = services.installation.find_executable
|
|
802
|
+
get_current_provider = services.config.get_current_provider
|
|
803
|
+
has_passthrough_option = services.installation.has_passthrough_option
|
|
804
|
+
install_ciel_runtime_codex_prompts = services.installation.install_ciel_runtime_codex_prompts
|
|
805
|
+
install_codex_if_missing = services.installation.install_codex_if_missing
|
|
806
|
+
launch_agy = services.dispatch.launch_agy
|
|
807
|
+
launch_claude = services.dispatch.launch_claude
|
|
808
|
+
launch_codex_app_server = services.dispatch.launch_codex_app_server
|
|
809
|
+
launch_readiness_errors = services.routing.launch_readiness_errors
|
|
810
|
+
load_config = services.config.load_config
|
|
811
|
+
log_codex_passthrough_mapping = services.dispatch.log_codex_passthrough_mapping
|
|
812
|
+
materialize_runtime_command = services.dispatch.materialize_runtime_command
|
|
813
|
+
native_codex_enabled = services.routing.native_codex_enabled
|
|
814
|
+
path_with_ciel_runtime_user_dirs = services.process.path_with_ciel_runtime_user_dirs
|
|
815
|
+
provider_mode_label = services.config.provider_mode_label
|
|
816
|
+
record_launch_state_for_cwd = services.config.record_launch_state_for_cwd
|
|
817
|
+
run_ciel_runtime_update_check = services.dispatch.run_ciel_runtime_update_check
|
|
818
|
+
run_codex_update_check = services.dispatch.run_codex_update_check
|
|
819
|
+
run_prelaunch_menu = services.dispatch.run_prelaunch_menu
|
|
820
|
+
run_with_router_lifetime = services.routing.run_with_router_lifetime
|
|
821
|
+
select_codex_resume_session = services.channel.select_codex_resume_session
|
|
822
|
+
start_codex_mcp_channel_sse_for_launch = services.channel.start_codex_mcp_channel_sse_for_launch
|
|
823
|
+
start_router_if_needed = services.routing.start_router_if_needed
|
|
824
|
+
subprocess_call_with_channel_wake_proxy = services.process.subprocess_call_with_channel_wake_proxy
|
|
825
|
+
terminate_existing_codex_processes_for_launch = services.process.terminate_existing_codex_processes_for_launch
|
|
826
|
+
terminate_existing_router_clients_for_launch = services.process.terminate_existing_router_clients_for_launch
|
|
827
|
+
warn_if_multiple_ciel_runtime_installs = services.installation.warn_if_multiple_ciel_runtime_installs
|
|
828
|
+
write_codex_mcp_config_for_channel_discovery = services.channel.write_codex_mcp_config_for_channel_discovery
|
|
829
|
+
warn_if_multiple_ciel_runtime_installs()
|
|
830
|
+
run_ciel_runtime_update_check(enabled=self_update_check)
|
|
831
|
+
env = os.environ.copy()
|
|
832
|
+
env["PATH"] = path_with_ciel_runtime_user_dirs(env)
|
|
833
|
+
codex = install_codex_if_missing()
|
|
834
|
+
if not codex:
|
|
835
|
+
raise RuntimeError(
|
|
836
|
+
"codex executable was not found in PATH or the Ciel Runtime user bin directories, "
|
|
837
|
+
"and automatic install of @openai/codex did not make it available"
|
|
838
|
+
)
|
|
839
|
+
updated_codex = run_codex_update_check(codex, enabled=update_check)
|
|
840
|
+
if isinstance(updated_codex, str) and updated_codex:
|
|
841
|
+
codex = updated_codex
|
|
842
|
+
codex = find_executable("codex") or codex
|
|
843
|
+
codex_passthrough, codex_passthrough_notes = codex_passthrough_args_for_launch(passthrough)
|
|
844
|
+
if codex_help_requested(codex_passthrough):
|
|
845
|
+
log_codex_passthrough_mapping(codex_passthrough_notes)
|
|
846
|
+
return subprocess.call([codex, *codex_passthrough], env=env)
|
|
847
|
+
if codex_passthrough_has_command(codex_passthrough):
|
|
848
|
+
skip_menu = True
|
|
849
|
+
auto_import_passthrough_channels(passthrough)
|
|
850
|
+
rc = run_prelaunch_menu(passthrough, skip_menu=skip_menu, force_menu=force_menu)
|
|
851
|
+
if rc == PRELAUNCH_LAUNCH_CLAUDE:
|
|
852
|
+
return launch_claude(
|
|
853
|
+
passthrough,
|
|
854
|
+
skip_menu=True,
|
|
855
|
+
force_menu=False,
|
|
856
|
+
update_check=update_check,
|
|
857
|
+
self_update_check=False,
|
|
858
|
+
)
|
|
859
|
+
if rc == PRELAUNCH_LAUNCH_AGY:
|
|
860
|
+
return launch_agy(
|
|
861
|
+
passthrough,
|
|
862
|
+
skip_menu=True,
|
|
863
|
+
force_menu=False,
|
|
864
|
+
update_check=update_check,
|
|
865
|
+
self_update_check=False,
|
|
866
|
+
)
|
|
867
|
+
if rc == PRELAUNCH_LAUNCH_CODEX_APP_SERVER:
|
|
868
|
+
return launch_codex_app_server(
|
|
869
|
+
passthrough,
|
|
870
|
+
skip_menu=True,
|
|
871
|
+
force_menu=False,
|
|
872
|
+
update_check=update_check,
|
|
873
|
+
self_update_check=False,
|
|
874
|
+
)
|
|
875
|
+
if rc == PRELAUNCH_CANCEL:
|
|
876
|
+
return 0
|
|
877
|
+
if rc not in (0, PRELAUNCH_LAUNCH_CODEX):
|
|
878
|
+
return rc
|
|
879
|
+
cfg = load_config()
|
|
880
|
+
provider, pcfg = get_current_provider(cfg)
|
|
881
|
+
for line in apply_launch_endpoint_policy(cfg, "codex"):
|
|
882
|
+
print(line, flush=True)
|
|
883
|
+
provider, pcfg = get_current_provider(cfg)
|
|
884
|
+
blockers = launch_readiness_errors(cfg)
|
|
885
|
+
if blockers:
|
|
886
|
+
print("Ciel Runtime Codex launch blocked:", flush=True)
|
|
887
|
+
for line in blockers:
|
|
888
|
+
print(f"- {line}", flush=True)
|
|
889
|
+
return 2
|
|
890
|
+
cleanup_managed_services_for_provider(provider, pcfg, cfg, quiet=True)
|
|
891
|
+
use_native_codex = direct_native_codex_enabled(provider, pcfg)
|
|
892
|
+
use_codex_routed = codex_routed_enabled(provider, pcfg)
|
|
893
|
+
launch_cwd = Path.cwd()
|
|
894
|
+
mapped_continue = any(note.startswith("--continue -> resume --last") for note in codex_passthrough_notes)
|
|
895
|
+
if not use_native_codex and mapped_continue:
|
|
896
|
+
try:
|
|
897
|
+
resume_index = codex_passthrough.index("resume")
|
|
898
|
+
except ValueError:
|
|
899
|
+
resume_index = -1
|
|
900
|
+
if resume_index >= 0 and resume_index + 1 < len(codex_passthrough):
|
|
901
|
+
if codex_passthrough[resume_index + 1] == "--last":
|
|
902
|
+
del codex_passthrough[resume_index + 1]
|
|
903
|
+
codex_passthrough_notes.append("routed --continue -> provider-independent session picker")
|
|
904
|
+
if not use_native_codex and codex_resume_picker_requested(codex_passthrough):
|
|
905
|
+
session_id = select_codex_resume_session(
|
|
906
|
+
env,
|
|
907
|
+
include_non_interactive="--include-non-interactive" in codex_passthrough,
|
|
908
|
+
passthrough=codex_passthrough,
|
|
909
|
+
cwd=launch_cwd,
|
|
910
|
+
)
|
|
911
|
+
if session_id == "":
|
|
912
|
+
return 0
|
|
913
|
+
if session_id:
|
|
914
|
+
codex_passthrough = codex_resume_with_session_id(codex_passthrough, session_id)
|
|
915
|
+
codex_passthrough_notes.append("resume picker -> selected local Codex session")
|
|
916
|
+
restore_codex_mcp_config_from_managed(
|
|
917
|
+
codex_passthrough, env=env, cwd=launch_cwd
|
|
918
|
+
)
|
|
919
|
+
if use_native_codex:
|
|
920
|
+
disable_ciel_runtime_codex_prompts_for_native(env)
|
|
921
|
+
else:
|
|
922
|
+
install_ciel_runtime_codex_prompts(env)
|
|
923
|
+
codex_mcp_config = write_codex_mcp_config_for_channel_discovery(codex_passthrough, env=env)
|
|
924
|
+
env["CIEL_RUNTIME_CODEX_MANAGED"] = "1"
|
|
925
|
+
env["CIEL_RUNTIME_CONFIG_DIR"] = str(CONFIG_DIR)
|
|
926
|
+
env["CIEL_RUNTIME_LAUNCH_CWD"] = str(launch_cwd)
|
|
927
|
+
terminate_existing_codex_processes_for_launch("codex_prelaunch_processes", cwd=launch_cwd, quiet=True)
|
|
928
|
+
if not use_native_codex:
|
|
929
|
+
terminate_existing_router_clients_for_launch("codex_prelaunch_active_clients", quiet=True)
|
|
930
|
+
if use_native_codex:
|
|
931
|
+
manage_router_lifetime = bool(
|
|
932
|
+
start_router_if_needed(replace_active_clients=False)
|
|
933
|
+
) if web_backend_start_requested(cfg) else False
|
|
934
|
+
else:
|
|
935
|
+
manage_router_lifetime = bool(start_router_if_needed())
|
|
936
|
+
if not native_codex_enabled(provider):
|
|
937
|
+
ensure_model_cache_for_launch(provider, pcfg)
|
|
938
|
+
codex_channel_owned_names = (
|
|
939
|
+
codex_channel_capable_mcp_server_names(cfg, codex_mcp_config)
|
|
940
|
+
if not use_native_codex and channel_delivery_mode(cfg) == "llm"
|
|
941
|
+
else []
|
|
942
|
+
)
|
|
943
|
+
codex_mcp_compat_args = codex_mcp_native_http_compat_args(
|
|
944
|
+
codex_mcp_config,
|
|
945
|
+
split_http_proxy=(not use_native_codex and codex_mcp_split_proxy_enabled()),
|
|
946
|
+
channel_owned_server_names=codex_channel_owned_names,
|
|
947
|
+
include_builtin_channel=(
|
|
948
|
+
channel_delivery_mode(cfg) == "llm" and web_backend_start_requested(cfg)
|
|
949
|
+
),
|
|
950
|
+
)
|
|
951
|
+
codex_yolo_args = codex_yolo_launch_args(codex_passthrough)
|
|
952
|
+
if not use_native_codex and not use_codex_routed:
|
|
953
|
+
env[CODEX_RUNTIME_API_KEY_ENV] = env.get(CODEX_RUNTIME_API_KEY_ENV) or "ciel-runtime-router-local-key"
|
|
954
|
+
log_codex_passthrough_mapping(codex_passthrough_notes)
|
|
955
|
+
model_alias_args: list[str] = []
|
|
956
|
+
if not native_codex_enabled(provider) and not has_passthrough_option(codex_passthrough, "-m", "--model"):
|
|
957
|
+
model = current_alias(cfg)
|
|
958
|
+
if model:
|
|
959
|
+
model_alias_args.extend(["-m", model])
|
|
960
|
+
codex_mode = "native" if use_native_codex else ("routed" if use_codex_routed else "router")
|
|
961
|
+
cmd, env = materialize_runtime_command(
|
|
962
|
+
"codex",
|
|
963
|
+
codex,
|
|
964
|
+
env,
|
|
965
|
+
provider,
|
|
966
|
+
pcfg,
|
|
967
|
+
mode=codex_mode,
|
|
968
|
+
protocol="openai_responses",
|
|
969
|
+
cwd=launch_cwd,
|
|
970
|
+
enable_channels=bool(codex_channel_owned_names),
|
|
971
|
+
passthrough=codex_passthrough,
|
|
972
|
+
options={
|
|
973
|
+
"yolo_args": tuple(codex_yolo_args),
|
|
974
|
+
"model_args": tuple(codex_current_model_cli_args(pcfg, codex_passthrough)),
|
|
975
|
+
"routed_config_args": tuple(codex_native_routed_config_args()),
|
|
976
|
+
"router_config_args": tuple(codex_runtime_config_args()),
|
|
977
|
+
"model_catalog_args": tuple(codex_runtime_model_catalog_args(codex, cfg)),
|
|
978
|
+
"alternate_screen_args": tuple(codex_alternate_screen_compat_args(codex_passthrough, env=env)),
|
|
979
|
+
"mcp_args": tuple(codex_mcp_compat_args),
|
|
980
|
+
"model_alias_args": tuple(model_alias_args),
|
|
981
|
+
},
|
|
982
|
+
)
|
|
983
|
+
_log_codex_command_for_diagnostics(cmd, env)
|
|
984
|
+
record_launch_state_for_cwd(
|
|
985
|
+
current_launch_cwd_key(),
|
|
986
|
+
provider,
|
|
987
|
+
provider_mode_label(provider, pcfg) if native_codex_enabled(provider) else "codex-router",
|
|
988
|
+
str(pcfg.get("current_model") or ("" if native_codex_enabled(provider) else current_alias(cfg)) or ""),
|
|
989
|
+
)
|
|
990
|
+
|
|
991
|
+
def run_codex_process() -> int:
|
|
992
|
+
_set_channel_transcript_scope(
|
|
993
|
+
"codex",
|
|
994
|
+
codex_home=Path(env.get("CODEX_HOME") or (Path.home() / ".codex")),
|
|
995
|
+
)
|
|
996
|
+
if not use_native_codex:
|
|
997
|
+
start_codex_mcp_channel_sse_for_launch(cfg, codex_mcp_config, allowed_server_names=codex_channel_owned_names)
|
|
998
|
+
codex_synthetic_enter = None if _channel_wake_enter_env_is_fixed() else b"\r"
|
|
999
|
+
return subprocess_call_with_channel_wake_proxy(
|
|
1000
|
+
cmd,
|
|
1001
|
+
env,
|
|
1002
|
+
wake_for_llm_delivery=channel_delivery_mode(cfg) == "llm",
|
|
1003
|
+
synthetic_enter_bytes=codex_synthetic_enter,
|
|
1004
|
+
normalize_bare_cr_for_synthetic_enter=False,
|
|
1005
|
+
channel_wake_submit_retries=_codex_channel_wake_submit_retries(),
|
|
1006
|
+
channel_wake_confirm_submit=True,
|
|
1007
|
+
channel_wake_bracketed_paste=True,
|
|
1008
|
+
channel_wake_submit_delay_seconds=_codex_channel_wake_submit_delay_seconds(),
|
|
1009
|
+
tracked_child_pid_path=codex_process_record_path("client"),
|
|
1010
|
+
)
|
|
1011
|
+
|
|
1012
|
+
return run_with_router_lifetime(run_codex_process, manage_router_lifetime)
|
|
1013
|
+
|
|
1014
|
+
|
|
1015
|
+
|
|
1016
|
+
@dataclass(frozen=True, slots=True)
|
|
1017
|
+
class CodexAppServerProcess:
|
|
1018
|
+
_log_codex_app_server_command_for_diagnostics: Callable[..., Any]
|
|
1019
|
+
codex_process_record_path: Callable[..., Any]
|
|
1020
|
+
path_with_ciel_runtime_user_dirs: Callable[..., Any]
|
|
1021
|
+
subprocess_call_with_child_pid_record: Callable[..., Any]
|
|
1022
|
+
terminate_existing_codex_processes_for_launch: Callable[..., Any]
|
|
1023
|
+
terminate_existing_router_clients_for_launch: Callable[..., Any]
|
|
1024
|
+
|
|
1025
|
+
|
|
1026
|
+
@dataclass(frozen=True, slots=True)
|
|
1027
|
+
class CodexAppServerConfig:
|
|
1028
|
+
apply_launch_endpoint_policy: Callable[..., Any]
|
|
1029
|
+
current_alias: Callable[..., Any]
|
|
1030
|
+
current_launch_cwd_key: Callable[..., Any]
|
|
1031
|
+
ensure_model_cache_for_launch: Callable[..., Any]
|
|
1032
|
+
get_current_provider: Callable[..., Any]
|
|
1033
|
+
load_config: Callable[..., Any]
|
|
1034
|
+
provider_mode_label: Callable[..., Any]
|
|
1035
|
+
record_launch_state_for_cwd: Callable[..., Any]
|
|
1036
|
+
|
|
1037
|
+
|
|
1038
|
+
@dataclass(frozen=True, slots=True)
|
|
1039
|
+
class CodexAppServerCliPolicy:
|
|
1040
|
+
codex_app_server_default_listen_url: Callable[..., Any]
|
|
1041
|
+
codex_app_server_launch_args: Callable[..., Any]
|
|
1042
|
+
codex_current_model_config_args: Callable[..., Any]
|
|
1043
|
+
codex_native_routed_config_args: Callable[..., Any]
|
|
1044
|
+
codex_passthrough_has_model_override: Callable[..., Any]
|
|
1045
|
+
codex_runtime_config_args: Callable[..., Any]
|
|
1046
|
+
toml_string: Callable[..., Any]
|
|
1047
|
+
|
|
1048
|
+
|
|
1049
|
+
@dataclass(frozen=True, slots=True)
|
|
1050
|
+
class CodexAppServerInstallation:
|
|
1051
|
+
find_executable: Callable[..., Any]
|
|
1052
|
+
install_codex_if_missing: Callable[..., Any]
|
|
1053
|
+
warn_if_multiple_ciel_runtime_installs: Callable[..., Any]
|
|
1054
|
+
|
|
1055
|
+
|
|
1056
|
+
@dataclass(frozen=True, slots=True)
|
|
1057
|
+
class CodexAppServerDispatch:
|
|
1058
|
+
launch_agy: Callable[..., Any]
|
|
1059
|
+
launch_claude: Callable[..., Any]
|
|
1060
|
+
launch_codex: Callable[..., Any]
|
|
1061
|
+
run_ciel_runtime_update_check: Callable[..., Any]
|
|
1062
|
+
run_codex_update_check: Callable[..., Any]
|
|
1063
|
+
run_prelaunch_menu: Callable[..., Any]
|
|
1064
|
+
|
|
1065
|
+
|
|
1066
|
+
@dataclass(frozen=True, slots=True)
|
|
1067
|
+
class CodexAppServerRouting:
|
|
1068
|
+
cleanup_managed_services_for_provider: Callable[..., Any]
|
|
1069
|
+
codex_launch_enabled_for_provider: Callable[..., Any]
|
|
1070
|
+
codex_routed_enabled: Callable[..., Any]
|
|
1071
|
+
direct_native_codex_enabled: Callable[..., Any]
|
|
1072
|
+
launch_readiness_errors: Callable[..., Any]
|
|
1073
|
+
native_codex_enabled: Callable[..., Any]
|
|
1074
|
+
run_with_router_lifetime: Callable[..., Any]
|
|
1075
|
+
start_router_if_needed: Callable[..., Any]
|
|
1076
|
+
|
|
1077
|
+
|
|
1078
|
+
@dataclass(frozen=True, slots=True)
|
|
1079
|
+
class CodexAppServerChannel:
|
|
1080
|
+
auto_import_passthrough_channels: Callable[..., Any]
|
|
1081
|
+
channel_delivery_mode: Callable[..., Any]
|
|
1082
|
+
codex_channel_capable_mcp_server_names: Callable[..., Any]
|
|
1083
|
+
codex_mcp_native_http_compat_args: Callable[..., Any]
|
|
1084
|
+
codex_mcp_split_proxy_enabled: Callable[..., Any]
|
|
1085
|
+
restore_codex_mcp_config_from_managed: Callable[..., Any]
|
|
1086
|
+
start_codex_mcp_channel_sse_for_launch: Callable[..., Any]
|
|
1087
|
+
write_codex_mcp_config_for_channel_discovery: Callable[..., Any]
|
|
1088
|
+
|
|
1089
|
+
|
|
1090
|
+
@dataclass(frozen=True, slots=True)
|
|
1091
|
+
class CodexAppServerLaunchServices:
|
|
1092
|
+
constants: CodexLaunchConstants
|
|
1093
|
+
process: CodexAppServerProcess
|
|
1094
|
+
config: CodexAppServerConfig
|
|
1095
|
+
cli_policy: CodexAppServerCliPolicy
|
|
1096
|
+
installation: CodexAppServerInstallation
|
|
1097
|
+
dispatch: CodexAppServerDispatch
|
|
1098
|
+
routing: CodexAppServerRouting
|
|
1099
|
+
channel: CodexAppServerChannel
|
|
1100
|
+
|
|
1101
|
+
|
|
1102
|
+
def run_codex_app_server(
|
|
1103
|
+
passthrough: list[str],
|
|
1104
|
+
skip_menu: bool = True,
|
|
1105
|
+
force_menu: bool = False,
|
|
1106
|
+
update_check: bool = True,
|
|
1107
|
+
self_update_check: bool = True,
|
|
1108
|
+
*,
|
|
1109
|
+
services: CodexAppServerLaunchServices,
|
|
1110
|
+
) -> int:
|
|
1111
|
+
CODEX_RUNTIME_API_KEY_ENV = services.constants.CODEX_RUNTIME_API_KEY_ENV
|
|
1112
|
+
CONFIG_DIR = services.constants.CONFIG_DIR
|
|
1113
|
+
PRELAUNCH_CANCEL = services.constants.PRELAUNCH_CANCEL
|
|
1114
|
+
PRELAUNCH_LAUNCH_AGY = services.constants.PRELAUNCH_LAUNCH_AGY
|
|
1115
|
+
PRELAUNCH_LAUNCH_CLAUDE = services.constants.PRELAUNCH_LAUNCH_CLAUDE
|
|
1116
|
+
PRELAUNCH_LAUNCH_CODEX = services.constants.PRELAUNCH_LAUNCH_CODEX
|
|
1117
|
+
PRELAUNCH_LAUNCH_CODEX_APP_SERVER = services.constants.PRELAUNCH_LAUNCH_CODEX_APP_SERVER
|
|
1118
|
+
_log_codex_app_server_command_for_diagnostics = services.process._log_codex_app_server_command_for_diagnostics
|
|
1119
|
+
apply_launch_endpoint_policy = services.config.apply_launch_endpoint_policy
|
|
1120
|
+
auto_import_passthrough_channels = services.channel.auto_import_passthrough_channels
|
|
1121
|
+
channel_delivery_mode = services.channel.channel_delivery_mode
|
|
1122
|
+
cleanup_managed_services_for_provider = services.routing.cleanup_managed_services_for_provider
|
|
1123
|
+
codex_app_server_default_listen_url = services.cli_policy.codex_app_server_default_listen_url
|
|
1124
|
+
codex_app_server_launch_args = services.cli_policy.codex_app_server_launch_args
|
|
1125
|
+
codex_channel_capable_mcp_server_names = services.channel.codex_channel_capable_mcp_server_names
|
|
1126
|
+
codex_current_model_config_args = services.cli_policy.codex_current_model_config_args
|
|
1127
|
+
codex_launch_enabled_for_provider = services.routing.codex_launch_enabled_for_provider
|
|
1128
|
+
codex_mcp_native_http_compat_args = services.channel.codex_mcp_native_http_compat_args
|
|
1129
|
+
codex_mcp_split_proxy_enabled = services.channel.codex_mcp_split_proxy_enabled
|
|
1130
|
+
restore_codex_mcp_config_from_managed = services.channel.restore_codex_mcp_config_from_managed
|
|
1131
|
+
codex_native_routed_config_args = services.cli_policy.codex_native_routed_config_args
|
|
1132
|
+
codex_passthrough_has_model_override = services.cli_policy.codex_passthrough_has_model_override
|
|
1133
|
+
codex_process_record_path = services.process.codex_process_record_path
|
|
1134
|
+
codex_routed_enabled = services.routing.codex_routed_enabled
|
|
1135
|
+
codex_runtime_config_args = services.cli_policy.codex_runtime_config_args
|
|
1136
|
+
current_alias = services.config.current_alias
|
|
1137
|
+
current_launch_cwd_key = services.config.current_launch_cwd_key
|
|
1138
|
+
direct_native_codex_enabled = services.routing.direct_native_codex_enabled
|
|
1139
|
+
ensure_model_cache_for_launch = services.config.ensure_model_cache_for_launch
|
|
1140
|
+
find_executable = services.installation.find_executable
|
|
1141
|
+
get_current_provider = services.config.get_current_provider
|
|
1142
|
+
install_codex_if_missing = services.installation.install_codex_if_missing
|
|
1143
|
+
launch_agy = services.dispatch.launch_agy
|
|
1144
|
+
launch_claude = services.dispatch.launch_claude
|
|
1145
|
+
launch_codex = services.dispatch.launch_codex
|
|
1146
|
+
launch_readiness_errors = services.routing.launch_readiness_errors
|
|
1147
|
+
load_config = services.config.load_config
|
|
1148
|
+
native_codex_enabled = services.routing.native_codex_enabled
|
|
1149
|
+
path_with_ciel_runtime_user_dirs = services.process.path_with_ciel_runtime_user_dirs
|
|
1150
|
+
provider_mode_label = services.config.provider_mode_label
|
|
1151
|
+
record_launch_state_for_cwd = services.config.record_launch_state_for_cwd
|
|
1152
|
+
run_ciel_runtime_update_check = services.dispatch.run_ciel_runtime_update_check
|
|
1153
|
+
run_codex_update_check = services.dispatch.run_codex_update_check
|
|
1154
|
+
run_prelaunch_menu = services.dispatch.run_prelaunch_menu
|
|
1155
|
+
run_with_router_lifetime = services.routing.run_with_router_lifetime
|
|
1156
|
+
start_codex_mcp_channel_sse_for_launch = services.channel.start_codex_mcp_channel_sse_for_launch
|
|
1157
|
+
start_router_if_needed = services.routing.start_router_if_needed
|
|
1158
|
+
subprocess_call_with_child_pid_record = services.process.subprocess_call_with_child_pid_record
|
|
1159
|
+
terminate_existing_codex_processes_for_launch = services.process.terminate_existing_codex_processes_for_launch
|
|
1160
|
+
terminate_existing_router_clients_for_launch = services.process.terminate_existing_router_clients_for_launch
|
|
1161
|
+
toml_string = services.cli_policy.toml_string
|
|
1162
|
+
warn_if_multiple_ciel_runtime_installs = services.installation.warn_if_multiple_ciel_runtime_installs
|
|
1163
|
+
write_codex_mcp_config_for_channel_discovery = services.channel.write_codex_mcp_config_for_channel_discovery
|
|
1164
|
+
warn_if_multiple_ciel_runtime_installs()
|
|
1165
|
+
run_ciel_runtime_update_check(enabled=self_update_check)
|
|
1166
|
+
env = os.environ.copy()
|
|
1167
|
+
env["PATH"] = path_with_ciel_runtime_user_dirs(env)
|
|
1168
|
+
codex = install_codex_if_missing()
|
|
1169
|
+
if not codex:
|
|
1170
|
+
raise RuntimeError(
|
|
1171
|
+
"codex executable was not found in PATH or the Ciel Runtime user bin directories, "
|
|
1172
|
+
"and automatic install of @openai/codex did not make it available"
|
|
1173
|
+
)
|
|
1174
|
+
updated_codex = run_codex_update_check(codex, enabled=update_check)
|
|
1175
|
+
if isinstance(updated_codex, str) and updated_codex:
|
|
1176
|
+
codex = updated_codex
|
|
1177
|
+
codex = find_executable("codex") or codex
|
|
1178
|
+
auto_import_passthrough_channels(passthrough)
|
|
1179
|
+
rc = run_prelaunch_menu(passthrough, skip_menu=skip_menu, force_menu=force_menu)
|
|
1180
|
+
if rc == PRELAUNCH_LAUNCH_CLAUDE:
|
|
1181
|
+
return launch_claude(
|
|
1182
|
+
passthrough,
|
|
1183
|
+
skip_menu=True,
|
|
1184
|
+
force_menu=False,
|
|
1185
|
+
update_check=update_check,
|
|
1186
|
+
self_update_check=False,
|
|
1187
|
+
)
|
|
1188
|
+
if rc == PRELAUNCH_LAUNCH_CODEX:
|
|
1189
|
+
return launch_codex(
|
|
1190
|
+
passthrough,
|
|
1191
|
+
skip_menu=True,
|
|
1192
|
+
force_menu=False,
|
|
1193
|
+
update_check=update_check,
|
|
1194
|
+
self_update_check=False,
|
|
1195
|
+
)
|
|
1196
|
+
if rc == PRELAUNCH_LAUNCH_AGY:
|
|
1197
|
+
return launch_agy(
|
|
1198
|
+
passthrough,
|
|
1199
|
+
skip_menu=True,
|
|
1200
|
+
force_menu=False,
|
|
1201
|
+
update_check=update_check,
|
|
1202
|
+
self_update_check=False,
|
|
1203
|
+
)
|
|
1204
|
+
if rc == PRELAUNCH_CANCEL:
|
|
1205
|
+
return 0
|
|
1206
|
+
if rc not in (0, PRELAUNCH_LAUNCH_CODEX_APP_SERVER):
|
|
1207
|
+
return rc
|
|
1208
|
+
cfg = load_config()
|
|
1209
|
+
provider, pcfg = get_current_provider(cfg)
|
|
1210
|
+
for line in apply_launch_endpoint_policy(cfg, "codex-app-server"):
|
|
1211
|
+
print(line, flush=True)
|
|
1212
|
+
provider, pcfg = get_current_provider(cfg)
|
|
1213
|
+
if not codex_launch_enabled_for_provider(provider):
|
|
1214
|
+
print("Ciel Runtime Codex App Server launch blocked:", flush=True)
|
|
1215
|
+
print("- Select Codex or Codex routed as the provider before launching Codex App Server.", flush=True)
|
|
1216
|
+
return 2
|
|
1217
|
+
blockers = launch_readiness_errors(cfg)
|
|
1218
|
+
if blockers:
|
|
1219
|
+
print("Ciel Runtime Codex App Server launch blocked:", flush=True)
|
|
1220
|
+
for line in blockers:
|
|
1221
|
+
print(f"- {line}", flush=True)
|
|
1222
|
+
return 2
|
|
1223
|
+
cleanup_managed_services_for_provider(provider, pcfg, cfg, quiet=True)
|
|
1224
|
+
restore_codex_mcp_config_from_managed(
|
|
1225
|
+
passthrough, env=env, cwd=Path.cwd()
|
|
1226
|
+
)
|
|
1227
|
+
codex_mcp_config = write_codex_mcp_config_for_channel_discovery(passthrough, env=env)
|
|
1228
|
+
use_native_codex = direct_native_codex_enabled(provider, pcfg)
|
|
1229
|
+
use_codex_routed = codex_routed_enabled(provider, pcfg)
|
|
1230
|
+
launch_cwd = Path.cwd()
|
|
1231
|
+
env["CIEL_RUNTIME_CODEX_MANAGED"] = "1"
|
|
1232
|
+
env["CIEL_RUNTIME_CONFIG_DIR"] = str(CONFIG_DIR)
|
|
1233
|
+
env["CIEL_RUNTIME_LAUNCH_CWD"] = str(launch_cwd)
|
|
1234
|
+
terminate_existing_codex_processes_for_launch("codex_app_server_prelaunch_processes", cwd=launch_cwd, quiet=True)
|
|
1235
|
+
if not use_native_codex:
|
|
1236
|
+
terminate_existing_router_clients_for_launch("codex_app_server_prelaunch_active_clients", quiet=True)
|
|
1237
|
+
if use_native_codex:
|
|
1238
|
+
manage_router_lifetime = bool(
|
|
1239
|
+
start_router_if_needed(replace_active_clients=False)
|
|
1240
|
+
) if web_backend_start_requested(cfg) else False
|
|
1241
|
+
else:
|
|
1242
|
+
manage_router_lifetime = bool(start_router_if_needed())
|
|
1243
|
+
if use_codex_routed:
|
|
1244
|
+
config_args = codex_native_routed_config_args()
|
|
1245
|
+
elif use_native_codex:
|
|
1246
|
+
config_args = []
|
|
1247
|
+
else:
|
|
1248
|
+
env[CODEX_RUNTIME_API_KEY_ENV] = env.get(CODEX_RUNTIME_API_KEY_ENV) or "ciel-runtime-router-local-key"
|
|
1249
|
+
config_args = codex_runtime_config_args()
|
|
1250
|
+
if native_codex_enabled(provider):
|
|
1251
|
+
config_args = [*config_args, *codex_current_model_config_args(pcfg, passthrough)]
|
|
1252
|
+
if not native_codex_enabled(provider):
|
|
1253
|
+
ensure_model_cache_for_launch(provider, pcfg)
|
|
1254
|
+
model = current_alias(cfg)
|
|
1255
|
+
if model and not codex_passthrough_has_model_override(passthrough):
|
|
1256
|
+
config_args = [*config_args, "-c", f"model={toml_string(model)}"]
|
|
1257
|
+
codex_channel_owned_names = (
|
|
1258
|
+
codex_channel_capable_mcp_server_names(cfg, codex_mcp_config)
|
|
1259
|
+
if not use_native_codex and channel_delivery_mode(cfg) == "llm"
|
|
1260
|
+
else []
|
|
1261
|
+
)
|
|
1262
|
+
codex_mcp_compat_args = codex_mcp_native_http_compat_args(
|
|
1263
|
+
codex_mcp_config,
|
|
1264
|
+
split_http_proxy=(not use_native_codex and codex_mcp_split_proxy_enabled()),
|
|
1265
|
+
channel_owned_server_names=codex_channel_owned_names,
|
|
1266
|
+
include_builtin_channel=(
|
|
1267
|
+
channel_delivery_mode(cfg) == "llm" and web_backend_start_requested(cfg)
|
|
1268
|
+
),
|
|
1269
|
+
)
|
|
1270
|
+
config_args = [*config_args, *codex_mcp_compat_args]
|
|
1271
|
+
listen_url = codex_app_server_default_listen_url()
|
|
1272
|
+
app_server_args = codex_app_server_launch_args(
|
|
1273
|
+
passthrough,
|
|
1274
|
+
config_args=config_args,
|
|
1275
|
+
default_listen_url=listen_url,
|
|
1276
|
+
)
|
|
1277
|
+
cmd = [codex, *app_server_args]
|
|
1278
|
+
print("Launching Codex App Server through Ciel Runtime.", flush=True)
|
|
1279
|
+
if "--listen" in cmd:
|
|
1280
|
+
try:
|
|
1281
|
+
print(f"Codex App Server listen: {cmd[cmd.index('--listen') + 1]}", flush=True)
|
|
1282
|
+
except Exception:
|
|
1283
|
+
pass
|
|
1284
|
+
_log_codex_app_server_command_for_diagnostics(cmd, env)
|
|
1285
|
+
record_launch_state_for_cwd(
|
|
1286
|
+
current_launch_cwd_key(),
|
|
1287
|
+
provider,
|
|
1288
|
+
provider_mode_label(provider, pcfg) if native_codex_enabled(provider) else "codex-app-server-router",
|
|
1289
|
+
str(pcfg.get("current_model") or ("" if native_codex_enabled(provider) else current_alias(cfg)) or ""),
|
|
1290
|
+
)
|
|
1291
|
+
|
|
1292
|
+
split_proxy_enabled = bool(not use_native_codex and (codex_mcp_split_proxy_enabled() or codex_channel_owned_names))
|
|
1293
|
+
|
|
1294
|
+
def run_codex_app_server_process() -> int:
|
|
1295
|
+
if split_proxy_enabled:
|
|
1296
|
+
start_codex_mcp_channel_sse_for_launch(cfg, codex_mcp_config, allowed_server_names=codex_channel_owned_names)
|
|
1297
|
+
return subprocess_call_with_child_pid_record(cmd, env, codex_process_record_path("app-server"))
|
|
1298
|
+
|
|
1299
|
+
return run_with_router_lifetime(run_codex_app_server_process, manage_router_lifetime)
|
|
1300
|
+
|
|
1301
|
+
|
|
1302
|
+
|
|
1303
|
+
@dataclass(frozen=True, slots=True)
|
|
1304
|
+
class AgyLaunchConstants:
|
|
1305
|
+
PRELAUNCH_CANCEL: Any
|
|
1306
|
+
PRELAUNCH_LAUNCH_AGY: Any
|
|
1307
|
+
PRELAUNCH_LAUNCH_CLAUDE: Any
|
|
1308
|
+
PRELAUNCH_LAUNCH_CODEX: Any
|
|
1309
|
+
PRELAUNCH_LAUNCH_CODEX_APP_SERVER: Any
|
|
1310
|
+
|
|
1311
|
+
|
|
1312
|
+
def build_default_agy_launch_constants() -> AgyLaunchConstants:
|
|
1313
|
+
"""Build immutable AGY launch dispatch constants."""
|
|
1314
|
+
return AgyLaunchConstants(
|
|
1315
|
+
PRELAUNCH_CANCEL=PRELAUNCH_CANCEL,
|
|
1316
|
+
PRELAUNCH_LAUNCH_AGY=PRELAUNCH_LAUNCH_AGY,
|
|
1317
|
+
PRELAUNCH_LAUNCH_CLAUDE=PRELAUNCH_LAUNCH_CLAUDE,
|
|
1318
|
+
PRELAUNCH_LAUNCH_CODEX=PRELAUNCH_LAUNCH_CODEX,
|
|
1319
|
+
PRELAUNCH_LAUNCH_CODEX_APP_SERVER=PRELAUNCH_LAUNCH_CODEX_APP_SERVER,
|
|
1320
|
+
)
|
|
1321
|
+
|
|
1322
|
+
|
|
1323
|
+
@dataclass(frozen=True, slots=True)
|
|
1324
|
+
class AgyLaunchProcess:
|
|
1325
|
+
_codex_channel_wake_submit_delay_seconds: Callable[..., Any]
|
|
1326
|
+
_codex_channel_wake_submit_retries: Callable[..., Any]
|
|
1327
|
+
_log_agy_command_for_diagnostics: Callable[..., Any]
|
|
1328
|
+
path_with_ciel_runtime_user_dirs: Callable[..., Any]
|
|
1329
|
+
subprocess_call_with_channel_wake_proxy: Callable[..., Any]
|
|
1330
|
+
|
|
1331
|
+
|
|
1332
|
+
@dataclass(frozen=True, slots=True)
|
|
1333
|
+
class AgyLaunchCliPolicy:
|
|
1334
|
+
agy_dangerous_launch_args: Callable[..., Any]
|
|
1335
|
+
agy_help_requested: Callable[..., Any]
|
|
1336
|
+
agy_passthrough_args_for_launch: Callable[..., Any]
|
|
1337
|
+
agy_passthrough_has_command: Callable[..., Any]
|
|
1338
|
+
|
|
1339
|
+
|
|
1340
|
+
@dataclass(frozen=True, slots=True)
|
|
1341
|
+
class AgyLaunchChannel:
|
|
1342
|
+
auto_import_passthrough_channels: Callable[..., Any]
|
|
1343
|
+
channel_delivery_mode: Callable[..., Any]
|
|
1344
|
+
|
|
1345
|
+
|
|
1346
|
+
@dataclass(frozen=True, slots=True)
|
|
1347
|
+
class AgyLaunchConfig:
|
|
1348
|
+
current_launch_cwd_key: Callable[..., Any]
|
|
1349
|
+
get_current_provider: Callable[..., Any]
|
|
1350
|
+
load_config: Callable[..., Any]
|
|
1351
|
+
provider_mode_label: Callable[..., Any]
|
|
1352
|
+
record_launch_state_for_cwd: Callable[..., Any]
|
|
1353
|
+
restore_agy_mcp_config_from_managed: Callable[..., Any]
|
|
1354
|
+
|
|
1355
|
+
|
|
1356
|
+
@dataclass(frozen=True, slots=True)
|
|
1357
|
+
class AgyLaunchInstallation:
|
|
1358
|
+
find_executable: Callable[..., Any]
|
|
1359
|
+
install_agy_if_missing: Callable[..., Any]
|
|
1360
|
+
warn_if_multiple_ciel_runtime_installs: Callable[..., Any]
|
|
1361
|
+
|
|
1362
|
+
|
|
1363
|
+
@dataclass(frozen=True, slots=True)
|
|
1364
|
+
class AgyLaunchDispatch:
|
|
1365
|
+
launch_claude: Callable[..., Any]
|
|
1366
|
+
launch_codex: Callable[..., Any]
|
|
1367
|
+
launch_codex_app_server: Callable[..., Any]
|
|
1368
|
+
log_agy_passthrough_mapping: Callable[..., Any]
|
|
1369
|
+
materialize_runtime_command: Callable[..., Any]
|
|
1370
|
+
run_agy_update_check: Callable[..., Any]
|
|
1371
|
+
run_ciel_runtime_update_check: Callable[..., Any]
|
|
1372
|
+
run_prelaunch_menu: Callable[..., Any]
|
|
1373
|
+
|
|
1374
|
+
|
|
1375
|
+
@dataclass(frozen=True, slots=True)
|
|
1376
|
+
class AgyLaunchRouting:
|
|
1377
|
+
agy_routed_enabled: Callable[..., Any]
|
|
1378
|
+
cleanup_managed_services_for_provider: Callable[..., Any]
|
|
1379
|
+
launch_readiness_errors: Callable[..., Any]
|
|
1380
|
+
native_agy_enabled: Callable[..., Any]
|
|
1381
|
+
run_with_router_lifetime: Callable[..., Any]
|
|
1382
|
+
start_router_if_needed: Callable[..., Any]
|
|
1383
|
+
|
|
1384
|
+
|
|
1385
|
+
@dataclass(frozen=True, slots=True)
|
|
1386
|
+
class AgyLaunchServices:
|
|
1387
|
+
constants: AgyLaunchConstants
|
|
1388
|
+
process: AgyLaunchProcess
|
|
1389
|
+
cli_policy: AgyLaunchCliPolicy
|
|
1390
|
+
channel: AgyLaunchChannel
|
|
1391
|
+
config: AgyLaunchConfig
|
|
1392
|
+
installation: AgyLaunchInstallation
|
|
1393
|
+
dispatch: AgyLaunchDispatch
|
|
1394
|
+
routing: AgyLaunchRouting
|
|
1395
|
+
|
|
1396
|
+
|
|
1397
|
+
def run_agy(
|
|
1398
|
+
passthrough: list[str],
|
|
1399
|
+
skip_menu: bool = False,
|
|
1400
|
+
force_menu: bool = False,
|
|
1401
|
+
update_check: bool = True,
|
|
1402
|
+
self_update_check: bool = True,
|
|
1403
|
+
*,
|
|
1404
|
+
services: AgyLaunchServices,
|
|
1405
|
+
) -> int:
|
|
1406
|
+
PRELAUNCH_CANCEL = services.constants.PRELAUNCH_CANCEL
|
|
1407
|
+
PRELAUNCH_LAUNCH_AGY = services.constants.PRELAUNCH_LAUNCH_AGY
|
|
1408
|
+
PRELAUNCH_LAUNCH_CLAUDE = services.constants.PRELAUNCH_LAUNCH_CLAUDE
|
|
1409
|
+
PRELAUNCH_LAUNCH_CODEX = services.constants.PRELAUNCH_LAUNCH_CODEX
|
|
1410
|
+
PRELAUNCH_LAUNCH_CODEX_APP_SERVER = services.constants.PRELAUNCH_LAUNCH_CODEX_APP_SERVER
|
|
1411
|
+
_codex_channel_wake_submit_delay_seconds = services.process._codex_channel_wake_submit_delay_seconds
|
|
1412
|
+
_codex_channel_wake_submit_retries = services.process._codex_channel_wake_submit_retries
|
|
1413
|
+
_log_agy_command_for_diagnostics = services.process._log_agy_command_for_diagnostics
|
|
1414
|
+
agy_dangerous_launch_args = services.cli_policy.agy_dangerous_launch_args
|
|
1415
|
+
agy_help_requested = services.cli_policy.agy_help_requested
|
|
1416
|
+
agy_passthrough_args_for_launch = services.cli_policy.agy_passthrough_args_for_launch
|
|
1417
|
+
agy_passthrough_has_command = services.cli_policy.agy_passthrough_has_command
|
|
1418
|
+
agy_routed_enabled = services.routing.agy_routed_enabled
|
|
1419
|
+
auto_import_passthrough_channels = services.channel.auto_import_passthrough_channels
|
|
1420
|
+
channel_delivery_mode = services.channel.channel_delivery_mode
|
|
1421
|
+
cleanup_managed_services_for_provider = services.routing.cleanup_managed_services_for_provider
|
|
1422
|
+
current_launch_cwd_key = services.config.current_launch_cwd_key
|
|
1423
|
+
find_executable = services.installation.find_executable
|
|
1424
|
+
get_current_provider = services.config.get_current_provider
|
|
1425
|
+
install_agy_if_missing = services.installation.install_agy_if_missing
|
|
1426
|
+
launch_claude = services.dispatch.launch_claude
|
|
1427
|
+
launch_codex = services.dispatch.launch_codex
|
|
1428
|
+
launch_codex_app_server = services.dispatch.launch_codex_app_server
|
|
1429
|
+
launch_readiness_errors = services.routing.launch_readiness_errors
|
|
1430
|
+
load_config = services.config.load_config
|
|
1431
|
+
log_agy_passthrough_mapping = services.dispatch.log_agy_passthrough_mapping
|
|
1432
|
+
materialize_runtime_command = services.dispatch.materialize_runtime_command
|
|
1433
|
+
native_agy_enabled = services.routing.native_agy_enabled
|
|
1434
|
+
path_with_ciel_runtime_user_dirs = services.process.path_with_ciel_runtime_user_dirs
|
|
1435
|
+
provider_mode_label = services.config.provider_mode_label
|
|
1436
|
+
record_launch_state_for_cwd = services.config.record_launch_state_for_cwd
|
|
1437
|
+
restore_agy_mcp_config_from_managed = services.config.restore_agy_mcp_config_from_managed
|
|
1438
|
+
run_agy_update_check = services.dispatch.run_agy_update_check
|
|
1439
|
+
run_ciel_runtime_update_check = services.dispatch.run_ciel_runtime_update_check
|
|
1440
|
+
run_prelaunch_menu = services.dispatch.run_prelaunch_menu
|
|
1441
|
+
run_with_router_lifetime = services.routing.run_with_router_lifetime
|
|
1442
|
+
start_router_if_needed = services.routing.start_router_if_needed
|
|
1443
|
+
subprocess_call_with_channel_wake_proxy = services.process.subprocess_call_with_channel_wake_proxy
|
|
1444
|
+
warn_if_multiple_ciel_runtime_installs = services.installation.warn_if_multiple_ciel_runtime_installs
|
|
1445
|
+
warn_if_multiple_ciel_runtime_installs()
|
|
1446
|
+
run_ciel_runtime_update_check(enabled=self_update_check)
|
|
1447
|
+
env = os.environ.copy()
|
|
1448
|
+
env["PATH"] = path_with_ciel_runtime_user_dirs(env)
|
|
1449
|
+
agy = install_agy_if_missing()
|
|
1450
|
+
if not agy:
|
|
1451
|
+
raise RuntimeError(
|
|
1452
|
+
"agy executable was not found in PATH or the Ciel Runtime/AGY user bin directories, "
|
|
1453
|
+
"and automatic install from Google's official AGY manifest did not make it available"
|
|
1454
|
+
)
|
|
1455
|
+
updated_agy = run_agy_update_check(agy, enabled=update_check)
|
|
1456
|
+
if isinstance(updated_agy, str) and updated_agy:
|
|
1457
|
+
agy = updated_agy
|
|
1458
|
+
agy = find_executable("agy") or agy
|
|
1459
|
+
agy_passthrough, agy_passthrough_notes = agy_passthrough_args_for_launch(passthrough)
|
|
1460
|
+
if agy_help_requested(agy_passthrough):
|
|
1461
|
+
log_agy_passthrough_mapping(agy_passthrough_notes)
|
|
1462
|
+
return subprocess.call([agy, *agy_passthrough], env=env)
|
|
1463
|
+
if agy_passthrough_has_command(agy_passthrough):
|
|
1464
|
+
skip_menu = True
|
|
1465
|
+
auto_import_passthrough_channels(passthrough)
|
|
1466
|
+
rc = run_prelaunch_menu(passthrough, skip_menu=skip_menu, force_menu=force_menu)
|
|
1467
|
+
if rc == PRELAUNCH_LAUNCH_CLAUDE:
|
|
1468
|
+
return launch_claude(
|
|
1469
|
+
passthrough,
|
|
1470
|
+
skip_menu=True,
|
|
1471
|
+
force_menu=False,
|
|
1472
|
+
update_check=update_check,
|
|
1473
|
+
self_update_check=False,
|
|
1474
|
+
)
|
|
1475
|
+
if rc == PRELAUNCH_LAUNCH_CODEX:
|
|
1476
|
+
return launch_codex(
|
|
1477
|
+
passthrough,
|
|
1478
|
+
skip_menu=True,
|
|
1479
|
+
force_menu=False,
|
|
1480
|
+
update_check=update_check,
|
|
1481
|
+
self_update_check=False,
|
|
1482
|
+
)
|
|
1483
|
+
if rc == PRELAUNCH_LAUNCH_CODEX_APP_SERVER:
|
|
1484
|
+
return launch_codex_app_server(
|
|
1485
|
+
passthrough,
|
|
1486
|
+
skip_menu=True,
|
|
1487
|
+
force_menu=False,
|
|
1488
|
+
update_check=update_check,
|
|
1489
|
+
self_update_check=False,
|
|
1490
|
+
)
|
|
1491
|
+
if rc == PRELAUNCH_CANCEL:
|
|
1492
|
+
return 0
|
|
1493
|
+
if rc not in (0, PRELAUNCH_LAUNCH_AGY):
|
|
1494
|
+
return rc
|
|
1495
|
+
cfg = load_config()
|
|
1496
|
+
provider, pcfg = get_current_provider(cfg)
|
|
1497
|
+
if not native_agy_enabled(provider):
|
|
1498
|
+
print("Ciel Runtime AGY launch blocked:", flush=True)
|
|
1499
|
+
print("- Select AGY or AGY Routed as the provider before launching AGY.", flush=True)
|
|
1500
|
+
return 2
|
|
1501
|
+
blockers = launch_readiness_errors(cfg)
|
|
1502
|
+
if blockers:
|
|
1503
|
+
print("Ciel Runtime AGY launch blocked:", flush=True)
|
|
1504
|
+
for line in blockers:
|
|
1505
|
+
print(f"- {line}", flush=True)
|
|
1506
|
+
return 2
|
|
1507
|
+
cleanup_managed_services_for_provider(provider, pcfg, cfg, quiet=True)
|
|
1508
|
+
restore_agy_mcp_config_from_managed(env=env, cwd=Path.cwd())
|
|
1509
|
+
use_agy_routed = agy_routed_enabled(provider, pcfg)
|
|
1510
|
+
if use_agy_routed and channel_delivery_mode(cfg) == "llm":
|
|
1511
|
+
manage_router_lifetime = bool(start_router_if_needed())
|
|
1512
|
+
elif web_backend_start_requested(cfg):
|
|
1513
|
+
manage_router_lifetime = bool(
|
|
1514
|
+
start_router_if_needed(replace_active_clients=False)
|
|
1515
|
+
)
|
|
1516
|
+
else:
|
|
1517
|
+
manage_router_lifetime = False
|
|
1518
|
+
agy_dangerous_args = agy_dangerous_launch_args(agy_passthrough)
|
|
1519
|
+
cmd, env = materialize_runtime_command(
|
|
1520
|
+
"agy",
|
|
1521
|
+
agy,
|
|
1522
|
+
env,
|
|
1523
|
+
provider,
|
|
1524
|
+
pcfg,
|
|
1525
|
+
mode="routed" if use_agy_routed else "native",
|
|
1526
|
+
protocol="anthropic_messages",
|
|
1527
|
+
cwd=Path.cwd(),
|
|
1528
|
+
enable_channels=use_agy_routed,
|
|
1529
|
+
passthrough=agy_passthrough,
|
|
1530
|
+
options={"dangerous_args": tuple(agy_dangerous_args)},
|
|
1531
|
+
)
|
|
1532
|
+
log_agy_passthrough_mapping(agy_passthrough_notes)
|
|
1533
|
+
_log_agy_command_for_diagnostics(cmd, env)
|
|
1534
|
+
record_launch_state_for_cwd(
|
|
1535
|
+
current_launch_cwd_key(),
|
|
1536
|
+
provider,
|
|
1537
|
+
provider_mode_label(provider, pcfg),
|
|
1538
|
+
str(pcfg.get("current_model") or ""),
|
|
1539
|
+
)
|
|
1540
|
+
|
|
1541
|
+
def run_agy_process() -> int:
|
|
1542
|
+
if use_agy_routed:
|
|
1543
|
+
return subprocess_call_with_channel_wake_proxy(
|
|
1544
|
+
cmd,
|
|
1545
|
+
env,
|
|
1546
|
+
wake_for_llm_delivery=channel_delivery_mode(cfg) == "llm",
|
|
1547
|
+
synthetic_enter_bytes=None,
|
|
1548
|
+
normalize_bare_cr_for_synthetic_enter=False,
|
|
1549
|
+
channel_wake_submit_retries=_codex_channel_wake_submit_retries(),
|
|
1550
|
+
channel_wake_confirm_submit=True,
|
|
1551
|
+
channel_wake_bracketed_paste=True,
|
|
1552
|
+
channel_wake_submit_delay_seconds=_codex_channel_wake_submit_delay_seconds(),
|
|
1553
|
+
)
|
|
1554
|
+
return subprocess.call(cmd, env=env)
|
|
1555
|
+
|
|
1556
|
+
return run_with_router_lifetime(run_agy_process, manage_router_lifetime)
|
|
1557
|
+
|
|
1558
|
+
|
|
1559
|
+
|
|
1560
|
+
__all__ = [
|
|
1561
|
+
"AgyLaunchServices",
|
|
1562
|
+
"AgyLaunchChannel",
|
|
1563
|
+
"AgyLaunchCliPolicy",
|
|
1564
|
+
"AgyLaunchConfig",
|
|
1565
|
+
"AgyLaunchConstants",
|
|
1566
|
+
"AgyLaunchDispatch",
|
|
1567
|
+
"AgyLaunchInstallation",
|
|
1568
|
+
"AgyLaunchProcess",
|
|
1569
|
+
"AgyLaunchRouting",
|
|
1570
|
+
"ClaudeLaunchChannelDelivery",
|
|
1571
|
+
"ClaudeLaunchChannelDiscovery",
|
|
1572
|
+
"ClaudeLaunchConfig",
|
|
1573
|
+
"ClaudeLaunchConstants",
|
|
1574
|
+
"ClaudeLaunchDispatch",
|
|
1575
|
+
"ClaudeLaunchInstallation",
|
|
1576
|
+
"ClaudeLaunchMcpConfig",
|
|
1577
|
+
"ClaudeLaunchPolicy",
|
|
1578
|
+
"ClaudeLaunchProcess",
|
|
1579
|
+
"ClaudeLaunchRouting",
|
|
1580
|
+
"ClaudeLaunchServices",
|
|
1581
|
+
"CodexAppServerLaunchServices",
|
|
1582
|
+
"CodexAppServerChannel",
|
|
1583
|
+
"CodexAppServerCliPolicy",
|
|
1584
|
+
"CodexAppServerConfig",
|
|
1585
|
+
"CodexAppServerDispatch",
|
|
1586
|
+
"CodexAppServerInstallation",
|
|
1587
|
+
"CodexAppServerProcess",
|
|
1588
|
+
"CodexAppServerRouting",
|
|
1589
|
+
"CodexLaunchChannel",
|
|
1590
|
+
"CodexLaunchCliPolicy",
|
|
1591
|
+
"CodexLaunchConfig",
|
|
1592
|
+
"CodexLaunchConstants",
|
|
1593
|
+
"CodexLaunchDispatch",
|
|
1594
|
+
"CodexLaunchInstallation",
|
|
1595
|
+
"CodexLaunchProcess",
|
|
1596
|
+
"CodexLaunchRouting",
|
|
1597
|
+
"CodexLaunchServices",
|
|
1598
|
+
"run_agy",
|
|
1599
|
+
"run_claude",
|
|
1600
|
+
"run_codex",
|
|
1601
|
+
"run_codex_app_server",
|
|
1602
|
+
]
|