fix(ci): restore workspace validation

This commit is contained in:
777genius 2026-05-25 00:14:43 +03:00
parent 50f876f863
commit 1bc8ccc07a
29 changed files with 63 additions and 39 deletions

View file

@ -1,6 +1,7 @@
import type { JSX } from 'react';
import { useAppTranslation } from '@features/localization/renderer';
import type { JSX } from 'react';
/**
* Empty state for ChatHistory when no conversation exists.
*/

View file

@ -5,6 +5,7 @@
import React, { useMemo } from 'react';
import { useAppTranslation } from '@features/localization/renderer';
import { CLAUDE_MD_GROUP_CONFIG, CLAUDE_MD_GROUP_ORDER } from '../types';
import { ClaudeMdSubSection } from './ClaudeMdSection';

View file

@ -5,6 +5,7 @@
import React from 'react';
import { useAppTranslation } from '@features/localization/renderer';
import { MentionedFileItem } from '../items/MentionedFileItem';
import { CollapsibleSection } from './CollapsibleSection';

View file

@ -5,6 +5,7 @@
import React from 'react';
import { useAppTranslation } from '@features/localization/renderer';
import { TaskCoordinationItem } from '../items/TaskCoordinationItem';
import { CollapsibleSection } from './CollapsibleSection';

View file

@ -5,6 +5,7 @@
import React from 'react';
import { useAppTranslation } from '@features/localization/renderer';
import { ThinkingTextItem } from '../items/ThinkingTextItem';
import { CollapsibleSection } from './CollapsibleSection';

View file

@ -5,6 +5,7 @@
import React from 'react';
import { useAppTranslation } from '@features/localization/renderer';
import { ToolOutputItem } from '../items/ToolOutputItem';
import { CollapsibleSection } from './CollapsibleSection';

View file

@ -5,6 +5,7 @@
import React from 'react';
import { useAppTranslation } from '@features/localization/renderer';
import { UserMessageItem } from '../items/UserMessageItem';
import { CollapsibleSection } from './CollapsibleSection';

View file

@ -5,6 +5,7 @@
import React from 'react';
import { useAppTranslation } from '@features/localization/renderer';
import { formatTokens } from '../utils/formatting';
import type { ToolTokenBreakdown } from '@renderer/types/contextInjection';

View file

@ -1,5 +1,6 @@
import React, { useCallback, useMemo, useState } from 'react';
import { useAppTranslation } from '@features/localization/renderer';
import {
CARD_BG,
CARD_BORDER_STYLE,
@ -12,7 +13,6 @@ import {
COLOR_TEXT_MUTED,
COLOR_TEXT_SECONDARY,
} from '@renderer/constants/cssVariables';
import { useAppTranslation } from '@features/localization/renderer';
import {
getSubagentTypeColorSet,
getTeamColorSet,

View file

@ -7,6 +7,7 @@
import React, { memo } from 'react';
import { useAppTranslation } from '@features/localization/renderer';
import { StatusDot } from '../BaseItem';
import { renderOutput } from './renderHelpers';

View file

@ -228,12 +228,12 @@ class ErrorBoundaryInner extends Component<Props, State> {
}
}
export function ErrorBoundary(props: Omit<Props, 'labels'>): React.JSX.Element {
export const ErrorBoundary = ({ children, fallback }: Omit<Props, 'labels'>): React.JSX.Element => {
const { t } = useAppTranslation('common');
return (
<ErrorBoundaryInner
{...props}
fallback={fallback}
labels={{
title: t('errorBoundary.title'),
description: t('errorBoundary.description'),
@ -245,6 +245,8 @@ export function ErrorBoundary(props: Omit<Props, 'labels'>): React.JSX.Element {
reloadApp: t('errorBoundary.reloadApp'),
diagnosticsNotice: t('errorBoundary.diagnosticsNotice'),
}}
/>
>
{children}
</ErrorBoundaryInner>
);
}
};

View file

@ -2,8 +2,8 @@
* PluginCard grid card for a single plugin in the catalog.
*/
import { Badge } from '@renderer/components/ui/badge';
import { useAppTranslation } from '@features/localization/renderer';
import { Badge } from '@renderer/components/ui/badge';
import { useStore } from '@renderer/store';
import {
getCapabilityLabel,

View file

@ -1,5 +1,5 @@
import { DiffViewer } from '@renderer/components/chat/viewers/DiffViewer';
import { useAppTranslation } from '@features/localization/renderer';
import { DiffViewer } from '@renderer/components/chat/viewers/DiffViewer';
import { Badge } from '@renderer/components/ui/badge';
import { Button } from '@renderer/components/ui/button';
import {

View file

@ -40,6 +40,7 @@ const authMethodOptionValues: readonly SshAuthMethod[] = [
const authMethodLabelKeys = {
agent: 'workspaceProfiles.authMethods.agent',
auto: 'workspaceProfiles.authMethods.auto',
// eslint-disable-next-line sonarjs/no-hardcoded-passwords -- SSH auth method label key, not a credential.
password: 'workspaceProfiles.authMethods.password',
privateKey: 'workspaceProfiles.authMethods.privateKey',
} as const satisfies Record<SshAuthMethod, string>;
@ -436,7 +437,6 @@ export const ConnectionSection = (): React.JSX.Element => {
</div>
<div>
{/* eslint-disable-next-line jsx-a11y/label-has-associated-control -- SettingsSelect is a custom dropdown without a native control */}
<label className="mb-1 block text-xs" style={{ color: 'var(--color-text-muted)' }}>
{t('connection.form.authentication')}
</label>

View file

@ -40,6 +40,7 @@ const authMethodOptionValues: readonly SshAuthMethod[] = [
const authMethodLabelKeys = {
agent: 'workspaceProfiles.authMethods.agent',
auto: 'workspaceProfiles.authMethods.auto',
// eslint-disable-next-line sonarjs/no-hardcoded-passwords -- SSH auth method label key, not a credential.
password: 'workspaceProfiles.authMethods.password',
privateKey: 'workspaceProfiles.authMethods.privateKey',
} as const satisfies Record<SshAuthMethod, string>;
@ -261,7 +262,6 @@ export const WorkspaceSection = (): React.JSX.Element => {
</div>
<div>
{/* eslint-disable-next-line jsx-a11y/label-has-associated-control -- SettingsSelect is a custom dropdown without a native control */}
<label className="mb-1 block text-xs" style={{ color: 'var(--color-text-muted)' }}>
{t('workspaceProfiles.form.authentication')}
</label>

View file

@ -1,3 +1,4 @@
import { useAppTranslation } from '@features/localization/renderer';
import {
ContextMenu,
ContextMenuContent,
@ -5,7 +6,6 @@ import {
ContextMenuSeparator,
ContextMenuTrigger,
} from '@renderer/components/ui/context-menu';
import { useAppTranslation } from '@features/localization/renderer';
import { Archive, ArchiveRestore, Mail, Pencil, Pin, PinOff, Trash2 } from 'lucide-react';
import type { GlobalTask } from '@shared/types';

View file

@ -1,6 +1,5 @@
import React, { useEffect, useRef } from 'react';
import { useAppTranslation } from '@features/localization/renderer';
import { closeBrackets, closeBracketsKeymap } from '@codemirror/autocomplete';
import { defaultKeymap, history, historyKeymap } from '@codemirror/commands';
import { json } from '@codemirror/lang-json';
@ -20,6 +19,7 @@ import {
keymap,
lineNumbers,
} from '@codemirror/view';
import { useAppTranslation } from '@features/localization/renderer';
import { Button } from '@renderer/components/ui/button';
import { baseEditorTheme, jsonLinter } from '@renderer/utils/codemirrorTheme';
import { X } from 'lucide-react';

View file

@ -1,12 +1,12 @@
import React from 'react';
import { useAppTranslation } from '@features/localization/renderer';
import { api } from '@renderer/api';
import { ProviderBrandLogo } from '@renderer/components/common/ProviderBrandLogo';
import { Button } from '@renderer/components/ui/button';
import { Combobox } from '@renderer/components/ui/combobox';
import { Input } from '@renderer/components/ui/input';
import { Label } from '@renderer/components/ui/label';
import { useAppTranslation } from '@features/localization/renderer';
import { cn } from '@renderer/lib/utils';
import { Check, FolderOpen, FolderX } from 'lucide-react';

View file

@ -1,6 +1,6 @@
import { useAppTranslation } from '@features/localization/renderer';
import { MemberBadge } from '@renderer/components/team/MemberBadge';
import { Tooltip, TooltipContent, TooltipTrigger } from '@renderer/components/ui/tooltip';
import { useAppTranslation } from '@features/localization/renderer';
import { cn } from '@renderer/lib/utils';
import {
REVIEW_STATE_DISPLAY,

View file

@ -1,5 +1,6 @@
import { useCallback, useEffect, useMemo, useState } from 'react';
import { useAppTranslation } from '@features/localization/renderer';
import { MarkdownViewer } from '@renderer/components/chat/viewers/MarkdownViewer';
import { CopyButton } from '@renderer/components/common/CopyButton';
import { AnimatedHeightReveal } from '@renderer/components/team/activity/AnimatedHeightReveal';
@ -10,7 +11,6 @@ import { MemberBadge } from '@renderer/components/team/MemberBadge';
import { ExpandableContent } from '@renderer/components/ui/ExpandableContent';
import { MentionableTextarea } from '@renderer/components/ui/MentionableTextarea';
import { Tooltip, TooltipContent, TooltipTrigger } from '@renderer/components/ui/tooltip';
import { useAppTranslation } from '@features/localization/renderer';
import { useChipDraftPersistence } from '@renderer/hooks/useChipDraftPersistence';
import { useDraftPersistence } from '@renderer/hooks/useDraftPersistence';
import { useMarkCommentsRead } from '@renderer/hooks/useMarkCommentsRead';

View file

@ -7,7 +7,6 @@
import { useCallback, useMemo, useState } from 'react';
import { useAppTranslation } from '@features/localization/renderer';
import {
closestCenter,
DndContext,
@ -18,6 +17,7 @@ import {
} from '@dnd-kit/core';
import { horizontalListSortingStrategy, SortableContext, useSortable } from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';
import { useAppTranslation } from '@features/localization/renderer';
import { Tooltip, TooltipContent, TooltipTrigger } from '@renderer/components/ui/tooltip';
import { useStore } from '@renderer/store';
import { X } from 'lucide-react';

View file

@ -1,10 +1,10 @@
import { useAppTranslation } from '@features/localization/renderer';
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from '@renderer/components/ui/tooltip';
import { useAppTranslation } from '@features/localization/renderer';
import { cn } from '@renderer/lib/utils';
import type { AgentActionMode } from '@shared/types';

View file

@ -1,5 +1,6 @@
import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
import { useAppTranslation } from '@features/localization/renderer';
import { api } from '@renderer/api';
import { AttachmentPreviewList } from '@renderer/components/team/attachments/AttachmentPreviewList';
import { DropZoneOverlay } from '@renderer/components/team/attachments/DropZoneOverlay';
@ -10,7 +11,6 @@ import { MentionableTextarea } from '@renderer/components/ui/MentionableTextarea
import { Popover, PopoverContent, PopoverTrigger } from '@renderer/components/ui/popover';
import { Tooltip, TooltipContent, TooltipTrigger } from '@renderer/components/ui/tooltip';
import { getTeamColorSet } from '@renderer/constants/teamColors';
import { useAppTranslation } from '@features/localization/renderer';
import { useComposerDraft } from '@renderer/hooks/useComposerDraft';
import { useTaskSuggestions } from '@renderer/hooks/useTaskSuggestions';
import { useTeamSuggestions } from '@renderer/hooks/useTeamSuggestions';

View file

@ -46,7 +46,7 @@ class DiffErrorBoundaryInner extends Component<
render(): JSX.Element {
if (!this.state.hasError) {
return <>{this.props.children}</>;
return this.props.children as JSX.Element;
}
const { filePath, oldString, newString, onRetry, t } = this.props;
@ -116,7 +116,18 @@ class DiffErrorBoundaryInner extends Component<
}
}
export function DiffErrorBoundary(props: DiffErrorBoundaryProps): JSX.Element {
export const DiffErrorBoundary = (props: DiffErrorBoundaryProps): JSX.Element => {
const { t } = useAppTranslation('team');
return <DiffErrorBoundaryInner {...props} t={t} />;
}
const { children, filePath, newString, oldString, onRetry } = props;
return (
<DiffErrorBoundaryInner
filePath={filePath}
newString={newString}
oldString={oldString}
onRetry={onRetry}
t={t}
>
{children}
</DiffErrorBoundaryInner>
);
};

View file

@ -1,6 +1,7 @@
import React, { useCallback, useEffect, useRef } from 'react';
import { useAppTranslation } from '@features/localization/renderer';
import { CodeMirrorDiffView } from './CodeMirrorDiffView';
import { DiffErrorBoundary } from './DiffErrorBoundary';
import { FileSectionPlaceholder } from './FileSectionPlaceholder';

View file

@ -1,7 +1,7 @@
import React from 'react';
import { Tooltip, TooltipContent, TooltipTrigger } from '@renderer/components/ui/tooltip';
import { useAppTranslation } from '@features/localization/renderer';
import { Tooltip, TooltipContent, TooltipTrigger } from '@renderer/components/ui/tooltip';
import { cn } from '@renderer/lib/utils';
import { Check, Eye, EyeOff, GitMerge, Loader2, Pencil, Undo2, X } from 'lucide-react';

View file

@ -51,12 +51,11 @@ type PendingDiagnosticBucket =
| 'noRuntime';
type PendingDiagnosticNameGroups = Record<PendingDiagnosticBucket, string[]>;
type TeamProvisioningTranslator = unknown;
const MAX_PENDING_DIAGNOSTIC_NAMES = 4;
function translateProvisioning(
t: TeamProvisioningTranslator | undefined,
t: unknown,
key: string,
fallback: string,
options?: Record<string, unknown>
@ -199,7 +198,7 @@ function countPermissionBlockedMembers(params: {
return count;
}
function buildAwaitingPermissionPhrase(count: number, t?: TeamProvisioningTranslator): string {
function buildAwaitingPermissionPhrase(count: number, t?: unknown): string {
return translateProvisioning(
t,
'provisioning.presentation.awaitingPermission',
@ -210,7 +209,7 @@ function buildAwaitingPermissionPhrase(count: number, t?: TeamProvisioningTransl
);
}
function formatMemberNameList(names: readonly string[], t?: TeamProvisioningTranslator): string {
function formatMemberNameList(names: readonly string[], t?: unknown): string {
const listedNames = names.slice(0, MAX_PENDING_DIAGNOSTIC_NAMES).join(', ');
const remainingCount = names.length - Math.min(names.length, MAX_PENDING_DIAGNOSTIC_NAMES);
return remainingCount > 0
@ -346,7 +345,7 @@ function buildOpenCodeSecondaryWaitPhrase(params: {
memberSpawnStatuses: MemberSpawnStatusCollection;
memberSpawnSnapshotStatuses?: MemberSpawnStatusesSnapshot['statuses'];
memberSpawnSnapshotUpdatedAt?: string;
t?: TeamProvisioningTranslator;
t?: unknown;
}): string | null {
const pendingNames = getPendingSpawnNames({
memberSpawnStatuses: params.memberSpawnStatuses,
@ -399,7 +398,7 @@ function buildOpenCodeSecondaryWaitPhrase(params: {
function formatNamedPendingDiagnostic(
label: string,
names: readonly string[],
t?: TeamProvisioningTranslator
t?: unknown
): string | null {
if (names.length === 0) {
return null;
@ -415,7 +414,7 @@ function formatNamedPendingDiagnostic(
function formatCountPendingDiagnostic(
count: number | undefined,
label: string,
t?: TeamProvisioningTranslator
t?: unknown
): string | null {
return count && count > 0
? translateProvisioning(
@ -443,7 +442,7 @@ function buildPendingDiagnosticPhrase({
memberSpawnSnapshotStatuses?: MemberSpawnStatusesSnapshot['statuses'];
memberSpawnSnapshotUpdatedAt?: string;
fallbackJoiningPhrase: string;
t?: TeamProvisioningTranslator;
t?: unknown;
}): string {
const groups = getPendingDiagnosticNameGroups({
memberSpawnStatuses,
@ -722,7 +721,7 @@ function normalizeFailureReason(reason: string): string {
function buildFailedSpawnPanelMessage(
failedSpawnDetails: readonly FailedSpawnDetail[],
t?: TeamProvisioningTranslator
t?: unknown
): string | null {
if (failedSpawnDetails.length === 0) {
return null;
@ -746,7 +745,7 @@ function buildFailedSpawnPanelMessage(
function buildFailedSpawnCompactDetail(
failedSpawnDetails: readonly FailedSpawnDetail[],
t?: TeamProvisioningTranslator
t?: unknown
): string | null {
if (failedSpawnDetails.length === 0) {
return null;
@ -770,7 +769,7 @@ function buildFailedSpawnCompactDetail(
function buildGenericFailedSpawnPanelMessage(
failedSpawnCount: number,
expectedTeammateCount: number,
t?: TeamProvisioningTranslator
t?: unknown
): string | null {
if (failedSpawnCount <= 0) {
return null;
@ -793,7 +792,7 @@ function buildGenericFailedSpawnPanelMessage(
function buildSkippedSpawnPanelMessage(
skippedSpawnDetails: readonly SkippedSpawnDetail[],
t?: TeamProvisioningTranslator
t?: unknown
): string | null {
if (skippedSpawnDetails.length === 0) {
return null;
@ -831,7 +830,7 @@ function buildSkippedSpawnPanelMessage(
function buildSkippedSpawnCompactDetail(
skippedSpawnDetails: readonly SkippedSpawnDetail[],
t?: TeamProvisioningTranslator
t?: unknown
): string | null {
if (skippedSpawnDetails.length === 0) {
return null;
@ -904,7 +903,7 @@ export function buildTeamProvisioningPresentation({
> & {
statuses?: MemberSpawnStatusesSnapshot['statuses'];
};
t?: TeamProvisioningTranslator;
t?: unknown;
}): TeamProvisioningPresentation | null {
if (!progress) {
return null;

View file

@ -3075,13 +3075,13 @@ describe('Team agent launch matrix safe e2e', () => {
expect(runtimeSnapshot.members.alice).toMatchObject({
providerId: 'anthropic',
laneKind: 'primary',
alive: false,
alive: true,
runtimeModel: 'haiku',
});
expect(runtimeSnapshot.members.bob).toMatchObject({
providerId: 'anthropic',
laneKind: 'primary',
alive: false,
alive: true,
runtimeModel: 'sonnet',
});
});

View file

@ -421,6 +421,8 @@ vi.mock('@renderer/utils/geminiUiFreeze', () => ({
vi.mock('@renderer/utils/teamModelAvailability', () => ({
getTeamModelSelectionError: vi.fn(() => null),
isTeamModelAvailableForUi: vi.fn(() => true),
isTeamProviderModelVerificationPending: vi.fn(() => false),
isTeamProviderRuntimeStatusLoading: vi.fn(() => false),
normalizeExplicitTeamModelForUi: vi.fn((_providerId: string, model: string) => model),
}));