Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
ab59020
docs(webui): the engine layer has six files, not five (webui-parity 107)
fengzhi09 Oct 1, 2026
1dc559a
test(webui): M2 capability-declaration snapshot vs the real host (eng…
fengzhi09 Oct 1, 2026
8c085fa
test(webui): point the capability snapshot at the engine layer's real…
fengzhi09 Oct 1, 2026
aa5ab47
fix(webui): stop the shell from carrying one session's state into ano…
fengzhi09 Oct 1, 2026
af01e0e
refactor(webui): the plugins and turn-diff routes take the host from …
fengzhi09 Oct 1, 2026
f1842ba
test(webui): make the run-mirror, first-turn-guard and mavis-usage su…
fengzhi09 Oct 1, 2026
726d286
refactor(webui): the plugins and turn-diff routes take the host from …
fengzhi09 Oct 1, 2026
a4fad96
test(webui): make the run-mirror, first-turn-guard and mavis-usage su…
fengzhi09 Oct 1, 2026
e7c0ce9
feat(webui): the five read endpoints ask the engine facade, not the t…
fengzhi09 Oct 1, 2026
e053ae7
feat(webui): the session-tree and export endpoints ask the engine fac…
fengzhi09 Oct 1, 2026
4fb8267
feat(webui): the usage endpoints ask the engine facade, and the deriv…
fengzhi09 Oct 1, 2026
88b9a48
fix(webui): rebase M3-B3 onto M3-B2, register B2's two tmp prefixes, …
fengzhi09 Oct 1, 2026
6bc24bd
feat(webui): the account, model and capability reads ask the engine f…
fengzhi09 Oct 2, 2026
eb2a429
feat(webui): #73 swaps the ACP wire table for the 14-key engine-capab…
fengzhi09 Oct 2, 2026
2baf051
fix(webui): stop two B4 comments describing behaviour the code no lon…
fengzhi09 Oct 2, 2026
edf2b1e
feat(webui): move the session write family behind the engine facade
fengzhi09 Oct 2, 2026
1506cc2
fix(webui): drop whitespace text nodes in markdown tables and dedupe …
fengzhi09 Oct 2, 2026
8cca235
fix(webui): sweep the non-flipping inverted text token off primary su…
fengzhi09 Oct 2, 2026
eecd8c0
feat(webui): move session switch behind the engine facade
fengzhi09 Oct 2, 2026
0cfd51f
Merge main into dev-lhl
fengzhi09 Oct 2, 2026
e4cf052
chore: allowlist the leak-tripwire fixture in model-reads tests
fengzhi09 Oct 2, 2026
3f5b8d2
test(webui): pin session-writes cleanup-orphans test to isolated paths
fengzhi09 Oct 2, 2026
e7df93d
chore: ignore gitleaks fingerprints of deliberate test fixtures
fengzhi09 Oct 2, 2026
62814ff
chore: make the gitleaks fixture allowlists path-only
fengzhi09 Oct 2, 2026
3074010
feat(webui): move interrupt and load endpoints behind the engine facade
fengzhi09 Oct 3, 2026
063a43a
fix(webui): take the plan's 5s abort force-kill bound by product call
fengzhi09 Oct 3, 2026
90cf85e
Merge main into dev-lhl
fengzhi09 Oct 3, 2026
a9af820
docs(webui): add session-switch, interrupt and session-load to the ar…
fengzhi09 Oct 3, 2026
4d904c3
docs(webui): add the missing zh-CN section for the B5 write family
fengzhi09 Oct 3, 2026
fdc3ff2
fix(webui): make webui-only session delete return promptly instead of…
fengzhi09 Oct 3, 2026
dab453d
fix(webui): retire lossy streaming mirrors when the engine transcript…
fengzhi09 Oct 3, 2026
7138b5b
feat(webui): add the streaming-send capability gate and pure stream b…
fengzhi09 Oct 3, 2026
a2223f4
feat(webui): run send on the runtime transport behind the engine facade
fengzhi09 Oct 3, 2026
8b51fdd
Merge main into dev-lhl
fengzhi09 Oct 3, 2026
964c0cf
feat(webui): answer set-mode and set-config-option with structured 50…
fengzhi09 Oct 3, 2026
bdde1eb
Merge main into dev-lhl
fengzhi09 Oct 3, 2026
a112e45
Merge main into dev-lhl
fengzhi09 Oct 3, 2026
245a101
docs(webui): add the streaming-send architecture section, bilingual
fengzhi09 Oct 3, 2026
d9e181d
Merge main into dev-lhl
fengzhi09 Oct 3, 2026
679d0fe
docs(webui): add the streaming-send architecture section, bilingual
fengzhi09 Oct 3, 2026
a078ee6
Merge main into dev-lhl
fengzhi09 Oct 3, 2026
591ccff
Merge main into dev-lhl
fengzhi09 Oct 3, 2026
b529543
fix(local-runtime): make an abandoned migration lease recoverable at …
fengzhi09 Oct 3, 2026
a8e56dc
feat(webui): move model and permission writes behind the engine facade
fengzhi09 Oct 3, 2026
48199c5
Reset dev-lhl to the full local integration line (B9+B10+docs+P13+P14…
fengzhi09 Oct 3, 2026
5661bb9
Merge main into dev-lhl
fengzhi09 Oct 3, 2026
4b5e8d2
Merge main into dev-lhl
fengzhi09 Oct 3, 2026
9fdd8d1
fix(webui): surface truncated acp stderr in failure alerts
fengzhi09 Oct 3, 2026
5427f23
feat(webui): move the provider family behind the engine facade with s…
fengzhi09 Oct 3, 2026
afa995e
fix(webui): acknowledge in-flight messages explicitly instead of echo…
fengzhi09 Oct 3, 2026
6c30484
fix(webui): normalise the expected side of the provider cwd path asse…
fengzhi09 Oct 3, 2026
e68a8df
feat(webui): bridge thinkingEffort as the third config id and gate th…
fengzhi09 Oct 3, 2026
1473183
Merge main into dev-lhl
fengzhi09 Oct 3, 2026
15a3f42
feat(webui): register the acp transport as the first engine capabilit…
fengzhi09 Oct 3, 2026
313286a
fix(webui): keep over-tall code blocks inside their scroll container
fengzhi09 Oct 3, 2026
506c0a9
feat(webui): replace the flat provider form with the desktop-style di…
fengzhi09 Oct 3, 2026
25da27a
docs(webui): document the provider dialog interaction, bilingual
fengzhi09 Oct 3, 2026
38befac
feat(webui): route session deletion through the engine deleteSession …
fengzhi09 Oct 3, 2026
06a0e8e
feat(webui): open the host services window for capability exposure ba…
fengzhi09 Oct 3, 2026
60e5361
feat(webui): register the exec transport in the engine capability reg…
fengzhi09 Oct 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 118 additions & 14 deletions docs/webui.md

Large diffs are not rendered by default.

141 changes: 134 additions & 7 deletions docs/webui.zh-CN.md

Large diffs are not rendered by default.

16 changes: 16 additions & 0 deletions packages/local-runtime-v2/src/local/host-contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type {
} from '@mavis/local-runtime';
import type { LocalBrowserAdapter, LocalBrowserToolExposure } from '@mavis/agent-tools/desktop';
import type { RuntimeApplications } from '../application/initialize.js';
import type { RuntimeServices } from '../services.js';
import type {
MiniAppPresenter,
LocalRuntimeApplication,
Expand Down Expand Up @@ -80,6 +81,21 @@ interface CreatedLocalRuntimeHost extends V1CreatedLocalRuntimeHost {
*/
applications?: RuntimeApplications;
cliService?: import('./cli-service.js').CliService;
/**
* The composed V2 service owners (`managedWorktrees`, `pinService`,
* `agent`, `mcp`, `skill`, `modelSystem`, …), handed to the embedder
* as-is. Distinct from `application` / `applications`: those two are
* the PRODUCT use cases, this is the OWNER graph behind them, so a
* consumer that finds no use case it can call (`agent` has none on
* the process-local facade) still has a real path to the capability.
*
* Optional because a host without the V2 compatibility slice
* (`compatibility === undefined`) has no service owners at all — the
* member is absent rather than an empty object, so "no owner" and
* "owner with no members" cannot be confused. Every member is
* `readonly`; lifecycle stays with the host's `close()`.
*/
services?: RuntimeServices;
}

export type {
Expand Down
7 changes: 7 additions & 0 deletions packages/local-runtime-v2/src/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,13 @@ function createStartedHost(
? {
application: ownerRuntime.services.application,
applications: ownerRuntime.services.applications,
// The owner graph itself, for embedders whose product facade
// carries no use case for a capability the services do own
// (the process-local facade declares no `agent` member, while
// `services.agent` is a full AgentApplication). Same object,
// same lifetime: `services.close()` stays reached only through
// the host's own shutdown path.
services: ownerRuntime.services,
}
: {}),
...(cliService ? { cliService } : {}),
Expand Down
42 changes: 39 additions & 3 deletions packages/webui/docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -2697,8 +2697,17 @@ There is no manual `?v=N` cache-bust any more — every chunk URL under
Read-only, declaration-backed: which of the 14 engine capability keys a
provider supports, plus the `unavailable` summary the capability-driven
UI renders from. Boots no host and runs no probe. `?provider=` defaults
to `local-runtime-v2`; the other registered surface is
`tui-runtime-adapter`.
to `local-runtime-v2` — unchanged since B1, so every existing caller keeps the
declaration it had. The other three registered providers are
`tui-runtime-adapter` (the in-process adapter surface), `acp` (the
`mcode acp` subprocess protocol) and `exec` (the one-shot `mcode exec`
subprocess).

Registering a provider is not routing it. Both `acp` and `exec` are
registered and unreachable: no capability gate resolves to either of
them, so a server running on either transport still evaluates every
gate against no provider at all. `?provider=exec` is answerable today;
a gate that consults the exec declaration is M4-3's work.

**Response 200**
```json
Expand All @@ -2716,9 +2725,36 @@ to `local-runtime-v2`; the other registered surface is
```
(`capabilities` carries all 14 keys; three are shown.)

A `none` entry may carry an extra `servedBy: "<providerId>"` alongside its
`reason`. It does not change the level or the `unavailable` roll-up — the
provider really has none of that capability. It records that webui still
serves the endpoint, from another provider's in-process host. Both
transport providers use it for exactly two keys (`turnDiff`, `plugins`):
neither the acp protocol nor the exec CLI has a diff method or a plugin
method, yet those thirteen endpoints work on either transport because
they project the in-process local-runtime-v2 host and gate on no
transport at all. That is why the field is a per-key declaration field
rather than an acp special case: the exception belongs to the two
routes, so every transport inherits it. A client that wants to know who
answers a request should treat `servedBy` as "not a degradation" — and
must not read it as the capability being present.

The `exec` declaration is the one worth reading before writing a client
against it, because its shape follows from the transport having **no
request channel**: `mcode exec` takes a prompt on stdin and writes a
`stream-json` event stream to stdout, so there are no methods to call
and nothing to declare `full` except sending. It is `full` on
`streamingSend`, `partial` on `sessionCrud` (it can re-enter or resume an
existing session but cannot list, load, close or delete one), `partial`
on `toolSkillInvocation`, `mcp` and `usageStats`, and `none` on the other
six — including `interrupt` and `authCredentials`, which the acp provider
answers `partial`. Each `reason` names the file and line it was taken
from, and the level is a statement about the transport's interface, not
about which endpoints currently respond under it.

**Errors** — `404 {"ok":false,"code":"unknown_engine_provider","knownProviders":[…]}` for an unknown `?provider=` (caller confusion — never 501). Any future route gated on an undeclared capability answers `501 {"ok":false,"code":"engine_capability_not_supported","capability","provider","missing"?,"reason"?}` — expected degradation, not a server fault; treat it as "hide the entry point", not as an error toast.

Contract details (the 14-key table, both providers' levels, the
Contract details (the 14-key table, every provider's levels, the
migration state) live in [`docs/webui.md`](../../../docs/webui.md)
under "Engine capability declaration".

Expand Down
32 changes: 29 additions & 3 deletions packages/webui/docs/API.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -2487,8 +2487,15 @@ chunk URL 都做内容寻址,rebuild 时自动失效。

只读、声明直出:返回某个 provider 在 14 个引擎能力键上的支持档位,
附前端能力驱动渲染所用的 `unavailable` 汇总。不起 host、不探测。
`?provider=` 缺省为 `local-runtime-v2`;另一个已注册面是
`tui-runtime-adapter`。
`?provider=` 缺省为 `local-runtime-v2`(自 B1 起未变);另外三个已注册的
provider 是 `tui-runtime-adapter`(进程内 adapter 面)、`acp`
(`mcode acp` 子进程协议,传输面)与 `exec`(一次性 `mcode exec`
子进程,传输面)。

注册 provider 不等于把它接进路由。`acp` 与 `exec` 都已注册但不可达:
没有任何能力门控会解析到它们,因此跑在这两条传输上的 server 对每道门控
仍然按「没有 provider」来评估。`?provider=exec` 今天就能作答;会去查
exec 声明的门控属于 M4-3 的活。

**Response 200**
```json
Expand All @@ -2506,9 +2513,28 @@ chunk URL 都做内容寻址,rebuild 时自动失效。
```
(`capabilities` 实际含全部 14 键;此处示例 3 个。)

`none` 条目除 `reason` 外还可带一个 `servedBy: "<providerId>"`。它**不改变**
档位,也不改变 `unavailable` 汇总——该 provider 确实没有这个能力。它记录的是
webui 仍从另一个 provider 的进程内 host 服务该端点。两个传输 provider 都只对
两个键用它(`turnDiff`、`plugins`):acp 协议与 exec CLI 既无 diff 方法也无
插件方法,但那十三个端点在任一条传输上都可用,因为它们投影的是进程内
local-runtime-v2 host 且完全不按传输门控。这正是该字段是「逐键声明字段」而
不是 acp 特例的原因:这个例外属于那两个路由,所以每条传输都继承它。客户端若
想知道「由谁应答」,应把 `servedBy` 读作「这不是降级」——但绝不可读作该能力
可用。

写客户端之前值得先读 `exec` 那份声明,因为它的形状源自这条传输
**没有请求通道**:`mcode exec` 从 stdin 取 prompt、向 stdout 写
`stream-json` 事件流,因此没有方法可调,除了「发送」之外没有哪一项能声明成
`full`。它是 `streamingSend` 为 `full`,`sessionCrud`(能重新进入或续接已有
会话,但列举不了、加载不了、关不掉、删不掉)、`toolSkillInvocation`、`mcp`、
`usageStats` 为 `partial`,其余六键为 `none`——其中包含 acp provider 答成
`partial` 的 `interrupt` 与 `authCredentials`。每条 `reason` 都写明取证的文件
与行号,且档位是关于这条传输的**接口面**的陈述,而不是关于当前哪些端点会应答。

**错误** —— `?provider=` 写错答 `404 {"ok":false,"code":"unknown_engine_provider","knownProviders":[…]}`(调用方的错,绝不会是 501)。未来任何按能力门控的路由,调到未声明能力答 `501 {"ok":false,"code":"engine_capability_not_supported","capability","provider","missing"?,"reason"?}`——这是预期降级、不是服务端故障;按「隐藏入口」处理,不弹错误提示。

契约细节(14 键总表、两个 provider 的档位、迁移状态)见
契约细节(14 键总表、各 provider 的档位、迁移状态)见
[`docs/webui.zh-CN.md`](../../../docs/webui.zh-CN.md) 的
「引擎能力声明」一节。

Expand Down
Loading
Loading