From 7ba0330fd768fb0bf8ed9b2f7abac392bc7ad0c4 Mon Sep 17 00:00:00 2001 From: Kai Xia Date: Mon, 16 Feb 2026 00:11:22 +1100 Subject: [PATCH] backward compat fixes Signed-off-by: Kai Xia --- cmd/picoclaw/auth.go | 12 +++-- cmd/picoclaw/auth/auth.go | 10 ++++ cmd/picoclaw/auth/login.go | 17 ++----- cmd/picoclaw/auth/logout.go | 8 ++-- cmd/picoclaw/cronpkg/add.go | 2 +- cmd/picoclaw/onboard.go | 56 ----------------------- cmd/picoclaw/skillspkg/install_builtin.go | 23 +--------- cmd/picoclaw/skillspkg/list_builtin.go | 17 ++----- cmd/picoclaw/skillspkg/remove.go | 9 ++-- cmd/picoclaw/skillspkg/skills.go | 4 +- cmd/picoclaw/utils.go | 11 +++-- 11 files changed, 45 insertions(+), 124 deletions(-) create mode 100644 cmd/picoclaw/auth/auth.go diff --git a/cmd/picoclaw/auth.go b/cmd/picoclaw/auth.go index c2a1b8a13..b32ec980e 100644 --- a/cmd/picoclaw/auth.go +++ b/cmd/picoclaw/auth.go @@ -6,7 +6,7 @@ package main import ( "fmt" - "github.com/sipeed/picoclaw/cmd/picoclaw/auth" + authpkg "github.com/sipeed/picoclaw/cmd/picoclaw/auth" "github.com/spf13/cobra" ) @@ -20,9 +20,13 @@ var authCmd = &cobra.Command{ } func init() { - authCmd.AddCommand(auth.LoginCmd) - authCmd.AddCommand(auth.LogoutCmd) - authCmd.AddCommand(auth.StatusCmd) + authCmd.PersistentPreRun = func(cmd *cobra.Command, args []string) { + authpkg.SetConfigPath(getConfigPath()) + } + + authCmd.AddCommand(authpkg.LoginCmd) + authCmd.AddCommand(authpkg.LogoutCmd) + authCmd.AddCommand(authpkg.StatusCmd) } func authHelp() { diff --git a/cmd/picoclaw/auth/auth.go b/cmd/picoclaw/auth/auth.go new file mode 100644 index 000000000..c0bb0d291 --- /dev/null +++ b/cmd/picoclaw/auth/auth.go @@ -0,0 +1,10 @@ +// PicoClaw - Ultra-lightweight personal AI agent +// License: MIT + +package auth + +var configPath string + +func SetConfigPath(path string) { + configPath = path +} diff --git a/cmd/picoclaw/auth/login.go b/cmd/picoclaw/auth/login.go index 6c9e795ee..7de0dccb3 100644 --- a/cmd/picoclaw/auth/login.go +++ b/cmd/picoclaw/auth/login.go @@ -37,15 +37,6 @@ func init() { LoginCmd.Flags().BoolVar(&loginDeviceCode, "device-code", false, "Use device code flow (for headless environments)") } -func getConfigPath() string { - home, _ := os.UserHomeDir() - return fmt.Sprintf("%s/.picoclaw/config.json", home) -} - -func loadConfig() (*config.Config, error) { - return config.LoadConfig(getConfigPath()) -} - func loginImpl() { switch loginProvider { case "openai": @@ -81,10 +72,10 @@ func loginOpenAI(useDeviceCode bool) { os.Exit(1) } - appCfg, err := loadConfig() + appCfg, err := config.LoadConfig(configPath) if err == nil { appCfg.Providers.OpenAI.AuthMethod = "oauth" - if err := config.SaveConfig(getConfigPath(), appCfg); err != nil { + if err := config.SaveConfig(configPath, appCfg); err != nil { fmt.Printf("Warning: could not update config: %v\n", err) } } @@ -107,7 +98,7 @@ func loginPasteToken(provider string) { os.Exit(1) } - appCfg, err := loadConfig() + appCfg, err := config.LoadConfig(configPath) if err == nil { switch provider { case "anthropic": @@ -115,7 +106,7 @@ func loginPasteToken(provider string) { case "openai": appCfg.Providers.OpenAI.AuthMethod = "token" } - if err := config.SaveConfig(getConfigPath(), appCfg); err != nil { + if err := config.SaveConfig(configPath, appCfg); err != nil { fmt.Printf("Warning: could not update config: %v\n", err) } } diff --git a/cmd/picoclaw/auth/logout.go b/cmd/picoclaw/auth/logout.go index fdd0858c7..5904b2728 100644 --- a/cmd/picoclaw/auth/logout.go +++ b/cmd/picoclaw/auth/logout.go @@ -34,7 +34,7 @@ func logoutImpl() { os.Exit(1) } - appCfg, err := loadConfig() + appCfg, err := config.LoadConfig(configPath) if err == nil { switch logoutProvider { case "openai": @@ -42,7 +42,7 @@ func logoutImpl() { case "anthropic": appCfg.Providers.Anthropic.AuthMethod = "" } - config.SaveConfig(getConfigPath(), appCfg) + config.SaveConfig(configPath, appCfg) } fmt.Printf("Logged out from %s\n", logoutProvider) @@ -52,11 +52,11 @@ func logoutImpl() { os.Exit(1) } - appCfg, err := loadConfig() + appCfg, err := config.LoadConfig(configPath) if err == nil { appCfg.Providers.OpenAI.AuthMethod = "" appCfg.Providers.Anthropic.AuthMethod = "" - config.SaveConfig(getConfigPath(), appCfg) + config.SaveConfig(configPath, appCfg) } fmt.Println("Logged out from all providers") diff --git a/cmd/picoclaw/cronpkg/add.go b/cmd/picoclaw/cronpkg/add.go index 54ff2066c..e5da95397 100644 --- a/cmd/picoclaw/cronpkg/add.go +++ b/cmd/picoclaw/cronpkg/add.go @@ -46,7 +46,7 @@ func init() { AddCmd.Flags().StringVarP(&cronName, "name", "n", "", "Job name (required)") AddCmd.Flags().StringVarP(&cronMessage, "message", "m", "", "Message for agent (required)") AddCmd.Flags().StringVarP(&cronCronExpr, "cron", "c", "", "Cron expression (e.g. '0 9 * * *')") - AddCmd.Flags().StringVarP(&cronTo, "to", "", "", "Recipient for delivery") + AddCmd.Flags().StringVar(&cronTo, "to", "", "Recipient for delivery") AddCmd.Flags().StringVar(&cronChannel, "channel", "", "Channel for delivery") AddCmd.Flags().Int64VarP(&cronEvery, "every", "e", 0, "Run every N seconds") AddCmd.Flags().BoolVarP(&cronDeliver, "deliver", "d", false, "Deliver response to channel") diff --git a/cmd/picoclaw/onboard.go b/cmd/picoclaw/onboard.go index cae4368f9..a84797489 100644 --- a/cmd/picoclaw/onboard.go +++ b/cmd/picoclaw/onboard.go @@ -6,7 +6,6 @@ package main import ( "embed" "fmt" - "io" "io/fs" "os" "path/filepath" @@ -57,61 +56,6 @@ func onboard() { fmt.Println(" 2. Chat: picoclaw agent -m \"Hello!\"") } -func copyDirectory(src, dst string) error { - return filepath.Walk(src, func(path string, info os.FileInfo, err error) error { - if err != nil { - return err - } - - relPath, err := filepath.Rel(src, path) - if err != nil { - return err - } - - dstPath := filepath.Join(dst, relPath) - - if info.IsDir() { - return os.MkdirAll(dstPath, info.Mode()) - } - - srcFile, err := os.Open(path) - if err != nil { - return err - } - defer srcFile.Close() - - dstFile, err := os.OpenFile(dstPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, info.Mode()) - if err != nil { - return err - } - defer dstFile.Close() - - _, err = fmtCopy(dstFile, srcFile) - return err - }) -} - -func fmtCopy(dst *os.File, src *os.File) (int64, error) { - buf := make([]byte, 32*1024) - var written int64 - for { - n, err := src.Read(buf) - if n > 0 { - wn, err := dst.Write(buf[:n]) - if err != nil { - return written, err - } - written += int64(wn) - } - if err != nil { - if err == io.EOF { - return written, nil - } - return written, err - } - } -} - func copyEmbeddedToTarget(targetDir string) error { // Ensure target directory exists if err := os.MkdirAll(targetDir, 0755); err != nil { diff --git a/cmd/picoclaw/skillspkg/install_builtin.go b/cmd/picoclaw/skillspkg/install_builtin.go index 0850aad50..54a101bad 100644 --- a/cmd/picoclaw/skillspkg/install_builtin.go +++ b/cmd/picoclaw/skillspkg/install_builtin.go @@ -86,28 +86,7 @@ func copyDirectory(src, dst string) error { } defer dstFile.Close() - _, err = fmtCopy(dstFile, srcFile) + _, err = io.Copy(dstFile, srcFile) return err }) } - -func fmtCopy(dst *os.File, src *os.File) (int64, error) { - buf := make([]byte, 32*1024) - var written int64 - for { - n, err := src.Read(buf) - if n > 0 { - wn, err := dst.Write(buf[:n]) - if err != nil { - return written, err - } - written += int64(wn) - } - if err != nil { - if err == io.EOF { - return written, nil - } - return written, err - } - } -} diff --git a/cmd/picoclaw/skillspkg/list_builtin.go b/cmd/picoclaw/skillspkg/list_builtin.go index d17d951e9..79cae0430 100644 --- a/cmd/picoclaw/skillspkg/list_builtin.go +++ b/cmd/picoclaw/skillspkg/list_builtin.go @@ -44,18 +44,11 @@ func listBuiltinImpl() { skillFile := filepath.Join(builtinSkillsDir, skillName, "SKILL.md") description := "No description" - if _, err := os.Stat(skillFile); err == nil { - data, err := os.ReadFile(skillFile) - if err == nil { - content := string(data) - if idx := strings.Index(content, "\n"); idx > 0 { - firstLine := content[:idx] - if strings.Contains(firstLine, "description:") { - descLine := strings.Index(content[idx:], "\n") - if descLine > 0 { - description = strings.TrimSpace(content[idx+descLine : idx+descLine]) - } - } + if data, err := os.ReadFile(skillFile); err == nil { + for _, line := range strings.Split(string(data), "\n") { + if strings.HasPrefix(line, "description:") { + description = strings.TrimSpace(strings.TrimPrefix(line, "description:")) + break } } } diff --git a/cmd/picoclaw/skillspkg/remove.go b/cmd/picoclaw/skillspkg/remove.go index 7ae6b92f6..d68e63599 100644 --- a/cmd/picoclaw/skillspkg/remove.go +++ b/cmd/picoclaw/skillspkg/remove.go @@ -11,10 +11,11 @@ import ( ) var RemoveCmd = &cobra.Command{ - Use: "remove ", - Short: "Remove installed skill", - Long: `Remove an installed skill by name.`, - Args: cobra.ExactArgs(1), + Use: "remove ", + Aliases: []string{"uninstall"}, + Short: "Remove installed skill", + Long: `Remove an installed skill by name.`, + Args: cobra.ExactArgs(1), Run: func(cmd *cobra.Command, args []string) { removeImpl(args[0]) }, diff --git a/cmd/picoclaw/skillspkg/skills.go b/cmd/picoclaw/skillspkg/skills.go index e3ef08459..7e5ed75f5 100644 --- a/cmd/picoclaw/skillspkg/skills.go +++ b/cmd/picoclaw/skillspkg/skills.go @@ -4,8 +4,6 @@ package skillspkg import ( - "path/filepath" - "github.com/sipeed/picoclaw/pkg/skills" ) @@ -37,5 +35,5 @@ func getWorkspace() string { } func getBuiltinSkillsDir() string { - return filepath.Join(workspace, "../picoclaw/skills") + return builtinSkillsDir } diff --git a/cmd/picoclaw/utils.go b/cmd/picoclaw/utils.go index 9fe224e0d..52cbf4a7b 100644 --- a/cmd/picoclaw/utils.go +++ b/cmd/picoclaw/utils.go @@ -13,13 +13,14 @@ import ( ) var ( - version = "dev" - gitCommit string - buildTime string - goVersion string - logo = "🦞" + version = "dev" + gitCommit string + buildTime string + goVersion string ) +const logo = "🦞" + // formatVersion returns the version string with optional git commit func formatVersion() string { v := version