共享工程标准附录
本附录是案例集所有 7 个案例共同遵循的工程标准的集中参考。每个案例文档只在必要处做最小重复,完整字段表 / capability 列表 / 发布 checklist 等都指向本附录,避免在多处复制粘贴导致失同步。
阅读顺序提示:新读者建议先浏览本附录建立全局认知,再进入具体案例。已经有经验的读者可以按需跳转。
metadata.json / manifest.json Schema
NeoMind 生态有两类可发布工件——扩展(Rust cdylib + 可选 React 前端)与仪表板组件(纯 React,以 bundle.js 形式分发)。两类工件的元数据文件名不同:
- 扩展 →
metadata.json(源仓库extensions/<id>/metadata.json,构建脚本从Cargo.toml自动生成) - 组件 →
manifest.json(源仓库components/<id>/manifest.json,手写维护)
两份 schema 字段重合度很高,但扩展独有 builds / frontend / type,组件独有 size_constraints / has_* 系列 / default_config。下表合并展示,分组说明,每个字段标注来源。
基础信息
| 字段 | 类型 | 必填 | 说明 | 示例 |
|---|---|---|---|---|
id | string | 是 | 工件唯一标识,全生态唯一。扩展用 kebab-case(中划线,如 weather-forecast-v2),组件用 snake_case(下划线,如 ne101_camera) | weather-forecast-v2 / ne101_camera |
name | string | object | 是 | 展示名。组件支持 { "en": "...", "zh": "..." } 多语言对象 | "weather forecast" / { "en": "NE101 Camera Panel", "zh": "NE101 感知摄像头面板" } |
version | string (semver) | 是 | 三段语义化版本。扩展从 Cargo.toml 自动读取;组件手写 | "2.7.6" / "2.14.9" |
description | string | object | 是 | 一句话描述,组件支持多语言 | "Real-time weather forecast..." |
author | string | 是 | 作者或团队名 | "NeoMind Team" / "CamThink Team" |
license | string | 扩展必填 | SPDX 许可证标识 | "Apache-2.0" / "MIT" |
homepage | string (URL) | 否 | 源码或文档地址 | "https://github.com/camthink-ai/NeoMind-Extensions/tree/main/extensions/weather-forecast-v2" |
icon | string | 否(组件常用) | 图标标识,对应 NeoMind 图标库 | "Camera" |
类型与分类
| 字段 | 类型 | 必填 | 说明 | 示例 |
|---|---|---|---|---|
type | string | 扩展必填 | 工件类型。当前固定为 "native"(Rust cdylib);未来 WASM 类型会扩展 | "native" |
categories | string[] | 扩展可选 | 市场分类标签数组 | ["weather"] |
category | string | 组件可选 | 单一分类,组件用 | "device" |
构建产物(扩展独有)
builds 字段是扩展独有的,列出 5 个跨平台构建产物的下载 URL。每个 key 对应一个 Rust target triple,URL 指向 GitHub Release 资产。
{
"builds": {
"darwin-aarch64": { "url": "https://github.com/camthink-ai/NeoMind-Extensions/releases/download/v2.7.6/weather-forecast-v2-2.7.6-darwin_aarch64.nep" },
"darwin-x86_64": { "url": ".../weather-forecast-v2-2.7.6-darwin_x86_64.nep" },
"linux-x86_64": { "url": ".../weather-forecast-v2-2.7.6-linux_amd64.nep" },
"linux-aarch64": { "url": ".../weather-forecast-v2-2.7.6-linux_arm64.nep" },
"windows-x86_64": { "url": ".../weather-forecast-v2-2.7.6-windows_amd64.nep" }
}
}
完整的 5 个 target 说明见 跨平台构建目标矩阵。
前端声明(扩展独有)
扩展如带 React 前端,必须声明 frontend 对象:
| 字段 | 类型 | 必填 | 说明 | 示例 |
|---|---|---|---|---|
frontend.components | string[] | 是 | 组件名数组,纯字符串不是对象 | ["WeatherCard"] |
frontend.entrypoint | string | 是 | UMD 入口文件名,必须与 frontend.json 的 entrypoint 一致 | "weather-forecast-v2-components.umd.cjs" |
常见错误:把
components写成对象数组[{ "name": "WeatherCard", ... }]。市场解析器会拒绝。
组件专用字段(manifest.json 独有)
| 字段 | 类型 | 必填 | 说明 | 示例 |
|---|---|---|---|---|
size_constraints | object | 是 | 网格尺寸约束(单位:网格单元) | { "min_w": 2, "min_h": 2, "default_w": 3, "default_h": 3, "max_w": 6, "max_h": 6 } |
has_data_source | boolean | 是 | 是否支持数据源绑定(Data Source tab) | false |
has_device_binding | boolean | 是 | 是否支持设备绑定,影响 deviceContext prop 注入 | true |
device_type_filter | string[] | 否 | 限定可绑定的设备类型,空表示不限制 | ["ne101_camera"] |
has_display_config | boolean | 是 | 是否展示「显示配置」tab | false |
has_actions | boolean | 是 | 是否展示「操作」tab(按钮、命令) | false |
default_config | object | 是 | 默认配置对象,用户未自定义时使用 | 见下方代码块 |
global_name | string | 是 | bundle.js 挂载到 window 的全局变量名 | "NE101CameraPanel" |
export_name | string | 是 | IIFE 默认导出名,与 global_name 通常一致 | "NE101CameraPanel" |
max_data_sources | integer | 可选 | 当 has_data_source 为 true 时生效,限制可绑定数据源数量上限 | 12 |
default_config 示例(节选自 ne101_camera):
{
"default_config": {
"showMetrics": true,
"showCommands": true,
"location": "",
"displayTitle": "",
"processingEnabled": false,
"processingExtensionId": "",
"processingTemplate": "object_detection"
}
}
Capability 类目
NeoMind 通过显式 capability 申请实现扩展对平台能力的细粒度访问控制。扩展在代码中通过 CapabilityContext::invoke_capability(name, params) 调用平台能力;运行时会校验调用的 capability 是否在扩展声明的白名单内,未声明直接调用会 panic(非降级,强制开发者显式申请)。
完整 Capability 枚举
下表为 SDK ExtensionCapability 全部变体(来源:neomind-extension-sdk):
| Capability 标识 | 含义 | 典型使用扩展 |
|---|---|---|
device_metrics_read | 读取设备指标 | 仪表板类扩展 |
device_metrics_write | 写入设备指标(含虚拟指标) | weather-forecast-v2、所有 bridge 扩展 |
device_control | 向设备下发命令 | homeassistant-bridge、modbus-bridge |
storage_query | 查询时序存储 | 数据分析类扩展 |
event_publish | 发布事件 | 自动化触发类扩展 |
event_subscribe | 订阅事件 | 联动类扩展 |
telemetry_history | 查询设备遥测历史 | 历史趋势类扩展 |
metrics_aggregate | 聚合设备指标 | 报表类扩展 |
extension_call | 调用其他扩展 | 编排类扩展 |
agent_trigger | 触发 AI Agent | LLM 联动类扩展 |
rule_trigger | 触发自动化规则 | 自动化类扩展 |
device_template_register | 注册设备类型模板 | lorawan-bridge、modbus-bridge、onvif-bridge、bacnet-bridge、opcua-bridge、uink-rms-bridge |
device_register | 注册设备实例 | 所有 bridge 扩展 |
device_unregister | 注销设备实例 | bridge 扩展清理逻辑 |
Custom(String) | 自定义 capability | 项目 定制场景 |
实际代码中的使用模式
通过 grep 仓库源码统计,最常用的 capability 是 device_metrics_write(几乎所有 bridge 扩展都用来上报遥测)和 device_register / device_template_register(bridge 扩展注册外部设备到 NeoMind 设备模型)。典型调用模式:
use neomind_extension_sdk::capabilities::CapabilityContext;
use serde_json::json;
// 写入虚拟指标(最常用)
let _ = ctx.invoke_capability("device_metrics_write", &json!({
"device_id": "virtual-sensor-1",
"metric": "temperature",
"value": 25.5
}));
// 注册设备类型模板(bridge 扩展启动时)
let result = ctx.invoke_capability("device_template_register", &template_json);
// 注册设备实例
let result = ctx.invoke_capability("device_register", &device_json);
同步 vs 异步调用
- 异步上下文(如
execute_command):使用ctx.invoke_capability(name, params).await - 同步上下文(如
produce_metrics/handle_event):扩展内部封装invoke_capability_sync()方法,通过CapabilityContext::default()桥接
版本号三段一致性
NeoMind-Extensions 仓库有三个层级的版本号,发布时必须全部一致(除非有明确理由保持不同):
| 文件 | 版本含义 | 示例 |
|---|---|---|
VERSION | 市场发布版本(仓库级单一版本) | 2.7.0 |
extensions/index.json → version | 市场发布版本(与 VERSION 同步) | 2.7.0 |
extensions/*/Cargo.toml → version | 每个扩展自身版本(影响包文件名) | 2.7.0 |
extensions/*/metadata.json → version | 自动从 Cargo.toml 读取,不手写 | 2.7.0 |
常见错误
只更新了 VERSION 和 index.json, 但忘了更新各扩展的 Cargo.toml。后果:
- 包文件名是旧版本:
weather-forecast-v2-2.6.0-darwin_aarch64.nep - GitHub Release 标题是 v2.7.0,但里面的包都是 2.6.0
index.json的buildsURL 指向2.7.0的资产名,但实际文件名是2.6.0→ 404- 用户体验混乱,市场无法安装
正确流程
使用 ./scripts/update-versions.sh 一键同步:
# 完整更新:同步 Cargo.toml + VERSION + 生成 JSON(推荐)
./scripts/update-versions.sh 2.7.0 --bump-extensions
# 验证版本一致性(必须通过!)
./scripts/update-versions.sh 2.7.0 --check
跨平台构建目标矩阵
NeoMind 扩展支持 5 个 target(不是 6 个,没有 windows-aarch64):
| Target Key | Rust Target Triple | 产物后缀 | 用途 |
|---|---|---|---|
darwin-aarch64 | aarch64-apple-darwin | .dylib | Apple Silicon macOS(M1/M2/M3/M4) |
darwin-x86_64 | x86_64-apple-darwin | .dylib | Intel macOS |
linux-x86_64 | x86_64-unknown-linux-gnu | .so | 通用 Linux 服务器 |
linux-aarch64 | aarch64-unknown-linux-gnu | .so | ARM Linux(树莓派 4/5、ARM 服务器) |
windows-x86_64 | x86_64-pc-windows-msvc | .dll | Windows 10/11 |
构建命令
# 一次性构建全部 5 个 target 的 .nep 包
./build.sh --release 2.7.0
# 只构建单个扩展
./build.sh --single weather-forecast-v2 --release 2.7.0
build.sh 内部使用 cross(基于 Docker)或本地工具链交叉编译。开发者本地如已安装对应 target 的 Rust 工具链,可跳过 Docker 直接编译。
.nep 包结构
weather-forecast-v2-2.7.6-darwin_aarch64.nep (ZIP 格式)
├── manifest.json # 安装清单(从 metadata.json 转换)
├── binaries/
│ └── darwin_aarch64/
│ └── libneomind_extension_weather_forecast_v2.dylib
├── frontend/
│ └── weather-forecast-v2-components.umd.cjs
└── models/ # 可选:ONNX 模型
└── model.onnx
测试覆盖率与质量要求
NeoMind 生态对测试有明确要求,不达标的扩展不予发布。
扩展测试(Rust)
| 测试类型 | 位置 | 要求 | 参考 |
|---|---|---|---|
| 单元测试 | src/lib.rs 内 #[cfg(test)] mod tests | 至少覆盖核心命令的 happy path | weather-forecast-v2/src/lib.rs |
| 集成测试 | tests/ 目录 | 至少 1 个集成测试文件 | weather-forecast-v2/tests/ |
最小化示例:
// src/lib.rs
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_increment_command() {
let ext = MyExtension::new();
let result = ext.execute_command("increment", &json!({"amount": 5}))
.await
.unwrap();
assert_eq!(result["counter"], 5);
}
}