Bare Caps
CI / Build & Test (push) Successful in 3m7s

This commit is contained in:
Raven Scott
2026-07-26 23:09:00 -04:00
parent f4569b765e
commit 631f9c4023
19 changed files with 1412 additions and 108 deletions
+26
View File
@@ -26,6 +26,10 @@ These are the main APIs your page uses. For host request types and event payload
- **`BridgeSwarm.request(type, payload, options)`** — Sends a request to the host. Optional third argument: `{ timeoutMs: number }` aborts after that many milliseconds and rejects with `"Request timed out after N ms"`. If the page does not pass `timeoutMs`, the extensions **default request timeout** (from the options page) is used when it is > 0.
- **`BridgeSwarm.capabilities`** — Optional Bare capability packs on the host. `list()`, `has(pack)`, `call(pack, cmd, payload)`, `on(event, fn)`. See [CAPABILITIES.md](CAPABILITIES.md).
- **`BridgeSwarm.media.*`** — Media pack wrappers (`info`, `imageTransform`, `extractFrame`, `transcode`, `cancel`, `writeInput`, `readOutput`). Requires the media host artifact.
---
## Host request types and events
@@ -134,9 +138,31 @@ Full details and examples: [DATA-API.md](DATA-API.md).
---
## Capabilities (optional packs)
| Type | Payload | Response |
|------|---------|----------|
| `capabilities.list` | `{}` | `{ ok, packs }` |
| `capabilities.has` | `{ pack }` | `{ ok, pack, has }` |
| `capability` | `{ pack, cmd, payload }` | pack-specific |
| `media.info` / `media.imageTransform` / `media.extractFrame` / `media.transcode` / `media.cancel` / … | command payload | see [CAPABILITIES.md](CAPABILITIES.md) |
### Capability events
| Event | Payload |
|-------|---------|
| `cap-chunk` | `{ pack, jobId, index?, data?, progress?, bytes? }` |
| `cap-end` | `{ pack, jobId, … }` |
| `cap-error` | `{ pack, jobId, message }` |
These events are broadcast to all subscribed tabs (no `swarmId` filter).
---
## See also
- [DATA-API.md](DATA-API.md) — Data API details and examples.
- [CAPABILITIES.md](CAPABILITIES.md) — Optional Bare capability packs (media, install, security).
- [HRPC.md](HRPC.md) — HRPC (attachHrpc) and commands.
- [PROTOMUX.md](PROTOMUX.md) — Protomux in the browser and connection attachment.
- [ARCHITECTURE.md](ARCHITECTURE.md) — Message flow and components.
+114
View File
@@ -0,0 +1,114 @@
# Capabilities
BridgeSwarm exposes selected [Bare](https://github.com/holepunchto/bare) native APIs to the page as **optional capability packs**. The default host stays swarm/data-focused and does **not** ship heavy addons like `bare-ffmpeg` (~400+ MB unpacked).
Curated packs — not “every `bare-*` package” — is an intentional design choice.
## Page API
```js
await BridgeSwarm.capabilities.list() // e.g. ['media'] or []
await BridgeSwarm.capabilities.has('media')
// Generic dispatch
await BridgeSwarm.capabilities.call('media', 'info', { path: '…' })
// Thin wrappers (Pack 1)
await BridgeSwarm.media.info({ dataBase64, filename })
await BridgeSwarm.media.imageTransform({ dataBase64, maxWidth: 640, mimetype: 'image/webp' })
await BridgeSwarm.media.extractFrame({ dataBase64, frameIndex: 0 })
await BridgeSwarm.media.transcode({ dataBase64, format: 'webm' }, { onProgress })
await BridgeSwarm.media.cancel(jobId)
```
Streaming results use host events (under the ~1 MB native-messaging limit):
| Event | Payload |
|-------|---------|
| `cap-chunk` | `{ pack, jobId, index?, data? (base64), progress?, bytes? }` |
| `cap-end` | `{ pack, jobId, chunks?, path?, mimetype?, … }` |
| `cap-error` | `{ pack, jobId, message }` |
`BridgeSwarm.media.*` helpers assign a `jobId`, listen for these events, and resolve with assembled `dataBase64` (or a host-relative `path` for large transcodes).
You can also subscribe manually:
```js
const off = BridgeSwarm.capabilities.on('cap-chunk', (p) => console.log(p))
```
## Security
Every pack that touches the filesystem is **allowlisted** under:
```text
$BRIDGE_SWARM_STORAGE/cap-jobs/
```
(default: `~/.bridgeswarm/bridge-swarm-storage/cap-jobs/`). Absolute paths outside that tree are rejected. Large outputs are written there and returned as relative paths; the page can stream them back with `media.readOutput`.
## Pack 1 — Media
| Command | Behavior |
|---------|----------|
| `media.info` | Probe image/video metadata |
| `media.imageTransform` | Decode → optional resize/crop → encode (webp/jpeg/png); stream base64 |
| `media.extractFrame` | Extract one video frame → encode; stream base64 |
| `media.transcode` | Async job to webm/mp4/mkv (VP9+Opus where supported); progress events |
| `media.cancel` | Cancel in-flight job |
| `media.writeInput` / `media.readOutput` | Chunked upload / download under `cap-jobs/` |
### Install media host
Default `latest-main` artifacts are **lean** (no ffmpeg). Build and install the media variant:
```bash
# From a clone (heavy; downloads native prebuilds)
npm run build:dist:media
# Install into ~/.bridgeswarm (backs up lean host to bridge-swarm-host.lean.bak)
npm run install:capability:media
```
Or download `bridge-swarm-host-media-<platform>-<arch>.zip` from releases and point `BRIDGE_SWARM_MEDIA_URL` at it.
On macOS the install script extracts addons into `~/.bridgeswarm/tmp` and codesigns `*.bare` / `*.dylib` (same Gatekeeper fix as the lean host). Then **fully quit** the browser and reload the extension.
Verify:
```js
await BridgeSwarm.capabilities.has('media') // true
```
Demo: [`examples/media-demo/`](../examples/media-demo/) (`npm run examples``/media-demo/`).
### Local Bare (dev)
```bash
cd native-host
npm install bare-media
# run entry that registers the pack:
node ./node_modules/bare/bin/bare index-media.mjs
```
Point the native messaging manifest at that process the same way as the lean host.
## Planned packs (not in this release)
| Pack | Notes |
|------|--------|
| **fs / sqlite** | RPC over `bare-fs` / `bare-sqlite` under allowlisted roots |
| **net** | Host `fetch`, optional tcp/dgram — CORS-free from the page |
UI/mobile/build Bare packages (`bare-gtk`, `bare-ios`, `bare-build`, …) are out of scope for BridgeSwarm.
## Host protocol
| Type | Payload | Response |
|------|---------|----------|
| `capabilities.list` | `{}` | `{ ok, packs: string[] }` |
| `capabilities.has` | `{ pack }` | `{ ok, pack, has }` |
| `capability` | `{ pack, cmd, payload }` | pack-specific |
| `media.<cmd>` | same as `payload` | shortcut when pack installed |
Unknown pack → `{ ok: false, error: "capability 'media' not installed" }`.