@oneciel-ai/ciel-runtime 0.2.2 → 0.2.3
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.
- package/ciel_runtime.py +2553 -9635
- package/ciel_runtime_support/advisor_request_builder.py +8 -21
- package/ciel_runtime_support/anthropic_tool_turns.py +13 -8
- package/ciel_runtime_support/architecture.py +68 -0
- package/ciel_runtime_support/architecture_budget.py +1 -1
- package/ciel_runtime_support/channel_connection_context.py +233 -0
- package/ciel_runtime_support/channel_delivery_context.py +332 -0
- package/ciel_runtime_support/channel_mcp_context.py +313 -0
- package/ciel_runtime_support/channel_mcp_discovery.py +47 -0
- package/ciel_runtime_support/channel_mcp_transport.py +5 -1
- package/ciel_runtime_support/channel_message_context.py +212 -0
- package/ciel_runtime_support/channel_message_repository.py +14 -3
- package/ciel_runtime_support/channel_pending_injection.py +9 -0
- package/ciel_runtime_support/channel_probe_launch_context.py +213 -0
- package/ciel_runtime_support/channel_replay_policy.py +38 -0
- package/ciel_runtime_support/channel_runtime_environment.py +8 -0
- package/ciel_runtime_support/channel_session_context.py +236 -0
- package/ciel_runtime_support/channel_terminal_context.py +350 -0
- package/ciel_runtime_support/channel_wake_context.py +532 -0
- package/ciel_runtime_support/claude_environment.py +60 -0
- package/ciel_runtime_support/claude_launch_assembly.py +249 -0
- package/ciel_runtime_support/claude_router.py +62 -12
- package/ciel_runtime_support/cli_application_context.py +132 -0
- package/ciel_runtime_support/cli_assembly.py +50 -0
- package/ciel_runtime_support/codex_backend_context.py +363 -0
- package/ciel_runtime_support/codex_config.py +13 -1
- package/ciel_runtime_support/codex_launch_assembly.py +213 -0
- package/ciel_runtime_support/codex_launch_configuration.py +30 -1
- package/ciel_runtime_support/codex_mcp_integration.py +90 -8
- package/ciel_runtime_support/codex_model_catalog.py +4 -1
- package/ciel_runtime_support/codex_reasoning_rejects.py +225 -0
- package/ciel_runtime_support/codex_router.py +38 -8
- package/ciel_runtime_support/codex_turn_recovery.py +154 -0
- package/ciel_runtime_support/config_migrations.py +103 -0
- package/ciel_runtime_support/configuration_cli.py +38 -0
- package/ciel_runtime_support/context_compaction.py +9 -4
- package/ciel_runtime_support/credential_management.py +12 -0
- package/ciel_runtime_support/credentials.py +12 -0
- package/ciel_runtime_support/github_copilot_oauth.py +2 -2
- package/ciel_runtime_support/hosted_formula_tools.py +216 -0
- package/ciel_runtime_support/kimi_runtime_context.py +208 -0
- package/ciel_runtime_support/llm_preset_context.py +338 -0
- package/ciel_runtime_support/managed_mcp_config.py +8 -4
- package/ciel_runtime_support/mcp_configuration_context.py +291 -0
- package/ciel_runtime_support/mcp_http_proxy.py +14 -8
- package/ciel_runtime_support/mcp_probe_transport.py +47 -15
- package/ciel_runtime_support/mcp_transport.py +14 -1
- package/ciel_runtime_support/native_context_recovery.py +72 -0
- package/ciel_runtime_support/ollama_catalog_context.py +213 -0
- package/ciel_runtime_support/ollama_stream_collection.py +103 -0
- package/ciel_runtime_support/ollama_thinking.py +6 -1
- package/ciel_runtime_support/ollama_wire_projection.py +157 -0
- package/ciel_runtime_support/openai_forwarding.py +32 -10
- package/ciel_runtime_support/openai_responses_router.py +12 -0
- package/ciel_runtime_support/package_lifecycle.py +39 -0
- package/ciel_runtime_support/prelaunch_assembly.py +37 -0
- package/ciel_runtime_support/prelaunch_panel_context.py +418 -0
- package/ciel_runtime_support/prelaunch_shell_context.py +394 -0
- package/ciel_runtime_support/prompt_compaction.py +144 -0
- package/ciel_runtime_support/prompt_injection.py +45 -0
- package/ciel_runtime_support/protocols/anthropic_thinking_policy.py +1 -1
- package/ciel_runtime_support/protocols/chat_projection.py +85 -5
- package/ciel_runtime_support/protocols/conversation_turn_policy.py +43 -0
- package/ciel_runtime_support/protocols/ollama_chat.py +31 -0
- package/ciel_runtime_support/protocols/ollama_response.py +57 -5
- package/ciel_runtime_support/protocols/openai_reasoning.py +5 -2
- package/ciel_runtime_support/protocols/openai_responses.py +61 -15
- package/ciel_runtime_support/provider_adapters.py +26 -0
- package/ciel_runtime_support/provider_administration_context.py +207 -0
- package/ciel_runtime_support/provider_config_mutations.py +3 -0
- package/ciel_runtime_support/provider_model_catalog_context.py +137 -0
- package/ciel_runtime_support/provider_model_context.py +107 -0
- package/ciel_runtime_support/provider_model_metadata_context.py +197 -0
- package/ciel_runtime_support/provider_model_selection.py +10 -3
- package/ciel_runtime_support/provider_models.py +45 -2
- package/ciel_runtime_support/provider_option_cli.py +19 -0
- package/ciel_runtime_support/provider_policy.py +1 -1
- package/ciel_runtime_support/provider_readiness_context.py +189 -0
- package/ciel_runtime_support/provider_request_builder.py +64 -28
- package/ciel_runtime_support/provider_responses_passthrough.py +21 -2
- package/ciel_runtime_support/provider_timeout_policy.py +54 -0
- package/ciel_runtime_support/provider_tool_policy.py +9 -1
- package/ciel_runtime_support/providers/__init__.py +6 -0
- package/ciel_runtime_support/providers/alibaba.py +634 -0
- package/ciel_runtime_support/providers/catalog.py +24 -16
- package/ciel_runtime_support/providers/deepseek.py +73 -0
- package/ciel_runtime_support/providers/github_copilot_oauth.py +22 -1
- package/ciel_runtime_support/providers/kimi.py +69 -9
- package/ciel_runtime_support/providers/ollama.py +8 -0
- package/ciel_runtime_support/providers/ollama_context.py +21 -2
- package/ciel_runtime_support/providers/vllm.py +7 -1
- package/ciel_runtime_support/response_collection.py +68 -18
- package/ciel_runtime_support/response_collection_context.py +391 -0
- package/ciel_runtime_support/response_stream_context.py +555 -0
- package/ciel_runtime_support/responses_input_compatibility.py +121 -0
- package/ciel_runtime_support/responses_usage_observer.py +83 -0
- package/ciel_runtime_support/router_client_lifecycle.py +1 -0
- package/ciel_runtime_support/router_http.py +239 -3
- package/ciel_runtime_support/router_observability_context.py +251 -0
- package/ciel_runtime_support/router_process_context.py +200 -0
- package/ciel_runtime_support/router_process_lifecycle.py +2 -0
- package/ciel_runtime_support/router_request_assembly.py +399 -0
- package/ciel_runtime_support/router_request_context.py +215 -0
- package/ciel_runtime_support/router_server_context.py +82 -0
- package/ciel_runtime_support/runaway_output_guard.py +488 -0
- package/ciel_runtime_support/runtime_asset_assembly.py +147 -0
- package/ciel_runtime_support/runtime_asset_context.py +297 -0
- package/ciel_runtime_support/runtime_constants.py +16 -1
- package/ciel_runtime_support/runtime_launch.py +9 -5
- package/ciel_runtime_support/runtime_launch_context.py +130 -0
- package/ciel_runtime_support/runtime_maintenance_assembly.py +60 -0
- package/ciel_runtime_support/runtime_maintenance_context.py +309 -0
- package/ciel_runtime_support/runtime_maintenance_services.py +265 -0
- package/ciel_runtime_support/runtime_paths.py +60 -40
- package/ciel_runtime_support/runtime_primitives.py +78 -0
- package/ciel_runtime_support/sse_stream_collection.py +236 -0
- package/ciel_runtime_support/statusline_script.py +57 -8
- package/ciel_runtime_support/streaming_anthropic.py +361 -24
- package/ciel_runtime_support/tool_schema.py +40 -2
- package/ciel_runtime_support/tool_side_effect_dedupe.py +117 -12
- package/ciel_runtime_support/upstream_dump.py +68 -0
- package/ciel_runtime_support/upstream_retry_context.py +259 -0
- package/ciel_runtime_support/workspace_router_selection.py +86 -0
- package/docs/Configuration.md +50 -0
- package/docs/Test-Suite.md +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
"""Router shutdown and listener-replacement bounded context."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Any, Callable
|
|
8
|
+
|
|
9
|
+
from .router_process_lifecycle import (
|
|
10
|
+
ClockPorts,
|
|
11
|
+
RouterProcessConfig,
|
|
12
|
+
RouterStatePorts,
|
|
13
|
+
RouterTerminationPorts,
|
|
14
|
+
ensure_port_available,
|
|
15
|
+
stop_router_processes,
|
|
16
|
+
stop_with_guarantee,
|
|
17
|
+
terminate_health_pid,
|
|
18
|
+
terminate_pid_file,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@dataclass(frozen=True, slots=True)
|
|
23
|
+
class RouterListenerPorts:
|
|
24
|
+
platform_name: str
|
|
25
|
+
bind_host: Callable[[], str]
|
|
26
|
+
windows_pids: Callable[[int, str], list[int]]
|
|
27
|
+
posix_pids: Callable[[int, str], list[int]]
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@dataclass(frozen=True, slots=True)
|
|
31
|
+
class RouterProcessEffects:
|
|
32
|
+
terminate_pid: Callable[[int, str, bool], bool]
|
|
33
|
+
pid_is_running: Callable[[int], bool]
|
|
34
|
+
protected_pids: Callable[[], tuple[int, int]]
|
|
35
|
+
now: Callable[[], float]
|
|
36
|
+
sleep: Callable[[float], None]
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@dataclass(frozen=True, slots=True)
|
|
40
|
+
class RouterProcessCompatibilityPorts:
|
|
41
|
+
terminate_pid_file: Callable[[Path, str, bool], bool]
|
|
42
|
+
terminate_health: Callable[[dict[str, Any] | None, bool], bool]
|
|
43
|
+
stop_processes: Callable[[bool], bool]
|
|
44
|
+
listener_pids: Callable[[], list[int]]
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@dataclass(frozen=True, slots=True)
|
|
48
|
+
class RouterProcessContext:
|
|
49
|
+
config: RouterProcessConfig
|
|
50
|
+
state: RouterStatePorts
|
|
51
|
+
listener: RouterListenerPorts
|
|
52
|
+
effects: RouterProcessEffects
|
|
53
|
+
compatibility: RouterProcessCompatibilityPorts
|
|
54
|
+
|
|
55
|
+
def listener_pids(self) -> list[int]:
|
|
56
|
+
host = self.listener.bind_host()
|
|
57
|
+
if self.listener.platform_name == "nt":
|
|
58
|
+
return self.listener.windows_pids(self.config.router_port, host)
|
|
59
|
+
return self.listener.posix_pids(self.config.router_port, host)
|
|
60
|
+
|
|
61
|
+
def termination_ports(self) -> RouterTerminationPorts:
|
|
62
|
+
return RouterTerminationPorts(
|
|
63
|
+
terminate_pid=self.effects.terminate_pid,
|
|
64
|
+
terminate_pid_file=self.compatibility.terminate_pid_file,
|
|
65
|
+
terminate_health=self.compatibility.terminate_health,
|
|
66
|
+
stop_processes=self.compatibility.stop_processes,
|
|
67
|
+
listener_pids=self.compatibility.listener_pids,
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
def terminate_pid_file(
|
|
71
|
+
self,
|
|
72
|
+
path: Path,
|
|
73
|
+
label: str,
|
|
74
|
+
quiet: bool = False,
|
|
75
|
+
) -> bool:
|
|
76
|
+
return terminate_pid_file(
|
|
77
|
+
path,
|
|
78
|
+
label,
|
|
79
|
+
quiet,
|
|
80
|
+
terminate_pid=self.effects.terminate_pid,
|
|
81
|
+
pid_is_running=self.effects.pid_is_running,
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
def terminate_health_pid(
|
|
85
|
+
self,
|
|
86
|
+
health: dict[str, Any] | None,
|
|
87
|
+
quiet: bool = True,
|
|
88
|
+
) -> bool:
|
|
89
|
+
return terminate_health_pid(
|
|
90
|
+
health,
|
|
91
|
+
quiet,
|
|
92
|
+
config=self.config,
|
|
93
|
+
state=self.state,
|
|
94
|
+
terminate_pid=self.effects.terminate_pid,
|
|
95
|
+
protected_pids=self.effects.protected_pids(),
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
def stop_processes(self, quiet: bool = False) -> bool:
|
|
99
|
+
return stop_router_processes(
|
|
100
|
+
quiet,
|
|
101
|
+
config=self.config,
|
|
102
|
+
state=self.state,
|
|
103
|
+
termination=self.termination_ports(),
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
def ensure_port_available(
|
|
107
|
+
self,
|
|
108
|
+
reason: str,
|
|
109
|
+
health: dict[str, Any] | None = None,
|
|
110
|
+
max_wait_seconds: float = 5.0,
|
|
111
|
+
) -> None:
|
|
112
|
+
ensure_port_available(
|
|
113
|
+
reason,
|
|
114
|
+
health,
|
|
115
|
+
max_wait_seconds,
|
|
116
|
+
config=self.config,
|
|
117
|
+
state=self.state,
|
|
118
|
+
termination=self.termination_ports(),
|
|
119
|
+
clock=ClockPorts(now=self.effects.now, sleep=self.effects.sleep),
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
def stop_with_guarantee(
|
|
123
|
+
self,
|
|
124
|
+
reason: str,
|
|
125
|
+
max_wait_seconds: float = 5.0,
|
|
126
|
+
quiet: bool = True,
|
|
127
|
+
) -> bool:
|
|
128
|
+
return stop_with_guarantee(
|
|
129
|
+
reason,
|
|
130
|
+
max_wait_seconds,
|
|
131
|
+
quiet,
|
|
132
|
+
config=self.config,
|
|
133
|
+
state=self.state,
|
|
134
|
+
termination=self.termination_ports(),
|
|
135
|
+
clock=ClockPorts(now=self.effects.now, sleep=self.effects.sleep),
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
@dataclass(frozen=True, slots=True)
|
|
140
|
+
class RouterProcessCompatibilityApi:
|
|
141
|
+
context: Callable[[], RouterProcessContext]
|
|
142
|
+
|
|
143
|
+
def config(self) -> RouterProcessConfig:
|
|
144
|
+
return self.context().config
|
|
145
|
+
|
|
146
|
+
def state_ports(self) -> RouterStatePorts:
|
|
147
|
+
return self.context().state
|
|
148
|
+
|
|
149
|
+
def termination_ports(self) -> RouterTerminationPorts:
|
|
150
|
+
return self.context().termination_ports()
|
|
151
|
+
|
|
152
|
+
def listener_pids(self) -> list[int]:
|
|
153
|
+
return self.context().listener_pids()
|
|
154
|
+
|
|
155
|
+
def terminate_pid_file(
|
|
156
|
+
self,
|
|
157
|
+
path: Path,
|
|
158
|
+
label: str,
|
|
159
|
+
quiet: bool = False,
|
|
160
|
+
) -> bool:
|
|
161
|
+
return self.context().terminate_pid_file(path, label, quiet)
|
|
162
|
+
|
|
163
|
+
def terminate_health_pid(
|
|
164
|
+
self,
|
|
165
|
+
health: dict[str, Any] | None,
|
|
166
|
+
quiet: bool = True,
|
|
167
|
+
) -> bool:
|
|
168
|
+
return self.context().terminate_health_pid(health, quiet)
|
|
169
|
+
|
|
170
|
+
def stop_processes(self, quiet: bool = False) -> bool:
|
|
171
|
+
return self.context().stop_processes(quiet)
|
|
172
|
+
|
|
173
|
+
def ensure_port_available(
|
|
174
|
+
self,
|
|
175
|
+
reason: str,
|
|
176
|
+
health: dict[str, Any] | None = None,
|
|
177
|
+
max_wait_seconds: float = 5.0,
|
|
178
|
+
) -> None:
|
|
179
|
+
self.context().ensure_port_available(reason, health, max_wait_seconds)
|
|
180
|
+
|
|
181
|
+
def stop_with_guarantee(
|
|
182
|
+
self,
|
|
183
|
+
reason: str,
|
|
184
|
+
max_wait_seconds: float = 5.0,
|
|
185
|
+
quiet: bool = True,
|
|
186
|
+
) -> bool:
|
|
187
|
+
return self.context().stop_with_guarantee(
|
|
188
|
+
reason,
|
|
189
|
+
max_wait_seconds,
|
|
190
|
+
quiet,
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
__all__ = [
|
|
195
|
+
"RouterListenerPorts",
|
|
196
|
+
"RouterProcessCompatibilityApi",
|
|
197
|
+
"RouterProcessCompatibilityPorts",
|
|
198
|
+
"RouterProcessContext",
|
|
199
|
+
"RouterProcessEffects",
|
|
200
|
+
]
|
|
@@ -194,6 +194,8 @@ def start_router_if_needed(
|
|
|
194
194
|
environment = spawn.environment()
|
|
195
195
|
environment["CIEL_RUNTIME_MANAGED_ROUTER"] = "1"
|
|
196
196
|
environment["CIEL_RUNTIME_ROUTER_OWNER_PID"] = str(spawn.process_id())
|
|
197
|
+
environment["CIEL_RUNTIME_LAUNCH_CWD"] = str(Path.cwd())
|
|
198
|
+
environment["CIEL_RUNTIME_ROUTER_PORT"] = str(config.router_port)
|
|
197
199
|
with log_path.open("ab", buffering=0) as log:
|
|
198
200
|
spawn.popen(
|
|
199
201
|
command,
|
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
"""Compose OpenAI Responses and Claude router request pipelines from typed ports."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import Any, Callable, Mapping
|
|
7
|
+
|
|
8
|
+
from . import claude_router, openai_responses_router
|
|
9
|
+
from .router_request_context import (
|
|
10
|
+
RouterRequestContext,
|
|
11
|
+
RouterRequestPorts,
|
|
12
|
+
RuntimeRouterPorts,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
Callback = Callable[..., Any]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dataclass(frozen=True, slots=True)
|
|
20
|
+
class OpenAIResponseCorePorts:
|
|
21
|
+
event_bus: Any
|
|
22
|
+
request_id: Callback
|
|
23
|
+
input_as_list: Callback
|
|
24
|
+
is_client_disconnect: Callback
|
|
25
|
+
log: Callback
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@dataclass(frozen=True, slots=True)
|
|
29
|
+
class OpenAIResponseConversionPorts:
|
|
30
|
+
to_anthropic: Callback
|
|
31
|
+
current_alias: Callback
|
|
32
|
+
update_tool_schema: Callback
|
|
33
|
+
normalize_thinking: Callback
|
|
34
|
+
filter_blocked_tools: Callback
|
|
35
|
+
normalize_tool_choice: Callback
|
|
36
|
+
write_context_usage: Callback
|
|
37
|
+
strip_advisor_tools: Callback
|
|
38
|
+
inject_channel_context: Callback
|
|
39
|
+
inject_tool_result_context: Callback
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@dataclass(frozen=True, slots=True)
|
|
43
|
+
class OpenAIResponseRoutingPorts:
|
|
44
|
+
maybe_import_session: Callback
|
|
45
|
+
codex_routed_enabled: Callback
|
|
46
|
+
forward_codex: Callback
|
|
47
|
+
select_protocol: Callback
|
|
48
|
+
forward_provider_responses: Callback
|
|
49
|
+
dump_request: Callback
|
|
50
|
+
normalize_provider_wire: Callback
|
|
51
|
+
collect_message: Callback
|
|
52
|
+
apply_codex_compat_instructions: Callback
|
|
53
|
+
recover_preamble_only_turn: Callback
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@dataclass(frozen=True, slots=True)
|
|
57
|
+
class OpenAIResponseDeliveryPorts:
|
|
58
|
+
begin: Callback
|
|
59
|
+
mark_success: Callback
|
|
60
|
+
mark_failed: Callback
|
|
61
|
+
commit: Callback
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@dataclass(frozen=True, slots=True)
|
|
65
|
+
class OpenAIResponseOutputPorts:
|
|
66
|
+
write_response: Callback
|
|
67
|
+
write_error: Callback
|
|
68
|
+
upstream_error_message: Callback
|
|
69
|
+
codex_auth_error_message: Callback
|
|
70
|
+
event_preview: Callback
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@dataclass(frozen=True, slots=True)
|
|
74
|
+
class OpenAIResponseAssembly:
|
|
75
|
+
core: OpenAIResponseCorePorts
|
|
76
|
+
conversion: OpenAIResponseConversionPorts
|
|
77
|
+
routing: OpenAIResponseRoutingPorts
|
|
78
|
+
delivery: OpenAIResponseDeliveryPorts
|
|
79
|
+
output: OpenAIResponseOutputPorts
|
|
80
|
+
|
|
81
|
+
def services(self) -> openai_responses_router.OpenAIResponsesServices:
|
|
82
|
+
return openai_responses_router.OpenAIResponsesServices(
|
|
83
|
+
core=openai_responses_router.OpenAIResponsesCore(
|
|
84
|
+
event_bus=self.core.event_bus,
|
|
85
|
+
request_id=self.core.request_id,
|
|
86
|
+
input_as_list=self.core.input_as_list,
|
|
87
|
+
is_client_disconnect=self.core.is_client_disconnect,
|
|
88
|
+
log=self.core.log,
|
|
89
|
+
),
|
|
90
|
+
conversion=openai_responses_router.OpenAIResponsesConversion(
|
|
91
|
+
to_anthropic=self.conversion.to_anthropic,
|
|
92
|
+
current_alias=self.conversion.current_alias,
|
|
93
|
+
update_tool_schema=self.conversion.update_tool_schema,
|
|
94
|
+
normalize_thinking=self.conversion.normalize_thinking,
|
|
95
|
+
filter_blocked_tools=self.conversion.filter_blocked_tools,
|
|
96
|
+
normalize_tool_choice=self.conversion.normalize_tool_choice,
|
|
97
|
+
write_context_usage=self.conversion.write_context_usage,
|
|
98
|
+
strip_advisor_tools=self.conversion.strip_advisor_tools,
|
|
99
|
+
inject_channel_context=self.conversion.inject_channel_context,
|
|
100
|
+
inject_tool_result_context=self.conversion.inject_tool_result_context,
|
|
101
|
+
),
|
|
102
|
+
routing=openai_responses_router.OpenAIResponsesRouting(
|
|
103
|
+
maybe_import_session=self.routing.maybe_import_session,
|
|
104
|
+
codex_routed_enabled=self.routing.codex_routed_enabled,
|
|
105
|
+
forward_codex=self.routing.forward_codex,
|
|
106
|
+
select_protocol=self.routing.select_protocol,
|
|
107
|
+
forward_provider_responses=self.routing.forward_provider_responses,
|
|
108
|
+
dump_request=self.routing.dump_request,
|
|
109
|
+
normalize_provider_wire=self.routing.normalize_provider_wire,
|
|
110
|
+
collect_message=self.routing.collect_message,
|
|
111
|
+
apply_codex_compat_instructions=self.routing.apply_codex_compat_instructions,
|
|
112
|
+
recover_preamble_only_turn=self.routing.recover_preamble_only_turn,
|
|
113
|
+
),
|
|
114
|
+
delivery=openai_responses_router.OpenAIResponsesDelivery(
|
|
115
|
+
begin=self.delivery.begin,
|
|
116
|
+
mark_success=self.delivery.mark_success,
|
|
117
|
+
mark_failed=self.delivery.mark_failed,
|
|
118
|
+
commit=self.delivery.commit,
|
|
119
|
+
),
|
|
120
|
+
output=openai_responses_router.OpenAIResponsesOutput(
|
|
121
|
+
write_response=self.output.write_response,
|
|
122
|
+
write_error=self.output.write_error,
|
|
123
|
+
upstream_error_message=self.output.upstream_error_message,
|
|
124
|
+
codex_auth_error_message=self.output.codex_auth_error_message,
|
|
125
|
+
event_preview=self.output.event_preview,
|
|
126
|
+
),
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
@dataclass(frozen=True, slots=True)
|
|
131
|
+
class ClaudeRouterCorePorts:
|
|
132
|
+
event_bus: Any
|
|
133
|
+
log: Callback
|
|
134
|
+
try_write_json: Callback
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
@dataclass(frozen=True, slots=True)
|
|
138
|
+
class ClaudeRouterCountPorts:
|
|
139
|
+
estimate_tokens: Callback
|
|
140
|
+
write_context_usage: Callback
|
|
141
|
+
write_json: Callback
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
@dataclass(frozen=True, slots=True)
|
|
145
|
+
class ClaudeRouterPipelinePorts:
|
|
146
|
+
update_tool_schema: Callback
|
|
147
|
+
event_preview: Callback
|
|
148
|
+
dump_request: Callback
|
|
149
|
+
filter_blocked_tools: Callback
|
|
150
|
+
normalize_tool_choice: Callback
|
|
151
|
+
write_context_usage: Callback
|
|
152
|
+
strip_advisor_tools: Callback
|
|
153
|
+
inject_channel_context: Callback
|
|
154
|
+
inject_tool_result_context: Callback
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
@dataclass(frozen=True, slots=True)
|
|
158
|
+
class ClaudeRouterShortcutPorts:
|
|
159
|
+
plan_mode: Callback
|
|
160
|
+
router_debug: Callback
|
|
161
|
+
version: Callback
|
|
162
|
+
channel_clear: Callback
|
|
163
|
+
import_session: Callback
|
|
164
|
+
llm_options: Callback
|
|
165
|
+
api_keys: Callback
|
|
166
|
+
advisor: Callback
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
@dataclass(frozen=True, slots=True)
|
|
170
|
+
class ClaudeRouterDeliveryPorts:
|
|
171
|
+
begin: Callback
|
|
172
|
+
commit: Callback
|
|
173
|
+
mark_failed: Callback
|
|
174
|
+
mark_success: Callback
|
|
175
|
+
is_client_disconnect: Callback
|
|
176
|
+
write_activity: Callback
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
@dataclass(frozen=True, slots=True)
|
|
180
|
+
class ClaudeRouterRoutingPorts:
|
|
181
|
+
forward_ollama: Callback
|
|
182
|
+
forward_openai: Callback
|
|
183
|
+
select_protocol: Callback
|
|
184
|
+
request_policy: Callback
|
|
185
|
+
resolve_model: Callback
|
|
186
|
+
provider_labels: Mapping[str, str]
|
|
187
|
+
write_json: Callback
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
@dataclass(frozen=True, slots=True)
|
|
191
|
+
class ClaudeRouterNormalizationPorts:
|
|
192
|
+
normalize_provider_wire: Callback
|
|
193
|
+
normalize_thinking: Callback
|
|
194
|
+
normalize_system_roles: Callback
|
|
195
|
+
cap_body: Callback
|
|
196
|
+
apply_request_options: Callback
|
|
197
|
+
rehydrate_thinking: Callback
|
|
198
|
+
ncp_model_id: Callback
|
|
199
|
+
resolve_tool_models: Callback
|
|
200
|
+
normalize_model_options: Callback
|
|
201
|
+
strip_internal_metadata: Callback
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
@dataclass(frozen=True, slots=True)
|
|
205
|
+
class ClaudeRouterTransportPorts:
|
|
206
|
+
native_base_url: Callback
|
|
207
|
+
native_compat_enabled: Callback
|
|
208
|
+
upstream_base: Callback
|
|
209
|
+
join_url: Callback
|
|
210
|
+
upstream_query: Callback
|
|
211
|
+
provider_headers: Callback
|
|
212
|
+
apply_rate_limit: Callback
|
|
213
|
+
open_request: Callback
|
|
214
|
+
request_timeout: Callback
|
|
215
|
+
idle_timeout: Callback
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
@dataclass(frozen=True, slots=True)
|
|
219
|
+
class ClaudeRouterResponsePorts:
|
|
220
|
+
rebatch_sse: Callback
|
|
221
|
+
preserves_thinking: Callback
|
|
222
|
+
normalize_stream_tool_use: Callback
|
|
223
|
+
set_stream_timeout: Callback
|
|
224
|
+
normalize_thinking: Callback
|
|
225
|
+
append_tasklist: Callback
|
|
226
|
+
prepend_text: Callback
|
|
227
|
+
rate_limit_notice: Callback
|
|
228
|
+
register_key_cooldown: Callback
|
|
229
|
+
key_from_headers: Callback
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
@dataclass(frozen=True, slots=True)
|
|
233
|
+
class ClaudeRouterContextRecoveryPorts:
|
|
234
|
+
recover_output_budget: Callback
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
@dataclass(frozen=True, slots=True)
|
|
238
|
+
class ClaudeRouterAssembly:
|
|
239
|
+
core: ClaudeRouterCorePorts
|
|
240
|
+
count_tokens: ClaudeRouterCountPorts
|
|
241
|
+
pipeline: ClaudeRouterPipelinePorts
|
|
242
|
+
shortcuts: ClaudeRouterShortcutPorts
|
|
243
|
+
delivery: ClaudeRouterDeliveryPorts
|
|
244
|
+
routing: ClaudeRouterRoutingPorts
|
|
245
|
+
normalization: ClaudeRouterNormalizationPorts
|
|
246
|
+
transport: ClaudeRouterTransportPorts
|
|
247
|
+
response: ClaudeRouterResponsePorts
|
|
248
|
+
context_recovery: ClaudeRouterContextRecoveryPorts
|
|
249
|
+
|
|
250
|
+
def services(self) -> claude_router.ClaudeRouterServices:
|
|
251
|
+
return claude_router.ClaudeRouterServices(
|
|
252
|
+
core=claude_router.ClaudeRouterCore(
|
|
253
|
+
event_bus=self.core.event_bus,
|
|
254
|
+
log=self.core.log,
|
|
255
|
+
try_write_json=self.core.try_write_json,
|
|
256
|
+
),
|
|
257
|
+
count_tokens=claude_router.ClaudeRouterCountTokens(
|
|
258
|
+
estimate_tokens=self.count_tokens.estimate_tokens,
|
|
259
|
+
write_context_usage=self.count_tokens.write_context_usage,
|
|
260
|
+
write_json=self.count_tokens.write_json,
|
|
261
|
+
),
|
|
262
|
+
pipeline=claude_router.ClaudeRouterPipeline(
|
|
263
|
+
update_tool_schema_registry=self.pipeline.update_tool_schema,
|
|
264
|
+
router_event_message_preview=self.pipeline.event_preview,
|
|
265
|
+
dump_request_for_trace=self.pipeline.dump_request,
|
|
266
|
+
filter_blocked_tools=self.pipeline.filter_blocked_tools,
|
|
267
|
+
normalize_tool_choice=self.pipeline.normalize_tool_choice,
|
|
268
|
+
write_context_usage=self.pipeline.write_context_usage,
|
|
269
|
+
strip_advisor_tools=self.pipeline.strip_advisor_tools,
|
|
270
|
+
inject_channel_context=self.pipeline.inject_channel_context,
|
|
271
|
+
inject_tool_result_context=self.pipeline.inject_tool_result_context,
|
|
272
|
+
),
|
|
273
|
+
shortcuts=claude_router.ClaudeRouterShortcuts(
|
|
274
|
+
plan_mode=self.shortcuts.plan_mode,
|
|
275
|
+
router_debug=self.shortcuts.router_debug,
|
|
276
|
+
version=self.shortcuts.version,
|
|
277
|
+
channel_clear=self.shortcuts.channel_clear,
|
|
278
|
+
import_session=self.shortcuts.import_session,
|
|
279
|
+
llm_options=self.shortcuts.llm_options,
|
|
280
|
+
api_keys=self.shortcuts.api_keys,
|
|
281
|
+
advisor=self.shortcuts.advisor,
|
|
282
|
+
),
|
|
283
|
+
delivery=claude_router.ClaudeRouterDelivery(
|
|
284
|
+
begin=self.delivery.begin,
|
|
285
|
+
commit=self.delivery.commit,
|
|
286
|
+
mark_failed=self.delivery.mark_failed,
|
|
287
|
+
mark_success=self.delivery.mark_success,
|
|
288
|
+
is_client_disconnect=self.delivery.is_client_disconnect,
|
|
289
|
+
write_activity=self.delivery.write_activity,
|
|
290
|
+
),
|
|
291
|
+
routing=claude_router.ClaudeRouterRouting(
|
|
292
|
+
forward_ollama=self.routing.forward_ollama,
|
|
293
|
+
forward_openai=self.routing.forward_openai,
|
|
294
|
+
select_protocol=self.routing.select_protocol,
|
|
295
|
+
request_policy=self.routing.request_policy,
|
|
296
|
+
resolve_model=self.routing.resolve_model,
|
|
297
|
+
provider_labels=self.routing.provider_labels,
|
|
298
|
+
write_json=self.routing.write_json,
|
|
299
|
+
),
|
|
300
|
+
normalization=claude_router.ClaudeRouterNativeNormalization(
|
|
301
|
+
normalize_provider_wire=self.normalization.normalize_provider_wire,
|
|
302
|
+
normalize_thinking=self.normalization.normalize_thinking,
|
|
303
|
+
normalize_system_roles=self.normalization.normalize_system_roles,
|
|
304
|
+
cap_body=self.normalization.cap_body,
|
|
305
|
+
apply_request_options=self.normalization.apply_request_options,
|
|
306
|
+
rehydrate_thinking=self.normalization.rehydrate_thinking,
|
|
307
|
+
ncp_model_id=self.normalization.ncp_model_id,
|
|
308
|
+
resolve_tool_models=self.normalization.resolve_tool_models,
|
|
309
|
+
normalize_model_options=self.normalization.normalize_model_options,
|
|
310
|
+
strip_internal_metadata=self.normalization.strip_internal_metadata,
|
|
311
|
+
),
|
|
312
|
+
transport=claude_router.ClaudeRouterTransport(
|
|
313
|
+
native_base_url=self.transport.native_base_url,
|
|
314
|
+
native_compat_enabled=self.transport.native_compat_enabled,
|
|
315
|
+
upstream_base=self.transport.upstream_base,
|
|
316
|
+
join_url=self.transport.join_url,
|
|
317
|
+
upstream_query=self.transport.upstream_query,
|
|
318
|
+
provider_headers=self.transport.provider_headers,
|
|
319
|
+
apply_rate_limit=self.transport.apply_rate_limit,
|
|
320
|
+
open_request=self.transport.open_request,
|
|
321
|
+
request_timeout=self.transport.request_timeout,
|
|
322
|
+
idle_timeout=self.transport.idle_timeout,
|
|
323
|
+
),
|
|
324
|
+
response=claude_router.ClaudeRouterResponse(
|
|
325
|
+
rebatch_sse=self.response.rebatch_sse,
|
|
326
|
+
preserves_thinking=self.response.preserves_thinking,
|
|
327
|
+
normalize_stream_tool_use=self.response.normalize_stream_tool_use,
|
|
328
|
+
set_stream_timeout=self.response.set_stream_timeout,
|
|
329
|
+
normalize_thinking=self.response.normalize_thinking,
|
|
330
|
+
append_tasklist=self.response.append_tasklist,
|
|
331
|
+
prepend_text=self.response.prepend_text,
|
|
332
|
+
rate_limit_notice=self.response.rate_limit_notice,
|
|
333
|
+
register_key_cooldown=self.response.register_key_cooldown,
|
|
334
|
+
key_from_headers=self.response.key_from_headers,
|
|
335
|
+
),
|
|
336
|
+
context_recovery=claude_router.ClaudeRouterContextRecovery(
|
|
337
|
+
recover_output_budget=self.context_recovery.recover_output_budget,
|
|
338
|
+
),
|
|
339
|
+
)
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
@dataclass(frozen=True, slots=True)
|
|
343
|
+
class RouterRequestOuterPorts:
|
|
344
|
+
forward_backend_json: Callback
|
|
345
|
+
forward_backend_get: Callback
|
|
346
|
+
write_responses_error: Callback
|
|
347
|
+
write_json: Callback
|
|
348
|
+
upstream_error_message: Callback
|
|
349
|
+
is_client_disconnect: Callback
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
@dataclass(frozen=True, slots=True)
|
|
353
|
+
class RouterRequestAssembly:
|
|
354
|
+
openai: OpenAIResponseAssembly
|
|
355
|
+
outer: RouterRequestOuterPorts
|
|
356
|
+
codex_routed_enabled: Callback
|
|
357
|
+
forward_provider_chat: Callback
|
|
358
|
+
claude: ClaudeRouterAssembly
|
|
359
|
+
|
|
360
|
+
def context(self) -> RouterRequestContext:
|
|
361
|
+
return RouterRequestContext(
|
|
362
|
+
request=RouterRequestPorts(
|
|
363
|
+
openai_responses=self.openai.services(),
|
|
364
|
+
forward_backend_json=self.outer.forward_backend_json,
|
|
365
|
+
forward_backend_get=self.outer.forward_backend_get,
|
|
366
|
+
write_responses_error=self.outer.write_responses_error,
|
|
367
|
+
write_json=self.outer.write_json,
|
|
368
|
+
upstream_error_message=self.outer.upstream_error_message,
|
|
369
|
+
is_client_disconnect=self.outer.is_client_disconnect,
|
|
370
|
+
),
|
|
371
|
+
runtime=RuntimeRouterPorts(
|
|
372
|
+
codex_routed_enabled=self.codex_routed_enabled,
|
|
373
|
+
forward_provider_chat=self.forward_provider_chat,
|
|
374
|
+
claude_services=self.claude.services(),
|
|
375
|
+
),
|
|
376
|
+
)
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
__all__ = [
|
|
380
|
+
"ClaudeRouterAssembly",
|
|
381
|
+
"ClaudeRouterContextRecoveryPorts",
|
|
382
|
+
"ClaudeRouterCorePorts",
|
|
383
|
+
"ClaudeRouterCountPorts",
|
|
384
|
+
"ClaudeRouterDeliveryPorts",
|
|
385
|
+
"ClaudeRouterNormalizationPorts",
|
|
386
|
+
"ClaudeRouterPipelinePorts",
|
|
387
|
+
"ClaudeRouterResponsePorts",
|
|
388
|
+
"ClaudeRouterRoutingPorts",
|
|
389
|
+
"ClaudeRouterShortcutPorts",
|
|
390
|
+
"ClaudeRouterTransportPorts",
|
|
391
|
+
"OpenAIResponseAssembly",
|
|
392
|
+
"OpenAIResponseConversionPorts",
|
|
393
|
+
"OpenAIResponseCorePorts",
|
|
394
|
+
"OpenAIResponseDeliveryPorts",
|
|
395
|
+
"OpenAIResponseOutputPorts",
|
|
396
|
+
"OpenAIResponseRoutingPorts",
|
|
397
|
+
"RouterRequestAssembly",
|
|
398
|
+
"RouterRequestOuterPorts",
|
|
399
|
+
]
|