Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 19 additions & 6 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,19 @@ jobs:
- name: Build Windows
run: |
pnpm run build
pnpm run plugin:bundle -- --name feishu --platform win32 --arch ${{ matrix.arch }}
pnpm exec electron-builder --win --${{ matrix.arch }} --publish=never
env:
VITE_GITHUB_CLIENT_ID: ${{ secrets.DC_GITHUB_CLIENT_ID }}
VITE_GITHUB_CLIENT_SECRET: ${{ secrets.DC_GITHUB_CLIENT_SECRET }}
VITE_GITHUB_REDIRECT_URI: ${{ secrets.DC_GITHUB_REDIRECT_URI }}
VITE_PROVIDER_DB_URL: ${{ secrets.CDN_PROVIDER_DB_URL }}

- name: Verify bundled plugins
shell: bash
run: |
pnpm run plugin:verify -- --name feishu --platform win32 --arch ${{ matrix.arch }} --plugin-root dist/win-unpacked/resources/app.asar.unpacked/plugins

- name: Upload artifacts
uses: actions/upload-artifact@v6
with:
Expand Down Expand Up @@ -125,13 +131,19 @@ jobs:
- name: Build Linux
run: |
pnpm run build
pnpm run plugin:bundle -- --name feishu --platform linux --arch ${{ matrix.arch }}
pnpm exec electron-builder --linux --${{ matrix.arch }} --publish=never
env:
VITE_GITHUB_CLIENT_ID: ${{ secrets.DC_GITHUB_CLIENT_ID }}
VITE_GITHUB_CLIENT_SECRET: ${{ secrets.DC_GITHUB_CLIENT_SECRET }}
VITE_GITHUB_REDIRECT_URI: ${{ secrets.DC_GITHUB_REDIRECT_URI }}
VITE_PROVIDER_DB_URL: ${{ secrets.CDN_PROVIDER_DB_URL }}

- name: Verify bundled plugins
shell: bash
run: |
pnpm run plugin:verify -- --name feishu --platform linux --arch ${{ matrix.arch }} --plugin-root dist/linux-unpacked/resources/app.asar.unpacked/plugins

- name: Upload artifacts
uses: actions/upload-artifact@v6
with:
Expand Down Expand Up @@ -188,7 +200,9 @@ jobs:
- name: Build Mac
run: |
pnpm run build
pnpm run plugin:cua:bundle:mac:${{ matrix.arch }}
pnpm run plugin:cua:build:mac:${{ matrix.arch }}
pnpm run plugin:bundle -- --name cua --platform darwin --arch ${{ matrix.arch }}
pnpm run plugin:bundle -- --name feishu --platform darwin --arch ${{ matrix.arch }}
pnpm exec electron-builder --mac --${{ matrix.arch }} --publish=never
env:
CSC_LINK: ${{ secrets.DEEPCHAT_CSC_LINK }}
Expand All @@ -203,19 +217,18 @@ jobs:
NODE_OPTIONS: '--max-old-space-size=4096'
VITE_PROVIDER_DB_URL: ${{ secrets.CDN_PROVIDER_DB_URL }}

- name: Verify bundled CUA plugin
- name: Verify bundled plugins
shell: bash
env:
TARGET_ARCH: ${{ matrix.arch }}
run: |
VERSION="$(node -p "require('./package.json').version")"
APP_DIR="dist/mac/DeepChat.app"
if [ "$TARGET_ARCH" = "arm64" ]; then
APP_DIR="dist/mac-arm64/DeepChat.app"
fi
PLUGIN="${APP_DIR}/Contents/Resources/app.asar.unpacked/plugins/deepchat-plugin-cua-${VERSION}-darwin-${TARGET_ARCH}.dcplugin"
test -f "$PLUGIN"
ls -lh "$PLUGIN"
PLUGIN_ROOT="${APP_DIR}/Contents/Resources/app.asar.unpacked/plugins"
pnpm run plugin:verify -- --name cua --platform darwin --arch "$TARGET_ARCH" --plugin-root "$PLUGIN_ROOT"
pnpm run plugin:verify -- --name feishu --platform darwin --arch "$TARGET_ARCH" --plugin-root "$PLUGIN_ROOT"

- name: Upload artifacts
uses: actions/upload-artifact@v6
Expand Down
25 changes: 19 additions & 6 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ jobs:
- name: Build Windows
run: |
pnpm run build
pnpm run plugin:bundle -- --name feishu --platform win32 --arch ${{ matrix.arch }}
pnpm exec electron-builder --win --${{ matrix.arch }} --publish=never
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand All @@ -173,6 +174,11 @@ jobs:
VITE_GITHUB_REDIRECT_URI: ${{ secrets.DC_GITHUB_REDIRECT_URI }}
VITE_PROVIDER_DB_URL: ${{ secrets.CDN_PROVIDER_DB_URL }}

- name: Verify bundled plugins
shell: bash
run: |
pnpm run plugin:verify -- --name feishu --platform win32 --arch ${{ matrix.arch }} --plugin-root dist/win-unpacked/resources/app.asar.unpacked/plugins

- name: Upload artifacts
uses: actions/upload-artifact@v6
with:
Expand Down Expand Up @@ -221,6 +227,7 @@ jobs:
- name: Build Linux
run: |
pnpm run build
pnpm run plugin:bundle -- --name feishu --platform linux --arch ${{ matrix.arch }}
pnpm exec electron-builder --linux --${{ matrix.arch }} --publish=never
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand All @@ -229,6 +236,11 @@ jobs:
VITE_GITHUB_REDIRECT_URI: ${{ secrets.DC_GITHUB_REDIRECT_URI }}
VITE_PROVIDER_DB_URL: ${{ secrets.CDN_PROVIDER_DB_URL }}

- name: Verify bundled plugins
shell: bash
run: |
pnpm run plugin:verify -- --name feishu --platform linux --arch ${{ matrix.arch }} --plugin-root dist/linux-unpacked/resources/app.asar.unpacked/plugins

- name: Upload artifacts
uses: actions/upload-artifact@v6
with:
Expand Down Expand Up @@ -288,7 +300,9 @@ jobs:
- name: Build Mac
run: |
pnpm run build
pnpm run plugin:cua:bundle:mac:${{ matrix.arch }}
pnpm run plugin:cua:build:mac:${{ matrix.arch }}
pnpm run plugin:bundle -- --name cua --platform darwin --arch ${{ matrix.arch }}
pnpm run plugin:bundle -- --name feishu --platform darwin --arch ${{ matrix.arch }}
pnpm exec electron-builder --mac --${{ matrix.arch }} --publish=never
env:
CSC_LINK: ${{ secrets.DEEPCHAT_CSC_LINK }}
Expand All @@ -304,19 +318,18 @@ jobs:
NODE_OPTIONS: '--max-old-space-size=4096'
VITE_PROVIDER_DB_URL: ${{ secrets.CDN_PROVIDER_DB_URL }}

- name: Verify bundled CUA plugin
- name: Verify bundled plugins
shell: bash
env:
TARGET_ARCH: ${{ matrix.arch }}
run: |
VERSION="$(node -p "require('./package.json').version")"
APP_DIR="dist/mac/DeepChat.app"
if [ "$TARGET_ARCH" = "arm64" ]; then
APP_DIR="dist/mac-arm64/DeepChat.app"
fi
PLUGIN="${APP_DIR}/Contents/Resources/app.asar.unpacked/plugins/deepchat-plugin-cua-${VERSION}-darwin-${TARGET_ARCH}.dcplugin"
test -f "$PLUGIN"
ls -lh "$PLUGIN"
PLUGIN_ROOT="${APP_DIR}/Contents/Resources/app.asar.unpacked/plugins"
pnpm run plugin:verify -- --name cua --platform darwin --arch "$TARGET_ARCH" --plugin-root "$PLUGIN_ROOT"
pnpm run plugin:verify -- --name feishu --platform darwin --arch "$TARGET_ARCH" --plugin-root "$PLUGIN_ROOT"

- name: Upload artifacts
uses: actions/upload-artifact@v6
Expand Down
139 changes: 96 additions & 43 deletions docs/guides/plugin-packaging.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,97 +23,150 @@ Official packages keep DeepChat release asset URLs in their manifest metadata:
https://github.com/ThinkInAIXYZ/deepchat/releases/download/v<version>/<asset-name>.dcplugin
```

## CUA Plugin Artifacts
Output naming pattern: `deepchat-plugin-<name>-<version>[-<platform>-<arch>].dcplugin`

The CUA plugin ships one macOS helper app per CPU architecture. The bundled package filename
includes both platform and architecture:
## Generic Commands

```text
deepchat-plugin-cua-<version>-darwin-arm64.dcplugin
deepchat-plugin-cua-<version>-darwin-x64.dcplugin
```
All plugins share a common set of commands powered by `scripts/plugin.mjs`, which delegates to
`scripts/package-plugin.mjs` for the actual packaging logic.

The manifest inside each package keeps the official DeepChat release-download namespace for trust
metadata. Runtime detection inside the package uses the same architecture-specific plugin path:
### Validate

```text
plugin:runtime/darwin/<arch>/DeepChat Computer Use.app/Contents/MacOS/cua-driver
Dry-run: validates the manifest and file references without producing a `.dcplugin`.

```bash
pnpm run plugin:validate -- --name <plugin> --platform <platform> --arch <arch>
```

Architecture mapping:
### Package

| DeepChat arch | Swift arch | Runtime directory |
| --- | --- | --- |
| `arm64` | `arm64` | `runtime/darwin/arm64/` |
| `x64` | `x86_64` | `runtime/darwin/x64/` |
Build (if the plugin has a native build step) and package into a `.dcplugin` under `dist/plugins/`.

Each `.dcplugin` contains only the runtime directory for its target architecture.
```bash
pnpm run plugin:package -- --name <plugin> --platform <platform> --arch <arch>
```

## Local Commands
### Bundle

Validate the package metadata for the current host architecture:
Package into `build/bundled-plugins/` for embedding into the Electron app.

```bash
pnpm run plugin:cua:validate
pnpm run plugin:bundle -- --name <plugin> --platform <platform> --arch <arch>
```

Build and package the current host architecture:
### Verify

Verify expected bundled official plugin artifacts from plugin metadata.

```bash
pnpm run plugin:cua:package
pnpm run plugin:verify -- --name <plugin> --platform <platform> --arch <arch> --plugin-root <plugins-dir>
```

Build and package explicit macOS architectures:
When `--name` is omitted, the script verifies all official plugins supported by the target platform.

### Clean

Remove all bundled plugin artifacts:

```bash
pnpm run plugin:cua:package:mac:arm64
pnpm run plugin:cua:package:mac:x64
pnpm run plugin:bundle:clean
```

Build the package that will be embedded into the macOS app:
## Plugins with Native Build Steps

Some plugins (like CUA) include pre-compiled native binaries. These require an additional build
step before packaging. The dispatcher script automatically detects and runs
`scripts/build-<name>-plugin-runtime.mjs` when it exists.

CUA native build commands (macOS-only, requires Swift toolchain):

```bash
pnpm run plugin:cua:bundle:mac:arm64
pnpm run plugin:cua:bundle:mac:x64
pnpm run plugin:cua:build # host architecture
pnpm run plugin:cua:build:mac:arm64 # explicit ARM64
pnpm run plugin:cua:build:mac:x64 # explicit x64
```

Validate explicit macOS architectures after their helper runtimes have been staged:
## CUA Plugin Artifacts

```bash
pnpm run plugin:cua:validate:mac:arm64
pnpm run plugin:cua:validate:mac:x64
The CUA plugin ships one macOS helper app per CPU architecture. The bundled package filename
includes both platform and architecture:

```text
deepchat-plugin-cua-<version>-darwin-arm64.dcplugin
deepchat-plugin-cua-<version>-darwin-x64.dcplugin
```

Runtime detection inside the package uses architecture-specific paths:

```text
plugin:runtime/darwin/<arch>/DeepChat Computer Use.app/Contents/MacOS/cua-driver
```

Each `.dcplugin` contains only the runtime directory for its target architecture.

## Feishu Plugin Artifacts

The feishu plugin targets all platforms (darwin, linux, win32). Its MCP server uses
`node serve.mjs` which calls `npx` at runtime to download the `@larksuiteoapi/lark-mcp`
package on first use.

```text
deepchat-plugin-feishu-<version>-darwin-arm64.dcplugin
deepchat-plugin-feishu-<version>-darwin-x64.dcplugin
deepchat-plugin-feishu-<version>-linux-x64.dcplugin
deepchat-plugin-feishu-<version>-win32-x64.dcplugin
```

Standalone packages are written to:
## Output Locations

Standalone packages:

```text
dist/plugins/
```

Bundled packages are written to:
Bundled packages (embedded into the Electron app):

```text
build/bundled-plugins/
```

## CI And Release
## CI and Release

The build matrix in `.github/workflows/build.yml` bundles plugins before running `electron-builder`
on every platform:

- **macOS**: bundles both CUA (with native build) and feishu plugins.
- **Linux**: bundles feishu plugin only (CUA is macOS-only).
- **Windows**: bundles feishu plugin only.

The macOS build matrix in `.github/workflows/build.yml` builds the matching CUA plugin bundle before
running `electron-builder`. Electron Builder embeds it into:
Electron Builder embeds `.dcplugin` files from `build/bundled-plugins/` into:

```text
DeepChat.app/Contents/Resources/app.asar.unpacked/plugins/
<app>/Contents/Resources/app.asar.unpacked/plugins/ (macOS)
<app>/resources/app.asar.unpacked/plugins/ (Windows/Linux)
```

Each matrix job verifies the expected bundled `.dcplugin` exists inside the app before uploading
artifacts.
Each matrix job verifies the expected bundled `.dcplugin` files exist inside the app before
uploading artifacts.

The release workflow repeats the same bundled package step. The final release uploads app artifacts
only; `.dcplugin` files are not published as separate GitHub Release assets.
The release workflow (`.github/workflows/release.yml`) repeats the same steps. Final release
uploads app artifacts only; `.dcplugin` files are not published as separate GitHub Release assets.

Expected embedded files:
Expected embedded files (macOS example):

```text
app.asar.unpacked/plugins/deepchat-plugin-cua-<version>-darwin-x64.dcplugin
app.asar.unpacked/plugins/deepchat-plugin-cua-<version>-darwin-arm64.dcplugin
app.asar.unpacked/plugins/deepchat-plugin-feishu-<version>-darwin-x64.dcplugin
app.asar.unpacked/plugins/deepchat-plugin-feishu-<version>-darwin-arm64.dcplugin
```

## Adding a New Plugin

1. Create `plugins/<name>/plugin.json` with required fields (`id`, `name`, `version`, `publisher`,
`source`, `engines.platforms`, skills, settings contributions).
2. If the plugin needs a native build step, create `scripts/build-<name>-plugin-runtime.mjs`.
3. Test locally: `pnpm run plugin:validate -- --name <name> --platform <platform> --arch <arch>`
4. Add bundling commands to the CI workflows for the relevant platforms.
5. Add verification steps to CI to confirm the `.dcplugin` is embedded in the built app.
7 changes: 3 additions & 4 deletions electron-builder.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ extraResources:
- from: ./resources/skills/
to: app.asar.unpacked/resources/skills
filter: ['**/*']
- from: ./build/bundled-plugins/
to: app.asar.unpacked/plugins
filter: ['**/*.dcplugin']
electronLanguages:
- zh-CN
- zh-TW
Expand Down Expand Up @@ -78,10 +81,6 @@ nsis:
afterSign: scripts/notarize.js
afterPack: scripts/afterPack.js
mac:
extraResources:
- from: ./build/bundled-plugins/
to: app.asar.unpacked/plugins
filter: ['**/*.dcplugin']
entitlementsInherit: build/entitlements.mac.plist
extendInfo:
- NSCameraUsageDescription: Application requests access to the device's camera.
Expand Down
Loading