Documentation
¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
View Source
var AskCmd = &cli.Command{ Name: "ask", Usage: "Ask a model a question", Description: "Send a question to a specific model and display the JSON response", MaxArgs: cli.UnlimitedArgs, Arguments: []cli.Argument{ &cli.StringArg{ Name: "model", Required: true, Usage: "Model to use", }, }, Flags: []cli.Flag{ &cli.StringFlag{ Name: "server", Usage: "Server URL", DefaultValue: "http://localhost:12345", }, &cli.StringFlag{ Name: "token", Aliases: []string{"t"}, Usage: "Bearer token for server authentication", }, }, Run: func(ctx context.Context, cmd *cli.Command) error { model := cmd.GetStringArg("model") question := strings.Join(cmd.GetArgs(), " ") serverURL := cmd.GetString("server") token := cmd.GetString("token") if question == "" { return fmt.Errorf("question is required") } payload := map[string]any{ "model": model, "messages": []map[string]string{ {"role": "user", "content": question}, }, } body, err := json.Marshal(payload) if err != nil { return fmt.Errorf("failed to marshal request: %w", err) } client := &http.Client{Timeout: 120 * time.Second} req, err := http.NewRequest("POST", serverURL+"/v1/chat/completions", bytes.NewReader(body)) if err != nil { return fmt.Errorf("failed to create request: %w", err) } req.Header.Set("Content-Type", "application/json") if token != "" { req.Header.Set("Authorization", "Bearer "+token) } resp, err := client.Do(req) if err != nil { return fmt.Errorf("request failed: %w", err) } defer resp.Body.Close() respBody, err := io.ReadAll(resp.Body) if err != nil { return fmt.Errorf("failed to read response: %w", err) } var out any if err := json.Unmarshal(respBody, &out); err != nil { return fmt.Errorf("failed to parse response: %w", err) } formatted, err := json.MarshalIndent(out, "", " ") if err != nil { return fmt.Errorf("failed to format response: %w", err) } fmt.Println(string(formatted)) return nil }, }
View Source
var ModelsCmd = &cli.Command{ Name: "models", Usage: "List available models", Description: "List all models available from the LLM router", Flags: []cli.Flag{ &cli.StringFlag{ Name: "server", Usage: "Server URL", DefaultValue: "http://localhost:12345", }, &cli.StringFlag{ Name: "token", Aliases: []string{"t"}, Usage: "Bearer token for server authentication", }, }, Run: func(ctx context.Context, cmd *cli.Command) error { serverURL := cmd.GetString("server") token := cmd.GetString("token") client := &http.Client{Timeout: 30 * time.Second} req, err := http.NewRequest("GET", serverURL+"/v1/models", nil) if err != nil { return fmt.Errorf("failed to create request: %w", err) } if token != "" { req.Header.Set("Authorization", "Bearer "+token) } resp, err := client.Do(req) if err != nil { return fmt.Errorf("request failed: %w", err) } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { return fmt.Errorf("failed to read response: %w", err) } var out any if err := json.Unmarshal(body, &out); err != nil { return fmt.Errorf("failed to parse response: %w", err) } formatted, err := json.MarshalIndent(out, "", " ") if err != nil { return fmt.Errorf("failed to format response: %w", err) } fmt.Println(string(formatted)) return nil }, }
View Source
var RootCmd = &cli.Command{ Name: "llmrouter", Version: build.Version, Usage: "LLM Routing Service", Description: "Routes requests to different LLM providers based on configuration", ConfigFile: cli_toml.NewConfigFile(&configFile, func() []string { paths := []string{"."} if home, err := os.UserHomeDir(); err == nil { paths = append(paths, filepath.Join(home, ".llmrouter")) paths = append(paths, filepath.Join(home, ".config", "llmrouter")) paths = append(paths, filepath.Join(home, ".config")) } return paths }), Flags: append([]cli.Flag{ &cli.StringFlag{ Name: "config", Aliases: []string{"c"}, Usage: "Configuration file path", AssignTo: &configFile, Global: true, }, &cli.StringFlag{ Name: "log-level", Usage: "Log level (trace|debug|info|warn|error)", DefaultValue: "info", ConfigPath: []string{"logging.level"}, Global: true, }, &cli.StringFlag{ Name: "log-format", Usage: "Log format (console|json)", DefaultValue: "console", ConfigPath: []string{"logging.format"}, Global: true, }, }, ServerFlags()...), PreRun: func(ctx context.Context, cmd *cli.Command) (context.Context, error) { log.Configure(cmd.GetString("log-level"), cmd.GetString("log-format")) return ctx, nil }, Commands: []*cli.Command{ ServerCmd, ToolCmd, ModelsCmd, AskCmd, }, }
RootCmd is the top-level command. With no subcommand:
- desktop builds (default) open the GUI window via RootCmd.Run (set by init() in root_desktop.go)
- server builds (-tags server) show help (Run stays nil — the original behaviour before desktop support was added)
In both builds, `llmrouter server` explicitly starts the headless server.
View Source
var ServerCmd = &cli.Command{ Name: "server", Usage: "Start the LLM router server", Description: "Start the LLM router server with MCP and OpenAI API endpoints", Flags: ServerFlags(), Run: func(ctx context.Context, cmd *cli.Command) error { return server.RunServer(ctx, cmd) }, }
View Source
var ToolCmd = &cli.Command{ Name: "tool", Usage: "Execute a tool via the MCP server", Description: "Execute a specific tool through the MCP server", Arguments: []cli.Argument{ &cli.StringArg{ Name: "toolname", Required: true, Usage: "Name of the tool to execute", }, &cli.StringArg{ Name: "arguments", Required: false, Usage: "JSON arguments for the tool (optional)", }, }, Flags: []cli.Flag{ &cli.StringFlag{ Name: "server", Usage: "MCP server URL", DefaultValue: "http://localhost:12345", }, &cli.BoolFlag{ Name: "verbose", Aliases: []string{"v"}, Usage: "Enable verbose output", DefaultValue: false, }, &cli.StringFlag{ Name: "token", Aliases: []string{"t"}, Usage: "Bearer token for server authentication", }, }, Run: func(ctx context.Context, cmd *cli.Command) error { toolName := cmd.GetStringArg("toolname") argsStr := cmd.GetStringArg("arguments") serverURL := cmd.GetString("server") verbose := cmd.GetBool("verbose") token := cmd.GetString("token") var toolArgs map[string]interface{} if argsStr != "" { if err := json.Unmarshal([]byte(argsStr), &toolArgs); err != nil { return fmt.Errorf("error parsing arguments: %w\nHint: Quote your JSON string properly", err) } } if verbose { log.GetLogger().Debug("executing tool", "tool", toolName, "args", toolArgs) } var request map[string]interface{} if serverTools[toolName] { request = map[string]interface{}{ "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": map[string]interface{}{ "name": toolName, "arguments": toolArgs, }, } } else { request = map[string]interface{}{ "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": map[string]interface{}{ "name": "execute_tool", "arguments": map[string]interface{}{ "name": toolName, "arguments": toolArgs, }, }, } } return ExecuteMCPRequest(serverURL, request, token, verbose) }, }
Functions ¶
func ExecuteMCPRequest ¶
func ExecuteMCPRequest(serverURL string, request map[string]interface{}, token string, verbose bool) error
ExecuteMCPRequest sends an MCP request and processes the response
func ServerFlags ¶ added in v0.9.0
ServerFlags returns the flag set for the server. Shared between the `server` subcommand and the root command so that `llmrouter -p 8080` (desktop mode) and `llmrouter server -p 8080` (headless) accept the same options.
Types ¶
This section is empty.
Click to show internal directories.
Click to hide internal directories.