@oneciel-ai/ciel-runtime 0.2.2 → 0.2.4
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 +2555 -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/config_repository.py +30 -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 +245 -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 +84 -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/speech_http_controller.py +335 -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/web_ui.py +248 -1
- package/ciel_runtime_support/workspace_router_selection.py +86 -0
- package/docs/COLAB_SPEECH.md +32 -0
- package/docs/Configuration.md +50 -0
- package/docs/Test-Suite.md +1 -0
- package/package.json +4 -1
- package/scripts/colab/__pycache__/bootstrap_moss_tts.cpython-311.pyc +0 -0
- package/scripts/colab/__pycache__/bootstrap_qwen_asr.cpython-311.pyc +0 -0
- package/scripts/colab/bootstrap_moss_tts.py +106 -0
- package/scripts/colab/bootstrap_qwen_asr.py +106 -0
- package/scripts/configure_speech_workers.py +37 -0
- package/scripts/deploy_colab_speech.ps1 +47 -0
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
"""Executable discovery and runtime-owned command asset installation context."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Any, Callable, Mapping
|
|
8
|
+
|
|
9
|
+
from .command_asset_installer import CommandAsset, CommandAssetInstaller
|
|
10
|
+
from .executable_discovery import ExecutableDiscovery
|
|
11
|
+
from .statusline_settings import StatusLineServices, install_statusline_settings
|
|
12
|
+
from .tool_guard_hooks import (
|
|
13
|
+
LegacyToolGuardShimInstaller,
|
|
14
|
+
LegacyToolGuardShimServices,
|
|
15
|
+
ToolGuardHookServices,
|
|
16
|
+
install_tool_guard_hook_settings,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@dataclass(frozen=True, slots=True)
|
|
21
|
+
class RuntimeExecutablePaths:
|
|
22
|
+
home: Path
|
|
23
|
+
source_file: Path
|
|
24
|
+
platform_path: Callable[[], str]
|
|
25
|
+
runtime_bin_dir: Callable[[], Path]
|
|
26
|
+
agy_bin_dir: Callable[[], Path]
|
|
27
|
+
python_executable: str
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@dataclass(frozen=True, slots=True)
|
|
31
|
+
class RuntimeAssetPaths:
|
|
32
|
+
package_root: Path
|
|
33
|
+
statusline_path: Path
|
|
34
|
+
statusline_script: Path
|
|
35
|
+
claude_commands_dir: Path
|
|
36
|
+
codex_prompts_dir_name: str
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@dataclass(frozen=True, slots=True)
|
|
40
|
+
class RuntimeAssetEffects:
|
|
41
|
+
settings_repository: Callable[[], Any]
|
|
42
|
+
chmod: Callable[[Path, int], None]
|
|
43
|
+
log: Callable[[str, str], None]
|
|
44
|
+
warn: Callable[[str], None]
|
|
45
|
+
environ: Mapping[str, str]
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@dataclass(frozen=True, slots=True)
|
|
49
|
+
class RuntimeCommandAssetCatalog:
|
|
50
|
+
standard: dict[str, CommandAsset]
|
|
51
|
+
advisor: CommandAsset
|
|
52
|
+
advisor_markers: tuple[str, ...]
|
|
53
|
+
import_session: CommandAsset
|
|
54
|
+
import_markers: tuple[str, ...]
|
|
55
|
+
stale_markers: tuple[str, ...]
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@dataclass(frozen=True, slots=True)
|
|
59
|
+
class RuntimeToolGuardPolicy:
|
|
60
|
+
default_hook_policy: Any
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@dataclass(frozen=True, slots=True)
|
|
64
|
+
class RuntimeAssetCompatibilityPorts:
|
|
65
|
+
find_executable: Callable[[str], str | None]
|
|
66
|
+
find_tool_guard: Callable[[], Path | None]
|
|
67
|
+
tool_guard_command: Callable[[], str | None]
|
|
68
|
+
install_legacy_shim: Callable[[], None]
|
|
69
|
+
command_asset_installer: Callable[[Path], CommandAssetInstaller]
|
|
70
|
+
remove_advisor_command: Callable[[], None]
|
|
71
|
+
codex_prompts_dir: Callable[[Mapping[str, str] | None], Path]
|
|
72
|
+
command_assets: Callable[[bool], dict[str, CommandAsset]]
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
@dataclass(frozen=True, slots=True)
|
|
76
|
+
class RuntimeAssetContext:
|
|
77
|
+
executable: RuntimeExecutablePaths
|
|
78
|
+
paths: RuntimeAssetPaths
|
|
79
|
+
effects: RuntimeAssetEffects
|
|
80
|
+
catalog: RuntimeCommandAssetCatalog
|
|
81
|
+
tool_guard: RuntimeToolGuardPolicy
|
|
82
|
+
compatibility: RuntimeAssetCompatibilityPorts
|
|
83
|
+
|
|
84
|
+
def executable_discovery(self) -> ExecutableDiscovery:
|
|
85
|
+
return ExecutableDiscovery(
|
|
86
|
+
self.executable.home,
|
|
87
|
+
self.executable.source_file,
|
|
88
|
+
self.executable.platform_path,
|
|
89
|
+
self.executable.runtime_bin_dir,
|
|
90
|
+
self.executable.agy_bin_dir,
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
def executable_extra_dirs(self) -> list[Path]:
|
|
94
|
+
return self.executable_discovery().extra_dirs()
|
|
95
|
+
|
|
96
|
+
def find_executable(self, name: str) -> str | None:
|
|
97
|
+
return self.executable_discovery().find(name)
|
|
98
|
+
|
|
99
|
+
def resolve_executable(self, command: str) -> str:
|
|
100
|
+
return self.executable_discovery().resolve(command)
|
|
101
|
+
|
|
102
|
+
def resolve_mcp_process(
|
|
103
|
+
self, command: str, args: list[str]
|
|
104
|
+
) -> tuple[str, list[str]]:
|
|
105
|
+
return self.executable_discovery().resolve_mcp_process(
|
|
106
|
+
command, args, self.compatibility.find_executable
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
@staticmethod
|
|
110
|
+
def shell_command(args: list[str]) -> str:
|
|
111
|
+
return ExecutableDiscovery.shell_command(args)
|
|
112
|
+
|
|
113
|
+
def find_tool_guard(self) -> Path | None:
|
|
114
|
+
return self.executable_discovery().find_tool_guard(self.find_executable)
|
|
115
|
+
|
|
116
|
+
def tool_guard_command(self) -> str | None:
|
|
117
|
+
script = self.compatibility.find_tool_guard()
|
|
118
|
+
if script is None:
|
|
119
|
+
return None
|
|
120
|
+
command = (
|
|
121
|
+
[self.executable.python_executable, str(script)]
|
|
122
|
+
if script.suffix == ".py"
|
|
123
|
+
else [str(script)]
|
|
124
|
+
)
|
|
125
|
+
return self.shell_command(command)
|
|
126
|
+
|
|
127
|
+
def install_legacy_tool_guard_shim(self) -> None:
|
|
128
|
+
LegacyToolGuardShimInstaller(
|
|
129
|
+
LegacyToolGuardShimServices(
|
|
130
|
+
package_root=self.paths.package_root,
|
|
131
|
+
find_target=self.compatibility.find_tool_guard,
|
|
132
|
+
chmod=self.effects.chmod,
|
|
133
|
+
log=self.effects.log,
|
|
134
|
+
)
|
|
135
|
+
).install()
|
|
136
|
+
|
|
137
|
+
def install_tool_guard_hooks(self) -> None:
|
|
138
|
+
install_tool_guard_hook_settings(
|
|
139
|
+
self.compatibility.tool_guard_command(),
|
|
140
|
+
self.tool_guard.default_hook_policy,
|
|
141
|
+
ToolGuardHookServices(
|
|
142
|
+
repository=self.effects.settings_repository(),
|
|
143
|
+
install_legacy_shim=self.compatibility.install_legacy_shim,
|
|
144
|
+
warn=self.effects.warn,
|
|
145
|
+
),
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
def install_statusline(self) -> None:
|
|
149
|
+
install_statusline_settings(
|
|
150
|
+
self.paths.statusline_path,
|
|
151
|
+
self.paths.statusline_script,
|
|
152
|
+
self.executable.python_executable,
|
|
153
|
+
StatusLineServices(
|
|
154
|
+
repository=self.effects.settings_repository(),
|
|
155
|
+
warn=self.effects.warn,
|
|
156
|
+
),
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
def command_asset_installer(self, directory: Path) -> CommandAssetInstaller:
|
|
160
|
+
return CommandAssetInstaller(directory, self.effects.warn)
|
|
161
|
+
|
|
162
|
+
def remove_advisor_command(self) -> None:
|
|
163
|
+
self.compatibility.command_asset_installer(
|
|
164
|
+
self.paths.claude_commands_dir
|
|
165
|
+
).remove_one(
|
|
166
|
+
"advisor.md", self.catalog.advisor_markers
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
def codex_prompts_dir(
|
|
170
|
+
self, env: Mapping[str, str] | None = None
|
|
171
|
+
) -> Path:
|
|
172
|
+
environment = env or self.effects.environ
|
|
173
|
+
raw_home = environment.get("CODEX_HOME")
|
|
174
|
+
home = (
|
|
175
|
+
Path(raw_home).expanduser()
|
|
176
|
+
if raw_home
|
|
177
|
+
else self.executable.home / ".codex"
|
|
178
|
+
)
|
|
179
|
+
return home / self.paths.codex_prompts_dir_name
|
|
180
|
+
|
|
181
|
+
def install_codex_prompts(
|
|
182
|
+
self, env: Mapping[str, str] | None = None
|
|
183
|
+
) -> None:
|
|
184
|
+
self.compatibility.command_asset_installer(
|
|
185
|
+
self.compatibility.codex_prompts_dir(env)
|
|
186
|
+
).install_one(
|
|
187
|
+
"ImportSession.md", self.catalog.import_session
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
def disable_codex_prompts(
|
|
191
|
+
self, env: Mapping[str, str] | None = None
|
|
192
|
+
) -> None:
|
|
193
|
+
self.compatibility.command_asset_installer(
|
|
194
|
+
self.compatibility.codex_prompts_dir(env)
|
|
195
|
+
).remove_one(
|
|
196
|
+
"ImportSession.md", self.catalog.import_markers
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
def command_assets(self, include_advisor: bool = True) -> dict[str, CommandAsset]:
|
|
200
|
+
assets = dict(self.catalog.standard)
|
|
201
|
+
if include_advisor:
|
|
202
|
+
assets["advisor.md"] = self.catalog.advisor
|
|
203
|
+
return assets
|
|
204
|
+
|
|
205
|
+
def install_slash_commands(self, include_advisor: bool = True) -> None:
|
|
206
|
+
if not include_advisor:
|
|
207
|
+
self.compatibility.remove_advisor_command()
|
|
208
|
+
self.compatibility.command_asset_installer(
|
|
209
|
+
self.paths.claude_commands_dir
|
|
210
|
+
).install_all(
|
|
211
|
+
self.compatibility.command_assets(include_advisor),
|
|
212
|
+
stale_glob="llm-*.md",
|
|
213
|
+
stale_markers=self.catalog.stale_markers,
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
def disable_slash_commands(self) -> None:
|
|
217
|
+
self.compatibility.command_asset_installer(
|
|
218
|
+
self.paths.claude_commands_dir
|
|
219
|
+
).remove_all(
|
|
220
|
+
self.compatibility.command_assets(True),
|
|
221
|
+
stale_glob="llm-*.md",
|
|
222
|
+
stale_markers=self.catalog.stale_markers,
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
@dataclass(frozen=True, slots=True)
|
|
227
|
+
class RuntimeAssetCompatibilityApi:
|
|
228
|
+
context: Callable[[], RuntimeAssetContext]
|
|
229
|
+
|
|
230
|
+
def executable_discovery(self) -> ExecutableDiscovery:
|
|
231
|
+
return self.context().executable_discovery()
|
|
232
|
+
|
|
233
|
+
def executable_extra_dirs(self) -> list[Path]:
|
|
234
|
+
return self.context().executable_extra_dirs()
|
|
235
|
+
|
|
236
|
+
def find_executable(self, name: str) -> str | None:
|
|
237
|
+
return self.context().find_executable(name)
|
|
238
|
+
|
|
239
|
+
def resolve_executable(self, command: str) -> str:
|
|
240
|
+
return self.context().resolve_executable(command)
|
|
241
|
+
|
|
242
|
+
def resolve_mcp_process(self, *args: Any, **kwargs: Any) -> tuple[str, list[str]]:
|
|
243
|
+
return self.context().resolve_mcp_process(*args, **kwargs)
|
|
244
|
+
|
|
245
|
+
def shell_command(self, args: list[str]) -> str:
|
|
246
|
+
return self.context().shell_command(args)
|
|
247
|
+
|
|
248
|
+
def find_tool_guard(self) -> Path | None:
|
|
249
|
+
return self.context().find_tool_guard()
|
|
250
|
+
|
|
251
|
+
def tool_guard_command(self) -> str | None:
|
|
252
|
+
return self.context().tool_guard_command()
|
|
253
|
+
|
|
254
|
+
def install_legacy_tool_guard_shim(self) -> None:
|
|
255
|
+
self.context().install_legacy_tool_guard_shim()
|
|
256
|
+
|
|
257
|
+
def install_tool_guard_hooks(self) -> None:
|
|
258
|
+
self.context().install_tool_guard_hooks()
|
|
259
|
+
|
|
260
|
+
def install_statusline(self) -> None:
|
|
261
|
+
self.context().install_statusline()
|
|
262
|
+
|
|
263
|
+
def command_asset_installer(self, directory: Path) -> CommandAssetInstaller:
|
|
264
|
+
return self.context().command_asset_installer(directory)
|
|
265
|
+
|
|
266
|
+
def remove_advisor_command(self) -> None:
|
|
267
|
+
self.context().remove_advisor_command()
|
|
268
|
+
|
|
269
|
+
def codex_prompts_dir(self, *args: Any, **kwargs: Any) -> Path:
|
|
270
|
+
return self.context().codex_prompts_dir(*args, **kwargs)
|
|
271
|
+
|
|
272
|
+
def install_codex_prompts(self, *args: Any, **kwargs: Any) -> None:
|
|
273
|
+
self.context().install_codex_prompts(*args, **kwargs)
|
|
274
|
+
|
|
275
|
+
def disable_codex_prompts(self, *args: Any, **kwargs: Any) -> None:
|
|
276
|
+
self.context().disable_codex_prompts(*args, **kwargs)
|
|
277
|
+
|
|
278
|
+
def command_assets(self, include_advisor: bool = True) -> dict[str, CommandAsset]:
|
|
279
|
+
return self.context().command_assets(include_advisor)
|
|
280
|
+
|
|
281
|
+
def install_slash_commands(self, include_advisor: bool = True) -> None:
|
|
282
|
+
self.context().install_slash_commands(include_advisor)
|
|
283
|
+
|
|
284
|
+
def disable_slash_commands(self) -> None:
|
|
285
|
+
self.context().disable_slash_commands()
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
__all__ = [
|
|
289
|
+
"RuntimeAssetCompatibilityApi",
|
|
290
|
+
"RuntimeAssetCompatibilityPorts",
|
|
291
|
+
"RuntimeAssetContext",
|
|
292
|
+
"RuntimeAssetEffects",
|
|
293
|
+
"RuntimeAssetPaths",
|
|
294
|
+
"RuntimeCommandAssetCatalog",
|
|
295
|
+
"RuntimeExecutablePaths",
|
|
296
|
+
"RuntimeToolGuardPolicy",
|
|
297
|
+
]
|
|
@@ -93,7 +93,7 @@ OFFICIAL_CHANNEL_PLUGINS = {
|
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
APP_NAME = "Ciel Runtime"
|
|
96
|
-
VERSION = "0.2.
|
|
96
|
+
VERSION = "0.2.4"
|
|
97
97
|
CREDITS = "Credits: One Ciel LLC"
|
|
98
98
|
PRELAUNCH_CANCEL = 10
|
|
99
99
|
PRELAUNCH_LAUNCH_CODEX = 11
|
|
@@ -159,6 +159,21 @@ ROUTED_COMPAT_PROMPT = (
|
|
|
159
159
|
"or report the concrete connection state. Never write pseudo tool calls, partial JSON, or markdown code fences when a real Claude Code tool call is required."
|
|
160
160
|
)
|
|
161
161
|
NON_ANTHROPIC_COMPAT_PROMPT = ROUTED_COMPAT_PROMPT
|
|
162
|
+
# ROUTED_COMPAT_PROMPT is Claude Code specific -- it names Claude Code tools and
|
|
163
|
+
# is delivered with --append-system-prompt, a flag Codex classifies as Claude-only.
|
|
164
|
+
# Routed Codex sessions therefore had no equivalent instruction and would end a
|
|
165
|
+
# turn right after announcing what they were about to do. This is the Codex
|
|
166
|
+
# wording, appended to the Responses `instructions` field instead of a CLI flag.
|
|
167
|
+
# Keep it constant: it sits at the head of the prompt, so any variation would
|
|
168
|
+
# invalidate the upstream prefix cache on every turn.
|
|
169
|
+
ROUTED_CODEX_COMPAT_PROMPT = (
|
|
170
|
+
"You are running inside Codex CLI through the ciel-runtime router. Do not stop after announcing what you plan to do. "
|
|
171
|
+
"When the user asks you to inspect, create, edit, or run code, call the tools available in this turn and report the concrete result. "
|
|
172
|
+
"Never end a turn with only a statement of intent such as saying you will now start; perform the work in the same turn. "
|
|
173
|
+
"If the task has several reasonable in-scope parts, do all of them; do not ask which part to start unless the user explicitly asked for a choice. "
|
|
174
|
+
"If you decide not to use tools, give the complete answer in the same turn. "
|
|
175
|
+
"Use exactly the tool schema provided and do not invent extra fields, and never write pseudo tool calls or partial JSON where a real tool call is required."
|
|
176
|
+
)
|
|
162
177
|
LANGUAGES = {"en": "English", "ko": "한국어", "ja": "日本語", "zh": "中文"}
|
|
163
178
|
MODEL_PRESETS: dict[str, dict[str, Any]] = {
|
|
164
179
|
"deepseek-v4-flash:0731": {"compat_max_tokens": 64, "thinking": True, "num_ctx_min": 32768, "num_ctx_max": 1000000},
|
|
@@ -18,7 +18,7 @@ from ciel_runtime_support.runtime_constants import (
|
|
|
18
18
|
PRELAUNCH_LAUNCH_CODEX_APP_SERVER,
|
|
19
19
|
ROUTED_COMPAT_PROMPT,
|
|
20
20
|
)
|
|
21
|
-
from ciel_runtime_support.runtime_paths import CONFIG_DIR, LOG_PATH
|
|
21
|
+
from ciel_runtime_support.runtime_paths import CONFIG_DIR, LOG_PATH, ROUTER_INSTANCE_DIR
|
|
22
22
|
from ciel_runtime_support.web_endpoints import web_backend_settings
|
|
23
23
|
|
|
24
24
|
|
|
@@ -160,7 +160,6 @@ class ClaudeLaunchChannelDelivery:
|
|
|
160
160
|
claude_channel_args: Callable[..., Any]
|
|
161
161
|
native_channel_passthrough_requested: Callable[..., Any]
|
|
162
162
|
normalize_channel_passthrough: Callable[..., Any]
|
|
163
|
-
prepare_channel_llm_delivery_for_launch: Callable[..., Any]
|
|
164
163
|
should_launch_process_start_channel_sse: Callable[..., Any]
|
|
165
164
|
should_use_channel_llm_delivery: Callable[..., Any]
|
|
166
165
|
should_use_channel_stdin_proxy: Callable[..., Any]
|
|
@@ -255,7 +254,6 @@ def run_claude(
|
|
|
255
254
|
native_channel_passthrough_requested = services.channel_delivery.native_channel_passthrough_requested
|
|
256
255
|
normalize_channel_passthrough = services.channel_delivery.normalize_channel_passthrough
|
|
257
256
|
path_with_ciel_runtime_user_dirs = services.process.path_with_ciel_runtime_user_dirs
|
|
258
|
-
prepare_channel_llm_delivery_for_launch = services.channel_delivery.prepare_channel_llm_delivery_for_launch
|
|
259
257
|
print_routed_claude_exit_diagnostics = services.process.print_routed_claude_exit_diagnostics
|
|
260
258
|
provider_menu_label = services.config.provider_menu_label
|
|
261
259
|
read_channel_probe_cache = services.channel_discovery.read_channel_probe_cache
|
|
@@ -347,6 +345,9 @@ def run_claude(
|
|
|
347
345
|
)
|
|
348
346
|
cleanup_managed_services_for_provider(provider, pcfg, cfg, quiet=True)
|
|
349
347
|
env = os.environ.copy()
|
|
348
|
+
env["CIEL_RUNTIME_CONFIG_DIR"] = str(CONFIG_DIR)
|
|
349
|
+
env["CIEL_RUNTIME_STATE_DIR"] = str(ROUTER_INSTANCE_DIR)
|
|
350
|
+
env["CIEL_RUNTIME_LAUNCH_CWD"] = str(Path.cwd())
|
|
350
351
|
env["PATH"] = path_with_ciel_runtime_user_dirs(env)
|
|
351
352
|
launch_passthrough = normalize_channel_passthrough(passthrough)
|
|
352
353
|
native_channel_bridge = should_use_native_channel_bridge(use_router_mode, cfg, launch_passthrough)
|
|
@@ -513,8 +514,6 @@ def run_claude(
|
|
|
513
514
|
mcp_config_paths.extend(native_direct_mcp_config_paths)
|
|
514
515
|
claude_passthrough = strip_mcp_config_passthrough(launch_passthrough)
|
|
515
516
|
elif stdin_channel_proxy or llm_channel_delivery or native_auto_channel_specs:
|
|
516
|
-
if llm_channel_delivery:
|
|
517
|
-
prepare_channel_llm_delivery_for_launch()
|
|
518
517
|
if should_launch_process_start_channel_sse(stdin_channel_proxy, native_channel_bridge, llm_channel_delivery):
|
|
519
518
|
auto_start_sse_channels_from_mcp_configs(
|
|
520
519
|
launch_passthrough,
|
|
@@ -829,6 +828,7 @@ def run_codex(
|
|
|
829
828
|
warn_if_multiple_ciel_runtime_installs()
|
|
830
829
|
run_ciel_runtime_update_check(enabled=self_update_check)
|
|
831
830
|
env = os.environ.copy()
|
|
831
|
+
env["CIEL_RUNTIME_STATE_DIR"] = str(ROUTER_INSTANCE_DIR)
|
|
832
832
|
env["PATH"] = path_with_ciel_runtime_user_dirs(env)
|
|
833
833
|
codex = install_codex_if_missing()
|
|
834
834
|
if not codex:
|
|
@@ -1172,6 +1172,7 @@ def run_codex_app_server(
|
|
|
1172
1172
|
warn_if_multiple_ciel_runtime_installs()
|
|
1173
1173
|
run_ciel_runtime_update_check(enabled=self_update_check)
|
|
1174
1174
|
env = os.environ.copy()
|
|
1175
|
+
env["CIEL_RUNTIME_STATE_DIR"] = str(ROUTER_INSTANCE_DIR)
|
|
1175
1176
|
env["PATH"] = path_with_ciel_runtime_user_dirs(env)
|
|
1176
1177
|
codex = install_codex_if_missing()
|
|
1177
1178
|
if not codex:
|
|
@@ -1453,6 +1454,9 @@ def run_agy(
|
|
|
1453
1454
|
warn_if_multiple_ciel_runtime_installs()
|
|
1454
1455
|
run_ciel_runtime_update_check(enabled=self_update_check)
|
|
1455
1456
|
env = os.environ.copy()
|
|
1457
|
+
env["CIEL_RUNTIME_CONFIG_DIR"] = str(CONFIG_DIR)
|
|
1458
|
+
env["CIEL_RUNTIME_STATE_DIR"] = str(ROUTER_INSTANCE_DIR)
|
|
1459
|
+
env["CIEL_RUNTIME_LAUNCH_CWD"] = str(Path.cwd())
|
|
1456
1460
|
env["PATH"] = path_with_ciel_runtime_user_dirs(env)
|
|
1457
1461
|
agy = install_agy_if_missing()
|
|
1458
1462
|
if not agy:
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"""Runtime launch dispatch context with explicitly supplied service factories."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import Any, Callable
|
|
7
|
+
|
|
8
|
+
from .runtime_launch import (
|
|
9
|
+
AgyLaunchServices,
|
|
10
|
+
ClaudeLaunchServices,
|
|
11
|
+
CodexAppServerLaunchServices,
|
|
12
|
+
CodexLaunchServices,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass(frozen=True, slots=True)
|
|
17
|
+
class RuntimeLaunchRunners:
|
|
18
|
+
claude: Callable[..., int]
|
|
19
|
+
codex: Callable[..., int]
|
|
20
|
+
codex_app_server: Callable[..., int]
|
|
21
|
+
agy: Callable[..., int]
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass(frozen=True, slots=True)
|
|
25
|
+
class RuntimeLaunchServiceFactories:
|
|
26
|
+
claude: Callable[[], ClaudeLaunchServices]
|
|
27
|
+
codex: Callable[[], CodexLaunchServices]
|
|
28
|
+
codex_app_server: Callable[[], CodexAppServerLaunchServices]
|
|
29
|
+
agy: Callable[[], AgyLaunchServices]
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@dataclass(frozen=True, slots=True)
|
|
33
|
+
class RuntimeLaunchContext:
|
|
34
|
+
runners: RuntimeLaunchRunners
|
|
35
|
+
services: RuntimeLaunchServiceFactories
|
|
36
|
+
|
|
37
|
+
def launch_claude(
|
|
38
|
+
self,
|
|
39
|
+
passthrough: list[str],
|
|
40
|
+
skip_menu: bool = False,
|
|
41
|
+
force_menu: bool = False,
|
|
42
|
+
web_search_override: bool | None = None,
|
|
43
|
+
update_check: bool = True,
|
|
44
|
+
self_update_check: bool = True,
|
|
45
|
+
) -> int:
|
|
46
|
+
return self.runners.claude(
|
|
47
|
+
passthrough,
|
|
48
|
+
skip_menu=skip_menu,
|
|
49
|
+
force_menu=force_menu,
|
|
50
|
+
web_search_override=web_search_override,
|
|
51
|
+
update_check=update_check,
|
|
52
|
+
self_update_check=self_update_check,
|
|
53
|
+
services=self.services.claude(),
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
def launch_codex(
|
|
57
|
+
self,
|
|
58
|
+
passthrough: list[str],
|
|
59
|
+
skip_menu: bool = False,
|
|
60
|
+
force_menu: bool = False,
|
|
61
|
+
update_check: bool = True,
|
|
62
|
+
self_update_check: bool = True,
|
|
63
|
+
) -> int:
|
|
64
|
+
return self.runners.codex(
|
|
65
|
+
passthrough,
|
|
66
|
+
skip_menu=skip_menu,
|
|
67
|
+
force_menu=force_menu,
|
|
68
|
+
update_check=update_check,
|
|
69
|
+
self_update_check=self_update_check,
|
|
70
|
+
services=self.services.codex(),
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
def launch_codex_app_server(
|
|
74
|
+
self,
|
|
75
|
+
passthrough: list[str],
|
|
76
|
+
skip_menu: bool = True,
|
|
77
|
+
force_menu: bool = False,
|
|
78
|
+
update_check: bool = True,
|
|
79
|
+
self_update_check: bool = True,
|
|
80
|
+
) -> int:
|
|
81
|
+
return self.runners.codex_app_server(
|
|
82
|
+
passthrough,
|
|
83
|
+
skip_menu=skip_menu,
|
|
84
|
+
force_menu=force_menu,
|
|
85
|
+
update_check=update_check,
|
|
86
|
+
self_update_check=self_update_check,
|
|
87
|
+
services=self.services.codex_app_server(),
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
def launch_agy(
|
|
91
|
+
self,
|
|
92
|
+
passthrough: list[str],
|
|
93
|
+
skip_menu: bool = False,
|
|
94
|
+
force_menu: bool = False,
|
|
95
|
+
update_check: bool = True,
|
|
96
|
+
self_update_check: bool = True,
|
|
97
|
+
) -> int:
|
|
98
|
+
return self.runners.agy(
|
|
99
|
+
passthrough,
|
|
100
|
+
skip_menu=skip_menu,
|
|
101
|
+
force_menu=force_menu,
|
|
102
|
+
update_check=update_check,
|
|
103
|
+
self_update_check=self_update_check,
|
|
104
|
+
services=self.services.agy(),
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
@dataclass(frozen=True, slots=True)
|
|
109
|
+
class RuntimeLaunchCompatibilityApi:
|
|
110
|
+
context: Callable[[], RuntimeLaunchContext]
|
|
111
|
+
|
|
112
|
+
def launch_claude(self, *args: Any, **kwargs: Any) -> int:
|
|
113
|
+
return self.context().launch_claude(*args, **kwargs)
|
|
114
|
+
|
|
115
|
+
def launch_codex(self, *args: Any, **kwargs: Any) -> int:
|
|
116
|
+
return self.context().launch_codex(*args, **kwargs)
|
|
117
|
+
|
|
118
|
+
def launch_codex_app_server(self, *args: Any, **kwargs: Any) -> int:
|
|
119
|
+
return self.context().launch_codex_app_server(*args, **kwargs)
|
|
120
|
+
|
|
121
|
+
def launch_agy(self, *args: Any, **kwargs: Any) -> int:
|
|
122
|
+
return self.context().launch_agy(*args, **kwargs)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
__all__ = [
|
|
126
|
+
"RuntimeLaunchCompatibilityApi",
|
|
127
|
+
"RuntimeLaunchContext",
|
|
128
|
+
"RuntimeLaunchRunners",
|
|
129
|
+
"RuntimeLaunchServiceFactories",
|
|
130
|
+
]
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""Composition boundary for runtime installation and maintenance services."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import Callable, Mapping
|
|
7
|
+
|
|
8
|
+
from .runtime_maintenance_context import (
|
|
9
|
+
RuntimeAgyPorts,
|
|
10
|
+
RuntimeLifecyclePorts,
|
|
11
|
+
RuntimeMaintenanceContext,
|
|
12
|
+
RuntimePackagePorts,
|
|
13
|
+
RuntimeUpgradeCommandPorts,
|
|
14
|
+
)
|
|
15
|
+
from .runtime_maintenance_services import RuntimeMaintenanceServices
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclass(frozen=True, slots=True)
|
|
19
|
+
class RuntimeMaintenanceCommandPorts:
|
|
20
|
+
environment: Mapping[str, str]
|
|
21
|
+
claude_version: Callable[[str], str]
|
|
22
|
+
codex_version: Callable[[str], str]
|
|
23
|
+
upgrade_runtime: Callable[[], int]
|
|
24
|
+
upgrade_claude: Callable[[], int]
|
|
25
|
+
upgrade_codex: Callable[[], int]
|
|
26
|
+
upgrade_agy: Callable[[], int]
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@dataclass(frozen=True, slots=True)
|
|
30
|
+
class RuntimeMaintenanceAssembly:
|
|
31
|
+
service_graph: RuntimeMaintenanceServices
|
|
32
|
+
commands: RuntimeMaintenanceCommandPorts
|
|
33
|
+
|
|
34
|
+
def context(self) -> RuntimeMaintenanceContext:
|
|
35
|
+
services = self.service_graph
|
|
36
|
+
commands = self.commands
|
|
37
|
+
return RuntimeMaintenanceContext(
|
|
38
|
+
packages=RuntimePackagePorts(
|
|
39
|
+
services.npm_lifecycle,
|
|
40
|
+
commands.environment,
|
|
41
|
+
commands.claude_version,
|
|
42
|
+
commands.codex_version,
|
|
43
|
+
),
|
|
44
|
+
lifecycle=RuntimeLifecyclePorts(
|
|
45
|
+
services.install_diagnostics,
|
|
46
|
+
services.restart_service,
|
|
47
|
+
services.self_update,
|
|
48
|
+
services.upgrade,
|
|
49
|
+
),
|
|
50
|
+
agy=RuntimeAgyPorts(services.agy_installer),
|
|
51
|
+
upgrade_commands=RuntimeUpgradeCommandPorts(
|
|
52
|
+
commands.upgrade_runtime,
|
|
53
|
+
commands.upgrade_claude,
|
|
54
|
+
commands.upgrade_codex,
|
|
55
|
+
commands.upgrade_agy,
|
|
56
|
+
),
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
__all__ = ["RuntimeMaintenanceAssembly", "RuntimeMaintenanceCommandPorts"]
|