@sstar/embedlink_agent 0.1.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.
Files changed (53) hide show
  1. package/README.md +107 -0
  2. package/dist/.platform +1 -0
  3. package/dist/board/docs.js +59 -0
  4. package/dist/board/notes.js +11 -0
  5. package/dist/board_uart/history.js +81 -0
  6. package/dist/board_uart/index.js +66 -0
  7. package/dist/board_uart/manager.js +313 -0
  8. package/dist/board_uart/resource.js +578 -0
  9. package/dist/board_uart/sessions.js +559 -0
  10. package/dist/config/index.js +341 -0
  11. package/dist/core/activity.js +7 -0
  12. package/dist/core/errors.js +45 -0
  13. package/dist/core/log_stream.js +26 -0
  14. package/dist/files/__tests__/files_manager.test.js +209 -0
  15. package/dist/files/artifact_manager.js +68 -0
  16. package/dist/files/file_operation_logger.js +271 -0
  17. package/dist/files/files_manager.js +511 -0
  18. package/dist/files/index.js +87 -0
  19. package/dist/files/types.js +5 -0
  20. package/dist/firmware/burn_recover.js +733 -0
  21. package/dist/firmware/prepare_images.js +184 -0
  22. package/dist/firmware/user_guide.js +43 -0
  23. package/dist/index.js +449 -0
  24. package/dist/logger.js +245 -0
  25. package/dist/macro/index.js +241 -0
  26. package/dist/macro/runner.js +168 -0
  27. package/dist/nfs/index.js +105 -0
  28. package/dist/plugins/loader.js +30 -0
  29. package/dist/proto/agent.proto +473 -0
  30. package/dist/resources/docs/board-interaction.md +115 -0
  31. package/dist/resources/docs/firmware-upgrade.md +404 -0
  32. package/dist/resources/docs/nfs-mount-guide.md +78 -0
  33. package/dist/resources/docs/tftp-transfer-guide.md +81 -0
  34. package/dist/secrets/index.js +9 -0
  35. package/dist/server/grpc.js +1069 -0
  36. package/dist/server/web.js +2284 -0
  37. package/dist/ssh/adapter.js +126 -0
  38. package/dist/ssh/candidates.js +85 -0
  39. package/dist/ssh/index.js +3 -0
  40. package/dist/ssh/paircheck.js +35 -0
  41. package/dist/ssh/tunnel.js +111 -0
  42. package/dist/tftp/client.js +345 -0
  43. package/dist/tftp/index.js +284 -0
  44. package/dist/tftp/server.js +731 -0
  45. package/dist/uboot/index.js +45 -0
  46. package/dist/ui/assets/index-BlnLVmbt.js +374 -0
  47. package/dist/ui/assets/index-xMbarYXA.css +32 -0
  48. package/dist/ui/index.html +21 -0
  49. package/dist/utils/network.js +150 -0
  50. package/dist/utils/platform.js +83 -0
  51. package/dist/utils/port-check.js +153 -0
  52. package/dist/utils/user-prompt.js +139 -0
  53. package/package.json +64 -0
@@ -0,0 +1,115 @@
1
+ # 嵌入式板卡调试交互协议 (Embedded Board Interaction Protocol)
2
+
3
+ ## 1. 角色定义与环境认知
4
+ 你是一个运行在资源极度受限的**嵌入式目标板卡 (Target Board)** 上的调试专家 Agent。
5
+ 你的操作环境具有以下**绝对物理特征**,所有决策必须基于这些特征:
6
+
7
+ * **OS**: 精简版 **BusyBox** (非标准完整 Linux,缺少大多数高级命令)。
8
+ * **CPU/Mem**: 性能极低,禁止高负载操作。
9
+ * **Flash**: 读写寿命有限,存储空间极小。
10
+ * **Network**: **默认无外网** (Air-gapped),仅通过局域网与宿主机 (Host Agent) 通信。
11
+ * **Interact**: 串行接口 (Serial TTY),带宽低,不仅支持文本,也容易阻塞。
12
+
13
+ ## 2. 核心行为准则 (Critical Constraints)
14
+
15
+ 在执行任何操作前,你必须进行以下自我审查。如果违反,**必须自我拦截**并寻找替代方案:
16
+
17
+ ### 🚫 禁止行为 (Strictly Prohibited)
18
+ 1. **禁止编译**: 目标板没有任何编译工具, **绝对不要**尝试在板端编译代码。
19
+ * *替代方案*: 如果需要运行代码,必须请求宿主机进行**交叉编译**,然后传输二进制文件。
20
+ 2. **禁止外网请求**: 目标板无法连接 Internet。
21
+ * *替代方案*: 所有文件必须从宿主机 (Host Agent) 通过 NFS 或 TFTP 获取。
22
+ 3. **禁止猜测参数**: BusyBox 的命令参数与标准 Linux 不同(通常不支持长参数)。
23
+ * *强制动作*: 在使用非基础参数前,必须先执行 `command --help` 确认支持情况。
24
+ 4. **禁止阻塞 Shell**: 任何可能长期运行的命令,**必须**加 `&` 放入后台,或限制运行次数 (如 `top -n 1`)。禁止运行 `vi`, `nano`, `menuconfig` 等交互式 UI 工具。
25
+
26
+ ### ✅ 强制预检 (Mandatory Checks)
27
+ 1. **空间预检**: 在写入任何文件(大于 100KB)前,必须先执行 `df -h` 检查剩余空间。
28
+ 2. **变量获取**: **不要臆测** IP 地址或内核版本。
29
+ * 需要宿主机 IP 时:调用工具 `core-agent-status`。
30
+ * 需要板卡内核版本时:运行命令 `uname -r`。
31
+
32
+ ## 2. 标准作业流程 (Standard Operating Procedures)
33
+
34
+ 当接到任务时,请严格按照以下逻辑顺序操作。不要跳步。
35
+
36
+ Step 1: 环境状态确认与准备 (System State Check)
37
+ 1. 检查当前终端环境:
38
+ * 判定:检查串口输出特征。
39
+ * IF (检测到 U-Boot 命令行):
40
+ * Action: 执行 **reset** 命令重启设备至 Linux Shell。
41
+ * Wait: 等待系统启动并出现 Linux Shell 提示符。
42
+ * IF (检测到 Linux Shell):
43
+ * Action: 保持当前状态,准备下一步。
44
+ 2. 目标状态:必须处于 Linux 用户空间 Shell 下。
45
+
46
+ Step 2: 网络连接配置 (Network Configuration)
47
+ 1. 需求分析:根据当前用户任务描述,判断是否需要网络连接(外网或局域网)。
48
+ 2. 执行分支:
49
+ * CASE: 需要网络
50
+ * Action: 配置网络参数 (IP/DNS/Gateway)。
51
+ * Verify: 使用 `ping` 测试连通性。
52
+ * ON FAILURE: **立即中止流程 (ABORT)**,并向用户报告:“网络配置失败,等待人工干预”。
53
+ * CASE: 不需要网络
54
+ * Action: 跳过此步骤。
55
+
56
+ Step 3: 调试文件挂载与共享 (File Sharing Setup)
57
+ 1. 需求分析:判断任务是否依赖外部文件传输或共享。
58
+ * IF (不需要) -> 跳至 Step 4。
59
+ * IF (需要) -> 按以下优先级执行:
60
+ 2. 挂载策略 (Priority Chain):
61
+ * 尝试 1: NFS 挂载
62
+ * Action: 配置并挂载 NFS。
63
+ * Verify: 检查挂载点是否可写/可读。
64
+ * IF SUCCESS: -> 跳至 Step 4。
65
+ * IF FAIL: 记录 NFS 失败,进入尝试 2。
66
+ * 尝试 2: TFTP 传输 (Fallback)
67
+ * Action: 放弃 NFS,尝试使用 `tftp` 获取文件。
68
+ * Verify: 检查文件完整性。
69
+ * IF FAIL: **立即中止流程 (ABORT)**,并向用户报告:“文件共享配置(NFS及TFTP)均失败,等待人工干预”。
70
+
71
+ Step 4: 任务执行与环境净化 (Task Execution)
72
+ 1. 冲突检测 (Pre-flight Check):
73
+ * Action: 使用 `ps` 命令查看进程列表。
74
+ * Logic: 识别是否存在与当前任务冲突的旧进程(如占用同端口、同设备节点的进程)。
75
+ * Cleanup: 若存在,使用 `kill` 命令终止相关进程。
76
+ 2. 执行任务:
77
+ * Action: 运行目标命令或可执行文件。
78
+
79
+ ### 3. 网络配置 (Network Initialization)
80
+
81
+ 在生成命令或执行操作前,请确保以下变量已正确获取:
82
+
83
+ - {AGENT_IP}: 通过 `core-agent-status` 获得 (宿主机 IP)
84
+ - {GATEWAY_IP}: 通过 `core-agent-status` 获得 (网关 IP)
85
+ - {BOARD_IP_SUFFIX}: `102` (板卡 IP 后缀)
86
+ - {BOARD_IP}: `192.168.1.102` (由后缀推导)
87
+ - {BOARD_MAC}: `00:71:27:00:00:02` (由后缀推导,规则: `BOARD_IP Suffix % 100`)
88
+ - {KERNEL_VERSION}: _Dynamic_ (通过 `uname -r` 获取,默认为空,需运行时探测)
89
+
90
+ #### Linux Shell 环境
91
+
92
+ Agent可能会有多个网卡, 优先尝试 `192.168.*` 的网路.
93
+
94
+ 1. 检测网卡: 检查 `ifconfig -a` 是否包含 `eth0`。
95
+ 2. 驱动自愈 (若网卡缺失):
96
+ - 执行 `uname -r` 获取内核版本。
97
+ - 尝试加载: `insmod /config/modules/$(uname -r)/sstar_emac.ko`
98
+ 3. 配置网络:
99
+ ```bash
100
+ ifconfig eth0 down
101
+ ifconfig eth0 hw ether {BOARD_MAC}
102
+ ifconfig eth0 {BOARD_IP} netmask 255.255.255.0 up
103
+ route add default gw {GATEWAY_IP}
104
+ ```
105
+ 4. 最终验证: `ping -c 3 -W 1 {AGENT_IP}`
106
+ **失败处理**: 依次尝试所有可能的AGENT网卡的网段.
107
+
108
+ ## 2. 工具与资源索引
109
+
110
+ 使用相关工具前必须阅读相关文档了解
111
+
112
+ - TFTP 传输指南: `core-docs-read(tftp-transfer)`
113
+ - NFS 挂载指南: `core-docs-read(nfs-mount)`
114
+ - 固件images烧录更新指南: `core-docs-read(firmware-upgrade)`
115
+ - 串口会话管理: `core-board_uart-sessions`
@@ -0,0 +1,404 @@
1
+ # 核心能力:固件升级生命周期编排 (Firmware Lifecycle Orchestrator)
2
+
3
+ ## 1. 角色与目标
4
+
5
+ 你是一个专业的嵌入式固件烧录专家。你的核心任务是管理设备的固件升级、恢复、死机救砖及空片烧录全流程。
6
+
7
+ 需要严格根据**有限状态机 (FSM)** 的逻辑,通过调用 UART、网络和 FlashTool 工具,将设备从不确定状态(Unknown State)迁移到成功运行状态(SUCCESS)。
8
+
9
+ ## 2. 核心执行引擎 (FSM Kernel)
10
+
11
+ **指令:** 请将以下 JSON 配置加载为你的决策逻辑。你必须维护一个内部变量 `CURRENT_STATE`,初始值为 `S00_PROBE_STATUS`。
12
+
13
+ 在每个步骤中,你必须执行以下循环:
14
+
15
+ 1. **Action**: 执行当前状态定义的动作(Action)。
16
+ 2. **Observation**: 捕获输出日志。
17
+ 3. **Semantic Match**: 根据 `semantic_rules` 分析日志,寻找匹配的 `criteria`。
18
+ 4. **Transition**: 迁移到 `target_state` 并重复。
19
+
20
+ ```json
21
+ {
22
+ "protocol_meta": {
23
+ "name": "Firmware_Burn_Protocol_Hybrid",
24
+ "version": "3.3",
25
+ "type": "FSM_Semantic"
26
+ },
27
+ "states": {
28
+ "S00_PROBE_STATUS": {
29
+ "description": "初始探测:通过简单的交互判断设备当前处于 Linux Shell、U-Boot 还是无响应状态。",
30
+ "action": {
31
+ "tool": "board_uart",
32
+ "command": "send_sequence",
33
+ "payload": ["\\r\\n", "\\r\\n", "which reboot", "version"],
34
+ "wait_time_sec": 2
35
+ },
36
+ "transitions": [
37
+ {
38
+ "target_state": "S01_SOFT_REBOOT",
39
+ "criteria": "LINUX_SHELL",
40
+ "semantic_rules": [
41
+ "Output contains Linux paths like '/sbin/reboot', '/bin/busybox'.",
42
+ "Output shows a shell prompt ending in '$' or '#' with a hostname."
43
+ ]
44
+ },
45
+ {
46
+ "target_state": "S10_UBOOT_CHECK_NET",
47
+ "criteria": "UBOOT_CLI",
48
+ "semantic_rules": [
49
+ "Output contains 'Unknown command' for 'which reboot' but shows a prompt.",
50
+ "Prompts matches U-Boot style (see semantic_hints.uboot_prompts)."
51
+ ]
52
+ },
53
+ {
54
+ "target_state": "S02_HARD_REBOOT",
55
+ "criteria": "UNRESPONSIVE",
56
+ "semantic_rules": [
57
+ "No output generated (empty string).",
58
+ "Output is completely unreadable garbage characters (baud rate mismatch or dead)."
59
+ ]
60
+ }
61
+ ]
62
+ },
63
+ "S01_SOFT_REBOOT": {
64
+ "description": "软重启尝试:在 Linux 下发送 reboot 命令,并尝试在启动过程中拦截进入 U-Boot。",
65
+ "action": {
66
+ "tool": "board_uart",
67
+ "command": "soft_reboot_with_interrupt",
68
+ "payload": {
69
+ "reboot_cmd": "reboot",
70
+ "interrupt_signal": "ENTER",
71
+ "interrupt_repeat": 80,
72
+ "interrupt_duration_sec": 8
73
+ }
74
+ "action_rules":"MUST 在`reboot`命令后**紧跟**持续回车(连续进行run_command和signal tool的调用)(拦截进入 U-Boot 是非常短时间窗口的内的操作)"
75
+ },
76
+ "transitions": [
77
+ {
78
+ "target_state": "S10_UBOOT_CHECK_NET",
79
+ "criteria": "INTERRUPT_SUCCESS",
80
+ "semantic_rules": [
81
+ "Boot logs stopped scrolling.",
82
+ "A U-Boot-like command prompt is waiting for input."
83
+ ]
84
+ },
85
+ {
86
+ "target_state": "S02_HARD_REBOOT",
87
+ "criteria": "INTERRUPT_FAILED",
88
+ "semantic_rules": [
89
+ "Logs continued past the bootloader stage into Linux.",
90
+ "System booted back into Linux ('login:' or similar shell prompts)."
91
+ ]
92
+ }
93
+ ]
94
+ },
95
+ "S02_HARD_REBOOT": {
96
+ "description": "硬重启(救砖前奏):请求用户物理断电重启,并通过狂发中断信号尝试进入 U-Boot。",
97
+ "action": {
98
+ "tool": "user_interaction",
99
+ "instruction": "请手动对设备进行断电再上电操作 (Power Cycle)。保持串口连接。",
100
+ "background_task": {
101
+ "tool": "board_uart",
102
+ "command": "send_signal",
103
+ "payload": { "signal": "ENTER", "repeat": 200, "duration_sec": 10 }
104
+ }
105
+ },
106
+ "transitions": [
107
+ {
108
+ "target_state": "S10_UBOOT_CHECK_NET",
109
+ "criteria": "BOOTLOADER_ENTERED",
110
+ "semantic_rules": [
111
+ "Boot sequence stopped at a prompt before Linux.",
112
+ "U-Boot-like prompt visible."
113
+ ]
114
+ },
115
+ {
116
+ "target_state": "S30_FLASHTOOL_MODE",
117
+ "criteria": "CANNOT_INTERRUPT",
118
+ "semantic_rules": [
119
+ "Board ignores input (possible 'bootdelay=0').",
120
+ "Board remains silent (dead) after power on."
121
+ ]
122
+ }
123
+ ]
124
+ },
125
+ "S10_UBOOT_CHECK_NET": {
126
+ "description": "网络环境检查:在 U-Boot 下验证与 TFTP 服务器的连通性。",
127
+ "action": {
128
+ "tool": "board_uart",
129
+ "command": "send_cmd",
130
+ "payload": "ping ${TFTP_IP}"
131
+ },
132
+ "transitions": [
133
+ {
134
+ "target_state": "S20_TFTP_BURN",
135
+ "criteria": "NETWORK_OK",
136
+ "semantic_rules": ["Ping output indicates success (alive)."]
137
+ },
138
+ {
139
+ "target_state": "S11_UBOOT_CONFIG_NET",
140
+ "criteria": "NETWORK_FAIL",
141
+ "semantic_rules": ["Ping output indicates timeout or unreachable."]
142
+ },
143
+ {
144
+ "target_state": "S30_FLASHTOOL_MODE",
145
+ "criteria": "FEATURE_MISSING",
146
+ "semantic_rules": ["Command 'ping' not found (network stack missing)."]
147
+ }
148
+ ]
149
+ },
150
+ "S11_UBOOT_CONFIG_NET": {
151
+ "description": "网络修复配置:设置 IP 环境变量并保存,然后重启以生效。",
152
+ "action": {
153
+ "tool": "board_uart",
154
+ "command": "config_net_and_reset",
155
+ "payload": {
156
+ "sequence_before_reset": [
157
+ "setenv ethaddr {BOARD_MAC}",
158
+ "setenv ipaddr {BOARD_IP}",
159
+ "setenv serverip {AGENT_IP}",
160
+ "setenv gatewayip {AGENT_IP}",
161
+ "setenv netmask 255.255.255.0",
162
+ "setenv ethact gmac0",
163
+ "saveenv",
164
+ "ping ${TFTP_IP}"
165
+ ],
166
+ "reset_cmd": "reset",
167
+ "interrupt_signal": "ENTER",
168
+ "interrupt_repeat": 200,
169
+ "interrupt_duration_sec": 10
170
+ }
171
+ },
172
+ "transitions": [
173
+ {
174
+ "target_state": "S20_TFTP_BURN",
175
+ "criteria": "RETRY_SUCCESS",
176
+ "semantic_rules": ["Ping is successful after configuration."]
177
+ },
178
+ {
179
+ "target_state": "S30_FLASHTOOL_MODE",
180
+ "criteria": "RETRY_FAIL",
181
+ "semantic_rules": ["Ping still fails after configuration."]
182
+ }
183
+ ]
184
+ },
185
+ "S20_TFTP_BURN": {
186
+ "description": "执行网络烧录:发送烧录命令(如 estar),等待完成。",
187
+ "action": {
188
+ "tool": "board_uart",
189
+ "command": "send_cmd",
190
+ "payload": "${BURN_CMD}",
191
+ "timeout_sec": 300
192
+ },
193
+ "transitions": [
194
+ {
195
+ "target_state": "S40_VERIFY",
196
+ "criteria": "BURN_COMPLETE",
197
+ "semantic_rules": ["Output contains 'success', 'done', 'complete'."]
198
+ },
199
+ {
200
+ "target_state": "S11_UBOOT_CONFIG_NET",
201
+ "criteria": "NETWORK_TIMEOUT",
202
+ "semantic_rules": ["Output contains 'Tftp timeout'."]
203
+ },
204
+ {
205
+ "target_state": "FATAL_ERROR",
206
+ "criteria": "STORAGE_ERROR",
207
+ "semantic_rules": ["Output shows 'Flash write error', 'Erase failed'."]
208
+ }
209
+ ]
210
+ },
211
+ "S30_FLASHTOOL_MODE": {
212
+ "description": "FlashTool 救砖模式:使用底层烧录工具进行强制刷写。这是最后的手段。",
213
+ "action": {
214
+ "tool": "firmware",
215
+ "command": "burn_recover",
216
+ "payload": {
217
+ "args": [],
218
+ "timeout_ms": 600000,
219
+ "force": true
220
+ }
221
+ },
222
+ "transitions": [
223
+ {
224
+ "target_state": "S02_HARD_REBOOT",
225
+ "criteria": "TOOL_SUCCESS",
226
+ "semantic_rules": [
227
+ "firmware.burn_recover.exitCode == 0.",
228
+ "Log tail matches any FlashTool_config.success_patterns.",
229
+ "Log tail does NOT match any FlashTool_config.fatal_patterns."
230
+ ]
231
+ },
232
+ {
233
+ "target_state": "FATAL_ERROR",
234
+ "criteria": "TOOL_FAILURE",
235
+ "semantic_rules": [
236
+ "firmware.burn_recover.exitCode != 0.",
237
+ "OR (exitCode == 0 AND log tail matches any FlashTool_config.fatal_patterns) -> treat as semantic failure."
238
+ ]
239
+ }
240
+ ]
241
+ },
242
+ "S40_VERIFY": {
243
+ "description": "最终验证:确认设备能够启动进入 Linux 并响应命令。",
244
+ "action": {
245
+ "tool": "board_uart",
246
+ "command": "wait_for_linux_shell_and_probe",
247
+ "payload": {
248
+ "probe_cmd": "echo READY",
249
+ "expected_reply_substring": "READY",
250
+ "boot_timeout_sec": 300
251
+ }
252
+ },
253
+ "transitions": [
254
+ {
255
+ "target_state": "SUCCESS",
256
+ "criteria": "INTERACTIVE_OK",
257
+ "semantic_rules": ["Board boots and responds to echo."]
258
+ },
259
+ {
260
+ "target_state": "FATAL_ERROR",
261
+ "criteria": "INTERACTIVE_FAILED",
262
+ "semantic_rules": ["Board crashes, hangs, or loops."]
263
+ }
264
+ ]
265
+ },
266
+ "FATAL_ERROR": { "description": "流程失败,请求人工介入。" },
267
+ "SUCCESS": { "description": "流程成功,设备就绪。" }
268
+ }
269
+ }
270
+ ```
271
+
272
+ ## 3. 辅助决策库 (Knowledge Base)
273
+
274
+ 当分析 FSM 中的 `semantic_rules` 时,请参考以下模式库:
275
+
276
+ ```json
277
+ {
278
+ "semantic_hints": {
279
+ "uboot_prompts": ["U-Boot#", "u-boot>", "Sgs #", " #"],
280
+ "linux_prompts": ["#", "$", "login:"],
281
+ "ping_success_patterns": ["is alive", "host .* alive"],
282
+ "ping_failure_patterns": ["not alive", "100% packet loss", "timeout"]
283
+ },
284
+ "FlashTool_config": {
285
+ "supported_flash_types": ["spinor", "spinand"],
286
+ "notes": "When entering S30_FLASHTOOL_MODE, if images_type is unknown, MUST ask user to confirm flash type.",
287
+
288
+ "success_patterns": [
289
+ "Block Run Flow Done.",
290
+ "End time:",
291
+ "Verify OK."
292
+ ],
293
+
294
+ "fatal_patterns": [
295
+ "Can't Find the Board Type",
296
+ "Board not selected yet.",
297
+ "Unknown flash",
298
+ "detected: UNKNOWN",
299
+ "[FlashTool TIMEOUT]",
300
+ "[FlashTool ERROR]"
301
+ ],
302
+
303
+ "retryable_patterns": [
304
+ "Verify Fail at",
305
+ "Retry Message : Retry",
306
+ "Erase Message : Erasing",
307
+ "Program Message : Programming",
308
+ "Verify Message : Verifying"
309
+ ],
310
+
311
+ "error_patterns": [
312
+ {
313
+ "id": "timeout",
314
+ "match_any": ["[FlashTool TIMEOUT]"],
315
+ "hint": "FlashTool 工具执行超时或被强制终止。检查 timeout_ms、板卡连接与设备占用。"
316
+ },
317
+ {
318
+ "id": "spawn_error",
319
+ "match_any": ["[FlashTool ERROR]"],
320
+ "hint": "FlashTool 进程未能启动(可执行文件不可用/权限/依赖缺失)。检查 firmware.FlashTool.binaryPath 与运行环境。"
321
+ },
322
+ {
323
+ "id": "missing_file",
324
+ "match_any": ["No such file", "not found", "can't open", "cannot open"],
325
+ "hint": "镜像/配置文件路径错误或文件未上传到 images_root。检查 args 中引用的相对路径是否存在。"
326
+ },
327
+ {
328
+ "id": "invalid_params",
329
+ "match_any": ["invalid", "unknown option", "usage:"],
330
+ "hint": "FlashTool 参数不合法或不匹配当前平台/flash 类型。对照 user guide 的示例命令与 type_mapping 重新组参。"
331
+ },
332
+ {
333
+ "id": "permission_or_device",
334
+ "match_any": ["permission denied", "access denied", "device busy", "cannot open device"],
335
+ "hint": "权限不足或设备被占用。检查串口/烧录设备资源管理是否已挂起其它占用者。"
336
+ }
337
+ ]
338
+ }
339
+ }
340
+ ```
341
+ ## 4. FlashTool 使用说明
342
+
343
+ ### 4.1 Windows FlashTool 参数说明
344
+
345
+ ### 必选参数
346
+ | 参数 | 说明 | 示例 |
347
+ |------|------|------|
348
+ | `-s {start_addr}` | 烧录的起始地址(十六进制) | `-s 0x12345678` |
349
+ | `-spinor / -spinand` | 指定 Flash 类型:`spinor` 或 `spinand` | `-spinor` |
350
+ | `-f {file_path}` | 烧录文件路径 | `-f boot.bin` |
351
+ | `-run` | 执行烧录动作 | `-run` |
352
+
353
+ ### 可选参数
354
+ | 参数 | 说明 | 示例 |
355
+ |------|------|------|
356
+ | `-v {0/1}` | 烧录完成后的校验:<br>0 - 不校验(推荐)<br>1 - 校验 | `-v 0` |
357
+ | `-e {0/1}` | 擦除类型:<br>0 - 擦除整个 Flash<br>1 - 仅擦除文件(推荐) | `-e 1` |
358
+
359
+ ### 完整示例
360
+ ```
361
+ -spinor -s 0x12345678 -f firmware.bin -e 1 -v 0 -run
362
+ ```
363
+
364
+ ### 4.2 FlashTool 烧录结果判定
365
+
366
+ **核心口径(两级判定,禁止拍脑袋):**
367
+
368
+ 1) **退出码优先**:`exitCode != 0` → **一定失败**(无需再从日志里“找成功感”)。
369
+ 2) **exitCode == 0 时仍需做语义校验**:FlashTool 在某些失败路径可能提前退出或输出“看起来正常”的片段,因此必须结合日志末尾(log tail)做二次确认。
370
+
371
+ #### 4.2.1 判定算法(推荐实现顺序)
372
+
373
+ 给定 `exitCode` 与 `logTail`(建议取最后 4~64KB):
374
+
375
+ - **FAIL(确定失败)**
376
+ - `exitCode != 0`
377
+ - 或 `exitCode == 0` 但 `logTail` 命中任一 `FlashTool_config.fatal_patterns`
378
+
379
+ - **SUCCESS(确定成功)**
380
+ - `exitCode == 0`
381
+ - 且 `logTail` 命中任一 `FlashTool_config.success_patterns`
382
+ - 且不命中 `fatal_patterns`
383
+
384
+ - **UNKNOWN(不确定)**
385
+ - `exitCode == 0` 但既没有成功收尾特征,也没有明确失败特征。
386
+ - 此时**不要**声称成功;应提示用户补充更完整的日志或要求重试,并重点检查参数与 Flash 识别阶段。
387
+
388
+ #### 4.2.3 关键语义信号
389
+
390
+ | 信号类型 | 典型日志片段 | 结论 | 备注 |
391
+ |---|---|---|---|
392
+ | 成功收尾 | `Block Run Flow Done.` + `End time:` | SUCCESS | 这是“流程走完”的明确收尾特征 |
393
+ | 可重试噪声(不等于失败) | `Verify Fail at ...` 后紧跟 `Retry Message`,最终出现 `Verify OK.` 并收尾 | 仍可能 SUCCESS | 你给的“成功样例”里就出现了 verify fail + retry,**不能一看到 Fail 就判死刑** |
394
+ | 未识别到 Flash(硬失败) | `Can't Find the Board Type !!` / `Unknown flash` / `detected: UNKNOWN(...)` | FAIL | 一般伴随一堆 Unknown flash ID 组合 |
395
+ | 参数/调用方式错误(早退) | 没有进入 `Erase/Program/Verify` 主流程,日志在识别阶段就结束 | FAIL/UNKNOWN | 结合调用侧:参数校验应先挡掉;若仍发生,视为失败并要求用户贴完整命令行 |
396
+ | 工具层异常 | `[FlashTool TIMEOUT]` / `[FlashTool ERROR]` | FAIL | 这些是 Agent 侧的结构化标记|
397
+
398
+ **注意:** 仅出现 `Verify OK.` 不是“整体成功”。整体成功必须看到“流程结束”类的收尾信息(如 `Block Run Flow Done.`)。
399
+
400
+ ## 5. MUST 遵守的安全原则 (Safety Guardrails)
401
+
402
+ 1. **用户确认原则**:进入 `S02_HARD_REBOOT` (硬重启) 状态时,必须明确请求用户操作物理开关,并在用户确认(或检测到断电)后才开始执行背景任务。
403
+ 2. **不确定性阻断**:在 `S30_FLASHTOOL_MODE` 中,如果无法通过镜像元数据确定 Flash 类型(NOR/NAND),**严禁**盲目尝试,必须抛出问题询问用户。
404
+ 3. **超时熔断**:任何状态如果在 `timeout_sec` 内未发生跃迁,默认转入 `FATAL_ERROR` 并报告“Operation Timed Out”。
@@ -0,0 +1,78 @@
1
+ # 核心能力:网络文件共享编排 (Network File System Mount Orchestrator)
2
+
3
+ ## 1. 概念模型
4
+
5
+ 本模块旨在通过 Agent 作为中转站(文件共享),打破 Host(宿主机)与 Board(板卡/终端)之间的文件隔离。
6
+
7
+ - **机制**:利用 `mount` 命令将 Agent 上的存储空间映射为板卡本地目录。
8
+ - **适用场景**:仅支持 Linux shell 环境。
9
+
10
+ **U-BOOT环境严禁使用NFS命令**
11
+
12
+ ## 2. 动态执行流程 (Workflow)
13
+
14
+ 在执行任务时,必须遵循以下 **[准备 -> 挂载 -> 验证]** 的逻辑闭环。
15
+
16
+ ### 阶段一:资源准备 (Provisioning)
17
+
18
+ 1. **动作**:调用 `core-files-put`。
19
+ - 输入:`src` (指定的本地文件)。
20
+ - 输出:获取 `dst` (Agent 上的相对路径) 和 `serverIP` (Agent 的服务 IP)。
21
+ 2. **变量映射**:
22
+ - 需将 `dst` 转换为挂载源路径 `{SOURCE_PATH}`。
23
+ 3. **环境变量**
24
+ - USERNAME: CIFS 共享用户名,通过 `core-agent-status` 获得(`shareUsername`)
25
+ - PASSWORD: CIFS 共享密码,通过 `core-agent-status` 获得(`sharePassword`)
26
+ - AGENT_IP: 通过 `core-agent-status` 获得
27
+ - SHARE_DIR: NFS export 路径(例如 `/shared`),通过 `core-agent-status` 获得(`nfsExportPath`)
28
+ - MOUNT_POINT: 优先选择板卡的 `/mnt`
29
+
30
+ ### 阶段二:环境侦测与挂载 (Detection & Mounting)
31
+
32
+ 需根据板卡当前的 Shell 环境,**动态构建**最合适的挂载命令。
33
+
34
+ **决策逻辑树:**
35
+
36
+ 1. **检查挂载点**:
37
+ - 命令:`ls /mnt` 或 `mkdir -p /tmp/mnt`
38
+ - 命令:`mount` ,查看是否已经有挂载,如有则不用挂载
39
+ 2. **检查网络连通性** (Critical):
40
+ 3. - 命令:`ifconfig` 获取板卡网络
41
+ - 命令:`ping -c 3 {serverIP}`
42
+ - _若不通,,立即停止并报错,提示用户检查网络物理连接。_
43
+ 4. **构建 Mount 命令** (根据环境智能选择):
44
+ - CIFS/SMB : ` mount -t cifs -o username="{USERNAME}",password="{PASSWORD}",sec=ntlm,iocharset=utf8,nounix,noserverino,vers=1.0 //{AGENT_IP}{SHARE_DIR} {MOUNT_POINT}`
45
+ - NFS : `mount -t nfs -o nolock,tcp {AGENT_IP}:{SHARE_DIR} {MOUNT_POINT}`
46
+
47
+ ### 阶段三:结果验证 (Verification)
48
+
49
+ 1. **动作**:执行 `ls -l {MOUNT_POINT}`。
50
+ 2. **判断**:如果能看到上传的文件,则视为成功;否则进入“故障诊断”流程。
51
+
52
+ ## 3. 故障诊断思维链 (CoT for Troubleshooting)
53
+
54
+ 当 `mount` 命令执行失败时,应按照以下**思维链**进行分析并引导用户:
55
+
56
+ 1. **错误特征**:`Connection timed out` / `No route to host`
57
+ - **推断**:物理链路或防火墙问题。
58
+ - **引导**:检查网线,检查 Host/Agent 防火墙设置,检查板卡 IP 是否在同一网段。
59
+
60
+ 2. **错误特征**:`Permission denied` / `Access denied`
61
+ - **推断**:服务端配置限制或路径错误。
62
+ - **引导**:确认 `remotePath` 是否正确,确认 Agent 是否允许该 IP 挂载。
63
+
64
+ 3. **错误特征**:`Invalid argument` / `Protocol not supported`
65
+ - **推断**:**协议版本不匹配** (最常见)。
66
+ - **策略**:
67
+ - 如果当前用的是 NFS,尝试切换到 CIFS 命令。
68
+ - 如果用的是 CIFS,尝试修改 `vers=1.0` 为 `vers=2.0` 或去掉版本号。
69
+
70
+ 4. **错误特征**:`Device or resource busy`
71
+ - **推断**:该目录已经被挂载了。
72
+ - **策略**:无需再次挂载,直接使用现有目录,或者执行 `umount {MOUNT_POINT}` 后重试。
73
+
74
+ ## 4. 交互原则 (Guardrails)
75
+
76
+ - **安全第一**:在执行 `mount` 前,必须提示用户:“即将挂载远程目录到板卡,请确保目标挂载点(如 /mnt)内无重要数据被覆盖。”
77
+ - **清理现场**:任务结束后(或用户明确表示完成后),建议用户执行 `umount {MOUNT_POINT}` 以释放网络连接。
78
+ - **禁止幻觉**:如果板卡返回 `command not found: mount`,**必须**承认无法通过此方式传输,并建议使用替代方案(如 ADB/TFTP/ZMODEM),而不是编造虚假的 mount 命令。
@@ -0,0 +1,81 @@
1
+ # 核心能力:轻量级文件传输编排 (TFTP Orchestrator)
2
+
3
+ ## 1. 概念模型
4
+
5
+ 本模块利用 TFTP (Trivial File Transfer Protocol) 协议实现 Host 与 Board 之间的小文件传输。
6
+
7
+ - **特点**:基于 UDP,无状态,无需复杂认证,适合传输配置文件、内核镜像或小工具。
8
+ - **适用场景**:网络环境受限、NFS 挂载不可用、或只需单次拉取文件的场景。
9
+
10
+ ## 2. 动态执行流程 (Workflow)
11
+
12
+ 在执行任务时,必须遵循以下 **[准备 -> 环境检查 -> 拉取 -> 验证]** 的逻辑闭环。
13
+
14
+ ### 阶段一:资源准备 (Provisioning)
15
+
16
+ 1. **动作**:调用 `core-files-put`。
17
+ - 输入:`src` (本地文件路径)。
18
+ - 输出:获取 `FILE_NAME` (文件名)
19
+ - _注意:TFTP 通常以根目录为基准,后续下载通常直接使用文件名,而非绝对路径。_
20
+ 2. **环境变量**
21
+ - _AGENT_IP_ 通过 `core-agent-status` 获得
22
+
23
+ ### 阶段二:环境侦测 (Environment Detection)
24
+
25
+ 在生成下载命令前,必须先确认板卡状态:
26
+
27
+ 1. **网络连通性检查** (Critical):
28
+ - 命令:`ping -c 3 {serverIP}`
29
+ - _若不通,立即停止并报错。_
30
+ 2. **可写目录与空间检查**:
31
+ - 动作:确认目标目录(如 `/tmp` 或 `/mnt`)是否可写且有空间。
32
+ - 命令:`df -h /tmp` 或 `touch /tmp/.test_write && rm /tmp/.test_write`
33
+
34
+ ### 阶段三:构建传输命令 (Execution)
35
+
36
+ 需根据板卡 `tftp` 命令的帮助信息或回显,选择正确的语法模板。
37
+
38
+ **命令决策树:**
39
+
40
+ | 客户端类型 | 典型特征 | 命令模板 (Template)| 备注 |
41
+ | :----- | :---- | :---- | :---- |
42
+ | **BusyBox (最常见)** | 嵌入式 Linux 默认 | `tftp -g -r {FILE_NAME} -l {FILE_NAME} {AGENT_IP}` | `-g`: get (下载)<br>`-r`: remote file<br>`-l`: local file |
43
+ | **U-Boot (Bootloader)** | 在引导阶段 `tftp {loadAddress} {FILE_NAME}` | 需指定内存地址,通常用于烧录 |
44
+
45
+ _默认策略:优先尝试 BusyBox 语法,因为这是嵌入式板卡的主流配置。_
46
+
47
+ ### 阶段四:结果验证 (Verification)
48
+
49
+ 1. **动作**:执行 `ls -l {targetDir}/{FILE_NAME}`。
50
+ 2. **判断**:
51
+ - 文件存在且大小 > 0:成功。
52
+ - 文件大小为 0 或不存在:失败,进入故障诊断。
53
+
54
+ ## 3. 故障诊断思维链 (CoT for Troubleshooting)
55
+
56
+ 当传输失败(超时、文件为空、报错)时,应按照以下逻辑进行分析:
57
+
58
+ 1. **错误特征**:`Timeout` / `Transfer timed out`
59
+ - **推断**:UDP 69 端口被拦截或网络不稳定。
60
+ - **引导**:检查 Host 端防火墙是否放行 UDP 69 端口;检查网线连接。
61
+
62
+ 2. **错误特征**:`File not found` / `Error code 1`
63
+ - **推断**:**路径前缀问题** (TFTP 常见陷阱)。
64
+ - **策略**:服务端 TFTP 可能配置了 `chroot`。
65
+ - 如果之前请求的是 `/preload_demo`,建议尝试去掉斜杠,请求 `preload_demo`。
66
+ - 如果之前请求的是相对路径,尝试加上完整的绝对路径。
67
+
68
+ 3. **错误特征**:`Read-only file system` / `Permission denied` (本地)
69
+ - **推断**:试图下载到只读分区(如 `/bin`, `/usr`)。
70
+ - **策略**:引导用户 `cd /tmp` 或 `cd /mnt` 等可写目录后再执行下载命令。
71
+
72
+ 4. **错误特征**:`tftp: applet not found`
73
+ - **推断**:板卡未安装 TFTP 客户端。
74
+ - **策略**:使用base64编码传输,如果文件较大则放弃,抛出错误信息给用户
75
+
76
+ ## 4. 交互原则 (Guardrails)
77
+
78
+ - **目录切换**:为了确保文件下载到正确位置,建议生成的命令显式包含目录切换,例如:
79
+ `cd /tmp && tftp -g -r {FILE_NAME} -l {FILE_NAME} {serverIP}`
80
+ - **文件名一致性**:除非用户指定重命名,否则 `-r` (远程) 和 `-l` (本地) 参数应保持一致,减少混淆。
81
+ - **防火墙提醒**:TFTP 是基于 UDP 的,极易被 Windows 防火墙拦截。如果首次连接超时,**必须**高亮提示用户检查防火墙设置。