Rename AuthMode to Backend, fix LiteLLM variant typo, add image update alerts, clean up Settings
All checks were successful
Build App / compute-version (push) Successful in 6s
Build App / build-macos (push) Successful in 2m21s
Build App / build-windows (push) Successful in 3m28s
Build App / build-linux (push) Successful in 5m14s
Build App / create-tag (push) Successful in 2s
Build App / sync-to-github (push) Successful in 10s
All checks were successful
Build App / compute-version (push) Successful in 6s
Build App / build-macos (push) Successful in 2m21s
Build App / build-windows (push) Successful in 3m28s
Build App / build-linux (push) Successful in 5m14s
Build App / create-tag (push) Successful in 2s
Build App / sync-to-github (push) Successful in 10s
- Fix serde deserialization error: TypeScript sent "lit_llm" but Rust expected "lite_llm" - Rename AuthMode enum to Backend across Rust and TypeScript (with serde alias for backward compat) - Add container image update checking via registry digest comparison - Improve Settings page: fix image address display spacing, remove per-project auth section - Update UI labels from "Auth" to "Backend" throughout Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
export default function ApiKeyInput() {
|
||||
return (
|
||||
<div>
|
||||
<label className="block text-sm font-medium mb-1">Authentication</label>
|
||||
<label className="block text-sm font-medium mb-1">Backend</label>
|
||||
<p className="text-xs text-[var(--text-secondary)] mb-3">
|
||||
Each project can use <strong>claude login</strong> (OAuth, run inside the terminal) or <strong>AWS Bedrock</strong>. Set auth mode per-project.
|
||||
Each project can use <strong>claude login</strong> (OAuth, run inside the terminal) or <strong>AWS Bedrock</strong>. Set backend per-project.
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -121,9 +121,9 @@ export default function DockerSettings() {
|
||||
)}
|
||||
|
||||
{/* Resolved image display */}
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<span className="text-[var(--text-secondary)]">Image</span>
|
||||
<span className="text-xs text-[var(--text-secondary)] truncate max-w-[200px]" title={resolvedImageName}>
|
||||
<span className="block text-xs text-[var(--text-secondary)] font-mono mt-0.5 truncate" title={resolvedImageName}>
|
||||
{resolvedImageName}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
91
app/src/components/settings/ImageUpdateDialog.tsx
Normal file
91
app/src/components/settings/ImageUpdateDialog.tsx
Normal file
@@ -0,0 +1,91 @@
|
||||
import { useEffect, useRef, useCallback } from "react";
|
||||
import type { ImageUpdateInfo } from "../../lib/types";
|
||||
|
||||
interface Props {
|
||||
imageUpdateInfo: ImageUpdateInfo;
|
||||
onDismiss: () => void;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
export default function ImageUpdateDialog({
|
||||
imageUpdateInfo,
|
||||
onDismiss,
|
||||
onClose,
|
||||
}: Props) {
|
||||
const overlayRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
if (e.key === "Escape") onClose();
|
||||
};
|
||||
document.addEventListener("keydown", handleKeyDown);
|
||||
return () => document.removeEventListener("keydown", handleKeyDown);
|
||||
}, [onClose]);
|
||||
|
||||
const handleOverlayClick = useCallback(
|
||||
(e: React.MouseEvent<HTMLDivElement>) => {
|
||||
if (e.target === overlayRef.current) onClose();
|
||||
},
|
||||
[onClose],
|
||||
);
|
||||
|
||||
const shortDigest = (digest: string) => {
|
||||
// Show first 16 chars of the hash part (after "sha256:")
|
||||
const hash = digest.startsWith("sha256:") ? digest.slice(7) : digest;
|
||||
return hash.slice(0, 16);
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={overlayRef}
|
||||
onClick={handleOverlayClick}
|
||||
className="fixed inset-0 bg-black/50 flex items-center justify-center z-50"
|
||||
>
|
||||
<div className="bg-[var(--bg-secondary)] border border-[var(--border-color)] rounded-lg p-6 w-[28rem] max-h-[80vh] overflow-y-auto shadow-xl">
|
||||
<h2 className="text-lg font-semibold mb-3">Container Image Update</h2>
|
||||
|
||||
<p className="text-sm text-[var(--text-secondary)] mb-4">
|
||||
A newer version of the container image is available in the registry.
|
||||
Re-pull the image in Docker settings to get the latest tools and fixes.
|
||||
</p>
|
||||
|
||||
<div className="space-y-2 mb-4 text-xs bg-[var(--bg-primary)] rounded p-3 border border-[var(--border-color)]">
|
||||
{imageUpdateInfo.local_digest && (
|
||||
<div className="flex justify-between">
|
||||
<span className="text-[var(--text-secondary)]">Local digest</span>
|
||||
<span className="font-mono text-[var(--text-primary)]">
|
||||
{shortDigest(imageUpdateInfo.local_digest)}...
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex justify-between">
|
||||
<span className="text-[var(--text-secondary)]">Remote digest</span>
|
||||
<span className="font-mono text-[var(--accent)]">
|
||||
{shortDigest(imageUpdateInfo.remote_digest)}...
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p className="text-xs text-[var(--text-secondary)] mb-4">
|
||||
Go to Settings > Docker and click "Re-pull Image" to update.
|
||||
Running containers will not be affected until restarted.
|
||||
</p>
|
||||
|
||||
<div className="flex items-center justify-end gap-2">
|
||||
<button
|
||||
onClick={onDismiss}
|
||||
className="px-3 py-1.5 text-xs text-[var(--text-secondary)] hover:text-[var(--text-primary)] transition-colors"
|
||||
>
|
||||
Dismiss
|
||||
</button>
|
||||
<button
|
||||
onClick={onClose}
|
||||
className="px-3 py-1.5 text-xs bg-[var(--bg-tertiary)] border border-[var(--border-color)] rounded hover:bg-[var(--border-color)] transition-colors"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import ApiKeyInput from "./ApiKeyInput";
|
||||
import DockerSettings from "./DockerSettings";
|
||||
import AwsSettings from "./AwsSettings";
|
||||
import { useSettings } from "../../hooks/useSettings";
|
||||
@@ -11,7 +10,7 @@ import type { EnvVar } from "../../lib/types";
|
||||
|
||||
export default function SettingsPanel() {
|
||||
const { appSettings, saveSettings } = useSettings();
|
||||
const { appVersion, checkForUpdates } = useUpdates();
|
||||
const { appVersion, imageUpdateInfo, checkForUpdates, checkImageUpdate } = useUpdates();
|
||||
const [globalInstructions, setGlobalInstructions] = useState(appSettings?.global_claude_instructions ?? "");
|
||||
const [globalEnvVars, setGlobalEnvVars] = useState<EnvVar[]>(appSettings?.global_custom_env_vars ?? []);
|
||||
const [checkingUpdates, setCheckingUpdates] = useState(false);
|
||||
@@ -39,7 +38,7 @@ export default function SettingsPanel() {
|
||||
const handleCheckNow = async () => {
|
||||
setCheckingUpdates(true);
|
||||
try {
|
||||
await checkForUpdates();
|
||||
await Promise.all([checkForUpdates(), checkImageUpdate()]);
|
||||
} finally {
|
||||
setCheckingUpdates(false);
|
||||
}
|
||||
@@ -55,7 +54,6 @@ export default function SettingsPanel() {
|
||||
<h2 className="text-xs font-semibold uppercase text-[var(--text-secondary)]">
|
||||
Settings
|
||||
</h2>
|
||||
<ApiKeyInput />
|
||||
<DockerSettings />
|
||||
<AwsSettings />
|
||||
|
||||
@@ -146,6 +144,12 @@ export default function SettingsPanel() {
|
||||
>
|
||||
{checkingUpdates ? "Checking..." : "Check now"}
|
||||
</button>
|
||||
{imageUpdateInfo && (
|
||||
<div className="flex items-center gap-2 px-3 py-2 text-xs bg-[var(--bg-primary)] border border-[var(--warning,#f59e0b)] rounded">
|
||||
<span className="inline-block w-2 h-2 rounded-full bg-[var(--warning,#f59e0b)]" />
|
||||
<span>A newer container image is available. Re-pull the image in Docker settings above to update.</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user