mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 09:00:42 +00:00
docs(plugins): add generated plugin inventory
This commit is contained in:
@@ -1182,6 +1182,7 @@
|
||||
"pages": [
|
||||
"tools/plugin",
|
||||
"plugins/community",
|
||||
"plugins/plugin-inventory",
|
||||
"plugins/bundles",
|
||||
"plugins/dependency-resolution",
|
||||
"plugins/codex-harness",
|
||||
|
||||
@@ -95,6 +95,9 @@ Lightweight and core-critical bundled plugins are shipped as part of OpenClaw.
|
||||
They should either have no heavy runtime dependency tree or be moved out to a
|
||||
downloadable package on ClawHub/npm.
|
||||
|
||||
For the current generated list of plugins that ship in the core package, install
|
||||
externally, or stay source-only, see [Plugin inventory](/plugins/plugin-inventory).
|
||||
|
||||
Bundled plugin manifests must not request dependency staging. Large or optional
|
||||
plugin functionality should be packaged as a normal plugin and installed through
|
||||
the same npm/git/ClawHub path as third-party plugins.
|
||||
|
||||
157
docs/plugins/plugin-inventory.md
Normal file
157
docs/plugins/plugin-inventory.md
Normal file
@@ -0,0 +1,157 @@
|
||||
---
|
||||
summary: "Generated inventory of OpenClaw plugins shipped in core, published externally, or kept source-only"
|
||||
read_when:
|
||||
- You are deciding whether a plugin ships in the core npm package or installs separately
|
||||
- You are updating bundled plugin package metadata or release automation
|
||||
- You need the canonical internal vs external plugin list
|
||||
title: "Plugin inventory"
|
||||
---
|
||||
|
||||
# Plugin inventory
|
||||
|
||||
This page is generated from `extensions/*/package.json`, `openclaw.plugin.json`,
|
||||
and the root npm package `files` exclusions. Regenerate it with:
|
||||
|
||||
```bash
|
||||
pnpm plugins:inventory:gen
|
||||
```
|
||||
|
||||
## Definitions
|
||||
|
||||
- **Core npm package:** built into the `openclaw` npm package and available without a separate plugin install.
|
||||
- **Official external package:** OpenClaw-maintained plugin omitted from the core npm package and installed through ClawHub and/or npm.
|
||||
- **Source checkout only:** repo-local plugin omitted from published npm artifacts and not advertised as an installable package.
|
||||
|
||||
Source checkouts are different from npm installs: after `pnpm install`, bundled
|
||||
plugins load from `extensions/<id>` so local edits and package-local workspace
|
||||
dependencies are available.
|
||||
|
||||
## Core npm package
|
||||
|
||||
| Plugin | Package | Surface | Docs | Install |
|
||||
| --------------------- | ------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- | -------------------- |
|
||||
| alibaba | `@openclaw/alibaba-provider` | contracts: videoGenerationProviders | [alibaba](/providers/alibaba) | included in OpenClaw |
|
||||
| amazon-bedrock | `@openclaw/amazon-bedrock-provider` | providers: amazon-bedrock; contracts: memoryEmbeddingProviders | [amazon-bedrock](/providers/bedrock) | included in OpenClaw |
|
||||
| amazon-bedrock-mantle | `@openclaw/amazon-bedrock-mantle-provider` | providers: amazon-bedrock-mantle | [amazon-bedrock-mantle](/providers/bedrock-mantle) | included in OpenClaw |
|
||||
| anthropic | `@openclaw/anthropic-provider` | providers: anthropic; contracts: mediaUnderstandingProviders | [anthropic](/providers/anthropic) | included in OpenClaw |
|
||||
| anthropic-vertex | `@openclaw/anthropic-vertex-provider` | providers: anthropic-vertex | - | included in OpenClaw |
|
||||
| arcee | `@openclaw/arcee-provider` | providers: arcee | [arcee](/providers/arcee) | included in OpenClaw |
|
||||
| azure-speech | `@openclaw/azure-speech` | contracts: speechProviders | [azure-speech](/providers/azure-speech) | included in OpenClaw |
|
||||
| bonjour | `@openclaw/bonjour` | plugin | - | included in OpenClaw |
|
||||
| browser | `@openclaw/browser-plugin` | contracts: tools; skills | [browser](/tools/browser) | included in OpenClaw |
|
||||
| byteplus | `@openclaw/byteplus-provider` | providers: byteplus, byteplus-plan; contracts: videoGenerationProviders | - | included in OpenClaw |
|
||||
| cerebras | `@openclaw/cerebras-provider` | providers: cerebras | [cerebras](/providers/cerebras) | included in OpenClaw |
|
||||
| chutes | `@openclaw/chutes-provider` | providers: chutes | [chutes](/providers/chutes) | included in OpenClaw |
|
||||
| cloudflare-ai-gateway | `@openclaw/cloudflare-ai-gateway-provider` | providers: cloudflare-ai-gateway | [cloudflare-ai-gateway](/providers/cloudflare-ai-gateway) | included in OpenClaw |
|
||||
| comfy | `@openclaw/comfy-provider` | providers: comfy; contracts: imageGenerationProviders, musicGenerationProviders, videoGenerationProviders | [comfy](/providers/comfy) | included in OpenClaw |
|
||||
| copilot-proxy | `@openclaw/copilot-proxy` | providers: copilot-proxy | - | included in OpenClaw |
|
||||
| deepgram | `@openclaw/deepgram-provider` | contracts: mediaUnderstandingProviders, realtimeTranscriptionProviders | [deepgram](/providers/deepgram) | included in OpenClaw |
|
||||
| deepinfra | `@openclaw/deepinfra-provider` | providers: deepinfra; contracts: imageGenerationProviders, mediaUnderstandingProviders, memoryEmbeddingProviders, speechProviders, videoGenerationProviders | [deepinfra](/providers/deepinfra) | included in OpenClaw |
|
||||
| deepseek | `@openclaw/deepseek-provider` | providers: deepseek | [deepseek](/providers/deepseek) | included in OpenClaw |
|
||||
| document-extract | `@openclaw/document-extract-plugin` | contracts: documentExtractors | [document-extract](/tools/pdf) | included in OpenClaw |
|
||||
| duckduckgo | `@openclaw/duckduckgo-plugin` | contracts: webSearchProviders | [duckduckgo](/tools/duckduckgo-search) | included in OpenClaw |
|
||||
| elevenlabs | `@openclaw/elevenlabs-speech` | contracts: mediaUnderstandingProviders, realtimeTranscriptionProviders, speechProviders | [elevenlabs](/providers/elevenlabs) | included in OpenClaw |
|
||||
| exa | `@openclaw/exa-plugin` | contracts: webSearchProviders | [exa](/tools/exa-search) | included in OpenClaw |
|
||||
| fal | `@openclaw/fal-provider` | providers: fal; contracts: imageGenerationProviders, videoGenerationProviders | [fal](/providers/fal) | included in OpenClaw |
|
||||
| file-transfer | `@openclaw/file-transfer` | contracts: tools | - | included in OpenClaw |
|
||||
| firecrawl | `@openclaw/firecrawl-plugin` | contracts: tools, webFetchProviders, webSearchProviders | [firecrawl](/tools/firecrawl) | included in OpenClaw |
|
||||
| fireworks | `@openclaw/fireworks-provider` | providers: fireworks | [fireworks](/providers/fireworks) | included in OpenClaw |
|
||||
| github-copilot | `@openclaw/github-copilot-provider` | providers: github-copilot; contracts: memoryEmbeddingProviders | [github-copilot](/providers/github-copilot) | included in OpenClaw |
|
||||
| google | `@openclaw/google-plugin` | providers: google, google-gemini-cli, google-vertex; contracts: imageGenerationProviders, mediaUnderstandingProviders, memoryEmbeddingProviders, musicGenerationProviders, realtimeVoiceProviders, speechProviders, videoGenerationProviders, webSearchProviders | [google](/providers/google) | included in OpenClaw |
|
||||
| gradium | `@openclaw/gradium-speech` | contracts: speechProviders | [gradium](/providers/gradium) | included in OpenClaw |
|
||||
| groq | `@openclaw/groq-provider` | providers: groq; contracts: mediaUnderstandingProviders | [groq](/providers/groq) | included in OpenClaw |
|
||||
| huggingface | `@openclaw/huggingface-provider` | providers: huggingface | [huggingface](/providers/huggingface) | included in OpenClaw |
|
||||
| imessage | `@openclaw/imessage` | channels: imessage | [imessage](/channels/imessage) | included in OpenClaw |
|
||||
| inworld | `@openclaw/inworld-speech` | contracts: speechProviders | [inworld](/providers/inworld) | included in OpenClaw |
|
||||
| irc | `@openclaw/irc` | channels: irc | [irc](/channels/irc) | included in OpenClaw |
|
||||
| kilocode | `@openclaw/kilocode-provider` | providers: kilocode | [kilocode](/providers/kilocode) | included in OpenClaw |
|
||||
| kimi | `@openclaw/kimi-provider` | providers: kimi, kimi-coding | [kimi](/providers/moonshot) | included in OpenClaw |
|
||||
| litellm | `@openclaw/litellm-provider` | providers: litellm; contracts: imageGenerationProviders | [litellm](/providers/litellm) | included in OpenClaw |
|
||||
| llm-task | `@openclaw/llm-task` | contracts: tools | - | included in OpenClaw |
|
||||
| lmstudio | `@openclaw/lmstudio-provider` | providers: lmstudio; contracts: memoryEmbeddingProviders | [lmstudio](/providers/lmstudio) | included in OpenClaw |
|
||||
| memory-core | `@openclaw/memory-core` | contracts: memoryEmbeddingProviders, tools | - | included in OpenClaw |
|
||||
| memory-wiki | `@openclaw/memory-wiki` | contracts: tools; skills | [memory-wiki](/plugins/memory-wiki) | included in OpenClaw |
|
||||
| microsoft | `@openclaw/microsoft-speech` | contracts: speechProviders | - | included in OpenClaw |
|
||||
| microsoft-foundry | `@openclaw/microsoft-foundry` | providers: microsoft-foundry | - | included in OpenClaw |
|
||||
| migrate-claude | `@openclaw/migrate-claude` | contracts: migrationProviders | - | included in OpenClaw |
|
||||
| migrate-hermes | `@openclaw/migrate-hermes` | contracts: migrationProviders | - | included in OpenClaw |
|
||||
| minimax | `@openclaw/minimax-provider` | providers: minimax, minimax-portal; contracts: imageGenerationProviders, mediaUnderstandingProviders, musicGenerationProviders, speechProviders, videoGenerationProviders, webSearchProviders | [minimax](/providers/minimax) | included in OpenClaw |
|
||||
| mistral | `@openclaw/mistral-provider` | providers: mistral; contracts: mediaUnderstandingProviders, memoryEmbeddingProviders, realtimeTranscriptionProviders | [mistral](/providers/mistral) | included in OpenClaw |
|
||||
| moonshot | `@openclaw/moonshot-provider` | providers: moonshot; contracts: mediaUnderstandingProviders, webSearchProviders | [moonshot](/providers/moonshot) | included in OpenClaw |
|
||||
| nvidia | `@openclaw/nvidia-provider` | providers: nvidia | [nvidia](/providers/nvidia) | included in OpenClaw |
|
||||
| ollama | `@openclaw/ollama-provider` | providers: ollama; contracts: memoryEmbeddingProviders, webSearchProviders | [ollama](/providers/ollama) | included in OpenClaw |
|
||||
| open-prose | `@openclaw/open-prose` | skills | - | included in OpenClaw |
|
||||
| openai | `@openclaw/openai-provider` | providers: openai, openai-codex; contracts: imageGenerationProviders, mediaUnderstandingProviders, memoryEmbeddingProviders, realtimeTranscriptionProviders, realtimeVoiceProviders, speechProviders, videoGenerationProviders | [openai](/providers/openai) | included in OpenClaw |
|
||||
| opencode | `@openclaw/opencode-provider` | providers: opencode; contracts: mediaUnderstandingProviders | [opencode](/providers/opencode) | included in OpenClaw |
|
||||
| opencode-go | `@openclaw/opencode-go-provider` | providers: opencode-go; contracts: mediaUnderstandingProviders | [opencode-go](/providers/opencode-go) | included in OpenClaw |
|
||||
| openrouter | `@openclaw/openrouter-provider` | providers: openrouter; contracts: imageGenerationProviders, mediaUnderstandingProviders, speechProviders, videoGenerationProviders | [openrouter](/providers/openrouter) | included in OpenClaw |
|
||||
| openshell | `@openclaw/openshell-sandbox` | plugin | - | included in OpenClaw |
|
||||
| perplexity | `@openclaw/perplexity-plugin` | contracts: webSearchProviders | [perplexity](/tools/perplexity-search) | included in OpenClaw |
|
||||
| qianfan | `@openclaw/qianfan-provider` | providers: qianfan | [qianfan](/providers/qianfan) | included in OpenClaw |
|
||||
| qwen | `@openclaw/qwen-provider` | providers: qwen, qwencloud, modelstudio, dashscope; contracts: mediaUnderstandingProviders, videoGenerationProviders | [qwen](/providers/qwen) | included in OpenClaw |
|
||||
| runway | `@openclaw/runway-provider` | contracts: videoGenerationProviders | [runway](/providers/runway) | included in OpenClaw |
|
||||
| searxng | `@openclaw/searxng-plugin` | contracts: webSearchProviders | - | included in OpenClaw |
|
||||
| senseaudio | `@openclaw/senseaudio-provider` | contracts: mediaUnderstandingProviders | [senseaudio](/providers/senseaudio) | included in OpenClaw |
|
||||
| sglang | `@openclaw/sglang-provider` | providers: sglang | [sglang](/providers/sglang) | included in OpenClaw |
|
||||
| signal | `@openclaw/signal` | channels: signal | [signal](/channels/signal) | included in OpenClaw |
|
||||
| skill-workshop | `@openclaw/skill-workshop` | contracts: tools | [skill-workshop](/plugins/skill-workshop) | included in OpenClaw |
|
||||
| slack | `@openclaw/slack` | channels: slack | [slack](/channels/slack) | included in OpenClaw |
|
||||
| stepfun | `@openclaw/stepfun-provider` | providers: stepfun, stepfun-plan | [stepfun](/providers/stepfun) | included in OpenClaw |
|
||||
| synthetic | `@openclaw/synthetic-provider` | providers: synthetic | [synthetic](/providers/synthetic) | included in OpenClaw |
|
||||
| tavily | `@openclaw/tavily-plugin` | contracts: tools, webSearchProviders; skills | [tavily](/tools/tavily) | included in OpenClaw |
|
||||
| telegram | `@openclaw/telegram` | channels: telegram | [telegram](/channels/telegram) | included in OpenClaw |
|
||||
| tencent | `@openclaw/tencent-provider` | providers: tencent-tokenhub | [tencent](/providers/tencent) | included in OpenClaw |
|
||||
| together | `@openclaw/together-provider` | providers: together; contracts: videoGenerationProviders | [together](/providers/together) | included in OpenClaw |
|
||||
| tokenjuice | `@openclaw/tokenjuice` | contracts: agentToolResultMiddleware | [tokenjuice](/tools/tokenjuice) | included in OpenClaw |
|
||||
| tts-local-cli | `@openclaw/tts-local-cli` | contracts: speechProviders | - | included in OpenClaw |
|
||||
| venice | `@openclaw/venice-provider` | providers: venice | [venice](/providers/venice) | included in OpenClaw |
|
||||
| vercel-ai-gateway | `@openclaw/vercel-ai-gateway-provider` | providers: vercel-ai-gateway | [vercel-ai-gateway](/providers/vercel-ai-gateway) | included in OpenClaw |
|
||||
| vllm | `@openclaw/vllm-provider` | providers: vllm | [vllm](/providers/vllm) | included in OpenClaw |
|
||||
| volcengine | `@openclaw/volcengine-provider` | providers: volcengine, volcengine-plan; contracts: speechProviders | [volcengine](/providers/volcengine) | included in OpenClaw |
|
||||
| voyage | `@openclaw/voyage-provider` | contracts: memoryEmbeddingProviders | - | included in OpenClaw |
|
||||
| vydra | `@openclaw/vydra-provider` | providers: vydra; contracts: imageGenerationProviders, speechProviders, videoGenerationProviders | [vydra](/providers/vydra) | included in OpenClaw |
|
||||
| web-readability | `@openclaw/web-readability-plugin` | contracts: webContentExtractors | - | included in OpenClaw |
|
||||
| webhooks | `@openclaw/webhooks` | plugin | [webhooks](/plugins/webhooks) | included in OpenClaw |
|
||||
| xai | `@openclaw/xai-plugin` | providers: xai; contracts: imageGenerationProviders, mediaUnderstandingProviders, realtimeTranscriptionProviders, speechProviders, tools, videoGenerationProviders, webSearchProviders | [xai](/providers/xai) | included in OpenClaw |
|
||||
| xiaomi | `@openclaw/xiaomi-provider` | providers: xiaomi; contracts: speechProviders | [xiaomi](/providers/xiaomi) | included in OpenClaw |
|
||||
| zai | `@openclaw/zai-provider` | providers: zai; contracts: mediaUnderstandingProviders | [zai](/providers/zai) | included in OpenClaw |
|
||||
|
||||
## Official external packages
|
||||
|
||||
| Plugin | Package | Surface | Docs | Install |
|
||||
| ---------------------- | ---------------------------------- | ---------------------------------------------------------------------------- | ------------------------------------------------------------- | ------------------------------------------------- |
|
||||
| acpx | `@openclaw/acpx` | skills | [acpx](/tools/acp-agents-setup) | ClawHub + npm: `@openclaw/acpx` |
|
||||
| bluebubbles | `@openclaw/bluebubbles` | channels: bluebubbles | [bluebubbles](/channels/bluebubbles) | ClawHub + npm: `@openclaw/bluebubbles` |
|
||||
| brave | `@openclaw/brave-plugin` | contracts: webSearchProviders | [brave](/tools/brave-search) | ClawHub + npm: `@openclaw/brave-plugin` |
|
||||
| codex | `@openclaw/codex` | providers: codex; contracts: mediaUnderstandingProviders, migrationProviders | [codex](/plugins/codex-harness) | ClawHub + npm: `@openclaw/codex` |
|
||||
| diagnostics-otel | `@openclaw/diagnostics-otel` | plugin | - | ClawHub + npm: `@openclaw/diagnostics-otel` |
|
||||
| diagnostics-prometheus | `@openclaw/diagnostics-prometheus` | plugin | - | ClawHub + npm: `@openclaw/diagnostics-prometheus` |
|
||||
| diffs | `@openclaw/diffs` | contracts: tools; skills | - | ClawHub + npm: `@openclaw/diffs` |
|
||||
| discord | `@openclaw/discord` | channels: discord | [discord](/channels/discord) | ClawHub + npm: `@openclaw/discord` |
|
||||
| feishu | `@openclaw/feishu` | channels: feishu; contracts: tools; skills | [feishu](/channels/feishu) | ClawHub + npm: `@openclaw/feishu` |
|
||||
| google-meet | `@openclaw/google-meet` | contracts: tools | [google-meet](/plugins/google-meet) | ClawHub + npm: `@openclaw/google-meet` |
|
||||
| googlechat | `@openclaw/googlechat` | channels: googlechat | [googlechat](/channels/googlechat) | ClawHub + npm: `@openclaw/googlechat` |
|
||||
| line | `@openclaw/line` | channels: line | [line](/channels/line) | ClawHub + npm: `@openclaw/line` |
|
||||
| lobster | `@openclaw/lobster` | contracts: tools | - | ClawHub + npm: `@openclaw/lobster` |
|
||||
| matrix | `@openclaw/matrix` | channels: matrix | [matrix](/channels/matrix) | ClawHub + npm: `@openclaw/matrix` |
|
||||
| mattermost | `@openclaw/mattermost` | channels: mattermost | [mattermost](/channels/mattermost) | ClawHub + npm: `@openclaw/mattermost` |
|
||||
| memory-lancedb | `@openclaw/memory-lancedb` | contracts: tools | [memory-lancedb](/plugins/memory-lancedb) | ClawHub + npm: `@openclaw/memory-lancedb` |
|
||||
| msteams | `@openclaw/msteams` | channels: msteams | [msteams](/channels/msteams) | ClawHub + npm: `@openclaw/msteams` |
|
||||
| nextcloud-talk | `@openclaw/nextcloud-talk` | channels: nextcloud-talk | [nextcloud-talk](/channels/nextcloud-talk) | ClawHub + npm: `@openclaw/nextcloud-talk` |
|
||||
| nostr | `@openclaw/nostr` | channels: nostr | [nostr](/channels/nostr) | ClawHub + npm: `@openclaw/nostr` |
|
||||
| qqbot | `@openclaw/qqbot` | channels: qqbot; contracts: tools; skills | [qqbot](/channels/qqbot) | ClawHub + npm: `@openclaw/qqbot` |
|
||||
| synology-chat | `@openclaw/synology-chat` | channels: synology-chat | [synology-chat](/channels/synology-chat) | ClawHub + npm: `@openclaw/synology-chat` |
|
||||
| tlon | `@openclaw/tlon` | channels: tlon; contracts: tools; skills | [tlon](/channels/tlon) | ClawHub + npm: `@openclaw/tlon` |
|
||||
| twitch | `@openclaw/twitch` | channels: twitch | [twitch](/channels/twitch) | ClawHub + npm: `@openclaw/twitch` |
|
||||
| voice-call | `@openclaw/voice-call` | contracts: tools | [voice-call](/plugins/voice-call) | ClawHub + npm: `@openclaw/voice-call` |
|
||||
| whatsapp | `@openclaw/whatsapp` | channels: whatsapp | [whatsapp](/channels/whatsapp) | ClawHub + npm: `@openclaw/whatsapp` |
|
||||
| zalo | `@openclaw/zalo` | channels: zalo | [zalo](/channels/zalo) | ClawHub + npm: `@openclaw/zalo` |
|
||||
| zalouser | `@openclaw/zalouser` | channels: zalouser; contracts: tools | [zalouser](/channels/zalouser), [zalouser](/plugins/zalouser) | ClawHub + npm: `@openclaw/zalouser` |
|
||||
|
||||
## Source checkout only
|
||||
|
||||
| Plugin | Package | Surface | Docs | Install |
|
||||
| ---------- | ---------------------- | -------------------- | ---------------------------------- | -------------------- |
|
||||
| qa-channel | `@openclaw/qa-channel` | channels: qa-channel | [qa-channel](/channels/qa-channel) | source checkout only |
|
||||
| qa-lab | `@openclaw/qa-lab` | plugin | - | source checkout only |
|
||||
| qa-matrix | `@openclaw/qa-matrix` | plugin | - | source checkout only |
|
||||
@@ -1438,6 +1438,8 @@
|
||||
"plugins:boundary-report:ci": "node --import tsx scripts/plugin-boundary-report.ts --summary --fail-on-cross-owner --fail-on-unclassified-unused-reserved --fail-on-eligible-compat",
|
||||
"plugins:boundary-report:json": "node --import tsx scripts/plugin-boundary-report.ts --json",
|
||||
"plugins:boundary-report:summary": "node --import tsx scripts/plugin-boundary-report.ts --summary",
|
||||
"plugins:inventory:check": "node scripts/generate-plugin-inventory-doc.mjs --check",
|
||||
"plugins:inventory:gen": "node scripts/generate-plugin-inventory-doc.mjs --write",
|
||||
"plugins:sync": "node --import tsx scripts/sync-plugin-versions.ts",
|
||||
"plugins:sync:check": "node --import tsx scripts/sync-plugin-versions.ts --check",
|
||||
"postinstall": "node scripts/postinstall-bundled-plugins.mjs",
|
||||
@@ -1462,7 +1464,7 @@
|
||||
"qa:lab:watch": "vite build --watch --config extensions/qa-lab/web/vite.config.ts",
|
||||
"qa:otel:smoke": "node --import tsx scripts/qa-otel-smoke.ts",
|
||||
"release-metadata:check": "node scripts/check-release-metadata-only.mjs",
|
||||
"release:check": "pnpm deps:root-ownership:check && pnpm check:base-config-schema && pnpm check:bundled-channel-config-metadata && pnpm config:docs:check && pnpm plugin-sdk:check-exports && pnpm plugin-sdk:api:check && node --import tsx scripts/release-check.ts",
|
||||
"release:check": "pnpm deps:root-ownership:check && pnpm plugins:inventory:check && pnpm check:base-config-schema && pnpm check:bundled-channel-config-metadata && pnpm config:docs:check && pnpm plugin-sdk:check-exports && pnpm plugin-sdk:api:check && node --import tsx scripts/release-check.ts",
|
||||
"release:openclaw:npm:check": "node --import tsx scripts/openclaw-npm-release-check.ts",
|
||||
"release:openclaw:npm:verify-published": "node --import tsx scripts/openclaw-npm-postpublish-verify.ts",
|
||||
"release:plugins:clawhub:check": "node --import tsx scripts/plugin-clawhub-release-check.ts",
|
||||
|
||||
318
scripts/generate-plugin-inventory-doc.mjs
Normal file
318
scripts/generate-plugin-inventory-doc.mjs
Normal file
@@ -0,0 +1,318 @@
|
||||
#!/usr/bin/env node
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import process from "node:process";
|
||||
|
||||
const DOC_PATH = "docs/plugins/plugin-inventory.md";
|
||||
const ROOT = process.cwd();
|
||||
const EXTENSIONS_DIR = path.join(ROOT, "extensions");
|
||||
|
||||
const PROVIDER_DOC_ALIASES = new Map([
|
||||
["amazon-bedrock", "/providers/bedrock"],
|
||||
["amazon-bedrock-mantle", "/providers/bedrock-mantle"],
|
||||
["kimi", "/providers/moonshot"],
|
||||
["perplexity", "/providers/perplexity-provider"],
|
||||
]);
|
||||
const PLUGIN_DOC_ALIASES = new Map([
|
||||
["acpx", "/tools/acp-agents-setup"],
|
||||
["brave", "/tools/brave-search"],
|
||||
["browser", "/tools/browser"],
|
||||
["codex", "/plugins/codex-harness"],
|
||||
["document-extract", "/tools/pdf"],
|
||||
["duckduckgo", "/tools/duckduckgo-search"],
|
||||
["exa", "/tools/exa-search"],
|
||||
["firecrawl", "/tools/firecrawl"],
|
||||
["perplexity", "/tools/perplexity-search"],
|
||||
["tavily", "/tools/tavily"],
|
||||
["tokenjuice", "/tools/tokenjuice"],
|
||||
]);
|
||||
|
||||
function readJson(relativePath) {
|
||||
return JSON.parse(fs.readFileSync(path.join(ROOT, relativePath), "utf8"));
|
||||
}
|
||||
|
||||
function fileExists(relativePath) {
|
||||
return fs.existsSync(path.join(ROOT, relativePath));
|
||||
}
|
||||
|
||||
function collectExcludedPackagedExtensionDirs(rootPackageJson) {
|
||||
const excluded = new Set();
|
||||
for (const entry of rootPackageJson.files ?? []) {
|
||||
if (typeof entry !== "string") {
|
||||
continue;
|
||||
}
|
||||
const match = /^!dist\/extensions\/([^/]+)\/\*\*$/u.exec(entry);
|
||||
if (match?.[1]) {
|
||||
excluded.add(match[1]);
|
||||
}
|
||||
}
|
||||
return excluded;
|
||||
}
|
||||
|
||||
function normalizeDocPath(value) {
|
||||
if (typeof value !== "string" || !value.startsWith("/")) {
|
||||
return null;
|
||||
}
|
||||
return value.replace(/\.mdx?$/u, "");
|
||||
}
|
||||
|
||||
function docLink(label, href) {
|
||||
return `[${label}](${href})`;
|
||||
}
|
||||
|
||||
function pushUnique(values, value) {
|
||||
if (value && !values.includes(value)) {
|
||||
values.push(value);
|
||||
}
|
||||
}
|
||||
|
||||
function resolveDocs({ dirName, manifest, packageJson }) {
|
||||
const links = [];
|
||||
const pluginAlias = PLUGIN_DOC_ALIASES.get(manifest.id) ?? PLUGIN_DOC_ALIASES.get(dirName);
|
||||
if (pluginAlias) {
|
||||
pushUnique(links, docLink(manifest.id ?? dirName, pluginAlias));
|
||||
}
|
||||
|
||||
const channelDoc = normalizeDocPath(packageJson.openclaw?.channel?.docsPath);
|
||||
if (channelDoc) {
|
||||
pushUnique(links, docLink(channelDoc.replace(/^\/channels\//u, ""), channelDoc));
|
||||
}
|
||||
|
||||
for (const channel of manifest.channels ?? []) {
|
||||
if (typeof channel !== "string") {
|
||||
continue;
|
||||
}
|
||||
const relativePath = `docs/channels/${channel}.md`;
|
||||
if (fileExists(relativePath)) {
|
||||
pushUnique(links, docLink(channel, `/channels/${channel}`));
|
||||
}
|
||||
}
|
||||
|
||||
for (const provider of manifest.providers ?? []) {
|
||||
if (typeof provider !== "string") {
|
||||
continue;
|
||||
}
|
||||
const alias = PROVIDER_DOC_ALIASES.get(provider);
|
||||
if (alias) {
|
||||
pushUnique(links, docLink(provider, alias));
|
||||
continue;
|
||||
}
|
||||
const relativePath = `docs/providers/${provider}.md`;
|
||||
if (fileExists(relativePath)) {
|
||||
pushUnique(links, docLink(provider, `/providers/${provider}`));
|
||||
}
|
||||
}
|
||||
|
||||
for (const candidate of [manifest.id, dirName]) {
|
||||
if (typeof candidate !== "string") {
|
||||
continue;
|
||||
}
|
||||
if (fileExists(`docs/channels/${candidate}.md`)) {
|
||||
pushUnique(links, docLink(candidate, `/channels/${candidate}`));
|
||||
}
|
||||
if (fileExists(`docs/providers/${candidate}.md`)) {
|
||||
pushUnique(links, docLink(candidate, `/providers/${candidate}`));
|
||||
}
|
||||
if (fileExists(`docs/plugins/${candidate}.md`)) {
|
||||
pushUnique(links, docLink(candidate, `/plugins/${candidate}`));
|
||||
}
|
||||
}
|
||||
|
||||
return links.length > 0 ? links.join(", ") : "-";
|
||||
}
|
||||
|
||||
function resolveSurface(manifest) {
|
||||
const parts = [];
|
||||
if (Array.isArray(manifest.channels) && manifest.channels.length > 0) {
|
||||
parts.push(`channels: ${manifest.channels.join(", ")}`);
|
||||
}
|
||||
if (Array.isArray(manifest.providers) && manifest.providers.length > 0) {
|
||||
parts.push(`providers: ${manifest.providers.join(", ")}`);
|
||||
}
|
||||
const contracts = Object.keys(manifest.contracts ?? {}).toSorted((left, right) =>
|
||||
left.localeCompare(right),
|
||||
);
|
||||
if (contracts.length > 0) {
|
||||
parts.push(`contracts: ${contracts.join(", ")}`);
|
||||
}
|
||||
if (Array.isArray(manifest.skills) && manifest.skills.length > 0) {
|
||||
parts.push("skills");
|
||||
}
|
||||
if (parts.length === 0) {
|
||||
return "plugin";
|
||||
}
|
||||
return parts.join("; ");
|
||||
}
|
||||
|
||||
function resolveInstall(packageJson, status) {
|
||||
if (status === "source") {
|
||||
return "source checkout only";
|
||||
}
|
||||
if (status === "core") {
|
||||
return "included in OpenClaw";
|
||||
}
|
||||
const install = packageJson.openclaw?.install;
|
||||
const release = packageJson.openclaw?.release;
|
||||
if (release?.publishToClawHub === true && release?.publishToNpm === true) {
|
||||
return install?.npmSpec ? `ClawHub + npm: \`${install.npmSpec}\`` : "ClawHub + npm";
|
||||
}
|
||||
if (release?.publishToClawHub === true) {
|
||||
return install?.npmSpec ? `ClawHub: \`${install.npmSpec}\`` : "ClawHub";
|
||||
}
|
||||
if (release?.publishToNpm === true || typeof install?.npmSpec === "string") {
|
||||
return `npm: \`${install.npmSpec}\``;
|
||||
}
|
||||
return "installable plugin";
|
||||
}
|
||||
|
||||
function resolveStatus({ dirName, packageJson, excludedDirs }) {
|
||||
const release = packageJson.openclaw?.release;
|
||||
const hasInstallSpec = typeof packageJson.openclaw?.install?.npmSpec === "string";
|
||||
const excluded =
|
||||
excludedDirs.has(dirName) || packageJson.openclaw?.bundle?.includeInCore === false;
|
||||
if (!excluded) {
|
||||
return "core";
|
||||
}
|
||||
if (release?.publishToClawHub === true || release?.publishToNpm === true || hasInstallSpec) {
|
||||
return "external";
|
||||
}
|
||||
return "source";
|
||||
}
|
||||
|
||||
function escapeCell(value) {
|
||||
return String(value).replaceAll("\n", " ").replaceAll("|", "\\|");
|
||||
}
|
||||
|
||||
function renderTable(records) {
|
||||
const rows = [
|
||||
["Plugin", "Package", "Surface", "Docs", "Install"],
|
||||
...records.map((record) => [
|
||||
escapeCell(record.id),
|
||||
`\`${escapeCell(record.packageName)}\``,
|
||||
escapeCell(record.surface),
|
||||
escapeCell(record.docs),
|
||||
escapeCell(record.install),
|
||||
]),
|
||||
];
|
||||
const widths = rows[0].map((_, index) => Math.max(...rows.map((row) => row[index].length), 3));
|
||||
const lines = [];
|
||||
lines.push(formatTableRow(rows[0], widths));
|
||||
lines.push(
|
||||
formatTableRow(
|
||||
widths.map((width) => "-".repeat(width)),
|
||||
widths,
|
||||
),
|
||||
);
|
||||
for (const row of rows.slice(1)) {
|
||||
lines.push(formatTableRow(row, widths));
|
||||
}
|
||||
return lines.join("\n");
|
||||
}
|
||||
|
||||
function formatTableRow(row, widths) {
|
||||
return `| ${row.map((cell, index) => cell.padEnd(widths[index])).join(" | ")} |`;
|
||||
}
|
||||
|
||||
function collectPluginRecords() {
|
||||
const rootPackageJson = readJson("package.json");
|
||||
const excludedDirs = collectExcludedPackagedExtensionDirs(rootPackageJson);
|
||||
const records = [];
|
||||
|
||||
for (const dirName of fs
|
||||
.readdirSync(EXTENSIONS_DIR)
|
||||
.toSorted((left, right) => left.localeCompare(right))) {
|
||||
const packagePath = path.join(EXTENSIONS_DIR, dirName, "package.json");
|
||||
const manifestPath = path.join(EXTENSIONS_DIR, dirName, "openclaw.plugin.json");
|
||||
if (!fs.existsSync(packagePath) || !fs.existsSync(manifestPath)) {
|
||||
continue;
|
||||
}
|
||||
const packageJson = JSON.parse(fs.readFileSync(packagePath, "utf8"));
|
||||
const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
|
||||
const id = typeof manifest.id === "string" && manifest.id ? manifest.id : dirName;
|
||||
const status = resolveStatus({ dirName, packageJson, excludedDirs });
|
||||
records.push({
|
||||
docs: resolveDocs({ dirName, manifest, packageJson }),
|
||||
id,
|
||||
install: resolveInstall(packageJson, status),
|
||||
packageName: packageJson.name ?? "-",
|
||||
status,
|
||||
surface: resolveSurface(manifest),
|
||||
});
|
||||
}
|
||||
|
||||
return records.toSorted((left, right) => left.id.localeCompare(right.id));
|
||||
}
|
||||
|
||||
function renderDocument() {
|
||||
const records = collectPluginRecords();
|
||||
const groups = {
|
||||
core: records.filter((record) => record.status === "core"),
|
||||
external: records.filter((record) => record.status === "external"),
|
||||
source: records.filter((record) => record.status === "source"),
|
||||
};
|
||||
|
||||
return `---
|
||||
summary: "Generated inventory of OpenClaw plugins shipped in core, published externally, or kept source-only"
|
||||
read_when:
|
||||
- You are deciding whether a plugin ships in the core npm package or installs separately
|
||||
- You are updating bundled plugin package metadata or release automation
|
||||
- You need the canonical internal vs external plugin list
|
||||
title: "Plugin inventory"
|
||||
---
|
||||
|
||||
# Plugin inventory
|
||||
|
||||
This page is generated from \`extensions/*/package.json\`, \`openclaw.plugin.json\`,
|
||||
and the root npm package \`files\` exclusions. Regenerate it with:
|
||||
|
||||
\`\`\`bash
|
||||
pnpm plugins:inventory:gen
|
||||
\`\`\`
|
||||
|
||||
## Definitions
|
||||
|
||||
- **Core npm package:** built into the \`openclaw\` npm package and available without a separate plugin install.
|
||||
- **Official external package:** OpenClaw-maintained plugin omitted from the core npm package and installed through ClawHub and/or npm.
|
||||
- **Source checkout only:** repo-local plugin omitted from published npm artifacts and not advertised as an installable package.
|
||||
|
||||
Source checkouts are different from npm installs: after \`pnpm install\`, bundled
|
||||
plugins load from \`extensions/<id>\` so local edits and package-local workspace
|
||||
dependencies are available.
|
||||
|
||||
## Core npm package
|
||||
|
||||
${renderTable(groups.core)}
|
||||
|
||||
## Official external packages
|
||||
|
||||
${renderTable(groups.external)}
|
||||
|
||||
## Source checkout only
|
||||
|
||||
${renderTable(groups.source)}
|
||||
`;
|
||||
}
|
||||
|
||||
function main(argv = process.argv.slice(2)) {
|
||||
const write = argv.includes("--write");
|
||||
const check = argv.includes("--check");
|
||||
if (write === check) {
|
||||
console.error("usage: node scripts/generate-plugin-inventory-doc.mjs --write|--check");
|
||||
process.exit(2);
|
||||
}
|
||||
|
||||
const next = renderDocument();
|
||||
const docPath = path.join(ROOT, DOC_PATH);
|
||||
if (write) {
|
||||
fs.writeFileSync(docPath, next, "utf8");
|
||||
return;
|
||||
}
|
||||
|
||||
const current = fs.existsSync(docPath) ? fs.readFileSync(docPath, "utf8") : "";
|
||||
if (current !== next) {
|
||||
console.error(`${DOC_PATH} is stale. Run \`pnpm plugins:inventory:gen\`.`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
Reference in New Issue
Block a user