diff --git a/.agents/skills/release/SKILL.md b/.agents/skills/release/SKILL.md new file mode 100644 index 00000000..0e1bbf9f --- /dev/null +++ b/.agents/skills/release/SKILL.md @@ -0,0 +1,206 @@ +--- +name: release +description: Prepare and publish @onkernel/cua-ai and @onkernel/cua-agent npm releases from kernel/cua. Use when checking release readiness, choosing package versions, writing package changelogs, committing release metadata to main, pushing package-prefixed tags, or monitoring release workflows. +--- + +# Release + +Use this workflow to release `@onkernel/cua-ai` and `@onkernel/cua-agent`. The +packages do not need to release in lockstep. + +If a release run hits an unexpected bump, unclear decision, missing command, or +avoidable manual step, update this skill as part of the release cleanup. Keep +the note concise and operational so the next release is faster and less +error-prone. + +## Package Map + +| package | directory | tag prefix | workflow | +| --- | --- | --- | --- | +| `@onkernel/cua-ai` | `packages/ai` | `cua-ai/v` | `release-cua-ai.yml` | +| `@onkernel/cua-agent` | `packages/agent` | `cua-agent/v` | `release-cua-agent.yml` | + +Release `@onkernel/cua-ai` before `@onkernel/cua-agent` when both are changing +or when the agent package depends on the new AI package version. + +## Quick Start + +1. Sync `main` and tags: + +```bash +git switch main +git pull --ff-only origin main +git fetch --tags origin +``` + +2. Check release readiness: + +```bash +git status --short +npm view @onkernel/cua-ai versions --json +npm view @onkernel/cua-agent versions --json +test -f .github/workflows/release-cua-ai.yml +test -f .github/workflows/release-cua-agent.yml +``` + +3. For each package, find the previous release tag: + +```bash +git tag --list "cua-ai/v*" --sort=-v:refname | head -1 +git tag --list "cua-agent/v*" --sort=-v:refname | head -1 +``` + +If no tag exists, treat the next release as the package's current +`package.json` version unless npm already has that version. + +4. Inspect package-specific changes since the last tag: + +```bash +git log --oneline ..HEAD -- packages/ai package.json package-lock.json tsconfig.base.json +git diff --name-status ..HEAD -- packages/ai package.json package-lock.json tsconfig.base.json + +git log --oneline ..HEAD -- packages/agent packages/ai package.json package-lock.json tsconfig.base.json +git diff --name-status ..HEAD -- packages/agent packages/ai package.json package-lock.json tsconfig.base.json +``` + +For `@onkernel/cua-agent`, include `packages/ai` changes only when they affect +the published agent dependency or runtime behavior. + +## Version Choice + +Choose a version per package from source changes, existing npm versions, and the +previous tag: + +- No package-relevant changes: do not release that package. +- Bug fixes, docs that affect package consumers, dependency metadata, or small + behavior fixes: patch. +- New exported APIs, new model/provider support, new examples intended for + consumers, or materially expanded behavior: minor. +- Breaking API or behavior changes: major. While packages are `0.x`, use a + minor bump for breaking changes unless the package is intentionally moving to + `1.0.0`. + +The candidate version must be greater than both the last tag for that package +and every version returned by `npm view versions --json`. + +## Changelog + +Update only the changelog for packages being released: + +- `packages/ai/CHANGELOG.md` +- `packages/agent/CHANGELOG.md` + +Add a new top entry: + +```markdown +## - YYYY-MM-DD + +- ... +``` + +Write customer-facing changes. Do not dump commit subjects, internal issue +names, Slack context, or vague entries like "misc improvements." Group details +only when it improves readability. If the release is only metadata or docs, +say that plainly. + +## Edit Release Metadata + +Set versions explicitly: + +```bash +npm pkg set version= --workspace @onkernel/cua-ai +npm pkg set version= --workspace @onkernel/cua-agent +``` + +When releasing `@onkernel/cua-agent`, ensure its `@onkernel/cua-ai` dependency +points at the intended published AI package version. Edit +`packages/agent/package.json` directly if `npm pkg set` is awkward for the +scoped dependency key. + +Refresh the lockfile: + +```bash +npm install --package-lock-only +``` + +## Validate + +Run the checks for each package being released: + +```bash +npm ci +npm run build --workspace @onkernel/cua-ai +npm test --workspace @onkernel/cua-ai -- test/api-keys.test.ts test/models.test.ts test/providers.test.ts test/runtime-spec.test.ts test/tools.test.ts test/yutori-payload.test.ts +npm pack --workspace @onkernel/cua-ai --dry-run +``` + +For `@onkernel/cua-agent`: + +```bash +npm run build --workspace @onkernel/cua-ai +npm run build --workspace @onkernel/cua-agent +npm test --workspace @onkernel/cua-agent -- test/agent.test.ts test/tool-exhaustiveness.test.ts +npm pack --workspace @onkernel/cua-agent --dry-run +``` + +Do not push release tags if build, tests, or pack dry-runs fail. + +## Commit To Main + +Direct commits to `main` are acceptable for release metadata. Keep the commit +limited to package versions, changelogs, and `package-lock.json`. + +```bash +git status --short +git add package-lock.json packages/ai/package.json packages/ai/CHANGELOG.md packages/agent/package.json packages/agent/CHANGELOG.md +git commit -m "Release CUA packages" +git push origin main +``` + +Use a package-specific commit message if releasing only one package, for +example `Release CUA AI v0.2.0`. + +## Tag And Push + +After the release commit is on `main`, create annotated package tags at that +commit: + +```bash +git tag -a cua-ai/v -m "@onkernel/cua-ai v" +git push origin cua-ai/v +``` + +For the agent package: + +```bash +git tag -a cua-agent/v -m "@onkernel/cua-agent v" +git push origin cua-agent/v +``` + +Push the AI tag first and wait for it to publish before pushing the agent tag +when the agent depends on that AI version. + +## Monitor + +Find and watch the workflow run triggered by each tag: + +```bash +gh run list --workflow release-cua-ai.yml --json databaseId,status,conclusion,headBranch,displayTitle,url --limit 10 +gh run watch --exit-status + +gh run list --workflow release-cua-agent.yml --json databaseId,status,conclusion,headBranch,displayTitle,url --limit 10 +gh run watch --exit-status +``` + +After a workflow succeeds, verify npm: + +```bash +npm view @onkernel/cua-ai@ version +npm dist-tag ls @onkernel/cua-ai +npm view @onkernel/cua-agent@ version +npm dist-tag ls @onkernel/cua-agent +``` + +If a workflow fails after a tag is pushed, do not reuse the same package +version unless npm did not publish it. Fix forward with a new commit and a new +patch version when a package version has reached npm. diff --git a/.github/workflows/release-cua-agent.yml b/.github/workflows/release-cua-agent.yml new file mode 100644 index 00000000..9a597f65 --- /dev/null +++ b/.github/workflows/release-cua-agent.yml @@ -0,0 +1,73 @@ +name: Release CUA Agent + +on: + push: + tags: + - "cua-agent/v*" + +permissions: + contents: read + id-token: write + +concurrency: + group: release-cua-agent-${{ github.ref_name }} + cancel-in-progress: false + +jobs: + publish: + runs-on: ubuntu-latest + timeout-minutes: 20 + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Verify tag is on main + run: | + git fetch origin main:refs/remotes/origin/main + git merge-base --is-ancestor "$GITHUB_SHA" origin/main + + - uses: actions/setup-node@v4 + with: + node-version: 24 + registry-url: https://registry.npmjs.org + + - name: Ensure npm supports trusted publishing + run: npm install -g npm@^11.5.1 + + - run: npm ci + + - name: Verify package version matches tag + run: | + node --input-type=module <<'EOF' + import { readFileSync } from "node:fs"; + + const tag = process.env.GITHUB_REF_NAME; + const prefix = "cua-agent/v"; + if (!tag?.startsWith(prefix)) { + throw new Error(`Expected tag to start with ${prefix}, got ${tag}`); + } + + const tagVersion = tag.slice(prefix.length); + const pkg = JSON.parse(readFileSync("packages/agent/package.json", "utf8")); + if (pkg.version !== tagVersion) { + throw new Error(`Tag version ${tagVersion} does not match ${pkg.name} package.json version ${pkg.version}`); + } + + console.log(`${pkg.name}@${pkg.version}`); + EOF + + - run: npm run build --workspace @onkernel/cua-ai + - run: npm run build --workspace @onkernel/cua-agent + + - name: Unit tests + run: npm test --workspace @onkernel/cua-agent -- test/agent.test.ts test/tool-exhaustiveness.test.ts + + - name: Verify dependency package is published + run: npm view @onkernel/cua-ai@$(node -p 'require("./packages/agent/package.json").dependencies["@onkernel/cua-ai"]') version + + - name: Pack dry run + run: npm pack --workspace @onkernel/cua-agent --dry-run + + - name: Publish to npm + run: npm publish --workspace @onkernel/cua-agent --access public diff --git a/.github/workflows/release-cua-ai.yml b/.github/workflows/release-cua-ai.yml new file mode 100644 index 00000000..ae1e34aa --- /dev/null +++ b/.github/workflows/release-cua-ai.yml @@ -0,0 +1,76 @@ +name: Release CUA AI + +on: + push: + tags: + - "cua-ai/v*" + +permissions: + contents: read + id-token: write + +concurrency: + group: release-cua-ai-${{ github.ref_name }} + cancel-in-progress: false + +jobs: + publish: + runs-on: ubuntu-latest + timeout-minutes: 20 + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Verify tag is on main + run: | + git fetch origin main:refs/remotes/origin/main + git merge-base --is-ancestor "$GITHUB_SHA" origin/main + + - uses: actions/setup-node@v4 + with: + node-version: 24 + registry-url: https://registry.npmjs.org + + - name: Ensure npm supports trusted publishing + run: npm install -g npm@^11.5.1 + + - run: npm ci + + - name: Verify package version matches tag + run: | + node --input-type=module <<'EOF' + import { readFileSync } from "node:fs"; + + const tag = process.env.GITHUB_REF_NAME; + const prefix = "cua-ai/v"; + if (!tag?.startsWith(prefix)) { + throw new Error(`Expected tag to start with ${prefix}, got ${tag}`); + } + + const tagVersion = tag.slice(prefix.length); + const pkg = JSON.parse(readFileSync("packages/ai/package.json", "utf8")); + if (pkg.version !== tagVersion) { + throw new Error(`Tag version ${tagVersion} does not match ${pkg.name} package.json version ${pkg.version}`); + } + + console.log(`${pkg.name}@${pkg.version}`); + EOF + + - run: npm run build --workspace @onkernel/cua-ai + + - name: Unit tests + run: > + npm test --workspace @onkernel/cua-ai -- + test/api-keys.test.ts + test/models.test.ts + test/providers.test.ts + test/runtime-spec.test.ts + test/tools.test.ts + test/yutori-payload.test.ts + + - name: Pack dry run + run: npm pack --workspace @onkernel/cua-ai --dry-run + + - name: Publish to npm + run: npm publish --workspace @onkernel/cua-ai --access public diff --git a/docs/npm-releases.md b/docs/npm-releases.md new file mode 100644 index 00000000..731d9134 --- /dev/null +++ b/docs/npm-releases.md @@ -0,0 +1,49 @@ +# npm releases + +`@onkernel/cua-ai` and `@onkernel/cua-agent` publish from package-specific tags: + +- `cua-ai/v0.1.0` runs `.github/workflows/release-cua-ai.yml` +- `cua-agent/v0.1.0` runs `.github/workflows/release-cua-agent.yml` + +The tag version must match the target package's `package.json` version, and the +tagged commit must be contained in `main`. + +## Trusted publishing setup + +Configure each package on npm with a GitHub Actions trusted publisher: + +| package | organization | repository | workflow filename | environment | +| --- | --- | --- | --- | --- | +| `@onkernel/cua-ai` | `kernel` | `cua` | `release-cua-ai.yml` | leave blank | +| `@onkernel/cua-agent` | `kernel` | `cua` | `release-cua-agent.yml` | leave blank | + +The same configuration can be created from the npm CLI: + +```sh +npm install -g npm@^11.10.0 +npm trust github @onkernel/cua-ai --repo kernel/cua --file release-cua-ai.yml +npm trust github @onkernel/cua-agent --repo kernel/cua --file release-cua-agent.yml +``` + +npm requires packages to exist before a trusted publisher can be configured. If +the package has not been published yet, either publish the first version manually +and use trusted publishing for later versions, or publish a bootstrap version +first, configure trusted publishing, then release `0.1.0` from tags. + +## Releasing 0.1.0 + +Publish `@onkernel/cua-ai` first because `@onkernel/cua-agent` depends on it: + +```sh +git checkout main +git pull --ff-only +git tag cua-ai/v0.1.0 +git push origin cua-ai/v0.1.0 +``` + +After `@onkernel/cua-ai@0.1.0` is available on npm: + +```sh +git tag cua-agent/v0.1.0 +git push origin cua-agent/v0.1.0 +``` diff --git a/package-lock.json b/package-lock.json index 3091a2cd..9e8d9fb8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4631,6 +4631,7 @@ "packages/agent": { "name": "@onkernel/cua-agent", "version": "0.1.0", + "license": "MIT", "dependencies": { "@earendil-works/pi-agent-core": "^0.74.0", "@earendil-works/pi-ai": "^0.74.0", @@ -4644,6 +4645,7 @@ "packages/ai": { "name": "@onkernel/cua-ai", "version": "0.1.0", + "license": "MIT", "dependencies": { "@earendil-works/pi-ai": "^0.74.0", "@tzafon/lightcone": "^0.7.0", diff --git a/packages/agent/package.json b/packages/agent/package.json index cf11139c..58d71e32 100644 --- a/packages/agent/package.json +++ b/packages/agent/package.json @@ -2,9 +2,19 @@ "name": "@onkernel/cua-agent", "version": "0.1.0", "description": "Kernel browser computer-use Agent and AgentHarness classes built on pi-agent-core", + "license": "MIT", "type": "module", "main": "./dist/index.js", "types": "./dist/index.d.ts", + "repository": { + "type": "git", + "url": "git+https://github.com/kernel/cua.git", + "directory": "packages/agent" + }, + "bugs": { + "url": "https://github.com/kernel/cua/issues" + }, + "homepage": "https://github.com/kernel/cua/tree/main/packages/agent#readme", "exports": { ".": { "types": "./dist/index.d.ts", @@ -18,6 +28,9 @@ "README.md", "CHANGELOG.md" ], + "publishConfig": { + "access": "public" + }, "scripts": { "build": "tsc -b", "clean": "tsc -b --clean", diff --git a/packages/ai/package.json b/packages/ai/package.json index dc1ed2a4..d6dd1ede 100644 --- a/packages/ai/package.json +++ b/packages/ai/package.json @@ -2,9 +2,19 @@ "name": "@onkernel/cua-ai", "version": "0.1.0", "description": "Kernel-curated computer-use model access built on pi-ai", + "license": "MIT", "type": "module", "main": "./dist/index.js", "types": "./dist/index.d.ts", + "repository": { + "type": "git", + "url": "git+https://github.com/kernel/cua.git", + "directory": "packages/ai" + }, + "bugs": { + "url": "https://github.com/kernel/cua/issues" + }, + "homepage": "https://github.com/kernel/cua/tree/main/packages/ai#readme", "exports": { ".": { "types": "./dist/index.d.ts", @@ -18,6 +28,9 @@ "README.md", "CHANGELOG.md" ], + "publishConfig": { + "access": "public" + }, "scripts": { "build": "tsc -b", "clean": "tsc -b --clean",