@oneciel-ai/ciel-runtime 0.2.37 → 0.2.38

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/CHANGELOG.md +78 -0
  2. package/README.md +5 -2
  3. package/ciel_runtime.py +94 -96
  4. package/ciel_runtime_support/anthropic_model_policy.py +20 -3
  5. package/ciel_runtime_support/architecture.py +5 -0
  6. package/ciel_runtime_support/channel_inflight.py +4 -4
  7. package/ciel_runtime_support/channel_injection.py +56 -1
  8. package/ciel_runtime_support/channel_mcp_tools.py +34 -0
  9. package/ciel_runtime_support/channel_message_policy.py +9 -1
  10. package/ciel_runtime_support/channel_message_prompt.py +23 -0
  11. package/ciel_runtime_support/channel_pending_injection.py +86 -32
  12. package/ciel_runtime_support/channel_pending_poll.py +6 -2
  13. package/ciel_runtime_support/channel_runtime_environment.py +0 -11
  14. package/ciel_runtime_support/channel_terminal_context.py +0 -6
  15. package/ciel_runtime_support/channel_terminal_proxy.py +3 -42
  16. package/ciel_runtime_support/channel_transcript_repository.py +16 -1
  17. package/ciel_runtime_support/channel_wake_claim_repository.py +0 -19
  18. package/ciel_runtime_support/channel_wake_context.py +6 -13
  19. package/ciel_runtime_support/channel_wake_delivery_repository.py +50 -0
  20. package/ciel_runtime_support/chat_http_controller.py +88 -5
  21. package/ciel_runtime_support/claude_environment.py +100 -3
  22. package/ciel_runtime_support/claude_launch_assembly.py +4 -0
  23. package/ciel_runtime_support/claude_session_socket.py +181 -0
  24. package/ciel_runtime_support/cli_application_context.py +18 -10
  25. package/ciel_runtime_support/cli_dispatch.py +19 -3
  26. package/ciel_runtime_support/cli_parser.py +2 -0
  27. package/ciel_runtime_support/cli_usage.py +3 -2
  28. package/ciel_runtime_support/codex_backend_context.py +8 -3
  29. package/ciel_runtime_support/codex_completion_gate.py +198 -0
  30. package/ciel_runtime_support/codex_turn_recovery.py +240 -83
  31. package/ciel_runtime_support/compatibility_protocol.py +5 -2
  32. package/ciel_runtime_support/config_migrations.py +79 -0
  33. package/ciel_runtime_support/config_repository.py +7 -0
  34. package/ciel_runtime_support/context_summary_policy.py +24 -4
  35. package/ciel_runtime_support/external_event_menu.py +107 -0
  36. package/ciel_runtime_support/external_event_receiver.py +19 -1
  37. package/ciel_runtime_support/launch_state.py +2 -0
  38. package/ciel_runtime_support/managed_tool_injection.py +33 -0
  39. package/ciel_runtime_support/muse_runtime_context.py +291 -0
  40. package/ciel_runtime_support/ollama_thinking.py +12 -26
  41. package/ciel_runtime_support/prelaunch.py +13 -0
  42. package/ciel_runtime_support/prelaunch_launch_panel.py +2 -1
  43. package/ciel_runtime_support/prompt_compaction.py +39 -0
  44. package/ciel_runtime_support/provider_files_proxy.py +248 -0
  45. package/ciel_runtime_support/provider_model_identity.py +10 -2
  46. package/ciel_runtime_support/provider_option_cli.py +1 -1
  47. package/ciel_runtime_support/provider_request_access.py +54 -1
  48. package/ciel_runtime_support/provider_responses_passthrough.py +152 -15
  49. package/ciel_runtime_support/providers/alibaba.py +34 -1
  50. package/ciel_runtime_support/providers/anthropic.py +18 -1
  51. package/ciel_runtime_support/providers/meta.py +252 -21
  52. package/ciel_runtime_support/pseudo_tool_parser.py +17 -1
  53. package/ciel_runtime_support/remote_bridge.py +4 -0
  54. package/ciel_runtime_support/remote_instructions.py +5 -0
  55. package/ciel_runtime_support/remote_memory.py +1 -1
  56. package/ciel_runtime_support/responses_cache_diagnostics.py +82 -0
  57. package/ciel_runtime_support/responses_custom_tool_bridge.py +282 -0
  58. package/ciel_runtime_support/responses_input_compatibility.py +19 -3
  59. package/ciel_runtime_support/router_http.py +301 -4
  60. package/ciel_runtime_support/router_observability_context.py +26 -0
  61. package/ciel_runtime_support/router_server_context.py +1 -0
  62. package/ciel_runtime_support/runtime_adapters.py +31 -0
  63. package/ciel_runtime_support/runtime_constants.py +23 -1
  64. package/ciel_runtime_support/runtime_input_gateway.py +85 -5
  65. package/ciel_runtime_support/runtime_input_status.py +150 -0
  66. package/ciel_runtime_support/runtime_launch.py +27 -4
  67. package/ciel_runtime_support/runtime_paths.py +1 -0
  68. package/ciel_runtime_support/speech_http_controller.py +3 -2
  69. package/ciel_runtime_support/streaming_anthropic.py +3 -0
  70. package/ciel_runtime_support/tool_call_events.py +98 -0
  71. package/ciel_runtime_support/transcript_delta_delivery.py +140 -1
  72. package/ciel_runtime_support/ui_text.py +1 -0
  73. package/ciel_runtime_support/web_search_result_events.py +130 -0
  74. package/ciel_runtime_support/web_ui.py +1 -0
  75. package/ciel_runtime_support/windows_conpty.py +92 -8
  76. package/ciel_runtime_support/workspace_mcp.py +4 -1
  77. package/ciel_runtime_support/workspace_state.py +1 -0
  78. package/docs/Configuration.md +20 -4
  79. package/docs/MCP-Channels.md +79 -6
  80. package/docs/Managed-Tool-Injection.md +25 -0
  81. package/docs/Module-Map.md +4 -0
  82. package/docs/Muse-Code.md +73 -0
  83. package/docs/Observability.md +39 -0
  84. package/docs/Providers.md +29 -2
  85. package/docs/Remote-Bridge.md +12 -0
  86. package/docs/Router.md +1 -0
  87. package/docs/journal/2026/09/01/diagnostics/anthropic/router/fable51-usage-credits.okf +70 -0
  88. package/docs/journal/2026/09/01/implementation/claude/session-socket/all-input-paths/default-delivery.okf +133 -0
  89. package/docs/journal/2026/09/01/implementation/claude/session-socket/windows-direct-input.okf +112 -0
  90. package/docs/journal/2026/09/02/diagnostics/cache/alibaba/qwen38-post-restart-hit-rate.okf +107 -0
  91. package/docs/journal/2026/09/02/diagnostics/cache/ollama-cloud/kimi-k3-codex-hit-rate.okf +91 -0
  92. package/docs/journal/2026/09/02/diagnostics/codex/tui/statusline-cache-metrics.okf +44 -0
  93. package/docs/journal/2026/09/02/diagnostics/input/transport/fallback-behavior.okf +31 -0
  94. package/docs/journal/2026/09/02/diagnostics/providers/ollama-cloud/kimi-k3-agent-turn-recovery.okf +125 -0
  95. package/docs/journal/2026/09/02/diagnostics/providers/ollama-cloud/kimi-k3-parameters.okf +128 -0
  96. package/docs/journal/2026/09/02/diagnostics/remote/mia/socket-tui-visibility.okf +47 -0
  97. package/docs/journal/2026/09/02/diagnostics/runtime/alibaba/token-plan/qwen38-latency.okf +108 -0
  98. package/docs/journal/2026/09/02/diagnostics/runtime/alibaba/token-plan/qwen38-vs-gpt56-latency.okf +92 -0
  99. package/docs/journal/2026/09/02/implementation/anthropic/context/one-million-defaults.okf +85 -0
  100. package/docs/journal/2026/09/02/implementation/cache/alibaba/qwen38-cache-hit-improvement.okf +104 -0
  101. package/docs/journal/2026/09/02/implementation/cache/alibaba/qwen38-cache-hit-improvement.png +0 -0
  102. package/docs/journal/2026/09/02/implementation/cache/alibaba/responses-session-cache.okf +97 -0
  103. package/docs/journal/2026/09/02/implementation/providers/alibaba/qwen38/0902-parameter-alignment.okf +97 -0
  104. package/docs/journal/2026/09/02/implementation/providers/meta/multimodal-tools/contributor-protocol-adoption.okf +140 -0
  105. package/docs/journal/2026/09/02/implementation/providers/meta/muse-spark-1.3-support.okf +53 -0
  106. package/docs/journal/2026/09/02/monitoring/cache/alibaba/cielarvis-qwen38-live-hit-rate.okf +858 -0
  107. package/docs/journal/2026/09/02/operations/release/main-merge-local-deploy.okf +36 -0
  108. package/docs/journal/2026/09/02/operations/release/nightly/local-cache-deployment.okf +54 -0
  109. package/docs/journal/2026/09/02/operations/release/nightly/ollama-kimi-recovery-model-audit-deployment.okf +58 -0
  110. package/docs/journal/2026/09/02/operations/release/nightly/qwen38-cache-improvement-deployment.okf +72 -0
  111. package/docs/journal/2026/09/02/research/cache/alibaba/qwen38-hit-rate-improvement.okf +233 -0
  112. package/docs/journal/2026/09/02/research/cache/codex/provider-scope.okf +77 -0
  113. package/docs/journal/2026/09/02/research/providers/ollama-cloud/desktop-model-exhaustive-audit.okf +159 -0
  114. package/docs/journal/2026/09/03/diagnostics/providers/meta/muse-spark-contributor-cache-hit.okf +148 -0
  115. package/docs/journal/2026/09/03/diagnostics/providers/meta/muse-spark-contributor-required-schema.okf +127 -0
  116. package/docs/journal/2026/09/03/diagnostics/providers/ollama-cloud/kimi-k3-resumed-session-stall.okf +160 -0
  117. package/docs/journal/2026/09/03/diagnostics/providers/ollama-cloud/kimi-k3-substantive-dangling-action.okf +94 -0
  118. package/docs/journal/2026/09/03/diagnostics/remote/kevin/codex-gpt-early-turn-completion.okf +162 -0
  119. package/docs/journal/2026/09/03/implementation/runtimes/meta/muse-code/default-yolo.okf +40 -0
  120. package/docs/journal/2026/09/03/implementation/runtimes/meta/muse-code/native-subscription-router.okf +86 -0
  121. package/docs/journal/2026/09/03/operations/deployment/local/session-socket-default-fallback.okf +41 -0
  122. package/docs/journal/2026/09/03/research/deployment/colab/tailscale/credential-storage.okf +41 -0
  123. package/docs/journal/2026/09/03/research/providers/meta/muse-code/subscription-billing-boundary.okf +64 -0
  124. package/docs/journal/2026/09/03/research/web-chat/voice/instruction-format.okf +135 -0
  125. package/docs/journal/2026/09/04/diagnostics/claude/context/early-auto-compaction.okf +75 -0
  126. package/docs/journal/2026/09/04/diagnostics/claude/context/fable-51-status-200k.okf +54 -0
  127. package/docs/journal/2026/09/04/diagnostics/runtime/codex/responses/replayed-item-id-validation.okf +74 -0
  128. package/docs/journal/2026/09/04/diagnostics/workspaces/onecieldmsui/codex/replay-stall.okf +100 -0
  129. package/docs/journal/2026/09/04/implementation/observability/tool-calls/websocket-stream.okf +49 -0
  130. package/docs/journal/2026/09/04/implementation/web-chat/input/raw-injection.okf +42 -0
  131. package/docs/journal/2026/09/05/diagnostics/tty/claude-raw-idle-render.okf +25 -0
  132. package/docs/journal/2026/09/05/implementation/events/search-response-urls.okf +23 -0
  133. package/docs/journal/2026/09/05/implementation/tools/native-injection.okf +19 -0
  134. package/docs/journal/2026/09/05/implementation/windows/conpty/prompt-delivery-lifecycle.okf +43 -0
  135. package/docs/journal/2026/09/05/release/nightly/conpty-native-tools.okf +13 -0
  136. package/docs/journal/2026/09/05/release/nightly/search-result-urls.okf +14 -0
  137. package/docs/journal/2026/09/06/implementation/codex/inherited-web-mcp.okf +22 -0
  138. package/docs/journal/2026/09/07/integration/main/nightly-merge.okf +13 -0
  139. package/docs/journal/2026/09/07/release/stable/0.2.38.okf +10 -0
  140. package/package.json +1 -1
@@ -12,7 +12,17 @@ from http.client import IncompleteRead
12
12
  from typing import Any, Callable, Mapping
13
13
 
14
14
  from .responses_usage_observer import ResponsesUsageObserver
15
+ from .responses_cache_diagnostics import (
16
+ cache_trace,
17
+ request_cache_profile,
18
+ usage_with_cache_profile,
19
+ )
15
20
  from .responses_input_compatibility import repair_replayed_response_items
21
+ from .responses_custom_tool_bridge import (
22
+ ResponsesCustomToolStreamProjector,
23
+ project_response_payload,
24
+ tool_definitions,
25
+ )
16
26
  from .remote_bridge import is_remote_bridge_request
17
27
  from .upstream_dump import dump_upstream_request
18
28
  from .upstream_error_policy import UpstreamStreamReadError
@@ -34,7 +44,7 @@ class ProviderResponsesPassthroughPorts:
34
44
  urlopen: Callable[..., Any]
35
45
  timeout_seconds: Callable[[dict[str, Any]], float]
36
46
  copy_response_headers: Callable[[Any, Any], None]
37
- record_usage: Callable[[str, str, dict[str, int]], None] = (
47
+ record_usage: Callable[[str, str, dict[str, Any]], None] = (
38
48
  lambda _provider, _model, _usage: None
39
49
  )
40
50
  log: Callable[[str, str], Any] = lambda _level, _message: None
@@ -73,6 +83,44 @@ class ProviderResponsesPassthrough:
73
83
  )
74
84
  return self._ports.join_url(self._ports.upstream_base(provider, config), path)
75
85
 
86
+ def _request_headers(
87
+ self,
88
+ provider: str,
89
+ config: dict[str, Any],
90
+ inbound_headers: Any,
91
+ body: Mapping[str, Any],
92
+ ) -> dict[str, str]:
93
+ headers = self._ports.headers(provider, config, inbound_headers)
94
+ if not config.get("responses_session_cache_requires_previous_response_id"):
95
+ return headers
96
+ if str(body.get("previous_response_id") or "").strip():
97
+ return headers
98
+ filtered = {
99
+ name: value
100
+ for name, value in headers.items()
101
+ if str(name).casefold() != "x-dashscope-session-cache"
102
+ }
103
+ if len(filtered) != len(headers):
104
+ self._ports.log(
105
+ "INFO",
106
+ "provider_responses_session_cache_deferred "
107
+ f"provider={provider} reason=missing_previous_response_id",
108
+ )
109
+ return filtered
110
+
111
+ @staticmethod
112
+ def _response_headers(headers: Any, *, transformed: bool) -> Any:
113
+ if not transformed:
114
+ return headers
115
+ try:
116
+ return {
117
+ key: value
118
+ for key, value in headers.items()
119
+ if str(key).casefold() != "content-length"
120
+ }
121
+ except (AttributeError, TypeError):
122
+ return headers
123
+
76
124
  def forward_compact(
77
125
  self,
78
126
  handler: Any,
@@ -90,11 +138,16 @@ class ProviderResponsesPassthrough:
90
138
  upstream_body = self._ports.finalize_body(upstream_body)
91
139
  data = self._encode(upstream_body)
92
140
  url = self._endpoint(provider, config, "openai_responses_compact")
93
- dump_upstream_request(url, data, self._ports.log)
141
+ request_headers = self._request_headers(
142
+ provider, config, handler.headers, upstream_body
143
+ )
144
+ dump_upstream_request(
145
+ url, data, self._ports.log, headers=request_headers
146
+ )
94
147
  request = urllib.request.Request(
95
148
  url,
96
149
  data=data,
97
- headers=self._ports.headers(provider, config, handler.headers),
150
+ headers=request_headers,
98
151
  method="POST",
99
152
  )
100
153
  with self._ports.urlopen(
@@ -168,6 +221,9 @@ class ProviderResponsesPassthrough:
168
221
  provider=provider,
169
222
  model=str(current.get("model") or ""),
170
223
  remote_bridge=remote_bridge,
224
+ stable_prefix_checkpoint_items=config.get(
225
+ "responses_cache_checkpoint_items", 0
226
+ ),
171
227
  )
172
228
  if not remote_bridge:
173
229
  compacted = self._ports.finalize_body(compacted)
@@ -228,6 +284,8 @@ class ProviderResponsesPassthrough:
228
284
  provider: str,
229
285
  config: dict[str, Any],
230
286
  upstream_body: dict[str, Any],
287
+ response_tools: Mapping[str, Mapping[str, Any]],
288
+ cache_profile: Mapping[str, Any],
231
289
  ) -> None:
232
290
  """Validate a native Responses stream before exposing it downstream."""
233
291
 
@@ -297,14 +355,33 @@ class ProviderResponsesPassthrough:
297
355
  ) from failure
298
356
 
299
357
  handler.send_response(getattr(response, "status", 200))
300
- self._ports.copy_response_headers(handler, response.headers)
358
+ self._ports.copy_response_headers(
359
+ handler,
360
+ self._response_headers(
361
+ response.headers, transformed=bool(response_tools)
362
+ ),
363
+ )
301
364
  handler.end_headers()
302
365
  spool.seek(0)
366
+ projector = (
367
+ ResponsesCustomToolStreamProjector(response_tools)
368
+ if response_tools
369
+ else None
370
+ )
303
371
  while chunk := spool.read(65_536):
304
- handler.wfile.write(chunk)
305
- handler.wfile.flush()
372
+ output = projector.feed(chunk) if projector is not None else chunk
373
+ if output:
374
+ handler.wfile.write(output)
375
+ handler.wfile.flush()
376
+ if projector is not None:
377
+ tail = projector.finish()
378
+ if tail:
379
+ handler.wfile.write(tail)
380
+ handler.wfile.flush()
306
381
  if observed:
307
- self._ports.record_usage(provider, model, observed)
382
+ observation = usage_with_cache_profile(observed, cache_profile)
383
+ self._ports.record_usage(provider, model, observation)
384
+ self._ports.log(*cache_trace(provider, model, observation))
308
385
  return
309
386
 
310
387
  def forward(
@@ -318,6 +395,11 @@ class ProviderResponsesPassthrough:
318
395
  upstream_body = dict(
319
396
  body if remote_bridge else repair_replayed_response_items(body)
320
397
  )
398
+ response_tools = (
399
+ tool_definitions(upstream_body)
400
+ if config.get("responses_custom_tools_as_functions")
401
+ else {}
402
+ )
321
403
  upstream_body["model"] = self._ports.normalize_model(
322
404
  provider, config, str(body.get("model") or "")
323
405
  )
@@ -340,11 +422,17 @@ class ProviderResponsesPassthrough:
340
422
  upstream_body,
341
423
  remote_bridge=remote_bridge,
342
424
  )
343
- dump_upstream_request(url, data, self._ports.log)
425
+ cache_profile = request_cache_profile(upstream_body, len(data))
426
+ request_headers = self._request_headers(
427
+ provider, config, handler.headers, upstream_body
428
+ )
429
+ dump_upstream_request(
430
+ url, data, self._ports.log, headers=request_headers
431
+ )
344
432
  request = urllib.request.Request(
345
433
  url,
346
434
  data=data,
347
- headers=self._ports.headers(provider, config, handler.headers),
435
+ headers=request_headers,
348
436
  method="POST",
349
437
  )
350
438
  if not remote_bridge and self._stream_truncation_retries(config):
@@ -354,6 +442,8 @@ class ProviderResponsesPassthrough:
354
442
  provider,
355
443
  config,
356
444
  upstream_body,
445
+ response_tools,
446
+ cache_profile,
357
447
  )
358
448
  return delivery_body
359
449
  with self._ports.urlopen(
@@ -365,21 +455,46 @@ class ProviderResponsesPassthrough:
365
455
  usage = ResponsesUsageObserver()
366
456
  received_bytes = 0
367
457
  handler.send_response(getattr(response, "status", 200))
368
- self._ports.copy_response_headers(handler, response.headers)
458
+ self._ports.copy_response_headers(
459
+ handler,
460
+ self._response_headers(
461
+ response.headers, transformed=bool(response_tools)
462
+ ),
463
+ )
369
464
  handler.end_headers()
465
+ projector = (
466
+ ResponsesCustomToolStreamProjector(response_tools)
467
+ if response_tools and bool(upstream_body.get("stream", True))
468
+ else None
469
+ )
470
+ response_body = bytearray()
370
471
  try:
371
472
  while chunk := response.read(65_536):
372
473
  received_bytes += len(chunk)
373
474
  usage.feed(chunk)
374
- handler.wfile.write(chunk)
375
- handler.wfile.flush()
475
+ if response_tools and projector is None:
476
+ response_body.extend(chunk)
477
+ continue
478
+ output = projector.feed(chunk) if projector is not None else chunk
479
+ if output:
480
+ handler.wfile.write(output)
481
+ handler.wfile.flush()
376
482
  except IncompleteRead as exc:
377
483
  partial = bytes(exc.partial or b"")
378
484
  if partial:
379
485
  received_bytes += len(partial)
380
486
  usage.feed(partial)
381
- handler.wfile.write(partial)
382
- handler.wfile.flush()
487
+ if response_tools and projector is None:
488
+ response_body.extend(partial)
489
+ else:
490
+ output = (
491
+ projector.feed(partial)
492
+ if projector is not None
493
+ else partial
494
+ )
495
+ if output:
496
+ handler.wfile.write(output)
497
+ handler.wfile.flush()
383
498
  usage.finish()
384
499
  if usage.terminal_event is None:
385
500
  self._ports.log(
@@ -403,6 +518,20 @@ class ProviderResponsesPassthrough:
403
518
  f"provider={provider} model={upstream_body.get('model')} "
404
519
  f"terminal={usage.terminal_event} bytes={received_bytes}",
405
520
  )
521
+ if projector is not None:
522
+ tail = projector.finish()
523
+ if tail:
524
+ handler.wfile.write(tail)
525
+ handler.wfile.flush()
526
+ elif response_tools:
527
+ try:
528
+ decoded = json.loads(response_body)
529
+ projected_body = project_response_payload(decoded, response_tools)
530
+ handler.wfile.write(self._encode(projected_body))
531
+ handler.wfile.flush()
532
+ except (UnicodeDecodeError, ValueError, TypeError):
533
+ handler.wfile.write(response_body)
534
+ handler.wfile.flush()
406
535
  observed = usage.finish()
407
536
  if bool(upstream_body.get("stream", True)) and usage.terminal_event is None:
408
537
  error = EOFError("upstream Responses stream ended without a terminal event")
@@ -422,10 +551,18 @@ class ProviderResponsesPassthrough:
422
551
  received_bytes=received_bytes,
423
552
  ) from error
424
553
  if observed and not remote_bridge:
554
+ observation = usage_with_cache_profile(observed, cache_profile)
425
555
  self._ports.record_usage(
426
556
  provider,
427
557
  str(upstream_body.get("model") or ""),
428
- observed,
558
+ observation,
559
+ )
560
+ self._ports.log(
561
+ *cache_trace(
562
+ provider,
563
+ str(upstream_body.get("model") or ""),
564
+ observation,
565
+ )
429
566
  )
430
567
  return delivery_body
431
568
 
@@ -19,6 +19,7 @@ from .base import HttpBearerProviderAdapter, provider_configuration
19
19
 
20
20
 
21
21
  QWEN38_MAX_MODEL = "qwen3.8-max"
22
+ QWEN38_MAX_SNAPSHOT_MODEL = "qwen3.8-max-0902"
22
23
  QWEN38_MAX_PREVIEW_MODEL = "qwen3.8-max-preview"
23
24
  QWEN38_CONTEXT_WINDOW = 1_000_000
24
25
  QWEN38_MAX_INPUT = 991_808
@@ -40,10 +41,15 @@ QWEN38_CODEX_CATALOG = {
40
41
  "experimental_supported_tools": [],
41
42
  "truncation_policy": {"mode": "bytes", "limit": 10_000},
42
43
  "supported_reasoning_levels": [
44
+ {"effort": "none", "description": "Disable reasoning"},
45
+ {"effort": "minimal", "description": "Minimal reasoning for fastest responses"},
43
46
  {"effort": "low", "description": "Fast responses with lighter reasoning"},
44
47
  {"effort": "medium", "description": "Greater reasoning depth for complex problems"},
48
+ {"effort": "high", "description": "High reasoning depth for complex problems"},
45
49
  {"effort": "xhigh", "description": "Extra high reasoning depth for complex problems"},
50
+ {"effort": "max", "description": "Maximum reasoning depth"},
46
51
  ],
52
+ "default_reasoning_level": "xhigh",
47
53
  }
48
54
  QWEN37_MAX_MODEL = "qwen3.7-max"
49
55
  QWEN37_CONTEXT_WINDOW = 1_000_000
@@ -84,6 +90,7 @@ ALIBABA_CODING_PLAN_MODELS = (
84
90
  )
85
91
  ALIBABA_MODEL_STUDIO_MODELS = (
86
92
  QWEN38_MAX_MODEL,
93
+ QWEN38_MAX_SNAPSHOT_MODEL,
87
94
  QWEN37_MAX_MODEL,
88
95
  "qwen3.7-plus",
89
96
  "qwen3.6-plus",
@@ -173,6 +180,11 @@ class AlibabaModelStudioProviderAdapter(HttpBearerProviderAdapter):
173
180
  effort_level="xhigh",
174
181
  explicit_cache=True,
175
182
  explicit_cache_markers=4,
183
+ protocol_headers={
184
+ "openai_responses": {
185
+ "x-dashscope-session-cache": "enable",
186
+ },
187
+ },
176
188
  haiku_model="qwen3.6-flash",
177
189
  opus_model=QWEN38_MAX_MODEL,
178
190
  sonnet_model="qwen3.7-plus",
@@ -204,6 +216,9 @@ class AlibabaModelStudioProviderAdapter(HttpBearerProviderAdapter):
204
216
  fallback_models=ALIBABA_MODEL_STUDIO_MODELS,
205
217
  allow_configured_fallback=True,
206
218
  authoritative_upstream_catalog=True,
219
+ supplemental_model_aliases=(
220
+ (QWEN38_MAX_MODEL, QWEN38_MAX_SNAPSHOT_MODEL),
221
+ ),
207
222
  )
208
223
  )
209
224
 
@@ -402,7 +417,7 @@ class AlibabaModelStudioProviderAdapter(HttpBearerProviderAdapter):
402
417
  projected = dict(reasoning)
403
418
  effort = str(projected.get("effort") or "xhigh").strip().lower()
404
419
  projected["effort"] = (
405
- cls._normalize_qwen38_effort(effort)
420
+ cls._normalize_qwen38_responses_effort(effort)
406
421
  if cls._is_qwen38(model)
407
422
  else effort if effort in _EFFORTS else "xhigh"
408
423
  )
@@ -505,6 +520,11 @@ class AlibabaModelStudioProviderAdapter(HttpBearerProviderAdapter):
505
520
  return "none"
506
521
  return "xhigh"
507
522
 
523
+ @staticmethod
524
+ def _normalize_qwen38_responses_effort(value: Any) -> str:
525
+ effort = str(value or "xhigh").strip().lower()
526
+ return effort if effort in _EFFORTS else "xhigh"
527
+
508
528
  @classmethod
509
529
  def _apply_explicit_cache_markers(
510
530
  cls, messages: list[Any], configured_limit: Any
@@ -687,11 +707,23 @@ class AlibabaTokenPlanProviderAdapter(AlibabaModelStudioProviderAdapter):
687
707
  codex_auto_compact_window=QWEN38_AUTO_COMPACT,
688
708
  request_timeout_ms=DEFAULT_REQUEST_TIMEOUT_MS,
689
709
  responses_stream_truncation_retries=1,
710
+ # Alibaba documents this header together with a response-id-linked
711
+ # session. Stateless Codex replay uses the model's implicit prefix
712
+ # cache until Ciel has a validated previous_response_id chain.
713
+ responses_session_cache_requires_previous_response_id=True,
714
+ # Keep the summarized Responses prefix byte-stable across several
715
+ # appended Codex tool turns so Alibaba can reuse its session cache.
716
+ responses_cache_checkpoint_items=24,
690
717
  stream_enabled=True,
691
718
  stream_word_chunking=False,
692
719
  effort_level="xhigh",
693
720
  explicit_cache=True,
694
721
  explicit_cache_markers=4,
722
+ protocol_headers={
723
+ "openai_responses": {
724
+ "x-dashscope-session-cache": "enable",
725
+ },
726
+ },
695
727
  haiku_model="qwen3.6-flash",
696
728
  opus_model=QWEN38_MAX_MODEL,
697
729
  sonnet_model="qwen3.7-plus",
@@ -765,6 +797,7 @@ __all__ = [
765
797
  "QWEN38_CONTEXT_WINDOW",
766
798
  "QWEN38_MAX_INPUT",
767
799
  "QWEN38_MAX_MODEL",
800
+ "QWEN38_MAX_SNAPSHOT_MODEL",
768
801
  "QWEN38_MAX_OUTPUT",
769
802
  "QWEN38_MAX_REASONING",
770
803
  "QWEN38_THINKING_MAX_INPUT",
@@ -3,6 +3,7 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  from dataclasses import dataclass, field
6
+ import re
6
7
  from typing import Any, Mapping
7
8
 
8
9
  from ..architecture import (
@@ -17,6 +18,7 @@ from ..architecture import (
17
18
  )
18
19
  from .base import NoAuthProviderAdapter, provider_configuration
19
20
  from .constants import PROVIDER_DEFAULT_BASE_URLS
21
+ from ..runtime_constants import ANTHROPIC_ONE_MILLION_MODEL_IDS
20
22
 
21
23
 
22
24
  @dataclass(frozen=True)
@@ -25,7 +27,9 @@ class AnthropicProviderAdapter(NoAuthProviderAdapter):
25
27
  base_url: str = PROVIDER_DEFAULT_BASE_URLS["anthropic"]
26
28
  configuration_defaults_value: dict = field(
27
29
  default_factory=lambda: provider_configuration(
28
- "claude-sonnet-4-6", route_through_router=False
30
+ "claude-opus-5[1m]",
31
+ custom_models=ANTHROPIC_ONE_MILLION_MODEL_IDS,
32
+ route_through_router=False,
29
33
  )
30
34
  )
31
35
  capabilities_value: ProviderCapabilities = field(
@@ -50,6 +54,19 @@ class AnthropicProviderAdapter(NoAuthProviderAdapter):
50
54
  default_factory=lambda: ProviderModelCatalogPolicy(kind="anthropic")
51
55
  )
52
56
 
57
+ def normalize_model_id(self, model_id: str) -> str:
58
+ text = str(model_id or "").strip()
59
+ base = re.sub(r"\[1m\]\s*$", "", text, flags=re.IGNORECASE).strip()
60
+ return f"{base}[1m]" if base and re.search(r"\[1m\]\s*$", text, re.IGNORECASE) else base
61
+
62
+ def upstream_api_model_id(self, model_id: str) -> str:
63
+ return re.sub(
64
+ r"\[1m\]\s*$", "", str(model_id or "").strip(), flags=re.IGNORECASE
65
+ ).strip()
66
+
67
+ def preserves_claude_context_suffix_in_alias(self) -> bool:
68
+ return True
69
+
53
70
  def advisor_panel_notice(
54
71
  self, config: ProviderConfig
55
72
  ) -> tuple[tuple[str, ...], tuple[str, ...]]: