From bb2fdf0145fcb31962d13b0896992157b5bd1345 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Thu, 9 Apr 2026 18:29:38 -0500 Subject: [PATCH] Build and link bundled RPC client --- package.json | 3 ++- scripts/ensure-workspace-builds.cjs | 1 + scripts/link-workspace-packages.cjs | 39 +++++++++++++++++------------ scripts/validate-pack.js | 16 +++++++----- 4 files changed, 36 insertions(+), 23 deletions(-) diff --git a/package.json b/package.json index 90b1f5a05..e43d754ce 100644 --- a/package.json +++ b/package.json @@ -46,9 +46,10 @@ "build:pi-agent-core": "npm run build -w @gsd/pi-agent-core", "build:pi-coding-agent": "npm run build -w @gsd/pi-coding-agent", "build:native-pkg": "npm run build -w @gsd/native", + "build:rpc-client": "npm run build -w @gsd-build/rpc-client", "build:pi": "npm run build:native-pkg && npm run build:pi-tui && npm run build:pi-ai && npm run build:pi-agent-core && npm run build:pi-coding-agent", "build:mcp-server": "npm run build -w @gsd-build/mcp-server", - "build": "npm run build:pi && npm run build:mcp-server && tsc && npm run copy-resources && npm run copy-themes && npm run copy-export-html && node scripts/build-web-if-stale.cjs", + "build": "npm run build:pi && npm run build:rpc-client && npm run build:mcp-server && tsc && npm run copy-resources && npm run copy-themes && npm run copy-export-html && node scripts/build-web-if-stale.cjs", "stage:web-host": "node scripts/stage-web-standalone.cjs", "build:web-host": "npm --prefix web run build && npm run stage:web-host", "copy-resources": "node scripts/copy-resources.cjs", diff --git a/scripts/ensure-workspace-builds.cjs b/scripts/ensure-workspace-builds.cjs index daecd8689..60636feb6 100644 --- a/scripts/ensure-workspace-builds.cjs +++ b/scripts/ensure-workspace-builds.cjs @@ -97,6 +97,7 @@ if (require.main === module) { 'pi-ai', 'pi-agent-core', 'pi-coding-agent', + 'rpc-client', 'mcp-server', ] diff --git a/scripts/link-workspace-packages.cjs b/scripts/link-workspace-packages.cjs index f1faf9875..7c203a19f 100644 --- a/scripts/link-workspace-packages.cjs +++ b/scripts/link-workspace-packages.cjs @@ -2,7 +2,8 @@ /** * link-workspace-packages.cjs * - * Creates node_modules/@gsd/* symlinks pointing to packages/* directories. + * Creates node_modules/@gsd/* and node_modules/@gsd-build/* symlinks pointing + * to shipped packages/* directories. * * During development, npm workspaces creates these automatically. But in the * published tarball, workspace packages are shipped under packages/ (via the @@ -20,27 +21,33 @@ const { resolve, join } = require('path') const root = resolve(__dirname, '..') const packagesDir = join(root, 'packages') -const nodeModulesGsd = join(root, 'node_modules', '@gsd') - -// Map directory names to package names -const packageMap = { - 'native': 'native', - 'pi-agent-core': 'pi-agent-core', - 'pi-ai': 'pi-ai', - 'pi-coding-agent': 'pi-coding-agent', - 'pi-tui': 'pi-tui', +const scopeDirs = { + '@gsd': join(root, 'node_modules', '@gsd'), + '@gsd-build': join(root, 'node_modules', '@gsd-build'), } -// Ensure @gsd scope directory exists -if (!existsSync(nodeModulesGsd)) { - mkdirSync(nodeModulesGsd, { recursive: true }) +// Map directory names to scoped package names +const packageMap = { + 'native': { scope: '@gsd', name: 'native' }, + 'pi-agent-core': { scope: '@gsd', name: 'pi-agent-core' }, + 'pi-ai': { scope: '@gsd', name: 'pi-ai' }, + 'pi-coding-agent': { scope: '@gsd', name: 'pi-coding-agent' }, + 'pi-tui': { scope: '@gsd', name: 'pi-tui' }, + 'rpc-client': { scope: '@gsd-build', name: 'rpc-client' }, +} + +for (const scopeDir of Object.values(scopeDirs)) { + if (!existsSync(scopeDir)) { + mkdirSync(scopeDir, { recursive: true }) + } } let linked = 0 let copied = 0 -for (const [dir, name] of Object.entries(packageMap)) { +for (const [dir, pkg] of Object.entries(packageMap)) { const source = join(packagesDir, dir) - const target = join(nodeModulesGsd, name) + const scopeDir = scopeDirs[pkg.scope] + const target = join(scopeDir, pkg.name) if (!existsSync(source)) continue @@ -50,7 +57,7 @@ for (const [dir, name] of Object.entries(packageMap)) { const stat = lstatSync(target) if (stat.isSymbolicLink()) { const linkTarget = readlinkSync(target) - if (resolve(join(nodeModulesGsd, linkTarget)) === source || linkTarget === source) { + if (resolve(join(scopeDir, linkTarget)) === source || linkTarget === source) { continue // Already correct } unlinkSync(target) // Wrong target, relink diff --git a/scripts/validate-pack.js b/scripts/validate-pack.js index a29cd1f76..e4bbe6277 100644 --- a/scripts/validate-pack.js +++ b/scripts/validate-pack.js @@ -65,6 +65,7 @@ try { const requiredFiles = [ 'dist/loader.js', 'packages/pi-coding-agent/dist/index.js', + 'packages/rpc-client/dist/index.js', 'packages/mcp-server/dist/cli.js', 'scripts/link-workspace-packages.cjs', 'dist/web/standalone/server.js', @@ -110,16 +111,19 @@ try { // node_modules/@gsd/ is never populated, causing ERR_MODULE_NOT_FOUND at runtime. console.log('==> Verifying @gsd/* workspace package resolution...'); const installedRoot = join(installDir, 'node_modules', 'gsd-pi'); - const criticalPkgs = ['pi-coding-agent']; + const criticalPackages = [ + { scope: '@gsd', name: 'pi-coding-agent' }, + { scope: '@gsd-build', name: 'rpc-client' }, + ]; let resolutionFailed = false; - for (const pkg of criticalPkgs) { - const pkgPath = join(installedRoot, 'node_modules', '@gsd', pkg); - const fallbackPath = join(installedRoot, 'packages', pkg); + for (const pkg of criticalPackages) { + const pkgPath = join(installedRoot, 'node_modules', pkg.scope, pkg.name); + const fallbackPath = join(installedRoot, 'packages', pkg.name); if (!existsSync(pkgPath)) { if (existsSync(fallbackPath)) { - console.log(` MISSING symlink/copy: node_modules/@gsd/${pkg} (packages/${pkg} exists — postinstall may not have run)`); + console.log(` MISSING symlink/copy: node_modules/${pkg.scope}/${pkg.name} (packages/${pkg.name} exists — postinstall may not have run)`); } else { - console.log(` MISSING: node_modules/@gsd/${pkg} (packages/${pkg} also absent — package is broken)`); + console.log(` MISSING: node_modules/${pkg.scope}/${pkg.name} (packages/${pkg.name} also absent — package is broken)`); } resolutionFailed = true; }