@seeed-studio/solution-cli 0.4.2 → 0.4.3
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/lib/agent.js +23 -2
- package/lib/installer.js +32 -1
- package/package.json +1 -1
- package/skills/solution-cli/SKILL.md +2 -2
- package/skills/solution-cli/references/device-management.md +42 -15
- package/skills/solution-cli/references/diagnose.md +1 -1
- package/skills/solution-cli/references/edge-gotchas.md +2 -2
- package/skills/solution-cli/references/error-catalog.md +2 -2
package/lib/agent.js
CHANGED
|
@@ -59,15 +59,36 @@ export function getKnownAgents() {
|
|
|
59
59
|
{
|
|
60
60
|
id: 'doubao',
|
|
61
61
|
name: '豆包工作 (Doubao Work)',
|
|
62
|
-
homeDirs: [
|
|
62
|
+
homeDirs: [
|
|
63
|
+
path.join(home, 'Doubao'),
|
|
64
|
+
path.join(home, '.doubao'),
|
|
65
|
+
path.join(home, '.agents'),
|
|
66
|
+
...(process.platform === 'darwin'
|
|
67
|
+
? [path.join(home, 'Library', 'Application Support', 'LarkShell')]
|
|
68
|
+
: [])
|
|
69
|
+
],
|
|
63
70
|
getSkillsDir: () => {
|
|
64
71
|
const pDoubao = path.join(home, 'Doubao', 'skills');
|
|
65
72
|
const pAgents = path.join(home, '.agents', 'skills');
|
|
66
73
|
const pLegacy = path.join(home, '.doubao', 'skills');
|
|
67
74
|
if (fs.existsSync(path.join(pDoubao, 'solution-cli', 'SKILL.md'))) return pDoubao;
|
|
68
75
|
if (fs.existsSync(path.join(pAgents, 'solution-cli', 'SKILL.md'))) return pAgents;
|
|
69
|
-
if (fs.existsSync(path.join(pLegacy, 'solution-cli', 'SKILL.md')))
|
|
76
|
+
if (fs.existsSync(path.join(pLegacy, 'solution-cli', 'SKILL.md'))) {
|
|
77
|
+
if (fs.existsSync(path.join(home, 'Doubao'))) return pDoubao;
|
|
78
|
+
return pLegacy;
|
|
79
|
+
}
|
|
70
80
|
if (fs.existsSync(path.join(home, 'Doubao'))) return pDoubao;
|
|
81
|
+
if (process.platform === 'darwin') {
|
|
82
|
+
const larkUsers = path.join(home, 'Library', 'Application Support', 'LarkShell', 'aha', 'users');
|
|
83
|
+
if (fs.existsSync(larkUsers)) {
|
|
84
|
+
try {
|
|
85
|
+
for (const u of fs.readdirSync(larkUsers)) {
|
|
86
|
+
const ws = path.join(larkUsers, u, 'doubao', '.doubao', 'agent_mode', 'workspace', '.user_skills');
|
|
87
|
+
if (fs.existsSync(ws)) return ws;
|
|
88
|
+
}
|
|
89
|
+
} catch (_) {}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
71
92
|
if (fs.existsSync(path.join(home, '.agents'))) return pAgents;
|
|
72
93
|
if (fs.existsSync(path.join(home, '.doubao'))) return pLegacy;
|
|
73
94
|
return pDoubao;
|
package/lib/installer.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import fs from 'node:fs';
|
|
3
|
+
import os from 'node:os';
|
|
3
4
|
import { fileURLToPath } from 'node:url';
|
|
4
5
|
import {
|
|
5
6
|
getPlatformInfo,
|
|
@@ -39,7 +40,10 @@ function assertCanonicalSkillState(ledger, agents) {
|
|
|
39
40
|
}
|
|
40
41
|
const record = ledger.installations?.[agent.id];
|
|
41
42
|
if (record && path.resolve(record.target_dir) !== expectedTarget) {
|
|
42
|
-
|
|
43
|
+
const isDoubaoMigration = agent.id === 'doubao' && path.resolve(record.target_dir).includes('.doubao');
|
|
44
|
+
if (!isDoubaoMigration) {
|
|
45
|
+
errors.push(`${agent.id} is managed at legacy target ${record.target_dir}; run uninstall --agent ${agent.id} before installing solution-cli`);
|
|
46
|
+
}
|
|
43
47
|
}
|
|
44
48
|
}
|
|
45
49
|
|
|
@@ -239,6 +243,33 @@ export async function runInstall(options = {}) {
|
|
|
239
243
|
|
|
240
244
|
// Record into ledger
|
|
241
245
|
recordInstallation(a.id, a.skillsDir, destDir, engineVersion, filesWritten);
|
|
246
|
+
|
|
247
|
+
// Clean up legacy target if migrating from old path (e.g. .doubao -> Doubao)
|
|
248
|
+
if (priorRecord && path.resolve(priorRecord.target_dir) !== destDir) {
|
|
249
|
+
try {
|
|
250
|
+
if (priorRecord.target_dir.includes('.doubao') && fs.existsSync(priorRecord.target_dir)) {
|
|
251
|
+
fs.rmSync(priorRecord.target_dir, { recursive: true, force: true });
|
|
252
|
+
}
|
|
253
|
+
} catch (_) {}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// For Doubao on macOS, additionally sync into active LarkShell agent workspace .user_skills if present
|
|
257
|
+
if (a.id === 'doubao' && process.platform === 'darwin') {
|
|
258
|
+
try {
|
|
259
|
+
const larkUsers = path.join(os.homedir(), 'Library', 'Application Support', 'LarkShell', 'aha', 'users');
|
|
260
|
+
if (fs.existsSync(larkUsers)) {
|
|
261
|
+
for (const u of fs.readdirSync(larkUsers)) {
|
|
262
|
+
const wsUserSkills = path.join(larkUsers, u, 'doubao', '.doubao', 'agent_mode', 'workspace', '.user_skills');
|
|
263
|
+
if (fs.existsSync(wsUserSkills)) {
|
|
264
|
+
const wsDest = path.join(wsUserSkills, SKILL_DIR_NAME);
|
|
265
|
+
fs.mkdirSync(wsDest, { recursive: true });
|
|
266
|
+
copyFolderSafely(destDir, wsDest, wsDest, {}, true, () => {});
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
} catch (_) {}
|
|
271
|
+
}
|
|
272
|
+
|
|
242
273
|
logger(` ✔ Skill successfully installed to: ${destDir}`);
|
|
243
274
|
installedAgents.push({ id: a.id, name: a.name, path: destDir });
|
|
244
275
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@seeed-studio/solution-cli",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.3",
|
|
4
4
|
"description": "Installer for the Rust deployment engine and Solution CLI Agent skills (Doubao Work, WorkBuddy, Claude Code, Codex, CodeBuddy, Hermes)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/installer.js",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: solution-cli
|
|
3
|
-
description:
|
|
3
|
+
description: 用于客户询盘、方案选型、产品硬件规格与SKU查询、包装清单(Box Contents)、电源适配器与必需配件(Power Adapter/Cables)、硬件兼容性校验、芯片与边缘硬件踩坑排错(RK3588/Jetson/reComputer/reServer/Watcher等)、边缘/IoT方案部署与自愈诊断。凡用户提及 solution-cli,或询问 Seeed 硬件产品(如 reComputer J4012/J4011/Super、reServer、Watcher、XIAO 等)的配件、电源、开箱即用状态、接口与方案选型,必须优先调用 solution-cli。
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Solution CLI
|
|
@@ -157,7 +157,7 @@ daemon is a host prerequisite, not evidence that a deployment has passed.
|
|
|
157
157
|
you checked, what you changed). Transient registry or network errors follow
|
|
158
158
|
the backoff rule in `references/deploy.md` §6 and do not use up a round.
|
|
159
159
|
4. **Preserving official cache & Local auto-patching**: Never edit files directly under the official content cache directory (`~/.sensecraft/content/`). When fixing a solution-level bug (timeout too short, wrong port/env var, minor syntax/transfer glitch, broken health check):
|
|
160
|
-
- In CLI / Engine mode: copy the solution from `~/.sensecraft/content/solutions/<id>` into `./.sensecraft-work/solutions/<id>`, apply the minimal fix in that copy. Then re-run deployment with `sensecraft-engine deploy <
|
|
160
|
+
- In CLI / Engine mode: copy the solution from `~/.sensecraft/content/solutions/<id>` into `./.sensecraft-work/solutions/<id>`, apply the minimal fix in that copy. Then re-run deployment with `sensecraft-engine deploy --params <params-file> --solutions-dir ./.sensecraft-work/solutions --yes --detach` (preserving the original preset, connection, and target parameters) so the engine picks up the patched files. Show the user the patch diff.
|
|
161
161
|
- If running with the Desktop App: use the app's edit copy mechanism (`references/app-only.md` §4).
|
|
162
162
|
5. **Reading output:** read the CLI's JSON output directly; it is small. If a
|
|
163
163
|
filter is needed, use `jq` only when it is already installed. Do not start
|
|
@@ -26,7 +26,7 @@ sensecraft-engine device scan
|
|
|
26
26
|
- **Class A 判定(MCU / Watcher)**:USB VID:PID 匹配 `303a:1001` (ESP32-S3) 或出现 USB-CDC 虚拟串口。*注:Watcher 目前无固定官方固件版本线,免除日常版本更新检测,仅在需要时进行全量固件刷写。*
|
|
27
27
|
- **Class B 判定(reCamera 与 reCamera Pro,重点核心)**:系统包含 `/userdata` 持久分区、轻量 Buildroot 系统、运行 `rkipc` 或 `sscma`,带有硬件 ISP/VPSS 节点。**这是分层更新与打补丁的核心对象!**
|
|
28
28
|
- **Class C 判定(reComputer 系列 / SBC)**:`uname -m` 为 aarch64,运行完整 Ubuntu/Debian,存在 Docker 守护进程与持久化大存储。
|
|
29
|
-
- **reComputer Jetson(J
|
|
29
|
+
- **reComputer Jetson(J 系列)**:读取 `/etc/nv_tegra_release` 识别实际 L4T/JetPack 版本(如 Orin 架构 J4012/J4011 搭载 JetPack 5.x/6.x,出厂预装 JP 6.x / L4T r36.x;Xavier 架构 J2012 搭载 JetPack 5.x / L4T r35.x,不支持 JP6)。底层系统稳定,不重装底层系统,按实际 JetPack 版本匹配容器与 CUDA 依赖;
|
|
30
30
|
- **reComputer RK 系列(RK3588/RK3576)**:底层为稳定的 Linux 6.1.x 定制系统,目前无频繁大版本迭代。
|
|
31
31
|
|
|
32
32
|
### 0.2 如何检测设备是否需要更新?
|
|
@@ -149,8 +149,8 @@ export HF_ENDPOINT=https://hf-mirror.com
|
|
|
149
149
|
### 2.2 应用容器镜像更新与切换 (Docker Compose)
|
|
150
150
|
当官方发布了新的应用镜像,或用户需要切换为特定测试镜像:
|
|
151
151
|
```bash
|
|
152
|
-
# 1.
|
|
153
|
-
cd
|
|
152
|
+
# 1. 进入方案实际运行目录(本地部署通常位于 ~/.sensecraft/deployments/<solution_id>/;远程 SBC 需根据方案定义进入对应远端工作目录,如 /home/<user>/<workdir>/)
|
|
153
|
+
cd <deploy_workdir>
|
|
154
154
|
|
|
155
155
|
# 2. 检查当前运行的镜像版本
|
|
156
156
|
docker compose images
|
|
@@ -181,23 +181,41 @@ reCamera 架构分为三层:**L1 固件与 OS 层**、**L2 中间件与流媒
|
|
|
181
181
|
ssh admin@<device_ip> "curl -s -X POST http://127.0.0.1:8080/api/model/reload -d '{\"model\": \"/userdata/models/my_model.cvimodel\"}'"
|
|
182
182
|
```
|
|
183
183
|
|
|
184
|
-
### 3.2 L2 中间件服务热替换与补丁测试
|
|
184
|
+
### 3.2 L2 中间件服务热替换与补丁测试
|
|
185
|
+
|
|
185
186
|
当官方发布了中间件二进制修复补丁,或用户需要替换自编译版本:
|
|
187
|
+
|
|
188
|
+
#### (A) reCamera Pro (RK3576):基于 ADB 传输与 /oem/usr/bin/rkipc
|
|
189
|
+
> ⚠️ **注意**:reCamera Pro 官方固件无 SSH root 权限,**标准通信通道为 ADB**。原厂二进制位于 `/oem/usr/bin/rkipc`。
|
|
186
190
|
```bash
|
|
187
191
|
# 1. 备份原厂二进制
|
|
188
|
-
|
|
192
|
+
adb shell "cp /oem/usr/bin/rkipc /userdata/rkipc.orig"
|
|
189
193
|
|
|
190
|
-
# 2.
|
|
191
|
-
|
|
192
|
-
|
|
194
|
+
# 2. 推送自编译二进制到 /userdata(持久可写分区)并赋予执行权限
|
|
195
|
+
adb push ./build/rkipc /userdata/rkipc.patch
|
|
196
|
+
adb shell "chmod +x /userdata/rkipc.patch"
|
|
193
197
|
|
|
194
198
|
# 3. 严格遵循安全停止与重启规范(防 VPSS 崩溃)
|
|
195
|
-
|
|
199
|
+
adb shell << 'EOF'
|
|
196
200
|
for p in $(pgrep -f rkipc); do kill -9 $p; done
|
|
197
201
|
sleep 3 # 关键:等待 3 秒彻底释放 VPSS / VI 硬件通道
|
|
198
202
|
/userdata/rkipc.patch -c /userdata/rkipc.ini &
|
|
199
203
|
EOF
|
|
200
204
|
```
|
|
205
|
+
|
|
206
|
+
#### (B) reCamera (SG2002):基于 SSH 传输与 /usr/bin/sscma
|
|
207
|
+
```bash
|
|
208
|
+
# 1. 备份原厂二进制
|
|
209
|
+
ssh admin@<device_ip> "cp /usr/bin/sscma /userdata/sscma.orig"
|
|
210
|
+
|
|
211
|
+
# 2. 部署自编译二进制到 /userdata 并赋予执行权限
|
|
212
|
+
scp ./build/sscma admin@<device_ip>:/userdata/sscma.patch
|
|
213
|
+
ssh admin@<device_ip> "chmod +x /userdata/sscma.patch"
|
|
214
|
+
|
|
215
|
+
# 3. 安全重启服务
|
|
216
|
+
ssh admin@<device_ip> "killall sscma; sleep 2; /userdata/sscma.patch &"
|
|
217
|
+
```
|
|
218
|
+
|
|
201
219
|
> [!CAUTION]
|
|
202
220
|
> **严禁在脚本中使用 `while true; do ...; sleep 1; done` 监控拉起进程**!若新二进制存在参数缺陷快速闪退,会造成整机 **Fork 暴风**,耗尽内核 PID,导致 SSH/HTTP/ADB 全瘫痪,只能拔电源。
|
|
203
221
|
|
|
@@ -210,10 +228,10 @@ EOF
|
|
|
210
228
|
## 4. Class A: MCU / 纯固件设备 (Watcher / ESP32) 更新
|
|
211
229
|
|
|
212
230
|
Watcher 等设备属于单片机架构,无操作系统与文件系统抽象:
|
|
213
|
-
1.
|
|
214
|
-
2. **烧录接入**:通过 USB
|
|
231
|
+
1. **固件编译与生成**:在本地完成完整固件二进制构建。注意:**写入 `0x0` 地址必须是包含 bootloader、partition table 和 app 的合体固件(merged-bin)**;如果是独立的 app-only 二进制,严禁刷写到 `0x0`(否则会破坏 bootloader 导致变砖),必须按照分区表偏移量(如默认 app 分区 `0x10000` 或设备配置中声明的 offset)进行刷写。
|
|
232
|
+
2. **烧录接入**:通过 USB 连接,利用烧录工具刷写(以已合并的全量固件为例):
|
|
215
233
|
```bash
|
|
216
|
-
esptool.py --chip esp32s3 -p /dev/ttyUSB0 -b 921600 write_flash 0x0
|
|
234
|
+
esptool.py --chip esp32s3 -p /dev/ttyUSB0 -b 921600 write_flash 0x0 watcher_firmware_merged_v1.2.0.bin
|
|
217
235
|
```
|
|
218
236
|
3. **固件重置**:遇到配置错乱时,先全量擦除再烧写:`esptool.py erase_flash`。
|
|
219
237
|
|
|
@@ -233,10 +251,18 @@ Watcher 等设备属于单片机架构,无操作系统与文件系统抽象:
|
|
|
233
251
|
|
|
234
252
|
当设备已经部署运行,用户希望修改 L1 参数(如更改 MQTT 目标服务器)时:
|
|
235
253
|
|
|
254
|
+
> ⚠️ **前置依赖**:在线配置热配端点依赖 SenseCraft 桌面客户端(FastAPI 后端提供),独立 `sensecraft-engine` 命令行暂不支持。请先核对桌面 App 运行状态与契约版本(需 `contract_version >= 6` 且 `python_backend` 非空,参见 `references/app-only.md` §1)。
|
|
255
|
+
|
|
236
256
|
### 步骤一:获取运行时信息与当前部署列表
|
|
237
257
|
```bash
|
|
238
|
-
|
|
239
|
-
|
|
258
|
+
RUNTIME=~/.sensecraft/runtime.json
|
|
259
|
+
[ -f "$RUNTIME" ] || { echo "未检测到运行时文件,请先启动 SenseCraft 桌面客户端"; exit 1; }
|
|
260
|
+
PYTHON_BACKEND=$(jq -r '.python_backend // empty' "$RUNTIME" 2>/dev/null)
|
|
261
|
+
[ -n "$PYTHON_BACKEND" ] || { echo "当前仅运行独立 Engine,热配端点需要 SenseCraft 桌面 App,请启动桌面客户端"; exit 1; }
|
|
262
|
+
CONTRACT_VER=$(jq -r '.contract_version // 0' "$RUNTIME" 2>/dev/null)
|
|
263
|
+
[ "$CONTRACT_VER" -ge 6 ] || { echo "当前桌面 App contract_version < 6,不支持在线配置修改,请升级 App"; exit 1; }
|
|
264
|
+
BASE_URL=$(jq -r '.base_url // "http://127.0.0.1:3260"' "$RUNTIME")
|
|
265
|
+
curl -sf "$BASE_URL/api/health" > /dev/null || { echo "SenseCraft App 服务未就绪"; exit 1; }
|
|
240
266
|
curl -s "$BASE_URL/api/device-management/active"
|
|
241
267
|
```
|
|
242
268
|
|
|
@@ -273,8 +299,9 @@ curl -s -X PUT "$BASE_URL/api/docker-devices/local/config/<solution_id>" \
|
|
|
273
299
|
在 `./.sensecraft-work/solutions/<solution_id>/` 下直接修改 `docker-compose.yml` 或 `devices/<id>.yaml`。
|
|
274
300
|
3. **通过本地补丁源重新注入热重载**:
|
|
275
301
|
```bash
|
|
276
|
-
sensecraft-engine deploy <
|
|
302
|
+
sensecraft-engine deploy --params <params-file> --solutions-dir ./.sensecraft-work/solutions --replace-existing --yes --detach
|
|
277
303
|
```
|
|
304
|
+
*(复用原部署请求 `--params` 文件以完整保留 preset、connection 及目标参数,并限制仅对目标设备重新部署)*
|
|
278
305
|
4. **回流官方**:验证无误后,遵循 `references/diagnose.md` §7 自动生成脱敏 GitHub Issue/PR 建议草稿。
|
|
279
306
|
|
|
280
307
|
---
|
|
@@ -81,7 +81,7 @@ three classes:
|
|
|
81
81
|
| Class | Example | What you do |
|
|
82
82
|
|---|---|---|
|
|
83
83
|
| **Device / environment** | port taken, disk full, Docker missing, network blocked, wrong password, serial permission | Propose the exact fix commands → user OK → run them → retry |
|
|
84
|
-
| **Solution configuration** | timeout too short, wrong port/env in compose, health check endpoint 404, minor syntax/transfer glitch | **CLI / Engine mode (Auto-healing patch)**: Copy the solution from `~/.sensecraft/content/solutions/<id>` to `./.sensecraft-work/solutions/<id>`, apply the minimal required fix, and redeploy with `sensecraft-engine deploy <
|
|
84
|
+
| **Solution configuration** | timeout too short, wrong port/env in compose, health check endpoint 404, minor syntax/transfer glitch | **CLI / Engine mode (Auto-healing patch)**: Copy the solution from `~/.sensecraft/content/solutions/<id>` to `./.sensecraft-work/solutions/<id>`, apply the minimal required fix, and redeploy with `sensecraft-engine deploy --params <params-file> --solutions-dir ./.sensecraft-work/solutions --yes --detach` (preserving parameters, restricted to failed devices) so the user succeeds immediately! Show the user the patch diff. Desktop app running: fix it in the edit copy (`app-only.md` §4) → validate → apply → retry. |
|
|
85
85
|
| **Engine bug** | exit code 5, a panic in `engine.log`, a step that fails the same way on any device, behaviour contradicting the solution's own config | Stop. Prepare the issue report below |
|
|
86
86
|
|
|
87
87
|
If the evidence does not fit any row, say so and show the user the first error
|
|
@@ -158,8 +158,8 @@
|
|
|
158
158
|
- **症状**:通过 `adb shell 'setsid rkipc &'` 后台拉起进程,断开 adb 终端后进程直接消失。
|
|
159
159
|
- **根因**:adbd 会在会话断开时主动收割(reap)该会话树下的所有孤儿/子进程。
|
|
160
160
|
- **修复**:
|
|
161
|
-
1.
|
|
162
|
-
2.
|
|
161
|
+
1. 将常驻服务交由系统的服务管理器托管(例如通过 `/etc/init.d/` 或 `/userdata/init.d/` 启动脚本注册),由 init/systemd/procd 统一管理生命周期,脱离交互式 adb 会话;
|
|
162
|
+
2. 若排障临时脱离终端,通过 `daemon` 或服务守护命令拉起,重定向所有标准输入输出并脱离控制终端,避免随 adbd 会话断开被 reap。
|
|
163
163
|
|
|
164
164
|
### 3.4 OSD Overlay Layer 图层优先级与色彩倒置
|
|
165
165
|
- **症状**:
|
|
@@ -23,11 +23,11 @@ environment, **Config** = solution configuration, **Engine** = engine / app bug.
|
|
|
23
23
|
| `permission denied while trying to connect to the Docker daemon socket` | Env | User not in `docker` group | Propose `sudo usermod -aG docker <user>` then re-login (user OK) |
|
|
24
24
|
| Image pull: `TLS handshake timeout`, `i/o timeout`, `toomanyrequests` | Env | Registry unreachable or rate-limited | Look for `Mirror context resolved` in the logs: absent → mirror detection failed; retry once, then report network status to the user |
|
|
25
25
|
| `manifest unknown` / `not found` for an image | Config | Image name or tag wrong, or not built for the device's CPU (arm64 vs amd64) | `docker manifest inspect <image>` (read-only): "no such manifest" → the tag does not exist, fix it; it exists but lists no platform matching the device's `uname -m` → wrong architecture, pick an image built for it |
|
|
26
|
-
| Container `Restarting` / `Exited (1)`; error in `docker logs` | Config (usually) | App inside the container misconfigured: env var, mounted path, port, timeout | Read `docker logs`; CLI mode: copy to `./.sensecraft-work/solutions/<id>`, fix compose / env / timeout, and redeploy with `--solutions-dir ./.sensecraft-work/solutions`; Desktop app: fix in edit copy (`app-only.md` §4) |
|
|
26
|
+
| Container `Restarting` / `Exited (1)`; error in `docker logs` | Config (usually) | App inside the container misconfigured: env var, mounted path, port, timeout | Read `docker logs`; CLI mode: copy to `./.sensecraft-work/solutions/<id>`, fix compose / env / timeout, and redeploy with `--params <params-file> --solutions-dir ./.sensecraft-work/solutions`; Desktop app: fix in edit copy (`app-only.md` §4) |
|
|
27
27
|
| Container `(healthy)` but the step reports health-check failure | Config | `health_check_endpoint` points at a URL that returns 401/404 | Fix the endpoint in the device YAML (`docker.services[].health_check_endpoint`) via local patch copy or app edit copy |
|
|
28
28
|
| Containers up, but the page / port does not answer from another machine | Env | Device firewall | Check `sudo iptables -L -n` / `ufw status`; propose opening the port (user OK) |
|
|
29
29
|
| USB device not detected (`No device found`, `detect` returns nothing) | Env | Cable is charge-only, wrong port, driver missing | Ask the user to replug with a data cable; on Windows check Device Manager for a COM port |
|
|
30
|
-
| YAML / validation error naming a solution file | Config | Broken solution file, syntax typo, or timeout too short | CLI mode: copy to `./.sensecraft-work/solutions/<id>`, fix typo/timeout, and redeploy with `--solutions-dir ./.sensecraft-work/solutions`; Desktop app: fix in edit copy (`app-only.md` §4) |
|
|
30
|
+
| YAML / validation error naming a solution file | Config | Broken solution file, syntax typo, or timeout too short | CLI mode: copy to `./.sensecraft-work/solutions/<id>`, fix typo/timeout, and redeploy with `--params <params-file> --solutions-dir ./.sensecraft-work/solutions`; Desktop app: fix in edit copy (`app-only.md` §4) |
|
|
31
31
|
| Python traceback mentioning `provisioning_station/` | Engine | App bug | Issue report (`diagnose.md` §6) |
|
|
32
32
|
| `sensecraft-engine` exits 5, or a panic in `~/.sensecraft/logs/engine.log` | Engine | Engine bug | Issue report (`diagnose.md` §6) |
|
|
33
33
|
| Same step fails identically on two different devices after the environment checks pass | Engine (likely) | App bug | Issue report (`diagnose.md` §6) |
|