feat: integrate Changesets for multi-package npm publishing

Migrate from single-bundle CLI publishing to publishing all @paperclipai/*
packages individually via Changesets. This fixes the "Cannot find package
@paperclipai/server" error when installing from npm.

Changes:
- Add @changesets/cli with fixed versioning (all packages share version)
- Make 7 packages publishable (shared, adapter-utils, db, 3 adapters, server)
- Add build scripts, publishConfig, and files fields to all packages
- Mark @paperclipai/server as external in CLI esbuild config
- Simplify CLI importServerEntry() to use string-literal dynamic import
- Add generate-npm-package-json support for external workspace packages
- Create scripts/release.sh for one-command releases
- Remove old bump-and-publish.sh and version-bump.sh
- All packages start at version 0.2.0

Usage: ./scripts/release.sh patch|minor|major [--dry-run]

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dotta
2026-03-03 14:46:16 -06:00
parent 6e7f948314
commit defccdd4d9
20 changed files with 1197 additions and 256 deletions

View File

@@ -12,10 +12,10 @@ import { fileURLToPath } from "node:url";
const __dirname = dirname(fileURLToPath(import.meta.url));
const repoRoot = resolve(__dirname, "..");
// Workspace packages whose code should be bundled into the CLI
// Workspace packages whose code should be bundled into the CLI.
// Note: "server" is excluded — it's published separately and resolved at runtime.
const workspacePaths = [
"cli",
"server",
"packages/db",
"packages/shared",
"packages/adapter-utils",
@@ -24,17 +24,31 @@ const workspacePaths = [
"packages/adapters/openclaw",
];
// Workspace packages that should NOT be bundled — they'll be published
// to npm and resolved at runtime (e.g. @paperclipai/server uses dynamic import).
const externalWorkspacePackages = new Set([
"@paperclipai/server",
]);
// Collect all external (non-workspace) npm package names
const externals = new Set();
for (const p of workspacePaths) {
const pkg = JSON.parse(readFileSync(resolve(repoRoot, p, "package.json"), "utf8"));
for (const name of Object.keys(pkg.dependencies || {})) {
if (!name.startsWith("@paperclipai/")) externals.add(name);
if (externalWorkspacePackages.has(name)) {
externals.add(name);
} else if (!name.startsWith("@paperclipai/")) {
externals.add(name);
}
}
for (const name of Object.keys(pkg.optionalDependencies || {})) {
externals.add(name);
}
}
// Also add all published workspace packages as external
for (const name of externalWorkspacePackages) {
externals.add(name);
}
/** @type {import('esbuild').BuildOptions} */
export default {