This repository has been archived on 2026-08-12. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
Cyrene/backend/pkg/plugins/iot_query/plugin.go
T
AskaEth 673ff752c5 feat: 插件-工具合并 — 创建 pkg/plugins 共享模块并移除 tool-engine
- 新增 backend/pkg/plugins/ 共享模块:SDK 接口、PluginManager、ToolRegistry(含环形缓冲区调用日志)
- 13 个通用插件从 plugin-manager 迁移至共享模块(import 路径统一)
- ai-core 切换至共享 ToolRegistry,进程内执行(零网络开销),包装 6 个专属工具
- plugin-manager 迁移至共享模块,保留管理 REST API
- 新增 DevTools 插件管理面板(侧边栏 → 🔌 插件管理)
- 移除 tool-engine 服务(从 go.work、DevTools 配置、编译系统)
- 工具调用记录 API 从 Tool-Engine 迁至 AI-Core(/api/v1/tools/calls)
- ai-core ContextStore 启动时从 PostgreSQL 恢复会话历史
- 清理所有过时引用和备份文件

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-25 20:52:39 +08:00

121 lines
3.7 KiB
Go

package iotquery
import (
"context"
"fmt"
"github.com/yourname/cyrene-ai/pkg/plugins/sdk"
)
// IoTClient is the interface for IoT device access.
type IoTClient interface {
GetAllDevices(ctx context.Context) ([]sdk.IoTDeviceState, error)
GetDevice(ctx context.Context, deviceID string) (*sdk.IoTDeviceState, error)
}
type IoTQueryPlugin struct {
sdk.BasePlugin
iotClient IoTClient
}
func NewIoTQueryPlugin(client IoTClient) *IoTQueryPlugin {
return &IoTQueryPlugin{iotClient: client}
}
func (p *IoTQueryPlugin) Metadata() sdk.PluginMetadata {
return sdk.PluginMetadata{
Name: "iot_query", DisplayName: "IoT Device Query", Version: "1.0.0",
Description: "Query smart home device status (single device or all devices)",
Category: "iot", Author: sdk.PluginAuthor{Name: "Cyrene Team"},
}
}
func (p *IoTQueryPlugin) Tools() []sdk.Tool { return []sdk.Tool{&IoTQueryTool{iotClient: p.iotClient}} }
type IoTQueryTool struct {
sdk.BaseTool
iotClient IoTClient
}
func (t *IoTQueryTool) Definition() sdk.ToolDefinition {
return sdk.ToolDefinition{
ID: "iot_query", Name: "iot_query", DisplayName: "IoT Device Query",
Description: "Query smart home device status. Device status is typically auto-injected; use this only when status is stale.",
Category: "iot", Complexity: sdk.ComplexitySimple,
Parameters: map[string]interface{}{
"type": "object",
"properties": map[string]interface{}{"device_id": map[string]interface{}{"type": "string"}},
},
}
}
func (t *IoTQueryTool) Validate(args map[string]interface{}) error { return nil }
func (t *IoTQueryTool) Execute(ctx context.Context, args map[string]interface{}) (*sdk.ToolResult, error) {
if t.iotClient == nil {
return &sdk.ToolResult{ToolName: "iot_query", Success: false, Error: "IoT client not configured"}, nil
}
deviceID, _ := args["device_id"].(string)
if deviceID != "" {
dev, err := t.iotClient.GetDevice(ctx, deviceID)
if err != nil {
return &sdk.ToolResult{ToolName: "iot_query", Success: false, Error: err.Error()}, nil
}
return &sdk.ToolResult{ToolName: "iot_query", Success: true, Output: formatDevice(dev)}, nil
}
devices, err := t.iotClient.GetAllDevices(ctx)
if err != nil {
return &sdk.ToolResult{ToolName: "iot_query", Success: false, Error: err.Error()}, nil
}
if len(devices) == 0 {
return &sdk.ToolResult{ToolName: "iot_query", Success: true, Output: "No devices found"}, nil
}
var out string
for _, d := range devices {
out += formatDeviceLine(&d) + "\n"
}
return &sdk.ToolResult{ToolName: "iot_query", Success: true, Output: out}, nil
}
func formatDevice(d *sdk.IoTDeviceState) string {
emoji := deviceEmoji(d.Type)
return fmt.Sprintf("%s %s (%s)\n Status: %s\n ID: %s", emoji, d.Name, d.Type, d.Status, d.ID)
}
func formatDeviceLine(d *sdk.IoTDeviceState) string {
emoji := deviceEmoji(d.Type)
switch d.Type {
case "light":
return fmt.Sprintf("%s %s: %s (brightness: %d, color: %s)", emoji, d.Name, d.Status, d.Brightness, d.Color)
case "ac":
return fmt.Sprintf("%s %s: %s (mode: %s, temp: %.1fC)", emoji, d.Name, d.Status, d.Mode, d.Temperature)
case "curtain":
return fmt.Sprintf("%s %s: %s (position: %d%%)", emoji, d.Name, d.Status, d.Position)
case "sensor":
return fmt.Sprintf("%s %s: %.1f%s", emoji, d.Name, d.Value, d.Unit)
case "lock":
return fmt.Sprintf("%s %s: %s (battery: %d%%)", emoji, d.Name, d.Status, d.Battery)
default:
return fmt.Sprintf("%s %s: %s", emoji, d.Name, d.Status)
}
}
func deviceEmoji(t string) string {
switch t {
case "light":
return "\U0001F4A1"
case "ac":
return "❄️"
case "curtain":
return "\U0001F3E0"
case "sensor":
return "\U0001F4CA"
case "lock":
return "\U0001F512"
default:
return "\U0001F4E6"
}
}