mu-agent 0.2.6 → 0.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +35 -0
- package/README.md +1 -0
- package/dist/bundle/chunks/{chunk-C4L65EFW.js → chunk-SJA6GZQX.js} +2 -2
- package/dist/bundle/chunks/{chunk-VPSGIO2O.js → chunk-Y4V36NDW.js} +1 -1
- package/dist/bundle/chunks/{virtual-modules-4BSUQTRT.js → virtual-modules-P3ZGSM7W.js} +1 -1
- package/dist/bundle/cli-runtime.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/judge/dist/auth.js +1 -0
- package/judge/dist/mude.js +3 -0
- package/judge/dist/setup.js +121 -24
- package/judge/manifest.json +132 -13
- package/judge/mu/{chunk-JK2OO2CN.js → chunk-GELL4P7W.js} +1 -1
- package/judge/mu/{cloud-code-K5ONKXO7.js → cloud-code-CM6I6AXS.js} +1 -1
- package/judge/mu/index.js +1910 -960
- package/kyrn/bin/kyrn-doctor +17 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,41 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.2.8] - 2026-10-24
|
|
6
|
+
|
|
7
|
+
**0.2.8 is plain-language board v2: a teammate's update (`headline`, `blocked`, `next`, `agents`), subagent outcomes as they happen, a stall clock, the writer in the person's language, and two races fixed.**
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- Plain-language board v2 (`kyrn/docs/features/plain-language-board.md`; contract with the desktop app in §4, codes in `presentation-codes.md`). The writer's prompt now asks for a teammate's spoken update, in this JSON: `headline`, `now`, `blocked`, `next`, `progress`, `agents: [{who, doing}]`, `confirm`, `note`. Its first sentence, "You are the voice of a coding session's status board.", is the new routing marker for tests and the desktop's e2e fake model. Only the example in the board's language is included. The request starts with `FACTS`: the task (clipped to 600 characters), the frame's `currentSubgoal`, the checklist, the stage, the run's and the previous board's age, the permission being waited for, the previous board, what is in flight (the main agent's call and how long since its last output, background jobs, the judge's permission review, the goal check), each subagent on its own line (elapsed time, silence, failed steps, retry, the report's first line, the error), the news (a failed step carries the first error-like lines of its output, redacted with `redactSecrets`), the frame's open questions, the account and the latest steps.
|
|
12
|
+
- The reply parser still reads the four-field reply (its headline is then the first sentence of `now`). It caps the headline at 14 words or 24 CJK characters and every other field at 2 sentences, strips filler in Chinese and English, and keeps `agents` only for names the request listed. A board whose headline equals the one shown, with no news, no note and no pending permission, is not published. Mid-run replies are capped at 600 tokens (`runtime.llm` takes `maxTokens`).
|
|
13
|
+
- `board.update` gains `headline` (with `headlineCode` and `headlineParams` on rules headlines: `now_<phase>`, `still_running`, `helpers_working`, `waiting_permission`), `blocked` (with `blockedCode` and `blockedParams` when filled by rules), `next`, `agents` (built by rules from `activeRuns()`: `who`, `role`, `state`, `doing`, `sinceMs`; the writer's `doing` replaces the rules' summary only for an exact name) and `updatedAt`. `phase` gains `blocked`. `board.note` gains `who`, and the codes `helper_done`, `helper_failed` and `still_running`; `helpers_back` gains `failed`.
|
|
14
|
+
- `board.read` v5: the phase `blocked` ("Waiting on something other than the user"), an `in_flight` state key, failure excerpts in `steps` and `events`, and subagents back, failed or stuck in the `changed` question. Without a judge, a stall reads as `blocked`.
|
|
15
|
+
- A subagent's end is an event and an account line as it happens: the board diffs bee statuses from the swarm tool's streamed snapshots, a one-second tick over the live runs, and the call's final snapshot. `helpers_back` counts the subagents that did not end `done`.
|
|
16
|
+
- Stall clock: while a run is on, an unref'd interval (every `stallMs`/4, 1 to 15 s) finds a main-agent call running, or a subagent's call silent, for 1, 3 and 10 times `stallMs` (default 60000; 0 turns it off). Each crossing replaces one `still_running` line in place (same `sequence` and `at`) and schedules one look. A call waiting for permission doesn't count.
|
|
17
|
+
- When a look decides to update and the stage changed, something is stuck or a permission is pending, a rules headline is presented (not stored) before the writer's board replaces it.
|
|
18
|
+
- The writer writes in the language the person writes in (`writingLanguage` in `src/language.ts`, from their last 1 to 3 messages: kana, Hangul, Han; Latin letters are the app's language only when it is a Latin-script one other than English; a message that tells nothing defers to the one before it, then to `MU_LANG`). Fixed sentences keep following `MU_LANG`. The `language` option's help says so.
|
|
19
|
+
- The terminal widget is at most three lines: `μ <headline>`, then what needs the person or what is blocked, then the latest account line. `/board` shows now, blocked, next, progress, subagents, what waits on the person and the account.
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- A look that started before a permission request no longer publishes over it: while `pendingAsk` is set, the board keeps the permission line in `confirm`, `needsUser: true`, `phase: "waiting"` and a `waiting_permission` headline. The board shown when permission is asked now has `phase: "waiting"`; the headline and phase from before come back once it's answered.
|
|
24
|
+
- Writer starvation: a look overtaken by a newer trigger while the judge read skipped the writer even when no board had been written yet. It now writes anyway when there is no board or the shown board is older than `maxStaleMs` (default 15000). The writer's timeout is split: 20 s mid-run, `narrateTimeoutMs` (60 s) at the end.
|
|
25
|
+
|
|
26
|
+
## [0.2.7] - 2026-10-24
|
|
27
|
+
|
|
28
|
+
**0.2.7 adds OpenAI's decision model (`gpt-6-luna`, through the Decisions API) as a judge, and makes `gpt-6.1-sol` the `openai` provider's default model.**
|
|
29
|
+
|
|
30
|
+
### Added
|
|
31
|
+
|
|
32
|
+
- The `openai` judge (type and built-in name): OpenAI's decision model, `gpt-6-luna`, through `POST /v1/decisions` ([Decisions API](https://developers.openai.com/api/docs/guides/decisions)). Yes/no questions go out as predicates with their criteria in the instructions, choices as choices and scores as levels; answers come back with their probabilities and confidence, and usage with the cached and cache-write input tokens (`cachedInputTokens`, `cacheWriteTokens` in the ledger). A refusal or a missing answer fails the call as with TypeSafe, so the next judge or the fallback answers, and HTTP 401, 403, 429 and 5xx are classified the same way. The key is `MU_JUDGE_OPENAI_KEY`. Without it, at OpenAI's own address, the judge takes the key of the `openai` model provider (auth.json or `OPENAI_API_KEY`), but not a Sign in with ChatGPT token, nor the key of an `openai` provider that models.json points elsewhere. With a `baseUrl` (a relay or proxy that serves the same Decisions endpoint), only the judge's own key goes there. The keys of other judge services are never sent to it, and `MU_JUDGE_OPENAI_KEY` and `OPENAI_API_KEY` never to TypeSafe.
|
|
33
|
+
- The `openai` judge checks a request against the API's limits before sending it (1–400 questions, 2–255 choices, 2–10 levels; `bad_request` otherwise, so the next judge answers), and exports the models the API serves (`OPENAI_DECISIONS_MODELS`, today `gpt-6-luna`). When it has no key (`missing`: signed out of OpenAI, or the key removed) or OpenAI answers 401, or a 403 not about billing (`rejected`), the session says so once: `judge.notice` with `code: "openai_key"` and `reason`, then the line.
|
|
34
|
+
- `mu setup` offers OpenAI's decision model in its judge step, and scripts use `--judge openai`: the OpenAI key mu has, or a key on stdin's second line, written to the .env as `MU_JUDGE_OPENAI_KEY`. `mu doctor` reports where its key comes from, and `/mu judge` lists `openai`.
|
|
35
|
+
|
|
36
|
+
### Changed
|
|
37
|
+
|
|
38
|
+
- The `openai` provider's default model is `gpt-6.1-sol` (was `gpt-5.5`), as `openai-codex` and `github-copilot` already were; `mu setup` names it for an OpenAI key.
|
|
39
|
+
|
|
5
40
|
## [0.2.6] - 2026-10-24
|
|
6
41
|
|
|
7
42
|
**0.2.6 shows the note that Laya was replaced when a person sends a message, keeps mude 1.0 local only when it's installed again, and stops `mu doctor` failing on a machine without Chrome.**
|
package/README.md
CHANGED
|
@@ -30,6 +30,7 @@ mu is built on [pi](https://github.com/earendil-works/pi). It hands the small qu
|
|
|
30
30
|
Out of the box, the judge is Jev 1.13, TypeSafe's hosted judge model, free on OpenCode Zen for a limited time and with no key needed. What it judges goes to OpenCode, which doesn't train on it, and mu reminds you of that once a day. To send nothing anywhere, run `mu setup --judge off` (or choose "Not now" when `mu setup` asks): no decision point asks a judge, and mu's features fall back to their own rules. Or, on a Mac with Apple silicon, use mude 1.0 with `--local-only`.
|
|
31
31
|
|
|
32
32
|
- **Jev** (hosted): set `TYPESAFE_API_KEY` (TypeSafe), `MU_JUDGE_OPENROUTER_API_KEY` (Jev on OpenRouter), `AI_GATEWAY_API_KEY` (Vercel AI Gateway), `OPENCODE_API_KEY` (OpenCode Zen) or `CLOUDFLARE_API_KEY` with `CLOUDFLARE_ACCOUNT_ID` (Cloudflare Workers AI) in your environment, or add it to `~/.mu/.env` as `KEY=value`. `mu setup` asks for a key and writes it there. mu reads that file as data, never prints it and starts using the key automatically.
|
|
33
|
+
- **OpenAI's decision model**, `gpt-6-luna`, through OpenAI's Decisions API: `mu setup --judge openai`, or `/mu judge openai`. It uses `MU_JUDGE_OPENAI_KEY` (in your environment or `~/.mu/.env`), else the OpenAI API key mu already has for its `openai` provider. With a `baseUrl` (a relay or proxy that serves the same Decisions endpoint), only its own key is sent there.
|
|
33
34
|
- **Another classifier** from pi's catalog: `/mu judge classifier:<provider>/<model>`, for example Cloudflare's Clef (`clef`, `clef-flash`) or a System One model on OpenRouter, with that provider's key.
|
|
34
35
|
- **CLM** (self-hosted; its encoder needs a GPU): start `clm-serve` from [Contrastive-LM/CLM](https://github.com/Contrastive-LM/CLM), then run `/mu judge clm`. For a server on another machine, add `"judges": { "clm": { "type": "clm", "baseUrl": "http://<host>:8700" } }` to `~/.mu/agent/mu.json`. If the server was started with `CLM_API_KEY`, set the same value in `MU_JUDGE_CLM_API_KEY`. `mu doctor` checks the server.
|
|
35
36
|
- **mude 1.0** (local, a Mac with Apple silicon, macOS 14+), mu's own decision model, optimized for coding: `mu judge mude install` downloads it (1.8 GB), sets it up in `~/.mu/local-judge/mude`, starts its server on 127.0.0.1 and puts it first. What it can't answer goes to the judges you had before, which are hosted; `mu judge mude enable --local-only` keeps everything on your Mac. Its server uses about 4 GB of memory until `mu judge mude stop`.
|