- Go gateway (stdlib only): /v1/messages non-stream + SSE, /v1/messages/count_tokens, management API /api/* (providers CRUD, apply/restore, settings, backups, logs) - Protocol conversion: Anthropic Messages <-> Chat Completions with a streaming state machine keyed by content block index (text, tool_use, parallel calls) - ~/.claude/settings.json guarded read/write: timestamped backups, managed env keys only, one-click restore - Tauri 2 shell: spawns the gateway sidecar, parses the random port from stdout, stdin pipe watchdog prevents orphans, kills the child on exit - React frontend: Dashboard/Providers/Settings, zh-CN + en-US, TanStack Query - Tests: Go table-driven + httptest integration (all green), vitest + RTL
35 lines
665 B
Go
35 lines
665 B
Go
package gateway
|
|
|
|
import "sync"
|
|
|
|
// logRing keeps the most recent log entries in memory.
|
|
type logRing struct {
|
|
mu sync.Mutex
|
|
entries []LogEntry
|
|
cap int
|
|
}
|
|
|
|
func newLogRing(capacity int) *logRing {
|
|
return &logRing{cap: capacity}
|
|
}
|
|
|
|
func (r *logRing) add(entry LogEntry) {
|
|
r.mu.Lock()
|
|
defer r.mu.Unlock()
|
|
r.entries = append(r.entries, entry)
|
|
if len(r.entries) > r.cap {
|
|
r.entries = r.entries[len(r.entries)-r.cap:]
|
|
}
|
|
}
|
|
|
|
// list returns entries newest first.
|
|
func (r *logRing) list() []LogEntry {
|
|
r.mu.Lock()
|
|
defer r.mu.Unlock()
|
|
out := make([]LogEntry, len(r.entries))
|
|
for i, e := range r.entries {
|
|
out[len(r.entries)-1-i] = e
|
|
}
|
|
return out
|
|
}
|