mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 04:40:43 +00:00
docs: typography hygiene across 6 pages
Replaced 66 typography characters (curly quotes, apostrophes, em/en dashes, non-breaking hyphens) with ASCII equivalents per docs/CLAUDE.md heading and content hygiene rules. - docs/channels/mattermost.md: 12 chars - docs/tools/plugin.md: 11 chars - docs/providers/xai.md: 11 chars - docs/plugins/building-plugins.md: 11 chars - docs/concepts/streaming.md: 11 chars - docs/concepts/model-providers.md: 11 chars
This commit is contained in:
@@ -361,7 +361,7 @@ When a user clicks a button:
|
||||
<AccordionGroup>
|
||||
<Accordion title="Implementation notes">
|
||||
- Button callbacks use HMAC-SHA256 verification (automatic, no config needed).
|
||||
- Mattermost strips callback data from its API responses (security feature), so all buttons are removed on click — partial removal is not possible.
|
||||
- Mattermost strips callback data from its API responses (security feature), so all buttons are removed on click - partial removal is not possible.
|
||||
- Action IDs containing hyphens or underscores are sanitized automatically (Mattermost routing limitation).
|
||||
|
||||
</Accordion>
|
||||
@@ -391,7 +391,7 @@ External scripts and webhooks can post buttons directly via the Mattermost REST
|
||||
{
|
||||
actions: [
|
||||
{
|
||||
id: "mybutton01", // alphanumeric only — see below
|
||||
id: "mybutton01", // alphanumeric only - see below
|
||||
type: "button", // required, or clicks are silently ignored
|
||||
name: "Approve", // display label
|
||||
style: "primary", // optional: "default", "primary", "danger"
|
||||
@@ -416,11 +416,11 @@ External scripts and webhooks can post buttons directly via the Mattermost REST
|
||||
**Critical rules**
|
||||
|
||||
1. Attachments go in `props.attachments`, not top-level `attachments` (silently ignored).
|
||||
2. Every action needs `type: "button"` — without it, clicks are swallowed silently.
|
||||
3. Every action needs an `id` field — Mattermost ignores actions without IDs.
|
||||
2. Every action needs `type: "button"` - without it, clicks are swallowed silently.
|
||||
3. Every action needs an `id` field - Mattermost ignores actions without IDs.
|
||||
4. Action `id` must be **alphanumeric only** (`[a-zA-Z0-9]`). Hyphens and underscores break Mattermost's server-side action routing (returns 404). Strip them before use.
|
||||
5. `context.action_id` must match the button's `id` so the confirmation message shows the button name (e.g., "Approve") instead of a raw ID.
|
||||
6. `context.action_id` is required — the interaction handler returns 400 without it.
|
||||
6. `context.action_id` is required - the interaction handler returns 400 without it.
|
||||
|
||||
</Warning>
|
||||
|
||||
@@ -467,7 +467,7 @@ context = {**ctx, "_token": token}
|
||||
<Accordion title="Common HMAC pitfalls">
|
||||
- Python's `json.dumps` adds spaces by default (`{"key": "val"}`). Use `separators=(",", ":")` to match JavaScript's compact output (`{"key":"val"}`).
|
||||
- Always sign **all** context fields (minus `_token`). The gateway strips `_token` then signs everything remaining. Signing a subset causes silent verification failure.
|
||||
- Use `sort_keys=True` — the gateway sorts keys before signing, and Mattermost may reorder context fields when storing the payload.
|
||||
- Use `sort_keys=True` - the gateway sorts keys before signing, and Mattermost may reorder context fields when storing the payload.
|
||||
- Derive the secret from the bot token (deterministic), not random bytes. The secret must be the same across the process that creates buttons and the gateway that verifies.
|
||||
|
||||
</Accordion>
|
||||
@@ -477,7 +477,7 @@ context = {**ctx, "_token": token}
|
||||
|
||||
The Mattermost plugin includes a directory adapter that resolves channel and user names via the Mattermost API. This enables `#channel-name` and `@username` targets in `openclaw message send` and cron/webhook deliveries.
|
||||
|
||||
No configuration is needed — the adapter uses the bot token from the account config.
|
||||
No configuration is needed - the adapter uses the bot token from the account config.
|
||||
|
||||
## Multi-account
|
||||
|
||||
@@ -531,8 +531,8 @@ Mattermost supports multiple accounts under `channels.mattermost.accounts`:
|
||||
|
||||
## Related
|
||||
|
||||
- [Channel Routing](/channels/channel-routing) — session routing for messages
|
||||
- [Channels Overview](/channels) — all supported channels
|
||||
- [Groups](/channels/groups) — group chat behavior and mention gating
|
||||
- [Pairing](/channels/pairing) — DM authentication and pairing flow
|
||||
- [Security](/gateway/security) — access model and hardening
|
||||
- [Channel Routing](/channels/channel-routing) - session routing for messages
|
||||
- [Channels Overview](/channels) - all supported channels
|
||||
- [Groups](/channels/groups) - group chat behavior and mention gating
|
||||
- [Pairing](/channels/pairing) - DM authentication and pairing flow
|
||||
- [Security](/gateway/security) - access model and hardening
|
||||
|
||||
@@ -82,7 +82,7 @@ Provider-owned runner behavior lives on explicit provider hooks such as replay p
|
||||
|
||||
## Built-in providers (pi-ai catalog)
|
||||
|
||||
OpenClaw ships with the pi‑ai catalog. These providers require **no** `models.providers` config; just set auth + pick a model.
|
||||
OpenClaw ships with the pi-ai catalog. These providers require **no** `models.providers` config; just set auth + pick a model.
|
||||
|
||||
### OpenAI
|
||||
|
||||
@@ -295,11 +295,11 @@ See [/providers/kilocode](/providers/kilocode) for setup details.
|
||||
| ----------------------- | -------------------------------- | ------------------------------------------------------------ | --------------------------------------------- |
|
||||
| BytePlus | `byteplus` / `byteplus-plan` | `BYTEPLUS_API_KEY` | `byteplus-plan/ark-code-latest` |
|
||||
| Cerebras | `cerebras` | `CEREBRAS_API_KEY` | `cerebras/zai-glm-4.7` |
|
||||
| Cloudflare AI Gateway | `cloudflare-ai-gateway` | `CLOUDFLARE_AI_GATEWAY_API_KEY` | — |
|
||||
| Cloudflare AI Gateway | `cloudflare-ai-gateway` | `CLOUDFLARE_AI_GATEWAY_API_KEY` | - |
|
||||
| DeepInfra | `deepinfra` | `DEEPINFRA_API_KEY` | `deepinfra/deepseek-ai/DeepSeek-V3.2` |
|
||||
| DeepSeek | `deepseek` | `DEEPSEEK_API_KEY` | `deepseek/deepseek-v4-flash` |
|
||||
| GitHub Copilot | `github-copilot` | `COPILOT_GITHUB_TOKEN` / `GH_TOKEN` / `GITHUB_TOKEN` | — |
|
||||
| Groq | `groq` | `GROQ_API_KEY` | — |
|
||||
| GitHub Copilot | `github-copilot` | `COPILOT_GITHUB_TOKEN` / `GH_TOKEN` / `GITHUB_TOKEN` | - |
|
||||
| Groq | `groq` | `GROQ_API_KEY` | - |
|
||||
| Hugging Face Inference | `huggingface` | `HUGGINGFACE_HUB_TOKEN` or `HF_TOKEN` | `huggingface/deepseek-ai/DeepSeek-R1` |
|
||||
| Kilo Gateway | `kilocode` | `KILOCODE_API_KEY` | `kilocode/kilo/auto` |
|
||||
| Kimi Coding | `kimi` | `KIMI_API_KEY` or `KIMICODE_API_KEY` | `kimi/kimi-code` |
|
||||
@@ -312,7 +312,7 @@ See [/providers/kilocode](/providers/kilocode) for setup details.
|
||||
| Qwen Cloud | `qwen` | `QWEN_API_KEY` / `MODELSTUDIO_API_KEY` / `DASHSCOPE_API_KEY` | `qwen/qwen3.5-plus` |
|
||||
| StepFun | `stepfun` / `stepfun-plan` | `STEPFUN_API_KEY` | `stepfun/step-3.5-flash` |
|
||||
| Together | `together` | `TOGETHER_API_KEY` | `together/moonshotai/Kimi-K2.5` |
|
||||
| Venice | `venice` | `VENICE_API_KEY` | — |
|
||||
| Venice | `venice` | `VENICE_API_KEY` | - |
|
||||
| Vercel AI Gateway | `vercel-ai-gateway` | `AI_GATEWAY_API_KEY` | `vercel-ai-gateway/anthropic/claude-opus-4.6` |
|
||||
| Volcano Engine (Doubao) | `volcengine` / `volcengine-plan` | `VOLCANO_ENGINE_API_KEY` | `volcengine-plan/ark-code-latest` |
|
||||
| xAI | `xai` | `XAI_API_KEY` | `xai/grok-4.3` |
|
||||
@@ -343,7 +343,7 @@ See [/providers/kilocode](/providers/kilocode) for setup details.
|
||||
|
||||
## Providers via `models.providers` (custom/base URL)
|
||||
|
||||
Use `models.providers` (or `models.json`) to add **custom** providers or OpenAI/Anthropic‑compatible proxies.
|
||||
Use `models.providers` (or `models.json`) to add **custom** providers or OpenAI/Anthropic-compatible proxies.
|
||||
|
||||
Many of the bundled provider plugins below already publish a default catalog. Use explicit `models.providers.<id>` entries only when you want to override the default base URL, headers, or model list.
|
||||
|
||||
@@ -635,7 +635,7 @@ See [/providers/sglang](/providers/sglang) for details.
|
||||
|
||||
### Local proxies (LM Studio, vLLM, LiteLLM, etc.)
|
||||
|
||||
Example (OpenAI‑compatible):
|
||||
Example (OpenAI-compatible):
|
||||
|
||||
```json5
|
||||
{
|
||||
@@ -708,7 +708,7 @@ See also: [Configuration](/gateway/configuration) for full configuration example
|
||||
|
||||
## Related
|
||||
|
||||
- [Configuration reference](/gateway/config-agents#agent-defaults) — model config keys
|
||||
- [Model failover](/concepts/model-failover) — fallback chains and retry behavior
|
||||
- [Models](/concepts/models) — model configuration and aliases
|
||||
- [Providers](/providers) — per-provider setup guides
|
||||
- [Configuration reference](/gateway/config-agents#agent-defaults) - model config keys
|
||||
- [Model failover](/concepts/model-failover) - fallback chains and retry behavior
|
||||
- [Models](/concepts/models) - model configuration and aliases
|
||||
- [Providers](/providers) - per-provider setup guides
|
||||
|
||||
@@ -69,17 +69,17 @@ streaming and the provider also includes it in the completed reply.
|
||||
|
||||
Block chunking is implemented by `EmbeddedBlockChunker`:
|
||||
|
||||
- **Low bound:** don’t emit until buffer >= `minChars` (unless forced).
|
||||
- **Low bound:** don't emit until buffer >= `minChars` (unless forced).
|
||||
- **High bound:** prefer splits before `maxChars`; if forced, split at `maxChars`.
|
||||
- **Break preference:** `paragraph` → `newline` → `sentence` → `whitespace` → hard break.
|
||||
- **Code fences:** never split inside fences; when forced at `maxChars`, close + reopen the fence to keep Markdown valid.
|
||||
|
||||
`maxChars` is clamped to the channel `textChunkLimit`, so you can’t exceed per-channel caps.
|
||||
`maxChars` is clamped to the channel `textChunkLimit`, so you can't exceed per-channel caps.
|
||||
|
||||
## Coalescing (merge streamed blocks)
|
||||
|
||||
When block streaming is enabled, OpenClaw can **merge consecutive block chunks**
|
||||
before sending them out. This reduces “single-line spam” while still providing
|
||||
before sending them out. This reduces "single-line spam" while still providing
|
||||
progressive output.
|
||||
|
||||
- Coalescing waits for **idle gaps** (`idleMs`) before flushing.
|
||||
@@ -98,7 +98,7 @@ block replies (after the first block). This makes multi-bubble responses feel
|
||||
more natural.
|
||||
|
||||
- Config: `agents.defaults.humanDelay` (override per agent via `agents.list[].humanDelay`).
|
||||
- Modes: `off` (default), `natural` (800–2500ms), `custom` (`minMs`/`maxMs`).
|
||||
- Modes: `off` (default), `natural` (800-2500ms), `custom` (`minMs`/`maxMs`).
|
||||
- Applies only to **block replies**, not final replies or tool summaries.
|
||||
|
||||
## "Stream chunks or everything"
|
||||
@@ -193,7 +193,7 @@ Matrix:
|
||||
|
||||
### Tool-progress preview updates
|
||||
|
||||
Preview streaming can also include **tool-progress** updates — short status lines like "searching the web", "reading file", or "calling tool" — that appear in the same preview message while tools are running, ahead of the final reply. This keeps multi-step tool turns visually alive rather than silent between the first thinking preview and the final answer.
|
||||
Preview streaming can also include **tool-progress** updates - short status lines like "searching the web", "reading file", or "calling tool" - that appear in the same preview message while tools are running, ahead of the final reply. This keeps multi-step tool turns visually alive rather than silent between the first thinking preview and the final answer.
|
||||
|
||||
Supported surfaces:
|
||||
|
||||
@@ -243,7 +243,7 @@ Use the same shape under another compact progress channel key, for example `chan
|
||||
## Related
|
||||
|
||||
- [Message lifecycle refactor](/concepts/message-lifecycle-refactor) - target shared preview, edit, stream, and finalization design
|
||||
- [Progress drafts](/concepts/progress-drafts) — visible work-in-progress messages that update during long turns
|
||||
- [Messages](/concepts/messages) — message lifecycle and delivery
|
||||
- [Retry](/concepts/retry) — retry behavior on delivery failure
|
||||
- [Channels](/channels) — per-channel streaming support
|
||||
- [Progress drafts](/concepts/progress-drafts) - visible work-in-progress messages that update during long turns
|
||||
- [Messages](/concepts/messages) - message lifecycle and delivery
|
||||
- [Retry](/concepts/retry) - retry behavior on delivery failure
|
||||
- [Channels](/channels) - per-channel streaming support
|
||||
|
||||
@@ -36,7 +36,7 @@ install from npm during the launch cutover.
|
||||
Add a model provider (LLM, proxy, or custom endpoint)
|
||||
</Card>
|
||||
<Card title="Tool / hook plugin" icon="wrench" href="/plugins/hooks">
|
||||
Register agent tools, event hooks, or services — continue below
|
||||
Register agent tools, event hooks, or services - continue below
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@@ -126,7 +126,7 @@ and provider plugins have dedicated guides linked above.
|
||||
```
|
||||
|
||||
`definePluginEntry` is for non-channel plugins. For channels, use
|
||||
`defineChannelPluginEntry` — see [Channel Plugins](/plugins/sdk-channel-plugins).
|
||||
`defineChannelPluginEntry` - see [Channel Plugins](/plugins/sdk-channel-plugins).
|
||||
For full entry point options, see [Entry Points](/plugins/sdk-entrypoints).
|
||||
|
||||
</Step>
|
||||
@@ -144,7 +144,7 @@ and provider plugins have dedicated guides linked above.
|
||||
Bare package specs like `@myorg/openclaw-my-plugin` install from npm during
|
||||
the launch cutover. Use `clawhub:` when you want ClawHub resolution.
|
||||
|
||||
**In-repo plugins:** place under the bundled plugin workspace tree — automatically discovered.
|
||||
**In-repo plugins:** place under the bundled plugin workspace tree - automatically discovered.
|
||||
|
||||
```bash
|
||||
pnpm test -- <bundled-plugin-root>/my-plugin/
|
||||
@@ -220,7 +220,7 @@ available) or optional (user opt-in):
|
||||
|
||||
```typescript
|
||||
register(api) {
|
||||
// Required tool — always available
|
||||
// Required tool - always available
|
||||
api.registerTool({
|
||||
name: "my_tool",
|
||||
description: "Do a thing",
|
||||
@@ -230,7 +230,7 @@ register(api) {
|
||||
},
|
||||
});
|
||||
|
||||
// Optional tool — user must add to allowlist
|
||||
// Optional tool - user must add to allowlist
|
||||
api.registerTool(
|
||||
{
|
||||
name: "workflow_tool",
|
||||
@@ -338,7 +338,7 @@ import { ... } from "openclaw/plugin-sdk";
|
||||
For the full subpath reference, see [SDK Overview](/plugins/sdk-overview).
|
||||
|
||||
Within your plugin, use local barrel files (`api.ts`, `runtime-api.ts`) for
|
||||
internal imports — never import your own plugin through its SDK path.
|
||||
internal imports - never import your own plugin through its SDK path.
|
||||
|
||||
For provider plugins, keep provider-specific helpers in those package-root
|
||||
barrels unless the seam is truly generic. Current bundled examples:
|
||||
@@ -398,8 +398,8 @@ reserved surfaces, not as the default pattern for new third-party plugins.
|
||||
|
||||
## Related
|
||||
|
||||
- [Plugin Architecture](/plugins/architecture) — internal architecture deep dive
|
||||
- [SDK Overview](/plugins/sdk-overview) — Plugin SDK reference
|
||||
- [Manifest](/plugins/manifest) — plugin manifest format
|
||||
- [Channel Plugins](/plugins/sdk-channel-plugins) — building channel plugins
|
||||
- [Provider Plugins](/plugins/sdk-provider-plugins) — building provider plugins
|
||||
- [Plugin Architecture](/plugins/architecture) - internal architecture deep dive
|
||||
- [SDK Overview](/plugins/sdk-overview) - Plugin SDK reference
|
||||
- [Manifest](/plugins/manifest) - plugin manifest format
|
||||
- [Channel Plugins](/plugins/sdk-channel-plugins) - building channel plugins
|
||||
- [Provider Plugins](/plugins/sdk-provider-plugins) - building provider plugins
|
||||
|
||||
@@ -68,7 +68,7 @@ variants are the current image-capable Grok refs in the bundled catalog.
|
||||
|
||||
The bundled plugin maps xAI's current public API surface onto OpenClaw's shared
|
||||
provider and tool contracts. Capabilities that don't fit the shared contract
|
||||
(for example streaming TTS and realtime voice) are not exposed — see the table
|
||||
(for example streaming TTS and realtime voice) are not exposed - see the table
|
||||
below.
|
||||
|
||||
| xAI capability | OpenClaw surface | Status |
|
||||
@@ -80,10 +80,10 @@ below.
|
||||
| Images | `image_generate` | Yes |
|
||||
| Videos | `video_generate` | Yes |
|
||||
| Batch text-to-speech | `messages.tts.provider: "xai"` / `tts` | Yes |
|
||||
| Streaming TTS | — | Not exposed; OpenClaw's TTS contract returns complete audio buffers |
|
||||
| Streaming TTS | - | Not exposed; OpenClaw's TTS contract returns complete audio buffers |
|
||||
| Batch speech-to-text | `tools.media.audio` / media understanding | Yes |
|
||||
| Streaming speech-to-text | Voice Call `streaming.provider: "xai"` | Yes |
|
||||
| Realtime voice | — | Not exposed yet; different session/WebSocket contract |
|
||||
| Realtime voice | - | Not exposed yet; different session/WebSocket contract |
|
||||
| Files / batches | Generic model API compatibility only | Not a first-class OpenClaw tool |
|
||||
|
||||
<Note>
|
||||
@@ -343,13 +343,13 @@ Legacy aliases still normalize to the canonical bundled ids:
|
||||
|
||||
| Key | Type | Default | Description |
|
||||
| ------------------ | ------- | ------------------ | ------------------------------------ |
|
||||
| `enabled` | boolean | — | Enable or disable x_search |
|
||||
| `enabled` | boolean | - | Enable or disable x_search |
|
||||
| `model` | string | `grok-4-1-fast` | Model used for x_search requests |
|
||||
| `baseUrl` | string | — | xAI Responses base URL override |
|
||||
| `inlineCitations` | boolean | — | Include inline citations in results |
|
||||
| `maxTurns` | number | — | Maximum conversation turns |
|
||||
| `timeoutSeconds` | number | — | Request timeout in seconds |
|
||||
| `cacheTtlMinutes` | number | — | Cache time-to-live in minutes |
|
||||
| `baseUrl` | string | - | xAI Responses base URL override |
|
||||
| `inlineCitations` | boolean | - | Include inline citations in results |
|
||||
| `maxTurns` | number | - | Maximum conversation turns |
|
||||
| `timeoutSeconds` | number | - | Request timeout in seconds |
|
||||
| `cacheTtlMinutes` | number | - | Cache time-to-live in minutes |
|
||||
|
||||
```json5
|
||||
{
|
||||
@@ -382,8 +382,8 @@ Legacy aliases still normalize to the canonical bundled ids:
|
||||
| ----------------- | ------- | ------------------ | ---------------------------------------- |
|
||||
| `enabled` | boolean | `true` (if key available) | Enable or disable code execution |
|
||||
| `model` | string | `grok-4-1-fast` | Model used for code execution requests |
|
||||
| `maxTurns` | number | — | Maximum conversation turns |
|
||||
| `timeoutSeconds` | number | — | Request timeout in seconds |
|
||||
| `maxTurns` | number | - | Maximum conversation turns |
|
||||
| `timeoutSeconds` | number | - | Request timeout in seconds |
|
||||
|
||||
<Note>
|
||||
This is remote xAI sandbox execution, not local [`exec`](/tools/exec).
|
||||
|
||||
@@ -257,8 +257,8 @@ current OpenClaw or a local checkout until a newer npm package is published.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Memory plugins">
|
||||
- `memory-core` — bundled memory search (default via `plugins.slots.memory`)
|
||||
- `memory-lancedb` — LanceDB-backed long-term memory with auto-recall/capture (set `plugins.slots.memory = "memory-lancedb"`)
|
||||
- `memory-core` - bundled memory search (default via `plugins.slots.memory`)
|
||||
- `memory-lancedb` - LanceDB-backed long-term memory with auto-recall/capture (set `plugins.slots.memory = "memory-lancedb"`)
|
||||
|
||||
See [Memory LanceDB](/plugins/memory-lancedb) for OpenAI-compatible
|
||||
embedding setup, Ollama examples, recall limits, and troubleshooting.
|
||||
@@ -270,8 +270,8 @@ current OpenClaw or a local checkout until a newer npm package is published.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Other">
|
||||
- `browser` — bundled browser plugin for the browser tool, `openclaw browser` CLI, `browser.request` gateway method, browser runtime, and default browser control service (enabled by default; disable before replacing it)
|
||||
- `copilot-proxy` — VS Code Copilot Proxy bridge (disabled by default)
|
||||
- `browser` - bundled browser plugin for the browser tool, `openclaw browser` CLI, `browser.request` gateway method, browser runtime, and default browser control service (enabled by default; disable before replacing it)
|
||||
- `copilot-proxy` - VS Code Copilot Proxy bridge (disabled by default)
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
@@ -344,7 +344,7 @@ OpenClaw scans for plugins in this order (first match wins):
|
||||
|
||||
<Steps>
|
||||
<Step title="Config paths">
|
||||
`plugins.load.paths` — explicit file or directory paths. Paths that point
|
||||
`plugins.load.paths` - explicit file or directory paths. Paths that point
|
||||
back at OpenClaw's own packaged bundled plugin directories are ignored;
|
||||
run `openclaw doctor --fix` to remove those stale aliases.
|
||||
</Step>
|
||||
@@ -714,9 +714,9 @@ For full typed hook behavior, see [SDK overview](/plugins/sdk-overview#hook-deci
|
||||
|
||||
## Related
|
||||
|
||||
- [Building plugins](/plugins/building-plugins) — create your own plugin
|
||||
- [Plugin bundles](/plugins/bundles) — Codex/Claude/Cursor bundle compatibility
|
||||
- [Plugin manifest](/plugins/manifest) — manifest schema
|
||||
- [Registering tools](/plugins/building-plugins#registering-agent-tools) — add agent tools in a plugin
|
||||
- [Plugin internals](/plugins/architecture) — capability model and load pipeline
|
||||
- [Community plugins](/plugins/community) — third-party listings
|
||||
- [Building plugins](/plugins/building-plugins) - create your own plugin
|
||||
- [Plugin bundles](/plugins/bundles) - Codex/Claude/Cursor bundle compatibility
|
||||
- [Plugin manifest](/plugins/manifest) - manifest schema
|
||||
- [Registering tools](/plugins/building-plugins#registering-agent-tools) - add agent tools in a plugin
|
||||
- [Plugin internals](/plugins/architecture) - capability model and load pipeline
|
||||
- [Community plugins](/plugins/community) - third-party listings
|
||||
|
||||
Reference in New Issue
Block a user