From 4d4d771f4339868795d55513063196f3f0e85521 Mon Sep 17 00:00:00 2001 From: Nihal-Srivastava05 Date: Thu, 9 Jul 2026 19:28:45 +0530 Subject: [PATCH 1/3] feat: basic cli --- .python-version | 1 + GUILD_CLI_README.md | 261 +++++++++++ forge-go/cli/guild_runtime.go | 590 ++++++++++++++++++++++++ forge-go/cli/message_builder.go | 133 ++++++ forge-go/cli/subscription.go | 98 ++++ forge-go/command/guild.go | 86 ++++ forge-go/command/guild_inspect.go | 138 ++++++ forge-go/command/guild_run.go | 552 ++++++++++++++++++++++ forge-go/command/guild_validate.go | 113 +++++ forge-go/command/root.go | 3 + forge-go/conf/agent-dependencies.yaml | 56 +-- forge-go/conf/forge-agent-registry.yaml | 67 +-- forge-go/go.mod | 23 +- forge-go/go.sum | 295 +++--------- guilds/echo_app.json | 72 +++ guilds/react_guild.json | 202 ++++++++ guilds/uniko_research_guild.json | 479 +++++++++++++++++++ 17 files changed, 2870 insertions(+), 299 deletions(-) create mode 100644 .python-version create mode 100644 GUILD_CLI_README.md create mode 100644 forge-go/cli/guild_runtime.go create mode 100644 forge-go/cli/message_builder.go create mode 100644 forge-go/cli/subscription.go create mode 100644 forge-go/command/guild.go create mode 100644 forge-go/command/guild_inspect.go create mode 100644 forge-go/command/guild_run.go create mode 100644 forge-go/command/guild_validate.go create mode 100644 guilds/echo_app.json create mode 100644 guilds/react_guild.json create mode 100644 guilds/uniko_research_guild.json diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..24ee5b1 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.13 diff --git a/GUILD_CLI_README.md b/GUILD_CLI_README.md new file mode 100644 index 0000000..377cc13 --- /dev/null +++ b/GUILD_CLI_README.md @@ -0,0 +1,261 @@ +# Forge Guild CLI + +A command-line interface for running and debugging Forge guilds locally without the rustic-ui frontend. + +## Features + +- πŸš€ Launch guilds from JSON/YAML specs +- πŸ’¬ Interactive REPL for chatting with guilds +- πŸ“Š Real-time message flow visualization +- πŸ” Agent status monitoring +- πŸ”€ Routing decision display +- ⚑ Ctrl+C signal handling for clean shutdown +- 🐍 Auto-detection of Python 3.13+ +- πŸ”• Quiet mode to hide noisy logs +- βœ… Guild spec validation and inspection + +## Prerequisites + +- Python 3.13+ (auto-detected from pyenv or system) +- Go 1.21+ (for building) +- Redis or NATS backend + +## Installation + +```bash +cd /home/nihal/Projects/forge/forge-go +go build -o forge . +# Optionally install to PATH +sudo cp forge /usr/local/bin/ +``` + +## Quick Start + +```bash +# Run a guild (quiet mode) +./forge guild run -q ../guilds/echo_app.json + +# Type messages to interact with the guild +> hello! + +# Use commands +> /status +> /help +> /quit +``` + +## Usage + +### Run a Guild + +```bash +# Basic usage +./forge guild run ../guilds/echo_app.json + +# With custom Python +./forge guild run --python /path/to/python3.13 ../guilds/echo_app.json + +# Quiet mode (minimal startup output, clean display) +./forge guild run -q ../guilds/echo_app.json + +# Verbose mode (show all message details) +./forge guild run -v ../guilds/echo_app.json + +# Show routing information +./forge guild run --show-routing ../guilds/echo_app.json +``` + +### Inspect a Guild Spec + +```bash +./forge guild inspect ../guilds/echo_app.json +``` + +Shows guild structure, agents, routing rules, and dependencies. + +### Validate a Guild Spec + +```bash +./forge guild validate ../guilds/echo_app.json +``` + +Checks for syntax errors and validates configuration. + +## Interactive Commands + +Once the REPL starts, you can use: + +- Type any text to send a chat message to the guild +- `/status` - Show current agent status +- `/help` - Show help message +- `/quit` or `/exit` - Exit the REPL +- `Ctrl+C` - Shutdown cleanly + +## Flags + +### Common Flags + +- `--backend` - Messaging backend: `redis` or `nats` (default: `nats`) +- `--org-id` - Organization ID (default: `local-dev`) +- `--user-id` - User ID for sending messages (default: `test-user`) +- `--user-name` - User display name (default: `Test User`) +- `--supervisor` - Supervisor type: `process`, `docker`, or `bubblewrap` (default: `process`) +- `--python` - Python executable path (auto-detected if not specified) + +### Output Control + +- `-q, --quiet` - Minimal startup output, hide noisy logs (recommended) +- `-v, --verbose` - Show full message details including payloads +- `--show-routing` - Show routing history and transformations (default: `true`) + +## Message Display + +The CLI automatically filters noisy internal messages: + +**Shown by default:** +- βœ… User chat messages +- βœ… Agent responses +- βœ… Errors and warnings +- βœ… Important state changes + +**Hidden by default** (use `-v` to see): +- ❌ Health checks and heartbeats +- ❌ Internal state updates +- ❌ Infrastructure events +- ❌ HTTP request logs + +## Python Version + +The CLI requires **Python 3.13+**. It auto-detects in this order: + +1. `pyenv which python` (preferred - gets real path, not shim) +2. `python` from PATH +3. `python3` from PATH + +### Setting up Python 3.13 + +If you're getting Python version errors, recreate your virtual environment: + +```bash +cd /home/nihal/Projects/forge + +# Remove old venv +rm -rf .env + +# Create new venv with Python 3.13 +python3.13 -m venv .env +# OR if pyenv is active with 3.13: +python -m venv .env + +# Activate and install +source .env/bin/activate +pip install -e ./forge-python +``` + +## Troubleshooting + +### "Python 3.12 does not satisfy Python>=3.13" + +Your virtual environment was created with Python 3.12. See "Setting up Python 3.13" above. + +### "could not find forge root" + +Run the CLI from the `forge-go` directory or any subdirectory of the forge repository. + +### Server logs cluttering output + +Use `-q` flag for quiet mode. Server logs are automatically redirected to `/tmp/forge-cli-*/server.log`. + +### Guild won't launch + +1. Check Python version at startup (should show 3.13+) +2. Use `/status` to check if agents are running +3. Look at server logs: `/tmp/forge-cli-*/server.log` +4. Verify agent registry seeded: Look for "Seeding agent registry" at startup + +### Ctrl+C doesn't work + +This was fixed. Update to latest version and rebuild. + +## Examples + +### Echo Guild (recommended for testing) + +```bash +./forge guild run -q ../guilds/echo_app.json +``` + +Type messages and see them echoed back by the agent. + +### React Guild + +```bash +./forge guild run ../guilds/react_guild.json +``` + +### Custom Configuration + +```bash +./forge guild run \ + --backend redis \ + --org-id my-org \ + --user-id alice \ + --user-name "Alice Smith" \ + --python /home/nihal/.pyenv/versions/3.13.0/bin/python \ + -q \ + ../guilds/echo_app.json +``` + +## Development + +### Project Structure + +``` +forge-go/ +β”œβ”€β”€ cli/ +β”‚ β”œβ”€β”€ guild_runtime.go # Embedded runtime +β”‚ β”œβ”€β”€ subscription.go # Message subscriptions +β”‚ └── message_builder.go # Message construction +β”œβ”€β”€ command/ +β”‚ β”œβ”€β”€ guild.go # Command group +β”‚ β”œβ”€β”€ guild_run.go # Interactive REPL +β”‚ β”œβ”€β”€ guild_inspect.go # Guild inspection +β”‚ └── guild_validate.go # Guild validation +└── go.mod # Dependencies +``` + +### Architecture + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ CLI REPL (guild_run.go) β”‚ +β”‚ - User input handling β”‚ +β”‚ - Message display β”‚ +β”‚ - Command processing β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ GuildRuntime (guild_runtime.go) β”‚ +β”‚ - Embedded forge server β”‚ +β”‚ - Agent registry seeding β”‚ +β”‚ - Guild lifecycle management β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Forge Server (embedded) β”‚ +β”‚ - Redis/NATS messaging β”‚ +β”‚ - Agent supervision β”‚ +β”‚ - Guild management API β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Python Agents (Python 3.13+) β”‚ +β”‚ - Guild manager agent β”‚ +β”‚ - User-defined agents β”‚ +β”‚ - Message processing β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +## License + +Same as the Forge project. diff --git a/forge-go/cli/guild_runtime.go b/forge-go/cli/guild_runtime.go new file mode 100644 index 0000000..0e00c28 --- /dev/null +++ b/forge-go/cli/guild_runtime.go @@ -0,0 +1,590 @@ +package cli + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "io" + "log/slog" + "net" + "net/http" + "os" + "os/exec" + "path/filepath" + "strings" + "syscall" + "time" + + "github.com/redis/go-redis/v9" + "github.com/rustic-ai/forge/forge-go/guild" + "github.com/rustic-ai/forge/forge-go/messaging" + "github.com/rustic-ai/forge/forge-go/protocol" + "gopkg.in/yaml.v3" +) + +// RuntimeConfig holds configuration for the guild runtime +type RuntimeConfig struct { + Backend string // "redis" or "nats" + OrgID string // Organization ID + UserID string // User ID for sending messages + UserName string // User name for sending messages + ForgeHome string // Forge home directory (optional) + ForgeRoot string // Forge repository root + DependencyConfig string // Path to dependency config + AgentRegistry string // Path to agent registry + ForgePythonPath string // Path to forge-python package + NATSUrl string // NATS server URL (if using NATS backend) + SupervisorType string // "process", "docker", or "bubblewrap" + PythonPath string // Path to Python executable (optional, will auto-detect) +} + +// GuildRuntime manages an embedded forge runtime for running guilds +type GuildRuntime struct { + config RuntimeConfig + serverCmd *exec.Cmd + serverBase string + rusticBase string + redisAddr string + redisClient *redis.Client + tempDir string + dbPath string + dataDir string + ctx context.Context + cancel context.CancelFunc + agentNames map[string]string // Maps agent ID to agent name +} + +// AgentStatus represents the status of an agent +type AgentStatus struct { + AgentID string + State string + PID int +} + +// NewGuildRuntime creates a new guild runtime instance +func NewGuildRuntime(config RuntimeConfig) (*GuildRuntime, error) { + // Set defaults + if config.Backend == "" { + config.Backend = "nats" + } + if config.OrgID == "" { + config.OrgID = "local-dev" + } + if config.UserID == "" { + config.UserID = "test-user" + } + if config.UserName == "" { + config.UserName = "Test User" + } + if config.SupervisorType == "" { + config.SupervisorType = "process" + } + + // Create temp directory for runtime + tempDir, err := os.MkdirTemp("", "forge-cli-*") + if err != nil { + return nil, fmt.Errorf("failed to create temp dir: %w", err) + } + + dbPath := filepath.Join(tempDir, "forge-cli.db") + dataDir := filepath.Join(tempDir, "forge-data") + if err := os.MkdirAll(dataDir, 0o755); err != nil { + os.RemoveAll(tempDir) + return nil, fmt.Errorf("failed to create data dir: %w", err) + } + + ctx, cancel := context.WithCancel(context.Background()) + + runtime := &GuildRuntime{ + config: config, + tempDir: tempDir, + dbPath: dbPath, + dataDir: dataDir, + ctx: ctx, + cancel: cancel, + agentNames: make(map[string]string), + } + + return runtime, nil +} + +// Start starts the embedded forge server +func (r *GuildRuntime) Start() error { + // Reserve a local address for the server + listenAddr, err := reserveLocalAddr() + if err != nil { + return fmt.Errorf("failed to reserve listen address: %w", err) + } + + embeddedRedisAddr, err := reserveLocalAddr() + if err != nil { + return fmt.Errorf("failed to reserve redis address: %w", err) + } + r.redisAddr = embeddedRedisAddr + + // Find forge binary + binPath, err := exec.LookPath("forge") + if err != nil { + // Try to build it + slog.Info("forge binary not found, attempting to build...") + buildCmd := exec.Command("go", "build", "-o", filepath.Join(r.tempDir, "forge"), "./cmd/forge") + buildCmd.Dir = r.config.ForgeRoot + if output, err := buildCmd.CombinedOutput(); err != nil { + return fmt.Errorf("failed to build forge: %w\n%s", err, output) + } + binPath = filepath.Join(r.tempDir, "forge") + } + + // Build server arguments + args := []string{ + "server", + "--listen", listenAddr, + "--db", "sqlite:///" + r.dbPath, + "--embedded-redis-addr", embeddedRedisAddr, + "--data-dir", r.dataDir, + "--dependency-config", r.config.DependencyConfig, + "--with-client", + "--client-node-id", "cli-node", + "--client-metrics-addr", "127.0.0.1:0", + "--client-default-supervisor", r.config.SupervisorType, + } + + if r.config.NATSUrl != "" { + args = append(args, "--nats", r.config.NATSUrl) + } + + // Create server command + cmd := exec.Command(binPath, args...) + cmd.Dir = r.config.ForgeRoot + cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} + + // Redirect server logs to temp files to avoid cluttering the CLI + // Only show them if there's an error + logFile := filepath.Join(r.tempDir, "server.log") + if logF, err := os.Create(logFile); err == nil { + cmd.Stdout = logF + cmd.Stderr = logF + } + + // Set environment variables + env := []string{} + + // If Python path is specified, ensure its directory is first in PATH + if r.config.PythonPath != "" { + pythonDir := filepath.Dir(r.config.PythonPath) + currentPath := os.Getenv("PATH") + env = append(env, "PATH="+pythonDir+":"+currentPath) + env = append(env, "FORGE_PYTHON_EXECUTABLE="+r.config.PythonPath) + } + + // Add all other environment variables + for _, e := range os.Environ() { + // Skip PATH if we already set it above + if r.config.PythonPath != "" && strings.HasPrefix(e, "PATH=") { + continue + } + env = append(env, e) + } + + // Add Forge-specific variables + env = append(env, + "FORGE_AGENT_REGISTRY="+r.config.AgentRegistry, + "FORGE_PYTHON_PKG="+r.config.ForgePythonPath, + "FORGE_ENABLE_PUBLIC_API=true", + "FORGE_ENABLE_UI_API=true", + "FORGE_IDENTITY_MODE=local", + "FORGE_QUOTA_MODE=local", + "PYTHONUNBUFFERED=1", + ) + if r.config.NATSUrl != "" { + env = append(env, "FORGE_EXTRA_DEPS=rusticai-nats") + } + + cmd.Env = env + + // Start server + if err := cmd.Start(); err != nil { + return fmt.Errorf("failed to start forge server: %w", err) + } + + r.serverCmd = cmd + r.serverBase = "http://" + listenAddr + r.rusticBase = r.serverBase + "/rustic" + + // Wait for server to be ready + if err := r.waitForReady(30 * time.Second); err != nil { + r.kill() + return fmt.Errorf("server did not become ready: %w", err) + } + + // Create Redis client + r.redisClient = redis.NewClient(&redis.Options{Addr: embeddedRedisAddr}) + + slog.Info("Guild runtime started", "listen_addr", listenAddr, "backend", r.config.Backend) + + // Seed agent registry into catalog + if err := r.seedAgentRegistry(); err != nil { + slog.Warn("Failed to seed agent registry", "error", err) + // Continue anyway - some agents might already be registered + } + + return nil +} + +// seedAgentRegistry loads the agent registry and registers all agents in the catalog +func (r *GuildRuntime) seedAgentRegistry() error { + registryPath := r.config.AgentRegistry + content, err := os.ReadFile(registryPath) + if err != nil { + return fmt.Errorf("failed to read registry: %w", err) + } + + var registry struct { + Entries []map[string]interface{} `yaml:"entries"` + } + if err := yaml.Unmarshal(content, ®istry); err != nil { + return fmt.Errorf("failed to parse registry: %w", err) + } + + slog.Info("Seeding agent registry", "agent_count", len(registry.Entries)) + + // Register each agent + for _, agent := range registry.Entries { + className, _ := agent["class_name"].(string) + if className == "" { + continue + } + + // Convert to catalog agent entry format + agentEntry := map[string]interface{}{ + "qualified_class_name": className, + "agent_name": agent["id"], // API expects agent_name + "agent_doc": agent["description"], + "agent_props_schema": map[string]interface{}{}, // Empty schema for now + "message_handlers": map[string]interface{}{}, // Empty for now + } + + // POST to /rustic/catalog/agents + if err := r.postJSON(r.rusticBase+"/catalog/agents", agentEntry, nil); err != nil { + // Ignore duplicate errors + if !strings.Contains(err.Error(), "409") && !strings.Contains(err.Error(), "duplicate") { + slog.Warn("Failed to register agent", "class_name", className, "error", err) + } + } + } + + return nil +} + +// LoadGuild loads a guild spec from a file +func (r *GuildRuntime) LoadGuild(specPath string) (*protocol.GuildSpec, error) { + // Read file and check if it's a blueprint wrapper + content, err := os.ReadFile(specPath) + if err != nil { + return nil, fmt.Errorf("failed to read file: %w", err) + } + + // Check if this is a blueprint wrapper (has a "spec" field) + var checker map[string]interface{} + json.Unmarshal(content, &checker) + + if specField, hasSpec := checker["spec"]; hasSpec && specField != nil { + // This is a blueprint wrapper - extract the nested spec + var wrapper struct { + Spec json.RawMessage `json:"spec"` + } + if err := json.Unmarshal(content, &wrapper); err != nil { + return nil, fmt.Errorf("failed to parse wrapper: %w", err) + } + + var nestedSpec protocol.GuildSpec + if err := json.Unmarshal(wrapper.Spec, &nestedSpec); err != nil { + return nil, fmt.Errorf("failed to parse nested spec: %w", err) + } + return &nestedSpec, nil + } + + // This is a direct guild spec + spec, _, err := guild.ParseFile(specPath) + if err != nil { + return nil, fmt.Errorf("failed to parse guild spec: %w", err) + } + return spec, nil +} + +// LaunchGuild launches a guild from a spec +func (r *GuildRuntime) LaunchGuild(spec *protocol.GuildSpec) (string, error) { + // Create blueprint in catalog + blueprintResp, err := r.createBlueprint(spec) + if err != nil { + return "", fmt.Errorf("failed to create blueprint: %w", err) + } + + blueprintID, ok := blueprintResp["id"].(string) + if !ok { + return "", fmt.Errorf("blueprint response missing id") + } + + // Launch guild from blueprint + guildID, err := r.launchFromBlueprint(blueprintID, spec.Name) + if err != nil { + return "", fmt.Errorf("failed to launch guild: %w", err) + } + + // Wait for guild to be running + if err := r.waitForGuildRunning(guildID, 2*time.Minute); err != nil { + return "", fmt.Errorf("guild did not start: %w", err) + } + + // Build agent name mapping for display + r.buildAgentNameMap(guildID, spec) + + slog.Info("Guild launched successfully", "guild_id", guildID, "name", spec.Name) + return guildID, nil +} + +// buildAgentNameMap creates a mapping from agent IDs to agent names +func (r *GuildRuntime) buildAgentNameMap(guildID string, spec *protocol.GuildSpec) { + // Add manager agent + r.agentNames[guildID+"#manager_agent"] = spec.Name + " Manager" + + // Query running agents to get their IDs + statuses, err := r.GetAgentStatuses(guildID) + if err != nil { + return + } + + // Map agent names from spec + agentsByName := make(map[string]string) + for _, agent := range spec.Agents { + agentsByName[agent.Name] = agent.Name + } + + // Try to match IDs to names (this is approximate since we don't have the actual mapping) + // Store what we know + for agentID := range statuses { + // Check if this is the manager agent + if agentID == guildID+"#manager_agent" { + continue + } + + // For now, try to find matching agent from spec by index + // In a real scenario, we'd need to query the guild API for the actual mapping + if len(spec.Agents) > 0 { + r.agentNames[agentID] = spec.Agents[0].Name + } + } +} + +// GetAgentName returns the display name for an agent ID +func (r *GuildRuntime) GetAgentName(agentID string) string { + if name, ok := r.agentNames[agentID]; ok { + return name + } + return agentID +} + +// GetAgentStatuses gets the status of all agents in a guild +func (r *GuildRuntime) GetAgentStatuses(guildID string) (map[string]AgentStatus, error) { + const statusPrefix = "forge:agent:status:" + pattern := fmt.Sprintf("%s%s:*", statusPrefix, guildID) + + keys, err := r.redisClient.Keys(r.ctx, pattern).Result() + if err != nil { + return nil, fmt.Errorf("failed to query agent statuses: %w", err) + } + + statuses := make(map[string]AgentStatus) + for _, key := range keys { + raw, err := r.redisClient.Get(r.ctx, key).Result() + if err != nil { + continue + } + + var status struct { + State string `json:"state"` + PID int `json:"pid"` + } + if err := json.Unmarshal([]byte(raw), &status); err != nil { + continue + } + + agentID := strings.TrimPrefix(key, statusPrefix+guildID+":") + statuses[agentID] = AgentStatus{ + AgentID: agentID, + State: status.State, + PID: status.PID, + } + } + + return statuses, nil +} + +// PublishMessage publishes a message to a topic +func (r *GuildRuntime) PublishMessage(namespace, topic string, msg *protocol.Message) error { + backend, err := r.getMessagingBackend() + if err != nil { + return err + } + + return backend.PublishMessage(r.ctx, namespace, topic, msg) +} + +// getMessagingBackend returns the messaging backend for the runtime +func (r *GuildRuntime) getMessagingBackend() (messaging.Backend, error) { + // For now, we always use the embedded Redis backend + // The server internally handles NATS if configured + return messaging.NewRedisBackend(r.redisClient), nil +} + +// Shutdown gracefully shuts down the runtime +func (r *GuildRuntime) Shutdown() error { + slog.Info("Shutting down guild runtime") + + r.cancel() + + if r.redisClient != nil { + r.redisClient.Close() + } + + if r.serverCmd != nil && r.serverCmd.Process != nil { + r.kill() + } + + if r.tempDir != "" { + os.RemoveAll(r.tempDir) + } + + return nil +} + +// Helper functions + +func (r *GuildRuntime) waitForReady(timeout time.Duration) error { + deadline := time.Now().Add(timeout) + for time.Now().Before(deadline) { + resp, err := http.Get(r.serverBase + "/readyz") + if err == nil && resp.StatusCode == http.StatusOK { + resp.Body.Close() + return nil + } + if resp != nil { + resp.Body.Close() + } + time.Sleep(200 * time.Millisecond) + } + return fmt.Errorf("timeout waiting for server ready") +} + +func (r *GuildRuntime) waitForGuildRunning(guildID string, timeout time.Duration) error { + deadline := time.Now().Add(timeout) + for time.Now().Before(deadline) { + statuses, err := r.GetAgentStatuses(guildID) + if err == nil && len(statuses) > 0 { + allRunning := true + for _, status := range statuses { + if status.State != "running" { + allRunning = false + break + } + } + if allRunning { + return nil + } + } + time.Sleep(1 * time.Second) + } + return fmt.Errorf("timeout waiting for guild to be running") +} + +func (r *GuildRuntime) createBlueprint(spec *protocol.GuildSpec) (map[string]interface{}, error) { + // Convert spec to blueprint format + blueprint := map[string]interface{}{ + "name": spec.Name, + "description": spec.Description, + "spec": spec, // API expects "spec" not "guild_spec" + "exposure": "public", // Make it public so we can launch it + "author_id": r.config.UserID, + "organization_id": r.config.OrgID, + } + + var result map[string]interface{} + if err := r.postJSON(r.rusticBase+"/catalog/blueprints/", blueprint, &result); err != nil { + return nil, err + } + return result, nil +} + +func (r *GuildRuntime) launchFromBlueprint(blueprintID, guildName string) (string, error) { + launchReq := map[string]interface{}{ + "guild_name": guildName, + "user_id": r.config.UserID, + "org_id": r.config.OrgID, + } + + var result map[string]interface{} + url := fmt.Sprintf("%s/catalog/blueprints/%s/guilds", r.rusticBase, blueprintID) + if err := r.postJSON(url, launchReq, &result); err != nil { + return "", err + } + + // API returns {"id": "..."} not {"guild_id": "..."} + guildID, ok := result["id"].(string) + if !ok { + return "", fmt.Errorf("launch response missing id") + } + return guildID, nil +} + +func (r *GuildRuntime) postJSON(url string, payload, result interface{}) error { + data, err := json.Marshal(payload) + if err != nil { + return err + } + + req, err := http.NewRequest(http.MethodPost, url, bytes.NewReader(data)) + if err != nil { + return err + } + req.Header.Set("Content-Type", "application/json") + + client := &http.Client{Timeout: 30 * time.Second} + resp, err := client.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return err + } + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + return fmt.Errorf("HTTP %d: %s", resp.StatusCode, string(body)) + } + + if result != nil { + return json.Unmarshal(body, result) + } + return nil +} + +func (r *GuildRuntime) kill() { + if r.serverCmd != nil && r.serverCmd.Process != nil { + syscall.Kill(-r.serverCmd.Process.Pid, syscall.SIGKILL) + r.serverCmd.Wait() + } +} + +// reserveLocalAddr finds and reserves a free local TCP address +func reserveLocalAddr() (string, error) { + listener, err := net.Listen("tcp", "127.0.0.1:0") + if err != nil { + return "", err + } + addr := listener.Addr().String() + listener.Close() + return addr, nil +} diff --git a/forge-go/cli/message_builder.go b/forge-go/cli/message_builder.go new file mode 100644 index 0000000..15936e7 --- /dev/null +++ b/forge-go/cli/message_builder.go @@ -0,0 +1,133 @@ +package cli + +import ( + "encoding/json" + "fmt" + "sync" + + "github.com/rustic-ai/forge/forge-go/protocol" +) + +var ( + idGen *protocol.GemstoneGenerator + idGenOnce sync.Once +) + +func getIDGen() *protocol.GemstoneGenerator { + idGenOnce.Do(func() { + // Use machine ID 1 for CLI + gen, _ := protocol.NewGemstoneGenerator(1) + idGen = gen + }) + return idGen +} + +// BuildChatMessage creates a chatCompletionRequest message +func BuildChatMessage(userID, userName, text, topic string) (*protocol.Message, error) { + gen := getIDGen() + msgID, err := gen.Generate(protocol.PriorityNormal) + if err != nil { + return nil, fmt.Errorf("failed to generate message ID: %w", err) + } + + // Create chat completion request payload + payload := map[string]interface{}{ + "messages": []interface{}{ + map[string]interface{}{ + "role": "user", + "name": userID, + "content": []interface{}{ + map[string]interface{}{ + "type": "text", + "text": text, + }, + }, + }, + }, + } + + payloadBytes, err := json.Marshal(payload) + if err != nil { + return nil, fmt.Errorf("failed to marshal payload: %w", err) + } + + convID, _ := gen.Generate(protocol.PriorityNormal) + convIDInt := convID.ToInt() + + msg := protocol.NewMessageFromGemstoneID(msgID) + msg.Format = "chatCompletionRequest" + msg.Sender = protocol.AgentTag{ + ID: &userID, + Name: &userName, + } + msg.Topics = protocol.TopicsFromString(topic) + msg.Payload = json.RawMessage(payloadBytes) + msg.ConversationID = &convIDInt + + return &msg, nil +} + +// BuildSystemMessage creates a system message +func BuildSystemMessage(topic string, payload map[string]interface{}, format string) (*protocol.Message, error) { + gen := getIDGen() + msgID, err := gen.Generate(protocol.PriorityNormal) + if err != nil { + return nil, fmt.Errorf("failed to generate message ID: %w", err) + } + + if format == "" { + format = "system" + } + + payloadBytes, err := json.Marshal(payload) + if err != nil { + return nil, fmt.Errorf("failed to marshal payload: %w", err) + } + + msg := protocol.NewMessageFromGemstoneID(msgID) + msg.Format = format + msg.Topics = protocol.TopicsFromString(topic) + msg.Payload = json.RawMessage(payloadBytes) + + return &msg, nil +} + +// ParseMessageFromJSON parses a message from JSON +func ParseMessageFromJSON(data []byte) (*protocol.Message, error) { + var msg protocol.Message + if err := json.Unmarshal(data, &msg); err != nil { + return nil, fmt.Errorf("failed to parse message: %w", err) + } + return &msg, nil +} + +// BuildHealthCheckMessage creates a health check message +func BuildHealthCheckMessage(userID, topic string) (*protocol.Message, error) { + gen := getIDGen() + msgID, err := gen.Generate(protocol.PriorityNormal) + if err != nil { + return nil, fmt.Errorf("failed to generate message ID: %w", err) + } + + payload := map[string]interface{}{ + "dummy": 1, + } + payloadBytes, err := json.Marshal(payload) + if err != nil { + return nil, fmt.Errorf("failed to marshal payload: %w", err) + } + + convID, _ := gen.Generate(protocol.PriorityNormal) + convIDInt := convID.ToInt() + + msg := protocol.NewMessageFromGemstoneID(msgID) + msg.Format = "healthcheck" + msg.Sender = protocol.AgentTag{ + ID: &userID, + } + msg.Topics = protocol.TopicsFromString(topic) + msg.Payload = json.RawMessage(payloadBytes) + msg.ConversationID = &convIDInt + + return &msg, nil +} diff --git a/forge-go/cli/subscription.go b/forge-go/cli/subscription.go new file mode 100644 index 0000000..e4c6835 --- /dev/null +++ b/forge-go/cli/subscription.go @@ -0,0 +1,98 @@ +package cli + +import ( + "context" + "fmt" + + "github.com/rustic-ai/forge/forge-go/messaging" + "github.com/rustic-ai/forge/forge-go/protocol" +) + +// GuildSubscription wraps a messaging subscription for guild messages +type GuildSubscription struct { + sub messaging.Subscription + msgChan chan *protocol.Message + errChan chan error + ctx context.Context + cancel context.CancelFunc +} + +// Subscribe creates a subscription to guild message topics +func (r *GuildRuntime) Subscribe(guildID, userID string, spec *protocol.GuildSpec) (*GuildSubscription, error) { + // Subscribe to relevant topics + topics := []string{ + "user_notifications:" + userID, // Messages to user + "user_system_notification:" + userID, // System notifications + "user_message_broadcast", // Broadcast messages from agents + "user:" + userID, // Direct user messages + "default_topic", // Guild default inbox + "guild_status_topic", // Guild status + "infra_events_topic", // Infrastructure events + } + + // Add all additional_topics from agents in the guild + for _, agent := range spec.Agents { + topics = append(topics, agent.AdditionalTopics...) + } + + backend, err := r.getMessagingBackend() + if err != nil { + return nil, fmt.Errorf("failed to get messaging backend: %w", err) + } + + sub, err := backend.Subscribe(r.ctx, guildID, topics...) + if err != nil { + return nil, fmt.Errorf("failed to subscribe: %w", err) + } + + ctx, cancel := context.WithCancel(r.ctx) + guildSub := &GuildSubscription{ + sub: sub, + msgChan: make(chan *protocol.Message, 100), + errChan: make(chan error, 10), + ctx: ctx, + cancel: cancel, + } + + // Start message forwarding goroutine + go guildSub.forward() + + return guildSub, nil +} + +// Messages returns the channel for receiving messages +func (s *GuildSubscription) Messages() <-chan *protocol.Message { + return s.msgChan +} + +// Errors returns the channel for receiving errors +func (s *GuildSubscription) Errors() <-chan error { + return s.errChan +} + +// Close closes the subscription +func (s *GuildSubscription) Close() error { + s.cancel() + close(s.msgChan) + close(s.errChan) + return s.sub.Close() +} + +func (s *GuildSubscription) forward() { + for { + select { + case <-s.ctx.Done(): + return + case subMsg, ok := <-s.sub.Channel(): + if !ok { + return + } + s.msgChan <- subMsg.Message + case err, ok := <-s.sub.ErrChannel(): + if !ok { + return + } + s.errChan <- err + } + } +} diff --git a/forge-go/command/guild.go b/forge-go/command/guild.go new file mode 100644 index 0000000..b9761f5 --- /dev/null +++ b/forge-go/command/guild.go @@ -0,0 +1,86 @@ +package command + +import ( + "github.com/spf13/cobra" +) + +var ( + guildBackend string + guildOrgID string + guildUserID string + guildUserName string + guildSupervisor string + guildPython string + guildVerbose bool + guildShowRouting bool + guildQuiet bool +) + +// GuildCmd is the parent command for guild-related operations +var GuildCmd = &cobra.Command{ + Use: "guild", + Short: "Guild testing and debugging commands", + Long: "Commands for running guilds locally for testing and debugging without the rustic-ui frontend", +} + +var guildRunCmd = &cobra.Command{ + Use: "run [guild-file]", + Short: "Run a guild locally with interactive chat", + Long: `Run a guild locally with interactive chat and message flow visualization. + +This command launches a guild from a YAML/JSON spec file and provides an interactive +REPL for chatting with the guild. You can see all messages flowing between agents, +routing decisions, and transformations in real-time. + +Example: + forge guild run examples/echo.yaml + forge guild run --verbose testdata/minimal.yaml + forge guild run --show-routing testdata/e2e/002_basic_message_routing.yaml`, + Args: cobra.ExactArgs(1), + RunE: runGuildREPL, +} + +var guildInspectCmd = &cobra.Command{ + Use: "inspect [guild-file]", + Short: "Parse and display guild specification", + Long: `Parse a guild spec file and display its structure. + +Shows agents, routing rules, dependencies, and other guild configuration +in a human-readable format. + +Example: + forge guild inspect examples/echo.yaml`, + Args: cobra.ExactArgs(1), + RunE: inspectGuild, +} + +var guildValidateCmd = &cobra.Command{ + Use: "validate [guild-file]", + Short: "Validate guild specification", + Long: `Validate a guild spec file for correctness. + +Checks for syntax errors, missing dependencies, invalid agent references, +and other common issues. + +Example: + forge guild validate examples/echo.yaml`, + Args: cobra.ExactArgs(1), + RunE: validateGuild, +} + +func init() { + GuildCmd.AddCommand(guildRunCmd) + GuildCmd.AddCommand(guildInspectCmd) + GuildCmd.AddCommand(guildValidateCmd) + + // Flags for 'run' command + guildRunCmd.Flags().StringVar(&guildBackend, "backend", "nats", "Messaging backend (redis|nats)") + guildRunCmd.Flags().StringVar(&guildOrgID, "org-id", "local-dev", "Organization ID") + guildRunCmd.Flags().StringVar(&guildUserID, "user-id", "test-user", "User ID") + guildRunCmd.Flags().StringVar(&guildUserName, "user-name", "Test User", "User name") + guildRunCmd.Flags().StringVar(&guildSupervisor, "supervisor", "process", "Supervisor type (process|docker|bubblewrap)") + guildRunCmd.Flags().StringVar(&guildPython, "python", "", "Python executable path (auto-detected if not specified)") + guildRunCmd.Flags().BoolVarP(&guildVerbose, "verbose", "v", false, "Verbose output (show full message details)") + guildRunCmd.Flags().BoolVarP(&guildQuiet, "quiet", "q", false, "Quiet mode (minimal startup output)") + guildRunCmd.Flags().BoolVar(&guildShowRouting, "show-routing", true, "Show routing decisions and transformations") +} diff --git a/forge-go/command/guild_inspect.go b/forge-go/command/guild_inspect.go new file mode 100644 index 0000000..40b8665 --- /dev/null +++ b/forge-go/command/guild_inspect.go @@ -0,0 +1,138 @@ +package command + +import ( + "encoding/json" + "fmt" + "os" + + "github.com/rustic-ai/forge/forge-go/guild" + "github.com/rustic-ai/forge/forge-go/protocol" + "github.com/spf13/cobra" +) + +func inspectGuild(cmd *cobra.Command, args []string) error { + guildFile := args[0] + + fmt.Printf("πŸ“‹ Inspecting guild spec: %s\n\n", guildFile) + + // Read file and check if it's a blueprint wrapper + content, err := os.ReadFile(guildFile) + if err != nil { + return fmt.Errorf("failed to read file: %w", err) + } + + // Check if this is a blueprint wrapper (has a "spec" field) + var checker map[string]interface{} + json.Unmarshal(content, &checker) + + var spec *protocol.GuildSpec + if specField, hasSpec := checker["spec"]; hasSpec && specField != nil { + // This is a blueprint wrapper - extract the nested spec + var wrapper struct { + Spec json.RawMessage `json:"spec"` + } + if err := json.Unmarshal(content, &wrapper); err != nil { + return fmt.Errorf("failed to parse wrapper: %w", err) + } + + var nestedSpec protocol.GuildSpec + if err := json.Unmarshal(wrapper.Spec, &nestedSpec); err != nil { + return fmt.Errorf("failed to parse nested spec: %w", err) + } + spec = &nestedSpec + } else { + // This is a direct guild spec + var err error + spec, _, err = guild.ParseFile(guildFile) + if err != nil { + return fmt.Errorf("failed to parse guild spec: %w", err) + } + } + + // Display basic info + fmt.Println("Guild Information:") + fmt.Printf(" Name: %s\n", spec.Name) + if spec.Description != "" { + fmt.Printf(" Description: %s\n", spec.Description) + } + if spec.ID != "" { + fmt.Printf(" ID: %s\n", spec.ID) + } + fmt.Println() + + // Display agents + fmt.Printf("Agents (%d):\n", len(spec.Agents)) + for i, agent := range spec.Agents { + fmt.Printf(" %d. %s (%s)\n", i+1, agent.Name, agent.ID) + fmt.Printf(" Class: %s\n", agent.ClassName) + if agent.Description != "" { + fmt.Printf(" Description: %s\n", agent.Description) + } + if len(agent.AdditionalTopics) > 0 { + fmt.Printf(" Additional Topics: %v\n", agent.AdditionalTopics) + } + fmt.Println() + } + + // Display routing rules + if spec.Routes != nil && len(spec.Routes.Steps) > 0 { + fmt.Printf("Routing Rules (%d):\n", len(spec.Routes.Steps)) + for i, rule := range spec.Routes.Steps { + fmt.Printf(" %d. ", i+1) + if rule.Agent != nil { + if rule.Agent.Name != nil && *rule.Agent.Name != "" { + fmt.Printf("Agent: %s", *rule.Agent.Name) + } else if rule.Agent.ID != nil && *rule.Agent.ID != "" { + fmt.Printf("Agent ID: %s", *rule.Agent.ID) + } + } + if rule.MethodName != nil && *rule.MethodName != "" { + fmt.Printf(" | Method: %s", *rule.MethodName) + } + fmt.Println() + + if rule.OriginFilter != nil { + if rule.OriginFilter.OriginMessageFormat != nil { + fmt.Printf(" Origin Format: %s\n", *rule.OriginFilter.OriginMessageFormat) + } + if rule.OriginFilter.OriginTopic != nil { + fmt.Printf(" Origin Topic: %s\n", *rule.OriginFilter.OriginTopic) + } + } + + if rule.Destination != nil { + if !rule.Destination.Topics.IsZero() { + fmt.Printf(" Destination Topics: %v\n", rule.Destination.Topics.ToSlice()) + } + if len(rule.Destination.RecipientList) > 0 { + fmt.Printf(" Recipients: %d agents\n", len(rule.Destination.RecipientList)) + } + } + + if rule.Transformer != nil { + fmt.Printf(" Transformer: present\n") + } + + fmt.Println() + } + } + + // Display dependencies + if spec.DependencyMap != nil && len(spec.DependencyMap) > 0 { + fmt.Printf("Dependencies (%d):\n", len(spec.DependencyMap)) + for name, dep := range spec.DependencyMap { + fmt.Printf(" - %s: %s\n", name, dep.ClassName) + } + fmt.Println() + } + + // Display properties + if spec.Properties != nil && len(spec.Properties) > 0 { + fmt.Println("Properties:") + propsJSON, _ := json.MarshalIndent(spec.Properties, " ", " ") + fmt.Printf(" %s\n", string(propsJSON)) + fmt.Println() + } + + return nil +} diff --git a/forge-go/command/guild_run.go b/forge-go/command/guild_run.go new file mode 100644 index 0000000..5fd2675 --- /dev/null +++ b/forge-go/command/guild_run.go @@ -0,0 +1,552 @@ +package command + +import ( + "bufio" + "context" + "encoding/json" + "fmt" + "os" + "os/exec" + "os/signal" + "path/filepath" + "strings" + "syscall" + "time" + + "github.com/rustic-ai/forge/forge-go/cli" + "github.com/rustic-ai/forge/forge-go/protocol" + "github.com/spf13/cobra" +) + +func runGuildREPL(cmd *cobra.Command, args []string) error { + guildFile := args[0] + + // Get current working directory and forge root + cwd, err := os.Getwd() + if err != nil { + return fmt.Errorf("failed to get working directory: %w", err) + } + + // Find forge root (look for go.mod) + forgeRoot := findForgeRoot(cwd) + if forgeRoot == "" { + return fmt.Errorf("could not find forge root (no go.mod found)") + } + + // Auto-detect Python if not specified + pythonPath := guildPython + if pythonPath == "" { + pythonPath = detectPython() + } + + // Set up runtime config + // forgeRoot is already the forge-go directory + forgeRepoRoot := filepath.Dir(forgeRoot) // Parent is the repo root + config := cli.RuntimeConfig{ + Backend: guildBackend, + OrgID: guildOrgID, + UserID: guildUserID, + UserName: guildUserName, + ForgeRoot: forgeRepoRoot, + DependencyConfig: filepath.Join(forgeRoot, "conf", "dependencies.yaml"), + AgentRegistry: filepath.Join(forgeRoot, "conf", "forge-agent-registry.yaml"), + ForgePythonPath: filepath.Join(forgeRepoRoot, "forge-python"), + SupervisorType: guildSupervisor, + PythonPath: pythonPath, + } + + if !guildQuiet { + if pythonPath != "" { + fmt.Printf(" Python: %s\n", pythonPath) + } + + fmt.Println("πŸš€ Starting Forge Guild CLI...") + fmt.Printf(" Backend: %s\n", config.Backend) + fmt.Printf(" Guild: %s\n", guildFile) + fmt.Println() + } + + // Create and start runtime + runtime, err := cli.NewGuildRuntime(config) + if err != nil { + return fmt.Errorf("failed to create runtime: %w", err) + } + defer runtime.Shutdown() + + if !guildQuiet { + fmt.Println("βš™οΈ Starting embedded forge server...") + } + if err := runtime.Start(); err != nil { + return fmt.Errorf("failed to start runtime: %w", err) + } + + // Load guild spec + if !guildQuiet { + fmt.Printf("πŸ“‹ Loading guild spec from %s...\n", guildFile) + } + spec, err := runtime.LoadGuild(guildFile) + if err != nil { + return fmt.Errorf("failed to load guild: %w", err) + } + + // Launch guild + if !guildQuiet { + fmt.Printf("🎯 Launching guild '%s'...\n", spec.Name) + } + guildID, err := runtime.LaunchGuild(spec) + if err != nil { + return fmt.Errorf("failed to launch guild: %w", err) + } + + if !guildQuiet { + fmt.Printf("\nβœ… Guild launched successfully!\n") + fmt.Printf(" Guild ID: %s\n", guildID) + fmt.Println() + } + + // Wait a moment for agents to fully start + time.Sleep(2 * time.Second) + + // Determine the topic to send user messages to + // For guilds with routing rules (UserProxyAgent), use default_topic + // Otherwise use the first agent's topic (simple echo-style guilds) + userMessageTopic := "default_topic" + hasRoutingRules := spec.Routes != nil && len(spec.Routes.Steps) > 0 + + if !hasRoutingRules && len(spec.Agents) > 0 && len(spec.Agents[0].AdditionalTopics) > 0 { + // Simple guild without routing - send directly to first agent + userMessageTopic = spec.Agents[0].AdditionalTopics[0] + } + // Complex guilds with routing rules - keep default_topic + + // Show agent status + if !guildQuiet { + if err := showAgentStatus(runtime, guildID); err != nil { + fmt.Printf("⚠️ Warning: could not get agent status: %v\n", err) + } + + fmt.Println("\nπŸ“‘ Subscribing to message topics...") + } + + sub, err := runtime.Subscribe(guildID, config.UserID, spec) + if err != nil { + return fmt.Errorf("failed to subscribe: %w", err) + } + defer sub.Close() + + if guildVerbose { + fmt.Printf(" Sending user messages to: %s\n\n", userMessageTopic) + } + + // Set up context for shutdown + ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) + defer cancel() + + // Start message display goroutine + go displayMessages(ctx, sub, runtime, spec, guildVerbose, guildShowRouting) + + // Interactive REPL + fmt.Println("\n" + strings.Repeat("=", 70)) + fmt.Println("πŸ’¬ Interactive Chat - Type your messages below") + fmt.Println(" Commands:") + fmt.Println(" /quit or /exit - Exit the REPL") + fmt.Println(" /status - Show agent status") + fmt.Println(" /help - Show this help") + fmt.Println(" Ctrl+C - Shutdown") + fmt.Println(strings.Repeat("=", 70)) + fmt.Println() + + // Create channel for stdin input + inputChan := make(chan string) + errChan := make(chan error) + + // Start goroutine to read from stdin + go func() { + scanner := bufio.NewScanner(os.Stdin) + for scanner.Scan() { + select { + case <-ctx.Done(): + return + case inputChan <- scanner.Text(): + } + } + if err := scanner.Err(); err != nil { + errChan <- err + } + close(inputChan) + }() + + // Main REPL loop + for { + fmt.Print("> ") + + select { + case <-ctx.Done(): + fmt.Println("\nπŸ‘‹ Shutting down...") + return nil + + case err := <-errChan: + return fmt.Errorf("error reading input: %w", err) + + case line, ok := <-inputChan: + if !ok { + // Input channel closed (EOF) + fmt.Println("\nπŸ‘‹ Shutting down...") + return nil + } + + line = strings.TrimSpace(line) + if line == "" { + continue + } + + // Handle commands + if strings.HasPrefix(line, "/") { + switch strings.ToLower(line) { + case "/quit", "/exit": + fmt.Println("πŸ‘‹ Goodbye!") + return nil + case "/status": + showAgentStatus(runtime, guildID) + continue + case "/help": + fmt.Println("\nCommands:") + fmt.Println(" /quit, /exit - Exit the REPL") + fmt.Println(" /status - Show agent status") + fmt.Println(" /help - Show this help") + fmt.Println(" Ctrl+C - Shutdown") + fmt.Println() + continue + default: + fmt.Printf("Unknown command: %s\n", line) + continue + } + } + + // Send chat message + if err := sendChatMessage(runtime, guildID, config.UserID, config.UserName, line, userMessageTopic); err != nil { + fmt.Printf("❌ Error sending message: %v\n", err) + } + } + } +} + +func showAgentStatus(runtime *cli.GuildRuntime, guildID string) error { + statuses, err := runtime.GetAgentStatuses(guildID) + if err != nil { + return err + } + + fmt.Println("\nπŸ€– Agent Status:") + if len(statuses) == 0 { + fmt.Println(" No agents found") + return nil + } + + for agentID, status := range statuses { + stateIcon := "●" + switch status.State { + case "running": + stateIcon = "🟒" + case "starting": + stateIcon = "🟑" + case "stopped": + stateIcon = "⚫" + case "error": + stateIcon = "πŸ”΄" + } + + // Get agent display name + agentName := runtime.GetAgentName(agentID) + if agentName != agentID { + fmt.Printf(" %s %s (PID: %d) - %s\n", stateIcon, agentName, status.PID, status.State) + } else { + fmt.Printf(" %s %s (PID: %d) - %s\n", stateIcon, agentID, status.PID, status.State) + } + } + fmt.Println() + + return nil +} + +func sendChatMessage(runtime *cli.GuildRuntime, guildID, userID, userName, text, topic string) error { + msg, err := cli.BuildChatMessage(userID, userName, text, topic) + if err != nil { + return err + } + + fmt.Printf("πŸ“€ Sending to topic: %s\n", topic) + if err := runtime.PublishMessage(guildID, topic, msg); err != nil { + return fmt.Errorf("failed to publish: %w", err) + } + + return nil +} + +func displayMessages(ctx context.Context, sub *cli.GuildSubscription, runtime *cli.GuildRuntime, spec *protocol.GuildSpec, verbose, showRouting bool) { + for { + select { + case <-ctx.Done(): + return + case msg, ok := <-sub.Messages(): + if !ok { + return + } + printMessage(msg, runtime, spec, verbose, showRouting) + case err, ok := <-sub.Errors(): + if !ok { + return + } + fmt.Printf("\n❌ Subscription error: %v\n> ", err) + } + } +} + +func printMessage(msg *protocol.Message, runtime *cli.GuildRuntime, spec *protocol.GuildSpec, verbose, showRouting bool) { + // Debug: show all message formats in verbose mode only + if verbose { + topicsDebug := msg.Topics.ToSlice() + fmt.Printf("\n[DEBUG] Format: %-50s Topics: %v\n", msg.Format, topicsDebug) + } + + // Skip internal system messages unless verbose + if !verbose { + // Skip health/heartbeat messages + if msg.Format == "healthReport" || msg.Format == "heartbeat" { + return + } + // Skip agent health reports + if msg.Format == "rustic_ai.core.guild.agent_ext.mixins.health.AgentsHealthReport" { + return + } + // Skip guild updated announcements (noisy during startup) + if msg.Format == "rustic_ai.core.agents.system.models.GuildUpdatedAnnouncement" { + return + } + // Skip state fetch responses + if msg.Format == "rustic_ai.core.state.models.StateFetchResponse" { + return + } + // Skip infra events unless they're errors + if msg.Format == "rustic_ai.forge.runtime.InfraEvent" { + return + } + } + + timestamp := time.Unix(int64(msg.Timestamp), 0).Format("15:04:05") + topics := msg.Topics.ToSlice() + topicStr := strings.Join(topics, ", ") + + // Message header + fmt.Println("\n" + strings.Repeat("─", 70)) + fmt.Printf("πŸ“¨ [%s] %s\n", timestamp, topicStr) + + // Get sender name - use agent name map if available + senderName := "" + senderID := "" + if msg.Sender.Name != nil && *msg.Sender.Name != "" { + senderName = *msg.Sender.Name + } + if msg.Sender.ID != nil { + senderID = *msg.Sender.ID + // Try to get a better name from the agent map + if agentName := runtime.GetAgentName(senderID); agentName != senderID { + senderName = agentName + } + } + + // Display sender - just the name, not the ID (cleaner) + if senderName != "" { + fmt.Printf(" From: %s\n", senderName) + } else if senderID != "" { + // Fallback to ID if no name + fmt.Printf(" From: %s\n", senderID) + } + + // Message content + if len(msg.Payload) > 0 { + var payload map[string]interface{} + if err := json.Unmarshal(msg.Payload, &payload); err == nil { + // Pretty print payload + if verbose { + prettyPayload, _ := json.MarshalIndent(payload, " ", " ") + fmt.Printf(" Payload:\n %s\n", string(prettyPayload)) + } else { + // Show condensed version - try different message formats + displayed := false + + // Try chatCompletionRequest format (user messages) + if messages, ok := payload["messages"].([]interface{}); ok && len(messages) > 0 { + if firstMsg, ok := messages[0].(map[string]interface{}); ok { + if content, ok := firstMsg["content"].([]interface{}); ok && len(content) > 0 { + if textContent, ok := content[0].(map[string]interface{}); ok { + if text, ok := textContent["text"].(string); ok { + fmt.Printf(" πŸ’¬ %s\n", text) + displayed = true + } + } + } + } + } + + // Try chatCompletionResponse format (agent responses) + if !displayed { + if choices, ok := payload["choices"].([]interface{}); ok && len(choices) > 0 { + if choice, ok := choices[0].(map[string]interface{}); ok { + if message, ok := choice["message"].(map[string]interface{}); ok { + if content, ok := message["content"].(string); ok { + fmt.Printf(" πŸ’¬ %s\n", content) + displayed = true + } + } + } + } + } + + // Try simple text field + if !displayed { + if text, ok := payload["text"].(string); ok { + fmt.Printf(" πŸ’¬ %s\n", text) + displayed = true + } + } + + // Try content field directly (common in some formats) + if !displayed { + if content, ok := payload["content"].(string); ok { + fmt.Printf(" πŸ’¬ %s\n", content) + displayed = true + } + } + + // Generic payload display if nothing matched + if !displayed { + payloadBytes, _ := json.Marshal(payload) + if len(payloadBytes) > 150 { + fmt.Printf(" πŸ“„ %s...\n", string(payloadBytes[:150])) + } else { + fmt.Printf(" πŸ“„ %s\n", string(payloadBytes)) + } + } + } + } + } + + // Routing information + if showRouting && len(msg.MessageHistory) > 0 { + fmt.Println(" πŸ”€ Routing History:") + for i, entry := range msg.MessageHistory { + agent := "" + agentID := "" + if entry.Agent.Name != nil && *entry.Agent.Name != "" { + agent = *entry.Agent.Name + } + if entry.Agent.ID != nil { + agentID = *entry.Agent.ID + // Try to get better name from runtime + if betterName := runtime.GetAgentName(agentID); betterName != agentID { + agent = betterName + } else if agent == "" { + agent = agentID + } + } + if agent == "" { + agent = "unknown" + } + processor := entry.Processor + if processor == "" { + processor = "unknown" + } + + reasonStr := "" + if len(entry.Reason) > 0 { + reasonStr = fmt.Sprintf(" [%s]", strings.Join(entry.Reason, ", ")) + } + + fromTopic := "" + if entry.FromTopic != nil { + fromTopic = fmt.Sprintf(" from %s", *entry.FromTopic) + } + + toTopics := "" + if len(entry.ToTopics) > 0 { + toTopics = fmt.Sprintf(" β†’ %s", strings.Join(entry.ToTopics, ", ")) + } + + fmt.Printf(" %d. %s (%s)%s%s%s\n", + i+1, agent, processor, fromTopic, toTopics, reasonStr) + } + } + + if verbose && msg.RoutingSlip != nil { + fmt.Println(" πŸ“‹ Routing Slip:") + slipBytes, _ := json.MarshalIndent(msg.RoutingSlip, " ", " ") + fmt.Printf(" %s\n", string(slipBytes)) + } + + fmt.Print("> ") +} + +func findForgeRoot(startDir string) string { + dir := startDir + for { + goModPath := filepath.Join(dir, "go.mod") + if _, err := os.Stat(goModPath); err == nil { + // Check if this is the forge-go module + content, _ := os.ReadFile(goModPath) + if strings.Contains(string(content), "github.com/rustic-ai/forge/forge-go") { + // Return the forge-go directory itself + return dir + } + } + + parent := filepath.Dir(dir) + if parent == dir { + break + } + dir = parent + } + return "" +} + +func detectPython() string { + // Try pyenv which command first to get the real Python path (not shim) + cmd := exec.Command("pyenv", "which", "python") + if output, err := cmd.Output(); err == nil { + realPath := strings.TrimSpace(string(output)) + // Verify it's Python 3.13+ + versionCmd := exec.Command(realPath, "--version") + if versionOutput, err := versionCmd.Output(); err == nil { + version := strings.TrimSpace(string(versionOutput)) + if strings.Contains(version, "Python 3.13") || strings.Contains(version, "Python 3.14") { + return realPath + } + } + } + + // Try python from PATH (may be a shim) + if pythonPath, err := exec.LookPath("python"); err == nil { + cmd := exec.Command(pythonPath, "--version") + if output, err := cmd.Output(); err == nil { + version := strings.TrimSpace(string(output)) + if strings.Contains(version, "Python 3.13") || strings.Contains(version, "Python 3.14") { + return pythonPath + } + } + } + + // Try python3 as fallback + if pythonPath, err := exec.LookPath("python3"); err == nil { + cmd := exec.Command(pythonPath, "--version") + if output, err := cmd.Output(); err == nil { + version := strings.TrimSpace(string(output)) + if strings.Contains(version, "Python 3.13") || strings.Contains(version, "Python 3.14") { + return pythonPath + } + } + // Return python3 even if not 3.13, better than nothing + return pythonPath + } + + return "" +} diff --git a/forge-go/command/guild_validate.go b/forge-go/command/guild_validate.go new file mode 100644 index 0000000..2ae2422 --- /dev/null +++ b/forge-go/command/guild_validate.go @@ -0,0 +1,113 @@ +package command + +import ( + "encoding/json" + "fmt" + "os" + + "github.com/rustic-ai/forge/forge-go/guild" + "github.com/rustic-ai/forge/forge-go/protocol" + "github.com/spf13/cobra" +) + +func validateGuild(cmd *cobra.Command, args []string) error { + guildFile := args[0] + + fmt.Printf("πŸ” Validating guild spec: %s\n\n", guildFile) + + // Read file and check if it's a blueprint wrapper + content, err := os.ReadFile(guildFile) + if err != nil { + fmt.Printf("❌ Validation FAILED: %v\n", err) + return err + } + + // Check if this is a blueprint wrapper (has a "spec" field) + var checker map[string]interface{} + json.Unmarshal(content, &checker) + + var spec *protocol.GuildSpec + if specField, hasSpec := checker["spec"]; hasSpec && specField != nil { + // This is a blueprint wrapper - extract the nested spec + var wrapper struct { + Spec json.RawMessage `json:"spec"` + } + if err := json.Unmarshal(content, &wrapper); err != nil { + fmt.Printf("❌ Validation FAILED: %v\n", err) + return err + } + + var nestedSpec protocol.GuildSpec + if err := json.Unmarshal(wrapper.Spec, &nestedSpec); err != nil { + fmt.Printf("❌ Validation FAILED: %v\n", err) + return err + } + spec = &nestedSpec + } else { + // This is a direct guild spec + var err error + spec, _, err = guild.ParseFile(guildFile) + if err != nil { + fmt.Printf("❌ Validation FAILED: %v\n", err) + return err + } + } + + errors := []string{} + warnings := []string{} + + // Validate basic fields + if spec.Name == "" { + errors = append(errors, "Guild name is required") + } + + if len(spec.Agents) == 0 { + errors = append(errors, "Guild must have at least one agent") + } + + // Validate agents + for i, agent := range spec.Agents { + if agent.ClassName == "" { + errors = append(errors, fmt.Sprintf("Agent %d (%s) missing class_name", i+1, agent.Name)) + } + if agent.ID == "" { + warnings = append(warnings, fmt.Sprintf("Agent %d (%s) has no ID", i+1, agent.Name)) + } + } + + // Validate routing rules + if spec.Routes != nil { + for i, rule := range spec.Routes.Steps { + if rule.Agent == nil && rule.AgentType == nil { + warnings = append(warnings, fmt.Sprintf("Routing rule %d has no agent or agent_type specified", i+1)) + } + } + } + + // Display results + if len(errors) > 0 { + fmt.Println("❌ Validation Errors:") + for _, err := range errors { + fmt.Printf(" β€’ %s\n", err) + } + fmt.Println() + } + + if len(warnings) > 0 { + fmt.Println("⚠️ Validation Warnings:") + for _, warn := range warnings { + fmt.Printf(" β€’ %s\n", warn) + } + fmt.Println() + } + + if len(errors) == 0 { + fmt.Println("βœ… Validation PASSED") + if len(warnings) > 0 { + fmt.Printf(" (with %d warnings)\n", len(warnings)) + } + return nil + } + + return fmt.Errorf("validation failed with %d errors", len(errors)) +} diff --git a/forge-go/command/root.go b/forge-go/command/root.go index da9e346..ddc69b1 100644 --- a/forge-go/command/root.go +++ b/forge-go/command/root.go @@ -33,4 +33,7 @@ func init() { forgepath.SetHome(forgeHome) } } + + // Register guild command + RootCmd.AddCommand(GuildCmd) } diff --git a/forge-go/conf/agent-dependencies.yaml b/forge-go/conf/agent-dependencies.yaml index 413344e..3bc684f 100644 --- a/forge-go/conf/agent-dependencies.yaml +++ b/forge-go/conf/agent-dependencies.yaml @@ -1,18 +1,16 @@ kvstore: class_name: rustic_ai.core.guild.agent_ext.depends.kvstore.InMemoryKVStoreResolver - provided_type: rustic_ai.core.kvstore.KVStore properties: {} filesystem: class_name: rustic_ai.core.guild.agent_ext.depends.filesystem.FileSystemResolver - provided_type: rustic_ai.core.filesystem.FileSystem properties: - path_base: /tmp + path_base: / protocol: file storage_options: auto_mkdir: true + asynchronous: true code_runner: class_name: rustic_ai.core.guild.agent_ext.depends.code_execution.stateless.InProcessCodeInterpreterResolver - provided_type: rustic_ai.core.code_execution.CodeRunner properties: {} embeddings: class_name: rustic_ai.langchain.agent_ext.embeddings.openai.OpenAIEmbeddingsResolver @@ -29,6 +27,9 @@ textsplitter: kb_backend: class_name: rustic_ai.core.knowledgebase.kbindex_backend_memory.InMemoryKBIndexBackendResolver properties: {} +uniko: + class_name: rustic_ai.uniko_agent.resolver.UnikoResolver + properties: {} # --------------------------------------------------------------------------- # LLM Dependencies @@ -38,59 +39,56 @@ kb_backend: llm: class_name: rustic_ai.litellm.agent_ext.llm.LiteLLMResolver - provided_type: rustic_ai.core.llm.LLM properties: - model: openai/rustic/qwen3.5-0.8b-starter - base_url: http://localhost:55262/v1 + model: gpt-4.1 llm_local_qwen3_5_0_8b: class_name: rustic_ai.litellm.agent_ext.llm.LiteLLMResolver - provided_type: rustic_ai.core.llm.LLM properties: model: openai/rustic/qwen3.5-0.8b-starter - base_url: http://localhost:55262/v1 + conf: + base_url: http://localhost:55262/v1 llm_local_nomic_embed: class_name: rustic_ai.litellm.agent_ext.llm.LiteLLMResolver - provided_type: rustic_ai.core.llm.LLM properties: model: openai/rustic/nomic-embed-default - base_url: http://localhost:55262/v1 + conf: + base_url: http://localhost:55262/v1 llm_local_qwen3_5_2b: class_name: rustic_ai.litellm.agent_ext.llm.LiteLLMResolver - provided_type: rustic_ai.core.llm.LLM properties: model: openai/rustic/qwen3.5-2b-balanced - base_url: http://localhost:55262/v1 + conf: + base_url: http://localhost:55262/v1 llm_local_qwen3_5_4b: class_name: rustic_ai.litellm.agent_ext.llm.LiteLLMResolver - provided_type: rustic_ai.core.llm.LLM properties: model: openai/rustic/qwen3.5-4b-quality - base_url: http://localhost:55262/v1 + conf: + base_url: http://localhost:55262/v1 llm_local_qwen3_4b_text: class_name: rustic_ai.litellm.agent_ext.llm.LiteLLMResolver - provided_type: rustic_ai.core.llm.LLM properties: model: openai/rustic/qwen3-4b-text - base_url: http://localhost:55262/v1 + conf: + base_url: http://localhost:55262/v1 llm_local_gemma3_4b: class_name: rustic_ai.litellm.agent_ext.llm.LiteLLMResolver - provided_type: rustic_ai.core.llm.LLM properties: model: openai/rustic/gemma-3-4b-it - base_url: http://localhost:55262/v1 + conf: + base_url: http://localhost:55262/v1 # --- OpenAI --- # Requires: OPENAI_API_KEY llm_openai: class_name: rustic_ai.litellm.agent_ext.llm.LiteLLMResolver - provided_type: rustic_ai.core.llm.LLM properties: model: gpt-5.4 @@ -100,19 +98,18 @@ llm_openai: llm_anthropic_sonnet: class_name: rustic_ai.litellm.agent_ext.llm.LiteLLMResolver properties: - model: anthropic/claude-sonnet-4-6-20260301 + model: claude-sonnet-4-6 llm_anthropic_opus: class_name: rustic_ai.litellm.agent_ext.llm.LiteLLMResolver properties: - model: anthropic/claude-opus-4-6-20260301 + model: claude-opus-4-5 # --- Google Gemini (AI Studio) --- # Requires: GEMINI_API_KEY llm_gemini: class_name: rustic_ai.litellm.agent_ext.llm.LiteLLMResolver - provided_type: rustic_ai.core.llm.LLM properties: model: gemini/gemini-3.1 @@ -123,8 +120,9 @@ llm_vertexai: class_name: rustic_ai.litellm.agent_ext.llm.LiteLLMResolver properties: model: vertex_ai/gemini-3.1 - vertex_project: null - vertex_location: null + conf: + vertex_project: null + vertex_location: null # --- AWS Bedrock --- # Requires: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION_NAME @@ -133,7 +131,8 @@ llm_bedrock: class_name: rustic_ai.litellm.agent_ext.llm.LiteLLMResolver properties: model: bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0 - custom_llm_provider: bedrock + conf: + custom_llm_provider: bedrock # --- Azure OpenAI --- # Requires: AZURE_API_KEY, AZURE_API_BASE, AZURE_API_VERSION @@ -142,8 +141,9 @@ llm_azure: class_name: rustic_ai.litellm.agent_ext.llm.LiteLLMResolver properties: model: azure/ - base_url: null - api_version: "2024-06-01" + conf: + base_url: null + api_version: "2024-06-01" # --- Cohere --- # Requires: COHERE_API_KEY diff --git a/forge-go/conf/forge-agent-registry.yaml b/forge-go/conf/forge-agent-registry.yaml index a132f8e..db91212 100644 --- a/forge-go/conf/forge-agent-registry.yaml +++ b/forge-go/conf/forge-agent-registry.yaml @@ -22,7 +22,7 @@ entries: class_name: rustic_ai.vertexai.agents.google_research_agent.GoogleResearchAgent description: Google Search grounding agent runtime: uvx - package: rusticai-vertexai + package: /home/nihal/Projects/ai-platform/rustic-ai/vertexai/dist/rusticai_vertexai-1.2.3-py3-none-any.whl secrets: - VERTEXAI_PROJECT - VERTEXAI_LOCATION @@ -30,7 +30,7 @@ entries: class_name: rustic_ai.vertexai.agents.content_moderation.ContentModerationAgent description: Vertex AI content moderation runtime: uvx - package: rusticai-vertexai + package: /home/nihal/Projects/ai-platform/rustic-ai/vertexai/dist/rusticai_vertexai-1.2.3-py3-none-any.whl with_dependencies: - pandas secrets: @@ -40,7 +40,7 @@ entries: class_name: rustic_ai.vertexai.agents.image_generation.VertexAiImagenAgent description: Vertex AI Imagen generation runtime: uvx - package: rusticai-vertexai + package: /home/nihal/Projects/ai-platform/rustic-ai/vertexai/dist/rusticai_vertexai-1.2.3-py3-none-any.whl secrets: - VERTEXAI_PROJECT - VERTEXAI_LOCATION @@ -54,6 +54,7 @@ entries: with_dependencies: - rusticai-litellm - rusticai-lancedb + - /home/nihal/Projects/ai-platform/rustic-ai/pandas-analyst/dist/rusticai_pandas_analyst-0.1.3-py3-none-any.whl secrets: - OPENAI_API_KEY - ANTHROPIC_API_KEY @@ -66,6 +67,7 @@ entries: with_dependencies: - rusticai-litellm - rusticai-lancedb + - /home/nihal/Projects/ai-platform/rustic-ai/pandas-analyst/dist/rusticai_pandas_analyst-0.1.3-py3-none-any.whl secrets: - OPENAI_API_KEY - ANTHROPIC_API_KEY @@ -175,132 +177,132 @@ entries: class_name: rustic_ai.demos.agents.bom_risk_explorer.ask_question_agent.AskQuestionAgent description: Auto-added from static agents snapshot runtime: uvx - package: rusticai-demos + package: /home/nihal/Projects/ai-platform/demos/dist/rusticai_demos-0.0.1-py3-none-any.whl - id: ComplianceScanAgent class_name: rustic_ai.demos.agents.contract_copilot.compliance_scan_agent.ComplianceScanAgent description: Auto-added from static agents snapshot runtime: uvx - package: rusticai-demos + package: /home/nihal/Projects/ai-platform/demos/dist/rusticai_demos-0.0.1-py3-none-any.whl - id: RedlineDiffAgent class_name: rustic_ai.demos.agents.contract_copilot.redline_diff_agent.RedlineDiffAgent description: Auto-added from static agents snapshot runtime: uvx - package: rusticai-demos + package: /home/nihal/Projects/ai-platform/demos/dist/rusticai_demos-0.0.1-py3-none-any.whl - id: CSVDataAgent class_name: rustic_ai.demos.agents.csv.csv_data_agent.CSVDataAgent description: Auto-added from static agents snapshot runtime: uvx - package: rusticai-demos + package: /home/nihal/Projects/ai-platform/demos/dist/rusticai_demos-0.0.1-py3-none-any.whl - id: ForecastingAgent class_name: rustic_ai.demos.agents.forecasting.prophet.ForecastingAgent description: Auto-added from static agents snapshot runtime: uvx - package: rusticai-demos + package: /home/nihal/Projects/ai-platform/demos/dist/rusticai_demos-0.0.1-py3-none-any.whl - id: BeautifulSoupAgent class_name: rustic_ai.demos.agents.html_parser.beautiful_soup_agent.BeautifulSoupAgent description: Auto-added from static agents snapshot runtime: uvx - package: rusticai-demos + package: /home/nihal/Projects/ai-platform/demos/dist/rusticai_demos-0.0.1-py3-none-any.whl - id: LifecycleScorerAgent class_name: rustic_ai.demos.agents.obsolescence_radar.lifecycle_scorer_agent.LifecycleScorerAgent description: Auto-added from static agents snapshot runtime: uvx - package: rusticai-demos + package: /home/nihal/Projects/ai-platform/demos/dist/rusticai_demos-0.0.1-py3-none-any.whl - id: ProductRiskCalculatorAgent class_name: rustic_ai.demos.agents.obsolescence_radar.product_risk_calculator_agent.ProductRiskCalculatorAgent description: Auto-added from static agents snapshot runtime: uvx - package: rusticai-demos + package: /home/nihal/Projects/ai-platform/demos/dist/rusticai_demos-0.0.1-py3-none-any.whl - id: ReplacementFinderAgent class_name: rustic_ai.demos.agents.obsolescence_radar.replacement_finder_agent.ReplacementFinderAgent description: Auto-added from static agents snapshot runtime: uvx - package: rusticai-demos + package: /home/nihal/Projects/ai-platform/demos/dist/rusticai_demos-0.0.1-py3-none-any.whl - id: OCRAgent class_name: rustic_ai.demos.agents.ocr.tesseract_agent.OCRAgent description: Auto-added from static agents snapshot runtime: uvx - package: rusticai-demos + package: /home/nihal/Projects/ai-platform/demos/dist/rusticai_demos-0.0.1-py3-none-any.whl - id: FileReaderWriterAgent class_name: rustic_ai.demos.agents.preprocessing.file_reader_writer_agent.FileReaderWriterAgent description: Auto-added from static agents snapshot runtime: uvx - package: rusticai-demos + package: /home/nihal/Projects/ai-platform/demos/dist/rusticai_demos-0.0.1-py3-none-any.whl - id: ImageAgent class_name: rustic_ai.demos.agents.preprocessing.image_agent.ImageAgent description: Auto-added from static agents snapshot runtime: uvx - package: rusticai-demos + package: /home/nihal/Projects/ai-platform/demos/dist/rusticai_demos-0.0.1-py3-none-any.whl - id: PandasAgent class_name: rustic_ai.demos.agents.preprocessing.pandas_agent.PandasAgent description: Auto-added from static agents snapshot runtime: uvx - package: rusticai-demos + package: /home/nihal/Projects/ai-platform/demos/dist/rusticai_demos-0.0.1-py3-none-any.whl - id: CPQAgent class_name: rustic_ai.demos.agents.quote_ai.cpq_integration_agent.CPQAgent description: Auto-added from static agents snapshot runtime: uvx - package: rusticai-demos + package: /home/nihal/Projects/ai-platform/demos/dist/rusticai_demos-0.0.1-py3-none-any.whl - id: OptimizerAgent class_name: rustic_ai.demos.agents.quote_ai.optimizer_agent.OptimizerAgent description: Auto-added from static agents snapshot runtime: uvx - package: rusticai-demos + package: /home/nihal/Projects/ai-platform/demos/dist/rusticai_demos-0.0.1-py3-none-any.whl - id: ReportGeneratorAgent class_name: rustic_ai.demos.agents.report_generator.report_agent.ReportGeneratorAgent description: Auto-added from static agents snapshot runtime: uvx - package: rusticai-demos + package: /home/nihal/Projects/ai-platform/demos/dist/rusticai_demos-0.0.1-py3-none-any.whl - id: HunterIOAgent class_name: rustic_ai.demos.agents.research.hunter_io_agent.HunterIOAgent description: Auto-added from static agents snapshot runtime: uvx - package: rusticai-demos + package: /home/nihal/Projects/ai-platform/demos/dist/rusticai_demos-0.0.1-py3-none-any.whl - id: RFQAssistManager class_name: rustic_ai.demos.agents.rfq_assist.manager.RFQAssistManager description: Auto-added from static agents snapshot runtime: uvx - package: rusticai-demos + package: /home/nihal/Projects/ai-platform/demos/dist/rusticai_demos-0.0.1-py3-none-any.whl - id: ClockAgent class_name: rustic_ai.demos.agents.simulation.clock_agent.ClockAgent description: Auto-added from static agents snapshot runtime: uvx - package: rusticai-demos + package: /home/nihal/Projects/ai-platform/demos/dist/rusticai_demos-0.0.1-py3-none-any.whl - id: DynamicRoutingAgent class_name: rustic_ai.demos.agents.simulation.dynamic_router_agent.DynamicRoutingAgent description: Auto-added from static agents snapshot runtime: uvx - package: rusticai-demos + package: /home/nihal/Projects/ai-platform/demos/dist/rusticai_demos-0.0.1-py3-none-any.whl - id: StatusTrackerAgent class_name: rustic_ai.demos.agents.simulation.status_tracker_agent.StatusTrackerAgent description: Auto-added from static agents snapshot runtime: uvx - package: rusticai-demos + package: /home/nihal/Projects/ai-platform/demos/dist/rusticai_demos-0.0.1-py3-none-any.whl - id: StoryImageAgent class_name: rustic_ai.demos.agents.story_telling.image_agent.StoryImageAgent description: Auto-added from static agents snapshot runtime: uvx - package: rusticai-demos + package: /home/nihal/Projects/ai-platform/demos/dist/rusticai_demos-0.0.1-py3-none-any.whl - id: LiteLLMAgentWithContext class_name: rustic_ai.demos.agents.story_telling.lite_llm_agent_with_context.LiteLLMAgentWithContext description: Auto-added from static agents snapshot runtime: uvx - package: rusticai-demos + package: /home/nihal/Projects/ai-platform/demos/dist/rusticai_demos-0.0.1-py3-none-any.whl - id: SyncMarvinAgent class_name: rustic_ai.demos.agents.story_telling.sync_classifier_agent.SyncMarvinAgent description: Auto-added from static agents snapshot runtime: uvx - package: rusticai-demos + package: /home/nihal/Projects/ai-platform/demos/dist/rusticai_demos-0.0.1-py3-none-any.whl - id: LineageBuilderAgent class_name: rustic_ai.demos.agents.traceability.lineage_builder_agent.LineageBuilderAgent description: Auto-added from static agents snapshot runtime: uvx - package: rusticai-demos + package: /home/nihal/Projects/ai-platform/demos/dist/rusticai_demos-0.0.1-py3-none-any.whl - id: VegaLiteAgent class_name: rustic_ai.demos.agents.viz.vegalite_agent.VegaLiteAgent description: Auto-added from static agents snapshot runtime: uvx - package: rusticai-demos + package: /home/nihal/Projects/ai-platform/demos/dist/rusticai_demos-0.0.1-py3-none-any.whl - id: AutonomousCFO class_name: rustic_ai.fiscal_eye.data_analyst.autonomous_cfo.AutonomousCFO description: Auto-added from static agents snapshot @@ -360,4 +362,9 @@ entries: class_name: rustic_ai.simulation.agent.SimulationAgent description: Auto-added from static agents snapshot runtime: uvx - package: rusticai-simulation \ No newline at end of file + package: rusticai-simulation + - id: MemoryAgent + class_name: rustic_ai.uniko_agent.agent.MemoryAgent + description: Memory and knowledge management agent + runtime: uvx + package: /home/nihal/Projects/ai-platform/rustic-ai/uniko-agent/dist/rusticai_uniko_agent-0.0.1-py3-none-any.whl \ No newline at end of file diff --git a/forge-go/go.mod b/forge-go/go.mod index 7a3918a..612c918 100644 --- a/forge-go/go.mod +++ b/forge-go/go.mod @@ -67,7 +67,6 @@ require ( github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.22.18 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.23 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.23 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6 // indirect github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.24 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.9 // indirect github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.15 // indirect @@ -79,12 +78,23 @@ require ( github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.21 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.42.1 // indirect github.com/aws/smithy-go v1.25.1 // indirect + github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bytedance/gopkg v0.1.4 // indirect github.com/bytedance/sonic v1.15.1 // indirect github.com/bytedance/sonic/loader v0.5.1 // indirect github.com/cenkalti/backoff/v5 v5.0.3 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/charmbracelet/bubbles v1.0.0 // indirect + github.com/charmbracelet/bubbletea v1.3.10 // indirect + github.com/charmbracelet/colorprofile v0.4.1 // indirect + github.com/charmbracelet/lipgloss v1.1.0 // indirect + github.com/charmbracelet/x/ansi v0.11.6 // indirect + github.com/charmbracelet/x/cellbuf v0.0.15 // indirect + github.com/charmbracelet/x/term v0.2.2 // indirect + github.com/clipperhouse/displaywidth v0.9.0 // indirect + github.com/clipperhouse/stringish v0.1.1 // indirect + github.com/clipperhouse/uax29/v2 v2.5.0 // indirect github.com/cloudwego/base64x v0.1.7 // indirect github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2 // indirect github.com/containerd/errdefs v1.0.0 // indirect @@ -92,13 +102,13 @@ require ( github.com/containerd/log v0.1.0 // indirect github.com/danieljoos/wincred v1.2.3 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/go-connections v0.7.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/envoyproxy/go-control-plane/envoy v1.37.0 // indirect github.com/envoyproxy/protoc-gen-validate v1.3.3 // indirect + github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect github.com/fatih/color v1.19.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/gabriel-vasile/mimetype v1.4.13 // indirect @@ -140,9 +150,12 @@ require ( github.com/klauspost/compress v1.18.6 // indirect github.com/klauspost/cpuid/v2 v2.3.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect + github.com/lucasb-eyer/go-colorful v1.3.0 // indirect github.com/lufia/plan9stats v0.0.0-20260330125221-c963978e514e // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.22 // indirect + github.com/mattn/go-localereader v0.0.1 // indirect + github.com/mattn/go-runewidth v0.0.19 // indirect github.com/mattn/go-sqlite3 v1.14.44 // indirect github.com/miekg/dns v1.1.72 // indirect github.com/minio/highwayhash v1.0.4 // indirect @@ -152,6 +165,9 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/morikuni/aec v1.1.0 // indirect + github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect + github.com/muesli/cancelreader v0.2.2 // indirect + github.com/muesli/termenv v0.16.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/nats-io/jwt/v2 v2.8.1 // indirect github.com/nats-io/nkeys v0.4.15 // indirect @@ -171,6 +187,7 @@ require ( github.com/quic-go/qpack v0.6.0 // indirect github.com/quic-go/quic-go v0.59.0 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect + github.com/rivo/uniseg v0.4.7 // indirect github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect github.com/shoenig/go-m1cpu v0.2.1 // indirect github.com/spf13/pflag v1.0.10 // indirect @@ -179,6 +196,7 @@ require ( github.com/tklauser/numcpus v0.11.0 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.3.1 // indirect + github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect github.com/yuin/gopher-lua v1.1.2 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect go.mongodb.org/mongo-driver/v2 v2.6.0 // indirect @@ -191,7 +209,6 @@ require ( go.yaml.in/yaml/v2 v2.4.4 // indirect golang.org/x/arch v0.27.0 // indirect golang.org/x/crypto v0.51.0 // indirect - golang.org/x/exp v0.0.0-20260508232706-74f9aab9d74a // indirect golang.org/x/mod v0.36.0 // indirect golang.org/x/net v0.54.0 // indirect golang.org/x/sync v0.20.0 // indirect diff --git a/forge-go/go.sum b/forge-go/go.sum index 114d581..3f577ce 100644 --- a/forge-go/go.sum +++ b/forge-go/go.sum @@ -1,55 +1,35 @@ -cel.dev/expr v0.25.1 h1:1KrZg61W6TWSxuNZ37Xy49ps13NUovb66QLprthtwi4= -cel.dev/expr v0.25.1/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4= cel.dev/expr v0.25.2 h1:K6j46C81hXtZQfuX60cVWQFBJahKSE2gfRbNuvr5bFs= cel.dev/expr v0.25.2/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE= cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU= -cloud.google.com/go/auth v0.18.2 h1:+Nbt5Ev0xEqxlNjd6c+yYUeosQ5TtEUaNcN/3FozlaM= -cloud.google.com/go/auth v0.18.2/go.mod h1:xD+oY7gcahcu7G2SG2DsBerfFxgPAJz17zz2joOFF3M= cloud.google.com/go/auth v0.20.0 h1:kXTssoVb4azsVDoUiF8KvxAqrsQcQtB53DcSgta74CA= cloud.google.com/go/auth v0.20.0/go.mod h1:942/yi/itH1SsmpyrbnTMDgGfdy2BUqIKyd0cyYLc5Q= cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc= cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c= cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= -cloud.google.com/go/iam v1.5.3 h1:+vMINPiDF2ognBJ97ABAYYwRgsaqxPbQDlMnbHMjolc= -cloud.google.com/go/iam v1.5.3/go.mod h1:MR3v9oLkZCTlaqljW6Eb2d3HGDGK5/bDv93jhfISFvU= cloud.google.com/go/iam v1.11.0 h1:KieQ9Pb+LLPak1O3Rv3GgCxhnmkYf7Xyh0P5HfF1jFM= cloud.google.com/go/iam v1.11.0/go.mod h1:KP+nKGugNJW4LcLx1uEZcq1ok5sQHFaQehQNl4QDgV4= -cloud.google.com/go/logging v1.13.1 h1:O7LvmO0kGLaHY/gq8cV7T0dyp6zJhYAOtZPX4TF3QtY= -cloud.google.com/go/logging v1.13.1/go.mod h1:XAQkfkMBxQRjQek96WLPNze7vsOmay9H5PqfsNYDqvw= cloud.google.com/go/logging v1.17.0 h1:rUFekZYwHiKElXCyz3zYBGz4BOeIqzgCKxVLdgrZ5mY= -cloud.google.com/go/longrunning v0.8.0 h1:LiKK77J3bx5gDLi4SMViHixjD2ohlkwBi+mKA7EhfW8= -cloud.google.com/go/longrunning v0.8.0/go.mod h1:UmErU2Onzi+fKDg2gR7dusz11Pe26aknR4kHmJJqIfk= +cloud.google.com/go/logging v1.17.0/go.mod h1:ZGKnpBaURITh+g/uom2VhbiFoFWvejcrHPDhxFtU/gI= cloud.google.com/go/longrunning v0.12.0 h1:wLv2hXvID9zHejLtcPo1B0JBjErnwZCYAPKSTa65xpY= -cloud.google.com/go/monitoring v1.24.3 h1:dde+gMNc0UhPZD1Azu6at2e79bfdztVDS5lvhOdsgaE= -cloud.google.com/go/monitoring v1.24.3/go.mod h1:nYP6W0tm3N9H/bOw8am7t62YTzZY+zUeQ+Bi6+2eonI= +cloud.google.com/go/longrunning v0.12.0/go.mod h1:8nqFBPOO1U/XkhWl0I19AMZEphrHi73VNABIpKYaTwM= cloud.google.com/go/monitoring v1.29.0 h1:AHhDsFaSax1/4k+qlIDX/SDGe6hggnfXJ9dkgD9qBPY= cloud.google.com/go/monitoring v1.29.0/go.mod h1:72NOVjJXHY/HBfoLT0+qlCZBT059+9VXLeAnL2PeeVM= -cloud.google.com/go/storage v1.57.2 h1:sVlym3cHGYhrp6XZKkKb+92I1V42ks2qKKpB0CF5Mb4= -cloud.google.com/go/storage v1.57.2/go.mod h1:n5ijg4yiRXXpCu0sJTD6k+eMf7GRrJmPyr9YxLXGHOk= cloud.google.com/go/storage v1.62.1 h1:Os0G3XbUbjZumkpDUf2Y0rLoXJTCF1kU2kWUujKYXD8= cloud.google.com/go/storage v1.62.1/go.mod h1:cpYz/kRVZ+UQAF1uHeea10/9ewcRbxGoGNKsS9daSXA= -cloud.google.com/go/trace v1.11.7 h1:kDNDX8JkaAG3R2nq1lIdkb7FCSi1rCmsEtKVsty7p+U= -cloud.google.com/go/trace v1.11.7/go.mod h1:TNn9d5V3fQVf6s4SCveVMIBS2LJUqo73GACmq/Tky0s= cloud.google.com/go/trace v1.15.0 h1:kAYkTwKyYHkGtAGFuu6qaUFRBkOVr+d1Yo44yZtGtgg= +cloud.google.com/go/trace v1.15.0/go.mod h1:r+bdAn16dKLSV1G2D5v3e58IlQlizfxWrUfjx7kM7X0= github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.30.0 h1:sBEjpZlNHzK1voKq9695PJSX2o5NEXl7/OL3coiIY0c= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.30.0/go.mod h1:P4WPRUkOhJC13W//jWpyfJNDAIpvRbAUIYLX/4jtlE0= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.32.0 h1:rIkQfkCOVKc1OiRCNcSDD8ml5RJlZbH/Xsq7lbpynwc= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.32.0/go.mod h1:RD2SsorTmYhF6HkTmDw7KmPYQk8OBYwTkuasChwv7R4= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.54.0 h1:lhhYARPUu3LmHysQ/igznQphfzynnqI3D75oUyw1HXk= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.54.0/go.mod h1:l9rva3ApbBpEJxSNYnwT9N4CDLrWgtq3u8736C5hyJw= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.56.0 h1:O2sXMyJh8b7devAGdE+163xtRurt0RVpB6DIzX5vGfg= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.56.0/go.mod h1:hEpiGU18xf70qb3jbTcIggWAiEfX/cOIVc2OTe4OegA= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.54.0 h1:xfK3bbi6F2RDtaZFtUdKO3osOBIhNb+xTs8lFW6yx9o= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.54.0/go.mod h1:vB2GH9GAYYJTO3mEn8oYwzEdhlayZIdQz6zdzgUIRvA= github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.56.0 h1:ZIT85vKP7LBS84XJ0WdJ3dPOX3iz4j3c0+lpajGQMyo= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.54.0 h1:s0WlVbf9qpvkh1c/uDAPElam0WrL7fHRIidgZJ7UqZI= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.54.0/go.mod h1:Mf6O40IAyB9zR/1J8nGDDPirZQQPbYJni8Yisy7NTMc= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.56.0/go.mod h1:rqP9UEhOXv9WhQ7Gjz+G5y/pf8+BJZW5/Ts0AhE0PwE= github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.56.0 h1:0YP0+/ixwu+Uqeu/FGiBZNQ19huiUxxiPXIc9WsLKuQ= github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.56.0/go.mod h1:6ZZMQhZKDvUvkJw2rc+oDP90tMMzuU/J+5HG1ZmPOmE= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= @@ -62,94 +42,52 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alicebob/miniredis/v2 v2.37.0 h1:RheObYW32G1aiJIj81XVt78ZHJpHonHLHW7OLIshq68= github.com/alicebob/miniredis/v2 v2.37.0/go.mod h1:TcL7YfarKPGDAthEtl5NBeHZfeUQj6OXMm/+iu5cLMM= -github.com/antithesishq/antithesis-sdk-go v0.6.0-default-no-op h1:kpBdlEPbRvff0mDD1gk7o9BhI16b9p5yYAXRlidpqJE= -github.com/antithesishq/antithesis-sdk-go v0.6.0-default-no-op/go.mod h1:IUpT2DPAKh6i/YhSbt6Gl3v2yvUZjmKncl7U91fup7E= github.com/antithesishq/antithesis-sdk-go v0.7.0 h1:uWDG8BqLD1lI2ps38WDz2vXflrTX2+vLX0SvZtztJtE= github.com/antithesishq/antithesis-sdk-go v0.7.0/go.mod h1:FQyySiasQQM8735Ddel3MRojmy4dA1IqCeyJ5jmPMbI= github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ= github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk= github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= -github.com/aws/aws-sdk-go-v2 v1.40.0 h1:/WMUA0kjhZExjOQN2z3oLALDREea1A7TobfuiBrKlwc= -github.com/aws/aws-sdk-go-v2 v1.40.0/go.mod h1:c9pm7VwuW0UPxAEYGyTmyurVcNrbF6Rt/wixFqDhcjE= github.com/aws/aws-sdk-go-v2 v1.41.7 h1:DWpAJt66FmnnaRIOT/8ASTucrvuDPZASqhhLey6tLY8= github.com/aws/aws-sdk-go-v2 v1.41.7/go.mod h1:4LAfZOPHNVNQEckOACQx60Y8pSRjIkNZQz1w92xpMJc= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.3 h1:DHctwEM8P8iTXFxC/QK0MRjwEpWQeM9yzidCRjldUz0= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.3/go.mod h1:xdCzcZEtnSTKVDOmUZs4l/j3pSV6rpo1WXl5ugNsL8Y= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.10 h1:gx1AwW1Iyk9Z9dD9F4akX5gnN3QZwUB20GGKH/I+Rho= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.10/go.mod h1:qqY157uZoqm5OXq/amuaBJyC9hgBCBQnsaWnPe905GY= -github.com/aws/aws-sdk-go-v2/config v1.32.2 h1:4liUsdEpUUPZs5WVapsJLx5NPmQhQdez7nYFcovrytk= -github.com/aws/aws-sdk-go-v2/config v1.32.2/go.mod h1:l0hs06IFz1eCT+jTacU/qZtC33nvcnLADAPL/XyrkZI= github.com/aws/aws-sdk-go-v2/config v1.32.17 h1:FpL4/758/diKwqbytU0prpuiu60fgXKUWCpDJtApclU= github.com/aws/aws-sdk-go-v2/config v1.32.17/go.mod h1:OXqUMzgXytfoF9JaKkhrOYsyh72t9G+MJH8mMRaexOE= -github.com/aws/aws-sdk-go-v2/credentials v1.19.2 h1:qZry8VUyTK4VIo5aEdUcBjPZHL2v4FyQ3QEOaWcFLu4= -github.com/aws/aws-sdk-go-v2/credentials v1.19.2/go.mod h1:YUqm5a1/kBnoK+/NY5WEiMocZihKSo15/tJdmdXnM5g= github.com/aws/aws-sdk-go-v2/credentials v1.19.16 h1:r3RJBuU7X9ibt8RHbMjWE6y60QbKBiII6wSrXnapxSU= github.com/aws/aws-sdk-go-v2/credentials v1.19.16/go.mod h1:6cx7zqDENJDbBIIWX6P8s0h6hqHC8Avbjh9Dseo27ug= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.14 h1:WZVR5DbDgxzA0BJeudId89Kmgy6DIU4ORpxwsVHz0qA= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.14/go.mod h1:Dadl9QO0kHgbrH1GRqGiZdYtW5w+IXXaBNCHTIaheM4= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.23 h1:UuSfcORqNSz/ey3VPRS8TcVH2Ikf0/sC+Hdj400QI6U= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.23/go.mod h1:+G/OSGiOFnSOkYloKj/9M35s74LgVAdJBSD5lsFfqKg= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.20.12 h1:Zy6Tme1AA13kX8x3CnkHx5cqdGWGaj/anwOiWGnA0Xo= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.20.12/go.mod h1:ql4uXYKoTM9WUAUSmthY4AtPVrlTBZOvnBJTiCUdPxI= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.22.18 h1:9XFUd2lkr7VrbE4Qtrhm7AtNhGgZeGFI5QLZtQIflj8= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.22.18/go.mod h1:trImuKdWelQIJALvyGj6sKolJ1W8t628JOoTdDGVL9Q= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.14 h1:PZHqQACxYb8mYgms4RZbhZG0a7dPW06xOjmaH0EJC/I= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.14/go.mod h1:VymhrMJUWs69D8u0/lZ7jSB6WgaG/NqHi3gX0aYf6U0= github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.23 h1:GpT/TrnBYuE5gan2cZbTtvP+JlHsutdmlV2YfEyNde0= github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.23/go.mod h1:xYWD6BS9ywC5bS3sz9Xh04whO/hzK2plt2Zkyrp4JuA= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.14 h1:bOS19y6zlJwagBfHxs0ESzr1XCOU2KXJCWcq3E2vfjY= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.14/go.mod h1:1ipeGBMAxZ0xcTm6y6paC2C/J6f6OO7LBODV9afuAyM= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.23 h1:bpd8vxhlQi2r1hiueOw02f/duEPTMK59Q4QMAoTTtTo= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.23/go.mod h1:15DfR2nw+CRHIk0tqNyifu3G1YdAOy68RftkhMDDwYk= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 h1:WKuaxf++XKWlHWu9ECbMlha8WOEGm0OUEZqm4K/Gcfk= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4/go.mod h1:ZWy7j6v1vWGmPReu0iSGvRiise4YI5SkR3OHKTZ6Wuc= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6 h1:qYQ4pzQ2Oz6WpQ8T3HvGHnZydA72MnLuFK9tJwmrbHw= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6/go.mod h1:O3h0IK87yXci+kg6flUKzJnWeziQUKciKrLjcatSNcY= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.14 h1:ITi7qiDSv/mSGDSWNpZ4k4Ve0DQR6Ug2SJQ8zEHoDXg= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.14/go.mod h1:k1xtME53H1b6YpZt74YmwlONMWf4ecM+lut1WQLAF/U= github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.24 h1:OQqn11BtaYv1WLUowvcA30MpzIu8Ti4pcLPIIyoKZrA= github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.24/go.mod h1:X5ZJyfwVrWA96GzPmUCWFQaEARPR7gCrpq2E92PJwAE= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.3 h1:x2Ibm/Af8Fi+BH+Hsn9TXGdT+hKbDd5XOTZxTMxDk7o= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.3/go.mod h1:IW1jwyrQgMdhisceG8fQLmQIydcT/jWY21rFhzgaKwo= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.9 h1:FLudkZLt5ci0ozzgkVo8BJGwvqNaZbTWb3UcucAateA= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.9/go.mod h1:w7wZ/s9qK7c8g4al+UyoF1Sp/Z45UwMGcqIzLWVQHWk= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.5 h1:Hjkh7kE6D81PgrHlE/m9gx+4TyyeLHuY8xJs7yXN5C4= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.5/go.mod h1:nPRXgyCfAurhyaTMoBMwRBYBhaHI4lNPAnJmjM0Tslc= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.15 h1:ieLCO1JxUWuxTZ1cRd0GAaeX7O6cIxnwk7tc1LsQhC4= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.15/go.mod h1:e3IzZvQ3kAWNykvE0Tr0RDZCMFInMvhku3qNpcIQXhM= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.14 h1:FIouAnCE46kyYqyhs0XEBDFFSREtdnr8HQuLPQPLCrY= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.14/go.mod h1:UTwDc5COa5+guonQU8qBikJo1ZJ4ln2r1MkF7Dqag1E= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.23 h1:pbrxO/kuIwgEsOPLkaHu0O+m4fNgLU8B3vxQ+72jTPw= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.23/go.mod h1:/CMNUqoj46HpS3MNRDEDIwcgEnrtZlKRaHNaHxIFpNA= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.14 h1:FzQE21lNtUor0Fb7QNgnEyiRCBlolLTX/Z1j65S7teM= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.14/go.mod h1:s1ydyWG9pm3ZwmmYN21HKyG9WzAZhYVW85wMHs5FV6w= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.23 h1:03xatSQO4+AM1lTAbnRg5OK528EUg744nW7F73U8DKw= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.23/go.mod h1:M8l3mwgx5ToK7wot2sBBce/ojzgnPzZXUV445gTSyE8= -github.com/aws/aws-sdk-go-v2/service/s3 v1.92.1 h1:OgQy/+0+Kc3khtqiEOk23xQAglXi3Tj0y5doOxbi5tg= -github.com/aws/aws-sdk-go-v2/service/s3 v1.92.1/go.mod h1:wYNqY3L02Z3IgRYxOBPH9I1zD9Cjh9hI5QOy/eOjQvw= github.com/aws/aws-sdk-go-v2/service/s3 v1.101.0 h1:etqBTKY581iwLL/H/S2sVgk3C9lAsTJFeXWFDsDcWOU= github.com/aws/aws-sdk-go-v2/service/s3 v1.101.0/go.mod h1:L2dcoOgS2VSgbPLvpak2NyUPsO1TBN7M45Z4H7DlRc4= -github.com/aws/aws-sdk-go-v2/service/signin v1.0.2 h1:MxMBdKTYBjPQChlJhi4qlEueqB1p1KcbTEa7tD5aqPs= -github.com/aws/aws-sdk-go-v2/service/signin v1.0.2/go.mod h1:iS6EPmNeqCsGo+xQmXv0jIMjyYtQfnwg36zl2FwEouk= github.com/aws/aws-sdk-go-v2/service/signin v1.0.11 h1:TdJ+HdzOBhU8+iVAOGUTU63VXopcumCOF1paFulHWZc= github.com/aws/aws-sdk-go-v2/service/signin v1.0.11/go.mod h1:R82ZRExE/nheo0N+T8zHPcLRTcH8MGsnR3BiVGX0TwI= -github.com/aws/aws-sdk-go-v2/service/sso v1.30.5 h1:ksUT5KtgpZd3SAiFJNJ0AFEJVva3gjBmN7eXUZjzUwQ= -github.com/aws/aws-sdk-go-v2/service/sso v1.30.5/go.mod h1:av+ArJpoYf3pgyrj6tcehSFW+y9/QvAY8kMooR9bZCw= github.com/aws/aws-sdk-go-v2/service/sso v1.30.17 h1:7byT8HUWrgoRp6sXjxtZwgOKfhss5fW6SkLBtqzgRoE= github.com/aws/aws-sdk-go-v2/service/sso v1.30.17/go.mod h1:xNWknVi4Ezm1vg1QsB/5EWpAJURq22uqd38U8qKvOJc= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.10 h1:GtsxyiF3Nd3JahRBJbxLCCdYW9ltGQYrFWg8XdkGDd8= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.10/go.mod h1:/j67Z5XBVDx8nZVp9EuFM9/BS5dvBznbqILGuu73hug= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.21 h1:+1Kl1zx6bWi4X7cKi3VYh29h8BvsCoHQEQ6ST9X8w7w= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.21/go.mod h1:4vIRDq+CJB2xFAXZ+YgGUTiEft7oAQlhIs71xcSeuVg= -github.com/aws/aws-sdk-go-v2/service/sts v1.41.2 h1:a5UTtD4mHBU3t0o6aHQZFJTNKVfxFWfPX7J0Lr7G+uY= -github.com/aws/aws-sdk-go-v2/service/sts v1.41.2/go.mod h1:6TxbXoDSgBQ225Qd8Q+MbxUxUh6TtNKwbRt/EPS9xso= github.com/aws/aws-sdk-go-v2/service/sts v1.42.1 h1:F/M5Y9I3nwr2IEpshZgh1GeHpOItExNM9L1euNuh/fk= github.com/aws/aws-sdk-go-v2/service/sts v1.42.1/go.mod h1:mTNxImtovCOEEuD65mKW7DCsL+2gjEH+RPEAexAzAio= -github.com/aws/smithy-go v1.24.0 h1:LpilSUItNPFr1eY85RYgTIg5eIEPtvFbskaFcmmIUnk= -github.com/aws/smithy-go v1.24.0/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0= github.com/aws/smithy-go v1.25.1 h1:J8ERsGSU7d+aCmdQur5Txg6bVoYelvQJgtZehD12GkI= github.com/aws/smithy-go v1.25.1/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= +github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= +github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -159,16 +97,10 @@ github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= -github.com/bytedance/gopkg v0.1.3 h1:TPBSwH8RsouGCBcMBktLt1AymVo2TVsBVCY4b6TnZ/M= -github.com/bytedance/gopkg v0.1.3/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM= github.com/bytedance/gopkg v0.1.4 h1:oZnQwnX82KAIWb7033bEwtxvTqXcYMxDBaQxo5JJHWM= github.com/bytedance/gopkg v0.1.4/go.mod h1:v1zWfPm21Fb+OsyXN2VAHdL6TBb2L88anLQgdyje6R4= -github.com/bytedance/sonic v1.15.0 h1:/PXeWFaR5ElNcVE84U0dOHjiMHQOwNIx3K4ymzh/uSE= -github.com/bytedance/sonic v1.15.0/go.mod h1:tFkWrPz0/CUCLEF4ri4UkHekCIcdnkqXw9VduqpJh0k= github.com/bytedance/sonic v1.15.1 h1:nJD5PmM0vY7J8CT6MxoqbVAAMhkSmV2HgRAUrrpLoOw= github.com/bytedance/sonic v1.15.1/go.mod h1:mT2NbXunuaEbnZ+mRIX/vYqKISmgEuHFDI4UzmKx2SA= -github.com/bytedance/sonic/loader v0.5.0 h1:gXH3KVnatgY7loH5/TkeVyXPfESoqSBSBEiDd5VjlgE= -github.com/bytedance/sonic/loader v0.5.0/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo= github.com/bytedance/sonic/loader v0.5.1 h1:Ygpfa9zwRCCKSlrp5bBP/b/Xzc3VxsAW+5NIYXrOOpI= github.com/bytedance/sonic/loader v0.5.1/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo= github.com/cbroglie/mustache v1.4.0 h1:Azg0dVhxTml5me+7PsZ7WPrQq1Gkf3WApcHMjMprYoU= @@ -178,14 +110,30 @@ github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F9 github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/charmbracelet/bubbles v1.0.0 h1:12J8/ak/uCZEMQ6KU7pcfwceyjLlWsDLAxB5fXonfvc= +github.com/charmbracelet/bubbles v1.0.0/go.mod h1:9d/Zd5GdnauMI5ivUIVisuEm3ave1XwXtD1ckyV6r3E= +github.com/charmbracelet/bubbletea v1.3.10 h1:otUDHWMMzQSB0Pkc87rm691KZ3SWa4KUlvF9nRvCICw= +github.com/charmbracelet/bubbletea v1.3.10/go.mod h1:ORQfo0fk8U+po9VaNvnV95UPWA1BitP1E0N6xJPlHr4= +github.com/charmbracelet/colorprofile v0.4.1 h1:a1lO03qTrSIRaK8c3JRxJDZOvhvIeSco3ej+ngLk1kk= +github.com/charmbracelet/colorprofile v0.4.1/go.mod h1:U1d9Dljmdf9DLegaJ0nGZNJvoXAhayhmidOdcBwAvKk= +github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY= +github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30= +github.com/charmbracelet/x/ansi v0.11.6 h1:GhV21SiDz/45W9AnV2R61xZMRri5NlLnl6CVF7ihZW8= +github.com/charmbracelet/x/ansi v0.11.6/go.mod h1:2JNYLgQUsyqaiLovhU2Rv/pb8r6ydXKS3NIttu3VGZQ= +github.com/charmbracelet/x/cellbuf v0.0.15 h1:ur3pZy0o6z/R7EylET877CBxaiE1Sp1GMxoFPAIztPI= +github.com/charmbracelet/x/cellbuf v0.0.15/go.mod h1:J1YVbR7MUuEGIFPCaaZ96KDl5NoS0DAWkskup+mOY+Q= +github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk= +github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= -github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M= -github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU= +github.com/clipperhouse/displaywidth v0.9.0 h1:Qb4KOhYwRiN3viMv1v/3cTBlz3AcAZX3+y9OLhMtAtA= +github.com/clipperhouse/displaywidth v0.9.0/go.mod h1:aCAAqTlh4GIVkhQnJpbL0T/WfcrJXHcj8C0yjYcjOZA= +github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs= +github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA= +github.com/clipperhouse/uax29/v2 v2.5.0 h1:x7T0T4eTHDONxFJsL94uKNKPHrclyFI0lm7+w94cO8U= +github.com/clipperhouse/uax29/v2 v2.5.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g= github.com/cloudwego/base64x v0.1.7 h1:NppS+Fgzg5ovhn4NkUXaDT3x9jldgH5ToMCqzBSi2zI= github.com/cloudwego/base64x v0.1.7/go.mod h1:Cu1PV9zfrSf7ET2tIbWbbEy7jO7HHJ13q4X2SQ8aWYg= -github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 h1:6xNmx7iTtyBRev0+D/Tv1FZd4SCg8axKApyNyRsAt/w= -github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5/go.mod h1:KdCmV+x/BuvyMxRnYBlmVaq4OLiKW6iRQfvC62cvdkI= github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2 h1:aBangftG7EVZoUb69Os8IaYg++6uMOdKK83QtkkvJik= github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2/go.mod h1:qwXFYgsP6T7XnJtbKlf1HP8AjxZZyzxMmc+Lq5GjlU4= github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= @@ -201,16 +149,12 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= -github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI= github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/docker/docker v28.5.2+incompatible h1:DBX0Y0zAjZbSrm1uzOkdr1onVghKaftjlSWt4AFexzM= github.com/docker/docker v28.5.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94= -github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE= github.com/docker/go-connections v0.7.0 h1:6SsRfJddP22WMrCkj19x9WKjEDTB+ahsdiGYf0mN39c= github.com/docker/go-connections v0.7.0/go.mod h1:no1qkHdjq7kLMGUXYAduOhYPSJxxvgWBh7ogVvptn3Q= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= @@ -219,34 +163,25 @@ github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkp github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/envoyproxy/go-control-plane v0.14.0 h1:hbG2kr4RuFj222B6+7T83thSPqLjwBIfQawTkC++2HA= github.com/envoyproxy/go-control-plane v0.14.0/go.mod h1:NcS5X47pLl/hfqxU70yPwL9ZMkUlwlKxtAohpi2wBEU= -github.com/envoyproxy/go-control-plane/envoy v1.36.0 h1:yg/JjO5E7ubRyKX3m07GF3reDNEnfOboJ0QySbH736g= -github.com/envoyproxy/go-control-plane/envoy v1.36.0/go.mod h1:ty89S1YCCVruQAm9OtKeEkQLTb+Lkz0k8v9W0Oxsv98= github.com/envoyproxy/go-control-plane/envoy v1.37.0 h1:u3riX6BoYRfF4Dr7dwSOroNfdSbEPe9Yyl09/B6wBrQ= github.com/envoyproxy/go-control-plane/envoy v1.37.0/go.mod h1:DReE9MMrmecPy+YvQOAOHNYMALuowAnbjjEMkkWOi6A= github.com/envoyproxy/go-control-plane/ratelimit v0.1.0 h1:/G9QYbddjL25KvtKTv3an9lx6VBE2cnb8wp1vEGNYGI= github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJPzVVHnPgRKdUdwW/KdbRt94AzgRee4= -github.com/envoyproxy/protoc-gen-validate v1.3.0 h1:TvGH1wof4H33rezVKWSpqKz5NXWg5VPuZ0uONDT6eb4= -github.com/envoyproxy/protoc-gen-validate v1.3.0/go.mod h1:HvYl7zwPa5mffgyeTUHA9zHIH36nmrm7oCbo4YKoSWA= github.com/envoyproxy/protoc-gen-validate v1.3.3 h1:MVQghNeW+LZcmXe7SY1V36Z+WFMDjpqGAGacLe2T0ds= github.com/envoyproxy/protoc-gen-validate v1.3.3/go.mod h1:TsndJ/ngyIdQRhMcVVGDDHINPLWB7C82oDArY51KfB0= -github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= +github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4= +github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/color v1.19.0 h1:Zp3PiM21/9Ld6FzSKyL5c/BULoe/ONr9KlbYVOfG8+w= github.com/fatih/color v1.19.0/go.mod h1:zNk67I0ZUT1bEGsSGyCZYZNrHuTkJJB+r6Q9VuMi0LE= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/gabriel-vasile/mimetype v1.4.12 h1:e9hWvmLYvtp846tLHam2o++qitpguFiYCKbn0w9jyqw= -github.com/gabriel-vasile/mimetype v1.4.12/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s= github.com/gabriel-vasile/mimetype v1.4.13 h1:46nXokslUBsAJE/wMsp5gtO500a4F3Nkz9Ufpk2AcUM= github.com/gabriel-vasile/mimetype v1.4.13/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s= -github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w= -github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM= github.com/gin-contrib/sse v1.1.1 h1:uGYpNwTacv5R68bSGMapo62iLTRa9l5zxGCps4hK6ko= github.com/gin-contrib/sse v1.1.1/go.mod h1:QXzuVkA0YO7o/gun03UI1Q+FTI8ZV/n5t03kIQAI89s= github.com/gin-gonic/gin v1.12.0 h1:b3YAbrZtnf8N//yjKeU2+MQsh2mY5htkZidOM7O0wG8= github.com/gin-gonic/gin v1.12.0/go.mod h1:VxccKfsSllpKshkBWgVgRniFFAzFb9csfngsqANjnLc= -github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs= -github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= @@ -260,7 +195,6 @@ github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= @@ -270,8 +204,6 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.30.1 h1:f3zDSN/zOma+w6+1Wswgd9fLkdwy06ntQJp0BBvFG0w= -github.com/go-playground/validator/v10 v10.30.1/go.mod h1:oSuBIQzuJxL//3MelwSLD5hc2Tu889bF0Idm9Dg26cM= github.com/go-playground/validator/v10 v10.30.2 h1:JiFIMtSSHb2/XBUbWM4i/MpeQm9ZK2xqPNk8vgvu5JQ= github.com/go-playground/validator/v10 v10.30.2/go.mod h1:mAf2pIOVXjTEBrwUMGKkCWKKPs9NheYGabeB04txQSc= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -279,8 +211,6 @@ github.com/go-zeromq/goczmq/v4 v4.2.2 h1:HAJN+i+3NW55ijMJJhk7oWxHKXgAuSBkoFfvr8b github.com/go-zeromq/goczmq/v4 v4.2.2/go.mod h1:Sm/lxrfxP/Oxqs0tnHD6WAhwkWrx+S+1MRrKzcxoaYE= github.com/go-zeromq/zmq4 v0.17.0 h1:r12/XdqPeRbuaF4C3QZJeWCt7a5vpJbslDH1rTXF+Kc= github.com/go-zeromq/zmq4 v0.17.0/go.mod h1:EQxjJD92qKnrsVMzAnx62giD6uJIPi1dMGZ781iCDtY= -github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= -github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/goccy/go-json v0.10.6 h1:p8HrPJzOakx/mn/bQtjgNjdTcN+/S6FcG2CTtQOrHVU= github.com/goccy/go-json v0.10.6/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM= @@ -307,7 +237,6 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-replayers/grpcreplay v1.3.0 h1:1Keyy0m1sIpqstQmgz307zhiJ1pV4uIlFds5weTmxbo= @@ -327,29 +256,20 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/wire v0.7.0 h1:JxUKI6+CVBgCO2WToKy/nQk0sS+amI9z9EjVmdaocj4= github.com/google/wire v0.7.0/go.mod h1:n6YbUQD9cPKTnHXEBN2DXlOp/mVADhVErcMFb0v3J18= -github.com/googleapis/enterprise-certificate-proxy v0.3.14 h1:yh8ncqsbUY4shRD5dA6RlzjJaT4hi3kII+zYw8wmLb8= -github.com/googleapis/enterprise-certificate-proxy v0.3.14/go.mod h1:vqVt9yG9480NtzREnTlmGSBmFrA+bzb0yl0TxoBQXOg= github.com/googleapis/enterprise-certificate-proxy v0.3.15 h1:xolVQTEXusUcAA5UgtyRLjelpFFHWlPQ4XfWGc7MBas= github.com/googleapis/enterprise-certificate-proxy v0.3.15/go.mod h1:vqVt9yG9480NtzREnTlmGSBmFrA+bzb0yl0TxoBQXOg= -github.com/googleapis/gax-go/v2 v2.17.0 h1:RksgfBpxqff0EZkDWYuz9q/uWsTVz+kf43LsZ1J6SMc= -github.com/googleapis/gax-go/v2 v2.17.0/go.mod h1:mzaqghpQp4JDh3HvADwrat+6M3MOIDp5YKHhb9PAgDY= github.com/googleapis/gax-go/v2 v2.22.0 h1:PjIWBpgGIVKGoCXuiCoP64altEJCj3/Ei+kSU5vlZD4= github.com/googleapis/gax-go/v2 v2.22.0/go.mod h1:irWBbALSr0Sk3qlqb9SyJ1h68WjgeFuiOzI4Rqw5+aY= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 h1:HWRh5R2+9EifMyIHV7ZV+MIZqgz+PMpZ14Jynv3O2Zs= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0/go.mod h1:JfhWUomR1baixubs02l85lZYYOm7LV6om4ceouMv45c= github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0 h1:5VipnvEpbqr2gA2VbM+nYVbkIF28c5ZQfqCBQ5g2xfk= github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0/go.mod h1:Hyl3n6Twe1hvtd9XUXDec4pTvgMSEixRuQKPTMH2bNs= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-hclog v1.6.2 h1:NOtoftovWkDheyUM/8JW3QMiXyxJK3uHRK7wV04nD2I= -github.com/hashicorp/go-hclog v1.6.2/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= -github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= @@ -364,10 +284,11 @@ github.com/hashicorp/go-sockaddr v1.0.7 h1:G+pTkSO01HpR5qCxg7lxfsFEZaG+C0VssTy/9 github.com/hashicorp/go-sockaddr v1.0.7/go.mod h1:FZQbEYa1pxkQ7WLpyXJ6cbjpT8q0YgQaK/JakXqGyWw= github.com/hashicorp/go-uuid v1.0.0 h1:RS8zrF7PhGwyNPOtxSClXXj9HA8feRnJzgnI1RJCSnM= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hashicorp/memberlist v0.5.4 h1:40YY+3qq2tAUhZIMEK8kqusKZBBjdwJ3NUjvYkcxh74= github.com/hashicorp/memberlist v0.5.4/go.mod h1:OgN6xiIo6RlHUWk+ALjP9e32xWCoQrsOCmHrWCm2MWA= github.com/hashicorp/raft v1.7.3 h1:DxpEqZJysHN0wK+fviai5mFcSYsCkNpFUl1xpAW8Rbo= @@ -378,8 +299,6 @@ github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsI github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= -github.com/jackc/pgx/v5 v5.6.0 h1:SWJzexBzPL5jb0GEsrPMLIsi/3jOo7RHlzTjcAeDrPY= -github.com/jackc/pgx/v5 v5.6.0/go.mod h1:DNZ/vlrUnhWCoFGxHAG8U2ljioxukquj7utPDgtQdTw= github.com/jackc/pgx/v5 v5.9.2 h1:3ZhOzMWnR4yJ+RW1XImIPsD1aNSz4T4fyP7zlQb56hw= github.com/jackc/pgx/v5 v5.9.2/go.mod h1:mal1tBGAFfLHvZzaYh77YS/eC6IX9OWbRV1QIIM0Jn4= github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= @@ -398,8 +317,6 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c= -github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4= github.com/klauspost/compress v1.18.6 h1:2jupLlAwFm95+YDR+NwD2MEfFO9d4z4Prjl1XXDjuao= github.com/klauspost/compress v1.18.6/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= @@ -418,34 +335,27 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0 github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= -github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= -github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/lucasb-eyer/go-colorful v1.3.0 h1:2/yBRLdWBZKrf7gB40FoiKfAWYQ0lqNcbuQwVHXptag= +github.com/lucasb-eyer/go-colorful v1.3.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/lufia/plan9stats v0.0.0-20260330125221-c963978e514e h1:Q6MvJtQK/iRcRtzAscm/zF23XxJlbECiGPyRicsX+Ak= github.com/lufia/plan9stats v0.0.0-20260330125221-c963978e514e/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.22 h1:j8l17JJ9i6VGPUFUYoTUKPSgKe/83EYU2zBC7YNKMw4= github.com/mattn/go-isatty v0.0.22/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4= -github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= -github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4= +github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= +github.com/mattn/go-runewidth v0.0.19 h1:v++JhqYnZuu5jSKrk9RbgF5v4CGUjqRfBm05byFGLdw= +github.com/mattn/go-runewidth v0.0.19/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= github.com/mattn/go-sqlite3 v1.14.44 h1:3VSe+xafpbzsLbdr2AWlAZk9yRHiBhTBakioXaCKTF8= github.com/mattn/go-sqlite3 v1.14.44/go.mod h1:pjEuOr8IwzLJP2MfGeTb0A35jauH+C2kbHKBr7yXKVQ= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/miekg/dns v1.1.68 h1:jsSRkNozw7G/mnmXULynzMNIsgY2dHC8LO6U6Ij2JEA= -github.com/miekg/dns v1.1.68/go.mod h1:fujopn7TB3Pu3JM69XaawiU0wqjpL9/8xGop5UrTPps= github.com/miekg/dns v1.1.72 h1:vhmr+TF2A3tuoGNkLDFK9zi36F2LS+hKTRW0Uf8kbzI= github.com/miekg/dns v1.1.72/go.mod h1:+EuEPhdHOsfk6Wk5TT2CzssZdqkmFhf8r+aVyDEToIs= -github.com/minio/highwayhash v1.0.4-0.20251030100505-070ab1a87a76 h1:KGuD/pM2JpL9FAYvBrnBBeENKZNh6eNtjqytV6TYjnk= -github.com/minio/highwayhash v1.0.4-0.20251030100505-070ab1a87a76/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ= github.com/minio/highwayhash v1.0.4 h1:asJizugGgchQod2ja9NJlGOWq4s7KsAWr5XUc9Clgl4= github.com/minio/highwayhash v1.0.4/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= @@ -465,30 +375,28 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/morikuni/aec v1.1.0 h1:vBBl0pUnvi/Je71dsRrhMBtreIqNMYErSAbEeb8jrXQ= github.com/morikuni/aec v1.1.0/go.mod h1:xDRgiq/iw5l+zkao76YTKzKttOp2cwPEne25HDkJnBw= +github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI= +github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo= +github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= +github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= +github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc= +github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nats-io/jwt/v2 v2.8.1 h1:V0xpGuD/N8Mi+fQNDynXohVvp7ZztevW5io8CUWlPmU= github.com/nats-io/jwt/v2 v2.8.1/go.mod h1:nWnOEEiVMiKHQpnAy4eXlizVEtSfzacZ1Q43LIRavZg= -github.com/nats-io/nats-server/v2 v2.12.6 h1:Egbx9Vl7Ch8wTtpXPGqbehkZ+IncKqShUxvrt1+Enc8= -github.com/nats-io/nats-server/v2 v2.12.6/go.mod h1:4HPlrvtmSO3yd7KcElDNMx9kv5EBJBnJJzQPptXlheo= github.com/nats-io/nats-server/v2 v2.14.0 h1:+8q0HrDFotwLLcGH/legOEOnowunhK+aZ4GYBIWpQlM= github.com/nats-io/nats-server/v2 v2.14.0/go.mod h1:ImVUUDvfClJbb6cuJQRc1VmgDCXKM5ds0OoiG9MVOKo= -github.com/nats-io/nats.go v1.49.0 h1:yh/WvY59gXqYpgl33ZI+XoVPKyut/IcEaqtsiuTJpoE= -github.com/nats-io/nats.go v1.49.0/go.mod h1:fDCn3mN5cY8HooHwE2ukiLb4p4G4ImmzvXyJt+tGwdw= github.com/nats-io/nats.go v1.52.0 h1:n3avV4VBsCgsdwh71TppsTwtv+QdPs7ntSKM8qJLGsc= github.com/nats-io/nats.go v1.52.0/go.mod h1:26HypzazeOkyO3/mqd1zZd53STJN0EjCYF9Uy2ZOBno= github.com/nats-io/nkeys v0.4.15 h1:JACV5jRVO9V856KOapQ7x+EY8Jo3qw1vJt/9Jpwzkk4= github.com/nats-io/nkeys v0.4.15/go.mod h1:CpMchTXC9fxA5zrMo4KpySxNjiDVvr8ANOSZdiNfUrs= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= -github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w= github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= -github.com/oapi-codegen/runtime v1.2.0 h1:RvKc1CVS1QeKSNzO97FBQbSMZyQ8s6rZd+LpmzwHMP4= -github.com/oapi-codegen/runtime v1.2.0/go.mod h1:Y7ZhmmlE8ikZOmuHRRndiIm7nf3xcVv+YMweKgG1DT0= github.com/oapi-codegen/runtime v1.4.0 h1:KLOSFOp7UzkbS7Cs1ms6NBEKYr0WmH2wZG0KKbd2er4= github.com/oapi-codegen/runtime v1.4.0/go.mod h1:5sw5fxCDmnOzKNYmkVNF8d34kyUeejJEY8HNT2WaPec= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= @@ -497,8 +405,6 @@ github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJw github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= -github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/pelletier/go-toml/v2 v2.3.1 h1:MYEvvGnQjeNkRF1qUuGolNtNExTDwct51yp7olPtrEc= github.com/pelletier/go-toml/v2 v2.3.1/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -510,8 +416,6 @@ github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= -github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU= github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= @@ -539,20 +443,18 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4Vws= -github.com/prometheus/procfs v0.19.2/go.mod h1:M0aotyiemPhBCM0z5w87kL22CxfcH05ZpYlu+b4J7mw= github.com/prometheus/procfs v0.20.1 h1:XwbrGOIplXW/AU3YhIhLODXMJYyC1isLFfYCsTEycfc= github.com/prometheus/procfs v0.20.1/go.mod h1:o9EMBZGRyvDrSPH1RqdxhojkuXstoe4UlK79eF5TGGo= github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8= github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII= github.com/quic-go/quic-go v0.59.0 h1:OLJkp1Mlm/aS7dpKgTc6cnpynnD2Xg7C1pwL6vy/SAw= github.com/quic-go/quic-go v0.59.0/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU= -github.com/redis/go-redis/v9 v9.18.0 h1:pMkxYPkEbMPwRdenAzUNyFNrDgHx9U+DrBabWNfSRQs= -github.com/redis/go-redis/v9 v9.18.0/go.mod h1:k3ufPphLU5YXwNTUcCRXGxUoF1fqxnhFQmscfkCoDA0= github.com/redis/go-redis/v9 v9.19.0 h1:XPVaaPSnG6RhYf7p+rmSa9zZfeVAnWsH5h3lxthOm/k= github.com/redis/go-redis/v9 v9.19.0/go.mod h1:v/M13XI1PVCDcm01VtPFOADfZtHf8YW3baQf57KlIkA= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -562,13 +464,10 @@ github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUt github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI= github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk= -github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= -github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shoenig/go-m1cpu v0.2.1 h1:yqRB4fvOge2+FyRXFkXqsyMoqPazv14Yyy+iyccT2E4= github.com/shoenig/go-m1cpu v0.2.1/go.mod h1:KkDOw6m3ZJQAPHbrzkZki4hnx+pDRR1Lo+ldA56wD5w= -github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= -github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= github.com/shoenig/test v1.7.0 h1:eWcHtTXa6QLnBvm0jgEabMRN/uJ4DMV3M8xUGgRkZmk= +github.com/shoenig/test v1.7.0/go.mod h1:UxJ6u/x2v/TNs/LoLxBNJRV9DiwBBKYxXSyczsBHFoI= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= @@ -599,12 +498,8 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= -github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= -github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/go-sysconf v0.3.16 h1:frioLaCQSsF5Cy1jgRBrzr6t502KIIwQ0MArYICU0nA= github.com/tklauser/go-sysconf v0.3.16/go.mod h1:/qNL9xxDhc7tx3HSRsLWNnuzbVfh3e7gh/BmM179nYI= -github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= -github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/tklauser/numcpus v0.11.0 h1:nSTwhKH5e1dMNsCdVBukSZrURJRoHbSEQjdEbY+9RXw= github.com/tklauser/numcpus v0.11.0/go.mod h1:z+LwcLq54uWZTX0u/bGobaV34u6V7KNlTZejzM6/3MQ= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= @@ -612,84 +507,50 @@ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/ugorji/go/codec v1.3.1 h1:waO7eEiFDwidsBN6agj1vJQ4AG7lh2yqXyOXqhgQuyY= github.com/ugorji/go/codec v1.3.1/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4= -github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M= -github.com/yuin/gopher-lua v1.1.1/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= github.com/yuin/gopher-lua v1.1.2 h1:yF/FjE3hD65tBbt0VXLE13HWS9h34fdzJmrWRXwobGA= github.com/yuin/gopher-lua v1.1.2/go.mod h1:7aRmXIWl37SqRf0koeyylBEzJ+aPt8A+mmkQ4f1ntR8= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/zalando/go-keyring v0.2.8 h1:6sD/Ucpl7jNq10rM2pgqTs0sZ9V3qMrqfIIy5YPccHs= github.com/zalando/go-keyring v0.2.8/go.mod h1:tsMo+VpRq5NGyKfxoBVjCuMrG47yj8cmakZDO5QGii0= -github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0= -github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= github.com/zeebo/xxh3 v1.1.0 h1:s7DLGDK45Dyfg7++yxI0khrfwq9661w9EN78eP/UZVs= -go.mongodb.org/mongo-driver/v2 v2.5.0 h1:yXUhImUjjAInNcpTcAlPHiT7bIXhshCTL3jVBkF3xaE= -go.mongodb.org/mongo-driver/v2 v2.5.0/go.mod h1:yOI9kBsufol30iFsl1slpdq1I0eHPzybRWdyYUs8K/0= +github.com/zeebo/xxh3 v1.1.0/go.mod h1:IisAie1LELR4xhVinxWS5+zf1lA4p0MW4T+w+W07F5s= go.mongodb.org/mongo-driver/v2 v2.6.0 h1:b9sJOYrkmt4l8bY43ZenFBcPlhYIjaOfYHLtbB/5qi8= go.mongodb.org/mongo-driver/v2 v2.6.0/go.mod h1:yOI9kBsufol30iFsl1slpdq1I0eHPzybRWdyYUs8K/0= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= -go.opentelemetry.io/contrib/detectors/gcp v1.39.0 h1:kWRNZMsfBHZ+uHjiH4y7Etn2FK26LAGkNFw7RHv1DhE= -go.opentelemetry.io/contrib/detectors/gcp v1.39.0/go.mod h1:t/OGqzHBa5v6RHZwrDBJ2OirWc+4q/w2fTbLZwAKjTk= go.opentelemetry.io/contrib/detectors/gcp v1.43.0 h1:62yY3dT7/ShwOxzA0RsKRgshBmfElKI4d/Myu2OxDFU= go.opentelemetry.io/contrib/detectors/gcp v1.43.0/go.mod h1:RyaZMFY7yi1kAs45S6mbFGz8O8rqB0dTY14uzvG4LCs= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0 h1:YH4g8lQroajqUwWbq/tr2QX1JFmEXaDLgG+ew9bLMWo= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0/go.mod h1:fvPi2qXDqFs8M4B4fmJhE92TyQs9Ydjlg3RvfUp+NbQ= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 h1:0Qx7VGBacMm9ZENQ7TnNObTYI4ShC+lHI16seduaxZo= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0/go.mod h1:Sje3i3MjSPKTSPvVWCaL8ugBzJwik3u4smCjUeuupqg= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0 h1:OyrsyzuttWTSur2qN/Lm0m2a8yqyIjUVBZcxFPuXq2o= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0/go.mod h1:C2NGBr+kAB4bk3xtMXfZ94gqFDtg/GkI7e9zqGh5Beg= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 h1:CqXxU8VOmDefoh0+ztfGaymYbhdB/tT3zs79QaZTNGY= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0/go.mod h1:BuhAPThV8PBHBvg8ZzZ/Ok3idOdhWIodywz2xEcRbJo= -go.opentelemetry.io/otel v1.42.0 h1:lSQGzTgVR3+sgJDAU/7/ZMjN9Z+vUip7leaqBKy4sho= -go.opentelemetry.io/otel v1.42.0/go.mod h1:lJNsdRMxCUIWuMlVJWzecSMuNjE7dOYyWlqOXWkdqCc= go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I= go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.42.0 h1:H7O6RlGOMTizyl3R08Kn5pdM06bnH8oscSj7o11tmLA= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.42.0/go.mod h1:mBFWu/WOVDkWWsR7Tx7h6EpQB8wsv7P0Yrh0Pb7othc= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.43.0 h1:w1K+pCJoPpQifuVpsKamUdn9U0zM3xUziVOqsGksUrY= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.43.0/go.mod h1:HBy4BjzgVE8139ieRI75oXm3EcDN+6GhD88JT1Kjvxg= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.42.0 h1:THuZiwpQZuHPul65w4WcwEnkX2QIuMT+UFoOrygtoJw= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.42.0/go.mod h1:J2pvYM5NGHofZ2/Ru6zw/TNWnEQp5crgyDeSrYpXkAw= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 h1:88Y4s2C8oTui1LGM6bTWkw0ICGcOLCAI5l6zsD1j20k= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0/go.mod h1:Vl1/iaggsuRlrHf/hfPJPvVag77kKyvrLeD10kpMl+A= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.42.0 h1:zWWrB1U6nqhS/k6zYB74CjRpuiitRtLLi68VcgmOEto= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.42.0/go.mod h1:2qXPNBX1OVRC0IwOnfo1ljoid+RD0QK3443EaqVlsOU= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0 h1:RAE+JPfvEmvy+0LzyUA25/SGawPwIUbZ6u0Wug54sLc= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0/go.mod h1:AGmbycVGEsRx9mXMZ75CsOyhSP6MFIcj/6dnG+vhVjk= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.42.0 h1:uLXP+3mghfMf7XmV4PkGfFhFKuNWoCvvx5wP/wOXo0o= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.42.0/go.mod h1:v0Tj04armyT59mnURNUJf7RCKcKzq+lgJs6QSjHjaTc= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0 h1:3iZJKlCZufyRzPzlQhUIWVmfltrXuGyfjREgGP3UUjc= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0/go.mod h1:/G+nUPfhq2e+qiXMGxMwumDrP5jtzU+mWN7/sjT2rak= -go.opentelemetry.io/otel/exporters/prometheus v0.64.0 h1:g0LRDXMX/G1SEZtK8zl8Chm4K6GBwRkjPKE36LxiTYs= -go.opentelemetry.io/otel/exporters/prometheus v0.64.0/go.mod h1:UrgcjnarfdlBDP3GjDIJWe6HTprwSazNjwsI+Ru6hro= go.opentelemetry.io/otel/exporters/prometheus v0.65.0 h1:jOveH/b4lU9HT7y+Gfamf18BqlOuz2PWEvs8yM7Q6XE= go.opentelemetry.io/otel/exporters/prometheus v0.65.0/go.mod h1:i1P8pcumauPtUI4YNopea1dhzEMuEqWP1xoUZDylLHo= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.37.0 h1:6VjV6Et+1Hd2iLZEPtdV7vie80Yyqf7oikJLjQ/myi0= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.37.0/go.mod h1:u8hcp8ji5gaM/RfcOo8z9NMnf1pVLfVY7lBY2VOGuUU= go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.43.0 h1:TC+BewnDpeiAmcscXbGMfxkO+mwYUwE/VySwvw88PfA= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.42.0 h1:s/1iRkCKDfhlh1JF26knRneorus8aOwVIDhvYx9WoDw= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.42.0/go.mod h1:UI3wi0FXg1Pofb8ZBiBLhtMzgoTm1TYkMvn71fAqDzs= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.43.0/go.mod h1:J/ZyF4vfPwsSr9xJSPyQ4LqtcTPULFR64KwTikGLe+A= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.43.0 h1:mS47AX77OtFfKG4vtp+84kuGSFZHTyxtXIN269vChY0= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.43.0/go.mod h1:PJnsC41lAGncJlPUniSwM81gc80GkgWJWr3cu2nKEtU= -go.opentelemetry.io/otel/metric v1.42.0 h1:2jXG+3oZLNXEPfNmnpxKDeZsFI5o4J+nz6xUlaFdF/4= -go.opentelemetry.io/otel/metric v1.42.0/go.mod h1:RlUN/7vTU7Ao/diDkEpQpnz3/92J9ko05BIwxYa2SSI= go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM= go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY= -go.opentelemetry.io/otel/sdk v1.42.0 h1:LyC8+jqk6UJwdrI/8VydAq/hvkFKNHZVIWuslJXYsDo= -go.opentelemetry.io/otel/sdk v1.42.0/go.mod h1:rGHCAxd9DAph0joO4W6OPwxjNTYWghRWmkHuGbayMts= go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg= go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg= -go.opentelemetry.io/otel/sdk/metric v1.42.0 h1:D/1QR46Clz6ajyZ3G8SgNlTJKBdGp84q9RKCAZ3YGuA= -go.opentelemetry.io/otel/sdk/metric v1.42.0/go.mod h1:Ua6AAlDKdZ7tdvaQKfSmnFTdHx37+J4ba8MwVCYM5hc= go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw= go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A= -go.opentelemetry.io/otel/trace v1.42.0 h1:OUCgIPt+mzOnaUTpOQcBiM/PLQ/Op7oq6g4LenLmOYY= -go.opentelemetry.io/otel/trace v1.42.0/go.mod h1:f3K9S+IFqnumBkKhRJMeaZeNk9epyhnCmQh/EysQCdc= go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A= go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0= -go.opentelemetry.io/proto/otlp v1.9.0 h1:l706jCMITVouPOqEnii2fIAuO3IVGBRPV5ICjceRb/A= -go.opentelemetry.io/proto/otlp v1.9.0/go.mod h1:xE+Cx5E/eEHw+ISFkwPLwCZefwVjY+pqKg1qcK03+/4= go.opentelemetry.io/proto/otlp v1.10.0 h1:IQRWgT5srOCYfiWnpqUYz9CVmbO8bFmKcwYxpuCSL2g= go.opentelemetry.io/proto/otlp v1.10.0/go.mod h1:/CV4QoCR/S9yaPj8utp3lvQPoqMtxXdzn7ozvvozVqk= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= @@ -698,30 +559,18 @@ go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y= go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= -go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0= -go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8= go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= gocloud.dev v0.45.0 h1:WknIK8IbRdmynDvara3Q7G6wQhmEiOGwpgJufbM39sY= gocloud.dev v0.45.0/go.mod h1:0kXKmkCLG6d31N7NyLZWzt7jDSQura9zD/mWgiB6THI= -golang.org/x/arch v0.22.0 h1:c/Zle32i5ttqRXjdLyyHZESLD/bB90DCU1g9l/0YBDI= -golang.org/x/arch v0.22.0/go.mod h1:dNHoOeKiyja7GTvF9NJS1l3Z2yntpQNzgrjh1cU103A= golang.org/x/arch v0.27.0 h1:0WNVcR8u9yFz8j5FvdHpgwNp3FS5U4guYdzHwEiGjoU= golang.org/x/arch v0.27.0/go.mod h1:0X+GdSIP+kL5wPmpK7sdkEVTt2XoYP0cSjQSbZBwOi8= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= -golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= golang.org/x/crypto v0.51.0 h1:IBPXwPfKxY7cWQZ38ZCIRPI50YLeevDLlLnyC5wRGTI= golang.org/x/crypto v0.51.0/go.mod h1:8AdwkbraGNABw2kOX6YFPs3WM22XqI4EXEd8g+x7Oc8= -golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o= -golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8= -golang.org/x/exp v0.0.0-20260508232706-74f9aab9d74a h1:+3jdDGGB8NGb1Zktc737jlt3/A5f6UlwSzmvqUuufxw= -golang.org/x/exp v0.0.0-20260508232706-74f9aab9d74a/go.mod h1:d2fgXJLVs4dYDHUk5lwMIfzRzSrWCfGZb0ZqeLa/Vcw= -golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8= -golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w= golang.org/x/mod v0.36.0 h1:JJjpVx6myfUsUdAzZuOSTTmRE0PfZeNWzzvKrP7amb4= golang.org/x/mod v0.36.0/go.mod h1:moc6ELqsWcOw5Ef3xVprK5ul/MvtVvkIXLziUOICjUQ= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -730,13 +579,9 @@ golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo= -golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y= golang.org/x/net v0.54.0 h1:2zJIZAxAHV/OHCDTCOHAYehQzLfSXuf/5SoL/Dv6w/w= golang.org/x/net v0.54.0/go.mod h1:Sj4oj8jK6XmHpBZU/zWHw3BV3abl4Kvi+Ut7cQcY+cQ= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.35.0 h1:Mv2mzuHuZuY2+bkyWXIHMfhNdJAdwW3FuWeCPYN5GVQ= -golang.org/x/oauth2 v0.35.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -762,56 +607,36 @@ golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo= -golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ= golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8= -golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA= golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc= golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38= golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k= -golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0= golang.org/x/tools v0.45.0 h1:18qN3FAooORvApf5XjCXgsuayZOEtXf6JK18I3+ONa8= golang.org/x/tools v0.45.0/go.mod h1:LuUGqqaXcXMEFEruIVJVm5mgDD8vww/z/SR1gQ4uE/0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da h1:noIWHXmPHxILtqtCOPIhSt0ABwskkZKjD3bXGnZGpNY= golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= -gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= -gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= -google.golang.org/api v0.270.0 h1:4rJZbIuWSTohczG9mG2ukSDdt9qKx4sSSHIydTN26L4= -google.golang.org/api v0.270.0/go.mod h1:5+H3/8DlXpQWrSz4RjGGwz5HfJAQSEI8Bc6JqQNH77U= +gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= google.golang.org/api v0.278.0 h1:W7jiRvRi53VYFfZ/HoZjQBtJk7gOFbHD8ot1RzVZU6E= google.golang.org/api v0.278.0/go.mod h1:B9TqLBwJqVjp1mtt7WeoQwWRwvu/400y5lETOql+giQ= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20260128011058-8636f8732409 h1:VQZ/yAbAtjkHgH80teYd2em3xtIkkHd7ZhqfH2N9CsM= -google.golang.org/genproto v0.0.0-20260128011058-8636f8732409/go.mod h1:rxKD3IEILWEu3P44seeNOAwZN4SaoKaQ/2eTg4mM6EM= google.golang.org/genproto v0.0.0-20260504160031-60b97b32f348 h1:JjVGDZYWkJWZcxveJGzfkXC5myDVWAd4dZdgbzrDUv8= google.golang.org/genproto v0.0.0-20260504160031-60b97b32f348/go.mod h1:95PqD4xM+AdOcBGsmgfaofXsiA37uXDtDufVbntT3TU= -google.golang.org/genproto/googleapis/api v0.0.0-20260209200024-4cfbd4190f57 h1:JLQynH/LBHfCTSbDWl+py8C+Rg/k1OVH3xfcaiANuF0= -google.golang.org/genproto/googleapis/api v0.0.0-20260209200024-4cfbd4190f57/go.mod h1:kSJwQxqmFXeo79zOmbrALdflXQeAYcUbgS7PbpMknCY= google.golang.org/genproto/googleapis/api v0.0.0-20260504160031-60b97b32f348 h1:U8orV30l6KpDsi9dxU0CoJZGbjS8EEpw+6ba+XwGPQA= google.golang.org/genproto/googleapis/api v0.0.0-20260504160031-60b97b32f348/go.mod h1:Yzdzr5OOZFgSsEV2D/Xi9NL3bszpXFAg0hFJiRohcD8= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/genproto/googleapis/rpc v0.0.0-20260504160031-60b97b32f348 h1:pfIbyB44sWzHiCpRqIen67ZQnVXSfIxWrqUMk1qwODE= google.golang.org/genproto/googleapis/rpc v0.0.0-20260504160031-60b97b32f348/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= -google.golang.org/grpc v1.79.3 h1:sybAEdRIEtvcD68Gx7dmnwjZKlyfuc61Dyo9pGXXkKE= -google.golang.org/grpc v1.79.3/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= google.golang.org/grpc v1.81.0 h1:W3G9N3KQf3BU+YuCtGKJk0CmxQNbAISICD/9AORxLIw= google.golang.org/grpc v1.81.0/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -844,34 +669,28 @@ gorm.io/gorm v1.31.1 h1:7CA8FTFz/gRfgqgpeKIBcervUn3xSyPUmr6B2WXJ7kg= gorm.io/gorm v1.31.1/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs= gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= -modernc.org/cc/v4 v4.26.2 h1:991HMkLjJzYBIfha6ECZdjrIYz2/1ayr+FL8GN+CNzM= -modernc.org/cc/v4 v4.26.2/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0= modernc.org/cc/v4 v4.28.2 h1:3tQ0lf2ADtoby2EtSP+J7IE2SHwEJdP8ioR59wx7XpY= -modernc.org/ccgo/v4 v4.28.0 h1:rjznn6WWehKq7dG4JtLRKxb52Ecv8OUGah8+Z/SfpNU= -modernc.org/ccgo/v4 v4.28.0/go.mod h1:JygV3+9AV6SmPhDasu4JgquwU81XAKLd3OKTUDNOiKE= +modernc.org/cc/v4 v4.28.2/go.mod h1:OnovgIhbbMXMu1aISnJ0wvVD1KnW+cAUJkIrAWh+kVI= modernc.org/ccgo/v4 v4.34.0 h1:yRLPFZieg532OT4rp4JFNIVcquwalMX26G95WQDqwCQ= -modernc.org/fileutil v1.3.8 h1:qtzNm7ED75pd1C7WgAGcK4edm4fvhtBsEiI/0NQ54YM= -modernc.org/fileutil v1.3.8/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc= +modernc.org/ccgo/v4 v4.34.0/go.mod h1:AS5WYMyBakQ+fhsHhtP8mWB82KTGPkNNJDGfGQCe0/A= modernc.org/fileutil v1.4.0 h1:j6ZzNTftVS054gi281TyLjHPp6CPHr2KCxEXjEbD6SM= +modernc.org/fileutil v1.4.0/go.mod h1:EqdKFDxiByqxLk8ozOxObDSfcVOv/54xDs/DUHdvCUU= modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI= modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito= +modernc.org/gc/v3 v3.1.2 h1:ZtDCnhonXSZexk/AYsegNRV1lJGgaNZJuKjJSWKyEqo= +modernc.org/gc/v3 v3.1.2/go.mod h1:HFK/6AGESC7Ex+EZJhJ2Gni6cTaYpSMmU/cT9RmlfYY= modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks= modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI= -modernc.org/libc v1.66.3 h1:cfCbjTUcdsKyyZZfEUKfoHcP3S0Wkvz3jgSzByEWVCQ= -modernc.org/libc v1.66.3/go.mod h1:XD9zO8kt59cANKvHPXpx7yS2ELPheAey0vjIuZOhOU8= modernc.org/libc v1.72.3 h1:ZnDF4tXn4NBXFutMMQC4vtbTFSXhhKzR73fv0beZEAU= modernc.org/libc v1.72.3/go.mod h1:dn0dZNnnn1clLyvRxLxYExxiKRZIRENOfqQ8XEeg4Qs= modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU= modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg= modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI= modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw= -modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8= -modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns= modernc.org/opt v0.2.0 h1:tGyef5ApycA7FSEOMraay9SaTk5zmbx7Tu+cJs4QKZg= +modernc.org/opt v0.2.0/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns= modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w= modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE= -modernc.org/sqlite v1.39.0 h1:6bwu9Ooim0yVYA7IZn9demiQk/Ejp0BtTjBWFLymSeY= -modernc.org/sqlite v1.39.0/go.mod h1:cPTJYSlgg3Sfg046yBShXENNtPrWrDX8bsbAQBzgQ5E= modernc.org/sqlite v1.50.0 h1:eMowQSWLK0MeiQTdmz3lqoF5dqclujdlIKeJA11+7oM= modernc.org/sqlite v1.50.0/go.mod h1:m0w8xhwYUVY3H6pSDwc3gkJ/irZT/0YEXwBlhaxQEew= modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0= diff --git a/guilds/echo_app.json b/guilds/echo_app.json new file mode 100644 index 0000000..5ea9967 --- /dev/null +++ b/guilds/echo_app.json @@ -0,0 +1,72 @@ +{ + "name": "Simple Echo", + "description": "Simple Echo is a lightweight app that mirrors your input. Whatever you say, it says backβ€”perfect for testing, demos, or lightweight message flows.", + "version": "v1", + "icon": null, + "intro_msg": "Hi there! I’ll echo back anything you send me. Give it a try!", + "exposure": "public", + "author_id": "dummyuserid", + "organization_id": null, + "category_id": null, + "tags": [], + "commands": [], + "starter_prompts": [], + "spec": { + "name": "Simple Echo", + "description": "Simple Echo is a lightweight app that mirrors your input. Whatever you say, it says backβ€”perfect for testing, demos, or lightweight message flows.", + "properties": {}, + "agents": [ + { + "name": "Echo Agent", + "description": "An agent that echoes every message it receivesβ€”word for word.", + "class_name": "rustic_ai.core.agents.testutils.echo_agent.EchoAgent", + "additional_topics": ["echo_topic"], + "properties": {}, + "listen_to_default_topic": false, + "act_only_when_tagged": false + } + ], + "routes": { + "steps": [ + { + "agent": null, + "agent_type": "rustic_ai.core.agents.utils.user_proxy_agent.UserProxyAgent", + "method_name": "unwrap_and_forward_message", + "origin_filter": null, + "message_format": null, + "destination": { + "topics": "echo_topic", + "recipient_list": [], + "priority": null + }, + "mark_forwarded": false, + "route_times": 1, + "transformer": null, + "agent_state_update": null, + "guild_state_update": null + }, + { + "agent": { + "id": null, + "name": "Echo Agent" + }, + "agent_type": null, + "method_name": null, + "origin_filter": null, + "message_format": null, + "destination": { + "topics": "user_message_broadcast", + "recipient_list": [], + "priority": null + }, + "mark_forwarded": false, + "route_times": 1, + "transformer": null, + "agent_state_update": null, + "guild_state_update": null, + "process_status": "completed" + } + ] + } + } +} diff --git a/guilds/react_guild.json b/guilds/react_guild.json new file mode 100644 index 0000000..8caa54d --- /dev/null +++ b/guilds/react_guild.json @@ -0,0 +1,202 @@ +{ + "name": "Data Analyst Assistant", + "description": "An intelligent data analysis assistant powered by the ReAct pattern with Codex-style dataset enrichment. Upload CSV files and ask questions about your data - the assistant will load, query, and analyze your datasets automatically.", + "version": "v1", + "icon": null, + "intro_msg": "Welcome to the Data Analyst Assistant! I can help you analyze CSV data files. Just tell me which file to load and what you'd like to know about the data. I can calculate statistics, run SQL queries, describe datasets, and more. When you load a dataset, I'll automatically analyze its structure to provide better insights.", + "exposure": "public", + "author_id": "dummyuserid", + "organization_id": "acmeorganizationid", + "category_id": null, + "tags": [ + "Data Analysis", + "CSV", + "SQL", + "Pandas", + "ReAct", + "Codex Enrichment" + ], + "commands": [], + "starter_prompts": [ + "Load sales_data.csv and show me the first 5 rows", + "What is the average price of products in the dataset?", + "Load the employees file and tell me the total salary by department", + "Show me the schema of the loaded dataset", + "Find all products with quantity greater than 30" + ], + "spec": { + "name": "Data Analyst Guild", + "description": "Guild for data analysis using ReActAgent with DataAnalystReActToolset and Codex enrichment", + "properties": {}, + "configuration_schema": { + "type": "object", + "properties": { + "default_model": { + "type": "string", + "default": "gpt-4o-mini", + "description": "The LLM model to use for analysis" + } + } + }, + "configuration": {}, + "agents": [ + { + "id": "react_data_analyst", + "name": "Data Analyst Agent", + "description": "A ReAct-based agent that can load, query, and analyze datasets using pandas and SQL", + "class_name": "rustic_ai.llm_agent.react.react_agent.ReActAgent", + "additional_topics": [], + "properties": { + "max_iterations": 10, + "temperature": 0.7, + "system_prompt": "You are a Data Analyst Agent. You help users analyze data using pandas and SQL.\n\nYou have access to tools for loading, querying, and analyzing datasets:\n- load_file: Load a CSV, JSON, or Parquet file as a dataset\n- list_datasets: List all currently loaded datasets\n- get_schema: Get the schema/columns of a dataset\n- preview_dataset: Preview the first few rows of a dataset\n- describe_dataset: Get descriptive statistics for a dataset\n- query_dataset: Run SQL queries on datasets\n- summarize_dataset: Get a summary of a dataset\n- value_counts: Get value counts for a column\n- correlation_matrix: Get correlation matrix for numeric columns\n- transform_dataset: Apply transformations to a dataset\n- join_datasets: Join two datasets together\n- clean_dataset: Clean missing/invalid data\n\nUse the ReAct pattern to answer user questions about data:\n1. Think about what information you need\n2. Use tools to load and explore the data\n3. Analyze the results and provide insights\n\nIMPORTANT: When the user uploads a file, the file path will be provided in a system message. Use that exact path with the load_file tool to load the data.\n\nNOTE: If enrichment context is provided for a dataset, use that information to better understand the data structure, semantics, and recommended usage patterns.", + "request_preprocessors": [ + { + "kind": "rustic_ai.pandas_analyst.file_url_preprocessor.FileUrlExtractorPreprocessor" + }, + { + "kind": "rustic_ai.pandas_analyst.enrichment.preprocessor.EnrichmentContextPreprocessor" + } + ], + "tool_wrappers": [ + { + "kind": "rustic_ai.pandas_analyst.enrichment.emitter.DatasetLoadedEmitter", + "sample_rows": 5 + } + ], + "toolset": { + "kind": "rustic_ai.pandas_analyst.react_toolset.DataAnalystReActToolset", + "filesystem_base_path": "/tmp", + "filesystem_protocol": "file", + "filesystem_options": { + "auto_mkdir": true + } + } + }, + "listen_to_default_topic": true, + "act_only_when_tagged": false, + "predicates": {}, + "dependency_map": {}, + "additional_dependencies": [], + "resources": { + "num_cpus": null, + "num_gpus": null, + "custom_resources": {} + }, + "qos": { + "timeout": null, + "retry_count": null, + "latency": null + } + }, + { + "id": "codex_enrichment_llm", + "name": "Codex Enrichment LLM", + "description": "LLM agent that generates rich dataset metadata for Codex-style enrichment", + "class_name": "rustic_ai.llm_agent.llm_agent.LLMAgent", + "additional_topics": [ + "enrichment_requests" + ], + "properties": { + "default_system_prompt": "You are a data catalog expert. Analyze the provided dataset information and generate rich metadata as JSON.\n\nReturn a JSON object with these fields:\n- table_purpose: Brief description of what this table is for (1 sentence)\n- table_description: Detailed description of the table's contents and structure\n- grain_description: What each row in the table represents (e.g., \"One row per customer order\")\n- primary_key_candidates: Array of column names that could serve as primary keys\n- columns: Array of column objects, each with:\n - name: Column name\n - description: What this column represents\n - semantic_type: One of (identifier, dimension, measure, timestamp, category, text)\n - uniqueness: One of (unique, mostly_unique, low_cardinality, unknown)\n - is_primary_key_candidate: boolean\n- freshness_indicators: Object with date range info if applicable\n- recommended_usage: Array of suggested analyses or queries\n- when_to_use: Guidance on when to use this dataset\n- limitations: Array of known data limitations or caveats\n\nBe concise but informative. Focus on practical insights that would help a data analyst work with this data effectively.\n\nReturn ONLY the JSON object, no additional text.", + "temperature": 0.3 + }, + "listen_to_default_topic": false, + "act_only_when_tagged": false, + "predicates": {}, + "dependency_map": {}, + "additional_dependencies": [], + "resources": { + "num_cpus": null, + "num_gpus": null, + "custom_resources": {} + }, + "qos": { + "timeout": null, + "retry_count": null, + "latency": null + } + } + ], + "dependency_map": {}, + "routes": { + "steps": [ + { + "agent": { + "id": null, + "name": "Data Analyst Agent" + }, + "agent_type": null, + "method_name": null, + "origin_filter": null, + "message_format": "rustic_ai.core.guild.agent_ext.depends.llm.models.ChatCompletionResponse", + "destination": { + "topics": "user_message_broadcast", + "recipient_list": [], + "priority": null + }, + "mark_forwarded": true, + "route_times": -1, + "transformer": null, + "agent_state_update": null, + "guild_state_update": null, + "process_status": "completed", + "reason": "Send analysis results back to user" + }, + { + "agent": { + "id": null, + "name": "Data Analyst Agent" + }, + "agent_type": null, + "method_name": null, + "origin_filter": null, + "message_format": "rustic_ai.pandas_analyst.enrichment.models.DatasetLoadedEvent", + "destination": { + "topics": "enrichment_requests", + "recipient_list": [], + "priority": null + }, + "mark_forwarded": true, + "route_times": -1, + "transformer": { + "style": "simple", + "output_format": "rustic_ai.core.guild.agent_ext.depends.llm.models.ChatCompletionRequest", + "expression": "{'messages': [{'role': 'user', 'content': 'Analyze this dataset and generate enrichment metadata:\\n\\nDataset: ' & dataset_name & '\\nRows: ' & $string(row_count) & '\\nColumns: ' & $string(column_count) & '\\n\\nColumn Names: ' & $join(columns, ', ') & '\\n\\nSchema (column -> type):\\n' & $string(column_schema) & '\\n\\nSample Data (first ' & $string($count(sample_data)) & ' rows):\\n' & $string(sample_data)}]}" + }, + "agent_state_update": null, + "guild_state_update": null, + "process_status": null, + "reason": "Transform DatasetLoadedEvent to ChatCompletionRequest for enrichment LLM" + }, + { + "agent": { + "id": null, + "name": "Codex Enrichment LLM" + }, + "agent_type": null, + "method_name": null, + "origin_filter": null, + "message_format": "rustic_ai.core.guild.agent_ext.depends.llm.models.ChatCompletionResponse", + "destination": { + "topics": "enrichment_results", + "recipient_list": [], + "priority": null + }, + "mark_forwarded": true, + "route_times": -1, + "transformer": null, + "agent_state_update": null, + "guild_state_update": { + "expression_type": "jsonata", + "update_format": "json-merge-patch", + "state_update": "($content := origin.payload.messages[0].content; $dataset_name := $match($content, /Dataset: (\\S+)/).groups[0]; $row_count := $number($match($content, /Rows: (\\d+)/).groups[0]); $column_count := $number($match($content, /Columns: (\\d+)/).groups[0]); $llm_response := payload.choices[0].message.content; $clean_json := $trim($replace($replace($llm_response, /^```json\\s*/, ''), /\\s*```$/, '')); $enrichment := $eval($clean_json); {'codex_enrichment': {'datasets': {$dataset_name: $merge([$enrichment, {'dataset_name': $dataset_name, 'row_count': $row_count, 'column_count': $column_count, 'enrichment_timestamp': $now()}])}}})" + }, + "process_status": "completed", + "reason": "Store enrichment response in guild state" + } + ] + }, + "gateway": null + } +} \ No newline at end of file diff --git a/guilds/uniko_research_guild.json b/guilds/uniko_research_guild.json new file mode 100644 index 0000000..1051b0f --- /dev/null +++ b/guilds/uniko_research_guild.json @@ -0,0 +1,479 @@ +{ + "name": "Uniko Research Guild", + "description": "Advanced research guild with persistent memory using Uniko cognitive memory system, combining KB search, web scraping, and intelligent memory management.", + "version": "v2", + "icon": null, + "intro_msg": "Welcome to the Uniko Research Guild! I can help you research topics with persistent memory. What would you like to explore?", + "exposure": "public", + "author_id": "dummyuserid", + "organization_id": "acmeorganizationid", + "category_id": null, + "tags": [ + "research", + "memory", + "uniko", + "knowledge-base" + ], + "commands": [], + "starter_prompts": [ + "Research recent developments in quantum computing", + "Find information about sustainable energy solutions", + "What have I previously researched about AI?" + ], + "spec": { + "name": "Uniko Research Guild", + "description": "Advanced research guild with persistent memory using Uniko cognitive memory system, combining KB search, web scraping, and intelligent memory management.", + "agents": [ + { + "id": "memory_agent", + "name": "Memory Agent", + "description": "Comprehensive memory agent using Uniko's 5-tier cognitive memory system for persistent knowledge storage and recall", + "class_name": "rustic_ai.uniko_agent.agent.MemoryAgent", + "additional_topics": [ + "memory_observe", + "memory_recall", + "memory_answer", + "memory_ingest" + ], + "listen_to_default_topic": true, + "properties": { + "default_session_id": null, + "recall_max_tokens": 3000, + "recall_phase1_only": false, + "answer_max_tokens": 800, + "auto_flush": true + } + }, + { + "id": "google_agent", + "name": "Google Research Agent", + "description": "Performs intelligent Google Search with grounding", + "class_name": "rustic_ai.vertexai.agents.google_research_agent.GoogleResearchAgent", + "additional_topics": [], + "listen_to_default_topic": true, + "properties": { + "project_id": null, + "location": null, + "model_id": "gemini-2.5-pro" + } + }, + { + "id": "serp_agent", + "name": "Search Agent", + "description": "Handles search engine results page queries via SerpAPI", + "class_name": "rustic_ai.serpapi.agent.SERPAgent", + "additional_topics": [], + "properties": {}, + "listen_to_default_topic": true + }, + { + "id": "playwright_agent", + "name": "Web Scraper Agent", + "description": "Web scraping agent using Playwright for content extraction", + "class_name": "rustic_ai.playwright.agent.PlaywrightScraperAgent", + "additional_topics": [], + "properties": { + "headless": true, + "parallel_pages": 5 + }, + "listen_to_default_topic": true + }, + { + "id": "markdown_agent", + "name": "Markdown Agent", + "description": "Generates and manages Markdown files from research results", + "class_name": "rustic_ai.demos.agents.preprocessing.file_reader_writer_agent.FileReaderWriterAgent", + "additional_topics": [], + "listen_to_default_topic": true, + "properties": {} + }, + { + "id": "synthesis_agent", + "name": "Synthesis Agent", + "description": "Synthesizes research findings and generates comprehensive answers", + "class_name": "rustic_ai.llm_agent.llm_agent.LLMAgent", + "additional_topics": [ + "synthesis_agent" + ], + "listen_to_default_topic": false, + "properties": { + "model": "vertex_ai/gemini-3-pro-preview", + "default_system_prompt": "You are a research synthesis expert. Analyze the provided context from multiple sources and generate a comprehensive, well-structured answer to the user's question. Include key insights, relevant facts, and cite sources when applicable. Be thorough but concise." + } + }, + { + "id": "query_agent", + "name": "Query Agent", + "description": "Generates optimized search queries using LLM for comprehensive research coverage", + "class_name": "rustic_ai.llm_agent.llm_agent.LLMAgent", + "additional_topics": [ + "query_agent" + ], + "listen_to_default_topic": false, + "properties": { + "model": "vertex_ai/gemini-3-pro-preview", + "default_system_prompt": "Generate 5-7 comprehensive google-optimized subqueries for deep research on the topic.\n\nFor thorough coverage, create subqueries across multiple dimensions:\n- Core concepts and definitions\n- Latest developments and breakthroughs (recent news, 2025-2026)\n- Historical context and evolution\n- Technical implementations and real-world applications\n- Expert opinions, academic research, and papers\n- Industry trends, market analysis, and adoption\n- Future implications, predictions, and emerging patterns\n- Challenges, limitations, and critiques\n- Related technologies, comparisons, and alternatives\n- Case studies and practical examples\n\nConsider when creating subqueries:\n- Neural search formulation: Use natural language questions and descriptive phrases\n- Domain filters: Suggest specific domains when relevant (arxiv.org for papers, techcrunch.com for tech news)\n- Time periods: Specify recent, past_week, past_month, past_year, or any\n- Content types: Specify type when relevant (news, research paper, pdf, blog, tutorial)\n\nEach subquery should focus on a different aspect to ensure comprehensive, multi-dimensional coverage.\n\nOutput format:\n- Separate queries using '####' as delimiter\n- Example: Query 1####Query 2####Query 3\n- Return ONLY the queries, nothing else" + } + }, + { + "id": "splitter_agent", + "name": "Splitter Agent", + "description": "Splits generated queries into individual search requests", + "class_name": "rustic_ai.core.agents.eip.splitter_agent.SplitterAgent", + "additional_topics": [ + "splitter_agent" + ], + "properties": { + "splitter": { + "split_type": "jsonata", + "expression": "($map($split($.choices[0].message.content, '####'), function($v){ ({\"query\": $v, \"engine\": \"google\", \"num\": 8}) }))" + }, + "format_selector": { + "strategy": "fixed", + "fixed_format": "rustic_ai.serpapi.agent.SERPQuery" + } + }, + "listen_to_default_topic": false + }, + { + "id": "basic_wiring_agent", + "name": "Basic Wiring Agent", + "description": "Routes and transforms messages between agents", + "class_name": "rustic_ai.core.agents.eip.basic_wiring_agent.BasicWiringAgent", + "additional_topics": [ + "basic_wiring" + ], + "listen_to_default_topic": false, + "properties": {} + }, + { + "id": "gateway_agent", + "name": "Research Gateway", + "description": "Gateway agent for receiving research requests from other guilds", + "class_name": "rustic_ai.core.guild.g2g.gateway_agent.GatewayAgent", + "additional_topics": [ + "outbound" + ], + "listen_to_default_topic": false, + "properties": { + "input_formats": [ + "rustic_ai.demos.research_guild.types.ResearchRequest" + ], + "output_formats": [ + "rustic_ai.demos.research_guild.types.ResearchResults" + ], + "returned_formats": [] + } + } + ], + "dependency_map": { + "filesystem": { + "class_name": "rustic_ai.core.guild.agent_ext.depends.filesystem.filesystem.FileSystemResolver", + "properties": { + "path_base": "/tmp/research_guild", + "protocol": "file", + "storage_options": { + "auto_mkdir": true + }, + "asynchronous": true + } + }, + "llm": { + "class_name": "rustic_ai.litellm.agent_ext.llm.LiteLLMResolver", + "properties": { + "model": "vertex_ai/gemini-3-pro-preview", + "conf": { + "vertex_location": "global" + } + } + }, + "uniko": { + "class_name": "rustic_ai.uniko_agent.resolver.UnikoResolver", + "properties": { + "storage_path": "./data/memory/{org_id}/{guild_id}", + "llm_spec": { + "alias": "openai", + "model_id": "gpt-4o-mini", + "key_env": "OPENAI_API_KEY" + }, + "streaming": false + } + } + }, + "routes": { + "steps": [ + { + "agent_type": "rustic_ai.core.agents.utils.user_proxy_agent.UserProxyAgent", + "method_name": "unwrap_and_forward_message", + "message_format": "rustic_ai.core.guild.agent_ext.depends.llm.models.ChatCompletionRequest", + "destination": null, + "route_times": -1, + "transformer": { + "style": "content_based_router", + "handler": "($content := $type($.payload.messages[0].content) = \"string\" ? [{\"type\": \"text\", \"text\": $.payload.messages[0].content}] : $.payload.messages[0].content; $hasFiles := $count($content[type in [\"image_url\", \"file_url\"]]) > 0; $textContent := $content[type = \"text\"][0].text; $urls := $match($textContent, /(https?:\\/\\/[^\\s]+|www\\.[^\\s]+)/).match; $hasUrls := $count($urls) > 0; $hasFiles ? {\"format\": \"rustic_ai.uniko_agent.models.IngestDocumentRequest\", \"topics\": \"memory_ingest\", \"payload\": {\"source_spec\": $content[type in [\"image_url\", \"file_url\"]][0].type = \"image_url\" ? {\"url\": $content[type in [\"image_url\", \"file_url\"]][0].image_url.url} : {\"url\": $content[type in [\"image_url\", \"file_url\"]][0].file_url.url}}, \"context\": {\"original_query\": $textContent, \"current_id\": 'current_id' in $keys($.guild_state) ? $.guild_state.current_id + 1 : 0}} : $hasUrls ? {\"format\": \"rustic_ai.playwright.agent.WebScrapingRequest\", \"topics\": \"default_topic\", \"payload\": {\"links\": [$map($urls, function($url){ {\"url\": $url} })], \"depth\": \"0\", \"output_format\": \"text/markdown\"}, \"context\": {\"original_query\": $textContent, \"current_id\": 'current_id' in $keys($.guild_state) ? $.guild_state.current_id + 1 : 0}} : {\"payload\": {\"query\": $textContent}, \"format\": \"rustic_ai.uniko_agent.models.RecallRequest\", \"topics\": \"memory_recall\", \"context\": {\"original_query\": $textContent, \"current_id\": 'current_id' in $keys($.guild_state) ? $.guild_state.current_id + 1 : 0}})" + }, + "guild_state_update": { + "update_format": "json-merge-patch", + "state_update": "({\"user_queries\": $append($.guild_state.user_queries, $.payload.text), \"current_id\": 'current_id' in $keys($.guild_state) ? $.guild_state.current_id + 1 : 0})" + } + }, + { + "agent": { + "id": "memory_agent", + "name": "Memory Agent" + }, + "message_format": "rustic_ai.uniko_agent.models.RecallResponse", + "destination": null, + "route_times": -1, + "transformer": { + "style": "content_based_router", + "handler": "($is_answered := $.context.current_id in $.guild_state.answered; $has_good_recall := $count($.payload.items[score > 0.3]) > 0; $ToAnswer := function($items){ {\"topics\": \"memory_answer\", \"format\": \"rustic_ai.uniko_agent.models.AnswerRequest\", \"payload\": {\"question\": $.context.original_query, \"max_tokens\": 800}} }; $ToQueryAgent := function(){ {\"topics\": \"query_agent\", \"format\": \"rustic_ai.core.guild.agent_ext.depends.llm.models.ChatCompletionRequest\", \"payload\": {\"messages\": [{\"role\": \"user\", \"content\": \"User Question: \" & $.context.original_query}]}} }; $is_answered ? null : ($has_good_recall ? $ToAnswer($.payload.items) : $ToQueryAgent()))" + }, + "guild_state_update": { + "update_format": "json-merge-patch", + "state_update": "($is_answered := $.context.current_id in $.guild_state.answered; $has_good_recall := $count($.untransformed.payload.items[score > 0.3]) > 0; $UpdateGuildState := {\"answered\": $append(guild_state.answered, $.context.current_id)}; $is_answered ? null : ($has_good_recall ? $UpdateGuildState : null))" + } + }, + { + "agent": { + "name": "Memory Agent" + }, + "message_format": "rustic_ai.uniko_agent.models.AnswerResponse", + "destination": { + "topics": "user_message_broadcast", + "recipient_list": [], + "priority": null + }, + "route_times": -1, + "transformer": { + "style": "simple", + "output_format": "rustic_ai.core.guild.agent_ext.depends.llm.models.ChatCompletionResponse", + "expression": "({\"choices\": [{\"message\": {\"content\": $.text}, \"finish_reason\": \"stop\"}], \"usage\": {\"prompt_tokens\": $.input_tokens, \"completion_tokens\": $.output_tokens, \"total_tokens\": $.input_tokens + $.output_tokens}})" + }, + "process_status": "completed" + }, + { + "agent": { + "name": "Research Gateway" + }, + "message_format": "rustic_ai.demos.research_guild.types.ResearchRequest", + "destination": null, + "route_times": -1, + "transformer": { + "style": "content_based_router", + "handler": "({\"payload\":{\"query\": $.payload.topic}, \"format\": \"rustic_ai.uniko_agent.models.RecallRequest\", \"topics\":\"memory_recall\", \"context\": {\"original_query\": $.payload.topic, \"current_id\": 'current_id' in $keys($.guild_state) ? $.guild_state.current_id + 1 : 0, \"correlation_id\": $.payload.correlation_id}})" + }, + "guild_state_update": { + "update_format": "json-merge-patch", + "state_update": "({\"user_queries\": $append($.guild_state.user_queries, $.payload.topic), \"current_id\": 'current_id' in $keys($.guild_state) ? $.guild_state.current_id + 1 : 0})" + } + }, + { + "agent": { + "name": "Research Gateway" + }, + "message_format": "rustic_ai.demos.research_guild.types.ResearchRequest", + "destination": null, + "transformer": { + "style": "content_based_router", + "handler": "({\"format\": \"rustic_ai.core.guild.agent_ext.depends.llm.models.ChatCompletionResponse\", \"topics\": \"user_message_broadcast\", \"payload\":{\"choices\": [{\"message\": {\"content\": 'Research initiated for: ' & $.payload.topic & '. Checking memory and initiating comprehensive web research...'}}]}})" + }, + "route_times": -1, + "process_status": "completed" + }, + { + "agent": { + "name": "Query Agent" + }, + "message_format": "rustic_ai.core.guild.agent_ext.depends.llm.models.ChatCompletionResponse", + "destination": { + "topics": "splitter_agent", + "recipient_list": [], + "priority": null + }, + "route_times": -1 + }, + { + "agent": { + "name": "Splitter Agent" + }, + "message_format": "rustic_ai.serpapi.agent.SERPQuery", + "destination": { + "topics": "default_topic", + "recipient_list": [], + "priority": null + }, + "route_times": -1 + }, + { + "agent": { + "name": "Google Research Agent" + }, + "message_format": "rustic_ai.core.guild.agent_ext.depends.llm.models.ChatCompletionResponse", + "destination": { + "topics": "default_topic", + "recipient_list": [], + "priority": null + }, + "route_times": -1 + }, + { + "agent": { + "name": "Markdown Agent" + }, + "message_format": "rustic_ai.core.agents.commons.media.MediaLink", + "destination": { + "topics": "memory_ingest", + "recipient_list": [], + "priority": null + }, + "route_times": -1, + "transformer": { + "style": "simple", + "output_format": "rustic_ai.uniko_agent.models.IngestDocumentRequest", + "expression": "{\"source_spec\": {\"url\": $.url}}" + } + }, + { + "agent": { + "name": "Search Agent" + }, + "message_format": "rustic_ai.serpapi.agent.SERPResults", + "destination": { + "topics": "default_topic", + "recipient_list": [], + "priority": null + }, + "route_times": -1, + "transformer": { + "style": "simple", + "output_format": "rustic_ai.playwright.agent.WebScrapingRequest", + "expression": "({\"id\": $.id, \"links\": $.results[url ~> /linkedin|facebook|instagram|twitter/ ? false : true], \"depth\": \"0\", \"output_format\": \"text/markdown\"})" + } + }, + { + "agent": { + "name": "Web Scraper Agent" + }, + "message_format": "rustic_ai.core.agents.commons.media.MediaLink", + "destination": { + "topics": "memory_ingest", + "recipient_list": [], + "priority": null + }, + "route_times": -1, + "transformer": { + "style": "simple", + "output_format": "rustic_ai.uniko_agent.models.IngestDocumentRequest", + "expression": "{\"source_spec\": {\"url\": $.url}}" + } + }, + { + "agent": { + "name": "Memory Agent" + }, + "message_format": "rustic_ai.uniko_agent.models.IngestOutcome", + "destination": { + "topics": "basic_wiring", + "recipient_list": [], + "priority": null + }, + "route_times": -1 + }, + { + "agent": { + "name": "Basic Wiring Agent" + }, + "message_format": "rustic_ai.uniko_agent.models.IngestOutcome", + "destination": { + "topics": "memory_observe", + "recipient_list": [], + "priority": null + }, + "route_times": -1, + "transformer": { + "style": "content_based_router", + "handler": "({\"format\": \"rustic_ai.uniko_agent.models.ObserveTurnRequest\", \"payload\": {\"sender_id\": \"memory_agent\", \"content\": \"Ingested document: \" & $string($.payload.chunk_count) & \" chunks, \" & $string($count($.payload.extracted_entities)) & \" entities extracted\", \"metadata\": {\"chunk_count\": $.payload.chunk_count, \"page_count\": $.payload.page_count, \"artifact_node_id\": $.payload.artifact_node_id}}})" + } + }, + { + "agent": { + "name": "Memory Agent" + }, + "message_format": "rustic_ai.uniko_agent.models.ObserveResult", + "destination": { + "topics": "basic_wiring", + "recipient_list": [], + "priority": null + }, + "route_times": -1 + }, + { + "agent": { + "name": "Basic Wiring Agent" + }, + "message_format": "rustic_ai.uniko_agent.models.ObserveResult", + "destination": { + "topics": "memory_recall", + "recipient_list": [], + "priority": null + }, + "route_times": -1, + "transformer": { + "style": "content_based_router", + "handler": "{\"payload\": {\"query\": $.context.original_query}, \"format\": \"rustic_ai.uniko_agent.models.RecallRequest\"}" + } + }, + { + "agent": { + "name": "Memory Agent" + }, + "message_format": "rustic_ai.uniko_agent.models.RecallResponse", + "destination": null, + "route_times": -1, + "transformer": { + "style": "content_based_router", + "handler": "($is_answered := $.context.current_id in $.guild_state.answered; $recalled_content := $join($.payload.items.content, '\\n\\n'); $ToSynthesis := function(){ {\"topics\": \"synthesis_agent\", \"format\": \"rustic_ai.core.guild.agent_ext.depends.llm.models.ChatCompletionRequest\", \"payload\": {\"messages\": [{\"role\": \"user\", \"content\": \"Context from research:\\n\" & $recalled_content & \"\\n\\nOriginal Question: \" & $.context.original_query & \"\\n\\nProvide a comprehensive answer based on the context above.\"}]}} }; $is_answered ? null : ($count($.payload.items) > 0 ? $ToSynthesis() : null))" + }, + "guild_state_update": { + "update_format": "json-merge-patch", + "state_update": "($is_answered := $.context.current_id in $.guild_state.answered; $has_recall := $count($.untransformed.payload.items) > 0; $UpdateGuildState := {\"answered\": $append(guild_state.answered, $.context.current_id)}; $is_answered ? null : ($has_recall ? $UpdateGuildState : null))" + } + }, + { + "agent": { + "name": "Synthesis Agent" + }, + "route_times": -1, + "message_format": "rustic_ai.core.guild.agent_ext.depends.llm.models.ChatCompletionResponse", + "destination": { + "topics": "memory_observe", + "recipient_list": [], + "priority": null + }, + "transformer": { + "style": "content_based_router", + "handler": "({\"format\": \"rustic_ai.uniko_agent.models.ObserveTurnRequest\", \"payload\": {\"sender_id\": \"synthesis_agent\", \"content\": $.choices[0].message.content, \"metadata\": {\"type\": \"synthesis_result\", \"original_query\": $.context.original_query}}})" + } + }, + { + "agent": { + "name": "Memory Agent" + }, + "message_format": "rustic_ai.uniko_agent.models.ObserveResult", + "destination": { + "topics": "user_message_broadcast", + "recipient_list": [], + "priority": null + }, + "route_times": -1, + "transformer": { + "style": "content_based_router", + "handler": "({\"format\": \"rustic_ai.core.guild.agent_ext.depends.llm.models.ChatCompletionResponse\", \"payload\": {\"choices\": [{\"message\": {\"content\": $.context.synthesized_response ? $.context.synthesized_response : \"Research completed and stored in memory. \" & $string($.payload.extracted_entities) & \" entities and \" & $string($.payload.extracted_observations) & \" observations extracted.\"}}]}})" + }, + "process_status": "completed" + } + ] + } + } +} \ No newline at end of file From 1fedbcf59721ba88c5e29364cde8c0e65446979f Mon Sep 17 00:00:00 2001 From: Nihal-Srivastava05 Date: Thu, 9 Jul 2026 23:07:47 +0530 Subject: [PATCH 2/3] echo works --- forge-go/cli/message_builder.go | 71 +++++++++++++++++- forge-go/command/guild_run.go | 126 ++++++++++++++++++++++++++++---- 2 files changed, 180 insertions(+), 17 deletions(-) diff --git a/forge-go/cli/message_builder.go b/forge-go/cli/message_builder.go index 15936e7..19fc83b 100644 --- a/forge-go/cli/message_builder.go +++ b/forge-go/cli/message_builder.go @@ -55,7 +55,7 @@ func BuildChatMessage(userID, userName, text, topic string) (*protocol.Message, convIDInt := convID.ToInt() msg := protocol.NewMessageFromGemstoneID(msgID) - msg.Format = "chatCompletionRequest" + msg.Format = "chatCompletionRequest" // Use short format - gateway normalizes it msg.Sender = protocol.AgentTag{ ID: &userID, Name: &userName, @@ -131,3 +131,72 @@ func BuildHealthCheckMessage(userID, topic string) (*protocol.Message, error) { return &msg, nil } + +// BuildWrappedChatMessage creates a wrapped chat message for UserProxyAgent +// This mimics how the gateway wraps user messages before sending them to user:{userID} +func BuildWrappedChatMessage(userID, userName, text string) (*protocol.Message, error) { + gen := getIDGen() + + // Create the inner chat message + innerMsg, err := BuildChatMessage(userID, userName, text, "default_topic") + if err != nil { + return nil, fmt.Errorf("failed to build inner message: %w", err) + } + + // Generate a new ID for the wrapper + wrapperID, err := gen.Generate(protocol.PriorityNormal) + if err != nil { + return nil, fmt.Errorf("failed to generate wrapper ID: %w", err) + } + + // Marshal the inner message as the payload + innerBytes, err := json.Marshal(innerMsg) + if err != nil { + return nil, fmt.Errorf("failed to marshal inner message: %w", err) + } + + // Create the wrapper message + senderID := fmt.Sprintf("user_socket:%s", userID) + wrapper := protocol.NewMessageFromGemstoneID(wrapperID) + wrapper.Format = "rustic_ai.core.messaging.core.message.Message" + wrapper.Sender = protocol.AgentTag{ + ID: &senderID, + Name: &userName, + } + wrapper.Topics = protocol.TopicsFromString(fmt.Sprintf("user:%s", userID)) + wrapper.Payload = json.RawMessage(innerBytes) + wrapper.Thread = []uint64{wrapperID.ToInt()} + + return &wrapper, nil +} + +// BuildUserProxyCreationRequest creates a UserAgentCreationRequest message +// This triggers the manager to create a UserProxyAgent for the user +func BuildUserProxyCreationRequest(userID, userName string) (*protocol.Message, error) { + gen := getIDGen() + msgID, err := gen.Generate(protocol.PriorityNormal) + if err != nil { + return nil, fmt.Errorf("failed to generate message ID: %w", err) + } + + payload := map[string]interface{}{ + "user_id": userID, + "user_name": userName, + } + payloadBytes, err := json.Marshal(payload) + if err != nil { + return nil, fmt.Errorf("failed to marshal payload: %w", err) + } + + senderID := fmt.Sprintf("user_socket:%s", userID) + msg := protocol.NewMessageFromGemstoneID(msgID) + msg.Format = "rustic_ai.core.agents.system.models.UserAgentCreationRequest" + msg.Sender = protocol.AgentTag{ + ID: &senderID, + Name: &userName, + } + msg.Topics = protocol.TopicsFromString("system_topic") + msg.Payload = json.RawMessage(payloadBytes) + + return &msg, nil +} diff --git a/forge-go/command/guild_run.go b/forge-go/command/guild_run.go index 5fd2675..db37a10 100644 --- a/forge-go/command/guild_run.go +++ b/forge-go/command/guild_run.go @@ -108,16 +108,31 @@ func runGuildREPL(cmd *cobra.Command, args []string) error { time.Sleep(2 * time.Second) // Determine the topic to send user messages to - // For guilds with routing rules (UserProxyAgent), use default_topic + // For guilds with routing rules, extract the destination from the first route // Otherwise use the first agent's topic (simple echo-style guilds) userMessageTopic := "default_topic" + useWrappedMessages := false hasRoutingRules := spec.Routes != nil && len(spec.Routes.Steps) > 0 - if !hasRoutingRules && len(spec.Agents) > 0 && len(spec.Agents[0].AdditionalTopics) > 0 { + if hasRoutingRules && len(spec.Routes.Steps) > 0 { + // Guild has routing - check if it uses UserProxyAgent + firstRoute := spec.Routes.Steps[0] + if firstRoute.AgentType != nil && *firstRoute.AgentType == "rustic_ai.core.agents.utils.user_proxy_agent.UserProxyAgent" { + // This guild uses UserProxyAgent - we need to create one and send wrapped messages + useWrappedMessages = true + // Messages go to user:{userID} and UserProxyAgent will route them + // according to the guild routing rules + } else if firstRoute.Destination != nil { + // Send directly to the route destination + topics := firstRoute.Destination.Topics.ToSlice() + if len(topics) > 0 { + userMessageTopic = topics[0] + } + } + } else if len(spec.Agents) > 0 && len(spec.Agents[0].AdditionalTopics) > 0 { // Simple guild without routing - send directly to first agent userMessageTopic = spec.Agents[0].AdditionalTopics[0] } - // Complex guilds with routing rules - keep default_topic // Show agent status if !guildQuiet { @@ -134,8 +149,54 @@ func runGuildREPL(cmd *cobra.Command, args []string) error { } defer sub.Close() + // Create UserProxyAgent only if this guild uses wrapped messages + if useWrappedMessages { + if !guildQuiet { + fmt.Println(" Creating UserProxyAgent...") + } + creationMsg, err := cli.BuildUserProxyCreationRequest(config.UserID, config.UserName) + if err != nil { + return fmt.Errorf("failed to build UserProxyAgent creation request: %w", err) + } + if err := runtime.PublishMessage(guildID, "system_topic", creationMsg); err != nil { + return fmt.Errorf("failed to create UserProxyAgent: %w", err) + } + + // Wait for UserProxyAgent to be created and appear in agent status + if !guildQuiet { + fmt.Println(" Waiting for UserProxyAgent to start...") + } + userProxyCreated := false + for i := 0; i < 10; i++ { + time.Sleep(500 * time.Millisecond) + statuses, err := runtime.GetAgentStatuses(guildID) + if err == nil { + for agentID := range statuses { + agentName := runtime.GetAgentName(agentID) + if strings.Contains(agentName, "test-user") || strings.Contains(agentID, "upa-") { + userProxyCreated = true + if guildVerbose { + fmt.Printf(" UserProxyAgent created: %s\n", agentName) + } + break + } + } + } + if userProxyCreated { + break + } + } + if !userProxyCreated && guildVerbose { + fmt.Println(" Warning: UserProxyAgent may not have been created") + } + } + if guildVerbose { - fmt.Printf(" Sending user messages to: %s\n\n", userMessageTopic) + if useWrappedMessages { + fmt.Printf(" Sending wrapped messages to: user:%s (routes to %s)\n\n", config.UserID, userMessageTopic) + } else { + fmt.Printf(" Sending user messages to: %s\n\n", userMessageTopic) + } } // Set up context for shutdown @@ -143,7 +204,7 @@ func runGuildREPL(cmd *cobra.Command, args []string) error { defer cancel() // Start message display goroutine - go displayMessages(ctx, sub, runtime, spec, guildVerbose, guildShowRouting) + go displayMessages(ctx, sub, runtime, spec, config.UserID, guildVerbose, guildShowRouting) // Interactive REPL fmt.Println("\n" + strings.Repeat("=", 70)) @@ -224,7 +285,7 @@ func runGuildREPL(cmd *cobra.Command, args []string) error { } // Send chat message - if err := sendChatMessage(runtime, guildID, config.UserID, config.UserName, line, userMessageTopic); err != nil { + if err := sendChatMessage(runtime, guildID, config.UserID, config.UserName, line, userMessageTopic, useWrappedMessages); err != nil { fmt.Printf("❌ Error sending message: %v\n", err) } } @@ -269,21 +330,37 @@ func showAgentStatus(runtime *cli.GuildRuntime, guildID string) error { return nil } -func sendChatMessage(runtime *cli.GuildRuntime, guildID, userID, userName, text, topic string) error { - msg, err := cli.BuildChatMessage(userID, userName, text, topic) - if err != nil { - return err +func sendChatMessage(runtime *cli.GuildRuntime, guildID, userID, userName, text, topic string, useWrapped bool) error { + var msg *protocol.Message + var err error + var actualTopic string + + if useWrapped { + // Build a wrapped message for UserProxyAgent + msg, err = cli.BuildWrappedChatMessage(userID, userName, text) + if err != nil { + return err + } + // Extract the actual topic from the message (should be user:{userID}) + actualTopic = msg.Topics.ToSlice()[0] + } else { + // Build a regular chat message + msg, err = cli.BuildChatMessage(userID, userName, text, topic) + if err != nil { + return err + } + actualTopic = topic } - fmt.Printf("πŸ“€ Sending to topic: %s\n", topic) - if err := runtime.PublishMessage(guildID, topic, msg); err != nil { + fmt.Printf("πŸ“€ Sending to topic: %s\n", actualTopic) + if err := runtime.PublishMessage(guildID, actualTopic, msg); err != nil { return fmt.Errorf("failed to publish: %w", err) } return nil } -func displayMessages(ctx context.Context, sub *cli.GuildSubscription, runtime *cli.GuildRuntime, spec *protocol.GuildSpec, verbose, showRouting bool) { +func displayMessages(ctx context.Context, sub *cli.GuildSubscription, runtime *cli.GuildRuntime, spec *protocol.GuildSpec, userID string, verbose, showRouting bool) { for { select { case <-ctx.Done(): @@ -292,7 +369,7 @@ func displayMessages(ctx context.Context, sub *cli.GuildSubscription, runtime *c if !ok { return } - printMessage(msg, runtime, spec, verbose, showRouting) + printMessage(msg, runtime, spec, userID, verbose, showRouting) case err, ok := <-sub.Errors(): if !ok { return @@ -302,7 +379,7 @@ func displayMessages(ctx context.Context, sub *cli.GuildSubscription, runtime *c } } -func printMessage(msg *protocol.Message, runtime *cli.GuildRuntime, spec *protocol.GuildSpec, verbose, showRouting bool) { +func printMessage(msg *protocol.Message, runtime *cli.GuildRuntime, spec *protocol.GuildSpec, userID string, verbose, showRouting bool) { // Debug: show all message formats in verbose mode only if verbose { topicsDebug := msg.Topics.ToSlice() @@ -331,10 +408,27 @@ func printMessage(msg *protocol.Message, runtime *cli.GuildRuntime, spec *protoc if msg.Format == "rustic_ai.forge.runtime.InfraEvent" { return } + // Skip participant list updates (noisy) + if msg.Format == "rustic_ai.core.agents.utils.user_proxy_agent.ParticipantList" { + return + } } - timestamp := time.Unix(int64(msg.Timestamp), 0).Format("15:04:05") topics := msg.Topics.ToSlice() + + if !verbose { + // Skip messages on user:{userID} topic - these are echoes of our sent messages + if len(topics) > 0 && topics[0] == "user:"+userID { + return + } + + // For user_notifications: show only agent responses (3+ routing entries), skip unwrap notifications + if len(topics) > 0 && topics[0] == "user_notifications:"+userID && len(msg.MessageHistory) < 3 { + return + } + } + + timestamp := time.Unix(int64(msg.Timestamp), 0).Format("15:04:05") topicStr := strings.Join(topics, ", ") // Message header From f23301053f1b53d4ad190a7039d53701975053e6 Mon Sep 17 00:00:00 2001 From: Nihal-Srivastava05 Date: Fri, 10 Jul 2026 00:18:36 +0530 Subject: [PATCH 3/3] feat: fix bugs --- forge-go/cli/message_builder.go | 2 +- forge-go/command/guild_run.go | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/forge-go/cli/message_builder.go b/forge-go/cli/message_builder.go index 19fc83b..4e8c96a 100644 --- a/forge-go/cli/message_builder.go +++ b/forge-go/cli/message_builder.go @@ -55,7 +55,7 @@ func BuildChatMessage(userID, userName, text, topic string) (*protocol.Message, convIDInt := convID.ToInt() msg := protocol.NewMessageFromGemstoneID(msgID) - msg.Format = "chatCompletionRequest" // Use short format - gateway normalizes it + msg.Format = "rustic_ai.core.guild.agent_ext.depends.llm.models.ChatCompletionRequest" // Use full format to match routing rules msg.Sender = protocol.AgentTag{ ID: &userID, Name: &userName, diff --git a/forge-go/command/guild_run.go b/forge-go/command/guild_run.go index db37a10..45bad48 100644 --- a/forge-go/command/guild_run.go +++ b/forge-go/command/guild_run.go @@ -352,7 +352,7 @@ func sendChatMessage(runtime *cli.GuildRuntime, guildID, userID, userName, text, actualTopic = topic } - fmt.Printf("πŸ“€ Sending to topic: %s\n", actualTopic) + fmt.Printf("πŸ“€ Sending to topic: %s (format: %s)\n", actualTopic, msg.Format) if err := runtime.PublishMessage(guildID, actualTopic, msg); err != nil { return fmt.Errorf("failed to publish: %w", err) } @@ -582,6 +582,7 @@ func printMessage(msg *protocol.Message, runtime *cli.GuildRuntime, spec *protoc } func findForgeRoot(startDir string) string { + // First try current directory and walk up dir := startDir for { goModPath := filepath.Join(dir, "go.mod") @@ -600,6 +601,21 @@ func findForgeRoot(startDir string) string { } dir = parent } + + // If not found walking up, try common subdirectory patterns + // This handles the case where we're in the repo root but go.mod is in forge-go/ + commonSubdirs := []string{"forge-go", "go", "backend"} + for _, subdir := range commonSubdirs { + forgeGoPath := filepath.Join(startDir, subdir) + goModPath := filepath.Join(forgeGoPath, "go.mod") + if _, err := os.Stat(goModPath); err == nil { + content, _ := os.ReadFile(goModPath) + if strings.Contains(string(content), "github.com/rustic-ai/forge/forge-go") { + return forgeGoPath + } + } + } + return "" }