Clean up types (#9057)

Signed-off-by: Douwe Osinga <douwe@squareup.com>
Co-authored-by: Douwe Osinga <douwe@squareup.com>
This commit is contained in:
Douwe Osinga
2026-05-07 09:38:37 -04:00
committed by GitHub
parent 64f795f82c
commit bced4ea5ec
21 changed files with 123 additions and 262 deletions
@@ -141,11 +141,8 @@ describe("useChat attachments", () => {
{ type: "text", text: "" },
{
type: "image",
source: {
type: "base64",
mediaType: "image/png",
data: "abc123",
},
data: "abc123",
mimeType: "image/png",
},
]);
expect(mockAcpSendMessage).toHaveBeenCalledWith("session-1", " ", {
+3 -6
View File
@@ -94,7 +94,7 @@ function markMessageStopped(sessionId: string, messageId: string) {
completionStatus: "stopped",
},
content: message.content.map((block) =>
block.type === "toolRequest" && block.status === "executing"
block.type === "toolRequest" && block.status === "in_progress"
? { ...block, status: "stopped" }
: block,
),
@@ -215,11 +215,8 @@ export function useChat(
for (const img of images) {
userMessage.content.push({
type: "image",
source: {
type: "base64",
mediaType: img.mimeType,
data: img.base64,
},
data: img.base64,
mimeType: img.mimeType,
});
}
}
@@ -74,13 +74,13 @@ describe("getToolItemStatus", () => {
it("treats response.isError as error", () => {
expect(getToolItemStatus(pair("a", { name: "x" }, { isError: true }))).toBe(
"error",
"failed",
);
});
it("uses request status when no response yet", () => {
expect(getToolItemStatus(pair("a", { status: "executing" }))).toBe(
"executing",
expect(getToolItemStatus(pair("a", { status: "in_progress" }))).toBe(
"in_progress",
);
});
});
@@ -89,17 +89,17 @@ describe("getChainAggregateStatus", () => {
it("prefers error over pending and executing", () => {
expect(
getChainAggregateStatus([
pair("a", { status: "executing" }),
pair("a", { status: "in_progress" }),
pair("b", { name: "x" }, { isError: true }),
pair("c", { status: "pending" }),
]),
).toBe("error");
).toBe("failed");
});
it("prefers stopped over executing/pending when there is no error", () => {
expect(
getChainAggregateStatus([
pair("a", { status: "executing" }),
pair("a", { status: "in_progress" }),
pair("b", { status: "stopped" }),
]),
).toBe("stopped");
@@ -109,9 +109,9 @@ describe("getChainAggregateStatus", () => {
expect(
getChainAggregateStatus([
pair("a", { name: "x" }, {}),
pair("b", { status: "executing" }),
pair("b", { status: "in_progress" }),
]),
).toBe("executing");
).toBe("in_progress");
});
it("returns pending when only pending is present", () => {
@@ -23,7 +23,7 @@ export function getToolItemName(item: ToolChainItem): string {
export function getToolItemStatus(item: ToolChainItem): ToolCallStatus {
if (item.response) {
return item.response.isError ? "error" : "completed";
return item.response.isError ? "failed" : "completed";
}
return item.request?.status ?? "completed";
}
@@ -35,10 +35,10 @@ export function getToolItemStatus(item: ToolChainItem): ToolCallStatus {
export function getChainAggregateStatus(
items: ToolChainItem[],
): ToolCallStatus {
if (items.some((i) => getToolItemStatus(i) === "error")) return "error";
if (items.some((i) => getToolItemStatus(i) === "failed")) return "failed";
if (items.some((i) => getToolItemStatus(i) === "stopped")) return "stopped";
if (items.some((i) => getToolItemStatus(i) === "executing"))
return "executing";
if (items.some((i) => getToolItemStatus(i) === "in_progress"))
return "in_progress";
if (items.some((i) => getToolItemStatus(i) === "pending")) return "pending";
return "completed";
}
@@ -3,8 +3,8 @@ import type { ToolPart } from "@/shared/ui/ai-elements/tool";
export const toolStatusMap: Record<ToolCallStatus, ToolPart["state"]> = {
pending: "input-streaming",
executing: "input-available",
in_progress: "input-available",
completed: "output-available",
error: "output-error",
failed: "output-error",
stopped: "output-denied",
};
@@ -219,10 +219,7 @@ function renderContentBlock(
}
case "image": {
const ic = content as ImageContent;
const src =
ic.source.type === "base64"
? `data:${ic.source.mediaType};base64,${ic.source.data}`
: ic.source.url;
const src = ic.uri ?? `data:${ic.mimeType};base64,${ic.data}`;
return (
<ClickableImage
key={`image-${index}`}
@@ -46,7 +46,7 @@ function useElapsedTime(status: ToolCallStatus, startedAt?: number) {
const [elapsed, setElapsed] = useState(0);
useEffect(() => {
if (status === "executing") {
if (status === "in_progress") {
const origin = startedAt ?? Date.now();
setElapsed(Math.floor((Date.now() - origin) / 1000));
const interval = setInterval(() => {
@@ -282,7 +282,7 @@ export function ToolCallAdapter({
[args, name],
);
const elapsedSeconds =
status === "executing" && elapsed >= 3 ? elapsed : undefined;
status === "in_progress" && elapsed >= 3 ? elapsed : undefined;
const { resolveMarkdownHref, openResolvedPath } = useArtifactPolicyContext();
@@ -17,25 +17,25 @@ import type { ToolCallStatus } from "@/shared/types/messages";
export type { ToolChainItem };
const STEP_BULLET_ICON: Record<
Exclude<ToolCallStatus, "error" | "stopped">,
Exclude<ToolCallStatus, "failed" | "stopped">,
LucideIcon
> = {
pending: CircleIcon,
executing: ClockIcon,
in_progress: ClockIcon,
completed: Check,
};
const STEP_BULLET_CLASS: Record<
Exclude<ToolCallStatus, "error" | "stopped">,
Exclude<ToolCallStatus, "failed" | "stopped">,
string
> = {
pending: "text-muted-foreground/70",
executing: "text-muted-foreground animate-pulse",
in_progress: "text-muted-foreground animate-pulse",
completed: "text-muted-foreground",
};
function ChainStepBullet({ status }: { status: ToolCallStatus }) {
if (status === "error") {
if (status === "failed") {
return (
<span aria-hidden className="size-1.5 shrink-0 rounded-full bg-red-600" />
);
@@ -172,7 +172,7 @@ export function ToolChainCards({ toolItems }: { toolItems: ToolChainItem[] }) {
const aggregateStatus = getChainAggregateStatus(toolItems);
const summary = summarizeToolChainSteps(primaryItems);
const isActiveChain =
aggregateStatus === "executing" || aggregateStatus === "pending";
aggregateStatus === "in_progress" || aggregateStatus === "pending";
// Chains that mount as already-complete (history replay) start collapsed;
// live chains mount mid-execution, stay open while running, and auto-collapse
// once they finish so the chat keeps moving forward.
@@ -349,7 +349,7 @@ describe("MessageBubble", () => {
id: "tool-1",
name: "readFile",
arguments: { path: "/tmp/demo.txt" },
status: "executing",
status: "in_progress",
},
{
type: "toolResponse",
@@ -374,7 +374,7 @@ describe("MessageBubble", () => {
id: "tool-1",
name: "readFile",
arguments: {},
status: "executing",
status: "in_progress",
},
{
type: "toolResponse",
@@ -410,7 +410,7 @@ describe("MessageBubble", () => {
id: "tool-1",
name: "readFile",
arguments: {},
status: "executing",
status: "in_progress",
},
{
type: "toolResponse",
@@ -79,7 +79,7 @@ describe("ToolChainCards", () => {
toolItems={[
pair("Shell · npm test", { completed: true }),
pair("Shell · npm build", {
status: "executing",
status: "in_progress",
completed: false,
}),
]}
@@ -97,7 +97,7 @@ describe("ToolChainCards", () => {
toolItems={[
pair("Edit · src/a.ts"),
pair("Edit · src/b.ts", {
status: "executing",
status: "in_progress",
completed: false,
}),
]}
@@ -129,7 +129,7 @@ describe("ToolChainCards", () => {
it("auto-collapses a live chain once every step has completed", () => {
const a = pair("Edit · src/a.ts");
const bRequest = pair("Edit · src/b.ts", {
status: "executing",
status: "in_progress",
completed: false,
});
const { rerender } = render(<ToolChainCards toolItems={[a, bRequest]} />);
@@ -171,7 +171,7 @@ describe("ToolChainCards", () => {
/>,
);
const wrapper = container.querySelector('[data-role="tool-chain-card"]');
expect(wrapper?.getAttribute("data-status")).toBe("error");
expect(wrapper?.getAttribute("data-status")).toBe("failed");
});
it("renders a step rail row for each child inside a chain", () => {
@@ -181,7 +181,7 @@ describe("ToolChainCards", () => {
pair("Edit · src/a.ts"),
pair("Edit · src/b.ts"),
pair("Edit · src/c.ts", {
status: "executing",
status: "in_progress",
completed: false,
}),
]}
@@ -317,7 +317,7 @@ describe("ToolChainCards", () => {
it("does not surface the chain summary while the chain is still active", () => {
const a = pair("Edit · src/a.ts");
const b = pair("Edit · src/b.ts", {
status: "executing",
status: "in_progress",
completed: false,
});
if (a.request) {
@@ -14,10 +14,7 @@ export async function getProviderConfig(
): Promise<ProviderFieldValue[]> {
const client = await getClient();
const response = await client.goose.GooseProvidersConfigRead({ providerId });
return response.fields.map((field) => ({
...field,
value: field.value ?? null,
}));
return response.fields;
}
export async function saveProviderConfig(