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
//! Cloudflare Workers AI provider for anyllm.
//!
//! This crate implements [`anyllm::ChatProvider`] using the `worker::Ai` binding,
//! enabling AI model calls directly from Cloudflare Workers without HTTP overhead.
//! Construction is runtime-bound: unlike the HTTP providers, this adapter is not
//! loaded from local environment variables and instead requires a live Worker
//! `Ai` binding.
//!
//! # Usage
//!
//! ```rust,ignore
//! use anyllm::prelude::*;
//! use anyllm_cloudflare_worker::Provider;
//!
//! async fn handler(env: &worker::Env) -> Result<String> {
//! let ai = env.ai("AI").map_err(|e| anyllm::Error::Provider {
//! status: None,
//! message: e.to_string(),
//! body: None,
//! request_id: None,
//! })?;
//!
//! let provider = Provider::new(ai);
//!
//! let response = provider.chat(
//! &ChatRequest::new("@cf/meta/llama-3.1-8b-instruct")
//! .message(Message::user("What is Rust?"))
//! ).await?;
//!
//! Ok(response.text_or_empty())
//! }
//! ```
//!
//! # Streaming
//!
//! Streaming uses `Ai::run_bytes()` with `stream: true`, parsing SSE events
//! from the raw byte stream:
//!
//! ```rust,ignore
//! use anyllm::prelude::*;
//! use anyllm_cloudflare_worker::Provider;
//! use futures_util::StreamExt;
//!
//! async fn stream_handler(env: &worker::Env) -> Result<()> {
//! let ai = env.ai("AI").map_err(|e| anyllm::Error::Provider {
//! status: None,
//! message: e.to_string(),
//! body: None,
//! request_id: None,
//! })?;
//!
//! let provider = Provider::new(ai);
//!
//! let mut stream = provider.chat_stream(
//! &ChatRequest::new("@cf/meta/llama-3.1-8b-instruct")
//! .message(Message::user("Tell me a story"))
//! ).await?;
//!
//! while let Some(event) = stream.next().await {
//! let event = event?;
//! if let StreamEvent::TextDelta { text, .. } = &event {
//! // Process streaming text
//! }
//! }
//! Ok(())
//! }
//! ```
use Arc;
use ;
/// Cloudflare Workers AI provider implementing `anyllm::ChatProvider`.
///
/// Wraps a `worker::Ai` binding to call AI models directly from within
/// a Cloudflare Worker. No HTTP overhead: calls go through the Workers
/// runtime's internal AI binding.
///
/// # Construction
///
/// Obtain the `worker::Ai` binding from the Worker's `Env`:
///
/// ```rust,ignore
/// let ai = env.ai("AI")?;
/// let provider = Provider::new(ai);
/// ```
///
/// The `"AI"` string must match the binding name in `wrangler.toml`:
///
/// ```toml
/// [ai]
/// binding = "AI"
/// ```