diff --git a/README.md b/README.md index 994e4d13a..0de13b429 100644 --- a/README.md +++ b/README.md @@ -1391,6 +1391,7 @@ picoclaw agent -m "Hello" | ------------------------- | ----------------------------- | | `picoclaw onboard` | Initialize config & workspace | | `picoclaw onboard weixin` | Connect WeChat account via QR | +| `picoclaw channels weixin login` | Connect WeChat account via QR | | `picoclaw agent -m "..."` | Chat with the agent | | `picoclaw agent` | Interactive chat mode | | `picoclaw gateway` | Start the gateway | diff --git a/cmd/picoclaw/internal/channels/command.go b/cmd/picoclaw/internal/channels/command.go new file mode 100644 index 000000000..d2a7fc48e --- /dev/null +++ b/cmd/picoclaw/internal/channels/command.go @@ -0,0 +1,15 @@ +package channels + +import "github.com/spf13/cobra" + +func NewChannelsCommand() *cobra.Command { + cmd := &cobra.Command{ + Use: "channels", + Aliases: []string{"channel"}, + Short: "Manage chat channel logins and configuration helpers", + } + + cmd.AddCommand(newWeixinCommand()) + + return cmd +} diff --git a/cmd/picoclaw/internal/channels/weixin.go b/cmd/picoclaw/internal/channels/weixin.go new file mode 100644 index 000000000..8a15147a2 --- /dev/null +++ b/cmd/picoclaw/internal/channels/weixin.go @@ -0,0 +1,37 @@ +package channels + +import ( + "time" + + "github.com/spf13/cobra" + + "github.com/sipeed/picoclaw/cmd/picoclaw/internal/onboard" +) + +func newWeixinCommand() *cobra.Command { + var baseURL string + var proxy string + var timeout int + + cmd := &cobra.Command{ + Use: "weixin", + Aliases: []string{"wechat", "wx"}, + Short: "Manage Weixin (WeChat personal) channel login", + } + + loginCmd := &cobra.Command{ + Use: "login", + Short: "Start QR login for Weixin (WeChat personal)", + RunE: func(cmd *cobra.Command, _ []string) error { + return onboard.RunWeixinOnboard(baseURL, proxy, time.Duration(timeout)*time.Second) + }, + } + + loginCmd.Flags().StringVar(&baseURL, "base-url", "https://ilinkai.weixin.qq.com/", "iLink API base URL") + loginCmd.Flags().StringVar(&proxy, "proxy", "", "HTTP proxy URL (e.g. http://localhost:7890)") + loginCmd.Flags().IntVar(&timeout, "timeout", 300, "Login timeout in seconds") + + cmd.AddCommand(loginCmd) + + return cmd +} diff --git a/cmd/picoclaw/internal/onboard/weixin.go b/cmd/picoclaw/internal/onboard/weixin.go index 721b4f0e9..6b9930d0e 100644 --- a/cmd/picoclaw/internal/onboard/weixin.go +++ b/cmd/picoclaw/internal/onboard/weixin.go @@ -18,7 +18,8 @@ func newWeixinCommand() *cobra.Command { var timeout int cmd := &cobra.Command{ - Use: "weixin", + Use: "weixin", + Aliases: []string{"wechat", "wx"}, Short: "Connect a WeChat personal account via QR code", Long: `Start the interactive Weixin (WeChat personal) QR code login flow. @@ -29,7 +30,7 @@ config so you can start the gateway immediately. Example: picoclaw onboard weixin`, RunE: func(cmd *cobra.Command, _ []string) error { - return runWeixinOnboard(baseURL, proxy, time.Duration(timeout)*time.Second) + return RunWeixinOnboard(baseURL, proxy, time.Duration(timeout)*time.Second) }, } @@ -40,7 +41,7 @@ Example: return cmd } -func runWeixinOnboard(baseURL, proxy string, timeout time.Duration) error { +func RunWeixinOnboard(baseURL, proxy string, timeout time.Duration) error { fmt.Println("Starting Weixin (WeChat personal) login...") fmt.Println() diff --git a/cmd/picoclaw/main.go b/cmd/picoclaw/main.go index bf9c0389f..cf050e2c5 100644 --- a/cmd/picoclaw/main.go +++ b/cmd/picoclaw/main.go @@ -15,6 +15,7 @@ import ( "github.com/sipeed/picoclaw/cmd/picoclaw/internal" "github.com/sipeed/picoclaw/cmd/picoclaw/internal/agent" "github.com/sipeed/picoclaw/cmd/picoclaw/internal/auth" + internalchannels "github.com/sipeed/picoclaw/cmd/picoclaw/internal/channels" "github.com/sipeed/picoclaw/cmd/picoclaw/internal/cron" "github.com/sipeed/picoclaw/cmd/picoclaw/internal/gateway" "github.com/sipeed/picoclaw/cmd/picoclaw/internal/migrate" @@ -37,6 +38,7 @@ func NewPicoclawCommand() *cobra.Command { cmd.AddCommand( onboard.NewOnboardCommand(), + internalchannels.NewChannelsCommand(), agent.NewAgentCommand(), auth.NewAuthCommand(), gateway.NewGatewayCommand(), diff --git a/config/config.example.json b/config/config.example.json index 28b29dfa1..e99785cf3 100644 --- a/config/config.example.json +++ b/config/config.example.json @@ -218,6 +218,16 @@ "welcome_message": "Hello! I'm your AI assistant. How can I help you today?", "reasoning_channel_id": "" }, + "weixin": { + "_comment": "Weixin (WeChat personal) - Native QR login via Tencent iLink API.", + "enabled": false, + "token": "YOUR_WEIXIN_TOKEN", + "base_url": "https://ilinkai.weixin.qq.com/", + "cdn_base_url": "https://novac2c.cdn.weixin.qq.com/c2c", + "proxy": "", + "allow_from": [], + "reasoning_channel_id": "" + }, "pico": { "enabled": false, "token": "YOUR_PICO_TOKEN", diff --git a/docs/changelogs/2026-03-23-picoclaw-weixin-command-config-alignment.md b/docs/changelogs/2026-03-23-picoclaw-weixin-command-config-alignment.md new file mode 100644 index 000000000..657d54abb --- /dev/null +++ b/docs/changelogs/2026-03-23-picoclaw-weixin-command-config-alignment.md @@ -0,0 +1,31 @@ +# 2026-03-23 Picoclaw Weixin Command And Config Alignment + +## Summary + +Aligned the existing native `weixin` implementation with the workflow used in the desktop-facing `agent/` changes by making the login path and sample configuration directly usable. + +## Changes + +- Added `picoclaw channels weixin login` +- Added command aliases: + - `picoclaw onboard wechat` + - `picoclaw channels wechat login` +- Added the missing `channels.weixin` section to `config/config.example.json` +- Updated `docs/channels/weixin/README.md` to document both login entrypoints and the full config fields used by the native channel + +## Why + +`picoclaw-clone` already had the native Weixin protocol layer, QR login flow, polling loop, and media support. The remaining gap was usability: + +- users could follow docs but not see `channels.weixin` in the shipped example config +- the command surface did not match the newer `channels ... login` workflow +- the full `base_url` / `cdn_base_url` fields were not documented in the main Weixin README + +## Result + +The repo now exposes a complete Weixin setup path through: + +1. `picoclaw onboard weixin` +2. `picoclaw channels weixin login` +3. `config/config.example.json` sample configuration +4. native `pkg/channels/weixin` runtime support already present in the codebase diff --git a/docs/channels/weixin/README.md b/docs/channels/weixin/README.md index 22687fec4..4d3708a45 100644 --- a/docs/channels/weixin/README.md +++ b/docs/channels/weixin/README.md @@ -4,10 +4,11 @@ PicoClaw supports connecting to your personal WeChat account using the official ## 🚀 Quick Onboarding -The easiest way to set up the Weixin channel is using the interactive onboarding command: +The easiest way to set up the Weixin channel is using the interactive onboarding command or the direct channel login command: ```bash picoclaw onboard weixin +picoclaw channels weixin login ``` This command will: @@ -33,6 +34,8 @@ You can also manually configure the filter rules in `config.json` under the `cha "weixin": { "enabled": true, "token": "YOUR_WEIXIN_TOKEN", + "base_url": "https://ilinkai.weixin.qq.com/", + "cdn_base_url": "https://novac2c.cdn.weixin.qq.com/c2c", "allow_from": [ "user_id_1", "user_id_2" @@ -49,6 +52,8 @@ You can also manually configure the filter rules in `config.json` under the `cha |---|---| | `enabled` | Set to `true` to enable the channel at startup. | | `token` | The authentication token obtained via QR login. | +| `base_url` | Tencent iLink API base URL. Keep the default unless the login flow returns a region-specific endpoint. | +| `cdn_base_url` | Tencent CDN base URL used for image, file, video, and voice transfer. | | `allow_from` | (Optional) List of WeChat User IDs permitted to interact with the bot. If empty, anyone who can send messages to the connected account can trigger the bot. | | `proxy` | (Optional) HTTP proxy address (e.g. `http://localhost:7890`) for environments where connection to `ilinkai.weixin.qq.com` is restricted. |