Skip to content

Commit 4d1b041

Browse files
committed
New feature: Enables filtering for class info
Adds filtering capabilities to the SFCC class information tool. This allows users to narrow down search results based on various criteria such as including/excluding descriptions, constants, properties, methods, and inheritance. Also introduces a search parameter to filter results by a specific term. The changes include modifications to the tool's parameters, the documentation client, and the tool configuration. Adds an example to the documentation site showing off filtering. Programmatic tests for documentation mode are included.
1 parent 77dfda8 commit 4d1b041

File tree

9 files changed

+1474
-22
lines changed

9 files changed

+1474
-22
lines changed

docs-site/pages/ExamplesPage.tsx

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,40 @@ Minimal Access Snippet:
131131
</div>
132132
</SectionCard>
133133

134+
<SectionCard
135+
id="focused-class-exploration"
136+
title="Focused Class Exploration with Filtering"
137+
icon="🔍"
138+
gradient="from-emerald-50 via-white to-teal-50"
139+
subtitle="Use enhanced filtering and search to find exactly what you need from SFCC classes."
140+
>
141+
<PromptBlock prompt="I need to understand only the getter methods in dw.catalog.Product that relate to pricing or availability. Don't show me everything." intent="Targeted exploration with precise filtering" />
142+
<div className="mb-4 flex flex-wrap gap-2">
143+
<ModeBadge>Docs Mode</ModeBadge>
144+
</div>
145+
<StepsList steps={[
146+
{ label: 'Show only methods with price-related terms', tool: 'get_sfcc_class_info {"className": "dw.catalog.Product", "includeProperties": false, "includeConstants": false, "includeDescription": false, "includeInheritance": false, "search": "price"}', mode: 'docs' },
147+
{ label: 'Show only methods with availability terms', tool: 'get_sfcc_class_info {"className": "dw.catalog.Product", "includeProperties": false, "includeConstants": false, "includeDescription": false, "includeInheritance": false, "search": "availab"}', mode: 'docs' },
148+
{ label: 'Compare with full getter methods', tool: 'get_sfcc_class_info {"className": "dw.catalog.Product", "includeProperties": false, "includeConstants": false, "includeDescription": false, "includeInheritance": false, "search": "get"}', mode: 'docs', note: 'See complete getter landscape' }
149+
]} />
150+
<div className="mt-6">
151+
<p className="text-sm font-semibold text-slate-700 mb-2">Focused Results (price-related methods only):</p>
152+
<CodeBlock language="markdown" code={`### dw.catalog.Product - Price Methods Only
153+
154+
**Methods:**
155+
• getPriceModel() : PriceModel - Returns pricing model for current product
156+
• getPriceModel(ProductOptionModel) : PriceModel - Returns pricing with option adjustments
157+
158+
**Key Benefits:**
159+
- Clean, targeted view without noise from 50+ other methods
160+
- Focus on exactly what's needed for pricing logic
161+
- Search functionality quickly surfaces relevant APIs`} />
162+
<div className="mt-4 p-3 bg-blue-50 rounded-lg">
163+
<p className="text-sm text-blue-800"><strong>Pro Tip:</strong> Use <code>search</code> parameter with partial terms like "get", "set", "price", "availab" to quickly find relevant methods. Combine with <code>includeProperties: false</code> to focus only on methods.</p>
164+
</div>
165+
</div>
166+
</SectionCard>
167+
134168
<SectionCard
135169
id="controller-from-docs"
136170
title="Generate a Controller from Documentation Context"

docs-site/utils/toolsData.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,25 @@ export const tools: ToolMeta[] = [
3939
name: 'get_sfcc_class_info',
4040
category: 'Documentation',
4141
mode: 'both',
42-
description: 'Detailed information about an SFCC class: properties, methods, descriptions.',
43-
params: [p('className', "SFCC class (e.g. 'Catalog' or 'dw.catalog.Catalog')"), p('expand', 'Include referenced type details (boolean)', false)],
42+
description: 'Detailed information about an SFCC class with filtering and search capabilities: properties, methods, descriptions.',
43+
params: [
44+
p('className', "SFCC class (e.g. 'Catalog' or 'dw.catalog.Catalog')"),
45+
p('expand', 'Include referenced type details (boolean)', false),
46+
p('includeDescription', 'Include class description (boolean, default: true)', false),
47+
p('includeConstants', 'Include class constants (boolean, default: true)', false),
48+
p('includeProperties', 'Include class properties (boolean, default: true)', false),
49+
p('includeMethods', 'Include class methods (boolean, default: true)', false),
50+
p('includeInheritance', 'Include inheritance info (boolean, default: true)', false),
51+
p('search', 'Filter results by search term (string)', false)
52+
],
4453
examples: [
4554
'Show methods and properties on dw.catalog.Product',
46-
'Explain dw.system.Status class and give usage examples'
55+
'Show only methods for dw.system.Status class',
56+
'Search for "get" methods in dw.catalog.Product',
57+
'Show dw.order.Order class without description or constants',
58+
'Find "name" related properties and methods in dw.catalog.Product'
4759
],
48-
tags: ['api','classes','introspection'],
60+
tags: ['api','classes','introspection','filtering','search'],
4961
popular: true
5062
},
5163
{ id: 'search-sfcc-classes', name: 'search_sfcc_classes', category: 'Documentation', mode: 'both', description: 'Search SFCC classes by partial name (single word).', params: [p('query', 'Search term (single word)')], examples: ['Find classes related to price','Search for catalog classes'], tags: ['search'], popular: true },

src/clients/docs-client.ts

Lines changed: 115 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,15 @@ export interface SFCCClassDetails {
5858
constructorInfo?: string;
5959
}
6060

61+
export interface ClassDetailsFilterOptions {
62+
includeDescription?: boolean;
63+
includeConstants?: boolean;
64+
includeProperties?: boolean;
65+
includeMethods?: boolean;
66+
includeInheritance?: boolean;
67+
search?: string;
68+
}
69+
6170
export class SFCCDocumentationClient {
6271
private docsPath: string;
6372
private classCache: Map<string, SFCCClassInfo> = new Map();
@@ -636,29 +645,49 @@ export class SFCCDocumentationClient {
636645
}
637646

638647
/**
639-
* Get class details with optional expansion of referenced types
648+
* Get class details with optional expansion of referenced types and filtering
640649
*/
641-
async getClassDetailsExpanded(className: string, expand: boolean = false):
642-
Promise<SFCCClassDetails & { referencedTypes?: SFCCClassDetails[] } | null> {
643-
// Check cache first for expanded details
644-
const cacheKey = `details-expanded:${className}:${expand}`;
650+
async getClassDetailsExpanded(
651+
className: string,
652+
expand: boolean = false,
653+
filterOptions?: ClassDetailsFilterOptions,
654+
): Promise<SFCCClassDetails & { referencedTypes?: SFCCClassDetails[] } | null> {
655+
// Set default filter options
656+
const filters = {
657+
includeDescription: filterOptions?.includeDescription ?? true,
658+
includeConstants: filterOptions?.includeConstants ?? true,
659+
includeProperties: filterOptions?.includeProperties ?? true,
660+
includeMethods: filterOptions?.includeMethods ?? true,
661+
includeInheritance: filterOptions?.includeInheritance ?? true,
662+
search: filterOptions?.search,
663+
};
664+
665+
// Check cache first for expanded details with filter options
666+
const cacheKey = `details-expanded:${className}:${expand}:${JSON.stringify(filters)}`;
645667
const cachedResult = this.cacheManager.getClassDetails(cacheKey);
646668
if (cachedResult !== undefined) {
647669
return cachedResult;
648670
}
649671

650672
const classDetails = await this.getClassDetails(className);
651-
if (!classDetails || !expand) {
652-
const result = classDetails;
653-
this.cacheManager.setClassDetails(cacheKey, result);
654-
return result;
673+
if (!classDetails) {
674+
this.cacheManager.setClassDetails(cacheKey, null);
675+
return null;
676+
}
677+
678+
// Apply filtering and search to the class details
679+
const filteredDetails = this.applyFiltersAndSearch(classDetails, filters);
680+
681+
if (!expand) {
682+
this.cacheManager.setClassDetails(cacheKey, filteredDetails);
683+
return filteredDetails;
655684
}
656685

657686
// Get the raw content to extract referenced types
658687
const content = await this.getClassDocumentation(className);
659688
if (!content) {
660-
this.cacheManager.setClassDetails(cacheKey, classDetails);
661-
return classDetails;
689+
this.cacheManager.setClassDetails(cacheKey, filteredDetails);
690+
return filteredDetails;
662691
}
663692

664693
const referencedTypeNames = this.extractReferencedTypes(content);
@@ -684,7 +713,7 @@ export class SFCCDocumentationClient {
684713
}
685714

686715
const result = {
687-
...classDetails,
716+
...filteredDetails,
688717
referencedTypes: referencedTypes.length > 0 ? referencedTypes : undefined,
689718
};
690719

@@ -694,6 +723,80 @@ export class SFCCDocumentationClient {
694723
return result;
695724
}
696725

726+
/**
727+
* Apply filters and search to class details
728+
*/
729+
private applyFiltersAndSearch(
730+
classDetails: SFCCClassDetails,
731+
filters: {
732+
includeDescription: boolean;
733+
includeConstants: boolean;
734+
includeProperties: boolean;
735+
includeMethods: boolean;
736+
includeInheritance: boolean;
737+
search?: string;
738+
},
739+
): SFCCClassDetails {
740+
const result: SFCCClassDetails = {
741+
className: classDetails.className,
742+
packageName: classDetails.packageName,
743+
description: filters.includeDescription ? classDetails.description : '',
744+
constants: [],
745+
properties: [],
746+
methods: [],
747+
inheritance: filters.includeInheritance ? classDetails.inheritance : undefined,
748+
constructorInfo: classDetails.constructorInfo,
749+
};
750+
751+
// Apply search filter to constants
752+
if (filters.includeConstants) {
753+
result.constants = filters.search
754+
? classDetails.constants.filter(constant =>
755+
this.matchesSearch(constant.name, constant.description, filters.search!),
756+
)
757+
: classDetails.constants;
758+
}
759+
760+
// Apply search filter to properties
761+
if (filters.includeProperties) {
762+
result.properties = filters.search
763+
? classDetails.properties.filter(property =>
764+
this.matchesSearch(property.name, property.description, filters.search!),
765+
)
766+
: classDetails.properties;
767+
}
768+
769+
// Apply search filter to methods
770+
if (filters.includeMethods) {
771+
result.methods = filters.search
772+
? classDetails.methods.filter(method =>
773+
this.matchesSearch(method.name, method.description, filters.search!) ||
774+
this.matchesSearch(method.signature, '', filters.search!),
775+
)
776+
: classDetails.methods;
777+
}
778+
779+
// Apply search filter to inheritance
780+
if (filters.includeInheritance && filters.search && result.inheritance) {
781+
result.inheritance = result.inheritance.filter(inheritanceItem =>
782+
this.matchesSearch(inheritanceItem, '', filters.search!),
783+
);
784+
}
785+
786+
return result;
787+
}
788+
789+
/**
790+
* Check if a name or description matches the search term (case-insensitive)
791+
*/
792+
private matchesSearch(name: string, description: string, searchTerm: string): boolean {
793+
const search = searchTerm.toLowerCase();
794+
return (
795+
name.toLowerCase().includes(search) ||
796+
description.toLowerCase().includes(search)
797+
);
798+
}
799+
697800
/**
698801
* Search for methods across all classes
699802
*/

src/core/tool-definitions.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,35 @@ export const SFCC_DOCUMENTATION_TOOLS = [
2121
description: 'Whether to include detailed information about referenced types used by this class (default: false)',
2222
default: false,
2323
},
24+
includeDescription: {
25+
type: 'boolean',
26+
description: 'Whether to include the class description in the response (default: true)',
27+
default: true,
28+
},
29+
includeConstants: {
30+
type: 'boolean',
31+
description: 'Whether to include constants in the response (default: true)',
32+
default: true,
33+
},
34+
includeProperties: {
35+
type: 'boolean',
36+
description: 'Whether to include properties in the response (default: true)',
37+
default: true,
38+
},
39+
includeMethods: {
40+
type: 'boolean',
41+
description: 'Whether to include methods in the response (default: true)',
42+
default: true,
43+
},
44+
includeInheritance: {
45+
type: 'boolean',
46+
description: 'Whether to include inheritance hierarchy in the response (default: true)',
47+
default: true,
48+
},
49+
search: {
50+
type: 'string',
51+
description: 'Optional search term to filter constants, properties, methods, and inheritance entries. Case-insensitive search across names and descriptions. Only one word at a time (e.g., "get", "create", "order"). Combining multiple words or looking for multiple items at the same time is not supported.',
52+
},
2453
},
2554
required: ['className'],
2655
},

src/tool-configs/docs-tool-config.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,37 @@ export const DOCS_TOOL_CONFIG: Record<DocToolName, GenericToolSpec<ToolArguments
2323
defaults: (args: ToolArguments) => ({
2424
...args,
2525
expand: args.expand ?? false,
26+
includeDescription: args.includeDescription ?? true,
27+
includeConstants: args.includeConstants ?? true,
28+
includeProperties: args.includeProperties ?? true,
29+
includeMethods: args.includeMethods ?? true,
30+
includeInheritance: args.includeInheritance ?? true,
31+
search: args.search ?? undefined,
2632
}),
2733
validate: (args: ToolArguments, toolName: string) => {
2834
ValidationHelpers.validateArguments(args, CommonValidations.requiredString('className'), toolName);
2935
},
3036
exec: async (args: ToolArguments, context: ToolExecutionContext) => {
3137
const client = context.docsClient as SFCCDocumentationClient;
32-
const result = await client.getClassDetailsExpanded(args.className as string, args.expand as boolean);
38+
const result = await client.getClassDetailsExpanded(
39+
args.className as string,
40+
args.expand as boolean,
41+
{
42+
includeDescription: args.includeDescription as boolean,
43+
includeConstants: args.includeConstants as boolean,
44+
includeProperties: args.includeProperties as boolean,
45+
includeMethods: args.includeMethods as boolean,
46+
includeInheritance: args.includeInheritance as boolean,
47+
search: args.search as string | undefined,
48+
},
49+
);
3350
if (!result) {
3451
throw new Error(`Class "${args.className}" not found`);
3552
}
3653
return result;
3754
},
3855
logMessage: (args: ToolArguments) =>
39-
`Class info ${args.className} expand=${args.expand ?? false}`,
56+
`Class info ${args.className} expand=${args.expand ?? false} ${args.search ? `search="${args.search}"` : ''}`,
4057
},
4158

4259
search_sfcc_classes: {

0 commit comments

Comments
 (0)