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
18 changes: 16 additions & 2 deletions .claude/rules/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,14 @@ requested feature set better than the minimal init template.
| `queues-demo` | Queue producer + consumer in one routeable worker, with consumed message state in KV. `wrangler.toml`. Use when requests should enqueue background work. |
| `durable-objects-demo` | Same-worker Durable Object class with SQLite-backed counter state. `wrangler.toml`. Use when one logical object needs serialized state. |
| `workflows-demo` | Workflow class with start/status/approval routes. `wrangler.toml`. Use when work spans multiple durable steps or needs CLI-visible instance state. |
| `ai-agent-demo` | Responses function-tool loop through `env.AI`. `wrangler.toml`. Use when a Worker needs OpenAI-compatible agent inference without receiving provider credentials. |
| `env-overrides-demo` | `[env.preview]` and `[env.production]` blocks showing WDL-specific env override behavior: no worker-name suffix, env-scoped vars that do not inherit top-level vars, and assets override. `wrangler.toml`. Layer on top of any of the above when you need env-specific config. |
| `inspection-demo` | Multi-binding example combining D1 + KV + R2 + assets. `wrangler.toml`. Use as a reference when the worker needs more than one binding. |

To pick: for a worker that serves a page or fronts an external API, start from
`pages-assets`. For pure compute, cron, or queue work, start from `hello-jsonc`,
`cron-demo`, or `queues-demo`.
`cron-demo`, or `queues-demo`. For a Responses function-tool agent, start from
`ai-agent-demo`.

## Scaffolding steps

Expand Down Expand Up @@ -77,7 +79,16 @@ To pick: for a worker that serves a page or fronts an external API, start from
wdl deploy . --ns <ns>
```
For `env-overrides-demo`, use `wdl deploy . --env preview --ns <ns>` or
`wdl deploy . --env production --ns <ns>`.
`wdl deploy . --env production --ns <ns>`. For `ai-agent-demo`, configure the
namespace provider credential and a Worker-level demo access token before
deploy:
```bash
wdl ai providers put openai --file provider.openai.json --ns <ns>
printf '%s' "$OPENAI_API_KEY" | wdl ai credential put openai --ns <ns>
AI_DEMO_TOKEN="$(openssl rand -hex 32)"
printf '%s' "$AI_DEMO_TOKEN" | wdl secret put --worker <project-name> AI_DEMO_TOKEN --ns <ns>
wdl deploy . --ns <ns>
```

## Anti-patterns

Expand All @@ -92,6 +103,9 @@ To pick: for a worker that serves a page or fronts an external API, start from
worker actually calls.
- ❌ Leaving `"name": "<example-name>"` in `package.json` or wrangler config.
Two workers with the same name collide on deploy.
- ❌ Removing the `ai-agent-demo` bearer gate or deploying a derived public AI
endpoint without application authentication. WDL does not provide a spend
quota for provider calls.

## Deploy

Expand Down
79 changes: 58 additions & 21 deletions .claude/skills/wdl-deploy/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: wdl-deploy
description: Deploy and manage Cloudflare Workers-style projects on the WDL platform via the `wdl` CLI (init, deploy, config explain, whoami, doctor, tail, secret, workers, delete, d1, r2, workflows). Trigger when the user asks to scaffold or deploy a Worker, inspect resolved CLI configuration, identify the active control token/principal, run diagnostics, tail live logs, configure KV / Queues / Durable Objects / Workflows bindings, manage D1 / R2 / secrets through `wdl`, or troubleshoot wdl CLI output. Works with `wrangler.json` / `wrangler.jsonc` / `wrangler.toml` projects pinned to wrangler@^4.
description: Deploy and manage Cloudflare Workers-style projects on the WDL platform via the `wdl` CLI (init, deploy, config explain, whoami, doctor, tail, secret, workers, delete, d1, r2, ai, workflows). Trigger when the user asks to scaffold or deploy a Worker, inspect resolved CLI configuration, identify the active control token/principal, run diagnostics, tail live logs, configure KV / Queues / Durable Objects / Workflows / AI bindings, manage D1 / R2 / AI providers / secrets through `wdl`, or troubleshoot wdl CLI output. Works with `wrangler.json` / `wrangler.jsonc` / `wrangler.toml` projects pinned to wrangler@^4.
---

# WDL CLI deploy skill
Expand Down Expand Up @@ -33,6 +33,8 @@ Open the relevant doc before answering:
queue handlers, message size and retry limits.
- `docs/workflows.md` — `[[workflows]]` config, the WDL Workflows surface,
`wdl workflows` instance management.
- `docs/ai.md` — `[ai]` config, namespace provider/credential management,
Responses/tools/SSE, OpenAI SDK use, and WebSocket inference.
- `docs/kv.md` — `[[kv_namespaces]]`, immediately visible writes, batch reads,
`list()` metadata / pagination differences.
- `docs/assets.md` — `[assets]` directory + `env.ASSETS`, size caps, default
Expand Down Expand Up @@ -65,27 +67,31 @@ default platform-domain URL; it requires at least one `route` / `routes` pattern
and is not inferred. The deploy summary prints every active route-pattern URL
hint, preserving the trailing `*` on prefix patterns, and includes the
platform-domain URL only while it is enabled. Cloudflare's separate
`preview_urls` field is unsupported and rejected by the CLI. WDL-only
`preview_urls` field is unsupported and rejected by the CLI. WDL consumes
`[[exports]]`, `[[platform_bindings]]`, `[[triggers.schedules]]`,
`[[services]].ns`, and `[wdl]` are parsed by the CLI and removed from Wrangler's
temporary bundle config; other fields retain their existing Wrangler passthrough
behavior. Specific nested fields that WDL cannot represent are rejected rather
than silently dropped, including Cloudflare Artifacts `triggers.events`
subscriptions and R2 `local_dev.experimental_s3_credentials`.
`[wdl] session_policy` accepts `preserve` or `restart`. The default `preserve`
leaves loaded Durable Object facets on the version that built them until the
host actor restarts or the facet is deleted, and keeps established WebSockets
draining while their backend stays healthy. `restart` closes the worker's open
WebSockets with code `1012` at promotion and retires stale facets on their next
dispatch, preserving SQLite state. Wrangler's object-shaped declarative
`exports` config is unsupported. The dry-run child hides Wrangler's banner (and
its normal update check) and disables anonymous telemetry. Wrangler may still
consult the configured npm registry when reporting an unknown configuration
field; project build hooks retain their normal network access. For
`[[services]]` and `[[exports]]`, read `docs/deploy.md`: tenant JSRPC may
delegate service or Durable Object class stubs as opaque capabilities, but the
receiver cannot rewrite their host-authored caller properties. Keep delegated
stubs in memory; long-term irrevocable stub storage is unsupported.
`[[services]].ns`, and `[wdl]` itself and removes those WDL extensions from
Wrangler's temporary bundle config. `[ai]` is standard Wrangler configuration
and stays in that config for Wrangler validation. If a selected named
environment omits its own `ai`, the CLI warns that the top-level binding is not
inherited; WDL independently maps its `binding` into the WDL manifest. Other
fields retain their existing Wrangler passthrough behavior. Specific nested
fields that WDL cannot represent are rejected rather than silently dropped,
including Cloudflare Artifacts `triggers.events` subscriptions and R2
`local_dev.experimental_s3_credentials`. `[wdl] session_policy` accepts
`preserve` or `restart`. The default `preserve` leaves loaded Durable Object
facets on the version that built them until the host actor restarts or the facet
is deleted, and keeps established WebSockets draining while their backend stays
healthy. `restart` closes the worker's open WebSockets with code `1012` at
promotion and retires stale facets on their next dispatch, preserving SQLite
state. Wrangler's object-shaped declarative `exports` config is unsupported. The
dry-run child hides Wrangler's banner (and its normal update check) and disables
anonymous telemetry. Wrangler may still consult the configured npm registry when
reporting an unknown configuration field; project build hooks retain their
normal network access. For `[[services]]` and `[[exports]]`, read
`docs/deploy.md`: tenant JSRPC may delegate service or Durable Object class
stubs as opaque capabilities, but the receiver cannot rewrite their
host-authored caller properties. Keep delegated stubs in memory; long-term
irrevocable stub storage is unsupported.

Never recommend setting `CONTROL_CONNECT_HOST` outside local development: it
overrides the TCP target the admin token connects to (Host header + TLS SNI
Expand All @@ -101,6 +107,37 @@ trusted projects. For a less-trusted or third-party project, recommend
`--no-token-store` (or `WDL_TOKEN_STORE=off`) with an ephemeral `--token` /
`--control-url`, rather than relying on the global store.

`wdl ai`, `wdl secret`, and `wdl token` redact invalid argument details. When a
string option precedes the complete subcommand path and its separate value is
also a command word, put the subcommand first or use `--flag=value`; for
example, use `wdl secret list --worker put` or `wdl secret --worker=put list`
for a worker named `put`.

Use `wdl ai providers init <provider>` to scaffold a one-model provider file
without loading credentials or contacting Control. It offers editable defaults
for kind, the `primary` alias, model id, and output filename. It pre-fills
`gpt-5.6-luna`, `grok-4.6`, or `deepseek-v4-flash` for the matching adapter and
emits a conservative text-only Responses descriptor over HTTP/SSE. It refuses to
overwrite files. The defaults reject non-text input, `previous_response_id`
continuation, and binary WebSocket frames until the matching `inputModalities`,
`previousResponseId`, or `binaryFrames` declaration is enabled. The bundled AI
agent demo needs `previousResponseId: true`, which its provider file already
declares. Other capability flags are catalog declarations and do not currently
gate WDL requests; edit the JSON for other model-specific protocols or
capabilities.

`wdl ai providers put` replaces the complete provider record and accepts only a
project-contained `{ kind, models }` file; omitted model aliases are removed.
When editing an existing provider, derive the file with
`wdl ai providers get <provider> --json | jq '.provider | {kind, models}'`
instead of feeding response-only fields back to Control.

Treat `wdl ai providers delete` as destructive: it removes both provider
metadata and its credential and has no dry-run. Run `wdl config explain` first
to confirm the resolved namespace, inspect the target with
`wdl ai providers get <provider> --ns <namespace>`, and use the same explicit
`--ns` for deletion. Never add `--yes` without user confirmation.

`templates/AGENTS.md` is the generic agent entrypoint that `wdl init` copies
into every new project. It points at the same `docs/` through
`node_modules/@wdl-dev/cli/docs/<name>.md` paths.
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,20 @@

## Unreleased

### Added

- Add the `[ai]` binding, an offline provider JSON initializer, namespace
provider and credential management commands, model discovery,
OpenAI-compatible SDK guidance, and a Responses function-tool agent example
protected by a Worker-level bearer token.

### Changed

- `wdl ai`, `wdl secret`, and `wdl token` now redact invalid argument details.
When a separate string option before the complete subcommand path has a value
that is also a command word, put the subcommand first or use `--flag=value` to
disambiguate it.

## 1.7.1

### Changed
Expand Down
Loading