@seeed-studio/solution-cli 0.3.1 → 0.4.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 (33) hide show
  1. package/README.md +157 -104
  2. package/bin/cli.js +410 -58
  3. package/bin/runner.js +1 -1
  4. package/catalog/client-config.json +2 -2
  5. package/catalog/knowledge-core.json +58452 -488
  6. package/docs/cli-guide.md +173 -200
  7. package/lib/agent.js +74 -15
  8. package/lib/catalog-dto.js +14 -1
  9. package/lib/detector.js +3 -3
  10. package/lib/doctor.js +19 -1
  11. package/lib/downloader.js +24 -0
  12. package/lib/gotchas.js +126 -0
  13. package/lib/installer.js +113 -19
  14. package/lib/integration.js +265 -0
  15. package/lib/knowledge.js +838 -100
  16. package/lib/ledger.js +1 -1
  17. package/package.json +3 -6
  18. package/skills/{sensecraft → solution-cli}/SKILL.md +125 -30
  19. package/skills/{sensecraft → solution-cli}/references/consult-and-select.md +61 -13
  20. package/skills/solution-cli/references/deploy.md +112 -0
  21. package/skills/solution-cli/references/device-management.md +298 -0
  22. package/skills/{sensecraft → solution-cli}/references/diagnose.md +15 -0
  23. package/skills/solution-cli/references/edge-gotchas.md +205 -0
  24. package/skills/solution-cli/references/generic-rk3588.md +106 -0
  25. package/skills/{sensecraft → solution-cli}/references/hardware-bom.md +9 -3
  26. package/skills/solution-cli/references/sales-feasibility.md +65 -0
  27. package/skills/{sensecraft → solution-cli}/references/secondary-development.md +10 -7
  28. package/skills/sensecraft/references/deploy.md +0 -300
  29. package/skills/sensecraft/references/device-management.md +0 -126
  30. /package/skills/{sensecraft → solution-cli}/references/app-only.md +0 -0
  31. /package/skills/{sensecraft → solution-cli}/references/error-catalog.md +0 -0
  32. /package/skills/{sensecraft → solution-cli}/references/offline.md +0 -0
  33. /package/skills/{sensecraft → solution-cli}/references/verify.md +0 -0
@@ -21,13 +21,15 @@ solution-cli product query <family_id> --json
21
21
  ```
22
22
  - 获取产品族名称、官方默认主 SKU、物理电气规格(电压、电流接口、M.2 槽位等)以及内置的 UTM 商城购买直达链接。
23
23
 
24
- ### 动作二:查询经过验证的配件清单
24
+ ### 动作二:查询经过验证的配件清单与批量加购链接
25
25
  ```bash
26
- solution-cli product accessories <family_id> --json
26
+ solution-cli product accessories <family_id> --compact --json
27
27
  ```
28
28
  - 输出严格由确定性代码计算物理兼容性的配件清单:
29
+ - `bundle_cart_url`:已自动将主机与必需配件打包的 Seeed 官方商城合并加购直达链接;
29
30
  - `REQUIRED` 列表:带必买技术原因(`reason`)、购买 SKU 与静默带 UTM 的直达链接;
30
- - `OPTIONAL` 列表:带周边传感器、通信模块、固态硬盘与购买链接。
31
+ - `OPTIONAL` 列表:带周边传感器、通信模块、固态硬盘与购买链接;
32
+ - **建议务必加 `--compact`**:去除底层冗余兼容性树,Token 消耗降低 70%。
31
33
 
32
34
  ### 动作三:验证物理配件兼容性
33
35
  当用户提到已有某个第三方配件或自制电源/天线时:
@@ -78,6 +80,10 @@ Agent 严禁凭“常识”告知配件通用,必须遵循 CLI 评估结果并
78
80
  - **M.2 NVMe SSD 256GB** (SKU: `112990246`):用于拉取 Docker 镜像与长期本地数据持久化。
79
81
  - **reSpeaker 4 麦克风阵列** (SKU: `107990193`):若需补充语音呼叫或声音事件感知。
80
82
 
83
+ #### 4. 🛒 一键批量合并采购 (Bundle Cart)
84
+ - **官方商城直达**:`[点击此处将主机与必需配件一键加购结算](${bundle_cart_url})`
85
+ *(调用 `solution-cli product accessories <family> --json` 时直接提取 `bundle_cart_url` 输出给用户,点击即可一次性将主机及必需配件加入购物车,大幅缩短采购转化链路。国内用户提示通过天猫/淘宝 Seeed 官方店或代理商采购。)*
86
+
81
87
  ---
82
88
  > 📦 硬件采购并收到后,只要通电并插上网线,随时对我说“设备已连接,开始部署”,我将直接为您全自动化完成环境配置与方案运行!
83
89
  ```
@@ -0,0 +1,65 @@
1
+ # 销售方案可行性评估与需求匹配度指南 (Sales Feasibility & Matching Guide)
2
+
3
+ > **定位**:供 AI Agent 在面对 **销售端询问团队技术能力边界(FEASIBILITY)**、**非标定制评估** 以及 **商机匹配度衡量(MATCHING_SCORE)** 时查阅。回答“我们能不能做”、“做这个需要多少周期”、“如何评估需求匹配度”。
4
+
5
+ ---
6
+
7
+ ## 1. 销售需求四级评估阶梯 (The 4-Tier Feasibility Matrix)
8
+
9
+ 当销售或商务询问“某某客户的需求我们能不能接/能不能做”时,严禁盲目回答“可以做”,必须按以下四级阶梯对齐技术成熟度:
10
+
11
+ | 阶梯等级 | 判定特征与技术依据 | 推荐答复话术与研发周期 |
12
+ |---|---|---|
13
+ | **Tier 1: 开箱即用 (Turnkey)** | 官方方案库已有现成参考设计(`reference_design`),已有预编译 Docker 镜像与验证硬件(Orin/树莓派/瑞芯微)。 | **“完全支持,开箱即用”**。<br>周期:0 天(到货即部署)。直接提供官方方案落地页、BOM 清单与一键加购链接。 |
14
+ | **Tier 2: 模型/协议适配 (Adaptation)** | 硬件算力与物理接口完全满足(如 Orin NX + 工业相机 + RS485),但需要更换目标检测模型(如把人脸换为特定零件缺陷),或需接入私有 Modbus 协议。 | **“技术可行,需轻量适配”**。<br>周期:1~2 周。支持通过开放的 Docker/Compose 与 ONNX/TensorRT 工具链接入,可由客户研发或我方技术支持协助跑通。 |
15
+ | **Tier 3: 硬件拓展/研发立项 (Custom Engineering)** | 涉及非标工况(如户外防爆、-40℃ 超宽温、太阳能休眠超低功耗微安级),或需自研特殊算子与驱动(如高频毫米波雷达定制算法)。 | **“需研发评估与项目立项”**。<br>周期:4~8 周以上。需销售组织现场工况评审会,评估硬件选型打样成本与预期出货量。 |
16
+ | **Tier 4: 物理超限 (Physically Infeasible)** | 违反物理规律或边缘算力严重倒挂(如要求 ESP32 跑 4K 30FPS 大模型全功能分割、无红外打光在全黑环境要求百米人脸抓拍)。 | **“物理上不可行,需调整方案设计”**。<br>明确解释物理原因(如算力/光学极限),并提供升阶改造建议(如增加外部补光或升级为 Jetson 工控机)。 |
17
+
18
+ ---
19
+
20
+ ## 2. 需求匹配度四维量化打分法 (Matching Score: 0~100%)
21
+
22
+ 当面对多个商业需求时,利用以下 4 项确定性工程维度进行加权评分,输出结构化匹配卡:
23
+
24
+ $$Score = \text{算法成熟度}(35\%) + \text{硬件适配性}(30\%) + \text{现场工况条件}(20\%) + \text{交付闭环复杂度}(15\%)$$
25
+
26
+ ```markdown
27
+ ### 🎯 方案匹配度评估:85% (高匹配 · 推荐推进)
28
+
29
+ - [x] **算法就绪度 (95%)**:官方已有成熟参考设计,已预置推理管线。
30
+ - [x] **硬件适配性 (90%)**:推荐 reComputer J4012 (Orin NX),算力满足并发路数。
31
+ - [!] **现场工况条件 (70%)**:现场需工业防尘,建议选配 IP66 防护机箱与工业级电源。
32
+ - [x] **交付周期 (90%)**:纯容器化部署,到货即可完成自动化交付。
33
+
34
+ 💡 **商务建议**:属于成熟方案,交付风险低,建议销售直接输出 BOM 报价并跟进采购。
35
+ ```
36
+
37
+ ---
38
+
39
+ ## 3. 双轨业务策略控制 (Business Policy Switching)
40
+
41
+ 根据团队当前交付负荷与销售阶段,Agent 可根据提示词自动切换或由用户指定策略:
42
+
43
+ ### 策略 A:`strict`(严格挑活 · 聚焦标准化规模交付)
44
+ - **触发条件**:交付团队高负荷、大促期、或明确要求“只要现成标准方案”。
45
+ - **规则**:
46
+ - **匹配度 $\ge 80\%$**:积极推进,提供 BOM 与自动化部署指南;
47
+ - **匹配度 $< 80\%$**:礼貌婉拒非标,守住研发成本底线:
48
+ > *“根据现场工况,目前官方方案库尚无开箱即用的标准套件。为确保您的交付稳定性与工程成本,建议优先考虑标准化场景,或参考 Seeed 开源硬件底座自行评估二次开发。”*
49
+
50
+ ### 策略 B:`flexible`(积极适配 · 扩大商机与生态定制)
51
+ - **触发条件**:业务开拓期、新市场线索挖掘、战略大客户定制。
52
+ - **规则**:
53
+ - **匹配度 $\ge 50\%$**:积极拆解定制路径:
54
+ > *“目前虽然没有 100% 对应的现成整机套件,但底层硬件平台(如 reComputer Jetson / SenseCAP)具备完全兼容的算力与工业接口,只需 1~2 周进行模型微调或协议适配即可跑通,我们可提供完整的二次开发技术 Wiki 与 GitHub 仓库。”*
55
+
56
+ ---
57
+
58
+ ## 4. 销售常用算力与并发速查卡 (Hardware Capability Benchmarks)
59
+
60
+ | 主机平台 | AI 算力 (INT8) | 视频分析路数上限 (1080P 15FPS) | 典型适用场景 | 工业接口支持 |
61
+ |---|---|---|---|---|
62
+ | **reComputer J3011 (Orin Nano 8GB)** | 40 TOPS | 2 ~ 4 路 | 跌倒检测、客流统计、离线语音助手 | USB 3.2, GbE, M.2 Key-M, M.2 Key-E |
63
+ | **reComputer J4012 (Orin NX 16GB)** | 100 TOPS | 6 ~ 8 路 | 多路车牌识别、流水线表面缺陷质检、多模态视觉 | USB 3.2, GbE, CAN 总线扩展, M.2 Key-M |
64
+ | **reComputer RK3576 / RK3588** | 6 TOPS NPU | 1 ~ 3 路 | 高性价比人脸抓拍、低功耗边缘网关 | 双千兆网口, 隔离 RS485, 工业宽温 |
65
+ | **reCamera (SG2002)** | 1 TOPS | 单路自摄抓拍 | 独立点位人员统计、门禁人脸识别、轻量姿态 | PoE 供电, 板载相机, 免拉长线 |
@@ -13,14 +13,14 @@ Seeed SenseCraft 方案体系在 GitHub 上采用清晰的双层开源结构:
13
13
  graph LR
14
14
  subgraph Repo1["1. 方案编排层 (Solution Package)"]
15
15
  direction TB
16
- R1_URL["github.com/Seeed-Studio/sensecraft-solutions"]
16
+ R1_URL["CLI 返回的方案编排仓库"]
17
17
  R1_Content["包含 solution.yaml, devices/*.yaml, docker-compose.yml, 启动脚本"]
18
18
  R1_Fit["适合:改端口、加环境变量、调整数据卷、增减联动微服务"]
19
19
  end
20
20
 
21
21
  subgraph Repo2["2. 核心算法与业务源码层 (Core App/Algorithm)"]
22
22
  direction TB
23
- R2_URL["各场景独立开源代码仓 (ModelAssistant / warehouse_system 等)"]
23
+ R2_URL["CLI 返回的场景源码仓库"]
24
24
  R2_Content["包含 Python 推理主循环、Vue/React 前端看板、模型权重、后处理时序"]
25
25
  R2_Fit["适合:重训模型、改检测类别与阈值、重构业务 UI、对接私有云数据库"]
26
26
  end
@@ -34,17 +34,20 @@ graph LR
34
34
  使用 CLI 查询方案元数据:
35
35
  ```bash
36
36
  solution-cli hub search "<方案名称或关键词>" --json
37
+ solution-cli hub get <reference-design-id> --section links --json
37
38
  ```
38
- - 输出中的 `repo_url` 提供了官方代码仓地址(例如 `https://github.com/Seeed-Studio/sensecraft-solutions/tree/main/solutions/fall_detection` 或核心项目地址)。
39
+ - 只使用 `hub get --section links` 返回并标明角色为 repository/source 的
40
+ URL。不要根据 RD ID、落地页路径或 Wiki 路径自行拼接 GitHub、Wiki 或
41
+ CDN 地址;没有声明仓库时明确说明源码地址未提供。
39
42
 
40
43
  ### 步骤二:克隆方案到本地工程目录
41
44
  指导用户或在本地工作空间执行克隆:
42
45
  ```bash
43
- # 方案编排包开发
44
- git clone https://github.com/Seeed-Studio/sensecraft-solutions.git ./my-solutions
46
+ # 方案编排包开发;将 CLI 返回的 repository/source URL 填入
47
+ git clone <declared-repo-url> ./my-solutions
45
48
 
46
49
  # 或核心算法项目开发(以视觉推理为例)
47
- git clone https://github.com/Seeed-Studio/ModelAssistant.git ./my-model-assistant
50
+ git clone <declared-repo-url> ./my-model-assistant
48
51
  ```
49
52
 
50
53
  ---
@@ -81,4 +84,4 @@ sensecraft-engine deploy <id> --solutions-dir ./my-solutions/solutions
81
84
 
82
85
  1. **主动提供溯源**:当用户明确表达“想要改底层逻辑”、“换自研模型”时,主动告诉用户代码所在,并给出克隆建议。
83
86
  2. **语气自然诚恳**:
84
- - 示例:“*这套方案的源码完全开源在 [GitHub 仓库](https://github.com/suharvest/sensecraft-solutions/tree/main/solutions/<id>)。您可以克隆到本地,告诉我您具体想改哪部分(比如替换成自研的 Pose 模型或改告警通知格式),我可以直接帮您修改代码并用引擎本地联调。*”
87
+ - 示例:“*先执行 `solution-cli hub get <rd-id> --section links --json`,我会使用返回的已声明源码链接。确认仓库地址后,再克隆到本地并按方案文档联调。*”
@@ -1,300 +0,0 @@
1
- # Deploy a solution
2
-
3
- Run Step 0 in `SKILL.md` first (engine installed, solutions pulled). Examples
4
- use `--lang en`; use `--lang zh` for a Chinese-speaking user.
5
-
6
- ## 1. Find the solution
7
-
8
- ```
9
- sensecraft-engine solution list --json
10
- ```
11
-
12
- Match the user's wording against `name` / `summary`. Confirm the `id` with the
13
- user if more than one fits. `sensecraft-engine solution show <id> --lang en`
14
- prints the full solution if you need more detail.
15
-
16
- ## 2. Read what the deployment needs
17
-
18
- ```
19
- sensecraft-engine deploy-info <id> --lang en
20
- ```
21
-
22
- - `presets[]` — deployment variants. If there is more than one, ask the user which
23
- one, then run again with `--preset <preset>`. Without `--preset` the template
24
- lists the steps of every preset.
25
- - `steps[]` — each step's `device_id`, `type`, `required`, `connection_type`
26
- (`ssh` / `serial` / `none` / ...), `parameters`, `category` (`deploy` or
27
- `verify`) and `interactive`. Steps with `has_targets: true` (e.g.
28
- `docker_deploy`) list `targets`: `local` = this computer's Docker, `remote` =
29
- a device over SSH.
30
- - Verify steps that need the user carry a ready command list:
31
- `counting_cli`, `face_cli`, `wizard_cli` or `robot_cli` (see `verify.md`).
32
- - `request_template` — a ready request body. Values shaped like
33
- `<REQUIRED: ...>` must be filled in; everything else has a working default.
34
-
35
- Never make up step or device IDs: the keys of `device_connections` and the
36
- entries of `selected_devices` are exactly the ones in `request_template`.
37
-
38
- Optional discovery, to pre-fill values:
39
-
40
- ```
41
- sensecraft-engine device ports # serial ports (USB devices)
42
- sensecraft-engine device scan --timeout 5 # SSH devices on the LAN (mDNS, IPv4)
43
- sensecraft-engine device list # device catalog
44
- sensecraft-engine doctor --json # this computer: serial permission, Docker, disk, network
45
- ```
46
-
47
- ## 3. Fill in and confirm
48
-
49
- Ask the user for every `<REQUIRED: ...>` value (device IP, username, password,
50
- serial port, and any user inputs). Serial steps carry both `port` and
51
- `serial_port` placeholders; fill both with the port name from `device ports`.
52
-
53
- For `docker_deploy` steps pick the target with `"target": "<target id>"` **and
54
- set `"target_type"` to that target's own type** (`local` / `remote`) — or
55
- remove `target_type`. Leaving the template's type while switching `target` is
56
- rejected. Each deploy-info target carries `type` (`local` / `remote`) and,
57
- when the target is tied to a board, `device` / `device_name` /
58
- `device_class` (for example `rk3576`, `RK3576`): pick the target whose
59
- `type` and device match the user's hardware, and copy its `type` into
60
- `target_type`. `device` is null for targets that run on any Docker host. On
61
- engine builds whose targets have no `type` yet, the target id suffix (for
62
- example `_local`, `_remote`) is only a hint; confirm the type with `validate`
63
- (§3, dry run) before starting. Remote targets need `host`, `username`
64
- and either `password` or `key_file`:
65
-
66
- Windows native `local` Docker is unsupported by both deployers and returns the
67
- platform check failure; use a `remote` target over SSH to a Linux Docker host.
68
- WSL must use the Linux engine binary and is Linux-host evidence, not Windows
69
- native local Docker support. On macOS, the local target uses the literal
70
- `docker` executable visible to the new engine process. If Docker Desktop's CLI
71
- is only in its application bundle, provide that bundle's `bin` directory in a
72
- temporary engine-process `PATH`; do not alter global shell configuration or
73
- assume an already-running instance inherits the path. Docker Desktop being
74
- running is a prerequisite check, not a deployment result.
75
-
76
- - Password: `"password": "<the user's password>"`.
77
- - SSH key: `"key_file": "~/.ssh/id_ed25519"` and no `password` field. The key
78
- must be a regular file inside `~/.ssh` (or the engine's data directory); a
79
- relative path is resolved under `~/.ssh`; other locations are refused.
80
-
81
- Add `"auto_replace_containers": true` (or the `--replace-existing` flag) only if
82
- the user agrees to replace existing containers with the same name.
83
-
84
- Write the filled body to `./.sensecraft-work/body.json` in the current working
85
- directory, not `/tmp` (a file keeps the password out of the process list and
86
- avoids shell quoting problems, notably in PowerShell):
87
-
88
- ```json
89
- {
90
- "solution_id": "<id>",
91
- "preset_id": "<preset>",
92
- "selected_devices": ["<step_id>"],
93
- "device_connections": {
94
- "<step_id>": {"target": "<target_id>", "target_type": "remote",
95
- "host": "192.168.1.50", "username": "<user>",
96
- "password": "<password>"}
97
- }
98
- }
99
- ```
100
-
101
- Show the user the body with the password as `<REDACTED>` before starting.
102
-
103
- On Windows PowerShell 5.1, write the JSON as UTF-8 **without a BOM**. The
104
- default `Set-Content -Encoding UTF8` adds a BOM, which the Rust request reader
105
- rejects. Keep the request file under the current workspace and do not print it
106
- when it contains a password:
107
-
108
- ```powershell
109
- $RequestPath = [System.IO.Path]::GetFullPath('.sensecraft-work/body.json')
110
- $RequestDir = [System.IO.Path]::GetDirectoryName($RequestPath)
111
- New-Item -ItemType Directory -Force -Path $RequestDir | Out-Null
112
- $body = @{
113
- solution_id = '<id>'
114
- preset_id = '<preset>'
115
- selected_devices = @('<step_id>')
116
- device_connections = @{
117
- '<step_id>' = @{
118
- target = '<target_id>'
119
- target_type = 'remote'
120
- host = '192.168.1.50'
121
- username = '<user>'
122
- password = '<password>'
123
- }
124
- }
125
- }
126
- $json = $body | ConvertTo-Json -Depth 50
127
- [System.IO.File]::WriteAllText($RequestPath, $json, [System.Text.UTF8Encoding]::new($false))
128
- ```
129
-
130
- `-Depth 50` preserves nested `device_connections`; PowerShell's default depth
131
- of 2 is insufficient. Replace placeholders with user-provided values and keep
132
- the file protected; never print the password.
133
-
134
- Before a remote deploy, run the dry run (no changes on any device):
135
-
136
- ```
137
- sensecraft-engine validate --params ./.sensecraft-work/body.json
138
- ```
139
-
140
- It reports parameter errors and previews which verify steps will need the user
141
- (`verify_required`). It also lists the changes the deployment may make on each
142
- target beyond the solution's own files and containers, as
143
- `side_effects: {"<step_id>": [{"kind", "what", "when", "decided_in"}, ...]}`:
144
-
145
- | `kind` | Change on the target |
146
- |---|---|
147
- | `sudo` | Commands run with `sudo` (Docker through `sudo docker`, actions marked `sudo`) |
148
- | `daemon_json_write` | Merges `registry-mirrors` into `/etc/docker/daemon.json` (other keys kept) |
149
- | `docker_daemon_restart` | Restarts the Docker daemon (all containers on the device restart with it) |
150
- | `package_install` | Installs packages (Docker / Compose, `.deb`, apt / pip in an action) |
151
- | `system_config` | Changes system settings (`usermod`, `update-alternatives`, services) |
152
- | `reboot` | Reboots the device |
153
- | `firmware_flash` | Flashes firmware |
154
- | `local_script` | Runs a script on this computer |
155
-
156
- `what` says what happens in plain words, `when` the condition: `always`, a
157
- condition the engine checks during the deploy (for example "the device cannot
158
- reach Docker Hub"), or "the action's script decides". `decided_in` points at
159
- engine code; it is for bug reports, not something to read.
160
-
161
- Tell the user what the list contains. If the user forbade a kind that is
162
- listed (Docker restart, daemon.json changes, reboot, package installs) and
163
- has not agreed to it, stop and ask before starting, also when `when` is a
164
- condition: the deploy may meet it. Exception: when the action's script is in
165
- the solution's step file (`devices/<x>.yaml` under `actions` or
166
- `remote_overrides.actions` in `~/.sensecraft/content/solutions/<id>/`, or
167
- `$SC_HOME/content/solutions/<id>/` when `SC_HOME` is set), read
168
- it; if its condition can be checked read-only on the device and is not met,
169
- say so and continue. Actions that come from the engine's built-in device
170
- profile are not in that file: treat them as possible. Builds without a
171
- `side_effects` field: assume a remote Docker deploy may write
172
- `/etc/docker/daemon.json` and ask when the user restricted that.
173
-
174
- Before the deploy, save the target's current Docker daemon config so changes
175
- can be shown and restored:
176
-
177
- ```
178
- ssh <user>@<ip> cat /etc/docker/daemon.json > ./.sensecraft-work/daemon.json.before
179
- ```
180
-
181
- (a missing file is fine: note that it did not exist). After the deploy, `cat`
182
- it again and show the user any difference; restoring it is a change on the
183
- device and needs the user's OK.
184
-
185
- ## 4. Start and follow
186
-
187
- ```
188
- sensecraft-engine deploy --params ./.sensecraft-work/body.json --yes --detach --lang en
189
- ```
190
-
191
- `--detach` prints `{"deployment_id": "...", "log": "..."}` and returns. Keep the
192
- `deployment_id`. Exit code 2 means the request or arguments are invalid. When
193
- the JSON error contains a `missing[]` list, ask for those fields
194
- (`preset_id`, `device_connections.<id>.<key>`); for `bad_request` without
195
- `missing[]`, inspect the solution ID, JSON shape, and parameter spelling before
196
- asking for another value.
197
- Exit code 3 with a 409 means the device is busy with another deployment.
198
-
199
- Follow progress in one of two ways:
200
-
201
- - **Poll** (works with any agent's command timeout): every 3–5 seconds run
202
- `sensecraft-engine status <deployment_id> --json`. `status` is `running`
203
- while in progress and ends as `completed`, `failed`, `cancelled` or
204
- `interrupted`; each device and step has its own `status` and `message`.
205
- Exit code: 0 while running or completed, 1 for failed / cancelled /
206
- interrupted.
207
- - **Event stream:** `sensecraft-engine logs <deployment_id> --since <N>`
208
- prints NDJSON events (`{seq, type, ...}`) with `seq > N` and exits; add
209
- `--follow` to keep streaming until the deployment ends (run it in the
210
- background if your command timeout is short). Remember the last `seq` and
211
- pass it as `--since` next time, so you never read the same events twice.
212
-
213
- Event types to act on:
214
-
215
- | `type` | Meaning |
216
- |---|---|
217
- | `log` | `level`, `message`; `error`-level lines are evidence for `diagnose.md` |
218
- | `step_skipped` with `reason: verify_required` | The step needs the user — the `verify_required` event before it has the details |
219
- | `verify_required` | Go to `verify.md` with this event |
220
- | `device_completed` | One device finished |
221
- | `deployment_completed` | Last event; `status` is the final result |
222
-
223
- Read the JSON directly instead of grepping it (no interpreter, see `SKILL.md`
224
- rule 5). Delete `./.sensecraft-work/` afterwards (`body.json` holds a
225
- password).
226
-
227
- Without `--detach`, `deploy --json` streams the same events on stdout and ends
228
- with one `{"type": "result", "deployment_id", "status", "devices"}` line; the
229
- exit code is the deployment's result. Ctrl-C or a killed agent command only
230
- detaches: the deployment keeps running in the engine instance; continue with
231
- `status` / `logs`.
232
-
233
- If `--detach` prints `"backend": "python"`, the desktop app's backend is
234
- running this deployment: `logs` then has `log` and `deployment_completed`
235
- events only, no `verify_required`. Do the guide's verify steps with the user
236
- as described in `verify.md` §1.
237
-
238
- ## 5. Verify
239
-
240
- `completed` is not enough. Check the result is actually usable:
241
-
242
- - `verify_required` events: handle each one with `verify.md`.
243
- - Docker steps: on the target the solution's containers have `status`
244
- `running` (and are `(healthy)` in `docker ps` when they define a health
245
- check):
246
- `sensecraft-engine docker ps --json` (this computer),
247
- `sensecraft-engine docker ps --host <ip> --username <user> --key-file ~/.ssh/id_ed25519 --json`
248
- (remote with an SSH key; same path rules as `key_file` in §3), or
249
- `SC_SSH_PASSWORD=<password> sensecraft-engine docker ps --host <ip> --username <user> --json`
250
- (remote with a password; `--password-stdin` reads it from stdin instead).
251
- `docker logs <container> --host ... --key-file ...` takes the same options.
252
- Older engines without `--key-file` accept a password only; with a key-only
253
- device use `ssh <user>@<ip> docker ps`.
254
- - Services with a port: `curl -s -o /dev/null -w "%{http_code}" http://<host>:<port>/`
255
- returns 2xx/3xx.
256
- - Stay running: `completed` can precede a crash loop. CLI deploys already
257
- watch each Docker service for about 60 seconds after its health check
258
- answers and fail the step with `Service <name> is not healthy: ...` when a
259
- container restarts, exits or disappears. Check once more yourself: run `docker ps` once,
260
- wait about 60 seconds, then run it again and read the container restart
261
- count (`docker inspect -f '{{.Name}} {{.RestartCount}} {{.State.Status}}' <container>`
262
- over SSH, or the `Restarting` / `Up Less than a second` status in `docker ps`).
263
- The counts must stay 0 and the verify endpoint (the step's `url`, or the
264
- port check above) must still answer after the wait. If a container restarts
265
- or the endpoint stops answering, report a crash loop, not success, and go to
266
- `diagnose.md`.
267
- - Tell the user the URL to open and anything the guide says to do next.
268
-
269
- ## 6. If anything failed
270
-
271
- Go straight to `diagnose.md` with the `deployment_id`. Do not stop to ask.
272
-
273
- To retry after a fix, send the same body again — same `preset_id` and
274
- `device_connections` — with `selected_devices` listing only the device(s) that
275
- failed (or `--device <step_id>` for one device); the others are already done.
276
- Leaving manual steps in is harmless (they are skipped).
277
-
278
- Two kinds of failure, two policies:
279
-
280
- - **Transient registry or network errors** (image pull answered 401 / 429 /
281
- 500 / 502 / 503 / 504, `TLS handshake timeout`, `i/o timeout`,
282
- `connection reset`, a mirror that flaps): retry the same body without
283
- asking, up to 5 times, waiting 15, 30, 60, 120, 240 seconds between tries.
284
- These retries do not count as fix rounds. If the engine log shows the
285
- mirror changing between tries, that is the same transient case. After the
286
- 5th failure, stop and report the error text, the waits and the registry host.
287
- - **Deterministic failures** (bad parameter or credentials, port taken, disk
288
- full, missing file, a container that exits on start, the same error with the
289
- same text after a fix): stop retrying blindly. First retry after a fix
290
- without asking; later retries need the user's OK; at most 3 rounds, then
291
- report.
292
-
293
- If you cannot tell which kind it is, treat the second occurrence of the same
294
- error after a wait as deterministic.
295
-
296
- ## Cancel
297
-
298
- Only with the user's OK: `sensecraft-engine cancel <deployment_id>`. Then check
299
- `status` until it is `cancelled`, and tell the user which steps had already run:
300
- the device may be half-configured.
@@ -1,126 +0,0 @@
1
- # 设备管理与运行时参数热配手册 (Device Management & Reconfiguration Guide)
2
-
3
- > **定位**:供 AI Agent 在用户处于 **设备管理(MANAGE)** 或 **参数热配(RECONFIG)** 阶段查阅。
4
- > 当用户询问“改一下 MQTT 地址”、“修改运行参数”、“查看已安装应用”、“重启服务”、“停止某个方案”时加载本手册。
5
-
6
- ---
7
-
8
- ## 1. 参数可修改性的分层边界
9
-
10
- 在修改方案配置前,Agent 必须明确参数所属的层级,切勿越界操作:
11
-
12
- | 层级 | 参数类别 | 判断依据 | 处理方式 |
13
- |---|---|---|---|
14
- | **L1: 声明式热配参数** | 业务高频参数(MQTT Broker 地址、API Key、告警 Webhook、Wi-Fi 凭证) | 方案中声明了 `user_inputs` 且标记为 `reconfigurable: true` | **在线热修改**:直接调用设备管理 API 更新,后台自动重载并重启容器,零停机重装。 |
15
- | **L2: 方案编排层参数** | 内部端口映射、Docker 数据卷挂载路径、未暴露的环境变量 | 仅存在于 `docker-compose.yml` 或 `devices/<id>.yaml` 中 | **方案级本地补丁**:走本地 auto-patch 流程,用 `--solutions-dir` 重新加载。 |
16
- | **L3: 业务源码与算法层** | 模型置信度硬编码、状态机转移逻辑、前端 UI 界面组件 | 代码直接写死在 Python/C++/Vue 源码中 | **源码二次开发**:走 GitHub 克隆与本地构建联调流(查阅 `references/secondary-development.md`)。 |
17
-
18
- ---
19
-
20
- ## 2. L1 声明式热配标准操作流
21
-
22
- 当设备已经部署运行,用户希望修改 L1 参数(如更改 MQTT 目标服务器)时:
23
-
24
- ### 步骤一:获取运行时信息与当前部署列表
25
- 读取运行环境指针并校验服务健康(桌面端每次启动分配随机端口并写入 `~/.sensecraft/runtime.json`;源码开发环境固定为 `http://127.0.0.1:3260`):
26
- ```bash
27
- # 解析运行时 BASE_URL 并校验连通性
28
- BASE_URL=$(jq -r '.base_url // "http://127.0.0.1:3260"' ~/.sensecraft/runtime.json 2>/dev/null || echo "http://127.0.0.1:3260")
29
- curl -sf "$BASE_URL/api/health" > /dev/null || { echo "SenseCraft 服务未在 $BASE_URL 就绪"; exit 1; }
30
-
31
- # 查询当前设备上活跃运行的方案实例
32
- curl -s "$BASE_URL/api/device-management/active"
33
- ```
34
- - 输出包含 `solution_id`、`device_id`、`status`(running/stopped)、`deployed_at` 及运行 URL。
35
-
36
- ### 步骤二:读取可配参数及当前值(Get Config)
37
- ```bash
38
- # 本地 Docker 部署实例
39
- curl -s "$BASE_URL/api/docker-devices/local/config/<solution_id>"
40
-
41
- # 远程设备实例(通过 SSH 提取运行态值)
42
- curl -s -X POST "$BASE_URL/api/docker-devices/config/<solution_id>" \
43
- -H "Content-Type: application/json" \
44
- -d '{"connection": {"host": "<ip>", "username": "<user>", "password": "<pwd>"}}'
45
- ```
46
- - 检查返回的 `fields` 列表:
47
- - 确认用户想要修改的参数是否存在(`field.id`,如 `mqtt_broker`、`mqtt_port`);
48
- - 查看当前已生效的数值(`field.current_value`);
49
- - 核对其校验规则(`field.validation`)。
50
-
51
- ### 步骤三:验证并提交新参数(Update Config)
52
- > [!IMPORTANT]
53
- > `values` 字典中的 key 必须使用步骤二返回的 `field.id`(例如 `mqtt_broker`、`mqtt_port`),严禁使用环境变量大写名(如 `MQTT_BROKER_HOST`),否则会被后端配置解析器静默忽略。
54
-
55
- 向用户确认修改后,发起热更新请求:
56
- ```bash
57
- # 本地 Docker 部署实例更新(使用从 GET 返回查得的 field.id)
58
- curl -s -X PUT "$BASE_URL/api/docker-devices/local/config/<solution_id>" \
59
- -H "Content-Type: application/json" \
60
- -d '{
61
- "values": {
62
- "mqtt_broker": "192.168.1.200",
63
- "mqtt_port": 1883
64
- }
65
- }'
66
-
67
- # 远程设备实例更新
68
- curl -s -X PUT "$BASE_URL/api/docker-devices/config/<solution_id>" \
69
- -H "Content-Type: application/json" \
70
- -d '{
71
- "values": { "mqtt_broker": "192.168.1.200" },
72
- "connection": { "host": "<ip>", "username": "<user>", "password": "<pwd>" }
73
- }'
74
- ```
75
- - **后端自动执行**:根据 `field.id` 执行模板替换 ➔ 生成新的 env ➔ `docker compose up -d` 重新创建受影响容器 ➔ 更新部署 manifest 记录。
76
- - **无需整机重装**,数据卷与现有文件完全保留。
77
-
78
- ---
79
-
80
- ## 3. 运行态实例的生命周期管理
81
-
82
- 当用户要求“重启服务”、“暂停运行”或“更新容器镜像”时:
83
-
84
- ### 本地 Docker 部署实例(无凭据要求)
85
- ```bash
86
- # 执行 start / stop / restart / update
87
- curl -s -X POST "$BASE_URL/api/device-management/<deployment_id>/action" \
88
- -H "Content-Type: application/json" \
89
- -d '{
90
- "action": "restart",
91
- "device_id": "<step_id>"
92
- }'
93
- ```
94
-
95
- ### 远程设备实例(必须显式携带 SSH 认证凭据)
96
- 远程设备(Jetson / Raspberry Pi 等)通过 SSH 协议由底层执行容器编排动作。由于后端安全机制禁用了 SSH-agent 与自动公钥搜寻,且不持久化保存设备明文密码,因此远程操作**必须向用户获取并显式传入 `password` 或 `key_file`**:
97
-
98
- ```bash
99
- # 远程实例 - 密码认证
100
- curl -s -X POST "$BASE_URL/api/device-management/<deployment_id>/action" \
101
- -H "Content-Type: application/json" \
102
- -d '{
103
- "action": "restart",
104
- "device_id": "<step_id>",
105
- "password": "<ssh_password>"
106
- }'
107
-
108
- # 远程实例 - 私钥文件认证(支持 ~/.ssh/ 下的私钥路径)
109
- curl -s -X POST "$BASE_URL/api/device-management/<deployment_id>/action" \
110
- -H "Content-Type: application/json" \
111
- -d '{
112
- "action": "restart",
113
- "device_id": "<step_id>",
114
- "key_file": "~/.ssh/id_rsa"
115
- }'
116
- ```
117
- - `action` 支持:`start`(启动)、`stop`(停止)、`restart`(重启)、`update`(拉取最新镜像并重启)。
118
- - **判定规则**:从步骤一 `/api/device-management/active` 的返回值中检查目标实例的 `host` 字段。若 `host` 不为 `localhost` 或 `127.0.0.1`,即属于远程设备,发起 action 请求前必须准备好认证凭据。
119
-
120
- ---
121
-
122
- ## 4. 自然交互与应答守则
123
-
124
- 1. **先查后改**:绝不要盲目猜测当前配置。先调用接口读取 `current_value`,并明确告知用户:“*当前配置的 MQTT 地址是 127.0.0.1,我将为您更新为 192.168.1.200*”。
125
- 2. **越界平滑引导**:如果用户要改的参数不在 `reconfigurable` 列表中:
126
- - 坦诚解释:“*该参数属于底层容器编排配置(或写在源码中),无法直接在线热改。但我可以帮您修改本地编排文件重新生效,或者获取源码进行深度定制*”。