chore(app): remove unused files and code with Knip (#5185)

This commit is contained in:
Steven Enamakel
2026-07-25 05:08:01 +03:00
committed by GitHub
parent b9e0ce6171
commit ca0e65f196
400 changed files with 1647 additions and 2739 deletions
+12 -11
View File
@@ -1,27 +1,28 @@
{
"$schema": "https://unpkg.com/knip@6/schema.json",
"entry": ["src/main.tsx", "test/e2e/specs/**/*.spec.ts"],
"project": [
"src/**/*.{ts,tsx}",
"test/**/*.{ts,tsx}",
"test/e2e/globals.d.ts",
"*.config.{js,ts}"
"entry": [
"src/main.tsx",
"src/features/conversations/index.ts",
"vite.config.ts",
"test/vitest.config.ts",
"test/wdio.conf.ts",
"playwright.config.ts",
"test/e2e/specs/**/*.spec.ts",
"test/playwright/specs/**/*.spec.ts"
],
"project": ["src/**/*.{ts,tsx}", "test/**/*.{ts,tsx}", "*.config.{js,ts}"],
"tags": ["-knipignore"],
"ignoreDependencies": [
"@tauri-apps/cli",
"@testing-library/dom",
"@wdio/appium-service",
"@wdio/cli",
"@wdio/local-runner",
"@wdio/mocha-framework",
"@wdio/spec-reporter",
"buffer",
"eslint",
"husky",
"os-browserify",
"prettier",
"process",
"util"
],
"ignoreBinaries": ["eslint", "knip", "open", "prettier", "tauri", "tsc", "vite", "vitest"]
"ignoreBinaries": ["open"]
}
+4 -3
View File
@@ -95,14 +95,12 @@
"d3-force": "^3.0.0",
"debug": "^4.4.3",
"katex": "^0.16.47",
"lottie-react": "^2.4.1",
"os-browserify": "^0.3.0",
"pixi.js": "^8.18.1",
"process": "^0.11.10",
"qrcode.react": "^4.2.0",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"react-ga4": "^3.0.1",
"react-icons": "^5.6.0",
"react-joyride": "^3.1.0",
"react-markdown": "^10.1.0",
@@ -145,9 +143,11 @@
"@vitest/coverage-v8": "^4.0.18",
"@wdio/appium-service": "^9.24.0",
"@wdio/cli": "^9.24.0",
"@wdio/globals": "^9.24.0",
"@wdio/local-runner": "^9.24.0",
"@wdio/mocha-framework": "^9.24.0",
"@wdio/spec-reporter": "^9.24.0",
"@wdio/types": "^9.24.0",
"autoprefixer": "^10.4.23",
"cross-env": "^10.1.0",
"eslint": "^9.39.2",
@@ -166,6 +166,7 @@
"typescript": "~5.8.3",
"vite": "^8.0.0",
"vite-plugin-node-polyfills": "^0.26.0",
"vitest": "^4.0.18"
"vitest": "^4.0.18",
"webdriverio": "^9.24.0"
}
}
+9 -26
View File
@@ -46,9 +46,6 @@ importers:
debug:
specifier: ^4.4.3
version: 4.4.3(supports-color@8.1.1)
lottie-react:
specifier: ^2.4.1
version: 2.4.1(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
os-browserify:
specifier: ^0.3.0
version: 0.3.0
@@ -149,6 +146,9 @@ importers:
'@wdio/cli':
specifier: ^9.24.0
version: 9.27.0(@types/node@25.6.0)(expect-webdriverio@5.6.5)
'@wdio/globals':
specifier: ^9.24.0
version: 9.27.0(expect-webdriverio@5.6.5)(webdriverio@9.27.0)
'@wdio/local-runner':
specifier: ^9.24.0
version: 9.27.0(@wdio/globals@9.27.0)(webdriverio@9.27.0)
@@ -158,6 +158,9 @@ importers:
'@wdio/spec-reporter':
specifier: ^9.24.0
version: 9.27.0
'@wdio/types':
specifier: ^9.24.0
version: 9.27.0
autoprefixer:
specifier: ^10.4.23
version: 10.5.0(postcss@8.5.10)
@@ -206,6 +209,9 @@ importers:
vitest:
specifier: ^4.0.18
version: 4.1.5(@types/node@25.6.0)(@vitest/coverage-v8@4.1.5)(jsdom@28.1.0(@noble/hashes@2.2.0))(vite@7.3.2(@types/node@25.6.0)(jiti@1.21.7)(tsx@4.21.0)(yaml@2.8.3))
webdriverio:
specifier: ^9.24.0
version: 9.27.0
packages:
'@acemir/cssom@0.9.31':
@@ -5748,21 +5754,6 @@ packages:
}
hasBin: true
lottie-react@2.4.1:
resolution:
{
integrity: sha512-LQrH7jlkigIIv++wIyrOYFLHSKQpEY4zehPicL9bQsrt1rnoKRYCYgpCUe5maqylNtacy58/sQDZTkwMcTRxZw==,
}
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
lottie-web@5.13.0:
resolution:
{
integrity: sha512-+gfBXl6sxXMPe8tKQm7qzLnUy5DUPJPKIyRHwtpCpyUEYjHYRJC/5gjUvdkuO2c3JllrPtHXH5UJJK8LRYl5yQ==,
}
lru-cache@10.4.3:
resolution:
{
@@ -12146,14 +12137,6 @@ snapshots:
dependencies:
js-tokens: 4.0.0
lottie-react@2.4.1(react-dom@19.2.5(react@19.2.5))(react@19.2.5):
dependencies:
lottie-web: 5.13.0
react: 19.2.5
react-dom: 19.2.5(react@19.2.5)
lottie-web@5.13.0: {}
lru-cache@10.4.3: {}
lru-cache@11.3.5: {}
+1 -1
View File
@@ -84,7 +84,7 @@ vi.mock('../components/upsell/GlobalUpsellBanner', () => ({ default: () => null
vi.mock('../components/walkthrough/AppWalkthrough', () => ({ default: () => null }));
vi.mock('../features/meet/MascotFrameProducer', () => ({ MascotFrameProducer: () => null }));
vi.mock('../services/analytics', () => ({ trackPageView: vi.fn() }));
vi.mock('../utils/accountsFullscreen', () => ({ isAccountsFullscreen: vi.fn(() => false) }));
vi.mock('../utils/accountsFullscreen', () => ({ AGENT_ACCOUNT_ID: '__agent__' }));
vi.mock('../store/hooks', () => ({ useAppSelector: vi.fn(() => null) }));
vi.mock('@sentry/react', () => ({
ErrorBoundary: ({ children }: { children: React.ReactNode }) => <>{children}</>,
+1 -1
View File
@@ -15,7 +15,7 @@ const KNOWN_MINTS: Record<string, string> = {
};
/** Decimals per known symbol. USDC/CASH = 6, SOL/WSOL = 9, others = 0. */
export function decimalsForSymbol(symbol: string | undefined): number {
function decimalsForSymbol(symbol: string | undefined): number {
const up = (symbol ?? '').toUpperCase();
if (up === 'USDC' || up === 'CASH') return 6;
if (up === 'SOL' || up === 'WSOL') return 9;
@@ -37,7 +37,7 @@ function formatJoined(iso: string): string {
return date.toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric' });
}
export interface AgentProfileModalProps {
interface AgentProfileModalProps {
agent: AgentCard;
onClose: () => void;
}
@@ -17,7 +17,7 @@ import Button from '../../components/ui/Button';
import { ModalShell } from '../../components/ui/ModalShell';
import { useT } from '../../lib/i18n/I18nContext';
export interface AmountCommitDialogProps {
interface AmountCommitDialogProps {
/** Header title, e.g. "Bid on @handle". */
title: string;
/** Context line under the title. */
@@ -36,7 +36,7 @@ export interface AmountCommitDialogProps {
onCancel: () => void;
}
export interface ParsedAmount {
interface ParsedAmount {
/** Amount in base units, ready for the RPC. Only set when `valid`. */
base: string | null;
valid: boolean;
+2 -2
View File
@@ -25,9 +25,9 @@ import { useT } from '../../lib/i18n/I18nContext';
import AmountCommitDialog from './AmountCommitDialog';
import X402ConfirmDialog, { type X402WalletBalance } from './X402ConfirmDialog';
export type CommitKind = 'bid' | 'offer';
type CommitKind = 'bid' | 'offer';
export interface CommitFlowProps {
interface CommitFlowProps {
kind: CommitKind;
/** Display name of the listing/handle (e.g. "@auction"). */
name: string;
@@ -14,7 +14,7 @@
import Button from '../../components/ui/Button';
import { ModalShell } from '../../components/ui/ModalShell';
export interface ConfirmDialogProps {
interface ConfirmDialogProps {
/** Modal header (e.g. "Delete post"). */
title: string;
/** Body copy explaining the consequence (e.g. "Delete this post? This can't be undone."). */
@@ -21,7 +21,7 @@ import { apiClient } from '../AgentWorldShell';
// Namespaced already ('agentworld:identity'), so messages carry no prefix.
const debug = debugFactory('agentworld:identity');
export interface TransferHandleModalProps {
interface TransferHandleModalProps {
/** The handle being transferred away (without a leading @). */
handle: string;
onClose: () => void;
@@ -64,9 +64,9 @@ export interface X402WalletBalance {
* - `commit` — signed bid/offer commitment. Insufficient balance SOFT-warns but
* still allows Confirm (funds move only on acceptance).
*/
export type X402ConfirmMode = 'spend' | 'commit';
type X402ConfirmMode = 'spend' | 'commit';
export interface X402ConfirmDialogProps {
interface X402ConfirmDialogProps {
/** Title shown in the modal header (e.g. "Register @handle"). */
title: string;
/** Optional subtitle / context line. */
@@ -107,7 +107,7 @@ export interface X402ConfirmDialogProps {
* "unknown" case into "sufficient", silently bypassing the gate. Callers that
* only need the provable-shortfall signal can use `isInsufficient` below.
*/
export type BalanceStatus = 'unknown' | 'insufficient' | 'sufficient';
type BalanceStatus = 'unknown' | 'insufficient' | 'sufficient';
export function balanceStatus(balance: X402WalletBalance | null, amount: string): BalanceStatus {
if (!balance) return 'unknown';
@@ -2,13 +2,13 @@ import { useCallback, useEffect, useRef, useState } from 'react';
import { socketService } from '../../services/socketService';
export interface TinyplaceStreamMessage {
interface TinyplaceStreamMessage {
stream_id: string;
kind: string;
message: unknown;
}
export interface TinyplaceStreamStatus {
interface TinyplaceStreamStatus {
stream_id: string;
status: string;
}
+3 -3
View File
@@ -17,7 +17,7 @@ import {
type X402BuyResult,
} from '../../lib/agentworld/invokeApiClient';
export type X402BuyState =
type X402BuyState =
| { phase: 'idle' }
| { phase: 'challenge_loading' }
| {
@@ -35,7 +35,7 @@ export type X402BuyState =
| { phase: 'success'; result: Record<string, unknown>; onChainTx?: string; network?: string }
| { phase: 'error'; message: string; onChainTx?: string };
export type X402BuyFn = (id: string, opts: { confirmed: boolean }) => Promise<X402BuyResult>;
type X402BuyFn = (id: string, opts: { confirmed: boolean }) => Promise<X402BuyResult>;
/** Devnet/mainnet Solana explorer link for a settled payment tx. */
export function explorerTxUrl(tx: string, network?: string): string {
@@ -49,7 +49,7 @@ export function extractOnChainTx(message: string): string | undefined {
return match?.[1];
}
export interface UseX402Buy {
interface UseX402Buy {
state: X402BuyState;
reset: () => void;
begin: (id: string) => void;
+2 -2
View File
@@ -49,7 +49,7 @@ const RENDERER_PREFERENCE = 'webgl' as const;
const INIT_TIMEOUT_MS = 10_000;
/** Thrown when renderer init rejects or exceeds {@link INIT_TIMEOUT_MS}. */
export class RendererInitError extends Error {
class RendererInitError extends Error {
public constructor(message: string, options?: { cause?: unknown }) {
super(message, options);
this.name = 'RendererInitError';
@@ -191,7 +191,7 @@ function boxRelation(pointX: number, pointY: number, box: DepthObstacle): number
// several worlds mount over a session (e.g. React strict-mode double-mounts).
let fontsInstalled = false;
export interface AgentSummary {
interface AgentSummary {
id: string;
label: string;
}
-11
View File
@@ -9,17 +9,6 @@ function pack(red: number, green: number, blue: number): number {
return (clamp(red) << 16) | (clamp(green) << 8) | clamp(blue);
}
/** Linearly blend two colours; `amount` 0 returns `colorA`, 1 returns `colorB`. */
export function mixColor(colorA: number, colorB: number, amount: number): number {
const [redA, greenA, blueA] = channels(colorA);
const [redB, greenB, blueB] = channels(colorB);
return pack(
redA + (redB - redA) * amount,
greenA + (greenB - greenA) * amount,
blueA + (blueB - blueA) * amount
);
}
/** Scale a colour's brightness (`factor` < 1 darkens, > 1 lightens). */
export function shadeColor(color: number, factor: number): number {
const [red, green, blue] = channels(color);
+1 -1
View File
@@ -150,7 +150,7 @@ function tableBlueprint(options: {
};
}
export const FURNITURE_BLUEPRINTS: Record<string, FurnitureBlueprint> = {
const FURNITURE_BLUEPRINTS: Record<string, FurnitureBlueprint> = {
pokerTable: {
footprintWidth: 3,
footprintHeight: 2,
+2 -7
View File
@@ -29,7 +29,7 @@ export interface ScreenPoint {
y: number;
}
export interface TilePoint {
interface TilePoint {
x: number;
y: number;
}
@@ -62,7 +62,7 @@ export function screenToTile(screenX: number, screenY: number): TilePoint {
* Layer biases keep entities that share a tile in a stable front-to-back order
* without disturbing the dominant `gridX + gridY` ordering.
*/
export const DEPTH_TILE_SCALE = 16;
const DEPTH_TILE_SCALE = 16;
export const LAYER_FLOOR = 0;
export const LAYER_DECAL = 1;
export const LAYER_WALL = 2;
@@ -78,8 +78,3 @@ export function depthAt(gridX: number, gridY: number, level = 0, layer = 0): num
export function lerp(from: number, to: number, amount: number): number {
return from + (to - from) * amount;
}
/** Euclidean distance between two tile points. */
export function tileDistance(from: TilePoint, to: TilePoint): number {
return Math.hypot(to.x - from.x, to.y - from.y);
}
+2 -28
View File
@@ -1,30 +1,4 @@
/** Public surface of the isometric agent world engine. */
export { GameWorld, RendererInitError } from './GameWorld';
export type { AgentSummary } from './GameWorld';
export { BaseRoom } from './BaseRoom';
export {
ROOM_REGISTRY,
PokerTableRoom,
CourtHouseRoom,
OfficeRoom,
HomeRoom,
OutsideWorldRoom,
} from './rooms';
export type { RoomEntry } from './rooms';
export { ChatBubble } from './ChatBubble';
export { Agent } from './Agent';
export { FurnitureSprite, FURNITURE_BLUEPRINTS } from './furniture';
export { TextureFactory } from './textures';
export type {
AgentAction,
AgentState,
ChatMessage,
Facing,
FurnitureConfig,
InteractionPoint,
RoomDefinition,
RoomPalette,
WalkNode,
} from './types';
export { TileCode } from './types';
export { GameWorld } from './GameWorld';
export { ROOM_REGISTRY } from './rooms';
+5 -5
View File
@@ -415,31 +415,31 @@ function outsideDefinition(): RoomDefinition {
// ---- Concrete room subclasses ----------------------------------------------
export class PokerTableRoom extends BaseRoom {
class PokerTableRoom extends BaseRoom {
public constructor(factory: TextureFactory) {
super(pokerDefinition(), factory);
}
}
export class CourtHouseRoom extends BaseRoom {
class CourtHouseRoom extends BaseRoom {
public constructor(factory: TextureFactory) {
super(courtDefinition(), factory);
}
}
export class OfficeRoom extends BaseRoom {
class OfficeRoom extends BaseRoom {
public constructor(factory: TextureFactory) {
super(officeDefinition(), factory);
}
}
export class HomeRoom extends BaseRoom {
class HomeRoom extends BaseRoom {
public constructor(factory: TextureFactory) {
super(homeDefinition(), factory);
}
}
export class OutsideWorldRoom extends BaseRoom {
class OutsideWorldRoom extends BaseRoom {
public constructor(factory: TextureFactory) {
super(outsideDefinition(), factory);
}
+2 -2
View File
@@ -8,7 +8,7 @@
*/
import { type AgentCard } from '../../lib/agentworld/invokeApiClient';
export const AVATAR_COLORS = [
const AVATAR_COLORS = [
'bg-blue-500',
'bg-purple-500',
'bg-pink-500',
@@ -29,7 +29,7 @@ export function getAvatarColor(agentId: string): string {
return AVATAR_COLORS[total % AVATAR_COLORS.length] ?? 'bg-blue-500';
}
export function getDisplayName(agent: AgentCard): string {
function getDisplayName(agent: AgentCard): string {
const username = agent['username'] as string | undefined;
return username ?? agent.name ?? agent.agentId.slice(0, 8);
}
+3 -3
View File
@@ -1,11 +1,11 @@
export type PromptInjectionVerdict = 'allow' | 'block' | 'review';
type PromptInjectionVerdict = 'allow' | 'block' | 'review';
export interface PromptInjectionReason {
interface PromptInjectionReason {
code: string;
message: string;
}
export interface PromptInjectionCheck {
interface PromptInjectionCheck {
verdict: PromptInjectionVerdict;
score: number;
reasons: PromptInjectionReason[];
@@ -57,7 +57,7 @@ function StepRow({ step }: { step: HarnessInitStep }) {
);
}
export interface InitProgressScreenProps {
interface InitProgressScreenProps {
snapshot: HarnessInitSnapshot;
onRetry: () => void;
onContinue: () => void;
+1 -1
View File
@@ -11,7 +11,7 @@ interface LocaleOption {
label: string;
}
export const LOCALE_OPTIONS: LocaleOption[] = [
const LOCALE_OPTIONS: LocaleOption[] = [
{ value: 'en', flag: '🇬🇧', label: 'English' },
{ value: 'ko', flag: '🇰🇷', label: '한국어' },
{ value: 'zh-CN', flag: '🇨🇳', label: '简体中文' },
@@ -119,7 +119,7 @@ export type ParseErrorCode =
* actual schema string we got, etc.). Consumers render via
* `t(\`mcp.inventory.parseError.\${errorCode}\`)` + optional detail.
*/
export type ParseResult =
type ParseResult =
| { ok: true; manifest: McpInventoryManifest }
| { ok: false; errorCode: ParseErrorCode; detail?: string };
@@ -93,7 +93,7 @@ const transportOf = (server: SmitheryServer): Transport =>
* `io.gitlab.<user>/…`), which maps 1:1 to a repo page. Returns `null` for
* vendor reverse-DNS slugs that don't encode a code host.
*/
export const deriveRepoUrl = (qualifiedName: string): string | null => {
const deriveRepoUrl = (qualifiedName: string): string | null => {
const slash = qualifiedName.indexOf('/');
if (slash < 1) return null;
const prefix = qualifiedName.slice(0, slash);
@@ -79,7 +79,7 @@ const formatArgs = (raw: string): string => {
* caller can keep JSON-parse failures (user input) cleanly separate from RPC
* failures (the actual tool call) — they surface to the user differently.
*/
export type ParsedToolArgs = { ok: true; value: unknown } | { ok: false; error: string };
type ParsedToolArgs = { ok: true; value: unknown } | { ok: false; error: string };
export const parseToolArgs = (argsJson: string, fallbackMessage: string): ParsedToolArgs => {
if (argsJson.trim() === '') return { ok: true, value: {} };
@@ -31,7 +31,7 @@ interface Props {
* thread; clears itself on a recorded decision (the turn-end handlers in
* {@link ChatRuntimeProvider} also clear it if the turn is cancelled).
*/
export const ApprovalRequestCard: React.FC<Props> = ({ threadId, approval }) => {
const ApprovalRequestCard: React.FC<Props> = ({ threadId, approval }) => {
const { t } = useT();
const dispatch = useAppDispatch();
const [deciding, setDeciding] = useState<Decision | null>(null);
+1 -1
View File
@@ -28,7 +28,7 @@ import { extensionFor } from './artifactExtension';
* rounded card, dark/light Tailwind variants, mono accents on
* numeric values, inline SVG icons. No new icon dependency.
*/
export interface ArtifactCardProps {
interface ArtifactCardProps {
artifact: ArtifactSnapshot;
/** When provided, render a Retry button on the `failed` state. */
onRetry?: (artifactId: string) => void;
+1 -1
View File
@@ -18,7 +18,7 @@ import ChatFilesPanel from './ChatFilesPanel';
* survive app restarts via the `artifactsReadyOnlyTransform` configured in
* `store/index.ts`.
*/
export interface ChatFilesChipProps {
interface ChatFilesChipProps {
threadId: string;
}
+1 -1
View File
@@ -32,7 +32,7 @@ import { extensionFor } from './artifactExtension';
* state only shows if the user deletes the last artifact while the
* panel is open).
*/
export interface ChatFilesPanelProps {
interface ChatFilesPanelProps {
threadId: string;
artifacts: ArtifactSnapshot[];
onClose: () => void;
@@ -115,5 +115,3 @@ export const FlowApprovalRequestCard: React.FC<Props> = ({ request, onResolved }
</div>
);
};
export default FlowApprovalRequestCard;
@@ -59,7 +59,7 @@ function errorText(e: unknown): string {
return e instanceof Error ? e.message : String(e);
}
export const IntegrationConnectCard: React.FC<Props> = ({ threadId, approval }) => {
const IntegrationConnectCard: React.FC<Props> = ({ threadId, approval }) => {
const { t } = useT();
const dispatch = useAppDispatch();
// Canonicalize the slug the agent supplied (e.g. `google_drive` →
+1 -1
View File
@@ -1,7 +1,7 @@
import { useT } from '../../lib/i18n/I18nContext';
import type { QueuedFollowup } from '../../store/chatRuntimeSlice';
export interface QueuedFollowupsProps {
interface QueuedFollowupsProps {
/** Follow-ups queued for the current thread while a turn is streaming. */
items: QueuedFollowup[];
/** Dismiss every queued follow-up (clears the backend run-queue too). */
@@ -2,7 +2,7 @@ import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { markWorkflowProposalCompleted, type WorkflowProposal } from '../../store/chatRuntimeSlice';
import { WorkflowProposalCard } from './WorkflowProposalCard';
import WorkflowProposalCard from './WorkflowProposalCard';
// Echo i18n keys so we can assert on the stable key string.
vi.mock('../../lib/i18n/I18nContext', () => ({ useT: () => ({ t: (key: string) => key }) }));
@@ -106,7 +106,7 @@ interface Props {
* the tool-timeline `StatusTag`/detail-chip visual language for the
* node-kind badges + config hints in the step list.
*/
export const WorkflowProposalCard: React.FC<Props> = ({ threadId, proposal, onSaved }) => {
const WorkflowProposalCard: React.FC<Props> = ({ threadId, proposal, onSaved }) => {
const { t } = useT();
const dispatch = useAppDispatch();
const navigate = useNavigate();
@@ -8,7 +8,7 @@ import { beforeEach, describe, expect, it, vi } from 'vitest';
import type { FlowApprovalRequest } from '../../../hooks/useFlowApprovalRequests';
import { decideApproval } from '../../../services/api/approvalApi';
import FlowApprovalRequestCard from '../FlowApprovalRequestCard';
import { FlowApprovalRequestCard } from '../FlowApprovalRequestCard';
vi.mock('../../../services/api/approvalApi', () => ({ decideApproval: vi.fn() }));
@@ -40,7 +40,7 @@ export function activeTriggerSignature(t: ComposioActiveTrigger): string {
return t.slug.toUpperCase();
}
export interface TriggerTogglesProps {
interface TriggerTogglesProps {
toolkitSlug: string;
toolkitName: string;
connectionId: string;
@@ -4,7 +4,7 @@ import type { BudgetStatus } from '../../hooks/useCostDashboard';
import { useT } from '../../lib/i18n/I18nContext';
import { formatCurrency } from './formatCurrency';
export interface BudgetSummaryProps {
interface BudgetSummaryProps {
currency: string;
periodTotalUsd: number;
monthlyPaceUsd: number;
@@ -1,13 +1,13 @@
import type { ReactNode } from 'react';
export interface ChartTooltipRow {
interface ChartTooltipRow {
label: string;
value: string;
/** CSS colour for the legend swatch. */
color?: string;
}
export interface ChartTooltipProps {
interface ChartTooltipProps {
title: string;
rows: ChartTooltipRow[];
footer?: ReactNode;
@@ -15,7 +15,7 @@ import { useT } from '../../lib/i18n/I18nContext';
import ChartTooltip from './ChartTooltip';
import { dayOfMonth, formatCurrency, longDateLabel, shortDayLabel } from './formatCurrency';
export interface CostBarChartProps {
interface CostBarChartProps {
days: CostDashboardDay[];
currency: string;
/** Monthly budget in USD; used to derive a daily target. */
@@ -2,7 +2,7 @@ import type { CostDashboardModelStats } from '../../hooks/useCostDashboard';
import { useT } from '../../lib/i18n/I18nContext';
import { formatCurrency, formatTokens } from './formatCurrency';
export interface ModelCostTableProps {
interface ModelCostTableProps {
models: CostDashboardModelStats[];
currency: string;
}
@@ -5,7 +5,7 @@ import { useT } from '../../lib/i18n/I18nContext';
import ChartTooltip from './ChartTooltip';
import { dayOfMonth, formatTokens, longDateLabel, shortDayLabel } from './formatCurrency';
export interface TokenUsageChartProps {
interface TokenUsageChartProps {
days: CostDashboardDay[];
}
@@ -75,7 +75,7 @@ export function dayOfMonth(isoDate: string): string {
* is invoked with a string key and is expected to return the localised
* value (or the key itself when no translation is available).
*/
export type RelativeTimeTranslator = (key: string, fallback?: string) => string;
type RelativeTimeTranslator = (key: string, fallback?: string) => string;
/**
* Human-friendly relative-time string for the "updated Ns ago" pill.
@@ -1,6 +1,6 @@
import { useEffect, useId, useRef, useState } from 'react';
export interface FilterOption {
interface FilterOption {
value: string;
label: string;
}
+2 -2
View File
@@ -18,7 +18,7 @@ import { createPortal } from 'react-dom';
import { useEscapeKey } from '../../hooks/useEscapeKey';
import { useT } from '../../lib/i18n/I18nContext';
export interface FlowRowMenuItem {
interface FlowRowMenuItem {
key: string;
label: string;
onSelect: () => void;
@@ -27,7 +27,7 @@ export interface FlowRowMenuItem {
testId?: string;
}
export interface FlowRowMenuProps {
interface FlowRowMenuProps {
items: FlowRowMenuItem[];
/** Suffixed onto test ids so multiple rows stay addressable. */
rowId: string;
@@ -485,5 +485,3 @@ export function FlowRunInspectorDrawer({ runId, onClose, onFixWithAgent }: Props
</div>
);
}
export default FlowRunInspectorDrawer;
@@ -96,5 +96,3 @@ export function FlowRunPendingApprovalCard({ approval, deciding, onDecide }: Pro
</div>
);
}
export default FlowRunPendingApprovalCard;
@@ -18,7 +18,7 @@ import { beforeEach, describe, expect, it, vi } from 'vitest';
import type { FlowRun } from '../../services/api/flowsApi';
import { store } from '../../store';
import { FlowRunsDrawer } from './FlowRunsDrawer';
import FlowRunsDrawer from './FlowRunsDrawer';
const listFlowRuns = vi.hoisted(() => vi.fn());
vi.mock('../../services/api/flowsApi', () => ({ listFlowRuns }));
+1 -1
View File
@@ -74,7 +74,7 @@ interface Props {
* unconditionally and just flip `flowId` (same convention as
* `FlowRunInspectorDrawer`/`SubagentDrawer`).
*/
export function FlowRunsDrawer({ flowId, flowName, onClose, onFixWithAgent }: Props) {
function FlowRunsDrawer({ flowId, flowName, onClose, onFixWithAgent }: Props) {
const { t } = useT();
const [runs, setRuns] = useState<FlowRun[]>([]);
const [loading, setLoading] = useState(false);
+1 -1
View File
@@ -48,7 +48,7 @@ function relativeTime(iso: string, t: TFn): string {
const log = createDebug('app:flows:runs-sidebar');
export interface FlowRunsSidebarProps {
interface FlowRunsSidebarProps {
flowId: string;
}
@@ -317,5 +317,3 @@ function FragmentRow({
</>
);
}
export default RunItemDataBrowser;
@@ -37,12 +37,12 @@ const log = createDebug('app:flows:canvas:agentInspector');
* slugs `OpenHumanAgentRunner`/`resolve_model_for_hint` accept as bare tier
* names — so the value written here runs unchanged in the flow engine.
*/
export const AGENT_MANAGED_TIERS = ['reasoning-v1', 'chat-v1', 'agentic-v1', 'burst-v1'] as const;
const AGENT_MANAGED_TIERS = ['reasoning-v1', 'chat-v1', 'agentic-v1', 'burst-v1'] as const;
/** Sentinel select value for "type a raw model id" — never persisted. */
const CUSTOM_MODEL = '__custom__';
export interface AgentNodeInspectorProps {
interface AgentNodeInspectorProps {
/** The agent node's controlled config object. */
config: Record<string, unknown>;
/** Shallow-merge patch into the node's config. */
@@ -117,7 +117,7 @@ const CLICK_ADD_ORIGIN = { x: 80, y: 80 };
/** Per-click cascade so repeated palette clicks don't stack on one spot. */
const CLICK_ADD_STEP = 32;
export interface EditableFlowCanvasProps {
interface EditableFlowCanvasProps {
nodes: FlowNode[];
edges: FlowEdge[];
/** Graph-level metadata xyflow doesn't carry, needed to re-serialize on save. */
@@ -37,7 +37,7 @@ import EditableFlowCanvas, {
import './flowCanvasStyles.css';
import FlowNodeComponent from './FlowNodeComponent';
export interface FlowCanvasProps {
interface FlowCanvasProps {
nodes: FlowNode[];
edges: FlowEdge[];
/**
@@ -20,7 +20,7 @@ import { memo } from 'react';
import { useT } from '../../../lib/i18n/I18nContext';
import type { FlowValidation } from '../../../services/api/flowsApi';
export interface FlowValidationBannerProps {
interface FlowValidationBannerProps {
validation: FlowValidation | null;
/** Message from a failed `flows_update` Save, shown as a distinct error row. */
saveError?: string | null;
@@ -23,7 +23,7 @@ import { useT } from '../../../lib/i18n/I18nContext';
/** dataTransfer MIME key for a palette drag — read by the canvas `onDrop`. */
export const PALETTE_DND_MIME = 'application/tinyflows-node';
export interface NodePaletteProps {
interface NodePaletteProps {
/** Add a node from the given palette entry at the canvas's default position. */
onAdd: (entry: PaletteEntry) => void;
}
@@ -36,7 +36,7 @@ export interface NodeConfigPatch {
config?: Record<string, unknown>;
}
export interface NodeConfigDrawerProps {
interface NodeConfigDrawerProps {
/** The selected node to edit, or `null` when nothing single-node is selected. */
node: FlowNode | null;
onClose: () => void;
@@ -12,7 +12,7 @@ import { useMemo } from 'react';
import type { FlowEdge } from '../../../../lib/flows/graphAdapter';
import { useT } from '../../../../lib/i18n/I18nContext';
export interface NodeConnectionsProps {
interface NodeConnectionsProps {
nodeId: string;
edges: FlowEdge[];
nodeLabelById: Record<string, string>;
@@ -28,7 +28,7 @@ import {
import { useT } from '../../../../lib/i18n/I18nContext';
import { Field, INPUT_CLASS, MONO_CLASS } from './nodeConfigFields';
export interface ScheduleFieldProps {
interface ScheduleFieldProps {
/** The cron string stored on `config.schedule`. */
value: string;
onChange: (value: string) => void;
@@ -33,7 +33,7 @@ function toolkitLabel(slug: string): string {
}
/** Distinct connected Composio toolkits from the canvas's loaded connections. */
export function connectedToolkits(connections: FlowConnection[]): string[] {
function connectedToolkits(connections: FlowConnection[]): string[] {
const seen = new Set<string>();
for (const c of connections) {
if (c.kind === 'composio' && c.toolkit) seen.add(c.toolkit);
@@ -43,7 +43,7 @@ export function connectedToolkits(connections: FlowConnection[]): string[] {
// ── toolkit (app) picker ─────────────────────────────────────────────────────
export interface ComposioToolkitFieldProps {
interface ComposioToolkitFieldProps {
label: string;
hint?: string;
value: string;
@@ -18,7 +18,7 @@ import { Field, INPUT_CLASS, MONO_CLASS } from './nodeConfigFields';
/** The `oh:` prefix that marks a native-tool slug (mirrors the Rust constant). */
export const NATIVE_TOOL_PREFIX = 'oh:';
export interface NativeToolFieldProps {
interface NativeToolFieldProps {
label: string;
hint?: string;
/** The full `config.slug`, e.g. `oh:web_search` (or empty / `oh:`). */
@@ -75,7 +75,7 @@ export function Field({
);
}
export interface TextFieldProps {
interface TextFieldProps {
label: string;
hint?: string;
value: string;
@@ -101,7 +101,7 @@ export function TextField({ label, hint, value, onChange, placeholder, testId }:
);
}
export interface TextAreaFieldProps extends Omit<TextFieldProps, 'onChange'> {
interface TextAreaFieldProps extends Omit<TextFieldProps, 'onChange'> {
onChange: (value: string) => void;
rows?: number;
mono?: boolean;
@@ -133,12 +133,12 @@ export function TextAreaField({
);
}
export interface SelectOption {
interface SelectOption {
value: string;
label: string;
}
export interface SelectFieldProps {
interface SelectFieldProps {
label: string;
hint?: string;
value: string;
@@ -167,96 +167,6 @@ export function SelectField({ label, hint, value, onChange, options, testId }: S
);
}
/**
* Canonical model route hints (mirrors `AgentEditorPage`'s list, which in turn
* mirrors the Rust `ModelSpec::Hint(...)` slugs). Selecting one routes the
* agent node by capability tier; the workspace resolves the concrete model.
*/
export const AGENT_MODEL_HINTS = [
'hint:reasoning',
'hint:chat',
'hint:agentic',
'hint:burst',
'hint:coding',
'hint:summarization',
'hint:vision',
] as const;
/** Sentinel select value for "type a raw model id" — never persisted. */
const CUSTOM_MODEL = '__custom__';
export interface ModelHintFieldProps {
label: string;
hint?: string;
value: string;
onChange: (value: string) => void;
testId?: string;
}
/**
* Model selector for the `agent` node: a dropdown of the workspace's model
* route hints (`hint:chat`, `hint:coding`, …) with an "inherit" default and a
* custom escape hatch for a raw BYOK model id. Writes `hint:<tier>` (or the raw
* id, or `''` to inherit) onto `config.model`. Mirrors the agent-editor model
* picker so hints stay consistent across the app.
*/
export function ModelHintField({ label, hint, value, onChange, testId }: ModelHintFieldProps) {
const { t } = useT();
const id = useId();
// A value that's neither empty nor a known hint is a raw custom model id, so
// the picker opens in custom mode showing it in the text box.
const isKnown = value === '' || (AGENT_MODEL_HINTS as readonly string[]).includes(value);
const [customMode, setCustomMode] = useState(value !== '' && !isKnown);
const handleSelect = useCallback(
(next: string) => {
if (next === CUSTOM_MODEL) {
setCustomMode(true);
// Entering custom from a hint/inherit starts with an empty raw id.
if (isKnown) onChange('');
return;
}
setCustomMode(false);
onChange(next);
},
[isKnown, onChange]
);
return (
<Field label={label} hint={hint} htmlFor={id}>
<div className="space-y-2">
<select
id={id}
className={INPUT_CLASS}
value={customMode ? CUSTOM_MODEL : value}
data-testid={testId}
onChange={e => handleSelect(e.target.value)}>
<option value="">{t('flows.nodeConfig.agent.modelInherit')}</option>
<optgroup label={t('flows.nodeConfig.agent.modelHints')}>
{AGENT_MODEL_HINTS.map(h => (
<option key={h} value={h}>
{h}
</option>
))}
</optgroup>
<option value={CUSTOM_MODEL}>{t('flows.nodeConfig.agent.modelCustom')}</option>
</select>
{customMode && (
<input
type="text"
className={`${INPUT_CLASS} ${MONO_CLASS}`}
value={value}
placeholder={t('flows.nodeConfig.agent.modelCustomPlaceholder')}
aria-label={t('flows.nodeConfig.agent.modelCustomPlaceholder')}
data-testid={testId ? `${testId}-custom` : undefined}
onChange={e => onChange(e.target.value)}
/>
)}
</div>
</Field>
);
}
/**
* Compact "insert an upstream value" dropdown (Feature: `nodes` scope picker).
* Always renders with the empty placeholder selected; picking an option calls
@@ -304,7 +214,7 @@ export function UpstreamInsertSelect({
);
}
export interface ExpressionFieldProps extends TextFieldProps {
interface ExpressionFieldProps extends TextFieldProps {
/**
* `=nodes.…` expressions from upstream nodes; when non-empty a compact
* insert dropdown renders beside the input (picking replaces the value).
@@ -370,7 +280,7 @@ export function ExpressionField({
);
}
export interface KeyMapFieldProps {
interface KeyMapFieldProps {
label: string;
hint?: string;
value: Record<string, string>;
@@ -473,7 +383,7 @@ export function KeyMapField({
);
}
export interface JsonFieldProps {
interface JsonFieldProps {
label: string;
hint?: string;
value: unknown;
@@ -545,7 +455,7 @@ export function JsonField({ label, hint, value, onChange, rows = 6, testId }: Js
);
}
export interface CredentialPickerFieldProps {
interface CredentialPickerFieldProps {
label?: string;
value: string;
onChange: (value: string) => void;
@@ -67,7 +67,7 @@ export interface NodeConfigFormProps {
upstreamOptions?: UpstreamExpressionOption[];
}
export type NodeConfigForm = (props: NodeConfigFormProps) => React.ReactElement;
type NodeConfigForm = (props: NodeConfigFormProps) => React.ReactElement;
// ── trigger ────────────────────────────────────────────────────────────────
@@ -23,9 +23,9 @@ import { type FlowValidation, validateFlow } from '../../../services/api/flowsAp
const log = createDebug('app:flows:canvas:validate');
/** Idle delay after the last edit before auto-validating the draft. */
export const VALIDATION_DEBOUNCE_MS = 500;
const VALIDATION_DEBOUNCE_MS = 500;
export interface FlowValidationState {
interface FlowValidationState {
/** The most recent successful validation result, or `null` before the first. */
validation: FlowValidation | null;
/** True while a validation RPC is in flight (debounced or manual). */
@@ -105,5 +105,3 @@ export function useFlowValidation(
return { validation, validating, validateNow: run };
}
export default useFlowValidation;
+1 -1
View File
@@ -25,7 +25,7 @@ const log = createDebug('app:flows:create');
/** Sentinel `busyKey` for the "start from scratch" path (not a template id). */
export const BLANK_FLOW_KEY = 'blank';
export interface UseCreateFlow {
interface UseCreateFlow {
/** Persist `graph` under `name`, then navigate into its canvas. `key` tags the busy affordance. */
create: (key: string, name: string, graph: WorkflowGraph) => Promise<void>;
/** The `key` of the create currently in flight, or `null`. */
@@ -12,7 +12,7 @@ import { useT } from '../../lib/i18n/I18nContext';
import type { AttentionAction, AttentionQueue } from '../../lib/orchestration/orchestrationClient';
import AttentionQueueItem from './AttentionQueueItem';
export interface AttentionQueueProps {
interface AttentionQueueProps {
queue: AttentionQueue | null;
loading?: boolean;
onAction?: (action: AttentionAction) => void;
@@ -17,7 +17,7 @@ import type {
AttentionKind,
} from '../../lib/orchestration/orchestrationClient';
export interface AttentionQueueItemProps {
interface AttentionQueueItemProps {
item: AttentionItem;
onAction?: (action: AttentionAction) => void;
}
@@ -11,7 +11,7 @@ import type { HarnessType } from '../../lib/orchestration/orchestrationClient';
export type GlyphKind = HarnessType | 'openhuman';
export interface HarnessGlyphProps {
interface HarnessGlyphProps {
harness: GlyphKind;
className?: string;
}
@@ -10,7 +10,7 @@ import type { InstanceStatus, SessionSummary } from '../../lib/orchestration/orc
import HarnessGlyph, { type GlyphKind } from './HarnessGlyph';
import InstanceStatusDot from './InstanceStatusDot';
export interface InstanceCardProps {
interface InstanceCardProps {
session: SessionSummary;
selected?: boolean;
onSelect?: () => void;
@@ -11,7 +11,7 @@
*/
import type { InstanceStatus } from '../../lib/orchestration/orchestrationClient';
export interface InstanceStatusDotProps {
interface InstanceStatusDotProps {
status: InstanceStatus;
/** Accessible label (already translated by the caller). */
label?: string;
@@ -82,7 +82,7 @@ interface SyncResult {
* Per-stage fallback percentages so the progress bar always advances even
* when no numeric "N/M" ratio is present in the detail string (RC#4, #3295).
*/
export const STAGE_FALLBACK_PERCENT: Record<string, number> = {
const STAGE_FALLBACK_PERCENT: Record<string, number> = {
requested: 2,
fetching: 5,
stored: 15,
@@ -205,7 +205,7 @@ function statusDotClass(kind: MemoryTreePipelineStatus['status']): string {
* current data; per-provider failure attribution needs new core work and
* is filed as a follow-up to issue #2763.
*/
export type IntegrationHealth = 'active' | 'stale';
type IntegrationHealth = 'active' | 'stale';
/** Map the wire `freshness` enum to the two-state UI classification. */
export function classifyIntegration(
@@ -551,7 +551,3 @@ export function MemoryTreeStatusPanel({ onToast }: MemoryTreeStatusPanelProps) {
</div>
);
}
// Re-export the hook so unit tests can opt into the polling subscription
// directly without re-implementing it.
export { useMemoryTreeStatus };
@@ -10,7 +10,7 @@ import { useT } from '../../lib/i18n/I18nContext';
import type { ChatMessage, ChatWindow } from '../../lib/orchestration/useOrchestrationChats';
import { formatTime } from './orchestrationTabHelpers';
export interface ChatListButtonProps {
interface ChatListButtonProps {
chat: ChatWindow;
selected: boolean;
onSelect: () => void;
@@ -13,7 +13,7 @@
import { useT } from '../../lib/i18n/I18nContext';
import type { RelayInfo } from '../../lib/orchestration/orchestrationClient';
export interface RelayBadgeProps {
interface RelayBadgeProps {
relay: RelayInfo | null;
}
@@ -17,7 +17,7 @@ import { useCallback, useState } from 'react';
import { useT } from '../../lib/i18n/I18nContext';
import type { SelfIdentity } from '../../lib/orchestration/orchestrationClient';
export interface SelfIdentityCardProps {
interface SelfIdentityCardProps {
identity: SelfIdentity | null;
loading: boolean;
/**
@@ -11,7 +11,7 @@ import { useT } from '../../lib/i18n/I18nContext';
import type { HarnessType, SessionSummary } from '../../lib/orchestration/orchestrationClient';
import InstanceCard from './InstanceCard';
export interface TinyPlaceRosterProps {
interface TinyPlaceRosterProps {
sessions: SessionSummary[];
selectedId?: string;
onSelect?: (sessionId: string) => void;
+1 -1
View File
@@ -57,7 +57,7 @@ const TOAST_ICON_STYLES = {
info: 'text-primary-500',
};
export function Toast({ notification, onRemove }: ToastProps) {
function Toast({ notification, onRemove }: ToastProps) {
const [isVisible, setIsVisible] = useState(false);
const [isExiting, setIsExiting] = useState(false);
@@ -241,5 +241,3 @@ export function VaultHealthChecklist({ onToast, title }: VaultHealthChecklistPro
</div>
);
}
export default VaultHealthChecklist;
@@ -33,7 +33,7 @@ const REASON_KEY: Record<WorkflowCostReason, string> = {
};
/** i18n key for each safety tier label. */
export const SAFETY_TIER_KEY: Record<WorkflowSafetyTier, string> = {
const SAFETY_TIER_KEY: Record<WorkflowSafetyTier, string> = {
read_only: 'orchestration.tier.readOnly',
standard: 'orchestration.tier.standard',
edit_capable: 'orchestration.tier.editCapable',
@@ -48,7 +48,7 @@ interface Props {
onCancel: () => void;
}
export const WorkflowRunApprovalCard: React.FC<Props> = ({
const WorkflowRunApprovalCard: React.FC<Props> = ({
definition,
reasons,
starting = false,
@@ -78,7 +78,7 @@ interface Props {
onResume: (id: string) => void;
}
export const WorkflowRunDetail: React.FC<Props> = ({
const WorkflowRunDetail: React.FC<Props> = ({
definition,
run,
busy = false,
@@ -36,7 +36,7 @@ export const LEVEL_COLOR = [
export const LEAF_COLOR = '#94A3B8'; // raw chunks / leaves (no level)
export const CONTACT_COLOR = '#A78BFA'; // person entities (contacts mode)
export const SOURCE_COLOR = '#F97316'; // synthetic source root nodes
export const ROOT_COLOR = '#8B5CF6'; // master root hub (purple)
const ROOT_COLOR = '#8B5CF6'; // master root hub (purple)
/** Layout is computed in this fixed coordinate space; the renderer pans/zooms it. */
export const VIEWPORT_W = 1100;
@@ -100,7 +100,7 @@ export type SimLink = SimulationLinkDatum<SimNode>;
* Tree mode draws an edge from each node to its `parent_id`; contacts mode
* uses the explicit `edges`. Dangling endpoints are dropped.
*/
export const ROOT_NODE_ID = '__root__';
const ROOT_NODE_ID = '__root__';
export function buildGraph(
nodes: GraphNode[],
@@ -29,7 +29,7 @@ import {
ZOOM_MIN,
} from './memoryGraphLayout';
export interface PixiGraphOptions {
interface PixiGraphOptions {
simNodes: SimNode[];
links: SimLink[];
dark: boolean;
@@ -18,14 +18,14 @@
import { type GraphEdge, type GraphMode, type GraphNode } from '../../utils/tauriCommands';
import { VIEWPORT_H, VIEWPORT_W } from './memoryGraphLayout';
export interface SeededPosition {
interface SeededPosition {
x: number;
y: number;
/** True when the node had no carried-over position (newly arrived). */
isNew: boolean;
}
export interface SeedResult {
interface SeedResult {
/** Index-aligned with the input `nodes`. */
positions: SeededPosition[];
/** Edge index pairs [childIdx, parentIdx] (tree) or [fromIdx, toIdx] (contacts). */
@@ -13,7 +13,7 @@
*/
import { useCallback, useEffect, useRef } from 'react';
export interface SvgLayoutNode {
interface SvgLayoutNode {
x: number;
y: number;
}
+1 -1
View File
@@ -20,7 +20,7 @@ export interface ChipTabItem<T extends string> {
testId?: string;
}
export interface ChipTabsProps<T extends string> {
interface ChipTabsProps<T extends string> {
/** Chips to render, left to right. */
items: ChipTabItem<T>[];
/** Currently active chip id. */
@@ -10,7 +10,7 @@ import type { ReactNode } from 'react';
* the same max-width and centering as the content beneath it — header and body
* stay aligned. Pass width/centering via `className` (e.g. `mx-auto max-w-2xl`).
*/
export interface PageSectionHeaderProps {
interface PageSectionHeaderProps {
title: ReactNode;
/** One-line description of what the view does. */
description?: ReactNode;
+4 -4
View File
@@ -13,7 +13,7 @@ import Button from '../ui/Button';
*/
/** Accent families available for the icon tile. Keys map to design tokens. */
export type PageWelcomeAccent = 'ocean' | 'sage' | 'amber' | 'coral';
type PageWelcomeAccent = 'ocean' | 'sage' | 'amber' | 'coral';
/** Static per-accent tile tint (Tailwind only scans literal class names). */
const ACCENT_TILE: Record<PageWelcomeAccent, string> = {
@@ -23,7 +23,7 @@ const ACCENT_TILE: Record<PageWelcomeAccent, string> = {
coral: 'bg-coral-500/15 text-coral-600',
};
export interface WelcomeFeature {
interface WelcomeFeature {
/** Leading glyph — emoji string or icon node. */
icon: ReactNode;
/** Short feature title. */
@@ -32,7 +32,7 @@ export interface WelcomeFeature {
description: ReactNode;
}
export interface WelcomeCta {
interface WelcomeCta {
label: ReactNode;
onClick: () => void;
/** First CTA renders as primary; the rest as secondary (override here). */
@@ -41,7 +41,7 @@ export interface WelcomeCta {
testId?: string;
}
export interface PageWelcomeProps {
interface PageWelcomeProps {
/** Big glyph in the accent tile — emoji string or icon node. */
icon: ReactNode;
/** Optional short lead-in above the title (e.g. the page name). */
+1 -1
View File
@@ -1,6 +1,6 @@
import type { ReactNode } from 'react';
export interface PanelHeaderProps {
interface PanelHeaderProps {
/**
* Primary title rendered as an `h2` in the control row, left of `action`.
* Optional — generic panels stay title-less; the settings template
+1 -1
View File
@@ -23,7 +23,7 @@ export interface PanelPageTab<T extends string = string> {
chipTestId?: string;
}
export interface PanelPageProps<T extends string = string> {
interface PanelPageProps<T extends string = string> {
/** Page title, shown in the header above the description (optional). */
title?: ReactNode;
/** Page description, shown below the title and above any chips. */
+1 -1
View File
@@ -2,7 +2,7 @@ import type { ReactNode } from 'react';
import PanelHeader, { DEFAULT_PANEL_HEADER_BG, DEFAULT_PANEL_HEADER_CLASS } from './PanelHeader';
export interface PanelScaffoldProps {
interface PanelScaffoldProps {
/** Primary title rendered in the fixed header (optional; see {@link PanelHeader}). */
title?: ReactNode;
/** Fixed sub-title rendered in a muted tone, below the title. */
+2 -2
View File
@@ -1,12 +1,12 @@
import type { ReactNode } from 'react';
export interface TwoPaneNavItem {
interface TwoPaneNavItem {
value: string;
label: string;
icon?: ReactNode;
}
export interface TwoPaneNavGroup {
interface TwoPaneNavGroup {
/** Optional uppercase sub-header above the group's items. */
label?: string;
items: TwoPaneNavItem[];
+2 -2
View File
@@ -47,7 +47,7 @@ export function useTwoPanelLayout(id: string, defaults?: Partial<PanelLayout>) {
};
}
export interface TwoPanelLayoutProps {
interface TwoPanelLayoutProps {
/** Stable id used as the persistence key for this layout's geometry. */
id: string;
/** Content of the mini sidebar (left pane). */
@@ -103,7 +103,7 @@ export interface TwoPanelLayoutProps {
}
/** Default card look shared by both panes. */
export const DEFAULT_PANE_CLASS = 'bg-surface rounded-2xl shadow-soft border border-line';
const DEFAULT_PANE_CLASS = 'bg-surface rounded-2xl shadow-soft border border-line';
const DEFAULT_MIN_WIDTH = 180;
const DEFAULT_MAX_WIDTH = 480;
@@ -50,7 +50,7 @@ export function useRootSidebar() {
};
}
export interface RootShellLayoutProps {
interface RootShellLayoutProps {
/** Always-visible left pane (the app sidebar). */
sidebar: ReactNode;
/** Dynamic main content (the routed page area). */
@@ -15,10 +15,10 @@ const navIcon = (d: string) => (
const WELCOME_ICON = navIcon('M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z');
/** `'welcome'` / `'main'`, plus any extra sub-page value the caller declares. */
export type PageWelcomeViewId = string;
type PageWelcomeViewId = string;
/** An additional sub-page beyond Welcome · Main (e.g. Workflows' Runs / Discoveries). */
export interface PageWelcomeExtraItem {
interface PageWelcomeExtraItem {
/** `?view=` value + nav selection id. */
value: string;
/** Sidebar label. */
@@ -27,7 +27,7 @@ export interface PageWelcomeExtraItem {
iconPath: string;
}
export interface UsePageWelcomeViewOptions {
interface UsePageWelcomeViewOptions {
/** Accessible label for the sidebar nav. */
ariaLabel: string;
/** Label for the Welcome entry. */
@@ -42,7 +42,7 @@ export interface UsePageWelcomeViewOptions {
extraItems?: PageWelcomeExtraItem[];
}
export interface PageWelcomeView {
interface PageWelcomeView {
/** Current view — `welcome` (default landing) or `main`. */
view: PageWelcomeViewId;
/** Switch views (updates `?view=`). */
@@ -1,7 +1,7 @@
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { SecretPromptDialog } from './SecretPromptDialog';
import SecretPromptDialog from './SecretPromptDialog';
const callCoreRpc = vi.fn();
vi.mock('../../services/coreRpcClient', () => ({
@@ -16,7 +16,7 @@ import { callCoreRpc } from '../../services/coreRpcClient';
type Request = { refId: string; keyName: string; prompt: string };
export function SecretPromptDialog() {
function SecretPromptDialog() {
const { t } = useT();
const [request, setRequest] = useState<Request | null>(null);
const [value, setValue] = useState('');
@@ -19,7 +19,7 @@ interface ActionItemChecklistProps {
items: MeetCallActionItem[];
}
export function ActionItemChecklist({ items }: ActionItemChecklistProps) {
function ActionItemChecklist({ items }: ActionItemChecklistProps) {
const { t } = useT();
const navigate = useNavigate();
const [checked, setChecked] = useState<Record<number, boolean>>({});
@@ -41,7 +41,7 @@ type Toast = { type: 'success' | 'error' | 'info'; title: string; message?: stri
*/
export const LEAVE_SAFETY_TIMEOUT_MS = 10_000;
export interface ActiveMeetingBannerProps {
interface ActiveMeetingBannerProps {
onToast?: (toast: Toast) => void;
}
@@ -58,7 +58,7 @@ interface LoadedResult {
detail: MeetCallDetail | null;
}
export function HistoryDetail({ record }: HistoryDetailProps) {
function HistoryDetail({ record }: HistoryDetailProps) {
const { t } = useT();
// Keyed state: bundles status+detail with the request_id they belong to.
+1 -1
View File
@@ -212,7 +212,7 @@ function formatRelativeTime(ms: number, t: (key: string) => string): string {
}
}
export function HistoryRail({
function HistoryRail({
groups,
selectedId,
onSelect,

Some files were not shown because too many files have changed in this diff Show More