locatai-ts
Version:
Enterprise-grade AI-powered element locator for Selenium WebDriver - TypeScript implementation
115 lines • 4.09 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.JsonFileLocatorStats = void 0;
const path_1 = __importDefault(require("path"));
const JsonFileHelpers_1 = require("./JsonFileHelpers");
/**
* File-based implementation of ILocatorStats that tracks locator success rates
*/
class JsonFileLocatorStats {
/**
* Creates a new JSON file locator statistics tracker
* @param root Optional root directory path
*/
constructor(root = process.cwd()) {
this._gate = Promise.resolve();
this._stats = { version: 1, entries: [] };
this._cacheDir = path_1.default.join(root, 'LocatAICache');
this._filePath = path_1.default.join(this._cacheDir, 'locatai_stats.json');
this._init();
}
/**
* Initialize the stats by loading from disk
*/
async _init() {
await (0, JsonFileHelpers_1.ensureDir)(this._cacheDir);
this._stats = await (0, JsonFileHelpers_1.readJson)(this._filePath, { version: 1, entries: [] });
}
/**
* Execute a function with lock to prevent concurrent file access
* @param work Function to execute
* @returns Result of the function
*/
async _lock(work) {
const prev = this._gate;
let release;
this._gate = new Promise(r => (release = r));
await prev;
try {
const result = await work();
await (0, JsonFileHelpers_1.writeJson)(this._filePath, this._stats);
return result;
}
finally {
release();
}
}
/**
* @inheritdoc
*/
async recordAttempt(url, query, domHash, strategy, value, success) {
return this._lock(async () => {
let entry = this._stats.entries.find(e => e.url === url && e.query === query && e.dom === domHash);
if (!entry) {
entry = { url, query, dom: domHash, locators: [] };
this._stats.entries.push(entry);
}
let locator = entry.locators.find(l => l.strategy === strategy && l.value === value);
if (!locator) {
locator = { strategy, value, success: 0, failure: 0 };
entry.locators.push(locator);
}
success ? locator.success++ : locator.failure++;
const attempts = locator.success + locator.failure;
const rate = attempts === 0 ? 0 : locator.success / attempts;
// Prune bad locators (those with >=3 attempts and <30% success rate)
if (attempts >= 3 && rate < 0.30) {
entry.locators = entry.locators.filter(l => l !== locator);
}
return rate;
});
}
/**
* @inheritdoc
*/
async removeLocator(url, query, domHash, strategy, value) {
await this._lock(async () => {
const entry = this._stats.entries.find(e => e.url === url && e.query === query && e.dom === domHash);
if (entry) {
entry.locators = entry.locators.filter(l => !(l.strategy === strategy && l.value === value));
}
});
}
/**
* @inheritdoc
*/
async getAll() {
await this._gate;
const result = [];
for (const entry of this._stats.entries) {
for (const locator of entry.locators) {
const key = `${locator.strategy}=${locator.value}`;
const total = locator.success + locator.failure;
result.push({
locator: key,
total: total,
successes: locator.success
});
}
}
return result;
}
/**
* @inheritdoc
*/
async clear() {
await this._lock(async () => {
this._stats.entries = [];
});
}
}
exports.JsonFileLocatorStats = JsonFileLocatorStats;
//# sourceMappingURL=JsonFileLocatorStats.js.map