Files
Cyrene/backend/pkg/plugins/datetime/plugin.go
T
AskaEth 71f0a1abdb feat: Go模块路径迁移 + Docker生产部署适配 + ethend Docker兼容
- 所有Go模块路径从 github.com/yourname/cyrene-ai 迁移到 git.yeij.top/AskaEth/Cyrene
- 5个Go Dockerfile添加 GOPROXY=https://goproxy.cn,direct 解决国内构建问题
- ai-core go.mod 添加 pkg/plugins replace 指令
- Caddyfile 简化为 http:// 通配 + handle 保留 /api 前缀
- ethend Dockerfile 适配 (npm install + 仅 COPY package.json)
- ethend 新增 RUNNING_IN_DOCKER 环境变量,健康检查改用Docker服务名
- ethend 数据库状态检查支持Docker hostname (postgres/redis/qdrant/minio)
- process-manager 新增 CONTAINER_SVC_MAP + Docker模式自动检测
- 统一 docker-compose.dev.db.yml 卷名 (pg_data/redis_data/qdrant_data/minio_data)
- docker-compose.yml ethend服务挂载docker.sock + 端口变量化
- 清理 .env 统一后的残留文件与提示信息

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-30 13:43:22 +08:00

171 lines
5.5 KiB
Go

package datetime
import (
"context"
"fmt"
"strings"
"time"
"git.yeij.top/AskaEth/Cyrene/pkg/plugins/sdk"
)
type DatetimePlugin struct{ sdk.BasePlugin }
func (p *DatetimePlugin) Metadata() sdk.PluginMetadata {
return sdk.PluginMetadata{
Name: "datetime", DisplayName: "Date & Time", Version: "1.0.0",
Description: "Date/time utilities: now, format, arithmetic, diff, timezone list",
Category: "utility", Author: sdk.PluginAuthor{Name: "Cyrene Team"},
}
}
func (p *DatetimePlugin) Tools() []sdk.Tool { return []sdk.Tool{&DatetimeTool{}} }
type DatetimeTool struct{ sdk.BaseTool }
func (t *DatetimeTool) Definition() sdk.ToolDefinition {
return sdk.ToolDefinition{
ID: "datetime", Name: "datetime", DisplayName: "Date & Time",
Description: "Date/time utility. Get current time, format dates, date arithmetic, date diff, list timezones.",
Category: "utility", Complexity: sdk.ComplexitySimple,
Parameters: map[string]interface{}{
"type": "object",
"properties": map[string]interface{}{
"action": map[string]interface{}{"type": "string", "enum": []string{"now", "format", "add", "diff", "timezone_list"}},
"format": map[string]interface{}{"type": "string"},
"timezone": map[string]interface{}{"type": "string"},
"date": map[string]interface{}{"type": "string"},
"duration": map[string]interface{}{"type": "string"},
"date2": map[string]interface{}{"type": "string"},
},
"required": []string{"action"},
},
}
}
func (t *DatetimeTool) Validate(args map[string]interface{}) error {
if _, ok := args["action"]; !ok {
return fmt.Errorf("missing required parameter: action")
}
return nil
}
func (t *DatetimeTool) Execute(_ context.Context, args map[string]interface{}) (*sdk.ToolResult, error) {
action, _ := args["action"].(string)
tzStr, _ := args["timezone"].(string)
loc, _ := parseLocation(tzStr)
now := time.Now().In(loc)
switch action {
case "now":
return &sdk.ToolResult{ToolName: "datetime", Success: true,
Output: fmt.Sprintf("Current time: %s (unix: %d, zone: %s)", now.Format(time.RFC3339), now.Unix(), loc.String())}, nil
case "format":
dateStr, _ := args["date"].(string)
format, _ := args["format"].(string)
if format == "" {
format = time.RFC3339
}
parsed, err := parseDate(dateStr, loc)
if err != nil {
return &sdk.ToolResult{ToolName: "datetime", Success: false, Error: err.Error()}, nil
}
return &sdk.ToolResult{ToolName: "datetime", Success: true,
Output: fmt.Sprintf("Formatted: %s", parsed.Format(format))}, nil
case "add":
dateStr, _ := args["date"].(string)
durStr, _ := args["duration"].(string)
base := now
if dateStr != "" {
var err error
base, err = parseDate(dateStr, loc)
if err != nil {
return &sdk.ToolResult{ToolName: "datetime", Success: false, Error: err.Error()}, nil
}
}
result, err := addDuration(base, durStr)
if err != nil {
return &sdk.ToolResult{ToolName: "datetime", Success: false, Error: err.Error()}, nil
}
return &sdk.ToolResult{ToolName: "datetime", Success: true,
Output: fmt.Sprintf("%s + %s = %s", base.Format(time.RFC3339), durStr, result.Format(time.RFC3339))}, nil
case "diff":
d1, _ := args["date"].(string)
d2, _ := args["date2"].(string)
t1, err := parseDate(d1, loc)
if err != nil {
return &sdk.ToolResult{ToolName: "datetime", Success: false, Error: err.Error()}, nil
}
t2, err := parseDate(d2, loc)
if err != nil {
return &sdk.ToolResult{ToolName: "datetime", Success: false, Error: err.Error()}, nil
}
diff := t2.Sub(t1)
if diff < 0 {
diff = -diff
}
days := int(diff.Hours()) / 24
hours := int(diff.Hours()) % 24
minutes := int(diff.Minutes()) % 60
seconds := int(diff.Seconds()) % 60
return &sdk.ToolResult{ToolName: "datetime", Success: true,
Output: fmt.Sprintf("Difference: %d days, %d hours, %d minutes, %d seconds", days, hours, minutes, seconds)}, nil
case "timezone_list":
return &sdk.ToolResult{ToolName: "datetime", Success: true,
Output: "Common timezones: UTC, Asia/Shanghai, Asia/Tokyo, Asia/Seoul, Asia/Singapore, Asia/Kolkata, Asia/Dubai, Europe/London, Europe/Paris, Europe/Moscow, America/New_York, America/Chicago, America/Los_Angeles, America/Sao_Paulo, Australia/Sydney, Pacific/Auckland, Africa/Cairo, Africa/Lagos"}, nil
default:
return &sdk.ToolResult{ToolName: "datetime", Success: false,
Error: fmt.Sprintf("unknown action: %s", action)}, nil
}
}
func parseLocation(tz string) (*time.Location, error) {
if tz == "" {
loc, err := time.LoadLocation("Asia/Shanghai")
if err != nil {
return time.UTC, nil
}
return loc, nil
}
return time.LoadLocation(tz)
}
func parseDate(s string, loc *time.Location) (time.Time, error) {
formats := []string{time.RFC3339, "2006-01-02T15:04:05", "2006-01-02 15:04:05", "2006-01-02", "2006/01/02"}
for _, f := range formats {
if t, err := time.ParseInLocation(f, s, loc); err == nil {
return t, nil
}
}
return time.Time{}, fmt.Errorf("cannot parse date: %s", s)
}
func addDuration(t time.Time, durStr string) (time.Time, error) {
durStr = strings.TrimSpace(durStr)
if durStr == "" {
return t, nil
}
// Handle months and years
if strings.Contains(durStr, "M") || strings.Contains(durStr, "y") {
months := 0
years := 0
if strings.Contains(durStr, "y") {
fmt.Sscanf(durStr, "%dy", &years)
}
if strings.Contains(durStr, "M") {
fmt.Sscanf(durStr, "%dM", &months)
}
return t.AddDate(years, months, 0), nil
}
d, err := time.ParseDuration(durStr)
if err != nil {
return t, fmt.Errorf("invalid duration: %s", durStr)
}
return t.Add(d), nil
}