From 9cf178265bdad2a8b71995110e96fde8530307d3 Mon Sep 17 00:00:00 2001 From: Jack Amadeo Date: Fri, 10 Apr 2026 16:30:45 -0400 Subject: [PATCH] ci: switch npm publish to OIDC trusted publishing (#8454) Co-authored-by: Claude Opus 4.6 --- .github/workflows/ci.yml | 17 +- .github/workflows/publish-npm.yml | 403 ++++++------------ .github/workflows/release.yml | 16 +- Justfile | 32 ++ crates/goose-acp/acp-schema.json | 1 - .../goose-acp/src/bin/generate_acp_schema.rs | 28 ++ ui/.changeset/initial-release.md | 11 - ui/acp/package.json | 7 +- ui/acp/scripts/build-schema.ts | 73 ---- ui/acp/src/generated/zod.gen.ts | 2 +- .../goose-binary-darwin-arm64/package.json | 2 +- .../goose-binary-darwin-x64/package.json | 2 +- .../goose-binary-linux-arm64/package.json | 2 +- .../goose-binary-linux-x64/package.json | 2 +- .../goose-binary-win32-x64/package.json | 2 +- ui/text/package.json | 2 +- ui/text/scripts/postinstall.mjs | 9 +- 17 files changed, 237 insertions(+), 374 deletions(-) delete mode 100644 ui/.changeset/initial-release.md delete mode 100644 ui/acp/scripts/build-schema.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2c553a2021..97e139aded 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -121,8 +121,8 @@ jobs: export CARGO_INCREMENTAL=0 cargo clippy --workspace --all-targets --exclude v8 -- -D warnings - openapi-schema-check: - name: Check OpenAPI Schema is Up-to-Date + schema-check: + name: Check Generated Schemas are Up-to-Date runs-on: ubuntu-latest needs: changes if: needs.changes.outputs.code == 'true' || github.event_name != 'pull_request' @@ -140,9 +140,11 @@ jobs: - name: Cache Cargo artifacts uses: Swatinem/rust-cache@42dc69e1aa15d09112580998cf2ef0119e2e91ae # v2 - - name: Install Node.js Dependencies for OpenAPI Check - run: source ../../bin/activate-hermit && pnpm install --frozen-lockfile - working-directory: ui/desktop + - name: Install Node.js Dependencies + run: | + source ./bin/activate-hermit + cd ui/desktop && pnpm install --frozen-lockfile + cd ../acp && pnpm install --frozen-lockfile - name: Check OpenAPI Schema is Up-to-Date run: | @@ -150,6 +152,11 @@ jobs: hermit uninstall rustup just check-openapi-schema + - name: Check ACP Schema is Up-to-Date + run: | + source ./bin/activate-hermit + just check-acp-schema + desktop-lint: name: Test and Lint Electron Desktop App runs-on: macos-latest diff --git a/.github/workflows/publish-npm.yml b/.github/workflows/publish-npm.yml index 38c4a55c19..74f2cd7dfc 100644 --- a/.github/workflows/publish-npm.yml +++ b/.github/workflows/publish-npm.yml @@ -1,201 +1,31 @@ name: Publish to npm -# Security: This workflow uses the 'npm-production-publishing' environment to protect against -# accidental publishes from feature branches. The environment must be configured in -# GitHub Settings โ†’ Environments with: -# - Deployment branches: Selected branches โ†’ main -# - Environment secret: NPM_PUBLISH_TOKEN (npm publish token with write access) -# -# This ensures that even if the workflow file is modified on a feature branch to -# bypass the ref checks, GitHub will block access to the NPM_PUBLISH_TOKEN secret. - on: - push: - branches: - - main - paths: - - 'crates/goose-acp/**' - - 'ui/acp/**' - - '.github/workflows/publish-npm.yml' + workflow_call: + inputs: + release-tag: + description: 'Release tag to fetch binaries from (e.g. v1.0.0)' + required: true + type: string workflow_dispatch: inputs: - dry-run: - description: 'Dry run (skip actual npm publish)' - required: false - type: boolean - default: true - skip-cache: - description: 'Skip cache and rebuild everything' - required: false - type: boolean - default: false + release-tag: + description: 'Release tag to fetch binaries from (e.g. v1.0.0)' + required: true + type: string concurrency: ${{ github.workflow }}-${{ github.ref }} permissions: contents: write pull-requests: write - id-token: write # Required for npm provenance + id-token: write # Required for npm trusted publishing (OIDC) jobs: - # Generate ACP TypeScript schema first - this is needed before building npm packages - generate-schema: - name: Generate ACP Schema + # Build npm packages (no environment needed) + build: + name: Build npm packages runs-on: ubuntu-latest - outputs: - cache-key: ${{ steps.cache-key.outputs.key }} - steps: - - name: Checkout - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - - - name: Generate cache key - id: cache-key - run: | - # Create a cache key based on ACP crate files - HASH=$(find crates/goose-acp -type f -name "*.rs" -o -name "Cargo.toml" | sort | xargs sha256sum | sha256sum | cut -d' ' -f1) - echo "key=acp-schema-$HASH" >> "$GITHUB_OUTPUT" - echo "Generated cache key: acp-schema-$HASH" - - - name: Check cache - id: cache - if: inputs.skip-cache != true - uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4 - with: - path: | - crates/goose-acp/acp-schema.json - crates/goose-acp/acp-meta.json - key: ${{ steps.cache-key.outputs.key }} - - - name: Setup Rust - if: steps.cache.outputs.cache-hit != 'true' - uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable - - - name: Setup Rust cache - if: steps.cache.outputs.cache-hit != 'true' - uses: Swatinem/rust-cache@42dc69e1aa15d09112580998cf2ef0119e2e91ae # v2 - - - name: Build and run generate-acp-schema - if: steps.cache.outputs.cache-hit != 'true' - run: | - cargo build --release --bin generate-acp-schema - cargo run --release --bin generate-acp-schema - working-directory: crates/goose-acp - - - name: Upload schema artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 - with: - name: acp-schema - path: | - crates/goose-acp/acp-schema.json - crates/goose-acp/acp-meta.json - if-no-files-found: error - retention-days: 7 - - # Build goose CLI binaries for all platforms - build-goose-binaries: - name: Build goose CLI (${{ matrix.platform }}) - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - include: - - platform: darwin-arm64 - os: macos-latest - target: aarch64-apple-darwin - - platform: darwin-x64 - os: macos-latest - target: x86_64-apple-darwin - - platform: linux-arm64 - os: ubuntu-24.04-arm - target: aarch64-unknown-linux-gnu - - platform: linux-x64 - os: ubuntu-latest - target: x86_64-unknown-linux-gnu - # Temporarily disabled - Windows builds are slow (20+ min) without cache - # - platform: win32-x64 - # os: windows-latest - # target: x86_64-pc-windows-msvc - outputs: - cache-key-base: ${{ steps.cache-key.outputs.key-base }} - steps: - - name: Checkout - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - - - name: Generate cache key - id: cache-key - run: | - # Create a cache key based on Rust source files - if [ "${{ runner.os }}" = "Windows" ]; then - HASH=$(find crates -type f -name "*.rs" -o -name "Cargo.toml" -o -name "Cargo.lock" | sort | sha256sum | cut -d' ' -f1) - else - HASH=$(find crates -type f \( -name "*.rs" -o -name "Cargo.toml" -o -name "Cargo.lock" \) | sort | xargs sha256sum | sha256sum | cut -d' ' -f1) - fi - echo "key-base=goose-binary-$HASH" >> "$GITHUB_OUTPUT" - echo "key=goose-binary-$HASH-${{ matrix.platform }}" >> "$GITHUB_OUTPUT" - echo "Generated cache key: goose-binary-$HASH-${{ matrix.platform }}" - shell: bash - - - name: Setup Rust - uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable - with: - targets: ${{ matrix.target }} - - - name: Add Intel target for cross-compilation (macOS ARM64 โ†’ x86_64) - if: matrix.platform == 'darwin-x64' - run: rustup target add x86_64-apple-darwin - - - name: Install cross-compilation tools (Linux ARM64) - if: matrix.platform == 'linux-arm64' - run: | - sudo apt-get update - sudo apt-get install -y gcc-aarch64-linux-gnu - - - name: Setup Rust cache - uses: Swatinem/rust-cache@42dc69e1aa15d09112580998cf2ef0119e2e91ae # v2 - with: - key: ${{ matrix.platform }} - save-if: ${{ github.ref == 'refs/heads/main' }} - - - name: Check binary cache - id: binary-cache - if: inputs.skip-cache != true - uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4 - with: - path: | - target/${{ matrix.target }}/release/goose${{ matrix.platform == 'win32-x64' && '.exe' || '' }} - key: ${{ steps.cache-key.outputs.key }} - - - name: Build goose CLI binary - if: steps.binary-cache.outputs.cache-hit != 'true' - run: cargo build --release --target ${{ matrix.target }} --bin goose - - - name: Prepare artifact (Unix) - if: runner.os != 'Windows' - run: | - mkdir -p artifact/bin - cp target/${{ matrix.target }}/release/goose artifact/bin/ - chmod +x artifact/bin/goose - - - name: Prepare artifact (Windows) - if: runner.os == 'Windows' - shell: bash - run: | - mkdir -p artifact/bin - cp target/${{ matrix.target }}/release/goose.exe artifact/bin/ - - - name: Upload artifact - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 - with: - name: goose-${{ matrix.platform }} - path: artifact/ - if-no-files-found: error - retention-days: 7 - - # Publish to npm - release: - name: Release to npm - runs-on: ubuntu-latest - needs: [generate-schema, build-goose-binaries] steps: - name: Checkout uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 @@ -212,132 +42,163 @@ jobs: with: version: 10.30.3 - - name: Download ACP schema - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 - with: - name: acp-schema - path: crates/goose-acp - - - name: Download goose binaries - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 - with: - pattern: goose-* - path: goose-binaries - - - name: List downloaded artifacts (debug) + - name: Download goose binaries from release + env: + GH_TOKEN: ${{ github.token }} run: | - echo "Downloaded ACP schema:" - ls -lh crates/goose-acp/acp-*.json - echo "" - echo "Downloaded goose CLI binaries:" - ls -R goose-binaries/ + TAG="${{ inputs.release-tag }}" + echo "Downloading goose CLI binaries from release ${TAG}" + + # Map: npm platform name -> release artifact name (target triple) + declare -A PLATFORM_MAP=( + [darwin-arm64]=aarch64-apple-darwin + [darwin-x64]=x86_64-apple-darwin + [linux-arm64]=aarch64-unknown-linux-gnu + [linux-x64]=x86_64-unknown-linux-gnu + [win32-x64]=x86_64-pc-windows-msvc + ) + + for platform in "${!PLATFORM_MAP[@]}"; do + target="${PLATFORM_MAP[$platform]}" + pkg_dir="ui/goose-binary/goose-binary-${platform}/bin" + mkdir -p "${pkg_dir}" + + if [[ "${platform}" == "win32-x64" ]]; then + artifact="goose-${target}.zip" + gh release download "${TAG}" --pattern "${artifact}" --dir /tmp + unzip -o "/tmp/${artifact}" -d /tmp/goose-extract + cp /tmp/goose-extract/goose-package/goose.exe "${pkg_dir}/goose.exe" + rm -rf /tmp/goose-extract "/tmp/${artifact}" + else + artifact="goose-${target}.tar.bz2" + gh release download "${TAG}" --pattern "${artifact}" --dir /tmp + mkdir -p /tmp/goose-extract + tar -xjf "/tmp/${artifact}" -C /tmp/goose-extract + cp /tmp/goose-extract/goose "${pkg_dir}/goose" + chmod +x "${pkg_dir}/goose" + rm -rf /tmp/goose-extract "/tmp/${artifact}" + fi + + echo " โœ… ${platform} (${target})" + done + + - name: List downloaded binaries (debug) + run: find ui/goose-binary -name 'goose*' -type f | sort - name: Install dependencies run: | cd ui pnpm install --frozen-lockfile - - name: Generate TypeScript types from schema - run: | - cd ui/acp - # The schema JSON files are already downloaded, just generate TS types - # This only runs the TypeScript generation part, no Rust compilation - npx tsx generate-schema.ts - - name: Build packages run: | cd ui/acp - # Build only TypeScript, schema is already generated pnpm run build:ts - + cd ../text pnpm run build - - name: Prepare summary + - name: Upload built packages + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + with: + name: npm-packages + path: ui/ + if-no-files-found: error + retention-days: 7 + + - name: Build summary run: | { echo "## ๐Ÿ“ฆ Build Summary" echo "" - echo "### ACP Schema" - echo "โœ… Generated and cached" + echo "### Release" + echo "Tag: \`${{ inputs.release-tag }}\`" echo "" echo "### Goose CLI Binaries" - echo "โœ… Built for all platforms:" - for dir in goose-binaries/goose-*; do - platform=$(basename "$dir" | sed 's/goose-//') + echo "โœ… Downloaded from release for all platforms:" + for dir in ui/goose-binary/goose-binary-*/; do + platform=$(basename "$dir" | sed 's/goose-binary-//') echo " - $platform" done echo "" echo "### npm Packages" - echo "โœ… @aaif/goose-acp" - echo "โœ… @aaif/goose (TUI)" + cd ui + for pkg in acp text goose-binary/*/; do + if [ -f "$pkg/package.json" ]; then + name=$(jq -r '.name' "$pkg/package.json") + version=$(jq -r '.version' "$pkg/package.json") + echo "- $name@$version" + fi + done echo "" + if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then + echo "### โš ๏ธ Dry run โ€” packages were built but will NOT be published" + echo "Publishing only happens via release.yml (workflow_call)." + fi } >> "$GITHUB_STEP_SUMMARY" - - name: Dry run notice - if: inputs.dry-run == true || github.ref != 'refs/heads/main' - run: | - { - echo "## ๐Ÿงช Dry Run Mode" - echo "" - } >> "$GITHUB_STEP_SUMMARY" - if [ "${{ github.ref }}" != "refs/heads/main" ]; then - { - echo "โš ๏ธ Skipping actual npm publish (not on main branch)" - echo "" - echo "**Current branch:** \`${{ github.ref }}\`" - echo "" - echo "Publishing is only allowed from the \`main\` branch for security." - } >> "$GITHUB_STEP_SUMMARY" - else - { - echo "โš ๏ธ Skipping actual npm publish (dry-run mode)" - echo "" - echo "To publish for real, run this workflow without dry-run enabled." - echo "" - echo "**Note:** Changesets will still run to verify functionality." - } >> "$GITHUB_STEP_SUMMARY" - fi + # Publish to npm (only via workflow_call from release.yml) + # workflow_dispatch is build-only because npm trusted publishing OIDC claims + # are bound to the caller workflow filename (release.yml), not this file. + publish: + name: Publish to npm + if: github.event_name != 'workflow_dispatch' + runs-on: ubuntu-latest + needs: [build] + environment: npm-production-publishing + steps: + - name: Download built packages + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 + with: + name: npm-packages + path: ui/ - - name: Configure npm authentication - if: inputs.dry-run != true && github.ref == 'refs/heads/main' - run: | - cd ui - echo "//registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}" >> .npmrc - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }} + - name: Restore executable bits on goose binaries + run: find ui/goose-binary -name 'goose' -type f -exec chmod +x {} + + + - name: Setup Node.js + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 + with: + node-version: '24.10.0' + registry-url: 'https://registry.npmjs.org' + always-auth: true + + - name: Setup pnpm + uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4 + with: + version: 10.30.3 - name: Publish to npm - if: inputs.dry-run != true && github.ref == 'refs/heads/main' run: | cd ui - # Publish all packages in the workspace - pnpm publish -r --access public --no-git-checks - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }} - NPM_CONFIG_PROVENANCE: true - - - name: Dry run - Show what would be published - if: inputs.dry-run == true || github.ref != 'refs/heads/main' - run: | - cd ui - echo "## ๐Ÿ“ฆ Packages that would be published:" | tee -a "$GITHUB_STEP_SUMMARY" - echo "" | tee -a "$GITHUB_STEP_SUMMARY" - - # List all publishable packages - for pkg in acp text goose-binary/*/; do + # Publish each package individually so one failure doesn't abort the rest. + # Skips packages whose version is already published (409/403). + failed=0 + for pkg in acp goose-binary/*/ text; do if [ -f "$pkg/package.json" ]; then name=$(jq -r '.name' "$pkg/package.json") version=$(jq -r '.version' "$pkg/package.json") - echo "- $name@$version" | tee -a "$GITHUB_STEP_SUMMARY" + echo "Publishing $name@$version..." + if (cd "$pkg" && pnpm publish --access public --no-git-checks --provenance); then + echo " โœ… $name@$version published" + else + # Check if it failed because the version already exists + if npm view "$name@$version" version > /dev/null 2>&1; then + echo " โญ๏ธ $name@$version already published, skipping" + else + echo " โŒ $name@$version failed to publish" + failed=1 + fi + fi fi done - - echo "" | tee -a "$GITHUB_STEP_SUMMARY" - echo "**Note:** This is a dry run. No packages were published." | tee -a "$GITHUB_STEP_SUMMARY" + if [ "$failed" -eq 1 ]; then + echo "::error::One or more packages failed to publish" + exit 1 + fi - name: Publish summary - if: inputs.dry-run != true && github.ref == 'refs/heads/main' + if: always() run: | cd ui { diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2a24d591b3..85858b8604 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,9 +9,10 @@ on: name: Release permissions: - id-token: write # Required for Sigstore OIDC signing and AWS OIDC (Windows signing) + id-token: write # Required for Sigstore OIDC signing, AWS OIDC (Windows signing), and npm trusted publishing contents: write # Required for creating releases and by actions/checkout actions: read # May be needed for some workflows + pull-requests: write # Required for npm publish workflow attestations: write # Required for SLSA build provenance attestations concurrency: @@ -151,3 +152,16 @@ jobs: allowUpdates: true omitBody: true omitPrereleaseDuringUpdate: true + + # ------------------------------------ + # 8) Publish npm packages + # ------------------------------------ + publish-npm: + needs: [release] + uses: ./.github/workflows/publish-npm.yml + with: + release-tag: ${{ github.ref_name }} + permissions: + contents: write + pull-requests: write + id-token: write diff --git a/Justfile b/Justfile index 2ba028c19c..d2630df994 100644 --- a/Justfile +++ b/Justfile @@ -205,6 +205,38 @@ generate-openapi: @echo "Generating frontend API..." cd ui/desktop && npx @hey-api/openapi-ts +# Check if generated ACP schema and TypeScript types are up-to-date +check-acp-schema: generate-acp-types + #!/usr/bin/env bash + set -e + echo "๐Ÿ” Checking ACP schema and generated types are up-to-date..." + if ! git diff --exit-code crates/goose-acp/acp-schema.json crates/goose-acp/acp-meta.json ui/acp/src/generated/; then + echo "" + echo "โŒ ACP generated files are out of date!" + echo "" + echo "Run 'just generate-acp-types' locally, then commit the changes." + exit 1 + fi + echo "โœ… ACP schema and generated types are up-to-date" + +# Generate ACP JSON schema from Rust types +generate-acp-schema: + @echo "Generating ACP schema..." + cd crates/goose-acp && cargo run --bin generate-acp-schema + @echo "ACP schema generated: crates/goose-acp/acp-schema.json, crates/goose-acp/acp-meta.json" + +# Generate ACP TypeScript types from JSON schema (requires generate-acp-schema first) +generate-acp-types: generate-acp-schema + @echo "Generating ACP TypeScript types..." + cd ui/acp && npx tsx generate-schema.ts + @echo "ACP TypeScript types generated in ui/acp/src/generated/" + +# Build ACP TypeScript package (schema + types + compile) +build-acp: generate-acp-types + @echo "Compiling ACP TypeScript..." + cd ui/acp && pnpm run build:ts + @echo "ACP package built." + # Generate manpages for the CLI generate-manpages: @echo "Generating manpages..." diff --git a/crates/goose-acp/acp-schema.json b/crates/goose-acp/acp-schema.json index b261dffb06..0b8e85c059 100644 --- a/crates/goose-acp/acp-schema.json +++ b/crates/goose-acp/acp-schema.json @@ -436,7 +436,6 @@ }, "messageCount": { "type": "integer", - "format": "uint64", "minimum": 0 } }, diff --git a/crates/goose-acp/src/bin/generate_acp_schema.rs b/crates/goose-acp/src/bin/generate_acp_schema.rs index 0e9bf87989..e50afdaa8b 100644 --- a/crates/goose-acp/src/bin/generate_acp_schema.rs +++ b/crates/goose-acp/src/bin/generate_acp_schema.rs @@ -38,8 +38,12 @@ fn main() { // Replace `true` with `{}` throughout $defs. Both mean "accept any value" in // JSON Schema, but many TS codegen tools (e.g. @hey-api/openapi-ts Zod plugin) // silently drop properties whose schema is the bare `true` literal. + // + // Also strip "format": "uint64" / "int64" from integer types โ€” these cause TS + // codegen to emit BigInt validators, but JS/TS uses `number` for all integers. for def in defs.values_mut() { replace_true_schemas(def); + strip_integer_formats(def); } // Annotate $defs entries with x-method/x-side. Only set x-method for types @@ -189,6 +193,30 @@ fn main() { println!("{json_str}"); } +/// Recursively strip `"format"` from integer-typed schemas. +/// +/// schemars emits `"format": "uint64"` / `"int64"` etc. for Rust integer types. +/// TS codegen tools interpret these as BigInt, but JS/TS uses `number` everywhere. +fn strip_integer_formats(value: &mut Value) { + match value { + Value::Object(map) => { + let is_integer = map.get("type").and_then(|v| v.as_str()) == Some("integer"); + if is_integer { + map.remove("format"); + } + for v in map.values_mut() { + strip_integer_formats(v); + } + } + Value::Array(arr) => { + for v in arr.iter_mut() { + strip_integer_formats(v); + } + } + _ => {} + } +} + /// Recursively replace `true` with `{}` in a JSON value. /// /// In JSON Schema, `true` and `{}` both mean "accept any value", but many diff --git a/ui/.changeset/initial-release.md b/ui/.changeset/initial-release.md deleted file mode 100644 index 83a507ef6d..0000000000 --- a/ui/.changeset/initial-release.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -"@aaif/goose-acp": minor -"@aaif/goose": minor -"@aaif/goose-binary-darwin-arm64": minor -"@aaif/goose-binary-darwin-x64": minor -"@aaif/goose-binary-linux-arm64": minor -"@aaif/goose-binary-linux-x64": minor -"@aaif/goose-binary-win32-x64": minor ---- - -Initial release of Goose npm packages diff --git a/ui/acp/package.json b/ui/acp/package.json index a8b77a8409..3ea77be6b0 100644 --- a/ui/acp/package.json +++ b/ui/acp/package.json @@ -1,6 +1,6 @@ { "name": "@aaif/goose-acp", - "version": "0.2.0", + "version": "0.16.0", "description": "Agent Client Protocol (ACP) SDK for Goose AI agent", "license": "Apache-2.0", "repository": { @@ -21,12 +21,11 @@ "dist" ], "scripts": { - "build": "npm run build:schema && npm run build:ts", - "build:schema": "tsx scripts/build-schema.ts", + "build": "npm run generate && npm run build:ts", "build:ts": "tsc", "build:native": "tsx scripts/build-native.ts", "build:native:all": "tsx scripts/build-native.ts --all", - "generate": "npm run build:schema && npm run build:ts", + "generate": "tsx generate-schema.ts", "lint": "tsc --noEmit", "format": "prettier --write src/" }, diff --git a/ui/acp/scripts/build-schema.ts b/ui/acp/scripts/build-schema.ts deleted file mode 100644 index 8addaf1a57..0000000000 --- a/ui/acp/scripts/build-schema.ts +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/env node -/** - * Builds the generate-acp-schema Rust binary and runs it to generate - * acp-schema.json and acp-meta.json, then generates TypeScript types. - * - * Usage: - * npm run build:schema - */ - -import { execSync } from "child_process"; -import { dirname, resolve } from "path"; -import { fileURLToPath } from "url"; -import { existsSync, copyFileSync, mkdirSync } from "fs"; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = dirname(__filename); -const ROOT = resolve(__dirname, "../../.."); -const ACP_CRATE = resolve(ROOT, "crates/goose-acp"); -const SCHEMA_PATH = resolve(ACP_CRATE, "acp-schema.json"); -const META_PATH = resolve(ACP_CRATE, "acp-meta.json"); -const LOCAL_SCHEMA_PATH = resolve(__dirname, "..", "acp-schema.json"); -const LOCAL_META_PATH = resolve(__dirname, "..", "acp-meta.json"); - -main().catch((err) => { - console.error(err); - process.exit(1); -}); - -async function main() { - console.log("==> Building generate-acp-schema binary..."); - - try { - execSync( - "cargo build --release --bin generate-acp-schema", - { - cwd: ROOT, - stdio: "inherit", - } - ); - } catch (err) { - console.error("Failed to build generate-acp-schema binary"); - throw err; - } - - console.log("==> Running generate-acp-schema..."); - - try { - execSync( - "cargo run --release --bin generate-acp-schema", - { - cwd: ACP_CRATE, - stdio: "inherit", - } - ); - } catch (err) { - console.error("Failed to generate schema"); - throw err; - } - - // Copy schema files to ui/acp for reference - console.log("==> Copying schema files to ui/acp..."); - mkdirSync(dirname(LOCAL_SCHEMA_PATH), { recursive: true }); - copyFileSync(SCHEMA_PATH, LOCAL_SCHEMA_PATH); - copyFileSync(META_PATH, LOCAL_META_PATH); - - console.log("==> Generating TypeScript types..."); - - // Import and run the generate-schema logic - const { default: generateSchema } = await import("../generate-schema.js"); - await generateSchema(); - - console.log("โœ… Schema generation complete"); -} diff --git a/ui/acp/src/generated/zod.gen.ts b/ui/acp/src/generated/zod.gen.ts index f5927e5b3b..6c4860195b 100644 --- a/ui/acp/src/generated/zod.gen.ts +++ b/ui/acp/src/generated/zod.gen.ts @@ -217,7 +217,7 @@ export const zImportSessionResponse = z.object({ z.string(), z.null() ]).optional(), - messageCount: z.coerce.bigint().gte(BigInt(0)).max(BigInt('18446744073709551615'), { message: 'Invalid value: Expected uint64 to be <= 18446744073709551615' }) + messageCount: z.number().int().gte(0) }); /** diff --git a/ui/goose-binary/goose-binary-darwin-arm64/package.json b/ui/goose-binary/goose-binary-darwin-arm64/package.json index 9c02d98e4b..c2fa3f10a5 100644 --- a/ui/goose-binary/goose-binary-darwin-arm64/package.json +++ b/ui/goose-binary/goose-binary-darwin-arm64/package.json @@ -1,6 +1,6 @@ { "name": "@aaif/goose-binary-darwin-arm64", - "version": "0.2.0", + "version": "0.16.0", "description": "Goose binary for macOS ARM64", "license": "Apache-2.0", "repository": { diff --git a/ui/goose-binary/goose-binary-darwin-x64/package.json b/ui/goose-binary/goose-binary-darwin-x64/package.json index 3f119bc979..15d4e2a945 100644 --- a/ui/goose-binary/goose-binary-darwin-x64/package.json +++ b/ui/goose-binary/goose-binary-darwin-x64/package.json @@ -1,6 +1,6 @@ { "name": "@aaif/goose-binary-darwin-x64", - "version": "0.2.0", + "version": "0.16.0", "description": "Goose binary for macOS x64", "license": "Apache-2.0", "repository": { diff --git a/ui/goose-binary/goose-binary-linux-arm64/package.json b/ui/goose-binary/goose-binary-linux-arm64/package.json index 5fcac160d0..46672fda1a 100644 --- a/ui/goose-binary/goose-binary-linux-arm64/package.json +++ b/ui/goose-binary/goose-binary-linux-arm64/package.json @@ -1,6 +1,6 @@ { "name": "@aaif/goose-binary-linux-arm64", - "version": "0.2.0", + "version": "0.16.0", "description": "Goose binary for Linux ARM64", "license": "Apache-2.0", "repository": { diff --git a/ui/goose-binary/goose-binary-linux-x64/package.json b/ui/goose-binary/goose-binary-linux-x64/package.json index d12e7428ba..8a7d10fb14 100644 --- a/ui/goose-binary/goose-binary-linux-x64/package.json +++ b/ui/goose-binary/goose-binary-linux-x64/package.json @@ -1,6 +1,6 @@ { "name": "@aaif/goose-binary-linux-x64", - "version": "0.2.0", + "version": "0.16.0", "description": "Goose binary for Linux x64", "license": "Apache-2.0", "repository": { diff --git a/ui/goose-binary/goose-binary-win32-x64/package.json b/ui/goose-binary/goose-binary-win32-x64/package.json index 804348b386..124c54d83d 100644 --- a/ui/goose-binary/goose-binary-win32-x64/package.json +++ b/ui/goose-binary/goose-binary-win32-x64/package.json @@ -1,6 +1,6 @@ { "name": "@aaif/goose-binary-win32-x64", - "version": "0.2.0", + "version": "0.16.0", "description": "Goose binary for Windows x64", "license": "Apache-2.0", "repository": { diff --git a/ui/text/package.json b/ui/text/package.json index 43136865ae..fa7731ceff 100644 --- a/ui/text/package.json +++ b/ui/text/package.json @@ -1,6 +1,6 @@ { "name": "@aaif/goose", - "version": "0.2.0", + "version": "0.16.0", "description": "Goose - an open-source AI agent", "license": "Apache-2.0", "repository": { diff --git a/ui/text/scripts/postinstall.mjs b/ui/text/scripts/postinstall.mjs index b62b94e6cf..afefbf41d5 100644 --- a/ui/text/scripts/postinstall.mjs +++ b/ui/text/scripts/postinstall.mjs @@ -4,7 +4,7 @@ // optional dependency. Writes the result to a JSON file that the CLI reads at // startup so it can spawn the server automatically. -import { writeFileSync, mkdirSync } from "node:fs"; +import { writeFileSync, mkdirSync, chmodSync } from "node:fs"; import { createRequire } from "node:module"; import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; @@ -46,6 +46,13 @@ try { process.exit(0); } +// Ensure the binary is executable (npm may strip permissions during packaging) +if (process.platform !== "win32") { + try { + chmodSync(binaryPath, 0o755); + } catch {} +} + const outDir = join(__dirname, ".."); mkdirSync(outDir, { recursive: true }); writeFileSync(