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
201 changes: 165 additions & 36 deletions frontend/src/App.tsx

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion frontend/src/adk/connections.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,10 @@ export function addRuntimeConnection(
appLabels,
currentVersion,
};
const list = [...loadConnections().filter((c) => c.runtimeId !== runtimeId), conn];
const list = loadConnections();
const existingIndex = list.findIndex((item) => item.runtimeId === runtimeId);
if (existingIndex === -1) list.push(conn);
else list[existingIndex] = conn;
persist(list);
registerConnections(list);
return conn;
Expand Down
35 changes: 7 additions & 28 deletions frontend/src/create/AgentBuildCanvas.css
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,12 @@
display: flex;
align-items: center;
justify-content: center;
padding: 10px 132px 10px 72px;
padding: 9px 56px;
border-bottom: 1px solid hsl(var(--border) / 0.75);
}

.abc-group-head > span:first-child {
width: 100%;
min-width: 0;
display: flex;
flex-direction: column;
Expand All @@ -156,25 +157,14 @@
}

.abc-group-head small {
display: -webkit-box;
overflow: hidden;
color: hsl(var(--muted-foreground));
font-size: 9.5px;
text-overflow: ellipsis;
white-space: nowrap;
}

.abc-group-head em {
position: absolute;
top: 12px;
right: 22px;
padding: 3px 7px;
border-radius: 999px;
background: hsl(var(--background) / 0.82);
color: hsl(var(--muted-foreground));
font-size: 9px;
font-style: normal;
font-weight: 600;
white-space: nowrap;
line-height: 1.3;
white-space: normal;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}

.abc-group-add {
Expand Down Expand Up @@ -387,10 +377,6 @@
z-index: 4;
}

.abc-group:has(> .abc-node-delete) .abc-group-head em {
right: 48px;
}

.abc-loop-handle {
left: 50% !important;
opacity: 0;
Expand All @@ -408,13 +394,6 @@
letter-spacing: 0.04em;
}

.abc-node-meta small {
color: hsl(var(--muted-foreground));
font-size: 8.5px;
font-weight: 550;
letter-spacing: 0;
}

.abc-node-copy > strong {
overflow: hidden;
font-size: 13px;
Expand Down
14 changes: 2 additions & 12 deletions frontend/src/create/AgentBuildCanvas.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ function buildCanvasGraph(
agent.name.trim() ||
(path.length === 0 ? "主 Agent" : PATTERN_COPY[type].label),
pattern: type,
description: PATTERN_COPY[type].description,
description: agent.description.trim() || PATTERN_COPY[type].description,
childCount: agent.subAgents.length,
containedIn,
layoutWidth: size.width,
Expand Down Expand Up @@ -620,7 +620,6 @@ function AgentCanvasNode({ data, selected }: NodeProps<CanvasNode>) {
<span className="abc-node-copy">
<span className="abc-node-meta">
<span>{copy.label}</span>
{!!data.childCount && <small>{data.childCount} 个步骤</small>}
</span>
<strong>{data.title}</strong>
<small>{data.description}</small>
Expand Down Expand Up @@ -667,8 +666,6 @@ function AgentGroupNode({ data, selected }: NodeProps<CanvasNode>) {
const sourcePosition = direction === "vertical" ? Position.Bottom : Position.Right;
const loopPosition = direction === "vertical" ? Position.Right : Position.Bottom;
const type = data.pattern ?? "sequential";
const copy = PATTERN_COPY[type];
const childUnit = type === "llm" ? "子 Agent" : "步骤";
const childCount = data.childCount ?? 0;
const addLabel =
type === "llm"
Expand All @@ -684,15 +681,8 @@ function AgentGroupNode({ data, selected }: NodeProps<CanvasNode>) {
<header className="abc-group-head">
<span>
<strong title={data.title}>{data.title}</strong>
<small>
{type === "llm"
? "智能体 · 可根据任务调用框内子 Agent"
: type === "parallel"
? `${copy.label} · 框内步骤同时开始,全部完成后再继续`
: `${copy.label} · ${copy.description}`}
</small>
<small>{data.description}</small>
</span>
<em>{childCount} 个{childUnit}</em>
</header>
{actions &&
data.path !== undefined &&
Expand Down
1 change: 1 addition & 0 deletions frontend/src/create/CustomCreate.css
Original file line number Diff line number Diff line change
Expand Up @@ -4377,6 +4377,7 @@
.cw-detail {
flex: none;
width: 100%;
max-width: none;
height: min(720px, calc(100dvh - 120px));
min-height: 560px;
}
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/create/CustomCreate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3268,7 +3268,7 @@ export function CustomCreate({
<>
<div className="cw-field">
<label className="cw-label">
{isRootAgent ? "Agent 名称" : "步骤名称"}
{isRootAgent ? "Agent 名称" : "名称"}
<span className="cw-req">*</span>
</label>
<input
Expand All @@ -3289,7 +3289,7 @@ export function CustomCreate({
</div>
<div className="cw-field">
<label className="cw-label">
{isRootAgent ? "描述" : "任务说明"}
{isRootAgent ? "描述" : "智能体描述"}
<span className="cw-req">*</span>
</label>
<textarea
Expand Down
23 changes: 23 additions & 0 deletions frontend/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,29 @@ import App from "./App";
import "react-photo-view/dist/react-photo-view.css";
import "./styles.css";

const PRELOAD_RECOVERY_KEY = "veadk.preloadRecoveryAt";

// An open tab can still reference hashed lazy chunks from the previous release.
// Reload once so the browser picks up the current HTML and asset manifest.
window.addEventListener("vite:preloadError", (event) => {
const now = Date.now();
let lastRecoveryAt = 0;
try {
lastRecoveryAt = Number(sessionStorage.getItem(PRELOAD_RECOVERY_KEY) || "0");
} catch {
/* storage unavailable */
}
if (now - lastRecoveryAt < 10_000) return;

event.preventDefault();
try {
sessionStorage.setItem(PRELOAD_RECOVERY_KEY, String(now));
} catch {
/* storage unavailable */
}
window.location.reload();
});

// OAuth popup callback landing. When an OAuth authorize flow (see runOAuthPopup
// in App.tsx) redirects back to our own origin, this same SPA is loaded inside
// the popup. Detect that case *before* the app boots, hand the full callback
Expand Down
70 changes: 70 additions & 0 deletions frontend/src/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -2992,6 +2992,23 @@ body {
min-width: 0;
gap: 6px;
}
.loading-gap-spinner {
display: inline-block;
width: 16px;
height: 16px;
flex: 0 0 16px;
box-sizing: border-box;
border: 1.5px solid #111;
border-right-color: transparent;
border-radius: 50%;
animation: loading-gap-spin 0.7s linear infinite;
}
@keyframes loading-gap-spin {
to { transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce) {
.loading-gap-spinner { animation-duration: 1.4s; }
}
.agent-info-trigger {
display: inline-flex;
width: 30px;
Expand Down Expand Up @@ -3401,6 +3418,44 @@ body {
transition: transform 0.2s ease;
}
.agent-dd-chev.open { transform: rotate(180deg); }
.agent-switch {
display: inline-flex;
min-width: 0;
max-width: 33.333cqw;
align-items: center;
gap: 6px;
padding: 5px 8px;
font-size: 16px;
font-weight: 650;
letter-spacing: -0.01em;
}
.agent-switch-action {
display: inline-flex;
width: 28px;
height: 28px;
flex: 0 0 28px;
align-items: center;
justify-content: center;
padding: 0;
border: 0;
border-radius: 7px;
background: transparent;
color: hsl(var(--muted-foreground));
cursor: pointer;
transition: background 0.12s, color 0.12s;
}
.agent-switch-action:hover {
background: hsl(var(--foreground) / 0.06);
color: hsl(var(--foreground));
}
.agent-switch-action:focus-visible {
outline: 2px solid hsl(var(--ring));
outline-offset: 1px;
}
.agent-switch-action svg {
width: 16px;
height: 16px;
}
@keyframes ddpop { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: translateY(0); } }

/* ---------- account (avatar button + click popover) ---------- */
Expand Down Expand Up @@ -5621,3 +5676,18 @@ a.search-result { text-decoration: none; color: inherit; }
color: #fff;
}
.confirm-btn--danger:hover { background: hsl(var(--destructive) / 0.9); }

.app-toast {
position: fixed;
top: 20px;
left: 50%;
z-index: 120;
padding: 9px 14px;
border-radius: 8px;
background: hsl(var(--foreground));
color: hsl(var(--background));
box-shadow: 0 8px 24px hsl(var(--foreground) / 0.18);
font-size: 13px;
font-weight: 400;
transform: translateX(-50%);
}
Loading
Loading