diff --git a/examples/cloudflare-hono/bun.lockb b/examples/cloudflare-hono/bun.lockb index d2ab7c8d6a..d562cb311c 100755 Binary files a/examples/cloudflare-hono/bun.lockb and b/examples/cloudflare-hono/bun.lockb differ diff --git a/examples/cloudflare-hono/index.ts b/examples/cloudflare-hono/index.ts index 03c49c4467..5c1e965dc2 100644 --- a/examples/cloudflare-hono/index.ts +++ b/examples/cloudflare-hono/index.ts @@ -21,6 +21,12 @@ const app = new Hono() const result = await Resource.MyBucket.get(first.key); c.header("content-type", result.httpMetadata.contentType); return c.body(result.body); + }) + .get("/ai", async (c) => { + const result = await Resource.ai.run("@cf/meta/llama-3-8b-instruct", { + prompt: "What is the origin of the phrase 'Hello, World'", + }); + return c.json(result.response); }); export default app; diff --git a/examples/cloudflare-hono/package.json b/examples/cloudflare-hono/package.json index b292178628..b357453b02 100644 --- a/examples/cloudflare-hono/package.json +++ b/examples/cloudflare-hono/package.json @@ -10,10 +10,10 @@ "author": "", "license": "ISC", "dependencies": { - "hono": "^4.2.3", + "hono": "^4.11.4", "sst": "latest" }, "devDependencies": { - "@cloudflare/workers-types": "^4.20240405.0" + "@cloudflare/workers-types": "^4.20260114.0" } } diff --git a/examples/cloudflare-hono/sst-env.d.ts b/examples/cloudflare-hono/sst-env.d.ts index 748808368f..85436eeb13 100644 --- a/examples/cloudflare-hono/sst-env.d.ts +++ b/examples/cloudflare-hono/sst-env.d.ts @@ -2,6 +2,7 @@ /* tslint:disable */ /* eslint-disable */ /* deno-fmt-ignore-file */ +/* biome-ignore-all lint: auto-generated */ import "sst" declare module "sst" { @@ -14,6 +15,7 @@ declare module "sst" { export interface Resource { "Hono": cloudflare.Service "MyBucket": cloudflare.R2Bucket + "ai": cloudflare.Ai } } diff --git a/examples/cloudflare-hono/sst.config.ts b/examples/cloudflare-hono/sst.config.ts index 2d9a4a5642..08e490b5c1 100644 --- a/examples/cloudflare-hono/sst.config.ts +++ b/examples/cloudflare-hono/sst.config.ts @@ -3,16 +3,17 @@ export default $config({ app(input) { return { - name: "cloudflare-hono", + name: "cloudflare-hono-example", home: "cloudflare", removal: input?.stage === "production" ? "retain" : "remove", }; }, async run() { + const ai = new sst.cloudflare.Ai("ai"); const bucket = new sst.cloudflare.Bucket("MyBucket"); const hono = new sst.cloudflare.Worker("Hono", { url: true, - link: [bucket], + link: [bucket, ai], handler: "index.ts", }); diff --git a/pkg/types/typescript/typescript.go b/pkg/types/typescript/typescript.go index ef1baf1842..1fea86cb69 100644 --- a/pkg/types/typescript/typescript.go +++ b/pkg/types/typescript/typescript.go @@ -13,6 +13,7 @@ import ( ) var mapping = map[string]string{ + "aiBinding": "Ai", "r2BucketBindings": "R2Bucket", "d1DatabaseBindings": "D1Database", "kvNamespaceBindings": "KVNamespace", diff --git a/platform/src/components/cloudflare/ai.ts b/platform/src/components/cloudflare/ai.ts new file mode 100644 index 0000000000..1ab7b37652 --- /dev/null +++ b/platform/src/components/cloudflare/ai.ts @@ -0,0 +1,37 @@ +import { ComponentResourceOptions } from "@pulumi/pulumi"; +import { Component, Transform } from "../component"; +import { Link } from "../link"; +import { binding } from "./binding"; + +export interface AiArgs { + transform?: { + binding?: Transform<{ name: string }>; + }; +} + +export class Ai extends Component implements Link.Linkable { + constructor(name: string, args?: AiArgs, opts?: ComponentResourceOptions) { + super(__pulumiType, name, args, opts); + this.name = name; + } + + getSSTLink() { + return { + properties: {}, + include: [ + binding({ + type: "aiBinding", + properties: { + name: this.name, + }, + }), + ], + }; + } + + name: string; +} + +const __pulumiType = "sst:cloudflare:Ai"; +// @ts-expect-error +Ai.__pulumiType = __pulumiType; diff --git a/platform/src/components/cloudflare/binding.ts b/platform/src/components/cloudflare/binding.ts index 1f438b362b..1865730fad 100644 --- a/platform/src/components/cloudflare/binding.ts +++ b/platform/src/components/cloudflare/binding.ts @@ -18,6 +18,13 @@ import { Input } from "../input"; +export interface AiBinding { + type: "aiBinding"; + properties: { + name: Input; + }; +} + export interface KvBinding { type: "kvNamespaceBindings"; properties: { @@ -63,6 +70,7 @@ export interface D1DatabaseBinding { } export type Binding = + | AiBinding | KvBinding | SecretTextBinding | ServiceBinding diff --git a/platform/src/components/cloudflare/index.ts b/platform/src/components/cloudflare/index.ts index f04b592115..ed1844c6c3 100644 --- a/platform/src/components/cloudflare/index.ts +++ b/platform/src/components/cloudflare/index.ts @@ -8,6 +8,7 @@ export * from "./account-id"; export * from "./auth"; export * from "./queue"; export * from "./cron"; +export * from "./ai"; export { binding } from "./binding.js"; /** diff --git a/platform/src/components/cloudflare/worker.ts b/platform/src/components/cloudflare/worker.ts index 366a30d6b5..dc2f950572 100644 --- a/platform/src/components/cloudflare/worker.ts +++ b/platform/src/components/cloudflare/worker.ts @@ -361,6 +361,7 @@ export class Worker extends Component implements Link.Linkable { b ? { type: { + aiBinding: "ai", plainTextBindings: "plain_text", secretTextBindings: "secret_text", queueBindings: "queue",