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
4 changes: 2 additions & 2 deletions frontend/src/adk/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1770,9 +1770,9 @@ export async function deployAgentkitProject(
throw error;
}
if (!res.ok) {
const t = await res.text().catch(() => "");
const detail = await httpErrorMessage(res, "部署失败");
clearController();
throw new Error(t || `部署失败 (${res.status})`);
throw new Error(detail);
}

let final: DeployFrame | null = null;
Expand Down
9 changes: 6 additions & 3 deletions frontend/src/create/CustomCreate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1976,6 +1976,7 @@ function DebugComparisonWorkspace({
<DeploymentErrorMessage
message={variant.error}
className="cw-debug-error-detail"
defaultExpanded
/>
) : starting ? (
<div className="cw-ab-empty cw-ab-starting">
Expand Down Expand Up @@ -2014,6 +2015,7 @@ function DebugComparisonWorkspace({
<DeploymentErrorMessage
message={message.error}
className="cw-debug-msg-error"
defaultExpanded
/>
) : message.blocks && message.blocks.length > 0 ? (
<Blocks blocks={message.blocks} onAction={() => {}} />
Expand Down Expand Up @@ -3273,9 +3275,10 @@ export function CustomCreate({
: undefined}
/>
{buildErr && (
<div className="cw-workspace-alert" role="alert">
{buildErr}
</div>
<DeploymentErrorMessage
className="cw-workspace-alert"
message={buildErr}
/>
)}
<main className="cw-workspace-main" id="cw-workspace-main">
{workspaceMode === "build" && (
Expand Down
5 changes: 4 additions & 1 deletion frontend/src/ui/DeploymentErrorMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ export function DeploymentErrorMessage({
className = "",
onRetry,
retryLabel = "重试部署",
defaultExpanded = true,
}: {
message: string;
className?: string;
onRetry?: () => Promise<void>;
retryLabel?: string;
defaultExpanded?: boolean;
}) {
const [expanded, setExpanded] = useState(false);
const [expanded, setExpanded] = useState(defaultExpanded);
const [copied, setCopied] = useState(false);
const [retrying, setRetrying] = useState(false);

Expand Down Expand Up @@ -41,6 +43,7 @@ export function DeploymentErrorMessage({
className={`deploy-error-message${expanded ? " is-expanded" : ""}${
className ? ` ${className}` : ""
}`}
role="alert"
>
<p className="deploy-error-message-text">{message}</p>
<div className="deploy-error-message-actions">
Expand Down
77 changes: 74 additions & 3 deletions frontend/tests/debugErrorPresentation.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,91 @@ const source = readFileSync(
new URL("../src/create/CustomCreate.tsx", import.meta.url),
"utf8",
);
const errorComponentSource = readFileSync(
new URL("../src/ui/DeploymentErrorMessage.tsx", import.meta.url),
"utf8",
);
const clientSource = readFileSync(
new URL("../src/adk/client.ts", import.meta.url),
"utf8",
);
const projectPreviewSource = readFileSync(
new URL("../src/ui/ProjectPreview.tsx", import.meta.url),
"utf8",
);
const appSource = readFileSync(
new URL("../src/App.tsx", import.meta.url),
"utf8",
);

test("debug errors support full expansion, copying, and footer restart", () => {
test("debug errors show the complete backend detail by default", () => {
assert.match(
source,
/import \{ DeploymentErrorMessage \} from "\.\.\/ui\/DeploymentErrorMessage"/,
);
assert.match(source, /className="cw-debug-error-detail"/);
assert.match(source, /className="cw-debug-msg-error"/);
assert.match(
source,
/message=\{variant\.error\}[\s\S]*?className="cw-debug-error-detail"[\s\S]*?defaultExpanded/,
);
assert.match(
source,
/message=\{message\.error\}[\s\S]*?className="cw-debug-msg-error"[\s\S]*?defaultExpanded/,
);
assert.match(errorComponentSource, /defaultExpanded = true/);
assert.match(errorComponentSource, /useState\(defaultExpanded\)/);
assert.match(errorComponentSource, /role="alert"/);
assert.match(
source,
/className="cw-ab-start cw-ab-footer-start"[\s\S]*?onClick=\{\(\) => onStartVariant\(variant\.id\)\}/,
);
});

test("creation and deployment keep friendly context and the original error", () => {
assert.match(
source,
/<DeploymentErrorMessage[\s\S]*?className="cw-workspace-alert"[\s\S]*?message=\{buildErr\}/,
);
assert.match(
source,
/setBuildErr\(error instanceof Error \? error\.message : String\(error\)\)/,
);
assert.match(
source,
/className="cw-ai-error-message"[\s\S]*?\{aiErrorDialog\}/,
);
assert.match(
clientSource,
/if \(!res\.ok\) \{[\s\S]*?httpErrorMessage\(res, "部署失败"\)[\s\S]*?throw new Error\(detail\)/,
);
assert.match(
projectPreviewSource,
/<DeploymentErrorMessage[\s\S]*?className="pp-error"[\s\S]*?\$\{deployError\}/,
);
assert.match(
appSource,
/<DeploymentErrorMessage[\s\S]*?className="global-deploy-error"[\s\S]*?message=\{task\.message\}/,
);
});

test("generated-agent debug requests preserve backend error details", () => {
assert.match(
clientSource,
/if \(typeof detail === "string"\) return detail/,
);
for (const fallback of [
"创建调试运行失败",
"创建调试会话失败",
"加载调试调用链路失败",
"调试运行失败",
"清理调试运行失败",
]) {
assert.match(
clientSource,
new RegExp(`new Error\\(await httpErrorMessage\\(res, "${fallback}"\\)\\)`),
);
}
});

test("debug test runs are persisted and reclaimed after refresh", () => {
assert.match(source, /const DEBUG_TEST_RUN_STORAGE_KEY = "veadk\.generatedAgentTestRuns"/);
assert.match(source, /window\.sessionStorage\.getItem\(DEBUG_TEST_RUN_STORAGE_KEY\)/);
Expand Down
2 changes: 1 addition & 1 deletion frontend/tests/markdownPromptEditor.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ test("container agents require child agents before debug or publish", () => {
);
assert.match(
createSource,
/\{buildErr && \([\s\S]*?className="cw-workspace-alert" role="alert"[\s\S]*?\{buildErr\}/,
/\{buildErr && \([\s\S]*?<DeploymentErrorMessage[\s\S]*?className="cw-workspace-alert"[\s\S]*?message=\{buildErr\}/,
);
assert.doesNotMatch(
createSource,
Expand Down

Large diffs are not rendered by default.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading