Docker服务下添加Web UI,增删改查端点等,反代后可跨域、跨物理机、服务器使用#64
Conversation
* resolve merge conflict in main.go, keep remote version * 已知问题修复1215 --------- Co-authored-by: hea7en <hea7enn@qq.com>
There was a problem hiding this comment.
Pull request overview
This pull request transforms ccNexus from a Wails desktop application into a headless HTTP service with Docker support and adds a comprehensive Web UI for management and monitoring. The version is bumped from 4.3.0 to 4.4.0.
Key Changes:
- Headless Mode: New
cmd/server/main.goentry point for running as a pure HTTP service without GUI - Docker Support: Complete containerization with Dockerfile, docker-compose.yml, and entrypoint script for easy deployment
- Web UI: Embedded web-based admin dashboard for endpoint management, statistics, and real-time monitoring
- API Improvements: Enhanced transformer support for function calling in OpenAI Responses, Gemini, and Claude APIs
- Bug Fixes: PowerShell Core detection, UI styling improvements, and input token fallback for Claude transformers
Reviewed changes
Copilot reviewed 27 out of 27 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| docker-entrypoint.sh | Shell script for container initialization with data directory checks |
| docker-compose.yml | Docker Compose configuration for running ccNexus as a containerized service |
| Dockerfile | Multi-stage Docker build for headless server with SQLite support |
| README_DOCKER.md | Comprehensive documentation for Docker deployment and Web UI usage |
| app/cmd/server/main.go | New headless server entry point with environment variable support |
| app/cmd/server/webui_plugin.go | Plugin registration for Web UI routes |
| app/cmd/webui/* | Complete Web UI implementation with API handlers and frontend assets |
| app/internal/transformer/convert/* | Enhanced API transformations with function calling and thinking block support |
| app/internal/transformer/cc/claude.go | Added input tokens fallback for Claude message_delta events |
| app/internal/terminal/launcher.go | PowerShell Core (pwsh) detection for Windows terminal launching |
| app/internal/proxy/streaming.go | Updated streaming handler to pass request body for token estimation |
| app/frontend/src/* | UI improvements for model selection and theme support |
| app/wails.json | Version bump to 4.4.0 |
Comments suppressed due to low confidence (1)
Dockerfile:2
- The Dockerfile references Golang version 1.24 which does not exist. As of January 2025, the latest stable Go version is 1.23. This will cause build failures. Consider using a valid version like golang:1.23-alpine or golang:1.22-alpine.
FROM golang:1.24-alpine AS builder
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| <!-- Chart.js from CDN --> | ||
| <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script> |
There was a problem hiding this comment.
Loading Chart.js from a CDN creates a dependency on external infrastructure and can fail if the CDN is unavailable or blocked. For a headless Docker deployment, consider either bundling Chart.js locally or documenting this external dependency clearly in the README.
| <!-- Chart.js from CDN --> | |
| <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script> | |
| <!-- Chart.js (bundled locally) --> | |
| <script src="/ui/js/vendor/chart.umd.min.js"></script> |
| // CORSMiddleware adds CORS headers to responses | ||
| func CORSMiddleware(next http.Handler) http.Handler { | ||
| return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||
| w.Header().Set("Access-Control-Allow-Origin", "*") |
There was a problem hiding this comment.
CORS is configured to allow all origins with "*". This is a security risk in production environments as it allows any website to make requests to the API. Consider restricting this to specific trusted origins or making it configurable via environment variables.
| if req.Model != "" { | ||
| existing.Model = req.Model | ||
| } |
There was a problem hiding this comment.
The Model field is only updated if req.Model is non-empty, but existing.Remark is always overwritten (line 224). This inconsistency means users cannot clear the Model field while they can clear the Remark field. Consider using the same pattern for both fields or allowing explicit clearing of the Model field.
| if req.Model != "" { | |
| existing.Model = req.Model | |
| } | |
| existing.Model = req.Model |
| new Chart(ctx, { | ||
| type: 'bar', | ||
| data: { | ||
| labels: endpoints, | ||
| datasets: [{ | ||
| label: 'Requests', | ||
| data: requests, | ||
| backgroundColor: '#3b82f6', | ||
| borderColor: '#2563eb', | ||
| borderWidth: 1 | ||
| }] | ||
| }, | ||
| options: { | ||
| responsive: true, | ||
| maintainAspectRatio: true, | ||
| plugins: { | ||
| legend: { | ||
| display: false | ||
| } | ||
| }, | ||
| scales: { | ||
| y: { | ||
| beginAtZero: true | ||
| } | ||
| } | ||
| } | ||
| }); |
There was a problem hiding this comment.
Creating a new Chart instance without destroying any previous chart can lead to memory leaks if renderChart is called multiple times (e.g., when the dashboard is re-rendered). Consider storing the chart instance and destroying it before creating a new one using chart.destroy().
| @@ -0,0 +1,177 @@ | |||
| import { api } from '../api.js'; | |||
| import { state } from '../state.js'; | |||
There was a problem hiding this comment.
Unused import state.
| import { state } from '../state.js'; |
| @@ -0,0 +1,330 @@ | |||
| import { api } from '../api.js'; | |||
| import { state } from '../state.js'; | |||
There was a problem hiding this comment.
Unused import state.
| import { state } from '../state.js'; |
…artWithMux undefined 的编译错误(主程序需要在已有 mux 上挂载 WebUI 时使用)
webui