@seeed-studio/solution-cli 0.3.2 → 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.
- package/README.md +158 -113
- package/bin/cli.js +315 -29
- package/catalog/client-config.json +2 -2
- package/catalog/knowledge-core.json +58452 -488
- package/docs/cli-guide.md +176 -231
- package/lib/agent.js +69 -10
- package/lib/catalog-dto.js +14 -1
- package/lib/doctor.js +19 -1
- package/lib/downloader.js +24 -0
- package/lib/gotchas.js +126 -0
- package/lib/installer.js +75 -9
- package/lib/integration.js +265 -0
- package/lib/knowledge.js +838 -100
- package/package.json +1 -1
- package/skills/solution-cli/SKILL.md +106 -24
- package/skills/solution-cli/references/consult-and-select.md +58 -14
- package/skills/solution-cli/references/deploy.md +60 -248
- package/skills/solution-cli/references/device-management.md +249 -77
- package/skills/solution-cli/references/diagnose.md +15 -0
- package/skills/solution-cli/references/edge-gotchas.md +205 -0
- package/skills/solution-cli/references/generic-rk3588.md +106 -0
- package/skills/solution-cli/references/hardware-bom.md +9 -3
- package/skills/solution-cli/references/sales-feasibility.md +65 -0
- package/skills/solution-cli/references/secondary-development.md +10 -7
package/docs/cli-guide.md
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
#
|
|
2
|
-
*(
|
|
1
|
+
# Solution CLI 使用与集成指南
|
|
2
|
+
*(Solution CLI & AI Agent Skill Guide)*
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
---
|
|
4
|
+
本文档面向方案架构师、现场工程师、开发者和 AI Agent。安装一次 `solution-cli` Skill 后,用户可以用自然语言完成方案咨询、硬件选型、部署前检查、本地/远程方案部署和部署后诊断。
|
|
7
5
|
|
|
8
6
|
## 目录
|
|
9
7
|
|
|
@@ -11,295 +9,242 @@
|
|
|
11
9
|
2. [安装与 Agent 技能挂载](#2-安装与-agent-技能挂载)
|
|
12
10
|
3. [核心功能、使用方法与具体产出](#3-核心功能使用方法与具体产出)
|
|
13
11
|
- [场景一:方案探索与工况诊断 (Hub Search)](#场景一方案探索与工况诊断-hub-search)
|
|
14
|
-
- [
|
|
15
|
-
- [
|
|
16
|
-
- [
|
|
12
|
+
- [场景二:硬件配置与配件选型(“买这个设备需要配什么配件?会不会买错?”)](#场景二硬件配置与配件选型买这个设备需要配什么配件会不会买错)
|
|
13
|
+
- [场景三:方案一键部署与本地/远程运行 (Solution Deployment)](#场景三方案一键部署与本地远程运行-solution-deployment)
|
|
14
|
+
- [场景四:设备状态感知与参数热修改 (Device Management)](#场景四设备状态感知与参数热修改-device-management)
|
|
15
|
+
- [场景五:自研模型替换与本地二次开发 (Secondary Dev)](#场景五自研模型替换与本地二次开发-secondary-dev)
|
|
17
16
|
4. [双轨运行机制:在线直连与离线托底](#4-双轨运行机制在线直连与离线托底)
|
|
18
17
|
5. [常见问题与环境自检 (Doctor)](#5-常见问题与环境自检-doctor)
|
|
19
18
|
|
|
20
|
-
---
|
|
21
|
-
|
|
22
19
|
## 1. 独特使用场景与核心价值
|
|
23
20
|
|
|
24
|
-
|
|
25
|
-
- **方案选型盲目**:不清楚现场环境(集中还是分散、有无现有监控摄像头、有无市电)对硬件架构的致命影响;
|
|
26
|
-
- **配件采购踩坑**:工控机买回后发现电源电压不符(如 12V 误插 19V 算力板)、DC 插头尺寸不对(5.5x2.1mm 插不进 5.5x2.5mm)、M.2 接口插槽类型搞混(Key-M 固态插不进 Key-E Wi-Fi 槽);
|
|
27
|
-
- **参数变更成本高**:改个 MQTT Broker 地址或算法置信度阈值就需要重新编译镜像或重装整套系统;
|
|
28
|
-
- **AI Agent 缺乏边缘硬件感知**:纯大模型对话缺乏真实物理世界的接口约束,容易凭空编造不存在的硬件型号或非官方链接。
|
|
21
|
+
`@seeed-studio/solution-cli` 提供三类能力:
|
|
29
22
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
3. **AI Agent 的物理世界触手**:一键将 solution-cli Skill 注入到主流 AI Agent 宿主中,让 Agent 具备从方案咨询、BOM 选型到现场部署、参数热更的全生命周期驱动能力。
|
|
23
|
+
- 根据客户工况搜索方案,并列出仍需确认的问题。
|
|
24
|
+
- 查询硬件规格、配件和物理兼容性。
|
|
25
|
+
- 通过签名 Rust Engine 预检查并在本地或远程部署已选方案,持续读取状态、日志和验证结果。
|
|
34
26
|
|
|
35
|
-
|
|
27
|
+
Agent 的默认工作流是“先咨询,再选型,再检查,最后在用户确认后部署”。用户只需描述目标,例如“帮我给锅炉房的 10 个恒温器设计改造方案”,Agent 应先查询方案并询问网络、供电、设备、温度约束和部署位置,不应把客户询盘直接当作部署授权。
|
|
36
28
|
|
|
37
29
|
## 2. 安装与 Agent 技能挂载
|
|
38
30
|
|
|
39
|
-
### 2.1
|
|
40
|
-
无需全局安装,安装或按需升级 Engine 与 Agent Skill 使用同一条命令:
|
|
41
|
-
```bash
|
|
42
|
-
npx -y @seeed-studio/solution-cli@latest install --agent workbuddy -y
|
|
43
|
-
```
|
|
31
|
+
### 2.1 按需精准安装(推荐:只针对当前 Agent 安装,避免环境污染)
|
|
44
32
|
|
|
45
|
-
|
|
46
|
-
Agent ID。需要交互选择时使用 `npx -y @seeed-studio/solution-cli@latest install`;
|
|
47
|
-
检测到一个或多个 Agent 时,直接回车默认选择全部已检测的 Agent,输入对应序号
|
|
48
|
-
选择指定宿主。非交互模式下,`install -y` 未提供 `--agent` 且检测到 Agent 时也会
|
|
49
|
-
选择全部已检测的 Agent。未检测到 Agent 时,这些默认仍使用 CLI 的默认目标集合;
|
|
50
|
-
需要明确控制范围时请提供 `--agent <agent-id>`。
|
|
51
|
-
|
|
52
|
-
首次安装和重复执行都会检查签名稳定版 Engine:本机已有相同或更新版本
|
|
53
|
-
时复用,版本较旧时升级。普通安装保留用户修改、未登记的 Skill 文件和受
|
|
54
|
-
保护的符号链接。需要指定宿主时追加 `--agent claude,antigravity`;需要固
|
|
55
|
-
定有效本地 Engine 时使用 `--engine-path <path>`。`--force` 可重新下载相同
|
|
56
|
-
或较旧版本并覆盖已有 Skill 文件(包括用户修改),请只在有意覆盖时使用;
|
|
57
|
-
受保护的外部符号链接不会追写,也不能降级更新的本机 Engine。
|
|
58
|
-
|
|
59
|
-
自动复用/升级规则自 solution-cli 0.3.1 起生效;该版本已公开发布。latest 检查或签名校验失败会在
|
|
60
|
-
修改 Engine、指针或 Skill 前停止;离线时请提供有效的 `--engine-path`。
|
|
61
|
-
|
|
62
|
-
The same command handles a fresh install and a user-requested upgrade. It checks
|
|
63
|
-
the signed stable Engine, reuses an equal/newer local version, preserves modified
|
|
64
|
-
skills, and stops before writes on latest/signature failure. Automatic reuse and
|
|
65
|
-
upgrade rules start with publicly published solution-cli 0.3.1. The example
|
|
66
|
-
targets WorkBuddy with `--agent workbuddy`; replace it with the current Agent ID
|
|
67
|
-
for another host. Use `npx -y @seeed-studio/solution-cli@latest install` for the
|
|
68
|
-
interactive form: when one or more Agents are detected, pressing Enter selects
|
|
69
|
-
all detected Agents, while entering a number selects one host. In non-interactive
|
|
70
|
-
mode, `install -y` without `--agent` also selects all detected Agents when any
|
|
71
|
-
are detected. If none are detected, these defaults still use the CLI's default
|
|
72
|
-
target set; pass `--agent <agent-id>` to control the scope explicitly.
|
|
73
|
-
|
|
74
|
-
### 2.2 全局安装
|
|
75
|
-
```bash
|
|
76
|
-
npm install -g @seeed-studio/solution-cli
|
|
77
|
-
solution-cli install --agent workbuddy -y
|
|
78
|
-
```
|
|
33
|
+
你可以直接复制下表中对应的专属命令发给对应的 AI 助手,或在终端执行:
|
|
79
34
|
|
|
80
|
-
|
|
81
|
-
`workbuddy` 替换为当前实际 Agent ID。交互执行 `solution-cli install` 时,
|
|
82
|
-
检测到一个或多个 Agent 后直接回车选择全部已检测的 Agent,输入对应序号选择指定
|
|
83
|
-
宿主;非交互执行 `solution-cli install -y` 且未提供 `--agent` 时,检测到 Agent
|
|
84
|
-
也会选择全部已检测的 Agent。未检测到 Agent 时,这些默认仍使用 CLI 的默认目标集合;
|
|
85
|
-
需要明确控制范围时请提供 `--agent <agent-id>`。
|
|
86
|
-
|
|
87
|
-
The global command targets WorkBuddy explicitly. Replace `workbuddy` with the
|
|
88
|
-
current Agent ID for another host. Interactive `solution-cli install` selects all
|
|
89
|
-
detected Agents on Enter when any are detected, or one host by number;
|
|
90
|
-
non-interactive `solution-cli install -y` without `--agent` also selects all
|
|
91
|
-
detected Agents when any are detected. If none are detected, these defaults still
|
|
92
|
-
use the CLI's default target set; pass `--agent <agent-id>` to control the scope
|
|
93
|
-
explicitly.
|
|
94
|
-
|
|
95
|
-
### 2.3 跨 Agent 平台技能挂载
|
|
96
|
-
执行 `solution-cli install` 时,工具会自动检测本机存在的 Agent 宿主环境,并将 `solution-cli` Skill 和全套参考手册安全复制到对应目录:
|
|
97
|
-
|
|
98
|
-
| Agent 宿主平台 | 技能默认配置路径 | 支持能力 |
|
|
35
|
+
| 目标 AI 宿主平台 | 专属安装命令(直接复制发给 AI 或在终端运行) | 技能默认配置路径 |
|
|
99
36
|
|---|---|---|
|
|
100
|
-
|
|
|
101
|
-
| **
|
|
102
|
-
| **
|
|
103
|
-
| **
|
|
104
|
-
| **
|
|
37
|
+
| **豆包工作 (Doubao Work)** | `npx -y @seeed-studio/solution-cli install --agent doubao` | `~/.doubao/skills` |
|
|
38
|
+
| **WorkBuddy** | `npx -y @seeed-studio/solution-cli install --agent workbuddy` | `~/.workbuddy/skills` |
|
|
39
|
+
| **Claude Code** | `npx -y @seeed-studio/solution-cli install --agent claude` | `~/.claude/skills` |
|
|
40
|
+
| **OpenAI Codex** | `npx -y @seeed-studio/solution-cli install --agent codex` | `~/.agents/skills` 或 `~/.codex/skills` |
|
|
41
|
+
| **Google Antigravity** | `npx -y @seeed-studio/solution-cli install --agent antigravity` | `~/.gemini/config/skills` |
|
|
42
|
+
| **CodeBuddy** | `npx -y @seeed-studio/solution-cli install --agent codebuddy` | `~/.codebuddy/skills` |
|
|
43
|
+
| **全部 Agent (全量覆盖)** | `npx -y @seeed-studio/solution-cli install --agent all` | 上述全部已检测目录 |
|
|
44
|
+
| **自定义目录 (如 Cursor)** | `npx -y @seeed-studio/solution-cli install --skills-dir <路径>` | `<自定义路径>/solution-cli` |
|
|
45
|
+
|
|
46
|
+
> [!TIP]
|
|
47
|
+
> - **丢给 AI 极简执行**:例如在豆包工作中直接发送:*“请帮我运行:`npx -y @seeed-studio/solution-cli install --agent doubao`”*,AI 将直接在后台非交互执行并自动就绪。
|
|
48
|
+
> - **严格隔离**:指定 `--agent <id>` 时,安装器依据 ledger 记录仅写入该 Agent 对应的目录,绝不修改其他 Agent 的技能或配置。
|
|
49
|
+
|
|
50
|
+
### 2.2 本地源码部署与定制开发 (Local Deployment)
|
|
51
|
+
|
|
52
|
+
如果你在本地仓库进行开发或调试,可以直接使用源码安装,无需经过 npm:
|
|
105
53
|
|
|
106
|
-
**非交互式多选安装示例**:
|
|
107
54
|
```bash
|
|
108
|
-
#
|
|
109
|
-
|
|
110
|
-
```
|
|
55
|
+
# 针对特定 Agent 安装
|
|
56
|
+
node bin/cli.js install --agent <doubao|claude|codex|antigravity|codebuddy>
|
|
111
57
|
|
|
112
|
-
|
|
58
|
+
# 挂载到自定义目录
|
|
59
|
+
node bin/cli.js install --skills-dir ~/.cursor/skills
|
|
60
|
+
```
|
|
113
61
|
|
|
114
62
|
## 3. 核心功能、使用方法与具体产出
|
|
115
63
|
|
|
116
|
-
|
|
64
|
+
安装后可直接在命令行运行 `solution-cli` 与 `sensecraft-engine`;若未执行安装,也可随时通过 `npx -y @seeed-studio/solution-cli <command>` 免安装即用。
|
|
117
65
|
|
|
118
|
-
|
|
66
|
+
### 场景一:方案探索与工况诊断 (Hub Search)
|
|
119
67
|
|
|
120
68
|
#### 1. 执行命令
|
|
121
|
-
```bash
|
|
122
|
-
# 人类工程师阅读模式 (格式化终端高亮)
|
|
123
|
-
solution-cli hub search "农业"
|
|
124
69
|
|
|
125
|
-
|
|
126
|
-
solution-cli hub search "
|
|
70
|
+
```bash
|
|
71
|
+
solution-cli hub search "锅炉恒温器" --json
|
|
127
72
|
```
|
|
128
73
|
|
|
74
|
+
*(免安装时可用:`npx -y @seeed-studio/solution-cli hub search "锅炉恒温器" --json`)*
|
|
75
|
+
|
|
129
76
|
#### 2. 产出物内容 (What it Outputs)
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
2. **静默商业闭环出口**:自动为该方案生成带有安全追踪标记(`utm_source=sensecraft_agent`)的官方落地页与开发 Wiki;
|
|
133
|
-
3. **官方开源仓库地址**:提供官方维护的 GitHub 源码仓库,为二次开发预留出口;
|
|
134
|
-
4. **现场工况诊断提问指引 (Diagnostic Playbook)**:直接给出当前场景下**必须向客户确认的 2~3 个核心工况问题**及其背后的技术决断理由。
|
|
77
|
+
|
|
78
|
+
Agent 根据结果解释匹配的方案、设备和限制,并追问客户现场信息。方案未确认前只查询,不运行部署。
|
|
135
79
|
|
|
136
80
|
#### 3. 产出示例 (以“农业”搜索为例)
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
81
|
+
|
|
82
|
+
输出应包含匹配方案、适用场景、设备要求和仍需确认的工况问题;具体内容以查询结果为准。
|
|
83
|
+
|
|
84
|
+
#### 4. 页面关系、内容读取与生产链接
|
|
85
|
+
|
|
86
|
+
方案目录按显式关系组织,不把页面名称混用:Scenario 是业务落地页,Tech 是独立技术归属页,Reference Design(RD)是具体方案设计。Scenario 会关联 Tech 和 RD;RD 可继续关联架构图、产品说明和部署文档。只有 RD 存在有效部署映射和 preset 时,才可进入一键部署流程。
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
# 全量目录:按页读取,直到 has_more=false
|
|
90
|
+
solution-cli hub list --type reference_design --locale zh --page 1 --limit 50 --json
|
|
91
|
+
# 选定记录:按需要读取关系、链接、架构、产品或部署内容
|
|
92
|
+
solution-cli hub get <id> --locale zh --section overview --json
|
|
93
|
+
solution-cli hub get <id> --locale zh --section links --json
|
|
94
|
+
solution-cli hub get <id> --locale zh --section architecture --json
|
|
95
|
+
solution-cli hub get <id> --locale zh --section products --json
|
|
96
|
+
solution-cli hub get <id> --locale zh --section deployment --json
|
|
150
97
|
```
|
|
151
98
|
|
|
152
|
-
|
|
99
|
+
三种生产语言使用不同域名:英文 `www.seeed.cc`、中文 `www.seeedstudio.com.cn`、日文 `www.seeed.co.jp`。实际链接必须使用 `hub get --section links` 返回的地址;不要从 slug 拼接 Wiki、图片 CDN 或其他语言 URL。Wiki 是单独的已发布文档链接,Tech 页面也不能被当成 Wiki。翻译正文缺失时,保留可用的生产页并说明返回的内容语言。
|
|
153
100
|
|
|
154
|
-
|
|
101
|
+
返回链接或 metadata 不等于已经阅读页面内容。回答方案能力、架构或产品问题时,必须读取对应的 `description`、`architecture`、`products` section;确切落地页或架构图片影响答案时,打开 CLI 返回的确切地址并说明实际核验范围。相对图片路径只有在签名本地内容存在时才可读取,否则标为 source asset 未就绪。
|
|
155
102
|
|
|
156
|
-
|
|
103
|
+
RD 的部署映射只是目录信息,执行前还要读取本机 Engine 的实际配置:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
sensecraft-engine deploy-info <solution-id> --lang zh
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
架构部分只引用来源明确标记为 architecture 的图;其余图片按 gallery 呈现。产品说明、BOM、架构来源和部署文档都要保留来源与内容语言。
|
|
110
|
+
|
|
111
|
+
### 场景二:硬件配置与配件选型(“买这个设备需要配什么配件?会不会买错?”)
|
|
112
|
+
|
|
113
|
+
#### 1. 适用场景(客户常问什么)
|
|
114
|
+
|
|
115
|
+
- “这款硬件(如 reComputer J40、SenseCAP Watcher)是什么配置?有几个网口、多大算力?”
|
|
116
|
+
- “我买了这台主机,还需要额外配什么配件?电源、天线、外壳带不带?”
|
|
117
|
+
- “我想加装 4G 模块或 SSD 固态硬盘,哪些型号能兼容?会不会买错插不上?”
|
|
118
|
+
|
|
119
|
+
#### 2. 执行命令
|
|
157
120
|
|
|
158
|
-
#### 1. 执行命令
|
|
159
121
|
```bash
|
|
160
|
-
# 1.
|
|
161
|
-
solution-cli product query
|
|
122
|
+
# 1. 查硬件配置参数(算力、电压、物理接口、外形尺寸)
|
|
123
|
+
solution-cli product query <family-id> --json
|
|
162
124
|
|
|
163
|
-
# 2.
|
|
164
|
-
solution-cli product accessories
|
|
125
|
+
# 2. 查配件推荐与兼容性清单(区分必买配件、可选配件,防踩坑)
|
|
126
|
+
solution-cli product accessories <family-id> --json
|
|
165
127
|
```
|
|
166
128
|
|
|
167
|
-
####
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
-
|
|
173
|
-
|
|
174
|
-
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
129
|
+
#### 3. 它能为你产出什么(解决什么痛点)
|
|
130
|
+
|
|
131
|
+
1. **查清硬件规格**:直接返回 CPU/GPU 算力、供电范围、物理接口(网口/串口/USB)、外形尺寸等真实参数,无需翻找繁琐的说明书。
|
|
132
|
+
2. **分清“必须买”与“按需选配”**:
|
|
133
|
+
- **必需配件(必须购买)**:如匹配功率的电源适配器、国标/美标电源线,不买设备无法开机;
|
|
134
|
+
- **可选配件(扩展使用)**:如安装导轨、外置天线、防护外壳、摄像头模组、M.2 扩展卡等。
|
|
135
|
+
3. **防止买错踩坑(兼容性校验)**:
|
|
136
|
+
- 自动对比接口规格(如 M.2 Key-M 还是 Key-E)、天线频段(4G/Wi-Fi/LoRa)、供电电压与功率;
|
|
137
|
+
- 明确标注 `VERIFIED`(官方实测兼容)、`REQUIRES_ADAPTER`(需搭配转接板)或 `INCOMPATIBLE`(不兼容,严禁搭配使用)。
|
|
138
|
+
4. **一键生成采购清单**:
|
|
139
|
+
- 结果直接包含官方真实 SKU、数量建议与购买链接,方便直接采购下单。
|
|
140
|
+
|
|
141
|
+
### 场景三:方案一键部署与本地/远程运行 (Solution Deployment)
|
|
142
|
+
|
|
143
|
+
方案部署由签名 Rust Engine (`sensecraft-engine`) 驱动,支持**本地一键部署**与**远程边缘设备部署**。
|
|
144
|
+
|
|
145
|
+
#### 1. 读取部署规范与预设
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
sensecraft-engine deploy-info <solution-id> --lang zh
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
根据返回的 `presets` 与 `device_connections` 准备参数文件 `./.sensecraft-work/body.json`。
|
|
152
|
+
|
|
153
|
+
#### 2. 参数文件配置
|
|
154
|
+
|
|
155
|
+
- **模式 A:本地快速部署(Local Docker,最简单、零密码配置)**
|
|
156
|
+
适用于在当前本地宿主机(Linux 工作站 / Jetson / 树莓派)上直接运行方案容器:
|
|
157
|
+
```json
|
|
158
|
+
{
|
|
159
|
+
"solution_id": "<solution-id>",
|
|
160
|
+
"preset_id": "default",
|
|
161
|
+
"selected_devices": ["host_device"],
|
|
162
|
+
"device_connections": {
|
|
163
|
+
"host_device": {
|
|
164
|
+
"target": "local_host",
|
|
165
|
+
"target_type": "local"
|
|
200
166
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
- **模式 B:远程边缘设备部署(Remote SSH 密钥认证)**
|
|
172
|
+
适用于部署到局域网内的远程边缘硬件。严禁使用明文密码,统一采用 SSH 私钥认证:
|
|
173
|
+
```json
|
|
174
|
+
{
|
|
175
|
+
"solution_id": "<solution-id>",
|
|
176
|
+
"preset_id": "default",
|
|
177
|
+
"selected_devices": ["host_device"],
|
|
178
|
+
"device_connections": {
|
|
179
|
+
"host_device": {
|
|
180
|
+
"target": "remote_edge",
|
|
181
|
+
"target_type": "remote",
|
|
182
|
+
"host": "192.168.1.50",
|
|
183
|
+
"username": "seeed",
|
|
184
|
+
"key_file": "~/.ssh/id_ed25519"
|
|
208
185
|
}
|
|
209
|
-
|
|
186
|
+
}
|
|
210
187
|
}
|
|
211
|
-
|
|
212
|
-
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
#### 3. 一行命令执行部署与状态追踪
|
|
213
191
|
|
|
214
|
-
|
|
192
|
+
```bash
|
|
193
|
+
# 1. 验证参数并启动部署
|
|
194
|
+
sensecraft-engine deploy --params ./.sensecraft-work/body.json --yes
|
|
215
195
|
|
|
216
|
-
|
|
196
|
+
# 2. 查询部署进度与容器日志
|
|
197
|
+
sensecraft-engine status <deployment-id> --json
|
|
198
|
+
sensecraft-engine logs <deployment-id>
|
|
199
|
+
```
|
|
217
200
|
|
|
218
|
-
|
|
201
|
+
### 场景四:设备状态感知与参数热修改 (Device Management)
|
|
219
202
|
|
|
220
203
|
#### 1. 核心流程与接口
|
|
221
|
-
系统支持**无需重新编译、无需重装整套系统**的零重启参数热修改:
|
|
222
|
-
1. **查询当前设备活跃部署**:
|
|
223
|
-
`GET http://<host>:5823/api/device-management/active`
|
|
224
|
-
2. **查询可修改参数**:
|
|
225
|
-
`GET http://<host>:5823/api/docker-devices/local/config/<solution_id>`
|
|
226
|
-
检查参数字段中的 `reconfigurable: true` 标记。
|
|
227
|
-
3. **提交热更新**:
|
|
228
|
-
`PUT http://<host>:5823/api/docker-devices/local/config/<solution_id>`
|
|
229
|
-
传入目标键值,容器环境无感热加载生效。
|
|
230
204
|
|
|
231
|
-
|
|
205
|
+
已部署设备的参数修改要先读取当前部署和可修改字段,确认目标和变更范围,再执行对应管理接口。能否热修改取决于方案返回的 `reconfigurable` 字段;不要假设所有参数都支持无重启修改。
|
|
232
206
|
|
|
233
|
-
###
|
|
234
|
-
|
|
235
|
-
当官方自带的模型无法满足客户特殊工况(如需要自研模型、特殊缺陷检测、修改前端大屏 UI)时使用。
|
|
207
|
+
### 场景五:自研模型替换与本地二次开发 (Secondary Dev)
|
|
236
208
|
|
|
237
209
|
#### 1. 开发闭环步骤
|
|
238
|
-
1. **克隆源码**:
|
|
239
|
-
从 `solution-cli hub search` 返回的 `repo_url` 将源码克隆到本地用户工作区:
|
|
240
|
-
```bash
|
|
241
|
-
git clone https://github.com/suharvest/sensecraft-solutions.git ./my-solutions
|
|
242
|
-
```
|
|
243
|
-
2. **端侧模型转换 (以 Jetson Orin 为例)**:
|
|
244
|
-
在设备上使用 TensorRT 将自定义 ONNX 导出为 Engine:
|
|
245
|
-
```bash
|
|
246
|
-
/usr/src/tensorrt/bin/trtexec --onnx=my_model.onnx --saveEngine=my_model.engine --fp16
|
|
247
|
-
```
|
|
248
|
-
3. **覆盖挂载配置**:
|
|
249
|
-
在方案目录创建 `docker-compose.override.yml` 将本地自研模型映射进容器中。
|
|
250
|
-
4. **驱动本地快速联调**:
|
|
251
|
-
使用 `--solutions-dir` 参数,强制底层引擎加载本地修改版方案,彻底不碰官方缓存:
|
|
252
|
-
```bash
|
|
253
|
-
sensecraft-engine deploy fall_detection --solutions-dir ./my-solutions/solutions
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
---
|
|
257
210
|
|
|
258
|
-
|
|
211
|
+
从查询结果中的官方仓库获取源码,在本地修改后按方案文档使用 `--solutions-dir` 进行测试。部署前展示修改和影响范围;不要把本地开发目录直接当作已验证的生产方案。
|
|
259
212
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
```mermaid
|
|
263
|
-
flowchart TD
|
|
264
|
-
RunCmd["用户 / Agent 触发 CLI 命令"] --> NetCheck{"检查网络与凭证"}
|
|
265
|
-
NetCheck -- "有外网且含烘焙配置" --> Typesense["直连 Seeed Typesense 云端搜索集群"]
|
|
266
|
-
Typesense -- "返回最新上线方案与配件" --> Done["输出 Catalog DTO"]
|
|
267
|
-
NetCheck -- "纯内网 / 无凭证 / 超时" --> LocalCore["无感降级: 读取 catalog/knowledge-core.json"]
|
|
268
|
-
LocalCore -- "331 KB 本地知识库 (18场景/39方案/119硬件)" --> Done
|
|
269
|
-
```
|
|
270
|
-
|
|
271
|
-
1. **在线实时模式 (Online Live)**:
|
|
272
|
-
- 采用安全方案 B 在构建发布期烘焙了公开的只读 Search-Only 凭证;
|
|
273
|
-
- 自动直连 `https://rel-search.seeedstudio.com`,实时获取最新的方案、Wiki、案例及商城 SKU;
|
|
274
|
-
2. **离线安全托底 (Offline Resilience)**:
|
|
275
|
-
- 打包了全量预生成的 `catalog/knowledge-core.json`(331 KB);
|
|
276
|
-
- 在军工、内网、无公网或云端响应超过 2.5 秒时,**自动毫秒级无感降级到本地内核**,工况诊断、BOM 评估与离线部署 100% 正常可用。
|
|
213
|
+
## 4. 双轨运行机制:在线直连与离线托底
|
|
277
214
|
|
|
278
|
-
|
|
215
|
+
目录和产品查询优先使用在线资源;无法联网时使用已安装包中的本地内容和知识库。离线能力不代表所有在线方案或实时设备状态都可用。部署仍需目标设备可达、凭据有效、目标环境满足 `deploy-info` 和 `validate` 的要求。
|
|
279
216
|
|
|
280
217
|
## 5. 常见问题与环境自检 (Doctor)
|
|
281
218
|
|
|
282
219
|
### 1. 运行自检工具
|
|
283
|
-
|
|
220
|
+
|
|
284
221
|
```bash
|
|
285
|
-
solution-cli doctor
|
|
222
|
+
solution-cli doctor --json
|
|
286
223
|
```
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
- `Docker Daemon`: 确认 Docker 服务是否正常运行;
|
|
290
|
-
- `Serial / Dialout Permissions`: 确认串口访问权限;
|
|
291
|
-
- `SenseCraft Engine`: 确认底座引擎完整性与版本;
|
|
292
|
-
- `Ledger Integrity`: 校验技能安装账本状态。
|
|
224
|
+
|
|
225
|
+
重点查看操作系统、架构、Engine、PATH、串口权限、Docker 和 Skill ledger 的结果。远程设备的 SSH、sudo、Docker 安装和启动状态需按 `deploy-info`、`validate` 和设备返回信息单独确认;CLI 不会静默取得权限。
|
|
293
226
|
|
|
294
227
|
### 2. 状态查询
|
|
228
|
+
|
|
295
229
|
```bash
|
|
296
230
|
solution-cli status
|
|
297
231
|
```
|
|
298
|
-
实时查看当前 Engine 所在路径、安装版本、本地 Content 方案缓存数量以及各大 Agent 的配置状态。
|
|
299
232
|
|
|
300
|
-
|
|
301
|
-
|
|
233
|
+
查看 Engine 路径、版本、内容缓存和 Skill 挂载状态。
|
|
234
|
+
|
|
235
|
+
### 3. 网络与源排查
|
|
236
|
+
|
|
237
|
+
若遇到 npm 下载或同步延迟,可在命令中显式指定官方源:
|
|
302
238
|
```bash
|
|
303
|
-
solution-cli
|
|
239
|
+
npx -y --registry=https://registry.npmjs.org/ @seeed-studio/solution-cli install -y
|
|
304
240
|
```
|
|
305
|
-
|
|
241
|
+
|
|
242
|
+
### 4. 干净卸载
|
|
243
|
+
|
|
244
|
+
只卸载指定宿主,并先备份需要保留的用户修改:
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
solution-cli uninstall --agent workbuddy
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
卸载依据 ledger 只删除 CLI 自己写入且未被修改的文件,不删除 Engine 或方案内容。旧的非 `solution-cli` Skill 目录需要用户自行备份和清理;不要使用 `rm -rf` 或 `--force` 代替确认。
|
package/lib/agent.js
CHANGED
|
@@ -2,17 +2,25 @@ import os from 'node:os';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import fs from 'node:fs';
|
|
4
4
|
import readline from 'node:readline';
|
|
5
|
+
import crypto from 'node:crypto';
|
|
6
|
+
import { loadLedger } from './ledger.js';
|
|
5
7
|
|
|
6
8
|
export function getKnownAgents() {
|
|
7
9
|
const home = os.homedir();
|
|
8
10
|
|
|
9
11
|
return [
|
|
12
|
+
{
|
|
13
|
+
id: 'doubao',
|
|
14
|
+
name: '豆包工作 (Doubao Work)',
|
|
15
|
+
homeDirs: [path.join(home, '.doubao')],
|
|
16
|
+
getSkillsDir: () => path.join(home, '.doubao', 'skills')
|
|
17
|
+
},
|
|
10
18
|
{
|
|
11
19
|
id: 'workbuddy',
|
|
12
|
-
|
|
20
|
+
aliases: ['workbody'],
|
|
21
|
+
name: 'WorkBuddy / Workbody',
|
|
13
22
|
homeDirs: [path.join(home, '.workbuddy'), path.join(home, '.workbody')],
|
|
14
23
|
getSkillsDir: () => {
|
|
15
|
-
// Check where an existing installation might already be
|
|
16
24
|
const p1 = path.join(home, '.workbuddy', 'skills');
|
|
17
25
|
const p2 = path.join(home, '.workbody', 'skills');
|
|
18
26
|
if (fs.existsSync(path.join(p1, 'solution-cli', 'SKILL.md'))) return p1;
|
|
@@ -66,6 +74,24 @@ export function getKnownAgents() {
|
|
|
66
74
|
|
|
67
75
|
export function scanLocalAgents() {
|
|
68
76
|
const agents = getKnownAgents();
|
|
77
|
+
|
|
78
|
+
try {
|
|
79
|
+
const ledger = loadLedger();
|
|
80
|
+
for (const [targetId, inst] of Object.entries(ledger?.installations || {})) {
|
|
81
|
+
if (targetId.startsWith('custom_') && inst) {
|
|
82
|
+
const skillsDir = inst.skills_dir || (inst.target_dir ? path.dirname(inst.target_dir) : (inst.targetDir ? path.dirname(inst.targetDir) : null));
|
|
83
|
+
if (skillsDir && fs.existsSync(skillsDir) && !agents.some(a => a.id === targetId)) {
|
|
84
|
+
agents.push({
|
|
85
|
+
id: targetId,
|
|
86
|
+
name: `Custom Agent (${skillsDir})`,
|
|
87
|
+
homeDirs: [skillsDir],
|
|
88
|
+
getSkillsDir: () => skillsDir,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
} catch {}
|
|
94
|
+
|
|
69
95
|
return agents.map(a => {
|
|
70
96
|
const skillsDir = a.getSkillsDir();
|
|
71
97
|
const detected = a.homeDirs.some(dir => fs.existsSync(dir)) || fs.existsSync(skillsDir);
|
|
@@ -79,29 +105,62 @@ export function scanLocalAgents() {
|
|
|
79
105
|
});
|
|
80
106
|
}
|
|
81
107
|
|
|
82
|
-
export
|
|
108
|
+
export function formatAgentList(scannedAgents) {
|
|
109
|
+
return scannedAgents.map(a => ({
|
|
110
|
+
id: a.id,
|
|
111
|
+
name: a.name,
|
|
112
|
+
detected: a.detected,
|
|
113
|
+
installed: a.installed,
|
|
114
|
+
skillsDir: a.skillsDir,
|
|
115
|
+
}));
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export async function promptAgentSelection(scannedAgents, cliArg, autoYes = false, skillsDir = null) {
|
|
119
|
+
// If custom skillsDir is specified, inject a custom target
|
|
120
|
+
if (skillsDir) {
|
|
121
|
+
const resolvedDir = path.resolve(skillsDir);
|
|
122
|
+
const dirHash = crypto.createHash('sha256').update(resolvedDir).digest('hex').slice(0, 8);
|
|
123
|
+
const customId = `custom_${dirHash}`;
|
|
124
|
+
const customTarget = {
|
|
125
|
+
id: customId,
|
|
126
|
+
name: `Custom Agent (${resolvedDir})`,
|
|
127
|
+
skillsDir: resolvedDir,
|
|
128
|
+
detected: true,
|
|
129
|
+
installed: fs.existsSync(path.join(resolvedDir, 'solution-cli', 'SKILL.md')),
|
|
130
|
+
homeDirs: [resolvedDir],
|
|
131
|
+
getSkillsDir: () => resolvedDir,
|
|
132
|
+
};
|
|
133
|
+
if (!cliArg) {
|
|
134
|
+
return [customTarget];
|
|
135
|
+
}
|
|
136
|
+
// Avoid duplicate if already scanned from ledger
|
|
137
|
+
const existingIdx = scannedAgents.findIndex(a => a.id === customId);
|
|
138
|
+
if (existingIdx >= 0) {
|
|
139
|
+
scannedAgents[existingIdx] = customTarget;
|
|
140
|
+
} else {
|
|
141
|
+
scannedAgents.push(customTarget);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
83
145
|
// If explicitly specified in CLI flags
|
|
84
146
|
if (cliArg) {
|
|
85
147
|
if (cliArg.toLowerCase() === 'all') {
|
|
86
148
|
return scannedAgents;
|
|
87
149
|
}
|
|
88
150
|
const requested = cliArg.split(',').map(s => s.trim().toLowerCase());
|
|
89
|
-
const matched = scannedAgents.filter(a => requested.includes(a.id));
|
|
151
|
+
const matched = scannedAgents.filter(a => requested.includes(a.id) || (a.aliases && a.aliases.some(alias => requested.includes(alias))));
|
|
90
152
|
if (matched.length === 0) {
|
|
91
153
|
throw new Error(`No matching agents for: "${cliArg}". Available: ${scannedAgents.map(a => a.id).join(', ')}`);
|
|
92
154
|
}
|
|
93
155
|
return matched;
|
|
94
156
|
}
|
|
95
157
|
|
|
96
|
-
// Non-interactive check (CI / piped / daemon)
|
|
158
|
+
// Non-interactive check (CI / piped / daemon / AI Agent subprocess)
|
|
97
159
|
const isInteractive = Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
98
160
|
|
|
99
161
|
if (!isInteractive) {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
return detectedOnly.length > 0 ? detectedOnly : scannedAgents.slice(0, 1);
|
|
103
|
-
}
|
|
104
|
-
throw new Error('Non-interactive environment detected. Please specify --agent <workbuddy|claude|codex|codebuddy|all> or pass -y.');
|
|
162
|
+
const detectedOnly = scannedAgents.filter(a => a.detected);
|
|
163
|
+
return detectedOnly.length > 0 ? detectedOnly : scannedAgents;
|
|
105
164
|
}
|
|
106
165
|
|
|
107
166
|
if (autoYes) {
|
package/lib/catalog-dto.js
CHANGED
|
@@ -13,6 +13,10 @@ export const SCHEMA_URL = 'https://spec.seeedstudio.com/schemas/v2/catalog-dto.j
|
|
|
13
13
|
* @param {'FRESH' | 'STALE' | 'UNKNOWN'} [options.freshness='FRESH']
|
|
14
14
|
* @param {string} [options.datasetVersion='2026-10-13.1']
|
|
15
15
|
* @param {Array} options.records
|
|
16
|
+
* @param {Object} [options.pagination]
|
|
17
|
+
* @param {string} [options.scope]
|
|
18
|
+
* @param {string} [options.locale]
|
|
19
|
+
* @param {Object} [options.provenance]
|
|
16
20
|
* @param {Object} [options.fieldCompleteness]
|
|
17
21
|
* @param {Array<string>} [options.warnings=[]]
|
|
18
22
|
* @returns {Object} Validated Catalog DTO
|
|
@@ -22,10 +26,14 @@ export function createCatalogDto({
|
|
|
22
26
|
freshness = 'FRESH',
|
|
23
27
|
datasetVersion = '2026-10-13.1',
|
|
24
28
|
records = [],
|
|
29
|
+
pagination = null,
|
|
30
|
+
scope = null,
|
|
31
|
+
locale = null,
|
|
32
|
+
provenance = null,
|
|
25
33
|
fieldCompleteness = { spec: true, compatibility: true, offer: source === 'typesense' },
|
|
26
34
|
warnings = [],
|
|
27
35
|
}) {
|
|
28
|
-
|
|
36
|
+
const dto = {
|
|
29
37
|
$schema: SCHEMA_URL,
|
|
30
38
|
schema_version: SCHEMA_VERSION,
|
|
31
39
|
dataset_version: datasetVersion,
|
|
@@ -37,6 +45,11 @@ export function createCatalogDto({
|
|
|
37
45
|
records: Array.isArray(records) ? records : [],
|
|
38
46
|
warnings: Array.isArray(warnings) ? warnings : [],
|
|
39
47
|
};
|
|
48
|
+
if (pagination) dto.pagination = pagination;
|
|
49
|
+
if (scope) dto.scope = scope;
|
|
50
|
+
if (locale) dto.locale = locale;
|
|
51
|
+
if (provenance) dto.provenance = provenance;
|
|
52
|
+
return dto;
|
|
40
53
|
}
|
|
41
54
|
|
|
42
55
|
/**
|