firmwareloop 0.2.0__tar.gz → 0.2.1__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.2.0 → firmwareloop-0.2.1}/PKG-INFO +3 -3
  2. {firmwareloop-0.2.0 → firmwareloop-0.2.1}/README.md +2 -2
  3. {firmwareloop-0.2.0 → firmwareloop-0.2.1}/firmwareloop.egg-info/PKG-INFO +3 -3
  4. {firmwareloop-0.2.0 → firmwareloop-0.2.1}/pyproject.toml +1 -1
  5. {firmwareloop-0.2.0 → firmwareloop-0.2.1}/tools/__init__.py +1 -1
  6. {firmwareloop-0.2.0 → firmwareloop-0.2.1}/tools/fw_mcp_server.py +66 -18
  7. {firmwareloop-0.2.0 → firmwareloop-0.2.1}/tools/ndtdbg_bridge.ps1 +23 -17
  8. {firmwareloop-0.2.0 → firmwareloop-0.2.1}/tools/ndtdbg_cli.py +2 -4
  9. {firmwareloop-0.2.0 → firmwareloop-0.2.1}/tools/setup-agent-mcp.ps1 +2 -2
  10. {firmwareloop-0.2.0 → firmwareloop-0.2.1}/LICENSE +0 -0
  11. {firmwareloop-0.2.0 → firmwareloop-0.2.1}/firmwareloop.egg-info/SOURCES.txt +0 -0
  12. {firmwareloop-0.2.0 → firmwareloop-0.2.1}/firmwareloop.egg-info/dependency_links.txt +0 -0
  13. {firmwareloop-0.2.0 → firmwareloop-0.2.1}/firmwareloop.egg-info/entry_points.txt +0 -0
  14. {firmwareloop-0.2.0 → firmwareloop-0.2.1}/firmwareloop.egg-info/requires.txt +0 -0
  15. {firmwareloop-0.2.0 → firmwareloop-0.2.1}/firmwareloop.egg-info/top_level.txt +0 -0
  16. {firmwareloop-0.2.0 → firmwareloop-0.2.1}/setup.cfg +0 -0
  17. {firmwareloop-0.2.0 → firmwareloop-0.2.1}/tools/acceptance-scenario.ps1 +0 -0
  18. {firmwareloop-0.2.0 → firmwareloop-0.2.1}/tools/build.ps1 +0 -0
  19. {firmwareloop-0.2.0 → firmwareloop-0.2.1}/tools/can.ps1 +0 -0
  20. {firmwareloop-0.2.0 → firmwareloop-0.2.1}/tools/check-qoder-mcp.ps1 +0 -0
  21. {firmwareloop-0.2.0 → firmwareloop-0.2.1}/tools/common/build-backends.psm1 +0 -0
  22. {firmwareloop-0.2.0 → firmwareloop-0.2.1}/tools/common/fw.psm1 +0 -0
  23. {firmwareloop-0.2.0 → firmwareloop-0.2.1}/tools/common/uart_probe.py +0 -0
  24. {firmwareloop-0.2.0 → firmwareloop-0.2.1}/tools/doctor.ps1 +0 -0
  25. {firmwareloop-0.2.0 → firmwareloop-0.2.1}/tools/flash.ps1 +0 -0
  26. {firmwareloop-0.2.0 → firmwareloop-0.2.1}/tools/instrument_cli.py +0 -0
  27. {firmwareloop-0.2.0 → firmwareloop-0.2.1}/tools/lib/__init__.py +0 -0
  28. {firmwareloop-0.2.0 → firmwareloop-0.2.1}/tools/lib/instruments.py +0 -0
  29. {firmwareloop-0.2.0 → firmwareloop-0.2.1}/tools/lib/ndtdbg.py +0 -0
  30. {firmwareloop-0.2.0 → firmwareloop-0.2.1}/tools/logic_capture.ps1 +0 -0
  31. {firmwareloop-0.2.0 → firmwareloop-0.2.1}/tools/logic_decode.ps1 +0 -0
  32. {firmwareloop-0.2.0 → firmwareloop-0.2.1}/tools/reset.ps1 +0 -0
  33. {firmwareloop-0.2.0 → firmwareloop-0.2.1}/tools/sigrok_csv_to_fwloop.py +0 -0
  34. {firmwareloop-0.2.0 → firmwareloop-0.2.1}/tools/test-backends.ps1 +0 -0
  35. {firmwareloop-0.2.0 → firmwareloop-0.2.1}/tools/test.ps1 +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: firmwareloop
3
- Version: 0.2.0
3
+ Version: 0.2.1
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
@@ -381,7 +381,7 @@ claude mcp remove --scope user agentic-hil
381
381
  ├── demo-firmware/ 示例固件(CMake;宿主编译模拟 MCU,闭环验证载体)
382
382
  ├── demo-make/ 示例固件(Make;构建测试载体)
383
383
  ├── docs/ DEPENDENCY_MATRIX / REUSE_PLAN / V0.0.2_GAP_VERIFICATION
384
- ├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.2.0)
384
+ ├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.2.1)
385
385
  ├── .mcp.example.json 双层 MCP 配置模板(firmwareloop + agentic-hil)
386
386
  ├── AGENTS.md 通用智能体规范(Antigravity / Qoder / Cursor 等)
387
387
  ├── CLAUDE.md Claude Code CLI 指南
@@ -391,7 +391,7 @@ claude mcp remove --scope user agentic-hil
391
391
 
392
392
  ---
393
393
 
394
- ## 能力验证状态(v0.2.0
394
+ ## 能力验证状态(v0.2.1
395
395
 
396
396
  > 状态定义:`Implemented`(已实现)/ `Simulator Validated`(模拟验证)/
397
397
  > `Real Hardware Validated`(真机验证)/ `Experimental` / `Not Implemented`
@@ -353,7 +353,7 @@ claude mcp remove --scope user agentic-hil
353
353
  ├── demo-firmware/ 示例固件(CMake;宿主编译模拟 MCU,闭环验证载体)
354
354
  ├── demo-make/ 示例固件(Make;构建测试载体)
355
355
  ├── docs/ DEPENDENCY_MATRIX / REUSE_PLAN / V0.0.2_GAP_VERIFICATION
356
- ├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.2.0)
356
+ ├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.2.1)
357
357
  ├── .mcp.example.json 双层 MCP 配置模板(firmwareloop + agentic-hil)
358
358
  ├── AGENTS.md 通用智能体规范(Antigravity / Qoder / Cursor 等)
359
359
  ├── CLAUDE.md Claude Code CLI 指南
@@ -363,7 +363,7 @@ claude mcp remove --scope user agentic-hil
363
363
 
364
364
  ---
365
365
 
366
- ## 能力验证状态(v0.2.0
366
+ ## 能力验证状态(v0.2.1
367
367
 
368
368
  > 状态定义:`Implemented`(已实现)/ `Simulator Validated`(模拟验证)/
369
369
  > `Real Hardware Validated`(真机验证)/ `Experimental` / `Not Implemented`
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: firmwareloop
3
- Version: 0.2.0
3
+ Version: 0.2.1
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
@@ -381,7 +381,7 @@ claude mcp remove --scope user agentic-hil
381
381
  ├── demo-firmware/ 示例固件(CMake;宿主编译模拟 MCU,闭环验证载体)
382
382
  ├── demo-make/ 示例固件(Make;构建测试载体)
383
383
  ├── docs/ DEPENDENCY_MATRIX / REUSE_PLAN / V0.0.2_GAP_VERIFICATION
384
- ├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.2.0)
384
+ ├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.2.1)
385
385
  ├── .mcp.example.json 双层 MCP 配置模板(firmwareloop + agentic-hil)
386
386
  ├── AGENTS.md 通用智能体规范(Antigravity / Qoder / Cursor 等)
387
387
  ├── CLAUDE.md Claude Code CLI 指南
@@ -391,7 +391,7 @@ claude mcp remove --scope user agentic-hil
391
391
 
392
392
  ---
393
393
 
394
- ## 能力验证状态(v0.2.0
394
+ ## 能力验证状态(v0.2.1
395
395
 
396
396
  > 状态定义:`Implemented`(已实现)/ `Simulator Validated`(模拟验证)/
397
397
  > `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.2.0"
7
+ version = "0.2.1"
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.2.0"
5
+ __version__ = "0.2.1"
@@ -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.2.0).
3
+ fw_mcp_server.py - FirmwareLoop High-Level Workflow & Device MCP Server (v0.2.1).
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
@@ -1619,7 +1619,7 @@ def process_request(req: Dict[str, Any]) -> Optional[Dict[str, Any]]:
1619
1619
  },
1620
1620
  "serverInfo": {
1621
1621
  "name": "firmwareloop",
1622
- "version": "0.2.0"
1622
+ "version": "0.2.1"
1623
1623
  }
1624
1624
  }
1625
1625
  }
@@ -1708,10 +1708,53 @@ def process_request(req: Dict[str, Any]) -> Optional[Dict[str, Any]]:
1708
1708
  return None
1709
1709
 
1710
1710
 
1711
+ def _local_bin_entrypoints() -> list:
1712
+ """uv tool 入口点 exe (~/.local/bin)——本命令自身与常驻 MCP server 都从这里运行。"""
1713
+ home = os.path.expanduser("~")
1714
+ return [os.path.join(home, ".local", "bin", name)
1715
+ for name in ("fwloop.exe", "fw-mcp.exe", "agentic-hil.exe")]
1716
+
1717
+
1718
+ def _stash_local_bin_entrypoints() -> list:
1719
+ """升级前把入口点 exe 重命名让位 (Windows 允许 rename 运行中的 exe, 不允许覆盖写)。
1720
+
1721
+ 否则 `fwloop update` 第一次必然失败: uv 复制新 fwloop.exe 的目标文件正是当前
1722
+ 命令自己的启动映像 (被锁定, os error 32), 第二次则因 "Nothing to upgrade"
1723
+ 跳过入口点同步。返回 [(原路径, 备份路径)]。
1724
+ """
1725
+ stashed = []
1726
+ for path in _local_bin_entrypoints():
1727
+ if not os.path.isfile(path):
1728
+ continue
1729
+ stash = path + ".upgrading"
1730
+ try:
1731
+ if os.path.exists(stash): # 上次升级残留 (旧映像仍被运行中进程持有)
1732
+ os.remove(stash)
1733
+ os.rename(path, stash)
1734
+ stashed.append((path, stash))
1735
+ print(f"[*] Entrypoint stashed for upgrade: {os.path.basename(path)} -> .upgrading")
1736
+ except OSError:
1737
+ pass # 让位失败不阻塞升级: uv 直接覆盖, 若 os error 32 走针对性诊断
1738
+ return stashed
1739
+
1740
+
1741
+ def _settle_stashed_entrypoints(stashed) -> None:
1742
+ """升级收尾: uv 已写入新入口点 -> 删备份 (旧映像仍被运行中进程持有时留待下次);
1743
+ uv 未写入 (升级失败/中止) -> 还原旧入口点, 保证 fwloop 命令不消失。"""
1744
+ for path, stash in stashed:
1745
+ try:
1746
+ if os.path.isfile(path):
1747
+ os.remove(stash) # 新 exe 已就位, 备份可弃
1748
+ else:
1749
+ os.rename(stash, path) # 升级未完成: 还原
1750
+ except OSError:
1751
+ pass # 旧映像仍被本命令/常驻 MCP 持有, 留待下次清理
1752
+
1753
+
1711
1754
  def handle_cli_update() -> int:
1712
1755
  """Handle `firmwareloop update` command."""
1713
1756
  print("============================================================")
1714
- print(" FirmwareLoop Auto-Updater (v0.2.0)")
1757
+ print(" FirmwareLoop Auto-Updater (v0.2.1)")
1715
1758
  print("============================================================")
1716
1759
 
1717
1760
  is_git_repo = os.path.exists(os.path.join(REPO_ROOT, ".git"))
@@ -1754,19 +1797,24 @@ def handle_cli_update() -> int:
1754
1797
  uv_path = shutil.which("uv")
1755
1798
  if uv_path:
1756
1799
  print("[*] Upgrading firmwareloop via `uv tool upgrade firmwareloop`...")
1800
+ # 关键: 入口点 exe (.local\bin\fwloop.exe) 正被本命令自身运行——Windows 禁止
1801
+ # 覆盖运行中的 exe (os error 32), 不让位则第一次 upgrade 必然失败。
1802
+ # rename 让位 (运行中的 exe 允许重命名), uv 复制新入口点后在收尾阶段清理/还原。
1803
+ stashed = _stash_local_bin_entrypoints()
1757
1804
  try:
1758
1805
  res = subprocess.run([uv_path, "tool", "upgrade", "firmwareloop"])
1759
- if res.returncode == 0:
1760
- print("\n============================================================")
1761
- print("[+] FirmwareLoop has been upgraded to the latest version!")
1762
- print("============================================================")
1763
- return 0
1764
- else:
1765
- print(f"[-] uv tool upgrade returned code {res.returncode}")
1766
- return res.returncode
1767
- except Exception as e:
1768
- print(f"[-] Error upgrading via uv tool: {e}")
1769
- return 1
1806
+ finally:
1807
+ _settle_stashed_entrypoints(stashed)
1808
+ if res.returncode == 0:
1809
+ print("\n============================================================")
1810
+ print("[+] FirmwareLoop has been upgraded to the latest version!")
1811
+ print("============================================================")
1812
+ return 0
1813
+ print(f"[-] uv tool upgrade returned code {res.returncode}")
1814
+ print(" 工具环境可能已升级成功, 仅入口点 exe 未更新 (os error 32 = 文件被占用)。")
1815
+ print(" 占用者通常是本命令自身或常驻的 MCP server 进程; 关闭 IDE 后重跑一次")
1816
+ print(" `fwloop update` 即可完成收尾。")
1817
+ return res.returncode
1770
1818
  else:
1771
1819
  print("[*] Upgrading via pip (`pip install --upgrade firmwareloop`)...")
1772
1820
  res = subprocess.run([sys.executable, "-m", "pip", "install", "--upgrade", "firmwareloop"])
@@ -1981,7 +2029,7 @@ def set_ndtdbg_dlldir(dll_path: str) -> str:
1981
2029
  def handle_cli_setup() -> int:
1982
2030
  """Handle `firmwareloop setup` command: simultaneously configure Antigravity CLI, Claude Code CLI, Qoder IDE, and CodeBuddy IDE."""
1983
2031
  print("============================================================")
1984
- print(" FirmwareLoop Multi-Agent Global Setup Helper (v0.2.0)")
2032
+ print(" FirmwareLoop Multi-Agent Global Setup Helper (v0.2.1)")
1985
2033
  print("============================================================")
1986
2034
  print("")
1987
2035
 
@@ -2106,7 +2154,7 @@ def handle_cli_setup() -> int:
2106
2154
  def handle_cli_init() -> int:
2107
2155
  """Handle `firmwareloop init` command."""
2108
2156
  print("============================================================")
2109
- print(" FirmwareLoop Multi-Agent Project Initializer (v0.2.0)")
2157
+ print(" FirmwareLoop Multi-Agent Project Initializer (v0.2.1)")
2110
2158
  print("============================================================")
2111
2159
  cwd = os.getcwd()
2112
2160
  print(f"[*] Initializing multi-agent guidelines & bench config in:\n {cwd}\n")
@@ -2127,7 +2175,7 @@ def handle_cli_init() -> int:
2127
2175
 
2128
2176
 
2129
2177
  def print_cli_help() -> None:
2130
- print("""FirmwareLoop (fwloop) — AI Agent Firmware Engineering & Lab Automation Platform (v0.2.0)
2178
+ print("""FirmwareLoop (fwloop) — AI Agent Firmware Engineering & Lab Automation Platform (v0.2.1)
2131
2179
 
2132
2180
  Usage:
2133
2181
  fwloop [command] (or: firmwareloop [command])
@@ -2167,7 +2215,7 @@ def main() -> None:
2167
2215
  sys.exit(2)
2168
2216
  sys.exit(handle_cli_ndtdebugtool(args[1]))
2169
2217
  elif cmd in ["version", "-v", "--version"]:
2170
- print("FirmwareLoop v0.2.0")
2218
+ print("FirmwareLoop v0.2.1")
2171
2219
  sys.exit(0)
2172
2220
  elif cmd in ["help", "-h", "--help"]:
2173
2221
  print_cli_help()
@@ -497,7 +497,6 @@ try {
497
497
  $consecIoFail = 0
498
498
  $aborted = $false; $abortReason = ""
499
499
  $durationMsTotal = [int]($sDurationS * 1000)
500
- $hexFmt = { param($b) $b.ToString("X2") }
501
500
  while ($true) {
502
501
  $frameNo++
503
502
  $frameStartMs = $sw.Elapsed.TotalMilliseconds
@@ -505,25 +504,32 @@ try {
505
504
  foreach ($r in $sRegs) {
506
505
  $reg = [int]$r.addr; $rlen = [int]$r.len
507
506
  $hexOut = "-"; $tag = "OK"
508
- for ($attempt = 0; $attempt -le $sRetry; $attempt++) {
509
- $tx = New-Object byte[] 2
510
- $tx[0] = [byte]$SlaveAddr; $tx[1] = [byte]$reg
511
- $rb = New-Object byte[] $rlen
512
- if (Invoke-WriteRead $h $tx $rb) {
513
- $hexStr = (($rb | ForEach-Object $hexFmt) -join "")
514
- $allFF = $true
515
- foreach ($b in $rb) { if ($b -ne 0xFF) { $allFF = $false; break } }
516
- if ($allFF) {
517
- $tag = "FF_GAP"; $hexOut = $hexStr # 总线高阻特征: 记录原值, 重试
518
- if ($attempt -lt $sRetry) { Start-Sleep -Milliseconds 5 }
507
+ try {
508
+ for ($attempt = 0; $attempt -le $sRetry; $attempt++) {
509
+ $tx = New-Object byte[] 2
510
+ $tx[0] = [byte]$SlaveAddr; $tx[1] = [byte]$reg
511
+ $rb = New-Object byte[] $rlen
512
+ if (Invoke-WriteRead $h $tx $rb) {
513
+ # ForEach-Object 将管道元素绑定到 $_——scriptblock param()
514
+ # 形式收参恒为 null (Null 方法调用), 必须内联 $_
515
+ $hexStr = (($rb | ForEach-Object { $_.ToString("X2") }) -join " ")
516
+ $allFF = $true
517
+ foreach ($b in $rb) { if ($b -ne 0xFF) { $allFF = $false; break } }
518
+ if ($allFF) {
519
+ $tag = "FF_GAP"; $hexOut = $hexStr # 总线高阻特征: 记录原值, 重试
520
+ if ($attempt -lt $sRetry) { Start-Sleep -Milliseconds 5 }
521
+ } else {
522
+ $tag = "OK"; $hexOut = $hexStr
523
+ break
524
+ }
519
525
  } else {
520
- $tag = "OK"; $hexOut = $hexStr
521
- break
526
+ $tag = "IO_FAIL"; $hexOut = "-"
527
+ if ($attempt -lt $sRetry) { Start-Sleep -Milliseconds 5 }
522
528
  }
523
- } else {
524
- $tag = "IO_FAIL"; $hexOut = "-"
525
- if ($attempt -lt $sRetry) { Start-Sleep -Milliseconds 5 }
526
529
  }
530
+ } catch {
531
+ # 单寄存器异常降级为 IO_FAIL 行继续采集, 不作废整个 stream (fail-closed 韧性)
532
+ $tag = "IO_FAIL"; $hexOut = "-"
527
533
  }
528
534
  if ($tag -eq "IO_FAIL") { $hasIoFail = $true }
529
535
  elseif ($tag -eq "FF_GAP") { $hasGap = $true }
@@ -245,13 +245,11 @@ def cmd_stream(io: NdtBoxIo, config: dict, specs: list, interval_ms, duration_s:
245
245
  fh.write(header + "\n")
246
246
 
247
247
  def on_row(parts: list) -> None:
248
- # 桥行协议: '#F', frame, t_rel_ms, reg, hex|'-', tag
248
+ # 桥行协议: '#F', frame, t_rel_ms, reg, hex|'-', tag (hex 已空格分隔, 直接透传)
249
249
  frame = int(parts[1]); t_rel = float(parts[2])
250
250
  reg = parts[3]; hexs = parts[4]; tag = parts[5] if len(parts) > 5 else "OK"
251
- hex_fmt = (" ".join(hexs[i:i + 2] for i in range(0, len(hexs), 2))
252
- if hexs and hexs != "-" else hexs)
253
251
  line = (f"{frame},{datetime.now().isoformat(timespec='milliseconds')},"
254
- f"{t_rel:g},{reg},{hex_fmt}")
252
+ f"{t_rel:g},{reg},{hexs}")
255
253
  if decode != "hex":
256
254
  line += "," + (decode_payload(hexs, decode) or "")
257
255
  if tag != "OK":
@@ -1,6 +1,6 @@
1
1
  <#
2
2
  .SYNOPSIS
3
- Dual-Tier MCP setup and registration helper (v0.2.0).
3
+ Dual-Tier MCP setup and registration helper (v0.2.1).
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.2.0)" -ForegroundColor Green
245
+ Write-Host " FirmwareLoop Dual-Tier MCP & Agent Setup Helper (v0.2.1)" -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