dsh-provider-mgoole
English | 简体中文
A DeepSeek Harness bundle plugin that adds the 芒果AI (MangoAI) OpenAI-compatible gateway as a model provider — and gives it the native Models-page card (API key field, endpoint / protocol / model list, “获取可用模型”).
Enabling the plugin registers the provider; disabling it removes the provider again.
| Route id | mangoai-official (fixed) |
| Default endpoint | https://mgoole.com/v1 |
| Protocol | openai-responses |
| Credential reference | MGOOLE_API_KEY |
| Settings namespace | llm-pi-ai (the namespace the Models page renders natively) |
Install
dsh plugin add github:sendya/dsh-provider-mgoole
Or from a local checkout:
dsh plugin add link:/path/to/dsh-provider-mgoole
Then enable it in 设置 → 插件 (Settings → Plugins). A provider named 芒果AI appears in 设置 → 模型 with the shipped editor; type your API key there and hit 获取可用模型 to pull the live model list.
The key is written through the credentials service; it never enters this repository or the patch file.
What it actually does
Two moving parts:
cordis.patch.yml insert one row: id: mangoai-provider, name: @sendya/dsh-provider-mgoole
index.js on enable -> settings.mutate('llm-pi-ai', set providers.mangoai-official)
on disable -> settings.mutate('llm-pi-ai', unset providers.mangoai-official)
cordis.patch.yml deliberately carries no config. Everything is written at
runtime through the settings service, which is what makes both requirements possible
at once:
The native card.
@deepseek-ai/dsh-client-ui-settings-modelschooses a provider editor by comparing the settings namespace literally:function layoutOf(ns) { if (ns === "llm-deepseek") return "deepseek"; if (ns === "llm-pi-ai") return "pi-ai"; return "unknown"; // fields render, but submitDisabled = ... || layout === "unknown" }and
@deepseek-ai/dsh-llm-pi-aiderives its namespace fromctx.fiber.entry.options.id. Declaring the provider inside thellm-pi-ainamespace is therefore the only way to get the shipped card — the same trick@deepseek-ai/dsh-llm-deepseek-api-keyuses by owning thellm-deepseekrow.Editable config.
@deepseek-ai/dsh-config-editorrejects a write to a namespace that a higher patch layer also configures:settings/rejected: Configuration for "llm-pi-ai" is overridden by a home patch or command-line overlaySo a bundle that ships
configforllm-pi-aifreezes the card (reads fine, saves fail, user-added models vanish on reload). Writing throughctx.settingsinstead keeps the profile document the single owner: the card stays editable and enable/disable really adds and removes the provider.
The transaction trap
Config edits may not run inside a Loader transaction, and apply() / disposer both
run inside one:
Error: HMR transactions cannot be nested
Deferring with setTimeout does not help — it inherits the same AsyncLocalStorage
context. The plugin therefore escapes the context explicitly before writing:
const als = ctx.get('hmr')?.executing // the AsyncLocalStorage behind the guard
als.exit(() => void settings.mutate(...)) // write on its own turn
Removal on disable additionally needs a listener that outlives the plugin's own
context, so a plugin-manager/changed listener is attached to ctx.root and
unsubscribes itself after it has deleted the entry. settings/document-updated,
connection/request, and a short timer ladder act as fallbacks.
Defaults written on first install
providers.mangoai-official:
displayName: 芒果AI
apiKeyEnv: MGOOLE_API_KEY
api: openai-responses
baseURL: https://mgoole.com/v1
models:
- deepseek-v4-flash
- deepseek-v4-pro
- deepseek-v4.1-flash # contextWindow 1000000, maxTokens 256000, text+image, reasoningEfforts
An existing providers.mangoai-official entry is never overwritten: the plugin only
fills in a missing one, so anything you change in the UI survives restarts, updates
and re-enables.
Files
index.js— the Host plugin (inject: ['settings']). No protocol code, no client half.cordis.patch.yml— one inserted row, no config.icon.svg,locale/*.json— display metadata for the plugin inventory.
Requirements
- DeepSeek Harness
0.2.1-rc.2or newer (needssettings.mutate,llm-pi-aias a configurable namespace, and thellm-pi-ai/deepseeklayouts in the Models page). - Node.js ≥ 20.
Debugging
DSH_MANGOAI_DEBUG=1 dsh web # traces install/uninstall decisions to /tmp/mangoai-plugin.log
Uninstall
Disable the plugin in 设置 → 插件: providers.mangoai-official is removed and the
route disappears. To drop it entirely:
dsh plugin remove @sendya/dsh-provider-mgoole
License
MIT
No comments yet. Be the first to write one.