@seeed-studio/solution-cli 0.1.0 → 0.3.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 CHANGED
@@ -1,78 +1,131 @@
1
1
  # @seeed-studio/solution-cli
2
2
 
3
- Zero-friction installer and CLI runner for **SenseCraft Engine** and AI Agent Skills (Work Buddy, Claude Code, Codex, CodeBuddy).
3
+ Zero-friction installer, CLI suite, and AI Agent Skill for **SenseCraft Edge IoT Solutions & Hardware Ecosystem** (reComputer Jetson, reCamera, SenseCAP, Grove Vision AI, ESP32).
4
4
 
5
- ## Quick Start (One-line Execution)
5
+ Compatible with **Claude Code, Codex, Google Antigravity (AGY), Work Buddy, and CodeBuddy**.
6
6
 
7
- Install the engine and configure your AI Agent skills in one command:
7
+ > 📖 **专属完整使用指南**:如果您需要系统了解本 CLI 的独特使用场景、详细命令参数、多 Agent 宿主集成以及各阶段具体产出物,请直接查阅独立手册:[**SenseCraft Solution CLI 使用与集成全景指南 (docs/cli-guide.md)**](docs/cli-guide.md)。
8
8
 
9
- ```bash
10
- # Interactive mode (scans local agents and prompts for target selection)
11
- npx @seeed-studio/solution-cli install
12
-
13
- # Non-interactive mode for a specific agent (e.g. Work Buddy)
14
- npx @seeed-studio/solution-cli install --agent workbuddy
9
+ ---
15
10
 
16
- # Install to multiple agents non-interactively
17
- npx @seeed-studio/solution-cli install --agent workbuddy,claude -y
18
- ```
11
+ ## 1. Quick Start & Agent Installation
19
12
 
20
- Or install globally:
13
+ Install the underlying engine and configure the AI Agent Skill with a single command:
21
14
 
22
15
  ```bash
16
+ # Interactive mode (auto-scans local agent environments and prompts for selection)
17
+ npx @seeed-studio/solution-cli install
18
+
19
+ # Non-interactive mode (e.g. install to Claude Code and Antigravity)
20
+ npx @seeed-studio/solution-cli install --agent claude,antigravity -y
21
+
22
+ # Install globally
23
23
  npm install -g @seeed-studio/solution-cli
24
- solution-cli install
24
+ solution-cli install -y
25
25
  ```
26
26
 
27
- ---
28
-
29
- ## Features
27
+ ### Supported AI Agent Harnesses
28
+ - **Claude Code**: `~/.claude/skills/sensecraft`
29
+ - **Codex / OpenAI**: `~/.agents/skills/sensecraft` or `~/.codex/skills/sensecraft`
30
+ - **Google Antigravity (AGY)**: `~/.gemini/config/skills/sensecraft`
31
+ - **Work Buddy / Workbody**: `~/.workbuddy/skills/sensecraft`
32
+ - **CodeBuddy**: `~/.codebuddy/skills/sensecraft`
30
33
 
31
- 1. **Smart Environment Inspection & Reuse**:
32
- - Detects if you already have the SenseCraft Desktop App installed.
33
- - Reuses the App's built-in engine binary and bundled solution assets without re-downloading (~30 MB saved, <0.5s execution).
34
- - If no App exists, automatically downloads the standalone engine binary from Seeed CDN and verifies cryptographic SHA256 integrity.
34
+ ---
35
35
 
36
- 2. **Selective Agent Integration**:
37
- - Supports **Work Buddy / Workbody**, **Claude Code**, **Codex**, and **CodeBuddy**.
38
- - Interactive prompt lets you choose which agent(s) to adapt without touching unselected directories.
36
+ ## 2. CLI Command Reference
39
37
 
40
- 3. **Deterministic Absolute Path Execution**:
41
- - Injects explicit, verified binary paths directly into `SKILL.md`, ensuring that desktop Agent GUI processes can invoke `sensecraft-engine` even if shell `$PATH` is not inherited.
38
+ The `solution-cli` provides unified commands for discovery, BOM calculation, device diagnostics, and engine execution:
42
39
 
43
- 4. **Installation Ledger & Clean Lifecycle**:
44
- - Tracks all installed files in `~/.sensecraft/skills-ledger.json`.
45
- - Prevents overwriting user modifications.
46
- - Supports clean uninstallation via `solution-cli uninstall`.
40
+ | Command | Description |
41
+ |---|---|
42
+ | `solution-cli hub search "<query>" [--json] [--limit N]` | Search scenarios & reference designs. Connects to live Typesense cloud or seamlessly falls back to bundled catalog. Returns diagnostic playbooks & UTM landing URLs. |
43
+ | `solution-cli product query <family_id> [--json]` | Query hardware family default SKUs, region variants, and physical specs. |
44
+ | `solution-cli product accessories <family_id> [--sku <sku>] [--json]` | Evaluate required vs. optional accessories with strict physical compatibility checks (power, RF antenna, M.2 slots). |
45
+ | `solution-cli install [--agent <agents>] [-y]` | Inspect host environment, download/verify engine, and install Agent skills. |
46
+ | `solution-cli status` | Inspect installed engine binary, content cache, and configured agent skills. |
47
+ | `solution-cli doctor` | Run pre-flight diagnostics (OS, Docker daemon, serial permissions, PATH, ledger). |
48
+ | `solution-cli uninstall [--agent <agents>]` | Cleanly remove SenseCraft skills using the installation ledger. |
49
+ | `sensecraft-engine <subcommand>` | Direct proxy to the underlying high-performance Rust execution engine. |
47
50
 
48
51
  ---
49
52
 
50
- ## Command Reference
53
+ ## 3. How the AI Agent Uses the Skill
51
54
 
52
- | Command | Description |
53
- |---|---|
54
- | `solution-cli install` | Inspect environment, verify/download engine, and configure Agent skills |
55
- | `solution-cli status` | Display current engine binary, solution cache, and installed skills |
56
- | `solution-cli doctor` | Diagnose environment (OS, Docker, serial permissions, PATH, ledger) |
57
- | `solution-cli uninstall` | Cleanly remove SenseCraft skills from specified agent(s) |
58
- | `sensecraft-engine <cmd>` | Direct proxy to the underlying Rust engine CLI |
55
+ Once installed, your AI Agent gains deep domain knowledge as an Edge IoT Solution Architect. The skill operates across a **4-tier progressive disclosure lifecycle**:
59
56
 
60
- ---
57
+ ```
58
+ [ Tier 1: 方案咨询与工况诊断 ]
59
+ Agent 讲透方案业务价值与边缘推理机制 ➔ 依据领域诊断知识库提出 2~3 个关键工况问题 ➔ 给出带静默 UTM 的落地页与源码出口
60
+ │
61
+ ▼
62
+ [ Tier 2: 硬件选型与配件 BOM 校验 ]
63
+ 运行配件评估引擎 ➔ 严格区分【必需配件】(电源适配器) 与【可选配件】(安装支架/天线) ➔ 规避物理插头/电压/引脚不兼容
64
+ │
65
+ ▼
66
+ [ Tier 3: 设备管理与在线参数修改 ]
67
+ 查询活跃部署 ➔ 读取 reconfigurable: true 字段 ➔ 零重装无损热更新 (如在线修改 MQTT Broker 地址或检测阈值)
68
+ │
69
+ ▼
70
+ [ Tier 4: 本地二次开发与自研模型 ]
71
+ 获取官方 GitHub 仓库 ➔ 引导本地代码克隆与模型转换 (trtexec / TensorRT) ➔ 通过 --solutions-dir 驱动本地开发联调闭环
72
+ ```
61
73
 
62
- ## AI Agent Usage Example
74
+ ### 常见自然语言对话范例
75
+
76
+ #### 范例 1:方案咨询与工况诊断 (Discovery & Diagnosis)
77
+ > **用户**:“我们打算在养老社区做老人跌倒检测,有什么成熟方案推荐吗?”
78
+ >
79
+ > **Agent**:
80
+ > 1. 调用 `solution-cli hub search "养老" --json`;
81
+ > 2. 详细解释 `fall_detection` 方案的端侧姿态估计与逐人时序状态机机制(1.4s 本地低延迟、视频不出本地保护隐私);
82
+ > 3. 自然给出官方方案落地页与 GitHub 源码地址(携带静默 UTM 跟踪);
83
+ > 4. **主动发起工况诊断黄金三问**:
84
+ > - 房间是同一栋楼集中分布(推荐 1 台 Orin 主机拉多路 RTSP 流摊薄成本)还是分散独栋(推荐每间房独立一体机)?
85
+ > - 现场是否已有支持 RTSP 协议的海康/大华存量摄像头(直接利旧节省采购成本)?
86
+ > - 卫生间/卧房私密空间是否对纯光学摄像头有顾虑(可选用 60GHz 毫米波雷达替代)?
87
+
88
+ #### 范例 2:硬件选型与配件兼容性校验 (BOM & Compatibility)
89
+ > **用户**:“选好了,我要买一台 reComputer J4012,帮我看看需要配哪些配件?”
90
+ >
91
+ > **Agent**:
92
+ > 1. 调用 `solution-cli product accessories recomputer_j40 --json`;
93
+ > 2. 明确区分:
94
+ > - **必需配件**:19V 4.74A DC Jack (5.5x2.5mm) 电源适配器(严禁配 12V 否则无法开机);
95
+ > - **可选配件**:NVMe M.2 2280 SSD(Key-M)、双频 Wi-Fi/BT 模组(Key-E 插槽)与匹配的 SMA 天线;
96
+ > 3. 提供官方 SKU 与带 UTM 标记的购买链接,杜绝编造第三方型号。
97
+
98
+ #### 范例 3:在线参数热修改 (Device Management)
99
+ > **用户**:“我已经部署完设备了,现在想把告警的 MQTT 服务器地址改成本地的 192.168.1.50,怎么弄?”
100
+ >
101
+ > **Agent**:
102
+ > 1. 查询当前应用的可配置参数;
103
+ > 2. 确认 `mqtt_broker` 属于 `reconfigurable: true` 字段;
104
+ > 3. 直接通过管理接口发起更新,提示用户无需重启容器或重装整个系统,参数热生效。
105
+
106
+ #### 范例 4:二次开发与自研模型替换 (Secondary Dev)
107
+ > **用户**:“我想改一下后处理检测逻辑,换成我们自己的 YOLOv11 跌倒模型,源码在哪里?”
108
+ >
109
+ > **Agent**:
110
+ > 1. 提供方案对应的官方 GitHub 开源仓库地址;
111
+ > 2. 指导用户克隆到本地工作区;
112
+ > 3. 指导通过 TensorRT `trtexec` 完成端侧引擎转换,并在 `docker-compose.override.yml` 中挂载自定义模型;
113
+ > 4. 使用 `sensecraft-engine deploy --solutions-dir ./solutions` 进行本地快速调测。
63
114
 
64
- Once installed, open Work Buddy, Claude Code, or Codex and say:
115
+ ---
65
116
 
66
- > "帮我把边缘安全方案 (edge_security) 部署到我的 Jetson 设备 (IP: 192.168.1.120,用户名 harvest)"
117
+ ## 4. 技术架构亮点
67
118
 
68
- The Agent will automatically:
69
- 1. Match the `sensecraft` Skill;
70
- 2. Query solution parameters via `sensecraft-engine deploy-info edge_security --lang zh`;
71
- 3. Generate or fill in required parameters;
72
- 4. Execute deployment and stream real-time progress via `sensecraft-engine deploy ...`.
119
+ 1. **双轨检索与开箱即用 (Out-of-the-Box)**:
120
+ - 内置 323 KB 离线核心清单(18 场景、39 参考设计、119 硬件族),无网断网 100% 可用;
121
+ - 线上发布版内置只读搜索凭据,联网时自动直连 Typesense 云端集群获取实时更新。
122
+ 2. **静默商业闭环 (Silent Attribution)**:
123
+ - 所有落地页、Wiki、商城 SKU 与配件链接均经安全工具注入 `utm_source=sensecraft_agent`,对话自然融入,杜绝生硬广告。
124
+ 3. **物理规格防呆保护**:
125
+ - 内置电源接口(DC 5.5x2.5 vs 5.5x2.1)、极性(中心正极)、电压(19V vs 12V)、M.2 Key-M/Key-E 及 RF 射频天线接头校验,从源头杜绝硬件烧板与返工风险。
73
126
 
74
127
  ---
75
128
 
76
- ## License
129
+ ## 5. 开源协议
77
130
 
78
131
  Apache-2.0 © Seeed Studio
package/bin/cli.js CHANGED
@@ -4,6 +4,8 @@ import path from 'node:path';
4
4
  import { fileURLToPath } from 'node:url';
5
5
  import { runInstall, runStatus, runUninstall } from '../lib/installer.js';
6
6
  import { runDoctor } from '../lib/doctor.js';
7
+ import { searchHub, queryProductFamily, queryAccessories, createDeploymentLockfile } from '../lib/knowledge.js';
8
+ import { assertCompatibility } from '../lib/compatibility.js';
7
9
 
8
10
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
11
  const pkg = JSON.parse(fs.readFileSync(path.resolve(__dirname, '../package.json'), 'utf8'));
@@ -25,6 +27,14 @@ Commands:
25
27
  status Display current engine, solution content, and agent skills status
26
28
  doctor Diagnose environment (platform, permissions, docker, PATH, ledger)
27
29
  uninstall Cleanly remove SenseCraft skills from specified agent(s)
30
+ hub Search scenarios and reference designs from Seeed Solution Hub
31
+ Usage: solution-cli hub search <keyword> [--limit 5] [--locale zh|en] [--json]
32
+ product Query product families, SKUs, and verified accessories
33
+ Usage: solution-cli product query <family_id> [--locale zh|en] [--json]
34
+ solution-cli product accessories <family_id> [--sku <sku>] [--json]
35
+ solution-cli product verify-compatibility --host <family_id> [--json]
36
+ lockfile Create an immutable DeploymentLockfile to isolate deployment execution
37
+ Usage: solution-cli lockfile create --solution <id> [--version <v>] [--hardware <fams>] [--json]
28
38
  help Show this help message
29
39
 
30
40
  Options:
@@ -33,13 +43,16 @@ Options:
33
43
  --dry-run Simulate operations without making changes to filesystem
34
44
  --skip-content Skip pulling IoT solution packages from CDN
35
45
  --force Force re-download or re-link even if already installed
36
- --json Output machine-readable JSON (supported by status and doctor)
46
+ --json Output machine-readable JSON (supported by all query/diagnostic commands)
47
+ --locale <zh|en> Language for hub and product results (default: zh)
48
+ --limit <num> Maximum results for search (default: 5)
37
49
  --engine-path <path> Use custom engine executable path
38
50
 
39
51
  Examples:
40
52
  npx @seeed-studio/solution-cli install
41
- npx @seeed-studio/solution-cli install --agent workbuddy
42
- npx @seeed-studio/solution-cli install --agent workbuddy,claude -y
53
+ solution-cli hub search "跌倒"
54
+ solution-cli product accessories recomputer_j40
55
+ solution-cli product query sensecap_watcher --json
43
56
  solution-cli status
44
57
  solution-cli doctor
45
58
  `);
@@ -53,7 +66,15 @@ function parseFlags(rawArgs) {
53
66
  skipContent: false,
54
67
  force: false,
55
68
  json: false,
56
- enginePath: null
69
+ enginePath: null,
70
+ limit: 5,
71
+ locale: 'zh',
72
+ sku: null,
73
+ host: null,
74
+ accessory: null,
75
+ solution: null,
76
+ version: '1.0.0',
77
+ hardware: null,
57
78
  };
58
79
 
59
80
  for (let i = 0; i < rawArgs.length; i++) {
@@ -74,6 +95,22 @@ function parseFlags(rawArgs) {
74
95
  flags.json = true;
75
96
  } else if (a === '--engine-path' && rawArgs[i + 1]) {
76
97
  flags.enginePath = rawArgs[++i];
98
+ } else if (a === '--limit' && rawArgs[i + 1]) {
99
+ flags.limit = parseInt(rawArgs[++i], 10) || 5;
100
+ } else if (a === '--locale' && rawArgs[i + 1]) {
101
+ flags.locale = rawArgs[++i];
102
+ } else if (a === '--sku' && rawArgs[i + 1]) {
103
+ flags.sku = rawArgs[++i];
104
+ } else if (a === '--host' && rawArgs[i + 1]) {
105
+ flags.host = rawArgs[++i];
106
+ } else if (a === '--accessory' && rawArgs[i + 1]) {
107
+ flags.accessory = rawArgs[++i];
108
+ } else if (a === '--solution' && rawArgs[i + 1]) {
109
+ flags.solution = rawArgs[++i];
110
+ } else if (a === '--version' && rawArgs[i + 1]) {
111
+ flags.version = rawArgs[++i];
112
+ } else if (a === '--hardware' && rawArgs[i + 1]) {
113
+ flags.hardware = rawArgs[++i];
77
114
  }
78
115
  }
79
116
 
@@ -123,6 +160,166 @@ async function main() {
123
160
  runUninstall(flags);
124
161
  break;
125
162
 
163
+ case 'hub': {
164
+ const sub = args[1] || 'search';
165
+ if (sub !== 'search') {
166
+ console.error(`Unknown hub action "${sub}". Supported: "solution-cli hub search <keyword>"`);
167
+ process.exit(1);
168
+ }
169
+ const query = args.slice(2).filter((a) => !a.startsWith('-')).join(' ');
170
+ const dto = await searchHub({ query, locale: flags.locale, limit: flags.limit });
171
+ if (flags.json) {
172
+ console.log(JSON.stringify(dto, null, 2));
173
+ } else {
174
+ console.log(`\n🔍 Solutions Hub Search Results for "${query}" (${dto.source}):\n`);
175
+ if (dto.records.length === 0) {
176
+ console.log(' No matching scenarios or reference designs found.');
177
+ } else {
178
+ dto.records.forEach((r, idx) => {
179
+ const tag = r.type === 'scenario' ? '\x1b[36m[Scenario]\x1b[0m' : '\x1b[35m[Reference Design]\x1b[0m';
180
+ console.log(` ${idx + 1}. ${tag} \x1b[1m${r.title}\x1b[0m (${r.id})`);
181
+ if (r.summary) console.log(` ${r.summary}`);
182
+ if (r.reference_designs?.length) console.log(` 对应参考设计: ${r.reference_designs.join(', ')}`);
183
+ if (r.family_ids?.length) console.log(` 推荐硬件族: ${r.family_ids.join(', ')}`);
184
+ if (r.presets?.length) console.log(` 预设模式: ${r.presets.join(', ')}`);
185
+ if (r.wiki_url) console.log(` 开发 Wiki: ${r.wiki_url}`);
186
+ if (r.diagnostic_playbook?.questions?.length) {
187
+ console.log(' 现场工况诊断提问指引:');
188
+ r.diagnostic_playbook.questions.forEach((q) => {
189
+ console.log(` • ${q.question} \x1b[90m(决断考量: ${q.rationale})\x1b[0m`);
190
+ });
191
+ }
192
+ console.log('');
193
+ });
194
+ }
195
+ if (dto.warnings.length) {
196
+ dto.warnings.forEach((w) => console.log(`\x1b[33mNote:\x1b[0m ${w}`));
197
+ }
198
+ }
199
+ break;
200
+ }
201
+
202
+ case 'product': {
203
+ const sub = args[1] || 'query';
204
+ const familyId = args.slice(2).find((a) => !a.startsWith('-')) || flags.host;
205
+
206
+ if (sub === 'query') {
207
+ if (!familyId) {
208
+ console.error('Please specify a product family ID (e.g. "solution-cli product query recomputer_j40")');
209
+ process.exit(1);
210
+ }
211
+ const dto = queryProductFamily(familyId, { locale: flags.locale });
212
+ if (flags.json) {
213
+ console.log(JSON.stringify(dto, null, 2));
214
+ } else {
215
+ const fam = dto.records[0];
216
+ if (!fam) {
217
+ console.log(`Product family "${familyId}" not found.`);
218
+ } else {
219
+ console.log(`\n📦 Product Family: \x1b[1m${fam.title}\x1b[0m (${fam.family_id})`);
220
+ console.log(` Default SKU: ${fam.default_sku || 'N/A'}`);
221
+ console.log(` Regions: ${(fam.regions || []).join(', ') || 'Global'}`);
222
+ console.log(` SKUs Available: ${fam.skus_count}`);
223
+ if (fam.physical_spec?.power_input) {
224
+ const p = fam.physical_spec.power_input;
225
+ console.log(` Power Spec: ${p.voltage_v || ''}V ${p.min_current_a || ''}A (${p.connector}) ${p.polarity || ''}`);
226
+ }
227
+ console.log(` Required Accessories: ${fam.required_accessories_count}`);
228
+ console.log(` Optional Accessories: ${fam.optional_accessories_count}`);
229
+ }
230
+ }
231
+ } else if (sub === 'accessories') {
232
+ if (!familyId) {
233
+ console.error('Please specify a product family ID (e.g. "solution-cli product accessories recomputer_j40")');
234
+ process.exit(1);
235
+ }
236
+ const dto = queryAccessories(familyId, { sku: flags.sku, locale: flags.locale });
237
+ if (flags.json) {
238
+ console.log(JSON.stringify(dto, null, 2));
239
+ } else {
240
+ const record = dto.records[0];
241
+ if (!record) {
242
+ console.log(`Product family "${familyId}" not found.`);
243
+ } else {
244
+ console.log(`\n📦 Verified Accessories for \x1b[1m${record.host_title}\x1b[0m (${record.family_id}):`);
245
+ console.log(` Host Default SKU: ${record.host_sku}`);
246
+ if (record.physical_spec?.power_input) {
247
+ const p = record.physical_spec.power_input;
248
+ console.log(` Host Power Spec: ${p.voltage_v || ''}V ${p.min_current_a || ''}A (${p.connector || ''})`);
249
+ }
250
+
251
+ console.log('\n \x1b[33m[REQUIRED (必需配件)]\x1b[0m');
252
+ if (record.accessories.required.length === 0) {
253
+ console.log(' (无强制单独采购的配件)');
254
+ } else {
255
+ record.accessories.required.forEach((acc) => {
256
+ const stat = acc.compatibility.is_compatible ? '\x1b[32m✔\x1b[0m' : '\x1b[31m✖\x1b[0m';
257
+ console.log(` ${stat} \x1b[1m${acc.name}\x1b[0m (SKU: ${acc.sku || 'N/A'}, Qty: ${acc.qty})`);
258
+ if (acc.reason) console.log(` 原因: ${acc.reason}`);
259
+ if (acc.url) console.log(` 购买链接: ${acc.url}`);
260
+ });
261
+ }
262
+
263
+ console.log('\n \x1b[36m[OPTIONAL (推荐选配)]\x1b[0m');
264
+ if (record.accessories.optional.length === 0) {
265
+ console.log(' (无选配项)');
266
+ } else {
267
+ record.accessories.optional.slice(0, 10).forEach((acc) => {
268
+ const stat = acc.compatibility.is_compatible ? '\x1b[32m✔\x1b[0m' : '\x1b[31m✖\x1b[0m';
269
+ console.log(` ${stat} ${acc.name} (SKU: ${acc.sku || 'N/A'})`);
270
+ if (acc.url) console.log(` 购买链接: ${acc.url}`);
271
+ });
272
+ }
273
+ console.log('');
274
+ }
275
+ }
276
+ } else if (sub === 'verify-compatibility') {
277
+ const comp = assertCompatibility(null, {
278
+ id: flags.accessory || 'custom_accessory',
279
+ name: flags.accessory || 'Custom Accessory',
280
+ });
281
+ if (flags.json) {
282
+ console.log(JSON.stringify(comp, null, 2));
283
+ } else {
284
+ const sym = comp.isCompatible ? '\x1b[32m✔\x1b[0m' : '\x1b[31m✖\x1b[0m';
285
+ console.log(`\n${sym} Physical Compatibility Status: ${comp.status}\n`);
286
+ comp.dimensions.forEach((d) => {
287
+ console.log(` - [${d.dimension}] ${d.status}: ${d.reason}`);
288
+ });
289
+ console.log('');
290
+ }
291
+ } else {
292
+ console.error(`Unknown product action "${sub}". Supported: query, accessories, verify-compatibility`);
293
+ process.exit(1);
294
+ }
295
+ break;
296
+ }
297
+
298
+ case 'lockfile': {
299
+ const sub = args[1] || 'create';
300
+ if (sub !== 'create') {
301
+ console.error(`Unknown lockfile action "${sub}". Supported: "solution-cli lockfile create"`);
302
+ process.exit(1);
303
+ }
304
+ const solutionId = flags.solution || 'unspecified_solution';
305
+ const hardware = (flags.hardware || '').split(',').map((h) => h.trim()).filter(Boolean);
306
+ const lockfile = createDeploymentLockfile({
307
+ solutionId,
308
+ solutionVersion: flags.version,
309
+ selectedHardware: hardware,
310
+ });
311
+ if (flags.json) {
312
+ console.log(JSON.stringify(lockfile, null, 2));
313
+ } else {
314
+ console.log('\n🔒 Generated DeploymentLockfile:');
315
+ console.log(` Solution: ${lockfile.solution_id}@${lockfile.solution_version}`);
316
+ console.log(` Dataset: ${lockfile.dataset_version}`);
317
+ console.log(` Network Isolation: Commercial queries DENIED during apply`);
318
+ console.log(` Selected Hardware: ${lockfile.selected_hardware.join(', ') || 'Local Host'}\n`);
319
+ }
320
+ break;
321
+ }
322
+
126
323
  default:
127
324
  console.error(`Unknown command: "${command}". Run "solution-cli help" for usage.`);
128
325
  process.exit(1);
@@ -0,0 +1,10 @@
1
+ {
2
+ "$schema": "https://spec.seeedstudio.com/schemas/v2/client-config.json",
3
+ "baked_at": "2026-10-13T09:54:46.940Z",
4
+ "typesense": {
5
+ "host": "https://rel-search.seeedstudio.com",
6
+ "search_key_solution": "dNsKBp0Pepdz9tvyIY1O92EMOM00XCHv",
7
+ "search_key_reference_design": "rEy4VhZnqEmrduFG2e8uvfWMz5ZzXhjb",
8
+ "search_key_purchase_profile": "YrowCXcDOGTt9KedslTEmeY0ZJEhlBml"
9
+ }
10
+ }