firmwareloop 0.1.0__tar.gz → 0.1.2__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 (35) hide show
  1. {firmwareloop-0.1.0 → firmwareloop-0.1.2}/PKG-INFO +3 -3
  2. {firmwareloop-0.1.0 → firmwareloop-0.1.2}/README.md +2 -2
  3. {firmwareloop-0.1.0 → firmwareloop-0.1.2}/firmwareloop.egg-info/PKG-INFO +3 -3
  4. {firmwareloop-0.1.0 → firmwareloop-0.1.2}/pyproject.toml +1 -1
  5. {firmwareloop-0.1.0 → firmwareloop-0.1.2}/tools/__init__.py +1 -1
  6. {firmwareloop-0.1.0 → firmwareloop-0.1.2}/tools/fw_mcp_server.py +110 -8
  7. {firmwareloop-0.1.0 → firmwareloop-0.1.2}/tools/ndtdbg_bridge.ps1 +6 -4
  8. {firmwareloop-0.1.0 → firmwareloop-0.1.2}/tools/setup-agent-mcp.ps1 +2 -2
  9. {firmwareloop-0.1.0 → firmwareloop-0.1.2}/LICENSE +0 -0
  10. {firmwareloop-0.1.0 → firmwareloop-0.1.2}/firmwareloop.egg-info/SOURCES.txt +0 -0
  11. {firmwareloop-0.1.0 → firmwareloop-0.1.2}/firmwareloop.egg-info/dependency_links.txt +0 -0
  12. {firmwareloop-0.1.0 → firmwareloop-0.1.2}/firmwareloop.egg-info/entry_points.txt +0 -0
  13. {firmwareloop-0.1.0 → firmwareloop-0.1.2}/firmwareloop.egg-info/requires.txt +0 -0
  14. {firmwareloop-0.1.0 → firmwareloop-0.1.2}/firmwareloop.egg-info/top_level.txt +0 -0
  15. {firmwareloop-0.1.0 → firmwareloop-0.1.2}/setup.cfg +0 -0
  16. {firmwareloop-0.1.0 → firmwareloop-0.1.2}/tools/acceptance-scenario.ps1 +0 -0
  17. {firmwareloop-0.1.0 → firmwareloop-0.1.2}/tools/build.ps1 +0 -0
  18. {firmwareloop-0.1.0 → firmwareloop-0.1.2}/tools/can.ps1 +0 -0
  19. {firmwareloop-0.1.0 → firmwareloop-0.1.2}/tools/check-qoder-mcp.ps1 +0 -0
  20. {firmwareloop-0.1.0 → firmwareloop-0.1.2}/tools/common/build-backends.psm1 +0 -0
  21. {firmwareloop-0.1.0 → firmwareloop-0.1.2}/tools/common/fw.psm1 +0 -0
  22. {firmwareloop-0.1.0 → firmwareloop-0.1.2}/tools/common/uart_probe.py +0 -0
  23. {firmwareloop-0.1.0 → firmwareloop-0.1.2}/tools/doctor.ps1 +0 -0
  24. {firmwareloop-0.1.0 → firmwareloop-0.1.2}/tools/flash.ps1 +0 -0
  25. {firmwareloop-0.1.0 → firmwareloop-0.1.2}/tools/instrument_cli.py +0 -0
  26. {firmwareloop-0.1.0 → firmwareloop-0.1.2}/tools/lib/__init__.py +0 -0
  27. {firmwareloop-0.1.0 → firmwareloop-0.1.2}/tools/lib/instruments.py +0 -0
  28. {firmwareloop-0.1.0 → firmwareloop-0.1.2}/tools/lib/ndtdbg.py +0 -0
  29. {firmwareloop-0.1.0 → firmwareloop-0.1.2}/tools/logic_capture.ps1 +0 -0
  30. {firmwareloop-0.1.0 → firmwareloop-0.1.2}/tools/logic_decode.ps1 +0 -0
  31. {firmwareloop-0.1.0 → firmwareloop-0.1.2}/tools/ndtdbg_cli.py +0 -0
  32. {firmwareloop-0.1.0 → firmwareloop-0.1.2}/tools/reset.ps1 +0 -0
  33. {firmwareloop-0.1.0 → firmwareloop-0.1.2}/tools/sigrok_csv_to_fwloop.py +0 -0
  34. {firmwareloop-0.1.0 → firmwareloop-0.1.2}/tools/test-backends.ps1 +0 -0
  35. {firmwareloop-0.1.0 → firmwareloop-0.1.2}/tools/test.ps1 +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: firmwareloop
3
- Version: 0.1.0
3
+ Version: 0.1.2
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
@@ -338,7 +338,7 @@ claude mcp remove --scope user agentic-hil
338
338
  ├── demo-firmware/ 示例固件(CMake;宿主编译模拟 MCU,闭环验证载体)
339
339
  ├── demo-make/ 示例固件(Make;构建测试载体)
340
340
  ├── docs/ DEPENDENCY_MATRIX / REUSE_PLAN / V0.0.2_GAP_VERIFICATION
341
- ├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.1.0)
341
+ ├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.1.2)
342
342
  ├── .mcp.example.json 双层 MCP 配置模板(firmwareloop + agentic-hil)
343
343
  ├── AGENTS.md 通用智能体规范(Antigravity / Qoder / Cursor 等)
344
344
  ├── CLAUDE.md Claude Code CLI 指南
@@ -348,7 +348,7 @@ claude mcp remove --scope user agentic-hil
348
348
 
349
349
  ---
350
350
 
351
- ## 能力验证状态(v0.1.0
351
+ ## 能力验证状态(v0.1.2
352
352
 
353
353
  > 状态定义:`Implemented`(已实现)/ `Simulator Validated`(模拟验证)/
354
354
  > `Real Hardware Validated`(真机验证)/ `Experimental` / `Not Implemented`
@@ -310,7 +310,7 @@ claude mcp remove --scope user agentic-hil
310
310
  ├── demo-firmware/ 示例固件(CMake;宿主编译模拟 MCU,闭环验证载体)
311
311
  ├── demo-make/ 示例固件(Make;构建测试载体)
312
312
  ├── docs/ DEPENDENCY_MATRIX / REUSE_PLAN / V0.0.2_GAP_VERIFICATION
313
- ├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.1.0)
313
+ ├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.1.2)
314
314
  ├── .mcp.example.json 双层 MCP 配置模板(firmwareloop + agentic-hil)
315
315
  ├── AGENTS.md 通用智能体规范(Antigravity / Qoder / Cursor 等)
316
316
  ├── CLAUDE.md Claude Code CLI 指南
@@ -320,7 +320,7 @@ claude mcp remove --scope user agentic-hil
320
320
 
321
321
  ---
322
322
 
323
- ## 能力验证状态(v0.1.0
323
+ ## 能力验证状态(v0.1.2
324
324
 
325
325
  > 状态定义:`Implemented`(已实现)/ `Simulator Validated`(模拟验证)/
326
326
  > `Real Hardware Validated`(真机验证)/ `Experimental` / `Not Implemented`
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: firmwareloop
3
- Version: 0.1.0
3
+ Version: 0.1.2
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
@@ -338,7 +338,7 @@ claude mcp remove --scope user agentic-hil
338
338
  ├── demo-firmware/ 示例固件(CMake;宿主编译模拟 MCU,闭环验证载体)
339
339
  ├── demo-make/ 示例固件(Make;构建测试载体)
340
340
  ├── docs/ DEPENDENCY_MATRIX / REUSE_PLAN / V0.0.2_GAP_VERIFICATION
341
- ├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.1.0)
341
+ ├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.1.2)
342
342
  ├── .mcp.example.json 双层 MCP 配置模板(firmwareloop + agentic-hil)
343
343
  ├── AGENTS.md 通用智能体规范(Antigravity / Qoder / Cursor 等)
344
344
  ├── CLAUDE.md Claude Code CLI 指南
@@ -348,7 +348,7 @@ claude mcp remove --scope user agentic-hil
348
348
 
349
349
  ---
350
350
 
351
- ## 能力验证状态(v0.1.0
351
+ ## 能力验证状态(v0.1.2
352
352
 
353
353
  > 状态定义:`Implemented`(已实现)/ `Simulator Validated`(模拟验证)/
354
354
  > `Real Hardware Validated`(真机验证)/ `Experimental` / `Not Implemented`
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "firmwareloop"
7
- version = "0.1.0"
7
+ version = "0.1.2"
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.1.0"
5
+ __version__ = "0.1.2"
@@ -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.1.0).
3
+ fw_mcp_server.py - FirmwareLoop High-Level Workflow & Device MCP Server (v0.1.2).
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, Cursor) via the Model Context
@@ -16,6 +16,8 @@ Tools provided:
16
16
  - fw_measure: Controlled PyVISA/SCPI instrument measurement (instrument_cli.py)
17
17
  - fw_ndtdbg_status: NdtBox (USB->IIC) connectivity & firmware version probe (ndtdbg_cli.py)
18
18
  - fw_ndtdbg_measure: NdtBox pressure-sensor data stream polling over IIC (ndtdbg_cli.py)
19
+ - fw_ndtdbg_read_reg: NdtBox IIC register read (ndtdbg_cli.py)
20
+ - fw_ndtdbg_write_reg: NdtBox IIC register write, double-gated (ndtdbg_cli.py)
19
21
  - fw_logic_capture: Logic analyzer protocol capture (logic_capture.ps1)
20
22
  - fw_logic_decode: Logic analyzer protocol decoding & assertion (logic_decode.ps1)
21
23
  - fw_get_evidence: Read structured audit run evidence (artifacts/runs/)
@@ -272,6 +274,37 @@ def handle_fw_ndtdbg_measure(args: Dict[str, Any]) -> Dict[str, Any]:
272
274
  return res
273
275
 
274
276
 
277
+ def _ndtdbg_reg_args(args: Dict[str, Any], cmd: List[str]) -> None:
278
+ if args.get("dll_dir"):
279
+ cmd.extend(["--dll-dir", args["dll_dir"]])
280
+ if args.get("slave_addr"):
281
+ cmd.extend(["--slave-addr", str(args["slave_addr"])])
282
+
283
+
284
+ def handle_fw_ndtdbg_read_reg(args: Dict[str, Any]) -> Dict[str, Any]:
285
+ cli_script = os.path.join(REPO_ROOT, "tools", "ndtdbg_cli.py")
286
+ cmd = [PYTHON_EXE, cli_script, "read-reg", "--addr", str(args.get("reg", "0x10")),
287
+ "--len", str(args.get("len", 1))]
288
+ _ndtdbg_reg_args(args, cmd)
289
+ res = run_process(cmd, timeout=60)
290
+ if res.get("data"):
291
+ return res["data"]
292
+ return res
293
+
294
+
295
+ def handle_fw_ndtdbg_write_reg(args: Dict[str, Any]) -> Dict[str, Any]:
296
+ cli_script = os.path.join(REPO_ROOT, "tools", "ndtdbg_cli.py")
297
+ cmd = [PYTHON_EXE, cli_script, "write-reg", "--addr", str(args.get("reg")),
298
+ "--data", str(args.get("data", ""))]
299
+ if args.get("confirm"):
300
+ cmd.append("--confirm")
301
+ _ndtdbg_reg_args(args, cmd)
302
+ res = run_process(cmd, timeout=60)
303
+ if res.get("data"):
304
+ return res["data"]
305
+ return res
306
+
307
+
275
308
  def handle_fw_logic_capture(args: Dict[str, Any]) -> Dict[str, Any]:
276
309
  script = os.path.join(REPO_ROOT, "tools", "logic_capture.ps1")
277
310
  cmd = [PWSH_EXE, "-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-File", script, "-Json"]
@@ -1106,6 +1139,66 @@ TOOLS_REGISTRY = {
1106
1139
  },
1107
1140
  "handler": handle_fw_ndtdbg_measure,
1108
1141
  },
1142
+ "fw_ndtdbg_read_reg": {
1143
+ "description": "Read IIC register bytes from the NdtBox target chip (ChipSea Fxx). Read-only, hardware-agnostic register access.",
1144
+ "inputSchema": {
1145
+ "type": "object",
1146
+ "properties": {
1147
+ "reg": {
1148
+ "type": "string",
1149
+ "description": "Register address (0x prefix or decimal), e.g. 0xBE",
1150
+ "default": "0x10",
1151
+ },
1152
+ "len": {
1153
+ "type": "integer",
1154
+ "description": "Bytes to read (1..256)",
1155
+ "default": 1,
1156
+ },
1157
+ "dll_dir": {
1158
+ "type": "string",
1159
+ "description": "NdtDebugTool lib directory; default from lab.yaml ndtdbg.dll_dir",
1160
+ },
1161
+ "slave_addr": {
1162
+ "type": "string",
1163
+ "description": "IIC slave address (e.g. 0xA0)",
1164
+ },
1165
+ },
1166
+ "additionalProperties": False,
1167
+ },
1168
+ "handler": handle_fw_ndtdbg_read_reg,
1169
+ },
1170
+ "fw_ndtdbg_write_reg": {
1171
+ "description": "Write bytes to an IIC register of the NdtBox target chip (ChipSea Fxx). Defended: requires lab.yaml ndtdbg.write_allowed: true AND the confirm: true argument; otherwise returns PERMISSION_DENIED.",
1172
+ "inputSchema": {
1173
+ "type": "object",
1174
+ "properties": {
1175
+ "reg": {
1176
+ "type": "string",
1177
+ "description": "Register address (0x prefix or decimal), e.g. 0xBE",
1178
+ },
1179
+ "data": {
1180
+ "type": "string",
1181
+ "description": "Hex payload, e.g. 01 or BE 42",
1182
+ },
1183
+ "confirm": {
1184
+ "type": "boolean",
1185
+ "description": "Acknowledge the write intent (double-gated with lab.yaml write_allowed)",
1186
+ "default": False,
1187
+ },
1188
+ "dll_dir": {
1189
+ "type": "string",
1190
+ "description": "NdtDebugTool lib directory; default from lab.yaml ndtdbg.dll_dir",
1191
+ },
1192
+ "slave_addr": {
1193
+ "type": "string",
1194
+ "description": "IIC slave address (e.g. 0xA0)",
1195
+ },
1196
+ },
1197
+ "required": ["reg", "data"],
1198
+ "additionalProperties": False,
1199
+ },
1200
+ "handler": handle_fw_ndtdbg_write_reg,
1201
+ },
1109
1202
  "fw_logic_capture": {
1110
1203
  "description": "Capture digital protocol waveforms (I2C, SPI, UART) via Saleae / sigrok or deterministic simulator.",
1111
1204
  "inputSchema": {
@@ -1243,7 +1336,7 @@ def process_request(req: Dict[str, Any]) -> Optional[Dict[str, Any]]:
1243
1336
  },
1244
1337
  "serverInfo": {
1245
1338
  "name": "firmwareloop",
1246
- "version": "0.1.0"
1339
+ "version": "0.1.2"
1247
1340
  }
1248
1341
  }
1249
1342
  }
@@ -1335,7 +1428,7 @@ def process_request(req: Dict[str, Any]) -> Optional[Dict[str, Any]]:
1335
1428
  def handle_cli_update() -> int:
1336
1429
  """Handle `firmwareloop update` command."""
1337
1430
  print("============================================================")
1338
- print(" FirmwareLoop Auto-Updater (v0.1.0)")
1431
+ print(" FirmwareLoop Auto-Updater (v0.1.2)")
1339
1432
  print("============================================================")
1340
1433
 
1341
1434
  is_git_repo = os.path.exists(os.path.join(REPO_ROOT, ".git"))
@@ -1433,7 +1526,16 @@ def upsert_qoder_mcp_json(mcp_path: str, servers: Optional[Dict[str, Any]] = Non
1433
1526
  mcp_servers = data.get("mcpServers")
1434
1527
  if not isinstance(mcp_servers, dict):
1435
1528
  mcp_servers = {}
1436
- mcp_servers.update(payload)
1529
+ # Merge per-entry (not whole-key replace): keep existing per-server extras
1530
+ # like "env" (e.g. FW_LAB_CONFIG) that this payload does not define.
1531
+ for name, entry in payload.items():
1532
+ old = mcp_servers.get(name)
1533
+ if isinstance(old, dict) and isinstance(entry, dict):
1534
+ merged = dict(old)
1535
+ merged.update(entry)
1536
+ mcp_servers[name] = merged
1537
+ else:
1538
+ mcp_servers[name] = entry
1437
1539
  data["mcpServers"] = mcp_servers
1438
1540
  parent = os.path.dirname(mcp_path)
1439
1541
  if parent:
@@ -1478,7 +1580,7 @@ def configure_qoder_user_mcp(user_home: str) -> List[Dict[str, Any]]:
1478
1580
  def handle_cli_setup() -> int:
1479
1581
  """Handle `firmwareloop setup` command: simultaneously configure Antigravity CLI, Claude Code CLI, and Qoder IDE."""
1480
1582
  print("============================================================")
1481
- print(" FirmwareLoop Multi-Agent Global Setup Helper (v0.1.0)")
1583
+ print(" FirmwareLoop Multi-Agent Global Setup Helper (v0.1.2)")
1482
1584
  print("============================================================")
1483
1585
  print("")
1484
1586
 
@@ -1583,7 +1685,7 @@ def handle_cli_setup() -> int:
1583
1685
  def handle_cli_init() -> int:
1584
1686
  """Handle `firmwareloop init` command."""
1585
1687
  print("============================================================")
1586
- print(" FirmwareLoop Multi-Agent Project Initializer (v0.1.0)")
1688
+ print(" FirmwareLoop Multi-Agent Project Initializer (v0.1.2)")
1587
1689
  print("============================================================")
1588
1690
  cwd = os.getcwd()
1589
1691
  print(f"[*] Initializing multi-agent guidelines & bench config in:\n {cwd}\n")
@@ -1604,7 +1706,7 @@ def handle_cli_init() -> int:
1604
1706
 
1605
1707
 
1606
1708
  def print_cli_help() -> None:
1607
- print("""FirmwareLoop (fwloop) — AI Agent Firmware Engineering & Lab Automation Platform (v0.1.0)
1709
+ print("""FirmwareLoop (fwloop) — AI Agent Firmware Engineering & Lab Automation Platform (v0.1.2)
1608
1710
 
1609
1711
  Usage:
1610
1712
  fwloop [command] (or: firmwareloop [command])
@@ -1635,7 +1737,7 @@ def main() -> None:
1635
1737
  elif cmd in ["setup", "register"]:
1636
1738
  sys.exit(handle_cli_setup())
1637
1739
  elif cmd in ["version", "-v", "--version"]:
1638
- print("FirmwareLoop v0.1.0")
1740
+ print("FirmwareLoop v0.1.2")
1639
1741
  sys.exit(0)
1640
1742
  elif cmd in ["help", "-h", "--help"]:
1641
1743
  print_cli_help()
@@ -68,7 +68,7 @@ function Parse-Hex([string]$s) {
68
68
  try { $bytes[[int]($i / 2)] = [Convert]::ToByte($clean.Substring($i, 2), 16) }
69
69
  catch { Fail "CONFIG_ERROR" "Data 含非法十六进制字符" $clean.Substring($i, 2) }
70
70
  }
71
- return $bytes
71
+ return ,$bytes # PS 函数返回会展开单元素数组, 一元数组符保护类型
72
72
  }
73
73
 
74
74
  function Open-Device([int]$iIndex) {
@@ -103,10 +103,12 @@ function Read-Reg([uint32]$h, [int]$addr, [int]$reg, [int]$len) {
103
103
  return $rb
104
104
  }
105
105
 
106
- function Write-Reg([uint32]$h, [int]$addr, [int]$reg, [byte[]]$data) {
107
- $wb = New-Object byte[] (2 + $data.Length)
106
+ function Write-Reg([uint32]$h, [int]$addr, [int]$reg, $data) {
107
+ # 无类型约束 + 函数内强转: 兼容标量/单元素数组/byte[] 各种传参形态 (PS5.1 会展开单元素数组)
108
+ $bytes = [byte[]]@($data)
109
+ $wb = New-Object byte[] (2 + $bytes.Length)
108
110
  for ($i = 0; $i -lt $wb.Length; $i++) {
109
- if ($i -eq 0) { $wb[0] = $addr } elseif ($i -eq 1) { $wb[1] = $reg } else { $wb[$i] = $data[$i - 2] }
111
+ if ($i -eq 0) { $wb[0] = $addr } elseif ($i -eq 1) { $wb[1] = $reg } else { $wb[$i] = $bytes[$i - 2] }
110
112
  }
111
113
  if (-not (Invoke-WriteRead $h $wb (New-Object byte[] 0))) { Fail "TARGET_MISMATCH" ("IIC 写无应答 addr=0x{0:X2} reg=0x{1:X2}" -f $addr, $reg) ("{0:X2}/{1:X2}" -f $addr, $reg) }
112
114
  }
@@ -1,6 +1,6 @@
1
1
  <#
2
2
  .SYNOPSIS
3
- Dual-Tier MCP setup and registration helper (v0.1.0).
3
+ Dual-Tier MCP setup and registration helper (v0.1.2).
4
4
  Inspects installed AI coding agents (Qoder, Claude Code, Antigravity, Cursor)
5
5
  and configures global MCP / skills or prints exact registration commands.
6
6
 
@@ -242,7 +242,7 @@ if ($Json) {
242
242
  Write-FwJson ([pscustomobject]$report)
243
243
  } else {
244
244
  Write-Host "============================================================" -ForegroundColor Cyan
245
- Write-Host " FirmwareLoop Dual-Tier MCP & Agent Setup Helper (v0.1.0)" -ForegroundColor Green
245
+ Write-Host " FirmwareLoop Dual-Tier MCP & Agent Setup Helper (v0.1.2)" -ForegroundColor Green
246
246
  Write-Host "============================================================" -ForegroundColor Cyan
247
247
  Write-Host ""
248
248
  Write-Host "[1] Google Antigravity / Gemini CLI:" -ForegroundColor Yellow
File without changes
File without changes
File without changes