| name | wagoui-libaddonprofiles-integration |
| description | Create or update WagoUI LibAddonProfiles integrations for locally installed World of Warcraft addons. Use when asked to add a new `WagoUI_Libraries/LibAddonProfiles/modules/*.lua` integration, wire it into `load.xml`, inspect a locally installed addon's `.toc` and source, verify the modern WagoUI API from `ImplementationGuide.lua`, or report missing required API functions instead of hallucinating them. |
WagoUI LibAddonProfiles Integration
Follow this workflow for modern LibAddonProfiles integrations in the WagoUI repository.
Start Here
Read AGENTS.md and AGENTS.local.md if it exists before making changes. Apply those repo rules together with this skill.
Approved Reference Set
Use only these implementation references when deciding how the integration should look:
WagoUI_Libraries/LibAddonProfiles/ImplementationGuide.lua
WagoUI_Libraries/LibAddonProfiles/modules/BuffReminders.lua
WagoUI_Libraries/LibAddonProfiles/modules/Ayije_CDM.lua
- The installed source of the target addon
- The installed source of
BuffReminders and Ayije_CDM if you need to see how their addon-side APIs are implemented
WagoUI_Libraries/LibAddonProfiles/load.xml
- For ignored comparison keys only:
WagoUI_Libraries/LibAddonProfiles/modules/Details.lua and WagoUI_Libraries/LibAddonProfiles/modules/Plater.lua
Do not study older LibAddonProfiles modules as design references. Ignore pre-guide integrations.
Use Details.lua and Plater.lua only to copy the private:DeepCompareAsync(..., ignoredKeys) pattern for volatile ignored keys. Do not copy their addon-specific logic.
Discover The Local AddOns Folder
Find the WoW addon root before inspecting the target addon.
- Check
E:\World of Warcraft\_retail_\Interface\AddOns first.
- Check
C:\Program Files (x86)\World of Warcraft\_retail_\Interface\AddOns next.
- If neither exists, search filesystem drives for
_retail_\Interface\AddOns and use the first real WoW install that contains the target addon.
Use short shell probes such as:
Test-Path 'E:\World of Warcraft\_retail_\Interface\AddOns'
Test-Path 'C:\Program Files (x86)\World of Warcraft\_retail_\Interface\AddOns'
Get-PSDrive -PSProvider FileSystem | ForEach-Object {
$candidate = Join-Path $_.Root 'World of Warcraft\_retail_\Interface\AddOns'
if (Test-Path $candidate) { $candidate }
}
Inspect The Target Addon
Start from the target addon's .toc file. Treat the .toc as the authoritative map for folder names, metadata, and load order.
From the .toc, collect:
- The main addon folder and
.toc filename
## Version
## IconTexture
## X-Wago-ID if present
- Saved variable names
- Candidate config or import/export files from the listed load order
Then search the installed addon source for the exact WagoUI guide functions:
rg -n "ExportProfile|ImportProfile|DecodeProfileString|SetProfile|GetProfileKeys|GetCurrentProfileKey|OpenConfig|CloseConfig" "<addon path>"
Locate the real addon API table or global and verify where each required function is implemented.
Required API Contract
Verify the installed addon implements these guide functions from ImplementationGuide.lua:
ExportProfile(profileKey)
ImportProfile(profileString, profileKey)
DecodeProfileString(profileString)
SetProfile(profileKey)
GetProfileKeys()
GetCurrentProfileKey()
OpenConfig()
CloseConfig()
Do not invent missing globals, tables, or methods.
Do not copy older addon-specific logic from unrelated LibAddonProfiles modules.
Build The Module
Create WagoUI_Libraries/LibAddonProfiles/modules/<AddonName>.lua in the same style and field order as BuffReminders.lua and Ayije_CDM.lua.
Use these rules:
- Prefer the addon folder name for
moduleName unless the .toc or existing repo naming makes a different exact name clearly better.
- Set
wagoId from ## X-Wago-ID when present. Find the id online on wago addons if not present.
- Set
oldestSupported to the currently installed addon version unless the user or repo gives hard evidence for an older supported minimum.
- Set
addonNames to the real required addon folders, usually only the main addon.
- Set
icon with C_AddOns.GetAddOnMetadata("<MainAddon>", "IconTexture").
- Set
slash from a proven slash command if you can find one quickly in the addon source. If not, use "?".
- Set profile and reload flags from actual addon behavior. Do not guess.
- Keep
testImport empty unless the target addon genuinely needs custom import validation.
For profile comparison:
- Before finalizing
areProfileStringsEqual, scan the target addon's decoded export payload shape and installed source for volatile, non-semantic keys that can legitimately differ between equivalent profiles.
- Good ignored-key candidates are timestamps, session ids, runtime caches, one-time migration flags, tutorial/dismissal flags, capture/setup sentinels, generated counters, and local environment state.
- Do not ignore real user settings, profile choices, layout data, enabled/disabled states, assignments, selected profile names, colors, fonts, or values that import/export should preserve.
- Only pass an ignored-key table to
private:DeepCompareAsync when you can point to source or saved-variable evidence that the key is non-semantic.
- Keep ignored keys specific to the target addon and explain notable additions in the final summary.
For addon API calls:
- Always call external addon functions inside
xpcall(function() ... end, geterrorhandler()).
- Do not add separate global existence checks or function existence checks around the addon API table or its methods.
- For getters, declare a local variable before
xpcall, assign inside xpcall, and return it afterward.
- For
getProfileKeys, default to {} if the addon API returns nil.
- For
isLoaded, usually only check C_AddOns.IsAddOnLoaded("<MainAddon>"), but save the result in a local loaded variable and return that variable to match the current house style.
- For
setProfile, reject missing keys and unknown keys before calling the addon API.
- For
exportProfile, reject missing or non-string keys and ensure the key exists before exporting.
- For
areProfileStringsEqual, decode both strings through the addon API and compare them with private:DeepCompareAsync.
Use this wrapper pattern:
openConfig = function(self)
xpcall(function()
TargetAddonAPI:OpenConfig()
end, geterrorhandler())
end,
getProfileKeys = function(self)
local profileKeys = {}
xpcall(function()
profileKeys = TargetAddonAPI:GetProfileKeys() or {}
end, geterrorhandler())
return profileKeys
end,
isLoaded = function(self)
local loaded = C_AddOns.IsAddOnLoaded("TargetAddon")
return loaded
end,
Handle Missing API Functions
If the installed addon does not implement one or more required guide functions:
- Tell the user exactly which functions are missing.
- Annotate the generated module with comments at the affected wrappers.
- Do not hallucinate calls to missing addon APIs.
- Keep the module loadable by using safe no-op behavior or safe default returns for the missing wrapper.
Use comment text like:
getProfileKeys = function(self)
return {}
end,
Use empty no-op wrappers for missing mutating or config functions:
openConfig = function(self)
end,
Only use the comment fallback when you have already verified from the installed addon source that the function is missing.
Wire The Module In
Add the new script entry to WagoUI_Libraries/LibAddonProfiles/load.xml so the module loads before finalize.lua.
Keep the new entry near the other recent module entries unless the surrounding ordering gives a better obvious fit.
Also add the module name to the defaultSortOrder list in WagoUI_Creator/modules/generic.lua so the creator UI can place the addon correctly in the generic module list.
Update Lua Diagnostics Globals
Add the target addon's verified public API global to .luarc.json under diagnostics.globals so Lua diagnostics recognize the wrapper calls.
Use the exact global table from the installed addon source, such as EXBossWagoAPI, BuffRemindersAPI, or Ayije_CDM_API. Do not add guessed aliases or internal locals.
Preserve the existing .luarc.json shape and append only when the global is missing.
Validate Before Finishing
Confirm all of the following:
- The new module only uses the modern guide functions or clearly annotated missing-function fallbacks.
- Every real addon API call is wrapped in
xpcall.
- No invented addon globals or methods appear in the module.
load.xml includes the new module.
WagoUI_Creator/modules/generic.lua includes the module name in defaultSortOrder.
.luarc.json includes the verified addon API global used by the module.
- The module fields come from real addon metadata or real source findings.
Concrete Good Examples
Use these files as the primary examples for future runs:
- Repo module:
WagoUI_Libraries/LibAddonProfiles/modules/BuffReminders.lua
- Repo module:
WagoUI_Libraries/LibAddonProfiles/modules/Ayije_CDM.lua
- Installed addon API:
BuffReminders\Display\ImportExport.lua
- Installed addon API:
Ayije_CDM\Config\WagoUI.lua
- Installed addon API example with full guide coverage:
NaowhQOL\Data\SettingsIO.lua