Configuration Assistant Plugin
The Configuration Assistant gives administrators a chat that edits this Codumentor instance's own configuration in plain language — "add this repo", "switch the main model to the fast slot", "enable the redmine plugin and tell me what secret it needs", "why are webhooks failing?" — instead of hand-editing YAML against the configuration reference.
It runs against the running instance (this server). A Configuration Assistant launcher on the Admin page opens a normal chat that only admins can create. Ordinary conversations are unchanged.
The safety flow
One typical turn:
- Ground — read the current config, the live schema (keys, types, defaults, and what a change costs to apply), and the matching docs section.
- Propose — build a candidate change, validate it against the real loader, and show a YAML diff plus when it takes effect: immediately, or only after a server restart. An invalid change is reported with the error and never offered for apply.
- Approve — once you have asked for a change, the assistant proposes and applies it in one go; the approval dialog (showing the diff and when it takes effect) is your single confirmation before anything is written. It asks in chat first only when you asked a question rather than for a change, or when the proposal needs a decision from you (warnings, a shared base file, an ambiguous request).
- Apply — a timestamped backup is written next to the file being changed, that file is updated, then the running server reloads it. The assistant tells you whether the change is now in effect or waits for a server restart.
- Rollback — undo the last apply: restore the most recent backup and reload.
What the assistant can do
These are the tools you will see in the chat. Read tools never ask for approval; apply and rollback do.
| Tool | Approval | Purpose |
|---|---|---|
config_schema | none (read) | Keys, types, defaults, and whether a section applies live, rebuilds, or needs a restart. Also a plugin's args schema — including a plugin that is documented but not installed yet. |
config_read | none (read) | The running config (env-substituted; secret values redacted). This is the merged result, bundled flavor default included. |
config_layers | none (read) | Which file sets what: every file the instance loaded, in merge order (bundled default, extends: bases, overlays), how the assistant reaches each one it can write (edit_with; shared_base marks an extends: base), which files set a given key and which value wins, and one file's own keys (secrets redacted). |
plugin_config | none (read) | Installed plugins, documented plugins not yet installed, and how to add one. Any section of a plugin's catalog page (topic=), or all of it. |
config_docs | none (read) | Sections of the configuration reference on demand. document='release-notes' lists released versions; add version='0.5.0' and locale='en' or 'hu' to read one (optionally topic= for a section). Drafts are excluded. These are user-facing release notes, not the operator migration page. Per-plugin docs are in the catalog, via plugin_config. |
read_logs | none (read) | Tail / search the configured log file to diagnose problems. |
config_propose | none (read) | Validate a patch against the chosen file (target) and return the exact YAML diff (secrets masked), plus warnings and notes. Writes nothing. |
config_apply | you approve first | Re-validate, back up, write the target file, then hot-reload. |
config_rollback | you approve first | Undo the last apply, whichever file it wrote (default leaf, an overlay, or an extends: base): restore that file's newest timestamped backup and reload. The approval names the file and the backup. |
read_content | none (read) | Page through a result that was too large to return in one piece. |
The catalog it can see is the one this build contains. An executable is built
as one edition, and a plugin outside it is not "not installed yet" but absent, so
the assistant does not list it, does not offer its configuration, and says so
plainly if you ask for it by name — rather than proposing a config the plugin
loader would refuse. codumentor build-info is the same answer from the CLI.
Configuration
plugins:
- module: codumentor.plugins.configuration_assistant
class: ConfigurationAssistantPlugin
args:
enabled: true
| Parameter | Type | Default | Description |
|---|---|---|---|
enabled | bool | true | Master on/off. When false, the Admin-page launcher is hidden. |
No other settings. config_propose / config_apply take a target naming the file to edit (the two overlays are listed as overlay_targets on config_schema with no section; every writable file as edit_with in config_layers):
target=user—$CODUMENTOR_HOME/config.yaml(models, API keys, auth, personal plugins)target=project— the discovered or--configYAML (repos, project plugins)target=<path>(or the file'sconfig_layersindex) — any other file this instance was loaded from, such as anextends:base. Only loaded files qualify, never an arbitrary path, and never the bundled flavor default (override it in any other file instead).
Omit target to edit the default leaf. A discovered project YAML still cannot set model endpoints or auth; those stay in the user overlay.
Editing lists
A patch merges into the target file. Mappings merge key by key, and a list of named entries merges by entry. An entry is named by its name, or by a plugin's module + class. A patch entry deep-merges onto the file's matching entry, and lists inside it merge the same way. An entry the file lacks is appended, and entries the patch leaves out stay as they are. So adding a plugin to plugins_overrides is a patch holding just that entry:
plugins_overrides:
- module: codumentor.plugins.thinking_modes
class: ThinkingModesPlugin
args: {enabled: true}
A list of plain values (strings) replaces the file's list. A list mixing named entries with unnamed ones is refused.
remove_paths deletes keys and entries. A list entry is named in brackets, by name, by module (optionally module:Class), or by position:
plugins_overrides[codumentor.plugins.svn]auth.ldap_directories[corp].bind_passwordrepos[2]
Removals run before the patch. So putting a list in remove_paths and sending it in the patch replaces the list, which is how to reorder one. Comments on untouched entries survive, and a removed entry's following comment moves to the entry it introduced.
Secrets
The assistant never sees a secret value. Every read, the proposal diff, the approval request and any validation error show it as redacted. A ${ENV_VAR} / ${secret:name} placeholder is shown as written, because it names the source and is not the secret itself.
The assistant sends only the entries it changes (see above), so it rarely restates a secret. If it does, a redacted in a patch means keep the current value:
- The value the edited file has there is kept as written. A literal stays that literal, and a placeholder stays a placeholder.
- If the file does not set it and the key merges onto a lower file (a mapping key, or a key inside a
*_overridesentry), the key is left out, so that file keeps supplying it. - In a list that replaces the lower files' lists, the value is copied the way another loaded file writes it.
- If no file has a value there, the edit is refused. Give the value as a placeholder instead.
A secret the edit changes shows in the diff as redacted (changed).
Only users with the admin:* permission can open a configuration-assistant chat.
What a change costs
Shown up front before you approve:
- 🟢 takes effect immediately — either read fresh on each use (for example
tools,ui,branding) or reloaded automatically, with open conversations picking it up from their next message (for examplemodels,agent,prompt,logging,repos). - 🔴 takes effect after a restart — written to the file but the running server keeps the old behaviour until the Codumentor server is restarted (for example
api,auth,vector_db,cache,ingestion, and any plugin change — adding, removing, or changing a plugin'sargs— because plugins are loaded once per process).
The assistant cannot restart the server itself; it tells you when one is needed.
Notes & limitations
- Comments and formatting outside the changed keys are kept on write. Every write is still preceded by a timestamped
<config>.bak.<UTC>next to the file it writes;config_rollbackrestores the newest one, whichever file that is. The proposed diff is the semantic change, not comment churn. - Secrets are not written. If a change needs a per-user /
${secret:…}secret, the assistant points you at Settings → User Secrets; it does not set secrets itself. - Edits target the leaf file unless you name another. If that leaf uses
plugins_overrides, plugin changes should be proposed that way rather than replacing the wholepluginslist. - An
extends:base can be shared. Other instance configs may extend the same base and pick up an edit on their next reload; only this instance is validated, and the proposal says so in a warning. For a change meant for this instance alone, the assistant edits this instance's own file, where it wins over the base. A base candidate is validated inside this instance's full stack, as the files above it inherit it. - A later file still wins. If a file later in the merge still sets a key you edit, the proposal warns and names that file: the edit will not change the running value until that file stops setting it. An
*_overrideskey elsewhere that adjusts it is flagged too. A diff that changes the text but no running section says so too. A file that is not writable is flagged at propose time and refused byconfig_apply. - Old key spellings are renamed on every edit. Before a patch is merged, the edited file's pre-rename keys (
scheduler:→tasks:,max_schedules_per_user→max_tasks_per_user,edition:→flavor:, …) are rewritten to the current spelling in place, comments and position kept, meaning unchanged. The proposal lists them undernotes, andconfig_applyreports them asrenamed.