From 28f66403760bbadd4d66e63f76579ff6979c75ce Mon Sep 17 00:00:00 2001 From: Dmitrii Balabanov Date: Mon, 9 Mar 2026 17:37:08 +0200 Subject: [PATCH] Fix lint issues after reply routing merge --- pkg/agent/loop.go | 2 +- pkg/agent/memory_test.go | 2 +- pkg/channels/manager.go | 16 +++++---- pkg/channels/manager_test.go | 1 - pkg/channels/telegram/target.go | 8 ----- pkg/channels/telegram/telegram.go | 7 +++- pkg/channels/telegram/telegram_test.go | 27 ++++++++++++--- pkg/config/config.go | 4 +-- pkg/tools/message.go | 8 +++-- pkg/tools/tasktool.go | 47 +++++++++++++++++++------- 10 files changed, 83 insertions(+), 39 deletions(-) diff --git a/pkg/agent/loop.go b/pkg/agent/loop.go index da41ca095..f29c764c0 100644 --- a/pkg/agent/loop.go +++ b/pkg/agent/loop.go @@ -896,7 +896,7 @@ func resolveFinalResponse( if hasDirective { directiveMode = strings.TrimSpace(strings.TrimSuffix(strings.TrimPrefix(directive, "[[reply:"), "]]")) } - directiveStatus := "none" + var directiveStatus string switch { case !hasDirective: directiveStatus = "none" diff --git a/pkg/agent/memory_test.go b/pkg/agent/memory_test.go index de6a0107c..93f9896c9 100644 --- a/pkg/agent/memory_test.go +++ b/pkg/agent/memory_test.go @@ -13,7 +13,7 @@ func TestWriteCompactionSummaryCreatesTimestampedFile(t *testing.T) { workspace := t.TempDir() store := NewMemoryStore(workspace) - timestamp := time.Date(2026, time.March, 8, 14, 5, 9, 0, time.Local) + timestamp := time.Date(2026, time.March, 8, 14, 5, 9, 0, time.UTC) path, err := store.WriteCompactionSummary(timestamp, "# Summary\n\nBody") if err != nil { diff --git a/pkg/channels/manager.go b/pkg/channels/manager.go index 5c199849e..82037330a 100644 --- a/pkg/channels/manager.go +++ b/pkg/channels/manager.go @@ -142,12 +142,16 @@ func (m *Manager) preSend(ctx context.Context, name string, msg bus.OutboundMess if msg.ReplyToMessageID != "" { if deleter, ok := ch.(MessageDeleter); ok { if err := deleter.DeleteMessage(ctx, msg.ChatID, entry.id); err != nil { - logger.WarnCF("manager", "Failed to delete placeholder before reply-targeted send", map[string]any{ - "channel": name, - "chat_id": msg.ChatID, - "placeholder_id": entry.id, - "error": err.Error(), - }) + logger.WarnCF( + "manager", + "Failed to delete placeholder before reply-targeted send", + map[string]any{ + "channel": name, + "chat_id": msg.ChatID, + "placeholder_id": entry.id, + "error": err.Error(), + }, + ) } } return false diff --git a/pkg/channels/manager_test.go b/pkg/channels/manager_test.go index 1045502af..667c328e8 100644 --- a/pkg/channels/manager_test.go +++ b/pkg/channels/manager_test.go @@ -52,7 +52,6 @@ func TestSendMessageWithID_FallsBackToBusWithoutError(t *testing.T) { ChatID: "1", Content: "hello", }) - if err != nil { t.Fatalf("expected nil error for async fallback, got %v", err) } diff --git a/pkg/channels/telegram/target.go b/pkg/channels/telegram/target.go index 22b98533a..febcfd3e4 100644 --- a/pkg/channels/telegram/target.go +++ b/pkg/channels/telegram/target.go @@ -61,14 +61,6 @@ func resolveTelegramForumThreadID(isForum bool, messageThreadID int) (int, bool) return messageThreadID, true } -func (t telegramTarget) chatIDString() string { - return strconv.FormatInt(t.ChatID, 10) -} - -func (t telegramTarget) topicChatID() string { - return buildTelegramTopicChatID(t.ChatID, t.MessageThreadID) -} - func (t telegramTarget) messageThreadIDForSend() (int, bool) { if t.MessageThreadID <= 0 || t.MessageThreadID == telegramGeneralTopicID { return 0, false diff --git a/pkg/channels/telegram/telegram.go b/pkg/channels/telegram/telegram.go index 60a89be04..98d4dc341 100644 --- a/pkg/channels/telegram/telegram.go +++ b/pkg/channels/telegram/telegram.go @@ -782,7 +782,12 @@ func parseTelegramMessageIDs(messageID string) ([]int, error) { return ids, nil } -func (c *TelegramChannel) editHTMLChunk(ctx context.Context, chatID int64, messageID int, htmlContent, mdFallback string) error { +func (c *TelegramChannel) editHTMLChunk( + ctx context.Context, + chatID int64, + messageID int, + htmlContent, mdFallback string, +) error { editMsg := tu.EditMessageText(tu.ID(chatID), messageID, htmlContent) editMsg.ParseMode = telego.ModeHTML diff --git a/pkg/channels/telegram/telegram_test.go b/pkg/channels/telegram/telegram_test.go index e522b5f4b..187cc90d4 100644 --- a/pkg/channels/telegram/telegram_test.go +++ b/pkg/channels/telegram/telegram_test.go @@ -151,7 +151,10 @@ func TestSendMessageWithID_ShortMessage_SingleCall(t *testing.T) { } ch := newTestChannel(t, caller) - msgID, err := ch.SendMessageWithID(context.Background(), bus.OutboundMessage{ChatID: "12345", Content: "Hello, world!"}) + msgID, err := ch.SendMessageWithID(context.Background(), bus.OutboundMessage{ + ChatID: "12345", + Content: "Hello, world!", + }) assert.NoError(t, err) assert.Equal(t, "1", msgID) @@ -253,7 +256,10 @@ func TestSendMessageWithID_HTMLFallback_PerChunk(t *testing.T) { } ch := newTestChannel(t, caller) - msgID, err := ch.SendMessageWithID(context.Background(), bus.OutboundMessage{ChatID: "12345", Content: "Hello **world**"}) + msgID, err := ch.SendMessageWithID( + context.Background(), + bus.OutboundMessage{ChatID: "12345", Content: "Hello **world**"}, + ) assert.NoError(t, err) assert.Equal(t, "1", msgID) @@ -306,10 +312,18 @@ func TestSendMessageWithID_MarkdownShortButHTMLLong_MultipleCalls(t *testing.T) markdownContent := strings.Repeat("**a** ", 600) assert.LessOrEqual(t, len([]rune(markdownContent)), 4000) - msgID, err := ch.SendMessageWithID(context.Background(), bus.OutboundMessage{ChatID: "12345", Content: markdownContent}) + msgID, err := ch.SendMessageWithID( + context.Background(), + bus.OutboundMessage{ChatID: "12345", Content: markdownContent}, + ) assert.NoError(t, err) - assert.Greater(t, len(caller.calls), 1, "markdown-short but HTML-long message should be split into multiple SendMessage calls") + assert.Greater( + t, + len(caller.calls), + 1, + "markdown-short but HTML-long message should be split into multiple SendMessage calls", + ) assert.Equal(t, "1,2", msgID) } @@ -458,7 +472,10 @@ func TestSendMessageWithID_InvalidChatID(t *testing.T) { } ch := newTestChannel(t, caller) - msgID, err := ch.SendMessageWithID(context.Background(), bus.OutboundMessage{ChatID: "not-a-number", Content: "Hello"}) + msgID, err := ch.SendMessageWithID( + context.Background(), + bus.OutboundMessage{ChatID: "not-a-number", Content: "Hello"}, + ) assert.Error(t, err) assert.Empty(t, msgID) diff --git a/pkg/config/config.go b/pkg/config/config.go index 9b42f5d22..68e50ebc1 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -703,8 +703,8 @@ type ToolsConfig struct { } type TaskToolConfig struct { - ToolConfig `envPrefix:"PICOCLAW_TOOLS_TASK_TOOL_"` - Icons TaskToolIconsConfig `json:"icons"` + ToolConfig ` envPrefix:"PICOCLAW_TOOLS_TASK_TOOL_"` + Icons TaskToolIconsConfig ` json:"icons"` } type TaskToolIconsConfig struct { diff --git a/pkg/tools/message.go b/pkg/tools/message.go index 98da6ba06..c4a1378c1 100644 --- a/pkg/tools/message.go +++ b/pkg/tools/message.go @@ -93,6 +93,10 @@ func (t *MessageTool) Execute(ctx context.Context, args map[string]any) *ToolRes currentChannel := ToolChannel(ctx) currentChatID := ToolChatID(ctx) + sameTarget := currentChannel != "" && + currentChatID != "" && + channel == currentChannel && + chatID == currentChatID replyMode, _ := args["reply_mode"].(string) replyMode = strings.ToLower(strings.TrimSpace(replyMode)) explicitReplyTo, _ := args["reply_to_message_id"].(string) @@ -106,7 +110,7 @@ func (t *MessageTool) Execute(ctx context.Context, args map[string]any) *ToolRes "reply_to_message_id": explicitReplyTo, }) } - if currentChannel != "" && currentChatID != "" && channel == currentChannel && chatID == currentChatID { + if sameTarget { logger.InfoCF("tool", "Message tool targeting current conversation", map[string]any{ "channel": channel, "chat_id": chatID, @@ -150,7 +154,7 @@ func (t *MessageTool) Execute(ctx context.Context, args map[string]any) *ToolRes "chat_id": chatID, "content_len": len(content), "reply_to_message_id": replyToMessageID, - "same_target": currentChannel != "" && currentChatID != "" && channel == currentChannel && chatID == currentChatID, + "same_target": sameTarget, }) // Silent: user already received the message directly diff --git a/pkg/tools/tasktool.go b/pkg/tools/tasktool.go index 738007d31..2befb369a 100644 --- a/pkg/tools/tasktool.go +++ b/pkg/tools/tasktool.go @@ -19,7 +19,6 @@ type TaskTool struct { } func NewTaskTool(taskManager *session.TaskManager, icons config.TaskToolIconsConfig) *TaskTool { - return &TaskTool{ taskManager: taskManager, icons: icons, @@ -130,15 +129,22 @@ func (t *TaskTool) Execute(ctx context.Context, args map[string]any) *ToolResult } } -func (t *TaskTool) handleCreatePlan(ctx context.Context, sessionKey, channel, chatID string, args map[string]any) *ToolResult { - tasksRaw, ok := args["tasks"].([]interface{}) +func (t *TaskTool) handleCreatePlan( + ctx context.Context, + sessionKey, channel, chatID string, + args map[string]any, +) *ToolResult { + tasksRaw, ok := args["tasks"].([]any) if !ok || len(tasksRaw) == 0 { - return &ToolResult{ForLLM: "tasktool: tasks array is required and cannot be empty for 'create_plan'", IsError: true} + return &ToolResult{ + ForLLM: "tasktool: tasks array is required and cannot be empty for 'create_plan'", + IsError: true, + } } var parsedTasks []session.Task for i, raw := range tasksRaw { - taskMap, ok := raw.(map[string]interface{}) + taskMap, ok := raw.(map[string]any) if !ok { return &ToolResult{ForLLM: fmt.Sprintf("tasktool: invalid task at index %d", i), IsError: true} } @@ -150,7 +156,10 @@ func (t *TaskTool) handleCreatePlan(ctx context.Context, sessionKey, channel, ch desc, ok := taskMap["description"].(string) if !ok || desc == "" { - return &ToolResult{ForLLM: fmt.Sprintf("tasktool: missing description for task at index %d", i), IsError: true} + return &ToolResult{ + ForLLM: fmt.Sprintf("tasktool: missing description for task at index %d", i), + IsError: true, + } } parsedTasks = append(parsedTasks, session.Task{ @@ -236,7 +245,11 @@ func (t *TaskTool) handleResendPlan(ctx context.Context, sessionKey, channel, ch return t.newPlanResult(summary, content, delivered, deliveryErr) } -func (t *TaskTool) handleUpdateTask(ctx context.Context, sessionKey, channel, chatID string, args map[string]any) *ToolResult { +func (t *TaskTool) handleUpdateTask( + ctx context.Context, + sessionKey, channel, chatID string, + args map[string]any, +) *ToolResult { taskID, _ := args["task_id"].(string) if taskID == "" { return &ToolResult{ForLLM: "tasktool: task_id is required for 'update_task'", IsError: true} @@ -331,15 +344,25 @@ func (t *TaskTool) newPlanResult(summary, content string, delivered bool, delive } } - forLLM := summary if deliveryErr != nil { - forLLM = fmt.Sprintf("%s\nAutomatic delivery failed (%v). Respond to the user with the following plan content:\n\n%s", summary, deliveryErr, content) - } else { - forLLM = fmt.Sprintf("%s\nAutomatic delivery is unavailable in this context. Respond to the user with the following plan content:\n\n%s", summary, content) + return &ToolResult{ + ForLLM: fmt.Sprintf( + "%s\nAutomatic delivery failed (%v). Respond to the user with the following plan content:\n\n%s", + summary, + deliveryErr, + content, + ), + ForUser: content, + Silent: false, + } } return &ToolResult{ - ForLLM: forLLM, + ForLLM: fmt.Sprintf( + "%s\nAutomatic delivery is unavailable in this context. Respond to the user with the following plan content:\n\n%s", + summary, + content, + ), ForUser: content, Silent: false, }