Skip to content

Add mcode-island plugin: Windows Dynamic Island status pill for MiniMax Code agents - #17

Open
antianqi wants to merge 3 commits into
MiniMax-AI:mainfrom
antianqi:add-mcode-island
Open

Add mcode-island plugin: Windows Dynamic Island status pill for MiniMax Code agents#17
antianqi wants to merge 3 commits into
MiniMax-AI:mainfrom
antianqi:add-mcode-island

Conversation

@antianqi

@antianqi antianqi commented Aug 22, 2026

Copy link
Copy Markdown

mcode-island — Windows Dynamic Island for MiniMax Code agents

A Skill-first Plugin that surfaces the agent's working state in a small WPF pill
anchored to the top center of the primary display, so the user can leave the
terminal in the background and still see exactly what the agent is doing.

idle thinking working waiting done error

The agent's only contract with the widget is: write JSON to
%APPDATA%\mcode-island\status.json (or call the notify-island.ps1 helper
that does that for you). The widget polls that file every 400 ms.

The problem this solves

While the agent runs a long tool call (compile, install, test, refactor), the
user often switches away from the terminal to read code, check docs, or browse
the web. There is no visible progress signal. The agent may also be paused on
a permission prompt, or have failed silently. mcode-island makes all of
that visible at a glance, without forcing the user to switch back.

Copyable example

In the agent loop, wrap every bash call through the bundled wrapper:

& "<plugin install dir>\wrap-tool.ps1" `
    -Tool bash -Command "npm test" -Description "run tests"

State flow this triggers automatically:

  1. working — bash: run tests (pushed before the command runs)
  2. on exit 0: done — bash 完成
  3. on exit 1 (configurable): waiting — bash 等待审批 (exit=1)
  4. on other non-zero: error — bash 失败 (exit=N)

For other tools (read / write / edit), the agent pushes state directly
via notify-island.ps1 before and after each tool call. The Skill body in
skills/mcode-island/SKILL.md documents the exact timing.

Expected result

After each push the widget on the user's primary display updates within
~400 ms (one polling cycle). On click, the originating terminal tab regains
focus. The widget is intentionally hard to kill: Alt+F4 hides it (not
closes), and mcode-island show re-raises the hidden window in under one
second.

Requirements

requirement version / note
Windows 10 1809+ or 11 (uses WPF, user32 / kernel32)
PowerShell 5.1 (ships with Windows 10/11) or PowerShell 7
.NET WPF runtime 4.x (ships with Windows 10/11)
execution policy Bypass for this directory; not changed globally
network access none
accounts none
paid services none

The plugin contains no node_modules, no native binaries, no symlinks, no
installers, no private endpoints, no telemetry.

Network and data behavior

  • The widget never makes a network request.
  • No telemetry, no analytics, no auto-update checks.
  • All state lives under %APPDATA%\mcode-island\:
    status.json, caller.json, config.json, widget.pid, island.log,
    widget.log, show.signal.
  • The only registry write is to HKCU\Software\Microsoft\Windows\CurrentVersion\Run
    for logon auto-start (opt-in, user runs autostart.ps1 -Enable).
  • No data leaves the local machine.

Test evidence

This plugin was exercised on Windows 11 24H2 with PowerShell 5.1 against a
live MiniMax Code session. Concrete observations captured during development:

  • 59 state transitions in island.log over a multi-hour session
    (21 working / 14 done / 11 idle / 6 waiting / 5 thinking / 1 error).
  • All 6 states screenshot-verified (assets/state-*.png).
  • Full state-machine demo wrap-demo.png: thinkingworking
    waitingworkingdone on a real bash npm test run.
  • Click-to-focus round-trip verified: from a Feishu tab, click the pill,
    focus jumps to the originating Windows Terminal tab (HWND consistent).
  • wrap-tool.ps1 exit-code semantics: 0 → done, 1 → waiting (default,
    configurable via -WaitingExitCodes), other → error.

npm run check result

Validator output for the hosted plugin directory:

OK   plugin antianqi/mcode-island

The 8 unrelated FAIL lines in npm run check are pre-existing on
upstream/main (other contributors' hosted plugins missing YAML
frontmatter); this PR does not touch them. The single npm test failure
(hosted-plugins.test.mjs:39) is a Windows-only path-separator mismatch
in the upstream test (plugins\alice\hello-world vs /plugins\/alice\/hello-world/)
and is unrelated to this PR.

Package contents

plugins/antianqi/mcode-island/
├── plugin.json                    # plugin manifest (Agent Plugins 1.0 schema)
├── README.md                      # full user-facing docs
├── LICENSE                        # Apache-2.0
├── mcode-island.ps1               # WPF widget main loop
├── mcode-island.cmd               # CLI shim: start/stop/status/show/pin/...
├── start-island.ps1               # launcher (forces STA + hidden console)
├── stop-island.ps1                # stop the widget
├── status-island.ps1              # print widget PID + recent log
├── show-island.ps1                # re-raise hidden widget
├── pin-island.ps1                 # lock click-to-focus target
├── autostart.ps1                  # register / unregister Windows logon
├── notify-island.ps1              # state-push helper (agents call this)
├── wrap-tool.ps1                  # all-in-one bash wrapper
├── skills/mcode-island/SKILL.md   # Skill consumed by the agent
└── assets/                        # screenshots embedded above

Limitations

  • Windows 10/11 only.
  • One widget per user session.
  • wrap-tool.ps1 only wraps bash; for read / write / edit the agent
    calls notify-island.ps1 directly.
  • No hover-expand, no token usage, no per-tool output yet (planned for v0.2,
    Tauri rewrite).

License

Apache-2.0.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

…ax Code agents

Adds a Skill-first plugin that surfaces the agent working state in a 320x60 WPF pill anchored to the top center of the primary display, so the user can leave the terminal in the background and still watch progress.

States: idle / thinking / working / waiting / done / error.

Includes wrap-tool.ps1, a thin bash wrapper that pushes working / done / error / waiting based on $LASTEXITCODE, so the user does not have to remember to call notify-island.ps1 for every shell command.
Adds a 1-second-polling daemon that reads the active mcode session messages.jsonl and infers the agent state (idle/thinking/working/done/error) without requiring the agent to call notify-island.ps1.

State mapping:

  role=user                  -> idle

  role=assistant + toolCall  -> working "<tool>: <args>"

  role=assistant + thinking  -> thinking

  role=assistant + text      -> idle (just replied)

  role=toolResult + !isError -> done "<tool> 完成"

  role=toolResult + isError  -> error "<tool> 失败"

  mcode 进程不在              -> error "mcode 进程已退出"

  60s 无新事件                -> idle 兑底

Priority logic: agent-pushed states (with Message) are preserved; detector takes over only for settle states (idle / error).

Tested on Windows 11 24H2 + PowerShell 5.1 against a live mcode session. All 6 state transitions verified, including mcode exit and recovery.

@hetaoBackend hetaoBackend left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review result: do not approve / do not merge yet.

The repository check passes (27 tests), but the core Windows detector is not ready:

  • mcode-status-detect.ps1:79-80 hard-codes C:\Users\Administrator\... and scans messages.jsonl, while the repository runtime uses resolved data directories and ledger.jsonl. Ordinary installations therefore report mcode 已退出 instead of detecting state.
  • mcode-status-detect.ps1:117-118,228-243 returns no message when the file mtime is unchanged, so the advertised 60-second idle fallback is unreachable during inactivity.
  • start-island.ps1:15-22, stop-island.ps1, and the detector start/stop scripts trust stale PID files and can refuse startup or Stop-Process -Force an unrelated process after PID reuse. Validate executable/command-line identity before acting.
  • wrap-tool.ps1:47-56 advertises a bash wrapper but executes -Command with Invoke-Expression as PowerShell code, creating an injection/shell-semantics boundary that should be removed or explicitly documented.
  • The quick-start commands are invalid PowerShell: README.md:82-90 uses %PLUGIN_DIR% and -Enable, but autostart.ps1:7-10 only supports -Action Enable.
  • start-island.ps1:40-44 waits for about to ShowDialog, a log message the widget never emits, so readiness is always reported as waiting.

Please fix the detector data-path/session contract, idle logic, PID validation, and launch/docs issues before requesting another review.

Fixes for review comments from hetaoBackend (commit fce7c5f):

  MiniMax-AI#1 detector hard-coded path: resolve the [userprofile]/.minimax-code
     directory at runtime via the mcode node process cmdline (regex on
     @minimax-ai/code/cli.js), with fallbacks to $env:USERPROFILE/.minimax-code,
     $env:APPDATA/minimax-code, and the current working directory.
     Override with -Root [path].

  MiniMax-AI#2 idle fallback unreachable: mtime cache now returns the last inferred
     message instead of null, so the 60s stale -> idle branch fires every
     poll. Verified locally: idle :: already idle 195s after 65s of inactivity.

  #2b session log: prefer ledger.jsonl (mcode v2 event stream) and fall
     back to messages.jsonl when ledger is missing. Both formats are handled
     in Infer-State (kind/phase for ledger, message.role for messages).

  MiniMax-AI#3 PID reuse safety: start/stop-{island,detect-island}.ps1 now verify
     the target PID command line contains the expected script path before
     acting. Stale PIDs and PID-reused processes are refused with a
     REFUSED log line instead of being killed.

  MiniMax-AI#4 wrap-tool.ps1 shell-injection: removed Invoke-Expression entirely.
     The wrapper is now status-only; the agent runs the command via mcode's
     own bash tool and passes -ExitCode to publish the outcome.
     Documented in README + SKILL.md.

  MiniMax-AI#5 README: -Enable -> -Action Enable to match autostart.ps1 parameter set.

  MiniMax-AI#6 start-island.ps1 readiness: dropped the 'about to ShowDialog' log wait
     (which was never emitted). Now polls MainWindowHandle != 0 every 500ms
     for up to 8s.

Tests: validator reports OK plugin antianqi/mcode-island. wrap-tool
6-state matrix verified locally (working / done / waiting / error).
@antianqi

Copy link
Copy Markdown
Author

Thanks for the review. Pushed bad0868 with fixes for all six items. Quick recap:

Code fixes

Local verification

  • node scripts/validate.mjs reports OK plugin antianqi/mcode-island.
  • wrap-tool.ps1 4-state matrix exercised locally: -ExitCode 0 → done, 1 → waiting, 2 → error, omitted → working.
  • detector v0.2.1 settles into idle :: 已静默 195s after 65s with no new events.

Not in this push (out of scope of the review)

  • Detector still polls every 1s. Worker-thread leak (PS 5.1 + pipeline cmdlets) is observed; documenting separately, planning a FileSystemWatcher-based replacement in v0.3.
  • No change to the public Skill surface area (still one Skill, mcode-island).

Ready for another pass.

antianqi added a commit to antianqi/mcode-island that referenced this pull request Aug 22, 2026
This standalone mirror is now in lockstep with the in-flight PR #17
(MiniMax-AI/MiniMax-Code-Plugins#17), commit bad0868.

Changes since v0.1.0:

  + mcode-status-detect.ps1     v0.2 detector daemon
  + start-detect-island.ps1
  + stop-detect-island.ps1
  + status-detect-island.ps1
  M README.md                    detector + wrap-tool new API + -Action Enable
  M mcode-island.cmd             detect-on / detect-off / detect-status subcommands
  M skills/mcode-island/SKILL.md detector + new wrap-tool two-step pattern
  M start-island.ps1             PID + cmdline check; readiness via MainWindowHandle
  M stop-island.ps1              PID + cmdline check (refuse on PID reuse)
  M wrap-tool.ps1                removed Invoke-Expression; status-only; -ExitCode arg

Detector resolves the mcode install root at startup by regexing the mcode
node process command line (matched on @minimax-ai/code/cli.js), with
fallbacks to $env:USERPROFILE/.minimax-code, $env:APPDATA/minimax-code, and
the current working directory.

Validator: OK plugin antianqi/mcode-island (same as PR #17 head).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants