tianshu-mcp 0.7.7 → 0.7.9

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.
Files changed (44) hide show
  1. package/CHANGELOG.en.md +124 -0
  2. package/CHANGELOG.md +141 -0
  3. package/README.en.md +17 -12
  4. package/README.md +17 -13
  5. package/dist/agents/builtin.js +2 -0
  6. package/dist/agents/minimax/adapter.js +72 -0
  7. package/dist/agents/minimax/cdp.js +578 -0
  8. package/dist/agents/minimax/dialog.js +299 -0
  9. package/dist/agents/minimax/discovery.js +183 -0
  10. package/dist/agents/minimax/dom.js +472 -0
  11. package/dist/agents/minimax/fixplan.js +152 -0
  12. package/dist/agents/minimax/instance.js +240 -0
  13. package/dist/agents/minimax/liveness.js +143 -0
  14. package/dist/agents/minimax/model-select.js +171 -0
  15. package/dist/agents/minimax/model.js +196 -0
  16. package/dist/agents/minimax/profile.js +94 -0
  17. package/dist/agents/minimax/project-modal.js +35 -0
  18. package/dist/agents/minimax/recovery.js +128 -0
  19. package/dist/agents/minimax/run.js +755 -0
  20. package/dist/agents/minimax/selectors.js +317 -0
  21. package/dist/agents/minimax/session.js +70 -0
  22. package/dist/agents/minimax/workspace.js +65 -0
  23. package/dist/agents/registry.js +57 -2
  24. package/dist/config/schema.js +57 -1
  25. package/dist/loop/fix-loop.js +30 -2
  26. package/dist/mcp/context.js +23 -0
  27. package/dist/mcp/handlers.js +9 -0
  28. package/dist/tasks/task-manager.js +22 -0
  29. package/dist/version.generated.js +1 -1
  30. package/docs/agent-profiles.en.md +443 -0
  31. package/docs/agent-profiles.md +461 -0
  32. package/docs/gui-log-viewer.en.md +157 -7
  33. package/docs/gui-log-viewer.md +124 -7
  34. package/docs/minimax-cdp.en.md +232 -0
  35. package/docs/minimax-cdp.md +232 -0
  36. package/docs/minimax-evidence/main-window-testids.txt +58 -0
  37. package/docs/minimax-evidence/model-menu-snippets.txt +11 -0
  38. package/docs/minimax-evidence/model-menu-structure.txt +14 -0
  39. package/docs/minimax-evidence/real-machine-e2e.txt +87 -0
  40. package/docs/minimax-evidence/sandbox-calc-after-fix.mjs +15 -0
  41. package/package.json +10 -3
  42. package/scripts/probe-minimax.mjs +601 -0
  43. package/skills/tianshu-mcp/SKILL.md +49 -34
  44. package/skills/tianshu-mcp/usage-examples.md +50 -7
package/CHANGELOG.en.md CHANGED
@@ -8,6 +8,129 @@ Chinese version: [CHANGELOG.md](CHANGELOG.md)
8
8
 
9
9
  ---
10
10
 
11
+ ## [0.1.1-beta.3] — 2026-10-02 — mcp-gui independent line
12
+
13
+ > This section records the **third and final pre-release batch** of the GUI's independent `0.1.1` line; **the MCP package
14
+ > is untouched**. It delivers A5 baseline drift / A6 stage gantt / A9 disk usage / A8b deep links — the first three are
15
+ > read-only enhancements, while A8b is the only item adding Tauri plugins and protocol registration (with a fallback).
16
+
17
+ ### Added
18
+
19
+ - **A5 a new "Baseline" section in the workspace**: it shows `baseline.json` read-only (repository or not / HEAD / whether the tree was already dirty / pre-existing change and untracked counts / capture time / message) alongside the **latest report's** change stats (report read on demand, cached per task). A missing or broken file always renders "no saved pre-work baseline" — **no zero values are invented**. New read-only Rust command `read_baseline` (`baseline.rs`, 4 unit tests).
20
+ - **A6 a new "Stages" view for the event stream (state-transition gantt)**: `ReadEventsRequest` gains `full` (defaults to `false`, **existing behaviour unchanged**); with `full = true`, `event_stream.rs` reads everything via `tail::read_whole` while **sharing the very same parsing code** as the windowed mode, falling back to the tail window if the full read fails. A stage spans two adjacent state transitions, bars are plain divs, and the last stage is marked "running" — **no invented durations**; if the file does not start at `created` the UI says so. New pure functions in `core/timeline.ts` (`buildStages` / `totalMs` / `stageShare`).
21
+ - **A9 a new "Disk usage" section on the Insights page**: new read-only command `scan_disk_usage` (`diskscan.rs`, 4 unit tests) measures the **actual size** of `logs/` and every directory under `tasks/` (**no `tsk_`/`vfy_` prefix filter**, `stat` only, contents never read) and reports totals / `logs/` share / top-20 task sizes / the median. Every cleanup rule is **relative** (`CLEANUP_HEAVIEST_RATIO = 0.5`, `CLEANUP_MEDIAN_MULTIPLE = 2`, named constants in `core/insights.ts`) with new pure functions `medianOf` / `cleanupHints`; **hints only — there is no delete entry of any kind**.
22
+ - **A8b deep link `tianshu://task/<taskId>`**: adds `tauri-plugin-single-instance` (with its `deep-link` feature; it **must be registered first**) and `tauri-plugin-deep-link`, and declares the `tianshu` scheme in `tauri.conf.json`. Cold start (`get_current`) and hot start (`on_open_url`) both **only enqueue and emit `gui://deeplink`**, and the frontend drains the queue before routing it (**the queue is the source of truth**, so cold-start links are never lost). Parsing lives in the pure `core/deeplink.ts` (id whitelist `[A-Za-z0-9_-]`; anything with `..`/`%2e` is rejected outright). **Deep links are handled entirely in Rust, so `capabilities/default.json` does not gain `deep-link:default`.**
23
+
24
+ ### Fixed
25
+
26
+ - **The command palette no longer caps task commands at 50 (fixed after `0.1.1-beta.2` shipped; delivered here)**: the old implementation **pre-generated** task commands as `slice(0, 50)`, so with more than 50 tasks the later ones were **unfindable** and the only feedback was "no matching commands" — no error, no truncation notice, **more misleading than not offering the feature**. Task commands are now produced by `buildTaskCommands`, which searches **every task live on each keystroke** (no cap; a blank query lists no tasks), and `rankCommands`'s `PALETTE_RESULT_LIMIT = 20` **limits only how many rows are shown, never the search scope**; the former `buildCommands` was split into `buildStaticCommands` (navigation + data homes) and `buildTaskCommands`. Regression cover: `test/palette.test.ts` asserts with 300 tasks that "the 300th is findable", "a blank query lists no tasks" and "the display limit only truncates the view".
27
+
28
+ ### Tests
29
+
30
+ - Frontend **169 passed** (15 files; new `test/timeline.test.ts` / `test/deeplink.test.ts`, plus `medianOf` / `cleanupHints` cases in `test/insights.test.ts`), with `check:schema` / `typecheck` / `lint` / `build` all green. Rust gains unit tests in `baseline.rs` (4) / `diskscan.rs` (4) / `event_stream.rs` (one full-read case); local `cargo fmt --all --check` passes (`clippy` / `cargo test` run in `gui.yml`).
31
+ - **Simulated real-machine run (headless Edge + mock preview) passed 14/14**: an empty deep-link queue raises no error, the baseline section shows the summary and the report comparison, a task without a baseline says so honestly, the stages view renders 12 stages (the last marked "running") plus the stage total, switching back to List still lists events, the disk section shows its four readings plus the top table and cleanup hints with **no delete or cleanup button anywhere on the page**, and there is no `pageerror`.
32
+
33
+ ### Docs
34
+
35
+ - Added `docs/release-gui-v0.1.1-beta.3.md` + `.en.md`; `docs/gui-log-viewer` gained §3.9 Baseline, §3.10 stages view and §3.11 deep links in both languages, §3.6 documents the disk-usage conventions, §8 the deep-link security boundary and the minimal-permission stance, and §9 the platform difference and "statistics only, never delete"; README documents this batch; ARCHITECTURE gained §16.10 "Deep link and single-instance contract" in both languages; HANDOFF's top snapshot and handoff section were updated.
36
+
37
+ ---
38
+
39
+ ## [0.1.1-beta.2] — 2026-10-02 — mcp-gui independent line
40
+
41
+ > This section records the two pre-release batches of the GUI's independent `0.1.1` line. **The MCP package is
42
+ > untouched** (the GUI versions independently of the package, under its own `gui-v*` tags). All three items in
43
+ > `0.1.1-beta.2` are **read-only** enhancements: structured filters, multi-task compare and a command palette.
44
+
45
+ ### Added
46
+
47
+ - **A7 richer structured filtering (`0.1.1-beta.2`)**: the overview filter sheet grows from 7 to 11 conditions, adding **error type `errorType`** (options come from the **facets** of the current task set — no hard-coded enum), **dry run `dryRun`**, **reworked `reworked`** (`roundsUsed > 1`; a single round is not rework) and **visual acceptance `hasVisual`** (a `report-<round>.html` exists). Rust's `TaskFilter` (`models.rs`) plus `matches_filter` in `scanner.rs` and the frontend's `filterTasks` in `core/filter.ts` are **two copies with identical semantics**; every new Rust field is `#[serde(default)]`, so older callers that omit it keep working.
48
+ - **A4 multi-task compare (`0.1.1-beta.2`)**: a new "Compare tasks" section on the Insights page — pick **2–4** tasks on the left (going past the limit gives an **explicit notice and never replaces** an existing pick) and read a side-by-side metric matrix on the right (status / agent / project / rounds / verify time / changed lines / files changed / latest verdict / failed checks / error type / message), with the rounds and verify-time rows marking the **best value across tasks**. Reports are read **on demand** and cached per `taskId`; anything missing shows `—` (never invented).
49
+ - **A8a command palette and hotkeys (`0.1.1-beta.2`)**: `Ctrl/Cmd + K` opens the palette (**subsequence fuzzy matching**; `↑` `↓` to move, `Enter` to run, `Esc` to close; while open **no other global hotkey fires**), and `Ctrl/Cmd + R` refreshes (intercepted, so the webview never reloads; combinations with `Alt` / `Shift` are never intercepted). Commands reuse existing data and actions (jump to pages / switch data home / open a task directly, capped at 50 task commands).
50
+ - **Insights page skeleton + A1 scoreboard / A2 attribution / A3 trend (`0.1.1-beta.1`)**: a new full "Insights" page in the sidebar (the shell `view` grows to four states); a new read-only aggregation command `get_insights` (`insights.rs` + `timestamps.rs`) that only **counts and sums**, leaving rates / TopN / trend gap-filling / week bucketing to frontend pure functions; the trend supports **by day / by week** (Monday week start) and a **rework rate**.
51
+
52
+ ### Tests
53
+
54
+ - **`0.1.1-beta.2`**: frontend **147 passed** (13 files; new `test/hotkeys.test.ts` / `test/palette.test.ts`, four new filter cases in `test/filter.test.ts`, and `compareTasks` / `bestOf` / `nextCompareSelection` cases in `test/insights.test.ts`), with `check:schema` / `typecheck` / `lint` / `build` all green. Rust gains the `matches_filter_supports_new_dimensions` test (local `cargo fmt --check` passes; `clippy` / `cargo test` run in `gui.yml`).
55
+ - **Simulated real-machine run (headless Edge + mock preview) passed 13/13**: all new filter controls present and "reworked = yes" actually filtering (4 → 1), `Ctrl+K` opening the palette, fuzzy-matching and jumping to the Insights page, the compare matrix headers and metric rows, the 4-task cap, and no `pageerror`.
56
+
57
+ ### Docs
58
+
59
+ - Added `docs/release-gui-v0.1.1-beta.1.md` + `.en.md` and `docs/release-gui-v0.1.1-beta.2.md` + `.en.md`; `docs/gui-log-viewer` gained §3.7 Compare tasks, §3.8 Command palette and hotkeys and §3.1 filter details in both languages; README gained the "structured filters / multi-task compare / command palette" bullet; ARCHITECTURE gained §16.9 "Filter semantics and command-palette contract" in both languages; HANDOFF's top snapshot and handoff section were updated.
60
+
61
+ ---
62
+
63
+ ## [0.7.9] - 2026-10-06
64
+
65
+ ### Fixed
66
+
67
+ - **Dead link to `docs/agent-profiles.md` inside the npm package**: three places in the README (including
68
+ the top navigation "Agent Profiles" entry) point at that document, but it was missing from the
69
+ `package.json` `files` allowlist — users installing from npm hit a 404. Both `docs/agent-profiles.md`
70
+ and `.en.md` are now included. **This defect predates 0.7.8; it was not introduced by it.**
71
+
72
+ ### Docs
73
+
74
+ - **Completed the documentation surface for the MiniMax Code adapter**: 0.7.8 shipped the full
75
+ `src/agents/minimax/` implementation and `docs/minimax-cdp.md`, but **the other documents that describe
76
+ agents were not synchronised** — this release fills in 4 files and 23 places:
77
+ - `README.md` / `README.en.md` (5 each): the agent banner, the `continue_task` resume-semantics list,
78
+ a new `minimax` row in the agent capability table, the `reasoningLevel` validation footnote, and the
79
+ version-history table.
80
+ - `docs/agent-profiles.md` / `.en.md` (4 each): the `adapter` enum comment, the `driver=gui` table's
81
+ agent list (**which had also been missing qoder / opendesign**), cross-document links, and a new
82
+ complete `minimax` profile example section.
83
+ - `skills/tianshu-mcp/SKILL.md` (35): the header `description` and `triggers` (**without which the skill
84
+ cannot be keyword-triggered**), the tool-surface `continue_task` support list, a new 8th column and a
85
+ `contextWindow` row in the §3.1 parameter matrix, a new minimax subsection in §3.2, the §3.3 platform
86
+ status, all six `needsUserKind` rows plus the anchor field in the §5 resume matrix, and minimax
87
+ semantics for six error codes in §9.
88
+ - `skills/tianshu-mcp/usage-examples.md` (9): a new §2.9 minimax example (including a **candidate table
89
+ for all four measured model shapes**), renumbering of the `codex-cli` section (**fixing a duplicate
90
+ `### 2.10` in the original**), a `contextWindow` row in the parameter-rejection table, and updates to
91
+ the `autoFixRounds` defaults and the session-anchor field table.
92
+
93
+ Every concrete assertion in these docs was **verified against the source** rather than recalled, and the
94
+ behavioural differences were exercised with a real probe:
95
+ `defaultAutoFixRounds=2` / `cdpPort=9999` / `permissionMode=始终授权` / the platform status check live in
96
+ `src/agents/minimax/profile.ts`; `contextWindow` is minimax-only per `src/mcp/handlers.ts:476`;
97
+ and **minimax is the only adapter that accepts `中`/`medium`** — it accepts `极高`/`最大` but
98
+ **rejects `关闭思考`** (confirmed by probe).
99
+
100
+ ### Changed
101
+
102
+ - Version `0.7.8` → `0.7.9` (`package.json` and `src/version.generated.ts`).
103
+ This release contains **no logic changes** — documentation and the packaging allowlist only.
104
+
105
+ ---
106
+
107
+ ## [0.7.8] - 2026-10-06
108
+
109
+ ### Added
110
+
111
+ - **Seventh GUI agent adapter: MiniMax Code (`agentId=minimax`)**. It sits alongside the existing six and covers the full loop of "locate the installation → launch it with CDP enabled → bind the project folder → select model / reasoning level / context window → send the task → detect completion → auto-verify → rework on failure → re-verify". See [MiniMax Code adapter](docs/minimax-cdp.en.md).
112
+
113
+ **Real-machine evidence (2026-10-05, MiniMax Code 3.1.0 / Electron 42.8.0 / Chromium 148.0.7778.280) corrected three structural assumptions** that were wrong before implementation; these conclusions live in both the code comments and the docs:
114
+
115
+ - **Reasoning level / context window live in a second-level submenu.** The product's own frontend artifacts show them as flat `role="group"` elements, but the live DOM **only renders them after hovering a model row carrying `aria-haspopup="menu"`** (`aria-expanded` flips to `true` and a second `role="menu"` appears). Selecting a model is therefore a three-step sequence: hover to expand → pick the tier/window → **finally** click the model row to commit (clicking it immediately commits and closes the menu). **The submenu container is reused**: moving straight into a row without first moving the pointer away does not fire `mouseenter`, so the DOM keeps the previously hovered model's tier set — picking from it selects another model's set. Candidate reads are therefore scoped to the owning model via `aria-label`.
116
+ - **Tier / window sets vary per model** (measured): `M3.1-Flash-Preview` has six tiers (default/low/medium/high/xhigh/max) plus windows (512K/1M); `M3` has **no tier group** plus windows; `deepseek-v4.1-flash` has three tiers (low/high/max) and **no window group**; `M2.7-highspeed` / `M2.7` have **no submenu**. Requesting these parameters on a model without a submenu is **fail-closed** — the adapter never silently keeps the UI's current value, and refuses to guess when the tier set cannot be read.
117
+ - **"New project" takes two steps**: clicking the sidebar's "New project" first opens an **in-app HTML modal** (`.responsive-modal-mask`); clicking "Choose folder" inside it then opens the **native `Select Directory`** dialog (title measured in English even on a Chinese UI), and after confirming the modal still needs its own "Create project" submit. Doing only one step misreads "the native dialog never appears" as a broken selector.
118
+
119
+ Other measured facts: the `Model menu` is a **separate renderer process** (hence the adapter connects across windows); that window **stays `visible` after the menu closes** (its content is emptied), so open/closed must be judged by "is content rendered" rather than `visibilityState`; the "new task" testid sits on a `<kbd>` (the clickable element is its ancestor `button`); the send button is a `DIV` (usability comes from `aria-disabled`, there is **no `disabled` property**); the input is **tiptap ProseMirror**; and the authoritative project-binding criterion is the sidebar's `data-workspace-dir` **full absolute path**.
120
+
121
+ **The real-machine loop passed** (sandbox `MiniMax-Test`, seeded with one deliberately failing test): dispatched `M3.1-Flash-Preview / low / 512K` → `ok=true`, `endReason=reply_stable`, with the `stop_button` run signal recorded live; the agent really edited `src/calc.mjs` and made the sandbox tests pass 4/4 (independently re-verified with `node --test` + `git diff`). Evidence: [real-machine loop transcript](docs/minimax-evidence/real-machine-e2e.txt).
122
+
123
+ - **New `contextWindow` parameter (minimax only)**: deliberately loose (UI candidates vary per model, and a hard-coded enum would reject valid values); validity is checked against the **actual UI candidates** before sending. Passing it for a non-minimax dispatch is an error.
124
+ - **New read-only diagnostic probe `scripts/probe-minimax.mjs`** (`npm run probe:minimax`): prints install discovery, processes and CDP topology, model/submenu candidates (**hover only, no clicks**), project groups, run-signal snapshot and native-dialog enumeration — it reproduces every conclusion above.
125
+
126
+ ### Tests
127
+
128
+ - Added `test/unit/minimax-*` (6 files, **121 cases**): discovery order, parameter surface, tier/window set validation (all fail-closed paths covered), selector structural contracts, run judging and question detection, project path normalisation and session location.
129
+ - Included a **new class of "in-page expression sandbox executability" test**: it runs every in-page expression through `node:vm` and asserts `/is not defined/`. Bugs of the "string-assembled expression missing a helper" kind are invisible to both `tsc` and ordinary unit tests — this is the only thing that catches them early (the real machine hit this twice).
130
+ - Full suite **126 files passed / 3 skipped / 0 failed**; typecheck / lint / build / strict stdio all green.
131
+
132
+ ---
133
+
11
134
  ## [0.7.7] - 2026-10-01
12
135
 
13
136
  ### Added
@@ -346,6 +469,7 @@ Chinese version: [CHANGELOG.md](CHANGELOG.md)
346
469
 
347
470
  ### Fixed
348
471
 
472
+ - **The update window's body was a single title line (GUI independent version `0.1.1-beta.1`, found on a real machine; manifests backfilled for that version, no version bump)**: the desktop "update notes" window renders the body from the **update manifest's `notes`** (`update.body` in `updater.rs`), but the release chain only passed the placeholder title `--notes "Tianshu-mcp 日志台 $VER"` when composing the manifest — the full bilingual body composed by `scripts/gui-release-body.mjs` was used for the GitHub / Gitee release pages (`--notes-file` / `--body-file`) yet was **never handed to the manifest builder**; the Gitee manifest reuses the same `latest.json` (`gitee-gui-release.mjs --github-manifest`), so **both** sources degraded to a one-line title. Fix: the manifest step in `gui.yml` now passes `--notes-file "${{ steps.meta.outputs.body }}"`, making the manifest `notes` and the release-page body **one and the same source**; `build-updater-manifest.mjs` gains `resolveNotes()` — `--notes-file` wins, a **read failure exits non-zero** (fail-closed, no silent degradation), and only an empty file falls back to `--notes` with a warning. The already-published `update/gui/latest.json` / `latest-gitee.json` had their `notes` backfilled with the full bilingual body (`version` / `pub_date` / `platforms` untouched); a new `test/unit/gui-updater-manifest.test.ts` (5 cases) covers the resolution.
349
473
  - **Clicking "Manual download" did nothing at all (GUI independent version `0.1.0-beta.7`)**: the entry was an `<a href target="_blank">`, and **Tauri 2's webview intercepts new-window requests**; no external-open capability was wired up (no opener / shell plugin and no `on_new_window` handler), so the request was **silently dropped** — the click appeared to do nothing. It is now a `<button>` that goes through `GuiApi.openExternal` → `openUrl()` and opens in the **system default browser**; failures flow through the existing `setError` and never block log viewing.
350
474
  - **"Manual download" did not jump to the matching update source (GUI independent version `0.1.0-beta.7`)**: the Rust-side fallback URL was a **single constant, `MANUAL_DOWNLOAD_URL`, always pointing at GitHub releases**, decoupled from the source actually used; with "Force Gitee" selected or Gitee winning the probe, the fallback still pointed at GitHub (which means it is still unusable on mainland-China networks). It is now split into `MANUAL_DOWNLOAD_URL_GITHUB` / `MANUAL_DOWNLOAD_URL_GITEE` and resolved by `manual_download_url_for(&chosen)` from `resolve_source()`'s result (**unknown sources always fall back to GitHub**); all four return branches of `check_update` use that function, and the frontend `mock`'s `checkUpdate(source)` mirrors the same semantics.
351
475
  - **A manual `GUI` workflow run could be silently skipped**: `workflow_dispatch` carries no `github.event.before`, so the change detection degraded to `git diff HEAD~1 HEAD`; when the last two commits touched only docs, the whole three-platform matrix was **skipped** (the run reported Success while doing nothing). Now a manual run **always builds**, tags always build, and only push / PR go through diff filtering.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,146 @@
7
7
 
8
8
  ---
9
9
 
10
+ ## [0.1.1-beta.3] — 2026-10-02 — mcp-gui 独立版本线
11
+
12
+ > 本段记录 GUI 独立版本线 `0.1.1` 的**第三个(最后一个)预发布批次**;**MCP 主包零改动**。
13
+ > 本批交付 A5 基线漂移 / A6 状态跃迁甘特 / A9 磁盘占用 / A8b 深链——前三项为只读增强,
14
+ > A8b 是本轮唯一新增 Tauri 插件与协议注册的系统集成项(含降级预案)。
15
+
16
+ ### 新增
17
+
18
+ - **A5 工作区新增「基线」分区**:只读展示 `baseline.json`(是否版本库 / HEAD / 动工前是否已脏 / 已有改动与未跟踪数 / 采集时间 / 说明),并与**最新报告**的改动统计对照(报告按需读取、按任务缓存);缺失或损坏一律提示「没有保存的动工前基线」,**不编造零值**。Rust 侧新增只读命令 `read_baseline`(`baseline.rs`,含 4 项单测)。
19
+ - **A6 事件流新增「阶段」视图(状态跃迁甘特)**:`ReadEventsRequest` 新增 `full`(缺省 `false`,**不改既有行为**);`event_stream.rs` 的 `full = true` 用 `tail::read_whole` 读全量,**解析逻辑与窗口模式共用同一段代码**,读取失败退回尾部窗口;阶段 = 相邻两次状态跃迁之间,纯 div 横向条,最后一段标「进行中」**不编造时长**;开头不在文件内时如实提示。新增纯函数 `core/timeline.ts`(`buildStages` / `totalMs` / `stageShare`)。
20
+ - **A9 洞察页新增「磁盘占用」分区**:新增只读命令 `scan_disk_usage`(`diskscan.rs`,含 4 项单测)统计 `logs/` 与 `tasks/` 各目录**实测体积**(**不按 `tsk_`/`vfy_` 前缀过滤**、只 `stat`、不读内容),给出总量 / `logs/` 占比 / 任务体积 TOP 20 / 中位数;「可清理」提示的判据全部为**相对口径**(`CLEANUP_HEAVIEST_RATIO = 0.5`、`CLEANUP_MEDIAN_MULTIPLE = 2`,具名常量集中在 `core/insights.ts`),新增 `medianOf` / `cleanupHints` 纯函数;**只有提示、没有任何删除入口**。
21
+ - **A8b 深链 `tianshu://task/<任务ID>`**:新增 `tauri-plugin-single-instance`(启用 `deep-link` feature,**必须最先注册**)与 `tauri-plugin-deep-link`,`tauri.conf.json` 声明 `tianshu` 协议;冷启动(`get_current`)与热启动(`on_open_url`)都**只入队并发 `gui://deeplink` 信号**,前端取走队列后解析路由(**队列是唯一事实来源**,避免冷启动丢链接);解析在纯函数 `core/deeplink.ts`(ID 白名单 `[A-Za-z0-9_-]`,含 `..`/`%2e` 直接拒绝);**深链全在 Rust 侧处理,`capabilities/default.json` 不新增 `deep-link:default`**。
22
+
23
+ ### 修复
24
+
25
+ - **命令面板的任务命令不再有 50 条上限(`0.1.1-beta.2` 发布后修复,本版交付)**:原实现把任务命令**预生成**为 `slice(0, 50)`,任务数超过 50 时排在后面的任务**搜不到**,且只给出「没有匹配的命令」——既不报错也不提示被截断,**比不提供该功能更误导**。现改为 `buildTaskCommands` **按输入实时检索全部任务**(无条数上限;空输入不列任务),`rankCommands` 的 `PALETTE_RESULT_LIMIT = 20` **只限制展示条数、不限制检索范围**;原 `buildCommands` 相应拆为 `buildStaticCommands`(导航 + 数据目录)与 `buildTaskCommands`。回归:`test/palette.test.ts` 用 300 个任务断言「第 300 个也能搜到」「空输入不铺任务」「展示上限只截显示」。
26
+
27
+ ### 测试
28
+
29
+ - 前端 **169 passed**(15 文件;新增 `test/timeline.test.ts` / `test/deeplink.test.ts`,`test/insights.test.ts` 补 `medianOf` / `cleanupHints` 用例),`check:schema` / `typecheck` / `lint` / `build` 全绿;Rust 新增 `baseline.rs`(4)/ `diskscan.rs`(4)/ `event_stream.rs`(全量读取 1)单测,本机 `cargo fmt --all --check` 通过(`clippy` / `cargo test` 交 `gui.yml`)。
30
+ - **模拟真机(无头 Edge + mock 预览)14/14 通过**:深链空队列不报错、基线分区显示摘要并与报告对照、无基线任务如实提示、阶段视图渲染 12 段(末段「进行中」)与阶段合计、切回列表仍有事件行、磁盘分区四项读数 + TOP 表 + 「可清理提示」且**页面上没有任何删除 / 清理按钮**、无 `pageerror`。
31
+
32
+ ### 文档
33
+
34
+ - 新增 `docs/release-gui-v0.1.1-beta.3.md` + `.en.md`;`docs/gui-log-viewer` 双语新增 §3.9 基线 / §3.10 阶段视图 / §3.11 深链,§3.6 补磁盘占用口径,§8 补深链安全边界与最小权限口径,§9 补平台差异与「磁盘只统计不删除」;README 双语补本批能力;ARCHITECTURE 双语新增 §16.10「深链与单实例契约」;HANDOFF 顶部快照与交接段同步。
35
+
36
+ ---
37
+
38
+ ## [0.1.1-beta.2] — 2026-10-02 — mcp-gui 独立版本线
39
+
40
+ > 本段记录 GUI 独立版本线 `0.1.1` 的两个预发布批次;**MCP 主包零改动**(GUI 与主包版本线互相独立,独立 tag `gui-v*`)。
41
+ > `0.1.1-beta.2` 的三项全部是**只读**增强:结构化筛选、多任务对比、命令面板。
42
+
43
+ ### 新增
44
+
45
+ - **A7 结构化筛选增强(`0.1.1-beta.2`)**:概览页筛选浮层由 7 项扩为 11 项,新增**错误类型 `errorType`**(选项取自当前任务集合的**分面**,不硬编码枚举)、**干跑 `dryRun`**、**返修 `reworked`**(`roundsUsed > 1`,1 轮不算返修)、**视觉验收 `hasVisual`**(存在 `report-<轮次>.html`);Rust `TaskFilter`(`models.rs`)+ `scanner.rs` 的 `matches_filter` 与前端 `core/filter.ts` 的 `filterTasks` **双份同口径实现**,Rust 侧新字段全部 `#[serde(default)]`(旧调用方不传不失败)。
46
+ - **A4 多任务对比(`0.1.1-beta.2`)**:洞察页新增「任务对比」子分区——左侧勾选 **2–4 个**任务(超上限**明确提示、不顶替**已有勾选),右侧并排指标矩阵(状态 / Agent / 项目 / 轮次 / 验收耗时 / 改动行数 / 改动文件数 / 最新报告判定 / 失败检查项 / 错误类型 / 结论说明),轮次与耗时两行标注**横向最优**;报告**按需读取**并按 `taskId` 缓存,缺失一律显示 `—`(不编造)。
47
+ - **A8a 命令面板与快捷键(`0.1.1-beta.2`)**:`Ctrl/Cmd + K` 打开命令面板(**子序列模糊匹配**、`↑` `↓` 移动、`Enter` 执行、`Esc` 关闭;面板打开时**不触发**其他全局快捷键),`Ctrl/Cmd + R` 刷新(已拦截,不会触发 webview 重载;带 `Alt` / `Shift` 的组合一律不拦截);命令复用既有数据与动作(跳页面 / 切数据目录 / 直接打开任务,任务命令上限 50 条)。
48
+ - **洞察页骨架 + A1 效能看板 / A2 失败归因 / A3 时间趋势(`0.1.1-beta.1`)**:侧栏新增「洞察」整页(`view` 扩为四态);后端新增只读聚合命令 `get_insights`(`insights.rs` + `timestamps.rs`,只做**计数与求和**,比率 / TopN / 趋势补齐 / 周历聚合留在前端纯函数);时间趋势支持**按天 / 按周**(周一为周始)与**返修率**。
49
+
50
+ ### 测试
51
+
52
+ - **`0.1.1-beta.2`**:前端 **147 passed**(13 文件;新增 `test/hotkeys.test.ts` / `test/palette.test.ts`,`test/filter.test.ts` 补四项新筛选,`test/insights.test.ts` 补 `compareTasks` / `bestOf` / `nextCompareSelection`),`check:schema` / `typecheck` / `lint` / `build` 全绿;Rust 新增 `matches_filter_supports_new_dimensions` 单测(本机 `cargo fmt --check` 通过,`clippy` / `cargo test` 交 `gui.yml`)。
53
+ - **模拟真机(无头 Edge + mock 预览)13/13 通过**:新筛选控件齐全且「返修 = 是」实际生效(4 → 1)、`Ctrl+K` 开面板并模糊命中后跳转洞察页、对比矩阵列头与指标行齐全、选满 4 个、无 `pageerror`。
54
+
55
+ ### 文档
56
+
57
+ - 新增 `docs/release-gui-v0.1.1-beta.1.md` + `.en.md` 与 `docs/release-gui-v0.1.1-beta.2.md` + `.en.md`;`docs/gui-log-viewer` 双语补 §3.7 任务对比 / §3.8 命令面板与快捷键 / §3.1 筛选增强;README 双语补「结构化筛选 / 多任务对比 / 命令面板」;ARCHITECTURE 双语新增 §16.9「筛选口径与命令面板契约」;HANDOFF 顶部快照与交接段同步。
58
+
59
+ ---
60
+
61
+ ## [0.7.9] - 2026-10-06
62
+
63
+ ### 修复
64
+
65
+ - **npm 包内 `docs/agent-profiles.md` 死链**:README 有 3 处(含顶部导航「Agent 配置」)指向该文档,
66
+ 但它不在 `package.json` 的 `files` 白名单里——从 npm 安装的用户点进去是 404。
67
+ 已补 `docs/agent-profiles.md` 与 `.en.md`。**这是 0.7.8 之前就存在的缺陷,不是 0.7.8 引入的。**
68
+
69
+ ### 文档
70
+
71
+ - **补全 MiniMax Code 适配的文档面**:0.7.8 发布了 `src/agents/minimax/` 全套实现与
72
+ `docs/minimax-cdp.md`,但**其它描述 agent 的文档面没同步**——本轮补齐 4 个文件共 23 处:
73
+ - `README.md` / `README.en.md`(各 5 处):Agent 横幅、`continue_task` 恢复语义列表、
74
+ agent 能力表新增 `minimax` 行、`reasoningLevel` 校验规则脚注、版本线历史表。
75
+ - `docs/agent-profiles.md` / `.en.md`(各 4 处):`adapter` 枚举注释、`driver=gui` 表格的
76
+ agent 列表(**此前连 qoder / opendesign 也漏了**)、文档互链、新增完整 `minimax` profile 示例段。
77
+ - `skills/tianshu-mcp/SKILL.md`(35 处):头部 `description` 与 `triggers`(**否则关键词触发不到该技能**)、
78
+ 工具面 `continue_task` 支持列表、§3.1 参数兼容矩阵新增第 8 列与 `contextWindow` 行、
79
+ §3.2 新增 minimax 小节、§3.3 平台状态、§5 恢复矩阵六类 `needsUserKind` 与锚点字段、
80
+ §9 六条错误码补 minimax 语义。
81
+ - `skills/tianshu-mcp/usage-examples.md`(9 处):新增 §2.9 minimax 完整示例(含**四种模型形态的
82
+ 候选对照表**)、`codex-cli` 小节顺延(**修掉原文重复的两个 `### 2.10`**)、参数拒绝表补 `contextWindow`、
83
+ `autoFixRounds` 缺省与会话锚点字段表。
84
+
85
+ 文档里的具体断言均**回源码核验**而非凭记忆,并对其中的行为差异跑了实测:
86
+ `defaultAutoFixRounds=2` / `cdpPort=9999` / `permissionMode=始终授权` / 平台状态判定见
87
+ `src/agents/minimax/profile.ts`;`contextWindow` 仅 minimax 见 `src/mcp/handlers.ts:476`;
88
+ **minimax 是唯一接受 `中`/`medium` 的适配器**,接受 `极高`/`最大` 但**拒绝 `关闭思考`**(实测确认)。
89
+
90
+ ### 变更
91
+
92
+ - 版本号 `0.7.8` → `0.7.9`(`package.json` 与 `src/version.generated.ts`)。
93
+ 本版**无代码逻辑变更**,仅文档与打包白名单。
94
+
95
+ ---
96
+
97
+ ## [0.7.8] - 2026-10-06
98
+
99
+ ### 新增
100
+
101
+ - **第七个 GUI agent 适配器:MiniMax Code(`agentId=minimax`)**。与既有 6 个并列,完成
102
+ 「定位安装 → 启动并开 CDP → 绑定项目文件夹 → 选模型 / 推理等级 / 上下文窗口 → 发指令开发
103
+ → 运行检测 → 自动验收 → 失败返修 → 再验收」全流程。详见 [MiniMax Code 适配器](docs/minimax-cdp.md)。
104
+
105
+ **真机取证(2026-10-05,MiniMax Code 3.1.0 / Electron 42.8.0 / Chromium 148.0.7778.280)修正了三处
106
+ 与实现前假设不符的关键结构**,这些结论都写进了代码注释与文档:
107
+
108
+ - **推理等级 / 上下文窗口在「二级子菜单」里**:产品前端产物显示它们是平铺的 `role="group"`,
109
+ 但真机 DOM **只在悬停带 `aria-haspopup="menu"` 的模型项后才渲染**(`aria-expanded` 变 `true`,
110
+ 出现第二个 `role="menu"`)。因此选模型是「悬停展开 → 选档位/窗口 → **最后**点模型项提交」
111
+ 三步——点模型项会立即提交并关闭菜单。**且子菜单容器是复用的**:不先移开鼠标就移入不会触发
112
+ `mouseenter`,DOM 会保留上一个悬停模型的档位集合,据此选档位会选到别的模型——故读候选必须按
113
+ `aria-label` 限定归属模型。
114
+ - **档位 / 窗口集合随模型变化**(实测):`M3.1-Flash-Preview` 六档(default/low/medium/high/xhigh/max)
115
+ + 窗口(512K/1M);`M3` **无档位组** + 窗口;`deepseek-v4.1-flash` 三档(low/high/max)+ **无窗口组**;
116
+ `M2.7-highspeed` / `M2.7` **无子菜单**。对无子菜单的模型请求这两项参数一律 **fail-closed 报错**,
117
+ 绝不静默沿用界面当前值;档位集合读不到时也拒绝猜测。
118
+ - **「新建项目」是两步**:点侧栏「新建项目」先弹**应用内 HTML 模态框**(`.responsive-modal-mask`),
119
+ 模态框里再点「选择文件夹」才弹**原生 `Select Directory`** 对话框(标题实测为英文,界面中文时亦然),
120
+ 确认后还需点模态框的「创建项目」提交。只走一步会把「原生对话框始终不出现」误判成选择器失效。
121
+
122
+ 其它真机实测要点:`Model menu` 是**独立渲染进程**(与主窗口分离,故适配器跨窗口连接);
123
+ 该窗口在菜单关闭后**仍为 `visible`**(内容清空),所以开/关判据必须用「内容是否渲染」而非
124
+ `visibilityState`;「新建任务」的 testid 挂在 `<kbd>` 上(真正可点击的是祖先 `button`);
125
+ 发送按钮是 `DIV`(可用性读 `aria-disabled`,**没有 `disabled` 属性**);
126
+ 输入框是 **tiptap ProseMirror**;项目绑定的权威判据是侧栏 `data-workspace-dir` 的**完整绝对路径**。
127
+
128
+ **真机闭环已跑通**(沙箱 `MiniMax-Test`,含一个刻意保留的失败用例):
129
+ 派发 `M3.1-Flash-Preview / low / 512K` → `ok=true`、`endReason=reply_stable`、
130
+ 日志实录运行信号 `stop_button`;agent 真实修改 `src/calc.mjs` 并使沙箱测试 4/4 通过
131
+ (独立复核:`node --test` + `git diff`)。证据见 [真机闭环实录](docs/minimax-evidence/real-machine-e2e.txt)。
132
+
133
+ - **新增 `contextWindow` 参数(仅 minimax 生效)**:取值刻意宽松(界面候选随模型变化,
134
+ 硬编码枚举会拒掉合法值),合法性由**界面实际候选**在发送前校验。非 minimax 派发时显式传入即报错。
135
+ - **新增只读诊断探针 `scripts/probe-minimax.mjs`**(`npm run probe:minimax`):
136
+ 打印安装探测、进程与 CDP 拓扑、模型/子菜单候选(**只悬停不点击**)、项目分组、运行信号快照、
137
+ 原生对话框枚举——可复现上述全部结论。
138
+
139
+ ### 测试
140
+
141
+ - 新增 `test/unit/minimax-*`(6 文件 **121 例**):安装探测顺序、参数面、模型档位/窗口集合校验
142
+ (fail-closed 路径全覆盖)、选择器结构契约、运行判定与提问检测、项目路径归一与会话定位。
143
+ - 其中**新增一类「页面内表达式沙箱可执行性」测试**:用 `node:vm` 逐个执行全部页面内表达式,
144
+ 以 `/is not defined/` 断言——这类「拼字符串注入页面的表达式漏带 helper」的缺陷
145
+ `tsc` 与常规单测**都发现不了**,只能靠它提前拦住(真机已因此踩到两次)。
146
+ - 全量 **126 files passed / 3 skipped / 0 failed**;typecheck / lint / build / 严格 stdio 全绿。
147
+
148
+ ---
149
+
10
150
  ## [0.7.7] - 2026-10-01
11
151
 
12
152
  ### 新增
@@ -311,6 +451,7 @@
311
451
 
312
452
  ### 修复
313
453
 
454
+ - **更新窗口正文只剩一行标题(GUI 独立版本 `0.1.1-beta.1`,真机发现;随该版本回填清单,版本号不升)**:桌面端「更新日志」窗口渲染的正文取自**更新清单的 `notes`**(`updater.rs` 的 `update.body`),而发布链合成清单时只传了兜底标题 `--notes "Tianshu-mcp 日志台 $VER"`——`scripts/gui-release-body.mjs` 合成的完整双语正文虽已用于 GitHub / Gitee 发行页(`--notes-file` / `--body-file`),却**没有传给清单生成脚本**;Gitee 清单复用同一份 `latest.json`(`gitee-gui-release.mjs --github-manifest`),故两个源**同时**退化成单行标题。修法:`gui.yml` 合成清单时新增 `--notes-file "${{ steps.meta.outputs.body }}"`,使清单 `notes` 与发行页正文**同源同一份**;`build-updater-manifest.mjs` 新增 `resolveNotes()`——`--notes-file` 优先、**读取失败非 0 退出**(fail-closed,杜绝静默退化)、文件为空才回退 `--notes` 并告警。已发布的 `update/gui/latest.json` / `latest-gitee.json` 的 `notes` 手工回填为完整双语说明(`version` / `pub_date` / `platforms` 未动);新增 `test/unit/gui-updater-manifest.test.ts`(5 例)回归取数。
314
455
  - **「手动下载」点击无任何反应(GUI 独立版本 `0.1.0-beta.7`)**:入口原是 `<a href target="_blank">`,而 **Tauri 2 的 webview 会拦截新建窗口请求**,此前又未接入任何外部打开能力(无 opener / shell 插件,也未处理 `on_new_window`),故请求被**静默丢弃**——表现为点了没反应。现改为 `<button>` 并经 `GuiApi.openExternal` 调 `openUrl()` 用**系统默认浏览器**打开;失败并入既有 `setError`,不影响日志查看主流程。
315
456
  - **「手动下载」不跳到对应的更新源(GUI 独立版本 `0.1.0-beta.7`)**:Rust 侧兜底地址原为**单常量 `MANUAL_DOWNLOAD_URL`,恒指 GitHub releases**,与本次实际使用的源脱钩;用户选「强制 Gitee」或实测择优命中 Gitee 时,兜底入口仍指向 GitHub(中国大陆网络下等于仍然不可用)。现拆为 `MANUAL_DOWNLOAD_URL_GITHUB` / `MANUAL_DOWNLOAD_URL_GITEE` 两个常量,由 `manual_download_url_for(&chosen)` 按 `resolve_source()` 的结果取值(**未知源一律回退 GitHub**),`check_update` 的 4 个返回分支全部改用该函数;前端 `mock` 的 `checkUpdate(source)` 同步该语义。
316
457
  - **`GUI` workflow 手动触发会被静默跳过**:`workflow_dispatch` 不带 `github.event.before`,原变更检测退化为 `git diff HEAD~1 HEAD`,若最近两次提交仅改文档,则三平台构建矩阵**全部 skipped**(运行显示 Success 却什么都没跑)。现改为**手动触发无条件构建**,tag 同样无条件构建,仅 push / PR 走 diff 过滤。
package/README.en.md CHANGED
@@ -63,7 +63,7 @@ Tianshu (TUI × GUI) ← commander / user surface / verdict
63
63
  ↓ MCP over stdio (stdout carries JSON-RPC only)
64
64
  tianshu-mcp ← scheduling · execution surface · acceptance gate
65
65
  ↓
66
- Codex · TraeWork · ZCode · Kimi Code · Qoder CN · Open Design
66
+ Codex · TraeWork · ZCode · Kimi Code · Qoder CN · Open Design · MiniMax Code
67
67
  ↓ (GUI driven over CDP; CLI via child process)
68
68
  target project workspace ← git repo + tests + .tianshu-mcp/
69
69
  ```
@@ -227,7 +227,7 @@ run_task(projectPath=D:/xxx/my-app, task="…task brief…", agentId=codex,
227
227
  | Tool | Capability / approval | Purpose |
228
228
  |---|---|---|
229
229
  | `run_task` | write + approval | Dispatch work (optionally with auto-verify / auto-rework), returning a `taskId` asynchronously; optional `idempotencyKey`, `acceptanceOverride` and `dryRun` |
230
- | `continue_task` | write + approval | Resume a `needs_user` session (ZCode / Codex / Kimi Code / Qoder CN each have their own resume semantics) |
230
+ | `continue_task` | write + approval | Resume a `needs_user` session (ZCode / Codex / Kimi Code / Qoder CN / MiniMax Code each have their own resume semantics) |
231
231
  | `query_task` | read | Poll status / progress / log tail / recent fine-grained events (optional `eventLimit`) |
232
232
  | `list_tasks` | read | Filtered list of historical tasks |
233
233
  | `get_task_report` | read | Full text of one round's acceptance report (`report.md`) |
@@ -256,9 +256,10 @@ run_task(projectPath=D:/xxx/my-app, task="…task brief…", agentId=codex,
256
256
  | `kimicode` | `gui` / `kimicode-gui` | **ready** (`research` on macOS) | Kimi Code desktop (Electron); **dual renderer processes** (main window plus a `Kimi Browser Overlay` that hosts the model / reasoning / mode menus); workspaces bind by full path; supports `model` / `reasoningLevel`, **not `mode`**, and **not project-less dispatch** |
257
257
  | `qoder` | `gui` / `qoder-gui` | closed-loop verified on Windows; **research** on macOS | Qoder CN only; requires an existing `projectPath` and a readable `planDoc`; `modelSource=default\|custom` disambiguates same-named models, and the reasoning level is saved as a global preference via "Model management" and read back |
258
258
  | `opendesign` | `gui` / `opendesign-gui` | **ready** (`research` on macOS) | Open Design desktop GUI; selectors are taken from the product's own web-frontend `data-testid` hooks, the full 12-step execution chain is wired, and the acceptance → auto-rework → re-acceptance loop is connected; it is the only driver with an "artifact signal" (file mtime / size fingerprint) |
259
+ | `minimax` | `gui` / `minimax-gui` | **ready** (`research` on macOS) | MiniMax Code desktop (Electron); **dual renderer processes** (main window plus a `Model menu` popup); the reasoning level / context window live in a **second-level submenu that only appears on hovering a model row**, and their **candidate sets vary per model** (requesting them on a submenu-less model is fail-closed); supports `model` / `reasoningLevel` / **`contextWindow`** (this adapter only), **not `mode`**, and **not project-less dispatch**; "New project" takes **two steps: in-app modal → native `Select Directory` → modal submit** |
259
260
  | `stub` | `spawn` | tests only | `test/stub-agent/stub-agent.mjs` with three scripts (good / fix-on-first / never) |
260
261
 
261
- > `mode` supports `Work` / `Code` / `Design` (TraeWork only) and is inferred from the task text when omitted. Kimi Code's `reasoningLevel` is validated against the **set of levels actually rendered by the UI** (official models `low` / `high` / `max`; unofficial models only `on` / `off`). Adding an agent is usually just a profile — see [docs/agent-profiles.en.md](docs/agent-profiles.en.md) and [CONTRIBUTING.en.md](CONTRIBUTING.en.md).
262
+ > `mode` supports `Work` / `Code` / `Design` (TraeWork only) and is inferred from the task text when omitted. Kimi Code's `reasoningLevel` is validated against the **set of levels actually rendered by the UI** (official models `low` / `high` / `max`; unofficial models only `on` / `off`). MiniMax Code's `reasoningLevel` / `contextWindow` are likewise validated against the **actual UI candidates** (e.g. `M3.1-Flash-Preview` offers `default`/`low`/`medium`/`high`/`xhigh`/`max` plus `512K`/`1M`, while `M3` has no level group and `deepseek-v4.1-flash` has no window group); an out-of-range or unreadable value is fail-closed. Adding an agent is usually just a profile — see [docs/agent-profiles.en.md](docs/agent-profiles.en.md) and [CONTRIBUTING.en.md](CONTRIBUTING.en.md).
262
263
 
263
264
  ### macOS headless path: codex-cli (user profile)
264
265
 
@@ -370,6 +371,7 @@ Allowing and disabling (a CLI flag or its equivalent environment variable; `--no
370
371
  | Visual and idempotency | 0.5.x | Visual acceptance (0.5.0) + optional AI content validation (0.5.4), ZCode project-less dispatch, Kimi Code / Qoder CN adapters, idempotency keys (0.5.10) |
371
372
  | Hardening and observability | 0.6.x | Skill self-install hardening (0.6.0), GUI selector drift fixes (0.6.2), fine-grained event stream, structured repair directives, dryRun, three-level acceptance config inheritance, terminal-state webhook |
372
373
  | Open Design | 0.7.x | Open Design desktop adapter (0.7.1), ZCode 3.14.x binding-contract fix (0.7.4) |
374
+ | MiniMax Code | 0.7.8 | Seventh GUI agent (0.7.8); real-machine evidence corrected three structural assumptions (second-level submenu / per-model candidate sets / two-step project creation), plus the `contextWindow` parameter and a read-only diagnostic probe |
373
375
  | Log viewer GUI | `gui-v*` (separate line) | `mcp-gui/` local read-only log viewer (Tauri 2.x + Vue 3), independent version and tag, **not released with the MCP main package** |
374
376
 
375
377
  > The complete per-version record is in [CHANGELOG.en.md](CHANGELOG.en.md); handoff status and the troubleshooting handbook are in [HANDOFF.md](HANDOFF.md); engineering-metric definitions are in [ARCHITECTURE.en.md](ARCHITECTURE.en.md).
@@ -392,11 +394,14 @@ Allowing and disabling (a CLI flag or its equivalent environment variable; `--no
392
394
  Key capabilities:
393
395
 
394
396
  - **Large logs and live tail** — the first paint reads only a 64 KiB tail window, loading earlier blocks on demand with a "loaded N / M" indicator; appended content refreshes incrementally, **scrolling up pauses following automatically**, and one click jumps back to the latest.
397
+ - **Insights (scoreboard / attribution / trend)** — read-only aggregation: a **scoreboard** by agent and by project (tasks / success rate / avg rounds / one-pass rate / avg verify time / missing reports), Top lists for four kinds of **failure attribution** (error type / failed check / blocking issue / code signal), and **trends by day or by week** for volume plus success and rework rates (plain inline SVG, no chart library). The conventions are stated on the page (UTC dates, Monday week start, "one pass" = succeeded in exactly 1 round, only each task's **latest** report round) and it is **read-only with no delete / cleanup**.
398
+ - **Structured filters / multi-task compare / command palette** — the overview filter gains **error type / dry run / reworked / visual acceptance** (semantics map one-to-one onto task-snapshot fields, identical in the backend and the frontend); the insights page gains a "**Compare tasks**" section that puts **2–4** tasks side by side across status / rounds / verify time / changed lines / latest verdict and more (reports are **read on demand** and cached, anything missing shows `—` and is **never invented**); `Ctrl/Cmd + K` opens the **command palette** (subsequence fuzzy matching; jump to pages, switch data home, open a task) and `Ctrl/Cmd + R` refreshes — **all read-only interactions**.
399
+ - **Baseline review / stage gantt / disk usage / deep links** — the workspace gains a **"Baseline"** section (the pre-work `baseline.json` summary next to the latest report's actual changes, with an honest notice when absent); the event stream gains a **"Stages" view** (a state-transition gantt that reads one full pass on demand, marking the last stage "running" rather than inventing a duration); the insights page gains **"Disk usage"** (totals / `logs/` share / top-20 task sizes, plus **hint-only, never-delete** relative cleanup rules); and **`tianshu://task/<taskId>` deep links** are supported (cold and hot start, single instance revealing the existing window, handled in Rust so the webview gets no extra permission).
395
400
  - **Cross-task search / export** — scanned on demand (**no local full-text index**) with progress and cancellation, results grouped by "task → file → line" and clickable; single-file export and whole-task zip export (optionally excluding the bulky raw logs).
396
401
  - **Reports and multi-round comparison** — `.md` rendering, `.json` structured cards and a sandboxed `.html` visual preview; `dry-run-report-*` and `report-*` are shown **separately** (static analysis vs real command acceptance, which have different verdict semantics), and multiple rounds can be compared side by side.
397
402
  - **Interface and theme** — bilingual (Chinese / English) with **follow-system / light / dark** themes; a self-built "Obsidian Terminal" design system with **zero UI libraries, zero external links and zero font files**, and all icons as inline SVG.
398
403
  - **System tray and close behaviour** — a resident tray ("Show log viewer" / "Quit log viewer", with labels following the UI language immediately); by default **closing the window minimizes to tray**, switchable to "quit the app" in settings.
399
- - **Update-notes window and dual-source auto-update** — a silent update check at startup pops the "update notes" window when a new version is found (download and install / ignore this version / later), whose body is that version's bilingual release notes; the update source is chosen by **concurrently probing Gitee / GitHub and picking the better one** (never relying on system region) and is shown truthfully, and every package is **minisign-verified** — **a failed signature is never installed**.
404
+ - **Update-notes window and dual-source auto-update** — a silent update check at startup pops the "update notes" window when a new version is found (download and install / ignore this version / later), whose body is that version's bilingual release notes, **taken from the very same source as the release page** (a missing body refuses to publish — never an empty body or a one-line title); the update source is chosen by **concurrently probing Gitee / GitHub and picking the better one** (never relying on system region) and is shown truthfully, and every package is **minisign-verified** — **a failed signature is never installed**.
400
405
 
401
406
  <p align="center">
402
407
  <a href="./assets/tianshu-mcp-gui-overview.png"><img src="./assets/tianshu-mcp-gui-overview.png" alt="Log viewer · task overview page" width="32%"></a>
@@ -446,6 +451,7 @@ Decoupling and release boundaries (read before changing anything here):
446
451
  | [docs/kimi-cdp.en.md](docs/kimi-cdp.en.md) | Kimi Code: dual renderer processes, workspace full-path binding and native import, three-level model selection and reasoning levels |
447
452
  | [docs/qoder-cdp.en.md](docs/qoder-cdp.en.md) | Qoder CN: install discovery and instance reuse, native workspace import, `modelSource` and global reasoning level, same-session rework |
448
453
  | [docs/opendesign-cdp.en.md](docs/opendesign-cdp.en.md) | Open Design: data-directory derivation, sidecar root-process detection, selector evidence table and the 12-step chain, dual-path transport, failure codes |
454
+ | docs/minimax-cdp.en.md | MiniMax Code: dual renderer processes, the model second-level submenu (reasoning level / context window) with per-model candidates, full-path project binding, the native `Select Directory` dialog |
449
455
 
450
456
  **Acceptance and observability**
451
457
 
@@ -518,14 +524,13 @@ Thanks to the community members who contributed through issues and pull requests
518
524
 
519
525
  <table>
520
526
  <tr>
521
- <td align="center"><a href="https://github.com/liuchsong"><img src="https://github.com/liuchsong.png" width="72" height="72" alt="liuchsong" /><br /><sub>liuchsong</sub></a></td>
522
- <td align="center"><a href="https://github.com/a13612745638"><img src="https://github.com/a13612745638.png" width="72" height="72" alt="a13612745638" /><br /><sub>a13612745638</sub></a></td>
523
- <td align="center"><a href="https://github.com/king195547"><img src="https://github.com/king195547.png" width="72" height="72" alt="king195547" /><br /><sub>king195547</sub></a></td>
524
- </tr>
525
- <tr>
526
- <td align="center"><a href="https://github.com/zhaoxc857"><img src="https://github.com/zhaoxc857.png" width="72" height="72" alt="zhaoxc857" /><br /><sub>zhaoxc857</sub></a></td>
527
- <td align="center"><a href="https://github.com/jian-in"><img src="https://github.com/jian-in.png" width="72" height="72" alt="jian-in" /><br /><sub>jian-in</sub></a></td>
528
- <td align="center"><a href="https://github.com/huiliyi37"><img src="https://github.com/huiliyi37.png" width="72" height="72" alt="huiliyi37" /><br /><sub>huiliyi37</sub></a></td>
527
+ <td align="center"><a href="https://github.com/liuchsong"><img src="https://github.com/liuchsong.png" width="50" height="50" alt="liuchsong" /><br /><sub>liuchsong</sub></a></td>
528
+ <td align="center"><a href="https://github.com/a13612745638"><img src="https://github.com/a13612745638.png" width="50" height="50" alt="a13612745638" /><br /><sub>a13612745638</sub></a></td>
529
+ <td align="center"><a href="https://github.com/king195547"><img src="https://github.com/king195547.png" width="50" height="50" alt="king195547" /><br /><sub>king195547</sub></a></td>
530
+ <td align="center"><a href="https://github.com/zhaoxc857"><img src="https://github.com/zhaoxc857.png" width="50" height="50" alt="zhaoxc857" /><br /><sub>zhaoxc857</sub></a></td>
531
+ <td align="center"><a href="https://github.com/jian-in"><img src="https://github.com/jian-in.png" width="50" height="50" alt="jian-in" /><br /><sub>jian-in</sub></a></td>
532
+ <td align="center"><a href="https://github.com/huiliyi37"><img src="https://github.com/huiliyi37.png" width="50" height="50" alt="huiliyi37" /><br /><sub>huiliyi37</sub></a></td>
533
+ <td align="center"><a href="https://github.com/MToF0214"><img src="https://github.com/MToF0214.png" width="50" height="50" alt="MToF0214" /><br /><sub>MToF0214</sub></a></td>
529
534
  </tr>
530
535
  </table>
531
536
 
package/README.md CHANGED
@@ -63,7 +63,7 @@
63
63
  ↓ MCP over stdio(stdout 仅承载 JSON-RPC)
64
64
  tianshu-mcp ← 调度 · 执行面 · 验收仪
65
65
  ↓
66
- Codex · TraeWork · ZCode · Kimi Code · Qoder CN · Open Design
66
+ Codex · TraeWork · ZCode · Kimi Code · Qoder CN · Open Design · MiniMax Code
67
67
  ↓(GUI 经 CDP 驱动桌面 UI;CLI 走子进程)
68
68
  目标项目工作区 ← git 仓库 + 测试 + .tianshu-mcp/
69
69
  ```
@@ -227,7 +227,7 @@ run_task(projectPath=D:/xxx/my-app, task="…任务书…", agentId=codex,
227
227
  | 工具 | 能力 / 审批 | 作用 |
228
228
  |---|---|---|
229
229
  | `run_task` | write + 审批 | 派活(可带自动验收 / 自动返修),异步返回 `taskId`;可选 `idempotencyKey`、`acceptanceOverride` 与 `dryRun` |
230
- | `continue_task` | write + 审批 | 恢复 `needs_user` 的原会话(ZCode / Codex / Kimi Code / Qoder CN 各有恢复语义) |
230
+ | `continue_task` | write + 审批 | 恢复 `needs_user` 的原会话(ZCode / Codex / Kimi Code / Qoder CN / MiniMax Code 各有恢复语义) |
231
231
  | `query_task` | read | 轮询状态 / 进度 / 日志尾 / 最近细粒度事件(可选 `eventLimit`) |
232
232
  | `list_tasks` | read | 历史任务过滤列表 |
233
233
  | `get_task_report` | read | 某轮验收报告全文(`report.md`) |
@@ -256,9 +256,10 @@ run_task(projectPath=D:/xxx/my-app, task="…任务书…", agentId=codex,
256
256
  | `kimicode` | `gui` / `kimicode-gui` | **ready**(macOS 为 `research`) | Kimi Code 桌面端(Electron);**双渲染进程**(主窗口 + `Kimi Browser Overlay` 浮层承载模型 / 档位 / 模式菜单);工作区以完整路径绑定;支持 `model` / `reasoningLevel`,**不支持 `mode`**,且**不支持无项目派发** |
257
257
  | `qoder` | `gui` / `qoder-gui` | Windows 真机闭环通过;macOS **research** | 仅 Qoder CN;必须提供已有 `projectPath` 与可读 `planDoc`;`modelSource=default\|custom` 消除同名模型歧义,思考等级经「模型管理」保存为全局偏好并回读 |
258
258
  | `opendesign` | `gui` / `opendesign-gui` | **ready**(macOS 为 `research`) | Open Design 桌面端 GUI;选择器取自产品自身 Web 前端的 `data-testid` 钩子,12 步执行链全部接线,并接入验收 → 自动返修 → 再验收闭环;它是唯一带「产物信号」(文件 mtime / 大小指纹)的 driver |
259
+ | `minimax` | `gui` / `minimax-gui` | **ready**(macOS 为 `research`) | MiniMax Code 桌面端(Electron);**双渲染进程**(主窗口 + `Model menu` 弹层);推理等级 / 上下文窗口在**悬停模型项展开的二级子菜单**里,且**候选集合随模型变化**(无子菜单的模型请求这两项即 fail-closed);支持 `model` / `reasoningLevel` / **`contextWindow`**(本适配器专属),**不支持 `mode`**,且**不支持无项目派发**;「新建项目」为**应用内模态框 → 原生 `Select Directory` → 模态框提交**两步 |
259
260
  | `stub` | `spawn` | 仅测试 | `test/stub-agent/stub-agent.mjs` 三剧本(good / fix-on-first / never) |
260
261
 
261
- > `mode` 支持 `Work` / `Code` / `Design`(仅 TraeWork),不传时从任务书文本识别。Kimi Code 的 `reasoningLevel` 按**界面实际渲染的档位集合**校验(官方模型 `低` / `高` / `max`,非官方模型仅 `on` / `off`)。新增 agent 通常只需加一个 profile,详见 [docs/agent-profiles.md](docs/agent-profiles.md) 与 [CONTRIBUTING.md](CONTRIBUTING.md)。
262
+ > `mode` 支持 `Work` / `Code` / `Design`(仅 TraeWork),不传时从任务书文本识别。Kimi Code 的 `reasoningLevel` 按**界面实际渲染的档位集合**校验(官方模型 `低` / `高` / `max`,非官方模型仅 `on` / `off`)。MiniMax Code 的 `reasoningLevel` / `contextWindow` 同样按**界面实际候选**校验(如 `M3.1-Flash-Preview` 为 `default`/`low`/`medium`/`high`/`xhigh`/`max` 与 `512K`/`1M`,而 `M3` 无档位组、`deepseek-v4.1-flash` 无窗口组),越权或读不到即 fail-closed。新增 agent 通常只需加一个 profile,详见 [docs/agent-profiles.md](docs/agent-profiles.md) 与 [CONTRIBUTING.md](CONTRIBUTING.md)。
262
263
 
263
264
  ### macOS 无头路径:codex-cli(用户 profile)
264
265
 
@@ -370,6 +371,7 @@ run_task(projectPath=D:/xxx/my-app, task="…任务书…", agentId=codex,
370
371
  | 视觉与幂等 | 0.5.x | 视觉验收(0.5.0)+ 可选 AI 内容校验(0.5.4)、ZCode 无项目派发、Kimi Code / Qoder CN 适配、幂等键(0.5.10) |
371
372
  | 加固与可观测 | 0.6.x | 技能自装加固(0.6.0)、GUI 选择器漂移修复(0.6.2)、细粒度事件流、结构化修复指令、dryRun、验收配置三级继承、终态通知 |
372
373
  | Open Design | 0.7.x | Open Design 桌面端适配(0.7.1)、ZCode 3.14.x 绑定契约修复(0.7.4) |
374
+ | MiniMax Code | 0.7.8 | 第七个 GUI agent 接入(0.7.8);真机取证修正三处结构假设(二级子菜单 / 集合随模型变化 / 项目创建两步),新增 `contextWindow` 参数与只读诊断探针 |
373
375
  | 日志台 GUI | `gui-v*`(独立线) | `mcp-gui/` 本地只读日志台(Tauri 2.x + Vue 3),独立版本与 tag,**不随 MCP 主包发布** |
374
376
 
375
377
  > 完整逐版记录见 [CHANGELOG.md](CHANGELOG.md),交接状态与排障手册见 [HANDOFF.md](HANDOFF.md),工程质量口径见 [ARCHITECTURE.md](ARCHITECTURE.md)。
@@ -392,11 +394,13 @@ run_task(projectPath=D:/xxx/my-app, task="…任务书…", agentId=codex,
392
394
  主要能力:
393
395
 
394
396
  - **大日志与实时跟随** —— 首屏只读尾部 64 KiB 窗口、向前按块加载并显示「已加载 N / 共 M」;文件被追加时增量刷新,**上翻自动暂停跟随**,可一键「跳到最新」。
395
- - **跨任务搜索 / 导出** —— 按需扫描(**不建本地全文索引**)+ 进度反馈 + 可取消,命中按「任务 → 文件 → 行」分组并可跳转;支持单文件导出与任务整包 zip(可排除体积大的原始日志)。
397
+ - **洞察(效能 / 归因 / 趋势)** —— 只读聚合:按 Agent 与按项目的**效能看板**(任务数 / 成功率 / 平均轮次 / 一次通过率 / 平均验收耗时 / 报告缺失)、四类**失败归因** TOP 列表(`errorType` / 失败检查项 / 阻塞问题 / 代码信号)、按天 / 按周的**任务量与成功率、返修率趋势**(纯内联 SVG,不引图表库)。口径显式标注(UTC 日期、周一为周始、「一次通过」= 成功且仅 1 轮、只统计每个任务的**最新一轮**报告),**只读统计、不提供删除 / 清理**。
398
+ - **结构化筛选 / 多任务对比 / 命令面板** —— 概览页筛选新增**错误类型 / 干跑 / 返修 / 视觉验收**四项(口径与任务快照字段一一对应,前后端同口径);洞察页新增「**任务对比**」子分区,勾选 **2–4 个** 任务并排看状态 / 轮次 / 验收耗时 / 改动行数 / 最新报告判定等指标(报告**按需读取**并缓存,缺失一律显示 `—`,**不编造**);`Ctrl/Cmd + K` 打开**命令面板**(子序列模糊匹配,跳页面 / 切数据目录 / 直接打开任务),`Ctrl/Cmd + R` 刷新,**全部为只读交互**。
399
+ - **基线与复盘 / 阶段甘特 / 磁盘占用 / 深链** —— 工作区新增**「基线」**分区(动工前 `baseline.json` 摘要并与最新报告改动对照,缺失如实提示);事件流新增**「阶段」视图**(状态跃迁甘特,按需读一次全量,最后一段标「进行中」不编造时长);洞察页新增**「磁盘占用」**(总量 / logs 占比 / 体积 TOP 20 / **只提示不删除**的「可清理」相对判据);支持 **`tianshu://task/<任务ID>` 深链**(冷启动 + 热启动、单实例唤出已有窗口,Rust 侧处理故不给 webview 多余权限)。
396
400
  - **报告与多轮对比** —— `.md` 渲染、`.json` 结构化卡片、视觉 `.html` 沙箱预览;`dry-run-report-*` 与 `report-*` **分开展示**(静态分析 vs 真实命令验收,结论口径不同),多轮报告可并排对比。
397
401
  - **界面与主题** —— 中英双语、**跟随系统 / 浅色 / 深色**三选一;自研「黑曜石终端」设计系统,**零 UI 库、零外链、零字体文件**,图标一律内联 SVG。
398
402
  - **系统托盘与关闭行为** —— 常驻托盘(「显示日志台 / 退出日志台」,文案随界面语言即时切换),默认 **关闭窗口 = 缩小到托盘**,可在设置面板改为「关闭应用」。
399
- - **更新日志窗口与双源自动更新** —— 启动静默检查更新,命中即弹「更新日志」(下载并安装 / 忽略此版本 / 稍后),正文即该版本的双语发行说明;更新源由 **Gitee / GitHub 并发实测择优**(不依赖系统区域)决定并如实展示,包体经 **minisign 验签**,**验签不通过一律拒绝安装**。
403
+ - **更新日志窗口与双源自动更新** —— 启动静默检查更新,命中即弹「更新日志」(下载并安装 / 忽略此版本 / 稍后),正文即该版本的双语发行说明,**与发行页同源同一份**(正文缺失即拒绝发版,不产出空正文 / 单行标题);更新源由 **Gitee / GitHub 并发实测择优**(不依赖系统区域)决定并如实展示,包体经 **minisign 验签**,**验签不通过一律拒绝安装**。
400
404
 
401
405
  <p align="center">
402
406
  <a href="./assets/tianshu-mcp-gui-overview.png"><img src="./assets/tianshu-mcp-gui-overview.png" alt="日志台 · 任务概览页" width="32%"></a>
@@ -446,6 +450,7 @@ run_task(projectPath=D:/xxx/my-app, task="…任务书…", agentId=codex,
446
450
  | [docs/kimi-cdp.md](docs/kimi-cdp.md) | Kimi Code:双渲染进程、工作区完整路径绑定与原生导入、模型三级选择与思考档位 |
447
451
  | [docs/qoder-cdp.md](docs/qoder-cdp.md) | Qoder CN:安装发现与实例复用、工作区原生导入、`modelSource` 与全局思考等级、原会话返修 |
448
452
  | [docs/opendesign-cdp.md](docs/opendesign-cdp.md) | Open Design:数据目录推导、sidecar 根进程判定、选择器取证表与 12 步执行链、传输层双路径、失败码表 |
453
+ | docs/minimax-cdp.md | MiniMax Code:双渲染进程、模型二级子菜单(推理等级 / 上下文窗口)与逐模型候选、完整路径项目绑定、`Select Directory` 原生对话框 |
449
454
 
450
455
  **验收与可观测**
451
456
 
@@ -518,14 +523,13 @@ npm run check:stdio # 严格 stdio 冒烟(真实进程字节流校验)
518
523
 
519
524
  <table>
520
525
  <tr>
521
- <td align="center"><a href="https://github.com/liuchsong"><img src="https://github.com/liuchsong.png" width="72" height="72" alt="liuchsong" /><br /><sub>liuchsong</sub></a></td>
522
- <td align="center"><a href="https://github.com/a13612745638"><img src="https://github.com/a13612745638.png" width="72" height="72" alt="a13612745638" /><br /><sub>a13612745638</sub></a></td>
523
- <td align="center"><a href="https://github.com/king195547"><img src="https://github.com/king195547.png" width="72" height="72" alt="king195547" /><br /><sub>king195547</sub></a></td>
524
- </tr>
525
- <tr>
526
- <td align="center"><a href="https://github.com/zhaoxc857"><img src="https://github.com/zhaoxc857.png" width="72" height="72" alt="zhaoxc857" /><br /><sub>zhaoxc857</sub></a></td>
527
- <td align="center"><a href="https://github.com/jian-in"><img src="https://github.com/jian-in.png" width="72" height="72" alt="jian-in" /><br /><sub>jian-in</sub></a></td>
528
- <td align="center"><a href="https://github.com/huiliyi37"><img src="https://github.com/huiliyi37.png" width="72" height="72" alt="huiliyi37" /><br /><sub>huiliyi37</sub></a></td>
526
+ <td align="center"><a href="https://github.com/liuchsong"><img src="https://github.com/liuchsong.png" width="50" height="50" alt="liuchsong" /><br /><sub>liuchsong</sub></a></td>
527
+ <td align="center"><a href="https://github.com/a13612745638"><img src="https://github.com/a13612745638.png" width="50" height="50" alt="a13612745638" /><br /><sub>a13612745638</sub></a></td>
528
+ <td align="center"><a href="https://github.com/king195547"><img src="https://github.com/king195547.png" width="50" height="50" alt="king195547" /><br /><sub>king195547</sub></a></td>
529
+ <td align="center"><a href="https://github.com/zhaoxc857"><img src="https://github.com/zhaoxc857.png" width="50" height="50" alt="zhaoxc857" /><br /><sub>zhaoxc857</sub></a></td>
530
+ <td align="center"><a href="https://github.com/jian-in"><img src="https://github.com/jian-in.png" width="50" height="50" alt="jian-in" /><br /><sub>jian-in</sub></a></td>
531
+ <td align="center"><a href="https://github.com/huiliyi37"><img src="https://github.com/huiliyi37.png" width="50" height="50" alt="huiliyi37" /><br /><sub>huiliyi37</sub></a></td>
532
+ <td align="center"><a href="https://github.com/MToF0214"><img src="https://github.com/MToF0214.png" width="50" height="50" alt="MToF0214" /><br /><sub>MToF0214</sub></a></td>
529
533
  </tr>
530
534
  </table>
531
535
 
@@ -1,7 +1,9 @@
1
1
  import { ZCODE_SETUP_DEFAULTS } from "../config/schema.js";
2
2
  import { QODER_PROFILE } from "./qoder/profile.js";
3
+ import { MINIMAX_PROFILE } from "./minimax/profile.js";
3
4
  export const BUILTIN_PROFILES = {
4
5
  qoder: QODER_PROFILE,
6
+ minimax: MINIMAX_PROFILE,
5
7
  codex: {
6
8
  displayName: "Codex (ChatGPT 桌面端 GUI)",
7
9
  type: "cli",
@@ -0,0 +1,72 @@
1
+ import path from "node:path";
2
+ /**
3
+ * 同一台机器上 MiniMax Code 只有一个受管实例:与 Kimi Code / Qoder / Open Design 同构的
4
+ * **全局串行门**。并行派活会两条流程同时点同一个「模型」/「项目」菜单,必然互相踩踏;
5
+ * 而模型弹层是**独立窗口**,两条流程的 hover 二级子菜单会互相覆盖。
6
+ */
7
+ let serial = Promise.resolve();
8
+ async function waitForPrevious(previous, signal) {
9
+ if (!signal) {
10
+ await previous;
11
+ return true;
12
+ }
13
+ if (signal.aborted)
14
+ return false;
15
+ let onAbort;
16
+ const aborted = new Promise((resolve) => {
17
+ onAbort = () => resolve(false);
18
+ signal.addEventListener("abort", onAbort, { once: true });
19
+ });
20
+ try {
21
+ return await Promise.race([previous.then(() => true), aborted]);
22
+ }
23
+ finally {
24
+ if (onAbort)
25
+ signal.removeEventListener("abort", onAbort);
26
+ }
27
+ }
28
+ export class MinimaxGuiAdapter {
29
+ id;
30
+ constructor(id) {
31
+ this.id = id;
32
+ }
33
+ buildInvocation() {
34
+ throw new Error("minimax-gui 不通过 spawn 执行");
35
+ }
36
+ parseExit(res) {
37
+ return { ...res, hardFailure: Boolean(res.error && res.exitCode === null) };
38
+ }
39
+ async run(ctx, resolved, opts) {
40
+ const previous = serial;
41
+ let release;
42
+ const gate = new Promise((resolve) => {
43
+ release = resolve;
44
+ });
45
+ // 串行链即使本次等待方被取消,也保留前一个持有者:后续任务不可能与它重叠执行。
46
+ serial = previous.then(() => gate);
47
+ try {
48
+ if (!(await waitForPrevious(previous, opts.signal))) {
49
+ return {
50
+ ok: false,
51
+ exitCode: null,
52
+ timeout: false,
53
+ killed: true,
54
+ durationMs: 0,
55
+ logFile: path.join(ctx.taskDir, `agent-${ctx.round}.log`),
56
+ endReason: "aborted",
57
+ keptInstance: true,
58
+ };
59
+ }
60
+ const { runMinimaxTask } = await import("./run.js");
61
+ return await runMinimaxTask({
62
+ ctx,
63
+ resolved,
64
+ opts,
65
+ logFile: path.join(ctx.taskDir, `agent-${ctx.round}.log`),
66
+ });
67
+ }
68
+ finally {
69
+ release();
70
+ }
71
+ }
72
+ }