Add Model Manager mini app by ocoomber - #4
Conversation
A MiniApp for browsing, searching, and enabling/disabling models in ~/.minimax/config.yaml directly from MiniMax Code. - Works with any provider (OpenRouter, custom, local endpoints) - Instant save per toggle; bulk enable/disable with one-level undo - Automatic timestamped backups before bulk changes - Atomic, line-based YAML editing preserving indentation and line endings - Restart reminder banner; OpenRouter model page links - English and Simplified Chinese READMEs; MIT licensed
The UI navigates by model family (ID prefix) only. All manageable model blocks in config.yaml are merged into a single family-grouped list; blocks without enabled flags (e.g. the built-in always-on provider) are skipped as before.
|
Thanks for the contribution — this is the first Mini App in the repo that writes to the host config, and the line-based approach that preserves indentation and unknown keys is a sensible choice. Package-level checks all pass: Because this plugin modifies 1. Required before merge (CONTRIBUTING / disclosure)a. README is missing the tested environment. CONTRIBUTING #3 asks each README to state tested client versions and operating systems. The PR description has "Windows 10.0.26200 x64, MiniMax Code Desktop, plugin v1.2.2" — please add that (with the MiniMax Code version) to both READMEs, and note that macOS/Linux are untested if that's the case. b. File access / process disclosure is incomplete. The Privacy section says the app "reads and writes only your
Both are fine, but the repo's model is "users read the README to decide what to install", so please list them. c. Two statements in the PR description have no counterpart in the diff.
d. Hardcoded 2. Please fix or disclose (data safety on
|
…1.2.3) server.mjs: - resolve config.yaml from the runtime dataDir first, ~/.minimax fallback - preserve each line's own terminator (CRLF/LF/CR mixed files stay intact) - atomic write keeps the original file mode; temp file removed on failure - serialize mutations behind a promise queue so overlapping requests cannot clobber each other or the undo snapshot - one-level undo now refuses (stale) if the file changed outside the app since the snapshot - backups moved next to config.yaml (backups/), pruned to newest 20 - 500 responses no longer leak raw error text; configPath removed from /api/providers client (index.html): - Undo enabled only when something actually changed; stale-undo shows a reload hint - group headers are real buttons with aria-controls (no nested interactive elements) - context menu closes on Escape and returns focus to the link - inline SVG icons (no emoji), no infinite pulse animation, warning colors from the visual-baseline tokens repo: - add tests/parser.test.mjs (node --test) covering EOL round-trip, provider discovery, colon ids, enabled flags - README/README.zh-CN: tested environment (Windows 11, MiniMax Code 3.0.73), macOS/Linux untested, process-spawning + temp-file + backups disclosures, corrected secrets wording, plugin-ID note - plugin.json: v1.2.3 + exampleQueries
|
Thanks for the careful review, @MyPrototypeWhat — everything is addressed in db10720 (v1.2.3). Point by point: Required fixes
Data-safety fixes
Suggestions taken
Happy to adjust anything further — thanks again. |
|
Thanks for the fast and thorough turnaround — I went through Confirmed resolved: tested-environment section in both READMEs; process-spawning and temp-file disclosure; PR body no longer claims Two things remain — one required, one your call. A. Required (pick either option): README vs. actual config resolutionThe README now says: "the runtime resolves Why: Reproduction (real Note the path: neither candidate existed, so L31 Either of these is fine with us:
B. Suggestion (your call): backups locationv1.2.3 moved backups from The README discloses this accurately, so it's not blocking. But from the Host side we'd prefer the v1.2.2 location ( Minor (non-blocking)
Once A is settled, this looks good to merge from our side. Thanks again! |
…e whole action (v1.2.4)
server.mjs:
- resolveConfigPath now walks ancestors of context.dataDir looking for config.yaml (matches the current Host layout where context.dataDir is several levels below the data root) and falls back to ~/.minimax/config.yaml; if neither is found it returns the default rather than a missing path
- DATA_DIR captured at startup so backups land under the plugin-owned namespace (context.dataDir/backups), pruned to the newest 20 — matches the 'store durable state under dataDir' runtime guidance and avoids touching anything in the data-root namespace
- /api/bulk now accepts {enabled, providers: [{provider, models}]} so a single bulk request takes one snapshot and one write; Undo reverts the whole action regardless of how many providers it touched
client (index.html):
- bulk() sends one multi-provider request to /api/bulk (instead of one Promise.all per provider); Undo enabled iff any model changed
tests/:
- parser.test.mjs: +1 test covering the multi-provider toggle invariant (ids remain valid across providers in a single write)
- resolveConfigPath.test.mjs (new): 3 tests covering the four-ancestor walk, the default fallback, and a sibling-ancestor config
READMEs (EN + zh):
- config-location: rewrote to describe the parent walk accurately, called out that the walk matches an implementation detail of the current Host layout, and noted the default fallback is what protects non-default installs
- backups: relocated disclosure to dataDir/backups (plugin-owned)
- Undo: noted that multi-provider bulk is reverted as one operation
- Tests/-folder wording: clarified it lives outside the Host's runtime payload roots (miniapp/client, miniapp/node) rather than being excluded from a directory copy
- Tested env: bumped to v1.2.4
plugin.json: 1.2.4
|
Thanks again for the close read — both items addressed in ff05789 (v1.2.4), plus the two minor nits. A. Config resolution (required) — went with option 2 (walk up) so non-default data directories still work.
The walk finds Added B. Backups location (your call) — moved back to Minor items
Ready for re-review whenever you are. Thanks! |
|
Thanks — re-reviewed Confirmed:
Two places where the README doesn't match the build — please fix before merge:
Non-blocking suggestions:
Once (1) and (2) are in, this is good to merge from our side. Thanks for the quick turnarounds. |
…ecks ## What changed Contributors — most of them working with AI coding agents — had no way to learn the Mini App package contract without access to the desktop app. This branch puts the contract in the repository and gates pull requests on it. - `AGENTS.md`: the entry point coding agents load automatically — steps, hard rules, review policy, navigation. - `docs/package-contract.md`, `docs/runtime.md`, `docs/security.md`: layout, the three manifests, portable paths and limits, the Node runtime contract, and the security rules. Each states the MiniMax Code version it was verified against. - `examples/hello-miniapp/`: the smallest valid package, copyable as a starting point. Its README doubles as the template for the two headings the check looks for. - `npm run check`: a zero-dependency validator (`scripts/validate.mjs`) plus its tests (`node --test`, 55 cases). It checks manifest field sets, patterns, enums and limits; portable paths and package size; `node_modules`; the Node entry's `start` export and stdout use; README headings (warning only); and, repository-wide, plugin-ID uniqueness and root README links. Plugin capabilities (Skills, MCP servers, hooks, host bindings, MCP endpoints, Connector access) are validated for shape only; MiniMax Code validates their contents at install time. - `.github/workflows/ci.yml`: runs `npm run check` on every pull request and push to `main`. - `CONTRIBUTING*.md` / `README*.md`: point at the example, the docs, and the check. The MiniApps tables and the two existing community packages are untouched. ## Validation - `npm ci && npm run check` on the branch head: `examples/hello-miniapp` OK; `plugins/amszuidas/mcode-token-usage-board` and `plugins/yanhy2000/mcode-usage-monitor` 0 errors (two README-heading warnings each, by design); `repository` OK; 55/55 tests; CI green. - The package from PR #4 (`openrouter-model-manager`, a package that runs on a real host) validated separately: 0 errors, 1 warning. - Example runtime: `start(context)` → `GET /dashboard` 200 → `dispose()` frees the port; nothing written to stdout. - Example installed into a real MiniMax Code (3.0.73, macOS) and opened through the Agent: page rendered. ## Not covered - No runtime smoke test in CI (a follow-up). - README headings are a warning, not an error, until the existing packages adopt them. - The validator's constants mirror the host's reader by hand; the `Verified against` markers and header comments in the host repository are the sync mechanism.
…l-manager # Conflicts: # README.md # README.zh-CN.md
|
Thanks — both blockers are fixed in 98279e4. The single-model helper is named setModelEnabled again, so POST /api/set now reaches the real implementation. I verified the installed v1.2.4 plugin in MiniMax Code with a per-row toggle, and added tests/api-set.test.mjs to exercise the real HTTP endpoint and confirm config.yaml changes. Both READMEs now document node --test. Result: 11/11 plugin tests pass. I also merged the latest upstream main, kept both new app-table entries while resolving the README overlap, and updated the PR description to match the current test suite. |
New MiniApp: Model Manager (
openrouter-model-manager)A MiniApp for browsing, searching, and enabling/disabling the models in your MiniMax Code
config.yaml— no more find-and-replace in a text editor.What it does
enabled:flags is picked up automatically and merged into one list grouped by model family — there is no provider-switching UI. (The plugin IDopenrouter-model-manageris kept for stability, but the app is not OpenRouter-specific.)backups/under the MiniApp's own data directory (per the runtime's "store durable state under dataDir" guidance), pruned to the newest 20 — nothing in the data-root namespace is touched.enabled:line is rewritten. Each line's own terminator is preserved (mixed CRLF/LF/CR files stay intact), the original file mode is kept, concurrent mutations are serialized, and colon-tolerant keys (llama3.1:latest,:free) are supported.Checklist
plugins/ocoomber/openrouter-model-manager/, including the hidden.minimax-plugin/directory~/.minimax/plugins/openrouter-model-manager/File access, process spawning & network
config.yaml. Resolution walks ancestors of the injected data directory looking for aconfig.yaml(the Host injects a plugin-owned subdirectory several levels below the data root, and the MiniMax Code config lives at the data root or one of its ancestors in the current Host layout), then falls back to the default~/.minimax/config.yaml. The parent walk is an implementation detail of the current Host layout, not a guaranteed API — the default fallback is what protects non-default installs..config.yaml.mm-tmpcreated next to the config, then renamed; the temp file is removed if anything fails.https://openrouter.ai/<vendor>/<model>pages in the user's own browser via the OS opener (rundll32/cmd/exploreron Windows,openon macOS,xdg-openon Linux); anything outside the allowlist is rejected server-side.id/name/enabled/contextLimitto the UI. API key material is never read into the UI, returned by the API, or displayed.Test environment & results
tests/api-set.test.mjs,tests/parser.test.mjs, andtests/resolveConfigPath.test.mjs, 11 tests vianode --test— including a realPOST /api/setrequest that verifies a single-model toggle changesconfig.yaml, plus EOL round-trip, provider discovery, colon-in-id keys, commented lines, enabled-state extraction, multi-provider toggle invariants, and config-path resolution.