@mondaydotcomorg/atp-client
Version:
Client SDK for Agent Tool Protocol
114 lines • 3.23 kB
JavaScript
/**
* Provenance Token Registry for Client
*
* Stores and manages provenance tokens for multi-step tracking
*/
export class ProvenanceTokenRegistry {
cache = new Map();
maxSize;
ttl;
sequenceCounter = 0;
constructor(maxSize = 10000, ttlHours = 1) {
this.maxSize = maxSize;
this.ttl = ttlHours * 3600 * 1000;
}
/**
* Add a token to the registry
*/
add(token) {
// Evict expired tokens first
this.evictExpired();
// Check if at capacity and evict LRU if needed
if (this.cache.size >= this.maxSize) {
this.evictLRU();
}
// Store token with sequence number for stable ordering
this.cache.set(token, {
token,
addedAt: Date.now(),
sequence: this.sequenceCounter++,
});
}
/**
* Get recent tokens (non-expired, sorted by age, limited)
* Returns tokens in chronological order (oldest first, most recent last)
*/
getRecentTokens(maxCount = 1000) {
if (maxCount <= 0) {
return [];
}
this.evictExpired();
const now = Date.now();
const expiredTokens = [];
const entries = Array.from(this.cache.values())
.filter((entry) => {
try {
const [body] = entry.token.split('.');
if (!body) {
expiredTokens.push(entry.token);
return false;
}
const payload = JSON.parse(Buffer.from(body, 'base64url').toString());
if (!payload.expiresAt || payload.expiresAt <= now) {
expiredTokens.push(entry.token);
return false;
}
return true;
}
catch {
expiredTokens.push(entry.token);
return false;
}
})
.sort((a, b) => a.sequence - b.sequence)
.slice(-maxCount);
for (const token of expiredTokens) {
this.cache.delete(token);
}
return entries.map((e) => e.token);
}
/**
* Clear all tokens
*/
clear() {
this.cache.clear();
}
/**
* Get registry size
*/
size() {
return this.cache.size;
}
/**
* Evict expired tokens
*/
evictExpired() {
const now = Date.now();
const toDelete = [];
for (const [token, entry] of this.cache.entries()) {
if (now - entry.addedAt > this.ttl) {
toDelete.push(token);
}
}
for (const token of toDelete) {
this.cache.delete(token);
}
}
/**
* Evict least recently used (oldest) token
*/
evictLRU() {
let oldestToken = null;
let oldestSequence = Infinity;
for (const [token, entry] of this.cache.entries()) {
if (entry.sequence < oldestSequence) {
oldestSequence = entry.sequence;
oldestToken = token;
}
}
if (oldestToken) {
this.cache.delete(oldestToken);
}
}
}
//# sourceMappingURL=provenance-registry.js.map