1
+ import { ofetch } from 'ofetch'
2
+ import { joinURL } from 'ufo'
1
3
import { createError } from 'h3'
2
- import type { Ai } from '@nuxthub/core'
4
+ import type { H3Error } from 'h3'
5
+ import type { Ai } from '../../../../types/ai'
3
6
import { requireNuxtHubFeature } from '../../../utils/features'
7
+ import { useRuntimeConfig } from '#imports'
4
8
5
9
let _ai : Ai
6
10
@@ -22,11 +26,56 @@ export function hubAi(): Ai {
22
26
if ( _ai ) {
23
27
return _ai
24
28
}
29
+ const hub = useRuntimeConfig ( ) . hub
25
30
// @ts -expect-error globalThis.__env__ is not defined
26
31
const binding = process . env . AI || globalThis . __env__ ?. AI || globalThis . AI
32
+ if ( hub . remote && hub . projectUrl && ! binding ) {
33
+ _ai = proxyHubAi ( hub . projectUrl , hub . projectSecretKey || hub . userToken )
34
+ return _ai
35
+ }
27
36
if ( binding ) {
28
37
_ai = binding as Ai
29
38
return _ai
30
39
}
31
40
throw createError ( 'Missing Cloudflare AI binding (AI)' )
32
41
}
42
+
43
+ /**
44
+ * Access remote Workers AI.
45
+ *
46
+ * @param projectUrl The project URL (e.g. https://my-deployed-project.nuxt.dev)
47
+ * @param secretKey The secret key to authenticate to the remote endpoint
48
+ *
49
+ * @example ```ts
50
+ * const ai = proxyHubAi('https://my-deployed-project.nuxt.dev', 'my-secret-key')
51
+ * await ai.run('@cf/meta/llama-3-8b-instruct', {
52
+ * prompt: "What is the origin of the phrase 'Hello, World'"
53
+ * })
54
+ * ```
55
+ *
56
+ * @see https://developers.cloudflare.com/workers-ai/configuration/bindings/#methods
57
+ */
58
+ export function proxyHubAi ( projectUrl : string , secretKey ?: string ) : Ai {
59
+ requireNuxtHubFeature ( 'ai' )
60
+
61
+ const aiAPI = ofetch . create ( {
62
+ baseURL : joinURL ( projectUrl , '/api/_hub/ai' ) ,
63
+ method : 'POST' ,
64
+ headers : {
65
+ Authorization : `Bearer ${ secretKey } `
66
+ }
67
+ } )
68
+ return {
69
+ async run ( model : string , params ?: Record < string , unknown > ) {
70
+ return aiAPI ( '/run' , { body : { model, params } } ) . catch ( handleProxyError )
71
+ }
72
+ } as Ai
73
+ }
74
+
75
+ function handleProxyError ( err : H3Error ) {
76
+ throw createError ( {
77
+ statusCode : err . statusCode ,
78
+ // @ts -expect-error not aware of data property
79
+ message : err . data ?. message || err . message
80
+ } )
81
+ }
0 commit comments