Files
agent-radar 2ed3415fb7
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
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:17:27 +08:00

81 lines
2.6 KiB
TypeScript

export function objectRecord(value: unknown): Record<string, unknown> | null {
return value && typeof value === "object" && !Array.isArray(value)
? (value as Record<string, unknown>)
: null;
}
export function numberValue(value: unknown): number | null {
if (typeof value === "number" && Number.isFinite(value)) {
return value;
}
if (typeof value === "string" && value.trim() !== "") {
const parsed = Number(value);
return Number.isFinite(parsed) ? parsed : null;
}
return null;
}
export function stringValue(value: unknown): string {
return typeof value === "string" ? value : "";
}
export function useStableEventCallback<Args extends unknown[], Result>(
callback: (...args: Args) => Result
): (...args: Args) => Result {
const callbackRef = useRef(callback);
useLayoutEffect(() => {
callbackRef.current = callback;
}, [callback]);
return useCallback((...args: Args) => callbackRef.current(...args), []);
}
export function useOptionalStableEventCallback<Args extends unknown[], Result>(
callback: ((...args: Args) => Result) | null | undefined
): ((...args: Args) => Result) | undefined {
const callbackRef = useRef(callback);
useLayoutEffect(() => {
callbackRef.current = callback;
}, [callback]);
return useMemo(() => {
if (callback == null) {
return undefined;
}
return (...args: Args) => callbackRef.current?.(...args) as Result;
}, [callback != null]);
}
import type { UiLanguage } from "../../../contexts/settings/domain/agentSettings";
import { resolveAgentGUIConversationDisplayTitle } from "../model/agentGuiProviderIdentity";
import type { AgentGUINodeViewModel } from "../model/agentGuiNodeTypes";
import type { AgentGUIViewLabels } from "../AgentGUINodeView";
import type { WorkspaceFileReferenceCopy } from "@tutti-os/workspace-file-reference/contracts";
export const fallbackWorkspaceFileReferenceCopy: WorkspaceFileReferenceCopy = {
t(key, values) {
return values ? `${key}:${JSON.stringify(values)}` : key;
}
};
export function agentGuiPerfNowMs(): number {
return globalThis.performance?.now?.() ?? Date.now();
}
export function roundAgentGuiPerfMs(value: number): number {
return Math.round(value * 100) / 100;
}
export function conversationPlainTitle(
conversation: Pick<
AgentGUINodeViewModel["rail"]["conversations"][number],
"title" | "titleFallback"
>,
labels: Pick<AgentGUIViewLabels, "untitledConversationTitle">,
uiLanguage: UiLanguage
): string {
void uiLanguage;
return resolveAgentGUIConversationDisplayTitle(
conversation,
labels.untitledConversationTitle
);
}
import { useCallback, useLayoutEffect, useMemo, useRef } from "react";