@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
package/README.md CHANGED
@@ -0,0 +1,132 @@
1
+ # Ciel Runtime
2
+
3
+ Ciel Runtime is a cross-platform launcher and local model-routing layer for AI coding agents. It can launch Claude Code, Codex, Codex App Server, or AGY and connect them to native or OpenAI-compatible model providers through one configuration.
4
+
5
+ ## Features
6
+
7
+ - Launch Claude Code, Codex, Codex App Server, and AGY from one CLI.
8
+ - Route Anthropic Messages, OpenAI Chat/Responses, and Ollama-compatible traffic.
9
+ - Select models and providers without rewriting each agent's configuration.
10
+ - Rotate API keys and observe provider rate limits.
11
+ - Normalize tool calls, thinking blocks, streaming events, and context limits.
12
+ - Receive external MCP channel messages and inject them into active agent sessions.
13
+ - Run on Windows, macOS, and Linux.
14
+
15
+ ## Requirements
16
+
17
+ - Node.js 18 or newer when installed from npm.
18
+ - Python 3.10 or newer.
19
+ - At least one supported coding-agent CLI or the credentials for the provider you intend to use.
20
+
21
+ The npm launcher searches for `py -3`, `python`, or `python3`. Set `CIEL_RUNTIME_PYTHON` to use a specific Python executable.
22
+
23
+ ## Install
24
+
25
+ ```sh
26
+ npm install -g @oneciel-ai/ciel-runtime
27
+ ```
28
+
29
+ The package installs these commands:
30
+
31
+ - `ciel-runtime` and `cielrt`: configure and launch an agent.
32
+ - `ciel-runtimectl`: inspect or change runtime configuration.
33
+ - `ciel-runtime-stop`: stop the managed local router.
34
+
35
+ Manual installation instructions are available in [docs/Installation.md](docs/Installation.md).
36
+
37
+ ## Quick start
38
+
39
+ Select a provider and model interactively:
40
+
41
+ ```sh
42
+ ciel-runtime
43
+ ```
44
+
45
+ Or configure them explicitly:
46
+
47
+ ```sh
48
+ ciel-runtimectl provider openrouter
49
+ ciel-runtimectl set-api-key openrouter YOUR_API_KEY
50
+ ciel-runtimectl model MODEL_ID
51
+ ```
52
+
53
+ Launch a specific runtime:
54
+
55
+ ```sh
56
+ ciel-runtime # Claude Code by default
57
+ ciel-runtime codex
58
+ ciel-runtime agy
59
+ ciel-runtime codex-app-server
60
+ ```
61
+
62
+ Inspect the active configuration and router status:
63
+
64
+ ```sh
65
+ ciel-runtimectl status
66
+ ciel-runtimectl models
67
+ ciel-runtimectl test
68
+ ```
69
+
70
+ See [docs/CLI-Reference.md](docs/CLI-Reference.md) for the complete command reference and [docs/Providers.md](docs/Providers.md) for provider-specific options.
71
+
72
+ ## Native and routed modes
73
+
74
+ Ciel Runtime uses a provider's native endpoint when the selected agent and provider support a direct connection. Other combinations use a local HTTP router that translates request, response, streaming, thinking, and tool-call formats.
75
+
76
+ The router binds to `127.0.0.1` by default. External router access is a debugging feature and should only be enabled on a trusted network with the external access token configured. Never expose an unauthenticated development router to the public internet.
77
+
78
+ Configuration is stored under `~/.config/ciel-runtime/` on macOS and Linux or `%APPDATA%\ciel-runtime\` on Windows. Override the location with `CIEL_RUNTIME_CONFIG_DIR`. Files containing credentials are written with restricted permissions where the platform supports them.
79
+
80
+ ## Channels and MCP
81
+
82
+ Ciel Runtime can discover channel-capable MCP servers and deliver channel messages to active Claude, Codex, or AGY sessions. Channel collection, delivery acknowledgement, and terminal injection are separate layers so a failed terminal submission does not incorrectly acknowledge a message.
83
+
84
+ See [docs/MCP-Channels.md](docs/MCP-Channels.md) for configuration and transport details.
85
+
86
+ ## Stable and nightly releases
87
+
88
+ Install the stable npm release:
89
+
90
+ ```sh
91
+ npm install -g @oneciel-ai/ciel-runtime@latest
92
+ ```
93
+
94
+ Install the latest nightly build:
95
+
96
+ ```sh
97
+ npm install -g @oneciel-ai/ciel-runtime@nightly
98
+ ```
99
+
100
+ Nightly builds are intended for early validation and may change behavior before the next stable release.
101
+
102
+ ## Development
103
+
104
+ ```sh
105
+ npm test
106
+ npm run lint
107
+ npm pack --dry-run
108
+ ```
109
+
110
+ `npm test` compiles the Python entry points and runs the complete unittest suite. The full suite includes subprocess and channel integration tests and can take several minutes.
111
+
112
+ Architecture and maintenance references:
113
+
114
+ - [Architecture](docs/Architecture.md)
115
+ - [Module map](docs/Module-Map.md)
116
+ - [Router](docs/Router.md)
117
+ - [Configuration](docs/Configuration.md)
118
+ - [Observability](docs/Observability.md)
119
+ - [Test suite](docs/Test-Suite.md)
120
+
121
+ ## Security
122
+
123
+ - Keep provider API keys out of source control and shell history.
124
+ - Keep the router bound to loopback unless remote debugging is explicitly required.
125
+ - Treat request traces, response traces, transcripts, and event logs as potentially sensitive.
126
+ - Review Tool Guard configuration before granting agents access to destructive tools.
127
+
128
+ Report security issues privately to the project maintainers rather than opening a public issue with credentials or request traces.
129
+
130
+ ## License
131
+
132
+ MIT. See [LICENSE](LICENSE) and [NOTICE](NOTICE).
@@ -2,6 +2,7 @@
2
2
  from __future__ import annotations
3
3
 
4
4
  import json
5
+ import os
5
6
  import select
6
7
  import shutil
7
8
  import subprocess
@@ -15,6 +16,12 @@ import urllib.parse
15
16
  import urllib.request
16
17
  from pathlib import Path
17
18
 
19
+ from ciel_runtime_support.prelaunch_launch_preference import (
20
+ preferred_provider_launch_action,
21
+ remember_launch_action,
22
+ )
23
+ from ciel_runtime_support.runtime_paths import CONFIG_PATH
24
+
18
25
  try:
19
26
  import msvcrt
20
27
  HAS_MSVCRT = True
@@ -204,7 +211,7 @@ def _write_safe(row: int, col: int, text: str, style: str = "") -> None:
204
211
 
205
212
 
206
213
  CTL = str(Path.home() / ".local/bin/ciel-runtimectl")
207
- CONFIG = Path.home() / ".config/ciel-runtime/config.json"
214
+ CONFIG = CONFIG_PATH
208
215
  NCP_ENV = Path.home() / ".config/nvd-claude-proxy/.env"
209
216
  PROVIDERS = [
210
217
  ("agy:native", "AGY"),
@@ -585,10 +592,28 @@ def load_cfg() -> dict:
585
592
  return {"current_provider": "nvidia-hosted", "providers": {}}
586
593
 
587
594
 
595
+ def persist_launch_action(action: str) -> None:
596
+ config = load_cfg()
597
+ if not remember_launch_action(config, action):
598
+ return
599
+ CONFIG.parent.mkdir(parents=True, exist_ok=True)
600
+ temporary = CONFIG.with_name(f".{CONFIG.name}.{os.getpid()}.tmp")
601
+ try:
602
+ temporary.write_text(json.dumps(config, indent=2, ensure_ascii=False) + "\n", encoding="utf-8")
603
+ if os.name != "nt":
604
+ temporary.chmod(0o600)
605
+ temporary.replace(CONFIG)
606
+ finally:
607
+ try:
608
+ temporary.unlink(missing_ok=True)
609
+ except Exception:
610
+ pass
611
+
612
+
588
613
  KNOWN_NVIDIA_MODEL_STATUS = {
589
614
  "claude-nvidia-llama-3.1-nemotron-ultra-253b-v1": ("FAIL 404", "listed but not callable for this NVIDIA account"),
590
615
  }
591
- DEFAULT_ADVISOR_MODELS = ["deepseek-v4-pro", "claude-opus-4-6", "claude-sonnet-4-6", "glm-5.1"]
616
+ DEFAULT_ADVISOR_MODELS = ["claude-opus-5", "deepseek-v4-pro", "claude-opus-4-6", "claude-sonnet-4-6", "glm-5.1"]
592
617
  COMPAT_OK_TTL_SECONDS = 24 * 60 * 60
593
618
  COMPAT_FAIL_TTL_SECONDS = 5 * 60
594
619
 
@@ -701,6 +726,21 @@ def meaningful_key(value: str | None) -> bool:
701
726
  return bool(value and value not in ("dummy", "not-used", "ollama"))
702
727
 
703
728
 
729
+ def stored_key_looks_like_error(value: str | None) -> bool:
730
+ text = str(value or "").strip().lower()
731
+ if not text:
732
+ return False
733
+ markers = (
734
+ "urlerror", "httperror", "http error", "<urlopen error",
735
+ "eof occurred in violation of protocol", "traceback (most recent call last)",
736
+ "connection refused", "connection reset", "timed out", "unauthorized",
737
+ "401 client error", "403 client error", "404 client error",
738
+ "500 internal server error", "502 bad gateway", "503 service unavailable",
739
+ "504 gateway",
740
+ )
741
+ return any(marker in text for marker in markers)
742
+
743
+
704
744
  def api_key_status(provider: str, pcfg: dict) -> str:
705
745
  if provider == "nvidia-hosted":
706
746
  return "API key: set (NVIDIA)" if meaningful_key(read_env_file(NCP_ENV).get("NVIDIA_API_KEY")) else "API key: missing (NVIDIA required)"
@@ -715,6 +755,8 @@ def api_key_status(provider: str, pcfg: dict) -> str:
715
755
  return "API key: not set (uses native Codex login/auth headers)"
716
756
  return "API key: optional fallback (uses native Codex login/config)"
717
757
  if provider == "ollama-cloud":
758
+ if stored_key_looks_like_error(pcfg.get("api_key")):
759
+ return "API key: INVALID (stored value is an error message, not a key — re-enter)"
718
760
  return "API key: set (Ollama Cloud)" if meaningful_key(pcfg.get("api_key")) else "API key: missing (Ollama Cloud required)"
719
761
  if provider == "deepseek":
720
762
  return "API key: set (DeepSeek)" if meaningful_key(pcfg.get("api_key")) else "API key: missing (DeepSeek required)"
@@ -727,7 +769,10 @@ def api_key_status(provider: str, pcfg: dict) -> str:
727
769
 
728
770
 
729
771
  def launch_requires_api_key(provider: str, pcfg: dict) -> bool:
730
- return provider in ("nvidia-hosted", "ollama-cloud", "deepseek") and "missing" in api_key_status(provider, pcfg).lower()
772
+ if provider in ("nvidia-hosted", "ollama-cloud", "deepseek"):
773
+ status = api_key_status(provider, pcfg).lower()
774
+ return "missing" in status or "invalid" in status
775
+ return False
731
776
 
732
777
 
733
778
  def join_url(base: str, path: str) -> str:
@@ -1649,9 +1694,10 @@ def index_for_action(action: str) -> int:
1649
1694
 
1650
1695
 
1651
1696
  def default_launch_action() -> str:
1652
- if agy_launch_enabled(current_provider()):
1653
- return "launch-agy"
1654
- return "launch-codex" if codex_launch_enabled(current_provider()) else "launch"
1697
+ provider = current_provider()
1698
+ return preferred_provider_launch_action(
1699
+ load_cfg(), provider, agy_launch_enabled, claude_launch_enabled, codex_launch_enabled
1700
+ )
1655
1701
 
1656
1702
 
1657
1703
  def add(stdscr, y: int, x: int, text: str, style: str = "") -> None:
@@ -1870,6 +1916,7 @@ def main() -> int:
1870
1916
  idx = index_for_action("api-key")
1871
1917
  sub = None
1872
1918
  continue
1919
+ persist_launch_action(action)
1873
1920
  return PRELAUNCH_LAUNCH_CLAUDE
1874
1921
  if action == "launch-agy":
1875
1922
  provider, pcfg = current_provider_cfg()
@@ -1902,6 +1949,7 @@ def main() -> int:
1902
1949
  idx = index_for_action("api-key")
1903
1950
  sub = None
1904
1951
  continue
1952
+ persist_launch_action(action)
1905
1953
  return PRELAUNCH_LAUNCH_CODEX
1906
1954
  if action == "test":
1907
1955
  code, out = run_test_with_animation(idx, checks)
@@ -2121,6 +2169,7 @@ def main() -> int:
2121
2169
  ]
2122
2170
  idx = index_for_action("api-key")
2123
2171
  continue
2172
+ persist_launch_action(action)
2124
2173
  return PRELAUNCH_LAUNCH_CLAUDE
2125
2174
  if action == "launch-agy":
2126
2175
  provider, pcfg = current_provider_cfg()
@@ -2149,6 +2198,7 @@ def main() -> int:
2149
2198
  ]
2150
2199
  idx = index_for_action("api-key")
2151
2200
  continue
2201
+ persist_launch_action(action)
2152
2202
  return PRELAUNCH_LAUNCH_CODEX
2153
2203
  if action == "test":
2154
2204
  code, out = run_test_with_animation(idx, checks)