@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.
Files changed (287) hide show
  1. package/README.md +132 -0
  2. package/ciel-runtime-menu.py +56 -6
  3. package/ciel_runtime.py +9379 -35909
  4. package/ciel_runtime_support/advisor_client.py +193 -0
  5. package/ciel_runtime_support/advisor_policy.py +320 -0
  6. package/ciel_runtime_support/advisor_refinement.py +160 -0
  7. package/ciel_runtime_support/advisor_request_builder.py +261 -0
  8. package/ciel_runtime_support/agy_installer.py +169 -0
  9. package/ciel_runtime_support/agy_mcp_restore.py +182 -0
  10. package/ciel_runtime_support/anthropic_model_policy.py +186 -0
  11. package/ciel_runtime_support/anthropic_response_writer.py +255 -0
  12. package/ciel_runtime_support/anthropic_tool_turns.py +130 -0
  13. package/ciel_runtime_support/api_key_cooldown.py +159 -0
  14. package/ciel_runtime_support/architecture.py +488 -1
  15. package/ciel_runtime_support/architecture_budget.py +42 -0
  16. package/ciel_runtime_support/channel_backlog.py +90 -0
  17. package/ciel_runtime_support/channel_cli.py +119 -0
  18. package/ciel_runtime_support/channel_compact_injection.py +82 -0
  19. package/ciel_runtime_support/channel_compact_poll.py +67 -0
  20. package/ciel_runtime_support/channel_compact_request_repository.py +113 -0
  21. package/ciel_runtime_support/channel_config_service.py +281 -0
  22. package/ciel_runtime_support/channel_connection_lifecycle.py +180 -0
  23. package/ciel_runtime_support/channel_connection_registry.py +128 -0
  24. package/ciel_runtime_support/channel_connection_worker.py +284 -0
  25. package/ciel_runtime_support/channel_cursor_recovery.py +92 -0
  26. package/ciel_runtime_support/channel_cursor_repository.py +89 -0
  27. package/ciel_runtime_support/channel_cursor_service.py +178 -0
  28. package/ciel_runtime_support/channel_event_identity.py +212 -0
  29. package/ciel_runtime_support/channel_event_projection.py +315 -0
  30. package/ciel_runtime_support/channel_inflight.py +127 -0
  31. package/ciel_runtime_support/channel_injection.py +115 -0
  32. package/ciel_runtime_support/channel_launch_guard_repository.py +58 -0
  33. package/ciel_runtime_support/channel_launch_policy.py +180 -0
  34. package/ciel_runtime_support/channel_llm_context.py +156 -0
  35. package/ciel_runtime_support/channel_mcp_discovery.py +186 -0
  36. package/ciel_runtime_support/channel_mcp_http_controller.py +239 -0
  37. package/ciel_runtime_support/channel_mcp_ownership.py +148 -0
  38. package/ciel_runtime_support/channel_mcp_tools.py +240 -0
  39. package/ciel_runtime_support/channel_mcp_transport.py +394 -0
  40. package/ciel_runtime_support/channel_message_dedupe.py +65 -0
  41. package/ciel_runtime_support/channel_message_policy.py +256 -0
  42. package/ciel_runtime_support/channel_message_prompt.py +305 -0
  43. package/ciel_runtime_support/channel_message_repository.py +234 -0
  44. package/ciel_runtime_support/channel_notification_projection.py +217 -0
  45. package/ciel_runtime_support/channel_panel.py +162 -0
  46. package/ciel_runtime_support/channel_pending_injection.py +209 -0
  47. package/ciel_runtime_support/channel_pending_poll.py +109 -0
  48. package/ciel_runtime_support/channel_probe_cache.py +433 -0
  49. package/ciel_runtime_support/channel_probe_report.py +101 -0
  50. package/ciel_runtime_support/channel_runtime_environment.py +181 -0
  51. package/ciel_runtime_support/channel_session_lifecycle.py +114 -0
  52. package/ciel_runtime_support/channel_session_repository.py +90 -0
  53. package/ciel_runtime_support/channel_terminal_dispatch.py +115 -0
  54. package/ciel_runtime_support/channel_terminal_input.py +277 -0
  55. package/ciel_runtime_support/channel_terminal_proxy.py +447 -0
  56. package/ciel_runtime_support/channel_tool_context.py +166 -0
  57. package/ciel_runtime_support/channel_transcript.py +414 -0
  58. package/ciel_runtime_support/channel_transcript_repository.py +96 -0
  59. package/ciel_runtime_support/channel_wake_claim_repository.py +126 -0
  60. package/ciel_runtime_support/channel_wake_delivery_repository.py +88 -0
  61. package/ciel_runtime_support/chat_files.py +138 -0
  62. package/ciel_runtime_support/chat_http_controller.py +235 -0
  63. package/ciel_runtime_support/claude_environment.py +375 -0
  64. package/ciel_runtime_support/claude_router.py +247 -193
  65. package/ciel_runtime_support/cli_dispatch.py +792 -0
  66. package/ciel_runtime_support/cli_parser.py +165 -0
  67. package/ciel_runtime_support/cli_usage.py +100 -0
  68. package/ciel_runtime_support/codex_app_server.py +20 -5
  69. package/ciel_runtime_support/codex_channel_sse_launch.py +87 -0
  70. package/ciel_runtime_support/codex_cli.py +42 -6
  71. package/ciel_runtime_support/codex_config.py +323 -0
  72. package/ciel_runtime_support/codex_launch_configuration.py +240 -0
  73. package/ciel_runtime_support/codex_launch_policy.py +66 -0
  74. package/ciel_runtime_support/codex_mcp_integration.py +195 -0
  75. package/ciel_runtime_support/codex_mcp_restore.py +304 -0
  76. package/ciel_runtime_support/codex_model_catalog.py +133 -0
  77. package/ciel_runtime_support/codex_process_lifecycle.py +271 -0
  78. package/ciel_runtime_support/codex_router.py +147 -1
  79. package/ciel_runtime_support/codex_session_repository.py +115 -0
  80. package/ciel_runtime_support/codex_session_selection.py +114 -0
  81. package/ciel_runtime_support/command_asset_installer.py +103 -0
  82. package/ciel_runtime_support/compatibility_probe.py +295 -0
  83. package/ciel_runtime_support/compatibility_protocol.py +251 -0
  84. package/ciel_runtime_support/compatibility_runtime.py +166 -0
  85. package/ciel_runtime_support/compatibility_test.py +370 -0
  86. package/ciel_runtime_support/config_migrations.py +307 -0
  87. package/ciel_runtime_support/config_repository.py +175 -0
  88. package/ciel_runtime_support/config_value_codec.py +64 -0
  89. package/ciel_runtime_support/configuration_cli.py +374 -0
  90. package/ciel_runtime_support/context_compaction.py +280 -0
  91. package/ciel_runtime_support/context_setup.py +208 -0
  92. package/ciel_runtime_support/context_summary_policy.py +392 -0
  93. package/ciel_runtime_support/credential_cli.py +104 -0
  94. package/ciel_runtime_support/credential_management.py +261 -0
  95. package/ciel_runtime_support/credentials.py +269 -0
  96. package/ciel_runtime_support/executable_discovery.py +141 -0
  97. package/ciel_runtime_support/github_copilot_oauth.py +335 -0
  98. package/ciel_runtime_support/github_copilot_oauth_runtime.py +213 -0
  99. package/ciel_runtime_support/header_forwarding.py +73 -0
  100. package/ciel_runtime_support/headless_config.py +221 -0
  101. package/ciel_runtime_support/http_response.py +129 -0
  102. package/ciel_runtime_support/install_diagnostics.py +149 -0
  103. package/ciel_runtime_support/kimi_identity.py +123 -0
  104. package/ciel_runtime_support/launch_diagnostics.py +204 -0
  105. package/ciel_runtime_support/launch_state.py +127 -0
  106. package/ciel_runtime_support/live_api_key_controller.py +58 -0
  107. package/ciel_runtime_support/llm_config_http.py +148 -0
  108. package/ciel_runtime_support/llm_option_config.py +259 -0
  109. package/ciel_runtime_support/llm_presentation_data.py +447 -0
  110. package/ciel_runtime_support/llm_presets.py +773 -0
  111. package/ciel_runtime_support/lm_studio_runtime.py +401 -0
  112. package/ciel_runtime_support/managed_mcp_config.py +144 -0
  113. package/ciel_runtime_support/managed_mcp_discovery.py +151 -0
  114. package/ciel_runtime_support/managed_service_cleanup.py +89 -0
  115. package/ciel_runtime_support/mcp_config_reader.py +230 -0
  116. package/ciel_runtime_support/mcp_http_proxy.py +607 -0
  117. package/ciel_runtime_support/mcp_inventory.py +59 -0
  118. package/ciel_runtime_support/mcp_notification_wait_policy.py +159 -0
  119. package/ciel_runtime_support/mcp_probe_codec.py +136 -0
  120. package/ciel_runtime_support/mcp_probe_transport.py +328 -0
  121. package/ciel_runtime_support/mcp_proxy_codec.py +345 -0
  122. package/ciel_runtime_support/mcp_proxy_config.py +107 -0
  123. package/ciel_runtime_support/mcp_proxy_notifications.py +261 -0
  124. package/ciel_runtime_support/mcp_proxy_process.py +560 -0
  125. package/ciel_runtime_support/mcp_split_proxy_http.py +165 -0
  126. package/ciel_runtime_support/mcp_stdio_probe.py +240 -0
  127. package/ciel_runtime_support/mcp_transport.py +146 -0
  128. package/ciel_runtime_support/model_cache_lifecycle.py +78 -0
  129. package/ciel_runtime_support/model_catalog_projection.py +61 -0
  130. package/ciel_runtime_support/model_context_hints.py +109 -0
  131. package/ciel_runtime_support/model_panel.py +147 -0
  132. package/ciel_runtime_support/model_registry_repository.py +231 -0
  133. package/ciel_runtime_support/npm_runtime.py +191 -0
  134. package/ciel_runtime_support/ollama_catalog.py +462 -0
  135. package/ciel_runtime_support/ollama_catalog_cli.py +41 -0
  136. package/ciel_runtime_support/ollama_catalog_repository.py +75 -0
  137. package/ciel_runtime_support/ollama_context_sync.py +87 -0
  138. package/ciel_runtime_support/ollama_forwarding.py +449 -0
  139. package/ciel_runtime_support/openai_chat_passthrough.py +67 -0
  140. package/ciel_runtime_support/openai_chat_router.py +64 -0
  141. package/ciel_runtime_support/openai_forwarding.py +194 -0
  142. package/ciel_runtime_support/openai_responses_router.py +291 -0
  143. package/ciel_runtime_support/openai_responses_stream.py +135 -0
  144. package/ciel_runtime_support/output_budget.py +89 -0
  145. package/ciel_runtime_support/package_lifecycle.py +217 -0
  146. package/ciel_runtime_support/plan_artifact_controller.py +104 -0
  147. package/ciel_runtime_support/prelaunch.py +959 -0
  148. package/ciel_runtime_support/prelaunch_launch_preference.py +75 -0
  149. package/ciel_runtime_support/prelaunch_panel_projection.py +396 -0
  150. package/ciel_runtime_support/prelaunch_terminal.py +764 -0
  151. package/ciel_runtime_support/process_control.py +708 -0
  152. package/ciel_runtime_support/prompt_compaction.py +322 -0
  153. package/ciel_runtime_support/prompt_injection.py +176 -0
  154. package/ciel_runtime_support/protocols/__init__.py +24 -0
  155. package/ciel_runtime_support/protocols/anthropic_content.py +29 -0
  156. package/ciel_runtime_support/protocols/anthropic_thinking_policy.py +336 -0
  157. package/ciel_runtime_support/protocols/chat_projection.py +315 -0
  158. package/ciel_runtime_support/protocols/conversation_policy.py +217 -0
  159. package/ciel_runtime_support/protocols/conversation_turn_policy.py +972 -0
  160. package/ciel_runtime_support/protocols/ollama_chat.py +111 -0
  161. package/ciel_runtime_support/protocols/ollama_response.py +231 -0
  162. package/ciel_runtime_support/protocols/openai_reasoning.py +75 -0
  163. package/ciel_runtime_support/protocols/openai_responses.py +271 -0
  164. package/ciel_runtime_support/protocols/pseudo_tool_history.py +248 -0
  165. package/ciel_runtime_support/protocols/tool_result_projection.py +112 -0
  166. package/ciel_runtime_support/provider_adapters.py +160 -0
  167. package/ciel_runtime_support/provider_catalog_sources.py +316 -0
  168. package/ciel_runtime_support/provider_choice.py +201 -0
  169. package/ciel_runtime_support/provider_compatibility.py +165 -0
  170. package/ciel_runtime_support/provider_config_mutations.py +361 -0
  171. package/ciel_runtime_support/provider_configuration_service.py +162 -0
  172. package/ciel_runtime_support/provider_context.py +308 -0
  173. package/ciel_runtime_support/provider_contract_projection.py +73 -0
  174. package/ciel_runtime_support/provider_descriptor.py +82 -0
  175. package/ciel_runtime_support/provider_endpoint_policy.py +130 -0
  176. package/ciel_runtime_support/provider_endpoint_probe.py +165 -0
  177. package/ciel_runtime_support/provider_launch_endpoint.py +109 -0
  178. package/ciel_runtime_support/provider_limits.py +457 -0
  179. package/ciel_runtime_support/provider_model_identity.py +139 -0
  180. package/ciel_runtime_support/provider_model_selection.py +431 -0
  181. package/ciel_runtime_support/provider_model_specs.py +142 -0
  182. package/ciel_runtime_support/provider_models.py +263 -0
  183. package/ciel_runtime_support/provider_network.py +176 -0
  184. package/ciel_runtime_support/provider_option_cli.py +238 -0
  185. package/ciel_runtime_support/provider_option_panel.py +275 -0
  186. package/ciel_runtime_support/provider_option_status.py +192 -0
  187. package/ciel_runtime_support/provider_policy.py +101 -0
  188. package/ciel_runtime_support/provider_query_policy.py +67 -0
  189. package/ciel_runtime_support/provider_readiness.py +112 -0
  190. package/ciel_runtime_support/provider_request_access.py +131 -0
  191. package/ciel_runtime_support/provider_request_builder.py +250 -0
  192. package/ciel_runtime_support/provider_responses_passthrough.py +81 -0
  193. package/ciel_runtime_support/provider_runtime_info.py +113 -0
  194. package/ciel_runtime_support/provider_runtime_modes.py +150 -0
  195. package/ciel_runtime_support/provider_sampling_policy.py +46 -0
  196. package/ciel_runtime_support/provider_status.py +145 -0
  197. package/ciel_runtime_support/provider_timeout_policy.py +184 -0
  198. package/ciel_runtime_support/provider_tool_policy.py +145 -0
  199. package/ciel_runtime_support/providers/__init__.py +65 -0
  200. package/ciel_runtime_support/providers/anthropic.py +160 -0
  201. package/ciel_runtime_support/providers/anthropic_catalog.py +119 -0
  202. package/ciel_runtime_support/providers/base.py +232 -0
  203. package/ciel_runtime_support/providers/catalog.py +326 -0
  204. package/ciel_runtime_support/providers/cloud.py +194 -0
  205. package/ciel_runtime_support/providers/constants.py +54 -0
  206. package/ciel_runtime_support/providers/deepseek.py +115 -0
  207. package/ciel_runtime_support/providers/fireworks.py +158 -0
  208. package/ciel_runtime_support/providers/github_copilot_oauth.py +199 -0
  209. package/ciel_runtime_support/providers/kimi.py +297 -0
  210. package/ciel_runtime_support/providers/lm_studio.py +76 -0
  211. package/ciel_runtime_support/providers/meta.py +257 -0
  212. package/ciel_runtime_support/providers/native.py +194 -0
  213. package/ciel_runtime_support/providers/nim.py +69 -0
  214. package/ciel_runtime_support/providers/nvidia.py +158 -0
  215. package/ciel_runtime_support/providers/nvidia_runtime.py +285 -0
  216. package/ciel_runtime_support/providers/ollama.py +181 -0
  217. package/ciel_runtime_support/providers/ollama_context.py +195 -0
  218. package/ciel_runtime_support/providers/ollama_runtime.py +213 -0
  219. package/ciel_runtime_support/providers/opencode.py +220 -0
  220. package/ciel_runtime_support/providers/opencode_go.py +37 -0
  221. package/ciel_runtime_support/providers/openrouter.py +57 -0
  222. package/ciel_runtime_support/providers/vllm.py +65 -0
  223. package/ciel_runtime_support/providers/zai.py +119 -0
  224. package/ciel_runtime_support/pseudo_tool_parser.py +115 -0
  225. package/ciel_runtime_support/rate_limit_policy.py +117 -0
  226. package/ciel_runtime_support/rate_limit_repository.py +154 -0
  227. package/ciel_runtime_support/registry.py +46 -0
  228. package/ciel_runtime_support/request_shortcuts.py +253 -0
  229. package/ciel_runtime_support/request_trace.py +323 -0
  230. package/ciel_runtime_support/response_collection.py +209 -0
  231. package/ciel_runtime_support/router_access.py +238 -0
  232. package/ciel_runtime_support/router_client_lifecycle.py +366 -0
  233. package/ciel_runtime_support/router_health_policy.py +101 -0
  234. package/ciel_runtime_support/router_http.py +513 -0
  235. package/ciel_runtime_support/router_process_lifecycle.py +401 -0
  236. package/ciel_runtime_support/router_rate_limit_service.py +285 -0
  237. package/ciel_runtime_support/router_server_runtime.py +103 -0
  238. package/ciel_runtime_support/router_shortcuts.py +201 -0
  239. package/ciel_runtime_support/routing_fallback.py +73 -0
  240. package/ciel_runtime_support/runtime_activity_repository.py +143 -0
  241. package/ciel_runtime_support/runtime_adapters.py +104 -0
  242. package/ciel_runtime_support/runtime_command_factory.py +73 -0
  243. package/ciel_runtime_support/runtime_compatibility.py +50 -0
  244. package/ciel_runtime_support/runtime_constants.py +178 -0
  245. package/ciel_runtime_support/runtime_launch.py +1602 -0
  246. package/ciel_runtime_support/runtime_llm_options.py +312 -0
  247. package/ciel_runtime_support/runtime_logging.py +161 -0
  248. package/ciel_runtime_support/runtime_paths.py +157 -0
  249. package/ciel_runtime_support/runtime_restart.py +84 -0
  250. package/ciel_runtime_support/runtime_upgrade.py +149 -0
  251. package/ciel_runtime_support/secure_json_repository.py +55 -0
  252. package/ciel_runtime_support/session_import.py +356 -0
  253. package/ciel_runtime_support/settings_repository.py +8 -0
  254. package/ciel_runtime_support/slash_command_assets.py +211 -0
  255. package/ciel_runtime_support/sse_stream.py +57 -0
  256. package/ciel_runtime_support/sse_trace.py +225 -0
  257. package/ciel_runtime_support/statusline_script.py +593 -0
  258. package/ciel_runtime_support/statusline_settings.py +53 -0
  259. package/ciel_runtime_support/stream_chunk_policy.py +18 -0
  260. package/ciel_runtime_support/streaming_anthropic.py +1955 -0
  261. package/ciel_runtime_support/synthetic_tool_policy.py +105 -0
  262. package/ciel_runtime_support/terminal_platform_io.py +127 -0
  263. package/ciel_runtime_support/timeout_profile.py +196 -0
  264. package/ciel_runtime_support/tool_dialects.py +85 -0
  265. package/ciel_runtime_support/tool_exposure_policy.py +63 -0
  266. package/ciel_runtime_support/tool_guard_hooks.py +218 -0
  267. package/ciel_runtime_support/tool_request_projection.py +96 -0
  268. package/ciel_runtime_support/tool_schema.py +483 -0
  269. package/ciel_runtime_support/tool_side_effect_dedupe.py +95 -0
  270. package/ciel_runtime_support/ui_text.py +266 -0
  271. package/ciel_runtime_support/upstream_error_policy.py +104 -0
  272. package/ciel_runtime_support/upstream_retry.py +419 -0
  273. package/ciel_runtime_support/upstream_stream_io.py +106 -0
  274. package/ciel_runtime_support/usage_events.py +96 -0
  275. package/ciel_runtime_support/visible_stream_filters.py +130 -0
  276. package/ciel_runtime_support/web_endpoints.py +447 -0
  277. package/ciel_runtime_support/web_ui.py +915 -0
  278. package/ciel_runtime_support/web_ui_controller.py +189 -0
  279. package/ciel_runtime_support/windows_console_input.py +137 -0
  280. package/ciel_runtime_support/windows_console_mode.py +112 -0
  281. package/docs/Architecture.md +54 -0
  282. package/docs/Configuration.md +17 -0
  283. package/docs/Module-Map.md +1093 -26
  284. package/docs/Providers.md +46 -1
  285. package/docs/adr/0001-runtime-bounded-contexts.md +295 -0
  286. package/npm-bin/run-ciel-runtime.js +22 -2
  287. package/package.json +9 -2
@@ -0,0 +1,165 @@
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ from dataclasses import dataclass
5
+ from typing import Any, Callable
6
+
7
+ CliHandler = Callable[[argparse.Namespace], Any]
8
+
9
+
10
+ @dataclass(frozen=True)
11
+ class CliParserLaunch:
12
+ cli: CliHandler
13
+ launch: CliHandler
14
+ launch_codex: CliHandler
15
+ launch_codex_app_server: CliHandler
16
+ launch_agy: CliHandler
17
+ serve: CliHandler
18
+
19
+
20
+ @dataclass(frozen=True)
21
+ class CliParserRuntime:
22
+ version: CliHandler
23
+ status: CliHandler
24
+ env: CliHandler
25
+ stop: CliHandler
26
+ test: CliHandler
27
+
28
+
29
+ @dataclass(frozen=True)
30
+ class CliParserSettings:
31
+ language: CliHandler
32
+ web_search: CliHandler
33
+ web_fetch: CliHandler
34
+ log_level: CliHandler
35
+ channels: CliHandler
36
+ channel_delivery: CliHandler
37
+
38
+
39
+ @dataclass(frozen=True)
40
+ class CliParserProvider:
41
+ ollama_native: CliHandler
42
+ ollama_options: CliHandler
43
+ provider_options: CliHandler
44
+ ollama_catalog: CliHandler
45
+ provider: CliHandler
46
+ api_key: CliHandler
47
+ set_api_key: CliHandler
48
+ set_api_keys: CliHandler
49
+ base_url: CliHandler
50
+ copilot_oauth: CliHandler
51
+
52
+
53
+ @dataclass(frozen=True)
54
+ class CliParserModels:
55
+ model: CliHandler
56
+ advisor_model: CliHandler
57
+ models: CliHandler
58
+
59
+
60
+ @dataclass(frozen=True)
61
+ class CliParserServices:
62
+ launch: CliParserLaunch
63
+ runtime: CliParserRuntime
64
+ settings: CliParserSettings
65
+ provider: CliParserProvider
66
+ models: CliParserModels
67
+
68
+
69
+ def build_cli_parser(services: CliParserServices) -> argparse.ArgumentParser:
70
+ parser = argparse.ArgumentParser(prog="ciel-runtimectl")
71
+ commands = parser.add_subparsers(dest="cmd", required=True)
72
+ _add_remainder_command(commands, "cli", services.launch.cli)
73
+ _add_remainder_command(commands, "launch", services.launch.launch)
74
+ _add_remainder_command(commands, "launch-codex", services.launch.launch_codex)
75
+ _add_remainder_command(
76
+ commands,
77
+ "launch-codex-app-server",
78
+ services.launch.launch_codex_app_server,
79
+ )
80
+ _add_remainder_command(commands, "launch-agy", services.launch.launch_agy)
81
+ commands.add_parser("serve").set_defaults(func=services.launch.serve)
82
+ commands.add_parser("version").set_defaults(func=services.runtime.version)
83
+ commands.add_parser("status").set_defaults(func=services.runtime.status)
84
+ commands.add_parser("env").set_defaults(func=services.runtime.env)
85
+ commands.add_parser("stop").set_defaults(func=services.runtime.stop)
86
+ _add_optional_value_command(commands, "language", services.settings.language)
87
+ _add_optional_value_command(commands, "web-search", services.settings.web_search)
88
+ _add_optional_value_command(commands, "web-fetch", services.settings.web_fetch)
89
+ _add_optional_value_command(commands, "log-level", services.settings.log_level)
90
+ channels = commands.add_parser("channels")
91
+ channels.add_argument("values", nargs="*")
92
+ channels.set_defaults(func=services.settings.channels)
93
+ _add_optional_value_command(commands, "channel-delivery", services.settings.channel_delivery)
94
+ _add_optional_value_command(commands, "ollama-native", services.provider.ollama_native)
95
+ _add_values_command(commands, "ollama-options", services.provider.ollama_options)
96
+ _add_values_command(commands, "provider-options", services.provider.provider_options)
97
+ ollama_catalog = commands.add_parser("ollama-catalog")
98
+ ollama_catalog.add_argument("--no-contexts", action="store_true")
99
+ ollama_catalog.add_argument("--timeout", type=float, default=10.0)
100
+ ollama_catalog.set_defaults(func=services.provider.ollama_catalog)
101
+ test = commands.add_parser("test")
102
+ test.add_argument("timeout", nargs="?", type=float, default=120.0)
103
+ test.add_argument("mode", nargs="?", choices=("auto", "quick", "smoke", "full"), default="auto")
104
+ test.set_defaults(func=services.runtime.test)
105
+ provider = commands.add_parser("provider")
106
+ provider.add_argument("name", nargs="?")
107
+ provider.set_defaults(func=services.provider.provider)
108
+ api_key = commands.add_parser("api-key")
109
+ api_key.add_argument("provider", nargs="?")
110
+ api_key.add_argument("action", nargs="?")
111
+ api_key.set_defaults(func=services.provider.api_key)
112
+ set_api_key = commands.add_parser("set-api-key")
113
+ set_api_key.add_argument("provider")
114
+ set_api_key.add_argument("key")
115
+ set_api_key.set_defaults(func=services.provider.set_api_key)
116
+ set_api_keys = commands.add_parser("set-api-keys")
117
+ set_api_keys.add_argument("provider")
118
+ set_api_keys.add_argument("keys", nargs="+")
119
+ set_api_keys.set_defaults(func=services.provider.set_api_keys)
120
+ base_url = commands.add_parser("base-url")
121
+ base_url.add_argument("provider")
122
+ base_url.add_argument("url")
123
+ base_url.set_defaults(func=services.provider.base_url)
124
+ copilot_oauth = commands.add_parser("copilot-oauth")
125
+ copilot_oauth.add_argument(
126
+ "action",
127
+ nargs="?",
128
+ choices=("login", "status", "logout"),
129
+ default="status",
130
+ )
131
+ copilot_oauth.set_defaults(func=services.provider.copilot_oauth)
132
+ _add_values_command(commands, "model", services.models.model, argument_name="value")
133
+ _add_values_command(commands, "advisor-model", services.models.advisor_model, argument_name="value")
134
+ models = commands.add_parser("models")
135
+ models.add_argument("provider", nargs="?")
136
+ models.set_defaults(func=services.models.models)
137
+ return parser
138
+
139
+
140
+ def _add_remainder_command(
141
+ commands: Any,
142
+ name: str,
143
+ handler: CliHandler,
144
+ ) -> None:
145
+ command = commands.add_parser(name, add_help=False)
146
+ command.add_argument("argv", nargs=argparse.REMAINDER)
147
+ command.set_defaults(func=handler)
148
+
149
+
150
+ def _add_optional_value_command(commands: Any, name: str, handler: CliHandler) -> None:
151
+ command = commands.add_parser(name)
152
+ command.add_argument("value", nargs="?")
153
+ command.set_defaults(func=handler)
154
+
155
+
156
+ def _add_values_command(
157
+ commands: Any,
158
+ name: str,
159
+ handler: CliHandler,
160
+ *,
161
+ argument_name: str = "values",
162
+ ) -> None:
163
+ command = commands.add_parser(name)
164
+ command.add_argument(argument_name, nargs="*")
165
+ command.set_defaults(func=handler)
@@ -0,0 +1,100 @@
1
+ """User-facing command-line usage presentation."""
2
+
3
+ def cli_usage_text() -> str:
4
+ return """Usage:
5
+ ciel-runtime Launch Claude Code through ciel-runtime router
6
+ ciel-runtime codex [args...] Launch Codex through ciel-runtime router
7
+ ciel-runtime codex-app-server [args...] Launch Codex app-server through ciel-runtime
8
+ ciel-runtime agy [args...] Launch Google Antigravity CLI through ciel-runtime
9
+ ciel-runtime resume Resume Codex/AGY when that runtime provider is selected
10
+
11
+ Control plane, runs before Claude Code and does not require LLM connectivity:
12
+ ciel-runtime version Print ciel-runtime version
13
+ ciel-runtime language [en|ko|ja|zh] Set display language
14
+ ciel-runtime provider Pick provider with arrow-key TUI
15
+ ciel-runtime provider list List providers
16
+ ciel-runtime provider PROVIDER Set provider
17
+ ciel-runtime base-url PROVIDER URL Set provider base URL
18
+ ciel-runtime model MODEL_ID Set current provider model
19
+ ciel-runtime advisor-model MODEL_ID Set current provider advisor model (off disables)
20
+ ciel-runtime models [PROVIDER] List models
21
+ ciel-runtime api-key PROVIDER Store API key securely
22
+ ciel-runtime api-key PROVIDER clear Clear stored API key(s)
23
+ ciel-runtime set-api-key PROVIDER KEY
24
+ ciel-runtime set-api-keys PROVIDER KEY1,KEY2
25
+ ciel-runtime web-search [on|off] Auto-attach DuckDuckGo MCP for non-native providers
26
+ ciel-runtime web-fetch [on|off] Auto-attach fetch MCP for web page content
27
+ ciel-runtime log-level [LEVEL] Show or set router log level
28
+ ciel-runtime channels [cmd] Configure external channel specs
29
+ ciel-runtime channel-delivery [stdin|native]
30
+ Select PTY wake proxy or native claude/channel bridge
31
+ ciel-runtime ollama-native [on|off] Use Ollama's official Claude Code env path
32
+ ciel-runtime ollama-options [provider] [key=value ...]
33
+ Set Ollama num_ctx/options/keep_alive/think
34
+ ciel-runtime provider-options [provider] [key=value ...]
35
+ Set vLLM/NIM/NVIDIA output/context/timeouts
36
+ ciel-runtime ollama-catalog Download Ollama model/context catalog
37
+ ciel-runtime test [seconds] [mode] Test compatibility; mode is auto, quick, smoke, or full
38
+ ciel-runtime stop Stop router/proxy
39
+
40
+ Headless setup flags, namespaced to avoid Claude CLI collisions:
41
+ ciel-runtime --ca-web-address HOST Bind the web/router server to HOST for this launch
42
+ ciel-runtime --ca-web-port PORT Select the web/router port for this launch
43
+ ciel-runtime --ca-tailscale-https[=PORT]
44
+ Publish localhost through Tailscale Serve HTTPS
45
+ ciel-runtime --ca-provider PROVIDER Set provider, then launch
46
+ ciel-runtime --ca-env-file PATH Load CIEL_RUNTIME_* values from a .env file
47
+ ciel-runtime --ca-runtime claude|codex|codex-app-server|agy
48
+ Select Claude Code, Codex, Codex app-server, or AGY for this launch
49
+ ciel-runtime --ca-menu Apply setup values, then open the menu
50
+ ciel-runtime --ca-language en|ko|ja|zh
51
+ ciel-runtime --ca-base-url URL Set current provider base URL, then launch
52
+ ciel-runtime --ca-model MODEL_ID Set provider model, then launch
53
+ ciel-runtime --ca-advisor-model MODEL_ID
54
+ ciel-runtime --ca-auto-llm-options [MODEL_ID]
55
+ Apply recommended LLM options for MODEL_ID or the saved model
56
+ ciel-runtime --ca-api-key KEY Set current provider API key, then launch
57
+ ciel-runtime --ca-api-key clear Clear current provider API key(s), then launch
58
+ ciel-runtime --ca-api-key-env ENVVAR Set current provider API key from env, then launch
59
+ ciel-runtime --ca-api-keys KEY1,KEY2 Set current provider API keys with round-robin
60
+ ciel-runtime --ca-api-keys-env ENVVAR
61
+ Set current provider API keys from env, then launch
62
+ ciel-runtime --ca-set-api-key PROVIDER KEY
63
+ ciel-runtime --ca-set-api-key-env PROVIDER ENVVAR
64
+ ciel-runtime --ca-set-api-keys PROVIDER KEY1,KEY2
65
+ ciel-runtime --ca-set-api-keys-env PROVIDER ENVVAR
66
+ ciel-runtime --ca-provider-option KEY=VALUE
67
+ Set a provider option for the current provider
68
+ ciel-runtime --ca-set-provider-option PROVIDER KEY=VALUE
69
+ Set a provider option for a specific provider
70
+ ciel-runtime --ca-ollama-num-ctx VALUE
71
+ ciel-runtime --ca-ollama-ctx-range MIN MAX
72
+ ciel-runtime --ca-ollama-option KEY=VALUE
73
+ ciel-runtime --ca-max-output-tokens VALUE
74
+ ciel-runtime --ca-context-window VALUE
75
+ ciel-runtime --ca-request-timeout-ms VALUE
76
+ ciel-runtime --ca-stream-idle-timeout-ms VALUE
77
+ ciel-runtime --ca-rate-limit-rpm VALUE
78
+ ciel-runtime --ca-rate-limit-status on|off
79
+ ciel-runtime --ca-stream on|off
80
+ ciel-runtime --ca-stream-word-chunking on|off
81
+ ciel-runtime --ca-log-level LEVEL Set router log level: SILENT, ERROR, WARN, INFO, DEBUG, TRACE
82
+ ciel-runtime --ca-web-search Force DuckDuckGo MCP for this launch
83
+ ciel-runtime --ca-no-web-search Disable DuckDuckGo MCP for this launch
84
+ ciel-runtime --ca-web-fetch Enable fetch MCP
85
+ ciel-runtime --ca-no-web-fetch Disable fetch MCP
86
+ ciel-runtime --ca-channel SPEC Add an official/approved Claude Code channel
87
+ ciel-runtime --ca-channel-delivery MODE
88
+ Set channel delivery: stdin or native
89
+ ciel-runtime --ca-clear-channels Clear saved channel specs
90
+ ciel-runtime --ca-no-self-update-check
91
+ Skip Ciel Runtime npm self-update check
92
+ ciel-runtime --ca-no-update-check Skip runtime update check for this launch
93
+ ciel-runtime --ca-upgrade-and-exit Update Ciel Runtime, Claude Code, Codex, and AGY without prompts, then exit
94
+ ciel-runtime --ca-no-launch Apply setup flags/env values, then exit without launching a runtime
95
+ ciel-runtime --ca-stop Stop router/proxy
96
+ ciel-runtime -- Pass all following args directly to the selected runtime
97
+
98
+ Provider names: agy, agy-routed, anthropic, ollama, ollama-cloud, deepseek, opencode, opencode-go, kimi, z.ai, vllm, lm-studio, nvidia-hosted, self-hosted-nim, openrouter, fireworks
99
+ Any other arguments are passed through to the selected runtime. Use -- before runtime
100
+ flags that collide with ciel-runtime setup flags."""
@@ -144,17 +144,32 @@ class CodexAppServerClient:
144
144
  with self._lock:
145
145
  return self._state
146
146
 
147
- def close(self) -> None:
147
+ def close(self, timeout: float = 2.0) -> None:
148
+ """Close pipes and reap the child, surfacing cleanup failures."""
149
+
150
+ errors: list[str] = []
148
151
  try:
149
152
  if self.process.stdin is not None:
150
153
  self.process.stdin.close()
151
- except Exception:
152
- pass
154
+ except Exception as exc:
155
+ errors.append(f"stdin close failed: {type(exc).__name__}: {exc}")
153
156
  if self.process.poll() is None:
154
157
  try:
155
158
  self.process.terminate()
156
- except Exception:
157
- pass
159
+ except Exception as exc:
160
+ errors.append(f"terminate failed: {type(exc).__name__}: {exc}")
161
+ try:
162
+ self.process.wait(timeout=max(0.0, timeout))
163
+ except subprocess.TimeoutExpired:
164
+ try:
165
+ self.process.kill()
166
+ self.process.wait(timeout=max(0.0, timeout))
167
+ except Exception as exc:
168
+ errors.append(f"kill failed: {type(exc).__name__}: {exc}")
169
+ except Exception as exc:
170
+ errors.append(f"wait failed: {type(exc).__name__}: {exc}")
171
+ if errors:
172
+ raise CodexAppServerError("; ".join(errors))
158
173
 
159
174
  def initialize(
160
175
  self,
@@ -0,0 +1,87 @@
1
+ """Codex MCP channel SSE launch ownership and capability policy."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Callable, Iterable
6
+ from dataclasses import dataclass
7
+ from pathlib import Path
8
+ from typing import Any
9
+
10
+
11
+ @dataclass(frozen=True, slots=True)
12
+ class CodexChannelSseQueryPorts:
13
+ delivery_mode: Callable[[dict[str, Any]], str]
14
+ channel_specs: Callable[[dict[str, Any], list[str]], list[str]]
15
+ server_names: Callable[[Iterable[str]], list[str]]
16
+ capable_names: Callable[[dict[str, Any], Path], list[str]]
17
+ dedupe: Callable[[Iterable[str]], list[str]]
18
+
19
+
20
+ @dataclass(frozen=True, slots=True)
21
+ class CodexChannelSseEffects:
22
+ auto_start: Callable[..., list[dict[str, Any]]]
23
+ log: Callable[[str, str], None]
24
+
25
+
26
+ @dataclass(frozen=True, slots=True)
27
+ class CodexChannelSseLaunchService:
28
+ query: CodexChannelSseQueryPorts
29
+ effects: CodexChannelSseEffects
30
+ native_channel_names: frozenset[str]
31
+
32
+ def start(
33
+ self,
34
+ config: dict[str, Any],
35
+ mcp_config: Path | None,
36
+ allowed_server_names: Iterable[str] | None = None,
37
+ ) -> list[dict[str, Any]]:
38
+ if not mcp_config or self.query.delivery_mode(config) != "llm":
39
+ return []
40
+ if not mcp_config.exists() or not mcp_config.is_file():
41
+ return []
42
+ explicit = {
43
+ name
44
+ for name in self.query.server_names(
45
+ self.query.channel_specs(config, [])
46
+ )
47
+ if name.strip().casefold() not in self.native_channel_names
48
+ }
49
+ if allowed_server_names is None:
50
+ names = self.query.capable_names(config, mcp_config)
51
+ else:
52
+ names = self.query.dedupe(
53
+ str(name or "").strip()
54
+ for name in allowed_server_names
55
+ if str(name or "").strip()
56
+ and str(name or "").strip().casefold()
57
+ not in self.native_channel_names
58
+ )
59
+ names = [name for name in names if name not in explicit]
60
+ if not names:
61
+ self.effects.log(
62
+ "INFO",
63
+ "codex_channel_sse_skipped "
64
+ "reason=no_capable_unowned_codex_mcp "
65
+ "allowed=%s explicit=%s"
66
+ % (
67
+ ",".join(names) or "-",
68
+ ",".join(sorted(explicit)) or "-",
69
+ ),
70
+ )
71
+ return []
72
+ started = self.effects.auto_start(
73
+ [],
74
+ extra_config_paths=[mcp_config],
75
+ allowed_server_names=names,
76
+ include_default_paths=False,
77
+ )
78
+ self.effects.log(
79
+ "INFO",
80
+ "codex_channel_sse_started count=%d servers=%s"
81
+ % (
82
+ len(started),
83
+ ",".join(str(item.get("name") or "") for item in started)
84
+ or "-",
85
+ ),
86
+ )
87
+ return started
@@ -72,11 +72,16 @@ CODEX_CLAUDE_ONLY_VALUE_FLAGS = {
72
72
 
73
73
 
74
74
  def codex_passthrough_first_non_option_arg(passthrough: list[str]) -> str:
75
+ index = codex_passthrough_first_non_option_index(passthrough)
76
+ return str(passthrough[index]) if index >= 0 else ""
77
+
78
+
79
+ def codex_passthrough_first_non_option_index(passthrough: list[str]) -> int:
75
80
  i = 0
76
81
  while i < len(passthrough):
77
82
  arg = str(passthrough[i])
78
83
  if arg == "--":
79
- return str(passthrough[i + 1]) if i + 1 < len(passthrough) else ""
84
+ return i + 1 if i + 1 < len(passthrough) else -1
80
85
  if arg.startswith("--") and "=" in arg:
81
86
  i += 1
82
87
  continue
@@ -86,14 +91,46 @@ def codex_passthrough_first_non_option_arg(passthrough: list[str]) -> str:
86
91
  if arg.startswith("-") and arg != "-":
87
92
  i += 1
88
93
  continue
89
- return arg
90
- return ""
94
+ return i
95
+ return -1
91
96
 
92
97
 
93
98
  def codex_passthrough_has_command(passthrough: list[str]) -> bool:
94
99
  return codex_passthrough_first_non_option_arg(passthrough) in CODEX_COMMAND_NAMES
95
100
 
96
101
 
102
+ def codex_resume_picker_requested(passthrough: list[str]) -> bool:
103
+ command_index = codex_passthrough_first_non_option_index(passthrough)
104
+ if command_index < 0 or str(passthrough[command_index]) != "resume":
105
+ return False
106
+ i = command_index + 1
107
+ while i < len(passthrough):
108
+ arg = str(passthrough[i])
109
+ if arg in ("--last", "--all") or arg.startswith(("--last=", "--all=")):
110
+ i += 1
111
+ continue
112
+ if arg.startswith("--") and "=" in arg:
113
+ i += 1
114
+ continue
115
+ if arg in CODEX_OPTIONS_WITH_VALUE:
116
+ i += 2 if i + 1 < len(passthrough) else 1
117
+ continue
118
+ if arg.startswith("-") and arg != "-":
119
+ i += 1
120
+ continue
121
+ return False
122
+ return "--last" not in passthrough and not any(str(arg).startswith("--last=") for arg in passthrough)
123
+
124
+
125
+ def codex_resume_with_session_id(passthrough: list[str], session_id: str) -> list[str]:
126
+ command_index = codex_passthrough_first_non_option_index(passthrough)
127
+ if command_index < 0 or str(passthrough[command_index]) != "resume":
128
+ return list(passthrough)
129
+ out = list(passthrough)
130
+ out.insert(command_index + 1, session_id)
131
+ return out
132
+
133
+
97
134
  def _codex_consume_optional_value(passthrough: list[str], index: int) -> tuple[str, int]:
98
135
  if index + 1 < len(passthrough):
99
136
  value = str(passthrough[index + 1])
@@ -298,6 +335,5 @@ def codex_passthrough_args_for_launch(passthrough: list[str]) -> tuple[list[str]
298
335
  out.append(arg)
299
336
  i += 1
300
337
 
301
- if mapped_command and not existing_codex_command:
302
- return [*mapped_command, *out], notes
303
- return out, notes
338
+ result = [*mapped_command, *out] if mapped_command and not existing_codex_command else out
339
+ return result, notes