Skip to content

feat(packaging): macOS .pkg + Windows .msi installer scaffolding - #37

Merged
rrader26 merged 2 commits into
mainfrom
feat/installer-bundling
May 12, 2026
Merged

feat(packaging): macOS .pkg + Windows .msi installer scaffolding#37
rrader26 merged 2 commits into
mainfrom
feat/installer-bundling

Conversation

@rrader26

Copy link
Copy Markdown
Contributor

Summary

  • Cross-platform installer scaffolding for the agentmark MCP server + bridges.
  • macOS `.pkg` (via `pkgbuild` + `productbuild`) and Windows `.msi` (via WiX 4).
  • GitHub Actions release workflow triggered on `v*` tags; uploads both artifacts to a draft Release.
  • Each installer bundles a pinned Node runtime (22.11.0 LTS) so end users don't need Node installed.
  • Signing-ready but unsigned by default — conditional on encrypted GitHub secrets, won't fail without them.

⚠️ Stacked on PR #36. Recommend merging that first so the production code being packaged includes the real `ActivepiecesMemoryBackend` instead of the speculative stubs.

What ships in each installer

macOS → `/opt/thinkfleet/agentmark/`
```
├── node (pinned 22.11.0 LTS, host arch)
├── agentmark/ (dist/ + schema/ + package.json + prod deps)
├── bridges/agentmark-bridge-macos
└── bin/agentmark-mcp (launcher; symlinked to /usr/local/bin)
```

Windows → `C:\Program Files\ThinkFleet\AgentMark\`
```
├── node.exe (pinned 22.11.0)
├── agentmark\ (dist\ + schema\ + package.json + prod deps)
├── bridges\agentmark-bridge-windows.exe + companion DLLs
└── agentmark-mcp.cmd (launcher; install dir added to PATH)
```

After install, `agentmark-mcp` is on PATH everywhere — same command on both platforms.

What's deliberately NOT bundled

  • Playwright Chromium (~150MB). The web plugin docs document `playwright install chromium` as a one-time post-install step for users who want it.
  • Activepieces backend wiring. Per-deployment env-var config; not part of the installer.

Signing (one-time setup, optional today)

Both build scripts detect signing secrets and run code-signing only when they're present. Without secrets, you get unsigned installers (fine for internal testing; Gatekeeper / SmartScreen will warn end users).

Required secrets for production releases:

macOS:

  • `APPLE_DEVELOPER_ID` — cert Common Name
  • `APPLE_CERT_P12_BASE64` — base64'd .p12
  • `APPLE_CERT_P12_PASSWORD`
  • `APPLE_APP_NOTARIZATION_USER` + `..._TEAM_ID` + `..._PASSWORD`

Windows:

  • `WINDOWS_CERT_PFX_BASE64` + `WINDOWS_CERT_PFX_PASSWORD`

Release flow

  1. Bump `package.json` version.
  2. Tag: `git tag v0.12.0 && git push --tags`
  3. GH Actions builds both installers in matrix → uploads to a draft GitHub Release.
  4. You review the draft, publish when ready.

Test plan

  • All scripts syntax-validated (bash + PowerShell)
  • All file paths verified to match the workflow
  • Manual: trigger `workflow_dispatch` to do a dry-run build without tagging
  • Manual: install the .pkg on a clean macOS VM; run `agentmark-mcp --help` and `agentmark-mcp list-tools` (or whatever the CLI surface is)
  • Manual: same drill on a clean Windows VM with the .msi

What's next (in memory, not this PR)

  • Linux `.AppImage` scaffolding
  • Bundled "first-run" UX (optional Chromium install prompt; Activepieces config wizard)
  • ThinkFleet Desktop UI app (the wrapper that runs this installer's MCP server + adds the kanban / orchestration surfaces)

🤖 Generated with Claude Code

rrader26-sys and others added 2 commits May 12, 2026 11:30
…emoryBackend

PR #35 shipped Remote{Memory,Recipe}Backend classes that targeted REST
endpoints we never built — pure stubs. They were marked "v1 proposal"
in their headers, which is the kind of speculative interface we don't
want in production code.

This PR removes the stubs and replaces them with a REAL
ActivepiecesMemoryBackend that hits live endpoints in the user's
Activepieces deployment:

  /v1/projects/:projectId/memory                               (project-scoped)
  /v1/projects/:projectId/chatbots/:chatbotId/memory          (chatbot-scoped)
  /v1/projects/:projectId/chatbots/:chatbotId/memory/search   (hybrid search)

Auth: `Authorization: Bearer sk-<api-key>` against the existing
Activepieces Service-principal flow. The same Claude Code / Cursor /
Codex agent connecting to agentmark now writes to **real Activepieces
memory** instead of a speculative service — and gets hybrid vector +
BM25 semantic search for free since agentmark_memory_search routes
to /memory/search.

Mapping (agentmark K/V → Activepieces rich shape):
  - agentmark `key`   → metadata.agentmark_key
  - agentmark `value` → content + metadata.raw_value (preserves type)
  - agentmark `scope` → Activepieces scope (same five-level enum)
  - agentmark `scope.id` → metadata.scope_id
  - agentmark `tags`  → metadata.tags
  - source stamp = "agentmark" (filterable; backends only see records
    they wrote)

Recipes: NO ActivepiecesRecipeBackend ships in this PR because
Activepieces has no recipes endpoints yet. RecipeBackend interface +
LocalFileRecipeBackend remain; when the recipes service ships, a
real implementation lands then.

Removed (the stubs):
  - src/plugins/memory/remote-backend.ts
  - src/plugins/recipes/remote-backend.ts
  - test/memory/remote-backend.test.ts
  - test/recipes/remote-backend.test.ts

Added:
  - src/plugins/memory/activepieces-backend.ts  (real impl)
  - test/memory/activepieces-backend.test.ts    (20 tests)

Tests: 491 pass / 10 skip. Build clean. All prior tests pass unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Ships the delivery vehicle for ThinkFleet Desktop. Each installer
bundles the agentmark MCP server + the platform bridge + a pinned Node
runtime so end users don't need to install Node themselves — just
double-click and `agentmark-mcp` is on their PATH.

Files:
  packaging/
    README.md                          operator instructions + signing-secret docs
    scripts/
      common.sh                        pinned Node version + shared helpers
      build-macos.sh                   pnpm build → Swift bridge → pkgbuild → productbuild
      build-windows.ps1                pnpm build → dotnet publish → WiX 4 → MSI
    templates/
      launcher.sh                      relocatable POSIX launcher
      launcher.cmd                     relocatable Windows launcher
      distribution.xml                 productbuild manifest
      AgentMark.wxs                    WiX 4 MSI manifest
      macos-pkg-scripts/
        postinstall                    symlinks /usr/local/bin/agentmark-mcp
  .github/workflows/release.yml        tag-triggered release; builds both
                                       platforms in parallel + uploads to
                                       a draft GitHub Release

What ships in each installer:

  macOS install to /opt/thinkfleet/agentmark/
    ├── node                        (pinned 22.11.0 LTS, host arch)
    ├── agentmark/                  (dist + schema + package.json + prod deps)
    ├── bridges/agentmark-bridge-macos
    └── bin/agentmark-mcp           (launcher; symlinked into /usr/local/bin)

  Windows install to C:\Program Files\ThinkFleet\AgentMark\
    ├── node.exe                    (pinned 22.11.0)
    ├── agentmark\                  (dist + schema + package.json + prod deps)
    ├── bridges\agentmark-bridge-windows.exe + companion DLLs
    └── agentmark-mcp.cmd           (launcher; install dir added to PATH)

What's deliberately NOT bundled:

  - Playwright Chromium (~150MB; only needed for the browser plugin).
    The web plugin documents `playwright install chromium` as a
    one-time post-install step for users who want it.
  - Activepieces backend wiring. That's per-deployment config the
    operator sets via env vars; not part of the installer.

Signing: optional, conditional on encrypted GitHub secrets:

  macOS:   APPLE_DEVELOPER_ID + APPLE_CERT_P12_BASE64 + notarisation creds
  Windows: WINDOWS_CERT_PFX_BASE64 + WINDOWS_CERT_PFX_PASSWORD

Missing secrets = build skips signing, produces unsigned installers
suitable for internal testing. Production signing is a one-time cert
setup; the workflow + scripts are signing-ready out of the box.

Pinned versions (single source of truth in packaging/scripts/common.sh
and packaging/scripts/build-windows.ps1):

  Node 22.11.0 LTS
  .NET 8 (for the Windows UIA bridge)
  Swift 5.9+ (for the macOS AXAPI bridge)
  WiX 4 (dotnet tool, installed by the workflow if missing)

Release flow: tag a version (e.g. `v0.12.0`). GH Actions builds both
installers in matrix, uploads to a draft GitHub Release. Tester runs
the .pkg or .msi; `agentmark-mcp --help` works immediately afterward.

Linux AppImage scaffolding lands as a follow-up.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@rrader26
rrader26 merged commit 9707f7d into main May 12, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants