llmshim 0.2.2__tar.gz → 0.2.3__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.3/.github/ISSUE_TEMPLATE/bug_report.yml +67 -0
- llmshim-0.2.3/.github/ISSUE_TEMPLATE/feature_request.yml +24 -0
- llmshim-0.2.3/.github/PULL_REQUEST_TEMPLATE.md +21 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/CLAUDE.md +1 -1
- llmshim-0.2.3/CODE_OF_CONDUCT.md +83 -0
- llmshim-0.2.3/CONTRIBUTING.md +113 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/Cargo.lock +1 -1
- {llmshim-0.2.2 → llmshim-0.2.3}/Cargo.toml +2 -2
- llmshim-0.2.3/LICENSE-APACHE +202 -0
- llmshim-0.2.3/NOTICE +12 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/PKG-INFO +2 -2
- {llmshim-0.2.2 → llmshim-0.2.3}/README.md +18 -1
- llmshim-0.2.3/SECURITY.md +47 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/docs/src/guides/reasoning.md +1 -1
- {llmshim-0.2.2 → llmshim-0.2.3}/docs/src/reference/models.md +2 -1
- {llmshim-0.2.2 → llmshim-0.2.3}/src/main.rs +1 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/src/models.rs +9 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/src/providers/anthropic.rs +1 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/tests/integration_thinking.rs +33 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/tests/unit_anthropic.rs +25 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/tests/unit_models.rs +2 -1
- {llmshim-0.2.2 → llmshim-0.2.3}/.github/workflows/pages.yml +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/.github/workflows/release.yml +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/.gitignore +0 -0
- /llmshim-0.2.2/LICENSE → /llmshim-0.2.3/LICENSE-MIT +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/benchmarks/bench.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/benchmarks/bench_python.py +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/benchmarks/loadtest.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/docs/.gitignore +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/docs/book.toml +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/docs/mermaid-init.js +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/docs/mermaid.min.js +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/docs/src/SUMMARY.md +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/docs/src/concepts/contracts.md +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/docs/src/concepts/conversations.md +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/docs/src/concepts/portability.md +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/docs/src/concepts/routing.md +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/docs/src/concepts/translation-flow.md +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/docs/src/guides/fallbacks.md +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/docs/src/guides/images.md +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/docs/src/guides/native-controls.md +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/docs/src/guides/streaming.md +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/docs/src/guides/tools.md +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/docs/src/introduction.md +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/docs/src/proxy/deployment.md +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/docs/src/proxy/http-api.md +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/docs/src/proxy/scaling.md +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/docs/src/reference/api.md +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/docs/src/reference/cli.md +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/docs/src/reference/configuration.md +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/docs/src/reference/errors.md +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/docs/src/reference/providers.md +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/docs/src/reference/request-fields.md +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/docs/src/reference/surfaces.md +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/docs/src/start/choose.md +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/docs/src/start/cli.md +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/docs/src/start/clients.md +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/docs/src/start/configure.md +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/docs/src/start/proxy.md +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/docs/src/start/rust.md +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/examples/chat.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/examples/stream.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/llmshim/__init__.py +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/llmshim/_client.py +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/llmshim/_server.py +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/llmshim/types.py +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/pyproject.toml +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/src/client.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/src/config.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/src/env.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/src/error.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/src/fallback.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/src/lib.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/src/log.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/src/provider.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/src/providers/gemini.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/src/providers/mod.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/src/providers/openai.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/src/providers/xai.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/src/proxy/convert.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/src/proxy/error.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/src/proxy/handlers.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/src/proxy/mod.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/src/proxy/ratelimit.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/src/proxy/types.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/src/router.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/src/vision.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/tests/integration.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/tests/integration_fallback.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/tests/integration_gemini.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/tests/integration_gemini_tools.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/tests/integration_long_context.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/tests/integration_multimodel.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/tests/integration_proxy.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/tests/integration_tool_roundtrip.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/tests/integration_vision.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/tests/unit_fallback.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/tests/unit_fast_mode.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/tests/unit_gemini.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/tests/unit_log.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/tests/unit_multimodel.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/tests/unit_openai.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/tests/unit_proxy.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/tests/unit_proxy_convert.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/tests/unit_router.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/tests/unit_sse.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/tests/unit_tools.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/tests/unit_vision.rs +0 -0
- {llmshim-0.2.2 → llmshim-0.2.3}/tests/unit_xai.rs +0 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
name: Bug report
|
|
2
|
+
description: A request produced wrong output, an error, or a crash
|
|
3
|
+
labels: [bug]
|
|
4
|
+
body:
|
|
5
|
+
- type: markdown
|
|
6
|
+
attributes:
|
|
7
|
+
value: |
|
|
8
|
+
Thanks! The single most useful thing you can attach is a **minimal
|
|
9
|
+
request that reproduces the problem** — the `model` and `messages` (plus
|
|
10
|
+
any `tools` or reasoning fields), with API keys and confidential content
|
|
11
|
+
redacted.
|
|
12
|
+
- type: textarea
|
|
13
|
+
id: what
|
|
14
|
+
attributes:
|
|
15
|
+
label: What happened?
|
|
16
|
+
description: What did you send, what did you expect, and what did you get instead?
|
|
17
|
+
placeholder: |
|
|
18
|
+
Sent {"model":"anthropic/claude-sonnet-5", ...} and the tool_calls came back ...
|
|
19
|
+
validations:
|
|
20
|
+
required: true
|
|
21
|
+
- type: textarea
|
|
22
|
+
id: output
|
|
23
|
+
attributes:
|
|
24
|
+
label: Relevant request / output
|
|
25
|
+
description: The request JSON, the error object, or the response snippet (redact keys).
|
|
26
|
+
render: json
|
|
27
|
+
- type: dropdown
|
|
28
|
+
id: surface
|
|
29
|
+
attributes:
|
|
30
|
+
label: Which surface?
|
|
31
|
+
options:
|
|
32
|
+
- Rust crate
|
|
33
|
+
- CLI
|
|
34
|
+
- Proxy (HTTP)
|
|
35
|
+
- Python client
|
|
36
|
+
- TypeScript client
|
|
37
|
+
- Go client
|
|
38
|
+
- Ruby client
|
|
39
|
+
validations:
|
|
40
|
+
required: true
|
|
41
|
+
- type: dropdown
|
|
42
|
+
id: provider
|
|
43
|
+
attributes:
|
|
44
|
+
label: Provider
|
|
45
|
+
options:
|
|
46
|
+
- OpenAI
|
|
47
|
+
- Anthropic
|
|
48
|
+
- Gemini
|
|
49
|
+
- xAI
|
|
50
|
+
- Multiple / model switching
|
|
51
|
+
- N/A
|
|
52
|
+
validations:
|
|
53
|
+
required: true
|
|
54
|
+
- type: input
|
|
55
|
+
id: version
|
|
56
|
+
attributes:
|
|
57
|
+
label: llmshim version / commit
|
|
58
|
+
placeholder: "0.2.2 (or main @ <sha>)"
|
|
59
|
+
validations:
|
|
60
|
+
required: true
|
|
61
|
+
- type: checkboxes
|
|
62
|
+
id: checks
|
|
63
|
+
attributes:
|
|
64
|
+
label: Checks
|
|
65
|
+
options:
|
|
66
|
+
- label: I redacted any API keys from the request/output above
|
|
67
|
+
- label: I can share a request that reproduces this (or described it if it involves confidential content)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
name: Feature request
|
|
2
|
+
description: Propose new provider/model support, API surface, or output shape
|
|
3
|
+
labels: [enhancement]
|
|
4
|
+
body:
|
|
5
|
+
- type: textarea
|
|
6
|
+
id: problem
|
|
7
|
+
attributes:
|
|
8
|
+
label: What are you trying to do?
|
|
9
|
+
description: The consumer-side problem, not just the feature — what do you need llmshim to translate or expose, and for which surface/provider?
|
|
10
|
+
validations:
|
|
11
|
+
required: true
|
|
12
|
+
- type: textarea
|
|
13
|
+
id: proposal
|
|
14
|
+
attributes:
|
|
15
|
+
label: Proposed behavior
|
|
16
|
+
description: >
|
|
17
|
+
If it changes the request or response shape, sketch it. Note that
|
|
18
|
+
portable controls map across providers, while provider-specific controls
|
|
19
|
+
go under an `x-openai` / `x-anthropic` / `x-gemini` passthrough.
|
|
20
|
+
- type: textarea
|
|
21
|
+
id: alternatives
|
|
22
|
+
attributes:
|
|
23
|
+
label: Alternatives considered
|
|
24
|
+
description: Including a native `x-*` passthrough or handling it in your own application — why isn't that enough?
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
## What & why
|
|
2
|
+
|
|
3
|
+
<!-- What changes, and what consumer-visible behavior it affects. -->
|
|
4
|
+
|
|
5
|
+
## Public API / contract impact
|
|
6
|
+
|
|
7
|
+
- [ ] No breaking change to semver-protected `pub` items (`src/lib.rs`, `router.rs`, `provider.rs`, `error.rs`, `fallback.rs`, `log.rs`, `config.rs`, `models.rs`, `vision.rs`) — or this PR bumps the version (pre-1.0: minor is the breaking channel) with justification
|
|
8
|
+
- [ ] Proxy request/response shapes unchanged — or `api/openapi.yaml` and the clients under `clients/` are updated to match
|
|
9
|
+
- [ ] Per-provider behavior changes (reasoning, tools, vision) are verified against the live API and the pinning tests updated
|
|
10
|
+
|
|
11
|
+
## Gates (all must pass locally — CI re-checks)
|
|
12
|
+
|
|
13
|
+
- [ ] Commits are signed off (`git commit -s`, [DCO](https://developercertificate.org/))
|
|
14
|
+
- [ ] `cargo fmt --check`
|
|
15
|
+
- [ ] `cargo clippy --features proxy -- -D warnings`
|
|
16
|
+
- [ ] `cargo test --features proxy --tests`
|
|
17
|
+
- [ ] Docs under `docs/src/` updated if the request/response shapes, CLI, proxy API, or configuration changed
|
|
18
|
+
|
|
19
|
+
## Tests
|
|
20
|
+
|
|
21
|
+
<!-- Which new assertions pin this change? A fix's test must fail on the pre-fix code. -->
|
|
@@ -13,7 +13,7 @@ This is a public crate on crates.io. Do NOT make breaking changes to `pub` items
|
|
|
13
13
|
## Supported models
|
|
14
14
|
|
|
15
15
|
- **OpenAI:** `gpt-5.6-sol`, `gpt-5.6-terra`, `gpt-5.6-luna`, `gpt-5.5`, `gpt-5.5-pro`, `gpt-5.4`, `gpt-5.4-pro`, `gpt-5.4-mini`, `gpt-5.4-nano`
|
|
16
|
-
- **Anthropic:** `claude-opus-4-8`, `claude-sonnet-5`, `claude-opus-4-7`, `claude-opus-4-6`, `claude-sonnet-4-6`, `claude-haiku-4-5-20251001`
|
|
16
|
+
- **Anthropic:** `claude-opus-5`, `claude-opus-4-8`, `claude-sonnet-5`, `claude-opus-4-7`, `claude-opus-4-6`, `claude-sonnet-4-6`, `claude-haiku-4-5-20251001`
|
|
17
17
|
- **Gemini:** `gemini-3.5-flash`, `gemini-3.1-pro-preview`, `gemini-3-flash-preview`
|
|
18
18
|
- **xAI:** `grok-4.5`, `grok-4.3`, `grok-4.20-multi-agent-beta-0309`, `grok-4.20-beta-0309-reasoning`, `grok-4.20-beta-0309-non-reasoning`
|
|
19
19
|
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our Pledge
|
|
4
|
+
|
|
5
|
+
We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation.
|
|
6
|
+
|
|
7
|
+
We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
|
|
8
|
+
|
|
9
|
+
## Our Standards
|
|
10
|
+
|
|
11
|
+
Examples of behavior that contributes to a positive environment for our community include:
|
|
12
|
+
|
|
13
|
+
* Demonstrating empathy and kindness toward other people
|
|
14
|
+
* Being respectful of differing opinions, viewpoints, and experiences
|
|
15
|
+
* Giving and gracefully accepting constructive feedback
|
|
16
|
+
* Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
|
|
17
|
+
* Focusing on what is best not just for us as individuals, but for the overall community
|
|
18
|
+
|
|
19
|
+
Examples of unacceptable behavior include:
|
|
20
|
+
|
|
21
|
+
* The use of sexualized language or imagery, and sexual attention or advances of any kind
|
|
22
|
+
* Trolling, insulting or derogatory comments, and personal or political attacks
|
|
23
|
+
* Public or private harassment
|
|
24
|
+
* Publishing others' private information, such as a physical or email address, without their explicit permission
|
|
25
|
+
* Other conduct which could reasonably be considered inappropriate in a professional setting
|
|
26
|
+
|
|
27
|
+
## Enforcement Responsibilities
|
|
28
|
+
|
|
29
|
+
Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.
|
|
30
|
+
|
|
31
|
+
Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate.
|
|
32
|
+
|
|
33
|
+
## Scope
|
|
34
|
+
|
|
35
|
+
This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
|
|
36
|
+
|
|
37
|
+
## Enforcement
|
|
38
|
+
|
|
39
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the maintainers via GitHub private vulnerability reporting on this repository (Security → Report a vulnerability), marked "code of conduct". All complaints will be reviewed and investigated promptly and fairly.
|
|
40
|
+
|
|
41
|
+
All community leaders are obligated to respect the privacy and security of the reporter of any incident.
|
|
42
|
+
|
|
43
|
+
## Enforcement Guidelines
|
|
44
|
+
|
|
45
|
+
Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct:
|
|
46
|
+
|
|
47
|
+
### 1. Correction
|
|
48
|
+
|
|
49
|
+
**Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community.
|
|
50
|
+
|
|
51
|
+
**Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested.
|
|
52
|
+
|
|
53
|
+
### 2. Warning
|
|
54
|
+
|
|
55
|
+
**Community Impact**: A violation through a single incident or series of actions.
|
|
56
|
+
|
|
57
|
+
**Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban.
|
|
58
|
+
|
|
59
|
+
### 3. Temporary Ban
|
|
60
|
+
|
|
61
|
+
**Community Impact**: A serious violation of community standards, including sustained inappropriate behavior.
|
|
62
|
+
|
|
63
|
+
**Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban.
|
|
64
|
+
|
|
65
|
+
### 4. Permanent Ban
|
|
66
|
+
|
|
67
|
+
**Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals.
|
|
68
|
+
|
|
69
|
+
**Consequence**: A permanent ban from any sort of public interaction within the community.
|
|
70
|
+
|
|
71
|
+
## Attribution
|
|
72
|
+
|
|
73
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.1, available at [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
|
|
74
|
+
|
|
75
|
+
Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder][Mozilla CoC].
|
|
76
|
+
|
|
77
|
+
For answers to common questions about this code of conduct, see the FAQ at [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at [https://www.contributor-covenant.org/translations][translations].
|
|
78
|
+
|
|
79
|
+
[homepage]: https://www.contributor-covenant.org
|
|
80
|
+
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
|
|
81
|
+
[Mozilla CoC]: https://github.com/mozilla/diversity
|
|
82
|
+
[FAQ]: https://www.contributor-covenant.org/faq
|
|
83
|
+
[translations]: https://www.contributor-covenant.org/translations
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# Contributing to llmshim
|
|
2
|
+
|
|
3
|
+
Thanks for your interest! llmshim is a small, sharply-scoped pure-Rust codebase
|
|
4
|
+
and we want contributions to be pleasant. This page is the human onboarding
|
|
5
|
+
path; the deep technical context lives in [CLAUDE.md](CLAUDE.md) — written for
|
|
6
|
+
coding agents but equally useful to people, and kept rigorously current.
|
|
7
|
+
|
|
8
|
+
## Where to start
|
|
9
|
+
|
|
10
|
+
- **Try it first**: the [documentation site](https://sanjay920.github.io/llmshim/)
|
|
11
|
+
shows what llmshim does and the contracts it keeps. `cargo run` drops you into
|
|
12
|
+
the interactive chat.
|
|
13
|
+
- **Issues** labeled `good first issue` are curated entry points; `bug` issues
|
|
14
|
+
with a minimal reproducing request (model + messages) are the most valuable
|
|
15
|
+
thing you can pick up.
|
|
16
|
+
- Open an issue before large changes — especially anything touching the public
|
|
17
|
+
API surface (see below), which is under semver protection.
|
|
18
|
+
|
|
19
|
+
## Development setup
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
git clone https://github.com/sanjay920/llmshim
|
|
23
|
+
cd llmshim
|
|
24
|
+
cargo build
|
|
25
|
+
cargo test --features proxy --tests # unit tests; ~CI's set
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Rust stable. Provider API keys are only needed for the integration tests
|
|
29
|
+
(`cargo test --features proxy -- --ignored`); set them via environment variables
|
|
30
|
+
(`OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, `GEMINI_API_KEY`, `XAI_API_KEY`) or
|
|
31
|
+
`llmshim configure`. The proxy is feature-gated: build it with `--features proxy`.
|
|
32
|
+
|
|
33
|
+
## Working with coding agents
|
|
34
|
+
|
|
35
|
+
This repo is deliberately agent-friendly: `CLAUDE.md` is the canonical context,
|
|
36
|
+
scoped rules live in `.claude/rules/`, and task-specific procedures live in
|
|
37
|
+
`.claude/skills/` (e.g. `/preflight`, `/add-model`, `/add-provider`, `/release`).
|
|
38
|
+
If you contribute with Claude Code, Codex, Cursor, or similar, your agent
|
|
39
|
+
already has what it needs. Agent-assisted PRs are welcome; you own what you
|
|
40
|
+
submit.
|
|
41
|
+
|
|
42
|
+
## The gates (CI enforces all of these)
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
cargo fmt --check
|
|
46
|
+
cargo clippy --features proxy -- -D warnings
|
|
47
|
+
cargo test --features proxy --tests
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
The `/preflight` skill runs exactly this trio.
|
|
51
|
+
|
|
52
|
+
## The rules that protect users
|
|
53
|
+
|
|
54
|
+
1. The public API is **semver-protected**. Do not make breaking changes to
|
|
55
|
+
`pub` items in `src/lib.rs`, `src/router.rs`, `src/provider.rs`,
|
|
56
|
+
`src/error.rs`, `src/fallback.rs`, `src/log.rs`, `src/config.rs`,
|
|
57
|
+
`src/models.rs`, or `src/vision.rs` without a version bump (pre-1.0, the
|
|
58
|
+
minor is the breaking channel). Additive changes are a patch.
|
|
59
|
+
2. **Value-based transforms.** Requests flow as `serde_json::Value`; each
|
|
60
|
+
provider maps only what it understands and puts provider-specific controls
|
|
61
|
+
under `x-openai` / `x-anthropic` / `x-gemini`. Don't invent a canonical
|
|
62
|
+
struct or forward a field a provider doesn't accept.
|
|
63
|
+
3. **Accuracy over freshness.** Per-model behavior (reasoning tiers, model
|
|
64
|
+
specs) is verified against the live provider APIs. Leave a value `Unknown`
|
|
65
|
+
rather than guessing it, and update the pinning tests when a mapping changes.
|
|
66
|
+
4. **No cross-provider leakage.** A message from one provider must be sanitized
|
|
67
|
+
before it reaches another — opaque tokens and provider-only fields never leak.
|
|
68
|
+
|
|
69
|
+
## Tests
|
|
70
|
+
|
|
71
|
+
Every test must pin real behavior that could regress — a fix's test should fail
|
|
72
|
+
on the pre-fix code. We decline tests that exist for coverage's own sake, and we
|
|
73
|
+
decline fixes without a test that would have caught the bug. Unit tests run
|
|
74
|
+
offline; integration tests (`--ignored`) hit real provider APIs and need keys.
|
|
75
|
+
|
|
76
|
+
## Pull requests
|
|
77
|
+
|
|
78
|
+
- Small and focused beats big-bang. The PR template's checklist mirrors the
|
|
79
|
+
gates above.
|
|
80
|
+
- If your change alters the request/response shapes, the CLI, the proxy HTTP
|
|
81
|
+
API, or configuration, update the corresponding page under `docs/src/` in the
|
|
82
|
+
same PR — and keep `api/openapi.yaml` and the language clients in `clients/` in
|
|
83
|
+
sync with the proxy contract.
|
|
84
|
+
- All language clients ship in lockstep with the crate version.
|
|
85
|
+
|
|
86
|
+
## Developer Certificate of Origin (DCO)
|
|
87
|
+
|
|
88
|
+
By contributing, you certify the [Developer Certificate of
|
|
89
|
+
Origin](https://developercertificate.org/) — that you wrote the code or
|
|
90
|
+
otherwise have the right to submit it under this project's licenses. Sign off
|
|
91
|
+
each commit:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
git commit -s # adds "Signed-off-by: Your Name <you@example.com>"
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Licensing of contributions
|
|
98
|
+
|
|
99
|
+
llmshim is dual-licensed under [MIT](LICENSE-MIT) and
|
|
100
|
+
[Apache-2.0](LICENSE-APACHE). Unless you explicitly state otherwise, any
|
|
101
|
+
contribution intentionally submitted for inclusion in llmshim by you, as defined
|
|
102
|
+
in the Apache-2.0 license, shall be dual licensed as above, without any
|
|
103
|
+
additional terms or conditions.
|
|
104
|
+
|
|
105
|
+
## Security issues
|
|
106
|
+
|
|
107
|
+
Do **not** open public issues for suspected vulnerabilities — see
|
|
108
|
+
[SECURITY.md](SECURITY.md).
|
|
109
|
+
|
|
110
|
+
## Conduct
|
|
111
|
+
|
|
112
|
+
We follow the [Contributor Covenant](CODE_OF_CONDUCT.md). Be excellent to each
|
|
113
|
+
other.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "llmshim"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.3"
|
|
4
4
|
edition = "2021"
|
|
5
5
|
description = "Blazing fast LLM API translation layer in pure Rust"
|
|
6
|
-
license = "MIT"
|
|
6
|
+
license = "MIT OR Apache-2.0"
|
|
7
7
|
repository = "https://github.com/sanjay920/llmshim"
|
|
8
8
|
homepage = "https://github.com/sanjay920/llmshim"
|
|
9
9
|
keywords = ["llm", "openai", "anthropic", "gemini", "ai"]
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
|
|
2
|
+
Apache License
|
|
3
|
+
Version 2.0, January 2004
|
|
4
|
+
http://www.apache.org/licenses/
|
|
5
|
+
|
|
6
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
7
|
+
|
|
8
|
+
1. Definitions.
|
|
9
|
+
|
|
10
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
11
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
12
|
+
|
|
13
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
14
|
+
the copyright owner that is granting the License.
|
|
15
|
+
|
|
16
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
17
|
+
other entities that control, are controlled by, or are under common
|
|
18
|
+
control with that entity. For the purposes of this definition,
|
|
19
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
20
|
+
direction or management of such entity, whether by contract or
|
|
21
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
22
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
23
|
+
|
|
24
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
25
|
+
exercising permissions granted by this License.
|
|
26
|
+
|
|
27
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
28
|
+
including but not limited to software source code, documentation
|
|
29
|
+
source, and configuration files.
|
|
30
|
+
|
|
31
|
+
"Object" form shall mean any form resulting from mechanical
|
|
32
|
+
transformation or translation of a Source form, including but
|
|
33
|
+
not limited to compiled object code, generated documentation,
|
|
34
|
+
and conversions to other media types.
|
|
35
|
+
|
|
36
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
37
|
+
Object form, made available under the License, as indicated by a
|
|
38
|
+
copyright notice that is included in or attached to the work
|
|
39
|
+
(an example is provided in the Appendix below).
|
|
40
|
+
|
|
41
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
42
|
+
form, that is based on (or derived from) the Work and for which the
|
|
43
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
44
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
45
|
+
of this License, Derivative Works shall not include works that remain
|
|
46
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
47
|
+
the Work and Derivative Works thereof.
|
|
48
|
+
|
|
49
|
+
"Contribution" shall mean any work of authorship, including
|
|
50
|
+
the original version of the Work and any modifications or additions
|
|
51
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
52
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
53
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
54
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
55
|
+
means any form of electronic, verbal, or written communication sent
|
|
56
|
+
to the Licensor or its representatives, including but not limited to
|
|
57
|
+
communication on electronic mailing lists, source code control systems,
|
|
58
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
59
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
60
|
+
excluding communication that is conspicuously marked or otherwise
|
|
61
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
62
|
+
|
|
63
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
64
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
65
|
+
subsequently incorporated within the Work.
|
|
66
|
+
|
|
67
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
68
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
69
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
70
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
71
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
72
|
+
Work and such Derivative Works in Source or Object form.
|
|
73
|
+
|
|
74
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
75
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
76
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
77
|
+
(except as stated in this section) patent license to make, have made,
|
|
78
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
79
|
+
where such license applies only to those patent claims licensable
|
|
80
|
+
by such Contributor that are necessarily infringed by their
|
|
81
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
82
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
83
|
+
institute patent litigation against any entity (including a
|
|
84
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
85
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
86
|
+
or contributory patent infringement, then any patent licenses
|
|
87
|
+
granted to You under this License for that Work shall terminate
|
|
88
|
+
as of the date such litigation is filed.
|
|
89
|
+
|
|
90
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
91
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
92
|
+
modifications, and in Source or Object form, provided that You
|
|
93
|
+
meet the following conditions:
|
|
94
|
+
|
|
95
|
+
(a) You must give any other recipients of the Work or
|
|
96
|
+
Derivative Works a copy of this License; and
|
|
97
|
+
|
|
98
|
+
(b) You must cause any modified files to carry prominent notices
|
|
99
|
+
stating that You changed the files; and
|
|
100
|
+
|
|
101
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
102
|
+
that You distribute, all copyright, patent, trademark, and
|
|
103
|
+
attribution notices from the Source form of the Work,
|
|
104
|
+
excluding those notices that do not pertain to any part of
|
|
105
|
+
the Derivative Works; and
|
|
106
|
+
|
|
107
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
108
|
+
distribution, then any Derivative Works that You distribute must
|
|
109
|
+
include a readable copy of the attribution notices contained
|
|
110
|
+
within such NOTICE file, excluding those notices that do not
|
|
111
|
+
pertain to any part of the Derivative Works, in at least one
|
|
112
|
+
of the following places: within a NOTICE text file distributed
|
|
113
|
+
as part of the Derivative Works; within the Source form or
|
|
114
|
+
documentation, if provided along with the Derivative Works; or,
|
|
115
|
+
within a display generated by the Derivative Works, if and
|
|
116
|
+
wherever such third-party notices normally appear. The contents
|
|
117
|
+
of the NOTICE file are for informational purposes only and
|
|
118
|
+
do not modify the License. You may add Your own attribution
|
|
119
|
+
notices within Derivative Works that You distribute, alongside
|
|
120
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
121
|
+
that such additional attribution notices cannot be construed
|
|
122
|
+
as modifying the License.
|
|
123
|
+
|
|
124
|
+
You may add Your own copyright statement to Your modifications and
|
|
125
|
+
may provide additional or different license terms and conditions
|
|
126
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
127
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
128
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
129
|
+
the conditions stated in this License.
|
|
130
|
+
|
|
131
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
132
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
133
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
134
|
+
this License, without any additional terms or conditions.
|
|
135
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
136
|
+
the terms of any separate license agreement you may have executed
|
|
137
|
+
with Licensor regarding such Contributions.
|
|
138
|
+
|
|
139
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
140
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
141
|
+
except as required for reasonable and customary use in describing the
|
|
142
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
143
|
+
|
|
144
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
145
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
146
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
147
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
148
|
+
implied, including, without limitation, any warranties or conditions
|
|
149
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
150
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
151
|
+
appropriateness of using or redistributing the Work and assume any
|
|
152
|
+
risks associated with Your exercise of permissions under this License.
|
|
153
|
+
|
|
154
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
155
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
156
|
+
unless required by applicable law (such as deliberate and grossly
|
|
157
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
158
|
+
liable to You for damages, including any direct, indirect, special,
|
|
159
|
+
incidental, or consequential damages of any character arising as a
|
|
160
|
+
result of this License or out of the use or inability to use the
|
|
161
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
162
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
163
|
+
other commercial damages or losses), even if such Contributor
|
|
164
|
+
has been advised of the possibility of such damages.
|
|
165
|
+
|
|
166
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
167
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
168
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
169
|
+
or other liability obligations and/or rights consistent with this
|
|
170
|
+
License. However, in accepting such obligations, You may act only
|
|
171
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
172
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
173
|
+
defend, and hold each Contributor harmless for any liability
|
|
174
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
175
|
+
of your accepting any such warranty or additional liability.
|
|
176
|
+
|
|
177
|
+
END OF TERMS AND CONDITIONS
|
|
178
|
+
|
|
179
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
180
|
+
|
|
181
|
+
To apply the Apache License to your work, attach the following
|
|
182
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
183
|
+
replaced with your own identifying information. (Don't include
|
|
184
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
185
|
+
comment syntax for the file format. We also recommend that a
|
|
186
|
+
file or class name and description of purpose be included on the
|
|
187
|
+
same "printed page" as the copyright notice for easier
|
|
188
|
+
identification within third-party archives.
|
|
189
|
+
|
|
190
|
+
Copyright [yyyy] [name of copyright owner]
|
|
191
|
+
|
|
192
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
193
|
+
you may not use this file except in compliance with the License.
|
|
194
|
+
You may obtain a copy of the License at
|
|
195
|
+
|
|
196
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
197
|
+
|
|
198
|
+
Unless required by applicable law or agreed to in writing, software
|
|
199
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
200
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
201
|
+
See the License for the specific language governing permissions and
|
|
202
|
+
limitations under the License.
|
llmshim-0.2.3/NOTICE
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
llmshim
|
|
2
|
+
Copyright (c) 2026 Sanjay Nadhavajhala and the llmshim contributors
|
|
3
|
+
|
|
4
|
+
This product is dual-licensed under the MIT License and the Apache License,
|
|
5
|
+
Version 2.0 (see LICENSE-MIT and LICENSE-APACHE).
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
8
|
+
IMPLIED. IN NO EVENT SHALL THE AUTHORS OR ANY CONTRIBUTOR BE LIABLE FOR ANY
|
|
9
|
+
CLAIM, DAMAGES OR OTHER LIABILITY ARISING FROM THE USE OF THIS SOFTWARE.
|
|
10
|
+
Users are solely responsible for validating the software's fitness for
|
|
11
|
+
their purposes, including how it handles untrusted input and third-party API
|
|
12
|
+
responses, before relying on it.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: llmshim
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Classifier: Development Status :: 4 - Beta
|
|
5
5
|
Classifier: Intended Audience :: Developers
|
|
6
6
|
Classifier: License :: OSI Approved :: MIT License
|
|
@@ -221,7 +221,7 @@ billed provider calls; run it only when you deliberately want to hit real APIs.
|
|
|
221
221
|
| Provider | Models |
|
|
222
222
|
|----------|--------|
|
|
223
223
|
| OpenAI | `gpt-5.5`, `gpt-5.5-pro`, `gpt-5.4`, `gpt-5.4-pro`, `gpt-5.4-mini`, `gpt-5.4-nano` |
|
|
224
|
-
| Anthropic | `claude-opus-4-8`, `claude-sonnet-5`, `claude-opus-4-7`, `claude-opus-4-6`, `claude-sonnet-4-6`, `claude-haiku-4-5-20251001` |
|
|
224
|
+
| Anthropic | `claude-opus-5`, `claude-opus-4-8`, `claude-sonnet-5`, `claude-opus-4-7`, `claude-opus-4-6`, `claude-sonnet-4-6`, `claude-haiku-4-5-20251001` |
|
|
225
225
|
| Gemini | `gemini-3.5-flash`, `gemini-3.1-pro-preview`, `gemini-3-flash-preview` |
|
|
226
226
|
| xAI | `grok-4.5`, `grok-4.3`, `grok-4.20-multi-agent-beta-0309`, `grok-4.20-beta-0309-reasoning`, `grok-4.20-beta-0309-non-reasoning` |
|
|
227
227
|
|
|
@@ -344,7 +344,7 @@ Standard library only. Full docs: [`clients/ruby/README.md`](clients/ruby/README
|
|
|
344
344
|
| Provider | Models | Reasoning visible |
|
|
345
345
|
|----------|--------|-------------------|
|
|
346
346
|
| **OpenAI** | `gpt-5.6-sol`, `gpt-5.6-terra`, `gpt-5.6-luna`, `gpt-5.5`, `gpt-5.5-pro`, `gpt-5.4`, `gpt-5.4-pro`, `gpt-5.4-mini`, `gpt-5.4-nano` | Yes (summaries) |
|
|
347
|
-
| **Anthropic** | `claude-opus-4-8`, `claude-sonnet-5`, `claude-opus-4-7`, `claude-opus-4-6`, `claude-sonnet-4-6`, `claude-haiku-4-5-20251001` | Yes (full thinking) |
|
|
347
|
+
| **Anthropic** | `claude-opus-5`, `claude-opus-4-8`, `claude-sonnet-5`, `claude-opus-4-7`, `claude-opus-4-6`, `claude-sonnet-4-6`, `claude-haiku-4-5-20251001` | Yes (full thinking) |
|
|
348
348
|
| **Google Gemini** | `gemini-3.5-flash`, `gemini-3.1-pro-preview`, `gemini-3-flash-preview` | Yes (thought summaries) |
|
|
349
349
|
| **xAI** | `grok-4.5`, `grok-4.3`, `grok-4.20-multi-agent-beta-0309`, `grok-4.20-beta-0309-reasoning`, `grok-4.20-beta-0309-non-reasoning` | No (hidden) |
|
|
350
350
|
|
|
@@ -390,3 +390,20 @@ cargo build --release --features proxy # release build (~6MB binary)
|
|
|
390
390
|
cargo test --features proxy --tests # unit tests (~370)
|
|
391
391
|
cargo test --features proxy -- --ignored # integration tests (needs API keys)
|
|
392
392
|
```
|
|
393
|
+
|
|
394
|
+
## Contributing
|
|
395
|
+
|
|
396
|
+
Contributions are welcome — see [CONTRIBUTING.md](CONTRIBUTING.md) for the
|
|
397
|
+
development setup, the CI gates, and the rules that protect the public API.
|
|
398
|
+
Report suspected vulnerabilities privately per [SECURITY.md](SECURITY.md), and
|
|
399
|
+
be excellent to each other ([Code of Conduct](CODE_OF_CONDUCT.md)).
|
|
400
|
+
|
|
401
|
+
## License
|
|
402
|
+
|
|
403
|
+
Licensed under either of [Apache License, Version 2.0](LICENSE-APACHE) or
|
|
404
|
+
[MIT license](LICENSE-MIT) at your option. llmshim is provided **"AS IS",
|
|
405
|
+
without warranty of any kind**; the authors and contributors accept no
|
|
406
|
+
liability for its use. See [NOTICE](NOTICE). Unless you explicitly state
|
|
407
|
+
otherwise, any contribution intentionally submitted for inclusion in llmshim by
|
|
408
|
+
you, as defined in the Apache-2.0 license, shall be dual licensed as above,
|
|
409
|
+
without any additional terms or conditions.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
llmshim forwards requests to third-party LLM providers and, in proxy mode,
|
|
4
|
+
holds provider API keys, so we take reports seriously.
|
|
5
|
+
|
|
6
|
+
## Reporting a vulnerability
|
|
7
|
+
|
|
8
|
+
**Please do not open a public issue.** Use GitHub's private vulnerability
|
|
9
|
+
reporting: [Security → Report a vulnerability](https://github.com/sanjay920/llmshim/security/advisories/new)
|
|
10
|
+
on this repository. We will acknowledge reports on a best-effort basis and
|
|
11
|
+
coordinate a fix and disclosure with you.
|
|
12
|
+
|
|
13
|
+
## Threat model (what counts as a vulnerability)
|
|
14
|
+
|
|
15
|
+
llmshim is a translation layer, not a security boundary. Its posture:
|
|
16
|
+
|
|
17
|
+
- **The proxy ships with no authentication and no TLS**, and is intended to run
|
|
18
|
+
on a trusted network behind your own gateway. Exposing it directly to the
|
|
19
|
+
public internet is an operator mistake, not a vulnerability.
|
|
20
|
+
- Provider API keys live in the proxy process environment (or `~/.llmshim/`) and
|
|
21
|
+
are never returned to clients. A defect that **leaks a configured key** — into
|
|
22
|
+
a response body, a log line, an error message, or another request's context —
|
|
23
|
+
is a vulnerability. Please report it.
|
|
24
|
+
- So is anything that lets a request reach an unintended destination
|
|
25
|
+
(server-side request forgery beyond the configured providers), crashes the
|
|
26
|
+
**proxy process** rather than failing a single request, achieves code
|
|
27
|
+
execution, or lets one request read another's data.
|
|
28
|
+
- A translation that merely produces wrong, incomplete, or provider-rejected
|
|
29
|
+
output is a bug, not a vulnerability — an ordinary public issue is perfect for
|
|
30
|
+
those.
|
|
31
|
+
|
|
32
|
+
## Supported versions
|
|
33
|
+
|
|
34
|
+
The latest release and `main`. We do not backport fixes to older releases.
|
|
35
|
+
|
|
36
|
+
## Hardening guidance for operators
|
|
37
|
+
|
|
38
|
+
Run the proxy behind your own authentication, TLS termination, and rate limits;
|
|
39
|
+
do not expose it directly. Keep provider keys in the server's environment or
|
|
40
|
+
config file, never in client code. See the deployment documentation for the
|
|
41
|
+
concurrency, rate-limit, and backpressure controls.
|
|
42
|
+
|
|
43
|
+
## No warranty
|
|
44
|
+
|
|
45
|
+
llmshim is provided "AS IS", without warranty of any kind. Operating it is at
|
|
46
|
+
your own risk; see [LICENSE-MIT](LICENSE-MIT) and [LICENSE-APACHE](LICENSE-APACHE)
|
|
47
|
+
(§7–§8) and [NOTICE](NOTICE).
|
|
@@ -87,7 +87,7 @@ would reject it.
|
|
|
87
87
|
|
|
88
88
|
Adaptive models use `thinking: {type}` plus `output_config: {effort}`:
|
|
89
89
|
|
|
90
|
-
| unified | Opus 4.7/4.8, Sonnet 5 | Opus/Sonnet 4.6 |
|
|
90
|
+
| unified | Opus 5, Opus 4.7/4.8, Sonnet 5 | Opus/Sonnet 4.6 |
|
|
91
91
|
|---|---|---|
|
|
92
92
|
| `none` | `thinking: {type: "disabled"}` | `thinking: {type: "disabled"}` |
|
|
93
93
|
| `low` | `adaptive` + `low` | `adaptive` + `low` |
|
|
@@ -14,7 +14,7 @@ the ID and display label.
|
|
|
14
14
|
|
|
15
15
|
## Registered catalog
|
|
16
16
|
|
|
17
|
-
The current registry contains
|
|
17
|
+
The current registry contains 24 entries, newest first within each provider.
|
|
18
18
|
This page mirrors `src/models.rs`; use runtime discovery rather than parsing
|
|
19
19
|
this table in applications.
|
|
20
20
|
|
|
@@ -36,6 +36,7 @@ this table in applications.
|
|
|
36
36
|
|
|
37
37
|
| ID | Display name |
|
|
38
38
|
|---|---|
|
|
39
|
+
| `anthropic/claude-opus-5` | Claude Opus 5 |
|
|
39
40
|
| `anthropic/claude-opus-4-8` | Claude Opus 4.8 |
|
|
40
41
|
| `anthropic/claude-sonnet-5` | Claude Sonnet 5 |
|
|
41
42
|
| `anthropic/claude-opus-4-7` | Claude Opus 4.7 |
|
|
@@ -15,6 +15,7 @@ const MODELS: &[(&str, &str)] = &[
|
|
|
15
15
|
("openai/gpt-5.4-pro", "GPT-5.4 Pro"),
|
|
16
16
|
("openai/gpt-5.4-mini", "GPT-5.4 Mini"),
|
|
17
17
|
("openai/gpt-5.4-nano", "GPT-5.4 Nano"),
|
|
18
|
+
("anthropic/claude-opus-5", "Claude Opus 5"),
|
|
18
19
|
("anthropic/claude-opus-4-8", "Claude Opus 4.8"),
|
|
19
20
|
("anthropic/claude-sonnet-5", "Claude Sonnet 5"),
|
|
20
21
|
("anthropic/claude-opus-4-7", "Claude Opus 4.7"),
|
|
@@ -262,6 +262,15 @@ pub const MODELS: &[ModelInfo] = &[
|
|
|
262
262
|
max_output_tokens: Some(128_000),
|
|
263
263
|
capabilities: CAPS_STD,
|
|
264
264
|
},
|
|
265
|
+
ModelInfo {
|
|
266
|
+
id: "anthropic/claude-opus-5",
|
|
267
|
+
provider: "anthropic",
|
|
268
|
+
name: "claude-opus-5",
|
|
269
|
+
label: "Claude Opus 5",
|
|
270
|
+
context_window_tokens: Some(1_000_000),
|
|
271
|
+
max_output_tokens: Some(128_000),
|
|
272
|
+
capabilities: CAPS_FULL,
|
|
273
|
+
},
|
|
265
274
|
ModelInfo {
|
|
266
275
|
id: "anthropic/claude-opus-4-8",
|
|
267
276
|
provider: "anthropic",
|
|
@@ -434,3 +434,36 @@ async fn anthropic_sonnet5_reasoning_summary_default_returns_text_live() {
|
|
|
434
434
|
);
|
|
435
435
|
println!("sonnet-5 reasoning text chars: {}", reasoning.len());
|
|
436
436
|
}
|
|
437
|
+
|
|
438
|
+
#[tokio::test]
|
|
439
|
+
#[ignore]
|
|
440
|
+
async fn anthropic_opus_5_reasoning_live() {
|
|
441
|
+
// End-to-end through llmshim: opus-5 is a new adaptive family — adaptive
|
|
442
|
+
// thinking, native xhigh, summarized display by default, reasoning surfaced.
|
|
443
|
+
if std::env::var("ANTHROPIC_API_KEY").is_err() {
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
let router = router();
|
|
447
|
+
let req = json!({
|
|
448
|
+
"model": "anthropic/claude-opus-5",
|
|
449
|
+
"messages": [{"role":"user","content":"Prove or disprove: for every positive integer n, n^2 + n + 41 is prime. Give rigorous reasoning."}],
|
|
450
|
+
"max_tokens": 4000,
|
|
451
|
+
"reasoning_effort": "xhigh",
|
|
452
|
+
});
|
|
453
|
+
let resp = llmshim::completion(&router, &req).await.unwrap();
|
|
454
|
+
assert_eq!(resp["object"], "chat.completion");
|
|
455
|
+
assert_eq!(resp["model"], "claude-opus-5");
|
|
456
|
+
let msg = &resp["choices"][0]["message"];
|
|
457
|
+
let content = msg["content"].as_str().unwrap_or("");
|
|
458
|
+
assert!(!content.is_empty(), "expected an answer, got: {resp}");
|
|
459
|
+
let reasoning = msg["reasoning_content"].as_str().unwrap_or("");
|
|
460
|
+
assert!(
|
|
461
|
+
!reasoning.is_empty(),
|
|
462
|
+
"expected reasoning text (adaptive + summarized default), got: {resp}"
|
|
463
|
+
);
|
|
464
|
+
println!(
|
|
465
|
+
"opus-5 OK — reasoning {} chars, answer {} chars",
|
|
466
|
+
reasoning.len(),
|
|
467
|
+
content.len()
|
|
468
|
+
);
|
|
469
|
+
}
|
|
@@ -1844,3 +1844,28 @@ fn passthrough_thinking_display_untouched() {
|
|
|
1844
1844
|
let result = p.transform_request("claude-sonnet-5", &req).unwrap();
|
|
1845
1845
|
assert_eq!(result.body["thinking"]["display"], "omitted");
|
|
1846
1846
|
}
|
|
1847
|
+
|
|
1848
|
+
#[test]
|
|
1849
|
+
fn opus_5_adaptive_native_xhigh_and_no_1m_beta() {
|
|
1850
|
+
// Opus 5 is a new adaptive family (adaptive thinking, native low..max incl.
|
|
1851
|
+
// xhigh — not clamped). Its 1M context is the DEFAULT, so unlike opus-4-8 it
|
|
1852
|
+
// must NOT send the context-1m beta header. Verified live 2026-07-25.
|
|
1853
|
+
let p = provider();
|
|
1854
|
+
let req = json!({
|
|
1855
|
+
"model": "claude-opus-5",
|
|
1856
|
+
"messages": [{"role": "user", "content": "hi"}],
|
|
1857
|
+
"reasoning_effort": "xhigh",
|
|
1858
|
+
});
|
|
1859
|
+
let result = p.transform_request("claude-opus-5", &req).unwrap();
|
|
1860
|
+
assert_eq!(result.body["thinking"]["type"], "adaptive");
|
|
1861
|
+
assert!(result.body["thinking"].get("budget_tokens").is_none());
|
|
1862
|
+
assert_eq!(result.body["output_config"]["effort"], "xhigh"); // native, not clamped to max
|
|
1863
|
+
let has_1m_beta = result
|
|
1864
|
+
.headers
|
|
1865
|
+
.iter()
|
|
1866
|
+
.any(|(k, v)| k == "anthropic-beta" && v.contains("context-1m"));
|
|
1867
|
+
assert!(
|
|
1868
|
+
!has_1m_beta,
|
|
1869
|
+
"opus-5 should not send the context-1m beta (1M is its default)"
|
|
1870
|
+
);
|
|
1871
|
+
}
|
|
@@ -11,7 +11,7 @@ fn models_registry_has_all_providers() {
|
|
|
11
11
|
|
|
12
12
|
#[test]
|
|
13
13
|
fn models_registry_has_expected_count() {
|
|
14
|
-
assert_eq!(MODELS.len(),
|
|
14
|
+
assert_eq!(MODELS.len(), 24);
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
#[test]
|
|
@@ -158,6 +158,7 @@ fn reasoning_support_matches_provider_behavior() {
|
|
|
158
158
|
// Effort-controlled models accept a reasoning control.
|
|
159
159
|
for id in [
|
|
160
160
|
"openai/gpt-5.6-sol",
|
|
161
|
+
"anthropic/claude-opus-5",
|
|
161
162
|
"anthropic/claude-opus-4-8",
|
|
162
163
|
"xai/grok-4.5",
|
|
163
164
|
] {
|
|
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
|