@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.
- package/README.md +157 -104
- package/bin/cli.js +410 -58
- package/bin/runner.js +1 -1
- package/catalog/client-config.json +2 -2
- package/catalog/knowledge-core.json +58452 -488
- package/docs/cli-guide.md +173 -200
- package/lib/agent.js +74 -15
- package/lib/catalog-dto.js +14 -1
- package/lib/detector.js +3 -3
- package/lib/doctor.js +19 -1
- package/lib/downloader.js +24 -0
- package/lib/gotchas.js +126 -0
- package/lib/installer.js +113 -19
- package/lib/integration.js +265 -0
- package/lib/knowledge.js +838 -100
- package/lib/ledger.js +1 -1
- package/package.json +3 -6
- package/skills/{sensecraft → solution-cli}/SKILL.md +125 -30
- package/skills/{sensecraft → solution-cli}/references/consult-and-select.md +61 -13
- package/skills/solution-cli/references/deploy.md +112 -0
- package/skills/solution-cli/references/device-management.md +298 -0
- package/skills/{sensecraft → 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/{sensecraft → solution-cli}/references/hardware-bom.md +9 -3
- package/skills/solution-cli/references/sales-feasibility.md +65 -0
- package/skills/{sensecraft → solution-cli}/references/secondary-development.md +10 -7
- package/skills/sensecraft/references/deploy.md +0 -300
- package/skills/sensecraft/references/device-management.md +0 -126
- /package/skills/{sensecraft → solution-cli}/references/app-only.md +0 -0
- /package/skills/{sensecraft → solution-cli}/references/error-catalog.md +0 -0
- /package/skills/{sensecraft → solution-cli}/references/offline.md +0 -0
- /package/skills/{sensecraft → solution-cli}/references/verify.md +0 -0
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,267 +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 的物理世界触手**:一键将 SenseCraft 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
|
-
|
|
31
|
+
### 2.1 按需精准安装(推荐:只针对当前 Agent 安装,避免环境污染)
|
|
32
|
+
|
|
33
|
+
你可以直接复制下表中对应的专属命令发给对应的 AI 助手,或在终端执行:
|
|
34
|
+
|
|
35
|
+
| 目标 AI 宿主平台 | 专属安装命令(直接复制发给 AI 或在终端运行) | 技能默认配置路径 |
|
|
36
|
+
|---|---|---|
|
|
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:
|
|
53
|
+
|
|
41
54
|
```bash
|
|
42
|
-
|
|
55
|
+
# 针对特定 Agent 安装
|
|
56
|
+
node bin/cli.js install --agent <doubao|claude|codex|antigravity|codebuddy>
|
|
57
|
+
|
|
58
|
+
# 挂载到自定义目录
|
|
59
|
+
node bin/cli.js install --skills-dir ~/.cursor/skills
|
|
43
60
|
```
|
|
44
61
|
|
|
45
|
-
|
|
46
|
-
时复用,版本较旧时升级。普通安装保留用户修改、未登记的 Skill 文件和受
|
|
47
|
-
保护的符号链接。需要指定宿主时追加 `--agent claude,antigravity`;需要固
|
|
48
|
-
定有效本地 Engine 时使用 `--engine-path <path>`。`--force` 可重新下载相同
|
|
49
|
-
或较旧版本并覆盖已有 Skill 文件(包括用户修改),请只在有意覆盖时使用;
|
|
50
|
-
受保护的外部符号链接不会追写,也不能降级更新的本机 Engine。
|
|
62
|
+
## 3. 核心功能、使用方法与具体产出
|
|
51
63
|
|
|
52
|
-
|
|
53
|
-
这些规则尚未上线。本次验证时 0.3.1 待发布。latest 检查或签名校验失败会在
|
|
54
|
-
修改 Engine、指针或 Skill 前停止;离线时请提供有效的 `--engine-path`。
|
|
64
|
+
安装后可直接在命令行运行 `solution-cli` 与 `sensecraft-engine`;若未执行安装,也可随时通过 `npx -y @seeed-studio/solution-cli <command>` 免安装即用。
|
|
55
65
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
upgrade rules start with solution-cli 0.3.1; if npm `latest` is still 0.3.0,
|
|
60
|
-
those rules are not live. At this verification, 0.3.1 is pending publication.
|
|
66
|
+
### 场景一:方案探索与工况诊断 (Hub Search)
|
|
67
|
+
|
|
68
|
+
#### 1. 执行命令
|
|
61
69
|
|
|
62
|
-
### 2.2 全局安装
|
|
63
70
|
```bash
|
|
64
|
-
|
|
71
|
+
solution-cli hub search "锅炉恒温器" --json
|
|
65
72
|
```
|
|
66
73
|
|
|
67
|
-
|
|
68
|
-
执行 `solution-cli install` 时,工具会自动检测本机存在的 Agent 宿主环境,并将 `sensecraft` Skill 和全套参考手册安全复制到对应目录:
|
|
74
|
+
*(免安装时可用:`npx -y @seeed-studio/solution-cli hub search "锅炉恒温器" --json`)*
|
|
69
75
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
76
|
+
#### 2. 产出物内容 (What it Outputs)
|
|
77
|
+
|
|
78
|
+
Agent 根据结果解释匹配的方案、设备和限制,并追问客户现场信息。方案未确认前只查询,不运行部署。
|
|
79
|
+
|
|
80
|
+
#### 3. 产出示例 (以“农业”搜索为例)
|
|
81
|
+
|
|
82
|
+
输出应包含匹配方案、适用场景、设备要求和仍需确认的工况问题;具体内容以查询结果为准。
|
|
83
|
+
|
|
84
|
+
#### 4. 页面关系、内容读取与生产链接
|
|
85
|
+
|
|
86
|
+
方案目录按显式关系组织,不把页面名称混用:Scenario 是业务落地页,Tech 是独立技术归属页,Reference Design(RD)是具体方案设计。Scenario 会关联 Tech 和 RD;RD 可继续关联架构图、产品说明和部署文档。只有 RD 存在有效部署映射和 preset 时,才可进入一键部署流程。
|
|
77
87
|
|
|
78
|
-
**非交互式多选安装示例**:
|
|
79
88
|
```bash
|
|
80
|
-
#
|
|
81
|
-
solution-cli
|
|
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
|
|
82
97
|
```
|
|
83
98
|
|
|
84
|
-
|
|
99
|
+
三种生产语言使用不同域名:英文 `www.seeed.cc`、中文 `www.seeedstudio.com.cn`、日文 `www.seeed.co.jp`。实际链接必须使用 `hub get --section links` 返回的地址;不要从 slug 拼接 Wiki、图片 CDN 或其他语言 URL。Wiki 是单独的已发布文档链接,Tech 页面也不能被当成 Wiki。翻译正文缺失时,保留可用的生产页并说明返回的内容语言。
|
|
85
100
|
|
|
86
|
-
|
|
101
|
+
返回链接或 metadata 不等于已经阅读页面内容。回答方案能力、架构或产品问题时,必须读取对应的 `description`、`architecture`、`products` section;确切落地页或架构图片影响答案时,打开 CLI 返回的确切地址并说明实际核验范围。相对图片路径只有在签名本地内容存在时才可读取,否则标为 source asset 未就绪。
|
|
87
102
|
|
|
88
|
-
|
|
103
|
+
RD 的部署映射只是目录信息,执行前还要读取本机 Engine 的实际配置:
|
|
89
104
|
|
|
90
|
-
|
|
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. 执行命令
|
|
91
120
|
|
|
92
|
-
#### 1. 执行命令
|
|
93
121
|
```bash
|
|
94
|
-
#
|
|
95
|
-
solution-cli
|
|
122
|
+
# 1. 查硬件配置参数(算力、电压、物理接口、外形尺寸)
|
|
123
|
+
solution-cli product query <family-id> --json
|
|
96
124
|
|
|
97
|
-
#
|
|
98
|
-
solution-cli
|
|
125
|
+
# 2. 查配件推荐与兼容性清单(区分必买配件、可选配件,防踩坑)
|
|
126
|
+
solution-cli product accessories <family-id> --json
|
|
99
127
|
```
|
|
100
128
|
|
|
101
|
-
####
|
|
102
|
-
运行该命令可产出 4 项关键资产:
|
|
103
|
-
1. **方案业务说明与技术架构**:解释为何适合在端侧运行、本地处理延迟、数据不出本地的隐私保障;
|
|
104
|
-
2. **静默商业闭环出口**:自动为该方案生成带有安全追踪标记(`utm_source=sensecraft_agent`)的官方落地页与开发 Wiki;
|
|
105
|
-
3. **官方开源仓库地址**:提供官方维护的 GitHub 源码仓库,为二次开发预留出口;
|
|
106
|
-
4. **现场工况诊断提问指引 (Diagnostic Playbook)**:直接给出当前场景下**必须向客户确认的 2~3 个核心工况问题**及其背后的技术决断理由。
|
|
129
|
+
#### 3. 它能为你产出什么(解决什么痛点)
|
|
107
130
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
(决断考量: 大棚内百米级可采用 RS485 总线;广域大田推荐 LoRaWAN 远距无线,配 SenseCAP M2 网关)
|
|
118
|
-
• 现场测点是否有 220V 市电供电,还是需要野外太阳能板/锂电池长续航供电?
|
|
119
|
-
(决断考量: 市电支持持续高频数据上报;无市电需选配支持休眠唤醒的超低功耗无线传感器)
|
|
120
|
-
• 需要监测哪些核心指标?仅空气温湿度,还是包括土壤剖面水肥墒情(水分/EC/pH)?
|
|
121
|
-
(决断考量: 决定是配置多合一微气象站,还是选配工业级土壤三参数探头与变送器)
|
|
122
|
-
```
|
|
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、数量建议与购买链接,方便直接采购下单。
|
|
123
140
|
|
|
124
|
-
|
|
141
|
+
### 场景三:方案一键部署与本地/远程运行 (Solution Deployment)
|
|
125
142
|
|
|
126
|
-
|
|
143
|
+
方案部署由签名 Rust Engine (`sensecraft-engine`) 驱动,支持**本地一键部署**与**远程边缘设备部署**。
|
|
127
144
|
|
|
128
|
-
|
|
145
|
+
#### 1. 读取部署规范与预设
|
|
129
146
|
|
|
130
|
-
#### 1. 执行命令
|
|
131
147
|
```bash
|
|
132
|
-
|
|
133
|
-
solution-cli product query recomputer_j40 --json
|
|
134
|
-
|
|
135
|
-
# 2. 评估该产品族所需的官方配件与兼容性
|
|
136
|
-
solution-cli product accessories recomputer_j40 --json
|
|
148
|
+
sensecraft-engine deploy-info <solution-id> --lang zh
|
|
137
149
|
```
|
|
138
150
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
{
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
"connector": "dc_jack_5.5x2.5",
|
|
155
|
-
"voltage_v": 19.0,
|
|
156
|
-
"min_current_a": 4.74,
|
|
157
|
-
"polarity": "center_positive"
|
|
158
|
-
},
|
|
159
|
-
"m2_slots": [
|
|
160
|
-
{"key": "M", "size": "2280", "interface": "PCIe Gen4 x4 NVMe"},
|
|
161
|
-
{"key": "E", "size": "2230", "interface": "WiFi/BT"}
|
|
162
|
-
]
|
|
163
|
-
},
|
|
164
|
-
"accessories": {
|
|
165
|
-
"required": [
|
|
166
|
-
{
|
|
167
|
-
"sku": "313080684",
|
|
168
|
-
"name": "19V 4.74A 电源适配器 (5.5x2.5mm)",
|
|
169
|
-
"category": "REQUIRED",
|
|
170
|
-
"compatibility": { "status": "VERIFIED" },
|
|
171
|
-
"url": "https://www.seeedstudio.com/Power-Adapter-19V-4-74A-p-5573.html?utm_source=sensecraft_agent..."
|
|
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"
|
|
172
166
|
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
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"
|
|
180
185
|
}
|
|
181
|
-
|
|
186
|
+
}
|
|
182
187
|
}
|
|
183
|
-
|
|
184
|
-
```
|
|
188
|
+
```
|
|
185
189
|
|
|
186
|
-
|
|
190
|
+
#### 3. 一行命令执行部署与状态追踪
|
|
187
191
|
|
|
188
|
-
|
|
192
|
+
```bash
|
|
193
|
+
# 1. 验证参数并启动部署
|
|
194
|
+
sensecraft-engine deploy --params ./.sensecraft-work/body.json --yes
|
|
189
195
|
|
|
190
|
-
|
|
196
|
+
# 2. 查询部署进度与容器日志
|
|
197
|
+
sensecraft-engine status <deployment-id> --json
|
|
198
|
+
sensecraft-engine logs <deployment-id>
|
|
199
|
+
```
|
|
191
200
|
|
|
192
|
-
|
|
193
|
-
系统支持**无需重新编译、无需重装整套系统**的零重启参数热修改:
|
|
194
|
-
1. **查询当前设备活跃部署**:
|
|
195
|
-
`GET http://<host>:5823/api/device-management/active`
|
|
196
|
-
2. **查询可修改参数**:
|
|
197
|
-
`GET http://<host>:5823/api/docker-devices/local/config/<solution_id>`
|
|
198
|
-
检查参数字段中的 `reconfigurable: true` 标记。
|
|
199
|
-
3. **提交热更新**:
|
|
200
|
-
`PUT http://<host>:5823/api/docker-devices/local/config/<solution_id>`
|
|
201
|
-
传入目标键值,容器环境无感热加载生效。
|
|
201
|
+
### 场景四:设备状态感知与参数热修改 (Device Management)
|
|
202
202
|
|
|
203
|
-
|
|
203
|
+
#### 1. 核心流程与接口
|
|
204
204
|
|
|
205
|
-
|
|
205
|
+
已部署设备的参数修改要先读取当前部署和可修改字段,确认目标和变更范围,再执行对应管理接口。能否热修改取决于方案返回的 `reconfigurable` 字段;不要假设所有参数都支持无重启修改。
|
|
206
206
|
|
|
207
|
-
|
|
207
|
+
### 场景五:自研模型替换与本地二次开发 (Secondary Dev)
|
|
208
208
|
|
|
209
209
|
#### 1. 开发闭环步骤
|
|
210
|
-
1. **克隆源码**:
|
|
211
|
-
从 `solution-cli hub search` 返回的 `repo_url` 将源码克隆到本地用户工作区:
|
|
212
|
-
```bash
|
|
213
|
-
git clone https://github.com/suharvest/sensecraft-solutions.git ./my-solutions
|
|
214
|
-
```
|
|
215
|
-
2. **端侧模型转换 (以 Jetson Orin 为例)**:
|
|
216
|
-
在设备上使用 TensorRT 将自定义 ONNX 导出为 Engine:
|
|
217
|
-
```bash
|
|
218
|
-
/usr/src/tensorrt/bin/trtexec --onnx=my_model.onnx --saveEngine=my_model.engine --fp16
|
|
219
|
-
```
|
|
220
|
-
3. **覆盖挂载配置**:
|
|
221
|
-
在方案目录创建 `docker-compose.override.yml` 将本地自研模型映射进容器中。
|
|
222
|
-
4. **驱动本地快速联调**:
|
|
223
|
-
使用 `--solutions-dir` 参数,强制底层引擎加载本地修改版方案,彻底不碰官方缓存:
|
|
224
|
-
```bash
|
|
225
|
-
sensecraft-engine deploy fall_detection --solutions-dir ./my-solutions/solutions
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
---
|
|
229
|
-
|
|
230
|
-
## 4. 双轨运行机制:在线直连与离线托底
|
|
231
|
-
|
|
232
|
-
为了保证在各类严苛现场环境下均能稳定运行,CLI 实现了智能双轨架构:
|
|
233
210
|
|
|
234
|
-
|
|
235
|
-
flowchart TD
|
|
236
|
-
RunCmd["用户 / Agent 触发 CLI 命令"] --> NetCheck{"检查网络与凭证"}
|
|
237
|
-
NetCheck -- "有外网且含烘焙配置" --> Typesense["直连 Seeed Typesense 云端搜索集群"]
|
|
238
|
-
Typesense -- "返回最新上线方案与配件" --> Done["输出 Catalog DTO"]
|
|
239
|
-
NetCheck -- "纯内网 / 无凭证 / 超时" --> LocalCore["无感降级: 读取 catalog/knowledge-core.json"]
|
|
240
|
-
LocalCore -- "331 KB 本地知识库 (18场景/39方案/119硬件)" --> Done
|
|
241
|
-
```
|
|
211
|
+
从查询结果中的官方仓库获取源码,在本地修改后按方案文档使用 `--solutions-dir` 进行测试。部署前展示修改和影响范围;不要把本地开发目录直接当作已验证的生产方案。
|
|
242
212
|
|
|
243
|
-
|
|
244
|
-
- 采用安全方案 B 在构建发布期烘焙了公开的只读 Search-Only 凭证;
|
|
245
|
-
- 自动直连 `https://rel-search.seeedstudio.com`,实时获取最新的方案、Wiki、案例及商城 SKU;
|
|
246
|
-
2. **离线安全托底 (Offline Resilience)**:
|
|
247
|
-
- 打包了全量预生成的 `catalog/knowledge-core.json`(331 KB);
|
|
248
|
-
- 在军工、内网、无公网或云端响应超过 2.5 秒时,**自动毫秒级无感降级到本地内核**,工况诊断、BOM 评估与离线部署 100% 正常可用。
|
|
213
|
+
## 4. 双轨运行机制:在线直连与离线托底
|
|
249
214
|
|
|
250
|
-
|
|
215
|
+
目录和产品查询优先使用在线资源;无法联网时使用已安装包中的本地内容和知识库。离线能力不代表所有在线方案或实时设备状态都可用。部署仍需目标设备可达、凭据有效、目标环境满足 `deploy-info` 和 `validate` 的要求。
|
|
251
216
|
|
|
252
217
|
## 5. 常见问题与环境自检 (Doctor)
|
|
253
218
|
|
|
254
219
|
### 1. 运行自检工具
|
|
255
|
-
|
|
220
|
+
|
|
256
221
|
```bash
|
|
257
|
-
solution-cli doctor
|
|
222
|
+
solution-cli doctor --json
|
|
258
223
|
```
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
- `Docker Daemon`: 确认 Docker 服务是否正常运行;
|
|
262
|
-
- `Serial / Dialout Permissions`: 确认串口访问权限;
|
|
263
|
-
- `SenseCraft Engine`: 确认底座引擎完整性与版本;
|
|
264
|
-
- `Ledger Integrity`: 校验技能安装账本状态。
|
|
224
|
+
|
|
225
|
+
重点查看操作系统、架构、Engine、PATH、串口权限、Docker 和 Skill ledger 的结果。远程设备的 SSH、sudo、Docker 安装和启动状态需按 `deploy-info`、`validate` 和设备返回信息单独确认;CLI 不会静默取得权限。
|
|
265
226
|
|
|
266
227
|
### 2. 状态查询
|
|
228
|
+
|
|
267
229
|
```bash
|
|
268
230
|
solution-cli status
|
|
269
231
|
```
|
|
270
|
-
实时查看当前 Engine 所在路径、安装版本、本地 Content 方案缓存数量以及各大 Agent 的配置状态。
|
|
271
232
|
|
|
272
|
-
|
|
273
|
-
|
|
233
|
+
查看 Engine 路径、版本、内容缓存和 Skill 挂载状态。
|
|
234
|
+
|
|
235
|
+
### 3. 网络与源排查
|
|
236
|
+
|
|
237
|
+
若遇到 npm 下载或同步延迟,可在命令中显式指定官方源:
|
|
274
238
|
```bash
|
|
275
|
-
solution-cli
|
|
239
|
+
npx -y --registry=https://registry.npmjs.org/ @seeed-studio/solution-cli install -y
|
|
276
240
|
```
|
|
277
|
-
|
|
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,21 +2,29 @@ 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
|
-
if (fs.existsSync(path.join(p1, '
|
|
19
|
-
if (fs.existsSync(path.join(p2, '
|
|
26
|
+
if (fs.existsSync(path.join(p1, 'solution-cli', 'SKILL.md'))) return p1;
|
|
27
|
+
if (fs.existsSync(path.join(p2, 'solution-cli', 'SKILL.md'))) return p2;
|
|
20
28
|
if (fs.existsSync(path.join(home, '.workbuddy'))) return p1;
|
|
21
29
|
if (fs.existsSync(path.join(home, '.workbody'))) return p2;
|
|
22
30
|
return p1;
|
|
@@ -36,8 +44,8 @@ export function getKnownAgents() {
|
|
|
36
44
|
// Honor existing installation first to avoid path drift (Codex Medium 13)
|
|
37
45
|
const pAgents = path.join(home, '.agents', 'skills');
|
|
38
46
|
const pCodex = path.join(home, '.codex', 'skills');
|
|
39
|
-
if (fs.existsSync(path.join(pAgents, '
|
|
40
|
-
if (fs.existsSync(path.join(pCodex, '
|
|
47
|
+
if (fs.existsSync(path.join(pAgents, 'solution-cli', 'SKILL.md'))) return pAgents;
|
|
48
|
+
if (fs.existsSync(path.join(pCodex, 'solution-cli', 'SKILL.md'))) return pCodex;
|
|
41
49
|
// Default to .agents/skills if .agents exists, otherwise .codex/skills if .codex exists
|
|
42
50
|
if (fs.existsSync(path.join(home, '.agents'))) return pAgents;
|
|
43
51
|
if (fs.existsSync(path.join(home, '.codex'))) return pCodex;
|
|
@@ -66,10 +74,28 @@ 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);
|
|
72
|
-
const installed = fs.existsSync(path.join(skillsDir, '
|
|
98
|
+
const installed = fs.existsSync(path.join(skillsDir, 'solution-cli', 'SKILL.md'));
|
|
73
99
|
return {
|
|
74
100
|
...a,
|
|
75
101
|
detected,
|
|
@@ -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
|
/**
|