Skip to content
Merged
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
36 changes: 36 additions & 0 deletions internal/api/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,46 @@ package api
import (
"encoding/json"
"net/http"
"runtime/debug"
"sync"

"commander/internal/hub"
"commander/internal/keepalive"
)

// Version is overridable at build time via -ldflags "-X commander/internal/api.Version=vX.Y.Z".
// When empty, we fall back to the VCS revision from the embedded build info.
var Version = ""

// Resolved version string cached on first read — build info never changes at runtime.
var (
cachedVersion string
cachedVersionOnce sync.Once
)

func commanderVersion() string {
cachedVersionOnce.Do(func() {
if Version != "" {
cachedVersion = Version
return
}
if info, ok := debug.ReadBuildInfo(); ok {
for _, s := range info.Settings {
if s.Key == "vcs.revision" {
if len(s.Value) > 7 {
cachedVersion = s.Value[:7]
} else {
cachedVersion = s.Value
}
return
}
}
}
cachedVersion = "dev"
})
return cachedVersion
}

// RegisterRoutes registers all REST API endpoints.
// ka is an optional KeepAlive for managed lifecycle (nil to disable).
func RegisterRoutes(mux *http.ServeMux, h *hub.Hub, ka *keepalive.KeepAlive) {
Expand Down Expand Up @@ -114,6 +149,7 @@ func handleInfo() http.HandlerFunc {
}
writeJSON(w, http.StatusOK, map[string]string{
"baseUrl": scheme + "://" + r.Host,
"version": commanderVersion(),
})
}
}
Expand Down
6 changes: 6 additions & 0 deletions web/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>web</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Black+Ops+One&family=JetBrains+Mono:wght@400;500;600;700&family=Inter:wght@400;500;600;700&display=swap"
/>
</head>
<body>
<div id="root"></div>
Expand Down
10 changes: 10 additions & 0 deletions web/public/squadron-logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 1 addition & 2 deletions web/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { MissionsPage } from './pages/MissionsPage'
import { AgentsPage } from './pages/AgentsPage'
import { PluginsPage } from './pages/PluginsPage'
import { MissionDetail } from './pages/MissionDetail'
import { MissionHistory } from './pages/MissionHistory'
import { MissionInstanceDetail } from './pages/MissionInstanceDetail'
import { AgentDetail } from './pages/AgentDetail'
import { ConfigPage } from './pages/ConfigPage'
Expand All @@ -32,7 +31,7 @@ function App() {
<Route path="skills" element={<SkillsPage />} />
<Route path="skills/:name" element={<SkillDetail />} />
<Route path="tools" element={<PluginsPage />} />
<Route path="history" element={<MissionHistory />} />
<Route path="history" element={<Navigate to="../missions?view=history" replace />} />
<Route path="missions/:name" element={<MissionDetail />} />
<Route path="runs/:mid" element={<MissionInstanceDetail />} />
<Route path="costs" element={<CostsPage />} />
Expand Down
4 changes: 2 additions & 2 deletions web/src/api/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ export async function logout(): Promise<void> {
window.location.href = '/auth/logout';
}

export async function getServerInfo(): Promise<{ baseUrl: string }> {
return fetchJSON<{ baseUrl: string }>('/info');
export async function getServerInfo(): Promise<{ baseUrl: string; version: string }> {
return fetchJSON<{ baseUrl: string; version: string }>('/info');
}

export async function listInstances(): Promise<InstanceState[]> {
Expand Down
4 changes: 2 additions & 2 deletions web/src/components/AppLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import { AppSidebar } from './AppSidebar';
export function AppLayout() {
return (
<TooltipProvider>
<SidebarProvider>
<SidebarProvider style={{ '--sidebar-width': '200px' } as React.CSSProperties}>
<AppSidebar />
<SidebarInset className="overflow-hidden min-w-0">
<SidebarInset className="min-w-0 h-svh overflow-y-auto">
<Outlet />
</SidebarInset>
</SidebarProvider>
Expand Down
Loading
Loading