lex-bedrock 0.2.1 → 0.2.2
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 +4 -4
- data/CHANGELOG.md +5 -0
- data/CLAUDE.md +28 -14
- data/README.md +67 -4
- data/lib/legion/extensions/bedrock/helpers/client.rb +19 -11
- data/lib/legion/extensions/bedrock/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9c54111009d79155a7a9b85e0ec03a17b6b48800ce5dd641df7286637471114d
|
|
4
|
+
data.tar.gz: cb5f69ffe79c02ba38ba60c205b5215d7d8500851616ff5933c0e61ecf2f5b43
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6cf4b797406f46d5b8b0f506913e429b90dc7aca0f17ead791476a1ab629f962c3c6495cc04f0cc16b9dc0be0b10704ac8546dbd164249aea378b30e9c1c290c
|
|
7
|
+
data.tar.gz: 1e886593369d42af3426a4bf30cda859642157d0f9199416b0ddb52c0ee5caf5621b6cbb0ad1cf2da324e112ade51c3cd2344a5ad3cecc5541dbb64a07166a4b
|
data/CHANGELOG.md
CHANGED
data/CLAUDE.md
CHANGED
|
@@ -6,29 +6,36 @@
|
|
|
6
6
|
|
|
7
7
|
## Purpose
|
|
8
8
|
|
|
9
|
-
Legion Extension that connects LegionIO to AWS Bedrock for foundation model inference. Provides runners for the Converse API, raw InvokeModel,
|
|
9
|
+
Legion Extension that connects LegionIO to AWS Bedrock for foundation model inference. Provides runners for the Converse API, raw InvokeModel, model listing, token counting, and inference profile management using the AWS SDK (not Faraday).
|
|
10
10
|
|
|
11
11
|
**GitHub**: https://github.com/LegionIO/lex-bedrock
|
|
12
12
|
**License**: MIT
|
|
13
|
-
**Version**: 0.
|
|
14
|
-
**Specs**:
|
|
13
|
+
**Version**: 0.2.2
|
|
14
|
+
**Specs**: 120 examples (13 spec files)
|
|
15
15
|
|
|
16
16
|
## Architecture
|
|
17
17
|
|
|
18
18
|
```
|
|
19
19
|
Legion::Extensions::Bedrock
|
|
20
20
|
├── Runners/
|
|
21
|
-
│ ├── Converse # create
|
|
22
|
-
│ ├── Invoke # invoke_model
|
|
23
|
-
│
|
|
21
|
+
│ ├── Converse # create, create_stream, create_with_thinking
|
|
22
|
+
│ ├── Invoke # invoke_model
|
|
23
|
+
│ ├── Models # list, get
|
|
24
|
+
│ ├── Tokens # count_tokens
|
|
25
|
+
│ └── Profiles # list_inference_profiles, get_inference_profile, resolve_profile_id
|
|
24
26
|
├── Helpers/
|
|
25
|
-
│
|
|
27
|
+
│ ├── Client # AWS SDK client factories (module, not Faraday)
|
|
28
|
+
│ ├── Credentials # credential resolution helpers
|
|
29
|
+
│ ├── Errors # error handling + with_retry
|
|
30
|
+
│ ├── ModelRegistry # canonical model name -> Bedrock cross-region profile ID mapping
|
|
31
|
+
│ ├── Thinking # extended thinking field builders
|
|
32
|
+
│ └── Usage # usage normalization
|
|
26
33
|
└── Client # Standalone client class (includes all runners, holds @config)
|
|
27
34
|
```
|
|
28
35
|
|
|
29
36
|
`Helpers::Client` is a **module** with two factory methods:
|
|
30
|
-
- `bedrock_runtime_client(...)` — builds `Aws::BedrockRuntime::Client` (used by Converse
|
|
31
|
-
- `bedrock_client(...)` — builds `Aws::Bedrock::Client` (used by Models
|
|
37
|
+
- `bedrock_runtime_client(...)` — builds `Aws::BedrockRuntime::Client` (used by Converse, Invoke, Tokens runners)
|
|
38
|
+
- `bedrock_client(...)` — builds `Aws::Bedrock::Client` (used by Models, Profiles runners)
|
|
32
39
|
|
|
33
40
|
`DEFAULT_REGION` is `'us-east-2'`. All credential kwargs (`access_key_id:`, `secret_access_key:`, `region:`, `session_token:`) are passed through to the AWS SDK constructors. `session_token:` is optional and omitted if nil.
|
|
34
41
|
|
|
@@ -36,25 +43,32 @@ Legion::Extensions::Bedrock
|
|
|
36
43
|
|
|
37
44
|
- This is the only extension in extensions-ai that uses the AWS SDK instead of Faraday. There is no HTTP connection object — SDK clients handle transport.
|
|
38
45
|
- `Invoke#invoke_model` uses `::JSON.dump` and `::JSON.parse` (stdlib, explicit `::` prefix) to avoid namespace collision with `Legion::JSON`.
|
|
39
|
-
- `Converse#create` returns `{ result: response.output, usage: response.usage, stop_reason: response.stop_reason }
|
|
40
|
-
- `
|
|
46
|
+
- `Converse#create` returns `{ result: response.output, usage: response.usage, stop_reason: response.stop_reason }`.
|
|
47
|
+
- `Converse#create_stream` accepts a block and yields `{ type: :delta, text: }`, `{ type: :stop, stop_reason: }`, `{ type: :usage, usage: }` events. Returns `{ result: accumulated_text, usage:, stop_reason: }`.
|
|
48
|
+
- `Converse#create_with_thinking` wraps `create` with `Helpers::Thinking.build_thinking_fields`. Supports `budget_tokens:`, `adaptive:`, `extra_betas:`.
|
|
49
|
+
- `Tokens#count_tokens` uses `client.count_tokens(...)` SDK call; returns `{ input_token_count: response.input_tokens }`.
|
|
50
|
+
- `Profiles` runner lists, gets, and resolves AWS cross-region inference profiles. `resolve_profile_id` finds the profile ARN for a canonical model ID.
|
|
51
|
+
- `Helpers::ModelRegistry` maps canonical model names (e.g. `'claude-sonnet-4-6'`) to Bedrock cross-region profile IDs (e.g. `'us.anthropic.claude-sonnet-4-6'`). Use `ModelRegistry.resolve(model_id)` before passing to SDK calls.
|
|
52
|
+
- `Helpers::Thinking` constants: `THINKING_BETA = 'interleaved-thinking-2025-05-14'`, `CONTEXT_1M_BETA = 'context-1m-2025-08-07'`, `TOOL_SEARCH_BETA = 'tool-search-tool-2025-10-19'`. Supports both `adaptive` and `enabled` thinking modes.
|
|
41
53
|
- `include Legion::Extensions::Helpers::Lex` is guarded with `const_defined?` pattern.
|
|
42
54
|
|
|
43
55
|
## Dependencies
|
|
44
56
|
|
|
45
57
|
| Gem | Purpose |
|
|
46
58
|
|-----|---------|
|
|
47
|
-
| `aws-sdk-bedrock` | Bedrock management API (model listing) |
|
|
48
|
-
| `aws-sdk-bedrockruntime` | Bedrock runtime API (inference) |
|
|
59
|
+
| `aws-sdk-bedrock` | Bedrock management API (model listing, inference profiles) |
|
|
60
|
+
| `aws-sdk-bedrockruntime` | Bedrock runtime API (inference, streaming, token counting) |
|
|
61
|
+
| `legion-cache`, `legion-crypt`, `legion-data`, `legion-json`, `legion-logging`, `legion-settings`, `legion-transport` | LegionIO core |
|
|
49
62
|
|
|
50
63
|
## Testing
|
|
51
64
|
|
|
52
65
|
```bash
|
|
53
66
|
bundle install
|
|
54
|
-
bundle exec rspec #
|
|
67
|
+
bundle exec rspec # 120 examples
|
|
55
68
|
bundle exec rubocop
|
|
56
69
|
```
|
|
57
70
|
|
|
58
71
|
---
|
|
59
72
|
|
|
60
73
|
**Maintained By**: Matthew Iverson (@Esity)
|
|
74
|
+
**Last Updated**: 2026-04-06
|
data/README.md
CHANGED
|
@@ -4,7 +4,7 @@ Legion Extension that connects LegionIO to AWS Bedrock for foundation model infe
|
|
|
4
4
|
|
|
5
5
|
## Purpose
|
|
6
6
|
|
|
7
|
-
Wraps the AWS Bedrock SDK as named runners consumable by any LegionIO task chain. Provides the Converse API (multi-turn chat), raw InvokeModel (direct model invocation),
|
|
7
|
+
Wraps the AWS Bedrock SDK as named runners consumable by any LegionIO task chain. Provides the Converse API (multi-turn chat with streaming and extended thinking), raw InvokeModel (direct model invocation), foundation model listing, token counting, and inference profile management. Uses the AWS SDK directly — no Faraday. Use this extension when you need direct access to the Bedrock API surface within the LEX runner/actor lifecycle. For simple chat/embed workflows, consider `legion-llm` instead.
|
|
8
8
|
|
|
9
9
|
## Installation
|
|
10
10
|
|
|
@@ -40,17 +40,46 @@ result = client.list
|
|
|
40
40
|
|
|
41
41
|
# Converse API
|
|
42
42
|
result = client.create(
|
|
43
|
-
model_id: 'anthropic.claude-
|
|
43
|
+
model_id: 'us.anthropic.claude-sonnet-4-6',
|
|
44
44
|
messages: [{ role: 'user', content: [{ text: 'Hello' }] }]
|
|
45
45
|
)
|
|
46
46
|
# => { result: ..., usage: ..., stop_reason: 'end_turn' }
|
|
47
47
|
|
|
48
|
+
# Streaming Converse
|
|
49
|
+
client.create_stream(
|
|
50
|
+
model_id: 'us.anthropic.claude-sonnet-4-6',
|
|
51
|
+
messages: [{ role: 'user', content: [{ text: 'Tell me a story.' }] }]
|
|
52
|
+
) do |event|
|
|
53
|
+
case event[:type]
|
|
54
|
+
when :delta then print event[:text]
|
|
55
|
+
when :stop then puts "\nStop: #{event[:stop_reason]}"
|
|
56
|
+
when :usage then puts event[:usage].inspect
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Extended thinking
|
|
61
|
+
result = client.create_with_thinking(
|
|
62
|
+
model_id: 'us.anthropic.claude-sonnet-4-6',
|
|
63
|
+
messages: [{ role: 'user', content: [{ text: 'Solve this step by step.' }] }],
|
|
64
|
+
budget_tokens: 8192
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
# Token counting
|
|
68
|
+
result = client.count_tokens(
|
|
69
|
+
model_id: 'us.anthropic.claude-sonnet-4-6',
|
|
70
|
+
messages: [{ role: 'user', content: [{ text: 'Hello' }] }]
|
|
71
|
+
)
|
|
72
|
+
# => { input_token_count: 10 }
|
|
73
|
+
|
|
48
74
|
# Raw InvokeModel
|
|
49
75
|
result = client.invoke_model(
|
|
50
76
|
model_id: 'anthropic.claude-3-5-sonnet-20241022-v2:0',
|
|
51
77
|
body: { prompt: 'Hello', max_tokens: 256 }
|
|
52
78
|
)
|
|
53
|
-
|
|
79
|
+
|
|
80
|
+
# Resolve model ID via ModelRegistry
|
|
81
|
+
resolved = Legion::Extensions::Bedrock::Helpers::ModelRegistry.resolve('claude-sonnet-4-6')
|
|
82
|
+
# => 'us.anthropic.claude-sonnet-4-6'
|
|
54
83
|
```
|
|
55
84
|
|
|
56
85
|
### Runner Modules
|
|
@@ -59,15 +88,45 @@ result = client.invoke_model(
|
|
|
59
88
|
include Legion::Extensions::Bedrock::Runners::Models
|
|
60
89
|
include Legion::Extensions::Bedrock::Runners::Converse
|
|
61
90
|
include Legion::Extensions::Bedrock::Runners::Invoke
|
|
91
|
+
include Legion::Extensions::Bedrock::Runners::Tokens
|
|
92
|
+
include Legion::Extensions::Bedrock::Runners::Profiles
|
|
62
93
|
```
|
|
63
94
|
|
|
64
95
|
## API Coverage
|
|
65
96
|
|
|
66
97
|
| Runner | Methods |
|
|
67
98
|
|--------|---------|
|
|
68
|
-
| `Converse` | `create` |
|
|
99
|
+
| `Converse` | `create`, `create_stream`, `create_with_thinking` |
|
|
69
100
|
| `Invoke` | `invoke_model` |
|
|
70
101
|
| `Models` | `list`, `get` |
|
|
102
|
+
| `Tokens` | `count_tokens` |
|
|
103
|
+
| `Profiles` | `list_inference_profiles`, `get_inference_profile`, `resolve_profile_id` |
|
|
104
|
+
|
|
105
|
+
## Model Registry
|
|
106
|
+
|
|
107
|
+
`Helpers::ModelRegistry` maps canonical model names to Bedrock cross-region inference profile IDs:
|
|
108
|
+
|
|
109
|
+
```ruby
|
|
110
|
+
Legion::Extensions::Bedrock::Helpers::ModelRegistry.resolve('claude-sonnet-4-6')
|
|
111
|
+
# => 'us.anthropic.claude-sonnet-4-6'
|
|
112
|
+
|
|
113
|
+
Legion::Extensions::Bedrock::Helpers::ModelRegistry.all
|
|
114
|
+
# => { 'claude-3-5-haiku-20241022' => 'us.anthropic.claude-3-5-haiku-20241022-v1:0', ... }
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Extended Thinking
|
|
118
|
+
|
|
119
|
+
`Helpers::Thinking` provides field builders for Anthropic extended thinking on Bedrock:
|
|
120
|
+
|
|
121
|
+
```ruby
|
|
122
|
+
# Fixed budget
|
|
123
|
+
fields = Legion::Extensions::Bedrock::Helpers::Thinking.build_thinking_fields(budget_tokens: 8192)
|
|
124
|
+
|
|
125
|
+
# Adaptive thinking
|
|
126
|
+
fields = Legion::Extensions::Bedrock::Helpers::Thinking.build_thinking_fields(adaptive: true)
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Constants: `THINKING_BETA = 'interleaved-thinking-2025-05-14'`, `CONTEXT_1M_BETA = 'context-1m-2025-08-07'`, `TOOL_SEARCH_BETA = 'tool-search-tool-2025-10-19'`.
|
|
71
130
|
|
|
72
131
|
## Related
|
|
73
132
|
|
|
@@ -75,6 +134,10 @@ include Legion::Extensions::Bedrock::Runners::Invoke
|
|
|
75
134
|
- `legion-llm` — High-level LLM interface including Bedrock via ruby_llm
|
|
76
135
|
- `extensions-ai/CLAUDE.md` — Architecture patterns shared across all AI extensions
|
|
77
136
|
|
|
137
|
+
## Version
|
|
138
|
+
|
|
139
|
+
0.2.1
|
|
140
|
+
|
|
78
141
|
## License
|
|
79
142
|
|
|
80
143
|
MIT
|
|
@@ -15,21 +15,17 @@ module Legion
|
|
|
15
15
|
def bedrock_runtime_client(access_key_id: nil, secret_access_key: nil,
|
|
16
16
|
region: DEFAULT_REGION, session_token: nil,
|
|
17
17
|
credentials: nil, **)
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
session_token:)
|
|
22
|
-
)
|
|
18
|
+
credentials ||= build_credentials(access_key_id:, secret_access_key:, session_token:)
|
|
19
|
+
credentials ||= resolve_broker_credentials
|
|
20
|
+
Aws::BedrockRuntime::Client.new(region:, credentials:)
|
|
23
21
|
end
|
|
24
22
|
|
|
25
23
|
def bedrock_client(access_key_id: nil, secret_access_key: nil,
|
|
26
24
|
region: DEFAULT_REGION, session_token: nil,
|
|
27
25
|
credentials: nil, **)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
session_token:)
|
|
32
|
-
)
|
|
26
|
+
credentials ||= build_credentials(access_key_id:, secret_access_key:, session_token:)
|
|
27
|
+
credentials ||= resolve_broker_credentials
|
|
28
|
+
Aws::Bedrock::Client.new(region:, credentials:)
|
|
33
29
|
end
|
|
34
30
|
|
|
35
31
|
def region_for_model(model_id:, region: nil)
|
|
@@ -48,6 +44,18 @@ module Legion
|
|
|
48
44
|
settings_region || DEFAULT_REGION
|
|
49
45
|
end
|
|
50
46
|
|
|
47
|
+
def resolve_broker_credentials
|
|
48
|
+
return nil unless defined?(Legion::Identity::Broker)
|
|
49
|
+
|
|
50
|
+
renewer = Legion::Identity::Broker.renewer_for(:aws)
|
|
51
|
+
return nil unless renewer&.provider.respond_to?(:current_credentials)
|
|
52
|
+
|
|
53
|
+
renewer.provider.current_credentials
|
|
54
|
+
rescue StandardError => e
|
|
55
|
+
log.warn("resolve_broker_credentials failed: #{e.message}")
|
|
56
|
+
nil
|
|
57
|
+
end
|
|
58
|
+
|
|
51
59
|
def build_credentials(access_key_id:, secret_access_key:, session_token:)
|
|
52
60
|
return nil if access_key_id.nil?
|
|
53
61
|
|
|
@@ -58,7 +66,7 @@ module Legion
|
|
|
58
66
|
end
|
|
59
67
|
end
|
|
60
68
|
|
|
61
|
-
private_class_method :build_credentials
|
|
69
|
+
private_class_method :build_credentials, :resolve_broker_credentials
|
|
62
70
|
end
|
|
63
71
|
end
|
|
64
72
|
end
|