backward compat fixes
Signed-off-by: Kai Xia <kaix+github@fastmail.com>
This commit is contained in:
parent
2b9b7720e3
commit
7ba0330fd7
11 changed files with 45 additions and 124 deletions
|
|
@ -6,7 +6,7 @@ package main
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/sipeed/picoclaw/cmd/picoclaw/auth"
|
authpkg "github.com/sipeed/picoclaw/cmd/picoclaw/auth"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -20,9 +20,13 @@ var authCmd = &cobra.Command{
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
authCmd.AddCommand(auth.LoginCmd)
|
authCmd.PersistentPreRun = func(cmd *cobra.Command, args []string) {
|
||||||
authCmd.AddCommand(auth.LogoutCmd)
|
authpkg.SetConfigPath(getConfigPath())
|
||||||
authCmd.AddCommand(auth.StatusCmd)
|
}
|
||||||
|
|
||||||
|
authCmd.AddCommand(authpkg.LoginCmd)
|
||||||
|
authCmd.AddCommand(authpkg.LogoutCmd)
|
||||||
|
authCmd.AddCommand(authpkg.StatusCmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
func authHelp() {
|
func authHelp() {
|
||||||
|
|
|
||||||
10
cmd/picoclaw/auth/auth.go
Normal file
10
cmd/picoclaw/auth/auth.go
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
// PicoClaw - Ultra-lightweight personal AI agent
|
||||||
|
// License: MIT
|
||||||
|
|
||||||
|
package auth
|
||||||
|
|
||||||
|
var configPath string
|
||||||
|
|
||||||
|
func SetConfigPath(path string) {
|
||||||
|
configPath = path
|
||||||
|
}
|
||||||
|
|
@ -37,15 +37,6 @@ func init() {
|
||||||
LoginCmd.Flags().BoolVar(&loginDeviceCode, "device-code", false, "Use device code flow (for headless environments)")
|
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() {
|
func loginImpl() {
|
||||||
switch loginProvider {
|
switch loginProvider {
|
||||||
case "openai":
|
case "openai":
|
||||||
|
|
@ -81,10 +72,10 @@ func loginOpenAI(useDeviceCode bool) {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
appCfg, err := loadConfig()
|
appCfg, err := config.LoadConfig(configPath)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
appCfg.Providers.OpenAI.AuthMethod = "oauth"
|
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)
|
fmt.Printf("Warning: could not update config: %v\n", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -107,7 +98,7 @@ func loginPasteToken(provider string) {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
appCfg, err := loadConfig()
|
appCfg, err := config.LoadConfig(configPath)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
switch provider {
|
switch provider {
|
||||||
case "anthropic":
|
case "anthropic":
|
||||||
|
|
@ -115,7 +106,7 @@ func loginPasteToken(provider string) {
|
||||||
case "openai":
|
case "openai":
|
||||||
appCfg.Providers.OpenAI.AuthMethod = "token"
|
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)
|
fmt.Printf("Warning: could not update config: %v\n", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ func logoutImpl() {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
appCfg, err := loadConfig()
|
appCfg, err := config.LoadConfig(configPath)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
switch logoutProvider {
|
switch logoutProvider {
|
||||||
case "openai":
|
case "openai":
|
||||||
|
|
@ -42,7 +42,7 @@ func logoutImpl() {
|
||||||
case "anthropic":
|
case "anthropic":
|
||||||
appCfg.Providers.Anthropic.AuthMethod = ""
|
appCfg.Providers.Anthropic.AuthMethod = ""
|
||||||
}
|
}
|
||||||
config.SaveConfig(getConfigPath(), appCfg)
|
config.SaveConfig(configPath, appCfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Logged out from %s\n", logoutProvider)
|
fmt.Printf("Logged out from %s\n", logoutProvider)
|
||||||
|
|
@ -52,11 +52,11 @@ func logoutImpl() {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
appCfg, err := loadConfig()
|
appCfg, err := config.LoadConfig(configPath)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
appCfg.Providers.OpenAI.AuthMethod = ""
|
appCfg.Providers.OpenAI.AuthMethod = ""
|
||||||
appCfg.Providers.Anthropic.AuthMethod = ""
|
appCfg.Providers.Anthropic.AuthMethod = ""
|
||||||
config.SaveConfig(getConfigPath(), appCfg)
|
config.SaveConfig(configPath, appCfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("Logged out from all providers")
|
fmt.Println("Logged out from all providers")
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ func init() {
|
||||||
AddCmd.Flags().StringVarP(&cronName, "name", "n", "", "Job name (required)")
|
AddCmd.Flags().StringVarP(&cronName, "name", "n", "", "Job name (required)")
|
||||||
AddCmd.Flags().StringVarP(&cronMessage, "message", "m", "", "Message for agent (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(&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().StringVar(&cronChannel, "channel", "", "Channel for delivery")
|
||||||
AddCmd.Flags().Int64VarP(&cronEvery, "every", "e", 0, "Run every N seconds")
|
AddCmd.Flags().Int64VarP(&cronEvery, "every", "e", 0, "Run every N seconds")
|
||||||
AddCmd.Flags().BoolVarP(&cronDeliver, "deliver", "d", false, "Deliver response to channel")
|
AddCmd.Flags().BoolVarP(&cronDeliver, "deliver", "d", false, "Deliver response to channel")
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ package main
|
||||||
import (
|
import (
|
||||||
"embed"
|
"embed"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
@ -57,61 +56,6 @@ func onboard() {
|
||||||
fmt.Println(" 2. Chat: picoclaw agent -m \"Hello!\"")
|
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 {
|
func copyEmbeddedToTarget(targetDir string) error {
|
||||||
// Ensure target directory exists
|
// Ensure target directory exists
|
||||||
if err := os.MkdirAll(targetDir, 0755); err != nil {
|
if err := os.MkdirAll(targetDir, 0755); err != nil {
|
||||||
|
|
|
||||||
|
|
@ -86,28 +86,7 @@ func copyDirectory(src, dst string) error {
|
||||||
}
|
}
|
||||||
defer dstFile.Close()
|
defer dstFile.Close()
|
||||||
|
|
||||||
_, err = fmtCopy(dstFile, srcFile)
|
_, err = io.Copy(dstFile, srcFile)
|
||||||
return err
|
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -44,18 +44,11 @@ func listBuiltinImpl() {
|
||||||
skillFile := filepath.Join(builtinSkillsDir, skillName, "SKILL.md")
|
skillFile := filepath.Join(builtinSkillsDir, skillName, "SKILL.md")
|
||||||
|
|
||||||
description := "No description"
|
description := "No description"
|
||||||
if _, err := os.Stat(skillFile); err == nil {
|
if data, err := os.ReadFile(skillFile); err == nil {
|
||||||
data, err := os.ReadFile(skillFile)
|
for _, line := range strings.Split(string(data), "\n") {
|
||||||
if err == nil {
|
if strings.HasPrefix(line, "description:") {
|
||||||
content := string(data)
|
description = strings.TrimSpace(strings.TrimPrefix(line, "description:"))
|
||||||
if idx := strings.Index(content, "\n"); idx > 0 {
|
break
|
||||||
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])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import (
|
||||||
|
|
||||||
var RemoveCmd = &cobra.Command{
|
var RemoveCmd = &cobra.Command{
|
||||||
Use: "remove <name>",
|
Use: "remove <name>",
|
||||||
|
Aliases: []string{"uninstall"},
|
||||||
Short: "Remove installed skill",
|
Short: "Remove installed skill",
|
||||||
Long: `Remove an installed skill by name.`,
|
Long: `Remove an installed skill by name.`,
|
||||||
Args: cobra.ExactArgs(1),
|
Args: cobra.ExactArgs(1),
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,6 @@
|
||||||
package skillspkg
|
package skillspkg
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"github.com/sipeed/picoclaw/pkg/skills"
|
"github.com/sipeed/picoclaw/pkg/skills"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -37,5 +35,5 @@ func getWorkspace() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func getBuiltinSkillsDir() string {
|
func getBuiltinSkillsDir() string {
|
||||||
return filepath.Join(workspace, "../picoclaw/skills")
|
return builtinSkillsDir
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,10 @@ var (
|
||||||
gitCommit string
|
gitCommit string
|
||||||
buildTime string
|
buildTime string
|
||||||
goVersion string
|
goVersion string
|
||||||
logo = "🦞"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const logo = "🦞"
|
||||||
|
|
||||||
// formatVersion returns the version string with optional git commit
|
// formatVersion returns the version string with optional git commit
|
||||||
func formatVersion() string {
|
func formatVersion() string {
|
||||||
v := version
|
v := version
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue