Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 128 additions & 0 deletions .flox/env/manifest.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions .flox/env/manifest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ docker.pkg-path = "docker"
docker.version = "^29.1.2"
docker-compose.pkg-path = "docker-compose"
docker-compose.version = "^5.0.0"
nodejs_24.pkg-path = "nodejs_24"
nodejs_24.version = "24.11.1"

[hook]
on-activate = """
Expand Down
2 changes: 1 addition & 1 deletion .infer/agents.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
agents:
- name: mock-agent
url: http://localhost:8081
url: http://localhost:8082
oci: ghcr.io/inference-gateway/mock-agent:latest
run: true
model: deepseek/deepseek-chat
Expand Down
26 changes: 26 additions & 0 deletions .infer/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,32 @@ mcp:
liveness_probe_interval: 10
max_retries: 10
servers: []
api:
host: 127.0.0.1
port: 8081
read_timeout: 30
write_timeout: 30
idle_timeout: 120
cors:
enabled: true
allowed_origins:
- http://localhost:3000
- http://localhost:3001
allowed_methods:
- GET
- POST
- PUT
- PATCH
- DELETE
- OPTIONS
allowed_headers:
- Content-Type
- Authorization
ui:
port: 3000
auto_open: true
mode: npm
working_dir: ./ui
pricing:
enabled: true
currency: USD
Expand Down
2 changes: 1 addition & 1 deletion Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ tasks:
desc: Run linter (requires golangci-lint)
cmds:
- golangci-lint run
- markdownlint . --ignore CHANGELOG.md --fix
- markdownlint . --ignore CHANGELOG.md --ignore ui/node_modules --fix

fmt:
desc: Format Go code
Expand Down
2 changes: 1 addition & 1 deletion cmd/agents.go
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ func listAgents(cmd *cobra.Command, args []string) error {
format, _ := cmd.Flags().GetString("format")

if format == "json" {
combinedOutput := map[string]interface{}{
combinedOutput := map[string]any{
"local": localAgents,
"external": externalAgents,
"total": totalAgents,
Expand Down
47 changes: 44 additions & 3 deletions cmd/chat.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import (
clipboard "github.com/inference-gateway/cli/internal/clipboard"
container "github.com/inference-gateway/cli/internal/container"
domain "github.com/inference-gateway/cli/internal/domain"
handlers "github.com/inference-gateway/cli/internal/handlers"
logger "github.com/inference-gateway/cli/internal/logger"
sdk "github.com/inference-gateway/sdk"
cobra "github.com/spf13/cobra"
viper "github.com/spf13/viper"
Expand All @@ -25,12 +27,20 @@ var chatCmd = &cobra.Command{
Short: "Start an interactive chat session with model selection",
Long: `Start an interactive chat session where you can select a model from a dropdown
and have a conversational interface with the inference gateway.`,
RunE: func(_ *cobra.Command, args []string) error {
RunE: func(cmd *cobra.Command, args []string) error {
cfg, err := getConfigFromViper()
if err != nil {
return fmt.Errorf("failed to load config: %w", err)
}

headless, _ := cmd.Flags().GetBool("headless")
sessionID, _ := cmd.Flags().GetString("session-id")
conversationID, _ := cmd.Flags().GetString("conversation-id")

if headless {
return runHeadlessChat(cfg, V, sessionID, conversationID)
}

if !isInteractiveTerminal() {
return runNonInteractiveChat(cfg, V)
}
Expand All @@ -56,6 +66,23 @@ func StartChatSession(cfg *config.Config, v *viper.Viper) error {
fmt.Printf(" Make sure the inference gateway is running at: %s\n\n", cfg.Gateway.URL)
}

agentManager := services.GetAgentManager()
if agentManager != nil {
agentCtx := context.Background()
if err := agentManager.StartAgents(agentCtx); err != nil {
logger.Error("Failed to start agents", "error", err)
}
}

mcpManager := services.GetMCPManager()
if mcpManager != nil {
mcpCtx, mcpCancel := context.WithTimeout(context.Background(), 120*time.Second)
defer mcpCancel()
if err := mcpManager.StartServers(mcpCtx); err != nil {
logger.Error("Some MCP servers failed to start", "error", err)
}
}

ctx, cancel := context.WithTimeout(context.Background(), time.Duration(cfg.Gateway.Timeout)*time.Second)
defer cancel()

Expand Down Expand Up @@ -86,10 +113,8 @@ func StartChatSession(cfg *config.Config, v *viper.Viper) error {
messageQueue := services.GetMessageQueue()
themeService := services.GetThemeService()
toolRegistry := services.GetToolRegistry()
mcpManager := services.GetMCPManager()
taskRetentionService := services.GetTaskRetentionService()
backgroundTaskService := services.GetBackgroundTaskService()
agentManager := services.GetAgentManager()
conversationOptimizer := services.GetConversationOptimizer()

versionInfo := GetVersionInfo()
Expand Down Expand Up @@ -300,6 +325,22 @@ func processStreamingOutput(events <-chan domain.ChatEvent) error {
return nil
}

// runHeadlessChat runs the chat in headless mode (JSON I/O via stdin/stdout)
func runHeadlessChat(cfg *config.Config, v *viper.Viper, sessionID string, conversationID string) error {
services := container.NewServiceContainer(cfg, v)

handler := handlers.NewHeadlessHandler(sessionID, conversationID, services, cfg)
defer func() {
_ = handler.Shutdown()
}()

return handler.Start()
}

func init() {
rootCmd.AddCommand(chatCmd)

chatCmd.Flags().Bool("headless", false, "Run in headless mode (JSON I/O via stdin/stdout)")
chatCmd.Flags().String("session-id", "", "Session identifier for headless mode")
chatCmd.Flags().String("conversation-id", "", "Conversation ID to continue (for headless mode)")
}
10 changes: 10 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,16 @@ func initConfig() { // nolint:funlen
v.SetDefault("tools.web_fetch.safety.timeout", defaults.Tools.WebFetch.Safety.Timeout)
v.SetDefault("tools.web_fetch.safety.allow_redirect", defaults.Tools.WebFetch.Safety.AllowRedirect)
v.SetDefault("tools.web_fetch.require_approval", defaults.Tools.WebFetch.RequireApproval)
v.SetDefault("api", defaults.API)
v.SetDefault("api.host", defaults.API.Host)
v.SetDefault("api.port", defaults.API.Port)
v.SetDefault("api.read_timeout", defaults.API.ReadTimeout)
v.SetDefault("api.write_timeout", defaults.API.WriteTimeout)
v.SetDefault("api.idle_timeout", defaults.API.IdleTimeout)
v.SetDefault("api.cors.enabled", defaults.API.CORS.Enabled)
v.SetDefault("api.cors.allowed_origins", defaults.API.CORS.AllowedOrigins)
v.SetDefault("api.cors.allowed_methods", defaults.API.CORS.AllowedMethods)
v.SetDefault("api.cors.allowed_headers", defaults.API.CORS.AllowedHeaders)
v.SetDefault("pricing", defaults.Pricing)
v.SetDefault("pricing.enabled", defaults.Pricing.Enabled)
v.SetDefault("pricing.currency", defaults.Pricing.Currency)
Expand Down
Loading