tui: set up for publishing via github actions (#8020)

This commit is contained in:
Alex Hancock
2026-03-23 13:21:20 -04:00
committed by GitHub
parent c493c6160c
commit 997f27ef33
39 changed files with 3143 additions and 7192 deletions
+116
View File
@@ -0,0 +1,116 @@
name: Build Native Packages
on:
workflow_call:
outputs:
artifact-name:
description: "Name of the artifact containing all native binaries"
value: ${{ jobs.collect.outputs.artifact-name }}
workflow_dispatch:
push:
branches:
- main
paths:
- 'crates/goose-acp/**'
- 'ui/acp/**'
- '.github/workflows/build-native-packages.yml'
pull_request:
paths:
- 'crates/goose-acp/**'
- 'ui/acp/**'
- '.github/workflows/build-native-packages.yml'
jobs:
build-matrix:
name: Build ${{ matrix.platform }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- platform: darwin-arm64
os: macos-14
target: aarch64-apple-darwin
- platform: darwin-x64
os: macos-13
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
- platform: win32-x64
os: windows-latest
target: x86_64-pc-windows-msvc
steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Setup Rust
uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable
with:
targets: ${{ matrix.target }}
- 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 }}
- name: Build goose-acp-server
run: cargo build --release --target ${{ matrix.target }} --bin goose-acp-server
- name: Prepare artifact (Unix)
if: runner.os != 'Windows'
run: |
mkdir -p artifact/bin
cp target/${{ matrix.target }}/release/goose-acp-server artifact/bin/
chmod +x artifact/bin/goose-acp-server
- name: Prepare artifact (Windows)
if: runner.os == 'Windows'
shell: bash
run: |
mkdir -p artifact/bin
cp target/${{ matrix.target }}/release/goose-acp-server.exe artifact/bin/
- name: Upload artifact
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: goose-acp-server-${{ matrix.platform }}
path: artifact/bin/
if-no-files-found: error
retention-days: 7
collect:
name: Collect all binaries
runs-on: ubuntu-latest
needs: build-matrix
outputs:
artifact-name: native-binaries-all
steps:
- name: Download all artifacts
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
path: native-binaries
- name: List downloaded artifacts
run: |
echo "Downloaded artifacts:"
ls -R native-binaries/
- name: Upload combined artifact
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: native-binaries-all
path: native-binaries/
if-no-files-found: error
retention-days: 7
+90
View File
@@ -0,0 +1,90 @@
name: Publish to npm
on:
push:
branches:
- main
concurrency: ${{ github.workflow }}-${{ github.ref }}
permissions:
contents: write
pull-requests: write
id-token: write # Required for npm provenance
jobs:
build-native:
name: Build native binaries
uses: ./.github/workflows/build-native-packages.yml
release:
name: Release
runs-on: ubuntu-latest
needs: build-native
steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Setup Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: '20'
registry-url: 'https://registry.npmjs.org'
- name: Setup Rust
uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable
- name: Setup Rust cache
uses: Swatinem/rust-cache@42dc69e1aa15d09112580998cf2ef0119e2e91ae # v2
- name: Download native binaries
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
name: ${{ needs.build-native.outputs.artifact-name }}
path: native-binaries
- name: Copy binaries to package directories
run: |
for platform_dir in native-binaries/goose-acp-server-*; do
platform=$(basename "$platform_dir")
pkg_dir="ui/goose-acp-server/${platform}"
echo "Copying binaries for ${platform}..."
mkdir -p "${pkg_dir}/bin"
cp -v "${platform_dir}/bin/"* "${pkg_dir}/bin/"
chmod +x "${pkg_dir}/bin/"*
done
- name: Install dependencies
run: |
cd ui
npm ci
- name: Build packages
run: |
cd ui/acp
npm run build
cd ../text
npm run build
- name: Create Release Pull Request or Publish to npm
id: changesets
uses: changesets/action@6d3568c53fbe1db6c1f9ab1c7fbf9092bc18627f # v1
with:
publish: npm run release
version: npm run version
commit: 'chore: version packages'
title: 'chore: version packages'
cwd: ui
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
NPM_CONFIG_PROVENANCE: true
- name: Summary
if: steps.changesets.outputs.published == 'true'
run: |
echo "## Published Packages" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo '${{ steps.changesets.outputs.publishedPackages }}' | jq -r '.[] | "- \(.name)@\(.version)"' >> $GITHUB_STEP_SUMMARY
Generated
+13 -13
View File
@@ -164,7 +164,7 @@ version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc"
dependencies = [
"windows-sys 0.61.2",
"windows-sys 0.60.2",
]
[[package]]
@@ -175,7 +175,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d"
dependencies = [
"anstyle",
"once_cell_polyfill",
"windows-sys 0.61.2",
"windows-sys 0.60.2",
]
[[package]]
@@ -3146,7 +3146,7 @@ dependencies = [
"libc",
"option-ext",
"redox_users 0.5.2",
"windows-sys 0.61.2",
"windows-sys 0.59.0",
]
[[package]]
@@ -3396,7 +3396,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
dependencies = [
"libc",
"windows-sys 0.61.2",
"windows-sys 0.52.0",
]
[[package]]
@@ -5353,7 +5353,7 @@ dependencies = [
"portable-atomic",
"portable-atomic-util",
"serde_core",
"windows-sys 0.61.2",
"windows-sys 0.52.0",
]
[[package]]
@@ -6144,7 +6144,7 @@ version = "0.50.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
dependencies = [
"windows-sys 0.61.2",
"windows-sys 0.59.0",
]
[[package]]
@@ -8006,7 +8006,7 @@ dependencies = [
"errno",
"libc",
"linux-raw-sys 0.12.1",
"windows-sys 0.61.2",
"windows-sys 0.52.0",
]
[[package]]
@@ -8065,7 +8065,7 @@ dependencies = [
"security-framework 3.7.0",
"security-framework-sys",
"webpki-root-certs",
"windows-sys 0.61.2",
"windows-sys 0.52.0",
]
[[package]]
@@ -8856,7 +8856,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e"
dependencies = [
"libc",
"windows-sys 0.61.2",
"windows-sys 0.60.2",
]
[[package]]
@@ -9975,9 +9975,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
[[package]]
name = "tar"
version = "0.4.44"
version = "0.4.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d863878d212c87a19c1a610eb53bb01fe12951c0501cf5a0d65f724914a667a"
checksum = "22692a6476a21fa75fdfc11d452fda482af402c008cdbaf3476414e122040973"
dependencies = [
"filetime",
"libc",
@@ -9994,7 +9994,7 @@ dependencies = [
"getrandom 0.4.2",
"once_cell",
"rustix 1.1.4",
"windows-sys 0.61.2",
"windows-sys 0.52.0",
]
[[package]]
@@ -11559,7 +11559,7 @@ version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
dependencies = [
"windows-sys 0.61.2",
"windows-sys 0.48.0",
]
[[package]]
-1
View File
@@ -1 +0,0 @@
*/bin/
-35
View File
@@ -1,35 +0,0 @@
# Native Binary Packages
This directory contains the npm package scaffolding for distributing the
`goose-acp-server` Rust binary as platform-specific npm packages.
## Packages
| Package | Platform |
|---------|----------|
| `@block/goose-acp-server-darwin-arm64` | macOS Apple Silicon |
| `@block/goose-acp-server-darwin-x64` | macOS Intel |
| `@block/goose-acp-server-linux-arm64` | Linux ARM64 |
| `@block/goose-acp-server-linux-x64` | Linux x64 |
| `@block/goose-acp-server-win32-x64` | Windows x64 |
## Building
From the repository root:
```bash
# Build for all platforms (requires cross-compilation toolchains)
./ui/text/scripts/build-native-packages.sh
# Build for a single platform
./ui/text/scripts/build-native-packages.sh darwin-arm64
```
The built binaries are placed into `npm/goose-acp-server-{platform}/bin/`.
These directories are git-ignored.
## Publishing
```bash
./ui/text/scripts/publish.sh
```
+8
View File
@@ -0,0 +1,8 @@
# Changesets
Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
with multi-package repos, or single-package repos to help you version and publish your code. You can
find the full documentation for it [in our repository](https://github.com/changesets/changesets)
We have a quick list of common questions to get you started engaging with this project in
[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
+11
View File
@@ -0,0 +1,11 @@
{
"$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json",
"changelog": "@changesets/cli/changelog",
"commit": false,
"fixed": [],
"linked": [],
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": []
}
+11
View File
@@ -0,0 +1,11 @@
---
"@aaif/goose-acp": minor
"@aaif/goose": minor
"@aaif/goose-acp-server-darwin-arm64": minor
"@aaif/goose-acp-server-darwin-x64": minor
"@aaif/goose-acp-server-linux-arm64": minor
"@aaif/goose-acp-server-linux-x64": minor
"@aaif/goose-acp-server-win32-x64": minor
---
Initial release of Goose npm packages
+4
View File
@@ -1 +1,5 @@
registry=https://registry.npmjs.org/
prefer-offline=true
node-linker=hoisted
supportedArchitectures.os=current,linux,darwin,win32
supportedArchitectures.cpu=current,x64,arm64
+4
View File
@@ -1,2 +1,6 @@
dist/
node_modules/
# Generated schema files (generated from Rust during build)
acp-schema.json
acp-meta.json
+131
View File
@@ -0,0 +1,131 @@
# @aaif/goose-acp
TypeScript client library for the Goose Agent Client Protocol (ACP).
This package provides:
- TypeScript types and Zod validators for Goose ACP extension methods
- A client for communicating with the Goose ACP server
## Installation
```bash
npm install @aaif/goose-acp
```
The native `goose-acp-server` binaries are distributed as optional dependencies
and will be automatically installed for your platform.
## Development
### Prerequisites
- Node.js 18+
- Rust toolchain
- (Optional) Cross-compilation toolchains for building all platforms
### Building
```bash
# Build everything (schema + TypeScript)
npm run build
# Build just the schema (requires Rust)
npm run build:schema
# Build just the TypeScript
npm run build:ts
# Build native binary for current platform
npm run build:native
# Build native binaries for all platforms
npm run build:native:all
```
### Local Development with npm link
To use this package locally in another project (e.g., `@aaif/goose`):
```bash
# In ui/acp
npm run build
npm link
# In ui/text (or another project)
npm link @aaif/goose-acp
```
### Schema Generation
The TypeScript types are generated from Rust schemas defined in `crates/goose-acp`.
The build process:
1. Builds the `generate-acp-schema` Rust binary
2. Runs it to generate `acp-schema.json` and `acp-meta.json`
3. Uses `@hey-api/openapi-ts` to generate TypeScript types and Zod validators
4. Generates a typed client in `src/generated/client.gen.ts`
To regenerate schemas after changing Rust types:
```bash
npm run build:schema
```
## Native Binary Packages
Platform-specific npm packages for the `goose-acp-server` binary are located in
`ui/goose-acp-server/`:
| Package | Platform |
|---------|----------|
| `@aaif/goose-acp-server-darwin-arm64` | macOS Apple Silicon |
| `@aaif/goose-acp-server-darwin-x64` | macOS Intel |
| `@aaif/goose-acp-server-linux-arm64` | Linux ARM64 |
| `@aaif/goose-acp-server-linux-x64` | Linux x64 |
| `@aaif/goose-acp-server-win32-x64` | Windows x64 |
These are published separately from `@aaif/goose-acp`.
### Building Native Binaries
```bash
# Build for current platform
npm run build:native
# Build for all platforms (requires cross-compilation toolchains)
npm run build:native:all
# Build for specific platform(s)
npx tsx scripts/build-native.ts darwin-arm64 linux-x64
```
## Publishing
Publishing is handled by GitHub Actions. See `.github/workflows/publish-npm.yml`.
For manual publishing:
```bash
# From repository root
./ui/scripts/publish.sh --real
```
This will:
1. Build and publish `@aaif/goose-acp`
2. Publish all native binary packages
3. Publish `@aaif/goose` (which depends on the above)
## Usage
```typescript
import { GooseClient } from "@aaif/goose-acp";
const client = new GooseClient({
// ... configuration
});
// Use the client
const result = await client.someMethod({ ... });
```
See the [main documentation](../../README.md) for more details.
+10 -6
View File
@@ -20,12 +20,8 @@ const SCHEMA_PATH = resolve(ROOT, "crates/goose-acp/acp-schema.json");
const META_PATH = resolve(ROOT, "crates/goose-acp/acp-meta.json");
const OUTPUT_DIR = resolve(__dirname, "src/generated");
main().catch((err) => {
console.error(err);
process.exit(1);
});
async function main() {
// Export the main function so it can be imported by build-schema.ts
export default async function main() {
const schemaSrc = await fs.readFile(SCHEMA_PATH, "utf8");
const jsonSchema = JSON.parse(
schemaSrc.replaceAll("#/$defs/", "#/components/schemas/"),
@@ -208,3 +204,11 @@ ${methodDefs.join("\n")}
const clientPath = resolve(OUTPUT_DIR, "client.gen.ts");
await fs.writeFile(clientPath, src);
}
// Run main if this file is executed directly
if (import.meta.url === `file://${process.argv[1]}`) {
main().catch((err) => {
console.error(err);
process.exit(1);
});
}
-1277
View File
File diff suppressed because it is too large Load Diff
+21 -3
View File
@@ -1,6 +1,19 @@
{
"name": "@block/goose-acp",
"name": "@aaif/goose-acp",
"version": "0.1.0",
"description": "Agent Client Protocol (ACP) SDK for Goose AI agent",
"license": "Apache-2.0",
"repository": {
"type": "git",
"url": "git+https://github.com/block/goose.git"
},
"keywords": [
"goose",
"ai",
"agent",
"acp",
"agent-client-protocol"
],
"type": "module",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
@@ -8,8 +21,12 @@
"dist"
],
"scripts": {
"build": "tsc",
"generate": "tsx generate-schema.ts",
"build": "npm run build:schema && npm run build:ts",
"build:schema": "tsx scripts/build-schema.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",
"lint": "tsc --noEmit",
"format": "prettier --write src/"
},
@@ -22,6 +39,7 @@
"devDependencies": {
"@agentclientprotocol/sdk": "^0.14.1",
"@hey-api/openapi-ts": "^0.92.3",
"@types/node": "^20.0.0",
"prettier": "^3.8.1",
"tsx": "^4.21.0",
"typescript": "~5.9.3"
+134
View File
@@ -0,0 +1,134 @@
#!/usr/bin/env node
/**
* Builds the goose-acp-server binary for target platforms and places them
* into the corresponding npm package directories under native/.
*
* Usage:
* npm run build:native # build for current platform only
* npm run build:native:all # build for all platforms
* tsx scripts/build-native.ts darwin-arm64 # build specific platform
*
* Prerequisites:
* - Rust cross-compilation toolchains installed for each target
*/
import { execSync } from "child_process";
import { dirname, resolve } from "path";
import { fileURLToPath } from "url";
import { mkdirSync, copyFileSync, chmodSync, existsSync } from "fs";
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const ROOT = resolve(__dirname, "../../..");
const NATIVE_DIR = resolve(ROOT, "ui/goose-acp-server");
const RUST_TARGETS: Record<string, string> = {
"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",
};
const PLATFORM_MAP: Record<string, string> = {
"darwin-arm64": "darwin-arm64",
"darwin-x64": "darwin-x64",
"linux-arm64": "linux-arm64",
"linux-x64": "linux-x64",
"win32-x64": "win32-x64",
};
function getCurrentPlatform(): string | null {
const platform = process.platform;
const arch = process.arch;
const key = `${platform}-${arch}`;
return PLATFORM_MAP[key] || null;
}
function buildTarget(platform: string): void {
const rustTarget = RUST_TARGETS[platform];
if (!rustTarget) {
throw new Error(`Unknown platform: ${platform}`);
}
const pkgDir = resolve(NATIVE_DIR, `goose-acp-server-${platform}`);
const binDir = resolve(pkgDir, "bin");
console.log(`==> Building goose-acp-server for ${platform} (${rustTarget})`);
try {
execSync(
`cargo build --release --target ${rustTarget} --bin goose-acp-server`,
{
cwd: ROOT,
stdio: "inherit",
}
);
} catch (err) {
console.error(`Failed to build for ${platform}`);
throw err;
}
mkdirSync(binDir, { recursive: true });
const ext = platform.startsWith("win32") ? ".exe" : "";
const binaryName = `goose-acp-server${ext}`;
const srcPath = resolve(ROOT, "target", rustTarget, "release", binaryName);
const destPath = resolve(binDir, binaryName);
if (!existsSync(srcPath)) {
throw new Error(`Binary not found at ${srcPath}`);
}
copyFileSync(srcPath, destPath);
chmodSync(destPath, 0o755);
console.log(` ✅ Placed binary at ${destPath}`);
}
async function main() {
const args = process.argv.slice(2);
const buildAll = args.includes("--all");
if (buildAll) {
console.log("==> Building for all platforms");
for (const platform of Object.keys(RUST_TARGETS)) {
try {
buildTarget(platform);
} catch (err) {
console.error(`Failed to build ${platform}:`, err);
process.exit(1);
}
}
} else if (args.length > 0 && !args[0].startsWith("--")) {
// Build specific platforms
for (const platform of args) {
if (!RUST_TARGETS[platform]) {
console.error(`Unknown platform: ${platform}`);
console.error(`Valid platforms: ${Object.keys(RUST_TARGETS).join(", ")}`);
process.exit(1);
}
buildTarget(platform);
}
} else {
// Build for current platform only
const currentPlatform = getCurrentPlatform();
if (!currentPlatform) {
console.error(
`Unsupported platform: ${process.platform}-${process.arch}`
);
console.error(`Valid platforms: ${Object.keys(RUST_TARGETS).join(", ")}`);
console.error(`Use --all to build for all platforms`);
process.exit(1);
}
console.log(`==> Building for current platform: ${currentPlatform}`);
buildTarget(currentPlatform);
}
console.log("==> Done. Native packages staged in ui/goose-acp-server/");
}
main().catch((err) => {
console.error(err);
process.exit(1);
});
+73
View File
@@ -0,0 +1,73 @@
#!/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");
}
-5
View File
@@ -1,5 +0,0 @@
registry=https://registry.npmjs.org/
prefer-offline=true
node-linker=hoisted
supportedArchitectures.os=current,linux,darwin,win32
supportedArchitectures.cpu=current,x64,arm64
+4 -15
View File
@@ -41,7 +41,8 @@
"start-alpha-gui": "ALPHA=true pnpm run start-gui"
},
"dependencies": {
"@mcp-ui/client": "^6.1.0",
"@aaif/goose-acp": "workspace:*",
"@mcp-ui/client": "6.1.0",
"@modelcontextprotocol/ext-apps": "^1.1.1",
"@radix-ui/react-accordion": "^1.2.12",
"@radix-ui/react-avatar": "^1.1.11",
@@ -54,7 +55,7 @@
"@radix-ui/react-slot": "^1.2.4",
"@radix-ui/react-tabs": "^1.1.13",
"@radix-ui/themes": "^3.3.0",
"@tanstack/react-form": "^1.28.3",
"@tanstack/react-form": "1.28.3",
"@types/react-router-dom": "^5.3.3",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
@@ -69,7 +70,6 @@
"electron-window-state": "^5.0.3",
"express": "^5.2.1",
"framer-motion": "^12.34.3",
"goose-acp-types": "file:../acp",
"katex": "^0.16.33",
"lodash": "^4.17.23",
"lucide-react": "^0.575.0",
@@ -121,6 +121,7 @@
"@types/electron-squirrel-startup": "^1.0.2",
"@types/express": "^5.0.6",
"@types/lodash": "^4.17.24",
"@types/node": "^25.5.0",
"@types/react": "^19.2.14",
"@types/react-dom": "^19.2.3",
"@types/react-syntax-highlighter": "^15.5.13",
@@ -150,18 +151,6 @@
},
"keywords": [],
"license": "Apache-2.0",
"pnpm": {
"overrides": {
"react": "^19.2.4",
"react-dom": "^19.2.4"
},
"onlyBuiltDependencies": [
"@modelcontextprotocol/ext-apps",
"electron",
"electron-winstaller",
"esbuild"
]
},
"lint-staged": {
"src/**/*.{ts,tsx}": [
"bash -c 'pnpm run typecheck'",
+1 -1
View File
@@ -11,6 +11,6 @@ import type { ClientOptions as ClientOptions2 } from './types.gen';
* `setConfig()`. This is useful for example if you're using Next.js
* to ensure your client always has the correct values.
*/
export type CreateClientConfig<T extends ClientOptions = ClientOptions2> = (override?: Config<ClientOptions & T>) => Config<Required<ClientOptions> & T>;
export type CreateClientConfig<T extends ClientOptions = ClientOptions2> = (override?: Config<ClientOptions & T>) => Config<Required<ClientOptions> & T> | Promise<Config<Required<ClientOptions> & T>>;
export const client = createClient(createConfig<ClientOptions2>());
+1 -1
View File
@@ -190,7 +190,7 @@ export type Client = CoreClient<RequestFn, Config, MethodFn, BuildUrlFn, SseFn>
*/
export type CreateClientConfig<T extends ClientOptions = ClientOptions> = (
override?: Config<ClientOptions & T>,
) => Config<Required<ClientOptions> & T>;
) => Config<Required<ClientOptions> & T> | Promise<Config<Required<ClientOptions> & T>>;
export interface TDataShape {
body?: unknown;
+1 -1
View File
@@ -96,7 +96,7 @@ interface Params {
const stripEmptySlots = (params: Params) => {
for (const [slot, value] of Object.entries(params)) {
if (value && typeof value === 'object' && !Object.keys(value).length) {
if (value && typeof value === 'object' && !Array.isArray(value) && !Object.keys(value).length) {
delete params[slot as Slot];
}
}
+1 -1
View File
@@ -21,7 +21,7 @@
/* Electron/Node.js specific */
"types": ["node"],
"typeRoots": ["./node_modules/@types", "./src/types", "./node_modules/electron"],
"typeRoots": ["./node_modules/@types", "../node_modules/@types", "./src/types", "./node_modules/electron"],
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true,
+2
View File
@@ -0,0 +1,2 @@
# Ignore built binaries - these are generated by build:native scripts
*/bin/
+54
View File
@@ -0,0 +1,54 @@
# Native Binary Packages for goose-acp-server
This directory contains the npm package scaffolding for distributing the
`goose-acp-server` Rust binary as platform-specific npm packages.
## Packages
| Package | Platform |
|---------|----------|
| `@aaif/goose-acp-server-darwin-arm64` | macOS Apple Silicon |
| `@aaif/goose-acp-server-darwin-x64` | macOS Intel |
| `@aaif/goose-acp-server-linux-arm64` | Linux ARM64 |
| `@aaif/goose-acp-server-linux-x64` | Linux x64 |
| `@aaif/goose-acp-server-win32-x64` | Windows x64 |
## Building
From the repository root:
```bash
# Build for current platform only
cd ui/acp
npm run build:native
# Build for all platforms (requires cross-compilation toolchains)
npm run build:native:all
# Build for specific platform(s)
npx tsx scripts/build-native.ts darwin-arm64 linux-x64
```
The built binaries are placed into `ui/goose-acp-server/goose-acp-server-{platform}/bin/`.
These directories are git-ignored.
## Publishing
Publishing is handled by GitHub Actions. See `.github/workflows/publish-npm.yml`.
For manual publishing:
```bash
# From repository root
./ui/scripts/publish.sh --real
```
This will publish all native packages along with `@aaif/goose-acp` and `@aaif/goose`.
## Usage
These packages are installed as optional dependencies by `@aaif/goose` (the TUI).
The appropriate package for the user's platform is automatically selected during
installation.
See `ui/text/scripts/postinstall.mjs` for how the binary path is resolved.
@@ -1,5 +1,5 @@
{
"name": "@block/goose-acp-server-darwin-arm64",
"name": "@aaif/goose-acp-server-darwin-arm64",
"version": "0.1.0",
"description": "Goose ACP server binary for macOS ARM64",
"license": "Apache-2.0",
@@ -7,6 +7,14 @@
"type": "git",
"url": "git+https://github.com/block/goose.git"
},
"keywords": [
"goose",
"ai",
"agent",
"acp",
"server",
"binary"
],
"os": [
"darwin"
],
@@ -14,6 +22,6 @@
"arm64"
],
"files": [
"bin/goose"
"bin/goose-acp-server"
]
}
@@ -1,5 +1,5 @@
{
"name": "@block/goose-acp-server-darwin-x64",
"name": "@aaif/goose-acp-server-darwin-x64",
"version": "0.1.0",
"description": "Goose ACP server binary for macOS x64",
"license": "Apache-2.0",
@@ -7,6 +7,14 @@
"type": "git",
"url": "git+https://github.com/block/goose.git"
},
"keywords": [
"goose",
"ai",
"agent",
"acp",
"server",
"binary"
],
"os": [
"darwin"
],
@@ -14,6 +22,6 @@
"x64"
],
"files": [
"bin/goose"
"bin/goose-acp-server"
]
}
@@ -1,5 +1,5 @@
{
"name": "@block/goose-acp-server-linux-arm64",
"name": "@aaif/goose-acp-server-linux-arm64",
"version": "0.1.0",
"description": "Goose ACP server binary for Linux ARM64",
"license": "Apache-2.0",
@@ -7,6 +7,14 @@
"type": "git",
"url": "git+https://github.com/block/goose.git"
},
"keywords": [
"goose",
"ai",
"agent",
"acp",
"server",
"binary"
],
"os": [
"linux"
],
@@ -14,6 +22,6 @@
"arm64"
],
"files": [
"bin/goose"
"bin/goose-acp-server"
]
}
@@ -1,5 +1,5 @@
{
"name": "@block/goose-acp-server-linux-x64",
"name": "@aaif/goose-acp-server-linux-x64",
"version": "0.1.0",
"description": "Goose ACP server binary for Linux x64",
"license": "Apache-2.0",
@@ -7,6 +7,14 @@
"type": "git",
"url": "git+https://github.com/block/goose.git"
},
"keywords": [
"goose",
"ai",
"agent",
"acp",
"server",
"binary"
],
"os": [
"linux"
],
@@ -14,6 +22,6 @@
"x64"
],
"files": [
"bin/goose"
"bin/goose-acp-server"
]
}
@@ -1,5 +1,5 @@
{
"name": "@block/goose-acp-server-win32-x64",
"name": "@aaif/goose-acp-server-win32-x64",
"version": "0.1.0",
"description": "Goose ACP server binary for Windows x64",
"license": "Apache-2.0",
@@ -7,6 +7,14 @@
"type": "git",
"url": "git+https://github.com/block/goose.git"
},
"keywords": [
"goose",
"ai",
"agent",
"acp",
"server",
"binary"
],
"os": [
"win32"
],
@@ -14,6 +22,6 @@
"x64"
],
"files": [
"bin/goose.exe"
"bin/goose-acp-server.exe"
]
}
-2929
View File
File diff suppressed because it is too large Load Diff
+24 -2
View File
@@ -2,6 +2,28 @@
"private": true,
"workspaces": [
"acp",
"text"
]
"text",
"desktop",
"goose-acp-server/*"
],
"scripts": {
"changeset": "changeset",
"version": "changeset version",
"release": "changeset publish"
},
"devDependencies": {
"@changesets/cli": "^2.27.1"
},
"pnpm": {
"overrides": {
"react": "^19.2.4",
"react-dom": "^19.2.4"
},
"onlyBuiltDependencies": [
"@modelcontextprotocol/ext-apps",
"electron",
"electron-winstaller",
"esbuild"
]
}
}
File diff suppressed because it is too large Load Diff
+5
View File
@@ -0,0 +1,5 @@
packages:
- 'acp'
- 'text'
- 'desktop'
- 'goose-acp-server/*'
+14 -14
View File
@@ -1,19 +1,19 @@
#!/usr/bin/env bash
set -euo pipefail
# Publishes @block/goose-acp, @block/goose, and all native binary packages to npm.
# Publishes @aaif/goose-acp, @aaif/goose, and all native binary packages to npm.
#
# Usage:
# ./ui/scripts/publish.sh # publish all (dry-run)
# ./ui/scripts/publish.sh --real # publish for real
#
# Prerequisites:
# - npm login to the @block scope
# - Native binaries built via build-native-packages.sh
# - npm login to the @aaif scope
# - Native binaries built via npm run build:native:all in ui/acp
REPO_ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
NPM_DIR="${REPO_ROOT}/npm"
ACP_DIR="${REPO_ROOT}/ui/acp"
NATIVE_DIR="${REPO_ROOT}/ui/goose-acp-server"
TEXT_DIR="${REPO_ROOT}/ui/text"
DRY_RUN="--dry-run"
@@ -24,15 +24,15 @@ else
echo "==> Dry run (pass --real to publish)"
fi
# Build and publish @block/goose-acp first (dependency of @block/goose)
echo "==> Building @block/goose-acp"
# Build and publish @aaif/goose-acp first (dependency of @aaif/goose)
echo "==> Building @aaif/goose-acp"
(cd "${ACP_DIR}" && npm run build)
echo "==> Publishing @block/goose-acp"
echo "==> Publishing @aaif/goose-acp"
(cd "${ACP_DIR}" && npm publish --access public ${DRY_RUN})
# Build @block/goose
echo "==> Building @block/goose"
# Build @aaif/goose
echo "==> Building @aaif/goose"
(cd "${TEXT_DIR}" && npm run build)
NATIVE_PACKAGES=(
@@ -45,19 +45,19 @@ NATIVE_PACKAGES=(
# Publish native binary packages
for pkg in "${NATIVE_PACKAGES[@]}"; do
pkg_dir="${NPM_DIR}/${pkg}"
pkg_dir="${NATIVE_DIR}/${pkg}"
if [ ! -f "${pkg_dir}/bin/goose" ] && [ ! -f "${pkg_dir}/bin/goose.exe" ]; then
echo " SKIP ${pkg} (no binary found — run build-native-packages.sh first)"
if [ ! -f "${pkg_dir}/bin/goose-acp-server" ] && [ ! -f "${pkg_dir}/bin/goose-acp-server.exe" ]; then
echo " SKIP ${pkg} (no binary found — run npm run build:native:all in ui/acp first)"
continue
fi
echo "==> Publishing @block/${pkg}"
echo "==> Publishing @aaif/${pkg}"
(cd "${pkg_dir}" && npm publish --access public ${DRY_RUN})
done
# Publish the main package
echo "==> Publishing @block/goose"
echo "==> Publishing @aaif/goose"
(cd "${TEXT_DIR}" && npm publish --access public ${DRY_RUN})
echo "==> Done"
-1762
View File
File diff suppressed because it is too large Load Diff
+14 -7
View File
@@ -1,5 +1,5 @@
{
"name": "@block/goose",
"name": "@aaif/goose",
"version": "0.1.0",
"description": "Goose - an open-source AI agent",
"license": "Apache-2.0",
@@ -7,6 +7,13 @@
"type": "git",
"url": "git+https://github.com/block/goose.git"
},
"keywords": [
"goose",
"ai",
"agent",
"cli",
"terminal"
],
"type": "module",
"bin": {
"goose": "dist/tui.js"
@@ -24,7 +31,7 @@
},
"dependencies": {
"@agentclientprotocol/sdk": "^0.14.1",
"@block/goose-acp": "^0.1.0",
"@aaif/goose-acp": "workspace:*",
"ink": "^6.8.0",
"ink-text-input": "^6.0.0",
"marked": "^15.0.12",
@@ -33,11 +40,11 @@
"react": "^19.2.4"
},
"optionalDependencies": {
"@block/goose-acp-server-darwin-arm64": "0.1.0",
"@block/goose-acp-server-darwin-x64": "0.1.0",
"@block/goose-acp-server-linux-arm64": "0.1.0",
"@block/goose-acp-server-linux-x64": "0.1.0",
"@block/goose-acp-server-win32-x64": "0.1.0"
"@aaif/goose-acp-server-darwin-arm64": "workspace:*",
"@aaif/goose-acp-server-darwin-x64": "workspace:*",
"@aaif/goose-acp-server-linux-arm64": "workspace:*",
"@aaif/goose-acp-server-linux-x64": "workspace:*",
"@aaif/goose-acp-server-win32-x64": "workspace:*"
},
"overrides": {
"react": "19.2.4"
-66
View File
@@ -1,66 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
# Builds the goose-acp-server binary for each target platform and places it
# into the corresponding npm package directory under npm/.
#
# Usage:
# ./ui/text/scripts/build-native-packages.sh # build all targets
# ./ui/text/scripts/build-native-packages.sh darwin-arm64 # build one target
#
# Prerequisites:
# - Rust cross-compilation toolchains installed for each target
# - Run from the repository root
REPO_ROOT="$(cd "$(dirname "$0")/../../.." && pwd)"
NPM_DIR="${REPO_ROOT}/npm"
declare -A RUST_TARGETS=(
["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"
)
build_target() {
local platform="$1"
local rust_target="${RUST_TARGETS[$platform]}"
local pkg_dir="${NPM_DIR}/goose-acp-server-${platform}"
local bin_dir="${pkg_dir}/bin"
echo "==> Building goose for ${platform} (${rust_target})"
cargo build --release --target "${rust_target}" --bin goose
mkdir -p "${bin_dir}"
local ext=""
if [[ "$platform" == win32-* ]]; then
ext=".exe"
fi
cp "${REPO_ROOT}/target/${rust_target}/release/goose${ext}" "${bin_dir}/goose${ext}"
chmod +x "${bin_dir}/goose${ext}"
echo " Placed binary at ${bin_dir}/goose${ext}"
}
if [ $# -gt 0 ]; then
# Build specific target(s)
for target in "$@"; do
if [[ -z "${RUST_TARGETS[$target]+x}" ]]; then
echo "Unknown target: ${target}"
echo "Valid targets: ${!RUST_TARGETS[*]}"
exit 1
fi
build_target "$target"
done
else
# Build all targets
for platform in "${!RUST_TARGETS[@]}"; do
build_target "$platform"
done
fi
echo "==> Done. Native packages staged in ${NPM_DIR}/"
+9 -9
View File
@@ -13,11 +13,11 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
const require = createRequire(import.meta.url);
const PLATFORMS = {
"darwin-arm64": "@block/goose-acp-server-darwin-arm64",
"darwin-x64": "@block/goose-acp-server-darwin-x64",
"linux-arm64": "@block/goose-acp-server-linux-arm64",
"linux-x64": "@block/goose-acp-server-linux-x64",
"win32-x64": "@block/goose-acp-server-win32-x64",
"darwin-arm64": "@aaif/goose-acp-server-darwin-arm64",
"darwin-x64": "@aaif/goose-acp-server-darwin-x64",
"linux-arm64": "@aaif/goose-acp-server-linux-arm64",
"linux-x64": "@aaif/goose-acp-server-linux-x64",
"win32-x64": "@aaif/goose-acp-server-win32-x64",
};
const key = `${process.platform}-${process.arch}`;
@@ -25,7 +25,7 @@ const pkg = PLATFORMS[key];
if (!pkg) {
console.warn(
`@block/goose: no prebuilt goose-acp-server binary for ${key}. ` +
`@aaif/goose: no prebuilt goose-acp-server binary for ${key}. ` +
`You will need to provide a server URL manually with --server.`,
);
process.exit(0);
@@ -35,12 +35,12 @@ let binaryPath;
try {
// Resolve the package directory, then point at the binary inside it
const pkgDir = dirname(require.resolve(`${pkg}/package.json`));
const binName = process.platform === "win32" ? "goose.exe" : "goose";
const binName = process.platform === "win32" ? "goose-acp-server.exe" : "goose-acp-server";
binaryPath = join(pkgDir, "bin", binName);
} catch {
// The optional dependency wasn't installed (e.g. wrong platform). That's fine.
console.warn(
`@block/goose: optional dependency ${pkg} not installed. ` +
`@aaif/goose: optional dependency ${pkg} not installed. ` +
`You will need to provide a server URL manually with --server.`,
);
process.exit(0);
@@ -53,4 +53,4 @@ writeFileSync(
JSON.stringify({ binaryPath }, null, 2) + "\n",
);
console.log(`@block/goose: found native server binary at ${binaryPath}`);
console.log(`@aaif/goose: found native server binary at ${binaryPath}`);
+1 -1
View File
@@ -19,7 +19,7 @@ import type {
Stream,
} from "@agentclientprotocol/sdk";
import { ndJsonStream } from "@agentclientprotocol/sdk";
import { GooseClient } from "@block/goose-acp";
import { GooseClient } from "@aaif/goose-acp";
import { renderMarkdown } from "./markdown.js";
import { buildToolCallCardLines, ToolCallCompact, findFeaturedToolCallId } from "./toolcall.js";
import type { ToolCallInfo } from "./toolcall.js";