@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,65 @@
1
+ """Concrete provider adapters and their shared transport bases."""
2
+
3
+ from .anthropic import AnthropicProviderAdapter
4
+ from .base import (
5
+ HttpBearerProviderAdapter,
6
+ NoAuthProviderAdapter,
7
+ OpenAICompatibleProviderAdapter,
8
+ )
9
+ from .constants import PROVIDER_DEFAULT_BASE_URLS, ZAI_MODEL_FALLBACK_IDS
10
+ from .native import AgyProviderAdapter, CodexProviderAdapter
11
+ from .ollama import OllamaCloudProviderAdapter, OllamaProviderAdapter
12
+ from .openrouter import OpenRouterProviderAdapter
13
+ from .lm_studio import LMStudioProviderAdapter
14
+ from .nim import SelfHostedNimProviderAdapter
15
+ from .nvidia import NvidiaHostedProviderAdapter
16
+ from .vllm import VllmProviderAdapter
17
+ from .deepseek import DeepSeekProviderAdapter
18
+ from .fireworks import FireworksProviderAdapter
19
+ from .zai import ZaiProviderAdapter
20
+ from .kimi import KimiProviderAdapter
21
+ from .opencode import OpenCodeProviderAdapter
22
+ from .opencode_go import OpenCodeGoProviderAdapter
23
+ from .catalog import (
24
+ COMPATIBLE_PROVIDER_SPECS,
25
+ CatalogOpenAIProviderAdapter,
26
+ CompatibleProviderSpec,
27
+ )
28
+ from .anthropic_catalog import (
29
+ ANTHROPIC_COMPATIBLE_PROVIDER_SPECS,
30
+ AnthropicCompatibleProviderSpec,
31
+ CatalogAnthropicProviderAdapter,
32
+ )
33
+ from .cloud import AzureOpenAIProviderAdapter, CodeBuddyCnProviderAdapter
34
+
35
+ __all__ = [
36
+ "ANTHROPIC_COMPATIBLE_PROVIDER_SPECS",
37
+ "AnthropicCompatibleProviderSpec",
38
+ "CatalogAnthropicProviderAdapter",
39
+ "AzureOpenAIProviderAdapter",
40
+ "CodeBuddyCnProviderAdapter",
41
+ "HttpBearerProviderAdapter",
42
+ "AnthropicProviderAdapter",
43
+ "NoAuthProviderAdapter",
44
+ "OpenAICompatibleProviderAdapter",
45
+ "PROVIDER_DEFAULT_BASE_URLS",
46
+ "ZAI_MODEL_FALLBACK_IDS",
47
+ "AgyProviderAdapter",
48
+ "CodexProviderAdapter",
49
+ "OllamaCloudProviderAdapter",
50
+ "OllamaProviderAdapter",
51
+ "OpenRouterProviderAdapter",
52
+ "LMStudioProviderAdapter",
53
+ "NvidiaHostedProviderAdapter",
54
+ "SelfHostedNimProviderAdapter",
55
+ "VllmProviderAdapter",
56
+ "DeepSeekProviderAdapter",
57
+ "FireworksProviderAdapter",
58
+ "ZaiProviderAdapter",
59
+ "KimiProviderAdapter",
60
+ "OpenCodeProviderAdapter",
61
+ "OpenCodeGoProviderAdapter",
62
+ "COMPATIBLE_PROVIDER_SPECS",
63
+ "CatalogOpenAIProviderAdapter",
64
+ "CompatibleProviderSpec",
65
+ ]
@@ -0,0 +1,160 @@
1
+ """Anthropic native and routed provider adapter."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass, field
6
+ from typing import Any, Mapping
7
+
8
+ from ..architecture import (
9
+ ProviderCapabilities,
10
+ ProviderConfigurationPolicy,
11
+ ProviderConfig,
12
+ ProviderContextPolicy,
13
+ ProviderModelCatalogPolicy,
14
+ ProviderOptionPresentationPolicy,
15
+ ProviderRequestPolicy,
16
+ ProviderUiPolicy,
17
+ )
18
+ from .base import NoAuthProviderAdapter, provider_configuration
19
+ from .constants import PROVIDER_DEFAULT_BASE_URLS
20
+
21
+
22
+ @dataclass(frozen=True)
23
+ class AnthropicProviderAdapter(NoAuthProviderAdapter):
24
+ name: str = "anthropic"
25
+ base_url: str = PROVIDER_DEFAULT_BASE_URLS["anthropic"]
26
+ configuration_defaults_value: dict = field(
27
+ default_factory=lambda: provider_configuration(
28
+ "claude-sonnet-4-6", route_through_router=False
29
+ )
30
+ )
31
+ capabilities_value: ProviderCapabilities = field(
32
+ default_factory=lambda: ProviderCapabilities(
33
+ upstream_protocol="anthropic_messages",
34
+ supports_thinking=True,
35
+ preserves_anthropic_thinking=True,
36
+ blocks_default_tools=False,
37
+ repairs_anthropic_tool_input=True,
38
+ )
39
+ )
40
+ request_policy_value: ProviderRequestPolicy = field(
41
+ default_factory=lambda: ProviderRequestPolicy(
42
+ chat_path="/v1/messages",
43
+ models_path="/v1/models",
44
+ credential_strategy="anthropic_inbound",
45
+ normalize_historical_tool_turns=False,
46
+ )
47
+ )
48
+ model_catalog_policy_value: ProviderModelCatalogPolicy = field(
49
+ default_factory=lambda: ProviderModelCatalogPolicy(kind="anthropic")
50
+ )
51
+
52
+ def advisor_panel_notice(
53
+ self, config: ProviderConfig
54
+ ) -> tuple[tuple[str, ...], tuple[str, ...]]:
55
+ del config
56
+ return (
57
+ (
58
+ "Claude native and Anthropic routed sessions use Claude Code's",
59
+ "built-in /advisor (run /advisor in the session to pick its model).",
60
+ "Back",
61
+ ),
62
+ ("back", "back", "back"),
63
+ )
64
+
65
+ def configuration_policy(
66
+ self, config: ProviderConfig
67
+ ) -> ProviderConfigurationPolicy:
68
+ del config
69
+ return ProviderConfigurationPolicy(
70
+ supports_route_through_router=True, restricts_runtime_options=True
71
+ )
72
+
73
+ def supports_server_advisor_tool(self, config: ProviderConfig) -> bool:
74
+ del config
75
+ return True
76
+
77
+ def context_compaction_available(self, config: ProviderConfig) -> bool:
78
+ return bool(config.api_keys)
79
+
80
+ def context_policy(self, config: ProviderConfig) -> ProviderContextPolicy:
81
+ routed = bool(config.options.get("route_through_router"))
82
+ return ProviderContextPolicy(
83
+ capacity_strategy="anthropic_hint" if routed else "managed",
84
+ hosted_timeout=True,
85
+ managed_preset_inference=True,
86
+ status_capacity_strategy="provider" if routed else "configured",
87
+ )
88
+
89
+ def intercepts_advisor_shortcut(self, config: ProviderConfig) -> bool:
90
+ del config
91
+ return False
92
+
93
+ def routing_mode_update(self, enabled: bool) -> tuple[str, ...]:
94
+ mode = (
95
+ "routed through ciel-runtime router" if enabled else "direct Claude Native"
96
+ )
97
+ return ("Anthropic routing mode updated.", f"mode: {mode}")
98
+
99
+ def selection_config_updates(self, config: ProviderConfig) -> Mapping[str, Any]:
100
+ del config
101
+ return {"route_through_router": False}
102
+
103
+ def selection_status_lines(self, config: ProviderConfig) -> tuple[str, ...]:
104
+ del config
105
+ return ("mode: anthropic-native",)
106
+
107
+ def option_presentation_policy(
108
+ self, config: ProviderConfig
109
+ ) -> ProviderOptionPresentationPolicy:
110
+ del config
111
+ return ProviderOptionPresentationPolicy(
112
+ show_route=True, show_ip_family_control=True
113
+ )
114
+
115
+ def ui_policy(self, config: ProviderConfig) -> ProviderUiPolicy:
116
+ del config
117
+ return ProviderUiPolicy(
118
+ menu_label="Claude Native",
119
+ routed_menu_label="Anthropic routed",
120
+ native_choice="anthropic:native",
121
+ routed_choice="anthropic:routed",
122
+ advisor_placeholder="Claude Code native /advisor",
123
+ uses_native_advisor=True,
124
+ )
125
+
126
+ def option_timeout_default(self) -> str:
127
+ return "Claude Code default"
128
+
129
+ def propagates_inbound_beta_query(self, config: ProviderConfig) -> bool:
130
+ del config
131
+ return True
132
+
133
+ def api_key_status(
134
+ self, config: ProviderConfig, *, key_count: int, primary_detail: str
135
+ ) -> str:
136
+ routed = bool(config.options.get("route_through_router"))
137
+ scope = "Anthropic routed" if routed else "Anthropic"
138
+ if key_count > 1:
139
+ return f"API keys: {key_count} keys, round-robin ({scope}{primary_detail})"
140
+ if key_count:
141
+ return f"API key: set ({scope}{primary_detail})"
142
+ return (
143
+ "API key: not set (uses Claude Code OAuth/API auth headers)"
144
+ if routed
145
+ else "API key: not set (use API key or Claude login)"
146
+ )
147
+
148
+ def build_model_headers(
149
+ self, config: ProviderConfig, api_key: str | None
150
+ ) -> Mapping[str, str]:
151
+ del config
152
+ key = str(api_key or "").strip()
153
+ return (
154
+ {"anthropic-version": "2023-06-01", "x-api-key": key}
155
+ if key
156
+ else {"anthropic-version": "2023-06-01"}
157
+ )
158
+
159
+
160
+ __all__ = ["AnthropicProviderAdapter"]
@@ -0,0 +1,119 @@
1
+ """Declarative adapters for Anthropic Messages-compatible API providers."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+ from functools import partial
7
+ from typing import Callable
8
+
9
+ from ..architecture import (
10
+ ProviderAdapter,
11
+ ProviderCapabilities,
12
+ ProviderConfig,
13
+ ProviderContextPolicy,
14
+ ProviderModelCatalogPolicy,
15
+ ProviderRequestPolicy,
16
+ )
17
+ from ..runtime_constants import DEFAULT_REQUEST_TIMEOUT_MS
18
+ from .base import HttpBearerProviderAdapter, provider_configuration
19
+
20
+
21
+ @dataclass(frozen=True, slots=True)
22
+ class AnthropicCompatibleProviderSpec:
23
+ name: str
24
+ label: str
25
+ base_url: str
26
+ models: tuple[str, ...]
27
+ aliases: tuple[str, ...] = ()
28
+
29
+
30
+ class CatalogAnthropicProviderAdapter(HttpBearerProviderAdapter):
31
+ """Anthropic-compatible transport assembled from immutable provider data."""
32
+
33
+ def __init__(
34
+ self,
35
+ spec: AnthropicCompatibleProviderSpec,
36
+ *,
37
+ base_url: str = "",
38
+ ) -> None:
39
+ self.spec = spec
40
+ super().__init__(
41
+ name=spec.name,
42
+ base_url=base_url or spec.base_url,
43
+ configuration_defaults_value=provider_configuration(
44
+ spec.models[0],
45
+ custom_models=spec.models,
46
+ native_compat=True,
47
+ preserve_anthropic_thinking=True,
48
+ context_window=200000,
49
+ max_output_tokens=8192,
50
+ context_reserve_tokens=8192,
51
+ request_timeout_ms=DEFAULT_REQUEST_TIMEOUT_MS,
52
+ stream_enabled=True,
53
+ stream_word_chunking=False,
54
+ ),
55
+ require_api_key=True,
56
+ api_key_display_name_value=spec.label,
57
+ api_key_launch_error_value=(
58
+ f"Launch blocked: {spec.label} requires an API key."
59
+ ),
60
+ capabilities_value=ProviderCapabilities(
61
+ upstream_protocol="anthropic_messages",
62
+ requires_api_key=True,
63
+ supports_thinking=True,
64
+ preserves_anthropic_thinking=True,
65
+ ),
66
+ request_policy_value=ProviderRequestPolicy(
67
+ chat_path="/v1/messages",
68
+ models_path="/v1/models",
69
+ ),
70
+ model_catalog_policy_value=ProviderModelCatalogPolicy(
71
+ kind="openai",
72
+ fallback_models=spec.models,
73
+ allow_configured_fallback=True,
74
+ ),
75
+ )
76
+
77
+ def context_policy(self, config: ProviderConfig) -> ProviderContextPolicy:
78
+ del config
79
+ return ProviderContextPolicy(
80
+ capacity_strategy="configured_first",
81
+ settings_strategy="standard",
82
+ hosted_timeout=True,
83
+ )
84
+
85
+
86
+ def anthropic_catalog_provider_factory(
87
+ spec: AnthropicCompatibleProviderSpec,
88
+ ) -> Callable[..., ProviderAdapter]:
89
+ return partial(CatalogAnthropicProviderAdapter, spec)
90
+
91
+
92
+ ANTHROPIC_COMPATIBLE_PROVIDER_SPECS = (
93
+ AnthropicCompatibleProviderSpec(
94
+ "minimax",
95
+ "MiniMax",
96
+ "https://api.minimax.io/anthropic",
97
+ ("MiniMax-M2.5", "MiniMax-M2.1", "MiniMax-M2"),
98
+ ),
99
+ AnthropicCompatibleProviderSpec(
100
+ "minimax-cn",
101
+ "MiniMax China",
102
+ "https://api.minimaxi.com/anthropic",
103
+ ("MiniMax-M2.5", "MiniMax-M2.1", "MiniMax-M2"),
104
+ ("minimaxi",),
105
+ ),
106
+ )
107
+
108
+ ANTHROPIC_CATALOG_PROVIDER_BASE_URLS = {
109
+ spec.name: spec.base_url for spec in ANTHROPIC_COMPATIBLE_PROVIDER_SPECS
110
+ }
111
+
112
+
113
+ __all__ = [
114
+ "ANTHROPIC_CATALOG_PROVIDER_BASE_URLS",
115
+ "ANTHROPIC_COMPATIBLE_PROVIDER_SPECS",
116
+ "AnthropicCompatibleProviderSpec",
117
+ "CatalogAnthropicProviderAdapter",
118
+ "anthropic_catalog_provider_factory",
119
+ ]
@@ -0,0 +1,232 @@
1
+ """Shared transport bases for concrete provider adapters."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from copy import deepcopy
6
+ from dataclasses import dataclass, field
7
+ from typing import Any, Mapping, Sequence
8
+
9
+ from ..architecture import (
10
+ MessageProtocol,
11
+ ModelInfo,
12
+ ProviderAdapter,
13
+ ProviderCapabilities,
14
+ ProviderConfigurationPolicy,
15
+ ProviderConfig,
16
+ ProviderContextPolicy,
17
+ ProviderModelCatalogPolicy,
18
+ ProviderOptionPresentationPolicy,
19
+ ProviderRequestPolicy,
20
+ )
21
+
22
+
23
+ ROUTER_STATUS_FIELDS: tuple[str, ...] = (
24
+ "context_window",
25
+ "context_reserve_tokens",
26
+ "max_output_tokens",
27
+ "request_timeout_ms",
28
+ "stream_idle_timeout_ms",
29
+ )
30
+
31
+
32
+ def configuration_policy(**values: Any) -> ProviderConfigurationPolicy:
33
+ status_fields = values.pop("status_fields", ROUTER_STATUS_FIELDS)
34
+ return ProviderConfigurationPolicy(status_fields=status_fields, **values)
35
+
36
+
37
+ def provider_configuration(
38
+ current_model: str = "",
39
+ *,
40
+ api_key: str = "",
41
+ custom_models: Sequence[str] = (),
42
+ **values: Any,
43
+ ) -> dict[str, Any]:
44
+ """Build the common persisted configuration shape for one provider."""
45
+
46
+ return {
47
+ "api_key": api_key,
48
+ "current_model": current_model,
49
+ "advisor_model": "",
50
+ "custom_models": list(custom_models),
51
+ **values,
52
+ }
53
+
54
+
55
+ @dataclass(frozen=True)
56
+ class HttpBearerProviderAdapter(ProviderAdapter):
57
+ """Provider adapter for bearer/x-api-key compatible APIs."""
58
+
59
+ name: str
60
+ base_url: str = ""
61
+ configuration_defaults_value: Mapping[str, Any] = field(default_factory=dict)
62
+ authorization_header: str = "authorization"
63
+ include_x_api_key: bool = True
64
+ require_api_key: bool = False
65
+ send_placeholder_key: bool = False
66
+ api_key_display_name_value: str = ""
67
+ api_key_launch_error_value: str = ""
68
+ capabilities_value: ProviderCapabilities = field(
69
+ default_factory=ProviderCapabilities
70
+ )
71
+ request_policy_value: ProviderRequestPolicy = field(
72
+ default_factory=lambda: ProviderRequestPolicy(
73
+ chat_path="/v1/chat/completions",
74
+ models_path="/v1/models",
75
+ )
76
+ )
77
+ model_catalog_policy_value: ProviderModelCatalogPolicy = field(
78
+ default_factory=ProviderModelCatalogPolicy
79
+ )
80
+
81
+ def default_base_url(self) -> str:
82
+ return self.base_url
83
+
84
+ def default_configuration(self) -> Mapping[str, Any]:
85
+ defaults = dict(super().default_configuration())
86
+ defaults.update(deepcopy(dict(self.configuration_defaults_value)))
87
+ defaults["base_url"] = self.default_base_url()
88
+ return defaults
89
+
90
+ def list_models(self, config: ProviderConfig) -> Sequence[ModelInfo]:
91
+ raw_models: Any = (
92
+ config.options.get("available_models") or config.options.get("models") or ()
93
+ )
94
+ if isinstance(raw_models, str):
95
+ raw_models = [raw_models]
96
+ models: list[ModelInfo] = []
97
+ if isinstance(raw_models, (list, tuple)):
98
+ for item in raw_models:
99
+ if isinstance(item, str) and item.strip():
100
+ models.append(ModelInfo(id=item.strip()))
101
+ elif isinstance(item, dict) and str(item.get("id") or "").strip():
102
+ models.append(ModelInfo(id=str(item["id"]).strip(), raw=item))
103
+ if config.model and all(model.id != config.model for model in models):
104
+ models.insert(0, ModelInfo(id=config.model))
105
+ return tuple(models)
106
+
107
+ def build_headers(
108
+ self, config: ProviderConfig, api_key: str | None
109
+ ) -> Mapping[str, str]:
110
+ key = str(api_key or "").strip()
111
+ if self.require_api_key and not key:
112
+ raise RuntimeError(f"{self.name} requires a configured API key.")
113
+ if not key and self.send_placeholder_key:
114
+ key = "not-used"
115
+ if not key:
116
+ return {}
117
+ headers = {self.authorization_header: f"Bearer {key}"}
118
+ if self.include_x_api_key:
119
+ headers["x-api-key"] = key
120
+ return headers
121
+
122
+ def capabilities(self, config: ProviderConfig) -> ProviderCapabilities:
123
+ del config
124
+ return self.capabilities_value
125
+
126
+ def request_policy(self, config: ProviderConfig) -> ProviderRequestPolicy:
127
+ del config
128
+ return self.request_policy_value
129
+
130
+ def model_catalog_policy(
131
+ self, config: ProviderConfig
132
+ ) -> ProviderModelCatalogPolicy:
133
+ del config
134
+ return self.model_catalog_policy_value
135
+
136
+ def configuration_policy(
137
+ self, config: ProviderConfig
138
+ ) -> ProviderConfigurationPolicy:
139
+ del config
140
+ return configuration_policy()
141
+
142
+ def api_key_display_name(self) -> str:
143
+ return self.api_key_display_name_value
144
+
145
+ def launch_api_key_error(self, config: ProviderConfig) -> str | None:
146
+ if self.capabilities(config).requires_api_key and not config.api_keys:
147
+ return self.api_key_launch_error_value or super().launch_api_key_error(
148
+ config
149
+ )
150
+ return None
151
+
152
+ def build_model_headers(
153
+ self, config: ProviderConfig, api_key: str | None
154
+ ) -> Mapping[str, str]:
155
+ del config
156
+ key = str(api_key or "").strip()
157
+ if not key:
158
+ return {}
159
+ headers = {self.authorization_header: f"Bearer {key}"}
160
+ if self.include_x_api_key:
161
+ headers["x-api-key"] = key
162
+ return headers
163
+
164
+
165
+ @dataclass(frozen=True)
166
+ class NoAuthProviderAdapter(HttpBearerProviderAdapter):
167
+ def build_headers(
168
+ self, config: ProviderConfig, api_key: str | None
169
+ ) -> Mapping[str, str]:
170
+ del config, api_key
171
+ return {}
172
+
173
+
174
+ @dataclass(frozen=True)
175
+ class OpenAICompatibleProviderAdapter(HttpBearerProviderAdapter):
176
+ """Base for providers that implement the OpenAI Chat/Models wire surface."""
177
+
178
+ def context_policy(self, config: ProviderConfig) -> ProviderContextPolicy:
179
+ del config
180
+ return ProviderContextPolicy(
181
+ capacity_strategy="hint_configured", settings_strategy="standard"
182
+ )
183
+
184
+ def router_native_anthropic_enabled(
185
+ self, config: ProviderConfig, model: str | None = None
186
+ ) -> bool:
187
+ del model
188
+ return bool(config.options.get("native_compat", True))
189
+
190
+ def option_presentation_policy(
191
+ self, config: ProviderConfig
192
+ ) -> ProviderOptionPresentationPolicy:
193
+ del config
194
+ return ProviderOptionPresentationPolicy(
195
+ show_native=True,
196
+ show_tool_choice=True,
197
+ show_sampling=True,
198
+ show_stream=True,
199
+ show_rate_limit_controls=True,
200
+ show_sampling_controls=True,
201
+ show_ip_family_control=True,
202
+ )
203
+
204
+ def supported_protocols(
205
+ self, config: ProviderConfig, model: str | None = None
206
+ ) -> frozenset[MessageProtocol]:
207
+ del model
208
+ protocols: set[MessageProtocol] = {"openai_chat"}
209
+ native = config.options.get("native_compat")
210
+ if native is True or str(native).strip().lower() in {"1", "true", "yes", "on"}:
211
+ protocols.add("anthropic_messages")
212
+ return frozenset(protocols)
213
+
214
+ def select_protocol(
215
+ self,
216
+ operation: MessageProtocol,
217
+ config: ProviderConfig,
218
+ model: str | None = None,
219
+ ) -> MessageProtocol:
220
+ supported = self.supported_protocols(config, model)
221
+ if operation == "anthropic_messages" and "anthropic_messages" in supported:
222
+ return "anthropic_messages"
223
+ return "openai_chat"
224
+
225
+
226
+ __all__ = [
227
+ "HttpBearerProviderAdapter",
228
+ "NoAuthProviderAdapter",
229
+ "OpenAICompatibleProviderAdapter",
230
+ "ROUTER_STATUS_FIELDS",
231
+ "configuration_policy",
232
+ ]