27a497e397
- reminder_create 新增 platform/channel_type/channel_id/adapter_name 参数 - Gateway Reminder 模型 + DB 迁移 + CRUD 全部支持新字段 - 提醒到期时:群聊提醒 → platform-bridge 发回原群聊 - 非群聊提醒 → 走 Web 端推送 - Thinker 新增 PushPlatformMessage 方法 Co-Authored-By: Claude <noreply@anthropic.com>
130 lines
3.8 KiB
Go
130 lines
3.8 KiB
Go
package tools
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"time"
|
|
)
|
|
|
|
// GatewayClient is a lightweight HTTP client for calling Gateway internal APIs
|
|
// (reminders, schedules, etc.) from ai-core tools.
|
|
type GatewayClient struct {
|
|
baseURL string
|
|
internalToken string
|
|
httpClient *http.Client
|
|
}
|
|
|
|
// NewGatewayClient creates a new Gateway API client.
|
|
func NewGatewayClient(baseURL, internalToken string) *GatewayClient {
|
|
return &GatewayClient{
|
|
baseURL: baseURL,
|
|
internalToken: internalToken,
|
|
httpClient: &http.Client{Timeout: 10 * time.Second},
|
|
}
|
|
}
|
|
|
|
// Reminder represents a reminder from the Gateway API.
|
|
type Reminder struct {
|
|
ID string `json:"id"`
|
|
Title string `json:"title"`
|
|
Description string `json:"description"`
|
|
RemindAt string `json:"remind_at"`
|
|
Status string `json:"status"`
|
|
RepeatType string `json:"repeat_type"`
|
|
}
|
|
|
|
// CreateReminder calls POST /api/v1/internal/reminders on the Gateway.
|
|
func (c *GatewayClient) CreateReminder(ctx context.Context, userID, title, description, remindAt, repeatType, sessionID, platform, channelType, channelID, adapterName string) (*Reminder, error) {
|
|
body := map[string]interface{}{
|
|
"user_id": userID,
|
|
"title": title,
|
|
"description": description,
|
|
"remind_at": remindAt,
|
|
"repeat_type": repeatType,
|
|
"session_id": sessionID,
|
|
"platform": platform,
|
|
"channel_type": channelType,
|
|
"channel_id": channelID,
|
|
"adapter_name": adapterName,
|
|
}
|
|
reqBody, _ := json.Marshal(body)
|
|
|
|
req, err := http.NewRequestWithContext(ctx, "POST", c.baseURL+"/api/v1/internal/reminders", bytes.NewReader(reqBody))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
req.Header.Set("Content-Type", "application/json")
|
|
req.Header.Set("X-Internal-Token", c.internalToken)
|
|
|
|
resp, err := c.httpClient.Do(req)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("gateway request failed: %w", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode >= 400 {
|
|
bodyBytes, _ := io.ReadAll(resp.Body)
|
|
return nil, fmt.Errorf("gateway returned %d: %s", resp.StatusCode, string(bodyBytes))
|
|
}
|
|
|
|
var reminder Reminder
|
|
if err := json.NewDecoder(resp.Body).Decode(&reminder); err != nil {
|
|
return nil, fmt.Errorf("decode response: %w", err)
|
|
}
|
|
return &reminder, nil
|
|
}
|
|
|
|
// ListReminders calls GET /api/v1/internal/reminders on the Gateway.
|
|
func (c *GatewayClient) ListReminders(ctx context.Context, userID, status string, limit int) ([]Reminder, error) {
|
|
url := fmt.Sprintf("%s/api/v1/internal/reminders?user_id=%s&status=%s&limit=%d", c.baseURL, userID, status, limit)
|
|
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
req.Header.Set("X-Internal-Token", c.internalToken)
|
|
|
|
resp, err := c.httpClient.Do(req)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("gateway request failed: %w", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode >= 400 {
|
|
bodyBytes, _ := io.ReadAll(resp.Body)
|
|
return nil, fmt.Errorf("gateway returned %d: %s", resp.StatusCode, string(bodyBytes))
|
|
}
|
|
|
|
var result struct {
|
|
Reminders []Reminder
|
|
}
|
|
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
|
|
return nil, fmt.Errorf("decode response: %w", err)
|
|
}
|
|
return result.Reminders, nil
|
|
}
|
|
|
|
// DeleteReminder calls DELETE /api/v1/internal/reminders/:id on the Gateway.
|
|
func (c *GatewayClient) DeleteReminder(ctx context.Context, reminderID string) error {
|
|
req, err := http.NewRequestWithContext(ctx, "DELETE", c.baseURL+"/api/v1/internal/reminders/"+reminderID, nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
req.Header.Set("X-Internal-Token", c.internalToken)
|
|
|
|
resp, err := c.httpClient.Do(req)
|
|
if err != nil {
|
|
return fmt.Errorf("gateway request failed: %w", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode >= 400 {
|
|
bodyBytes, _ := io.ReadAll(resp.Body)
|
|
return fmt.Errorf("gateway returned %d: %s", resp.StatusCode, string(bodyBytes))
|
|
}
|
|
return nil
|
|
}
|