SkillBundleSource interface. Three implementations are available; you choose by setting source.type in the plugin options.
static
Loads from a local filesystem path. Optional watch: true re-fetches on file change (debounced 250ms). Falls back to a 2-second poll if fs.watch rejects the file (some platforms reject watch on certain filesystems).
.json→ JSON.yaml/.yml→ YAML- anything else → format sniffed from the first non-whitespace byte
npm
Loads from a published npm package’s default (or named) export. Pinned by your package.json — updates require a server redeploy, which is intentional: the lower-blast-radius distribution mode.
ResolvedBundle shape; the plugin parses it through the same Zod validator the static source uses. Pin the package version in your package.json and sign your bundles via the integrity envelope as your supply-chain controls.
saas
Pulls bundles from a configured HTTPS endpoint with a pinned JWT. Boot pull is mandatory; interval polling refreshes; a last-good cached bundle on disk is the fallback if a fresh pull fails.
Boot semantics
- Initial pull runs synchronously when the plugin’s
BundleSyncServicefactory boots. - If the pull succeeds, the bundle is persisted to
bundleCacheDirand applied via the sync service. - If the pull fails AND a cached bundle exists, the cache is loaded with a startup warning. The server stays healthy.
- If the pull fails AND no cache exists, the source throws — the plugin reports a startup error but does not kill the server.
Polling
DefaultpollIntervalMs: 300_000 (5 min). Overlapping polls are skipped via a single-flight gate — if a previous poll is still in flight when the next interval fires, the new poll is dropped (not queued).
Source-conflict policy
If multiple sources somehow register the samebundleId (e.g. you wire both static and saas simultaneously), the plugin’s sourceConflictPolicy controls resolution:
'static-wins'(default): static beats npm beats saas'last-wins': most recent apply wins (use with caution; race-prone)'reject': fail to apply when a conflict is detected
options.source, so this policy only takes effect when more than one source registers the same bundleId.