Skip to content

workspace: add artifacts interface to worker backend#7

Open
aron-cf wants to merge 6 commits into
mainfrom
artifacts
Open

workspace: add artifacts interface to worker backend#7
aron-cf wants to merge 6 commits into
mainfrom
artifacts

Conversation

@aron-cf

@aron-cf aron-cf commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

This pull request adds first-class Cloudflare Artifacts support to @cloudflare/workspace. A worker can now wrap an ARTIFACTS binding with createArtifact(binding, sessionId) and work with local repository names while the library handles session scoping. That gives each agent, task, or user its own isolated set of repositories inside the same Artifacts namespace.

The new client covers the repository and token lifecycle: create, get, list, import, delete, create token, list tokens, get token metadata, and revoke token. Repository names are scoped before they touch the binding and unscoped before they come back to the caller. The scoped name uses a legal Artifacts repository name, such as session123__build-cache, while callers continue to pass and receive build-cache.

import { createArtifact } from "@cloudflare/workspace/artifacts";

const artifacts = createArtifact(env.ARTIFACTS, ctx.id.toString());

const repo = await artifacts.create("build-cache", {
  description: "Cached build output for this run",
  setDefaultBranch: "main",
});

console.log(repo.name); // "build-cache"
console.log(repo.remote); // Git remote for the scoped Artifacts repo

const token = await artifacts.createToken("build-cache", "read", 3600);
console.log(token.plaintext); // Capture this once. It is not returned by list/get.

const repos = await artifacts.list();
// Repos from other sessions in the same namespace are filtered out.

The same implementation is also available as an argv-style interface. That gives shell users and agents a stable command surface with machine-readable JSON output and predictable exit codes.

const result = await artifacts.cli({
  argv: ["repo", "create", "build-cache", "--description", "CI output"],
});

if (result.exitCode !== 0) {
  throw new Error(result.stderr);
}

const created = JSON.parse(result.stdout);

The worker backend can expose that CLI as an opt-in artifacts shell command. The command is not registered globally because the Artifacts binding belongs to the consuming worker, not to the workspace package itself.

import { ShellWorker, defineArtifactsCommand } from "@cloudflare/workspace/backends/worker";
import { createArtifact } from "@cloudflare/workspace/artifacts";
import type { CustomCommand } from "just-bash";

export class MyShell extends ShellWorker<Env> {
  protected override extraCommands(): CustomCommand[] {
    const artifacts = createArtifact(this.env.ARTIFACTS, this.env.SESSION_ID);
    return [defineArtifactsCommand({ artifacts })];
  }
}

With that command registered, code running through bash.exec can call the same surface directly:

artifacts repo create build-cache --description "CI output"
artifacts repo list
artifacts token create build-cache --scope read --ttl 3600

The implementation uses the global Cloudflare Workers Artifacts types from @cloudflare/workers-types instead of redeclaring the binding shape. The in-memory fake used by tests implements the same Artifacts interface and validates repository names against the binding's documented character set, so tests catch shape drift and invalid scoped names.

The CLI is designed to be safe for agents and logs. token create is the only token command that prints plaintext. token list, token get, and token revocation print metadata or a constant confirmation, so a caller does not accidentally echo a secret while revoking by plaintext.

Documentation is included in docs/14_artifacts_interface.md, with cross-links from the workspace docs and package README. The examples/think worker now shows optional typed Artifacts integration: it detects an ARTIFACTS binding when configured and returns an empty list when the binding is absent, so the example still runs without Artifacts.

Validation run:

npm run format
npx biome check .
npx vitest run src/artifacts/ src/backends/worker/artifacts-command.test.ts
npm test --workspace @cloudflare/workspace
npm run build --workspace @cloudflare/workspace
npm run typecheck --workspace @cloudflare/example-think

A filtered npm test --workspace @cloudflare/workspace -- src/artifacts/ ... command is not a useful shortcut for this package because the package test script forwards the filter to every Vitest config, including configs whose include patterns do not contain those files. The unfiltered workspace package test passes.

@aron-cf aron-cf marked this pull request as ready for review June 16, 2026 19:43
aron-cf added 6 commits June 17, 2026 21:46
Add the @cloudflare/workspace/artifacts subpath with a session-scoped
facade over the Cloudflare Artifacts Workers binding. Repository names
are scoped with a legal separator, list walks pages internally, and
CLI-shaped commands dispatch through the same typed client.

Add tests and a fake Artifacts binding that uses the Workers binding
shapes so the client and CLI behavior are covered without relying on
remote services.
Add optional Artifacts configuration to Workspace and expose a
session-scoped workspace.artifacts client. WorkspaceStub now carries an
artifacts target alongside fs, shell, and git, so the worker-backend
shell can register a built-in artifacts command without host-specific
wiring.

Keep the command available when no binding is configured, but make
operations fail with a clear configuration error. Also add a small
/dev/null virtual path for the worker shell and keep the dynamic worker
compatibility date current.
Teach the argv-driven git push command to split a single-colon
refspec such as HEAD:main into the local ref and remote ref expected
by the underlying git client. This matches the common git push URL
HEAD:branch shape used by generated Artifact repositories.
Document the session-scoped Artifacts facade, its CLI surface, and the
worker-backend shell command. Cross-link the Artifacts interface from
the docs index and Git / worker-backend docs, and describe the
Workspace-level binding configuration used by the shell.
Add optional Artifacts support to the think example. When a binding is
configured, the workflow can publish a generated review branch to an
Artifact repository and return the remote and clone details; without a
binding the example keeps running normally.
Add an example Worker that exposes POST /create. The endpoint gets a
Workspace from a minimal Durable Object, uses the worker backend shell
to clone and rewrite examples/worker, creates a session-scoped
Artifact repository through the built-in shell command, pushes the
generated project, and returns a short-lived read clone link.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant