@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,76 @@
1
+ """LM Studio provider adapter."""
2
+
3
+ from dataclasses import dataclass, field, replace
4
+
5
+ from ..architecture import (
6
+ ProviderCapabilities,
7
+ ProviderConfig,
8
+ ProviderContextPolicy,
9
+ ProviderModelCatalogPolicy,
10
+ ProviderOptionPresentationPolicy,
11
+ ProviderStatusPolicy,
12
+ )
13
+ from .base import OpenAICompatibleProviderAdapter, provider_configuration
14
+ from .constants import DEFAULT_REQUEST_TIMEOUT_MS, PROVIDER_DEFAULT_BASE_URLS
15
+
16
+
17
+ @dataclass(frozen=True)
18
+ class LMStudioProviderAdapter(OpenAICompatibleProviderAdapter):
19
+ name: str = "lm-studio"
20
+ base_url: str = PROVIDER_DEFAULT_BASE_URLS["lm-studio"]
21
+ configuration_defaults_value: dict = field(
22
+ default_factory=lambda: provider_configuration(
23
+ "local-model",
24
+ custom_models=("local-model",),
25
+ native_compat=True,
26
+ rate_limit_rpm=0,
27
+ rate_limit_status=False,
28
+ context_window=32768,
29
+ max_output_tokens=4096,
30
+ temperature=0.7,
31
+ top_p=0.8,
32
+ context_reserve_tokens=1024,
33
+ request_timeout_ms=DEFAULT_REQUEST_TIMEOUT_MS,
34
+ stream_enabled=True,
35
+ stream_word_chunking=False,
36
+ )
37
+ )
38
+ capabilities_value: ProviderCapabilities = field(
39
+ default_factory=lambda: ProviderCapabilities(
40
+ upstream_protocol="openai_chat", local=True
41
+ )
42
+ )
43
+ model_catalog_policy_value: ProviderModelCatalogPolicy = field(
44
+ default_factory=lambda: ProviderModelCatalogPolicy(kind="lm_studio")
45
+ )
46
+
47
+ def requires_catalog_model_selection(self, config: ProviderConfig) -> bool:
48
+ del config
49
+ return True
50
+
51
+ def placeholder_model_ids(self) -> frozenset[str]:
52
+ return super().placeholder_model_ids() | {"local-model"}
53
+
54
+ def context_policy(self, config: ProviderConfig) -> ProviderContextPolicy:
55
+ return replace(
56
+ super().context_policy(config), status_capacity_strategy="openai_budget"
57
+ )
58
+
59
+ def option_presentation_policy(
60
+ self, config: ProviderConfig
61
+ ) -> ProviderOptionPresentationPolicy:
62
+ return replace(super().option_presentation_policy(config), show_rate_limit=True)
63
+
64
+ def model_paths(self, config: ProviderConfig) -> tuple[str, ...]:
65
+ del config
66
+ return ("/api/v0/models", "/api/v1/models", "/v1/models", "/models")
67
+
68
+ def status_policy(self, config: ProviderConfig) -> ProviderStatusPolicy:
69
+ return replace(
70
+ super().status_policy(config),
71
+ unreachable_hint="Start LM Studio's Local Server or set a reachable Anthropic-compatible Base URL before launching Claude Code.",
72
+ readiness_validation="lm_studio",
73
+ )
74
+
75
+
76
+ __all__ = ["LMStudioProviderAdapter"]
@@ -0,0 +1,257 @@
1
+ """Meta Model API / Muse Spark 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
+ MessageProtocol,
10
+ ProviderCapabilities,
11
+ ProviderConfig,
12
+ ProviderContextPolicy,
13
+ ProviderModelCatalogPolicy,
14
+ ProviderOptionPresentationPolicy,
15
+ ProviderRequestPolicy,
16
+ ProviderStatusPolicy,
17
+ )
18
+ from .base import HttpBearerProviderAdapter, provider_configuration
19
+ from .constants import DEFAULT_REQUEST_TIMEOUT_MS, PROVIDER_DEFAULT_BASE_URLS
20
+
21
+
22
+ MUSE_SPARK_MODEL = "muse-spark-1.1"
23
+ MUSE_SPARK_CONTEXT_WINDOW = 1_048_576
24
+ MUSE_SPARK_AUTO_COMPACT_LIMIT = 900_000
25
+
26
+
27
+ @dataclass(frozen=True)
28
+ class MetaModelProviderAdapter(HttpBearerProviderAdapter):
29
+ """Preserve Meta's native Responses and Anthropic Messages contracts."""
30
+
31
+ name: str = "meta"
32
+ base_url: str = PROVIDER_DEFAULT_BASE_URLS["meta"]
33
+ configuration_defaults_value: dict = field(
34
+ default_factory=lambda: provider_configuration(
35
+ MUSE_SPARK_MODEL,
36
+ custom_models=(MUSE_SPARK_MODEL,),
37
+ native_compat=True,
38
+ preserve_anthropic_thinking=True,
39
+ normalize_anthropic_tool_use=True,
40
+ supports_tool_choice=True,
41
+ claude_code_supported_capabilities=["effort", "thinking"],
42
+ context_window=MUSE_SPARK_CONTEXT_WINDOW,
43
+ max_model_len=MUSE_SPARK_CONTEXT_WINDOW,
44
+ auto_compact_window=MUSE_SPARK_AUTO_COMPACT_LIMIT,
45
+ codex_auto_compact_window=MUSE_SPARK_AUTO_COMPACT_LIMIT,
46
+ request_timeout_ms=DEFAULT_REQUEST_TIMEOUT_MS,
47
+ stream_enabled=True,
48
+ stream_word_chunking=False,
49
+ effort_level="high",
50
+ enable_tool_search=True,
51
+ haiku_model=MUSE_SPARK_MODEL,
52
+ opus_model=MUSE_SPARK_MODEL,
53
+ sonnet_model=MUSE_SPARK_MODEL,
54
+ subagent_model=MUSE_SPARK_MODEL,
55
+ )
56
+ )
57
+ authorization_header: str = "authorization"
58
+ include_x_api_key: bool = False
59
+ require_api_key: bool = True
60
+ api_key_display_name_value: str = "Meta Model API"
61
+ api_key_launch_error_value: str = (
62
+ "Launch blocked: Meta Model API requires a MODEL_API_KEY."
63
+ )
64
+ capabilities_value: ProviderCapabilities = field(
65
+ default_factory=lambda: ProviderCapabilities(
66
+ upstream_protocol="anthropic_messages",
67
+ supports_thinking=True,
68
+ preserves_anthropic_thinking=True,
69
+ requires_api_key=True,
70
+ )
71
+ )
72
+ request_policy_value: ProviderRequestPolicy = field(
73
+ default_factory=lambda: ProviderRequestPolicy(
74
+ chat_path="/v1/messages",
75
+ models_path="/v1/models",
76
+ )
77
+ )
78
+ model_catalog_policy_value: ProviderModelCatalogPolicy = field(
79
+ default_factory=lambda: ProviderModelCatalogPolicy(
80
+ kind="openai",
81
+ fallback_models=(MUSE_SPARK_MODEL,),
82
+ allow_configured_fallback=True,
83
+ )
84
+ )
85
+
86
+ def context_policy(self, config: ProviderConfig) -> ProviderContextPolicy:
87
+ del config
88
+ return ProviderContextPolicy(
89
+ capacity_strategy="configured_first",
90
+ settings_strategy="standard",
91
+ hosted_timeout=True,
92
+ )
93
+
94
+ def router_native_anthropic_enabled(
95
+ self, config: ProviderConfig, model: str | None = None
96
+ ) -> bool:
97
+ del model
98
+ return bool(config.options.get("native_compat", True))
99
+
100
+ def supported_protocols(
101
+ self, config: ProviderConfig, model: str | None = None
102
+ ) -> frozenset[MessageProtocol]:
103
+ del config, model
104
+ return frozenset({"anthropic_messages", "openai_responses"})
105
+
106
+ def select_protocol(
107
+ self,
108
+ operation: MessageProtocol,
109
+ config: ProviderConfig,
110
+ model: str | None = None,
111
+ ) -> MessageProtocol:
112
+ del config, model
113
+ return (
114
+ "openai_responses"
115
+ if operation == "openai_responses"
116
+ else "anthropic_messages"
117
+ )
118
+
119
+ def model_configuration_profile(
120
+ self, config: ProviderConfig
121
+ ) -> tuple[Mapping[str, Any], str | None]:
122
+ if self.normalize_model_id(config.model) != MUSE_SPARK_MODEL:
123
+ return {}, None
124
+ return (
125
+ {
126
+ "context_window": MUSE_SPARK_CONTEXT_WINDOW,
127
+ "max_model_len": MUSE_SPARK_CONTEXT_WINDOW,
128
+ "auto_compact_window": MUSE_SPARK_AUTO_COMPACT_LIMIT,
129
+ "effort_level": "high",
130
+ "model_profile": "muse-spark-1.1-1m",
131
+ },
132
+ "Muse Spark 1.1 profile applied: 1M context, high reasoning effort, "
133
+ "and 900K automatic compaction. Start a new session after changing "
134
+ "model, context, or reasoning effort.",
135
+ )
136
+
137
+ def model_selection_config_updates(
138
+ self, config: ProviderConfig, model_id: str
139
+ ) -> dict[str, str]:
140
+ del config
141
+ return {
142
+ "haiku_model": model_id,
143
+ "opus_model": model_id,
144
+ "sonnet_model": model_id,
145
+ "subagent_model": model_id,
146
+ }
147
+
148
+ def option_presentation_policy(
149
+ self, config: ProviderConfig
150
+ ) -> ProviderOptionPresentationPolicy:
151
+ del config
152
+ return ProviderOptionPresentationPolicy(
153
+ show_native=True,
154
+ show_tool_choice=True,
155
+ show_stream=True,
156
+ show_rate_limit_controls=True,
157
+ show_sampling_controls=False,
158
+ show_ip_family_control=True,
159
+ )
160
+
161
+ def status_policy(self, config: ProviderConfig) -> ProviderStatusPolicy:
162
+ del config
163
+ return ProviderStatusPolicy(
164
+ kind="catalog",
165
+ label="Meta Model API",
166
+ catalog_path="/v1/models",
167
+ )
168
+
169
+ def normalize_request_options(
170
+ self, config: ProviderConfig, request: Mapping[str, Any]
171
+ ) -> Mapping[str, Any]:
172
+ del config
173
+ normalized = dict(request)
174
+ if "input" in normalized and "messages" not in normalized:
175
+ self._normalize_responses_request(normalized)
176
+ else:
177
+ self._normalize_messages_request(normalized)
178
+ return normalized
179
+
180
+ def normalize_tool_choice(
181
+ self, config: ProviderConfig, model: str, tool_choice: Any
182
+ ) -> Any:
183
+ del config, model
184
+ if not isinstance(tool_choice, Mapping):
185
+ return tool_choice
186
+ if str(tool_choice.get("type") or "").strip().lower() == "tool":
187
+ return {"type": "auto"}
188
+ return tool_choice
189
+
190
+ def allows_sampling_overrides(self, config: ProviderConfig) -> bool:
191
+ del config
192
+ return False
193
+
194
+ @classmethod
195
+ def _normalize_responses_request(cls, request: dict[str, Any]) -> None:
196
+ include = request.get("include")
197
+ if request.get("previous_response_id"):
198
+ if isinstance(include, list):
199
+ values = [
200
+ value
201
+ for value in include
202
+ if value != "reasoning.encrypted_content"
203
+ ]
204
+ if values:
205
+ request["include"] = values
206
+ else:
207
+ request.pop("include", None)
208
+ else:
209
+ values = list(include) if isinstance(include, list) else []
210
+ if "reasoning.encrypted_content" not in values:
211
+ values.append("reasoning.encrypted_content")
212
+ request["include"] = values
213
+ truncation = str(request.get("truncation") or "").strip().lower()
214
+ if truncation == "auto":
215
+ request["truncation"] = "disabled"
216
+ reasoning = request.get("reasoning")
217
+ if isinstance(reasoning, Mapping):
218
+ projected = dict(reasoning)
219
+ projected["effort"] = cls._effort(projected.get("effort"))
220
+ request["reasoning"] = projected
221
+
222
+ @classmethod
223
+ def _normalize_messages_request(cls, request: dict[str, Any]) -> None:
224
+ for key in ("stop_sequences", "top_k", "container", "inference_geo"):
225
+ request.pop(key, None)
226
+ if "temperature" in request and "top_p" in request:
227
+ request.pop("top_p", None)
228
+ thinking = request.get("thinking")
229
+ if isinstance(thinking, Mapping):
230
+ projected = dict(thinking)
231
+ if str(projected.get("type") or "").strip().lower() == "disabled":
232
+ projected = {"type": "adaptive"}
233
+ request["thinking"] = projected
234
+ output_config = request.get("output_config")
235
+ if isinstance(output_config, Mapping) and output_config.get("effort") is not None:
236
+ projected_output = dict(output_config)
237
+ projected_output["effort"] = cls._effort(projected_output.get("effort"))
238
+ request["output_config"] = projected_output
239
+
240
+ @staticmethod
241
+ def _effort(value: Any) -> str:
242
+ effort = str(value or "high").strip().lower()
243
+ if effort in {"none", "minimal"}:
244
+ return "minimal"
245
+ if effort in {"low", "medium", "high", "xhigh"}:
246
+ return effort
247
+ if effort in {"max", "ultra"}:
248
+ return "xhigh"
249
+ return "high"
250
+
251
+
252
+ __all__ = [
253
+ "MUSE_SPARK_AUTO_COMPACT_LIMIT",
254
+ "MUSE_SPARK_CONTEXT_WINDOW",
255
+ "MUSE_SPARK_MODEL",
256
+ "MetaModelProviderAdapter",
257
+ ]
@@ -0,0 +1,194 @@
1
+ """Native Codex and AGY provider-selection adapters."""
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
+ ProviderModelCatalogPolicy,
13
+ ProviderOptionPresentationPolicy,
14
+ ProviderRequestPolicy,
15
+ ProviderStatusPolicy,
16
+ ProviderUiPolicy,
17
+ )
18
+ from .base import NoAuthProviderAdapter, provider_configuration
19
+ from .constants import DEFAULT_REQUEST_TIMEOUT_MS, PROVIDER_DEFAULT_BASE_URLS
20
+
21
+
22
+ @dataclass(frozen=True)
23
+ class CodexProviderAdapter(NoAuthProviderAdapter):
24
+ name: str = "codex"
25
+ base_url: str = PROVIDER_DEFAULT_BASE_URLS["codex"]
26
+ configuration_defaults_value: dict = field(
27
+ default_factory=lambda: provider_configuration(
28
+ route_through_router=False,
29
+ request_timeout_ms=DEFAULT_REQUEST_TIMEOUT_MS,
30
+ )
31
+ )
32
+ capabilities_value: ProviderCapabilities = field(
33
+ default_factory=lambda: ProviderCapabilities(
34
+ upstream_protocol="openai_responses"
35
+ )
36
+ )
37
+ request_policy_value: ProviderRequestPolicy = field(
38
+ default_factory=lambda: ProviderRequestPolicy(
39
+ chat_path="/v1/responses", models_path="/v1/models"
40
+ )
41
+ )
42
+ model_catalog_policy_value: ProviderModelCatalogPolicy = field(
43
+ default_factory=lambda: ProviderModelCatalogPolicy(kind="configured")
44
+ )
45
+
46
+ def routing_mode_update(self, enabled: bool) -> tuple[str, ...]:
47
+ return (
48
+ "Codex routing mode updated.",
49
+ f"mode: {'codex-routed' if enabled else 'codex-native'}",
50
+ )
51
+
52
+ def selection_config_updates(self, config: ProviderConfig) -> Mapping[str, Any]:
53
+ del config
54
+ return {"route_through_router": False}
55
+
56
+ def selection_status_lines(self, config: ProviderConfig) -> tuple[str, ...]:
57
+ del config
58
+ return ("mode: codex-native",)
59
+
60
+ def option_presentation_policy(
61
+ self, config: ProviderConfig
62
+ ) -> ProviderOptionPresentationPolicy:
63
+ del config
64
+ return ProviderOptionPresentationPolicy(show_route=True)
65
+
66
+ def ui_policy(self, config: ProviderConfig) -> ProviderUiPolicy:
67
+ del config
68
+ return ProviderUiPolicy(
69
+ menu_label="Codex Native",
70
+ routed_menu_label="Codex routed",
71
+ native_choice="codex:native",
72
+ routed_choice="codex:routed",
73
+ model_placeholder="Codex default",
74
+ advisor_placeholder="Codex native",
75
+ )
76
+
77
+ def shows_claude_workflow_options(self, config: ProviderConfig) -> bool:
78
+ del config
79
+ return False
80
+
81
+ def option_timeout_default(self) -> str:
82
+ return "Codex default"
83
+
84
+ def api_key_status(
85
+ self, config: ProviderConfig, *, key_count: int, primary_detail: str
86
+ ) -> str:
87
+ routed = bool(config.options.get("route_through_router"))
88
+ if routed:
89
+ if key_count > 1:
90
+ return (
91
+ f"API keys: {key_count} keys, round-robin "
92
+ f"(stored; Codex routed uses native login/auth headers{primary_detail})"
93
+ )
94
+ return (
95
+ f"API key: set (stored; Codex routed uses native login/auth headers{primary_detail})"
96
+ if key_count
97
+ else "API key: not set (uses native Codex login/auth headers)"
98
+ )
99
+ if key_count > 1:
100
+ return f"API keys: {key_count} keys, round-robin (Codex fallback{primary_detail})"
101
+ return (
102
+ f"API key: set (Codex fallback{primary_detail})"
103
+ if key_count
104
+ else "API key: not set (uses native Codex login/config)"
105
+ )
106
+
107
+ def status_policy(self, config: ProviderConfig) -> ProviderStatusPolicy:
108
+ del config
109
+ return ProviderStatusPolicy(kind="native_codex")
110
+
111
+ def configuration_policy(
112
+ self, config: ProviderConfig
113
+ ) -> ProviderConfigurationPolicy:
114
+ del config
115
+ return ProviderConfigurationPolicy(
116
+ runtime_owns_model=True, restricts_runtime_options=True
117
+ )
118
+
119
+
120
+ @dataclass(frozen=True)
121
+ class AgyProviderAdapter(NoAuthProviderAdapter):
122
+ name: str = "agy"
123
+ base_url: str = PROVIDER_DEFAULT_BASE_URLS["agy"]
124
+ configuration_defaults_value: dict = field(
125
+ default_factory=lambda: provider_configuration(
126
+ route_through_router=False,
127
+ request_timeout_ms=DEFAULT_REQUEST_TIMEOUT_MS,
128
+ )
129
+ )
130
+ capabilities_value: ProviderCapabilities = field(
131
+ default_factory=lambda: ProviderCapabilities(
132
+ upstream_protocol="openai_responses"
133
+ )
134
+ )
135
+ model_catalog_policy_value: ProviderModelCatalogPolicy = field(
136
+ default_factory=lambda: ProviderModelCatalogPolicy(kind="configured")
137
+ )
138
+
139
+ def routing_mode_update(self, enabled: bool) -> tuple[str, ...]:
140
+ return (
141
+ "AGY routing mode updated.",
142
+ f"mode: {'agy-routed' if enabled else 'agy-native'}",
143
+ )
144
+
145
+ def selection_config_updates(self, config: ProviderConfig) -> Mapping[str, Any]:
146
+ del config
147
+ return {"route_through_router": False}
148
+
149
+ def selection_status_lines(self, config: ProviderConfig) -> tuple[str, ...]:
150
+ del config
151
+ return ("mode: agy-native",)
152
+
153
+ def option_presentation_policy(
154
+ self, config: ProviderConfig
155
+ ) -> ProviderOptionPresentationPolicy:
156
+ del config
157
+ return ProviderOptionPresentationPolicy(show_route=True)
158
+
159
+ def ui_policy(self, config: ProviderConfig) -> ProviderUiPolicy:
160
+ del config
161
+ return ProviderUiPolicy(
162
+ menu_label="AGY",
163
+ routed_menu_label="AGY Routed",
164
+ native_choice="agy:native",
165
+ routed_choice="agy:routed",
166
+ model_placeholder="AGY default",
167
+ advisor_placeholder="AGY native",
168
+ )
169
+
170
+ def option_timeout_default(self) -> str:
171
+ return "AGY default"
172
+
173
+ def api_key_status(
174
+ self, config: ProviderConfig, *, key_count: int, primary_detail: str
175
+ ) -> str:
176
+ del key_count, primary_detail
177
+ return (
178
+ "API key: not set (uses native AGY Google sign-in/keyring)"
179
+ if config.options.get("route_through_router")
180
+ else "API key: not set (uses native AGY Google sign-in/config)"
181
+ )
182
+
183
+ def status_policy(self, config: ProviderConfig) -> ProviderStatusPolicy:
184
+ del config
185
+ return ProviderStatusPolicy(kind="native_agy")
186
+
187
+ def configuration_policy(
188
+ self, config: ProviderConfig
189
+ ) -> ProviderConfigurationPolicy:
190
+ del config
191
+ return ProviderConfigurationPolicy(runtime_owns_model=True)
192
+
193
+
194
+ __all__ = ["AgyProviderAdapter", "CodexProviderAdapter"]
@@ -0,0 +1,69 @@
1
+ """Self-hosted NVIDIA NIM provider adapter."""
2
+
3
+ from dataclasses import dataclass, field, replace
4
+
5
+ from ..architecture import (
6
+ ProviderCapabilities,
7
+ ProviderConfig,
8
+ ProviderContextPolicy,
9
+ ProviderOptionPresentationPolicy,
10
+ ProviderStatusPolicy,
11
+ )
12
+ from .base import OpenAICompatibleProviderAdapter, provider_configuration
13
+ from .constants import DEFAULT_REQUEST_TIMEOUT_MS, PROVIDER_DEFAULT_BASE_URLS
14
+
15
+
16
+ @dataclass(frozen=True)
17
+ class SelfHostedNimProviderAdapter(OpenAICompatibleProviderAdapter):
18
+ name: str = "self-hosted-nim"
19
+ base_url: str = PROVIDER_DEFAULT_BASE_URLS["self-hosted-nim"]
20
+ configuration_defaults_value: dict = field(
21
+ default_factory=lambda: provider_configuration(
22
+ "model",
23
+ api_key="not-used",
24
+ custom_models=("model",),
25
+ native_compat=True,
26
+ rate_limit_rpm=0,
27
+ rate_limit_status=False,
28
+ context_window=32768,
29
+ max_output_tokens=4096,
30
+ temperature=0.7,
31
+ top_p=0.8,
32
+ context_reserve_tokens=1024,
33
+ request_timeout_ms=DEFAULT_REQUEST_TIMEOUT_MS,
34
+ stream_enabled=True,
35
+ stream_word_chunking=False,
36
+ )
37
+ )
38
+ send_placeholder_key: bool = True
39
+ capabilities_value: ProviderCapabilities = field(
40
+ default_factory=lambda: ProviderCapabilities(
41
+ upstream_protocol="openai_chat", local=True
42
+ )
43
+ )
44
+
45
+ def requires_catalog_model_selection(self, config: ProviderConfig) -> bool:
46
+ del config
47
+ return True
48
+
49
+ def option_presentation_policy(
50
+ self, config: ProviderConfig
51
+ ) -> ProviderOptionPresentationPolicy:
52
+ return replace(super().option_presentation_policy(config), show_rate_limit=True)
53
+
54
+ def context_policy(self, config: ProviderConfig) -> ProviderContextPolicy:
55
+ del config
56
+ return ProviderContextPolicy(
57
+ capacity_strategy="remote_first",
58
+ settings_strategy="standard",
59
+ status_capacity_strategy="openai_budget",
60
+ )
61
+
62
+ def status_policy(self, config: ProviderConfig) -> ProviderStatusPolicy:
63
+ return replace(
64
+ super().status_policy(config),
65
+ unreachable_hint="Start NIM or set a reachable Anthropic-compatible Base URL before launching Claude Code.",
66
+ )
67
+
68
+
69
+ __all__ = ["SelfHostedNimProviderAdapter"]