@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,211 @@
1
+ """Static Claude slash-command documents installed by Ciel Runtime."""
2
+
3
+ VERSION_SLASH_COMMAND = """---
4
+ description: Show ciel-runtime version
5
+ argument-hint: [ignored]
6
+ ---
7
+
8
+ CIEL_RUNTIME_VERSION_STATUS
9
+
10
+ Show the running ciel-runtime version for this session. This command is handled locally by the ciel-runtime router and must not be forwarded upstream.
11
+ """
12
+
13
+ ADVISOR_SLASH_COMMAND = """---
14
+ description: Run the selected ciel-runtime Advisor Model
15
+ argument-hint: [question or focus]
16
+ ---
17
+
18
+ CIEL_RUNTIME_ADVISOR_CALL
19
+
20
+ Focus: $ARGUMENTS
21
+
22
+ Use the Advisor Model selected in the ciel-runtime launch menu. If the Advisor Model is off, explain how to enable it. Otherwise review the current conversation, tool history, and task state. Return concise guidance with the blocker, next concrete action, and validation step.
23
+ """
24
+
25
+
26
+ ADVISOR_NATIVE_DISABLED_SLASH_COMMAND = """---
27
+ description: Ciel Runtime Advisor unavailable in Claude Native mode
28
+ argument-hint: [ignored]
29
+ ---
30
+
31
+ Ciel Runtime Advisor is unavailable in direct Claude Native mode.
32
+
33
+ Do not run tools, shell commands, file searches, config scans, or environment checks for this command. Reply immediately with this exact status and the short enablement hint below.
34
+
35
+ This session bypasses the ciel-runtime router, so /advisor cannot call the configured Advisor Model here. To use /advisor, launch a non-native provider or enable Anthropic routed mode in ciel-runtime.
36
+ """
37
+
38
+
39
+ ROUTER_DEBUG_SLASH_COMMAND = """---
40
+ description: Toggle ciel-runtime router external debug access
41
+ argument-hint: [on|off|status]
42
+ ---
43
+
44
+ CIEL_RUNTIME_ROUTER_DEBUG_ACCESS
45
+
46
+ Value: $ARGUMENTS
47
+
48
+ Toggle ciel-runtime router debug external access. With no argument, this toggles the current state. Use `on`, `off`, or `status` for explicit control.
49
+ """
50
+
51
+
52
+ ROUTER_DEBUG_NATIVE_DISABLED_SLASH_COMMAND = """---
53
+ description: ciel-runtime router debug unavailable in Claude Native mode
54
+ argument-hint: [ignored]
55
+ ---
56
+
57
+ ciel-runtime router debug controls are unavailable in direct Claude Native mode.
58
+
59
+ Do not run tools, shell commands, file searches, config scans, or environment checks for this command. Reply immediately with this exact status and the short enablement hint below.
60
+
61
+ This session bypasses the ciel-runtime router. Launch a non-native provider or enable Anthropic routed mode to use /router-debug.
62
+ """
63
+
64
+
65
+ LLM_SLIDER_SLASH_COMMAND = """---
66
+ description: Move/select ciel-runtime live LLM preset slider
67
+ argument-hint: [left|right|status|list|restore|preset-id]
68
+ ---
69
+
70
+ CIEL_RUNTIME_LIVE_LLM_OPTIONS
71
+
72
+ Value: $0
73
+ Arguments: $ARGUMENTS
74
+
75
+ Use one compact ciel-runtime live LLM preset control. With no argument, show the current slider. Use `left` or `right` to move one preset, `restore` to return to captured options, or a preset id/alias such as `coding`, `300k`, `512k`, or `1m`.
76
+ """
77
+
78
+
79
+ LLM_OPTIONS_SLASH_COMMAND = """---
80
+ description: Show or change ciel-runtime live LLM options
81
+ argument-hint: [left|right|status|list|restore|preset-id]
82
+ ---
83
+
84
+ CIEL_RUNTIME_LIVE_LLM_OPTIONS
85
+
86
+ Value: $0
87
+ Arguments: $ARGUMENTS
88
+
89
+ Show or change the live ciel-runtime LLM preset for this routed session. With no argument, show status and the compact preset slider. Use `left` or `right` to move one preset, `restore` to return to captured options, or a preset id/alias such as `coding`, `300k`, `512k`, or `1m`.
90
+ """
91
+
92
+
93
+ LLM_RESTORE_SLASH_COMMAND = """---
94
+ description: Restore ciel-runtime live LLM options
95
+ argument-hint: [ignored]
96
+ ---
97
+
98
+ CIEL_RUNTIME_LIVE_LLM_OPTIONS
99
+
100
+ Value: restore
101
+
102
+ Restore the LLM options captured before the first live preset change in this routed session.
103
+ """
104
+
105
+
106
+ CHANNEL_CLEAR_SLASH_COMMAND = """---
107
+ description: Discard pending ciel-runtime external channel backlog
108
+ argument-hint: [all|status]
109
+ ---
110
+
111
+ CIEL_RUNTIME_CHANNEL_CLEAR_BACKLOG
112
+
113
+ Value: $ARGUMENTS
114
+
115
+ Discard pending ciel-runtime external channel backlog without sending it to the model. Use `status` to show pending counts without clearing.
116
+ """
117
+
118
+
119
+ API_KEYS_SLASH_COMMAND = """---
120
+ description: Set/show ciel-runtime live API key(s)
121
+ argument-hint: [status|clear|KEY|KEY1,KEY2]
122
+ ---
123
+
124
+ Set API key(s) for the current ciel-runtime provider without restarting Claude Code. With no argument, show masked key status. Use `clear` or `unset` to remove keys for only the current provider. Multiple keys may be comma-, semicolon-, or newline-separated and are used round-robin. Never print raw keys.
125
+
126
+ CIEL_RUNTIME_LIVE_API_KEYS
127
+
128
+ Value: $0
129
+ Arguments:
130
+ $ARGUMENTS
131
+ """
132
+
133
+
134
+ IMPORT_SESSION_SLASH_COMMAND = """---
135
+ description: Import a Claude/Codex session transcript into this session
136
+ argument-hint: Codex|Claude [transcript-path]
137
+ ---
138
+
139
+ CIEL_RUNTIME_IMPORT_SESSION
140
+
141
+ Target: $1
142
+ Path: $2
143
+ Arguments: $ARGUMENTS
144
+
145
+ Import a session transcript into the current Ciel Runtime-routed session. `Target` names the source transcript format and must be `Codex` or `Claude`.
146
+ """
147
+
148
+
149
+ LEGACY_MARKER_PREFIX = "CLAUDE" + "_ANY"
150
+ LEGACY_ADVISOR_CALL_MARKER = LEGACY_MARKER_PREFIX + "_ADVISOR_CALL"
151
+ LEGACY_ROUTER_DEBUG_ACCESS_MARKER = LEGACY_MARKER_PREFIX + "_ROUTER_DEBUG_ACCESS"
152
+ LEGACY_LIVE_LLM_OPTIONS_MARKER = LEGACY_MARKER_PREFIX + "_LIVE_LLM_OPTIONS"
153
+ LEGACY_CHANNEL_CLEAR_BACKLOG_MARKER = LEGACY_MARKER_PREFIX + "_CHANNEL_CLEAR_BACKLOG"
154
+ LEGACY_LIVE_API_KEYS_MARKER = LEGACY_MARKER_PREFIX + "_LIVE_API_KEYS"
155
+
156
+ ADVISOR_REQUEST_MARKERS = ("CIEL_RUNTIME_ADVISOR_CALL", LEGACY_ADVISOR_CALL_MARKER)
157
+ ROUTER_DEBUG_REQUEST_MARKERS = (
158
+ "CIEL_RUNTIME_ROUTER_DEBUG_ACCESS",
159
+ LEGACY_ROUTER_DEBUG_ACCESS_MARKER,
160
+ )
161
+ VERSION_REQUEST_MARKERS = ("CIEL_RUNTIME_VERSION_STATUS",)
162
+ LIVE_LLM_OPTIONS_REQUEST_MARKERS = (
163
+ "CIEL_RUNTIME_LIVE_LLM_OPTIONS",
164
+ LEGACY_LIVE_LLM_OPTIONS_MARKER,
165
+ )
166
+ CHANNEL_CLEAR_REQUEST_MARKERS = (
167
+ "CIEL_RUNTIME_CHANNEL_CLEAR_BACKLOG",
168
+ LEGACY_CHANNEL_CLEAR_BACKLOG_MARKER,
169
+ )
170
+ LIVE_API_KEYS_REQUEST_MARKERS = (
171
+ "CIEL_RUNTIME_LIVE_API_KEYS",
172
+ LEGACY_LIVE_API_KEYS_MARKER,
173
+ )
174
+ IMPORT_SESSION_REQUEST_MARKERS = ("CIEL_RUNTIME_IMPORT_SESSION",)
175
+
176
+ CIEL_RUNTIME_ADVISOR_COMMAND_MARKERS = (
177
+ "CIEL_RUNTIME_ADVISOR_CALL",
178
+ "Run the selected ciel-runtime Advisor Model",
179
+ "Ciel Runtime Advisor is unavailable in direct Claude Native mode",
180
+ LEGACY_ADVISOR_CALL_MARKER,
181
+ )
182
+ CIEL_RUNTIME_ROUTER_DEBUG_COMMAND_MARKERS = (
183
+ "CIEL_RUNTIME_ROUTER_DEBUG_ACCESS",
184
+ "Toggle ciel-runtime router external debug access",
185
+ "ciel-runtime router debug controls are unavailable in direct Claude Native mode",
186
+ LEGACY_ROUTER_DEBUG_ACCESS_MARKER,
187
+ )
188
+ CIEL_RUNTIME_VERSION_COMMAND_MARKERS = (
189
+ "CIEL_RUNTIME_VERSION_STATUS",
190
+ "Show ciel-runtime version",
191
+ )
192
+ CIEL_RUNTIME_LLM_OPTIONS_COMMAND_MARKERS = (
193
+ "CIEL_RUNTIME_LIVE_LLM_OPTIONS",
194
+ "Show or change ciel-runtime live LLM options",
195
+ "Restore ciel-runtime live LLM options",
196
+ LEGACY_LIVE_LLM_OPTIONS_MARKER,
197
+ )
198
+ CIEL_RUNTIME_CHANNEL_CLEAR_COMMAND_MARKERS = (
199
+ "CIEL_RUNTIME_CHANNEL_CLEAR_BACKLOG",
200
+ "Discard pending ciel-runtime external channel backlog",
201
+ LEGACY_CHANNEL_CLEAR_BACKLOG_MARKER,
202
+ )
203
+ CIEL_RUNTIME_API_KEYS_COMMAND_MARKERS = (
204
+ "CIEL_RUNTIME_LIVE_API_KEYS",
205
+ "Set/show ciel-runtime live API key(s)",
206
+ LEGACY_LIVE_API_KEYS_MARKER,
207
+ )
208
+ CIEL_RUNTIME_IMPORT_SESSION_COMMAND_MARKERS = (
209
+ "CIEL_RUNTIME_IMPORT_SESSION",
210
+ "Import a Claude/Codex session transcript",
211
+ )
@@ -0,0 +1,57 @@
1
+ """Reusable Server-Sent Events stream parser and dispatch loop."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+ from typing import Any, Callable
7
+
8
+
9
+ @dataclass(frozen=True, slots=True)
10
+ class SseStreamServices:
11
+ should_continue: Callable[[], bool]
12
+ dispatch: Callable[[str, list[str], str | None], Any]
13
+ invalid_retry: Callable[[str], Any]
14
+
15
+
16
+ @dataclass(slots=True)
17
+ class SseRetryState:
18
+ seconds: float
19
+
20
+
21
+ def consume_sse_stream(
22
+ response: Any,
23
+ retry: SseRetryState,
24
+ end_message: str,
25
+ services: SseStreamServices,
26
+ ) -> None:
27
+ event_name = "message"
28
+ event_id: str | None = None
29
+ data_lines: list[str] = []
30
+ while services.should_continue():
31
+ raw = response.readline()
32
+ if raw == b"":
33
+ raise ConnectionError(end_message)
34
+ line = raw.decode("utf-8", errors="replace").rstrip("\r\n")
35
+ if not line:
36
+ if data_lines:
37
+ services.dispatch(event_name, data_lines, event_id)
38
+ event_name = "message"
39
+ event_id = None
40
+ data_lines = []
41
+ continue
42
+ if line.startswith(":"):
43
+ continue
44
+ field, _, value = line.partition(":")
45
+ if value.startswith(" "):
46
+ value = value[1:]
47
+ if field == "event":
48
+ event_name = value or "message"
49
+ elif field == "data":
50
+ data_lines.append(value)
51
+ elif field == "id":
52
+ event_id = value
53
+ elif field == "retry":
54
+ try:
55
+ retry.seconds = max(1.0, min(60.0, int(value) / 1000.0))
56
+ except (TypeError, ValueError):
57
+ services.invalid_retry(value)
@@ -0,0 +1,225 @@
1
+ """Bounded SSE event tracing and tool-call JSONL observability."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ import os
7
+ import time
8
+ from collections.abc import Callable
9
+ from dataclasses import dataclass
10
+ from pathlib import Path
11
+ from typing import Any
12
+
13
+
14
+ @dataclass(frozen=True, slots=True)
15
+ class SseTraceConfig:
16
+ config_dir: Path
17
+ last_path: Path
18
+ trace_path: Path
19
+ tool_call_path: Path
20
+ event_limit: int
21
+ payload_limit: int
22
+ max_bytes: int
23
+
24
+
25
+ @dataclass(frozen=True, slots=True)
26
+ class SseTracePorts:
27
+ enabled: Callable[[], bool]
28
+ truncate: Callable[[str, int], str]
29
+ log: Callable[[str, str], None]
30
+
31
+
32
+ def summarize_payload(
33
+ payload: dict[str, Any], truncate: Callable[[str, int], str]
34
+ ) -> dict[str, Any]:
35
+ summary: dict[str, Any] = {"type": payload.get("type")}
36
+ if "index" in payload:
37
+ summary["index"] = payload.get("index")
38
+ payload_type = payload.get("type")
39
+ if payload_type == "message_start":
40
+ message = payload.get("message") if isinstance(payload.get("message"), dict) else {}
41
+ summary["message"] = {
42
+ "id": message.get("id"),
43
+ "model": message.get("model"),
44
+ "role": message.get("role"),
45
+ "content_len": len(message.get("content") or []),
46
+ "usage": message.get("usage"),
47
+ }
48
+ elif payload_type == "message_delta":
49
+ summary["delta"] = payload.get("delta")
50
+ summary["usage"] = payload.get("usage")
51
+ elif payload_type == "content_block_start":
52
+ block = payload.get("content_block") if isinstance(payload.get("content_block"), dict) else {}
53
+ block_summary = {"type": block.get("type")}
54
+ if block.get("type") == "tool_use":
55
+ block_summary.update(
56
+ {"id": block.get("id"), "name": block.get("name"), "input": block.get("input")}
57
+ )
58
+ elif block.get("type") == "text":
59
+ block_summary["text_len"] = len(str(block.get("text") or ""))
60
+ else:
61
+ block_summary["keys"] = sorted(str(key) for key in block)
62
+ summary["content_block"] = block_summary
63
+ elif payload_type == "content_block_delta":
64
+ delta = payload.get("delta") if isinstance(payload.get("delta"), dict) else {}
65
+ delta_type = delta.get("type")
66
+ delta_summary: dict[str, Any] = {"type": delta_type}
67
+ if delta_type == "text_delta":
68
+ text = str(delta.get("text") or "")
69
+ delta_summary.update({"text_len": len(text), "text": truncate(text, 500)})
70
+ elif delta_type == "input_json_delta":
71
+ partial = str(delta.get("partial_json") or "")
72
+ delta_summary.update(
73
+ {
74
+ "partial_json_len": len(partial),
75
+ "partial_json": truncate(partial, 1000),
76
+ }
77
+ )
78
+ else:
79
+ delta_summary["keys"] = sorted(str(key) for key in delta)
80
+ summary["delta"] = delta_summary
81
+ else:
82
+ summary["keys"] = sorted(str(key) for key in payload)
83
+ return summary
84
+
85
+
86
+ class SseTraceRepository:
87
+ def __init__(self, config: SseTraceConfig, ports: SseTracePorts) -> None:
88
+ self.config = config
89
+ self.ports = ports
90
+
91
+ def begin(
92
+ self,
93
+ provider: str,
94
+ model: str,
95
+ source: str,
96
+ source_body: dict[str, Any] | None = None,
97
+ ) -> dict[str, Any]:
98
+ return {
99
+ "time": time.strftime("%Y-%m-%dT%H:%M:%S"),
100
+ "provider": provider,
101
+ "model": model,
102
+ "source": source,
103
+ "stream": True,
104
+ "messages_count": len(source_body.get("messages") or [])
105
+ if isinstance(source_body, dict)
106
+ else None,
107
+ "tools_count": len(source_body.get("tools") or [])
108
+ if isinstance(source_body, dict)
109
+ else None,
110
+ "metadata_keys": sorted(str(key) for key in (source_body.get("metadata") or {}))
111
+ if isinstance(source_body, dict) and isinstance(source_body.get("metadata"), dict)
112
+ else [],
113
+ "event_count": 0,
114
+ "events_truncated": False,
115
+ "events": [],
116
+ }
117
+
118
+ def record(
119
+ self, trace: dict[str, Any] | None, event_name: str, payload: dict[str, Any]
120
+ ) -> None:
121
+ if not isinstance(trace, dict):
122
+ return
123
+ try:
124
+ trace["event_count"] = int(trace.get("event_count") or 0) + 1
125
+ events = trace.get("events")
126
+ if not isinstance(events, list):
127
+ events = []
128
+ trace["events"] = events
129
+ if len(events) >= self.config.event_limit:
130
+ trace["events_truncated"] = True
131
+ return
132
+ raw = ""
133
+ if self.ports.enabled():
134
+ try:
135
+ encoded = json.dumps(payload, ensure_ascii=False, separators=(",", ":"))
136
+ raw = self.ports.truncate(encoded, self.config.payload_limit)
137
+ except (TypeError, ValueError, OverflowError) as exc:
138
+ self.ports.log(
139
+ "WARN",
140
+ f"sse_trace_payload_encode_failed event={event_name} "
141
+ f"error={type(exc).__name__}: {exc}",
142
+ )
143
+ event = {
144
+ "n": trace["event_count"],
145
+ "event": event_name,
146
+ "payload": summarize_payload(payload, self.ports.truncate),
147
+ }
148
+ if raw:
149
+ event["raw"] = raw
150
+ events.append(event)
151
+ except Exception as exc:
152
+ self.ports.log(
153
+ "WARN",
154
+ f"sse_trace_event_record_failed event={event_name} "
155
+ f"error={type(exc).__name__}: {exc}",
156
+ )
157
+
158
+ def finish(self, trace: dict[str, Any] | None, **outcome: Any) -> None:
159
+ if not isinstance(trace, dict):
160
+ return
161
+ try:
162
+ trace.update({"finished_at": time.strftime("%Y-%m-%dT%H:%M:%S"), **outcome})
163
+ self.config.config_dir.mkdir(parents=True, exist_ok=True)
164
+ temporary = self.config.last_path.with_name(
165
+ f"{self.config.last_path.name}.{os.getpid()}.{time.time_ns()}.tmp"
166
+ )
167
+ encoded = json.dumps(trace, ensure_ascii=False, separators=(",", ":"))
168
+ temporary.write_text(encoded, encoding="utf-8")
169
+ temporary.replace(self.config.last_path)
170
+ if self.ports.enabled():
171
+ self._rotate(self.config.trace_path, self.config.max_bytes)
172
+ with self.config.trace_path.open("a", encoding="utf-8") as stream:
173
+ stream.write(encoded + "\n")
174
+ except Exception as exc:
175
+ self.ports.log(
176
+ "WARN",
177
+ f"sse_trace_finish_failed outcome={outcome.get('outcome')} "
178
+ f"error={type(exc).__name__}: {exc}",
179
+ )
180
+
181
+ def finish_stream(
182
+ self,
183
+ trace: dict[str, Any] | None,
184
+ *,
185
+ outcome: str,
186
+ text_len: int = 0,
187
+ tool_call_count: int = 0,
188
+ chunks: int = 0,
189
+ stop_reason: str | None = None,
190
+ error: str | None = None,
191
+ ) -> None:
192
+ result: dict[str, Any] = {
193
+ "outcome": outcome,
194
+ "text_len": text_len,
195
+ "tool_call_count": tool_call_count,
196
+ "chunks": chunks,
197
+ "stop_reason": stop_reason,
198
+ }
199
+ if error:
200
+ result["error"] = error
201
+ self.finish(trace, **result)
202
+
203
+ def append_tool_call(self, event: str, payload: dict[str, Any]) -> None:
204
+ try:
205
+ self.config.config_dir.mkdir(parents=True, exist_ok=True)
206
+ self._rotate(self.config.tool_call_path, 2_000_000)
207
+ record = {
208
+ "time": time.strftime("%Y-%m-%dT%H:%M:%S"),
209
+ "event": event,
210
+ **payload,
211
+ }
212
+ with self.config.tool_call_path.open("a", encoding="utf-8") as stream:
213
+ stream.write(
214
+ json.dumps(record, ensure_ascii=False, separators=(",", ":")) + "\n"
215
+ )
216
+ except Exception as exc:
217
+ self.ports.log(
218
+ "WARN",
219
+ f"tool_call_log_write_failed event={event} error={type(exc).__name__}: {exc}",
220
+ )
221
+
222
+ @staticmethod
223
+ def _rotate(path: Path, max_bytes: int) -> None:
224
+ if path.exists() and path.stat().st_size > max_bytes:
225
+ path.replace(path.with_suffix(".jsonl.1"))