From 639544767371e21e0cbe27ff66d0f577f1af5e40 Mon Sep 17 00:00:00 2001 From: Jonathan Zhang Date: Mon, 27 Apr 2026 23:03:28 +0800 Subject: [PATCH 1/6] add CICD --- .github/workflows/ci.yml | 31 ++++++++ .github/workflows/release.yml | 105 ++++++++++++++++++++++++++ package.json | 1 + packages/desktop/electron-builder.yml | 15 ++++ packages/desktop/package.json | 4 +- scripts/bump-version.ts | 34 +++++++++ scripts/prepare-cloudflared.ts | 101 +++++++++++++++++++++++++ 7 files changed, 290 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/release.yml create mode 100644 scripts/bump-version.ts create mode 100644 scripts/prepare-cloudflared.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..816eeac --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,31 @@ +name: CI + +on: + push: + branches: [dev] + pull_request: + branches: [dev] + +jobs: + check: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - uses: oven-sh/setup-bun@v2 + + - uses: actions/setup-node@v4 + with: + node-version: 20 + + - run: bun install + working-directory: packages/server + + - run: npm install + working-directory: packages/desktop + + - run: npm run check + + - run: bun test + working-directory: packages/server diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..964d872 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,105 @@ +name: Release + +on: + push: + tags: + - 'v*.*.*' + +jobs: + build-mac: + runs-on: macos-latest + + steps: + - uses: actions/checkout@v4 + + - uses: oven-sh/setup-bun@v2 + + - uses: actions/setup-node@v4 + with: + node-version: 20 + + - run: bun run scripts/prepare-cloudflared.ts + + - run: bun install + working-directory: packages/server + + - run: bun run build + working-directory: packages/server + + - run: npm install + working-directory: packages/desktop + + - run: npm run build + working-directory: packages/desktop + + - run: npm run dist:mac + working-directory: packages/desktop + + - uses: actions/upload-artifact@v4 + with: + name: mac-build + path: packages/desktop/dist/*.dmg + + build-win: + runs-on: windows-latest + + steps: + - uses: actions/checkout@v4 + + - uses: oven-sh/setup-bun@v2 + + - uses: actions/setup-node@v4 + with: + node-version: 20 + + - run: bun run scripts/prepare-cloudflared.ts + + - run: bun install + working-directory: packages/server + + - run: bun run build + working-directory: packages/server + + - run: npm install + working-directory: packages/desktop + + - run: npm run build + working-directory: packages/desktop + + - run: npm run dist:win + working-directory: packages/desktop + + - uses: actions/upload-artifact@v4 + with: + name: win-build + path: packages/desktop/dist/*.exe + + release: + needs: [build-mac, build-win] + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + - uses: actions/checkout@v4 + + - uses: actions/download-artifact@v4 + with: + name: mac-build + path: ./artifacts/mac + + - uses: actions/download-artifact@v4 + with: + name: win-build + path: ./artifacts/win + + - name: Create Release + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + TAG=${GITHUB_REF#refs/tags/} + gh release create "$TAG" \ + ./artifacts/mac/*.dmg \ + ./artifacts/win/*.exe \ + --title "$TAG" \ + --generate-notes diff --git a/package.json b/package.json index 47a238d..7fe8d5a 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "format": "prettier --write \"packages/*/src/**/*.{ts,tsx}\"", "format:check": "prettier --check \"packages/*/src/**/*.{ts,tsx}\"", "check": "npm run lint && npm run format:check && npm run typecheck", + "bump": "bun run scripts/bump-version.ts", "prepare": "husky" }, "devDependencies": { diff --git a/packages/desktop/electron-builder.yml b/packages/desktop/electron-builder.yml index 7b8a41d..4ec2f38 100644 --- a/packages/desktop/electron-builder.yml +++ b/packages/desktop/electron-builder.yml @@ -5,9 +5,24 @@ extraResources: to: "bin/persona-agent-server" - from: "../server/bin/cloudflared" to: "bin/cloudflared" + filter: + - "**/*" mac: icon: "build/icon-mac.png" + target: + - target: dmg + arch: + - arm64 + - x64 win: icon: "build/icon-win.png" + target: + - target: nsis + arch: + - x64 + +nsis: + oneClick: false + allowToChangeInstallationDirectory: true diff --git a/packages/desktop/package.json b/packages/desktop/package.json index c2e7cf6..b27115d 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -12,7 +12,9 @@ "typecheck": "tsc --noEmit", "test": "vitest", "pack": "electron-builder --dir", - "dist": "electron-builder" + "dist": "electron-builder", + "dist:mac": "electron-builder --mac", + "dist:win": "electron-builder --win" }, "keywords": [ "electron", diff --git a/scripts/bump-version.ts b/scripts/bump-version.ts new file mode 100644 index 0000000..7c99908 --- /dev/null +++ b/scripts/bump-version.ts @@ -0,0 +1,34 @@ +import { readFileSync, writeFileSync } from 'node:fs'; +import { resolve } from 'node:path'; + +const semverRegex = /^\d+\.\d+\.\d+$/; + +const version = process.argv[2]; +if (!version || !semverRegex.test(version)) { + console.error( + 'Usage: bun run scripts/bump-version.ts \nExample: bun run scripts/bump-version.ts 1.0.1', + ); + process.exit(1); +} + +const files = [ + 'package.json', + 'packages/server/package.json', + 'packages/desktop/package.json', +]; + +const rootDir = resolve(import.meta.dirname, '..'); + +for (const file of files) { + const filePath = resolve(rootDir, file); + const content = readFileSync(filePath, 'utf-8'); + const json = JSON.parse(content); + + const oldVersion = json.version; + json.version = version; + + writeFileSync(filePath, JSON.stringify(json, null, 2) + '\n'); + console.log(`${file}: ${oldVersion} → ${version}`); +} + +console.log(`\nDone. All three package.json updated to v${version}.`); diff --git a/scripts/prepare-cloudflared.ts b/scripts/prepare-cloudflared.ts new file mode 100644 index 0000000..e4ae27e --- /dev/null +++ b/scripts/prepare-cloudflared.ts @@ -0,0 +1,101 @@ +import { + chmodSync, + existsSync, + mkdirSync, + renameSync, + unlinkSync, + writeFileSync, +} from 'node:fs'; +import { resolve } from 'node:path'; +import { execSync } from 'node:child_process'; + +const DEFAULT_VERSION = '2025.4.0'; + +function parseArgs(): string { + const args = process.argv.slice(2); + for (let i = 0; i < args.length; i++) { + if (args[i] === '--version' && args[i + 1]) { + return args[i + 1]; + } + } + return DEFAULT_VERSION; +} + +function getPlatformInfo(): { filename: string; isTgz: boolean; outName: string } { + const platform = process.platform; + const arch = process.arch; + + if (platform === 'darwin' && arch === 'arm64') { + return { filename: 'cloudflared-darwin-arm64.tgz', isTgz: true, outName: 'cloudflared' }; + } + if (platform === 'darwin' && arch === 'x64') { + return { filename: 'cloudflared-darwin-amd64.tgz', isTgz: true, outName: 'cloudflared' }; + } + if (platform === 'win32' && arch === 'x64') { + return { filename: 'cloudflared-windows-amd64.exe', isTgz: false, outName: 'cloudflared.exe' }; + } + if (platform === 'linux' && arch === 'x64') { + return { filename: 'cloudflared-linux-amd64', isTgz: false, outName: 'cloudflared' }; + } + if (platform === 'linux' && arch === 'arm64') { + return { filename: 'cloudflared-linux-arm64', isTgz: false, outName: 'cloudflared' }; + } + + throw new Error(`Unsupported platform: ${platform}-${arch}`); +} + +async function downloadFile(url: string, dest: string): Promise { + const response = await fetch(url); + if (!response.ok) { + throw new Error(`Failed to download ${url}: ${response.status} ${response.statusText}`); + } + const arrayBuffer = await response.arrayBuffer(); + writeFileSync(dest, Buffer.from(arrayBuffer)); +} + +function extractTgz(tgzPath: string, outDir: string, outName: string): string { + execSync(`tar xzf "${tgzPath}" -C "${outDir}"`, { stdio: 'inherit' }); + + const extractedPath = resolve(outDir, 'cloudflared'); + const finalPath = resolve(outDir, outName); + if (extractedPath !== finalPath && existsSync(extractedPath)) { + renameSync(extractedPath, finalPath); + } + return finalPath; +} + +async function main(): Promise { + const version = parseArgs(); + const { filename, isTgz, outName } = getPlatformInfo(); + + const rootDir = resolve(import.meta.dirname, '..'); + const binDir = resolve(rootDir, 'packages', 'server', 'bin'); + const outPath = resolve(binDir, outName); + + mkdirSync(binDir, { recursive: true }); + + const url = `https://github.com/cloudflare/cloudflared/releases/download/${version}/${filename}`; + console.log(`Downloading cloudflared v${version} for ${process.platform}-${process.arch}...`); + console.log(`URL: ${url}`); + + if (isTgz) { + const tgzPath = resolve(binDir, filename); + await downloadFile(url, tgzPath); + console.log('Extracting...'); + extractTgz(tgzPath, binDir, outName); + unlinkSync(tgzPath); + } else { + await downloadFile(url, outPath); + } + + if (process.platform !== 'win32') { + chmodSync(outPath, 0o755); + } + + console.log(`cloudflared v${version} installed to ${outPath}`); +} + +main().catch((err) => { + console.error('Failed to prepare cloudflared:', err); + process.exit(1); +}); From 27b47392a95ddda19b710722ba2f34e88c2b1bac Mon Sep 17 00:00:00 2001 From: Jonathan Zhang Date: Mon, 27 Apr 2026 23:04:08 +0800 Subject: [PATCH 2/6] chore: bump version to 1.0.1 --- package.json | 2 +- packages/desktop/package.json | 3 +-- packages/server/package.json | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 7fe8d5a..f81dc3d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "persona-agent", - "version": "1.0.0", + "version": "1.0.1", "private": true, "scripts": { "dev": "cd packages/desktop && npm run dev", diff --git a/packages/desktop/package.json b/packages/desktop/package.json index b27115d..570ae7d 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -1,6 +1,6 @@ { "name": "persona-agent-desktop", - "version": "1.0.0", + "version": "1.0.1", "description": "Persona Desktop - Electron GUI for Persona", "type": "module", "main": "./out/main/index.js", @@ -43,7 +43,6 @@ "rehype-highlight": "^7.0.0", "remark-gfm": "^4.0.0", "tailwind-merge": "^2.2.0", - "zustand": "^4.5.0" }, "devDependencies": { diff --git a/packages/server/package.json b/packages/server/package.json index c5e2dd1..dd63d59 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -1,6 +1,6 @@ { "name": "persona-agent-server", - "version": "1.0.0", + "version": "1.0.1", "type": "module", "bin": { "persona-agent-server": "dist/src/index.js" From 3ad473eab5c0cadd5e07a55f625ced8588c29ce8 Mon Sep 17 00:00:00 2001 From: Jonathan Zhang Date: Mon, 27 Apr 2026 23:23:30 +0800 Subject: [PATCH 3/6] Update CICD --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 816eeac..9d92d1d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,6 +19,8 @@ jobs: with: node-version: 20 + - run: bun install + - run: bun install working-directory: packages/server From 18b23305d6ccbf57512cabfad3cd7907697e24a8 Mon Sep 17 00:00:00 2001 From: Jonathan Zhang Date: Mon, 27 Apr 2026 23:27:55 +0800 Subject: [PATCH 4/6] fix lint --- packages/server/src/server/routers/tunnel.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/server/src/server/routers/tunnel.ts b/packages/server/src/server/routers/tunnel.ts index 44646ec..6023e48 100644 --- a/packages/server/src/server/routers/tunnel.ts +++ b/packages/server/src/server/routers/tunnel.ts @@ -9,11 +9,7 @@ import { Router } from 'express'; import type { Request, Response } from 'express'; -import { - startTunnel, - stopTunnel, - getTunnelStatus, -} from '../tunnel-service.js'; +import { startTunnel, stopTunnel, getTunnelStatus } from '../tunnel-service.js'; import { httpServer } from '../index.js'; import { Logger } from '../../util/logger.js'; From a538e45061af2e9f5f9b8f84198a8f894dc5187c Mon Sep 17 00:00:00 2001 From: Jonathan Zhang Date: Mon, 27 Apr 2026 23:37:36 +0800 Subject: [PATCH 5/6] fix type --- packages/server/bun.lock | 5 +++++ packages/server/package.json | 1 + 2 files changed, 6 insertions(+) diff --git a/packages/server/bun.lock b/packages/server/bun.lock index 7fa975b..4d6f2f5 100644 --- a/packages/server/bun.lock +++ b/packages/server/bun.lock @@ -31,6 +31,7 @@ "zod": "^4.3.5", }, "devDependencies": { + "@types/bun": "^1.2.0", "@types/cors": "^2.8.19", "@types/express": "^5.0.6", "@types/multer": "^2.1.0", @@ -354,6 +355,8 @@ "@types/body-parser": ["@types/body-parser@1.19.6", "https://registry.npmmirror.com/@types/body-parser/-/body-parser-1.19.6.tgz", { "dependencies": { "@types/connect": "*", "@types/node": "*" } }, "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g=="], + "@types/bun": ["@types/bun@1.3.13", "https://registry.npmmirror.com/@types/bun/-/bun-1.3.13.tgz", { "dependencies": { "bun-types": "1.3.13" } }, "sha512-9fqXWk5YIHGGnUau9TEi+qdlTYDAnOj+xLCmSTwXfAIqXr2x4tytJb43E9uCvt09zJURKXwAtkoH4nLQfzeTXw=="], + "@types/chai": ["@types/chai@5.2.3", "https://registry.npmmirror.com/@types/chai/-/chai-5.2.3.tgz", { "dependencies": { "@types/deep-eql": "*", "assertion-error": "^2.0.1" } }, "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA=="], "@types/connect": ["@types/connect@3.4.38", "https://registry.npmmirror.com/@types/connect/-/connect-3.4.38.tgz", { "dependencies": { "@types/node": "*" } }, "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug=="], @@ -456,6 +459,8 @@ "buffer-from": ["buffer-from@1.1.2", "https://registry.npmmirror.com/buffer-from/-/buffer-from-1.1.2.tgz", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="], + "bun-types": ["bun-types@1.3.13", "https://registry.npmmirror.com/bun-types/-/bun-types-1.3.13.tgz", { "dependencies": { "@types/node": "*" } }, "sha512-QXKeHLlOLqQX9LgYaHJfzdBaV21T63HhFJnvuRCcjZiaUDpbs5ED1MgxbMra71CsryN/1dAoXuJJJwIv/2drVA=="], + "bundle-name": ["bundle-name@4.1.0", "https://registry.npmmirror.com/bundle-name/-/bundle-name-4.1.0.tgz", { "dependencies": { "run-applescript": "^7.0.0" } }, "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q=="], "busboy": ["busboy@1.6.0", "https://registry.npmmirror.com/busboy/-/busboy-1.6.0.tgz", { "dependencies": { "streamsearch": "^1.1.0" } }, "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA=="], diff --git a/packages/server/package.json b/packages/server/package.json index dd63d59..f39ec2b 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -18,6 +18,7 @@ "server": "bun run src/server/standalone.ts" }, "devDependencies": { + "@types/bun": "^1.2.0", "@types/cors": "^2.8.19", "@types/express": "^5.0.6", "@types/multer": "^2.1.0", From a713982642001852385c60d26cea629c1fe39051 Mon Sep 17 00:00:00 2001 From: Jonathan Zhang Date: Mon, 27 Apr 2026 23:47:20 +0800 Subject: [PATCH 6/6] fix package --- packages/server/bun.lock | 3 +++ packages/server/package.json | 1 + 2 files changed, 4 insertions(+) diff --git a/packages/server/bun.lock b/packages/server/bun.lock index 4d6f2f5..48860c6 100644 --- a/packages/server/bun.lock +++ b/packages/server/bun.lock @@ -8,6 +8,7 @@ "@anthropic-ai/sdk": "^0.90.0", "@mariozechner/pi-ai": "0.70.2", "@modelcontextprotocol/sdk": "^1.28.0", + "@sinclair/typebox": "^0.34.0", "chalk": "^5.6.2", "cloudflared": "^0.7.1", "commander": "^14.0.2", @@ -257,6 +258,8 @@ "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-rc.10", "https://registry.npmmirror.com/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.10.tgz", {}, "sha512-UkVDEFk1w3mveXeKgaTuYfKWtPbvgck1dT8TUG3bnccrH0XtLTuAyfCoks4Q/M5ZGToSVJTIQYCzy2g/atAOeg=="], + "@sinclair/typebox": ["@sinclair/typebox@0.34.49", "https://registry.npmmirror.com/@sinclair/typebox/-/typebox-0.34.49.tgz", {}, "sha512-brySQQs7Jtn0joV8Xh9ZV/hZb9Ozb0pmazDIASBkYKCjXrXU3mpcFahmK/z4YDhGkQvP9mWJbVyahdtU5wQA+A=="], + "@smithy/config-resolver": ["@smithy/config-resolver@4.4.17", "https://registry.npmmirror.com/@smithy/config-resolver/-/config-resolver-4.4.17.tgz", { "dependencies": { "@smithy/node-config-provider": "^4.3.14", "@smithy/types": "^4.14.1", "@smithy/util-config-provider": "^4.2.2", "@smithy/util-endpoints": "^3.4.2", "@smithy/util-middleware": "^4.2.14", "tslib": "^2.6.2" } }, "sha512-TzDZcAnhTyAHbXVxWZo7/tEcrIeFq20IBk8So3OLOetWpR8EwY/yEqBMBFaJMeyEiREDq4NfEl+qO3OAUD+vbQ=="], "@smithy/core": ["@smithy/core@3.23.17", "https://registry.npmmirror.com/@smithy/core/-/core-3.23.17.tgz", { "dependencies": { "@smithy/protocol-http": "^5.3.14", "@smithy/types": "^4.14.1", "@smithy/url-parser": "^4.2.14", "@smithy/util-base64": "^4.3.2", "@smithy/util-body-length-browser": "^4.2.2", "@smithy/util-middleware": "^4.2.14", "@smithy/util-stream": "^4.5.25", "@smithy/util-utf8": "^4.2.2", "@smithy/uuid": "^1.1.2", "tslib": "^2.6.2" } }, "sha512-x7BlLbUFL8NWCGjMF9C+1N5cVCxcPa7g6Tv9B4A2luWx3be3oU8hQ96wIwxe/s7OhIzvoJH73HAUSg5JXVlEtQ=="], diff --git a/packages/server/package.json b/packages/server/package.json index f39ec2b..c4a292b 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -35,6 +35,7 @@ "@modelcontextprotocol/sdk": "^1.28.0", "@anthropic-ai/sdk": "^0.90.0", "@mariozechner/pi-ai": "0.70.2", + "@sinclair/typebox": "^0.34.0", "chalk": "^5.6.2", "cloudflared": "^0.7.1", "commander": "^14.0.2",