1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
//! `InvokeModel`, for the models Anthropic serves through Bedrock.
//!
//! # Signing is the transport's job, not this protocol's
//!
//! Bedrock authenticates with SigV4, which signs the **whole HTTP request**: the method, the
//! path, the query, a set of headers, and a hash of the body. That is exactly the surface
//! [`crate::HttpTransport`] sees and a [`Protocol`] does not — a protocol writes JSON and has
//! no idea what URL or headers the shared machinery is about to attach.
//!
//! It also needs state a protocol is not allowed to have. A signature covers a timestamp, so
//! signing needs a clock; it covers the region; and it needs credentials that rotate. Every
//! `Protocol` method here is a pure function, deliberately, and that is what makes one
//! instance safe to share across any number of concurrent calls.
//!
//! So this crate ships the translation and you supply a transport that signs. That is the
//! same bargain the crate already makes for HTTP itself — `reqwest` is a feature, not a
//! requirement — and it means you sign with whatever your program already uses, `aws-sigv4`
//! and `aws-config` most likely, rather than with an implementation of SigV4 written here
//! that nobody could test against the real thing.
//!
//! ```no_run
//! # use llmr::transport::{HttpRequest, HttpResponse, HttpTransport};
//! # use std::sync::Arc;
//! /// Wraps any transport and signs on the way past.
//! struct Signed<T>(T);
//!
//! #[async_trait::async_trait]
//! impl<T: HttpTransport> HttpTransport for Signed<T> {
//! async fn send(&self, mut request: HttpRequest) -> llmr::Result<HttpResponse> {
//! // Add the SigV4 headers here, over the request as it stands.
//! request = request.with_header("authorization", "AWS4-HMAC-SHA256 ...");
//! self.0.send(request).await
//! }
//! }
//! ```
//!
//! # No streaming
//!
//! Bedrock streams over its own binary event framing rather than server sent events, so the
//! frame reader in [`crate::providers::api`] cannot read it. [`Protocol::stream_body`] is
//! left at its default, which means [`crate::Provider::stream`] falls back to one whole call
//! handed over as a burst. That is an answer rather than a refusal, and
//! [`crate::ModelCapabilities::streaming`] is what says it is not the real thing.
use crate;
use crateResult;
use crate;
use crateMessages;
use crate;
use crateRegistry;
use crateSecret;
use crateHttpTransport;
use Value;
use Arc;
/// The version string Bedrock wants in place of a model name.
const ANTHROPIC_VERSION: &str = "bedrock-2023-05-31";
/// `InvokeModel`, speaking the body Anthropic's models take.
///
/// Holds nothing, like every protocol here. The translation is [`Messages`]', reused rather
/// than copied: Claude through Bedrock and Claude direct should send the same JSON, and two
/// copies of that translation would disagree the first time one was fixed.
;
/// Bedrock, ready to call.
pub type Bedrock = ;
/// The endpoint for a region.
/// A provider for Anthropic's models in one region.
///
/// **The transport must sign.** There is no key argument because SigV4 is not a bearer token
/// and does not fit one: the credential belongs to the transport, along with the clock and
/// the region the signature covers. See this module's header for the shape of one.
///
/// The reach is [`Reach::CloudPartner`] and is not a choice. A prompt sent through here goes
/// to Amazon on an Amazon credential, whoever trained the model, and a program asking where
/// its data may go must be told that rather than `FirstPartyApi`.