源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s

This commit is contained in:
agent-radar
2026-09-01 20:17:27 +08:00
commit 2ed3415fb7
8018 changed files with 1936476 additions and 0 deletions
@@ -0,0 +1,242 @@
import "@testing-library/jest-dom/vitest";
import { render, screen } from "@testing-library/react";
import { createRef } from "react";
import { describe, expect, it, vi } from "vitest";
import { DESKTOP_WINDOW_TOP_MARGIN } from "../../workspaceDesktop/constants";
import { ComposerFloatingMenuSurface } from "./ComposerFloatingMenuSurface";
function mockRect(rect: {
bottom: number;
height: number;
left: number;
right: number;
top: number;
width: number;
}): DOMRect {
return { ...rect, x: rect.left, y: rect.top, toJSON: () => ({}) } as DOMRect;
}
describe("ComposerFloatingMenuSurface", () => {
it("keeps viewport coordinates when a workbench boundary requests a body portal", () => {
const boundary = document.createElement("div");
boundary.setAttribute("data-slot", "viewport-menu-boundary");
boundary.setAttribute("data-viewport-menu-portal-target", "body");
boundary.setAttribute("data-workbench-window-id", "node-1");
boundary.style.zIndex = "4";
const anchorRef = createRef<HTMLDivElement>();
const anchor = document.createElement("div");
anchor.getBoundingClientRect = vi.fn(() =>
mockRect({
bottom: 560,
height: 30,
left: 312,
right: 588,
top: 530,
width: 276
})
);
boundary.appendChild(anchor);
document.body.appendChild(boundary);
anchorRef.current = anchor;
render(
<ComposerFloatingMenuSurface
anchorRef={anchorRef}
maxHeight={320}
open
placement="fixed-height"
testId="composer-floating-menu-surface-workbench"
>
<div>menu content</div>
</ComposerFloatingMenuSurface>
);
const surface = screen.getByTestId(
"composer-floating-menu-surface-workbench"
);
expect(surface.parentElement).toBe(document.body);
expect(surface.style.left).toBe("312px");
boundary.remove();
});
it("keeps a fixed-height menu clear of the workspace window's traffic-light header even when the anchor sits near the top of the viewport", () => {
const anchorRef = createRef<HTMLDivElement>();
const anchor = document.createElement("div");
anchor.getBoundingClientRect = vi.fn(() =>
mockRect({
bottom: 90,
height: 30,
left: 12,
right: 200,
top: 60,
width: 188
})
);
document.body.appendChild(anchor);
anchorRef.current = anchor;
render(
<ComposerFloatingMenuSurface
anchorRef={anchorRef}
maxHeight={320}
open
placement="fixed-height"
testId="composer-floating-menu-surface"
>
<div>menu content</div>
</ComposerFloatingMenuSurface>
);
const surface = screen.getByTestId("composer-floating-menu-surface");
const top = Number.parseFloat(surface.style.top);
expect(top).toBeGreaterThanOrEqual(DESKTOP_WINDOW_TOP_MARGIN);
anchor.remove();
});
it("clamps the menu against a compact virtual node window's own header, not just the real viewport's 52px margin", () => {
// Simulate a short WorkspaceNodeWindow (well under COMPOSER_MENU_MIN_HEIGHT_PX
// of 280px) parked in the middle of the workspace canvas, far from the real
// screen's top edge. Its own decorative header sits at, say, 400-436px in
// viewport coordinates -- nowhere near the real-window 52px safe area, so the
// 52px floor alone can't protect it.
const nodeRoot = document.createElement("div");
nodeRoot.setAttribute("data-workspace-node-window-root", "true");
nodeRoot.getBoundingClientRect = vi.fn(() =>
mockRect({
bottom: 570,
height: 170,
left: 300,
right: 600,
top: 400,
width: 300
})
);
const header = document.createElement("header");
header.setAttribute("data-workspace-node-window-header", "true");
header.getBoundingClientRect = vi.fn(() =>
mockRect({
bottom: 436,
height: 36,
left: 300,
right: 600,
top: 400,
width: 300
})
);
nodeRoot.appendChild(header);
const anchorRef = createRef<HTMLDivElement>();
const anchor = document.createElement("div");
// Composer sits directly below the header, near the bottom of the short node.
anchor.getBoundingClientRect = vi.fn(() =>
mockRect({
bottom: 560,
height: 30,
left: 312,
right: 588,
top: 530,
width: 276
})
);
nodeRoot.appendChild(anchor);
document.body.appendChild(nodeRoot);
anchorRef.current = anchor;
render(
<ComposerFloatingMenuSurface
anchorRef={anchorRef}
maxHeight={320}
open
placement="fixed-height"
testId="composer-floating-menu-surface-node"
>
<div>menu content</div>
</ComposerFloatingMenuSurface>
);
const surface = screen.getByTestId("composer-floating-menu-surface-node");
// The palette must render inside the node (portal target), not document.body.
expect(surface.parentElement).toBe(nodeRoot);
const top = Number.parseFloat(surface.style.top);
const minHeight = Number.parseFloat(surface.style.minHeight);
// The node's own header bottom edge (436) is a far more restrictive floor
// here than the real-viewport 52px margin -- the fix must honor it.
expect(top).toBeGreaterThanOrEqual(436);
// The forced minimum height must never be so large that top + minHeight
// pushes back above the node's own header, even though the palette's
// "natural" minimum (280px) alone would do exactly that from this anchor.
expect(top + minHeight).toBeLessThanOrEqual(560 - 8 + 0.5);
expect(minHeight).toBeLessThanOrEqual(280);
});
it("still applies the real-viewport 52px floor when the enclosing node's own header is above it (real window case is unaffected)", () => {
const nodeRoot = document.createElement("div");
nodeRoot.setAttribute("data-workspace-node-window-root", "true");
nodeRoot.getBoundingClientRect = vi.fn(() =>
mockRect({
bottom: 400,
height: 400,
left: 0,
right: 400,
top: 0,
width: 400
})
);
const header = document.createElement("header");
header.setAttribute("data-workspace-node-window-header", "true");
// Header bottom edge sits above the real-window 52px safe area (e.g. a
// maximized node docked flush with the canvas top).
header.getBoundingClientRect = vi.fn(() =>
mockRect({
bottom: 36,
height: 36,
left: 0,
right: 400,
top: 0,
width: 400
})
);
nodeRoot.appendChild(header);
const anchorRef = createRef<HTMLDivElement>();
const anchor = document.createElement("div");
anchor.getBoundingClientRect = vi.fn(() =>
mockRect({
bottom: 90,
height: 30,
left: 12,
right: 200,
top: 60,
width: 188
})
);
nodeRoot.appendChild(anchor);
document.body.appendChild(nodeRoot);
anchorRef.current = anchor;
render(
<ComposerFloatingMenuSurface
anchorRef={anchorRef}
maxHeight={320}
open
placement="fixed-height"
testId="composer-floating-menu-surface-real-floor"
>
<div>menu content</div>
</ComposerFloatingMenuSurface>
);
const surface = screen.getByTestId(
"composer-floating-menu-surface-real-floor"
);
const top = Number.parseFloat(surface.style.top);
expect(top).toBeGreaterThanOrEqual(DESKTOP_WINDOW_TOP_MARGIN);
});
});
@@ -0,0 +1,381 @@
import {
forwardRef,
useCallback,
useEffect,
useLayoutEffect,
useMemo,
useRef,
useState,
type CSSProperties,
type RefObject
} from "react";
import { createPortal } from "react-dom";
import { cn } from "../../../app/renderer/lib/utils";
import { DESKTOP_WINDOW_TOP_MARGIN } from "../../workspaceDesktop/constants";
import { resolveComposerPortalTarget } from "../composer/composerPortalTarget";
const COMPOSER_MENU_GAP_PX = 8;
const COMPOSER_MENU_VIEWPORT_PADDING_PX = 8;
// Keep the menu clear of the workspace window's own header, where the macOS
// traffic lights live (see `workspaceWindowHeaderHeightPx` in
// apps/desktop/src/main/windows/workspaceWindow.ts and the matching
// `DESKTOP_WINDOW_TOP_MARGIN` reserve used to place node windows below that
// header). Anchors near the top of the canvas otherwise collapse this menu's
// top offset down to the bare viewport padding, landing it on top of the
// traffic lights and drag region.
const COMPOSER_MENU_TOP_SAFE_AREA_PX = DESKTOP_WINDOW_TOP_MARGIN;
const COMPOSER_MENU_MIN_HEIGHT_PX = 280;
export interface ComposerAnchoredMenuFrame {
bottom: number;
height: number;
left: number;
minHeight: number;
portalTarget: Element;
top: number;
width: number;
zIndex: number | string;
}
export interface UseComposerAnchoredMenuFrameOptions {
anchorRef: RefObject<HTMLElement | null>;
maxHeight: number;
open: boolean;
}
export type ComposerFloatingMenuPlacement = "fixed-height" | "dynamic-above";
export interface ComposerFloatingMenuSurfaceProps {
anchorRef: RefObject<HTMLElement | null>;
children: React.ReactNode;
className?: string;
contentClassName?: string;
dismissBoundaryRef?: RefObject<HTMLElement | null>;
maxHeight: number;
onDismiss?: () => void;
open: boolean;
placement: ComposerFloatingMenuPlacement;
surfaceRef?: RefObject<HTMLDivElement | null>;
testId: string;
}
const COMPOSER_MENU_WINDOW_FRAME_SELECTOR =
"[data-workbench-window-id], [data-workspace-node-window-root='true']";
function resolveComposerMenuWindowFrame(anchor: HTMLElement): Element | null {
return anchor.closest(COMPOSER_MENU_WINDOW_FRAME_SELECTOR);
}
function resolveComposerMenuZIndex(anchor: HTMLElement): number | string {
let current: HTMLElement | null = anchor;
while (current) {
if (current.matches(COMPOSER_MENU_WINDOW_FRAME_SELECTOR)) {
const windowZIndex = Number.parseInt(
window.getComputedStyle(current).zIndex,
10
);
if (Number.isFinite(windowZIndex)) {
return windowZIndex + 1;
}
}
current = current.parentElement;
}
return "var(--z-popover)";
}
// Mirrors the real workspace window's `COMPOSER_MENU_TOP_SAFE_AREA_PX` floor,
// but scoped to a virtual node window on the workspace canvas
// (`WorkspaceNodeWindow.tsx`). Each node draws its own decorative header with
// fake traffic-light buttons (`data-workspace-node-window-header="true"`);
// clamping only against the real viewport's 52px chrome ignores that a
// compact node's header can sit well below (or, rarer, above) that mark.
// Falls back to the enclosing frame's own top edge when no explicit header
// is found, so the menu never renders above the window/node it lives in.
function resolveComposerMenuTopSafeArea(anchor: HTMLElement): number {
const windowFrame = resolveComposerMenuWindowFrame(anchor);
if (!windowFrame) {
return COMPOSER_MENU_TOP_SAFE_AREA_PX;
}
const header = windowFrame.querySelector(
'[data-workspace-node-window-header="true"]'
);
const localFloor = (header ?? windowFrame).getBoundingClientRect()[
header ? "bottom" : "top"
];
return Math.max(COMPOSER_MENU_TOP_SAFE_AREA_PX, localFloor);
}
function computeComposerAnchoredMenuFrame(
anchor: HTMLElement,
maxHeight: number
): ComposerAnchoredMenuFrame {
const rect = anchor.getBoundingClientRect();
const viewportWidth = window.innerWidth;
const viewportHeight = window.innerHeight;
const width = Math.max(
0,
Math.min(rect.width, viewportWidth - COMPOSER_MENU_VIEWPORT_PADDING_PX * 2)
);
const left = Math.max(
COMPOSER_MENU_VIEWPORT_PADDING_PX,
Math.min(
rect.left,
viewportWidth - COMPOSER_MENU_VIEWPORT_PADDING_PX - width
)
);
const topSafeArea = resolveComposerMenuTopSafeArea(anchor);
const availableAbove = rect.top - COMPOSER_MENU_GAP_PX - topSafeArea;
// Never demand more minimum height than the enclosing window/node actually
// has room for above its own safe area — otherwise a compact node (as
// short as `DESKTOP_WINDOW_MIN_HEIGHT`) is forced to render the menu past
// its own header, regardless of the safe-area clamp below.
const minHeight = Math.max(
0,
Math.min(COMPOSER_MENU_MIN_HEIGHT_PX, availableAbove)
);
const height =
availableAbove >= maxHeight
? maxHeight
: Math.max(minHeight, Math.min(maxHeight, availableAbove));
return {
bottom: Math.max(
COMPOSER_MENU_VIEWPORT_PADDING_PX,
viewportHeight - rect.top + COMPOSER_MENU_GAP_PX
),
height,
left,
minHeight,
portalTarget: resolveComposerPortalTarget(anchor),
top: Math.max(
topSafeArea,
Math.min(
rect.top - COMPOSER_MENU_GAP_PX - height,
viewportHeight - COMPOSER_MENU_VIEWPORT_PADDING_PX - height
)
),
width,
zIndex: resolveComposerMenuZIndex(anchor)
};
}
function sameComposerAnchoredMenuFrame(
left: ComposerAnchoredMenuFrame | null,
right: ComposerAnchoredMenuFrame
): boolean {
return (
left !== null &&
left.portalTarget === right.portalTarget &&
left.zIndex === right.zIndex &&
Math.abs(left.left - right.left) < 0.5 &&
Math.abs(left.top - right.top) < 0.5 &&
Math.abs(left.bottom - right.bottom) < 0.5 &&
Math.abs(left.width - right.width) < 0.5 &&
Math.abs(left.height - right.height) < 0.5 &&
Math.abs(left.minHeight - right.minHeight) < 0.5
);
}
export function useComposerAnchoredMenuFrame({
anchorRef,
maxHeight,
open
}: UseComposerAnchoredMenuFrameOptions): ComposerAnchoredMenuFrame | null {
const [frame, setFrame] = useState<ComposerAnchoredMenuFrame | null>(null);
const syncFrame = useCallback((): void => {
const anchor = anchorRef.current;
if (!anchor || typeof window === "undefined") {
setFrame(null);
return;
}
const nextFrame = computeComposerAnchoredMenuFrame(anchor, maxHeight);
setFrame((previous) =>
sameComposerAnchoredMenuFrame(previous, nextFrame) ? previous : nextFrame
);
}, [anchorRef, maxHeight]);
useLayoutEffect(() => {
if (!open) {
setFrame(null);
return;
}
syncFrame();
const anchor = anchorRef.current;
const resizeObserver =
typeof ResizeObserver === "undefined"
? null
: new ResizeObserver(syncFrame);
if (anchor) {
resizeObserver?.observe(anchor);
}
window.addEventListener("resize", syncFrame);
window.addEventListener("scroll", syncFrame, {
capture: true,
passive: true
});
return () => {
resizeObserver?.disconnect();
window.removeEventListener("resize", syncFrame);
window.removeEventListener("scroll", syncFrame, true);
};
}, [anchorRef, open, syncFrame]);
return frame;
}
function assignRef<T>(ref: RefObject<T | null> | undefined, value: T | null) {
if (ref) {
ref.current = value;
}
}
export const ComposerFloatingMenuSurface = forwardRef<
HTMLDivElement,
ComposerFloatingMenuSurfaceProps
>(function ComposerFloatingMenuSurface(
{
anchorRef,
children,
className,
contentClassName,
dismissBoundaryRef,
maxHeight,
onDismiss,
open,
placement,
surfaceRef,
testId
},
forwardedRef
): React.JSX.Element | null {
const localSurfaceRef = useRef<HTMLDivElement | null>(null);
const frame = useComposerAnchoredMenuFrame({
anchorRef,
maxHeight,
open
});
const setSurfaceRef = useCallback(
(node: HTMLDivElement | null): void => {
localSurfaceRef.current = node;
assignRef(surfaceRef, node);
if (typeof forwardedRef === "function") {
forwardedRef(node);
} else if (forwardedRef) {
forwardedRef.current = node;
}
},
[forwardedRef, surfaceRef]
);
useEffect(() => {
if (!open || !onDismiss) {
return;
}
const isInsideMenu = (target: EventTarget | null): boolean => {
if (!(target instanceof Node)) {
return false;
}
const boundaryRef = dismissBoundaryRef ?? anchorRef;
return Boolean(
boundaryRef.current?.contains(target) ||
localSurfaceRef.current?.contains(target)
);
};
const handleKeyDown = (event: KeyboardEvent): void => {
if (event.key !== "Escape" || event.defaultPrevented) {
return;
}
event.preventDefault();
onDismiss();
};
const handlePointerDown = (event: PointerEvent): void => {
if (isInsideMenu(event.target)) {
return;
}
onDismiss();
};
const handleFocusIn = (event: FocusEvent): void => {
if (isInsideMenu(event.target)) {
return;
}
onDismiss();
};
document.addEventListener("keydown", handleKeyDown);
document.addEventListener("pointerdown", handlePointerDown, true);
document.addEventListener("focusin", handleFocusIn, true);
window.addEventListener("blur", onDismiss);
return () => {
document.removeEventListener("keydown", handleKeyDown);
document.removeEventListener("pointerdown", handlePointerDown, true);
document.removeEventListener("focusin", handleFocusIn, true);
window.removeEventListener("blur", onDismiss);
};
}, [anchorRef, dismissBoundaryRef, onDismiss, open]);
const style = useMemo<CSSProperties>(() => {
const baseStyle: CSSProperties = {
position: "fixed",
left: `${frame?.left ?? 0}px`,
width: `${frame?.width ?? 0}px`,
maxWidth: `${frame?.width ?? 0}px`,
overflow: "hidden",
zIndex: frame?.zIndex ?? "var(--z-popover)"
};
if (placement === "fixed-height") {
return {
...baseStyle,
top: `${frame?.top ?? 0}px`,
minHeight: `${frame?.minHeight ?? COMPOSER_MENU_MIN_HEIGHT_PX}px`,
height: `${frame?.height ?? maxHeight}px`,
maxHeight: `${maxHeight}px`
};
}
return {
...baseStyle,
bottom: `${frame?.bottom ?? 0}px`,
maxHeight: `${frame?.height ?? maxHeight}px`
};
}, [frame, maxHeight, placement]);
if (!open || typeof document === "undefined" || !document.body) {
return null;
}
const portalTarget =
frame?.portalTarget ??
(anchorRef.current
? resolveComposerPortalTarget(anchorRef.current)
: document.body);
return createPortal(
<div
data-testid={testId}
ref={setSurfaceRef}
className={cn(
"nodrag isolate rounded-[12px] border border-hairline bg-background-fronted p-[4px] text-foreground shadow-[var(--tsh-shell-shadow)] [-webkit-app-region:no-drag]",
"overflow-hidden",
className
)}
style={style}
>
{contentClassName ? (
<div className={contentClassName}>{children}</div>
) : (
children
)}
</div>,
portalTarget
);
});