llmshim 0.2.1__tar.gz → 0.2.2__tar.gz
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.
- {llmshim-0.2.1 → llmshim-0.2.2}/CLAUDE.md +1 -1
- {llmshim-0.2.1 → llmshim-0.2.2}/Cargo.lock +1 -1
- {llmshim-0.2.1 → llmshim-0.2.2}/Cargo.toml +1 -1
- {llmshim-0.2.1 → llmshim-0.2.2}/PKG-INFO +1 -1
- {llmshim-0.2.1 → llmshim-0.2.2}/docs/src/reference/request-fields.md +1 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/src/providers/anthropic.rs +17 -2
- {llmshim-0.2.1 → llmshim-0.2.2}/tests/integration_thinking.rs +31 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/tests/unit_anthropic.rs +91 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/.github/workflows/pages.yml +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/.github/workflows/release.yml +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/.gitignore +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/LICENSE +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/README.md +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/benchmarks/bench.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/benchmarks/bench_python.py +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/benchmarks/loadtest.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/docs/.gitignore +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/docs/book.toml +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/docs/mermaid-init.js +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/docs/mermaid.min.js +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/docs/src/SUMMARY.md +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/docs/src/concepts/contracts.md +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/docs/src/concepts/conversations.md +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/docs/src/concepts/portability.md +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/docs/src/concepts/routing.md +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/docs/src/concepts/translation-flow.md +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/docs/src/guides/fallbacks.md +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/docs/src/guides/images.md +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/docs/src/guides/native-controls.md +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/docs/src/guides/reasoning.md +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/docs/src/guides/streaming.md +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/docs/src/guides/tools.md +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/docs/src/introduction.md +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/docs/src/proxy/deployment.md +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/docs/src/proxy/http-api.md +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/docs/src/proxy/scaling.md +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/docs/src/reference/api.md +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/docs/src/reference/cli.md +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/docs/src/reference/configuration.md +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/docs/src/reference/errors.md +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/docs/src/reference/models.md +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/docs/src/reference/providers.md +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/docs/src/reference/surfaces.md +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/docs/src/start/choose.md +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/docs/src/start/cli.md +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/docs/src/start/clients.md +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/docs/src/start/configure.md +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/docs/src/start/proxy.md +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/docs/src/start/rust.md +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/examples/chat.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/examples/stream.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/llmshim/__init__.py +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/llmshim/_client.py +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/llmshim/_server.py +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/llmshim/types.py +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/pyproject.toml +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/src/client.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/src/config.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/src/env.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/src/error.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/src/fallback.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/src/lib.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/src/log.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/src/main.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/src/models.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/src/provider.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/src/providers/gemini.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/src/providers/mod.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/src/providers/openai.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/src/providers/xai.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/src/proxy/convert.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/src/proxy/error.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/src/proxy/handlers.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/src/proxy/mod.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/src/proxy/ratelimit.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/src/proxy/types.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/src/router.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/src/vision.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/tests/integration.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/tests/integration_fallback.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/tests/integration_gemini.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/tests/integration_gemini_tools.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/tests/integration_long_context.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/tests/integration_multimodel.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/tests/integration_proxy.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/tests/integration_tool_roundtrip.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/tests/integration_vision.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/tests/unit_fallback.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/tests/unit_fast_mode.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/tests/unit_gemini.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/tests/unit_log.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/tests/unit_models.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/tests/unit_multimodel.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/tests/unit_openai.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/tests/unit_proxy.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/tests/unit_proxy_convert.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/tests/unit_router.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/tests/unit_sse.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/tests/unit_tools.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/tests/unit_vision.rs +0 -0
- {llmshim-0.2.1 → llmshim-0.2.2}/tests/unit_xai.rs +0 -0
|
@@ -81,7 +81,7 @@ Callers pass provider-specific controls under these keys. Each provider copies w
|
|
|
81
81
|
|
|
82
82
|
### Unified reasoning controls
|
|
83
83
|
|
|
84
|
-
Two knobs work across every provider: `reasoning_effort` (`none|low|medium|high|xhigh|max`) and `reasoning_mode` (`standard|pro`). Each provider transform maps them to its native dialect, **clamping to the nearest tier the target model accepts** (all boundaries verified live — e.g. `max` is native only on OpenAI gpt-5.6; Anthropic 4.6 rejects `xhigh` but has `max`; Gemini's enum tops out at `high`; xAI grok-4.20 models reject any reasoning param). `mode: "pro"` is native on OpenAI gpt-5.6/-pro models (`reasoning.mode`), emulated as a one-tier effort bump elsewhere; explicit `none` always wins. Native passthrough (`x-openai.reasoning`, `x-anthropic.thinking`, `x-gemini.thinkingConfig`) bypasses the mapping entirely and always takes precedence. **Full per-provider mapping tables: `docs/src/guides/reasoning.md`** — update it and the pinning tests in `tests/unit_*.rs` together whenever a mapping changes.
|
|
84
|
+
Two knobs work across every provider: `reasoning_effort` (`none|low|medium|high|xhigh|max`) and `reasoning_mode` (`standard|pro`). A third, `reasoning_summary` (`auto|none`), controls reasoning-text visibility → Anthropic `thinking.display` (`auto`→`summarized`, the default when `reasoning_effort` is present so newer models like Sonnet 5 / Opus 4.7-4.8 return reasoning text instead of the API-default `omitted`; `none`→`omitted` for lower latency). Applies to both the adaptive and pre-4.6 enabled thinking builders; a caller-supplied `thinking` block bypasses it. Each provider transform maps them to its native dialect, **clamping to the nearest tier the target model accepts** (all boundaries verified live — e.g. `max` is native only on OpenAI gpt-5.6; Anthropic 4.6 rejects `xhigh` but has `max`; Gemini's enum tops out at `high`; xAI grok-4.20 models reject any reasoning param). `mode: "pro"` is native on OpenAI gpt-5.6/-pro models (`reasoning.mode`), emulated as a one-tier effort bump elsewhere; explicit `none` always wins. Native passthrough (`x-openai.reasoning`, `x-anthropic.thinking`, `x-gemini.thinkingConfig`) bypasses the mapping entirely and always takes precedence. **Full per-provider mapping tables: `docs/src/guides/reasoning.md`** — update it and the pinning tests in `tests/unit_*.rs` together whenever a mapping changes.
|
|
85
85
|
|
|
86
86
|
### Tool format translation
|
|
87
87
|
|
|
@@ -23,6 +23,7 @@ renamed or reshaped for the selected provider; unsupported controls are omitted.
|
|
|
23
23
|
| `stop` | array of strings | Conditional, mapped | Passed as `stop` to Anthropic or mapped to Gemini `stopSequences`; omitted by OpenAI/xAI |
|
|
24
24
|
| `reasoning_effort` | string | Portable, mapped/clamped | Unified effort from `none` through `max` |
|
|
25
25
|
| `reasoning_mode` | string | Portable, mapped/clamped | `standard` or `pro` |
|
|
26
|
+
| `reasoning_summary` | string | Anthropic (`auto`\|`none`) | Reasoning visibility → Anthropic `thinking.display`; `auto`→`summarized` (default with `reasoning_effort`), `none`→`omitted` for lower latency |
|
|
26
27
|
| `tools` | array | Portable, mapped | OpenAI Chat Completions function schema translated to native tools |
|
|
27
28
|
| `tool_choice` | string or object | Portable, mapped | Translated where the provider supports tool choice |
|
|
28
29
|
| `x-openai` | object | Native passthrough | Fields copied to an OpenAI Responses request |
|
|
@@ -603,6 +603,17 @@ impl Provider for Anthropic {
|
|
|
603
603
|
.unwrap_or(false);
|
|
604
604
|
let effort = normalize_unified_effort(effort, pro);
|
|
605
605
|
|
|
606
|
+
// Reasoning-summary visibility. Newer models (Sonnet 5, Opus
|
|
607
|
+
// 4.7/4.8, ...) default `display` to "omitted" — a signed but
|
|
608
|
+
// empty thinking block with no thinking_delta text. Default to
|
|
609
|
+
// "summarized" so reasoning text is returned consistently across
|
|
610
|
+
// model generations; a latency-sensitive caller opts back into
|
|
611
|
+
// "omitted" via reasoning_summary. Verified live 2026-07-17.
|
|
612
|
+
let display = match obj.get("reasoning_summary").and_then(|v| v.as_str()) {
|
|
613
|
+
Some("none") | Some("omitted") => "omitted",
|
|
614
|
+
_ => "summarized",
|
|
615
|
+
};
|
|
616
|
+
|
|
606
617
|
if effort == "none" {
|
|
607
618
|
if Self::uses_adaptive_thinking(model) {
|
|
608
619
|
// Adaptive models think by default even with no config;
|
|
@@ -612,7 +623,10 @@ impl Provider for Anthropic {
|
|
|
612
623
|
}
|
|
613
624
|
// Pre-4.6/Haiku: thinking is opt-in; omitting the key IS "none".
|
|
614
625
|
} else if Self::uses_adaptive_thinking(model) {
|
|
615
|
-
body_obj.insert(
|
|
626
|
+
body_obj.insert(
|
|
627
|
+
"thinking".to_string(),
|
|
628
|
+
json!({"type": "adaptive", "display": display}),
|
|
629
|
+
);
|
|
616
630
|
// Opus/Sonnet 4.6 reject "xhigh" (their tiers: low/medium/high/max);
|
|
617
631
|
// Opus 4.7/4.8 + Sonnet 5 accept the full low..max range (verified).
|
|
618
632
|
let anthropic_effort =
|
|
@@ -644,7 +658,8 @@ impl Provider for Anthropic {
|
|
|
644
658
|
"thinking".to_string(),
|
|
645
659
|
json!({
|
|
646
660
|
"type": "enabled",
|
|
647
|
-
"budget_tokens": budget
|
|
661
|
+
"budget_tokens": budget,
|
|
662
|
+
"display": display
|
|
648
663
|
}),
|
|
649
664
|
);
|
|
650
665
|
}
|
|
@@ -403,3 +403,34 @@ async fn anthropic_reasoning_roundtrip_accepted_live() {
|
|
|
403
403
|
assert!(!content.is_empty(), "expected a final answer, got: {resp2}");
|
|
404
404
|
println!("Round-trip accepted. Final answer: {content}");
|
|
405
405
|
}
|
|
406
|
+
|
|
407
|
+
#[tokio::test]
|
|
408
|
+
#[ignore]
|
|
409
|
+
async fn anthropic_sonnet5_reasoning_summary_default_returns_text_live() {
|
|
410
|
+
// Issue #37: sonnet-5 defaults display to "omitted" (empty thinking text).
|
|
411
|
+
// With the fix, reasoning_effort defaults display to "summarized" so real
|
|
412
|
+
// reasoning text comes back.
|
|
413
|
+
if std::env::var("ANTHROPIC_API_KEY").is_err() {
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
let router = router();
|
|
417
|
+
// A prompt that reliably engages adaptive thinking (trivial prompts may be
|
|
418
|
+
// answered directly even at high effort — "adaptive" means the model decides).
|
|
419
|
+
let prompt = "Prove or disprove: for every positive integer n, the value \
|
|
420
|
+
n^2 + n + 41 is prime. Give rigorous reasoning.";
|
|
421
|
+
let req = json!({
|
|
422
|
+
"model": "anthropic/claude-sonnet-5",
|
|
423
|
+
"messages": [{"role": "user", "content": prompt}],
|
|
424
|
+
"max_tokens": 4000,
|
|
425
|
+
"reasoning_effort": "high",
|
|
426
|
+
});
|
|
427
|
+
let resp = llmshim::completion(&router, &req).await.unwrap();
|
|
428
|
+
let reasoning = resp["choices"][0]["message"]["reasoning_content"]
|
|
429
|
+
.as_str()
|
|
430
|
+
.unwrap_or("");
|
|
431
|
+
assert!(
|
|
432
|
+
!reasoning.is_empty(),
|
|
433
|
+
"expected reasoning text by default (display=summarized), got empty. resp: {resp}"
|
|
434
|
+
);
|
|
435
|
+
println!("sonnet-5 reasoning text chars: {}", reasoning.len());
|
|
436
|
+
}
|
|
@@ -1753,3 +1753,94 @@ fn stream_redacted_thinking_block_start_emits() {
|
|
|
1753
1753
|
"blob-stream"
|
|
1754
1754
|
);
|
|
1755
1755
|
}
|
|
1756
|
+
|
|
1757
|
+
// ============================================================
|
|
1758
|
+
// Reasoning summary visibility (issue #37): thinking.display
|
|
1759
|
+
// ============================================================
|
|
1760
|
+
|
|
1761
|
+
#[test]
|
|
1762
|
+
fn adaptive_thinking_defaults_display_summarized() {
|
|
1763
|
+
let p = provider();
|
|
1764
|
+
let req = json!({
|
|
1765
|
+
"model": "claude-sonnet-5",
|
|
1766
|
+
"messages": [{"role": "user", "content": "hi"}],
|
|
1767
|
+
"reasoning_effort": "high",
|
|
1768
|
+
});
|
|
1769
|
+
let result = p.transform_request("claude-sonnet-5", &req).unwrap();
|
|
1770
|
+
assert_eq!(result.body["thinking"]["type"], "adaptive");
|
|
1771
|
+
assert_eq!(result.body["thinking"]["display"], "summarized");
|
|
1772
|
+
assert_eq!(result.body["output_config"]["effort"], "high");
|
|
1773
|
+
}
|
|
1774
|
+
|
|
1775
|
+
#[test]
|
|
1776
|
+
fn adaptive_thinking_reasoning_summary_none_omits() {
|
|
1777
|
+
let p = provider();
|
|
1778
|
+
let req = json!({
|
|
1779
|
+
"model": "claude-sonnet-5",
|
|
1780
|
+
"messages": [{"role": "user", "content": "hi"}],
|
|
1781
|
+
"reasoning_effort": "high",
|
|
1782
|
+
"reasoning_summary": "none",
|
|
1783
|
+
});
|
|
1784
|
+
let result = p.transform_request("claude-sonnet-5", &req).unwrap();
|
|
1785
|
+
assert_eq!(result.body["thinking"]["display"], "omitted");
|
|
1786
|
+
// The unified control must not leak into the API body.
|
|
1787
|
+
assert!(result.body.get("reasoning_summary").is_none());
|
|
1788
|
+
}
|
|
1789
|
+
|
|
1790
|
+
#[test]
|
|
1791
|
+
fn adaptive_thinking_reasoning_summary_auto_summarizes() {
|
|
1792
|
+
let p = provider();
|
|
1793
|
+
let req = json!({
|
|
1794
|
+
"model": "claude-opus-4-8",
|
|
1795
|
+
"messages": [{"role": "user", "content": "hi"}],
|
|
1796
|
+
"reasoning_effort": "medium",
|
|
1797
|
+
"reasoning_summary": "auto",
|
|
1798
|
+
});
|
|
1799
|
+
let result = p.transform_request("claude-opus-4-8", &req).unwrap();
|
|
1800
|
+
assert_eq!(result.body["thinking"]["display"], "summarized");
|
|
1801
|
+
}
|
|
1802
|
+
|
|
1803
|
+
#[test]
|
|
1804
|
+
fn enabled_thinking_forwards_display() {
|
|
1805
|
+
// Pre-4.6 / Haiku use the enabled-budget path; display is valid there too.
|
|
1806
|
+
let p = provider();
|
|
1807
|
+
let req = json!({
|
|
1808
|
+
"model": "claude-haiku-4-5-20251001",
|
|
1809
|
+
"messages": [{"role": "user", "content": "hi"}],
|
|
1810
|
+
"reasoning_effort": "high",
|
|
1811
|
+
});
|
|
1812
|
+
let result = p
|
|
1813
|
+
.transform_request("claude-haiku-4-5-20251001", &req)
|
|
1814
|
+
.unwrap();
|
|
1815
|
+
assert_eq!(result.body["thinking"]["type"], "enabled");
|
|
1816
|
+
assert_eq!(result.body["thinking"]["display"], "summarized");
|
|
1817
|
+
assert!(result.body["thinking"]["budget_tokens"].as_u64().unwrap() >= 1024);
|
|
1818
|
+
}
|
|
1819
|
+
|
|
1820
|
+
#[test]
|
|
1821
|
+
fn reasoning_effort_none_stays_disabled_without_display() {
|
|
1822
|
+
let p = provider();
|
|
1823
|
+
let req = json!({
|
|
1824
|
+
"model": "claude-sonnet-5",
|
|
1825
|
+
"messages": [{"role": "user", "content": "hi"}],
|
|
1826
|
+
"reasoning_effort": "none",
|
|
1827
|
+
});
|
|
1828
|
+
let result = p.transform_request("claude-sonnet-5", &req).unwrap();
|
|
1829
|
+
assert_eq!(result.body["thinking"]["type"], "disabled");
|
|
1830
|
+
assert!(result.body["thinking"].get("display").is_none());
|
|
1831
|
+
}
|
|
1832
|
+
|
|
1833
|
+
#[test]
|
|
1834
|
+
fn passthrough_thinking_display_untouched() {
|
|
1835
|
+
// A caller-supplied thinking block wins; the effort translation (and its
|
|
1836
|
+
// default display) is bypassed by the has_thinking gate.
|
|
1837
|
+
let p = provider();
|
|
1838
|
+
let req = json!({
|
|
1839
|
+
"model": "claude-sonnet-5",
|
|
1840
|
+
"messages": [{"role": "user", "content": "hi"}],
|
|
1841
|
+
"reasoning_effort": "high",
|
|
1842
|
+
"thinking": {"type": "adaptive", "display": "omitted"},
|
|
1843
|
+
});
|
|
1844
|
+
let result = p.transform_request("claude-sonnet-5", &req).unwrap();
|
|
1845
|
+
assert_eq!(result.body["thinking"]["display"], "omitted");
|
|
1846
|
+
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|