llm_mock 0.1.0
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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +10 -0
- data/LICENSE +21 -0
- data/README.md +48 -0
- data/lib/llm_mock/provider.rb +51 -0
- data/lib/llm_mock/version.rb +5 -0
- data/lib/llm_mock.rb +13 -0
- metadata +69 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 76c3be4ff38f519d54043d67a1a91112c832e99bd320e9b887881576bbc4391e
|
|
4
|
+
data.tar.gz: cc1cab796fc5149bdf27a7dfc188a09868b6ff7e26b361a16e4e5b2a4afcbbcc
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: e33be7f603f386d41186f8f67a45c832194672164b5568b3648efefc9d40c0764b0ff5e84ca9dcf33f556c3a4b07b3dd94e01d559defbae990bca763fbb31645
|
|
7
|
+
data.tar.gz: de6b695425a8b983d188b9ec24f8d9c460d583f820fb94c22f5b1747abc07f04419aded7fcea0bdbd7d2311dcd31042812e2adb0b7bda59c5d78a9d844f3d746
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. This project adheres to
|
|
4
|
+
[Semantic Versioning](https://semver.org/).
|
|
5
|
+
|
|
6
|
+
## [0.1.0] - 2026-06-19
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
- Initial release: the `LlmMock::Provider` contract that provider mock gems
|
|
10
|
+
(e.g. `llm_mock_anthropic`) implement.
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Nate Brustein
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# llm_mock
|
|
2
|
+
|
|
3
|
+
When you test code that calls an LLM API, one robust approach is to **stub the
|
|
4
|
+
client and hand back a canned response object** — no network, no flakiness, no
|
|
5
|
+
cost. But every provider's SDK returns differently-shaped objects (messages,
|
|
6
|
+
content blocks, tool calls, streams), and constructing those by hand is fiddly.
|
|
7
|
+
The `llm_mock` family solves that per provider: `llm_mock_anthropic`,
|
|
8
|
+
`llm_mock_gemini`, and so on, each giving you ergonomic builders for that SDK's
|
|
9
|
+
response objects.
|
|
10
|
+
|
|
11
|
+
**`llm_mock` itself is just the shared foundation.** You almost never depend on
|
|
12
|
+
it directly — you pick a provider gem. This gem exists so that:
|
|
13
|
+
|
|
14
|
+
- every provider mock implements the **same contract**, and
|
|
15
|
+
- tools that orchestrate testing (like [`deja`](https://github.com/nbrustein/deja),
|
|
16
|
+
which records and replays real LLM calls) can drive **any** provider through
|
|
17
|
+
one interface instead of special-casing each SDK.
|
|
18
|
+
|
|
19
|
+
## Who depends on this
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
your test ──► llm_mock_anthropic ──► llm_mock (the contract)
|
|
23
|
+
deja ─────────► llm_mock_anthropic ──► llm_mock
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
You want **`llm_mock_anthropic`** (or another provider gem). It pulls in
|
|
27
|
+
`llm_mock` for you.
|
|
28
|
+
|
|
29
|
+
## The contract
|
|
30
|
+
|
|
31
|
+
A provider gem subclasses `LlmMock::Provider` and implements the parts it
|
|
32
|
+
supports:
|
|
33
|
+
|
|
34
|
+
| Method | Purpose |
|
|
35
|
+
| --- | --- |
|
|
36
|
+
| `build_client(&responder)` | Return a stub client; each SDK method calls `responder.call(method, kwargs)`. |
|
|
37
|
+
| `call_real(client, method, kwargs)` | Invoke the real SDK method on a live client. |
|
|
38
|
+
| `serialize(method, response)` | SDK response object → plain Hash (for caching). |
|
|
39
|
+
| `deserialize(method, data)` | Plain Hash → an object shaped like the SDK response. |
|
|
40
|
+
| `prompt_for(kwargs)` | Optional readable prompt string for audit logs. |
|
|
41
|
+
| `default_real_client` | Optional `-> { ... }` that builds a live SDK client. |
|
|
42
|
+
|
|
43
|
+
That's the whole gem: a namespace and one abstract class. The interesting code
|
|
44
|
+
lives in the provider gems.
|
|
45
|
+
|
|
46
|
+
## License
|
|
47
|
+
|
|
48
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LlmMock
|
|
4
|
+
# The contract every provider mock implements (llm_mock_anthropic, and more to
|
|
5
|
+
# come), so a consumer like the `deja` gem can drive any provider uniformly.
|
|
6
|
+
#
|
|
7
|
+
# A provider encapsulates one LLM SDK's *shape* for tests:
|
|
8
|
+
# - how to build a stub client whose methods route through a responder,
|
|
9
|
+
# - how to invoke the real SDK (when something isn't cached),
|
|
10
|
+
# - how to serialize/deserialize that SDK's response objects to/from the plain
|
|
11
|
+
# hashes a cache stores.
|
|
12
|
+
#
|
|
13
|
+
# Subclasses raise NotImplementedError for anything they don't provide.
|
|
14
|
+
class Provider
|
|
15
|
+
# Build a stub object shaped like the real SDK client. Every SDK method it
|
|
16
|
+
# exposes must call `responder.call(method_name, kwargs)` and return the
|
|
17
|
+
# result. The responder is supplied by the consumer (e.g. deja's cache layer),
|
|
18
|
+
# so the provider stays ignorant of caching.
|
|
19
|
+
def build_client(&responder)
|
|
20
|
+
raise NotImplementedError, "#{self.class} must implement #build_client"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Invoke the real SDK method on a live client — used to make the actual call
|
|
24
|
+
# when there's no cached response. `method` is the symbol the stub captured.
|
|
25
|
+
def call_real(client, method, kwargs)
|
|
26
|
+
raise NotImplementedError, "#{self.class} must implement #call_real"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Provider response object -> plain Hash (must round-trip through #deserialize).
|
|
30
|
+
def serialize(method, response)
|
|
31
|
+
raise NotImplementedError, "#{self.class} must implement #serialize"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Plain Hash -> an object shaped like the SDK's response.
|
|
35
|
+
def deserialize(method, data)
|
|
36
|
+
raise NotImplementedError, "#{self.class} must implement #deserialize"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# A human-readable prompt string stored alongside cached calls for auditing.
|
|
40
|
+
# Optional — defaults to nil.
|
|
41
|
+
def prompt_for(_kwargs)
|
|
42
|
+
nil
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# A callable (-> { ... }) that builds a live SDK client. Optional — consumers
|
|
46
|
+
# may supply their own instead.
|
|
47
|
+
def default_real_client
|
|
48
|
+
raise NotImplementedError, "#{self.class} must implement #default_real_client"
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
data/lib/llm_mock.rb
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "llm_mock/version"
|
|
4
|
+
require "llm_mock/provider"
|
|
5
|
+
|
|
6
|
+
# llm_mock is the shared foundation for a family of gems that fabricate LLM SDK
|
|
7
|
+
# response objects in tests — `llm_mock_anthropic`, and more providers to come.
|
|
8
|
+
#
|
|
9
|
+
# You don't usually depend on this gem directly; you pick a provider gem. This
|
|
10
|
+
# gem only defines the common contract (LlmMock::Provider) those providers
|
|
11
|
+
# implement, so tools like `deja` can drive any provider the same way.
|
|
12
|
+
module LlmMock
|
|
13
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: llm_mock
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Nate Brustein
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: rspec
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '3.0'
|
|
19
|
+
type: :development
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '3.0'
|
|
26
|
+
description: |
|
|
27
|
+
The shared foundation for a family of gems (llm_mock_anthropic, and more) that
|
|
28
|
+
build fake LLM SDK response objects for tests that stub the client directly.
|
|
29
|
+
This gem defines the common provider contract those gems implement so tools
|
|
30
|
+
like deja can drive any provider uniformly. You usually depend on a provider
|
|
31
|
+
gem, not this one.
|
|
32
|
+
email:
|
|
33
|
+
- nate@bidwrangler.com
|
|
34
|
+
executables: []
|
|
35
|
+
extensions: []
|
|
36
|
+
extra_rdoc_files: []
|
|
37
|
+
files:
|
|
38
|
+
- CHANGELOG.md
|
|
39
|
+
- LICENSE
|
|
40
|
+
- README.md
|
|
41
|
+
- lib/llm_mock.rb
|
|
42
|
+
- lib/llm_mock/provider.rb
|
|
43
|
+
- lib/llm_mock/version.rb
|
|
44
|
+
homepage: https://github.com/nbrustein/llm_mock
|
|
45
|
+
licenses:
|
|
46
|
+
- MIT
|
|
47
|
+
metadata:
|
|
48
|
+
homepage_uri: https://github.com/nbrustein/llm_mock
|
|
49
|
+
source_code_uri: https://github.com/nbrustein/llm_mock
|
|
50
|
+
changelog_uri: https://github.com/nbrustein/llm_mock/blob/main/CHANGELOG.md
|
|
51
|
+
rubygems_mfa_required: 'true'
|
|
52
|
+
rdoc_options: []
|
|
53
|
+
require_paths:
|
|
54
|
+
- lib
|
|
55
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
56
|
+
requirements:
|
|
57
|
+
- - ">="
|
|
58
|
+
- !ruby/object:Gem::Version
|
|
59
|
+
version: '3.2'
|
|
60
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
61
|
+
requirements:
|
|
62
|
+
- - ">="
|
|
63
|
+
- !ruby/object:Gem::Version
|
|
64
|
+
version: '0'
|
|
65
|
+
requirements: []
|
|
66
|
+
rubygems_version: 4.0.3
|
|
67
|
+
specification_version: 4
|
|
68
|
+
summary: Shared contract for gems that fabricate LLM SDK response objects in tests.
|
|
69
|
+
test_files: []
|