Extension:AIBatchEditor
Release status: stable |
|
|---|---|
| Implementation | specialpage (invalid type), API, artificial intelligence (invalid type) |
| Description | Batch-edit many wiki pages with AI assistance. Preview each change as a diff, approve individually, then save through MediaWiki's normal edit pipeline. |
| Author(s) | Uri Macías (UriMacíastalk) |
| Maintainer(s) | UriMacías |
| Latest version | 1.1.1 (2026-07-06) |
| Compatibility policy | Master maintains backward compatibility. |
| MediaWiki | |
| Database changes | No |
|
|
|
aibatcheditor |
|
|
aibatchedit |
|
| Licence | GNU General Public License 2.0 or later |
| Download | GitHub:
Note: https://github.com/urimacias/AIBatchEditor/blob/main/README.md |
| Help | Help:Extension:AIBatchEditor |
| Example | https://urimacias.github.io/AIBatchEditor/ |
The AIBatchEditor extension provides Special:AIBatchEditor, a Codex-based batch editor for MediaWiki 1.43+. Select many pages at once (by title list, category, or template transclusion), run AI-assisted operations on them, preview each proposed change as a wikitext diff, and save only the edits you approve.
Saved edits go through MediaWiki's normal edit pipeline: they are attributed to the saving user, appear in page history, can be reverted, and are tagged with the aibatcheditor change tag.
User guide: Help:Extension:AIBatchEditor
Features
[edit]- Validate pages from a title list, from category members, or by template transclusion (with optional title-prefix filter).
- Built-in AI operations: wikilinks, spellcheck, formatting, writing style, templates (with remote reference fetch), and custom (instructions-only).
- Three aggressiveness profiles per operation: conservative, balanced, aggressive (configurable via
$wgAIBatchEditorOperationProfiles). - Strict instruction-compliance prompts and low default temperature (
$wgAIBatchEditorTemperature). - Optional batch-wide and per-page AI instructions.
- Temporary prompt preview in the UI and API (
$wgAIBatchEditorPromptPreview). - Server-side batch processing — the browser starts a batch, calls
aibatcheditorbatchadvancefor LLM work, and pollsaibatcheditorbatchstatusfor progress; each advance request processes up to$wgAIBatchEditorConcurrencypages. - Per-page diff preview (lazy-loaded), Preview article (rendered proposed page in a new tab), re-draft, and selective approval before save.
- Retry failed pages without re-running the whole batch.
- Cancel a running batch — stop remaining pages while keeping finished results.
- Proposal warnings for risky AI output (major deletions, near-empty text, large growth, removed headings).
- Draft tokens — HMAC tokens bind each proposed edit to the user, base revision, and proposed text hash; saves reject stale or tampered proposals.
- Diff-reviewed and warning confirmations before bulk approve or save.
- Post-save revision and history links in the results panel.
- Page size limits, per-user hourly rate limits, and structured server-side logging.
- Seven Action API modules for list, preview, batch start/status/cancel, diff, and save workflows.
Requirements
[edit]- MediaWiki >= 1.43.0
- PHP 8.1+ (required by MediaWiki 1.43; OpenSSL extension enabled)
- A Grok-compatible chat-completions HTTP API (xAI Grok by default; other OpenAI-style endpoints may work if configured)
- JavaScript enabled in the browser
- Outbound HTTPS from the wiki server to the LLM endpoint (and to allowed remote wikis for the
templatesoperation) - Users need the
aibatchedituser right (granted tosysopby default)
Compatibility
[edit]The only formal dependency declared in extension.json is MediaWiki >= 1.43.0. The special-page UI uses core Vue (createMwApp) and Codex (CodexModule), which are not available on MediaWiki 1.42 or older. The extension has been tested on MediaWiki 1.43 LTS through 1.45+.
Wikis that can use this extension
[edit]| Environment | Supported? | Notes |
|---|---|---|
| Self-hosted wiki (Docker, VPS, local) | Yes | Administrator installs the extension and configures the LLM |
| Private, personal, or corporate wikis | Yes | Same as above |
| Wiki farms (Miraheze, ShoutWiki, etc.) | Maybe | Only if custom extensions and outbound HTTPS to the LLM are allowed |
| Wikimedia production wikis (Wikipedia, Commons, …) | No | Third-party extension; not part of the WMF deployment |
Operational prerequisites
[edit]$wgAIBatchEditorApiUrlconfigured and API key available server-side (for exampleXAI_API_KEYin$IP/.env, loaded automatically).- Users need the
aibatcheditright (granted tosysopby default). - Users still need normal
editpermission on each page they save. - For
templates: server outbound HTTPS to hosts in$wgAIBatchEditorTemplateSourceAllowHosts.
Page and content limits
[edit]Only pages that meet all of the following are processed:
- Exist and are not redirects
- Main content model is wikitext (not JSON, CSS, or other models)
- User can read and edit the page
- Category batch lists: content namespaces only
- Wikitext size within
$wgAIBatchEditorMaxPageSize(default 2097152 bytes / 2 MiB;0= no limit)
Does not apply to typical non-wikitext system pages, file description pages using other models, or pages the user cannot edit.
Installation
[edit]- Download or clone the extension from GitHub into your wiki's
extensions/directory:
cd extensions/
git clone https://github.com/urimacias/AIBatchEditor.git AIBatchEditor
- Add the following to the bottom of your LocalSettings.php:
wfLoadExtension( 'AIBatchEditor' );
$wgAIBatchEditorApiUrl = 'https://api.x.ai/v1/chat/completions';
// XAI_API_KEY in $IP/.env — loaded automatically; do not commit the key
Sensible defaults are built into the extension (model grok-4.3, 300 s LLM timeout, batch cap 25, 60 requests/hour, concurrency 1). Override only when needed. Wiki-specific LLM policy belongs in $wgAIBatchEditorSystemPromptAppend.
Store the API key in the environment (for example XAI_API_KEY in $IP/.env or Docker .env), not in git.
- Visit Special:Version and confirm AIBatchEditor appears.
- Open Special:AIBatchEditor with a user who has the
aibatcheditright.
Shared hosting / cPanel
[edit]On cPanel or other PHP-FPM hosts without memcached, enable a persistent object cache in LocalSettings.php:
$wgMainCacheType = CACHE_DB; // uses the objectcache table (e.g. mw_objectcache)
Without this, Redactar / Draft fails immediately with API error batch-not-found because batch progress is stored in MediaWiki object cache and the default per-request memory cache is not shared between HTTP workers. See #Troubleshooting.
Configuration
[edit]| Setting | Default | Description |
|---|---|---|
$wgAIBatchEditorApiUrl |
|
LLM chat-completions endpoint URL. Server-side only. |
$wgAIBatchEditorApiKey |
|
Bearer token or API key for the LLM endpoint. Server-side only; never exposed to clients. |
$wgAIBatchEditorModel |
grok-4.3 |
Model identifier sent to the API. |
$wgAIBatchEditorMaxBatch |
25 |
Maximum pages per batch (list, draft, and save). |
$wgAIBatchEditorMaxPageSize |
2097152 |
Maximum wikitext size in bytes per page before AI processing is rejected (2 MiB). 0 disables the limit.
|
$wgAIBatchEditorMaxInstructionsLength |
8192 |
Maximum length in bytes for AI instruction text. |
$wgAIBatchEditorRequestTimeout |
300 |
HTTP timeout in seconds for each LLM request. |
$wgAIBatchEditorTemperature |
0.1 |
LLM sampling temperature (0.0–1.0). Lower values follow instructions more strictly. |
$wgAIBatchEditorPromptPreview |
false |
Debug flag: expose built LLM prompts in the UI and API responses. Enable only for troubleshooting. |
$wgAIBatchEditorRateLimitPerHour |
60 |
Maximum AI completion requests per user per hour. |
$wgAIBatchEditorConcurrency |
1 |
Number of pages the server processes per batch advance request. |
$wgAIBatchEditorPollIntervalMs |
2500 |
Client interval in milliseconds between batchstatus polls.
|
$wgAIBatchEditorDraftTokenSecret |
|
Optional HMAC secret for draft tokens (defaults to $wgSecretKey).
|
$wgAIBatchEditorStubMode |
false |
Use a deterministic AI stub instead of HTTP (for automated browser tests only). |
$wgAIBatchEditorDefaultProfile |
balanced |
Default aggressiveness profile when the client does not specify one. |
$wgAIBatchEditorEnabledOperations |
all six operations enabled | Associative array toggling wikilinks, spellcheck, formatting, style, templates, and custom.
|
$wgAIBatchEditorTemplateSourceWiki |
https://es.wikipedia.org |
Default remote wiki base URL for fetching reference templates (HTTPS only). |
$wgAIBatchEditorTemplateSourceAllowHosts |
es/en.wikipedia.org, mediawiki.org | Allowed hostnames for templatesource overrides.
|
$wgAIBatchEditorOperationProfiles |
see extension.json |
Per-operation profile intensity (UI help text and LLM prompt). |
$wgAIBatchEditorSystemPromptAppend |
[] |
Extra bullet points appended to every LLM system prompt for wiki-wide policy (server-side only). Does not replace built-in safety rules. |
LLM system prompt
[edit]The server builds a structured system message for every AI request (prompt version 4 in PromptFactory):
- ROLE — MediaWiki wikitext editor and wiki content language code
- OUTPUT CONTRACT — full wikitext only; minimal edit; fidelity (no fact/markup drift); no invention; return input unchanged when already satisfied
- TASK — Operation — one-line goal (what kind of edit)
- TASK — Profile — intensity only (how much to change within scope);
$wgAIBatchEditorOperationProfilessupplies UI help and LLM text - SCOPE — what may change per operation (boundaries, not intensity)
- INSTRUCTIONS — optional editor focus text; supplementary to the operation task
- Template references — fetched wikitext when using the
templatesoperation - WIKI-SPECIFIC RULES — optional bullets from
$wgAIBatchEditorSystemPromptAppend
The Custom operation hides the profile dropdown in the UI and always uses balanced intensity.
The user message contains only === INPUT === and the page wikitext.
North star: make the smallest change that completes the task; copy everything else exactly; invent nothing.
Precedence (highest first): operation task + scope → editor instructions (additional focus only) → template references → wiki-specific rules (SystemPromptAppend) → built-in contract defaults in PromptFactory.
Process logs include promptVersion for audit trails.
Wiki-wide append
[edit]Administrators can set $wgAIBatchEditorSystemPromptAppend to an array of strings. Each non-empty string becomes a bullet under WIKI-SPECIFIC RULES. Built-in output contract and scope rules always remain; this setting cannot remove or replace them.
Use $wgAIBatchEditorPromptPreview = true and Preview prompt on Special:AIBatchEditor to inspect the composed prompt while tuning.
$wgAIBatchEditorSystemPromptAppend = [
'This wiki documents family history; never invent names or dates.',
'Prefer [[Plantilla:Persona]] for biography pages.',
];
Example: disable the aggressive style operation and lower the batch cap further:
$wgAIBatchEditorMaxBatch = 15;
$wgAIBatchEditorEnabledOperations = [
'wikilinks' => true,
'spellcheck' => true,
'formatting' => true,
'style' => false,
'templates' => true,
'custom' => true,
];
$wgAIBatchEditorTemperature = 0.1;
// $wgAIBatchEditorPromptPreview = true; // optional: show prompt debug UI while testing
AI capabilities and limits
[edit]The extension is a wikitext batch editor, not a research agent. For each page, the server sends the current wikitext, your instructions, and (for the templates operation) reference template definitions fetched from allowed remote wikis. The model returns revised wikitext only.
The AI can:
- Edit wikitext (links, spelling, structure, tone, template transclusions)
- Follow batch-wide or per-page instructions
- Insert, upgrade, or clone templates when you name references (for example
Plantilla:Fichafrom es.wikipedia.org)
The AI cannot:
- Search the web or call external APIs (weather, news, geocoding, and so on)
- Read other pages on your local wiki as context
- Share context between pages in a batch (each LLM request is isolated)
- Edit non-wikitext content models or process redirects and missing pages
If factual data is required (for example historical weather on a wedding date), provide it in the instructions or in the wikitext. Otherwise the model may invent plausible-sounding but unverified text.
Prompts use a surgical-edit system message (minimal change, fidelity, no invention) and a default low temperature to improve literal instruction following.
Permissions
[edit]| Right | Default groups | Purpose |
|---|---|---|
aibatchedit |
sysop |
Access Special:AIBatchEditor and all aibatcheditor* API modules.
|
Grant the right to trusted editors only. Users still need normal page-edit permission for each page they save.
API modules
[edit]All modules require the aibatchedit right.
| Module | Mode | Purpose |
|---|---|---|
aibatcheditorlist |
read | Validate and list pages for batch editing; returns rate-limit status. |
aibatcheditorpreview |
read | Build LLM prompts for one page without calling the AI or consuming rate limit. |
aibatcheditorbatchstart |
read | Start a server-side batch run; returns batchId.
|
aibatcheditorbatchadvance |
read | Process the next chunk of a batch (LLM work; may be long-running). |
aibatcheditorbatchstatus |
read | Read batch progress from object cache (fast; no LLM calls). |
aibatcheditorbatchcancel |
read | Cancel a running batch; clears pending pages. |
aibatcheditordiff |
read | Render a wikitext diff for preview. |
aibatcheditorarticlepreview |
read | Stage proposed wikitext and return a URL to render it as an article preview. |
aibatcheditorrefreshdrafttokens |
write | Refresh draftToken values before save (CSRF; edits without draftToken).
|
aibatcheditorsave |
write | Save approved proposed edits (CSRF token and draftToken per edit required).
|
The browser UI uses batch start, then batchadvance (sequential LLM work) with batchstatus polling for progress. Each changed page in batch responses includes draftToken and optional warnings.
batchstatus responses are lightweight (progress only; no wikitext bodies). Full page results and draftToken come from batchadvance. aibatcheditorsave recovers stale tokens when the revision still matches; aibatcheditorrefreshdrafttokens re-issues tokens explicitly for API integrations.
Shared list parameters:
titles— pipe- or newline-separated page titlescategory— category name without theCategory:prefixtemplate— template name (with or without theTemplate:prefix or braces); lists pages that transclude it on this wikiprefix— optional title-prefix filter for category or template members
Batch-specific parameters:
operation—wikilinks,spellcheck,formatting,style,templates, orcustomprofile—conservative,balanced, oraggressive(default:balanced)instructions— optional custom directions sent to the LLM (required forcustom)templates— pipe- or newline-separated template names (required fortemplates; max 5 per request)templatesource— optional HTTPS wiki base URL override (must be in$wgAIBatchEditorTemplateSourceAllowHosts)summary— optional edit summary echoed in the API response (used by the UI when saving)
Batch start returns batchId. The UI calls aibatcheditorbatchadvance to process pages (LLM work) and polls aibatcheditorbatchstatus for fast read-only progress.
When $wgAIBatchEditorPromptPreview is enabled, batch status responses include promptSystem and promptUser per page.
Preview-specific parameters (aibatcheditorpreview):
titles— single page title (required)pageinstructions— optional per-page instructions override for preview only
Save parameters:
summary— edit summary applied to each saved page (required)edits— JSON array of objects withtitle,revid,proposedwikitext, anddraftToken
See Special:ApiHelp on your wiki for generated documentation and examples.
Safety and review gates
[edit]| Feature | Behavior |
|---|---|
| Privacy notice | Shown on the special page when the LLM is configured |
| Rate-limit notice | Draft button disabled when the batch exceeds remaining hourly quota |
| Lazy diffs | Diffs load on demand (not automatically) |
| Proposal warnings | Server flags major deletions, near-empty output, large growth, removed headings |
| Diff-reviewed gate | Browser confirms approve/save if diffs were not previewed |
| Draft tokens | Each changed page gets an HMAC token; save rejects stale or tampered proposals |
| Post-save links | Revision and history links after successful save |
| Audit logging | Process/save logs include operation, profile, per-edit hashes and revision IDs |
Logging and change tags
[edit]- Batch actions are logged to the
aibatcheditorMonolog channel (list, process, save). Process logs includepromptVersion(currently3). Configure your wiki logging to retain this channel for audit trails. - Saved revisions are tagged
aibatcheditor("AI Batch Editor").
Security notes
[edit]- LLM requests are made server-side only; wikitext is not sent to the model until a privileged user runs a batch.
- The API key is read from wiki configuration and is never passed to the browser.
- Save requests use MediaWiki's standard CSRF protection.
- Saves require a valid
draftTokenmatching the user, base revision, and proposed text. - Saves check the base revision ID and fail with an edit-conflict error if the page changed meanwhile.
- Per-user hourly rate limiting reduces accidental or abusive LLM usage.
- Remote template fetches use HTTPS only and an administrator-defined host allowlist (SSRF protection).
- Template and page size caps limit prompt injection and oversized LLM payloads.
- Batch state is stored in object cache and tied to the starting user.
Troubleshooting
[edit]Redactar fails with batch-not-found
[edit]Symptom: Clicking Redactar (Draft) fails immediately. The UI may show batch-not-found or an untranslated ⧼batch-not-found⧽.
Cause: Server-side batch runs store progress in MediaWiki object cache (BatchRunService). The browser calls aibatcheditorbatchstart, then polls aibatcheditorbatchstatus about every 2.5 s ($wgAIBatchEditorPollIntervalMs). On cPanel / PHP-FPM without memcached, the default cache is per-request memory — start and status requests often hit different PHP workers, so the batch ID is not found.
Fix: Enable a persistent object cache in LocalSettings.php:
$wgMainCacheType = CACHE_DB; // uses objectcache table; no memcached required
Alternatives: CACHE_MEMCACHED with $wgMemCachedServers, or Redis if available.
Verify: The objectcache table exists (for example mw_objectcache). After enabling CACHE_DB, Redactar should show progress instead of failing instantly.
Batch fails with http or ⧼http⧽
[edit]Symptom: A batch run (especially large ones) stops with an error icon and http, ⧼http⧽, or a message like “The request to the wiki server failed.”
Cause: Each aibatcheditorbatchadvance request processes up to $wgAIBatchEditorConcurrency pages synchronously, and each page can take up to $wgAIBatchEditorRequestTimeout seconds (default 300) for the LLM call. If PHP-FPM, nginx, or the browser times out before that request finishes, the client reports a transport http error. Status polls are read-only and should remain fast.
Fix: Default concurrency is already 1. Raise timeouts only if needed:
# Default is 300 s; raise only if grok-4.x still times out on very large pages:
# $wgAIBatchEditorRequestTimeout = 420;
Also raise PHP max_execution_time and reverse-proxy read timeouts above the LLM timeout.
AI request fails with HTTP 0 on large pages
[edit]If only large pages fail with HTTP 0 (or the timeout message), the LLM call exceeded $wgAIBatchEditorRequestTimeout. For grok-4.3 on full wikitext, use at least 300 seconds (5 minutes). Check aibatcheditor.log for llmError and duration near the limit.
Verify: Single-page Redactar completes without error; a full batch advances steadily when concurrency is 1.
Batch runs forever with status polls but no LLM response
[edit]Symptom: Hundreds of small aibatcheditorbatchstatus requests over many minutes; few aibatcheditorbatchadvance calls; no AI results.
Cause: Only batchadvance invokes the LLM; batchstatus is read-only progress. A fixed client bug (4474d2a) had stopped the advance chain after the first page while polling continued.
Fix: Deploy the latest extension and hard-refresh the special page. Status responses omit wikitext bodies; the client schedules the next advance only after the previous advance finishes.
Save fails with draft-token bad signature
[edit]Symptom: draft-token-bad-signature or Spanish “la firma del token de borrador no es válida” after approve.
Fix: aibatcheditorsave recovers when the base revision is unchanged. Optional: $wgAIBatchEditorDraftTokenSecret = $wgSecretKey;. Enable $wgDebugLogGroups['aibatcheditor'] and look for draftTokenVerifyFailure with recovered: true.
Logging
[edit]Batch actions log to the aibatcheditor Monolog channel (list, process, save, draftTokenVerifyFailure):
$wgDebugLogGroups['aibatcheditor'] = "$wgCacheDirectory/aibatcheditor.log";
Testing
[edit]From the MediaWiki root (with dev dependencies installed via composer install --dev):
chmod +x extensions/AIBatchEditor/tests/run-phpunit.sh
./extensions/AIBatchEditor/tests/run-phpunit.sh
Expected: 127 PHPUnit tests (62 unit + 65 integration).
E2E browser tests (Playwright) require Node.js, a running wiki, and a sysop account:
export MW_E2E_USER=Admin
export MW_E2E_PASSWORD='your-sysop-password'
export AIBATCHEDITOR_E2E_STUB=1
./extensions/AIBatchEditor/tests/run-e2e.sh
Set $wgAIBatchEditorStubMode = getenv( 'AIBATCHEDITOR_E2E_STUB' ) === '1'; in LocalSettings.php when running browser tests.
The repository also includes a manual QA checklist at tests/QA-CHECKLIST.md.
Localization
[edit]English and Spanish message files ship with the extension. Message documentation is in i18n/qqq.json. To add more languages, follow Manual:Translating extensions or request inclusion on translatewiki.net after the extension is hosted in Wikimedia Gerrit.
License
[edit]This extension is licensed under the GNU General Public License (GPL-2.0-or-later). The full license text is in the COPYING file in the GitHub repository.
