From 38df11510da3d114f72c1478761e273209a4bd8a Mon Sep 17 00:00:00 2001 From: Jannis Metrikat <120120832+jmetrikat@users.noreply.github.com> Date: Tue, 7 Oct 2025 12:47:52 +0200 Subject: [PATCH 01/11] Add bot account authentication support and refactor related functions --- cmd/auth/create/create.go | 48 +++++++---- cmd/auth/login/login.go | 10 +-- cmd/auth/logout/logout.go | 2 +- cmd/auth/status/status.go | 22 ++--- core/auth.go | 112 ++++++++++++++++---------- core/auth_test.go | 46 +++++------ core/keyring.go | 66 +++++++++++---- core/serviceprogram/serviceprogram.go | 16 ++-- core/stream.go | 2 +- go.mod | 2 +- go.sum | 12 +-- 11 files changed, 199 insertions(+), 139 deletions(-) diff --git a/cmd/auth/create/create.go b/cmd/auth/create/create.go index 962b576..b306b0a 100644 --- a/cmd/auth/create/create.go +++ b/cmd/auth/create/create.go @@ -20,8 +20,8 @@ func NewCreateCmd() *cobra.Command { cmd := &cobra.Command{ Use: "create", - Short: "Create a new account", - Long: "Create a new Anytype account with a generated mnemonic phrase. The mnemonic is your master key for account recovery.", + Short: "Create a new bot account", + Long: "Create a new Anytype bot account with a generated account key. The account key is your credential for bot authentication.", RunE: func(cmd *cobra.Command, args []string) error { if name == "" { output.Print("Enter account name: ") @@ -34,33 +34,47 @@ func NewCreateCmd() *cobra.Command { } } - mnemonic, accountId, err := core.CreateWallet(name, rootPath, apiAddr) + botAccountKey, accountId, err := core.CreateBotWallet(name, rootPath, apiAddr) if err != nil { return output.Error("failed to create account: %w", err) } - output.Success("Account created successfully!") + output.Success("Bot account created successfully!") - output.Warning("IMPORTANT: Save your mnemonic phrase in a secure location.") - output.Info(" This is the ONLY way to recover your account if you lose access.") + output.Warning("IMPORTANT: Save your bot account key in a secure location.") + output.Info(" This is the ONLY way to authenticate your bot account.") - words := strings.Split(mnemonic, " ") output.Print("") - output.Print("╔════════════════════════════════════════════════════════╗") - output.Print("║ MNEMONIC PHRASE ║") - output.Print("╠════════════════════════════════════════════════════════╣") - output.Print("║ %-52s ║", strings.Join(words[0:6], " ")) - output.Print("║ %-52s ║", strings.Join(words[6:12], " ")) - output.Print("╚════════════════════════════════════════════════════════╝") + keyLen := len(botAccountKey) + boxWidth := keyLen + 4 // 2 spaces padding on each side + if boxWidth < 24 { // Minimum width for "BOT ACCOUNT KEY" title + boxWidth = 24 + } + + topBorder := "╔" + strings.Repeat("═", boxWidth) + "╗" + midBorder := "╠" + strings.Repeat("═", boxWidth) + "╣" + botBorder := "╚" + strings.Repeat("═", boxWidth) + "╝" + + title := "BOT ACCOUNT KEY" + titlePadding := (boxWidth - len(title)) / 2 + titleLine := "║" + strings.Repeat(" ", titlePadding) + title + strings.Repeat(" ", boxWidth-titlePadding-len(title)) + "║" + + keyLine := fmt.Sprintf("║ %s ║", botAccountKey) + + output.Print(topBorder) + output.Print(titleLine) + output.Print(midBorder) + output.Print(keyLine) + output.Print(botBorder) output.Print("") - output.Print("📋 Account Details:") + output.Print("📋 Bot Account Details:") output.Print(" Name: %s", name) - output.Print(" Id: %s", accountId) + output.Print(" Account Id: %s", accountId) output.Print("") - output.Success("You are now logged in to your new account.") - output.Success("Mnemonic saved to keychain.") + output.Success("You are now logged in to your new bot account.") + output.Success("Bot account key saved to keychain.") return nil }, diff --git a/cmd/auth/login/login.go b/cmd/auth/login/login.go index 763debc..bc511a4 100644 --- a/cmd/auth/login/login.go +++ b/cmd/auth/login/login.go @@ -13,14 +13,14 @@ import ( func NewLoginCmd() *cobra.Command { cmd := &cobra.Command{ Use: "login", - Short: "Log in to your account", - Long: "Authenticate using your mnemonic phrase to access your Anytype account and stored data.", + Short: "Log in to your bot account", + Long: "Authenticate using your bot account key to access your Anytype bot account and stored data.", RunE: func(cmd *cobra.Command, args []string) error { - mnemonic, _ := cmd.Flags().GetString("mnemonic") + accountKey, _ := cmd.Flags().GetString("account-key") rootPath, _ := cmd.Flags().GetString("path") apiAddr, _ := cmd.Flags().GetString("api-addr") - if err := core.Login(mnemonic, rootPath, apiAddr); err != nil { + if err := core.LoginBot(accountKey, rootPath, apiAddr); err != nil { return output.Error("failed to log in: %w", err) } output.Success("Successfully logged in") @@ -29,7 +29,7 @@ func NewLoginCmd() *cobra.Command { }, } - cmd.Flags().String("mnemonic", "", "Provide mnemonic (12 words) for authentication") + cmd.Flags().String("account-key", "", "Provide bot account key for authentication") cmd.Flags().String("path", "", "Provide custom root path for wallet recovery") cmd.Flags().String("api-addr", "", fmt.Sprintf("API listen address (default: %s)", config.DefaultAPIAddress)) diff --git a/cmd/auth/logout/logout.go b/cmd/auth/logout/logout.go index 39adbcb..adac261 100644 --- a/cmd/auth/logout/logout.go +++ b/cmd/auth/logout/logout.go @@ -11,7 +11,7 @@ func NewLogoutCmd() *cobra.Command { cmd := &cobra.Command{ Use: "logout", Short: "Log out and clear stored credentials", - Long: "End your current session and remove stored authentication tokens and mnemonic from the system keychain.", + Long: "End your current session and remove stored authentication tokens and bot account key from the system keychain.", RunE: func(cmd *cobra.Command, args []string) error { if err := core.Logout(); err != nil { return output.Error("failed to log out: %w", err) diff --git a/cmd/auth/status/status.go b/cmd/auth/status/status.go index f6dc20e..f727861 100644 --- a/cmd/auth/status/status.go +++ b/cmd/auth/status/status.go @@ -18,9 +18,9 @@ func NewStatusCmd() *cobra.Command { Short: "Show authentication status", Long: "Display current authentication status, including account information, server status, and stored credentials.", RunE: func(cmd *cobra.Command, args []string) error { - hasMnemonic := false - if _, err := core.GetStoredMnemonic(); err == nil { - hasMnemonic = true + hasBotKey := false + if _, err := core.GetStoredBotAccountKey(); err == nil { + hasBotKey = true } hasToken := false @@ -43,19 +43,19 @@ func NewStatusCmd() *cobra.Command { serverRunning = err == nil // If server is running and we have a token, we're logged in - // (server auto-logs in on restart using stored mnemonic) + // (server auto-logs in on restart using stored bot account key) isLoggedIn := serverRunning && hasToken // Display status based on priority: server -> credentials -> login if !serverRunning { output.Print("Server is not running. Run 'anytype serve' to start the server.") - if hasMnemonic || hasToken || accountId != "" { + if hasBotKey || hasToken || accountId != "" { output.Print("Credentials are stored in keychain.") } return nil } - if !hasMnemonic && !hasToken && accountId == "" { + if !hasBotKey && !hasToken && accountId == "" { output.Print("Not authenticated. Run 'anytype auth login' to authenticate or 'anytype auth create' to create a new account.") return nil } @@ -64,7 +64,7 @@ func NewStatusCmd() *cobra.Command { if isLoggedIn && accountId != "" { output.Print(" ✓ Logged in to account \033[1m%s\033[0m (keychain)", accountId) - } else if hasToken || hasMnemonic { + } else if hasToken || hasBotKey { output.Print(" ✗ Not logged in (credentials stored in keychain)") if !isLoggedIn && hasToken { output.Print(" Note: Server is not running or session expired. Run 'anytype serve' to start server.") @@ -75,15 +75,15 @@ func NewStatusCmd() *cobra.Command { output.Print(" - Active session: \033[1m%v\033[0m", isLoggedIn) - if hasMnemonic { - output.Print(" - Mnemonic: \033[1mstored\033[0m") + if hasBotKey { + output.Print(" - Bot Account Key: \033[1mstored\033[0m") } if hasToken { if len(token) > 8 { - output.Print(" - Token: \033[1m%s****\033[0m", token[:8]) + output.Print(" - Session Token: \033[1m%s****\033[0m", token[:8]) } else { - output.Print(" - Token: \033[1mstored\033[0m") + output.Print(" - Session Token: \033[1mstored\033[0m") } } diff --git a/core/auth.go b/core/auth.go index 341be37..890f053 100644 --- a/core/auth.go +++ b/core/auth.go @@ -43,8 +43,8 @@ func getDefaultWorkDir() string { } } -// LoginAccount performs the common steps for logging in with a given mnemonic and root path. -func LoginAccount(mnemonic, rootPath, apiAddr string) error { +// LoginBotAccount performs the login steps for a bot account using a bot account key. +func LoginBotAccount(botAccountKey, rootPath, apiAddr string) error { if rootPath == "" { rootPath = getDefaultDataPath() } @@ -55,7 +55,7 @@ func LoginAccount(mnemonic, rootPath, apiAddr string) error { var sessionToken string err := GRPCCallNoAuth(func(ctx context.Context, client service.ClientCommandsClient) error { - _, err := client.InitialSetParameters(ctx, &pb.RpcInitialSetParametersRequest{ + resp, err := client.InitialSetParameters(ctx, &pb.RpcInitialSetParametersRequest{ Platform: runtime.GOOS, Version: Version, Workdir: getDefaultWorkDir(), @@ -63,24 +63,33 @@ func LoginAccount(mnemonic, rootPath, apiAddr string) error { if err != nil { return fmt.Errorf("failed to set initial parameters: %w", err) } + if resp.Error.Code != pb.RpcInitialSetParametersResponseError_NULL { + return fmt.Errorf("failed to set initial parameters: %s", resp.Error.Description) + } - _, err = client.WalletRecover(ctx, &pb.RpcWalletRecoverRequest{ - Mnemonic: mnemonic, - RootPath: rootPath, + resp2, err := client.WalletRecover(ctx, &pb.RpcWalletRecoverRequest{ + AccountKey: botAccountKey, + RootPath: rootPath, }) if err != nil { return fmt.Errorf("wallet recovery failed: %w", err) } + if resp2.Error.Code != pb.RpcWalletRecoverResponseError_NULL { + return fmt.Errorf("wallet recovery failed: %s", resp2.Error.Description) + } - resp, err := client.WalletCreateSession(ctx, &pb.RpcWalletCreateSessionRequest{ - Auth: &pb.RpcWalletCreateSessionRequestAuthOfMnemonic{ - Mnemonic: mnemonic, + resp3, err := client.WalletCreateSession(ctx, &pb.RpcWalletCreateSessionRequest{ + Auth: &pb.RpcWalletCreateSessionRequestAuthOf{ + AppKey: botAccountKey, }, }) if err != nil { return fmt.Errorf("failed to create session: %w", err) } - sessionToken = resp.Token + if resp3.Error.Code != pb.RpcWalletCreateSessionResponseError_NULL { + return fmt.Errorf("failed to create session: %s", resp3.Error.Description) + } + sessionToken = resp3.Token return nil }) @@ -150,49 +159,47 @@ func LoginAccount(mnemonic, rootPath, apiAddr string) error { return nil } -func ValidateMnemonic(mnemonic string) error { - if mnemonic == "" { - return fmt.Errorf("mnemonic cannot be empty") +func ValidateAccountKey(accountKey string) error { + if accountKey == "" { + return fmt.Errorf("bot account key cannot be empty") } - - words := strings.Fields(mnemonic) - if len(words) != 12 { - return fmt.Errorf("mnemonic must be exactly 12 words, got %d", len(words)) + // Bot account keys are typically base64 encoded strings + if len(accountKey) < 20 { + return fmt.Errorf("invalid bot account key format") } return nil } -func Login(mnemonic, rootPath, apiAddr string) error { - usedStoredMnemonic := false - if mnemonic == "" { - storedMnemonic, err := GetStoredMnemonic() - if err == nil && storedMnemonic != "" { - mnemonic = storedMnemonic - output.Info("Using stored mnemonic from keychain.") - usedStoredMnemonic = true +func LoginBot(accountKey, rootPath, apiAddr string) error { + usedStoredKey := false + if accountKey == "" { + storedKey, err := GetStoredBotAccountKey() + if err == nil && storedKey != "" { + accountKey = storedKey + output.Info("Using stored bot account key from keychain.") + usedStoredKey = true } else { - output.Print("Enter mnemonic (12 words): ") + output.Print("Enter bot account key: ") reader := bufio.NewReader(os.Stdin) - mnemonic, _ = reader.ReadString('\n') - mnemonic = strings.TrimSpace(mnemonic) + accountKey, _ = reader.ReadString('\n') + accountKey = strings.TrimSpace(accountKey) } } - if err := ValidateMnemonic(mnemonic); err != nil { + if err := ValidateAccountKey(accountKey); err != nil { return err } - err := LoginAccount(mnemonic, rootPath, apiAddr) - if err != nil { - return fmt.Errorf("failed to log in: %w", err) + if err := LoginBotAccount(accountKey, rootPath, apiAddr); err != nil { + return err } - if !usedStoredMnemonic { - if err := SaveMnemonic(mnemonic); err != nil { - output.Warning("failed to save mnemonic in keychain: %v", err) + if !usedStoredKey { + if err := SaveBotAccountKey(accountKey); err != nil { + output.Warning("failed to save bot account key in keychain: %v", err) } else { - output.Success("Mnemonic saved to keychain.") + output.Success("Bot account key saved to keychain.") } } @@ -231,8 +238,8 @@ func Logout() error { return err } - if err := DeleteStoredMnemonic(); err != nil { - return fmt.Errorf("failed to delete stored mnemonic: %w", err) + if err := DeleteStoredBotAccountKey(); err != nil { + return fmt.Errorf("failed to delete stored bot account key: %w", err) } if err := DeleteStoredToken(); err != nil { @@ -249,8 +256,9 @@ func Logout() error { return nil } -// CreateWallet creates a new wallet with the given root path and returns the mnemonic and account Id -func CreateWallet(name, rootPath, apiAddr string) (string, string, error) { +// CreateBotWallet creates a new bot wallet with the given root path and returns the bot account key and account Id +// This creates a regular wallet but exports a bot-specific account key for authentication +func CreateBotWallet(name, rootPath, apiAddr string) (string, string, error) { if rootPath == "" { rootPath = getDefaultDataPath() } @@ -258,8 +266,8 @@ func CreateWallet(name, rootPath, apiAddr string) (string, string, error) { apiAddr = config.DefaultAPIAddress } - var mnemonic string var sessionToken string + var mnemonic string err := GRPCCallNoAuth(func(ctx context.Context, client service.ClientCommandsClient) error { _, err := client.InitialSetParameters(ctx, &pb.RpcInitialSetParametersRequest{ @@ -341,7 +349,25 @@ func CreateWallet(name, rootPath, apiAddr string) (string, string, error) { return "", "", err } - _ = SaveMnemonic(mnemonic) + var botAccountKey string + err = GRPCCall(func(ctx context.Context, client service.ClientCommandsClient) error { + resp, err := client.WalletExportBot(ctx, &pb.RpcWalletExportBotRequest{ + Mnemonic: mnemonic, + Index: 0, // Use index 0 for the first bot account + }) + if err != nil { + return fmt.Errorf("failed to export bot account key: %w", err) + } + botAccountKey = resp.AccountKey + return nil + }) + if err != nil { + return "", "", err + } + + if err := SaveBotAccountKey(botAccountKey); err != nil { + output.Warning("failed to save bot account key: %v", err) + } configMgr := config.GetConfigManager() if err := configMgr.Load(); err != nil { @@ -356,5 +382,5 @@ func CreateWallet(name, rootPath, apiAddr string) (string, string, error) { } } - return mnemonic, accountId, nil + return botAccountKey, accountId, nil } diff --git a/core/auth_test.go b/core/auth_test.go index 73eb7af..3c0d5f6 100644 --- a/core/auth_test.go +++ b/core/auth_test.go @@ -97,60 +97,54 @@ func TestGetDefaultWorkDir(t *testing.T) { } } -func TestValidateMnemonic(t *testing.T) { +func TestValidateAccountKey(t *testing.T) { tests := []struct { name string - mnemonic string + accountKey string wantErr bool errContains string }{ { - name: "valid 12 word mnemonic", - mnemonic: "word1 word2 word3 word4 word5 word6 word7 word8 word9 word10 word11 word12", - wantErr: false, + name: "valid bot account key", + accountKey: "somevalidbase64encodedkeythatislongenough", + wantErr: false, }, { - name: "valid 12 words with extra spaces", - mnemonic: "word1 word2 word3 word4 word5 word6 word7 word8 word9 word10 word11 word12", - wantErr: false, - }, - { - name: "invalid 11 word mnemonic", - mnemonic: "word1 word2 word3 word4 word5 word6 word7 word8 word9 word10 word11", + name: "empty account key", + accountKey: "", wantErr: true, - errContains: "must be exactly 12 words, got 11", + errContains: "bot account key cannot be empty", }, { - name: "invalid 13 word mnemonic", - mnemonic: "word1 word2 word3 word4 word5 word6 word7 word8 word9 word10 word11 word12 word13", + name: "too short account key", + accountKey: "shortkey", wantErr: true, - errContains: "must be exactly 12 words, got 13", + errContains: "invalid bot account key format", }, { - name: "empty mnemonic", - mnemonic: "", - wantErr: true, - errContains: "cannot be empty", + name: "minimum valid length key", + accountKey: "12345678901234567890", // exactly 20 chars + wantErr: false, }, { - name: "whitespace only", - mnemonic: " ", + name: "just under minimum length", + accountKey: "1234567890123456789", // 19 chars wantErr: true, - errContains: "must be exactly 12 words, got 0", + errContains: "invalid bot account key format", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - err := ValidateMnemonic(tt.mnemonic) + err := ValidateAccountKey(tt.accountKey) if (err != nil) != tt.wantErr { - t.Errorf("ValidateMnemonic() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("ValidateAccountKey() error = %v, wantErr %v", err, tt.wantErr) } if err != nil && tt.errContains != "" { if !strings.Contains(err.Error(), tt.errContains) { - t.Errorf("ValidateMnemonic() error = %q, want to contain %q", err.Error(), tt.errContains) + t.Errorf("ValidateAccountKey() error = %q, want to contain %q", err.Error(), tt.errContains) } } }) diff --git a/core/keyring.go b/core/keyring.go index 59686e8..5416015 100644 --- a/core/keyring.go +++ b/core/keyring.go @@ -1,33 +1,67 @@ package core -import "github.com/zalando/go-keyring" +import ( + "encoding/base64" + "strings" + + "github.com/anyproto/anytype-cli/core/output" + "github.com/zalando/go-keyring" +) const ( - keyringService = "anytype-cli" - keyringMnemonicUser = "mnemonic" - keyringTokenUser = "session-token" + keyringService = "anytype-cli" + keyringTokenUser = "session-token" + keyringBotAccountUser = "bot-account-key" ) -func SaveMnemonic(mnemonic string) error { - return keyring.Set(keyringService, keyringMnemonicUser, mnemonic) +func SaveToken(token string) error { + return keyring.Set(keyringService, keyringTokenUser, token) } -func GetStoredMnemonic() (string, error) { - return keyring.Get(keyringService, keyringMnemonicUser) +func GetStoredToken() (string, error) { + token, err := keyring.Get(keyringService, keyringTokenUser) + if err != nil { + return "", err + } + output.Info("Retrieved token from keyring %q", token) + // Handle go-keyring base64 encoding that may be added on some platforms + if strings.HasPrefix(token, "go-keyring-base64:") { + encoded := strings.TrimPrefix(token, "go-keyring-base64:") + decoded, err := base64.StdEncoding.DecodeString(encoded) + if err != nil { + return "", err + } + token = string(decoded) + } + return token, nil } -func DeleteStoredMnemonic() error { - return keyring.Delete(keyringService, keyringMnemonicUser) +func DeleteStoredToken() error { + return keyring.Delete(keyringService, keyringTokenUser) } -func SaveToken(token string) error { - return keyring.Set(keyringService, keyringTokenUser, token) +func SaveBotAccountKey(accountKey string) error { + return keyring.Set(keyringService, keyringBotAccountUser, accountKey) } -func GetStoredToken() (string, error) { - return keyring.Get(keyringService, keyringTokenUser) +func GetStoredBotAccountKey() (string, error) { + key, err := keyring.Get(keyringService, keyringBotAccountUser) + if err != nil { + return "", err + } + output.Info("Retrieved key from keyring %q", key) + // Handle go-keyring base64 encoding that may be added on some platforms + if strings.HasPrefix(key, "go-keyring-base64:") { + encoded := strings.TrimPrefix(key, "go-keyring-base64:") + decoded, err := base64.StdEncoding.DecodeString(encoded) + if err != nil { + return "", err + } + key = string(decoded) + } + return key, nil } -func DeleteStoredToken() error { - return keyring.Delete(keyringService, keyringTokenUser) +func DeleteStoredBotAccountKey() error { + return keyring.Delete(keyringService, keyringBotAccountUser) } diff --git a/core/serviceprogram/serviceprogram.go b/core/serviceprogram/serviceprogram.go index a8f8075..32bf4c2 100644 --- a/core/serviceprogram/serviceprogram.go +++ b/core/serviceprogram/serviceprogram.go @@ -89,25 +89,25 @@ func (p *Program) run() { } func (p *Program) attemptAutoLogin() { - mnemonic, err := core.GetStoredMnemonic() - if err != nil || mnemonic == "" { - output.Info("No stored mnemonic found, skipping auto-login") + botAccountKey, err := core.GetStoredBotAccountKey() + if err != nil || botAccountKey == "" { + output.Info("No stored bot account key found, skipping auto-login") return } - output.Info("Found stored mnemonic, attempting auto-login...") + output.Info("Found stored bot account key, attempting auto-login...") maxRetries := 5 for i := 0; i < maxRetries; i++ { - if err := core.LoginAccount(mnemonic, "", ""); err != nil { + if err := core.LoginBotAccount(botAccountKey, "", ""); err != nil { if i < maxRetries-1 { time.Sleep(2 * time.Second) continue } - output.Info("Failed to auto-login after %d attempts: %v", maxRetries, err) + output.Info("Failed to auto-login with bot key after %d attempts: %v", maxRetries, err) } else { - output.Success("Successfully logged in using stored mnemonic") - break + output.Success("Successfully logged in using stored bot account key") + return } } } diff --git a/core/stream.go b/core/stream.go index 37c4fce..dcd04f1 100644 --- a/core/stream.go +++ b/core/stream.go @@ -74,7 +74,7 @@ func (er *EventReceiver) receiveLoop(ctx context.Context) { for { event, err := er.stream.Recv() if errors.Is(err, io.EOF) { - output.Info("🔄 Event stream ended") + output.Info("Event stream ended") return } if err != nil { diff --git a/go.mod b/go.mod index ac1d9e7..7a9d410 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.24.6 require ( github.com/anyproto/any-sync v0.10.3-0.20250924192345-ac39daeebf86 - github.com/anyproto/anytype-heart v0.48.18-hotfix-1.0.20250924191541-b7d0a25cfa2e + github.com/anyproto/anytype-heart v0.48.18-hotfix-1.0.20250924201504-831824ca3128 github.com/cheggaaa/mb/v3 v3.0.2 github.com/chzyer/readline v1.5.1 github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 diff --git a/go.sum b/go.sum index 1248c20..2a6e9a4 100644 --- a/go.sum +++ b/go.sum @@ -40,18 +40,10 @@ github.com/andybalholm/cascadia v1.3.3 h1:AG2YHrzJIm4BZ19iwJ/DAua6Btl3IwJX+VI4kk github.com/andybalholm/cascadia v1.3.3/go.mod h1:xNd9bqTn98Ln4DwST8/nG+H0yuB8Hmgu1YHNnWw0GeA= github.com/anyproto/any-store v0.3.8 h1:s499vEwfAUVHZ0NpN/AliG94g2QwqUHTCrbSl27VXRk= github.com/anyproto/any-store v0.3.8/go.mod h1:P9CnoL9Q06eh051DwtcvCiiWCwdXO7AbEILcnD6yrss= -github.com/anyproto/any-sync v0.9.9-0.20250818132859-04a7b1bd8146 h1:kqYWSraI/8msZDQN71bSDqG/WJkgNiObgr0aDZTKDZ4= -github.com/anyproto/any-sync v0.9.9-0.20250818132859-04a7b1bd8146/go.mod h1:ITG3xpDnFTOZ0lRnKdmQdggHv78fTyX9aNHXa+G+17U= -github.com/anyproto/any-sync v0.10.2 h1:na1g2iAVX5/tef9+qjyRz+skVe6LoSvYmWV3YecareI= -github.com/anyproto/any-sync v0.10.2/go.mod h1:kSAW2IXIeDSUabu9jMKJirgFCyM4a99lM6URR8GCH6A= github.com/anyproto/any-sync v0.10.3-0.20250924192345-ac39daeebf86 h1:UzxlCEshfjtFmAh6hoKHCXNDZg94/EoO4xvYuzflLq4= github.com/anyproto/any-sync v0.10.3-0.20250924192345-ac39daeebf86/go.mod h1:cRDgI+U2nXZC2PXXSCKS2FCHWEBurH7TyELOOkgDblQ= -github.com/anyproto/anytype-heart v0.44.0-rc07 h1:kNE2gTB5BatFnXnKMsd4ufaYZojej7V7+jxCcgy98FE= -github.com/anyproto/anytype-heart v0.44.0-rc07/go.mod h1:AH56ESbHjVJiqncPLucuUKuybx9GXW/N5S2U0gltP9o= -github.com/anyproto/anytype-heart v0.48.18-hotfix-1 h1:DESNrdKrI80t4dl2pWZqaIz7rbm5fk4WnumdBZQ2Lig= -github.com/anyproto/anytype-heart v0.48.18-hotfix-1/go.mod h1:SkiQ5c/fc/QamGkkSf+nFVWtODmnsqVERrGMlb0lhMQ= -github.com/anyproto/anytype-heart v0.48.18-hotfix-1.0.20250924191541-b7d0a25cfa2e h1:6E/UbB+wR7o/lln1Ihgf1Gg2rn66i1VFQyWLB3KnFug= -github.com/anyproto/anytype-heart v0.48.18-hotfix-1.0.20250924191541-b7d0a25cfa2e/go.mod h1:Uq9G8qiHekx/B41a1HYCXxZQEaNen43ac/mvh8oiSvc= +github.com/anyproto/anytype-heart v0.48.18-hotfix-1.0.20250924201504-831824ca3128 h1:dXTF3Oj/JYqavxYWD6/nAHf9WATQeaBpEfbNze2HE4s= +github.com/anyproto/anytype-heart v0.48.18-hotfix-1.0.20250924201504-831824ca3128/go.mod h1:Uq9G8qiHekx/B41a1HYCXxZQEaNen43ac/mvh8oiSvc= github.com/anyproto/anytype-publish-server/publishclient v0.0.0-20250716122732-cdcfe3a126bb h1:X1os44y0QWf1mYGj8BOoYKlXwY5xb94xTQIw1IIKJbY= github.com/anyproto/anytype-publish-server/publishclient v0.0.0-20250716122732-cdcfe3a126bb/go.mod h1:OzzODq4OigiRVD2lSOX1iHAoLcxhJDRbZb8n5PLG3WE= github.com/anyproto/anytype-push-server/pushclient v0.0.0-20250801122506-553f6c085a23 h1:jXAjKY4g9ec7lDtayIlzM9u0/b3xGS9YgGA6JtRhHfU= From 2705ae54eedf3f8d1a20e3bc60103d26a6f72d24 Mon Sep 17 00:00:00 2001 From: Jannis Metrikat <120120832+jmetrikat@users.noreply.github.com> Date: Tue, 7 Oct 2025 12:49:55 +0200 Subject: [PATCH 02/11] Add run configurations for 'anytype' and 'anytype serve' --- .run/anytype serve.run.xml | 19 +++++++++++++++++++ .run/anytype.run.xml | 21 +++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 .run/anytype serve.run.xml create mode 100644 .run/anytype.run.xml diff --git a/.run/anytype serve.run.xml b/.run/anytype serve.run.xml new file mode 100644 index 0000000..a1b3410 --- /dev/null +++ b/.run/anytype serve.run.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.run/anytype.run.xml b/.run/anytype.run.xml new file mode 100644 index 0000000..d9cca43 --- /dev/null +++ b/.run/anytype.run.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 890f2f7d98009a6f92a27085c2ec6ae49af4c90a Mon Sep 17 00:00:00 2001 From: Jannis Metrikat <120120832+jmetrikat@users.noreply.github.com> Date: Tue, 28 Oct 2025 16:45:36 +0100 Subject: [PATCH 03/11] Support changed AccountKey auth protocol --- cmd/auth/create/create.go | 6 +- cmd/auth/status/status.go | 2 +- core/auth.go | 42 ++---- core/keyring.go | 44 +------ core/serviceprogram/serviceprogram.go | 2 +- go.mod | 57 ++++----- go.sum | 178 ++++++++++---------------- 7 files changed, 118 insertions(+), 213 deletions(-) diff --git a/cmd/auth/create/create.go b/cmd/auth/create/create.go index b306b0a..f135253 100644 --- a/cmd/auth/create/create.go +++ b/cmd/auth/create/create.go @@ -34,7 +34,7 @@ func NewCreateCmd() *cobra.Command { } } - botAccountKey, accountId, err := core.CreateBotWallet(name, rootPath, apiAddr) + accountKey, accountId, err := core.CreateBotWallet(name, rootPath, apiAddr) if err != nil { return output.Error("failed to create account: %w", err) } @@ -45,7 +45,7 @@ func NewCreateCmd() *cobra.Command { output.Info(" This is the ONLY way to authenticate your bot account.") output.Print("") - keyLen := len(botAccountKey) + keyLen := len(accountKey) boxWidth := keyLen + 4 // 2 spaces padding on each side if boxWidth < 24 { // Minimum width for "BOT ACCOUNT KEY" title boxWidth = 24 @@ -59,7 +59,7 @@ func NewCreateCmd() *cobra.Command { titlePadding := (boxWidth - len(title)) / 2 titleLine := "║" + strings.Repeat(" ", titlePadding) + title + strings.Repeat(" ", boxWidth-titlePadding-len(title)) + "║" - keyLine := fmt.Sprintf("║ %s ║", botAccountKey) + keyLine := fmt.Sprintf("║ %s ║", accountKey) output.Print(topBorder) output.Print(titleLine) diff --git a/cmd/auth/status/status.go b/cmd/auth/status/status.go index f727861..1f772dd 100644 --- a/cmd/auth/status/status.go +++ b/cmd/auth/status/status.go @@ -19,7 +19,7 @@ func NewStatusCmd() *cobra.Command { Long: "Display current authentication status, including account information, server status, and stored credentials.", RunE: func(cmd *cobra.Command, args []string) error { hasBotKey := false - if _, err := core.GetStoredBotAccountKey(); err == nil { + if _, err := core.GetStoredAccountKey(); err == nil { hasBotKey = true } diff --git a/core/auth.go b/core/auth.go index 890f053..bf55b8d 100644 --- a/core/auth.go +++ b/core/auth.go @@ -44,7 +44,7 @@ func getDefaultWorkDir() string { } // LoginBotAccount performs the login steps for a bot account using a bot account key. -func LoginBotAccount(botAccountKey, rootPath, apiAddr string) error { +func LoginBotAccount(accountKey, rootPath, apiAddr string) error { if rootPath == "" { rootPath = getDefaultDataPath() } @@ -68,7 +68,7 @@ func LoginBotAccount(botAccountKey, rootPath, apiAddr string) error { } resp2, err := client.WalletRecover(ctx, &pb.RpcWalletRecoverRequest{ - AccountKey: botAccountKey, + AccountKey: accountKey, RootPath: rootPath, }) if err != nil { @@ -79,8 +79,8 @@ func LoginBotAccount(botAccountKey, rootPath, apiAddr string) error { } resp3, err := client.WalletCreateSession(ctx, &pb.RpcWalletCreateSessionRequest{ - Auth: &pb.RpcWalletCreateSessionRequestAuthOf{ - AppKey: botAccountKey, + Auth: &pb.RpcWalletCreateSessionRequestAuthOfAccountKey{ + AccountKey: accountKey, }, }) if err != nil { @@ -174,7 +174,7 @@ func ValidateAccountKey(accountKey string) error { func LoginBot(accountKey, rootPath, apiAddr string) error { usedStoredKey := false if accountKey == "" { - storedKey, err := GetStoredBotAccountKey() + storedKey, err := GetStoredAccountKey() if err == nil && storedKey != "" { accountKey = storedKey output.Info("Using stored bot account key from keychain.") @@ -196,7 +196,7 @@ func LoginBot(accountKey, rootPath, apiAddr string) error { } if !usedStoredKey { - if err := SaveBotAccountKey(accountKey); err != nil { + if err := SaveAccountKey(accountKey); err != nil { output.Warning("failed to save bot account key in keychain: %v", err) } else { output.Success("Bot account key saved to keychain.") @@ -238,7 +238,7 @@ func Logout() error { return err } - if err := DeleteStoredBotAccountKey(); err != nil { + if err := DeleteStoredAccountKey(); err != nil { return fmt.Errorf("failed to delete stored bot account key: %w", err) } @@ -267,7 +267,7 @@ func CreateBotWallet(name, rootPath, apiAddr string) (string, string, error) { } var sessionToken string - var mnemonic string + var accountKey string err := GRPCCallNoAuth(func(ctx context.Context, client service.ClientCommandsClient) error { _, err := client.InitialSetParameters(ctx, &pb.RpcInitialSetParametersRequest{ @@ -285,11 +285,11 @@ func CreateBotWallet(name, rootPath, apiAddr string) (string, string, error) { if err != nil { return fmt.Errorf("wallet creation failed: %w", err) } - mnemonic = createResp.Mnemonic + accountKey = createResp.AccountKey sessionResp, err := client.WalletCreateSession(ctx, &pb.RpcWalletCreateSessionRequest{ - Auth: &pb.RpcWalletCreateSessionRequestAuthOfMnemonic{ - Mnemonic: mnemonic, + Auth: &pb.RpcWalletCreateSessionRequestAuthOfAccountKey{ + AccountKey: accountKey, }, }) if err != nil { @@ -349,23 +349,7 @@ func CreateBotWallet(name, rootPath, apiAddr string) (string, string, error) { return "", "", err } - var botAccountKey string - err = GRPCCall(func(ctx context.Context, client service.ClientCommandsClient) error { - resp, err := client.WalletExportBot(ctx, &pb.RpcWalletExportBotRequest{ - Mnemonic: mnemonic, - Index: 0, // Use index 0 for the first bot account - }) - if err != nil { - return fmt.Errorf("failed to export bot account key: %w", err) - } - botAccountKey = resp.AccountKey - return nil - }) - if err != nil { - return "", "", err - } - - if err := SaveBotAccountKey(botAccountKey); err != nil { + if err := SaveAccountKey(accountKey); err != nil { output.Warning("failed to save bot account key: %v", err) } @@ -382,5 +366,5 @@ func CreateBotWallet(name, rootPath, apiAddr string) (string, string, error) { } } - return botAccountKey, accountId, nil + return accountKey, accountId, nil } diff --git a/core/keyring.go b/core/keyring.go index 5416015..92df1f0 100644 --- a/core/keyring.go +++ b/core/keyring.go @@ -1,17 +1,13 @@ package core import ( - "encoding/base64" - "strings" - - "github.com/anyproto/anytype-cli/core/output" "github.com/zalando/go-keyring" ) const ( keyringService = "anytype-cli" keyringTokenUser = "session-token" - keyringBotAccountUser = "bot-account-key" + keyringBotAccountUser = "account-key" ) func SaveToken(token string) error { @@ -19,49 +15,21 @@ func SaveToken(token string) error { } func GetStoredToken() (string, error) { - token, err := keyring.Get(keyringService, keyringTokenUser) - if err != nil { - return "", err - } - output.Info("Retrieved token from keyring %q", token) - // Handle go-keyring base64 encoding that may be added on some platforms - if strings.HasPrefix(token, "go-keyring-base64:") { - encoded := strings.TrimPrefix(token, "go-keyring-base64:") - decoded, err := base64.StdEncoding.DecodeString(encoded) - if err != nil { - return "", err - } - token = string(decoded) - } - return token, nil + return keyring.Get(keyringService, keyringTokenUser) } func DeleteStoredToken() error { return keyring.Delete(keyringService, keyringTokenUser) } -func SaveBotAccountKey(accountKey string) error { +func SaveAccountKey(accountKey string) error { return keyring.Set(keyringService, keyringBotAccountUser, accountKey) } -func GetStoredBotAccountKey() (string, error) { - key, err := keyring.Get(keyringService, keyringBotAccountUser) - if err != nil { - return "", err - } - output.Info("Retrieved key from keyring %q", key) - // Handle go-keyring base64 encoding that may be added on some platforms - if strings.HasPrefix(key, "go-keyring-base64:") { - encoded := strings.TrimPrefix(key, "go-keyring-base64:") - decoded, err := base64.StdEncoding.DecodeString(encoded) - if err != nil { - return "", err - } - key = string(decoded) - } - return key, nil +func GetStoredAccountKey() (string, error) { + return keyring.Get(keyringService, keyringBotAccountUser) } -func DeleteStoredBotAccountKey() error { +func DeleteStoredAccountKey() error { return keyring.Delete(keyringService, keyringBotAccountUser) } diff --git a/core/serviceprogram/serviceprogram.go b/core/serviceprogram/serviceprogram.go index 32bf4c2..02d3431 100644 --- a/core/serviceprogram/serviceprogram.go +++ b/core/serviceprogram/serviceprogram.go @@ -89,7 +89,7 @@ func (p *Program) run() { } func (p *Program) attemptAutoLogin() { - botAccountKey, err := core.GetStoredBotAccountKey() + botAccountKey, err := core.GetStoredAccountKey() if err != nil || botAccountKey == "" { output.Info("No stored bot account key found, skipping auto-login") return diff --git a/go.mod b/go.mod index 7a9d410..dcf78f8 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,8 @@ module github.com/anyproto/anytype-cli go 1.24.6 require ( - github.com/anyproto/any-sync v0.10.3-0.20250924192345-ac39daeebf86 - github.com/anyproto/anytype-heart v0.48.18-hotfix-1.0.20250924201504-831824ca3128 + github.com/anyproto/any-sync v0.11.2-0.20251028122509-60b4b25dd9f1 + github.com/anyproto/anytype-heart v0.44.7-0.20251028140914-4ac7e6ade68d github.com/cheggaaa/mb/v3 v3.0.2 github.com/chzyer/readline v1.5.1 github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 @@ -13,14 +13,13 @@ require ( github.com/kardianos/service v1.2.4 github.com/spf13/cobra v1.9.1 github.com/zalando/go-keyring v0.2.6 - google.golang.org/grpc v1.74.2 + google.golang.org/grpc v1.75.0 ) require ( al.essio.dev/pkg/shellescape v1.6.0 // indirect filippo.io/edwards25519 v1.1.0 // indirect github.com/JohannesKaufmann/html-to-markdown v1.6.0 // indirect - github.com/Jorropo/jsync v1.0.1 // indirect github.com/KyleBanks/depth v1.2.1 // indirect github.com/PuerkitoBio/goquery v1.10.2 // indirect github.com/VividCortex/ewma v1.2.0 // indirect @@ -28,7 +27,7 @@ require ( github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b // indirect github.com/alexbrainman/goissue34681 v0.0.0-20191006012335-3fc7a47baff5 // indirect github.com/andybalholm/cascadia v1.3.3 // indirect - github.com/anyproto/any-store v0.3.8 // indirect + github.com/anyproto/any-store v0.4.2 // indirect github.com/anyproto/anytype-publish-server/publishclient v0.0.0-20250716122732-cdcfe3a126bb // indirect github.com/anyproto/anytype-push-server/pushclient v0.0.0-20250801122506-553f6c085a23 // indirect github.com/anyproto/go-chash v0.1.0 // indirect @@ -76,7 +75,8 @@ require ( github.com/ethereum/go-ethereum v1.13.15 // indirect github.com/flopp/go-findfont v0.1.0 // indirect github.com/fogleman/gg v1.3.0 // indirect - github.com/gabriel-vasile/mimetype v1.4.9 // indirect + github.com/gabriel-vasile/mimetype v1.4.10 // indirect + github.com/gammazero/chanqueue v1.1.1 // indirect github.com/gammazero/deque v1.1.0 // indirect github.com/gin-contrib/sse v0.1.0 // indirect github.com/gin-gonic/gin v1.10.0 // indirect @@ -131,13 +131,15 @@ require ( github.com/iancoleman/strcase v0.3.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/ipfs/bbloom v0.0.4 // indirect - github.com/ipfs/boxo v0.34.0 // indirect + github.com/ipfs/boxo v0.35.0 // indirect github.com/ipfs/go-bitfield v1.1.0 // indirect - github.com/ipfs/go-block-format v0.2.2 // indirect + github.com/ipfs/go-block-format v0.2.3 // indirect github.com/ipfs/go-cid v0.5.0 // indirect - github.com/ipfs/go-datastore v0.8.3 // indirect + github.com/ipfs/go-cidutil v0.1.0 // indirect + github.com/ipfs/go-datastore v0.9.0 // indirect github.com/ipfs/go-ds-flatfs v0.5.5 // indirect - github.com/ipfs/go-ipld-format v0.6.2 // indirect + github.com/ipfs/go-dsqueue v0.0.5 // indirect + github.com/ipfs/go-ipld-format v0.6.3 // indirect github.com/ipfs/go-ipld-legacy v0.2.2 // indirect github.com/ipfs/go-log v1.0.5 // indirect github.com/ipfs/go-log/v2 v2.8.1 // indirect @@ -155,9 +157,7 @@ require ( github.com/kovidgoyal/imaging v1.6.4 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect - github.com/libp2p/go-libp2p v0.43.0 // indirect - github.com/libp2p/go-libp2p-record v0.3.1 // indirect - github.com/libp2p/go-libp2p-routing-helpers v0.7.5 // indirect + github.com/libp2p/go-libp2p v0.44.0 // indirect github.com/libp2p/zeroconf/v2 v2.2.0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/mailru/easyjson v0.7.7 // indirect @@ -198,7 +198,7 @@ require ( github.com/prometheus/client_model v0.6.2 // indirect github.com/prometheus/common v0.66.1 // indirect github.com/prometheus/procfs v0.17.0 // indirect - github.com/quic-go/quic-go v0.54.0 // indirect + github.com/quic-go/quic-go v0.55.0 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/rs/cors v1.11.0 // indirect github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd // indirect @@ -232,28 +232,27 @@ require ( go.abhg.dev/goldmark/wikilink v0.6.0 // indirect go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect - go.opentelemetry.io/otel v1.37.0 // indirect - go.opentelemetry.io/otel/metric v1.37.0 // indirect - go.opentelemetry.io/otel/trace v1.37.0 // indirect + go.opentelemetry.io/otel v1.38.0 // indirect + go.opentelemetry.io/otel/metric v1.38.0 // indirect + go.opentelemetry.io/otel/trace v1.38.0 // indirect go.uber.org/atomic v1.11.0 // indirect - go.uber.org/mock v0.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect golang.org/x/arch v0.8.0 // indirect - golang.org/x/crypto v0.42.0 // indirect - golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b // indirect + golang.org/x/crypto v0.43.0 // indirect + golang.org/x/exp v0.0.0-20250911091902-df9299821621 // indirect golang.org/x/image v0.27.0 // indirect - golang.org/x/mod v0.28.0 // indirect - golang.org/x/net v0.44.0 // indirect - golang.org/x/oauth2 v0.30.0 // indirect + golang.org/x/mod v0.29.0 // indirect + golang.org/x/net v0.46.0 // indirect + golang.org/x/oauth2 v0.31.0 // indirect golang.org/x/sync v0.17.0 // indirect - golang.org/x/sys v0.36.0 // indirect - golang.org/x/text v0.29.0 // indirect - golang.org/x/time v0.13.0 // indirect - golang.org/x/tools v0.37.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250804133106-a7a43d27e69b // indirect - google.golang.org/protobuf v1.36.9 // indirect + golang.org/x/sys v0.37.0 // indirect + golang.org/x/text v0.30.0 // indirect + golang.org/x/time v0.14.0 // indirect + golang.org/x/tools v0.38.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 // indirect + google.golang.org/protobuf v1.36.10 // indirect gopkg.in/Graylog2/go-gelf.v2 v2.0.0-20191017102106-1550ee647df0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index 2a6e9a4..aea289a 100644 --- a/go.sum +++ b/go.sum @@ -7,8 +7,6 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/Jorropo/jsync v1.0.1 h1:6HgRolFZnsdfzRUj+ImB9og1JYOxQoReSywkHOGSaUU= -github.com/Jorropo/jsync v1.0.1/go.mod h1:jCOZj3vrBCri3bSU3ErUYvevKlnbssrXeCivybS5ABQ= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= @@ -38,12 +36,12 @@ github.com/alexbrainman/goissue34681 v0.0.0-20191006012335-3fc7a47baff5/go.mod h github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA= github.com/andybalholm/cascadia v1.3.3 h1:AG2YHrzJIm4BZ19iwJ/DAua6Btl3IwJX+VI4kktS1LM= github.com/andybalholm/cascadia v1.3.3/go.mod h1:xNd9bqTn98Ln4DwST8/nG+H0yuB8Hmgu1YHNnWw0GeA= -github.com/anyproto/any-store v0.3.8 h1:s499vEwfAUVHZ0NpN/AliG94g2QwqUHTCrbSl27VXRk= -github.com/anyproto/any-store v0.3.8/go.mod h1:P9CnoL9Q06eh051DwtcvCiiWCwdXO7AbEILcnD6yrss= -github.com/anyproto/any-sync v0.10.3-0.20250924192345-ac39daeebf86 h1:UzxlCEshfjtFmAh6hoKHCXNDZg94/EoO4xvYuzflLq4= -github.com/anyproto/any-sync v0.10.3-0.20250924192345-ac39daeebf86/go.mod h1:cRDgI+U2nXZC2PXXSCKS2FCHWEBurH7TyELOOkgDblQ= -github.com/anyproto/anytype-heart v0.48.18-hotfix-1.0.20250924201504-831824ca3128 h1:dXTF3Oj/JYqavxYWD6/nAHf9WATQeaBpEfbNze2HE4s= -github.com/anyproto/anytype-heart v0.48.18-hotfix-1.0.20250924201504-831824ca3128/go.mod h1:Uq9G8qiHekx/B41a1HYCXxZQEaNen43ac/mvh8oiSvc= +github.com/anyproto/any-store v0.4.2 h1:1ljcAogeZxQ6QmSpBy40InokgKBRB/fnAilDDFPUpYE= +github.com/anyproto/any-store v0.4.2/go.mod h1:P9CnoL9Q06eh051DwtcvCiiWCwdXO7AbEILcnD6yrss= +github.com/anyproto/any-sync v0.11.2-0.20251028122509-60b4b25dd9f1 h1:OwuaA0i4yUKqWk3TLV6kFB25EjCa3xEjj3O14+HHp1k= +github.com/anyproto/any-sync v0.11.2-0.20251028122509-60b4b25dd9f1/go.mod h1:fX0zyqrV9h7LFxH4eYPEAAdTfll+55hWJzx81qgBbh8= +github.com/anyproto/anytype-heart v0.44.7-0.20251028140914-4ac7e6ade68d h1:9NN6EpxFjE65uhjmUSL/UH+RAEkkkfY7IOfMHvtm21A= +github.com/anyproto/anytype-heart v0.44.7-0.20251028140914-4ac7e6ade68d/go.mod h1:yzDgR58Yt61nnRQCumVsPvqNq2sDHck9l7cgwh9kDLU= github.com/anyproto/anytype-publish-server/publishclient v0.0.0-20250716122732-cdcfe3a126bb h1:X1os44y0QWf1mYGj8BOoYKlXwY5xb94xTQIw1IIKJbY= github.com/anyproto/anytype-publish-server/publishclient v0.0.0-20250716122732-cdcfe3a126bb/go.mod h1:OzzODq4OigiRVD2lSOX1iHAoLcxhJDRbZb8n5PLG3WE= github.com/anyproto/anytype-push-server/pushclient v0.0.0-20250801122506-553f6c085a23 h1:jXAjKY4g9ec7lDtayIlzM9u0/b3xGS9YgGA6JtRhHfU= @@ -235,19 +233,15 @@ github.com/filecoin-project/go-clock v0.1.0 h1:SFbYIM75M8NnFm1yMHhN9Ahy3W5bEZV9g github.com/filecoin-project/go-clock v0.1.0/go.mod h1:4uB/O4PvOjlx1VCMdZ9MyDZXRm//gkj1ELEbxfI1AZs= github.com/flopp/go-findfont v0.1.0 h1:lPn0BymDUtJo+ZkV01VS3661HL6F4qFlkhcJN55u6mU= github.com/flopp/go-findfont v0.1.0/go.mod h1:wKKxRDjD024Rh7VMwoU90i6ikQRCr+JTHB5n4Ejkqvw= -github.com/flynn/noise v1.1.0 h1:KjPQoQCEFdZDiP03phOvGi11+SVVhBG2wOWAorLsstg= -github.com/flynn/noise v1.1.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8= github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= -github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= -github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBvAG7U/oYY= -github.com/gabriel-vasile/mimetype v1.4.9/go.mod h1:WnSQhFKJuBlRyLiKohA/2DtIlPFAbguNaG7QCHcyGok= +github.com/gabriel-vasile/mimetype v1.4.10 h1:zyueNbySn/z8mJZHLt6IPw0KoZsiQNszIpU+bX4+ZK0= +github.com/gabriel-vasile/mimetype v1.4.10/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s= github.com/gammazero/chanqueue v1.1.1 h1:n9Y+zbBxw2f7uUE9wpgs0rOSkP/I/yhDLiNuhyVjojQ= github.com/gammazero/chanqueue v1.1.1/go.mod h1:fMwpwEiuUgpab0sH4VHiVcEoji1pSi+EIzeG4TPeKPc= github.com/gammazero/deque v1.1.0 h1:OyiyReBbnEG2PP0Bnv1AASLIYvyKqIFN5xfl1t8oGLo= @@ -402,8 +396,6 @@ github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= -github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= @@ -486,24 +478,28 @@ github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLf github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs= github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0= -github.com/ipfs/boxo v0.34.0 h1:pMP9bAsTs4xVh8R0ZmxIWviV7kjDa60U24QrlGgHb1g= -github.com/ipfs/boxo v0.34.0/go.mod h1:kzdH/ewDybtO3+M8MCVkpwnIIc/d2VISX95DFrY4vQA= +github.com/ipfs/boxo v0.35.0 h1:3Mku5arSbAZz0dvb4goXRsQuZkFkPrGr5yYdu0YM1pY= +github.com/ipfs/boxo v0.35.0/go.mod h1:uhaF0DGnbgEiXDTmD249jCGbxVkMm6+Ew85q6Uub7lo= github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA= github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU= -github.com/ipfs/go-block-format v0.2.2 h1:uecCTgRwDIXyZPgYspaLXoMiMmxQpSx2aq34eNc4YvQ= -github.com/ipfs/go-block-format v0.2.2/go.mod h1:vmuefuWU6b+9kIU0vZJgpiJt1yicQz9baHXE8qR+KB8= +github.com/ipfs/go-block-format v0.2.3 h1:mpCuDaNXJ4wrBJLrtEaGFGXkferrw5eqVvzaHhtFKQk= +github.com/ipfs/go-block-format v0.2.3/go.mod h1:WJaQmPAKhD3LspLixqlqNFxiZ3BZ3xgqxxoSR/76pnA= github.com/ipfs/go-cid v0.5.0 h1:goEKKhaGm0ul11IHA7I6p1GmKz8kEYniqFopaB5Otwg= github.com/ipfs/go-cid v0.5.0/go.mod h1:0L7vmeNXpQpUS9vt+yEARkJ8rOg43DF3iPgn4GIN0mk= -github.com/ipfs/go-datastore v0.8.3 h1:z391GsQyGKUIUof2tPoaZVeDknbt7fNHs6Gqjcw5Jo4= -github.com/ipfs/go-datastore v0.8.3/go.mod h1:raxQ/CreIy9L6MxT71ItfMX12/ASN6EhXJoUFjICQ2M= +github.com/ipfs/go-cidutil v0.1.0 h1:RW5hO7Vcf16dplUU60Hs0AKDkQAVPVplr7lk97CFL+Q= +github.com/ipfs/go-cidutil v0.1.0/go.mod h1:e7OEVBMIv9JaOxt9zaGEmAoSlXW9jdFZ5lP/0PwcfpA= +github.com/ipfs/go-datastore v0.9.0 h1:WocriPOayqalEsueHv6SdD4nPVl4rYMfYGLD4bqCZ+w= +github.com/ipfs/go-datastore v0.9.0/go.mod h1:uT77w/XEGrvJWwHgdrMr8bqCN6ZTW9gzmi+3uK+ouHg= github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk= github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps= +github.com/ipfs/go-dsqueue v0.0.5 h1:TUOk15TlCJ/NKV8Yk2W5wgkEjDa44Nem7a7FGIjsMNU= +github.com/ipfs/go-dsqueue v0.0.5/go.mod h1:i/jAlpZjBbQJLioN+XKbFgnd+u9eAhGZs9IrqIzTd9g= github.com/ipfs/go-ipfs-delay v0.0.1 h1:r/UXYyRcddO6thwOnhiznIAiSvxMECGgtv35Xs1IeRQ= github.com/ipfs/go-ipfs-delay v0.0.1/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= github.com/ipfs/go-ipfs-pq v0.0.3 h1:YpoHVJB+jzK15mr/xsWC574tyDLkezVrDNeaalQBsTE= github.com/ipfs/go-ipfs-pq v0.0.3/go.mod h1:btNw5hsHBpRcSSgZtiNm/SLj5gYIZ18AKtv3kERkRb4= -github.com/ipfs/go-ipld-format v0.6.2 h1:bPZQ+A05ol0b3lsJSl0bLvwbuQ+HQbSsdGTy4xtYUkU= -github.com/ipfs/go-ipld-format v0.6.2/go.mod h1:nni2xFdHKx5lxvXJ6brt/pndtGxKAE+FPR1rg4jTkyk= +github.com/ipfs/go-ipld-format v0.6.3 h1:9/lurLDTotJpZSuL++gh3sTdmcFhVkCwsgx2+rAh4j8= +github.com/ipfs/go-ipld-format v0.6.3/go.mod h1:74ilVN12NXVMIV+SrBAyC05UJRk0jVvGqdmrcYZvCBk= github.com/ipfs/go-ipld-legacy v0.2.2 h1:DThbqCPVLpWBcGtU23KDLiY2YRZZnTkXQyfz8aOfBkQ= github.com/ipfs/go-ipld-legacy v0.2.2/go.mod h1:hhkj+b3kG9b2BcUNw8IFYAsfeNo8E3U7eYlWeAOPyDU= github.com/ipfs/go-log v1.0.5 h1:2dOuUCB1Z7uoczMWgAyDck5JLb72zHzrMnGnCNNbvY8= @@ -512,8 +508,10 @@ github.com/ipfs/go-metrics-interface v0.3.0 h1:YwG7/Cy4R94mYDUuwsBfeziJCVm9pBMJ6 github.com/ipfs/go-metrics-interface v0.3.0/go.mod h1:OxxQjZDGocXVdyTPocns6cOLwHieqej/jos7H4POwoY= github.com/ipfs/go-peertaskqueue v0.8.2 h1:PaHFRaVFdxQk1Qo3OKiHPYjmmusQy7gKQUaL8JDszAU= github.com/ipfs/go-peertaskqueue v0.8.2/go.mod h1:L6QPvou0346c2qPJNiJa6BvOibxDfaiPlqHInmzg0FA= -github.com/ipfs/go-test v0.2.2 h1:1yjYyfbdt1w93lVzde6JZ2einh3DIV40at4rVoyEcE8= -github.com/ipfs/go-test v0.2.2/go.mod h1:cmLisgVwkdRCnKu/CFZOk2DdhOcwghr5GsHeqwexoRA= +github.com/ipfs/go-test v0.2.3 h1:Z/jXNAReQFtCYyn7bsv/ZqUwS6E7iIcSpJ2CuzCvnrc= +github.com/ipfs/go-test v0.2.3/go.mod h1:QW8vSKkwYvWFwIZQLGQXdkt9Ud76eQXRQ9Ao2H+cA1o= +github.com/ipfs/go-unixfsnode v1.10.2 h1:TREegX1J4X+k1w4AhoDuxxFvVcS9SegMRvrmxF6Tca8= +github.com/ipfs/go-unixfsnode v1.10.2/go.mod h1:ImDPTSiKZ+2h4UVdkSDITJHk87bUAp7kX/lgifjRicg= github.com/ipld/go-codec-dagpb v1.7.0 h1:hpuvQjCSVSLnTnHXn+QAMR0mLmb1gA6wl10LExo2Ts0= github.com/ipld/go-codec-dagpb v1.7.0/go.mod h1:rD3Zg+zub9ZnxcLwfol/OTQRVjaLzXypgy4UqHQvilM= github.com/ipld/go-ipld-prime v0.21.0 h1:n4JmcpOlPDIxBcY037SVfpd1G+Sj1nKZah0m6QH9C2E= @@ -588,20 +586,18 @@ github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6 github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= github.com/libp2p/go-flow-metrics v0.3.0 h1:q31zcHUvHnwDO0SHaukewPYgwOBSxtt830uJtUx6784= github.com/libp2p/go-flow-metrics v0.3.0/go.mod h1:nuhlreIwEguM1IvHAew3ij7A8BMlyHQJ279ao24eZZo= -github.com/libp2p/go-libp2p v0.43.0 h1:b2bg2cRNmY4HpLK8VHYQXLX2d3iND95OjodLFymvqXU= -github.com/libp2p/go-libp2p v0.43.0/go.mod h1:IiSqAXDyP2sWH+J2gs43pNmB/y4FOi2XQPbsb+8qvzc= +github.com/libp2p/go-libp2p v0.44.0 h1:5Gtt8OrF8yiXmH+Mx4+/iBeFRMK1TY3a8OrEBDEqAvs= +github.com/libp2p/go-libp2p v0.44.0/go.mod h1:NovCojezAt4dnDd4fH048K7PKEqH0UFYYqJRjIIu8zc= github.com/libp2p/go-libp2p-asn-util v0.4.1 h1:xqL7++IKD9TBFMgnLPZR6/6iYhawHKHl950SO9L6n94= github.com/libp2p/go-libp2p-asn-util v0.4.1/go.mod h1:d/NI6XZ9qxw67b4e+NgpQexCIiFYJjErASrYW4PFDN8= github.com/libp2p/go-libp2p-record v0.3.1 h1:cly48Xi5GjNw5Wq+7gmjfBiG9HCzQVkiZOUZ8kUl+Fg= github.com/libp2p/go-libp2p-record v0.3.1/go.mod h1:T8itUkLcWQLCYMqtX7Th6r7SexyUJpIyPgks757td/E= -github.com/libp2p/go-libp2p-routing-helpers v0.7.5 h1:HdwZj9NKovMx0vqq6YNPTh6aaNzey5zHD7HeLJtq6fI= -github.com/libp2p/go-libp2p-routing-helpers v0.7.5/go.mod h1:3YaxrwP0OBPDD7my3D0KxfR89FlcX/IEbxDEDfAmj98= github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA= github.com/libp2p/go-libp2p-testing v0.12.0/go.mod h1:KcGDRXyN7sQCllucn1cOOS+Dmm7ujhfEyXQL5lvkcPg= github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0= github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM= -github.com/libp2p/go-netroute v0.2.2 h1:Dejd8cQ47Qx2kRABg6lPwknU7+nBnFRpko45/fFPuZ8= -github.com/libp2p/go-netroute v0.2.2/go.mod h1:Rntq6jUAH0l9Gg17w5bFGhcC9a+vk4KNXs6s7IljKYE= +github.com/libp2p/go-netroute v0.3.0 h1:nqPCXHmeNmgTJnktosJ/sIef9hvwYCrsLxXmfNks/oc= +github.com/libp2p/go-netroute v0.3.0/go.mod h1:Nkd5ShYgSMS5MUKy/MU2T57xFoOKvvLR92Lic48LEyA= github.com/libp2p/go-yamux/v5 v5.0.1 h1:f0WoX/bEF2E8SbE4c/k1Mo+/9z0O4oC/hWEA+nfYRSg= github.com/libp2p/go-yamux/v5 v5.0.1/go.mod h1:en+3cdX51U0ZslwRdRLrvQsdayFt3TSUKvBGErzpWbU= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= @@ -738,44 +734,6 @@ github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 h1:Dx7Ovyv/SFnMFw github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= -github.com/pion/datachannel v1.5.10 h1:ly0Q26K1i6ZkGf42W7D4hQYR90pZwzFOjTq5AuCKk4o= -github.com/pion/datachannel v1.5.10/go.mod h1:p/jJfC9arb29W7WrxyKbepTU20CFgyx5oLo8Rs4Py/M= -github.com/pion/dtls/v2 v2.2.12 h1:KP7H5/c1EiVAAKUmXyCzPiQe5+bCJrpOeKg/L05dunk= -github.com/pion/dtls/v2 v2.2.12/go.mod h1:d9SYc9fch0CqK90mRk1dC7AkzzpwJj6u2GU3u+9pqFE= -github.com/pion/dtls/v3 v3.0.6 h1:7Hkd8WhAJNbRgq9RgdNh1aaWlZlGpYTzdqjy9x9sK2E= -github.com/pion/dtls/v3 v3.0.6/go.mod h1:iJxNQ3Uhn1NZWOMWlLxEEHAN5yX7GyPvvKw04v9bzYU= -github.com/pion/ice/v4 v4.0.10 h1:P59w1iauC/wPk9PdY8Vjl4fOFL5B+USq1+xbDcN6gT4= -github.com/pion/ice/v4 v4.0.10/go.mod h1:y3M18aPhIxLlcO/4dn9X8LzLLSma84cx6emMSu14FGw= -github.com/pion/interceptor v0.1.40 h1:e0BjnPcGpr2CFQgKhrQisBU7V3GXK6wrfYrGYaU6Jq4= -github.com/pion/interceptor v0.1.40/go.mod h1:Z6kqH7M/FYirg3frjGJ21VLSRJGBXB/KqaTIrdqnOic= -github.com/pion/logging v0.2.3 h1:gHuf0zpoh1GW67Nr6Gj4cv5Z9ZscU7g/EaoC/Ke/igI= -github.com/pion/logging v0.2.3/go.mod h1:z8YfknkquMe1csOrxK5kc+5/ZPAzMxbKLX5aXpbpC90= -github.com/pion/mdns/v2 v2.0.7 h1:c9kM8ewCgjslaAmicYMFQIde2H9/lrZpjBkN8VwoVtM= -github.com/pion/mdns/v2 v2.0.7/go.mod h1:vAdSYNAT0Jy3Ru0zl2YiW3Rm/fJCwIeM0nToenfOJKA= -github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA= -github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8= -github.com/pion/rtcp v1.2.15 h1:LZQi2JbdipLOj4eBjK4wlVoQWfrZbh3Q6eHtWtJBZBo= -github.com/pion/rtcp v1.2.15/go.mod h1:jlGuAjHMEXwMUHK78RgX0UmEJFV4zUKOFHR7OP+D3D0= -github.com/pion/rtp v1.8.19 h1:jhdO/3XhL/aKm/wARFVmvTfq0lC/CvN1xwYKmduly3c= -github.com/pion/rtp v1.8.19/go.mod h1:bAu2UFKScgzyFqvUKmbvzSdPr+NGbZtv6UB2hesqXBk= -github.com/pion/sctp v1.8.39 h1:PJma40vRHa3UTO3C4MyeJDQ+KIobVYRZQZ0Nt7SjQnE= -github.com/pion/sctp v1.8.39/go.mod h1:cNiLdchXra8fHQwmIoqw0MbLLMs+f7uQ+dGMG2gWebE= -github.com/pion/sdp/v3 v3.0.13 h1:uN3SS2b+QDZnWXgdr69SM8KB4EbcnPnPf2Laxhty/l4= -github.com/pion/sdp/v3 v3.0.13/go.mod h1:88GMahN5xnScv1hIMTqLdu/cOcUkj6a9ytbncwMCq2E= -github.com/pion/srtp/v3 v3.0.6 h1:E2gyj1f5X10sB/qILUGIkL4C2CqK269Xq167PbGCc/4= -github.com/pion/srtp/v3 v3.0.6/go.mod h1:BxvziG3v/armJHAaJ87euvkhHqWe9I7iiOy50K2QkhY= -github.com/pion/stun v0.6.1 h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4= -github.com/pion/stun v0.6.1/go.mod h1:/hO7APkX4hZKu/D0f2lHzNyvdkTGtIy3NDmLR7kSz/8= -github.com/pion/stun/v3 v3.0.0 h1:4h1gwhWLWuZWOJIJR9s2ferRO+W3zA/b6ijOI6mKzUw= -github.com/pion/stun/v3 v3.0.0/go.mod h1:HvCN8txt8mwi4FBvS3EmDghW6aQJ24T+y+1TKjB5jyU= -github.com/pion/transport/v2 v2.2.10 h1:ucLBLE8nuxiHfvkFKnkDQRYWYfp8ejf4YBOPfaQpw6Q= -github.com/pion/transport/v2 v2.2.10/go.mod h1:sq1kSLWs+cHW9E+2fJP95QudkzbK7wscs8yYgQToO5E= -github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1o0= -github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo= -github.com/pion/turn/v4 v4.0.2 h1:ZqgQ3+MjP32ug30xAbD6Mn+/K4Sxi3SdNOTFf+7mpps= -github.com/pion/turn/v4 v4.0.2/go.mod h1:pMMKP/ieNAG/fN5cZiN4SDuyKsXtNTr0ccN7IToA1zs= -github.com/pion/webrtc/v4 v4.1.2 h1:mpuUo/EJ1zMNKGE79fAdYNFZBX790KE7kQQpLMjjR54= -github.com/pion/webrtc/v4 v4.1.2/go.mod h1:xsCXiNAmMEjIdFxAYU0MbB3RwRieJsegSB2JZsGN+8U= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -820,12 +778,8 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.17.0 h1:FuLQ+05u4ZI+SS/w9+BWEM2TXiHKsUQ9TADiRH7DuK0= github.com/prometheus/procfs v0.17.0/go.mod h1:oPQLaDAMRbA+u8H5Pbfq+dl3VDAvHxMUOVhe0wYB2zw= -github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI= -github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg= -github.com/quic-go/quic-go v0.54.0 h1:6s1YB9QotYI6Ospeiguknbp2Znb/jZYjZLRXn9kMQBg= -github.com/quic-go/quic-go v0.54.0/go.mod h1:e68ZEaCdyviluZmy44P6Iey98v/Wfz6HCjQEm+l8zTY= -github.com/quic-go/webtransport-go v0.9.0 h1:jgys+7/wm6JarGDrW+lD/r9BGqBAmqY/ssklE09bA70= -github.com/quic-go/webtransport-go v0.9.0/go.mod h1:4FUYIiUc75XSsF6HShcLeXXYZJ9AGwo/xh3L8M/P1ao= +github.com/quic-go/quic-go v0.55.0 h1:zccPQIqYCXDt5NmcEabyYvOnomjs8Tlwl7tISjJh9Mk= +github.com/quic-go/quic-go v0.55.0/go.mod h1:DR51ilwU1uE164KuWXhinFcKWGlEjzys2l8zUl5Ss1U= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= @@ -941,8 +895,6 @@ github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0 h1:GDDkbFiaK8jsSD github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f h1:jQa4QT2UP9WYv2nzyawpKMOCl+Z/jW7djv2/J50lj9E= github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f/go.mod h1:p9UJB6dDgdPgMJZs7UjUOdulKyRr9fqkS+6JKAInPy8= -github.com/wlynxg/anet v0.0.5 h1:J3VJGi1gvo0JwZ/P1/Yc/8p63SoW98B5dHkYDmpgvvU= -github.com/wlynxg/anet v0.0.5/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= @@ -980,16 +932,16 @@ go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= -go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= -go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE= -go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E= -go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI= -go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg= -go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis= -go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4= -go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= -go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= +go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8= +go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM= +go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA= +go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI= +go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E= +go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg= +go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc= +go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps= +go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE= +go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= @@ -1036,13 +988,13 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= -golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI= -golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8= +golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04= +golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= -golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b h1:DXr+pvt3nC887026GRP39Ej11UATqWDmWuS99x26cD0= -golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b/go.mod h1:4QTo5u+SEIbbKW1RacMZq1YEfOBqeXa19JeshGi+zc4= +golang.org/x/exp v0.0.0-20250911091902-df9299821621 h1:2id6c1/gto0kaHYyrixvknJ8tUK/Qs5IsmBtrc+FtgU= +golang.org/x/exp v0.0.0-20250911091902-df9299821621/go.mod h1:TwQYMMnGpvZyc+JpB/UAuTNIsVJifOlSkrZkhcvpVUk= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -1065,8 +1017,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U= -golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI= +golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA= +golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1110,13 +1062,13 @@ golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= -golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I= -golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= +golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4= +golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= -golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= +golang.org/x/oauth2 v0.31.0 h1:8Fq0yVZLh4j4YA47vHKFTa9Ew5XIrCP8LC6UeNZnLxo= +golang.org/x/oauth2 v0.31.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1187,8 +1139,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= -golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= +golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -1211,12 +1163,12 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= -golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= +golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= +golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.13.0 h1:eUlYslOIt32DgYD6utsuUeHs4d7AsEYLuIAdg7FlYgI= -golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= +golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI= +golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1241,12 +1193,14 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= -golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE= -golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w= +golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ= +golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= +gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1260,8 +1214,8 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98 google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250804133106-a7a43d27e69b h1:zPKJod4w6F1+nRGDI9ubnXYhU9NSWoFAijkHkUXeTK8= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250804133106-a7a43d27e69b/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 h1:eaY8u2EuxbRv7c3NiGK0/NedzVsCcV6hDuU5qPX5EGE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5/go.mod h1:M4/wBTSeyLxupu3W3tJtOgB14jILAS/XWPSSa3TAlJc= google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -1277,8 +1231,8 @@ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8 google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4= -google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM= +google.golang.org/grpc v1.75.0 h1:+TW+dqTd2Biwe6KKfhE5JpiYIBWq865PhKGSXiivqt4= +google.golang.org/grpc v1.75.0/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1289,8 +1243,8 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw= -google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From 06ec57fd96f7ae17b58e65c052c5b74bacda845b Mon Sep 17 00:00:00 2001 From: Jannis Metrikat <120120832+jmetrikat@users.noreply.github.com> Date: Thu, 30 Oct 2025 23:42:38 +0100 Subject: [PATCH 04/11] Improve error messages on exactArgs requirement --- cmd/auth/apikey/create/create.go | 3 ++- cmd/auth/apikey/revoke/revoke.go | 3 ++- cmd/cmdutil/args.go | 19 +++++++++++++++++++ cmd/config/set/set.go | 6 ++++-- cmd/space/join/join.go | 7 ++++--- cmd/space/leave/leave.go | 3 ++- 6 files changed, 33 insertions(+), 8 deletions(-) create mode 100644 cmd/cmdutil/args.go diff --git a/cmd/auth/apikey/create/create.go b/cmd/auth/apikey/create/create.go index b32d375..8bbe46f 100644 --- a/cmd/auth/apikey/create/create.go +++ b/cmd/auth/apikey/create/create.go @@ -3,6 +3,7 @@ package create import ( "github.com/spf13/cobra" + "github.com/anyproto/anytype-cli/cmd/cmdutil" "github.com/anyproto/anytype-cli/core" "github.com/anyproto/anytype-cli/core/output" ) @@ -12,7 +13,7 @@ func NewCreateCmd() *cobra.Command { Use: "create [name]", Short: "Create a new API key", Long: "Create a new API key for programmatic access to Anytype", - Args: cobra.ExactArgs(1), + Args: cmdutil.ExactArgs(1, "cannot create API key: name argument required"), RunE: func(cmd *cobra.Command, args []string) error { name := args[0] diff --git a/cmd/auth/apikey/revoke/revoke.go b/cmd/auth/apikey/revoke/revoke.go index b8aad78..780a492 100644 --- a/cmd/auth/apikey/revoke/revoke.go +++ b/cmd/auth/apikey/revoke/revoke.go @@ -3,6 +3,7 @@ package revoke import ( "github.com/spf13/cobra" + "github.com/anyproto/anytype-cli/cmd/cmdutil" "github.com/anyproto/anytype-cli/core" "github.com/anyproto/anytype-cli/core/output" ) @@ -12,7 +13,7 @@ func NewRevokeCmd() *cobra.Command { Use: "revoke ", Short: "Revoke an API key", Long: "Revoke an API key by its Id", - Args: cobra.ExactArgs(1), + Args: cmdutil.ExactArgs(1, "cannot revoke API key: Id argument required"), RunE: func(cmd *cobra.Command, args []string) error { appId := args[0] diff --git a/cmd/cmdutil/args.go b/cmd/cmdutil/args.go new file mode 100644 index 0000000..76ffd3f --- /dev/null +++ b/cmd/cmdutil/args.go @@ -0,0 +1,19 @@ +package cmdutil + +import ( + "fmt" + + "github.com/spf13/cobra" +) + +func ExactArgs(n int, msg string) cobra.PositionalArgs { + return func(cmd *cobra.Command, args []string) error { + if len(args) > n { + return fmt.Errorf("too many arguments") + } + if len(args) < n { + return fmt.Errorf("%s", msg) + } + return nil + } +} diff --git a/cmd/config/set/set.go b/cmd/config/set/set.go index 09a90f4..114a6a6 100644 --- a/cmd/config/set/set.go +++ b/cmd/config/set/set.go @@ -1,9 +1,11 @@ package set import ( + "github.com/spf13/cobra" + + "github.com/anyproto/anytype-cli/cmd/cmdutil" "github.com/anyproto/anytype-cli/core/config" "github.com/anyproto/anytype-cli/core/output" - "github.com/spf13/cobra" ) func NewSetCmd() *cobra.Command { @@ -11,7 +13,7 @@ func NewSetCmd() *cobra.Command { Use: "set ", Short: "Set a configuration value", Long: `Set a specific configuration value`, - Args: cobra.ExactArgs(2), + Args: cmdutil.ExactArgs(2, "cannot set config: key and value arguments required"), RunE: func(cmd *cobra.Command, args []string) error { key := args[0] value := args[1] diff --git a/cmd/space/join/join.go b/cmd/space/join/join.go index 0506cbe..fb6f846 100644 --- a/cmd/space/join/join.go +++ b/cmd/space/join/join.go @@ -1,14 +1,15 @@ package join import ( - "github.com/anyproto/anytype-cli/core/config" - "github.com/anyproto/anytype-cli/core/output" "net/url" "strings" "github.com/spf13/cobra" + "github.com/anyproto/anytype-cli/cmd/cmdutil" "github.com/anyproto/anytype-cli/core" + "github.com/anyproto/anytype-cli/core/config" + "github.com/anyproto/anytype-cli/core/output" ) func NewJoinCmd() *cobra.Command { @@ -22,7 +23,7 @@ func NewJoinCmd() *cobra.Command { Use: "join ", Short: "Join a space", Long: "Join a space using an invite link (https://invite.any.coop/...)", - Args: cobra.ExactArgs(1), + Args: cmdutil.ExactArgs(1, "cannot join space: invite-link argument required"), RunE: func(cmd *cobra.Command, args []string) error { input := args[0] var spaceId string diff --git a/cmd/space/leave/leave.go b/cmd/space/leave/leave.go index e710088..6412708 100644 --- a/cmd/space/leave/leave.go +++ b/cmd/space/leave/leave.go @@ -3,6 +3,7 @@ package leave import ( "github.com/spf13/cobra" + "github.com/anyproto/anytype-cli/cmd/cmdutil" "github.com/anyproto/anytype-cli/core" "github.com/anyproto/anytype-cli/core/output" ) @@ -12,7 +13,7 @@ func NewLeaveCmd() *cobra.Command { Use: "leave ", Short: "Leave a space", Long: "Leave a space and stop sharing it", - Args: cobra.ExactArgs(1), + Args: cmdutil.ExactArgs(1, "cannot leave space: space-id argument required"), RunE: func(cmd *cobra.Command, args []string) error { spaceId := args[0] From 398d77bff6130226eeb960c8167b8ad9646ad567 Mon Sep 17 00:00:00 2001 From: Jannis Metrikat <120120832+jmetrikat@users.noreply.github.com> Date: Fri, 31 Oct 2025 00:07:40 +0100 Subject: [PATCH 05/11] Refactor authentication commands to use listen address and default to localhost --- cmd/auth/create/create.go | 8 ++++---- cmd/auth/create/create_test.go | 4 ++-- cmd/auth/login/login.go | 18 ++++++++---------- cmd/space/join/join.go | 6 +++--- core/auth.go | 2 -- core/config/constants.go | 5 ++--- 6 files changed, 19 insertions(+), 24 deletions(-) diff --git a/cmd/auth/create/create.go b/cmd/auth/create/create.go index f135253..f10717e 100644 --- a/cmd/auth/create/create.go +++ b/cmd/auth/create/create.go @@ -16,7 +16,7 @@ import ( func NewCreateCmd() *cobra.Command { var name string var rootPath string - var apiAddr string + var listenAddress string cmd := &cobra.Command{ Use: "create", @@ -34,7 +34,7 @@ func NewCreateCmd() *cobra.Command { } } - accountKey, accountId, err := core.CreateBotWallet(name, rootPath, apiAddr) + accountKey, accountId, err := core.CreateBotWallet(name, rootPath, listenAddress) if err != nil { return output.Error("failed to create account: %w", err) } @@ -81,8 +81,8 @@ func NewCreateCmd() *cobra.Command { } cmd.Flags().StringVar(&name, "name", "", "Account name") - cmd.Flags().StringVar(&rootPath, "root-path", "", "Custom root path for storing account data") - cmd.Flags().StringVar(&apiAddr, "api-addr", "", fmt.Sprintf("Custom API address (default: %s)", config.DefaultAPIAddress)) + cmd.Flags().StringVar(&rootPath, "root-path", "", "Root path for account data") + cmd.Flags().StringVar(&listenAddress, "listen-address", config.DefaultAPIAddress, "API listen address in `host:port` format") return cmd } diff --git a/cmd/auth/create/create_test.go b/cmd/auth/create/create_test.go index 1780954..bc53fae 100644 --- a/cmd/auth/create/create_test.go +++ b/cmd/auth/create/create_test.go @@ -18,8 +18,8 @@ func TestCreateCommand(t *testing.T) { if cmd.Flag("root-path") == nil { t.Error("root-path flag not found") } - if cmd.Flag("api-addr") == nil { - t.Error("api-addr flag not found") + if cmd.Flag("listen-address") == nil { + t.Error("listen-address flag not found") } } diff --git a/cmd/auth/login/login.go b/cmd/auth/login/login.go index bc511a4..5901d65 100644 --- a/cmd/auth/login/login.go +++ b/cmd/auth/login/login.go @@ -1,8 +1,6 @@ package login import ( - "fmt" - "github.com/spf13/cobra" "github.com/anyproto/anytype-cli/core" @@ -11,16 +9,16 @@ import ( ) func NewLoginCmd() *cobra.Command { + var accountKey string + var rootPath string + var listenAddress string + cmd := &cobra.Command{ Use: "login", Short: "Log in to your bot account", Long: "Authenticate using your bot account key to access your Anytype bot account and stored data.", RunE: func(cmd *cobra.Command, args []string) error { - accountKey, _ := cmd.Flags().GetString("account-key") - rootPath, _ := cmd.Flags().GetString("path") - apiAddr, _ := cmd.Flags().GetString("api-addr") - - if err := core.LoginBot(accountKey, rootPath, apiAddr); err != nil { + if err := core.LoginBot(accountKey, rootPath, listenAddress); err != nil { return output.Error("failed to log in: %w", err) } output.Success("Successfully logged in") @@ -29,9 +27,9 @@ func NewLoginCmd() *cobra.Command { }, } - cmd.Flags().String("account-key", "", "Provide bot account key for authentication") - cmd.Flags().String("path", "", "Provide custom root path for wallet recovery") - cmd.Flags().String("api-addr", "", fmt.Sprintf("API listen address (default: %s)", config.DefaultAPIAddress)) + cmd.Flags().StringVar(&accountKey, "account-key", "", "Bot account key for authentication") + cmd.Flags().StringVar(&rootPath, "path", "", "Root path for account data") + cmd.Flags().StringVar(&listenAddress, "listen-address", config.DefaultAPIAddress, "API listen address in `host:port` format") return cmd } diff --git a/cmd/space/join/join.go b/cmd/space/join/join.go index fb6f846..e10f5ce 100644 --- a/cmd/space/join/join.go +++ b/cmd/space/join/join.go @@ -69,9 +69,9 @@ func NewJoinCmd() *cobra.Command { }, } - cmd.Flags().StringVar(&networkId, "network", "", "Network Id (optional, defaults to Anytype network address)") - cmd.Flags().StringVar(&inviteCid, "invite-cid", "", "Invite Cid (optional, extracted from invite link if provided)") - cmd.Flags().StringVar(&inviteFileKey, "invite-key", "", "Invite file key (optional, extracted from invite link if provided)") + cmd.Flags().StringVar(&networkId, "network", "", "Network `id` to join") + cmd.Flags().StringVar(&inviteCid, "invite-cid", "", "Invite `cid` (extracted from invite link if not provided)") + cmd.Flags().StringVar(&inviteFileKey, "invite-key", "", "Invite file `key` (extracted from invite link if not provided)") return cmd } diff --git a/core/auth.go b/core/auth.go index bf55b8d..f03a565 100644 --- a/core/auth.go +++ b/core/auth.go @@ -53,7 +53,6 @@ func LoginBotAccount(accountKey, rootPath, apiAddr string) error { } var sessionToken string - err := GRPCCallNoAuth(func(ctx context.Context, client service.ClientCommandsClient) error { resp, err := client.InitialSetParameters(ctx, &pb.RpcInitialSetParametersRequest{ Platform: runtime.GOOS, @@ -92,7 +91,6 @@ func LoginBotAccount(accountKey, rootPath, apiAddr string) error { sessionToken = resp3.Token return nil }) - if err != nil { return err } diff --git a/core/config/constants.go b/core/config/constants.go index 3220619..fa6b8d5 100644 --- a/core/config/constants.go +++ b/core/config/constants.go @@ -2,8 +2,7 @@ package config const ( // Default addresses - DefaultBindAddress = "0.0.0.0" - LocalhostIP = "127.0.0.1" + LocalhostIP = "127.0.0.1" // Port configuration GRPCPort = "31007" @@ -13,7 +12,7 @@ const ( // Full addresses DefaultGRPCAddress = LocalhostIP + ":" + GRPCPort DefaultGRPCWebAddress = LocalhostIP + ":" + GRPCWebPort - DefaultAPIAddress = DefaultBindAddress + ":" + APIPort + DefaultAPIAddress = LocalhostIP + ":" + APIPort // URLs GRPCDNSAddress = "dns:///" + DefaultGRPCAddress From 5c9be9e2ce4243d33fb1bc84f4ccc4a51b0e976c Mon Sep 17 00:00:00 2001 From: Jannis Metrikat <120120832+jmetrikat@users.noreply.github.com> Date: Fri, 31 Oct 2025 12:24:49 +0100 Subject: [PATCH 06/11] Add Heart version information to version output --- cmd/auth/create/create.go | 4 ++-- core/version.go | 19 +++++++++++++++++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/cmd/auth/create/create.go b/cmd/auth/create/create.go index f10717e..061693d 100644 --- a/cmd/auth/create/create.go +++ b/cmd/auth/create/create.go @@ -46,8 +46,8 @@ func NewCreateCmd() *cobra.Command { output.Print("") keyLen := len(accountKey) - boxWidth := keyLen + 4 // 2 spaces padding on each side - if boxWidth < 24 { // Minimum width for "BOT ACCOUNT KEY" title + boxWidth := keyLen + 4 + if boxWidth < 24 { boxWidth = 24 } diff --git a/core/version.go b/core/version.go index 8967d12..47dbe24 100644 --- a/core/version.go +++ b/core/version.go @@ -3,6 +3,7 @@ package core import ( "fmt" "runtime" + "runtime/debug" "strings" "github.com/anyproto/anytype-cli/core/config" @@ -25,8 +26,8 @@ func GetVersionVerbose() string { if buildTime == "" { buildTime = "unknown" } - return fmt.Sprintf("anytype-cli %s\nCommit: %s\nBuilt: %s\nGo: %s\nOS/Arch: %s/%s\nURL: %s", - GetVersion(), commit, buildTime, runtime.Version(), runtime.GOOS, runtime.GOARCH, GetReleaseURL()) + return fmt.Sprintf("anytype-cli %s\nCommit: %s\nBuilt: %s\nGo: %s\nOS/Arch: %s/%s\nHeart: %s\nURL: %s", + GetVersion(), commit, buildTime, runtime.Version(), runtime.GOOS, runtime.GOARCH, GetHeartVersion(), GetReleaseURL()) } func GetVersionBrief() string { @@ -53,3 +54,17 @@ func GetReleaseURL() string { } return config.GitHubReleaseURL + Version } + +func GetHeartVersion() string { + info, ok := debug.ReadBuildInfo() + if !ok { + return "unknown" + } + + for _, dep := range info.Deps { + if dep.Path == "github.com/anyproto/anytype-heart" { + return dep.Version + } + } + return "unknown" +} From 9550a5ebd54d35ead200a98d1ecaebd12cbdcc88 Mon Sep 17 00:00:00 2001 From: Jannis Metrikat <120120832+jmetrikat@users.noreply.github.com> Date: Fri, 31 Oct 2025 12:43:13 +0100 Subject: [PATCH 07/11] Remove system-wide installation in favor of user service --- CLAUDE.md | 20 ++++++++++---------- Makefile | 24 ++++-------------------- README.md | 26 ++++++++++---------------- cmd/service/service.go | 8 ++++---- 4 files changed, 28 insertions(+), 50 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 01c0c4c..0c70b7e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -12,11 +12,11 @@ This is the Anytype CLI, a Go-based command-line interface for interacting with # Build the CLI (includes embedded server, downloads tantivy library automatically) make build -# Install system-wide +# Install to ~/.local/bin (user installation) make install -# Install user-local (~/.local/bin) -make install-local +# Uninstall from ~/.local/bin +make uninstall # Clean tantivy libraries make clean-tantivy @@ -51,8 +51,8 @@ make build-windows-amd64 ```bash # Run server interactively (for development) ./dist/anytype serve - - # Or install as system service + + # Or install as user service ./dist/anytype service install ./dist/anytype service start ``` @@ -86,7 +86,7 @@ make build-windows-amd64 ## Architecture Overview ### Embedded Server Architecture -The CLI embeds the anytype-heart gRPC server directly, creating a self-contained binary. This eliminates the need for separate server installation or management. The server runs either interactively (`anytype serve`) or as a system service. +The CLI embeds the anytype-heart gRPC server directly, creating a self-contained binary. This eliminates the need for separate server installation or management. The server runs either interactively (`anytype serve`) or as a user service. ### Command Structure (`/cmd/`) - Uses Cobra framework for CLI commands @@ -119,13 +119,13 @@ The CLI embeds the anytype-heart gRPC server directly, creating a self-contained - `google.golang.org/grpc v1.74.2`: gRPC client-server communication - `github.com/zalando/go-keyring v0.2.6`: Secure credential storage in system keyring - `github.com/cheggaaa/mb/v3 v3.0.2`: Message batching queue for event handling -- `github.com/kardianos/service v1.2.4`: Cross-platform system service management +- `github.com/kardianos/service v1.2.4`: Cross-platform user service management - `github.com/anyproto/tantivy-go v1.0.4`: Full-text search capabilities (requires CGO) ## Important Notes -1. **Service Architecture**: The CLI includes an embedded gRPC server that runs as a system service or interactively -2. **Cross-Platform Service**: Works on Windows (Service), macOS (launchd), Linux (systemd/upstart/sysv) +1. **Service Architecture**: The CLI includes an embedded gRPC server that runs as a user service or interactively +2. **Cross-Platform Service**: Works on Windows (User Service), macOS (User Agent/launchd), Linux (systemd user service) 3. **Keyring Integration**: Authentication tokens are stored securely in the system keyring 4. **Port Configuration**: - gRPC: localhost:31007 @@ -196,7 +196,7 @@ func NewConfigCmd() *cobra.Command { ### Working with the Service - Service is managed via the `anytype service` command - Service program implementation is in `core/serviceprogram/` -- Supports both interactive mode (`anytype serve`) and system service installation +- Supports both interactive mode (`anytype serve`) and user service installation - Service logs are written to log files in the user's home directory (~/.anytype/logs/) ### Error Handling diff --git a/Makefile b/Makefile index 1fa7518..a6334fa 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: all build install install-local uninstall uninstall-local clean clean-tantivy download-tantivy lint lint-fix install-linter +.PHONY: all build install uninstall clean clean-tantivy download-tantivy lint lint-fix install-linter all: download-tantivy build @@ -94,18 +94,8 @@ download-tantivy: ## Download tantivy library for current platform ##@ Installation -install: build ## Install to /usr/local/bin (may require sudo) +install: build ## Install to ~/.local/bin (user installation) @echo "Installing anytype-cli..." - @cp dist/anytype /usr/local/bin/anytype 2>/dev/null || sudo cp dist/anytype /usr/local/bin/anytype - @ln -sf /usr/local/bin/anytype /usr/local/bin/any 2>/dev/null || sudo ln -sf /usr/local/bin/anytype /usr/local/bin/any - @echo "Installed to /usr/local/bin/ (available as 'anytype' and 'any')" - @echo "" - @echo "Usage:" - @echo " anytype serve # Run server in foreground" - @echo " anytype service install # Install as system service" - -install-local: build ## Install to ~/.local/bin (user installation) - @echo "Installing anytype-cli to local..." @mkdir -p $$HOME/.local/bin @cp dist/anytype $$HOME/.local/bin/anytype @ln -sf $$HOME/.local/bin/anytype $$HOME/.local/bin/any @@ -114,16 +104,10 @@ install-local: build ## Install to ~/.local/bin (user installation) @echo "" @echo "Usage:" @echo " anytype serve # Run server in foreground" - @echo " anytype service install # Install as system service" + @echo " anytype service install # Install as user service" -uninstall: ## Uninstall from /usr/local/bin +uninstall: ## Uninstall from ~/.local/bin @echo "Uninstalling anytype-cli..." - @rm -f /usr/local/bin/anytype 2>/dev/null || sudo rm -f /usr/local/bin/anytype - @rm -f /usr/local/bin/any 2>/dev/null || sudo rm -f /usr/local/bin/any - @echo "Uninstalled from /usr/local/bin/" - -uninstall-local: ## Uninstall from ~/.local/bin - @echo "Uninstalling anytype-cli from local..." @rm -f $$HOME/.local/bin/anytype @rm -f $$HOME/.local/bin/any @echo "Uninstalled from $$HOME/.local/bin/" diff --git a/README.md b/README.md index e42320d..90bddb1 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Install the latest release with a single command: # Run the Anytype server anytype serve -# Or install as a system service +# Or install as a user service anytype service install anytype service start @@ -35,7 +35,7 @@ anytype [flags] Commands: auth Manage authentication and accounts serve Run anytype in foreground - service Manage anytype as a system service + service Manage anytype as a user service shell Start interactive shell mode space Manage spaces update Update to the latest version @@ -43,7 +43,7 @@ Commands: Examples: anytype serve # Run in foreground - anytype service install # Install as system service + anytype service install # Install as user service anytype service start # Start the service anytype auth login # Log in to your account anytype auth create # Create a new account @@ -62,9 +62,9 @@ anytype serve ``` This runs the server in the foreground with logs output to stdout, similar to `ollama serve`. -#### 2. System Service (for production) +#### 2. User Service (for production) ```bash -# Install as system service +# Install as user service anytype service install # Start the service @@ -81,9 +81,9 @@ anytype service uninstall ``` The service management works across platforms: -- **macOS**: Uses launchd -- **Linux**: Uses systemd/upstart/sysv -- **Windows**: Uses Windows Service +- **macOS**: Uses User Agent (launchd) +- **Linux**: Uses systemd user service +- **Windows**: Uses Windows User Service ### Authentication @@ -171,12 +171,9 @@ cd anytype-cli # Build the CLI (automatically downloads tantivy library) make build -# Install system-wide (may require sudo) +# Install to ~/.local/bin (user installation) make install -# Install to ~/.local/bin (no sudo required) -make install-local - # Run tests go test ./... @@ -190,11 +187,8 @@ make cross-compile #### Uninstall ```bash -# Remove system-wide installation +# Remove installation from ~/.local/bin make uninstall - -# Remove user-local installation -make uninstall-local ``` ## Contribution diff --git a/cmd/service/service.go b/cmd/service/service.go index f8669b0..ed8258d 100644 --- a/cmd/service/service.go +++ b/cmd/service/service.go @@ -40,19 +40,19 @@ func getService() (service.Service, error) { func NewServiceCmd() *cobra.Command { cmd := &cobra.Command{ Use: "service", - Short: "Manage anytype as a system service", - Long: "Install, uninstall, start, stop, and check status of anytype running as a system service.", + Short: "Manage anytype as a user service", + Long: "Install, uninstall, start, stop, and check status of anytype running as a user service.", } cmd.AddCommand( &cobra.Command{ Use: "install", - Short: "Install as a system service", + Short: "Install as a user service", RunE: installService, }, &cobra.Command{ Use: "uninstall", - Short: "Uninstall the system service", + Short: "Uninstall the user service", RunE: uninstallService, }, &cobra.Command{ From 799ef07df9cb7f72db1a4f31aad5e6c80bea5c7f Mon Sep 17 00:00:00 2001 From: Jannis Metrikat <120120832+jmetrikat@users.noreply.github.com> Date: Fri, 31 Oct 2025 15:40:43 +0100 Subject: [PATCH 08/11] Enhance account key validation to check for mnemonics and base64 format --- CLAUDE.md | 2 +- core/auth.go | 20 +++++++++++++++++--- core/auth_test.go | 36 ++++++++++++++++++++++++------------ 3 files changed, 42 insertions(+), 16 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 0c70b7e..6e349ed 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -77,7 +77,7 @@ make build-windows-amd64 go test ./cmd/... # Run specific test - go test -run TestValidateMnemonic ./core + go test -run TestValidateAccountKey ./core # Run tests with verbose output go test -v ./... diff --git a/core/auth.go b/core/auth.go index f03a565..f9324f1 100644 --- a/core/auth.go +++ b/core/auth.go @@ -3,6 +3,7 @@ package core import ( "bufio" "context" + "encoding/base64" "fmt" "os" "path/filepath" @@ -161,9 +162,22 @@ func ValidateAccountKey(accountKey string) error { if accountKey == "" { return fmt.Errorf("bot account key cannot be empty") } - // Bot account keys are typically base64 encoded strings - if len(accountKey) < 20 { - return fmt.Errorf("invalid bot account key format") + + // Check if this looks like a mnemonic (space-separated words) instead of an account key + words := strings.Fields(accountKey) + if len(words) >= 12 { + return fmt.Errorf("this appears to be a mnemonic phrase, not an account key - the CLI only supports bot accounts created via 'anytype auth create'") + } + + // Validate base64 format by attempting to decode + decoded, err := base64.StdEncoding.DecodeString(accountKey) + if err != nil { + return fmt.Errorf("invalid bot account key format: must be valid base64") + } + + // Basic sanity check: key should be at least 32 bytes + if len(decoded) < 32 { + return fmt.Errorf("invalid bot account key format: insufficient key material") } return nil diff --git a/core/auth_test.go b/core/auth_test.go index 3c0d5f6..f278d48 100644 --- a/core/auth_test.go +++ b/core/auth_test.go @@ -105,32 +105,44 @@ func TestValidateAccountKey(t *testing.T) { errContains string }{ { - name: "valid bot account key", - accountKey: "somevalidbase64encodedkeythatislongenough", + name: "valid 64-byte account key (real example)", + accountKey: "bNYSkBlOzNMKpDupAgL3g31Hnq7JpeX45O6MCpUqNdt16Avbgy5T5oQECKvAoy3+E4wHGPpCRCVWZQQCXRh7xw==", + wantErr: false, + }, + { + name: "valid 32-byte account key (minimum)", + accountKey: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=", wantErr: false, }, { name: "empty account key", accountKey: "", wantErr: true, - errContains: "bot account key cannot be empty", + errContains: "cannot be empty", }, { - name: "too short account key", - accountKey: "shortkey", + name: "mnemonic instead of account key", + accountKey: "word1 word2 word3 word4 word5 word6 word7 word8 word9 word10 word11 word12", wantErr: true, - errContains: "invalid bot account key format", + errContains: "appears to be a mnemonic phrase", }, { - name: "minimum valid length key", - accountKey: "12345678901234567890", // exactly 20 chars - wantErr: false, + name: "not valid base64", + accountKey: "this-is-not-valid-base64!!!", + wantErr: true, + errContains: "must be valid base64", + }, + { + name: "base64 but insufficient key material", + accountKey: "QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQQ==", // 30 bytes decoded + wantErr: true, + errContains: "insufficient key material", }, { - name: "just under minimum length", - accountKey: "1234567890123456789", // 19 chars + name: "very short base64", + accountKey: "YWJj", // "abc" decoded (3 bytes) wantErr: true, - errContains: "invalid bot account key format", + errContains: "insufficient key material", }, } From 6f21f81a4955914dbbfaf9145f987dec8ba4e43b Mon Sep 17 00:00:00 2001 From: Jannis Metrikat <120120832+jmetrikat@users.noreply.github.com> Date: Sun, 2 Nov 2025 12:58:02 +0100 Subject: [PATCH 09/11] Refactor terminology to replace "bot account key" with "account key" --- cmd/auth/create/create.go | 4 ++-- cmd/auth/login/login.go | 4 ++-- cmd/auth/logout/logout.go | 2 +- core/auth.go | 20 ++++++++++---------- core/serviceprogram/serviceprogram.go | 10 +++++----- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/cmd/auth/create/create.go b/cmd/auth/create/create.go index 061693d..1d73959 100644 --- a/cmd/auth/create/create.go +++ b/cmd/auth/create/create.go @@ -41,7 +41,7 @@ func NewCreateCmd() *cobra.Command { output.Success("Bot account created successfully!") - output.Warning("IMPORTANT: Save your bot account key in a secure location.") + output.Warning("IMPORTANT: Save your account key in a secure location.") output.Info(" This is the ONLY way to authenticate your bot account.") output.Print("") @@ -74,7 +74,7 @@ func NewCreateCmd() *cobra.Command { output.Print("") output.Success("You are now logged in to your new bot account.") - output.Success("Bot account key saved to keychain.") + output.Success("Account key saved to keychain.") return nil }, diff --git a/cmd/auth/login/login.go b/cmd/auth/login/login.go index 5901d65..861eec9 100644 --- a/cmd/auth/login/login.go +++ b/cmd/auth/login/login.go @@ -16,7 +16,7 @@ func NewLoginCmd() *cobra.Command { cmd := &cobra.Command{ Use: "login", Short: "Log in to your bot account", - Long: "Authenticate using your bot account key to access your Anytype bot account and stored data.", + Long: "Authenticate using your account key to access your Anytype bot account and stored data.", RunE: func(cmd *cobra.Command, args []string) error { if err := core.LoginBot(accountKey, rootPath, listenAddress); err != nil { return output.Error("failed to log in: %w", err) @@ -27,7 +27,7 @@ func NewLoginCmd() *cobra.Command { }, } - cmd.Flags().StringVar(&accountKey, "account-key", "", "Bot account key for authentication") + cmd.Flags().StringVar(&accountKey, "account-key", "", "Account key for authentication") cmd.Flags().StringVar(&rootPath, "path", "", "Root path for account data") cmd.Flags().StringVar(&listenAddress, "listen-address", config.DefaultAPIAddress, "API listen address in `host:port` format") diff --git a/cmd/auth/logout/logout.go b/cmd/auth/logout/logout.go index adac261..7589240 100644 --- a/cmd/auth/logout/logout.go +++ b/cmd/auth/logout/logout.go @@ -11,7 +11,7 @@ func NewLogoutCmd() *cobra.Command { cmd := &cobra.Command{ Use: "logout", Short: "Log out and clear stored credentials", - Long: "End your current session and remove stored authentication tokens and bot account key from the system keychain.", + Long: "End your current session and remove stored authentication tokens and account key from the system keychain.", RunE: func(cmd *cobra.Command, args []string) error { if err := core.Logout(); err != nil { return output.Error("failed to log out: %w", err) diff --git a/core/auth.go b/core/auth.go index f9324f1..e1941c3 100644 --- a/core/auth.go +++ b/core/auth.go @@ -160,7 +160,7 @@ func LoginBotAccount(accountKey, rootPath, apiAddr string) error { func ValidateAccountKey(accountKey string) error { if accountKey == "" { - return fmt.Errorf("bot account key cannot be empty") + return fmt.Errorf("account key cannot be empty") } // Check if this looks like a mnemonic (space-separated words) instead of an account key @@ -172,12 +172,12 @@ func ValidateAccountKey(accountKey string) error { // Validate base64 format by attempting to decode decoded, err := base64.StdEncoding.DecodeString(accountKey) if err != nil { - return fmt.Errorf("invalid bot account key format: must be valid base64") + return fmt.Errorf("invalid account key format: must be valid base64") } // Basic sanity check: key should be at least 32 bytes if len(decoded) < 32 { - return fmt.Errorf("invalid bot account key format: insufficient key material") + return fmt.Errorf("invalid account key format: insufficient key material") } return nil @@ -189,10 +189,10 @@ func LoginBot(accountKey, rootPath, apiAddr string) error { storedKey, err := GetStoredAccountKey() if err == nil && storedKey != "" { accountKey = storedKey - output.Info("Using stored bot account key from keychain.") + output.Info("Using stored account key from keychain.") usedStoredKey = true } else { - output.Print("Enter bot account key: ") + output.Print("Enter account key: ") reader := bufio.NewReader(os.Stdin) accountKey, _ = reader.ReadString('\n') accountKey = strings.TrimSpace(accountKey) @@ -209,9 +209,9 @@ func LoginBot(accountKey, rootPath, apiAddr string) error { if !usedStoredKey { if err := SaveAccountKey(accountKey); err != nil { - output.Warning("failed to save bot account key in keychain: %v", err) + output.Warning("failed to save account key in keychain: %v", err) } else { - output.Success("Bot account key saved to keychain.") + output.Success("Account key saved to keychain.") } } @@ -251,7 +251,7 @@ func Logout() error { } if err := DeleteStoredAccountKey(); err != nil { - return fmt.Errorf("failed to delete stored bot account key: %w", err) + return fmt.Errorf("failed to delete stored account key: %w", err) } if err := DeleteStoredToken(); err != nil { @@ -268,7 +268,7 @@ func Logout() error { return nil } -// CreateBotWallet creates a new bot wallet with the given root path and returns the bot account key and account Id +// CreateBotWallet creates a new bot wallet with the given root path and returns the account key and account Id // This creates a regular wallet but exports a bot-specific account key for authentication func CreateBotWallet(name, rootPath, apiAddr string) (string, string, error) { if rootPath == "" { @@ -362,7 +362,7 @@ func CreateBotWallet(name, rootPath, apiAddr string) (string, string, error) { } if err := SaveAccountKey(accountKey); err != nil { - output.Warning("failed to save bot account key: %v", err) + output.Warning("failed to save account key: %v", err) } configMgr := config.GetConfigManager() diff --git a/core/serviceprogram/serviceprogram.go b/core/serviceprogram/serviceprogram.go index 02d3431..1006f56 100644 --- a/core/serviceprogram/serviceprogram.go +++ b/core/serviceprogram/serviceprogram.go @@ -91,22 +91,22 @@ func (p *Program) run() { func (p *Program) attemptAutoLogin() { botAccountKey, err := core.GetStoredAccountKey() if err != nil || botAccountKey == "" { - output.Info("No stored bot account key found, skipping auto-login") + output.Info("No stored account key found, skipping auto-login") return } - output.Info("Found stored bot account key, attempting auto-login...") + output.Info("Found stored account key, attempting auto-login...") - maxRetries := 5 + maxRetries := 3 for i := 0; i < maxRetries; i++ { if err := core.LoginBotAccount(botAccountKey, "", ""); err != nil { if i < maxRetries-1 { time.Sleep(2 * time.Second) continue } - output.Info("Failed to auto-login with bot key after %d attempts: %v", maxRetries, err) + output.Info("Failed to auto-login with account key after %d attempts: %v", maxRetries, err) } else { - output.Success("Successfully logged in using stored bot account key") + output.Success("Successfully logged in using stored account key") return } } From 56a41c7dd8ef97e99d8b52c50e28f47cd249b965 Mon Sep 17 00:00:00 2001 From: Jannis Metrikat <120120832+jmetrikat@users.noreply.github.com> Date: Sun, 2 Nov 2025 13:41:26 +0100 Subject: [PATCH 10/11] Improve auth status output --- cmd/auth/status/status.go | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/cmd/auth/status/status.go b/cmd/auth/status/status.go index 1f772dd..db57e46 100644 --- a/cmd/auth/status/status.go +++ b/cmd/auth/status/status.go @@ -18,9 +18,11 @@ func NewStatusCmd() *cobra.Command { Short: "Show authentication status", Long: "Display current authentication status, including account information, server status, and stored credentials.", RunE: func(cmd *cobra.Command, args []string) error { - hasBotKey := false - if _, err := core.GetStoredAccountKey(); err == nil { - hasBotKey = true + hasAccountKey := false + accountKey := "" + if ak, err := core.GetStoredAccountKey(); err == nil && ak != "" { + hasAccountKey = true + accountKey = ak } hasToken := false @@ -35,27 +37,27 @@ func NewStatusCmd() *cobra.Command { cfg := configMgr.Get() accountId := cfg.AccountId - serverRunning := false + isServerRunning := false err := core.GRPCCallNoAuth(func(ctx context.Context, client service.ClientCommandsClient) error { _, err := client.AppGetVersion(ctx, &pb.RpcAppGetVersionRequest{}) return err }) - serverRunning = err == nil + isServerRunning = err == nil // If server is running and we have a token, we're logged in - // (server auto-logs in on restart using stored bot account key) - isLoggedIn := serverRunning && hasToken + // (server auto-logs in on restart using stored account key) + isLoggedIn := isServerRunning && hasToken // Display status based on priority: server -> credentials -> login - if !serverRunning { - output.Print("Server is not running. Run 'anytype serve' to start the server.") - if hasBotKey || hasToken || accountId != "" { + if !isServerRunning { + output.Print("Server is not running. Start it with 'anytype service start' or 'anytype serve' (foreground mode).") + if hasAccountKey || hasToken || accountId != "" { output.Print("Credentials are stored in keychain.") } return nil } - if !hasBotKey && !hasToken && accountId == "" { + if !hasAccountKey && !hasToken && accountId == "" { output.Print("Not authenticated. Run 'anytype auth login' to authenticate or 'anytype auth create' to create a new account.") return nil } @@ -64,10 +66,10 @@ func NewStatusCmd() *cobra.Command { if isLoggedIn && accountId != "" { output.Print(" ✓ Logged in to account \033[1m%s\033[0m (keychain)", accountId) - } else if hasToken || hasBotKey { + } else if hasToken || hasAccountKey { output.Print(" ✗ Not logged in (credentials stored in keychain)") if !isLoggedIn && hasToken { - output.Print(" Note: Server is not running or session expired. Run 'anytype serve' to start server.") + output.Print(" Note: Server is not running or session expired. Start it with 'anytype service start' or 'anytype serve' (foreground mode).") } } else { output.Print(" ✗ Not logged in") @@ -75,8 +77,12 @@ func NewStatusCmd() *cobra.Command { output.Print(" - Active session: \033[1m%v\033[0m", isLoggedIn) - if hasBotKey { - output.Print(" - Bot Account Key: \033[1mstored\033[0m") + if hasAccountKey { + if len(accountKey) > 8 { + output.Print(" - Account Key: \033[1m%s****\033[0m", accountKey[:8]) + } else { + output.Print(" - Account Key: \033[1mstored\033[0m") + } } if hasToken { From 4c5dfe2547731a57f5d3684fe8862fb8ac38339c Mon Sep 17 00:00:00 2001 From: Jannis Metrikat <120120832+jmetrikat@users.noreply.github.com> Date: Sun, 2 Nov 2025 13:41:49 +0100 Subject: [PATCH 11/11] Enhance service installation checks --- cmd/service/service.go | 27 ++++++++++++++++++++++++++- core/auth.go | 1 - core/serviceprogram/serviceprogram.go | 6 +++--- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/cmd/service/service.go b/cmd/service/service.go index ed8258d..825e4df 100644 --- a/cmd/service/service.go +++ b/cmd/service/service.go @@ -1,6 +1,7 @@ package service import ( + "errors" "os" "path/filepath" @@ -122,6 +123,14 @@ func startService(cmd *cobra.Command, args []string) error { return output.Error("failed to create service: %w", err) } + // Check if service is installed first + _, err = s.Status() + if err != nil && errors.Is(err, service.ErrNotInstalled) { + output.Warning("anytype service is not installed") + output.Info("Run 'anytype service install' to install it first") + return nil + } + err = s.Start() if err != nil { return output.Error("failed to start service: %w", err) @@ -137,6 +146,14 @@ func stopService(cmd *cobra.Command, args []string) error { return output.Error("failed to create service: %w", err) } + // Check if service is installed first + _, err = s.Status() + if err != nil && errors.Is(err, service.ErrNotInstalled) { + output.Warning("anytype service is not installed") + output.Info("Run 'anytype service install' to install it first") + return nil + } + err = s.Stop() if err != nil { return output.Error("failed to stop service: %w", err) @@ -152,6 +169,14 @@ func restartService(cmd *cobra.Command, args []string) error { return output.Error("failed to create service: %w", err) } + // Check if service is installed first + _, err = s.Status() + if err != nil && errors.Is(err, service.ErrNotInstalled) { + output.Warning("anytype service is not installed") + output.Info("Run 'anytype service install' to install it first") + return nil + } + err = s.Restart() if err != nil { return output.Error("failed to restart service: %w", err) @@ -169,7 +194,7 @@ func statusService(cmd *cobra.Command, args []string) error { status, err := s.Status() if err != nil { - if err == service.ErrNotInstalled { + if errors.Is(err, service.ErrNotInstalled) { output.Info("anytype service is not installed") output.Info("Run 'anytype service install' to install it") return nil diff --git a/core/auth.go b/core/auth.go index e1941c3..5fc0887 100644 --- a/core/auth.go +++ b/core/auth.go @@ -269,7 +269,6 @@ func Logout() error { } // CreateBotWallet creates a new bot wallet with the given root path and returns the account key and account Id -// This creates a regular wallet but exports a bot-specific account key for authentication func CreateBotWallet(name, rootPath, apiAddr string) (string, string, error) { if rootPath == "" { rootPath = getDefaultDataPath() diff --git a/core/serviceprogram/serviceprogram.go b/core/serviceprogram/serviceprogram.go index 1006f56..e2cf270 100644 --- a/core/serviceprogram/serviceprogram.go +++ b/core/serviceprogram/serviceprogram.go @@ -89,8 +89,8 @@ func (p *Program) run() { } func (p *Program) attemptAutoLogin() { - botAccountKey, err := core.GetStoredAccountKey() - if err != nil || botAccountKey == "" { + accountKey, err := core.GetStoredAccountKey() + if err != nil || accountKey == "" { output.Info("No stored account key found, skipping auto-login") return } @@ -99,7 +99,7 @@ func (p *Program) attemptAutoLogin() { maxRetries := 3 for i := 0; i < maxRetries; i++ { - if err := core.LoginBotAccount(botAccountKey, "", ""); err != nil { + if err := core.LoginBotAccount(accountKey, "", ""); err != nil { if i < maxRetries-1 { time.Sleep(2 * time.Second) continue