@fission-ai/openspec
Version:
AI-native system for spec-driven development
102 lines • 3.1 kB
JavaScript
import { getActiveChangeIds, getSpecIds } from '../../utils/item-discovery.js';
/**
* Provides dynamic completion suggestions for OpenSpec items (changes and specs).
* Implements a 2-second cache to avoid excessive file system operations during
* tab completion.
*/
export class CompletionProvider {
cacheTTLMs;
projectRoot;
cacheTTL;
changeCache = null;
specCache = null;
/**
* Creates a new completion provider
*
* @param cacheTTLMs - Cache time-to-live in milliseconds (default: 2000ms)
* @param projectRoot - Project root directory (default: process.cwd())
*/
constructor(cacheTTLMs = 2000, projectRoot = process.cwd()) {
this.cacheTTLMs = cacheTTLMs;
this.projectRoot = projectRoot;
this.cacheTTL = cacheTTLMs;
}
/**
* Get all active change IDs for completion
*
* @returns Array of change IDs
*/
async getChangeIds() {
const now = Date.now();
// Check if cache is valid
if (this.changeCache && now - this.changeCache.timestamp < this.cacheTTL) {
return this.changeCache.data;
}
// Fetch fresh data
const changeIds = await getActiveChangeIds(this.projectRoot);
// Update cache
this.changeCache = {
data: changeIds,
timestamp: now,
};
return changeIds;
}
/**
* Get all spec IDs for completion
*
* @returns Array of spec IDs
*/
async getSpecIds() {
const now = Date.now();
// Check if cache is valid
if (this.specCache && now - this.specCache.timestamp < this.cacheTTL) {
return this.specCache.data;
}
// Fetch fresh data
const specIds = await getSpecIds(this.projectRoot);
// Update cache
this.specCache = {
data: specIds,
timestamp: now,
};
return specIds;
}
/**
* Get both change and spec IDs for completion
*
* @returns Object with changeIds and specIds arrays
*/
async getAllIds() {
const [changeIds, specIds] = await Promise.all([
this.getChangeIds(),
this.getSpecIds(),
]);
return { changeIds, specIds };
}
/**
* Clear all cached data
*/
clearCache() {
this.changeCache = null;
this.specCache = null;
}
/**
* Get cache statistics for debugging
*
* @returns Cache status information
*/
getCacheStats() {
const now = Date.now();
return {
changeCache: {
valid: this.changeCache !== null && now - this.changeCache.timestamp < this.cacheTTL,
age: this.changeCache ? now - this.changeCache.timestamp : undefined,
},
specCache: {
valid: this.specCache !== null && now - this.specCache.timestamp < this.cacheTTL,
age: this.specCache ? now - this.specCache.timestamp : undefined,
},
};
}
}
//# sourceMappingURL=completion-provider.js.map