Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 95 additions & 0 deletions app/_components/toolkit-docs/components/available-tools-filter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import type { AvailableToolsTableProps, BehaviorFlagKey } from "../types";
import { normalizeScopes } from "./scopes-display";

export type AvailableToolsFilter =
| "all"
| "has_scopes"
| "no_scopes"
| "has_secrets"
| "no_secrets";

export type FilterToolsOptions = {
activeOperations?: Set<string>;
behaviorFlags?: Partial<Record<BehaviorFlagKey, boolean>>;
};

function buildScopeDisplayItems(scopes: string[]): string[] {
return normalizeScopes(scopes);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactoring left buildScopeDisplayItems as orphaned dead code

Low Severity

The extraction of filter logic into available-tools-filter.ts created a new private buildScopeDisplayItems function, but the original exported buildScopeDisplayItems in available-tools-table.tsx was left behind. Its only caller (matchesFilterCategory) was moved to the new file, making it dead code. No file in the codebase imports buildScopeDisplayItems from available-tools-table.tsx. The new file could import and reuse the existing exported function instead of duplicating it.

Additional Locations (1)

Fix in Cursor Fix in Web


function matchesFilterCategory(
tool: AvailableToolsTableProps["tools"][number],
filter: AvailableToolsFilter
): boolean {
const hasScopes = buildScopeDisplayItems(tool.scopes ?? []).length > 0;
const hasSecrets =
(tool.secretsInfo?.length ?? 0) > 0 || (tool.secrets?.length ?? 0) > 0;

switch (filter) {
case "has_scopes":
return hasScopes;
case "no_scopes":
return !hasScopes;
case "has_secrets":
return hasSecrets;
case "no_secrets":
return !hasSecrets;
default:
return true;
}
}

function matchesOperations(
tool: AvailableToolsTableProps["tools"][number],
activeOperations: Set<string>
): boolean {
if (activeOperations.size === 0) {
return true;
}
const toolOps = tool.metadata?.behavior?.operations ?? [];
return toolOps.some((op) => activeOperations.has(op));
}

function matchesBehaviorFlags(
tool: AvailableToolsTableProps["tools"][number],
behaviorFlags: Partial<Record<BehaviorFlagKey, boolean>>
): boolean {
for (const [key, expected] of Object.entries(behaviorFlags) as [
BehaviorFlagKey,
boolean | undefined,
][]) {
if (expected === undefined) {
continue;
}
if (tool.metadata?.behavior?.[key] !== expected) {
return false;
}
}
return true;
}

export function filterTools(
tools: AvailableToolsTableProps["tools"],
query: string,
filter: AvailableToolsFilter,
options: FilterToolsOptions = {}
): AvailableToolsTableProps["tools"] {
const { activeOperations = new Set(), behaviorFlags = {} } = options;
const normalizedQuery = query.trim().toLowerCase();

return tools.filter((tool) => {
const haystack = [tool.name, tool.qualifiedName, tool.description ?? ""]
.join(" ")
.toLowerCase();
if (normalizedQuery.length > 0 && !haystack.includes(normalizedQuery)) {
return false;
}
if (!matchesFilterCategory(tool, filter)) {
return false;
}
if (!matchesOperations(tool, activeOperations)) {
return false;
}
return matchesBehaviorFlags(tool, behaviorFlags);
});
}
99 changes: 10 additions & 89 deletions app/_components/toolkit-docs/components/available-tools-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,18 @@ import type {
BehaviorFlagKey,
SecretType,
} from "../types";
import {
type AvailableToolsFilter,
filterTools,
} from "./available-tools-filter";
import { normalizeScopes } from "./scopes-display";

export {
type AvailableToolsFilter,
type FilterToolsOptions,
filterTools,
} from "./available-tools-filter";

const DEFAULT_PAGE_SIZE = 25;
const PAGE_SIZE_OPTIONS = [25, 50, 100, 200] as const;

Expand Down Expand Up @@ -226,13 +236,6 @@ export function toToolAnchorId(value: string): string {
return value.toLowerCase().replace(/\s+/g, "-").replace(/\./g, "");
}

export type AvailableToolsFilter =
| "all"
| "has_scopes"
| "no_scopes"
| "has_secrets"
| "no_secrets";

export type AvailableToolsSort =
| "name_asc"
| "name_desc"
Expand Down Expand Up @@ -692,88 +695,6 @@ export function sortTools(
}
}

export type FilterToolsOptions = {
activeOperations?: Set<string>;
behaviorFlags?: Partial<Record<BehaviorFlagKey, boolean>>;
};

function matchesFilterCategory(
tool: AvailableToolsTableProps["tools"][number],
filter: AvailableToolsFilter
): boolean {
const hasScopes = buildScopeDisplayItems(tool.scopes ?? []).length > 0;
const hasSecrets =
(tool.secretsInfo?.length ?? 0) > 0 || (tool.secrets?.length ?? 0) > 0;

switch (filter) {
case "has_scopes":
return hasScopes;
case "no_scopes":
return !hasScopes;
case "has_secrets":
return hasSecrets;
case "no_secrets":
return !hasSecrets;
default:
return true;
}
}

function matchesOperations(
tool: AvailableToolsTableProps["tools"][number],
activeOperations: Set<string>
): boolean {
if (activeOperations.size === 0) {
return true;
}
const toolOps = tool.metadata?.behavior?.operations ?? [];
return toolOps.some((op) => activeOperations.has(op));
}

function matchesBehaviorFlags(
tool: AvailableToolsTableProps["tools"][number],
behaviorFlags: Partial<Record<BehaviorFlagKey, boolean>>
): boolean {
for (const [key, expected] of Object.entries(behaviorFlags) as [
BehaviorFlagKey,
boolean | undefined,
][]) {
if (expected === undefined) {
continue;
}
if (tool.metadata?.behavior?.[key] !== expected) {
return false;
}
}
return true;
}

export function filterTools(
tools: AvailableToolsTableProps["tools"],
query: string,
filter: AvailableToolsFilter,
options: FilterToolsOptions = {}
): AvailableToolsTableProps["tools"] {
const { activeOperations = new Set(), behaviorFlags = {} } = options;
const normalizedQuery = query.trim().toLowerCase();

return tools.filter((tool) => {
const haystack = [tool.name, tool.qualifiedName, tool.description ?? ""]
.join(" ")
.toLowerCase();
if (normalizedQuery.length > 0 && !haystack.includes(normalizedQuery)) {
return false;
}
if (!matchesFilterCategory(tool, filter)) {
return false;
}
if (!matchesOperations(tool, activeOperations)) {
return false;
}
return matchesBehaviorFlags(tool, behaviorFlags);
});
}

/**
* AvailableToolsTable
*
Expand Down
38 changes: 38 additions & 0 deletions app/_components/toolkit-docs/components/toolkit-page-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
export function getSharedServiceDomain(
tools: ReadonlyArray<{
metadata?: {
classification?: {
serviceDomains?: string[];
} | null;
} | null;
}>
): string | null {
if (tools.length === 0) {
return null;
}

let sharedDomain: string | null = null;

for (const tool of tools) {
const serviceDomains = tool.metadata?.classification?.serviceDomains;
if (!serviceDomains || serviceDomains.length !== 1) {
return null;
}

const domain = serviceDomains[0];
if (!domain || typeof domain !== "string") {
return null;
}

if (sharedDomain === null) {
sharedDomain = domain;
continue;
}

if (sharedDomain !== domain) {
return null;
}
}

return sharedDomain;
}
42 changes: 3 additions & 39 deletions app/_components/toolkit-docs/components/toolkit-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ import {
TOOL_METADATA_FALLBACK_STYLE,
TOOL_METADATA_SERVICE_DOMAIN_STYLES,
} from "../constants";
import { getSharedServiceDomain } from "./toolkit-page-utils";

export { getSharedServiceDomain } from "./toolkit-page-utils";

// Scroll detection thresholds
const SCROLL_SHOW_BUTTONS_THRESHOLD = 300;
Expand Down Expand Up @@ -210,45 +213,6 @@ function inferToolkitType(toolkitId: string, type: ToolkitType): ToolkitType {
return type;
}

export function getSharedServiceDomain(
tools: ReadonlyArray<{
metadata?: {
classification?: {
serviceDomains?: string[];
} | null;
} | null;
}>
): string | null {
if (tools.length === 0) {
return null;
}

let sharedDomain: string | null = null;

for (const tool of tools) {
const serviceDomains = tool.metadata?.classification?.serviceDomains;
if (!serviceDomains || serviceDomains.length !== 1) {
return null;
}

const domain = serviceDomains[0];
if (!domain || typeof domain !== "string") {
return null;
}

if (sharedDomain === null) {
sharedDomain = domain;
continue;
}

if (sharedDomain !== domain) {
return null;
}
}

return sharedDomain;
}

function toTitleCaseCategory(category: ToolkitCategory): string {
return category
.split("-")
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
},
"homepage": "https://arcade.dev/",
"dependencies": {
"@arcadeai/design-system": "^3.30.0",
"@arcadeai/design-system": "^3.32.0",
"@mdx-js/mdx": "^3.1.1",
"@mdx-js/react": "^3.1.1",
"@next/third-parties": "16.0.1",
Expand Down
Loading