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
+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");
}