Vocabulary System
The playwright-praman/vocabulary sub-path provides a controlled vocabulary system for SAP S/4HANA business term resolution. It maps natural-language terms to UI5 selectors with fuzzy matching, synonym resolution, and cross-domain search.
Overview
import { createVocabularyService } from 'playwright-praman/vocabulary';
const svc = createVocabularyService();
await svc.loadDomain('procurement');
const results = await svc.search('vendor');
SAP Domain JSON Files
The vocabulary system ships with 6 SAP domain JSON files in src/vocabulary/domains/:
| File | Domain | SAP Module | Description |
|---|---|---|---|
procurement.json | procurement | MM | Materials Management -- vendors, POs, GR |
sales.json | sales | SD | Sales & Distribution -- customers, SOs, deliveries |
finance.json | finance | FI | Financial Accounting -- GL, AP, AR |
manufacturing.json | manufacturing | PP | Production Planning -- orders, BOMs, routings |
warehouse.json | warehouse | WM/EWM | Warehouse Management -- storage, picking |
quality.json | quality | QM | Quality Management -- inspections, lots |
Each JSON file contains vocabulary terms with synonyms and optional UI5 selectors:
{
"supplier": {
"name": "supplier",
"synonyms": ["vendor", "vendorId", "supplierId", "LIFNR"],
"domain": "procurement",
"sapField": "LIFNR",
"selector": {
"controlType": "sap.m.Input",
"properties": { "labelFor": "Supplier" }
}
}
}
VocabularyService API
Creating the Service
import { createVocabularyService } from 'playwright-praman/vocabulary';
import type { VocabularyService } from 'playwright-praman/vocabulary';
const svc: VocabularyService = createVocabularyService();
Loading Domains
Domains are loaded lazily on demand:
await svc.loadDomain('procurement');
await svc.loadDomain('finance');
// Only procurement and finance terms are in memory
Searching Terms
// Search across all loaded domains
const results = await svc.search('vendor');
// Search within a specific domain
const results = await svc.search('vendor', 'procurement');
Returns VocabularySearchResult[] sorted by confidence descending:
interface VocabularySearchResult {
readonly term: string; // 'supplier'
readonly synonyms: string[]; // ['vendor', 'vendorId', 'supplierId']
readonly confidence: number; // 0.0 to 1.0
readonly domain: SAPDomain; // 'procurement'
readonly sapField?: string; // 'LIFNR'
readonly selector?: UI5Selector;
}
Resolving Field Selectors
When a term matches with high enough confidence (>= 0.85), you can get its UI5 selector directly:
const selector = await svc.getFieldSelector('vendor', 'procurement');
if (selector) {
// { controlType: 'sap.m.Input', properties: { labelFor: 'Supplier' } }
await ui5.fill(selector, '100001');
}
Returns undefined when:
- No match reaches the 0.85 confidence threshold.
- Multiple matches score above 0.7 but below 0.85 (ambiguous).
Getting Suggestions
For autocomplete and disambiguation:
const suggestions = await svc.getSuggestions('sup');
// ['supplier', 'supplierName', 'supplyPlant', ...]
// Limit results
const top3 = await svc.getSuggestions('sup', 3);
Service Statistics
const stats = svc.getStats();
// {
// loadedDomains: ['procurement', 'sales'],
// totalTerms: 142,
// cacheHits: 37,
// cacheMisses: 5,
// }
Normalization and Matching Algorithm
The vocabulary matcher uses a tiered scoring system:
Match Tiers
| Tier | Confidence | Criteria |
|---|---|---|
| Exact | 1.0 | Query exactly matches term name or synonym (case-insensitive) |
| Prefix | 0.9 | Term name starts with the query string |
| Partial | 0.7 | Term name contains the query string |
| Fuzzy | 0.5 | Levenshtein distance <= 3 characters |
Normalization
Before matching, both the query and term names are normalized:
- Converted to lowercase
- Leading/trailing whitespace trimmed
Levenshtein Distance
The fuzzy matching tier uses Levenshtein edit distance (standard DP matrix approach). Terms within 3 edits of the query are considered fuzzy matches:
levenshtein('vendor', 'vendro') = 2 --> Fuzzy match (0.5)
levenshtein('vendor', 'vend') = 2 --> Fuzzy match (0.5)
levenshtein('vendor', 'xyz') = 6 --> No match
Scoring Priority
When multiple terms match, results are sorted by:
- Confidence score (descending)
- Within the same confidence tier, exact matches on synonyms score the same as exact matches on the canonical name
Disambiguation
The getFieldSelector() method includes disambiguation logic. If there are multiple high-confidence matches (0.7-0.85 range) without a clear winner, the method returns undefined rather than guessing, allowing the caller to present options to the user or AI agent.
Integration with Intents
The vocabulary system integrates with the intent API through the VocabLookup interface:
import { fillField } from 'playwright-praman/intents';
import { createVocabularyService } from 'playwright-praman/vocabulary';
const vocab = createVocabularyService();
await vocab.loadDomain('procurement');
// fillField uses vocab to resolve 'Vendor' to a UI5 selector
await fillField(ui5, vocab, 'Vendor', '100001', { domain: 'procurement' });
Supported Domain Types
type SAPDomain =
| 'procurement' // MM - Materials Management
| 'sales' // SD - Sales & Distribution
| 'finance' // FI - Financial Accounting
| 'manufacturing' // PP - Production Planning
| 'warehouse' // WM/EWM - Warehouse Management
| 'quality'; // QM - Quality Management
Extending the Vocabulary
To add terms to an existing domain, edit the corresponding JSON file in src/vocabulary/domains/. Each term must have:
name-- canonical term name (used as the Map key)synonyms-- array of alternative namesdomain-- must match one of the 6SAPDomainvaluessapField(optional) -- the underlying ABAP field nameselector(optional) -- UI5 selector for direct control discovery