Skip to content

Commit 3583c21

Browse files
authored
Merge branch 'cloudflare:production' into production
2 parents 22a1519 + 2422c65 commit 3583c21

File tree

212 files changed

+17979
-2367
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

212 files changed

+17979
-2367
lines changed

.github/CODEOWNERS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444

4545
# Browser Rendering API
4646

47-
/src/content/docs/browser-rendering/ @mchenco @cloudflare/pcx-technical-writing @celso @meddulla @danielgek
47+
/src/content/docs/browser-rendering/ @mchenco @cloudflare/pcx-technical-writing @celso @meddulla @danielgek @kathayl
4848

4949
# Changelogs
5050

.github/workflows/image-audit.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ jobs:
2121
id: find-files
2222
run: |
2323
# Find all .png and .svg files, but only look in the ./src/assets/images directory
24-
FILES=$(find . -type f \( -name "*.png" -o -name "*.svg" \) -path "./src/assets/images/*" -not -path "./src/assets/images/workers-ai/*.svg" -not -path "./src/assets/images/workers/ai/*.png" -not -path "./src/assets/images/changelog-next/*")
24+
FILES=$(find . -type f \( -name "*.png" -o -name "*.svg" \) -path "./src/assets/images/*" -not -path "./src/assets/images/workers-ai/*.svg" -not -path "./src/assets/images/workers/ai/*.png" -not -path "./src/assets/images/changelog/*")
2525
2626
# Check if files are referenced in any markdown file
2727
UNUSED_FILES=""

package-lock.json

Lines changed: 173 additions & 173 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
"@astrojs/starlight-docsearch": "0.6.0",
3737
"@astrojs/starlight-tailwind": "3.0.1",
3838
"@astrojs/tailwind": "5.1.5",
39-
"@cloudflare/vitest-pool-workers": "0.8.6",
39+
"@cloudflare/vitest-pool-workers": "0.8.8",
4040
"@cloudflare/workers-types": "4.20250327.0",
4141
"@codingheads/sticky-header": "1.0.2",
4242
"@expressive-code/plugin-collapsible-sections": "0.40.2",
@@ -47,12 +47,12 @@
4747
"@stoplight/json-schema-tree": "4.0.0",
4848
"@types/hast": "3.0.4",
4949
"@types/he": "1.2.3",
50-
"@types/node": "22.13.14",
50+
"@types/node": "22.13.17",
5151
"@types/react": "19.0.7",
5252
"@types/react-dom": "19.0.4",
53-
"@typescript-eslint/parser": "8.28.0",
54-
"algoliasearch": "5.23.0",
55-
"astro": "5.5.5",
53+
"@typescript-eslint/parser": "8.29.0",
54+
"algoliasearch": "5.23.1",
55+
"astro": "5.5.6",
5656
"astro-breadcrumbs": "3.3.1",
5757
"astro-icon": "1.1.5",
5858
"astro-live-code": "0.0.5",
@@ -116,7 +116,7 @@
116116
"ts-blank-space": "0.6.1",
117117
"tsx": "4.19.3",
118118
"typescript": "5.8.2",
119-
"typescript-eslint": "8.28.0",
119+
"typescript-eslint": "8.29.0",
120120
"unified": "11.0.5",
121121
"unist-util-visit": "5.0.0",
122122
"vite-tsconfig-paths": "5.1.4",

public/__redirects

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1110,6 +1110,7 @@
11101110
/support/more-dashboard-apps/cloudflare-apps/reporting-bugs-or-feature-requests-for-cloudflare-apps/ /workers/ 301
11111111
/support/more-dashboard-apps/cloudflare-apps/troubleshooting-issues-with-cloudflare-apps/ /workers/ 301
11121112
/support/more-dashboard-apps/cloudflare-apps/will-cloudflare-apps-make-my-site-slower/ /workers/ 301
1113+
/support/more-dashboard-apps/cloudflare-stream/delivering-videos-with-cloudflare/ /fundamentals/reference/policies-compliances/delivering-videos-with-cloudflare/ 301
11131114
/support/network/ /network/ 301
11141115
/support/network/configuring-ip-geolocation/ /network/ip-geolocation/ 301
11151116
/support/network/setting-up-response-buffering/ /network/response-buffering/ 301
@@ -1182,6 +1183,7 @@
11821183
/support/more-dashboard-apps/cloudflare-apps/managing-cloudflare-apps/ /workers/ 301
11831184
/support/more-dashboard-apps/cloudflare-apps/removing-cloudflare-apps/ /workers/ 301
11841185
/support/troubleshooting/http-status-codes/http-status-codes/ /support/troubleshooting/http-status-codes/ 301
1186+
/support/troubleshooting/cloudflare-errors/troubleshooting-other-errors/ /speed/optimization/protocol/http2/#err_http2_protocol_error 301
11851187

11861188
# r2
11871189
/r2/platform/s3-compatibility/api/ /r2/api/s3/api/ 301
12.4 KB
Loading
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

src/assets/images/reference-architecture/storing-user-generated-content/ai-generated-content-in-r2.svg

Lines changed: 7378 additions & 0 deletions
Loading

src/assets/images/reference-architecture/storing-user-generated-content/uploads-to-r2-via-signed-urls.svg

Lines changed: 7379 additions & 0 deletions
Loading
Loading
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 1 addition & 0 deletions
Loading

src/assets/images/workers-ai/qwen.svg

Lines changed: 1 addition & 0 deletions
Loading
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

src/components/APIRequest.astro

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@ import Details from "./Details.astro";
88
99
type Props = z.input<typeof props>;
1010
11+
const Record = z.record(z.string(), z.any());
12+
1113
const props = z
1214
.object({
1315
path: z.string(),
1416
method: z.enum(["GET", "HEAD", "POST", "PUT", "DELETE", "PATCH"]),
1517
parameters: z.record(z.string(), z.any()).optional(),
16-
json: z.record(z.string(), z.any()).optional(),
17-
form: z.record(z.string(), z.any()).optional(),
18+
json: z.union([Record, z.array(Record)]).optional(),
19+
form: Record.optional(),
1820
})
1921
.strict();
2022
@@ -109,17 +111,27 @@ const jsonSchema = requestBody?.content?.["application/json"]?.schema as
109111
| undefined;
110112
111113
if (jsonSchema?.required) {
112-
const providedProperties = Object.keys(json ?? {});
113-
const requiredProperties = jsonSchema.required;
114-
115-
const missingProperties = requiredProperties.filter(
116-
(property) => !providedProperties.includes(property),
117-
);
114+
const checkProperties = (obj?: object) => {
115+
const providedProperties = Object.keys(obj ?? {});
116+
const requiredProperties = jsonSchema.required!;
118117
119-
if (missingProperties.length > 0) {
120-
throw new Error(
121-
`[APIRequest] Missing the following required properties for ${method} ${path}: ${missingProperties.join(", ")}`,
118+
const missingProperties = requiredProperties.filter(
119+
(property) => !providedProperties.includes(property),
122120
);
121+
122+
if (missingProperties.length > 0) {
123+
throw new Error(
124+
`[APIRequest] Missing the following required properties for ${method} ${path}: ${missingProperties.join(", ")}`,
125+
);
126+
}
127+
};
128+
129+
if (Array.isArray(json)) {
130+
for (const obj of json) {
131+
checkProperties(obj);
132+
}
133+
} else {
134+
checkProperties(json);
123135
}
124136
}
125137
@@ -136,7 +148,9 @@ const tokenGroups = operation["x-api-token-group"];
136148
</span>
137149
<ul>
138150
{tokenGroups.map((group) => (
139-
<li><code>{group}</code></li>
151+
<li>
152+
<code>{group}</code>
153+
</li>
140154
))}
141155
</ul>
142156
</Details>

src/components/CURL.astro

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,16 @@ import { Code } from "@astrojs/starlight/components";
55
66
type Props = z.input<typeof props>;
77
8+
const Record = z.record(z.string(), z.any());
9+
810
const props = z.object({
911
method: z
1012
.enum(["GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"])
1113
.default("GET"),
1214
url: z.string().url(),
1315
headers: z.record(z.string(), z.string()).default({}),
14-
json: z.record(z.string(), z.any()).optional(),
15-
form: z.record(z.string(), z.any()).optional(),
16+
json: z.union([Record, z.array(Record)]).optional(),
17+
form: Record.optional(),
1618
code: z
1719
.custom<Omit<ComponentProps<typeof Code>, "code" | "lang">>()
1820
.optional(),
@@ -41,7 +43,8 @@ if (json) {
4143
4244
if (form) {
4345
const formLines = Object.entries(form).map(
44-
([key, value]) => `\t--form "${key}=${value}"`,
46+
([key, value]) =>
47+
`\t--form "${key}=${value.toString().replaceAll('"', '\\"')}"`,
4548
);
4649
lines.push(...formLines);
4750
}

src/components/ModelCatalog.tsx

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useEffect, useState } from "react";
1+
import { useEffect, useState, useMemo } from "react";
22
import ModelInfo from "./models/ModelInfo";
33
import ModelBadges from "./models/ModelBadges";
44
import { authorData } from "./models/data";
@@ -19,6 +19,37 @@ const ModelCatalog = ({ models }: { models: WorkersAIModelsSchema[] }) => {
1919
capabilities: [],
2020
});
2121

22+
// List of model names to pin at the top
23+
const pinnedModelNames = [
24+
"@cf/meta/llama-3.3-70b-instruct-fp8-fast",
25+
"@cf/meta/llama-3.1-8b-instruct-fast",
26+
];
27+
28+
// Sort models by pinned status first, then by created_at date
29+
const sortedModels = useMemo(() => {
30+
return [...models].sort((a, b) => {
31+
// First check if either model is pinned
32+
const isPinnedA = pinnedModelNames.includes(a.name);
33+
const isPinnedB = pinnedModelNames.includes(b.name);
34+
35+
// If pinned status differs, prioritize pinned models
36+
if (isPinnedA && !isPinnedB) return -1;
37+
if (!isPinnedA && isPinnedB) return 1;
38+
39+
// If both are pinned, sort by position in pinnedModelNames array (for manual ordering)
40+
if (isPinnedA && isPinnedB) {
41+
return (
42+
pinnedModelNames.indexOf(a.name) - pinnedModelNames.indexOf(b.name)
43+
);
44+
}
45+
46+
// If neither is pinned, sort by created_at date (newest first)
47+
const dateA = a.created_at ? new Date(a.created_at) : new Date(0);
48+
const dateB = b.created_at ? new Date(b.created_at) : new Date(0);
49+
return dateB.getTime() - dateA.getTime();
50+
});
51+
}, [models]);
52+
2253
useEffect(() => {
2354
const params = new URLSearchParams(window.location.search);
2455

@@ -35,7 +66,7 @@ const ModelCatalog = ({ models }: { models: WorkersAIModelsSchema[] }) => {
3566
});
3667
}, []);
3768

38-
const mapped = models.map((model) => ({
69+
const mapped = sortedModels.map((model) => ({
3970
model: {
4071
...model,
4172
capabilities: model.properties
@@ -237,13 +268,19 @@ const ModelCatalog = ({ models }: { models: WorkersAIModelsSchema[] }) => {
237268

238269
const author = model.model.name.split("/")[1];
239270
const authorInfo = authorData[author];
271+
const isPinned = pinnedModelNames.includes(model.model.name);
240272

241273
return (
242274
<a
243275
key={model.model.id}
244-
className="mb-3 block w-full self-start rounded-md border border-solid border-gray-200 p-3 !text-inherit no-underline hover:bg-gray-50 dark:border-gray-700 dark:hover:bg-gray-800 lg:w-[48%]"
276+
className="relative mb-3 block w-full self-start rounded-md border border-solid border-gray-200 p-3 !text-inherit no-underline hover:bg-gray-50 dark:border-gray-700 dark:hover:bg-gray-800 lg:w-[48%]"
245277
href={`/workers-ai/models/${model.model_display_name}`}
246278
>
279+
{isPinned && (
280+
<span className="absolute right-2 top-1" title="Pinned model">
281+
📌
282+
</span>
283+
)}
247284
<div className="-mb-1 flex items-center">
248285
{authorInfo?.logo ? (
249286
<img

src/components/models/ModelBadges.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ const ModelBadges = ({ model }: { model: WorkersAIModelsSchema }) => {
1717
}
1818

1919
if (property_id === "planned_deprecation_date") {
20-
const timestamp = Math.floor(new Date(value).getTime() / 1000);
20+
const timestamp = Math.floor(new Date(value as string).getTime() / 1000);
2121

2222
if (Date.now() > timestamp) {
2323
return { variant: "danger", text: "Deprecated" };

src/components/models/ModelFeatures.tsx

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@ import type { WorkersAIModelsSchema } from "~/schemas";
22

33
const ModelFeatures = ({ model }: { model: WorkersAIModelsSchema }) => {
44
const nf = new Intl.NumberFormat("en-US");
5+
const currencyFormatter = new Intl.NumberFormat("en-US", {
6+
style: "currency",
7+
currency: "USD",
8+
maximumFractionDigits: 10,
9+
});
510
const properties: any = {};
611
model.properties.forEach((property: any) => {
712
properties[property.property_id] = property.value;
@@ -15,7 +20,7 @@ const ModelFeatures = ({ model }: { model: WorkersAIModelsSchema }) => {
1520
<thead>
1621
<tr>
1722
<>
18-
<th>Features</th>
23+
<th>Model Info</th>
1924
<th />
2025
</>
2126
</tr>
@@ -105,6 +110,19 @@ const ModelFeatures = ({ model }: { model: WorkersAIModelsSchema }) => {
105110
<td>Yes</td>
106111
</tr>
107112
)}
113+
{properties.price && properties.price.length > 0 && (
114+
<tr>
115+
<td>Unit Pricing</td>
116+
<td>
117+
{properties.price
118+
.map(
119+
(price: { price: number; unit: string }) =>
120+
`${currencyFormatter.format(price.price)} ${price.unit}`,
121+
)
122+
.join(", ")}
123+
</td>
124+
</tr>
125+
)}
108126
</tbody>
109127
</table>
110128
</>

src/components/models/data.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ import mistral from "../../assets/images/workers-ai/mistralai.svg";
55
import stabilityai from "../../assets/images/workers-ai/stabilityai.svg";
66
import huggingface from "../../assets/images/workers-ai/huggingface.svg";
77
import google from "../../assets/images/workers-ai/google.svg";
8+
import deepseek from "../../assets/images/workers-ai/deepseek.svg";
9+
import qwen from "../../assets/images/workers-ai/qwen.svg";
10+
import blackforestlabs from "../../assets/images/workers-ai/blackforestlabs.svg";
811

912
export const authorData: Record<string, { name: string; logo: string }> = {
1013
openai: {
@@ -39,4 +42,16 @@ export const authorData: Record<string, { name: string; logo: string }> = {
3942
name: "Google",
4043
logo: google.src,
4144
},
45+
"deepseek-ai": {
46+
name: "DeepSeek",
47+
logo: deepseek.src,
48+
},
49+
qwen: {
50+
name: "Qwen",
51+
logo: qwen.src,
52+
},
53+
"black-forest-labs": {
54+
name: "Black Forest Labs",
55+
logo: blackforestlabs.src,
56+
},
4257
};
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
_build:
3+
publishResources: false
4+
render: never
5+
list: never
6+
7+
name: "Override cache rules cache settings in `request.cf` object for Fetch API"
8+
sort_date: "2023-08-01"
9+
enable_date: "2025-04-02"
10+
enable_flag: "request_cf_overrides_cache_rules"
11+
disable_flag: "no_request_cf_overrides_cache_rules"
12+
---
13+
14+
This flag changes the behavior of cache when requesting assets via the [Fetch API](/workers/runtime-apis/fetch). Cache settings specified in the `request.cf` object, such as `cacheEverything` and `cacheTtl`, are now given precedence over any [Cache Rules](/cache/how-to/cache-rules/) set.

src/content/docs/agents/model-context-protocol/authorization.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ sequenceDiagram
7373
Note over C,M: Begin standard MCP message exchange
7474
```
7575

76-
Remember — [authentication is different from authorization](https://www.cloudflare.com/learning/access-management/authn-vs-authz/). Your MCP Server can handle authorization itself, while still relying on an external authentication service to first authenticate users. The [example](/agents/guides/remote-mcp-server) in getting started provides a mock authentdcation flow. You will need to implement your own authentication handler — either handling authentication yourself, or using an external authentication services.
76+
Remember — [authentication is different from authorization](https://www.cloudflare.com/learning/access-management/authn-vs-authz/). Your MCP Server can handle authorization itself, while still relying on an external authentication service to first authenticate users. The [example](/agents/guides/remote-mcp-server) in getting started provides a mock authentication flow. You will need to implement your own authentication handler — either handling authentication yourself, or using an external authentication services.
7777

7878
### (2) Third-party OAuth Provider
7979

0 commit comments

Comments
 (0)