@ckanner/flywheel 0.33.0 → 0.33.1
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 +10 -0
- package/dist/client.js +67 -5
- package/docs/design.md +1 -1
- package/docs/en/flow-console.md +1 -1
- package/docs/validation/2026-11-14-release-0.33.0.md +49 -0
- package/docs/validation/README.md +1 -0
- package/docs/zh-CN/flow-console.md +1 -1
- package/native/darwin-amd64/flywheel +0 -0
- package/native/darwin-arm64/flywheel +0 -0
- package/native/linux-amd64/flywheel +0 -0
- package/native/linux-arm64/flywheel +0 -0
- package/native/manifest.json +5 -5
- package/package.json +2 -2
- package/plugins/dsh/PROTOCOL.md +2 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,16 @@ results are recorded separately in the [release runbook](docs/en/releasing.md)
|
|
|
5
5
|
and [validation index](docs/validation/README.md). Historical entries retain
|
|
6
6
|
their original language.
|
|
7
7
|
|
|
8
|
+
## 0.33.1 — Strict desktop read codecs
|
|
9
|
+
|
|
10
|
+
- Fix task discovery and configuration reads rejected by the actual DSH Client
|
|
11
|
+
Gateway. Supply strict schema factories for session identity, read requests and
|
|
12
|
+
result envelopes; consume the dynamic namespace through an owned injected
|
|
13
|
+
scope, use the host Agent registry's `agentId` wire field, and preserve session
|
|
14
|
+
isolation, teardown and silent reads.
|
|
15
|
+
- Exercise the shipped Client descriptor through the real public Client and Host
|
|
16
|
+
Gateway on both supported host fixtures instead of mocking Remote mounting.
|
|
17
|
+
|
|
8
18
|
## 0.33.0 — One complete npm distribution
|
|
9
19
|
|
|
10
20
|
- Consolidate the CLI, DSH host/client, workers, embedded skills and four native
|
package/dist/client.js
CHANGED
|
@@ -815,6 +815,53 @@ function Feedback({ control, selection, reconcile, t }) {
|
|
|
815
815
|
!selection.taskDir.trim() && h('p', null, t('taskRequired'))));
|
|
816
816
|
}
|
|
817
817
|
|
|
818
|
+
// Plain-JS external clients supply real schema factories through the public
|
|
819
|
+
// Typert codec contract; src-json is not a valid generated Client input codec.
|
|
820
|
+
function consoleReadCodec(type, parse) {
|
|
821
|
+
return { mode: 'strict', typeSymbol: '@ckanner/flywheel#' + type, create: () => ({ parse }) };
|
|
822
|
+
}
|
|
823
|
+
function consoleReadObject(value, keys, label) {
|
|
824
|
+
if (!record(value) || Object.keys(value).some(key => !keys.includes(key))) throw new Error('Invalid ' + label);
|
|
825
|
+
return value;
|
|
826
|
+
}
|
|
827
|
+
function consoleReadString(value, label) {
|
|
828
|
+
if (typeof value !== 'string' || !value.trim()) throw new Error('Invalid ' + label);
|
|
829
|
+
return value;
|
|
830
|
+
}
|
|
831
|
+
function consoleReadInput(value) {
|
|
832
|
+
consoleReadObject(value, ['action', 'taskDir', 'cwd', 'probe', 'editor', 'packet', 'runId', 'sessionKey', 'delivery'], 'console read request');
|
|
833
|
+
if (!['runs', 'status', 'config', 'config-edit', 'metrics', 'history', 'node', 'delivery', 'doctor'].includes(value.action)) throw new Error('Console Remote accepts reads only');
|
|
834
|
+
const output = { action: value.action };
|
|
835
|
+
for (const key of ['taskDir', 'cwd', 'packet', 'runId', 'sessionKey']) {
|
|
836
|
+
if (value[key] !== undefined) output[key] = consoleReadString(value[key], key);
|
|
837
|
+
}
|
|
838
|
+
if (value.probe !== undefined) {
|
|
839
|
+
if (value.action !== 'doctor' || typeof value.probe !== 'boolean') throw new Error('Invalid doctor probe');
|
|
840
|
+
output.probe = value.probe;
|
|
841
|
+
}
|
|
842
|
+
if (value.action === 'config-edit') {
|
|
843
|
+
consoleReadObject(value.editor, ['scope'], 'configuration scope');
|
|
844
|
+
if (!['global', 'project'].includes(value.editor.scope)) throw new Error('Invalid configuration scope');
|
|
845
|
+
output.editor = { scope: value.editor.scope };
|
|
846
|
+
} else if (value.editor !== undefined) throw new Error('Editor requires config-edit');
|
|
847
|
+
if (value.action === 'delivery') {
|
|
848
|
+
consoleReadObject(value.delivery, ['action', 'headBranch'], 'delivery inspection');
|
|
849
|
+
if (value.delivery.action !== 'inspect') throw new Error('Delivery Remote accepts inspection only');
|
|
850
|
+
output.delivery = { action: 'inspect' };
|
|
851
|
+
if (value.delivery.headBranch !== undefined) output.delivery.headBranch = consoleReadString(value.delivery.headBranch, 'headBranch');
|
|
852
|
+
} else if (value.delivery !== undefined) throw new Error('Delivery requires inspection');
|
|
853
|
+
if (value.action === 'node' ? !/^M\d+-T\d+$/.test(output.packet ?? '') : value.packet !== undefined) throw new Error('Invalid node packet');
|
|
854
|
+
if (value.action === 'history' ? !output.sessionKey : value.sessionKey !== undefined) throw new Error('Invalid history session key');
|
|
855
|
+
if (value.runId !== undefined && (value.action !== 'metrics' || value.runId.length > 128 || /[\0\r\n]/.test(value.runId))) throw new Error('Invalid metrics run ID');
|
|
856
|
+
return output;
|
|
857
|
+
}
|
|
858
|
+
function consoleReadResult(value) {
|
|
859
|
+
consoleReadObject(value, ['result'], 'console read result');
|
|
860
|
+
const result = consoleReadObject(value.result, ['kind', 'text'], 'console result envelope');
|
|
861
|
+
if (!['success', 'error'].includes(result.kind) || typeof result.text !== 'string') throw new Error('Invalid console result envelope');
|
|
862
|
+
return { result: { kind: result.kind, text: result.text } };
|
|
863
|
+
}
|
|
864
|
+
|
|
818
865
|
exports.inject = ['slots', 'remote', 'remote.commands', 'locale'];
|
|
819
866
|
exports.apply = function apply(ctx) {
|
|
820
867
|
ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'flywheel: locales');
|
|
@@ -833,10 +880,25 @@ exports.apply = function apply(ctx) {
|
|
|
833
880
|
const readsReady = ctx.remote.$mount({ package: '@ckanner/flywheel', descriptors: [{
|
|
834
881
|
id: '@ckanner/flywheel#flywheelConsole/read', service: 'flywheelConsole', namespace: 'flywheelConsole', method: 'read',
|
|
835
882
|
invocation: { kind: 'direct' }, parameters: [
|
|
836
|
-
{ name: 'agent', wire: '
|
|
837
|
-
{ name: 'input', wire: 'input', source: 'json', codec:
|
|
838
|
-
], cancellation: { parameter: 'signal' }, result: {
|
|
839
|
-
}] })
|
|
883
|
+
{ name: 'agent', wire: 'agentId', source: 'lookup', lookup: 'agent', codec: consoleReadCodec('SessionId', value => consoleReadString(value, 'sessionId')) },
|
|
884
|
+
{ name: 'input', wire: 'input', source: 'json', codec: consoleReadCodec('ConsoleReadRequest', consoleReadInput) },
|
|
885
|
+
], cancellation: { parameter: 'signal' }, result: { ...consoleReadCodec('ConsoleReadResult', consoleReadResult), decode: consoleReadResult },
|
|
886
|
+
}] }).then(async () => {
|
|
887
|
+
let readConsole;
|
|
888
|
+
// The namespace is installed asynchronously by $mount. Own its consumer in
|
|
889
|
+
// an injected child scope; the outer plugin cannot access undeclared services.
|
|
890
|
+
const consumer = ctx.inject(['remote.flywheelConsole'], scope => {
|
|
891
|
+
readConsole = (sessionId, request) => scope.remote.flywheelConsole.read(sessionId, request);
|
|
892
|
+
});
|
|
893
|
+
try {
|
|
894
|
+
await consumer;
|
|
895
|
+
if (disposed || !readConsole) throw new Error('Flywheel read scope is unavailable');
|
|
896
|
+
return readConsole;
|
|
897
|
+
} catch (error) {
|
|
898
|
+
await consumer.dispose();
|
|
899
|
+
throw error;
|
|
900
|
+
}
|
|
901
|
+
});
|
|
840
902
|
// A missing read capability is a visible error, never a noisy command fallback.
|
|
841
903
|
readsReady.catch(() => {});
|
|
842
904
|
ctx.slots.inject('conversation.view', () => ctx.slots.register({
|
|
@@ -851,7 +913,7 @@ exports.apply = function apply(ctx) {
|
|
|
851
913
|
control = createControl(async request => {
|
|
852
914
|
const value = readReply(await (mutates(request.action) || request.action === 'status' && control?.source.getSnapshot().uncertainty
|
|
853
915
|
? ctx.remote.commands.execute(sessionId, '/flywheel ' + JSON.stringify(request), [])
|
|
854
|
-
: readsReady.then(
|
|
916
|
+
: readsReady.then(readConsole => readConsole(sessionId, request))), request);
|
|
855
917
|
if (Array.isArray(value.runs)) value.runs = value.runs.filter(item => item.hostSessionId === sessionId);
|
|
856
918
|
return value;
|
|
857
919
|
}, pendingOperations, () => disposed);
|
package/docs/design.md
CHANGED
|
@@ -694,7 +694,7 @@ doctor 的状态为 pass/fail/warn/unknown/skipped,必需检查 fail 才使 ok
|
|
|
694
694
|
|
|
695
695
|
会话视图不提供任务选择器。只接受当前会话投影和精确匹配 `hostSessionId` 的运行索引;其他会话及无归属记录不可见。显式工具关联优先;没有投影时按开始时间选择最近的本会话任务,再请求 Go 状态。单纯打开页面、刷新或旧版 UI 产生的 `/flywheel status` 日志不能创建新的任务关联。未确认操作始终锁定原目标,fork 不继承关联。无关联时显示空状态,独立终端任务需要在目标会话通过 `flywheel_control status` 显式关联,不能按目录猜测或扫描磁盘。
|
|
696
696
|
|
|
697
|
-
自动发现、轮询、配置读取、节点与指标读取使用公开 Typert `flywheelConsole/read` Remote,宿主解析实际 Agent/Session,按会话过滤运行并核对任务身份;该入口只允许读取,不能启动或修改任务。读取不执行 slash command,不追加会话事件,不把 JSON 刷进聊天。UI 变更和未知结果的显式 status 核对仍走有持久回执的命令,确保重载后可恢复操作锁;人工命令及模型工具保持原 JSON 协议,不删除历史事件。读取通道不可用时显示错误,不回退到刷屏命令。
|
|
697
|
+
自动发现、轮询、配置读取、节点与指标读取使用公开 Typert `flywheelConsole/read` Remote,宿主解析实际 Agent/Session,按会话过滤运行并核对任务身份;该入口只允许读取,不能启动或修改任务。读取不执行 slash command,不追加会话事件,不把 JSON 刷进聊天。UI 变更和未知结果的显式 status 核对仍走有持久回执的命令,确保重载后可恢复操作锁;人工命令及模型工具保持原 JSON 协议,不删除历史事件。读取通道不可用时显示错误,不回退到刷屏命令。 客户端挂载使用公开 strict codec 工厂校验 Session ID、只读请求和返回 envelope,Agent lookup 的 wire 字段遵循真实宿主的 `agentId`,不以 src-json 充当生成的客户端输入 codec。兼容测试必须让实际打包 descriptor 经过真实 Client `$mount` 和 Host Gateway,不能仅模拟挂载成功。动态挂载完成后,以受父插件拥有的 `ctx.inject` 子作用域消费 `remote.flywheelConsole`,卸载时同时撤销读取 consumer;不得从未声明注入的外层 context 访问它。
|
|
698
698
|
|
|
699
699
|
项目、任务记录和分支在有值时直接显示。阶段操作、来源、失败证据、会话入口及配置操作使用普通分组,不提供折叠控件;视图导航与画布子图导航仍保留。已有运行只提供适用的继续/停止操作,准备好的新任务才显示 Auto/Quick/Full 启动选项。主工作区只有流程与记录,设置独立进入。设置使用运行方式、模型与会话、预算与重试、JEV、高级与诊断五个分类;重新读取、完整 JSON 和原始回执放在高级与诊断,范围及保存/撤销/恢复默认保持固定位置。窄窗口的设置导航行固定 54px、每项 36px;触控指针下按钮为 44px,并使用 5px 上下留白,不与内容分享最小高度。离开设置、切换范围和重新读取保护未保存草稿。
|
|
700
700
|
|
package/docs/en/flow-console.md
CHANGED
|
@@ -30,7 +30,7 @@ unavailable association tool explicitly. Standalone terminal tasks without a hos
|
|
|
30
30
|
While the canvas is visible, registered-task discovery refreshes every five seconds.
|
|
31
31
|
An observed running task refreshes status every two seconds, backing off to ten
|
|
32
32
|
seconds after an unsuccessful response. Hidden documents skip those requests.
|
|
33
|
-
Refresh uses a read-only Remote instead of a slash command, so it does not append chat events or JSON. Explicit mutations and uncertain-result reconciliation retain durable command receipts. Old chat records are preserved.
|
|
33
|
+
Refresh uses a read-only Remote instead of a slash command, so it does not append chat events or JSON. Explicit mutations and uncertain-result reconciliation retain durable command receipts. Old chat records are preserved. Session identity and read requests use strict Remote codecs; an unavailable or malformed read remains a visible error rather than falling back to chat commands.
|
|
34
34
|
|
|
35
35
|
## This stage versus the full workflow
|
|
36
36
|
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# 0.33.0 单包正式发行与桌面验收
|
|
2
|
+
|
|
3
|
+
[验证索引](README.md) · [单包工程验证](2026-11-14-single-package.md)
|
|
4
|
+
|
|
5
|
+
## 正式身份
|
|
6
|
+
|
|
7
|
+
- PR:[#45](https://github.com/ckanner/flywheel/pull/45)。
|
|
8
|
+
- 标签:`v0.33.0`,源码 `ac1ed320c68f6a8a466005985264e65b5a72fad9`。
|
|
9
|
+
- tree:`7e95a8219705354a3a26146facdd56182a971140`。
|
|
10
|
+
- snapshot SHA-256:`707c11a714e300c62da9bd4d6d5dbf7cad8ea6c90c76a67a642e3aad298bfa78`,dirty=false,candidate format 2。
|
|
11
|
+
- 唯一 npm 包:`@ckanner/flywheel@0.33.0`,tarball `ckanner-flywheel-0.33.0.tgz`,18,623,823 bytes。
|
|
12
|
+
- tarball integrity:`sha512-cvXjIw9LblMJabnEHtPNjj34mbZdJVbwH/R38U+AUkpyxOKxbqzO/7kdV1IStOC+l+/r2mDWd8v1icdYG/ue6g==`。
|
|
13
|
+
- candidate.json SHA-256:`d4bb51bf24f27a5d03cea7e78053d45cc7d265868286b1f0827144b3267edb15`。
|
|
14
|
+
- [正式发布 workflow](https://github.com/ckanner/flywheel/actions/runs/43568347331) 构建一次,双 OS 使用原始产物;本机下载的 Actions ZIP 摘要也已核对。
|
|
15
|
+
|
|
16
|
+
## 源码与候选验证
|
|
17
|
+
|
|
18
|
+
PR CI 的 Linux 和 macOS 均通过,包括逐函数 100% Go 覆盖率、插件、桥接、实际 npm 安装和 36 条会话场景。
|
|
19
|
+
PR 首次 macOS job 的 machine 测试包触发默认 10 分钟总超时;当时当前用例仅运行 2 秒。
|
|
20
|
+
该用例本机连续 10 次通过,随后同提交、同候选、原断言和原时限复跑通过。
|
|
21
|
+
保留[首次失败](https://github.com/ckanner/flywheel/actions/runs/43563991853/attempts/1)和[复跑通过](https://github.com/ckanner/flywheel/actions/runs/43563991853/attempts/2),不声称累计耗时风险已被修复。
|
|
22
|
+
|
|
23
|
+
正式标签的双平台验证均在首次运行通过:Go 全门禁、插件与兼容宿主、三项跨进程桥接、151 条 npm 检查、打包 Host/Client 10 条、安装 13 条、36 条会话场景;Linux 另通过核心 race。
|
|
24
|
+
本机对下载的同一正式候选另通过 Host/Client 10 条和实际安装 13 条,无跳过。
|
|
25
|
+
|
|
26
|
+
## 发布与安装回执
|
|
27
|
+
|
|
28
|
+
正式 workflow 首次通过 OIDC 上传后,版本公开可见性超过 180 秒窗口,publish job 停止,未移动 latest。
|
|
29
|
+
随后从 registry 核对到与候选一致的 SHA-512,仅重跑失败 job,复用原始 artifact;回执包含
|
|
30
|
+
`Verified existing @ckanner/flywheel@0.33.0`,公开 npm 安装通过,OIDC dist-tag 更新及最终 latest 校验通过。
|
|
31
|
+
未使用 npm token 回退或逐包浏览器认证;未重建或覆盖已接受版本。
|
|
32
|
+
|
|
33
|
+
本机在 DSH 无活动会话后退出桌面并备份配置、安装记录及 profile 清单。CLI 和 desktop profile
|
|
34
|
+
均升级至完整包 0.33.0,官方 CLI 移除旧插件注册;两处各 264 个文件与正式 tarball 一致。
|
|
35
|
+
其他插件依赖、cordis 配置及兼容设置不变;pnpm 的 `minimumReleaseAgeExclude` 自动追加
|
|
36
|
+
新包的精确版本,这是官方安装器产生的包管理元数据。全局配置与最新默认模板语义一致、
|
|
37
|
+
原始字节不变,四项无推理 SDK 探测通过。真实账号推理未测。
|
|
38
|
+
|
|
39
|
+
## 桌面验收失败与后续修复
|
|
40
|
+
|
|
41
|
+
重载后视图出现,但任务与配置读取报 `generated Remote flywheelConsole/read field "sessionId" has no strict codec`。
|
|
42
|
+
因此 **0.33.0 的桌面读取验收失败**,不能用源码/候选或 SDK 通过代替。
|
|
43
|
+
|
|
44
|
+
客户端原来用 src-json 挂载只读 Remote,旧 renderer 测试模拟了 `$mount`,Host 测试则直接调用
|
|
45
|
+
Gateway,遗漏真实 Client 注册。这一 descriptor 在 v0.32.1 源码中已经存在;不能据此次失败
|
|
46
|
+
倒推旧版本曾完成该路径的真实验收。当前 DSH 0.2.2-rc.3 要求 strict 输入 codec。
|
|
47
|
+
|
|
48
|
+
后续 0.33.1 保留单包结构,补充有实际校验的公开 codec 工厂,并让打包 Client descriptor
|
|
49
|
+
通过真实 Client 和 Host Gateway。0.33.0 产物与标签保持不变;补丁的实际验收另行记录。
|
|
@@ -11,6 +11,7 @@ Historical records retain their original language and findings.
|
|
|
11
11
|
|
|
12
12
|
| Date | Record |
|
|
13
13
|
| --- | --- |
|
|
14
|
+
| 2026-11-14 | [0.33.0 单包正式发行与桌面读取缺口](2026-11-14-release-0.33.0.md) |
|
|
14
15
|
| 2026-11-14 | [0.33.0 单包分发工程验证](2026-11-14-single-package.md) |
|
|
15
16
|
| 2026-11-13 | [0.32.1:DSH 兼容系列范围与发行(桌面重载待完成)](2026-11-13-release-0.32.1.md) |
|
|
16
17
|
| 2026-11-13 | [0.32.0 正式发行与本机安装(桌面重载待完成)](2026-11-13-release-0.32.0.md) |
|
|
@@ -26,7 +26,7 @@ Skill 已加载不代表引擎已经启动。`flywheel-task` 准备适合的契
|
|
|
26
26
|
无会话 ID 的独立终端任务需要在目标会话显式关联。
|
|
27
27
|
|
|
28
28
|
画布可见时,每五秒刷新已登记任务;已观察为运行中的任务每两秒刷新状态,失败后
|
|
29
|
-
延长到十秒。页面隐藏时跳过这些请求。刷新使用只读 Remote,不执行对话命令,也不新增聊天事件或 JSON
|
|
29
|
+
延长到十秒。页面隐藏时跳过这些请求。刷新使用只读 Remote,不执行对话命令,也不新增聊天事件或 JSON。显式修改与未知结果核对仍保留持久命令回执;既有聊天历史保持原样。会话身份与读取请求使用严格 Remote codec;读取不可用或格式不合法时保留可见错误,不回退到对话命令。
|
|
30
30
|
|
|
31
31
|
## 本次阶段与完整流程
|
|
32
32
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/native/manifest.json
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"protocol": 1,
|
|
3
|
-
"version": "0.33.
|
|
3
|
+
"version": "0.33.1",
|
|
4
4
|
"platforms": {
|
|
5
5
|
"darwin-arm64": {
|
|
6
6
|
"bytes": 10317010,
|
|
7
|
-
"sha256": "
|
|
7
|
+
"sha256": "4efb5efab4fce7b6fd86d15d6fcc21530b4aee169613b5009e2cee452c277c9c"
|
|
8
8
|
},
|
|
9
9
|
"darwin-amd64": {
|
|
10
10
|
"bytes": 11236784,
|
|
11
|
-
"sha256": "
|
|
11
|
+
"sha256": "a93e2f8802fb4a1c258dc331546e0a0e56165aec92e90e3eb64e42d88ac49b15"
|
|
12
12
|
},
|
|
13
13
|
"linux-arm64": {
|
|
14
14
|
"bytes": 10092704,
|
|
15
|
-
"sha256": "
|
|
15
|
+
"sha256": "82c611cbada4d1a8b932b619cfe1fb15b30aee2e35ba3fb1da527c000c19cffc"
|
|
16
16
|
},
|
|
17
17
|
"linux-amd64": {
|
|
18
18
|
"bytes": 11014304,
|
|
19
|
-
"sha256": "
|
|
19
|
+
"sha256": "7f49ac00660cf97502d27f150e7969b04cac50c894c5f8b7149a05a19f681316"
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ckanner/flywheel",
|
|
3
|
-
"version": "0.33.
|
|
3
|
+
"version": "0.33.1",
|
|
4
4
|
"description": "A deterministic Go orchestrator for coding-agent loops, with task contracts, verification gates, Git worktrees, and DSH desktop integration.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"flywheel": "bin/flywheel.js",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"test": "node --test npm/test/*.test.js",
|
|
55
55
|
"test:install": "node scripts/test-packed-host.js && node --test npm/test/install.integration.js",
|
|
56
56
|
"test:registry": "node npm/test/registry-smoke.js",
|
|
57
|
-
"build:npm": "bash scripts/build-npm.sh 0.33.
|
|
57
|
+
"build:npm": "bash scripts/build-npm.sh 0.33.1 dist-npm",
|
|
58
58
|
"test:sessions": "node scripts/test-session-evaluation.js"
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
package/plugins/dsh/PROTOCOL.md
CHANGED
|
@@ -464,6 +464,8 @@ host 在调用 Go 前把任务和仓库目录规范化为真实路径,并校
|
|
|
464
464
|
|
|
465
465
|
### 会话控制台的静默读取
|
|
466
466
|
|
|
467
|
+
客户端参数与结果使用公开 `strict` codec(`typeSymbol`、`create().parse`);结果还提供同一校验的 `decode`。Agent lookup 使用宿主规定的 wire 字段 `agentId`,其值仍为当前 Session ID;不能自行改名为 `sessionId`。Session ID 必须为非空字符串,请求只允许具名读取动作及相应字段,返回值保持 `{ result: { kind, text } }`。严格 codec 不替代 Host 的 Session/任务归属检查及 Go 控制验证;客户端仍只导入共享 React。`$mount` 成功后,通过父插件拥有的 `ctx.inject(['remote.flywheelConsole'])` 子作用域访问动态 namespace,随父插件撤销;初始外层 context 不直接访问未注入的服务。
|
|
468
|
+
|
|
467
469
|
`flywheelConsole/read` 是公开 Typert Remote,参数为宿主解析的 `agent`、控制请求 `input`
|
|
468
470
|
和取消信号 `signal`。客户端显式挂载描述符,只有 React 是运行时共享模块。
|
|
469
471
|
宿主只接受 runs/status/config/config-edit/metrics/history/node/delivery/doctor;其他 action
|