Files
openwork/packages/server/script/build.ts
ben 28b1ff39e4 feat: host mode prefers OpenWork server for skills/plugins management (#304)
* feat: host mode prefers OpenWork server for skills/plugins management

- Add hostToken support to OpenWork server client (X-OpenWork-Host-Token header)
- Add includeGlobal query param to listSkills and listPlugins
- Host mode now uses OpenWork server first for:
  - refreshSkills (with includeGlobal for global skills)
  - refreshPlugins (project scope)
  - addPlugin (project scope)
  - installSkillCreator
- Falls back to local filesystem if OpenWork server unavailable
- Fix missing WorkspaceInfo import in dashboard.tsx

* feat: add server binary build script and prefer opencode.jsonc

- Add packages/server/script/build.ts for compiling standalone server binary
- Add build:bin and build:bin:all scripts to server package.json
- Update workspace-files.ts to prefer opencode.jsonc over opencode.json

* fix: compile openwork-server as standalone binary on all platforms

Replace shell launcher script with bun build --compile to create
a standalone binary that doesn't require Bun at runtime.

* feat: host mode uses OpenWork server for commands, MCP, and default model

- Prefer OpenWork server for command save/delete/list in host mode
- Use OpenWork server for Notion MCP setup and MCP refresh/connect when available
- Resolve host workspace id via OpenWork server in host mode
- Fetch host capabilities and pass host token to server client
- Read/write default model via OpenWork server when connected

* fix: rebuild openwork-server sidecar reliably

- Use bun build CLI for compiled server binary
- Detect and replace stub launcher before building

* fix: create target-specific openwork-server sidecar

- Copy compiled openwork-server to platform triple name
- Regenerate stub targets when needed
2026-01-28 19:11:03 -08:00

113 lines
2.8 KiB
TypeScript

import { spawnSync } from "node:child_process";
import { mkdirSync } from "node:fs";
import { join, resolve } from "node:path";
const bunRuntime = (globalThis as typeof globalThis & {
Bun?: {
build?: (...args: any[]) => Promise<any>;
argv?: string[];
};
}).Bun;
if (!bunRuntime?.build || !bunRuntime.argv) {
console.error("This script must be run with Bun.");
process.exit(1);
}
const bun = bunRuntime as { build: (...args: any[]) => Promise<any>; argv: string[] };
type BuildOptions = {
targets: string[];
outdir: string;
filename: string;
};
function readArgs(argv: string[]): BuildOptions {
const options: BuildOptions = {
targets: [],
outdir: resolve("dist", "bin"),
filename: "openwork-server",
};
for (let index = 0; index < argv.length; index += 1) {
const value = argv[index];
if (!value) continue;
if (value === "--target") {
const next = argv[index + 1];
if (next) {
options.targets.push(next);
index += 1;
}
continue;
}
if (value.startsWith("--target=")) {
const next = value.slice("--target=".length).trim();
if (next) options.targets.push(next);
continue;
}
if (value === "--outdir") {
const next = argv[index + 1];
if (next) {
options.outdir = resolve(next);
index += 1;
}
continue;
}
if (value.startsWith("--outdir=")) {
const next = value.slice("--outdir=".length).trim();
if (next) options.outdir = resolve(next);
continue;
}
if (value === "--filename") {
const next = argv[index + 1];
if (next) {
options.filename = next;
index += 1;
}
continue;
}
if (value.startsWith("--filename=")) {
const next = value.slice("--filename=".length).trim();
if (next) options.filename = next;
}
}
return options;
}
function outputName(filename: string, target?: string) {
const needsExe = target ? target.includes("windows") : process.platform === "win32";
const suffix = target ? `-${target}` : "";
const ext = needsExe ? ".exe" : "";
return `${filename}${suffix}${ext}`;
}
async function buildOnce(entrypoint: string, outdir: string, filename: string, target?: string) {
mkdirSync(outdir, { recursive: true });
const outfile = join(outdir, outputName(filename, target));
const args = ["build", entrypoint, "--compile", "--outfile", outfile];
if (target) {
args.push("--target", target);
}
const result = spawnSync("bun", args, { stdio: "inherit" });
if (result.status !== 0) {
process.exit(result.status ?? 1);
}
}
const options = readArgs(bun.argv.slice(2));
const entrypoint = resolve("src", "cli.ts");
const targets = options.targets.length ? options.targets : [undefined];
for (const target of targets) {
await buildOnce(entrypoint, options.outdir, options.filename, target);
}