firmwareloop 0.5.0__tar.gz → 0.6.0__tar.gz

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 (37) hide show
  1. {firmwareloop-0.5.0 → firmwareloop-0.6.0}/PKG-INFO +5 -3
  2. {firmwareloop-0.5.0 → firmwareloop-0.6.0}/README.md +4 -2
  3. {firmwareloop-0.5.0 → firmwareloop-0.6.0}/firmwareloop.egg-info/PKG-INFO +5 -3
  4. {firmwareloop-0.5.0 → firmwareloop-0.6.0}/firmwareloop.egg-info/SOURCES.txt +3 -1
  5. {firmwareloop-0.5.0 → firmwareloop-0.6.0}/pyproject.toml +1 -1
  6. {firmwareloop-0.5.0 → firmwareloop-0.6.0}/tools/__init__.py +1 -1
  7. {firmwareloop-0.5.0 → firmwareloop-0.6.0}/tools/fw_mcp_server.py +260 -7
  8. firmwareloop-0.6.0/tools/lib/serial_assistant.py +954 -0
  9. {firmwareloop-0.5.0 → firmwareloop-0.6.0}/tools/ndtdbg_cli.py +515 -515
  10. firmwareloop-0.6.0/tools/serial_cli.py +385 -0
  11. {firmwareloop-0.5.0 → firmwareloop-0.6.0}/tools/setup-agent-mcp.ps1 +2 -2
  12. {firmwareloop-0.5.0 → firmwareloop-0.6.0}/LICENSE +0 -0
  13. {firmwareloop-0.5.0 → firmwareloop-0.6.0}/firmwareloop.egg-info/dependency_links.txt +0 -0
  14. {firmwareloop-0.5.0 → firmwareloop-0.6.0}/firmwareloop.egg-info/entry_points.txt +0 -0
  15. {firmwareloop-0.5.0 → firmwareloop-0.6.0}/firmwareloop.egg-info/requires.txt +0 -0
  16. {firmwareloop-0.5.0 → firmwareloop-0.6.0}/firmwareloop.egg-info/top_level.txt +0 -0
  17. {firmwareloop-0.5.0 → firmwareloop-0.6.0}/setup.cfg +0 -0
  18. {firmwareloop-0.5.0 → firmwareloop-0.6.0}/tools/acceptance-scenario.ps1 +0 -0
  19. {firmwareloop-0.5.0 → firmwareloop-0.6.0}/tools/build.ps1 +0 -0
  20. {firmwareloop-0.5.0 → firmwareloop-0.6.0}/tools/can.ps1 +0 -0
  21. {firmwareloop-0.5.0 → firmwareloop-0.6.0}/tools/check-qoder-mcp.ps1 +0 -0
  22. {firmwareloop-0.5.0 → firmwareloop-0.6.0}/tools/common/build-backends.psm1 +0 -0
  23. {firmwareloop-0.5.0 → firmwareloop-0.6.0}/tools/common/fw.psm1 +0 -0
  24. {firmwareloop-0.5.0 → firmwareloop-0.6.0}/tools/common/uart_probe.py +0 -0
  25. {firmwareloop-0.5.0 → firmwareloop-0.6.0}/tools/doctor.ps1 +0 -0
  26. {firmwareloop-0.5.0 → firmwareloop-0.6.0}/tools/flash.ps1 +0 -0
  27. {firmwareloop-0.5.0 → firmwareloop-0.6.0}/tools/instrument_cli.py +0 -0
  28. {firmwareloop-0.5.0 → firmwareloop-0.6.0}/tools/lib/__init__.py +0 -0
  29. {firmwareloop-0.5.0 → firmwareloop-0.6.0}/tools/lib/instruments.py +0 -0
  30. {firmwareloop-0.5.0 → firmwareloop-0.6.0}/tools/lib/ndtdbg.py +0 -0
  31. {firmwareloop-0.5.0 → firmwareloop-0.6.0}/tools/logic_capture.ps1 +0 -0
  32. {firmwareloop-0.5.0 → firmwareloop-0.6.0}/tools/logic_decode.ps1 +0 -0
  33. {firmwareloop-0.5.0 → firmwareloop-0.6.0}/tools/ndtdbg_bridge.ps1 +0 -0
  34. {firmwareloop-0.5.0 → firmwareloop-0.6.0}/tools/reset.ps1 +0 -0
  35. {firmwareloop-0.5.0 → firmwareloop-0.6.0}/tools/sigrok_csv_to_fwloop.py +0 -0
  36. {firmwareloop-0.5.0 → firmwareloop-0.6.0}/tools/test-backends.ps1 +0 -0
  37. {firmwareloop-0.5.0 → firmwareloop-0.6.0}/tools/test.ps1 +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: firmwareloop
3
- Version: 0.5.0
3
+ Version: 0.6.0
4
4
  Summary: AI Agent Firmware Development and Lab Automation Platform (Dual-Tier MCP Server)
5
5
  Author-email: WeilinZhang <19523330249@163.com>
6
6
  License: MIT
@@ -59,6 +59,7 @@ FirmwareLoop 为 AI Agent 暴露了开箱即用的 MCP 工具,涵盖 5 大核
59
59
  |---|---|---|
60
60
  | **构建与体检** | `fw_doctor` <br> `fw_build` | 环境诊断;编译固件并提取诊断日志。 |
61
61
  | **硬件与探针** | `fw_scan_hardware` <br> `fw_flash` <br> `fw_reset` | 扫描探针与串口;烧录固件、复位芯片。 |
62
+ | **串口助手** | `fw_serial_status` <br> `fw_serial_open` <br> `fw_serial_send` <br> `fw_serial_read` <br> `fw_serial_parse` <br> `fw_serial_capture` <br> `fw_serial_close` | 长驻会话串口收发(HEX/ASCII);发送序列(delay/loop);帧解析;窗口采集 CSV。 |
62
63
  | **总线与协议** | `fw_logic_capture` <br> `fw_logic_decode` | 逻辑分析仪抓取并解码 I2C / SPI / UART。 |
63
64
  | **测试与测量** | `fw_run_hil_test` <br> `fw_measure` <br> `fw_acceptance_scenario` | 运行 HIL 自动化测试;读取示波器 / 程控电源测量值。 |
64
65
  | **工程与脚手架** | `fw_init_project` <br> `fw_configure_lab` <br> `fw_get_evidence` | 生成多 Agent 指南;修改台架配置;提取审计证据。 |
@@ -381,7 +382,7 @@ claude mcp remove --scope user agentic-hil
381
382
  ├── demo-firmware/ 示例固件(CMake;宿主编译模拟 MCU,闭环验证载体)
382
383
  ├── demo-make/ 示例固件(Make;构建测试载体)
383
384
  ├── docs/ DEPENDENCY_MATRIX / REUSE_PLAN / V0.0.2_GAP_VERIFICATION
384
- ├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.5.0)
385
+ ├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.6.0)
385
386
  ├── .mcp.example.json 双层 MCP 配置模板(firmwareloop + agentic-hil)
386
387
  ├── AGENTS.md 通用智能体规范(Antigravity / Qoder / Cursor 等)
387
388
  ├── CLAUDE.md Claude Code CLI 指南
@@ -391,7 +392,7 @@ claude mcp remove --scope user agentic-hil
391
392
 
392
393
  ---
393
394
 
394
- ## 能力验证状态(v0.5.0)
395
+ ## 能力验证状态(v0.6.0)
395
396
 
396
397
  > 状态定义:`Implemented`(已实现)/ `Simulator Validated`(模拟验证)/
397
398
  > `Real Hardware Validated`(真机验证)/ `Experimental` / `Not Implemented`
@@ -399,6 +400,7 @@ claude mcp remove --scope user agentic-hil
399
400
  | 能力 | 状态 |
400
401
  |---|---|
401
402
  | 双层 MCP 服务(13 个工作流与硬件工具) | Implemented + Protocol Validated(31/31 测试通过) |
403
+ | 串口助手工具族(fw_serial_* 七工具, 长驻会话/发送序列/帧解析/窗口采集) | Implemented + Simulator Validated(48 例单测)-> Real Hardware Validated 待 DUT |
402
404
  | 一键多 Agent 脚手架(fwloop init / fw_init_project) | Implemented + Multi-Agent Validated |
403
405
  | 自定义/私有调试工具接入 Skill(fwloop-adapter) | Implemented + Multi-Skill Validated |
404
406
  | 一键终端更新(fwloop update) | Implemented + Auto-updater Validated |
@@ -31,6 +31,7 @@ FirmwareLoop 为 AI Agent 暴露了开箱即用的 MCP 工具,涵盖 5 大核
31
31
  |---|---|---|
32
32
  | **构建与体检** | `fw_doctor` <br> `fw_build` | 环境诊断;编译固件并提取诊断日志。 |
33
33
  | **硬件与探针** | `fw_scan_hardware` <br> `fw_flash` <br> `fw_reset` | 扫描探针与串口;烧录固件、复位芯片。 |
34
+ | **串口助手** | `fw_serial_status` <br> `fw_serial_open` <br> `fw_serial_send` <br> `fw_serial_read` <br> `fw_serial_parse` <br> `fw_serial_capture` <br> `fw_serial_close` | 长驻会话串口收发(HEX/ASCII);发送序列(delay/loop);帧解析;窗口采集 CSV。 |
34
35
  | **总线与协议** | `fw_logic_capture` <br> `fw_logic_decode` | 逻辑分析仪抓取并解码 I2C / SPI / UART。 |
35
36
  | **测试与测量** | `fw_run_hil_test` <br> `fw_measure` <br> `fw_acceptance_scenario` | 运行 HIL 自动化测试;读取示波器 / 程控电源测量值。 |
36
37
  | **工程与脚手架** | `fw_init_project` <br> `fw_configure_lab` <br> `fw_get_evidence` | 生成多 Agent 指南;修改台架配置;提取审计证据。 |
@@ -353,7 +354,7 @@ claude mcp remove --scope user agentic-hil
353
354
  ├── demo-firmware/ 示例固件(CMake;宿主编译模拟 MCU,闭环验证载体)
354
355
  ├── demo-make/ 示例固件(Make;构建测试载体)
355
356
  ├── docs/ DEPENDENCY_MATRIX / REUSE_PLAN / V0.0.2_GAP_VERIFICATION
356
- ├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.5.0)
357
+ ├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.6.0)
357
358
  ├── .mcp.example.json 双层 MCP 配置模板(firmwareloop + agentic-hil)
358
359
  ├── AGENTS.md 通用智能体规范(Antigravity / Qoder / Cursor 等)
359
360
  ├── CLAUDE.md Claude Code CLI 指南
@@ -363,7 +364,7 @@ claude mcp remove --scope user agentic-hil
363
364
 
364
365
  ---
365
366
 
366
- ## 能力验证状态(v0.5.0)
367
+ ## 能力验证状态(v0.6.0)
367
368
 
368
369
  > 状态定义:`Implemented`(已实现)/ `Simulator Validated`(模拟验证)/
369
370
  > `Real Hardware Validated`(真机验证)/ `Experimental` / `Not Implemented`
@@ -371,6 +372,7 @@ claude mcp remove --scope user agentic-hil
371
372
  | 能力 | 状态 |
372
373
  |---|---|
373
374
  | 双层 MCP 服务(13 个工作流与硬件工具) | Implemented + Protocol Validated(31/31 测试通过) |
375
+ | 串口助手工具族(fw_serial_* 七工具, 长驻会话/发送序列/帧解析/窗口采集) | Implemented + Simulator Validated(48 例单测)-> Real Hardware Validated 待 DUT |
374
376
  | 一键多 Agent 脚手架(fwloop init / fw_init_project) | Implemented + Multi-Agent Validated |
375
377
  | 自定义/私有调试工具接入 Skill(fwloop-adapter) | Implemented + Multi-Skill Validated |
376
378
  | 一键终端更新(fwloop update) | Implemented + Auto-updater Validated |
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: firmwareloop
3
- Version: 0.5.0
3
+ Version: 0.6.0
4
4
  Summary: AI Agent Firmware Development and Lab Automation Platform (Dual-Tier MCP Server)
5
5
  Author-email: WeilinZhang <19523330249@163.com>
6
6
  License: MIT
@@ -59,6 +59,7 @@ FirmwareLoop 为 AI Agent 暴露了开箱即用的 MCP 工具,涵盖 5 大核
59
59
  |---|---|---|
60
60
  | **构建与体检** | `fw_doctor` <br> `fw_build` | 环境诊断;编译固件并提取诊断日志。 |
61
61
  | **硬件与探针** | `fw_scan_hardware` <br> `fw_flash` <br> `fw_reset` | 扫描探针与串口;烧录固件、复位芯片。 |
62
+ | **串口助手** | `fw_serial_status` <br> `fw_serial_open` <br> `fw_serial_send` <br> `fw_serial_read` <br> `fw_serial_parse` <br> `fw_serial_capture` <br> `fw_serial_close` | 长驻会话串口收发(HEX/ASCII);发送序列(delay/loop);帧解析;窗口采集 CSV。 |
62
63
  | **总线与协议** | `fw_logic_capture` <br> `fw_logic_decode` | 逻辑分析仪抓取并解码 I2C / SPI / UART。 |
63
64
  | **测试与测量** | `fw_run_hil_test` <br> `fw_measure` <br> `fw_acceptance_scenario` | 运行 HIL 自动化测试;读取示波器 / 程控电源测量值。 |
64
65
  | **工程与脚手架** | `fw_init_project` <br> `fw_configure_lab` <br> `fw_get_evidence` | 生成多 Agent 指南;修改台架配置;提取审计证据。 |
@@ -381,7 +382,7 @@ claude mcp remove --scope user agentic-hil
381
382
  ├── demo-firmware/ 示例固件(CMake;宿主编译模拟 MCU,闭环验证载体)
382
383
  ├── demo-make/ 示例固件(Make;构建测试载体)
383
384
  ├── docs/ DEPENDENCY_MATRIX / REUSE_PLAN / V0.0.2_GAP_VERIFICATION
384
- ├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.5.0)
385
+ ├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.6.0)
385
386
  ├── .mcp.example.json 双层 MCP 配置模板(firmwareloop + agentic-hil)
386
387
  ├── AGENTS.md 通用智能体规范(Antigravity / Qoder / Cursor 等)
387
388
  ├── CLAUDE.md Claude Code CLI 指南
@@ -391,7 +392,7 @@ claude mcp remove --scope user agentic-hil
391
392
 
392
393
  ---
393
394
 
394
- ## 能力验证状态(v0.5.0)
395
+ ## 能力验证状态(v0.6.0)
395
396
 
396
397
  > 状态定义:`Implemented`(已实现)/ `Simulator Validated`(模拟验证)/
397
398
  > `Real Hardware Validated`(真机验证)/ `Experimental` / `Not Implemented`
@@ -399,6 +400,7 @@ claude mcp remove --scope user agentic-hil
399
400
  | 能力 | 状态 |
400
401
  |---|---|
401
402
  | 双层 MCP 服务(13 个工作流与硬件工具) | Implemented + Protocol Validated(31/31 测试通过) |
403
+ | 串口助手工具族(fw_serial_* 七工具, 长驻会话/发送序列/帧解析/窗口采集) | Implemented + Simulator Validated(48 例单测)-> Real Hardware Validated 待 DUT |
402
404
  | 一键多 Agent 脚手架(fwloop init / fw_init_project) | Implemented + Multi-Agent Validated |
403
405
  | 自定义/私有调试工具接入 Skill(fwloop-adapter) | Implemented + Multi-Skill Validated |
404
406
  | 一键终端更新(fwloop update) | Implemented + Auto-updater Validated |
@@ -21,6 +21,7 @@ tools/logic_decode.ps1
21
21
  tools/ndtdbg_bridge.ps1
22
22
  tools/ndtdbg_cli.py
23
23
  tools/reset.ps1
24
+ tools/serial_cli.py
24
25
  tools/setup-agent-mcp.ps1
25
26
  tools/sigrok_csv_to_fwloop.py
26
27
  tools/test-backends.ps1
@@ -30,4 +31,5 @@ tools/common/fw.psm1
30
31
  tools/common/uart_probe.py
31
32
  tools/lib/__init__.py
32
33
  tools/lib/instruments.py
33
- tools/lib/ndtdbg.py
34
+ tools/lib/ndtdbg.py
35
+ tools/lib/serial_assistant.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "firmwareloop"
7
- version = "0.5.0"
7
+ version = "0.6.0"
8
8
  description = "AI Agent Firmware Development and Lab Automation Platform (Dual-Tier MCP Server)"
9
9
  readme = "README.md"
10
10
  authors = [
@@ -2,4 +2,4 @@
2
2
  FirmwareLoop - AI Agent Firmware Development and Lab Automation Platform.
3
3
  """
4
4
 
5
- __version__ = "0.5.0"
5
+ __version__ = "0.6.0"
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env python3
2
2
  """
3
- fw_mcp_server.py - FirmwareLoop High-Level Workflow & Device MCP Server (v0.5.0).
3
+ fw_mcp_server.py - FirmwareLoop High-Level Workflow & Device MCP Server (v0.6.0).
4
4
 
5
5
  Exposes high-level firmware engineering and hardware management tools to AI Coding
6
6
  Agents (Antigravity CLI, Claude Code CLI, Qoder IDE, CodeBuddy IDE, Cursor) via the Model Context
@@ -22,6 +22,13 @@ Tools provided:
22
22
  - fw_ndtdbg_stream_start/status/stop: job mode for long stream captures (immediate job_id, CSV-tail polling, graceful stop)
23
23
  - fw_ndtdbg_flash: NdtBox IIC firmware flash (.bin/.nfw, full-chip erase, double-gated) (ndtdbg_cli.py)
24
24
  - fw_ndtdbg_stream: NdtBox high-rate register stream capture to CSV via one long-lived USB session (read-only) (ndtdbg_cli.py)
25
+ - fw_serial_status: Serial assistant session probe (serve liveness, port, RX/TX counters, log path) (serial_cli.py)
26
+ - fw_serial_open: Serial assistant - open (or reuse) the persistent COM session (HEX/ASCII duplex, session log) (serial_cli.py)
27
+ - fw_serial_send: Serial assistant - send HEX/UTF-8 text or a scripted frame sequence (delay/repeat), confirm-gated (serial_cli.py)
28
+ - fw_serial_read: Serial assistant - drain received bytes or wait-for-pattern (expect, not sleep) (serial_cli.py)
29
+ - fw_serial_parse: Serial assistant - frame parsing (delimiter / fixed-length / checksum / field extraction) (serial_cli.py)
30
+ - fw_serial_capture: Serial assistant - synchronous window capture to CSV with timestamps (serial_cli.py)
31
+ - fw_serial_close: Serial assistant - close the session and reclaim the serve process (serial_cli.py)
25
32
  - fw_logic_capture: Logic analyzer protocol capture (logic_capture.ps1)
26
33
  - fw_logic_decode: Logic analyzer protocol decoding & assertion (logic_decode.ps1)
27
34
  - fw_get_evidence: Read structured audit run evidence (artifacts/runs/)
@@ -1127,6 +1134,108 @@ def handle_fw_scan_hardware(args: Dict[str, Any]) -> Dict[str, Any]:
1127
1134
  }
1128
1135
 
1129
1136
 
1137
+ # ---------------------------------------------------------------------------
1138
+ # Serial assistant (fw_serial_*) - persistent COM session via serial_cli.py
1139
+ # ---------------------------------------------------------------------------
1140
+
1141
+ SERIAL_CLI = os.path.join(REPO_ROOT, "tools", "serial_cli.py")
1142
+
1143
+
1144
+ def _serial_run(cmd: List[str], timeout: int) -> Dict[str, Any]:
1145
+ """serial CLI 子进程用 MCP server 进程当前 CWD 运行 (同 _ndtdbg_run 语义:
1146
+ IDE 以用户工程根为 CWD, lab.yaml 的 CWD 查找链依赖它)。"""
1147
+ return run_process(cmd, timeout=timeout, cwd=os.getcwd())
1148
+
1149
+
1150
+ def handle_fw_serial_status(args: Dict[str, Any]) -> Dict[str, Any]:
1151
+ res = _serial_run([PYTHON_EXE, SERIAL_CLI, "status"], 30)
1152
+ return res.get("data") or res
1153
+
1154
+
1155
+ def handle_fw_serial_open(args: Dict[str, Any]) -> Dict[str, Any]:
1156
+ cmd = [PYTHON_EXE, SERIAL_CLI, "open"]
1157
+ if args.get("port"):
1158
+ cmd.extend(["--port", str(args["port"])])
1159
+ if args.get("baud"):
1160
+ cmd.extend(["--baud", str(args["baud"])])
1161
+ if args.get("backend"):
1162
+ cmd.extend(["--backend", str(args["backend"])])
1163
+ if args.get("data_bits"):
1164
+ cmd.extend(["--data-bits", str(args["data_bits"])])
1165
+ if args.get("parity"):
1166
+ cmd.extend(["--parity", str(args["parity"])])
1167
+ if args.get("stop_bits"):
1168
+ cmd.extend(["--stop-bits", str(args["stop_bits"])])
1169
+ if args.get("lab_config"):
1170
+ cmd.extend(["--lab-config", str(args["lab_config"])])
1171
+ res = _serial_run(cmd, 60)
1172
+ return res.get("data") or res
1173
+
1174
+
1175
+ def handle_fw_serial_send(args: Dict[str, Any]) -> Dict[str, Any]:
1176
+ cmd = [PYTHON_EXE, SERIAL_CLI, "send", "--confirm"] # MCP confirm 默认 true, 网关透传
1177
+ if args.get("hex"):
1178
+ cmd.extend(["--hex", str(args["hex"])])
1179
+ if args.get("text") is not None:
1180
+ cmd.extend(["--text", str(args["text"])])
1181
+ if args.get("frames"):
1182
+ cmd.extend(["--frames", json.dumps(args["frames"], ensure_ascii=False)])
1183
+ if args.get("lab_config"):
1184
+ cmd.extend(["--lab-config", str(args["lab_config"])])
1185
+ res = _serial_run(cmd, 150) # frames 序列 delay 预算上限 90s + 裕量
1186
+ return res.get("data") or res
1187
+
1188
+
1189
+ def handle_fw_serial_read(args: Dict[str, Any]) -> Dict[str, Any]:
1190
+ cmd = [PYTHON_EXE, SERIAL_CLI, "read", "--format", str(args.get("format", "both"))]
1191
+ if args.get("max_bytes"):
1192
+ cmd.extend(["--max-bytes", str(args["max_bytes"])])
1193
+ timeout_ms = int(args.get("timeout_ms", 2000))
1194
+ if args.get("expect"):
1195
+ cmd.extend(["--expect", str(args["expect"]), "--timeout-ms", str(timeout_ms)])
1196
+ if args.get("expect_hex"):
1197
+ cmd.append("--expect-hex")
1198
+ res = _serial_run(cmd, max(30, timeout_ms // 1000 + 30))
1199
+ return res.get("data") or res
1200
+
1201
+
1202
+ def handle_fw_serial_parse(args: Dict[str, Any]) -> Dict[str, Any]:
1203
+ cmd = [PYTHON_EXE, SERIAL_CLI, "parse"]
1204
+ if args.get("source"):
1205
+ cmd.extend(["--source", str(args["source"])])
1206
+ if args.get("mode"):
1207
+ cmd.extend(["--mode", str(args["mode"])])
1208
+ if args.get("delimiter"):
1209
+ cmd.extend(["--delimiter", str(args["delimiter"])])
1210
+ if args.get("fixed_length"):
1211
+ cmd.extend(["--fixed-length", str(args["fixed_length"])])
1212
+ if args.get("checksum"):
1213
+ cmd.extend(["--checksum", str(args["checksum"])])
1214
+ if args.get("fields"):
1215
+ cmd.extend(["--fields-json", json.dumps(args["fields"], ensure_ascii=False)])
1216
+ if args.get("lab_config"):
1217
+ cmd.extend(["--lab-config", str(args["lab_config"])])
1218
+ res = _serial_run(cmd, 60)
1219
+ return res.get("data") or res
1220
+
1221
+
1222
+ def handle_fw_serial_capture(args: Dict[str, Any]) -> Dict[str, Any]:
1223
+ duration_ms = int(args.get("duration_ms", 3000))
1224
+ cmd = [PYTHON_EXE, SERIAL_CLI, "capture", "--duration-ms", str(duration_ms)]
1225
+ if args.get("out"):
1226
+ cmd.extend(["--out", str(args["out"])])
1227
+ if args.get("lab_config"):
1228
+ cmd.extend(["--lab-config", str(args["lab_config"])])
1229
+ res = _serial_run(cmd, duration_ms // 1000 + 60)
1230
+ return res.get("data") or res
1231
+
1232
+
1233
+ def handle_fw_serial_close(args: Dict[str, Any]) -> Dict[str, Any]:
1234
+ res = _serial_run([PYTHON_EXE, SERIAL_CLI, "close"], 30)
1235
+ return res.get("data") or res
1236
+
1237
+
1238
+
1130
1239
  # ===========================================================================
1131
1240
  # Tool Definitions & Schemas
1132
1241
  # ===========================================================================
@@ -1792,6 +1901,150 @@ TOOLS_REGISTRY = {
1792
1901
  },
1793
1902
  "handler": handle_fw_init_project,
1794
1903
  },
1904
+ "fw_serial_status": {
1905
+ "description": "Serial assistant: probe the persistent serial session state (serve process liveness, port/baud, RX/TX counters, buffer watermark, session log path). Run this first to check an existing session.",
1906
+ "inputSchema": {
1907
+ "type": "object",
1908
+ "properties": {},
1909
+ "additionalProperties": False,
1910
+ },
1911
+ "handler": handle_fw_serial_status,
1912
+ },
1913
+ "fw_serial_open": {
1914
+ "description": "Serial assistant: open (or reuse) the persistent COM session backed by a long-lived serve process (RX never drops DUT-pushed data). Session log (JSONL, timestamped RX/TX) is written automatically. Same port/baud reuses the session; a different target returns UART_BUSY (close first, single-session in M1). backend=simulator runs an in-process mock DUT for offline tests (results carry simulated: true).",
1915
+ "inputSchema": {
1916
+ "type": "object",
1917
+ "properties": {
1918
+ "port": {
1919
+ "type": "string",
1920
+ "description": "COM port (e.g. COM5); defaults to lab.yaml serial.port. Required unless configured or backend=simulator",
1921
+ },
1922
+ "baud": {
1923
+ "type": "integer",
1924
+ "description": "Baud rate (default 115200)",
1925
+ "default": 115200,
1926
+ },
1927
+ "backend": {
1928
+ "type": "string",
1929
+ "enum": ["real", "simulator"],
1930
+ "description": "real=pyserial COM (default) / simulator=mock DUT (offline, simulated results)",
1931
+ "default": "real",
1932
+ },
1933
+ "data_bits": {"type": "integer", "enum": [5, 6, 7, 8], "default": 8},
1934
+ "parity": {"type": "string", "enum": ["N", "E", "O", "M", "S"], "default": "N"},
1935
+ "stop_bits": {"type": "number", "enum": [1, 1.5, 2], "default": 1},
1936
+ "lab_config": {"type": "string", "description": "Explicit lab.yaml path override"},
1937
+ },
1938
+ "additionalProperties": False,
1939
+ },
1940
+ "handler": handle_fw_serial_open,
1941
+ },
1942
+ "fw_serial_send": {
1943
+ "description": "Serial assistant: send data to the DUT over the open session - HEX ('A1 04 C9 EF', whitespace/0x tolerant) or UTF-8 text, or a scripted frame sequence (frames: [{hex|text, delay_ms, repeat}]) replicating the 'send list packet' workflow. uart_tx is a gated operation: confirm=true (default) required. Total sequence budget <= 90s.",
1944
+ "inputSchema": {
1945
+ "type": "object",
1946
+ "properties": {
1947
+ "hex": {
1948
+ "type": "string",
1949
+ "description": "HEX payload, e.g. 'A1 04 C9 EF' (mutually exclusive with text; one of hex/text required)",
1950
+ },
1951
+ "text": {
1952
+ "type": "string",
1953
+ "description": "UTF-8 text payload (mutually exclusive with hex; one of hex/text required)",
1954
+ },
1955
+ "frames": {
1956
+ "type": "array",
1957
+ "description": "Frame sequence (send-list packet): [{hex: 'A1 04', delay_ms: 1000}, {text: '33113', delay_ms: 100, repeat: 3}]; overrides hex/text",
1958
+ "items": {
1959
+ "type": "object",
1960
+ "properties": {
1961
+ "hex": {"type": "string"},
1962
+ "text": {"type": "string"},
1963
+ "delay_ms": {"type": "integer", "description": "Wait after sending this frame (default 0)"},
1964
+ "repeat": {"type": "integer", "description": "Repeat count (default 1)"},
1965
+ },
1966
+ },
1967
+ },
1968
+ "confirm": {
1969
+ "type": "boolean",
1970
+ "description": "Confirmation for uart_tx (gated operation)",
1971
+ "default": True,
1972
+ },
1973
+ "lab_config": {"type": "string", "description": "Explicit lab.yaml path override"},
1974
+ },
1975
+ "additionalProperties": False,
1976
+ },
1977
+ "handler": handle_fw_serial_send,
1978
+ },
1979
+ "fw_serial_read": {
1980
+ "description": "Serial assistant: drain bytes received since last read (hex + ascii both returned), or wait for a pattern in the receive stream (expect, not sleep - aligned with boot_expect semantics). Unread data is preserved: buffer (1 MiB ring) + timestamped JSONL session log, so DUT-pushed data is never lost between calls.",
1981
+ "inputSchema": {
1982
+ "type": "object",
1983
+ "properties": {
1984
+ "max_bytes": {"type": "integer", "description": "Max bytes to drain (default 65536)", "default": 65536},
1985
+ "expect": {
1986
+ "type": "string",
1987
+ "description": "Wait until this pattern appears in the stream (text; use expect_hex for byte patterns)",
1988
+ },
1989
+ "expect_hex": {"type": "boolean", "description": "Parse expect as HEX", "default": False},
1990
+ "timeout_ms": {"type": "integer", "description": "expect timeout (default 2000)", "default": 2000},
1991
+ "format": {"type": "string", "enum": ["hex", "text", "both"], "default": "both"},
1992
+ },
1993
+ "additionalProperties": False,
1994
+ },
1995
+ "handler": handle_fw_serial_read,
1996
+ },
1997
+ "fw_serial_parse": {
1998
+ "description": "Serial assistant: frame parsing (super-message simplified) - split the session buffer or a session log file into frames (delimiter e.g. '0D 0A', or fixed-length), verify frame checksums (sum8 / crc16-modbus) and extract typed fields (u8/i8/u16le/u32le/f32le/hex/text). Rules default to lab.yaml serial.parser; pass explicit args to override.",
1999
+ "inputSchema": {
2000
+ "type": "object",
2001
+ "properties": {
2002
+ "source": {
2003
+ "type": "string",
2004
+ "description": "'session' (drain current buffer) or path to a JSONL session log",
2005
+ "default": "session",
2006
+ },
2007
+ "mode": {"type": "string", "enum": ["none", "delimiter", "fixed_length"]},
2008
+ "delimiter": {"type": "string", "description": "HEX delimiter, e.g. '0D 0A' (default)"},
2009
+ "fixed_length": {"type": "integer", "description": "Frame length for fixed_length mode"},
2010
+ "checksum": {"type": "string", "enum": ["none", "sum8", "crc16-modbus"], "description": "Frame-trailer checksum algorithm"},
2011
+ "fields": {
2012
+ "type": "array",
2013
+ "description": "Field extraction: [{name, offset, type: u8|i8|u16le|u16be|i16le|i16be|u32le|u32be|i32le|i32be|f32le|f32be|hex|text, len?}]",
2014
+ "items": {"type": "object"},
2015
+ },
2016
+ "lab_config": {"type": "string", "description": "Explicit lab.yaml path override"},
2017
+ },
2018
+ "additionalProperties": False,
2019
+ },
2020
+ "handler": handle_fw_serial_parse,
2021
+ },
2022
+ "fw_serial_capture": {
2023
+ "description": "Serial assistant: synchronous window capture - record the RX stream for duration_ms into a timestamped CSV (t_rel_ms, dir, hex, printable) for offline analysis/plotting (real-time-curve equivalent; plotting happens in your tools/Agent from the CSV). duration_ms <= 90000; long background captures (job mode) are a planned follow-up.",
2024
+ "inputSchema": {
2025
+ "type": "object",
2026
+ "properties": {
2027
+ "duration_ms": {
2028
+ "type": "integer",
2029
+ "description": "Capture window length in ms (1..90000)",
2030
+ "default": 3000,
2031
+ },
2032
+ "out": {"type": "string", "description": "CSV output path (defaults to a temp-dir file)"},
2033
+ "lab_config": {"type": "string", "description": "Explicit lab.yaml path override"},
2034
+ },
2035
+ "additionalProperties": False,
2036
+ },
2037
+ "handler": handle_fw_serial_capture,
2038
+ },
2039
+ "fw_serial_close": {
2040
+ "description": "Serial assistant: close the session, stop the serve process and release the COM port. Returns final RX/TX stats.",
2041
+ "inputSchema": {
2042
+ "type": "object",
2043
+ "properties": {},
2044
+ "additionalProperties": False,
2045
+ },
2046
+ "handler": handle_fw_serial_close,
2047
+ },
1795
2048
  }
1796
2049
 
1797
2050
 
@@ -1828,7 +2081,7 @@ def process_request(req: Dict[str, Any]) -> Optional[Dict[str, Any]]:
1828
2081
  },
1829
2082
  "serverInfo": {
1830
2083
  "name": "firmwareloop",
1831
- "version": "0.5.0"
2084
+ "version": "0.6.0"
1832
2085
  }
1833
2086
  }
1834
2087
  }
@@ -1963,7 +2216,7 @@ def _settle_stashed_entrypoints(stashed) -> None:
1963
2216
  def handle_cli_update() -> int:
1964
2217
  """Handle `firmwareloop update` command."""
1965
2218
  print("============================================================")
1966
- print(" FirmwareLoop Auto-Updater (v0.5.0)")
2219
+ print(" FirmwareLoop Auto-Updater (v0.6.0)")
1967
2220
  print("============================================================")
1968
2221
 
1969
2222
  is_git_repo = os.path.exists(os.path.join(REPO_ROOT, ".git"))
@@ -2356,7 +2609,7 @@ def set_ndtdbg_dlldir(dll_path: str) -> str:
2356
2609
  def handle_cli_setup() -> int:
2357
2610
  """Handle `firmwareloop setup` command: simultaneously configure Antigravity CLI, Claude Code CLI, Qoder IDE, and CodeBuddy IDE."""
2358
2611
  print("============================================================")
2359
- print(" FirmwareLoop Multi-Agent Global Setup Helper (v0.5.0)")
2612
+ print(" FirmwareLoop Multi-Agent Global Setup Helper (v0.6.0)")
2360
2613
  print("============================================================")
2361
2614
  print("")
2362
2615
 
@@ -2481,7 +2734,7 @@ def handle_cli_setup() -> int:
2481
2734
  def handle_cli_init() -> int:
2482
2735
  """Handle `firmwareloop init` command."""
2483
2736
  print("============================================================")
2484
- print(" FirmwareLoop Multi-Agent Project Initializer (v0.5.0)")
2737
+ print(" FirmwareLoop Multi-Agent Project Initializer (v0.6.0)")
2485
2738
  print("============================================================")
2486
2739
  cwd = os.getcwd()
2487
2740
  print(f"[*] Initializing multi-agent guidelines & bench config in:\n {cwd}\n")
@@ -2502,7 +2755,7 @@ def handle_cli_init() -> int:
2502
2755
 
2503
2756
 
2504
2757
  def print_cli_help() -> None:
2505
- print("""FirmwareLoop (fwloop) — AI Agent Firmware Engineering & Lab Automation Platform (v0.5.0)
2758
+ print("""FirmwareLoop (fwloop) — AI Agent Firmware Engineering & Lab Automation Platform (v0.6.0)
2506
2759
 
2507
2760
  Usage:
2508
2761
  fwloop [command] (or: firmwareloop [command])
@@ -2545,7 +2798,7 @@ def main() -> None:
2545
2798
  sys.exit(2)
2546
2799
  sys.exit(handle_cli_ndtdebugtool(args[1]))
2547
2800
  elif cmd in ["version", "-v", "--version"]:
2548
- print("FirmwareLoop v0.5.0")
2801
+ print("FirmwareLoop v0.6.0")
2549
2802
  sys.exit(0)
2550
2803
  elif cmd in ["help", "-h", "--help"]:
2551
2804
  print_cli_help()