Summary
Setting plugins.ai.assistant to false in docmd.config.json does not remove the AI Assistant widget from the built site. The floating trigger still appears on every page.
Environment
@docmd/core: 0.9.3
@docmd/plugin-ai: 0.9.3 (bundled)
- Build engine:
js (default)
- OS: Linux
Reproduction
docmd.config.json:
{
"title": "My Docs",
"src": "docs",
"plugins": {
"ai": {
"assistant": false
}
}
}
npx @docmd/core build
- Open any generated page, e.g.
site/index.html
Expected: no AI Assistant assets or widget on the page.
Actual: the build log even prints [ DONE ] [ai] AI Assistant plugin ready for site., and the generated HTML still contains:
<link rel="stylesheet" href="./assets/css/docmd-ai.css" >
<script src="./assets/js/docmd-ai.js" ></script>
assets/js/docmd-ai.js and assets/css/docmd-ai.css are still emitted, and the widget still renders and self-mounts in the browser.
Root cause
In packages/plugin-ai/src/index.ts (compiled to dist/index.js), two separate hooks handle the AI plugin's output:
-
generateScripts(config, _options) — correctly checks the disable flags and returns empty HTML when disabled:
export function generateScripts(config, _options) {
const pluginOptions = config._aiConfig || (config.plugins && config.plugins.ai) || config.ai || {};
if (pluginOptions.enabled === false || pluginOptions.assistant === false || pluginOptions.chat === false) {
return { headScriptsHtml: '', bodyScriptsHtml: '' };
}
...
}
-
getAssets(_config) — registers the docmd-ai.js / docmd-ai.css assets for injection into every page, but has no such check at all:
export function getAssets(_config) {
const distDir = path.resolve(__dirname, '..', 'dist', 'client');
const jsPath = path.join(distDir, 'index.js');
const cssPath = path.join(distDir, 'ai.css');
const assets = [];
if (nativeFs.existsSync(jsPath)) {
assets.push({ src: jsPath, dest: 'assets/js/docmd-ai.js', type: 'js', location: 'body' });
}
...
return assets;
}
So the <script>/<link> tags are unconditionally injected regardless of config.
-
Even if step 2 were fixed, the client bundle itself (dist/client/index.ts) has a second problem: it self-mounts unconditionally.
var DocmdAIAssistantUI = class {
constructor() {
...
if (typeof document !== "undefined") {
this.mount(); // <-- always runs, no check against cfg.assistant/enabled
}
}
};
document.addEventListener("DOMContentLoaded", () => new DocmdAIAssistantUI());
Since generateScripts (correctly) omits window.__docmd_ai_config when disabled, the constructor reads window.__docmd_ai_config || {} and proceeds to mount the widget with an empty config anyway (rather than treating a missing/disabled config as "do not mount").
Suggested fix
getAssets() should apply the same pluginOptions.enabled === false || pluginOptions.assistant === false || pluginOptions.chat === false check that generateScripts() already uses, and return [] when disabled (note: getAssets receives the plugin's own resolved options object directly as its single argument — not the full site config — per the call site in @docmd/api's hooks.js: hooks.assets.push(async () => (await safeCall('getAssets', name, fn, options)) || [])).
- Defensively,
DocmdAIAssistantUI's constructor should also bail out early (skip this.mount()) when window.__docmd_ai_config is absent or explicitly disabled, instead of assuming an empty config means "enabled with defaults".
Workaround
We patched getAssets() locally with bun patch to add the missing check, mirroring generateScripts(). This fully removes the widget from the build. Happy to open a PR with this fix if useful — just let me know which of @docmd/plugin-ai / docmd-assistant should own the guard.
Verification
After patching, npx @docmd/core build no longer emits docmd-ai.js/docmd-ai.css, and npx @docmd/core validate still passes with no other regressions.
Summary
Setting
plugins.ai.assistanttofalseindocmd.config.jsondoes not remove the AI Assistant widget from the built site. The floating trigger still appears on every page.Environment
@docmd/core: 0.9.3@docmd/plugin-ai: 0.9.3 (bundled)js(default)Reproduction
docmd.config.json:{ "title": "My Docs", "src": "docs", "plugins": { "ai": { "assistant": false } } }npx @docmd/core buildsite/index.htmlExpected: no AI Assistant assets or widget on the page.
Actual: the build log even prints
[ DONE ] [ai] AI Assistant plugin ready for site., and the generated HTML still contains:assets/js/docmd-ai.jsandassets/css/docmd-ai.cssare still emitted, and the widget still renders and self-mounts in the browser.Root cause
In
packages/plugin-ai/src/index.ts(compiled todist/index.js), two separate hooks handle the AI plugin's output:generateScripts(config, _options)— correctly checks the disable flags and returns empty HTML when disabled:getAssets(_config)— registers thedocmd-ai.js/docmd-ai.cssassets for injection into every page, but has no such check at all:So the
<script>/<link>tags are unconditionally injected regardless of config.Even if step 2 were fixed, the client bundle itself (
dist/client/index.ts) has a second problem: it self-mounts unconditionally.Since
generateScripts(correctly) omitswindow.__docmd_ai_configwhen disabled, the constructor readswindow.__docmd_ai_config || {}and proceeds to mount the widget with an empty config anyway (rather than treating a missing/disabled config as "do not mount").Suggested fix
getAssets()should apply the samepluginOptions.enabled === false || pluginOptions.assistant === false || pluginOptions.chat === falsecheck thatgenerateScripts()already uses, and return[]when disabled (note:getAssetsreceives the plugin's own resolved options object directly as its single argument — not the full site config — per the call site in@docmd/api'shooks.js:hooks.assets.push(async () => (await safeCall('getAssets', name, fn, options)) || [])).DocmdAIAssistantUI's constructor should also bail out early (skipthis.mount()) whenwindow.__docmd_ai_configis absent or explicitly disabled, instead of assuming an empty config means "enabled with defaults".Workaround
We patched
getAssets()locally withbun patchto add the missing check, mirroringgenerateScripts(). This fully removes the widget from the build. Happy to open a PR with this fix if useful — just let me know which of@docmd/plugin-ai/docmd-assistantshould own the guard.Verification
After patching,
npx @docmd/core buildno longer emitsdocmd-ai.js/docmd-ai.css, andnpx @docmd/core validatestill passes with no other regressions.