Aquesta és una versió anterior. La versió actual és la 4.10.0. wmux 4.10.0 · Data de publicació:
Fitxers d’instal·lació 3.38.0
| Arquitectura | Tipus | Àmbit | Mida del fitxer | Baixa | SHA256 |
|---|---|---|---|---|---|
| 64 bits | EXE | Usuari actual | — | github.com | VirusTotal |
L’enllaç i l’SHA256 provenen del manifest comunitari del Gestor de paquets del Windows. Convé comparar el hash del fitxer baixat abans d’executar-lo.
Notes de la versió
Added
- Every production dependency's license is now checked before it can ship, and an undetermined verdict fails. wmux distributes signed, notarized binaries, so a GPL/AGPL dependency reaching that bundle creates a source-disclosure obligation that cannot be undone after a release — and nothing was checking. The new gate is deny-by-default: a package passes only if its license is on an explicit permissive allow list. Anything else fails, including the cases automated tooling reports as "no license found" — NOASSERTION, other, UNKNOWN, empty, or npm's SEE LICENSE IN <file>. That is the whole point: automated detection returns "other" for projects whose LICENSE file, when a person opens it, is the GNU General Public License, so a checker that treats "could not determine" as "nothing found" waves exactly that case through green. A third check reads the LICENSE text each package actually ships and rejects a copyleft body no matter what the manifest declares, because the manifest is what lies in that failure mode. Exceptions live in license-allowlist.json, pinned to an exact name, version, and declared license, each with a written reason recording what a human read — a version bump retires the exception and requires a fresh reading. Runs with npm test; node scripts/check-licenses.mjs reports on demand.
- THIRD_PARTY_NOTICES is now guarded against drift. It listed 110 packages while 128 were actually shipping and had not been regenerated in two months, attributing @modelcontextprotocol/sdk at a version no longer installed. The generator gained a --check mode that the test suite runs, so the file can no longer fall behind package-lock.json unnoticed — the same arrangement that already keeps docs/api/reference.md honest.
- An agent can now start a fan-out, not just a human. Fan-out — one prompt split into N isolated tasks, each with its own git worktree, branch, workspace, agent pane and private mission channel — existed only behind the in-app dialog, so the MCP surface wmux exposes to other agents could not reach its flagship journey. The new fanout_start tool does, and channel_mission_list reports back what each task became: status, branch, worktree path, and the workspace it runs in.
What a caller may ask for is deliberately narrower than what the dialog accepts, because the dialog's fields were typed by a human and a tool call's are not. The repository is not a parameter: it is the git top level of the calling terminal's own directory — the pane the request came from, not the workspace it sits in, so a pane next to the caller cannot choose the repository on its behalf — and naming one is rejected rather than quietly ignored. The same directory is derived a second time once the user approves, and the fan-out is refused if it has moved, so the repository named on the prompt is the repository that gets modified. The agent command is likewise not a parameter, because it is interpolated into a shell line. Which workspace owns the tasks — and the caller's name inside the resulting mission channels — is resolved from the caller's verified terminal, and stating one is refused, not overruled in silence. Task count and prompt and title sizes are capped where the request arrives, not only deeper in. And like the existing background-execution path, fan-out is refused outright to anything that did not arrive over the local machine's own socket.
Spawning takes far longer than a single call can wait for, so fanout_start answers as soon as it has accepted the work and you follow it by calling again with the same idempotency key: it reports waiting-for-approval, then running, then the full per-task result. A repeated key never starts a second fan-out — including after a failure, and including long after the result itself has aged out of memory, since a key that has already spawned is remembered as having spawned rather than forgotten wholesale.
Every fan-out started this way asks the user first, and that prompt is not covered by the existing auto-approve setting for background execution: agreeing that an agent may spawn a background agent is not agreeing that it may create N worktrees and branches in your repository. The prompt shows what each task will actually be told — the shared prompt and that task's own instructions, per task, with the byte count of anything too long to display — because an approval given to a summary of instructions is not consent to the instructions. If nobody answers the prompt, the fan-out is refused — and says so, with the reason, the next time the caller checks, rather than going quiet on an unattended machine. The in-app dialog is unchanged and still needs no prompt, since clicking it is the approval.
- An agent can now @-mention a specific pane over MCP, and that mention actually reaches the agent sitting in it. channel_post mentions accepted a workspace and a member id but had no way to say which pane — and pane-pinning is what the delivery path keys on, so an instruction posted to a channel by one agent for another could never be delivered automatically. It raised an unread badge and waited to be polled, which an agent that had just finished its work was not doing. Nothing errored on either side: the sender read the silence as "still working". Mentions now take an optional pane_id (from a2a_discover / pane_list), and a pinned mention is pasted into that pane at its next idle moment, exactly as the human composer's mentions already were. The pane must belong to the mentioned workspace — the daemon proves it against the principal registry, refuses a pin it cannot prove, and reports the refusal in droppedMentions as pane_not_in_workspace rather than dropping it quietly; the mention itself still lands as a badge. A pin naming a pane whose agent has since exited is refused the same way, as pane_not_live: an unrefused dead pin does not fail, it falls back to a workspace-level mention, and that fallback pastes into whichever agent the workspace still has — so an instruction addressed to a worker that left would have started a different worker's turn with nothing said to the sender. Unpinned mentions are unchanged and stay badge-only, which is the rule that keeps a message meant for a human out of an agent's prompt.
- The delegation contract is now written down where both sides read it. channel_post, send_message, and a2a_task_send state in their tool descriptions that a channel post is a notification and does not start an idle agent's turn, and which call does. Agents spawned by fan-out get the same paragraph appended to their opening prompt, so a worker knows before it goes idle that nothing will wake it for a workspace-level channel post. docs/how-to/delegate-to-agents.md is the long form.
- Channels can now be thrown away, and taken back out. Archiving a channel only made it read-only — the row kept its slot in the sidebar with no way to remove it or fold it out of sight, so a day of fan-out left the channel list unusable and the next day doubled it. There is now a trash: a channel you move there leaves every visible list and drops into a Trash group that is collapsed by default, so eight leftovers cost one line instead of eight. Restoring puts it back in the Archived group. The trash is a stop, not a shortcut — permanent deletion is refused on any channel that is not already in it, so nothing is destroyed without a separate, reversible step in front of it. Trashing, restoring and deleting are all reachable only from the app itself, never from an agent, for the same reason archiving and kicking already were. Trashing a channel that is still live takes two clicks — the first arms the button — because that same step also archives it, and archiving is one-way.
- The trash empties itself after 30 days, and nothing else does. config.json gains a channels section with two settings. trashTtlHours (30 days) is how long a channel waits in the trash before it is deleted for good; it is safe to have on because nothing reaches the trash except your own explicit action, so the sweep only ever finishes a deletion you started. autoTrashArchivedHours moves archived channels to the trash on their own after a given age, and is off — it is the only setting that would discard records nobody chose to discard. Turning it on is still recoverable: it only moves channels to the trash, so the full 30-day undo window applies before anything is destroyed. Set either to 0 to disable it. Both sweeps run at startup and hourly, so a daemon that stays up for weeks still tidies up. The sweep never deletes a channel an open mission still links to, and a channel in the trash is exempt from the older empty-channel reaper, so the full undo window is real rather than nominal.
- The sidebar footer has a Channels button. Channels were reachable only through the Agent button, which opens the deck on whatever tab it was last on, or through Settings for anyone whose Channels tab was still switched off — so the one surface that shows what the agents are saying to each other had no direct entry point. The footer cluster is now Agent / Git / Channels / web, with Channels opening the deck on its own tab and closing it again on a second press, amber with a count while anything is unread. The Channels tab defaults to off, so pressing the button switches it on rather than opening an empty tab; the Settings toggle still turns it back off. (#684)
Changed