1- import type { AgentUserConfig } from '#/config' ;
21import type { SseChatCompatibleOptions } from './request' ;
32import type {
43 ChatAgent ,
54 ChatAgentResponse ,
65 ChatStreamTextHandler ,
7- HistoryItem ,
86 ImageAgent ,
97 LLMChatParams ,
108} from './types' ;
9+ import { type AgentUserConfig , ENV } from '#/config' ;
1110import { renderOpenAIMessages } from './openai' ;
12- import { isJsonResponse , requestChatCompletions } from './request' ;
11+ import { isJsonResponse , mapResponseToAnswer , requestChatCompletions } from './request' ;
1312import { convertStringToResponseMessages , loadModelsList } from './utils' ;
1413
15- class WorkerBase {
16- readonly name = 'workers' ;
17- readonly run = async ( model : string , body : any , id : string , token : string ) : Promise < Response > => {
18- return await fetch (
19- `https://api.cloudflare.com/client/v4/accounts/${ id } /ai/run/${ model } ` ,
20- {
21- headers : { Authorization : `Bearer ${ token } ` } ,
22- method : 'POST' ,
23- body : JSON . stringify ( body ) ,
24- } ,
25- ) ;
26- } ;
14+ async function sendWorkerRequest ( model : string , body : any , id : string , token : string ) : Promise < Response > {
15+ return await fetch (
16+ `https://api.cloudflare.com/client/v4/accounts/${ id } /ai/run/${ model } ` ,
17+ {
18+ headers : { Authorization : `Bearer ${ token } ` } ,
19+ method : 'POST' ,
20+ body : JSON . stringify ( body ) ,
21+ } ,
22+ ) ;
23+ } ;
2724
28- readonly enable = ( context : AgentUserConfig ) : boolean => {
29- return ! ! ( context . CLOUDFLARE_ACCOUNT_ID && context . CLOUDFLARE_TOKEN ) ;
30- } ;
31- }
25+ function isWorkerAIEnable ( context : AgentUserConfig ) : boolean {
26+ if ( ENV . AI_BINDING ) {
27+ return true ;
28+ }
29+ return ! ! ( context . CLOUDFLARE_ACCOUNT_ID && context . CLOUDFLARE_TOKEN ) ;
30+ } ;
3231
33- export class WorkersChat extends WorkerBase implements ChatAgent {
32+ export class WorkersChat implements ChatAgent {
33+ readonly name = 'workers' ;
3434 readonly modelKey = 'WORKERS_CHAT_MODEL' ;
35+ readonly enable = isWorkerAIEnable ;
3536
3637 readonly model = ( ctx : AgentUserConfig ) : string | null => {
3738 return ctx . WORKERS_CHAT_MODEL ;
3839 } ;
3940
40- private render = ( item : HistoryItem ) : any => {
41- return {
42- role : item . role ,
43- content : item . content ,
44- } ;
45- } ;
46-
4741 readonly request = async ( params : LLMChatParams , context : AgentUserConfig , onStream : ChatStreamTextHandler | null ) : Promise < ChatAgentResponse > => {
4842 const { prompt, messages } = params ;
49- const id = context . CLOUDFLARE_ACCOUNT_ID ;
50- const token = context . CLOUDFLARE_TOKEN ;
5143 const model = context . WORKERS_CHAT_MODEL ;
52- const url = `https://api.cloudflare.com/client/v4/accounts/${ id } /ai/run/${ model } ` ;
53- const header = {
54- Authorization : `Bearer ${ token } ` ,
55- } ;
5644 const body = {
5745 messages : await renderOpenAIMessages ( prompt , messages , null ) ,
5846 stream : onStream !== null ,
5947 } ;
60-
6148 const options : SseChatCompatibleOptions = { } ;
6249 options . contentExtractor = function ( data : any ) {
6350 return data ?. response ;
@@ -68,6 +55,19 @@ export class WorkersChat extends WorkerBase implements ChatAgent {
6855 options . errorExtractor = function ( data : any ) {
6956 return data ?. errors ?. at ( 0 ) ?. message ;
7057 } ;
58+
59+ if ( ENV . AI_BINDING ) {
60+ const resp = ENV . AI_BINDING . run ( model , body ) ;
61+ const answer = mapResponseToAnswer ( resp , new AbortController ( ) , options , onStream ) ;
62+ return convertStringToResponseMessages ( answer ) ;
63+ }
64+
65+ const id = context . CLOUDFLARE_ACCOUNT_ID ;
66+ const token = context . CLOUDFLARE_TOKEN ;
67+ const url = `https://api.cloudflare.com/client/v4/accounts/${ id } /ai/run/${ model } ` ;
68+ const header = {
69+ Authorization : `Bearer ${ token } ` ,
70+ } ;
7171 return convertStringToResponseMessages ( requestChatCompletions ( url , header , body , onStream , options ) ) ;
7272 } ;
7373
@@ -86,20 +86,29 @@ export class WorkersChat extends WorkerBase implements ChatAgent {
8686 } ;
8787}
8888
89- export class WorkersImage extends WorkerBase implements ImageAgent {
89+ export class WorkersImage implements ImageAgent {
90+ readonly name = 'workers' ;
9091 readonly modelKey = 'WORKERS_IMAGE_MODEL' ;
92+ readonly enable = isWorkerAIEnable ;
9193
9294 readonly model = ( ctx : AgentUserConfig ) : string => {
9395 return ctx . WORKERS_IMAGE_MODEL ;
9496 } ;
9597
96- readonly request = async ( prompt : string , context : AgentUserConfig ) : Promise < Blob > => {
98+ readonly request = async ( prompt : string , context : AgentUserConfig ) : Promise < string | Blob > => {
9799 const id = context . CLOUDFLARE_ACCOUNT_ID ;
98100 const token = context . CLOUDFLARE_TOKEN ;
99- if ( ! id || ! token ) {
101+ let raw : Response | null = null ;
102+ if ( ENV . AI_BINDING ) {
103+ raw = ENV . AI_BINDING . run ( context . WORKERS_IMAGE_MODEL , { prompt } ) ;
104+ } else if ( id && token ) {
105+ raw = await sendWorkerRequest ( context . WORKERS_IMAGE_MODEL , { prompt } , id , token ) ;
106+ } else {
100107 throw new Error ( 'Cloudflare account ID or token is not set' ) ;
101108 }
102- const raw = await this . run ( context . WORKERS_IMAGE_MODEL , { prompt } , id , token ) ;
109+ if ( ! raw ) {
110+ throw new Error ( 'Invalid response' ) ;
111+ }
103112 if ( isJsonResponse ( raw ) ) {
104113 const { result } = await raw . json ( ) ;
105114 const image = result ?. image ;
0 commit comments