Plugin Development and Debugging
Use this runbook to bring up the local plugin stack, configure a device-local provider, trace lifecycle failures, and add new catalog capabilities without weakening the local-first boundary.
Local Environment
Run the regular service stack and the Desktop/Runner from the same checkout:
The local origin is https://scilaxy.local. Do not run full Compose stacks from two worktrees at the same time; the stack, database, Redis, ports, and Desktop connection are shared resources.
just dev provisions the Dev plugin authority before starting the service stack. desktop/scripts/provision-dev-plugin-runner.mjs creates or reuses ignored local material:
- the Dev server's Ed25519 signing key;
- the plugin-secret encryption keyring;
- the public trust resource under the Dev channel home.
just desktop-dev generates and stages the runtime manifest, seeds the local runtime cache, builds Runner, and starts Electron. API, Web, and Worker hot-reload under just dev; ordinary source edits do not require rebuilding the entire stack.
Before diagnosing a plugin, confirm:
- Desktop reports channel
devand backend originhttps://scilaxy.local. - The trust resource resolves the exact WSS origin and
/scilaxy/ws/v1/runner/devicepath. - The Desktop enrollment is
active, its lease expiry keeps advancing, and its catalog digest is present. - The installation and selected device belong to the same authenticated user.
Configure a Local Profile
For Feishu or GitHub, connection setup must complete before Enable:
- Install the plugin and select an online Desktop.
- Enter a profile label. After trimming it must contain 1–128 Unicode code points and only letters, digits, spaces,
.,_, or-. - Select Continue on Desktop to create an
authorize_local_profiledevice action. - Complete the isolated Electron prompt. Feishu asks for
cnorglobal, App ID, and App Secret. - Wait for the connection to become
readyand its local provider probe to become healthy. - Review and save the requested plugin permissions.
- Enable the installation.
The connection and permission steps may be completed in either order, but both must exist. If the profile label is empty, the Desktop continuation button is intentionally disabled.
Package Contract
Every portable package contains a root plugin.json conforming to Agent Plugins 1.0.0. Skills are discovered from skills/<name>/SKILL.md; an optional root mcp.json declares MCP servers. SciLaxy-specific local execution is declared under extensions["ai.scilaxy"].
A minimal local-provider manifest has this shape:
Replace the example tool-catalog digest with the actual lowercase SHA-256. The extension is a closed schema: localProviders may define package-relative stdio providers; inboundTransports may define provider WebSocket or acknowledged webhook relay; channels currently use the supported Feishu/GitHub contracts; agentRuntimes are builtin-source only and limited to supported adapters.
Validation is deterministic and offline—it does not execute code or fetch remote schemas. The package must contain only regular files, normalized safe relative paths, no links/devices/sockets, no credential-bearing files, at most 2,000 files and 64 MiB uncompressed data, path depth at most 32, and compression ratio at most 100:1. Non-bundled local providers also require explicit host-authority consent on the selected device.
API Surface
Authenticated plugin REST routes use /scilaxy/api/v1/plugins:
The Runner channel is WSS /scilaxy/ws/v1/runner/device. GitHub public ingress is POST /scilaxy/api/v1/plugin-webhooks/github/:endpoint_token.
Canonical REST paths have no trailing slash. Source-of-truth request and response types live in service/pkg/web/views/plugins/, plugindevices/, and runnerws/.
Readiness Failures
Enable submits an asynchronous lifecycle command. The API can accept the command even when the Worker later rejects it. Always read both the latest plugin_installation_operation and the installation health blockers.
The operation-level error requirements_unmet means one or more of these blockers exists. It does not, by itself, identify a lease, signing, or App Secret failure.
A common new-Feishu failure has all of these facts:
- installation is
disabled; - latest Enable operation failed with
requirements_unmet; - there is no
readyplugin_connection; - there is no current
plugin_permission; - the device enrollment and lease are healthy.
In that case, repeating device enrollment, rotating server keys, or clicking Enable again cannot help. Complete the local profile and permission steps.
Device Connection Failures
Diagnose the device transport separately from lifecycle readiness:
Do not collapse these into “lease problem.” The recovery action is different for every layer.
Database Diagnostics
Use read-only queries and never print secrets, ciphertext, nonces, raw provider payloads, tickets, or local paths.
List the current 23 tables:
Trace an installation and its latest operations:
Inspect non-secret connection and permission authority:
Inspect liveness without exposing key material:
Recommended order for an Enable failure:
- latest operation error code;
- health blockers;
- ready connection;
- current permission coverage;
- bound device lease and generation;
- only then local runtime/package/provider health.
Adding a Plugin
- Declare plugin identity, immutable release, capability, and platform runtime in the single catalog/manifest source. Do not duplicate deployment or presentation facts in executable code.
- Reuse the closed capability schema. A new protocol concept must update validation, database contracts, API projection, Runner, and tests together.
- Choose one credential owner: device-local, server OAuth, or no credential. Never mix ownership modes.
- Use package-relative provider entrypoints with closed argv, working-directory, transport, and verifier schemas. Do not construct shell commands.
- Declare minimum permissions. External writes must use effect intent, approval, receipt, and reconciliation.
- Use a local long connection or the controlled webhook relay for inbound events. Do not introduce cloud execution fallback.
- Test install, setup, permission, offline device, generation fence, revoked release, protocol drift, and retry/ambiguity behavior.
- Give Web, Desktop, and mobile users equivalent state and recovery information.
- Update both English and Chinese Rspress pages and provider-specific documentation.
- Validate installation through a real Desktop/Runner provider call.