@hpmicro-tools/hpmmfgctl 0.0.0-stage → 0.0.0
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/LICENSE +21 -0
- package/README.md +197 -2
- package/README.zh-CN.md +197 -0
- package/dist/command/arguments.d.ts +3 -0
- package/dist/command/arguments.js +18 -0
- package/dist/command/arguments.js.map +1 -0
- package/dist/command/runner.d.ts +22 -0
- package/dist/command/runner.js +119 -0
- package/dist/command/runner.js.map +1 -0
- package/dist/command/types.d.ts +37 -0
- package/dist/command/types.js +2 -0
- package/dist/command/types.js.map +1 -0
- package/dist/command/validate.d.ts +4 -0
- package/dist/command/validate.js +48 -0
- package/dist/command/validate.js.map +1 -0
- package/dist/config/config-path.d.ts +8 -0
- package/dist/config/config-path.js +27 -0
- package/dist/config/config-path.js.map +1 -0
- package/dist/config/config-store.d.ts +13 -0
- package/dist/config/config-store.js +61 -0
- package/dist/config/config-store.js.map +1 -0
- package/dist/config/config-type.d.ts +5 -0
- package/dist/config/config-type.js +2 -0
- package/dist/config/config-type.js.map +1 -0
- package/dist/device/enumerator.d.ts +12 -0
- package/dist/device/enumerator.js +65 -0
- package/dist/device/enumerator.js.map +1 -0
- package/dist/device/types.d.ts +22 -0
- package/dist/device/types.js +2 -0
- package/dist/device/types.js.map +1 -0
- package/dist/hpm-mfg-service.d.ts +37 -0
- package/dist/hpm-mfg-service.js +155 -0
- package/dist/hpm-mfg-service.js.map +1 -0
- package/dist/main.d.ts +2 -0
- package/dist/main.js +23 -0
- package/dist/main.js.map +1 -0
- package/dist/mcp/configuration.d.ts +4 -0
- package/dist/mcp/configuration.js +30 -0
- package/dist/mcp/configuration.js.map +1 -0
- package/dist/mcp/discovery.d.ts +4 -0
- package/dist/mcp/discovery.js +30 -0
- package/dist/mcp/discovery.js.map +1 -0
- package/dist/mcp/mcp-type.d.ts +11 -0
- package/dist/mcp/mcp-type.js +2 -0
- package/dist/mcp/mcp-type.js.map +1 -0
- package/dist/mcp/operations.d.ts +4 -0
- package/dist/mcp/operations.js +17 -0
- package/dist/mcp/operations.js.map +1 -0
- package/dist/mcp/registration.d.ts +15 -0
- package/dist/mcp/registration.js +23 -0
- package/dist/mcp/registration.js.map +1 -0
- package/dist/mcp/responses.d.ts +5 -0
- package/dist/mcp/responses.js +20 -0
- package/dist/mcp/responses.js.map +1 -0
- package/dist/mcp/schemas.d.ts +155 -0
- package/dist/mcp/schemas.js +253 -0
- package/dist/mcp/schemas.js.map +1 -0
- package/dist/mcp/server.d.ts +4 -0
- package/dist/mcp/server.js +16 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/operations/rom.d.ts +5 -0
- package/dist/operations/rom.js +81 -0
- package/dist/operations/rom.js.map +1 -0
- package/dist/service-type.d.ts +13 -0
- package/dist/service-type.js +2 -0
- package/dist/service-type.js.map +1 -0
- package/package.json +51 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 YiangQi
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,198 @@
|
|
|
1
|
-
#
|
|
1
|
+
# hpmmfgctl (TypeScript)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[English](README.md) | [简体中文](README.zh-CN.md)
|
|
4
|
+
|
|
5
|
+
HPM Manufacturing stdio MCP server implemented in TypeScript. It invokes a locally installed HPM Manufacturing CMD to discover, probe, and operate HPM ROM devices over serial or HID.
|
|
6
|
+
|
|
7
|
+
Requires Node.js 22.15+ and a separately installed HPM Manufacturing CMD. Supported platforms are Windows x64 and Linux x86_64. The server does not search `PATH` or installation directories.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
npm install -g hpmmfgctl --registry=https://registry.npmjs.org/
|
|
13
|
+
hpmmfgctl --help
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Alternatively, use `npx --yes "hpmmfgctl@<version>"` to run a pinned version.
|
|
17
|
+
|
|
18
|
+
Device discovery uses `@serialport/bindings-cpp` and `node-hid`, both of which contain native components. Environments without matching prebuilt binaries may need a native C/C++ build toolchain. Linux HID uses the hidraw backend and may also require udev rules or group permissions.
|
|
19
|
+
|
|
20
|
+
## CLI
|
|
21
|
+
|
|
22
|
+
`hpmmfgctl` starts the MCP server; it does not expose manufacturing operations as direct CLI subcommands. These entry points are equivalent:
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
hpmmfgctl mcp
|
|
26
|
+
hpmmfgctl serve --stdio
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
The service uses MCP over stdin/stdout, with stdout reserved for protocol messages. The current TypeScript implementation does not include the old Go server's HTTP transport.
|
|
30
|
+
|
|
31
|
+
## Configuration
|
|
32
|
+
|
|
33
|
+
Default configuration locations:
|
|
34
|
+
|
|
35
|
+
| Operating system | Default location |
|
|
36
|
+
| --- | --- |
|
|
37
|
+
| Windows | `%APPDATA%/hpmicro/hpmmfgctl/config.json` |
|
|
38
|
+
| macOS | `~/Library/Application Support/hpmicro/hpmmfgctl/config.json` |
|
|
39
|
+
| Linux | `$XDG_CONFIG_HOME/hpmicro/hpmmfgctl/config.json`, or `~/.config/hpmicro/hpmmfgctl/config.json` |
|
|
40
|
+
|
|
41
|
+
`HPMMFGCTL_CONFIG` overrides the default configuration file path in the same way that `HPMSDKCTL_CONFIG` does for `hpmsdkctl`: it names the file, not a directory. The format is compatible with the old Go server:
|
|
42
|
+
|
|
43
|
+
```json
|
|
44
|
+
{
|
|
45
|
+
"mfgCmdPath": "C:\\Program Files\\HPMicro\\hpm_manufacturing_cmd.exe"
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Use `mfg.set` instead of editing the file directly. It saves only after all compatibility checks pass:
|
|
50
|
+
|
|
51
|
+
- the path is absolute and identifies an executable regular file;
|
|
52
|
+
- the filename is `hpm_manufacturing_cmd.exe` on Windows or `hpm_manufacturing_cmd` on Linux;
|
|
53
|
+
- `--version`, no-argument failure, and `--help` behavior are compatible; and
|
|
54
|
+
- help contains the required `-p`, `-u`, `-r`, `-t`, and `-f` options.
|
|
55
|
+
|
|
56
|
+
The CMD executable path may contain spaces. Reading a missing configuration file returns empty configuration; only `mfg.set` or `mfg.clear` creates the configuration directory and writes the file.
|
|
57
|
+
|
|
58
|
+
## MCP
|
|
59
|
+
|
|
60
|
+
Pin a verified package version:
|
|
61
|
+
|
|
62
|
+
```json
|
|
63
|
+
{
|
|
64
|
+
"mcpServers": {
|
|
65
|
+
"hpm-mfg-tool-ctl": {
|
|
66
|
+
"command": "npx",
|
|
67
|
+
"args": ["--yes", "--registry=https://registry.npmjs.org/", "hpmmfgctl@<version>", "mcp"]
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Replace `<version>` with the package version. To isolate configuration, set `HPMMFGCTL_CONFIG` in the server's `env` to an absolute configuration file path. For local development, use `node` as the command and pass the absolute built `dist/main.js` path followed by `mcp`.
|
|
74
|
+
|
|
75
|
+
### Recommended workflow
|
|
76
|
+
|
|
77
|
+
1. Call `mfg.doctor` to check configuration and CMD compatibility. Call `mfg.set` if the executable is not configured.
|
|
78
|
+
2. Call `device.discover` for serial or HID devices.
|
|
79
|
+
3. Call `device.create`. The service probes the device with `query-rte 0` and returns a `targetId` only after a successful probe.
|
|
80
|
+
4. Pass that `targetId` to `rom.*` tools.
|
|
81
|
+
5. Call `device.delete` when the target is no longer needed.
|
|
82
|
+
|
|
83
|
+
Targets exist only in the current MCP process and must be recreated after a restart. CMD processes execute serially. Queued and running requests support cancellation, and commands are started without a shell.
|
|
84
|
+
|
|
85
|
+
### Complete MCP tool reference
|
|
86
|
+
|
|
87
|
+
`?` marks an optional parameter; all other parameters are required. Pass `{}` to tools without parameters. Parameter names are case-sensitive and use camelCase. Every tool returns structured content; precondition and operation failures set MCP `isError: true`.
|
|
88
|
+
|
|
89
|
+
#### Configuration tools
|
|
90
|
+
|
|
91
|
+
| Tool | Parameters | Behavior |
|
|
92
|
+
| --- | --- | --- |
|
|
93
|
+
| `mfg.doctor` | None | Force a CMD compatibility check and report server, platform, path, and validation details |
|
|
94
|
+
| `mfg.get` | None | Read current configuration; returns an empty object when unset |
|
|
95
|
+
| `mfg.set` | `path` | Validate and save an absolute CMD path; leaves existing configuration unchanged on failure |
|
|
96
|
+
| `mfg.clear` | None | Clear the saved CMD path and compatibility cache |
|
|
97
|
+
|
|
98
|
+
`mfg.doctor` and `mfg.set` start CMD for compatibility checks but do not access target hardware.
|
|
99
|
+
|
|
100
|
+
#### Device and target tools
|
|
101
|
+
|
|
102
|
+
| Tool | Parameters | Behavior |
|
|
103
|
+
| --- | --- | --- |
|
|
104
|
+
| `device.discover` | `transport`; `vid?`, `pid?` | Enumerate `serial` or `hid` devices; VID/PID filter only HID |
|
|
105
|
+
| `device.create` | `transport`; `port?`, `baudRate?`, `path?`, `vid?`, `pid?`, `timeoutMs?` | Probe a device and register a process-local target |
|
|
106
|
+
| `device.list` | None | List process-local targets and connection settings |
|
|
107
|
+
| `device.delete` | `targetId` | Delete one target; rejects an unknown ID |
|
|
108
|
+
|
|
109
|
+
Connection parameters:
|
|
110
|
+
|
|
111
|
+
| Parameter | Meaning / constraint |
|
|
112
|
+
| --- | --- |
|
|
113
|
+
| `transport` | `serial` or `hid` |
|
|
114
|
+
| `vid` | 0-65535; defaults to HPMicro VID `0x34B7` (decimal 13495) |
|
|
115
|
+
| `pid` | 0-65535; defaults to 0, which matches any PID |
|
|
116
|
+
| `port` | Serial path such as `COM11` or `/dev/ttyUSB0`; if omitted, exactly one serial port must exist |
|
|
117
|
+
| `baudRate` | Serial rate, 0-4294967295; omitted or zero defaults to 115200 |
|
|
118
|
+
| `path` | HID interface path; if omitted, exactly one matching accessible HID device must exist |
|
|
119
|
+
| `timeoutMs` | `device.create` probe timeout, 1000-1800000 ms; defaults to 10000 ms |
|
|
120
|
+
|
|
121
|
+
Windows serial enumeration proves only that a port exists, not that it is accessible. On every platform, `device.create` performs a real CMD probe. HID discovery attempts to open each interface and returns `accessible` plus a permission hint when appropriate.
|
|
122
|
+
|
|
123
|
+
#### ROM tools
|
|
124
|
+
|
|
125
|
+
Every ROM tool requires `targetId` and accepts optional `timeoutMs` from 1000 to 1800000 ms.
|
|
126
|
+
|
|
127
|
+
| Tool | Other parameters | Purpose |
|
|
128
|
+
| --- | --- | --- |
|
|
129
|
+
| `rom.query_rte` | `rteId`, `argument?` | Query ROM features, memory properties, or supported commands |
|
|
130
|
+
| `rom.config_rte` | `peripheralMask`, `baudRate` | Configure the runtime serial peripheral mask and rate |
|
|
131
|
+
| `rom.config_memory` | `memoryId`, `address` | Initialize external memory using configuration data already in device memory |
|
|
132
|
+
| `rom.read_memory` | `memoryId`, `address`, `length` | Read device data into CMD output, up to 65536 bytes |
|
|
133
|
+
| `rom.read_memory_to_file` | `memoryId`, `address`, `length`, `filePath`, `overwrite?` | Write device data to a local file |
|
|
134
|
+
| `rom.write_memory` | `memoryId`, `address`, `data` | Write hexadecimal words |
|
|
135
|
+
| `rom.write_memory_from_file` | `memoryId`, `address`, `filePath` | Write a local file |
|
|
136
|
+
| `rom.verify_checksum` | `memoryId`, `address`, `data` | Verify device data against hexadecimal words |
|
|
137
|
+
| `rom.verify_checksum_from_file` | `memoryId`, `address`, `filePath` | Verify device data against a local file |
|
|
138
|
+
| `rom.erase_region` | `memoryId`, `address`, `length` | Erase an XPI NOR region |
|
|
139
|
+
| `rom.erase_chip` | `memoryId` | Erase an entire XPI NOR device |
|
|
140
|
+
| `rom.load_image` | `filePath` | Load an existing image into a device that supports serial boot |
|
|
141
|
+
| `rom.load_bootloader_firmware` | `series`, `signed` | Load bootloader firmware for a SoC series; resets automatically on success |
|
|
142
|
+
| `rom.reset` | `resetType` | Reset the device: 0 default, 1 hot, or 2 cold |
|
|
143
|
+
|
|
144
|
+
ROM parameter constraints:
|
|
145
|
+
|
|
146
|
+
- `rteId` is 0 (ROM features), 4 (memory properties), or 5 (command list). `argument` is required only for `rteId=4` and contains the queried `memoryId`.
|
|
147
|
+
- `memoryId`, `address`, `peripheralMask`, and `query_rte.argument` are decimal or `0x` hexadecimal strings in the unsigned 32-bit range. For SDXC/eMMC transfers, `address` is a sector index. `config_memory.address` always identifies configuration data already stored in device memory.
|
|
148
|
+
- `length` is a positive byte count up to 4294967295; `read_memory` additionally caps it at 65536.
|
|
149
|
+
- `data` is a comma-separated list of 1-8 digit hexadecimal words, four bytes per word. Paired `[[...]]` brackets are optional. Example: `[[0xfcf90001,0x05,0x0,0x0]]`. Whitespace is not allowed.
|
|
150
|
+
- `series` is defined by the installed CMD, for example `HPM6700`, `HPM6400`, `HPM5300`, `HPM6200`, or `HPM6300`; `signed` is a boolean.
|
|
151
|
+
|
|
152
|
+
Supported memories and operation groups:
|
|
153
|
+
|
|
154
|
+
| `memoryId` | Memory | Read/write | Verify | Configure | Erase |
|
|
155
|
+
| ---------- | -------- | ---------- | ------ | --------- | ----- |
|
|
156
|
+
| `0` | ILM | Yes | Yes | No | No |
|
|
157
|
+
| `1` | DLM | Yes | Yes | No | No |
|
|
158
|
+
| `0x10000` | XPI0 NOR | Yes | Yes | Yes | Yes |
|
|
159
|
+
| `0x10001` | XPI1 NOR | Yes | Yes | Yes | Yes |
|
|
160
|
+
| `0x20000` | OTP | Yes | No | No | No |
|
|
161
|
+
| `0x30000` | SDXC0 | Yes | Yes | Yes | No |
|
|
162
|
+
| `0x30001` | SDXC1 | Yes | Yes | Yes | No |
|
|
163
|
+
|
|
164
|
+
“Read/write” means the schema permits those operations; the device, ROM, and installed CMD may impose tighter restrictions.
|
|
165
|
+
|
|
166
|
+
Default timeouts are 1800000 ms for `rom.erase_chip`; 600000 ms for region erase, writes, file reads, and loads; and 30000 ms for other ROM operations. Override them with `timeoutMs`.
|
|
167
|
+
|
|
168
|
+
### File and execution safety
|
|
169
|
+
|
|
170
|
+
- A ROM `filePath` must be absolute and contain no whitespace or control characters. This CMD parser restriction does not apply to the executable path passed to `mfg.set`.
|
|
171
|
+
- Input files must exist and be regular files. A file read requires an existing parent directory and refuses to replace an existing file unless `overwrite: true` is set.
|
|
172
|
+
- ROM results contain `success`, `exitCode`, `timedOut`, `durationMs`, and a combined `log`. Logs are capped at 1 MiB, preserving their beginning and end when truncated.
|
|
173
|
+
- Queries, inline reads, and verification are marked read-only. File reads, configuration, writes, erases, loads, and reset are marked destructive.
|
|
174
|
+
- The server has no second confirmation or authorization token. The caller must confirm the target, address, length, and file before writes, configuration, erases, loads, resets, and file replacement.
|
|
175
|
+
|
|
176
|
+
## Development and verification
|
|
177
|
+
|
|
178
|
+
```sh
|
|
179
|
+
cd mcp-servers/hpmmfgctl
|
|
180
|
+
npm ci
|
|
181
|
+
npm run lint
|
|
182
|
+
npm run format:check
|
|
183
|
+
npm run typecheck
|
|
184
|
+
npm run build
|
|
185
|
+
npm test
|
|
186
|
+
npm pack --dry-run
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Local startup example:
|
|
190
|
+
|
|
191
|
+
```powershell
|
|
192
|
+
$env:HPMMFGCTL_CONFIG = "C:\hpm-mfg-data\config.json"
|
|
193
|
+
node dist/main.js mcp
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Normal automated tests do not require hardware and do not perform manufacturing operations. Before release, smoke-test serial/HID discovery, target probing, and approved ROM operations with real devices on Windows and Linux.
|
|
197
|
+
|
|
198
|
+
Release tags use `hpmmfgctl-v<package version>`. The plugin pins a published npm version, so publish the package before updating or distributing the plugin.
|
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
# hpmmfgctl(TypeScript)
|
|
2
|
+
|
|
3
|
+
[English](README.md) | [简体中文](README.zh-CN.md)
|
|
4
|
+
|
|
5
|
+
使用 TypeScript 实现的 HPM 镜像烧写 stdio MCP 服务。它调用本机安装的镜像烧写 CMD,通过串口或 HID 发现、探测和操作 HPM ROM 设备。
|
|
6
|
+
|
|
7
|
+
支持 Windows x64 和 Linux x86_64,需要 Node.js 22.15 及以上版本,并需单独安装镜像烧写 CMD。服务不会搜索 `PATH` 或安装目录。
|
|
8
|
+
|
|
9
|
+
## 安装
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
npm install -g hpmmfgctl --registry=https://registry.npmjs.org/
|
|
13
|
+
hpmmfgctl --help
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
也可以使用 `npx --yes "hpmmfgctl@<version>"` 固定运行指定版本。
|
|
17
|
+
|
|
18
|
+
设备发现依赖 `@serialport/bindings-cpp` 和 `node-hid`,两者均包含原生组件。没有适用预编译文件的环境可能需要 C/C++ 原生构建工具链。Linux HID 使用 hidraw 后端,可能还需要配置 udev 规则或用户组权限。
|
|
19
|
+
|
|
20
|
+
## CLI
|
|
21
|
+
|
|
22
|
+
`hpmmfgctl` 只负责启动 MCP 服务,不直接提供镜像烧写操作子命令。支持以下两种等价入口:
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
hpmmfgctl mcp
|
|
26
|
+
hpmmfgctl serve --stdio
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
服务通过标准输入输出使用 MCP 协议;stdout 仅承载协议消息。
|
|
30
|
+
|
|
31
|
+
## 配置
|
|
32
|
+
|
|
33
|
+
默认配置文件位置:
|
|
34
|
+
|
|
35
|
+
| 操作系统 | 默认位置 |
|
|
36
|
+
| --- | --- |
|
|
37
|
+
| Windows | `%APPDATA%/hpmicro/hpmmfgctl/config.json` |
|
|
38
|
+
| Linux | `$XDG_CONFIG_HOME/hpmicro/hpmmfgctl/config.json`,或 `~/.config/hpmicro/hpmmfgctl/config.json` |
|
|
39
|
+
|
|
40
|
+
环境变量 `HPMMFGCTL_CONFIG` 可覆盖默认配置文件路径,值应指向配置文件,而不是目录。配置格式兼容旧 Go 服务:
|
|
41
|
+
|
|
42
|
+
```json
|
|
43
|
+
{
|
|
44
|
+
"mfgCmdPath": "C:\\Program Files\\HPMicro\\hpm_manufacturing_cmd.exe"
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
建议使用 `mfg.set` 写入配置,而不是手动编辑文件。它会先检查以下条件,全部通过后才保存:
|
|
49
|
+
|
|
50
|
+
- 路径为绝对路径,且指向可执行的普通文件;
|
|
51
|
+
- Windows 文件名为 `hpm_manufacturing_cmd.exe`,Linux 文件名为 `hpm_manufacturing_cmd`;
|
|
52
|
+
- `--version`、无参数错误退出和 `--help` 行为兼容;
|
|
53
|
+
- 帮助信息包含服务需要的 `-p`、`-u`、`-r`、`-t` 和 `-f` 选项。
|
|
54
|
+
|
|
55
|
+
CMD 路径本身可以包含空格。读取不存在的配置文件会得到空配置;只有 `mfg.set` 或 `mfg.clear` 才会创建配置目录并写入配置。
|
|
56
|
+
|
|
57
|
+
## MCP
|
|
58
|
+
|
|
59
|
+
建议固定经过验证的包版本:
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{
|
|
63
|
+
"mcpServers": {
|
|
64
|
+
"hpm-mfg-tool-ctl": {
|
|
65
|
+
"command": "npx",
|
|
66
|
+
"args": ["--yes", "--registry=https://registry.npmjs.org/", "hpmmfgctl@<version>", "mcp"]
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
将 `<version>` 替换为实际版本。需要隔离配置时,可在该服务的 `env` 中将 `HPMMFGCTL_CONFIG` 设置为一个绝对配置文件路径。本地开发时可将 `command` 改为 `node`,并把 `args` 设置为构建后的 `dist/main.js` 绝对路径和 `mcp`。
|
|
73
|
+
|
|
74
|
+
### 推荐工作流
|
|
75
|
+
|
|
76
|
+
1. 调用 `mfg.doctor` 检查配置和 CMD 兼容性;未配置时调用 `mfg.set`。
|
|
77
|
+
2. 调用 `device.discover` 枚举串口或 HID 设备。
|
|
78
|
+
3. 调用 `device.create`。服务会执行 `query-rte 0` 真实探测,成功后返回 `targetId`。
|
|
79
|
+
4. 使用 `targetId` 调用 `rom.*` 工具。
|
|
80
|
+
5. 不再使用设备时调用 `device.delete`。
|
|
81
|
+
|
|
82
|
+
Target 只存在于当前 MCP 进程中,服务重启后必须重新创建。CMD 进程串行执行,排队中和执行中的请求均可取消;启动外部命令时不经过 shell。
|
|
83
|
+
|
|
84
|
+
### 完整 MCP 工具参考
|
|
85
|
+
|
|
86
|
+
`?` 表示可选参数,其余参数均为必填;无参数工具传入 `{}`。参数名区分大小写,并使用 camelCase。所有工具都返回结构化结果;前置条件错误或操作失败时设置 MCP `isError: true`。
|
|
87
|
+
|
|
88
|
+
#### 配置工具
|
|
89
|
+
|
|
90
|
+
| 工具 | 参数 | 行为 |
|
|
91
|
+
| ------------ | ------ | ---------------------------------------------------------------------- |
|
|
92
|
+
| `mfg.doctor` | 无 | 强制重新检查 CMD,返回服务版本、平台、配置路径、已配置路径和兼容性结果 |
|
|
93
|
+
| `mfg.get` | 无 | 读取当前配置;未配置时返回空对象 |
|
|
94
|
+
| `mfg.set` | `path` | 校验并保存 CMD 绝对路径;失败时不修改已有配置 |
|
|
95
|
+
| `mfg.clear` | 无 | 清除已保存的 CMD 路径和兼容性缓存 |
|
|
96
|
+
|
|
97
|
+
`mfg.doctor` 和 `mfg.set` 会启动 CMD 进行兼容性检查,但不会访问目标硬件。
|
|
98
|
+
|
|
99
|
+
#### 设备与 Target 工具
|
|
100
|
+
|
|
101
|
+
| 工具 | 参数 | 行为 |
|
|
102
|
+
| --- | --- | --- |
|
|
103
|
+
| `device.discover` | `transport`;`vid?`、`pid?` | 枚举 `serial` 或 `hid` 设备;VID/PID 只过滤 HID |
|
|
104
|
+
| `device.create` | `transport`;`port?`、`baudRate?`、`path?`、`vid?`、`pid?`、`timeoutMs?` | 探测设备,成功后注册进程内 Target |
|
|
105
|
+
| `device.list` | 无 | 列出当前进程中已注册的 Target 及连接参数 |
|
|
106
|
+
| `device.delete` | `targetId` | 删除一个已注册 Target;未知 ID 报错 |
|
|
107
|
+
|
|
108
|
+
连接参数说明:
|
|
109
|
+
|
|
110
|
+
| 参数 | 含义与约束 |
|
|
111
|
+
| ----------- | ---------------------------------------------------------------------- |
|
|
112
|
+
| `transport` | `serial` 或 `hid` |
|
|
113
|
+
| `vid` | 0–65535;默认 HPMicro VID `0x34B7`(十进制 13495) |
|
|
114
|
+
| `pid` | 0–65535;默认 0,表示匹配任意 PID |
|
|
115
|
+
| `port` | 串口路径,如 `COM11` 或 `/dev/ttyUSB0`;省略时系统中必须恰好有一个串口 |
|
|
116
|
+
| `baudRate` | 串口波特率,0–4294967295;省略或 0 时使用 115200 |
|
|
117
|
+
| `path` | HID 接口路径;省略时匹配的可访问 HID 设备必须恰好有一个 |
|
|
118
|
+
| `timeoutMs` | `device.create` 探测超时,1000–1800000 ms,默认 10000 ms |
|
|
119
|
+
|
|
120
|
+
Windows 串口枚举只能说明端口存在,不能证明当前可访问;所有平台都会在 `device.create` 时通过 CMD 真实探测。HID 枚举会尝试打开接口,并在结果中返回 `accessible` 和权限提示。
|
|
121
|
+
|
|
122
|
+
#### ROM 工具
|
|
123
|
+
|
|
124
|
+
每个 ROM 工具都需要 `targetId`,并可传入 `timeoutMs`(1000–1800000 ms)。
|
|
125
|
+
|
|
126
|
+
| 工具 | 其余参数 | 用途 |
|
|
127
|
+
| --- | --- | --- |
|
|
128
|
+
| `rom.query_rte` | `rteId`、`argument?` | 查询 ROM 功能、存储器属性或支持的命令 |
|
|
129
|
+
| `rom.config_rte` | `peripheralMask`、`baudRate` | 配置运行时串口外设掩码和波特率 |
|
|
130
|
+
| `rom.config_memory` | `memoryId`、`address` | 使用设备内存中的配置数据初始化外部存储器 |
|
|
131
|
+
| `rom.read_memory` | `memoryId`、`address`、`length` | 将设备数据读入 CMD 输出,最多 65536 字节 |
|
|
132
|
+
| `rom.read_memory_to_file` | `memoryId`、`address`、`length`、`filePath`、`overwrite?` | 将设备数据写入本地文件 |
|
|
133
|
+
| `rom.write_memory` | `memoryId`、`address`、`data` | 写入十六进制字数组 |
|
|
134
|
+
| `rom.write_memory_from_file` | `memoryId`、`address`、`filePath` | 写入本地文件内容 |
|
|
135
|
+
| `rom.verify_checksum` | `memoryId`、`address`、`data` | 根据十六进制字数组校验设备数据 |
|
|
136
|
+
| `rom.verify_checksum_from_file` | `memoryId`、`address`、`filePath` | 根据本地文件校验设备数据 |
|
|
137
|
+
| `rom.erase_region` | `memoryId`、`address`、`length` | 擦除 XPI NOR 区域 |
|
|
138
|
+
| `rom.erase_chip` | `memoryId` | 擦除整片 XPI NOR |
|
|
139
|
+
| `rom.load_image` | `filePath` | 向支持串行启动的设备加载已有镜像 |
|
|
140
|
+
| `rom.load_bootloader_firmware` | `series`、`signed` | 按 SoC 系列加载 Bootloader 固件,成功后设备自动复位 |
|
|
141
|
+
| `rom.reset` | `resetType` | 复位设备:0 默认、1 热复位、2 冷复位 |
|
|
142
|
+
|
|
143
|
+
ROM 参数约束:
|
|
144
|
+
|
|
145
|
+
- `rteId` 只能为 0(ROM 功能)、4(存储器属性)或 5(命令列表)。仅 `rteId=4` 时必须提供 `argument`,其值为要查询的 `memoryId`。
|
|
146
|
+
- `memoryId`、`address`、`peripheralMask` 和 `query_rte.argument` 使用十进制或 `0x` 十六进制字符串,范围为 32 位无符号整数。对 SDXC/eMMC 操作,`address` 表示扇区索引;`config_memory.address` 则始终表示设备内存中配置数据的地址。
|
|
147
|
+
- `length` 是正整数字节数,最大 4294967295;`read_memory` 额外限制为 65536。
|
|
148
|
+
- `data` 是逗号分隔的 1–8 位十六进制字,每个字按 4 字节处理,可带成对的 `[[...]]`,例如 `[[0xfcf90001,0x05,0x0,0x0]]`,不能包含空格。
|
|
149
|
+
- `series` 由已安装 CMD 决定,例如 `HPM6700`、`HPM6400`、`HPM5300`、 `HPM6200` 或 `HPM6300`;`signed` 为布尔值。
|
|
150
|
+
|
|
151
|
+
支持的存储器及适用操作:
|
|
152
|
+
|
|
153
|
+
| `memoryId` | 存储器 | 读/写 | 校验 | 配置 | 擦除 |
|
|
154
|
+
| ---------- | -------- | ----- | ---- | ---- | ---- |
|
|
155
|
+
| `0` | ILM | 是 | 是 | 否 | 否 |
|
|
156
|
+
| `1` | DLM | 是 | 是 | 否 | 否 |
|
|
157
|
+
| `0x10000` | XPI0 NOR | 是 | 是 | 是 | 是 |
|
|
158
|
+
| `0x10001` | XPI1 NOR | 是 | 是 | 是 | 是 |
|
|
159
|
+
| `0x20000` | OTP | 是 | 否 | 否 | 否 |
|
|
160
|
+
| `0x30000` | SDXC0 | 是 | 是 | 是 | 否 |
|
|
161
|
+
| `0x30001` | SDXC1 | 是 | 是 | 是 | 否 |
|
|
162
|
+
|
|
163
|
+
“读/写”表示 schema 允许相应操作;设备、ROM 和 CMD 本身仍可能施加更严格限制。
|
|
164
|
+
|
|
165
|
+
默认超时为:`rom.erase_chip` 1800000 ms;擦除区域、写入、读取到文件和加载操作 600000 ms;其他 ROM 操作 30000 ms。可通过 `timeoutMs` 覆盖。
|
|
166
|
+
|
|
167
|
+
### 文件与执行安全
|
|
168
|
+
|
|
169
|
+
- ROM 命令中的 `filePath` 必须是绝对路径,且不能包含空白或控制字符。这是 CMD 内部命令解析的限制,不适用于 `mfg.set` 的 CMD 路径。
|
|
170
|
+
- 文件输入必须存在且为普通文件。读取到文件要求父目录已存在;默认拒绝覆盖,只有 `overwrite: true` 才允许覆盖已有文件。
|
|
171
|
+
- ROM 操作结果包含 `success`、`exitCode`、`timedOut`、`durationMs` 和合并后的 `log`。日志最多保留 1 MiB;过大时保留首尾并省略中间部分。
|
|
172
|
+
- `query`、内联 `read` 和 `verify` 被标注为只读。读取到文件以及配置、写入、擦除、加载和复位被标注为破坏性操作。
|
|
173
|
+
- 服务端没有二次确认或授权令牌机制。调用方必须在写入、配置、擦除、加载、复位及文件覆盖前确认目标、地址、长度和文件。
|
|
174
|
+
|
|
175
|
+
## 开发与验证
|
|
176
|
+
|
|
177
|
+
```sh
|
|
178
|
+
cd mcp-servers/hpmmfgctl
|
|
179
|
+
npm ci
|
|
180
|
+
npm run lint
|
|
181
|
+
npm run format:check
|
|
182
|
+
npm run typecheck
|
|
183
|
+
npm run build
|
|
184
|
+
npm test
|
|
185
|
+
npm pack --dry-run
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
本地启动示例:
|
|
189
|
+
|
|
190
|
+
```powershell
|
|
191
|
+
$env:HPMMFGCTL_CONFIG = "C:\hpm-mfg-data\config.json"
|
|
192
|
+
node dist/main.js mcp
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
常规自动化测试不需要真实设备,也不会执行镜像烧写操作。发布前仍需在 Windows 和 Linux 上使用真实设备验证串口/HID 枚举、Target 探测,以及经过授权的 ROM 操作。
|
|
196
|
+
|
|
197
|
+
发布标签使用 `hpmmfgctl-v<包版本>`。插件固定引用已发布的 npm 版本,因此应先发布 npm 包,再更新或分发插件。
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** Builds CMD arguments without shell quoting; ROM text remains a single argument. */
|
|
2
|
+
export function buildArgs(target, timeoutMs, command) {
|
|
3
|
+
if (!Number.isInteger(timeoutMs) || timeoutMs < 1000 || timeoutMs > 1800000) {
|
|
4
|
+
throw new Error("timeoutMs must be between 1000 and 1800000");
|
|
5
|
+
}
|
|
6
|
+
if (target.transport === "serial" && !target.port) {
|
|
7
|
+
throw new Error("Serial target has no port");
|
|
8
|
+
}
|
|
9
|
+
const connection = target.transport === "serial"
|
|
10
|
+
? ["-p", `${target.port},${target.baudRate ?? 115200}`]
|
|
11
|
+
: [
|
|
12
|
+
"-u",
|
|
13
|
+
target.path ??
|
|
14
|
+
`0x${(target.vid ?? 0).toString(16).padStart(4, "0")},0x${(target.pid ?? 0).toString(16).padStart(4, "0")}`,
|
|
15
|
+
];
|
|
16
|
+
return [...connection, "-t", String(timeoutMs), "-r", command];
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=arguments.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"arguments.js","sourceRoot":"","sources":["../../src/command/arguments.ts"],"names":[],"mappings":"AAEA,sFAAsF;AACtF,MAAM,UAAU,SAAS,CAAC,MAAc,EAAE,SAAiB,EAAE,OAAe;IAC1E,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,SAAS,GAAG,IAAI,IAAI,SAAS,GAAG,OAAO,EAAE,CAAC;QAC5E,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;IAChE,CAAC;IACD,IAAI,MAAM,CAAC,SAAS,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QAClD,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;IAC/C,CAAC;IACD,MAAM,UAAU,GACd,MAAM,CAAC,SAAS,KAAK,QAAQ;QAC3B,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,QAAQ,IAAI,MAAM,EAAE,CAAC;QACvD,CAAC,CAAC;YACE,IAAI;YACJ,MAAM,CAAC,IAAI;gBACT,KAAK,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;SAC9G,CAAC;IACR,OAAO,CAAC,GAAG,UAAU,EAAE,IAAI,EAAE,MAAM,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;AACjE,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Result } from "./types.js";
|
|
2
|
+
/** Retains bounded process output with the beginning and end of oversized logs. */
|
|
3
|
+
export declare class LogBuffer {
|
|
4
|
+
private limit;
|
|
5
|
+
private head;
|
|
6
|
+
private tail;
|
|
7
|
+
private total;
|
|
8
|
+
/** Sets the maximum retained output size in bytes. */
|
|
9
|
+
constructor(limit?: number);
|
|
10
|
+
/** Appends a process output chunk while discarding excess middle bytes. */
|
|
11
|
+
write(chunk: Buffer): void;
|
|
12
|
+
/** Returns retained output with a truncation marker when needed. */
|
|
13
|
+
bytes(): Buffer;
|
|
14
|
+
}
|
|
15
|
+
/** Serializes CMD processes and supports cancellation during queueing and execution. */
|
|
16
|
+
export declare class Runner {
|
|
17
|
+
private queue;
|
|
18
|
+
/** Runs one command after earlier requests finish; rejects cancelled queued requests. */
|
|
19
|
+
run(path: string, args: string[], timeout: number, signal?: AbortSignal): Promise<Result>;
|
|
20
|
+
/** Starts the process and collects its exit state, deadline, and decoded output. */
|
|
21
|
+
private execute;
|
|
22
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import iconv from "iconv-lite";
|
|
3
|
+
/** Retains bounded process output with the beginning and end of oversized logs. */
|
|
4
|
+
export class LogBuffer {
|
|
5
|
+
limit;
|
|
6
|
+
head = Buffer.alloc(0);
|
|
7
|
+
tail = Buffer.alloc(0);
|
|
8
|
+
total = 0;
|
|
9
|
+
/** Sets the maximum retained output size in bytes. */
|
|
10
|
+
constructor(limit = 1 << 20) {
|
|
11
|
+
this.limit = limit;
|
|
12
|
+
}
|
|
13
|
+
/** Appends a process output chunk while discarding excess middle bytes. */
|
|
14
|
+
write(chunk) {
|
|
15
|
+
this.total += chunk.length;
|
|
16
|
+
const headLimit = Math.floor(this.limit / 2);
|
|
17
|
+
const count = Math.min(chunk.length, headLimit - this.head.length);
|
|
18
|
+
this.head = Buffer.concat([this.head, chunk.subarray(0, count)]);
|
|
19
|
+
this.tail = Buffer.concat([this.tail, chunk.subarray(count)]).subarray(-headLimit);
|
|
20
|
+
}
|
|
21
|
+
/** Returns retained output with a truncation marker when needed. */
|
|
22
|
+
bytes() {
|
|
23
|
+
if (this.total <= this.limit) {
|
|
24
|
+
return Buffer.concat([this.head, this.tail]);
|
|
25
|
+
}
|
|
26
|
+
const marker = Buffer.from("\n[output truncated; middle omitted]\n");
|
|
27
|
+
return Buffer.concat([this.head, marker, this.tail.subarray(marker.length)]);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/** Serializes CMD processes and supports cancellation during queueing and execution. */
|
|
31
|
+
export class Runner {
|
|
32
|
+
queue = Promise.resolve();
|
|
33
|
+
/** Runs one command after earlier requests finish; rejects cancelled queued requests. */
|
|
34
|
+
async run(path, args, timeout, signal) {
|
|
35
|
+
signal?.throwIfAborted();
|
|
36
|
+
const previous = this.queue;
|
|
37
|
+
let release;
|
|
38
|
+
this.queue = new Promise((resolve) => {
|
|
39
|
+
release = resolve;
|
|
40
|
+
});
|
|
41
|
+
try {
|
|
42
|
+
await new Promise((resolve, reject) => {
|
|
43
|
+
const abort = () => reject(signal?.reason ?? new Error("Cancelled"));
|
|
44
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
45
|
+
previous.then(() => {
|
|
46
|
+
signal?.removeEventListener("abort", abort);
|
|
47
|
+
resolve();
|
|
48
|
+
});
|
|
49
|
+
if (signal?.aborted) {
|
|
50
|
+
abort();
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
void previous.then(release);
|
|
56
|
+
throw error;
|
|
57
|
+
}
|
|
58
|
+
try {
|
|
59
|
+
signal?.throwIfAborted();
|
|
60
|
+
return await this.execute(path, args, timeout, signal);
|
|
61
|
+
}
|
|
62
|
+
finally {
|
|
63
|
+
release();
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/** Starts the process and collects its exit state, deadline, and decoded output. */
|
|
67
|
+
execute(path, args, timeout, signal) {
|
|
68
|
+
const started = Date.now();
|
|
69
|
+
return new Promise((resolve) => {
|
|
70
|
+
const log = new LogBuffer();
|
|
71
|
+
let timedOut = false;
|
|
72
|
+
let startError;
|
|
73
|
+
const child = spawn(path, args, {
|
|
74
|
+
shell: false,
|
|
75
|
+
windowsHide: true,
|
|
76
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
77
|
+
});
|
|
78
|
+
child.stdout.on("data", (data) => log.write(data));
|
|
79
|
+
child.stderr.on("data", (data) => log.write(data));
|
|
80
|
+
child.on("error", (error) => {
|
|
81
|
+
startError = error;
|
|
82
|
+
log.write(Buffer.from(`failed to start command: ${error.message}`));
|
|
83
|
+
});
|
|
84
|
+
const abort = () => {
|
|
85
|
+
child.kill();
|
|
86
|
+
};
|
|
87
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
88
|
+
if (signal?.aborted) {
|
|
89
|
+
abort();
|
|
90
|
+
}
|
|
91
|
+
const timer = setTimeout(() => {
|
|
92
|
+
timedOut = true;
|
|
93
|
+
child.kill();
|
|
94
|
+
}, timeout);
|
|
95
|
+
child.on("close", (code) => {
|
|
96
|
+
clearTimeout(timer);
|
|
97
|
+
signal?.removeEventListener("abort", abort);
|
|
98
|
+
const bytes = log.bytes();
|
|
99
|
+
const utf8 = new TextDecoder("utf-8", { fatal: true });
|
|
100
|
+
let text;
|
|
101
|
+
try {
|
|
102
|
+
text = utf8.decode(bytes);
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
text =
|
|
106
|
+
process.platform === "win32" ? iconv.decode(bytes, "gb18030") : bytes.toString("utf8");
|
|
107
|
+
}
|
|
108
|
+
resolve({
|
|
109
|
+
success: code === 0 && !timedOut && !signal?.aborted && !startError,
|
|
110
|
+
exitCode: code ?? -1,
|
|
111
|
+
timedOut,
|
|
112
|
+
durationMs: Date.now() - started,
|
|
113
|
+
log: text,
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/command/runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/** Connection settings retained by a process-local ROM target. */
|
|
2
|
+
export interface Target {
|
|
3
|
+
/** CMD transport selected when the target is created. */
|
|
4
|
+
transport: "serial" | "hid";
|
|
5
|
+
/** Serial device path, such as COM11 or /dev/ttyUSB0. */
|
|
6
|
+
port?: string;
|
|
7
|
+
/** Serial speed; defaults to 115200 when omitted. */
|
|
8
|
+
baudRate?: number;
|
|
9
|
+
/** HID interface path passed directly to CMD. */
|
|
10
|
+
path?: string;
|
|
11
|
+
/** USB vendor ID; defaults to HPMicro VID 0x34B7. */
|
|
12
|
+
vid?: number;
|
|
13
|
+
/** USB product ID; zero matches any product during discovery. */
|
|
14
|
+
pid?: number;
|
|
15
|
+
}
|
|
16
|
+
/** Process result shared by ROM operations and failed target probes. */
|
|
17
|
+
export interface Result {
|
|
18
|
+
/** True only for exit code zero without timeout, cancellation, or start failure. */
|
|
19
|
+
success: boolean;
|
|
20
|
+
/** Process exit code, or -1 when no exit code is available. */
|
|
21
|
+
exitCode: number;
|
|
22
|
+
/** Whether the execution deadline terminated the process. */
|
|
23
|
+
timedOut: boolean;
|
|
24
|
+
/** Execution duration in milliseconds, excluding queue wait time. */
|
|
25
|
+
durationMs: number;
|
|
26
|
+
/** Combined stdout/stderr; capped at 1 MiB while preserving both ends. */
|
|
27
|
+
log: string;
|
|
28
|
+
}
|
|
29
|
+
/** Installed CMD compatibility determined without accessing target hardware. */
|
|
30
|
+
export interface Validation {
|
|
31
|
+
/** Whether executable checks and required CMD options passed. */
|
|
32
|
+
compatible: boolean;
|
|
33
|
+
/** Version text reported by the installed CMD. */
|
|
34
|
+
version?: string;
|
|
35
|
+
/** Reason the executable is unavailable or incompatible. */
|
|
36
|
+
message?: string;
|
|
37
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/command/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Runner } from "./runner.js";
|
|
2
|
+
import type { Validation } from "./types.js";
|
|
3
|
+
/** Checks the installed CMD name, version, failure exit behavior, and required options. */
|
|
4
|
+
export declare function validatePath(path: string, runner: Runner, signal?: AbortSignal): Promise<Validation>;
|