@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,215 @@
|
|
|
1
|
+
"""Runtime protocol request handling and router selection bounded context."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import urllib.error
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
from http.server import BaseHTTPRequestHandler
|
|
8
|
+
from typing import Any, Callable
|
|
9
|
+
|
|
10
|
+
from .agent_router import (
|
|
11
|
+
RuntimeRouter,
|
|
12
|
+
missing_common_capabilities,
|
|
13
|
+
router_capability_matrix,
|
|
14
|
+
)
|
|
15
|
+
from .claude_router import ClaudeRouter, ClaudeRouterServices
|
|
16
|
+
from .codex_router import CodexRouter
|
|
17
|
+
from .openai_chat_router import OpenAIChatRouter
|
|
18
|
+
from .openai_responses_router import (
|
|
19
|
+
OpenAIResponsesServices,
|
|
20
|
+
handle_openai_responses_request,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass(frozen=True, slots=True)
|
|
25
|
+
class RouterRequestPorts:
|
|
26
|
+
openai_responses: OpenAIResponsesServices
|
|
27
|
+
forward_backend_json: Callable[..., Any]
|
|
28
|
+
forward_backend_get: Callable[..., Any]
|
|
29
|
+
write_responses_error: Callable[..., Any]
|
|
30
|
+
write_json: Callable[..., Any]
|
|
31
|
+
upstream_error_message: Callable[..., str]
|
|
32
|
+
is_client_disconnect: Callable[[BaseException], bool]
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@dataclass(frozen=True, slots=True)
|
|
36
|
+
class RuntimeRouterPorts:
|
|
37
|
+
codex_routed_enabled: Callable[..., bool]
|
|
38
|
+
forward_provider_chat: Callable[..., Any]
|
|
39
|
+
claude_services: ClaudeRouterServices
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@dataclass(frozen=True, slots=True)
|
|
43
|
+
class RouterRequestContext:
|
|
44
|
+
request: RouterRequestPorts
|
|
45
|
+
runtime: RuntimeRouterPorts
|
|
46
|
+
|
|
47
|
+
def handle_openai_responses_post(
|
|
48
|
+
self,
|
|
49
|
+
handler: BaseHTTPRequestHandler,
|
|
50
|
+
cfg: dict[str, Any],
|
|
51
|
+
provider: str,
|
|
52
|
+
pcfg: dict[str, Any],
|
|
53
|
+
body: dict[str, Any],
|
|
54
|
+
) -> None:
|
|
55
|
+
handle_openai_responses_request(
|
|
56
|
+
handler,
|
|
57
|
+
cfg,
|
|
58
|
+
provider,
|
|
59
|
+
pcfg,
|
|
60
|
+
body,
|
|
61
|
+
self.request.openai_responses,
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
def handle_codex_backend_passthrough_post(
|
|
65
|
+
self,
|
|
66
|
+
handler: BaseHTTPRequestHandler,
|
|
67
|
+
provider: str,
|
|
68
|
+
pcfg: dict[str, Any],
|
|
69
|
+
body: dict[str, Any],
|
|
70
|
+
) -> None:
|
|
71
|
+
try:
|
|
72
|
+
self.request.forward_backend_json(
|
|
73
|
+
handler,
|
|
74
|
+
provider,
|
|
75
|
+
pcfg,
|
|
76
|
+
body,
|
|
77
|
+
mutate_responses=False,
|
|
78
|
+
)
|
|
79
|
+
except urllib.error.HTTPError as exc:
|
|
80
|
+
raw = exc.read().decode("utf-8", errors="ignore")
|
|
81
|
+
self.request.write_responses_error(
|
|
82
|
+
handler,
|
|
83
|
+
self.request.upstream_error_message(exc, raw),
|
|
84
|
+
stream=False,
|
|
85
|
+
status=exc.code,
|
|
86
|
+
)
|
|
87
|
+
except Exception as exc:
|
|
88
|
+
if self.request.is_client_disconnect(exc):
|
|
89
|
+
return
|
|
90
|
+
self.request.write_responses_error(
|
|
91
|
+
handler,
|
|
92
|
+
f"{type(exc).__name__}: {exc}",
|
|
93
|
+
stream=False,
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
def handle_codex_backend_passthrough_get(
|
|
97
|
+
self,
|
|
98
|
+
handler: BaseHTTPRequestHandler,
|
|
99
|
+
provider: str,
|
|
100
|
+
pcfg: dict[str, Any],
|
|
101
|
+
) -> None:
|
|
102
|
+
try:
|
|
103
|
+
self.request.forward_backend_get(handler, provider, pcfg)
|
|
104
|
+
except urllib.error.HTTPError as exc:
|
|
105
|
+
raw = exc.read().decode("utf-8", errors="ignore")
|
|
106
|
+
self.request.write_json(
|
|
107
|
+
handler,
|
|
108
|
+
{"error": {"message": self.request.upstream_error_message(exc, raw)}},
|
|
109
|
+
status=exc.code,
|
|
110
|
+
)
|
|
111
|
+
except Exception as exc:
|
|
112
|
+
if self.request.is_client_disconnect(exc):
|
|
113
|
+
return
|
|
114
|
+
self.request.write_json(
|
|
115
|
+
handler,
|
|
116
|
+
{"error": {"message": f"{type(exc).__name__}: {exc}"}},
|
|
117
|
+
status=502,
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
def build_claude_router_services(self) -> ClaudeRouterServices:
|
|
121
|
+
return self.runtime.claude_services
|
|
122
|
+
|
|
123
|
+
def build_runtime_routers(self) -> tuple[RuntimeRouter, ...]:
|
|
124
|
+
return (
|
|
125
|
+
CodexRouter(
|
|
126
|
+
routed_enabled=self.runtime.codex_routed_enabled,
|
|
127
|
+
handle_responses_post=self.handle_openai_responses_post,
|
|
128
|
+
handle_backend_passthrough_post=(
|
|
129
|
+
self.handle_codex_backend_passthrough_post
|
|
130
|
+
),
|
|
131
|
+
handle_backend_passthrough_get=(
|
|
132
|
+
self.handle_codex_backend_passthrough_get
|
|
133
|
+
),
|
|
134
|
+
),
|
|
135
|
+
OpenAIChatRouter(self.runtime.forward_provider_chat),
|
|
136
|
+
ClaudeRouter(services=self.runtime.claude_services),
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
def capability_matrix(self) -> dict[str, dict[str, Any]]:
|
|
140
|
+
return router_capability_matrix(self.build_runtime_routers())
|
|
141
|
+
|
|
142
|
+
def capability_gaps(self) -> dict[str, list[str]]:
|
|
143
|
+
return missing_common_capabilities(self.build_runtime_routers())
|
|
144
|
+
|
|
145
|
+
def route_get(
|
|
146
|
+
self,
|
|
147
|
+
handler: BaseHTTPRequestHandler,
|
|
148
|
+
path: str,
|
|
149
|
+
provider: str,
|
|
150
|
+
pcfg: dict[str, Any],
|
|
151
|
+
) -> bool:
|
|
152
|
+
for router in self.build_runtime_routers():
|
|
153
|
+
if router.can_handle_get(path, provider, pcfg):
|
|
154
|
+
return bool(router.handle_get(handler, path, provider, pcfg))
|
|
155
|
+
return False
|
|
156
|
+
|
|
157
|
+
def route_post(
|
|
158
|
+
self,
|
|
159
|
+
handler: BaseHTTPRequestHandler,
|
|
160
|
+
cfg: dict[str, Any],
|
|
161
|
+
provider: str,
|
|
162
|
+
pcfg: dict[str, Any],
|
|
163
|
+
path: str,
|
|
164
|
+
body: dict[str, Any],
|
|
165
|
+
) -> bool:
|
|
166
|
+
for router in self.build_runtime_routers():
|
|
167
|
+
if router.can_handle_post(path, provider, pcfg):
|
|
168
|
+
return bool(
|
|
169
|
+
router.handle_post(handler, cfg, provider, pcfg, path, body)
|
|
170
|
+
)
|
|
171
|
+
return False
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
@dataclass(frozen=True, slots=True)
|
|
175
|
+
class RouterRequestCompatibilityApi:
|
|
176
|
+
context: Callable[[], RouterRequestContext]
|
|
177
|
+
|
|
178
|
+
def handle_openai_responses_post(self, *args: Any, **kwargs: Any) -> None:
|
|
179
|
+
self.context().handle_openai_responses_post(*args, **kwargs)
|
|
180
|
+
|
|
181
|
+
def handle_codex_backend_passthrough_post(
|
|
182
|
+
self, *args: Any, **kwargs: Any
|
|
183
|
+
) -> None:
|
|
184
|
+
self.context().handle_codex_backend_passthrough_post(*args, **kwargs)
|
|
185
|
+
|
|
186
|
+
def handle_codex_backend_passthrough_get(
|
|
187
|
+
self, *args: Any, **kwargs: Any
|
|
188
|
+
) -> None:
|
|
189
|
+
self.context().handle_codex_backend_passthrough_get(*args, **kwargs)
|
|
190
|
+
|
|
191
|
+
def build_claude_router_services(self) -> ClaudeRouterServices:
|
|
192
|
+
return self.context().build_claude_router_services()
|
|
193
|
+
|
|
194
|
+
def build_runtime_routers(self) -> tuple[RuntimeRouter, ...]:
|
|
195
|
+
return self.context().build_runtime_routers()
|
|
196
|
+
|
|
197
|
+
def capability_matrix(self) -> dict[str, dict[str, Any]]:
|
|
198
|
+
return self.context().capability_matrix()
|
|
199
|
+
|
|
200
|
+
def capability_gaps(self) -> dict[str, list[str]]:
|
|
201
|
+
return self.context().capability_gaps()
|
|
202
|
+
|
|
203
|
+
def route_get(self, *args: Any, **kwargs: Any) -> bool:
|
|
204
|
+
return self.context().route_get(*args, **kwargs)
|
|
205
|
+
|
|
206
|
+
def route_post(self, *args: Any, **kwargs: Any) -> bool:
|
|
207
|
+
return self.context().route_post(*args, **kwargs)
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
__all__ = [
|
|
211
|
+
"RouterRequestCompatibilityApi",
|
|
212
|
+
"RouterRequestContext",
|
|
213
|
+
"RouterRequestPorts",
|
|
214
|
+
"RuntimeRouterPorts",
|
|
215
|
+
]
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"""Router HTTP presentation and server lifecycle 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_http import RouterHttpServices
|
|
10
|
+
from .router_server_runtime import RouterServerRuntime
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass(frozen=True, slots=True)
|
|
14
|
+
class RouterHealthPresentationPorts:
|
|
15
|
+
version: str
|
|
16
|
+
source_fingerprint: str
|
|
17
|
+
current_pid: Callable[[], int]
|
|
18
|
+
current_user: Callable[[], str]
|
|
19
|
+
home: Path
|
|
20
|
+
config_dir: Path
|
|
21
|
+
workspace: str
|
|
22
|
+
router_port: int
|
|
23
|
+
current_alias: Callable[[dict[str, Any]], str]
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dataclass(frozen=True, slots=True)
|
|
27
|
+
class RouterServerContext:
|
|
28
|
+
health: RouterHealthPresentationPorts
|
|
29
|
+
http_services: RouterHttpServices
|
|
30
|
+
server_runtime: RouterServerRuntime
|
|
31
|
+
|
|
32
|
+
def health_payload(
|
|
33
|
+
self,
|
|
34
|
+
cfg: dict[str, Any],
|
|
35
|
+
provider: str,
|
|
36
|
+
pcfg: dict[str, Any],
|
|
37
|
+
) -> dict[str, Any]:
|
|
38
|
+
del pcfg
|
|
39
|
+
return {
|
|
40
|
+
"ok": True,
|
|
41
|
+
"version": self.health.version,
|
|
42
|
+
"source_fingerprint": self.health.source_fingerprint,
|
|
43
|
+
"pid": self.health.current_pid(),
|
|
44
|
+
"user": self.health.current_user(),
|
|
45
|
+
"home": str(self.health.home),
|
|
46
|
+
"config_dir": str(self.health.config_dir),
|
|
47
|
+
"workspace": self.health.workspace,
|
|
48
|
+
"router_port": self.health.router_port,
|
|
49
|
+
"provider": provider,
|
|
50
|
+
"model": self.health.current_alias(cfg),
|
|
51
|
+
"web_chat": "/ca/web/chat",
|
|
52
|
+
"chat": "/ca/chat/health",
|
|
53
|
+
"plan": "/ca/plan/artifacts",
|
|
54
|
+
"events": "/ca/events",
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
def build_http_services(self) -> RouterHttpServices:
|
|
58
|
+
return self.http_services
|
|
59
|
+
|
|
60
|
+
def serve(self, _: Any) -> None:
|
|
61
|
+
self.server_runtime.run()
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@dataclass(frozen=True, slots=True)
|
|
65
|
+
class RouterServerCompatibilityApi:
|
|
66
|
+
context: Callable[[], RouterServerContext]
|
|
67
|
+
|
|
68
|
+
def health_payload(self, *args: Any, **kwargs: Any) -> dict[str, Any]:
|
|
69
|
+
return self.context().health_payload(*args, **kwargs)
|
|
70
|
+
|
|
71
|
+
def build_http_services(self) -> RouterHttpServices:
|
|
72
|
+
return self.context().build_http_services()
|
|
73
|
+
|
|
74
|
+
def serve(self, args: Any) -> None:
|
|
75
|
+
self.context().serve(args)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
__all__ = [
|
|
79
|
+
"RouterHealthPresentationPorts",
|
|
80
|
+
"RouterServerCompatibilityApi",
|
|
81
|
+
"RouterServerContext",
|
|
82
|
+
]
|