@oneciel-ai/ciel-runtime 0.2.37 → 0.2.39
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/CHANGELOG.md +85 -0
- package/README.md +5 -2
- package/ciel_runtime.py +94 -96
- package/ciel_runtime_support/anthropic_model_policy.py +20 -3
- package/ciel_runtime_support/architecture.py +5 -0
- package/ciel_runtime_support/channel_inflight.py +4 -4
- package/ciel_runtime_support/channel_injection.py +56 -1
- package/ciel_runtime_support/channel_mcp_tools.py +34 -0
- package/ciel_runtime_support/channel_message_policy.py +9 -1
- package/ciel_runtime_support/channel_message_prompt.py +23 -0
- package/ciel_runtime_support/channel_pending_injection.py +86 -32
- package/ciel_runtime_support/channel_pending_poll.py +6 -2
- package/ciel_runtime_support/channel_runtime_environment.py +0 -11
- package/ciel_runtime_support/channel_terminal_context.py +0 -6
- package/ciel_runtime_support/channel_terminal_proxy.py +3 -42
- package/ciel_runtime_support/channel_transcript_repository.py +16 -1
- package/ciel_runtime_support/channel_wake_claim_repository.py +0 -19
- package/ciel_runtime_support/channel_wake_context.py +6 -13
- package/ciel_runtime_support/channel_wake_delivery_repository.py +50 -0
- package/ciel_runtime_support/chat_http_controller.py +88 -5
- package/ciel_runtime_support/claude_environment.py +100 -3
- package/ciel_runtime_support/claude_launch_assembly.py +4 -0
- package/ciel_runtime_support/claude_session_socket.py +181 -0
- package/ciel_runtime_support/cli_application_context.py +18 -10
- package/ciel_runtime_support/cli_dispatch.py +19 -3
- package/ciel_runtime_support/cli_parser.py +2 -0
- package/ciel_runtime_support/cli_usage.py +3 -2
- package/ciel_runtime_support/codex_backend_context.py +8 -3
- package/ciel_runtime_support/codex_completion_gate.py +198 -0
- package/ciel_runtime_support/codex_turn_recovery.py +240 -83
- package/ciel_runtime_support/compatibility_protocol.py +5 -2
- package/ciel_runtime_support/config_migrations.py +79 -0
- package/ciel_runtime_support/config_repository.py +7 -0
- package/ciel_runtime_support/context_summary_policy.py +24 -4
- package/ciel_runtime_support/external_event_menu.py +107 -0
- package/ciel_runtime_support/external_event_receiver.py +19 -1
- package/ciel_runtime_support/launch_state.py +2 -0
- package/ciel_runtime_support/managed_tool_injection.py +81 -0
- package/ciel_runtime_support/muse_runtime_context.py +291 -0
- package/ciel_runtime_support/ollama_thinking.py +12 -26
- package/ciel_runtime_support/prelaunch.py +13 -0
- package/ciel_runtime_support/prelaunch_launch_panel.py +2 -1
- package/ciel_runtime_support/prompt_compaction.py +39 -0
- package/ciel_runtime_support/provider_files_proxy.py +248 -0
- package/ciel_runtime_support/provider_model_identity.py +10 -2
- package/ciel_runtime_support/provider_option_cli.py +1 -1
- package/ciel_runtime_support/provider_request_access.py +54 -1
- package/ciel_runtime_support/provider_responses_passthrough.py +152 -15
- package/ciel_runtime_support/providers/alibaba.py +34 -1
- package/ciel_runtime_support/providers/anthropic.py +18 -1
- package/ciel_runtime_support/providers/meta.py +252 -21
- package/ciel_runtime_support/pseudo_tool_parser.py +17 -1
- package/ciel_runtime_support/remote_bridge.py +4 -0
- package/ciel_runtime_support/remote_instructions.py +5 -0
- package/ciel_runtime_support/remote_memory.py +1 -1
- package/ciel_runtime_support/responses_cache_diagnostics.py +82 -0
- package/ciel_runtime_support/responses_custom_tool_bridge.py +282 -0
- package/ciel_runtime_support/responses_input_compatibility.py +19 -3
- package/ciel_runtime_support/router_http.py +301 -4
- package/ciel_runtime_support/router_observability_context.py +26 -0
- package/ciel_runtime_support/router_server_context.py +1 -0
- package/ciel_runtime_support/runtime_adapters.py +31 -0
- package/ciel_runtime_support/runtime_constants.py +23 -1
- package/ciel_runtime_support/runtime_input_gateway.py +85 -5
- package/ciel_runtime_support/runtime_input_status.py +150 -0
- package/ciel_runtime_support/runtime_launch.py +35 -4
- package/ciel_runtime_support/runtime_paths.py +1 -0
- package/ciel_runtime_support/speech_http_controller.py +3 -2
- package/ciel_runtime_support/streaming_anthropic.py +3 -0
- package/ciel_runtime_support/tool_call_events.py +98 -0
- package/ciel_runtime_support/transcript_delta_delivery.py +140 -1
- package/ciel_runtime_support/ui_text.py +1 -0
- package/ciel_runtime_support/web_search_result_events.py +130 -0
- package/ciel_runtime_support/web_ui.py +1 -0
- package/ciel_runtime_support/windows_conpty.py +92 -8
- package/ciel_runtime_support/workspace_mcp.py +4 -1
- package/ciel_runtime_support/workspace_state.py +1 -0
- package/docs/Configuration.md +20 -4
- package/docs/MCP-Channels.md +79 -6
- package/docs/Managed-Tool-Injection.md +25 -0
- package/docs/Module-Map.md +4 -0
- package/docs/Muse-Code.md +73 -0
- package/docs/Observability.md +39 -0
- package/docs/Providers.md +29 -2
- package/docs/Remote-Bridge.md +12 -0
- package/docs/Router.md +1 -0
- package/docs/journal/2026/09/01/diagnostics/anthropic/router/fable51-usage-credits.okf +70 -0
- package/docs/journal/2026/09/01/implementation/claude/session-socket/all-input-paths/default-delivery.okf +133 -0
- package/docs/journal/2026/09/01/implementation/claude/session-socket/windows-direct-input.okf +112 -0
- package/docs/journal/2026/09/02/diagnostics/cache/alibaba/qwen38-post-restart-hit-rate.okf +107 -0
- package/docs/journal/2026/09/02/diagnostics/cache/ollama-cloud/kimi-k3-codex-hit-rate.okf +91 -0
- package/docs/journal/2026/09/02/diagnostics/codex/tui/statusline-cache-metrics.okf +44 -0
- package/docs/journal/2026/09/02/diagnostics/input/transport/fallback-behavior.okf +31 -0
- package/docs/journal/2026/09/02/diagnostics/providers/ollama-cloud/kimi-k3-agent-turn-recovery.okf +125 -0
- package/docs/journal/2026/09/02/diagnostics/providers/ollama-cloud/kimi-k3-parameters.okf +128 -0
- package/docs/journal/2026/09/02/diagnostics/remote/mia/socket-tui-visibility.okf +47 -0
- package/docs/journal/2026/09/02/diagnostics/runtime/alibaba/token-plan/qwen38-latency.okf +108 -0
- package/docs/journal/2026/09/02/diagnostics/runtime/alibaba/token-plan/qwen38-vs-gpt56-latency.okf +92 -0
- package/docs/journal/2026/09/02/implementation/anthropic/context/one-million-defaults.okf +85 -0
- package/docs/journal/2026/09/02/implementation/cache/alibaba/qwen38-cache-hit-improvement.okf +104 -0
- package/docs/journal/2026/09/02/implementation/cache/alibaba/qwen38-cache-hit-improvement.png +0 -0
- package/docs/journal/2026/09/02/implementation/cache/alibaba/responses-session-cache.okf +97 -0
- package/docs/journal/2026/09/02/implementation/providers/alibaba/qwen38/0902-parameter-alignment.okf +97 -0
- package/docs/journal/2026/09/02/implementation/providers/meta/multimodal-tools/contributor-protocol-adoption.okf +140 -0
- package/docs/journal/2026/09/02/implementation/providers/meta/muse-spark-1.3-support.okf +53 -0
- package/docs/journal/2026/09/02/monitoring/cache/alibaba/cielarvis-qwen38-live-hit-rate.okf +858 -0
- package/docs/journal/2026/09/02/operations/release/main-merge-local-deploy.okf +36 -0
- package/docs/journal/2026/09/02/operations/release/nightly/local-cache-deployment.okf +54 -0
- package/docs/journal/2026/09/02/operations/release/nightly/ollama-kimi-recovery-model-audit-deployment.okf +58 -0
- package/docs/journal/2026/09/02/operations/release/nightly/qwen38-cache-improvement-deployment.okf +72 -0
- package/docs/journal/2026/09/02/research/cache/alibaba/qwen38-hit-rate-improvement.okf +233 -0
- package/docs/journal/2026/09/02/research/cache/codex/provider-scope.okf +77 -0
- package/docs/journal/2026/09/02/research/providers/ollama-cloud/desktop-model-exhaustive-audit.okf +159 -0
- package/docs/journal/2026/09/03/diagnostics/providers/meta/muse-spark-contributor-cache-hit.okf +148 -0
- package/docs/journal/2026/09/03/diagnostics/providers/meta/muse-spark-contributor-required-schema.okf +127 -0
- package/docs/journal/2026/09/03/diagnostics/providers/ollama-cloud/kimi-k3-resumed-session-stall.okf +160 -0
- package/docs/journal/2026/09/03/diagnostics/providers/ollama-cloud/kimi-k3-substantive-dangling-action.okf +94 -0
- package/docs/journal/2026/09/03/diagnostics/remote/kevin/codex-gpt-early-turn-completion.okf +162 -0
- package/docs/journal/2026/09/03/implementation/runtimes/meta/muse-code/default-yolo.okf +40 -0
- package/docs/journal/2026/09/03/implementation/runtimes/meta/muse-code/native-subscription-router.okf +86 -0
- package/docs/journal/2026/09/03/operations/deployment/local/session-socket-default-fallback.okf +41 -0
- package/docs/journal/2026/09/03/research/deployment/colab/tailscale/credential-storage.okf +41 -0
- package/docs/journal/2026/09/03/research/providers/meta/muse-code/subscription-billing-boundary.okf +64 -0
- package/docs/journal/2026/09/03/research/web-chat/voice/instruction-format.okf +135 -0
- package/docs/journal/2026/09/04/diagnostics/claude/context/early-auto-compaction.okf +75 -0
- package/docs/journal/2026/09/04/diagnostics/claude/context/fable-51-status-200k.okf +54 -0
- package/docs/journal/2026/09/04/diagnostics/runtime/codex/responses/replayed-item-id-validation.okf +74 -0
- package/docs/journal/2026/09/04/diagnostics/workspaces/onecieldmsui/codex/replay-stall.okf +100 -0
- package/docs/journal/2026/09/04/implementation/observability/tool-calls/websocket-stream.okf +49 -0
- package/docs/journal/2026/09/04/implementation/web-chat/input/raw-injection.okf +42 -0
- package/docs/journal/2026/09/05/diagnostics/tty/claude-raw-idle-render.okf +25 -0
- package/docs/journal/2026/09/05/implementation/events/search-response-urls.okf +23 -0
- package/docs/journal/2026/09/05/implementation/tools/native-injection.okf +19 -0
- package/docs/journal/2026/09/05/implementation/windows/conpty/prompt-delivery-lifecycle.okf +43 -0
- package/docs/journal/2026/09/05/release/nightly/conpty-native-tools.okf +13 -0
- package/docs/journal/2026/09/05/release/nightly/search-result-urls.okf +14 -0
- package/docs/journal/2026/09/06/implementation/codex/inherited-web-mcp.okf +22 -0
- package/docs/journal/2026/09/07/fixes/codex/native-web-transport.okf +39 -0
- package/docs/journal/2026/09/07/integration/main/nightly-merge.okf +13 -0
- package/docs/journal/2026/09/07/release/stable/0.2.38.okf +10 -0
- package/docs/journal/2026/09/07/release/stable/0.2.39.okf +10 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,91 @@ capability, followed by the complete commit ledger merged into each release.
|
|
|
5
5
|
|
|
6
6
|
## Unreleased
|
|
7
7
|
|
|
8
|
+
## 0.2.39 — 2026-09-07
|
|
9
|
+
|
|
10
|
+
- Fix native Codex startup failing with `invalid transport` when DuckDuckGo or
|
|
11
|
+
web_fetch is not registered. Inspect the effective workspace configuration
|
|
12
|
+
before adding process-only disabling overrides; never modify global or
|
|
13
|
+
workspace TOML. Concurrent non-native sessions retain their MCP settings.
|
|
14
|
+
|
|
15
|
+
## 0.2.38 — 2026-09-07
|
|
16
|
+
|
|
17
|
+
- Disable inherited DuckDuckGo and web_fetch MCP servers with per-launch
|
|
18
|
+
overrides for native Codex (direct/routed and app-server), without editing
|
|
19
|
+
global settings or changing non-native provider launches.
|
|
20
|
+
- Emit URL-only web search result events over the existing `tool.call` event
|
|
21
|
+
stream, parsing Claude search result links and available Codex response
|
|
22
|
+
sources. Persist bounded call correlation and result deduplication state.
|
|
23
|
+
- Select Ciel-managed MCP tools by native/non-native launch mode without
|
|
24
|
+
filtering user MCP definitions. Keep generated DuckDuckGo/fetch tools out
|
|
25
|
+
of Anthropic launches even when Ciel web search is explicitly enabled.
|
|
26
|
+
- Make Windows ConPTY prompt-render detection ANSI- and UTF-8-aware, and make
|
|
27
|
+
unconfirmed TUI delivery fail closed without retyping, ASCII sentinel wakes,
|
|
28
|
+
or automatic router fallback. Runtime Input requests now expose durable
|
|
29
|
+
`queued -> submitted -> replied|failed` status queries and real-time events;
|
|
30
|
+
unresolved earlier requests block later TUI drafts. ConPTY resize failures
|
|
31
|
+
and post-resize redraw observations are logged explicitly.
|
|
32
|
+
- Add `raw_injection=true` to the Web Chat message APIs so a caller can inject
|
|
33
|
+
only the exact `message` text without an envelope, attachment projection, or
|
|
34
|
+
response-routing instruction, independently of input transport and response
|
|
35
|
+
destination.
|
|
36
|
+
- Publish normalized Claude, Codex, Muse Code, and routed-provider tool-call
|
|
37
|
+
starts as `tool.call` observability events, with incremental transcript cursors and
|
|
38
|
+
duplicate call-ID suppression. Add authenticated WebSocket event streaming at
|
|
39
|
+
`/ca/events/ws`, including `after`, `level`, and `category` filters.
|
|
40
|
+
|
|
41
|
+
- Repair resumed Codex Responses history whose item IDs contain characters the
|
|
42
|
+
OpenAI backend rejects, and discard projected encrypted reasoning that the
|
|
43
|
+
destination backend cannot authenticate instead of rejecting it one item per
|
|
44
|
+
retry.
|
|
45
|
+
|
|
46
|
+
- Add Muse Code as a native Ciel runtime through `ciel-runtime muse`, including
|
|
47
|
+
official installer discovery, Windows WSL2 execution, Muse 1.3 model and
|
|
48
|
+
reasoning flags, launch-menu/CLI selection, channel-proxy input, and remote
|
|
49
|
+
AGENTS.md synchronization. Native launches remove `META_API_KEY` and
|
|
50
|
+
`MODEL_API_KEY` so Muse browser sign-in remains eligible for Muse Code
|
|
51
|
+
subscription billing instead of silently switching to API pay-as-you-go.
|
|
52
|
+
Normal Muse sessions now include the CLI's native `--yolo` option by default,
|
|
53
|
+
while utility subcommands remain side-effect-free passthrough commands.
|
|
54
|
+
- Make `session_socket` the explicit default for Web Chat and every Runtime
|
|
55
|
+
Input Gateway source. When a runtime has no usable Claude messaging socket,
|
|
56
|
+
idle delivery now falls back to TTY; an active turn retains the durable input
|
|
57
|
+
until terminal injection is safe. Explicit TTY and router selections remain.
|
|
58
|
+
- Improve Meta Muse Spark cache reuse for Codex Responses sessions by adding
|
|
59
|
+
the provider-documented `24h` retention hint when Codex supplies a stable
|
|
60
|
+
`prompt_cache_key`. Cache activity now records privacy-safe request-shape
|
|
61
|
+
fingerprints so intermittent misses can be distinguished from prefix/tool
|
|
62
|
+
changes without logging prompt contents.
|
|
63
|
+
- Complete Meta Muse Spark's native agent surface across Responses, Chat
|
|
64
|
+
Completions, and Messages. Hosted `web_search`/`tool_search`, deferred tools,
|
|
65
|
+
multimodal request blocks, and streaming `/v1/files` upload/list/download/
|
|
66
|
+
delete routes now pass through without lossy protocol conversion; Muse
|
|
67
|
+
compatibility probes reserve enough output budget for reasoning tool calls.
|
|
68
|
+
- Add Meta Muse Spark 1.3 and `muse-spark-1.3-contributor` as first-class
|
|
69
|
+
Meta Model API models. New configurations default to 1.3, existing catalogs
|
|
70
|
+
are migrated without overwriting the selected model, and Codex/Claude receive
|
|
71
|
+
the documented 1M context and `minimal` through `xhigh` reasoning controls.
|
|
72
|
+
- Improve Alibaba Singapore Token Plan cache reuse for Codex: stateless
|
|
73
|
+
full-history Responses requests now use Qwen's implicit prefix cache instead
|
|
74
|
+
of forcing the response-ID session-cache header, while oversized requests
|
|
75
|
+
align their summarized prefix to pair-safe 24-item checkpoints.
|
|
76
|
+
- Deliver Web Chat, configured external event streams/webhooks, and Ciel MCP
|
|
77
|
+
`submit_input` calls to interactive Claude Code sessions through Claude's
|
|
78
|
+
authenticated session socket by default. Windows named pipes and Unix
|
|
79
|
+
AF_UNIX sockets are supported; explicit TTY and router overrides remain.
|
|
80
|
+
- Add Claude Fable 5.1 to the Anthropic catalog and model policy.
|
|
81
|
+
- Stop forcing current Anthropic 1M-default models down to a 200K Claude Code
|
|
82
|
+
auto-compaction window when their configured model ID has no legacy `[1m]`
|
|
83
|
+
marker. Routed Opus 4.6+ / Opus 5, Sonnet 4.6+ / Sonnet 5, and current
|
|
84
|
+
Fable/Mythos models now follow Anthropic's documented default 1M capacity;
|
|
85
|
+
their Claude-facing gateway aliases carry the local `[1m]` context hint even
|
|
86
|
+
when the selected upstream ID does not. Legacy models such as Sonnet 4.5 and
|
|
87
|
+
Haiku 4.5 remain at 200K.
|
|
88
|
+
- Advertise provider descriptions in the gateway model catalog for Claude Code
|
|
89
|
+
2.1.257 and later model-picker discovery.
|
|
90
|
+
- Apply each routed provider's configured subagent model to every Claude Code
|
|
91
|
+
2.1.257+ subagent with the new force-model environment switch.
|
|
92
|
+
|
|
8
93
|
## 0.2.37 — 2026-09-01
|
|
9
94
|
|
|
10
95
|
- Add the authenticated remote runtime bridge with shared OpenAI-compatible and
|
package/README.md
CHANGED
|
@@ -77,6 +77,7 @@ ciel-runtime codex
|
|
|
77
77
|
ciel-runtime agy
|
|
78
78
|
ciel-runtime grok
|
|
79
79
|
ciel-runtime zcode
|
|
80
|
+
ciel-runtime muse
|
|
80
81
|
ciel-runtime --ca-runtime codex-app-server
|
|
81
82
|
```
|
|
82
83
|
|
|
@@ -92,7 +93,7 @@ ciel-runtimectl test
|
|
|
92
93
|
|
|
93
94
|
| Capability | What it provides |
|
|
94
95
|
|---|---|
|
|
95
|
-
| Runtime launch | Claude Code, Codex, Codex App Server, AGY, Grok Build, and
|
|
96
|
+
| Runtime launch | Claude Code, Codex, Codex App Server, AGY, Grok Build, ZCode, and Muse Code from one entrypoint |
|
|
96
97
|
| Provider routing | Native connections where supported; otherwise a loopback HTTP router with provider-owned endpoint and authentication rules |
|
|
97
98
|
| Remote Runtime Bridge | One authenticated OpenAI/Anthropic-compatible network endpoint with per-request provider/model routing, protocol projection, Router-host OAuth, and isolated request keys where allowed |
|
|
98
99
|
| Protocol adaptation | Anthropic Messages, OpenAI Chat, OpenAI Responses, Ollama Chat, tool calls, thinking blocks, and SSE streams |
|
|
@@ -146,7 +147,9 @@ See [Remote Memory](docs/Remote-Memory.md) and [Configuration](docs/Configuratio
|
|
|
146
147
|
Ciel's router exposes separate interfaces for inbound work and outbound
|
|
147
148
|
observability:
|
|
148
149
|
|
|
149
|
-
- external events
|
|
150
|
+
- external events, Web Chat, and Ciel MCP inputs use Claude Code's authenticated
|
|
151
|
+
session socket by default while an interactive Claude session is active, with
|
|
152
|
+
Windows named-pipe and Unix AF_UNIX support;
|
|
150
153
|
- transcript webhooks emit only new deltas and retain a retry cursor;
|
|
151
154
|
- routed token usage is stored per workspace without prompt or credential bodies;
|
|
152
155
|
- authenticated consumers can read immutable usage events, resume an SSE stream,
|
package/ciel_runtime.py
CHANGED
|
@@ -113,8 +113,11 @@ from ciel_runtime_support.channel_wake_delivery_repository import ChannelWakeDel
|
|
|
113
113
|
from ciel_runtime_support.chat_files import ChatFilePorts, ChatFileRepository
|
|
114
114
|
from ciel_runtime_support.chat_http_controller import ChatHttpController, ChatHttpReadServices, ChatHttpWriteServices
|
|
115
115
|
from ciel_runtime_support.runtime_input_gateway import RuntimeInputGateway
|
|
116
|
+
from ciel_runtime_support.runtime_input_status import RuntimeInputStatusRepository
|
|
116
117
|
from ciel_runtime_support.external_event_receiver import EventReceiverSecretVault, ExternalEventReceiverService
|
|
118
|
+
from ciel_runtime_support.external_event_menu import panel_rows as project_external_event_panel_rows, update_config as project_set_external_event_config
|
|
117
119
|
from ciel_runtime_support.claude_environment import ClaudeEnvironmentFeaturePorts, ClaudeEnvironmentProjection, ClaudeEnvironmentShellRenderer, ClaudeEnvironmentSourcePorts, ClaudeLimitPolicy, ClaudeLimitPorts, ClaudeModelAliasCompatibilityApi, ClaudeModelAliasPolicy, ClaudeModelPorts, ClaudeRuntimeSettingsPolicy, ClaudeRuntimeSettingsPorts
|
|
120
|
+
from ciel_runtime_support.claude_session_socket import ClaudeSessionSocketClient, prepared_socket_path
|
|
118
121
|
from ciel_runtime_support.cli_application_context import CliApplicationCompatibilityApi, CliApplicationContext, CliApplicationDispatchPorts, CliApplicationPresentationPorts
|
|
119
122
|
from ciel_runtime_support.cli_usage import cli_usage_text
|
|
120
123
|
from ciel_runtime_support.codex_app_server import codex_app_server_launch_args
|
|
@@ -175,6 +178,7 @@ from ciel_runtime_support.zai_start_plan_captcha import zai_start_plan_runtime_h
|
|
|
175
178
|
from ciel_runtime_support.headless_config import HeadlessConfigCommands, HeadlessConfigServices, HeadlessEnvFileLoader, apply_headless_config
|
|
176
179
|
from ciel_runtime_support.http_response import ChannelDeliveryGuard, HttpResponseAdapter
|
|
177
180
|
from ciel_runtime_support.kimi_runtime_context import KimiConfigurationPorts, KimiIdentityPorts, KimiLifecyclePorts, KimiProcessPorts, KimiRuntimeCompatibilityApi, KimiRuntimeContext
|
|
181
|
+
from ciel_runtime_support.muse_runtime_context import MuseConfigurationPorts, MuseLifecyclePorts, MuseProcessPorts, MuseRuntimeCompatibilityApi, MuseRuntimeContext
|
|
178
182
|
from ciel_runtime_support.zcode_runtime_context import ZcodeConfigurationPorts, ZcodeLifecyclePorts, ZcodeProcessPorts, ZcodeRuntimeCompatibilityApi, ZcodeRuntimeContext
|
|
179
183
|
from ciel_runtime_support.launch_diagnostics import LaunchCommandDiagnostics, StderrCaptureAdapter
|
|
180
184
|
from ciel_runtime_support.launch_state import LaunchStateRepository
|
|
@@ -371,6 +375,8 @@ from ciel_runtime_support.router_access import RouterAccessConfigService, Router
|
|
|
371
375
|
from ciel_runtime_support.router_client_lifecycle import ManagedRouterLifetime, ManagedRouterLifetimePorts, RoutedLaunchDiagnosticPorts, RoutedLaunchDiagnostics, RouterClientRegistry, RouterClientRegistryPorts, RouterClientSupervisor, RouterClientSupervisorPorts, RouterLifetimeRunner, RouterLifetimeRunnerPorts
|
|
372
376
|
from ciel_runtime_support.router_health_policy import RouterHealthPolicy
|
|
373
377
|
from ciel_runtime_support.router_http import EventHttpAdapter, EventHttpPorts, RouterHttpCore, RouterHttpErrors, RouterHttpGetEndpoints, RouterHttpHandler, RouterHttpPostEndpoints, RouterHttpPresentation, RouterHttpRemoteBridge, RouterHttpServices
|
|
378
|
+
from ciel_runtime_support.router_http import RouterHttpFileEndpoints
|
|
379
|
+
from ciel_runtime_support.provider_files_proxy import ProviderFilesProxy, ProviderFilesProxyPorts
|
|
374
380
|
from ciel_runtime_support.remote_bridge_runtime import RemoteBridgeRuntimeApi
|
|
375
381
|
from ciel_runtime_support.router_observability_context import RequestTraceConfiguration
|
|
376
382
|
from ciel_runtime_support.router_observability_context import RequestTracePorts as RouterRequestTracePorts
|
|
@@ -436,7 +442,7 @@ from ciel_runtime_support.runtime_maintenance_services import MaintenanceAgyPort
|
|
|
436
442
|
from ciel_runtime_support.runtime_paths import (CHANNEL_COMPACT_REQUEST_PATH, # noqa: F401
|
|
437
443
|
CHANNEL_LLM_CLEAR_FLOOR_PATH, CHANNEL_LLM_CURSOR_PATH,
|
|
438
444
|
CHANNEL_LLM_LAUNCH_GUARD_PATH,
|
|
439
|
-
CHANNEL_STDIN_WAKE_CLAIMS_PATH, CHAT_FILES_DIR, CHAT_MESSAGES_PATH, RUNTIME_INPUTS_PATH,
|
|
445
|
+
CHANNEL_STDIN_WAKE_CLAIMS_PATH, CHAT_FILES_DIR, CHAT_MESSAGES_PATH, RUNTIME_INPUTS_PATH, RUNTIME_INPUT_STATUS_PATH,
|
|
440
446
|
CIEL_RUNTIME_STATUSLINE_PATH, CLAUDE_COMMANDS_DIR, CLAUDE_GATEWAY_CACHE,
|
|
441
447
|
CLAUDE_SETTINGS_PATH, CODEX_PROCESS_DIR,
|
|
442
448
|
CODEX_PROMPTS_DIR_NAME, CONFIG_DIR, CONFIG_PATH, LEGACY_CONFIG_PATH,
|
|
@@ -584,19 +590,26 @@ _CHANNEL_STDIN_INJECT_LOCK = threading.Lock()
|
|
|
584
590
|
_CHANNEL_STDIN_WAKE_DELIVERED: set[int] = set()
|
|
585
591
|
_CHANNEL_STDIN_WAKE_PROMPTS: dict[int, str] = {}
|
|
586
592
|
_CHANNEL_STDIN_WAKE_BATCHES: dict[int, frozenset[int]] = {}
|
|
593
|
+
_CHANNEL_STDIN_WAKE_FAILED: dict[int, str] = {}
|
|
594
|
+
EVENT_BUS, TUI_OBSERVATION_BUS = EventBus(), TuiObservationBus()
|
|
595
|
+
_RUNTIME_INPUT_STATUS_REPOSITORY = RuntimeInputStatusRepository(
|
|
596
|
+
RUNTIME_INPUT_STATUS_PATH, EVENT_BUS.publish,
|
|
597
|
+
lambda level, message: router_log(level, message), threading.RLock(),
|
|
598
|
+
)
|
|
587
599
|
_CHANNEL_WAKE_DELIVERY_REPOSITORY = ChannelWakeDeliveryRepository(
|
|
588
600
|
lock=_CHANNEL_STDIN_WAKE_LOCK,
|
|
589
601
|
delivered=_CHANNEL_STDIN_WAKE_DELIVERED,
|
|
590
602
|
prompts=_CHANNEL_STDIN_WAKE_PROMPTS,
|
|
591
603
|
batches=_CHANNEL_STDIN_WAKE_BATCHES,
|
|
604
|
+
failed=_CHANNEL_STDIN_WAKE_FAILED,
|
|
592
605
|
clear_claim=lambda message_id: _channel_stdin_clear_wake_claim(message_id),
|
|
593
606
|
commit_cursor=lambda message_id: _commit_channel_llm_cursor_if_newer(message_id),
|
|
607
|
+
status=_RUNTIME_INPUT_STATUS_REPOSITORY,
|
|
594
608
|
)
|
|
595
609
|
_CHANNEL_COMPACT_REQUEST_LOCK = threading.Lock()
|
|
596
610
|
_TOOL_SIDE_EFFECT_DEDUP_TTL_SECONDS = 10 * 60.0
|
|
597
611
|
_TOOL_SIDE_EFFECT_DEDUP_LOCK = threading.Lock()
|
|
598
612
|
_TOOL_SIDE_EFFECT_DEDUP_RECENT: dict[str, float] = {}
|
|
599
|
-
EVENT_BUS, TUI_OBSERVATION_BUS = EventBus(), TuiObservationBus()
|
|
600
613
|
USAGE_API_KEYS = UsageApiKeyRepository(USAGE_LEDGER := SqliteUsageLedger(WORKSPACE_STATE_DIR / "usage" / "usage.sqlite3", ROUTER_WORKSPACE_ID), WORKSPACE_STATE_DIR / "usage" / "api-key.pepper", os.environ)
|
|
601
614
|
USAGE_EVENT_SINK = CompositeUsageEventSink(JsonlUsageEventSink(USAGE_EVENTS_PATH, enabled=lambda: usage_jsonl_enabled(load_config(), os.environ)), USAGE_LEDGER)
|
|
602
615
|
# Tools Claude Code injects into every model's tool list that misfire when called
|
|
@@ -743,6 +756,7 @@ def apply_config_migrations(cfg: dict[str, Any]) -> None:
|
|
|
743
756
|
run_config_migrations(
|
|
744
757
|
cfg,
|
|
745
758
|
policy=ConfigMigrationPolicy(
|
|
759
|
+
anthropic_defaults_to_one_million_context=anthropic_model_policy.defaults_to_one_million_context,
|
|
746
760
|
default_request_timeout_ms=DEFAULT_REQUEST_TIMEOUT_MS,
|
|
747
761
|
kimi_k3_model=KIMI_K3_MODEL,
|
|
748
762
|
opencode_provider_names=OPENCODE_PROVIDER_NAMES,
|
|
@@ -871,6 +885,7 @@ def model_object(provider: str, model_id: str, pcfg: dict[str, Any] | None = Non
|
|
|
871
885
|
"id": alias,
|
|
872
886
|
"type": "model",
|
|
873
887
|
"display_name": display_name(provider, model_id),
|
|
888
|
+
"description": f"Routed through Ciel Runtime provider '{provider}'.",
|
|
874
889
|
"created_at": 1700000000,
|
|
875
890
|
"object": "model",
|
|
876
891
|
"created": 1700000000,
|
|
@@ -883,7 +898,6 @@ def model_object(provider: str, model_id: str, pcfg: dict[str, Any] | None = Non
|
|
|
883
898
|
)
|
|
884
899
|
)
|
|
885
900
|
return obj
|
|
886
|
-
|
|
887
901
|
join_url = runtime_primitives.join_url
|
|
888
902
|
def inbound_query_has_beta_flag(request_path: str) -> bool: return provider_query_policy().inbound_has_beta(request_path)
|
|
889
903
|
def provider_query_policy() -> ProviderQueryPolicy: return ProviderQueryPolicy(normalize_provider=normalize_provider, propagates_inbound_beta=lambda provider, config: configured_provider_adapter(provider, config).propagates_inbound_beta_query(provider_contract_config(provider, config)))
|
|
@@ -1135,7 +1149,7 @@ def router_observability_context() -> RouterObservabilityContext:
|
|
|
1135
1149
|
anthropic_tool_continuation_block_count, router_log, USAGE_EVENT_SINK.record, EVENT_BUS.publish),
|
|
1136
1150
|
sse_config=SseTraceConfiguration(CONFIG_DIR, SSE_LAST_PATH, SSE_TRACE_PATH, TOOL_CALL_LOG_PATH, SSE_TRACE_EVENT_LIMIT,
|
|
1137
1151
|
SSE_TRACE_PAYLOAD_LIMIT, SSE_TRACE_MAX_BYTES, LOG_LEVELS["TRACE"]),
|
|
1138
|
-
sse=SseObservabilityPorts(os.environ, current_log_level, _truncate_for_dump, router_log),
|
|
1152
|
+
sse=SseObservabilityPorts(os.environ, current_log_level, _truncate_for_dump, router_log, EVENT_BUS.publish),
|
|
1139
1153
|
)
|
|
1140
1154
|
|
|
1141
1155
|
_ROUTER_OBSERVABILITY_API = RouterObservabilityCompatibilityApi(router_observability_context)
|
|
@@ -1860,6 +1874,8 @@ def runtime_input_gateway() -> RuntimeInputGateway:
|
|
|
1860
1874
|
return RuntimeInputGateway(
|
|
1861
1875
|
append_runtime_input,
|
|
1862
1876
|
chat_file_repository().runtime_attachment,
|
|
1877
|
+
_default_channel_input_transport,
|
|
1878
|
+
_RUNTIME_INPUT_STATUS_REPOSITORY,
|
|
1863
1879
|
)
|
|
1864
1880
|
|
|
1865
1881
|
def external_event_receiver_service() -> ExternalEventReceiverService:
|
|
@@ -1895,63 +1911,10 @@ def handle_external_event_raw_post(handler: BaseHTTPRequestHandler, path: str, r
|
|
|
1895
1911
|
return external_event_receiver_service().handle_raw_post(handler, path, raw)
|
|
1896
1912
|
|
|
1897
1913
|
def external_event_panel_rows(_cfg: dict[str, Any]) -> tuple[list[str], list[str]]:
|
|
1898
|
-
|
|
1899
|
-
receiver = service.receiver_configs().get("default", {})
|
|
1900
|
-
public_receiver = service.public_receiver("default", receiver)
|
|
1901
|
-
environment_references = public_receiver.get("environment_references", {})
|
|
1902
|
-
enabled = bool(receiver.get("enabled", False))
|
|
1903
|
-
transport = str(receiver.get("transport") or "webhook")
|
|
1904
|
-
event_types = receiver.get("event_types") if isinstance(receiver.get("event_types"), list) else []
|
|
1905
|
-
secret_status = service.vault.status("default")
|
|
1906
|
-
def secret_source(field_name: str, stored_key: str) -> str:
|
|
1907
|
-
reference = environment_references.get(field_name, {})
|
|
1908
|
-
if isinstance(reference, dict) and reference.get("name"):
|
|
1909
|
-
availability = "available" if reference.get("available") else "missing"
|
|
1910
|
-
return f"env:{reference['name']} {availability}"
|
|
1911
|
-
return "stored" if secret_status[stored_key] else "unset"
|
|
1912
|
-
rows = [
|
|
1913
|
-
f"Enabled [{'on' if enabled else 'off'}]",
|
|
1914
|
-
f"Transport [{transport}]",
|
|
1915
|
-
f"SSE URL [{str(receiver.get('url') or 'unset')}]",
|
|
1916
|
-
"SSE content mode [CloudEvents 1.0 structured JSON]",
|
|
1917
|
-
f"Allowed CloudEvent types [{', '.join(str(value) for value in event_types) if event_types else 'all'}]",
|
|
1918
|
-
f"Cursor JSON pointer [{str(receiver.get('cursor_json_pointer') or 'SSE id field')}]",
|
|
1919
|
-
f"Reconnect query parameter [{str(receiver.get('cursor_query_parameter') or 'Last-Event-ID header')}]",
|
|
1920
|
-
f"Webhook signing secret [{secret_source('webhook_secret', 'stored_webhook_secret')}]",
|
|
1921
|
-
f"SSE authorization [{secret_source('authorization', 'stored_authorization')}]",
|
|
1922
|
-
f"Webhook endpoint [{ROUTER_BASE}/ca/events/webhooks/default]",
|
|
1923
|
-
"Back",
|
|
1924
|
-
]
|
|
1925
|
-
return rows, ["enabled", "transport", "url", "__info__", "event_types", "cursor_json_pointer", "cursor_query_parameter",
|
|
1926
|
-
"webhook_secret", "authorization", "__info__", "back"]
|
|
1914
|
+
return project_external_event_panel_rows(external_event_receiver_service(), ROUTER_BASE)
|
|
1927
1915
|
|
|
1928
1916
|
def set_external_event_config(key: str, value: Any) -> list[str]:
|
|
1929
|
-
|
|
1930
|
-
current = service.receiver_configs().get("default", {})
|
|
1931
|
-
body: dict[str, Any] = {
|
|
1932
|
-
"enabled": bool(current.get("enabled", False)),
|
|
1933
|
-
"transport": str(current.get("transport") or "webhook"),
|
|
1934
|
-
"url": str(current.get("url") or ""),
|
|
1935
|
-
"event_types": current.get("event_types") if isinstance(current.get("event_types"), list) else [],
|
|
1936
|
-
"cursor_json_pointer": str(current.get("cursor_json_pointer") or ""),
|
|
1937
|
-
"cursor_query_parameter": str(current.get("cursor_query_parameter") or ""),
|
|
1938
|
-
}
|
|
1939
|
-
if key == "enabled":
|
|
1940
|
-
body["enabled"] = not body["enabled"]
|
|
1941
|
-
elif key == "transport":
|
|
1942
|
-
body["transport"] = "sse" if body["transport"] == "webhook" else "webhook"
|
|
1943
|
-
elif key == "event_types":
|
|
1944
|
-
body["event_types"] = [part.strip() for part in str(value or "").split(",") if part.strip()]
|
|
1945
|
-
elif key in {"url", "cursor_json_pointer", "cursor_query_parameter", "webhook_secret", "authorization"}:
|
|
1946
|
-
body[key] = str(value or "")
|
|
1947
|
-
else:
|
|
1948
|
-
raise ValueError(f"unsupported external event option: {key}")
|
|
1949
|
-
updated = service.save_receiver("default", body)
|
|
1950
|
-
return [
|
|
1951
|
-
f"External event receiver updated: enabled={updated.get('enabled')} transport={updated.get('transport')}.",
|
|
1952
|
-
"The router owns receiver connections; the prelaunch configuration process does not open a duplicate stream.",
|
|
1953
|
-
"External events use the private Runtime Input Gateway and are never published to Web Chat.",
|
|
1954
|
-
]
|
|
1917
|
+
return project_set_external_event_config(external_event_receiver_service(), key, value)
|
|
1955
1918
|
|
|
1956
1919
|
def remote_instruction_synchronizer() -> RemoteInstructionSynchronizer: return RemoteInstructionSynchronizer(load_config=load_config, workspace=lambda: Path(ROUTER_WORKSPACE), state_dir=WORKSPACE_STATE_DIR, log=router_log)
|
|
1957
1920
|
def remote_memory_synchronizer() -> RemoteMemorySynchronizer: return RemoteMemorySynchronizer(load_config=load_config, workspace=lambda: Path(ROUTER_WORKSPACE), state_dir=WORKSPACE_STATE_DIR, log=router_log)
|
|
@@ -1977,7 +1940,7 @@ def set_remote_instruction_config(key: str, value: Any) -> list[str]:
|
|
|
1977
1940
|
remote[key] = max(1, min(30, int(str(value).strip())))
|
|
1978
1941
|
except ValueError:
|
|
1979
1942
|
return ["HTTP timeout must be a whole number from 1 to 30 seconds."]
|
|
1980
|
-
elif key in {"claude_url", "codex_url", "agy_url", "kimi_url", "grok_url"}:
|
|
1943
|
+
elif key in {"claude_url", "codex_url", "agy_url", "kimi_url", "grok_url", "muse_url"}:
|
|
1981
1944
|
url = str(value or "").strip()
|
|
1982
1945
|
if url:
|
|
1983
1946
|
parsed = urllib.parse.urlparse(url)
|
|
@@ -1989,7 +1952,7 @@ def set_remote_instruction_config(key: str, value: Any) -> list[str]:
|
|
|
1989
1952
|
elif key == "sync":
|
|
1990
1953
|
results = [
|
|
1991
1954
|
sync_remote_instruction(runtime, reason="manual")
|
|
1992
|
-
for runtime in ("claude", "codex", "agy", "kimi", "grok")
|
|
1955
|
+
for runtime in ("claude", "codex", "agy", "kimi", "grok", "muse")
|
|
1993
1956
|
]
|
|
1994
1957
|
visible = [result for result in results if result.status != "not-configured"]
|
|
1995
1958
|
return [
|
|
@@ -2110,6 +2073,7 @@ def _channel_mcp_tool_call_response(request_id: Any, params: dict[str, Any]) ->
|
|
|
2110
2073
|
handle_llm_options=handle_live_llm_options_action,
|
|
2111
2074
|
read_runtime_inputs=read_runtime_inputs,
|
|
2112
2075
|
telemetry_logs=_TELEMETRY_LOG_RUNTIME.tool,
|
|
2076
|
+
submit_input=runtime_input_gateway().submit_stream_input,
|
|
2113
2077
|
),
|
|
2114
2078
|
)
|
|
2115
2079
|
|
|
@@ -2133,7 +2097,15 @@ def _first_param(params: dict[str, list[str]], name: str, default: str = "") ->
|
|
|
2133
2097
|
def chat_http_controller() -> ChatHttpController:
|
|
2134
2098
|
return ChatHttpController(
|
|
2135
2099
|
router_base=ROUTER_BASE,
|
|
2136
|
-
reads=ChatHttpReadServices(
|
|
2100
|
+
reads=ChatHttpReadServices(
|
|
2101
|
+
read_chat_messages,
|
|
2102
|
+
read_chat_messages_before,
|
|
2103
|
+
_CHAT_CONDITION,
|
|
2104
|
+
_safe_segment,
|
|
2105
|
+
CHAT_FILES_DIR,
|
|
2106
|
+
_RUNTIME_INPUT_STATUS_REPOSITORY.get,
|
|
2107
|
+
_RUNTIME_INPUT_STATUS_REPOSITORY.list_latest,
|
|
2108
|
+
),
|
|
2137
2109
|
writes=ChatHttpWriteServices(
|
|
2138
2110
|
write_json,
|
|
2139
2111
|
append_chat_message,
|
|
@@ -2141,6 +2113,7 @@ def chat_http_controller() -> ChatHttpController:
|
|
|
2141
2113
|
runtime_input_gateway().submit_web_chat,
|
|
2142
2114
|
runtime_input_gateway().submit_notification,
|
|
2143
2115
|
runtime_input_gateway().submit_tty,
|
|
2116
|
+
_default_channel_input_transport,
|
|
2144
2117
|
),
|
|
2145
2118
|
)
|
|
2146
2119
|
|
|
@@ -2990,6 +2963,22 @@ def _router_server_context() -> RouterServerContext:
|
|
|
2990
2963
|
external_event_receiver_service().start(), _TELEMETRY_LOG_RUNTIME.start(), usage_services.start()
|
|
2991
2964
|
def stop_router_services() -> None:
|
|
2992
2965
|
usage_services.stop(), _TELEMETRY_LOG_RUNTIME.stop(), external_event_receiver_service().stop()
|
|
2966
|
+
provider_files = ProviderFilesProxy(
|
|
2967
|
+
ProviderFilesProxyPorts(
|
|
2968
|
+
current_provider=get_current_provider,
|
|
2969
|
+
bridge_enabled=_REMOTE_BRIDGE.enabled,
|
|
2970
|
+
bridge_is_request=lambda handler, cfg: _ROUTER_ACCESS_POLICY.remote_bridge_request(handler, cfg, remote_bridge_access_token),
|
|
2971
|
+
bridge_resolve=_REMOTE_BRIDGE.resolve,
|
|
2972
|
+
upstream_base=provider_upstream_request_base,
|
|
2973
|
+
join_url=join_url,
|
|
2974
|
+
headers=provider_headers,
|
|
2975
|
+
urlopen=provider_urlopen,
|
|
2976
|
+
timeout_seconds=provider_request_timeout_seconds,
|
|
2977
|
+
copy_response_headers=_copy_upstream_response_headers,
|
|
2978
|
+
write_json=write_json,
|
|
2979
|
+
log=router_log,
|
|
2980
|
+
)
|
|
2981
|
+
)
|
|
2993
2982
|
http_services = RouterHttpServices(
|
|
2994
2983
|
core=RouterHttpCore(load_config, reject_external_router_request, get_current_provider, parse_json_body, is_client_disconnect_error, router_log, observe_tui_runtime_response, router_request_body_policy(), RouterHttpRemoteBridge(_REMOTE_BRIDGE.enabled, _REMOTE_BRIDGE.resolve, _REMOTE_BRIDGE.status_payload, lambda handler, cfg: _ROUTER_ACCESS_POLICY.remote_bridge_request(handler, cfg, remote_bridge_access_token))),
|
|
2995
2984
|
get=RouterHttpGetEndpoints(handle_tui_observation_get, handle_observability_get, handle_llm_config_get, lambda _handler, _path: False, handle_web_get,
|
|
@@ -2999,6 +2988,7 @@ def _router_server_context() -> RouterServerContext:
|
|
|
2999
2988
|
handle_plan_post, route_runtime_post, handle_external_event_raw_post, handle_external_event_config_post, handle_usage_post, telemetry_raw=_TELEMETRY_LOG_RUNTIME.http.post),
|
|
3000
2989
|
presentation=RouterHttpPresentation(render_router_home_html, router_health_payload, write_text_response, write_json, list_model_objects_for_request, resolve_requested_model, model_object, _REMOTE_BRIDGE.model_objects),
|
|
3001
2990
|
errors=RouterHttpErrors(write_openai_responses_error, try_write_json),
|
|
2991
|
+
files=RouterHttpFileEndpoints(provider_files.get, provider_files.post, provider_files.delete),
|
|
3002
2992
|
)
|
|
3003
2993
|
server_runtime = router_server_runtime.RouterServerRuntime(
|
|
3004
2994
|
router_server_runtime.RouterServerConfig(ROUTER_INSTANCE_DIR, PID_PATH, ROUTER_PORT, ROUTER_BASE, LOG_LEVEL_PATH, LOG_LEVEL_NAMES, RouterHandler),
|
|
@@ -3160,7 +3150,7 @@ portable_language_menu = _CONFIGURATION_CLI_API.portable_language_menu
|
|
|
3160
3150
|
|
|
3161
3151
|
def credential_cli_controller() -> CredentialCliController:
|
|
3162
3152
|
return CredentialCliController(
|
|
3163
|
-
policy=CredentialCliPolicy(frozenset({"anthropic", "ollama-cloud", "deepseek", "opencode", "opencode-go", "kimi", "nvidia-hosted", "openrouter", "fireworks", "zai", "zai-api", "zai-coding-plan", "zai-start-plan"})),
|
|
3153
|
+
policy=CredentialCliPolicy(frozenset({"anthropic", "ollama-cloud", "deepseek", "opencode", "opencode-go", "kimi", "meta", "nvidia-hosted", "openrouter", "fireworks", "zai", "zai-api", "zai-coding-plan", "zai-start-plan"})),
|
|
3164
3154
|
ports=CredentialCliPorts(normalize_provider, load_config, provider_api_key_count, provider_primary_api_key, mask_secret, secret_fingerprint,
|
|
3165
3155
|
api_key_clear_requested, clear_api_key_config, store_api_key_input_config, store_api_keys_config),
|
|
3166
3156
|
io=CredentialCliIO(sys.stdin.isatty, getpass.getpass, print),
|
|
@@ -3238,7 +3228,7 @@ def cmd_ollama_native(args: argparse.Namespace) -> None: provider_option_cli_con
|
|
|
3238
3228
|
def provider_option_policy() -> ProviderOptionPolicy: return ProviderOptionPolicy(normalize_claude_code_supported_capabilities, normalize_ip_family, normalize_model_id, normalize_opencode_endpoint_kind, parse_bool, parse_config_value, positive_int, ProviderSamplingPolicy())
|
|
3239
3229
|
def apply_ollama_option(pcfg: dict[str, Any], token: str) -> None: mutate_ollama_option(pcfg, token, policy=provider_option_policy())
|
|
3240
3230
|
def cmd_ollama_options(args: argparse.Namespace) -> None: provider_option_cli_controller().ollama_options(args)
|
|
3241
|
-
PROVIDER_OPTION_PROVIDERS = ("anthropic", "agy", "codex", "vllm", "lm-studio", "nvidia-hosted", "self-hosted-nim", "ollama", "ollama-cloud", "deepseek", "opencode", "opencode-go", "kimi", "openrouter", "fireworks", "zai", "zai-api", "zai-coding-plan", "zai-start-plan")
|
|
3231
|
+
PROVIDER_OPTION_PROVIDERS = ("anthropic", "agy", "codex", "vllm", "lm-studio", "nvidia-hosted", "self-hosted-nim", "ollama", "ollama-cloud", "deepseek", "opencode", "opencode-go", "kimi", "meta", "openrouter", "fireworks", "zai", "zai-api", "zai-coding-plan", "zai-start-plan")
|
|
3242
3232
|
PROVIDER_SAMPLING_OPTION_PROVIDERS = ("vllm", "lm-studio", "nvidia-hosted", "self-hosted-nim", "openrouter")
|
|
3243
3233
|
PROVIDER_SAMPLING_OPTIONS = ("temperature", "top_p", "top_k")
|
|
3244
3234
|
def sampling_option_key(key: str) -> str | None: return ProviderSamplingPolicy().option_key(key)
|
|
@@ -4023,6 +4013,27 @@ _ZCODE_RUNTIME_API = ZcodeRuntimeCompatibilityApi(zcode_runtime_context)
|
|
|
4023
4013
|
def install_zcode_if_missing() -> str: return _ZCODE_RUNTIME_API.install_if_missing()
|
|
4024
4014
|
def launch_zcode(passthrough: list[str] | None = None, **_kwargs: Any) -> int: return _ZCODE_RUNTIME_API.launch(list(passthrough or []))
|
|
4025
4015
|
launch_zcode = SynchronizedLaunch(launch_zcode, sync_remote_launch_assets, "zcode")
|
|
4016
|
+
|
|
4017
|
+
def muse_runtime_context() -> MuseRuntimeContext:
|
|
4018
|
+
return MuseRuntimeContext(
|
|
4019
|
+
process=MuseProcessPorts(find_executable, subprocess.run, subprocess.call, print, os.environ, path_with_ciel_runtime_user_dirs, os.name),
|
|
4020
|
+
config=MuseConfigurationPorts(load_config, get_current_provider),
|
|
4021
|
+
lifecycle=MuseLifecyclePorts(
|
|
4022
|
+
materialize_runtime_command,
|
|
4023
|
+
start_router_if_needed,
|
|
4024
|
+
run_with_router_lifetime,
|
|
4025
|
+
subprocess_call_with_channel_wake_proxy,
|
|
4026
|
+
channel_delivery_mode,
|
|
4027
|
+
runtime_launch.web_backend_start_requested,
|
|
4028
|
+
lambda provider, model: record_launch_state_for_cwd(current_launch_cwd_key(), provider, "muse-native-subscription", model),
|
|
4029
|
+
_set_channel_transcript_scope,
|
|
4030
|
+
),
|
|
4031
|
+
)
|
|
4032
|
+
|
|
4033
|
+
_MUSE_RUNTIME_API = MuseRuntimeCompatibilityApi(muse_runtime_context)
|
|
4034
|
+
def install_muse_if_missing(): return _MUSE_RUNTIME_API.install_if_missing()
|
|
4035
|
+
def launch_muse(passthrough: list[str] | None = None, **_kwargs: Any) -> int: return _MUSE_RUNTIME_API.launch(list(passthrough or []))
|
|
4036
|
+
launch_muse = SynchronizedLaunch(launch_muse, sync_remote_launch_assets, "muse")
|
|
4026
4037
|
enable_ansi = enable_terminal_ansi
|
|
4027
4038
|
ansi = render_ansi
|
|
4028
4039
|
animated_ansi_text = render_animated_ansi_text
|
|
@@ -4135,7 +4146,7 @@ def portable_prelaunch_menu(passthrough: list[str] | None = None) -> int:
|
|
|
4135
4146
|
config=prelaunch.PrelaunchConfig(clear_model_cache, current_provider_panel_choice, default_base_url, get_current_provider, load_config, preflight_lines,
|
|
4136
4147
|
provider_menu_label, save_config, settings_ready_except_api_key, read_model_list_cache),
|
|
4137
4148
|
launch_policy=prelaunch.PrelaunchLaunchPolicy(agy_launch_enabled_for_provider, claude_launch_enabled_for_provider, codex_launch_enabled_for_provider,
|
|
4138
|
-
launch_blockers_require_api_key, launch_readiness_errors, launch_kimi, launch_grok, launch_zcode),
|
|
4149
|
+
launch_blockers_require_api_key, launch_readiness_errors, launch_kimi, launch_grok, launch_zcode, launch_muse),
|
|
4139
4150
|
panel_rows=prelaunch.PrelaunchPanelRows(advisor_model_panel_rows, api_key_panel_rows, base_url_panel_rows, context_setup_panel_rows, language_panel_rows,
|
|
4140
4151
|
llm_option_panel_rows, llm_preset_panel_rows, log_level_panel_rows, model_panel_rows, provider_panel_rows),
|
|
4141
4152
|
mutations=prelaunch.PrelaunchMutations(apply_context_setup_config, apply_llm_preset_config, apply_timeout_profile_to_provider,
|
|
@@ -4342,6 +4353,8 @@ def should_use_channel_stdin_proxy(use_router_mode: bool, passthrough: list[str]
|
|
|
4342
4353
|
return False
|
|
4343
4354
|
claude_config = cfg.get("claude_code") if isinstance(cfg, dict) else {}
|
|
4344
4355
|
return not (isinstance(claude_config, dict) and claude_config.get("web_chat_session_bridge") is False)
|
|
4356
|
+
_CLAUDE_SESSION_SOCKET = ClaudeSessionSocketClient(HOME, router_log)
|
|
4357
|
+
def _default_channel_input_transport() -> str: return "session_socket"
|
|
4345
4358
|
def _channel_pending_scan_limit() -> int: return channel_runtime_environment_policy().pending_scan_limit()
|
|
4346
4359
|
def _channel_stdin_wake_batch_limit() -> int: return channel_runtime_environment_policy().wake_batch_limit()
|
|
4347
4360
|
_CHANNEL_LLM_TOOL_CONTEXT_LOCK = threading.Lock()
|
|
@@ -4417,9 +4430,9 @@ def channel_wake_context() -> ChannelWakeContext:
|
|
|
4417
4430
|
_channel_superseded_message_ids, _channel_message_is_web_chat_request, _channel_llm_message_skip_reason, _channel_message_event_identity_key,
|
|
4418
4431
|
_channel_stdin_wake_state_for_message, _channel_stdin_wake_queued_is_stale_for_message),
|
|
4419
4432
|
pending_delivery=ChannelPendingDeliveryPorts(format_channel_llm_delivery_wake_prompt, format_channel_visible_llm_delivery_wake_prompt, format_channel_web_chat_wake_batch_prompt, format_channel_wake_batch_prompt, _channel_enter_label,
|
|
4420
|
-
_channel_wake_store_release_stale, _CHANNEL_WAKE_DELIVERY_REPOSITORY
|
|
4421
|
-
|
|
4422
|
-
pending_io=ChannelPendingIoPorts(_CHANNEL_STDIN_INJECT_LOCK, read_runtime_inputs, _write_channel_wake_prompt, _read_channel_compact_request, _clear_channel_compact_request, _runtime_input_storage_path(), router_log),
|
|
4433
|
+
_channel_wake_store_release_stale, _CHANNEL_WAKE_DELIVERY_REPOSITORY,
|
|
4434
|
+
_commit_channel_llm_cursor_if_newer),
|
|
4435
|
+
pending_io=ChannelPendingIoPorts(_CHANNEL_STDIN_INJECT_LOCK, read_runtime_inputs, _write_channel_wake_prompt, _read_channel_compact_request, _clear_channel_compact_request, _runtime_input_storage_path(), router_log, _CLAUDE_SESSION_SOCKET.send),
|
|
4423
4436
|
pending_policy=ChannelPendingPolicyPorts(_channel_stdin_wake_batch_limit, time.time, lambda: channel_runtime_environment_policy().web_chat_replay_ttl_seconds(),
|
|
4424
4437
|
lambda message: runtime_input_repository().timestamp_seconds(message), _channel_message_is_web_chat_request),
|
|
4425
4438
|
)
|
|
@@ -4428,7 +4441,6 @@ def channel_wake_claim_repository() -> ChannelWakeClaimRepository: return channe
|
|
|
4428
4441
|
def _channel_stdin_wake_claim_prompt(message_id: int) -> str: return channel_wake_context().claim_prompt(message_id)
|
|
4429
4442
|
def _channel_stdin_claim_wake_prompt(message_id: int, prompt: str) -> bool: return channel_wake_context().claim_wake_prompt(message_id, prompt)
|
|
4430
4443
|
def _channel_stdin_clear_wake_claim(message_id: int) -> None: channel_wake_context().clear_wake_claim(message_id)
|
|
4431
|
-
def _channel_stdin_mark_body_fallback(message_id: int, reason: str) -> None: channel_wake_context().mark_wake_body_fallback(message_id, reason)
|
|
4432
4444
|
def _channel_prompt_references_message_id(text: str, message_id: int, prompt_texts: list[str] | tuple[str, ...] | None = None) -> bool: return channel_wake_context().prompt_references_message_id(text, message_id, prompt_texts)
|
|
4433
4445
|
def _channel_message_ids_already_in_request(body: dict[str, Any]) -> set[int]: return channel_wake_context().message_ids_already_in_request(body)
|
|
4434
4446
|
def _channel_llm_commit_cursor_locked(last_id: int) -> None: channel_wake_context().commit_cursor(last_id)
|
|
@@ -4445,9 +4457,6 @@ def _windows_channel_startup_grace_seconds() -> float:
|
|
|
4445
4457
|
"""Allow an interactive Windows TUI to begin reading console input."""
|
|
4446
4458
|
return channel_runtime_environment_policy().windows_startup_grace_seconds()
|
|
4447
4459
|
|
|
4448
|
-
def _windows_channel_wake_max_attempts() -> int:
|
|
4449
|
-
return channel_runtime_environment_policy().windows_wake_max_attempts()
|
|
4450
|
-
|
|
4451
4460
|
def _write_channel_wake_prompt( master_fd: int, prompt: str, enter_bytes: bytes | None = None, *, submit_retry_count: int = 1, confirm_submit: bool = False, bracketed_paste: bool = False, submit_delay_seconds: float | None = None, ) -> bool:
|
|
4452
4461
|
return channel_wake_context().write_prompt(
|
|
4453
4462
|
master_fd, prompt, enter_bytes, submit_retry_count=submit_retry_count,
|
|
@@ -4459,12 +4468,12 @@ def _write_channel_wake_prompt( master_fd: int, prompt: str, enter_bytes: bytes
|
|
|
4459
4468
|
_CHANNEL_TRANSCRIPT_CACHE: dict[str, Any] = {"checked_at": 0.0, "path": None}
|
|
4460
4469
|
_CHANNEL_TRANSCRIPT_SCOPE: dict[str, Any] = {
|
|
4461
4470
|
'runtime': '', 'started_at': 0.0, 'codex_home': None, 'cwd': None,
|
|
4462
|
-
'session_id': '', 'bound_path': None,
|
|
4471
|
+
'muse_home': None, 'session_id': '', 'bound_path': None,
|
|
4463
4472
|
}
|
|
4464
4473
|
_CHANNEL_STDIN_RECOVERY_CACHE: dict[str, Any] = {'checked_at': 0.0, 'last_id': None, 'marker': None, 'recovered_last_id': None}
|
|
4465
|
-
_TRANSCRIPT_DELIVERY_SERVICE = TranscriptDeltaDeliveryService(WORKSPACE_STATE_DIR / "transcript-event-cursors.json", ROUTER_WORKSPACE_ID, TranscriptDeliveryPorts(load_config, lambda: _latest_claude_transcript_path(ttl_seconds=0.5), lambda: dict(_CHANNEL_TRANSCRIPT_SCOPE), router_log))
|
|
4474
|
+
_TRANSCRIPT_DELIVERY_SERVICE = TranscriptDeltaDeliveryService(WORKSPACE_STATE_DIR / "transcript-event-cursors.json", ROUTER_WORKSPACE_ID, TranscriptDeliveryPorts(load_config, lambda: _latest_claude_transcript_path(ttl_seconds=0.5), lambda: dict(_CHANNEL_TRANSCRIPT_SCOPE), router_log, event_publish=EVENT_BUS.publish, event_recent=EVENT_BUS.recent))
|
|
4466
4475
|
def channel_transcript_repository() -> ChannelTranscriptRepository: return channel_wake_context().transcript_repository()
|
|
4467
|
-
def _set_channel_transcript_scope(runtime: str, *, started_at: float | None = None, codex_home: Path | None = None, cwd: Path | None = None, session_id: str | None = None) -> None: return (channel_wake_context().set_transcript_scope(runtime, started_at=started_at, codex_home=codex_home, cwd=cwd, session_id=session_id), _TRANSCRIPT_DELIVERY_SERVICE.start())[1]
|
|
4476
|
+
def _set_channel_transcript_scope(runtime: str, *, started_at: float | None = None, codex_home: Path | None = None, muse_home: Path | None = None, cwd: Path | None = None, session_id: str | None = None) -> None: return (channel_wake_context().set_transcript_scope(runtime, started_at=started_at, codex_home=codex_home, muse_home=muse_home, cwd=cwd, session_id=session_id), _TRANSCRIPT_DELIVERY_SERVICE.start())[1]
|
|
4468
4477
|
def _channel_transcript_roots() -> tuple[tuple[Path, str], ...]: return channel_wake_context().transcript_roots()
|
|
4469
4478
|
def _latest_claude_transcript_path(ttl_seconds: float = 2.0) -> Path | None: return channel_wake_context().latest_transcript_path(ttl_seconds)
|
|
4470
4479
|
_read_file_tail_text = ChannelTranscriptRepository.read_tail_text
|
|
@@ -4592,34 +4601,19 @@ def _open_windows_conpty(
|
|
|
4592
4601
|
return None
|
|
4593
4602
|
return WindowsConPtySession(cmd, env, log=log)
|
|
4594
4603
|
|
|
4595
|
-
def _write_windows_channel_body_fallback(writer: Any, message_id: int, enter_bytes: bytes) -> None:
|
|
4596
|
-
prompt = f"[ciel-runtime pending request-body input] id={int(message_id)}"
|
|
4597
|
-
channel_wake_context().write_prompt(
|
|
4598
|
-
writer,
|
|
4599
|
-
prompt,
|
|
4600
|
-
enter_bytes,
|
|
4601
|
-
submit_retry_count=1,
|
|
4602
|
-
confirm_submit=False,
|
|
4603
|
-
bracketed_paste=False,
|
|
4604
|
-
submit_delay_seconds=_channel_wake_submit_delay_seconds(),
|
|
4605
|
-
write_all=_write_fd_all,
|
|
4606
|
-
snapshot=_channel_current_tmux_pane_text,
|
|
4607
|
-
)
|
|
4608
|
-
|
|
4609
4604
|
def channel_terminal_context() -> ChannelTerminalContext:
|
|
4610
4605
|
return ChannelTerminalContext(
|
|
4611
4606
|
process=ChannelTerminalProcessPorts(subprocess.Popen, _write_codex_child_process_record, _terminate_recorded_child_process, _release_codex_child_process_record),
|
|
4612
4607
|
policy=ChannelTerminalPolicyPorts(ensure_channel_llm_delivery_cursor_initialized, _channel_wake_enter_bytes, _channel_enter_label,
|
|
4613
|
-
_channel_wake_enter_env_is_fixed, _channel_stdin_unseen_retry_seconds, _channel_stdin_inflight_is_stale, router_log,
|
|
4614
|
-
_windows_channel_wake_max_attempts),
|
|
4608
|
+
_channel_wake_enter_env_is_fixed, _channel_stdin_unseen_retry_seconds, _channel_stdin_inflight_is_stale, router_log),
|
|
4615
4609
|
polling=ChannelTerminalPollingPorts(_inject_pending_compact_request, _chat_messages_file_marker, _channel_stdin_should_check_pending,
|
|
4616
4610
|
_channel_stdin_active_tool_call, _channel_stdin_active_turn, _inject_pending_channel_messages, _channel_stdin_wake_state, channel_inflight_effects,
|
|
4617
|
-
|
|
4611
|
+
runtime_interactions.read),
|
|
4618
4612
|
io=ChannelTerminalIoPorts(_terminal_winsize_from_fd, _apply_pty_winsize, _write_fd_all, _TerminalMouseInputFilter,
|
|
4619
4613
|
_channel_synthetic_enter_bytes_from_user_input, _write_terminal_input_mode_reset),
|
|
4620
4614
|
windows=ChannelTerminalWindowsPorts(run_windows_channel_terminal_proxy, _reset_windows_terminal_input_modes,
|
|
4621
4615
|
_WindowsConsoleMouseInputGuard, _WindowsConsoleInputWriter, _windows_channel_startup_grace_seconds,
|
|
4622
|
-
_terminal_input_mode_reset_interval_seconds, _channel_stdin_active_turn,
|
|
4616
|
+
_terminal_input_mode_reset_interval_seconds, _channel_stdin_active_turn, time.sleep,
|
|
4623
4617
|
_open_windows_conpty),
|
|
4624
4618
|
dispatch_ports=ChannelTerminalDispatchPorts(os.name, sys.stdin.isatty, sys.stdout.isatty, subprocess.call,
|
|
4625
4619
|
lambda *args, **kwargs: subprocess_call_with_windows_console_wake_proxy(*args, **kwargs),
|
|
@@ -4738,6 +4732,8 @@ def claude_launch_services() -> runtime_launch.ClaudeLaunchServices:
|
|
|
4738
4732
|
_codex_channel_wake_submit_delay_seconds,
|
|
4739
4733
|
_codex_channel_wake_submit_retries,
|
|
4740
4734
|
_set_channel_transcript_scope,
|
|
4735
|
+
prepared_socket_path,
|
|
4736
|
+
_CLAUDE_SESSION_SOCKET.configure,
|
|
4741
4737
|
),
|
|
4742
4738
|
mcp_config=assembly.ClaudeLaunchMcpConfigPorts(
|
|
4743
4739
|
write_duckduckgo_mcp_config,
|
|
@@ -4938,7 +4934,7 @@ def cli_services() -> cli_dispatch.CliServices:
|
|
|
4938
4934
|
core=cli_dispatch.CliCore(VERSION, cli_usage, find_executable, get_current_provider, load_config, pop_headless_env_file_args,
|
|
4939
4935
|
portable_provider_menu, run_external_menu, run_quiet_upgrade_and_exit),
|
|
4940
4936
|
runtime=cli_dispatch.CliRuntime(agy_passthrough_has_command, codex_passthrough_has_command, last_launch_runtime, launch_agy, launch_claude,
|
|
4941
|
-
launch_codex, launch_codex_app_server, native_agy_enabled, native_codex_enabled, launch_grok, launch_zcode),
|
|
4937
|
+
launch_codex, launch_codex_app_server, native_agy_enabled, native_codex_enabled, launch_grok, launch_zcode, launch_muse),
|
|
4942
4938
|
provider_commands=cli_dispatch.CliProviderCommands(cmd_advisor_model, cmd_api_key, cmd_base_url, cmd_language, cmd_log_level, cmd_model,
|
|
4943
4939
|
cmd_models, cmd_provider, cmd_provider_options, cmd_set_api_key),
|
|
4944
4940
|
special_commands=cli_dispatch.CliSpecialCommands(cmd_ollama_catalog, cmd_ollama_native, cmd_ollama_options, cmd_web_fetch, cmd_web_search),
|
|
@@ -4948,7 +4944,7 @@ def cli_services() -> cli_dispatch.CliServices:
|
|
|
4948
4944
|
).services()
|
|
4949
4945
|
def cli_parser_services() -> cli_parser.CliParserServices:
|
|
4950
4946
|
return cli_assembly.CliParserAssembly(
|
|
4951
|
-
launch=cli_parser.CliParserLaunch(cmd_cli, cmd_launch, cmd_launch_codex, cmd_launch_codex_app_server, cmd_launch_agy, serve, cmd_remote_bridge, cmd_launch_grok, cmd_launch_zcode),
|
|
4947
|
+
launch=cli_parser.CliParserLaunch(cmd_cli, cmd_launch, cmd_launch_codex, cmd_launch_codex_app_server, cmd_launch_agy, serve, cmd_remote_bridge, cmd_launch_grok, cmd_launch_zcode, cmd_launch_muse),
|
|
4952
4948
|
runtime=cli_parser.CliParserRuntime(cmd_version, cmd_status, cmd_env, cmd_stop, cmd_test),
|
|
4953
4949
|
settings=cli_parser.CliParserSettings(cmd_language, cmd_web_search, cmd_web_fetch, cmd_log_level, *event_settings_cli.handlers(event_settings_cli.EventSettingsCliPorts(load_config, save_config, external_event_receiver_service, lambda: set_remote_instruction_config('sync', ''), sync_all_remote_memories, print, lambda: USAGE_API_KEYS))),
|
|
4954
4950
|
provider=cli_parser.CliParserProvider(cmd_ollama_native, cmd_ollama_options, cmd_provider_options, cmd_ollama_catalog, cmd_provider,
|
|
@@ -4959,7 +4955,8 @@ def cli_parser_services() -> cli_parser.CliParserServices:
|
|
|
4959
4955
|
def cli_application_context() -> CliApplicationContext:
|
|
4960
4956
|
return CliApplicationContext(
|
|
4961
4957
|
dispatch=CliApplicationDispatchPorts(dispatch_cli, cli_services, launch_claude, launch_codex, launch_codex_app_server,
|
|
4962
|
-
launch_agy, launch_kimi, run_kimi_oauth_login,
|
|
4958
|
+
launch_agy, launch_kimi, run_kimi_oauth_login,
|
|
4959
|
+
{"grok": launch_grok, "zcode": launch_zcode, "muse": launch_muse}),
|
|
4963
4960
|
presentation=CliApplicationPresentationPorts(build_cli_parser, cli_parser_services, VERSION, print, lambda: sys.argv),
|
|
4964
4961
|
)
|
|
4965
4962
|
|
|
@@ -4973,6 +4970,7 @@ cmd_launch_codex_app_server = _CLI_APPLICATION_API.cmd_launch_codex_app_server
|
|
|
4973
4970
|
cmd_launch_agy = _CLI_APPLICATION_API.cmd_launch_agy
|
|
4974
4971
|
cmd_launch_grok = _CLI_APPLICATION_API.cmd_launch_grok
|
|
4975
4972
|
cmd_launch_zcode = _CLI_APPLICATION_API.cmd_launch_zcode
|
|
4973
|
+
cmd_launch_muse = _CLI_APPLICATION_API.cmd_launch_muse
|
|
4976
4974
|
cmd_version = _CLI_APPLICATION_API.cmd_version
|
|
4977
4975
|
main = _CLI_APPLICATION_API.main
|
|
4978
4976
|
|
|
@@ -18,15 +18,32 @@ SUPPORTED_CAPABILITIES = (
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
def model_family(model_id: str) -> str:
|
|
21
|
-
model = (model_id or "").strip().lower()
|
|
21
|
+
model = re.sub(r"\[1m\]$", "", (model_id or "").strip().lower())
|
|
22
22
|
for family in ("fable", "mythos", "opus", "sonnet", "haiku"):
|
|
23
23
|
if re.search(rf"(?:^|-)claude-(?:\d+(?:-\d+){{0,2}}-)?{family}(?:-|$)", model) or f"-{family}-" in model:
|
|
24
24
|
return family
|
|
25
25
|
return "claude"
|
|
26
26
|
|
|
27
27
|
|
|
28
|
+
def defaults_to_one_million_context(model_id: str) -> bool:
|
|
29
|
+
"""Return whether Anthropic documents 1M as this model's default context."""
|
|
30
|
+
|
|
31
|
+
model = re.sub(r"\[1m\]$", "", (model_id or "").strip().lower())
|
|
32
|
+
return bool(
|
|
33
|
+
re.search(
|
|
34
|
+
r"(?:^|-)(?:"
|
|
35
|
+
r"fable-5(?:-1)?|"
|
|
36
|
+
r"mythos-(?:5(?:-1)?|preview)|"
|
|
37
|
+
r"opus-(?:5|4-[678])|"
|
|
38
|
+
r"sonnet-(?:5|4-6)"
|
|
39
|
+
r")(?:-|$)",
|
|
40
|
+
model,
|
|
41
|
+
)
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
|
|
28
45
|
def limit_hints(model_id: str) -> dict[str, Any]:
|
|
29
|
-
model = (model_id or "").strip().lower()
|
|
46
|
+
model = re.sub(r"\[1m\]$", "", (model_id or "").strip().lower())
|
|
30
47
|
family = model_family(model)
|
|
31
48
|
if family in ("fable", "mythos") or (
|
|
32
49
|
family == "opus" and re.search(r"(?:^|-)opus-(?:5|4-[678])(?:-|$)", model)
|
|
@@ -58,7 +75,7 @@ def limit_hints(model_id: str) -> dict[str, Any]:
|
|
|
58
75
|
|
|
59
76
|
|
|
60
77
|
def runtime_hints(model_id: str) -> dict[str, Any]:
|
|
61
|
-
model = (model_id or "").strip().lower()
|
|
78
|
+
model = re.sub(r"\[1m\]$", "", (model_id or "").strip().lower())
|
|
62
79
|
if model_family(model) in ("fable", "mythos"):
|
|
63
80
|
return {
|
|
64
81
|
"claude_code_default_effort": "high",
|
|
@@ -510,6 +510,11 @@ class ProviderAdapter(ABC):
|
|
|
510
510
|
del model_id
|
|
511
511
|
return False
|
|
512
512
|
|
|
513
|
+
def preserves_claude_context_suffix_in_alias(self) -> bool:
|
|
514
|
+
"""Whether ``[1m]`` remains a Claude-facing suffix after aliasing."""
|
|
515
|
+
|
|
516
|
+
return False
|
|
517
|
+
|
|
513
518
|
def display_model_name(self, model_id: str, provider_label: str) -> str:
|
|
514
519
|
"""Project a provider model id into the shared human-readable label."""
|
|
515
520
|
|