dd4a101139
Nuevo agente asistente-2 con herramienta current_time habilitada para demostrar el flujo completo de tool-use (LLM → tool call → resultado → respuesta). Incluye: - agents/asistente2/: reglas puras, config con tool_use.enabled, system prompt - tools/time.go: herramienta current_time (siempre disponible para todos los agentes) - cmd/verify/: comando para subir cross-signing keys y eliminar el warning "Encrypted by a device not verified by its owner" - Registro en runtime.go (current_time) y launcher/main.go (rulesRegistry) El cmd/verify usa mautrix GenerateAndUploadCrossSigningKeysWithPassword para configurar cross-signing via UIA con la password del bot. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
135 lines
4.0 KiB
Go
135 lines
4.0 KiB
Go
// Command verify sets up cross-signing keys for a Matrix bot user.
|
|
// This eliminates the "Encrypted by a device not verified by its owner" warning.
|
|
//
|
|
// Usage:
|
|
//
|
|
// go run -tags goolm ./cmd/verify --homeserver https://... --username asistente-2 --password <pass> --token <access_token>
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"crypto/sha256"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/spf13/cobra"
|
|
"maunium.net/go/mautrix"
|
|
"maunium.net/go/mautrix/crypto"
|
|
"maunium.net/go/mautrix/crypto/cryptohelper"
|
|
"maunium.net/go/mautrix/id"
|
|
)
|
|
|
|
func main() {
|
|
var (
|
|
homeserver string
|
|
username string
|
|
password string
|
|
token string
|
|
storePath string
|
|
)
|
|
|
|
root := &cobra.Command{
|
|
Use: "verify",
|
|
Short: "Set up cross-signing keys for a Matrix bot",
|
|
Long: `Generates and uploads cross-signing keys so the bot's device is verified.
|
|
This removes the "Encrypted by a device not verified by its owner" warning.
|
|
|
|
Requires the bot's access token and password (for UIA during key upload).`,
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
homeserver = strings.TrimRight(homeserver, "/")
|
|
serverName := homeserver
|
|
serverName = strings.TrimPrefix(serverName, "https://")
|
|
serverName = strings.TrimPrefix(serverName, "http://")
|
|
|
|
userID := id.UserID(fmt.Sprintf("@%s:%s", username, serverName))
|
|
fmt.Printf("→ Setting up cross-signing for %s\n", userID)
|
|
|
|
// Create mautrix client
|
|
client, err := mautrix.NewClient(homeserver, userID, token)
|
|
if err != nil {
|
|
return fmt.Errorf("create client: %w", err)
|
|
}
|
|
|
|
ctx := context.Background()
|
|
|
|
// Resolve device ID
|
|
whoami, err := client.Whoami(ctx)
|
|
if err != nil {
|
|
return fmt.Errorf("whoami: %w", err)
|
|
}
|
|
client.DeviceID = whoami.DeviceID
|
|
fmt.Printf("→ Device ID: %s\n", client.DeviceID)
|
|
|
|
// Initialize crypto
|
|
sum := sha256.Sum256([]byte(token))
|
|
pickleKey := sum[:]
|
|
|
|
dbPath := filepath.Join(storePath, "crypto.db")
|
|
if err := os.MkdirAll(filepath.Dir(dbPath), 0700); err != nil {
|
|
return fmt.Errorf("create store dir: %w", err)
|
|
}
|
|
|
|
helper, err := cryptohelper.NewCryptoHelper(client, pickleKey, dbPath)
|
|
if err != nil {
|
|
return fmt.Errorf("create crypto helper: %w", err)
|
|
}
|
|
helper.DBAccountID = username
|
|
|
|
if err := helper.Init(ctx); err != nil {
|
|
return fmt.Errorf("init crypto: %w", err)
|
|
}
|
|
defer helper.Close()
|
|
|
|
client.Crypto = helper
|
|
|
|
// Get the OlmMachine to generate cross-signing keys
|
|
olmMachine := helper.Machine()
|
|
if olmMachine == nil {
|
|
return fmt.Errorf("olm machine not available")
|
|
}
|
|
|
|
fmt.Println("→ Generating and uploading cross-signing keys...")
|
|
_, _, err = olmMachine.GenerateAndUploadCrossSigningKeysWithPassword(ctx, password, "")
|
|
if err != nil {
|
|
// If keys already exist, try to just sign our device
|
|
fmt.Printf(" Note: %v\n", err)
|
|
fmt.Println("→ Attempting to sign own device with existing keys...")
|
|
return signOwnDevice(ctx, olmMachine, client)
|
|
}
|
|
|
|
fmt.Println("✓ Cross-signing keys uploaded successfully")
|
|
fmt.Printf("✓ Device %s is now verified by %s\n", client.DeviceID, userID)
|
|
return nil
|
|
},
|
|
}
|
|
|
|
root.Flags().StringVar(&homeserver, "homeserver", "", "Matrix homeserver URL")
|
|
root.Flags().StringVar(&username, "username", "", "Bot username (without @ or server)")
|
|
root.Flags().StringVar(&password, "password", "", "Bot password (for UIA auth)")
|
|
root.Flags().StringVar(&token, "token", "", "Bot access token")
|
|
root.Flags().StringVar(&storePath, "store", "./data/verify-crypto/", "Crypto store path")
|
|
_ = root.MarkFlagRequired("homeserver")
|
|
_ = root.MarkFlagRequired("username")
|
|
_ = root.MarkFlagRequired("password")
|
|
_ = root.MarkFlagRequired("token")
|
|
|
|
if err := root.Execute(); err != nil {
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
func signOwnDevice(ctx context.Context, mach *crypto.OlmMachine, client *mautrix.Client) error {
|
|
device := &id.Device{
|
|
UserID: client.UserID,
|
|
DeviceID: client.DeviceID,
|
|
}
|
|
err := mach.SignOwnDevice(ctx, device)
|
|
if err != nil {
|
|
return fmt.Errorf("sign own device: %w", err)
|
|
}
|
|
fmt.Printf("✓ Device %s signed with cross-signing key\n", client.DeviceID)
|
|
return nil
|
|
}
|