Phase 11: remote UX & network attach (0.11.0)
- Live remote-stack logs over a WebSocket proxied through the central app to
the agent (/ws/agent-logs/{agent}/{stack}); agent gains a WS log endpoint.
- Deploy to a remote host from the UI: host selector in the New Stack editor
and template dialog; templates instantiate onto an agent via the proxy.
- Network attach/detach: expandable inspect view per network with
connect/disconnect + container picker; GET /{id}/containers, POST connect/disconnect.
- Remove dead pages/Placeholder.tsx.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
ec7e3e706f
commit
1931500c24
@@ -14,6 +14,7 @@ import {
|
||||
import { toast } from "sonner";
|
||||
import { Badge, Button, Card, Spinner, StatusDot } from "@/components/ui";
|
||||
import { HostDot } from "@/components/hosts/HostDot";
|
||||
import { LogViewer } from "@/components/stacks/LogViewer";
|
||||
import { BackupButton } from "@/components/stacks/BackupRestore";
|
||||
import { agentsApi } from "@/api/agents";
|
||||
import { apiErrorMessage } from "@/api/client";
|
||||
@@ -116,7 +117,11 @@ export function RemoteStackDetail() {
|
||||
|
||||
<div className="flex-1 overflow-hidden">
|
||||
{tab === "Overview" && <Overview containers={data.containers} />}
|
||||
{tab === "Logs" && <RemoteLogs agentId={aid} stackId={id} />}
|
||||
{tab === "Logs" && (
|
||||
<Card className="h-full overflow-hidden">
|
||||
<LogViewer stackId={id} agentId={aid} />
|
||||
</Card>
|
||||
)}
|
||||
{tab === "Environment" && (
|
||||
<RemoteEditor
|
||||
agentId={aid}
|
||||
@@ -169,30 +174,6 @@ function Overview({ containers }: { containers: any[] }) {
|
||||
);
|
||||
}
|
||||
|
||||
function RemoteLogs({ agentId, stackId }: { agentId: number; stackId: string }) {
|
||||
const { data, isLoading, refetch, isFetching } = useQuery({
|
||||
queryKey: ["agent-logs", agentId, stackId],
|
||||
queryFn: () => agentsApi.logs(agentId, stackId, 400),
|
||||
refetchInterval: 5000,
|
||||
});
|
||||
return (
|
||||
<Card className="flex h-full flex-col overflow-hidden">
|
||||
<div className="mb-2 flex justify-end">
|
||||
<Button variant="ghost" onClick={() => refetch()} loading={isFetching}>
|
||||
Refresh
|
||||
</Button>
|
||||
</div>
|
||||
{isLoading ? (
|
||||
<Spinner />
|
||||
) : (
|
||||
<pre className="flex-1 overflow-auto whitespace-pre-wrap break-all bg-slate-950 p-3 font-mono text-xs text-slate-100">
|
||||
{data?.logs || "No logs."}
|
||||
</pre>
|
||||
)}
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
function RemoteEditor({
|
||||
agentId,
|
||||
stackId,
|
||||
|
||||
Reference in New Issue
Block a user