Merge pull request #19 from lordmathis/docs/readme-screenshot

docs: Add dashboard screenshot to README
This commit is contained in:
2025-08-07 19:55:15 +02:00
committed by GitHub
7 changed files with 145 additions and 73 deletions

View File

@@ -2,7 +2,7 @@
![Build and Release](https://github.com/lordmathis/llamactl/actions/workflows/release.yaml/badge.svg) ![Go Tests](https://github.com/lordmathis/llamactl/actions/workflows/go_test.yaml/badge.svg) ![WebUI Tests](https://github.com/lordmathis/llamactl/actions/workflows/webui_test.yaml/badge.svg) ![Build and Release](https://github.com/lordmathis/llamactl/actions/workflows/release.yaml/badge.svg) ![Go Tests](https://github.com/lordmathis/llamactl/actions/workflows/go_test.yaml/badge.svg) ![WebUI Tests](https://github.com/lordmathis/llamactl/actions/workflows/webui_test.yaml/badge.svg)
**Management server for multiple llama.cpp instances with OpenAI-compatible API routing.** **Management server and proxy for multiple llama.cpp instances with OpenAI-compatible API routing.**
## Why llamactl? ## Why llamactl?
@@ -13,6 +13,8 @@
📊 **Instance Monitoring**: Health checks, auto-restart, log management 📊 **Instance Monitoring**: Health checks, auto-restart, log management
**Persistent State**: Instances survive server restarts **Persistent State**: Instances survive server restarts
![Dashboard Screenshot](docs/images/screenshot.png)
**Choose llamactl if**: You need authentication, health monitoring, auto-restart, and centralized management of multiple llama-server instances **Choose llamactl if**: You need authentication, health monitoring, auto-restart, and centralized management of multiple llama-server instances
**Choose Ollama if**: You want the simplest setup with strong community ecosystem and third-party integrations **Choose Ollama if**: You want the simplest setup with strong community ecosystem and third-party integrations
**Choose LM Studio if**: You prefer a polished desktop GUI experience with easy model management **Choose LM Studio if**: You prefer a polished desktop GUI experience with easy model management

View File

@@ -1,5 +1,5 @@
// Package docs Code generated by swaggo/swag. DO NOT EDIT // Package apidocs Code generated by swaggo/swag. DO NOT EDIT
package docs package apidocs
import "github.com/swaggo/swag" import "github.com/swaggo/swag"
@@ -37,7 +37,7 @@ const docTemplate = `{
"schema": { "schema": {
"type": "array", "type": "array",
"items": { "items": {
"$ref": "#/definitions/llamactl.Instance" "$ref": "#/definitions/instance.Process"
} }
} }
}, },
@@ -75,7 +75,7 @@ const docTemplate = `{
"200": { "200": {
"description": "Instance details", "description": "Instance details",
"schema": { "schema": {
"$ref": "#/definitions/llamactl.Instance" "$ref": "#/definitions/instance.Process"
} }
}, },
"400": { "400": {
@@ -120,7 +120,7 @@ const docTemplate = `{
"in": "body", "in": "body",
"required": true, "required": true,
"schema": { "schema": {
"$ref": "#/definitions/llamactl.CreateInstanceOptions" "$ref": "#/definitions/instance.CreateInstanceOptions"
} }
} }
], ],
@@ -128,7 +128,7 @@ const docTemplate = `{
"200": { "200": {
"description": "Updated instance details", "description": "Updated instance details",
"schema": { "schema": {
"$ref": "#/definitions/llamactl.Instance" "$ref": "#/definitions/instance.Process"
} }
}, },
"400": { "400": {
@@ -173,7 +173,7 @@ const docTemplate = `{
"in": "body", "in": "body",
"required": true, "required": true,
"schema": { "schema": {
"$ref": "#/definitions/llamactl.CreateInstanceOptions" "$ref": "#/definitions/instance.CreateInstanceOptions"
} }
} }
], ],
@@ -181,7 +181,7 @@ const docTemplate = `{
"201": { "201": {
"description": "Created instance details", "description": "Created instance details",
"schema": { "schema": {
"$ref": "#/definitions/llamactl.Instance" "$ref": "#/definitions/instance.Process"
} }
}, },
"400": { "400": {
@@ -401,7 +401,7 @@ const docTemplate = `{
"200": { "200": {
"description": "Restarted instance details", "description": "Restarted instance details",
"schema": { "schema": {
"$ref": "#/definitions/llamactl.Instance" "$ref": "#/definitions/instance.Process"
} }
}, },
"400": { "400": {
@@ -444,7 +444,7 @@ const docTemplate = `{
"200": { "200": {
"description": "Started instance details", "description": "Started instance details",
"schema": { "schema": {
"$ref": "#/definitions/llamactl.Instance" "$ref": "#/definitions/instance.Process"
} }
}, },
"400": { "400": {
@@ -487,7 +487,7 @@ const docTemplate = `{
"200": { "200": {
"description": "Stopped instance details", "description": "Stopped instance details",
"schema": { "schema": {
"$ref": "#/definitions/llamactl.Instance" "$ref": "#/definitions/instance.Process"
} }
}, },
"400": { "400": {
@@ -639,7 +639,35 @@ const docTemplate = `{
"200": { "200": {
"description": "List of OpenAI-compatible instances", "description": "List of OpenAI-compatible instances",
"schema": { "schema": {
"$ref": "#/definitions/llamactl.OpenAIListInstancesResponse" "$ref": "#/definitions/server.OpenAIListInstancesResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"type": "string"
}
}
}
}
},
"/version": {
"get": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "Returns the version of the llamactl command",
"tags": [
"version"
],
"summary": "Get llamactl version",
"responses": {
"200": {
"description": "Version information",
"schema": {
"type": "string"
} }
}, },
"500": { "500": {
@@ -653,7 +681,7 @@ const docTemplate = `{
} }
}, },
"definitions": { "definitions": {
"llamactl.CreateInstanceOptions": { "instance.CreateInstanceOptions": {
"type": "object", "type": "object",
"properties": { "properties": {
"alias": { "alias": {
@@ -751,7 +779,6 @@ const docTemplate = `{
"type": "string" "type": "string"
}, },
"draft_max": { "draft_max": {
"description": "Speculative decoding params",
"type": "integer" "type": "integer"
}, },
"draft_min": { "draft_min": {
@@ -955,7 +982,7 @@ const docTemplate = `{
"type": "boolean" "type": "boolean"
}, },
"no_context_shift": { "no_context_shift": {
"description": "Server/Example-specific params", "description": "Example-specific params",
"type": "boolean" "type": "boolean"
}, },
"no_escape": { "no_escape": {
@@ -1027,10 +1054,10 @@ const docTemplate = `{
"presence_penalty": { "presence_penalty": {
"type": "number" "type": "number"
}, },
"priority": { "prio": {
"type": "integer" "type": "integer"
}, },
"priority_batch": { "prio_batch": {
"type": "integer" "type": "integer"
}, },
"props": { "props": {
@@ -1101,7 +1128,7 @@ const docTemplate = `{
"ssl_key_file": { "ssl_key_file": {
"type": "string" "type": "string"
}, },
"temperature": { "temp": {
"type": "number" "type": "number"
}, },
"tensor_split": { "tensor_split": {
@@ -1167,7 +1194,7 @@ const docTemplate = `{
} }
} }
}, },
"llamactl.Instance": { "instance.Process": {
"type": "object", "type": "object",
"properties": { "properties": {
"created": { "created": {
@@ -1183,7 +1210,7 @@ const docTemplate = `{
} }
} }
}, },
"llamactl.OpenAIInstance": { "server.OpenAIInstance": {
"type": "object", "type": "object",
"properties": { "properties": {
"created": { "created": {
@@ -1200,13 +1227,13 @@ const docTemplate = `{
} }
} }
}, },
"llamactl.OpenAIListInstancesResponse": { "server.OpenAIListInstancesResponse": {
"type": "object", "type": "object",
"properties": { "properties": {
"data": { "data": {
"type": "array", "type": "array",
"items": { "items": {
"$ref": "#/definitions/llamactl.OpenAIInstance" "$ref": "#/definitions/server.OpenAIInstance"
} }
}, },
"object": { "object": {

View File

@@ -30,7 +30,7 @@
"schema": { "schema": {
"type": "array", "type": "array",
"items": { "items": {
"$ref": "#/definitions/llamactl.Instance" "$ref": "#/definitions/instance.Process"
} }
} }
}, },
@@ -68,7 +68,7 @@
"200": { "200": {
"description": "Instance details", "description": "Instance details",
"schema": { "schema": {
"$ref": "#/definitions/llamactl.Instance" "$ref": "#/definitions/instance.Process"
} }
}, },
"400": { "400": {
@@ -113,7 +113,7 @@
"in": "body", "in": "body",
"required": true, "required": true,
"schema": { "schema": {
"$ref": "#/definitions/llamactl.CreateInstanceOptions" "$ref": "#/definitions/instance.CreateInstanceOptions"
} }
} }
], ],
@@ -121,7 +121,7 @@
"200": { "200": {
"description": "Updated instance details", "description": "Updated instance details",
"schema": { "schema": {
"$ref": "#/definitions/llamactl.Instance" "$ref": "#/definitions/instance.Process"
} }
}, },
"400": { "400": {
@@ -166,7 +166,7 @@
"in": "body", "in": "body",
"required": true, "required": true,
"schema": { "schema": {
"$ref": "#/definitions/llamactl.CreateInstanceOptions" "$ref": "#/definitions/instance.CreateInstanceOptions"
} }
} }
], ],
@@ -174,7 +174,7 @@
"201": { "201": {
"description": "Created instance details", "description": "Created instance details",
"schema": { "schema": {
"$ref": "#/definitions/llamactl.Instance" "$ref": "#/definitions/instance.Process"
} }
}, },
"400": { "400": {
@@ -394,7 +394,7 @@
"200": { "200": {
"description": "Restarted instance details", "description": "Restarted instance details",
"schema": { "schema": {
"$ref": "#/definitions/llamactl.Instance" "$ref": "#/definitions/instance.Process"
} }
}, },
"400": { "400": {
@@ -437,7 +437,7 @@
"200": { "200": {
"description": "Started instance details", "description": "Started instance details",
"schema": { "schema": {
"$ref": "#/definitions/llamactl.Instance" "$ref": "#/definitions/instance.Process"
} }
}, },
"400": { "400": {
@@ -480,7 +480,7 @@
"200": { "200": {
"description": "Stopped instance details", "description": "Stopped instance details",
"schema": { "schema": {
"$ref": "#/definitions/llamactl.Instance" "$ref": "#/definitions/instance.Process"
} }
}, },
"400": { "400": {
@@ -632,7 +632,35 @@
"200": { "200": {
"description": "List of OpenAI-compatible instances", "description": "List of OpenAI-compatible instances",
"schema": { "schema": {
"$ref": "#/definitions/llamactl.OpenAIListInstancesResponse" "$ref": "#/definitions/server.OpenAIListInstancesResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"type": "string"
}
}
}
}
},
"/version": {
"get": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "Returns the version of the llamactl command",
"tags": [
"version"
],
"summary": "Get llamactl version",
"responses": {
"200": {
"description": "Version information",
"schema": {
"type": "string"
} }
}, },
"500": { "500": {
@@ -646,7 +674,7 @@
} }
}, },
"definitions": { "definitions": {
"llamactl.CreateInstanceOptions": { "instance.CreateInstanceOptions": {
"type": "object", "type": "object",
"properties": { "properties": {
"alias": { "alias": {
@@ -744,7 +772,6 @@
"type": "string" "type": "string"
}, },
"draft_max": { "draft_max": {
"description": "Speculative decoding params",
"type": "integer" "type": "integer"
}, },
"draft_min": { "draft_min": {
@@ -948,7 +975,7 @@
"type": "boolean" "type": "boolean"
}, },
"no_context_shift": { "no_context_shift": {
"description": "Server/Example-specific params", "description": "Example-specific params",
"type": "boolean" "type": "boolean"
}, },
"no_escape": { "no_escape": {
@@ -1020,10 +1047,10 @@
"presence_penalty": { "presence_penalty": {
"type": "number" "type": "number"
}, },
"priority": { "prio": {
"type": "integer" "type": "integer"
}, },
"priority_batch": { "prio_batch": {
"type": "integer" "type": "integer"
}, },
"props": { "props": {
@@ -1094,7 +1121,7 @@
"ssl_key_file": { "ssl_key_file": {
"type": "string" "type": "string"
}, },
"temperature": { "temp": {
"type": "number" "type": "number"
}, },
"tensor_split": { "tensor_split": {
@@ -1160,7 +1187,7 @@
} }
} }
}, },
"llamactl.Instance": { "instance.Process": {
"type": "object", "type": "object",
"properties": { "properties": {
"created": { "created": {
@@ -1176,7 +1203,7 @@
} }
} }
}, },
"llamactl.OpenAIInstance": { "server.OpenAIInstance": {
"type": "object", "type": "object",
"properties": { "properties": {
"created": { "created": {
@@ -1193,13 +1220,13 @@
} }
} }
}, },
"llamactl.OpenAIListInstancesResponse": { "server.OpenAIListInstancesResponse": {
"type": "object", "type": "object",
"properties": { "properties": {
"data": { "data": {
"type": "array", "type": "array",
"items": { "items": {
"$ref": "#/definitions/llamactl.OpenAIInstance" "$ref": "#/definitions/server.OpenAIInstance"
} }
}, },
"object": { "object": {

View File

@@ -1,6 +1,6 @@
basePath: /api/v1 basePath: /api/v1
definitions: definitions:
llamactl.CreateInstanceOptions: instance.CreateInstanceOptions:
properties: properties:
alias: alias:
type: string type: string
@@ -66,7 +66,6 @@ definitions:
device_draft: device_draft:
type: string type: string
draft_max: draft_max:
description: Speculative decoding params
type: integer type: integer
draft_min: draft_min:
type: integer type: integer
@@ -203,7 +202,7 @@ definitions:
no_cont_batching: no_cont_batching:
type: boolean type: boolean
no_context_shift: no_context_shift:
description: Server/Example-specific params description: Example-specific params
type: boolean type: boolean
no_escape: no_escape:
type: boolean type: boolean
@@ -251,9 +250,9 @@ definitions:
type: integer type: integer
presence_penalty: presence_penalty:
type: number type: number
priority: prio:
type: integer type: integer
priority_batch: prio_batch:
type: integer type: integer
props: props:
type: boolean type: boolean
@@ -301,7 +300,7 @@ definitions:
type: string type: string
ssl_key_file: ssl_key_file:
type: string type: string
temperature: temp:
type: number type: number
tensor_split: tensor_split:
type: string type: string
@@ -345,7 +344,7 @@ definitions:
yarn_orig_ctx: yarn_orig_ctx:
type: integer type: integer
type: object type: object
llamactl.Instance: instance.Process:
properties: properties:
created: created:
description: Creation time description: Creation time
@@ -356,7 +355,7 @@ definitions:
description: Status description: Status
type: boolean type: boolean
type: object type: object
llamactl.OpenAIInstance: server.OpenAIInstance:
properties: properties:
created: created:
type: integer type: integer
@@ -367,11 +366,11 @@ definitions:
owned_by: owned_by:
type: string type: string
type: object type: object
llamactl.OpenAIListInstancesResponse: server.OpenAIListInstancesResponse:
properties: properties:
data: data:
items: items:
$ref: '#/definitions/llamactl.OpenAIInstance' $ref: '#/definitions/server.OpenAIInstance'
type: array type: array
object: object:
type: string type: string
@@ -393,7 +392,7 @@ paths:
description: List of instances description: List of instances
schema: schema:
items: items:
$ref: '#/definitions/llamactl.Instance' $ref: '#/definitions/instance.Process'
type: array type: array
"500": "500":
description: Internal Server Error description: Internal Server Error
@@ -441,7 +440,7 @@ paths:
"200": "200":
description: Instance details description: Instance details
schema: schema:
$ref: '#/definitions/llamactl.Instance' $ref: '#/definitions/instance.Process'
"400": "400":
description: Invalid name format description: Invalid name format
schema: schema:
@@ -470,12 +469,12 @@ paths:
name: options name: options
required: true required: true
schema: schema:
$ref: '#/definitions/llamactl.CreateInstanceOptions' $ref: '#/definitions/instance.CreateInstanceOptions'
responses: responses:
"201": "201":
description: Created instance details description: Created instance details
schema: schema:
$ref: '#/definitions/llamactl.Instance' $ref: '#/definitions/instance.Process'
"400": "400":
description: Invalid request body description: Invalid request body
schema: schema:
@@ -504,12 +503,12 @@ paths:
name: options name: options
required: true required: true
schema: schema:
$ref: '#/definitions/llamactl.CreateInstanceOptions' $ref: '#/definitions/instance.CreateInstanceOptions'
responses: responses:
"200": "200":
description: Updated instance details description: Updated instance details
schema: schema:
$ref: '#/definitions/llamactl.Instance' $ref: '#/definitions/instance.Process'
"400": "400":
description: Invalid name format description: Invalid name format
schema: schema:
@@ -627,7 +626,7 @@ paths:
"200": "200":
description: Restarted instance details description: Restarted instance details
schema: schema:
$ref: '#/definitions/llamactl.Instance' $ref: '#/definitions/instance.Process'
"400": "400":
description: Invalid name format description: Invalid name format
schema: schema:
@@ -654,7 +653,7 @@ paths:
"200": "200":
description: Started instance details description: Started instance details
schema: schema:
$ref: '#/definitions/llamactl.Instance' $ref: '#/definitions/instance.Process'
"400": "400":
description: Invalid name format description: Invalid name format
schema: schema:
@@ -681,7 +680,7 @@ paths:
"200": "200":
description: Stopped instance details description: Stopped instance details
schema: schema:
$ref: '#/definitions/llamactl.Instance' $ref: '#/definitions/instance.Process'
"400": "400":
description: Invalid name format description: Invalid name format
schema: schema:
@@ -777,7 +776,7 @@ paths:
"200": "200":
description: List of OpenAI-compatible instances description: List of OpenAI-compatible instances
schema: schema:
$ref: '#/definitions/llamactl.OpenAIListInstancesResponse' $ref: '#/definitions/server.OpenAIListInstancesResponse'
"500": "500":
description: Internal Server Error description: Internal Server Error
schema: schema:
@@ -787,4 +786,21 @@ paths:
summary: List instances in OpenAI-compatible format summary: List instances in OpenAI-compatible format
tags: tags:
- openai - openai
/version:
get:
description: Returns the version of the llamactl command
responses:
"200":
description: Version information
schema:
type: string
"500":
description: Internal Server Error
schema:
type: string
security:
- ApiKeyAuth: []
summary: Get llamactl version
tags:
- version
swagger: "2.0" swagger: "2.0"

BIN
docs/images/screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

View File

@@ -116,7 +116,7 @@ func (h *Handler) LlamaServerListDevicesHandler() http.HandlerFunc {
// @Tags instances // @Tags instances
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Produces json // @Produces json
// @Success 200 {array} Instance "List of instances" // @Success 200 {array} instance.Process "List of instances"
// @Failure 500 {string} string "Internal Server Error" // @Failure 500 {string} string "Internal Server Error"
// @Router /instances [get] // @Router /instances [get]
func (h *Handler) ListInstances() http.HandlerFunc { func (h *Handler) ListInstances() http.HandlerFunc {
@@ -143,8 +143,8 @@ func (h *Handler) ListInstances() http.HandlerFunc {
// @Accept json // @Accept json
// @Produces json // @Produces json
// @Param name path string true "Instance Name" // @Param name path string true "Instance Name"
// @Param options body CreateInstanceOptions true "Instance configuration options" // @Param options body instance.CreateInstanceOptions true "Instance configuration options"
// @Success 201 {object} Instance "Created instance details" // @Success 201 {object} instance.Process "Created instance details"
// @Failure 400 {string} string "Invalid request body" // @Failure 400 {string} string "Invalid request body"
// @Failure 500 {string} string "Internal Server Error" // @Failure 500 {string} string "Internal Server Error"
// @Router /instances/{name} [post] // @Router /instances/{name} [post]
@@ -184,7 +184,7 @@ func (h *Handler) CreateInstance() http.HandlerFunc {
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Produces json // @Produces json
// @Param name path string true "Instance Name" // @Param name path string true "Instance Name"
// @Success 200 {object} Instance "Instance details" // @Success 200 {object} instance.Process "Instance details"
// @Failure 400 {string} string "Invalid name format" // @Failure 400 {string} string "Invalid name format"
// @Failure 500 {string} string "Internal Server Error" // @Failure 500 {string} string "Internal Server Error"
// @Router /instances/{name} [get] // @Router /instances/{name} [get]
@@ -218,8 +218,8 @@ func (h *Handler) GetInstance() http.HandlerFunc {
// @Accept json // @Accept json
// @Produces json // @Produces json
// @Param name path string true "Instance Name" // @Param name path string true "Instance Name"
// @Param options body CreateInstanceOptions true "Instance configuration options" // @Param options body instance.CreateInstanceOptions true "Instance configuration options"
// @Success 200 {object} Instance "Updated instance details" // @Success 200 {object} instance.Process "Updated instance details"
// @Failure 400 {string} string "Invalid name format" // @Failure 400 {string} string "Invalid name format"
// @Failure 500 {string} string "Internal Server Error" // @Failure 500 {string} string "Internal Server Error"
// @Router /instances/{name} [put] // @Router /instances/{name} [put]
@@ -258,7 +258,7 @@ func (h *Handler) UpdateInstance() http.HandlerFunc {
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Produces json // @Produces json
// @Param name path string true "Instance Name" // @Param name path string true "Instance Name"
// @Success 200 {object} Instance "Started instance details" // @Success 200 {object} instance.Process "Started instance details"
// @Failure 400 {string} string "Invalid name format" // @Failure 400 {string} string "Invalid name format"
// @Failure 500 {string} string "Internal Server Error" // @Failure 500 {string} string "Internal Server Error"
// @Router /instances/{name}/start [post] // @Router /instances/{name}/start [post]
@@ -291,7 +291,7 @@ func (h *Handler) StartInstance() http.HandlerFunc {
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Produces json // @Produces json
// @Param name path string true "Instance Name" // @Param name path string true "Instance Name"
// @Success 200 {object} Instance "Stopped instance details" // @Success 200 {object} instance.Process "Stopped instance details"
// @Failure 400 {string} string "Invalid name format" // @Failure 400 {string} string "Invalid name format"
// @Failure 500 {string} string "Internal Server Error" // @Failure 500 {string} string "Internal Server Error"
// @Router /instances/{name}/stop [post] // @Router /instances/{name}/stop [post]
@@ -324,7 +324,7 @@ func (h *Handler) StopInstance() http.HandlerFunc {
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Produces json // @Produces json
// @Param name path string true "Instance Name" // @Param name path string true "Instance Name"
// @Success 200 {object} Instance "Restarted instance details" // @Success 200 {object} instance.Process "Restarted instance details"
// @Failure 400 {string} string "Invalid name format" // @Failure 400 {string} string "Invalid name format"
// @Failure 500 {string} string "Internal Server Error" // @Failure 500 {string} string "Internal Server Error"
// @Router /instances/{name}/restart [post] // @Router /instances/{name}/restart [post]

View File

@@ -8,7 +8,7 @@ import (
"github.com/go-chi/cors" "github.com/go-chi/cors"
httpSwagger "github.com/swaggo/http-swagger" httpSwagger "github.com/swaggo/http-swagger"
_ "llamactl/docs" _ "llamactl/apidocs"
"llamactl/webui" "llamactl/webui"
) )