Commit graph

68 commits

Author SHA1 Message Date
yinwm
fbb7de6ec7 feat: US-014 - Add WebTool tests
Added comprehensive test coverage for WebTool (WebSearchTool, WebFetchTool) with 9 test cases:
- TestWebTool_WebFetch_Success: Verifies successful URL fetching
- TestWebTool_WebFetch_JSON: Verifies JSON content handling
- TestWebTool_WebFetch_InvalidURL: Verifies error handling for invalid URLs
- TestWebTool_WebFetch_UnsupportedScheme: Verifies only http/https allowed
- TestWebTool_WebFetch_MissingURL: Verifies missing URL parameter handling
- TestWebTool_WebFetch_Truncation: Verifies content truncation at maxChars
- TestWebTool_WebSearch_NoApiKey: Verifies API key requirement
- TestWebTool_WebSearch_MissingQuery: Verifies missing query parameter
- TestWebTool_WebFetch_HTMLExtraction: Verifies HTML tag removal and text extraction
- TestWebTool_WebFetch_MissingDomain: Verifies domain validation

WebTool implementation already conforms to ToolResult specification:
- WebFetch returns ForUser=fetched content, ForLLM=summary with byte count
- WebSearch returns ForUser=search results, ForLLM=result count
- Errors return ErrorResult with IsError=true

Tests use httptest.NewServer for mock HTTP servers, avoiding external API dependencies.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 19:54:44 +08:00
yinwm
a3e4dd7adb feat: US-013 - Add FilesystemTool tests
Added comprehensive test coverage for FilesystemTool (ReadFileTool, WriteFileTool, ListDirTool) with 10 test cases:
- TestFilesystemTool_ReadFile_Success: Verifies file content goes to ForLLM
- TestFilesystemTool_ReadFile_NotFound: Verifies error handling for missing files
- TestFilesystemTool_ReadFile_MissingPath: Verifies missing parameter handling
- TestFilesystemTool_WriteFile_Success: Verifies SilentResult behavior
- TestFilesystemTool_WriteFile_CreateDir: Verifies automatic directory creation
- TestFilesystemTool_WriteFile_MissingPath: Verifies missing path parameter handling
- TestFilesystemTool_WriteFile_MissingContent: Verifies missing content parameter handling
- TestFilesystemTool_ListDir_Success: Verifies directory listing functionality
- TestFilesystemTool_ListDir_NotFound: Verifies error handling for invalid paths
- TestFilesystemTool_ListDir_DefaultPath: Verifies default to current directory

FilesystemTool implementation already conforms to ToolResult specification:
- ReadFile/ListDir return NewToolResult (ForLLM only, ForUser empty)
- WriteFile returns SilentResult (Silent=true, ForUser empty)
- Errors return ErrorResult with IsError=true

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 19:53:00 +08:00
yinwm
5b288f2486 feat: US-012 - Add ShellTool tests
Added comprehensive test coverage for ShellTool (ExecTool) with 9 test cases:
- TestShellTool_Success: Verifies successful command execution
- TestShellTool_Failure: Verifies failed command execution with IsError flag
- TestShellTool_Timeout: Verifies command timeout handling
- TestShellTool_WorkingDir: Verifies custom working directory support
- TestShellTool_DangerousCommand: Verifies safety guard blocks dangerous commands
- TestShellTool_MissingCommand: Verifies error handling for missing command
- TestShellTool_StderrCapture: Verifies stderr is captured and included
- TestShellTool_OutputTruncation: Verifies long output is truncated
- TestShellTool_RestrictToWorkspace: Verifies workspace restriction

ShellTool implementation already conforms to ToolResult specification:
- Success returns ForUser = command output
- Failure returns IsError = true
- ForLLM contains full output and exit code

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 19:52:16 +08:00
yinwm
a58e77e342 feat: US-011 - Add MessageTool tests
- Added comprehensive test suite for MessageTool (message_test.go)
- 10 test cases covering all acceptance criteria:
  - Success returns SilentResult with proper ForLLM status
  - ForUser is empty (user receives message directly)
  - Failure returns ErrorResult with IsError=true
  - Custom channel/chat_id parameter handling
  - Error scenarios (missing content, no target, not configured)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 19:50:53 +08:00
yinwm
590376daab feat: US-010 - Add RecordLastChannel to AgentLoop with atomic state save
- Add state *state.Manager field to AgentLoop struct
- Initialize stateManager in NewAgentLoop using state.NewManager
- Implement RecordLastChannel method that calls state.SetLastChannel
- Implement RecordLastChatID method for chat ID tracking
- Add comprehensive tests for state persistence
- Verify state survives across AgentLoop instances

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 19:49:36 +08:00
yinwm
b8ec886036 feat: US-009 - Add state save atomicity with SetLastChannel
- Create pkg/state package with State and Manager structs
- Implement SetLastChannel with atomic save using temp file + rename
- Implement SetLastChatID with same atomic save pattern
- Add GetLastChannel, GetLastChatID, and GetTimestamp getters
- Use sync.RWMutex for thread-safe concurrent access
- Add comprehensive tests for atomic save, concurrent access, and persistence
- Cleanup temp file if rename fails

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 19:46:10 +08:00
yinwm
23add6bc02 feat: US-008 - Inject callback into async tools in AgentLoop
- Update ToolRegistry.ExecuteWithContext to accept asyncCallback parameter
- Check if tool implements AsyncTool and set callback if provided
- Define asyncCallback in AgentLoop.runLLMIteration
- Callback uses bus.PublishOutbound to send async results to user
- Update Execute method to pass nil for backward compatibility
- Add debug logging for async callback injection

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 19:42:24 +08:00
yinwm
3255203e38 feat: US-007 - Add heartbeat async task execution support
- Add local ToolResult struct definition to avoid circular dependencies
- Define HeartbeatHandler function type for tool-supporting callbacks
- Add SetOnHeartbeatWithTools method to configure new handler
- Add ExecuteHeartbeatWithTools public method
- Add internal executeHeartbeatWithTools implementation
- Update checkHeartbeat to prefer new tool-supporting handler
- Detect and handle async tasks (log and return immediately)
- Handle error results with proper logging
- Add comprehensive tests for async, error, sync, and nil result cases

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 19:39:57 +08:00
yinwm
a930691d30 feat: US-006 - Add AsyncCallback type and AsyncTool interface
- Define AsyncCallback function type for async tool completion notification
- Define AsyncTool interface with SetCallback method
- Add comprehensive godoc comments with usage examples
- This enables tools like SpawnTool to notify completion asynchronously

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 19:35:41 +08:00
yinwm
24e8f760a1 feat: US-005 - Update AgentLoop tool result processing logic
- Modify runLLMIteration to return lastToolResult for later decisions
- Send tool.ForUser content to user immediately when Silent=false
- Use tool.ForLLM for LLM context
- Implement Silent flag check to suppress user messages
- Add lastToolResult tracking for async callback support (US-008)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 19:34:32 +08:00
yinwm
1c2764addb feat: US-004 - Delete isToolConfirmationMessage function
The isToolConfirmationMessage function was already removed in commit 488e7a9.
This update marks US-004 as complete with a note.

The migration to ToolResult.Silent will be completed in US-005.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 19:30:47 +08:00
yinwm
419af2f745 feat: US-002 - Modify Tool interface to return *ToolResult
- Update all Tool implementations to return *ToolResult instead of (string, error)
- ShellTool: returns UserResult for command output, ErrorResult for failures
- SpawnTool: returns NewToolResult on success, ErrorResult on failure
- WebTool: returns ToolResult with ForUser=content, ForLLM=summary
- EditTool: returns SilentResult for silent edits, ErrorResult on failure
- FilesystemTool: returns SilentResult/NewToolResult for operations, ErrorResult on failure
- Temporarily disable cronTool in main.go (will be re-enabled in US-016)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 19:28:56 +08:00
yinwm
1f1d523e19 Merge pull request #49 from yinwm/main
refactor(channels): consolidate media handling and improve resource cleanup
2026-02-12 12:47:31 +08:00
yinwm
6f4da88b28 refactor(channels): consolidate media handling and improve resource cleanup
Extract common file download and audio detection logic to utils package,
implement consistent temp file cleanup with defer, add allowlist checks
before downloading attachments, and improve context management across
Discord, Slack, and Telegram channels. Replace logging with structured
logger and prevent context leaks in transcription and thinking animations.
2026-02-12 12:46:28 +08:00
yinwm
3f5f5349fb Merge pull request #45 from jadeydi/main
better version info
2026-02-12 12:07:42 +08:00
yinwm
51e55f6f11 Merge pull request #40 from mymmrac/telegram-using-telego
feat(telegram): Use Telego instead of go-telegram-bot-api
2026-02-12 12:07:00 +08:00
yinwm
bf7756645a Merge branch 'main' into telegram-using-telego 2026-02-12 12:06:48 +08:00
yinwm
5ecf82d125 Merge pull request #34 from corylanou/issue-31-feat-add-slack-channel-integration-with-socket-mode-threads-reactions-and-slash-commands
feat(channels): add Slack channel integration with Socket Mode
2026-02-12 12:01:19 +08:00
yinwm
a6c712737c Merge branch 'main' into issue-31-feat-add-slack-channel-integration-with-socket-mode-threads-reactions-and-slash-commands 2026-02-12 11:59:05 +08:00
yinwm
b4728faf2f Merge pull request #33 from corylanou/issue-27-feat-add-picoclaw-migrate-command-for-openclaw-workspace-migration
feat(migrate): add picoclaw migrate command for OpenClaw workspace migration

Adds migrate command to migrate workspace and config from OpenClaw to PicoClaw.

- Migrates workspace files (SOUL.md, AGENTS.md, USER.md, TOOLS.md, HEARTBEAT.md, memory/, skills/)
- Converts config from camelCase (OpenClaw) to snake_case (PicoClaw) format
- Supports --dry-run, --refresh, --config-only, --workspace-only, --force flags
- Safety: backups (.bak), confirmation prompts, no silent overwrites

Closes #27
2026-02-12 11:28:50 +08:00
yinwm
e223aa5e9c Merge branch 'main' into issue-27-feat-add-picoclaw-migrate-command-for-openclaw-workspace-migration 2026-02-12 11:22:06 +08:00
yinwm
a6a28adc1d Merge pull request #32 from corylanou/issue-18-add-support-for-openai-anthropic-oauth-based-login
feat(auth): add OAuth login with SDK-based subscription providers
2026-02-12 11:05:12 +08:00
yinwm
c21e591237 Merge pull request #44 from Sethispr/patch-1
chore: lint readme.md
2026-02-12 10:33:14 +08:00
yinwm
8b1db804d8 Merge pull request #30 from DevEverything01/fix/atomic-running
fix(agent): use atomic.Bool for AgentLoop.running to prevent data race
2026-02-12 10:21:39 +08:00
yinwm
bbdf8d4dd7 Merge pull request #29 from DevEverything01/fix/deduplicate-truncate
Remove duplicate truncate functions, reuse utils.Truncate
2026-02-12 09:48:28 +08:00
li
0ffcfe597b better version 2026-02-12 08:14:49 +08:00
seth
3795f8aaf6 chore: lint readme
17 - MD012 / no-multiple-blanks Multiple consecutive blank lines [Expected: 1; Actual: 2] [error] [Fix]
62 - MD012 / no-multiple-blanks Multiple consecutive blank lines [Expected: 1; Actual: 2] [error] [Fix]
221 - MD012 / no-multiple-blanks Multiple consecutive blank lines [Expected: 1; Actual: 2] [error] [Fix]
266 - MD012 / no-multiple-blanks Multiple consecutive blank lines [Expected: 1; Actual: 2] [error] [Fix]
368 - MD012 / no-multiple-blanks Multiple consecutive blank lines [Expected: 1; Actual: 2] [error] [Fix]
493 - MD012 / no-multiple-blanks Multiple consecutive blank lines [Expected: 1; Actual: 2] [error] [Fix]
39 - MD022 / blanks-around-headings Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "## 📢 News"] [error] [Fix]
63 - MD022 / blanks-around-headings Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "## 🦾 Demonstration"] [error] [Fix]
64 - MD022 / blanks-around-headings Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Above] [Context: "### 🛠️ Standard Assistant Workflows"] [error] [Fix]
64 - MD022 / blanks-around-headings Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "### 🛠️ Standard Assistant Workflows"] [error] [Fix]
83 - MD022 / blanks-around-headings Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "### 🐜 Innovative Low-Footprint Deploy"] [error] [Fix]
218 - MD031 / blanks-around-fences Fenced code blocks should be surrounded by blank lines [Context: "```"] [error] [Fix]
296 - MD031 / blanks-around-fences Fenced code blocks should be surrounded by blank lines [Context: "```"] [error] [Fix]
329 - MD031 / blanks-around-fences Fenced code blocks should be surrounded by blank lines [Context: "```"] [error] [Fix]
401 - MD031 / blanks-around-fences Fenced code blocks should be surrounded by blank lines [Context: "```"] [error] [Fix]
503 - MD031 / blanks-around-fences Fenced code blocks should be surrounded by blank lines [Context: "```json"] [error] [Fix]
226 - MD032 / blanks-around-lists Lists should be surrounded by blank lines [Context: "- Go to https://discord.com/de..."] [error] [Fix]
231 - MD032 / blanks-around-lists Lists should be surrounded by blank lines [Context: "- In the Bot settings, enable ..."] [error] [Fix]
235 - MD032 / blanks-around-lists Lists should be surrounded by blank lines [Context: "- Discord Settings → Advanced ..."] [error] [Fix]
253 - MD032 / blanks-around-lists Lists should be surrounded by blank lines [Context: "- OAuth2 → URL Generator"] [error] [Fix]
373 - MD032 / blanks-around-lists Lists should be surrounded by blank lines [Context: "- Get [API key](https://bigmod..."] [error] [Fix]
501 - MD032 / blanks-around-lists Lists should be surrounded by blank lines [Context: "1. Get a free API key at [http..."] [error] [Fix]
2026-02-11 15:53:16 -08:00
Artem Yadelskyi
b862615479 feat(telegram): Use Telego instead of go-telegram-bot-api 2026-02-11 23:51:18 +02:00
Cory LaNou
4dc290d8f0 chore(deps): upgrade openai-go from v1.12.0 to v3.21.0
Update to latest major version of the official OpenAI Go SDK.
Fix breaking change: FunctionCallOutput.Output is now a union type
(ResponseInputItemFunctionCallOutputOutputUnionParam) instead of string.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 13:39:19 -06:00
Cory LaNou
32c23f34b9 feat(providers): add SDK-based providers for subscription OAuth login
Add ClaudeProvider (anthropic-sdk-go) and CodexProvider (openai-go) that
use the correct subscription endpoints and API formats:

- CodexProvider: chatgpt.com/backend-api/codex/responses (Responses API)
  with OAuth Bearer auth and Chatgpt-Account-Id header
- ClaudeProvider: api.anthropic.com/v1/messages (Messages API) with
  Authorization: Bearer token auth

Update CreateProvider() routing to use new SDK-based providers when
auth_method is "oauth" or "token", removing the stopgap that sent
subscription tokens to pay-per-token endpoints.

Closes #18

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 13:27:59 -06:00
Cory LaNou
760ed7da58 feat(channels): add Slack channel integration with Socket Mode
Add Slack as a messaging channel using Socket Mode (WebSocket), bringing
the total supported channels to 8. Features include bidirectional
messaging, thread support with per-thread session context, @mention
handling, ack reactions (👀/), slash commands,
file/attachment support with Groq Whisper audio transcription, and
allowlist filtering by Slack user ID.

Closes #31

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 12:48:32 -06:00
Cory LaNou
b0bc8639ff feat(migrate): add picoclaw migrate command for OpenClaw workspace migration
Add a new `picoclaw migrate` CLI command that detects an existing OpenClaw
installation and migrates workspace files and configuration to PicoClaw.

Workspace markdown files (SOUL.md, AGENTS.md, USER.md, TOOLS.md, HEARTBEAT.md,
memory/, skills/) are copied 1:1. Config keys are mapped from OpenClaw's
camelCase JSON format to PicoClaw's snake_case format with provider and channel
field mapping.

Supports --dry-run, --refresh, --config-only, --workspace-only, --force flags.
Existing PicoClaw files are never silently overwritten; backups are created.

Closes #27

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 12:48:16 -06:00
Cory LaNou
839d57fb4a feat(auth): add OAuth and token-based login for OpenAI and Anthropic
Add `picoclaw auth` CLI command supporting:
- OpenAI OAuth2 (PKCE + browser callback or device code flow)
- Anthropic paste-token flow
- Token storage at ~/.picoclaw/auth.json with 0600 permissions
- Auto-refresh for expired OAuth tokens in provider

Closes #18

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 11:41:13 -06:00
Together
082cf69813 fix(agent): use atomic.Bool for AgentLoop.running to prevent data race
Run() and Stop() access the `running` field from different goroutines
without synchronization. Replace the bare `bool` with `sync/atomic.Bool`
to eliminate the data race.
2026-02-12 01:26:22 +08:00
Together
fae382f0e8 Remove duplicate truncate functions, reuse utils.Truncate
Multiple packages had their own private truncate implementations:
- channels/telegram.go: truncateString (byte-based, no "...")
- channels/dingtalk.go: truncateStringDingTalk (byte-based, no "...")
- voice/transcriber.go: truncateText (byte-based, with "...")

All three are functionally equivalent to the existing utils.Truncate,
which already handles rune-safe truncation and appends "..." correctly.

Replace all private copies with utils.Truncate and delete the dead code.
2026-02-12 00:46:48 +08:00
Only_Xianzo
7a5f236059 Fix: prioritize explicit provider prefixes and update max_tokens schema 2026-02-11 22:49:47 +08:00
zepan
af47916efb 1. update wechat group qrcode 2026-02-11 22:46:28 +08:00
lxowalle
03e3bc77f4 Merge pull request #23 from yinwm/fix/gateway-cron-tool
feat: Cron tool and agent integration
2026-02-11 21:25:06 +08:00
yinwm
695312cff9 Merge upstream/main 2026-02-11 21:08:30 +08:00
Harshdeep Sharma
872be9159f Fix typos and update API keys in README 2026-02-11 20:46:01 +08:00
Harshdeep Sharma
ae5bf17060 Fix typos and update API keys in README 2026-02-11 20:42:22 +08:00
yinwm
83f8f1351f refactor(tools): remove duplicate truncate functions and add docs
- Remove duplicate truncate/truncateString functions from loop.go and cron.go
- Use utils.Truncate consistently across codebase
- Add Workspace Layout section to README
- Document cron/scheduled tasks functionality

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 20:31:41 +08:00
yinwm
0a8b929776 refactor(agent): improve code quality and restore summarization
Code review fixes:
- Use map for O(n) job lookup in cron service (was O(n²))
- Set DeleteAfterRun=true for one-time cron tasks
- Restore context compression/summarization to prevent context overflow
- Add pkg/utils/string.go with Unicode-aware Truncate function
- Simplify setupCronTool to return only CronService
- Change Chinese comments to English in context.go

Refactoring:
- Replace toolsSummary callback with SetToolsRegistry setter pattern
- This makes dependency injection clearer and easier to test

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 20:31:41 +08:00
yinwm
f3fe539410 fix(cron): add one-time reminders and fix data paths to workspace
- Add at_seconds parameter for one-time reminders (e.g., "remind me in 10 minutes")
- Update every_seconds description to emphasize recurring-only usage
- Route cron delivery: deliver=true sends directly, deliver=false uses agent
- Fix cron data path from ~/.picoclaw/cron to workspace/cron
- Fix sessions path from workspace/../sessions to workspace/sessions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 20:31:41 +08:00
yinwm
af2221b221 feat: add cron tool integration with agent
- Add adhocore/gronx dependency for cron expression parsing
- Fix CronService race conditions and add cron expression support
- Add CronTool with add/list/remove/enable/disable actions
- Add ContextualTool interface for tools needing channel/chatID context
- Add ProcessDirectWithChannel to AgentLoop for cron job execution
- Register CronTool in gateway and wire up onJob handler
- Fix slice bounds panic in addJob for short messages

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 20:28:46 +08:00
Harshdeep Sharma
1475a6681d Fix typos and update API keys in README 2026-02-11 20:26:03 +08:00
lxowalle
1a6813be89 Merge pull request #19 from n0bisuke/main
fix a typo
2026-02-11 19:55:15 +08:00
lxowalle
b9138d1a7a Merge pull request #14 from yinwm/fix/tool-execution
Agent Memory System & Tool Execution Improvements
2026-02-11 19:53:26 +08:00
lxowalle
0ead672613 Merge branch 'pr-12' 2026-02-11 19:47:11 +08:00
lxowalle
c8d3db30b4 Merge pull request #5 from yinwm/add-qq-channel
Add QQ channel support
2026-02-11 17:25:32 +08:00