签到检查功能增强:返回签到时间和内容
问题: - 用户询问'我什么时候签到的'时,AI 说'系统只记录是否签到,没有时间戳' - 实际上数据库 signs 表有完整的 sign_time 和 sign_text 字段 解决方案: - 修改 executeCheck 方法,改用 ListSigns 查询今天的签到记录 - 返回完整的签到详情:签到时间(HH:MM:SS格式)+ 签到内容 - 未签到时仍返回简单提示 改动内容: - executeCheck 使用 ListSigns 替代 HasSignedOnDay - 构建 ListOptions 查询今天的签到记录(过滤 NodeID + 时间范围) - 返回格式:'XXX 今天已经签到过了。\n签到时间:10:30:45\n签到内容:上海-Kevin-GAT562签到' - 更新测试验证返回内容包含时间和签到文本 - 更新 mockSignStore.ListSigns 支持 NodeID 和 Limit 过滤 使用效果: - 用户:'我今天签到了吗?' → 返回是否签到 + 时间 + 内容 - 用户:'我什么时候签到的?' → 返回签到时间:10:30:45 测试: - ✅ 未签到场景测试通过 - ✅ 已签到场景测试通过(验证时间和内容) - ✅ 所有签到工具测试通过 - ✅ 项目编译成功 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -32,9 +32,9 @@
|
|||||||
### 3. 检查操作 (action=check) **新增**
|
### 3. 检查操作 (action=check) **新增**
|
||||||
|
|
||||||
检查当前节点今天是否已签到:
|
检查当前节点今天是否已签到:
|
||||||
- 用于回答"我今天签到了吗"之类的问题
|
- 用于回答"我今天签到了吗"、"我什么时候签到的"之类的问题
|
||||||
- 直接查询数据库,不依赖对话历史
|
- 直接查询数据库,不依赖对话历史
|
||||||
- 返回明确的已签到/未签到状态
|
- 返回明确的签到状态,**包括签到时间和签到内容**
|
||||||
|
|
||||||
## 修改内容
|
## 修改内容
|
||||||
|
|
||||||
@@ -102,15 +102,21 @@ AI 调用:
|
|||||||
```
|
```
|
||||||
|
|
||||||
返回(未签到):
|
返回(未签到):
|
||||||
```
|
```text
|
||||||
Test Node 今天还没有签到。
|
Test Node 今天还没有签到。
|
||||||
```
|
```
|
||||||
|
|
||||||
返回(已签到):
|
返回(已签到):
|
||||||
```
|
```text
|
||||||
Test Node 今天已经签到过了。
|
Test Node 今天已经签到过了。
|
||||||
|
签到时间:10:30:45
|
||||||
|
签到内容:上海闵行-Kevin-GAT562签到
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**用户**:"我什么时候签到的?"
|
||||||
|
|
||||||
|
AI 同样调用 check 操作,返回包含签到时间和内容的完整信息。
|
||||||
|
|
||||||
#### 查询今天的签到情况
|
#### 查询今天的签到情况
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ func (t *Tool) executeSign(ctx context.Context, params signParams, runtime agent
|
|||||||
return fmt.Sprintf("签到成功!%s\n签到内容:%s", displayName(node), record.SignText), nil
|
return fmt.Sprintf("签到成功!%s\n签到内容:%s", displayName(node), record.SignText), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// executeCheck 检查当前节点今天是否已签到
|
// executeCheck 检查当前节点今天是否已签到,并返回签到详情
|
||||||
func (t *Tool) executeCheck(ctx context.Context, params signParams, runtime agenttool.Runtime) (string, error) {
|
func (t *Tool) executeCheck(ctx context.Context, params signParams, runtime agenttool.Runtime) (string, error) {
|
||||||
// 节点身份来自消息上下文
|
// 节点身份来自消息上下文
|
||||||
node, ok := agenttool.NodeContextFromContext(ctx)
|
node, ok := agenttool.NodeContextFromContext(ctx)
|
||||||
@@ -192,18 +192,38 @@ func (t *Tool) executeCheck(ctx context.Context, params signParams, runtime agen
|
|||||||
now = time.Now()
|
now = time.Now()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询数据库检查今天是否已签到
|
// 构建查询选项:查询今天的签到记录
|
||||||
signed, err := t.store.HasSignedOnDay(node.NodeID, now)
|
loc := now.Location()
|
||||||
if err != nil {
|
if loc == nil {
|
||||||
return "", fmt.Errorf("检查签到状态失败:%w", err)
|
loc = time.Local
|
||||||
|
}
|
||||||
|
start := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, loc)
|
||||||
|
end := start.AddDate(0, 0, 1)
|
||||||
|
|
||||||
|
opts := storepkg.ListOptions{
|
||||||
|
NodeID: node.NodeID,
|
||||||
|
Since: &start,
|
||||||
|
Until: &end,
|
||||||
|
Limit: 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
if signed {
|
// 查询数据库获取今天的签到记录
|
||||||
return fmt.Sprintf("%s 今天已经签到过了。", displayName(node)), nil
|
signs, err := t.store.ListSigns(opts)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("查询签到记录失败:%w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(signs) == 0 {
|
||||||
return fmt.Sprintf("%s 今天还没有签到。", displayName(node)), nil
|
return fmt.Sprintf("%s 今天还没有签到。", displayName(node)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 返回签到详情
|
||||||
|
sign := signs[0]
|
||||||
|
signTimeStr := sign.SignTime.Format("15:04:05")
|
||||||
|
return fmt.Sprintf("%s 今天已经签到过了。\n签到时间:%s\n签到内容:%s",
|
||||||
|
displayName(node), signTimeStr, sign.SignText), nil
|
||||||
|
}
|
||||||
|
|
||||||
// executeQuery 执行查询操作
|
// executeQuery 执行查询操作
|
||||||
func (t *Tool) executeQuery(ctx context.Context, params signParams, runtime agenttool.Runtime) (string, error) {
|
func (t *Tool) executeQuery(ctx context.Context, params signParams, runtime agenttool.Runtime) (string, error) {
|
||||||
now := runtime.Now
|
now := runtime.Now
|
||||||
|
|||||||
@@ -85,6 +85,11 @@ func (m *mockSignStore) CountSignsByDay(opts storepkg.ListOptions) ([]storepkg.S
|
|||||||
func (m *mockSignStore) ListSigns(opts storepkg.ListOptions) ([]storepkg.SignRecord, error) {
|
func (m *mockSignStore) ListSigns(opts storepkg.ListOptions) ([]storepkg.SignRecord, error) {
|
||||||
var result []storepkg.SignRecord
|
var result []storepkg.SignRecord
|
||||||
for _, sign := range m.signs {
|
for _, sign := range m.signs {
|
||||||
|
// 过滤 NodeID
|
||||||
|
if opts.NodeID != "" && sign.NodeID != opts.NodeID {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// 过滤时间范围
|
||||||
if opts.Since != nil && sign.SignTime.Before(*opts.Since) {
|
if opts.Since != nil && sign.SignTime.Before(*opts.Since) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -93,6 +98,10 @@ func (m *mockSignStore) ListSigns(opts storepkg.ListOptions) ([]storepkg.SignRec
|
|||||||
}
|
}
|
||||||
result = append(result, sign)
|
result = append(result, sign)
|
||||||
}
|
}
|
||||||
|
// 应用 Limit
|
||||||
|
if opts.Limit > 0 && len(result) > opts.Limit {
|
||||||
|
result = result[:opts.Limit]
|
||||||
|
}
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,12 +270,13 @@ func TestSignTool_CheckAction(t *testing.T) {
|
|||||||
|
|
||||||
// 测试场景2:今天已签到
|
// 测试场景2:今天已签到
|
||||||
t.Run("今天已签到", func(t *testing.T) {
|
t.Run("今天已签到", func(t *testing.T) {
|
||||||
|
signTime := time.Date(2024, 6, 23, 10, 30, 45, 0, time.UTC)
|
||||||
store := &mockSignStore{
|
store := &mockSignStore{
|
||||||
signs: []storepkg.SignRecord{
|
signs: []storepkg.SignRecord{
|
||||||
{
|
{
|
||||||
NodeID: "test_node_123",
|
NodeID: "test_node_123",
|
||||||
SignText: "上海-TestUser-TestDevice签到",
|
SignText: "上海-TestUser-TestDevice签到",
|
||||||
SignTime: now,
|
SignTime: signTime,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
nodeInfoMap: make(map[string]*storepkg.NodeInfoRecord),
|
nodeInfoMap: make(map[string]*storepkg.NodeInfoRecord),
|
||||||
@@ -300,6 +310,15 @@ func TestSignTool_CheckAction(t *testing.T) {
|
|||||||
if !contains(result, "已经签到") {
|
if !contains(result, "已经签到") {
|
||||||
t.Errorf("Expected result to indicate already signed")
|
t.Errorf("Expected result to indicate already signed")
|
||||||
}
|
}
|
||||||
|
if !contains(result, "签到时间") {
|
||||||
|
t.Errorf("Expected result to contain sign time")
|
||||||
|
}
|
||||||
|
if !contains(result, "10:30:45") {
|
||||||
|
t.Errorf("Expected result to contain the exact sign time")
|
||||||
|
}
|
||||||
|
if !contains(result, "签到内容") {
|
||||||
|
t.Errorf("Expected result to contain sign text")
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user