mirror of
https://github.com/harivansh-afk/sandbox-agent.git
synced 2026-04-15 07:04:48 +00:00
- Add hidden `mock-agent-process` CLI subcommand implementing a stdio JSON-RPC echo agent (ported from examples/mock-acp-agent) - Update write_mock_agent_process_launcher() to exec the new subcommand instead of exiting with error - Update sdks/react to support React 18 and 19 peer dependencies - Update @types/react to v19 across workspace (pnpm override + inspector) - Fix RefObject<T | null> compatibility for React 19 useRef() signatures - Add version reference replacement logic to release update_version.ts covering all docs, examples, and code files listed in CLAUDE.md - Add missing files to CLAUDE.md Install Version References list (architecture.mdx, boxlite, modal, computesdk docs and examples) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
182 lines
7.1 KiB
TypeScript
182 lines
7.1 KiB
TypeScript
import * as fs from "node:fs/promises";
|
|
import { join } from "node:path";
|
|
import { $ } from "execa";
|
|
import { glob } from "glob";
|
|
import * as semver from "semver";
|
|
import type { ReleaseOpts } from "./main";
|
|
|
|
function assert(condition: any, message?: string): asserts condition {
|
|
if (!condition) {
|
|
throw new Error(message || "Assertion failed");
|
|
}
|
|
}
|
|
|
|
// Files containing version references that need channel/image tag updates.
|
|
// Keep in sync with CLAUDE.md "Install Version References" section.
|
|
const VERSION_REFERENCE_FILES = [
|
|
"README.md",
|
|
"docs/acp-http-client.mdx",
|
|
"docs/cli.mdx",
|
|
"docs/quickstart.mdx",
|
|
"docs/sdk-overview.mdx",
|
|
"docs/react-components.mdx",
|
|
"docs/session-persistence.mdx",
|
|
"docs/architecture.mdx",
|
|
"docs/deploy/local.mdx",
|
|
"docs/deploy/cloudflare.mdx",
|
|
"docs/deploy/vercel.mdx",
|
|
"docs/deploy/daytona.mdx",
|
|
"docs/deploy/e2b.mdx",
|
|
"docs/deploy/docker.mdx",
|
|
"docs/deploy/boxlite.mdx",
|
|
"docs/deploy/modal.mdx",
|
|
"docs/deploy/computesdk.mdx",
|
|
"frontend/packages/website/src/components/GetStarted.tsx",
|
|
".claude/commands/post-release-testing.md",
|
|
"examples/cloudflare/Dockerfile",
|
|
"examples/boxlite/Dockerfile",
|
|
"examples/boxlite-python/Dockerfile",
|
|
"examples/daytona/src/index.ts",
|
|
"examples/shared/src/docker.ts",
|
|
"examples/docker/src/index.ts",
|
|
"examples/e2b/src/index.ts",
|
|
"examples/vercel/src/index.ts",
|
|
"sdks/typescript/src/providers/shared.ts",
|
|
"scripts/release/main.ts",
|
|
"scripts/release/promote-artifacts.ts",
|
|
"scripts/release/sdk.ts",
|
|
"scripts/sandbox-testing/test-sandbox.ts",
|
|
];
|
|
|
|
export async function updateVersion(opts: ReleaseOpts) {
|
|
// 1. Read current version from Cargo.toml before overwriting
|
|
const cargoTomlPath = join(opts.root, "Cargo.toml");
|
|
let cargoContent = await fs.readFile(cargoTomlPath, "utf-8");
|
|
|
|
const oldVersionMatch = cargoContent.match(/\[workspace\.package\]\nversion = "([^"]+)"/);
|
|
assert(oldVersionMatch, "Could not find workspace.package version in Cargo.toml");
|
|
const oldVersion = oldVersionMatch[1];
|
|
const oldParsed = semver.parse(oldVersion);
|
|
assert(oldParsed, `Could not parse old version: ${oldVersion}`);
|
|
const oldMinorChannel = `${oldParsed.major}.${oldParsed.minor}.x`;
|
|
|
|
// Update [workspace.package] version
|
|
cargoContent = cargoContent.replace(/\[workspace\.package\]\nversion = ".*"/, `[workspace.package]\nversion = "${opts.version}"`);
|
|
|
|
// Discover internal crates from [workspace.dependencies] by matching
|
|
// lines with both `version = "..."` and `path = "..."` (internal path deps)
|
|
const internalCratePattern = /^(\S+)\s*=\s*\{[^}]*version\s*=\s*"[^"]+"\s*,[^}]*path\s*=/gm;
|
|
let match;
|
|
const internalCrates: string[] = [];
|
|
while ((match = internalCratePattern.exec(cargoContent)) !== null) {
|
|
internalCrates.push(match[1]);
|
|
}
|
|
|
|
console.log(`Discovered ${internalCrates.length} internal crates to version-bump:`);
|
|
for (const crate of internalCrates) console.log(` - ${crate}`);
|
|
|
|
for (const crate of internalCrates) {
|
|
const pattern = new RegExp(`(${crate.replace(/-/g, "-")} = \\{ version = ")[^"]+(",)`, "g");
|
|
cargoContent = cargoContent.replace(pattern, `$1${opts.version}$2`);
|
|
}
|
|
|
|
await fs.writeFile(cargoTomlPath, cargoContent);
|
|
await $({ cwd: opts.root })`git add Cargo.toml`;
|
|
|
|
// 2. Discover and update all non-private SDK package.json versions
|
|
const packageJsonPaths = await glob("sdks/**/package.json", {
|
|
cwd: opts.root,
|
|
ignore: ["**/node_modules/**"],
|
|
});
|
|
|
|
// Filter to non-private packages only
|
|
const toUpdate: string[] = [];
|
|
for (const relPath of packageJsonPaths) {
|
|
const fullPath = join(opts.root, relPath);
|
|
const content = await fs.readFile(fullPath, "utf-8");
|
|
const pkg = JSON.parse(content);
|
|
if (pkg.private) continue;
|
|
toUpdate.push(relPath);
|
|
}
|
|
|
|
console.log(`Discovered ${toUpdate.length} SDK package.json files to version-bump:`);
|
|
for (const relPath of toUpdate) console.log(` - ${relPath}`);
|
|
|
|
for (const relPath of toUpdate) {
|
|
const fullPath = join(opts.root, relPath);
|
|
const content = await fs.readFile(fullPath, "utf-8");
|
|
|
|
const versionPattern = /"version": ".*"/;
|
|
assert(versionPattern.test(content), `No version field in ${relPath}`);
|
|
|
|
const updated = content.replace(versionPattern, `"version": "${opts.version}"`);
|
|
await fs.writeFile(fullPath, updated);
|
|
await $({ cwd: opts.root })`git add ${relPath}`;
|
|
}
|
|
|
|
// 3. Update version references across docs, examples, and code
|
|
await updateVersionReferences(opts, oldVersion, oldMinorChannel);
|
|
}
|
|
|
|
async function updateVersionReferences(opts: ReleaseOpts, oldVersion: string, oldMinorChannel: string) {
|
|
const newMinorChannel = opts.minorVersionChannel;
|
|
|
|
// Find old Docker image tags by scanning for rivetdev/sandbox-agent:<version>-full patterns
|
|
// The old version might be a different patch or RC, so we match any version-full tag
|
|
const oldDockerTagPattern = /rivetdev\/sandbox-agent:([0-9]+\.[0-9]+\.[0-9]+(?:-[a-zA-Z0-9.]+)?)-full/;
|
|
|
|
console.log(`\nUpdating version references:`);
|
|
console.log(` Old minor channel: ${oldMinorChannel}`);
|
|
console.log(` New minor channel: ${newMinorChannel}`);
|
|
console.log(` New Docker tag: ${opts.version}-full`);
|
|
|
|
const modifiedFiles: string[] = [];
|
|
|
|
for (const relPath of VERSION_REFERENCE_FILES) {
|
|
const fullPath = join(opts.root, relPath);
|
|
|
|
let content: string;
|
|
try {
|
|
content = await fs.readFile(fullPath, "utf-8");
|
|
} catch (err: any) {
|
|
if (err.code === "ENOENT") {
|
|
console.log(` ⚠️ Skipping ${relPath} (file not found)`);
|
|
continue;
|
|
}
|
|
throw err;
|
|
}
|
|
|
|
const original = content;
|
|
|
|
// Replace minor channel references (e.g. sandbox-agent@0.3.x -> sandbox-agent@0.4.x)
|
|
content = content.replaceAll(`sandbox-agent@${oldMinorChannel}`, `sandbox-agent@${newMinorChannel}`);
|
|
content = content.replaceAll(`@sandbox-agent/cli@${oldMinorChannel}`, `@sandbox-agent/cli@${newMinorChannel}`);
|
|
content = content.replaceAll(`@sandbox-agent/react@${oldMinorChannel}`, `@sandbox-agent/react@${newMinorChannel}`);
|
|
|
|
// Replace install script URL channel
|
|
content = content.replaceAll(`releases.rivet.dev/sandbox-agent/${oldMinorChannel}/`, `releases.rivet.dev/sandbox-agent/${newMinorChannel}/`);
|
|
|
|
// Replace Docker image tags (rivetdev/sandbox-agent:<anything>-full -> rivetdev/sandbox-agent:<version>-full)
|
|
content = content.replaceAll(
|
|
new RegExp(`rivetdev/sandbox-agent:[0-9]+\\.[0-9]+\\.[0-9]+(?:-[a-zA-Z0-9.]+)?-full`, "g"),
|
|
`rivetdev/sandbox-agent:${opts.version}-full`,
|
|
);
|
|
|
|
// Replace standalone version-full references in prose (e.g. "The `0.3.2-full` tag pins...")
|
|
// Match backtick-wrapped version-full patterns
|
|
content = content.replaceAll(new RegExp("`[0-9]+\\.[0-9]+\\.[0-9]+(?:-[a-zA-Z0-9.]+)?-full`", "g"), `\`${opts.version}-full\``);
|
|
|
|
if (content !== original) {
|
|
await fs.writeFile(fullPath, content);
|
|
modifiedFiles.push(relPath);
|
|
console.log(` ✅ ${relPath}`);
|
|
}
|
|
}
|
|
|
|
if (modifiedFiles.length > 0) {
|
|
await $({ cwd: opts.root })`git add ${modifiedFiles}`;
|
|
console.log(`\nUpdated ${modifiedFiles.length} files with version references.`);
|
|
} else {
|
|
console.log(`\nNo version reference files needed updates.`);
|
|
}
|
|
}
|