Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/agent-skills-telemetry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"wrangler": minor
---

Add telemetry for detecting whether AI coding agents have Cloudflare skills installed

Wrangler now includes a `currentAgentSkillsInstalled` property in telemetry events that reports whether the current AI coding agent has Cloudflare skills present on disk. The value distinguishes between skills installed automatically by Wrangler (`"automatic"`), skills installed manually by the user (`"manual"`), no skills present (`false`), or no supported agent detected (`null`). Skill names are fetched from the GitHub Contents API with a 24-hour disk cache to avoid rate limits.
7 changes: 7 additions & 0 deletions .changeset/curly-deploy-helpers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@cloudflare/deploy-helpers": minor
---

Add `@cloudflare/deploy-helpers` package.

This introduces a shared internal package for deploy-related helper types and code.
12 changes: 12 additions & 0 deletions .changeset/dependabot-update-14003.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
"miniflare": patch
"wrangler": patch
---

Update dependencies of "miniflare", "wrangler"

The following dependency versions have been updated:

| Dependency | From | To |
| ---------- | ------------ | ------------ |
| workerd | 1.20260521.1 | 1.20260526.1 |
8 changes: 8 additions & 0 deletions .changeset/improve-pages-error-messages.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"wrangler": patch
---

Improve error messages for Pages CLI commands

Error messages across `wrangler pages` subcommands (deploy, dev, secret, project, etc.) now provide clearer descriptions and actionable guidance. For example, instead of "Must specify a project name.", you'll now see "Missing Pages project name. Use --project-name <name> or set the name in your wrangler.jsonc configuration file."

5 changes: 5 additions & 0 deletions .changeset/plain-deploy-gate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"wrangler": minor
---

Add `--x-deploy-helpers` to gate an upcoming deploy path refactor.
33 changes: 33 additions & 0 deletions .changeset/rare-ducks-occur.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
"@cloudflare/vite-plugin": minor
---

Add `assetsOnly` (entry Worker) and `devOnly` (auxiliary Workers) options to the plugin config

Both options accept a `boolean` or a function that returns a `boolean`. The function is evaluated lazily at build time, allowing frameworks to provide the value after initialization.

Use `assetsOnly` on the entry Worker to skip building the Worker and instead emit an assets-only Wrangler config to the client output directory. This enables frameworks such as Astro to use the `ssr` environment during development but produce a fully static app for deployment.

```ts
export default defineConfig({
plugins: [
cloudflare({
assetsOnly: () => isStaticBuild,
}),
],
});
```

Use `devOnly` on an auxiliary Worker to include it during `vite dev` but skip it at build time.

```ts
export default defineConfig({
plugins: [
cloudflare({
auxiliaryWorkers: [
{ configPath: "./dev-only-worker/wrangler.jsonc", devOnly: true },
],
}),
],
});
```
9 changes: 9 additions & 0 deletions .changeset/workflows-schedules-rename.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"wrangler": patch
---

Rename Workflow binding `schedule` property to `schedules`

The `schedule` property on Workflow bindings introduced in [#13467](https://github.com/cloudflare/workers-sdk/pull/13467) has been renamed to `schedules` to match the control plane API.

> **Note:** This remains a configuration-only change. Scheduled triggering of Workflow instances is not yet available — adding `schedules` to a Workflow binding will not result in scheduled invocations at this time.
52 changes: 52 additions & 0 deletions packages/deploy-helpers/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"name": "@cloudflare/deploy-helpers",
"version": "0.0.1",
"description": "Internal deploy helpers for workers-sdk. Not intended for external use — APIs may change without notice.",
"homepage": "https://github.com/cloudflare/workers-sdk/tree/main/packages/deploy-helpers#readme",
"bugs": {
"url": "https://github.com/cloudflare/workers-sdk/issues"
},
"license": "MIT OR Apache-2.0",
"author": "workers-devprod@cloudflare.com",
"repository": {
"type": "git",
"url": "https://github.com/cloudflare/workers-sdk.git",
"directory": "packages/deploy-helpers"
},
"files": [
"dist"
],
"sideEffects": false,
"exports": {
".": {
"import": "./dist/index.mjs",
"types": "./dist/index.d.mts"
}
},
"scripts": {
"build": "tsup",
"check:type": "tsc -p ./tsconfig.json",
"deploy": "echo 'no deploy'",
"dev": "concurrently -c black,blue --kill-others-on-fail false \"pnpm tsup --watch src\" \"pnpm run check:type --watch --preserveWatchOutput\"",
"test": "vitest",
"test:ci": "vitest run",
"type:tests": "tsc -p ./tests/tsconfig.json"
},
"devDependencies": {
"@cloudflare/containers-shared": "workspace:*",
"@cloudflare/workers-tsconfig": "workspace:*",
"@cloudflare/workers-utils": "workspace:*",
"@types/node": "catalog:default",
"concurrently": "^8.2.2",
"miniflare": "workspace:*",
"tsup": "8.3.0",
"typescript": "catalog:default",
"vitest": "catalog:default"
},
"volta": {
"extends": "../../package.json"
},
"workers-sdk": {
"prerelease": true
}
}
1 change: 1 addition & 0 deletions packages/deploy-helpers/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./shared/types";
113 changes: 113 additions & 0 deletions packages/deploy-helpers/src/shared/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import type { ContainerNormalizedConfig } from "@cloudflare/containers-shared";
import type {
AssetsOptions,
LegacyAssetPaths,
CfPlacement,
Config,
EphemeralDirectory,
Route,
Entry,
} from "@cloudflare/workers-utils";
import type { NodeJSCompatMode } from "miniflare";

/**
* Shared fields produced by merging CLI args with wrangler config.
* After this point, no raw config/arg merging should happen.
*
* Use props for all resolved/merged values. Only access config directly
* for raw values that aren't merged with CLI args (e.g., config.durable_objects,
* config.unsafe, config.tail_consumers).
*/
export type SharedDeployVersionsProps = {
config: Config;
/** Merged from args.script/config.main/config.site.entry-point/config.assets. */
entry: Entry;
/** From config.rules. */
rules: Config["rules"];
/** Merged: --name arg ?? config.name, with CI override applied. */
name: string;
workerNameOverridden: boolean;
/** Merged: --compatibility-date arg ?? config.compatibility_date. Still optional — validated as required in stage 4. */
compatibilityDate: string | undefined;
/** Merged: --compatibility-flags arg ?? config.compatibility_flags. */
compatibilityFlags: string[];
/** computed based on compat date and args */
nodejsCompatMode: NodeJSCompatMode;
/** Merged from --assets arg and config.assets. */
assetsOptions: AssetsOptions | undefined;
/** Merged: --jsx-factory arg || config.jsx_factory. */
jsxFactory: string;
/** Merged: --jsx-fragment arg || config.jsx_fragment. */
jsxFragment: string;
/** Merged: --tsconfig arg ?? config.tsconfig. */
tsconfig: string | undefined;
/** Merged: --minify arg ?? config.minify. */
minify: boolean | undefined;
/** Merged: !(--bundle arg ?? !config.no_bundle). */
noBundle: boolean;
/** Merged: --upload-source-maps arg ?? config.upload_source_maps. */
uploadSourceMaps: boolean | undefined;
/** Merged: --keep-vars arg || config.keep_vars. */
keepVars: boolean;
/** Merged from --site arg and config.site. */
isWorkersSite: boolean;
/** Merged: { ...config.define, ...--define arg }. CLI overrides config. */
defines: Record<string, string>;
/** Merged: { ...config.alias, ...--alias arg }. CLI overrides config. */
alias: Record<string, string>;
/**
* Whether to use the deprecated service environments API path.
* True only when config opts in (legacy_env: false) AND --env is specified.
*/
useServiceEnvApiPath: boolean;
placement: CfPlacement | undefined;
/** Output directory for the bundled Worker. From --outdir arg or a temp directory. */
destination: string | EphemeralDirectory;
/** From --dry-run arg. */
dryRun: boolean;
/** From --env arg. */
env: string | undefined;
/** From --outdir arg. Already used to derive `destination`, but also needed for outdir README and noBundleWorker. */
outdir: string | undefined;
/** From --outfile arg. */
outfile: string | undefined;
/** From --tag arg. */
tag: string | undefined;
/** From --message arg. */
message: string | undefined;
/** From --secrets-file arg. */
secretsFile: string | undefined;
/** From collectKeyValues(--var arg). Pre-resolved key-value pairs. */
var: Record<string, string>;
/** From --experimental-auto-create arg. */
experimentalAutoCreate: boolean;
};

export type DeployProps = SharedDeployVersionsProps & {
/** Discriminant for DeployProps vs VersionsUploadProps */
command: "deploy";
/** Merged from --site arg and config.site. */
legacyAssetPaths: LegacyAssetPaths | undefined;
/** Merged: --triggers arg ?? config.triggers.crons. */
triggers: string[] | undefined;
/** Merged: --routes arg ?? config.routes ?? config.route. AND --domains and custom_domains*/
routes: Route[];
/** Merged: --logpush arg ?? config.logpush. */
logpush: boolean | undefined;
containers: ContainerNormalizedConfig[];
/** From --dispatch-namespace arg. Deploy-only (Workers for Platforms). */
dispatchNamespace: string | undefined;
/** From --strict arg. Deploy-only. */
strict: boolean;
/** From --metafile arg. Deploy-only. */
metafile: string | boolean | undefined;
/** From --old-asset-ttl arg. Deploy-only. */
oldAssetTtl: number | undefined;
};

export type VersionsUploadProps = SharedDeployVersionsProps & {
/** Discriminant for DeployProps vs VersionsUploadProps */
command: "versions upload";
/** CLI-only (--preview-alias), or auto-generated from CI branch name. */
previewAlias: string | undefined;
};
7 changes: 7 additions & 0 deletions packages/deploy-helpers/tests/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { describe, it } from "vitest";

describe("placeholder", () => {
it("should pass", ({ expect }) => {
expect(true).toBe(true);
});
});
8 changes: 8 additions & 0 deletions packages/deploy-helpers/tests/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"extends": "@cloudflare/workers-tsconfig/tsconfig.json",
"compilerOptions": {
"module": "preserve",
"types": ["node"]
},
"include": ["../*.d.ts", "**/*.ts", "**/*.js"]
}
10 changes: 10 additions & 0 deletions packages/deploy-helpers/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"extends": "@cloudflare/workers-tsconfig/tsconfig.json",
"compilerOptions": {
"module": "esnext",
"types": ["node"],
"tsBuildInfoFile": ".tsbuildinfo"
},
"include": ["**/*.ts", "**/*.js"],
"exclude": ["dist", "node_modules", "**/__tests__/**", "**/*.test.ts"]
}
17 changes: 17 additions & 0 deletions packages/deploy-helpers/tsup.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { defineConfig } from "tsup";

export default defineConfig(() => [
{
treeshake: true,
keepNames: true,
entry: ["src/index.ts"],
platform: "node",
format: "esm",
dts: true,
outDir: "dist",
tsconfig: "tsconfig.json",
metafile: true,
sourcemap: process.env.SOURCEMAPS !== "false",
external: ["@cloudflare/*"],
},
]);
16 changes: 16 additions & 0 deletions packages/deploy-helpers/turbo.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"$schema": "http://turbo.build/schema.json",
"extends": ["//"],
"tasks": {
"build": {
"inputs": ["$TURBO_DEFAULT$", "!**/__tests__/**"],
"outputs": ["dist/**"],
"env": ["SOURCEMAPS"],
"passThroughEnv": ["PWD"]
},
"test:ci": {
"dependsOn": ["build"],
"env": ["LC_ALL", "TZ"]
}
}
}
11 changes: 11 additions & 0 deletions packages/deploy-helpers/vitest.config.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { defineConfig } from "vitest/config";

export default defineConfig({
test: {
testTimeout: 15_000,
pool: "forks",
include: ["**/tests/**/*.test.ts"],
reporters: ["default"],
mockReset: true,
},
});
11 changes: 7 additions & 4 deletions packages/devprod-status-bot/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,16 @@ async function getBotMessage(ai: Ai, prompt: string) {
role: "user",
content: prompt,
},
] as RoleScopedChatInput[],
],
} satisfies ChatCompletionsMessagesInput;
const message = (await ai.run("@cf/google/gemma-4-26b-a4b-it", chat)) as {
choices?: { message: { content: string } }[];
};
const message = await ai.run("@cf/google/gemma-4-26b-a4b-it", chat);
if (!("response" in message)) {
const content = message.choices?.[0]?.message.content;
if (!content) {
return "I'm feeling a bit poorly 🥲—try asking me for a message later!";
}
return message.response;
return content;
}

async function isWranglerTeamMember(
Expand Down
2 changes: 1 addition & 1 deletion packages/miniflare/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
"@cspotcode/source-map-support": "0.8.1",
"sharp": "^0.34.5",
"undici": "catalog:default",
"workerd": "1.20260521.1",
"workerd": "1.20260526.1",
"ws": "catalog:default",
"youch": "4.1.0-beta.10"
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
export default {
async fetch(_req, env) {
const content = await env.AI.run("@cf/google/gemma-4-26b-a4b-it", {
messages: [],
});
const content = (await env.AI.run("@cf/google/gemma-4-26b-a4b-it", {
messages: [{ role: "user", content: "Hello" }],
})) as { choices: { message: { content: string } }[] };

return Response.json({
response: content.response,
response: content.choices[0].message.content,
});
},
} satisfies ExportedHandler<{ AI: Ai }>;
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
import fs from "node:fs";
import semverGte from "semver/functions/gte";
import { version as viteVersion } from "vite";
import { onTestFinished, test } from "vitest";
import { isWindows } from "../vitest-setup";

export * from "../vitest-setup";
export * from "./responses";

export function satisfiesViteVersion(minVersion: string): boolean {
return semverGte(viteVersion, minVersion);
}
export { satisfiesMinimumViteVersion } from "./vite-version";

/** Common options to use with `vi.waitFor()` */
export const WAIT_FOR_OPTIONS = {
Expand Down
Loading
Loading