diff --git a/.github/skills/README.md b/.github/skills/README.md index 2671c2c..fc482d4 100644 --- a/.github/skills/README.md +++ b/.github/skills/README.md @@ -32,6 +32,24 @@ Agent Skills are directories containing a `SKILL.md` file and optional supportin - Schema documentation references - Usage examples and troubleshooting guides +### load-cache-data + +**Purpose**: Load and inspect the last 10 rows from the local session file cache to iterate with real data. + +**Use this skill when:** +- Inspecting cached session file data +- Debugging cache behavior or validation logic +- Understanding what data is being cached +- Working with real cached data for testing or development +- Iterating on features that rely on cached statistics + +**Contents:** +- Cache structure and storage location (VS Code globalState) +- Methods for accessing and managing the cache +- Example scripts demonstrating cache data access +- Cache validation and lifecycle documentation +- Integration with the extension's token tracking + ## Using Agent Skills ### In VS Code diff --git a/.github/skills/load-cache-data/README.md b/.github/skills/load-cache-data/README.md new file mode 100644 index 0000000..378e357 --- /dev/null +++ b/.github/skills/load-cache-data/README.md @@ -0,0 +1,78 @@ +# Load Cache Data Skill - Quick Reference + +This skill provides tools and documentation for accessing the GitHub Copilot Token Tracker's local session file cache. + +## Quick Start + +```bash +# Show last 10 cache entries (default) +node .github/skills/load-cache-data/load-cache-data.js + +# Show last 5 entries +node .github/skills/load-cache-data/load-cache-data.js --last 5 + +# Output as JSON +node .github/skills/load-cache-data/load-cache-data.js --json + +# Show help +node .github/skills/load-cache-data/load-cache-data.js --help +``` + +## What This Skill Does + +1. **Reads actual cache data** - Loads real cache data from export files on disk +2. **Multiple search locations** - Checks VS Code globalStorage, temp directory, and current directory +3. **Helps debugging** - Inspect what's being cached and when +4. **Supports development** - Iterate with real data structures when building features + +## Cache File Locations + +The script searches for cache export files in these locations (in order): + +**Windows:** +- `%APPDATA%\Code\User\globalStorage\rajbos.copilot-token-tracker\cache.json` +- `%TEMP%\copilot-token-tracker-cache.json` +- `.\cache-export.json` + +**macOS:** +- `~/Library/Application Support/Code/User/globalStorage/rajbos.copilot-token-tracker/cache.json` +- `/tmp/copilot-token-tracker-cache.json` +- `./cache-export.json` + +**Linux:** +- `~/.config/Code/User/globalStorage/rajbos.copilot-token-tracker/cache.json` +- `/tmp/copilot-token-tracker-cache.json` +- `./cache-export.json` + +*Note: Also checks other VS Code variants (Insiders, Cursor, VSCodium, Code - Exploration)* + +## Important Note + +The extension stores its cache in VS Code's internal globalState (SQLite database `state.vscdb`), which is not directly accessible from external scripts. To use this skill with real data: + +1. **Export from extension**: Add functionality to export cache to disk +2. **Export from tests**: Test code can write cache data to one of the expected locations +3. **Manual export**: Extract cache from globalState and save to disk + +To access real cache data, use the extension's API: + +```typescript +// In extension.ts or any file with access to ExtensionContext +const cacheData = context.globalState.get>('sessionFileCache'); +const entries = Object.entries(cacheData || {}); + +// Sort by most recent +entries.sort((a, b) => (b[1].mtime || 0) - (a[1].mtime || 0)); + +// Get last 10 +const last10 = entries.slice(0, 10); +``` + +## Full Documentation + +See [SKILL.md](./SKILL.md) for complete documentation including: +- Cache structure details +- Integration with extension code +- Cache management methods +- Troubleshooting guide +- Example use cases diff --git a/.github/skills/load-cache-data/SKILL.md b/.github/skills/load-cache-data/SKILL.md new file mode 100644 index 0000000..61084db --- /dev/null +++ b/.github/skills/load-cache-data/SKILL.md @@ -0,0 +1,351 @@ +--- +name: load-cache-data +description: Load and display the last 10 cache entries as raw JSON output. DO NOT create extra files or pretty-print the data - output raw JSON only. Use when you need to understand cached session statistics, debug cache behavior, or work with actual cached data. +--- + +# Load Cache Data Skill + +**IMPORTANT: Always output raw JSON only. Do not create extra files for displaying data.** + +This skill helps you access and inspect the GitHub Copilot Token Tracker's local session file cache. The cache stores pre-computed statistics for session files to avoid re-processing unchanged files. + +## Overview + +The extension maintains a local cache of session file statistics in VS Code's `globalState`. This cache contains: +- Token counts (total and per-model) +- Interaction counts +- Model usage breakdowns +- File modification times (for cache validation) +- Usage analysis data (tool calls, mode usage, context references) + +## When to Use This Skill + +Use this skill when you need to: +- Inspect cached session file data +- Debug cache behavior or validation logic +- Understand what data is being cached +- Work with real cached data for testing or development +- Iterate on features that rely on cached statistics + +## Output Requirements + +**CRITICAL**: When using this skill: +- **ALWAYS** use the `--json` flag to output raw JSON +- **NEVER** create extra files just for displaying data +- **DO NOT** pretty-print or format the output in human-readable text +- Simply run the script with `--json` and display the raw JSON output + +## Cache Structure + +The cache is stored in VS Code's global state under the key `'sessionFileCache'`. Each cache entry is keyed by the absolute file path and contains: + +```typescript +interface SessionFileCache { + tokens: number; // Total token count + interactions: number; // Number of interactions + modelUsage: ModelUsage; // Per-model token breakdown + mtime: number; // File modification timestamp + usageAnalysis?: SessionUsageAnalysis; // Detailed usage statistics +} + +interface ModelUsage { + [model: string]: { + inputTokens: number; + outputTokens: number; + }; +} + +interface SessionUsageAnalysis { + toolCalls: ToolCallUsage; // Tool usage statistics + modeUsage: ModeUsage; // Mode distribution + contextReferences: ContextReferenceUsage; // Context reference counts + mcpTools: McpToolUsage; // MCP tool usage +} +``` + +## Location + +**Cache Storage**: `VS Code globalState → 'sessionFileCache'` +- Accessed via: `context.globalState.get>('sessionFileCache')` +- Persisted automatically by VS Code +- Lives in VS Code's internal database (`state.vscdb`) + +**Implementation**: `src/extension.ts` (lines 74-80, 194, 336-360) + +## How to Access the Cache + +### From Within the Extension + +The cache can be accessed through the extension's context at runtime: + +```typescript +// Load cache from global state +const cacheData = context.globalState.get>('sessionFileCache'); +const cacheEntries = Object.entries(cacheData || {}); + +// Get last 10 entries (sorted by modification time) +const last10 = cacheEntries + .sort((a, b) => (b[1].mtime || 0) - (a[1].mtime || 0)) + .slice(0, 10); + +// Display cache entries +for (const [filePath, cacheEntry] of last10) { + console.log({ + file: filePath, + tokens: cacheEntry.tokens, + interactions: cacheEntry.interactions, + modelUsage: cacheEntry.modelUsage, + lastModified: new Date(cacheEntry.mtime).toISOString() + }); +} +``` + +### Using the Provided Script + +This skill includes an executable script that loads and displays actual cache data from disk: + +**Location**: `.github/skills/load-cache-data/load-cache-data.js` + +**Usage:** +```bash +# RECOMMENDED: Always use --json for raw JSON output +node .github/skills/load-cache-data/load-cache-data.js --json + +# Show last N entries as JSON (default is 10) +node .github/skills/load-cache-data/load-cache-data.js --last 5 --json + +# Show help +node .github/skills/load-cache-data/load-cache-data.js --help +``` + +**Note**: The script supports human-readable output without `--json`, but for LLM skills, always use `--json` to get structured data. + +**What it does:** +- Searches for cache export files in known locations +- Reads actual cache data if a file exists +- Displays cache entries sorted by most recent modification +- Shows detailed token counts, model usage, and usage analysis + +**Cache File Locations:** + +The script searches for cache export files in these locations: + +1. **VS Code globalStorage**: `%APPDATA%\Code\User\globalStorage\rajbos.copilot-token-tracker\cache.json` (Windows) + - Also checks other VS Code variants (Insiders, Cursor, VSCodium, etc.) +2. **Temp directory**: `%TEMP%\copilot-token-tracker-cache.json` +3. **Current directory**: `./cache-export.json` + +**Creating Cache Export Files:** + +Since the extension stores cache in VS Code's globalState (internal SQLite database), the cache data must be explicitly exported to one of the above locations for this script to access it. This can be done: + +1. **Via Extension**: The extension can be enhanced to export cache on demand +2. **Via Tests**: Test code can write cache data to disk for inspection +3. **Manually**: Copy cache data from extension's globalState and save to one of the expected locations + +**Exit Codes:** +- `0`: Cache file found and displayed successfully +- `1`: No cache file found + +**Note**: If no cache file is found, the script will display the searched locations and instructions for exporting cache data. + +## Cache Management Methods + +### Loading Cache +**Method**: `loadCacheFromStorage()` +**Location**: `src/extension.ts` (lines 336-350) + +Loads the cache from VS Code's global state on extension activation: +```typescript +const cacheData = this.context.globalState.get>('sessionFileCache'); +if (cacheData) { + this.sessionFileCache = new Map(Object.entries(cacheData)); +} +``` + +### Saving Cache +**Method**: `saveCacheToStorage()` +**Location**: `src/extension.ts` (lines 352-360) + +Saves the cache to VS Code's global state: +```typescript +const cacheData = Object.fromEntries(this.sessionFileCache); +await this.context.globalState.update('sessionFileCache', cacheData); +``` + +### Cache Validation +**Method**: `isCacheValid()` +**Location**: `src/extension.ts` (lines 285-290) + +Validates cache entries by comparing modification times: +```typescript +private isCacheValid(filePath: string, currentMtime: number): boolean { + const cached = this.sessionFileCache.get(filePath); + return cached !== undefined && cached.mtime === currentMtime; +} +``` + +### Clearing Cache +**Method**: `clearExpiredCache()` +**Location**: `src/extension.ts` (lines 308-333) + +Removes cache entries for files that no longer exist: +```typescript +const sessionFiles = await this.getCopilotSessionFiles(); +const validPaths = new Set(sessionFiles); +for (const [filePath, _] of this.sessionFileCache) { + if (!validPaths.has(filePath)) { + this.sessionFileCache.delete(filePath); + } +} +``` + +## Cache Entry Lifecycle + +1. **Session File Discovery**: Extension finds session files via `getCopilotSessionFiles()` +2. **Cache Check**: For each file, checks if cache is valid via `isCacheValid()` +3. **Read or Compute**: If valid, uses cache; otherwise, reads and parses the file +4. **Cache Update**: New statistics are stored in cache via `setCachedSessionData()` +5. **Persistence**: Cache is saved to global state via `saveCacheToStorage()` +6. **Cleanup**: Expired entries are removed via `clearExpiredCache()` + +## Example Use Cases + +### Example 1: Inspecting Recent Sessions +```typescript +// Get cache data +const cache = context.globalState.get('sessionFileCache'); +const entries = Object.entries(cache || {}); + +// Sort by most recent +entries.sort((a, b) => (b[1].mtime || 0) - (a[1].mtime || 0)); + +// Show top 10 +console.log('Most recent sessions:'); +entries.slice(0, 10).forEach(([path, data], i) => { + console.log(`${i + 1}. ${path.split('/').pop()}`); + console.log(` Tokens: ${data.tokens}, Interactions: ${data.interactions}`); + console.log(` Modified: ${new Date(data.mtime).toLocaleString()}`); +}); +``` + +### Example 2: Analyzing Model Usage in Cache +```typescript +const cache = context.globalState.get('sessionFileCache'); +const modelTotals = {}; + +for (const [path, data] of Object.entries(cache || {})) { + for (const [model, usage] of Object.entries(data.modelUsage)) { + if (!modelTotals[model]) { + modelTotals[model] = { input: 0, output: 0 }; + } + modelTotals[model].input += usage.inputTokens; + modelTotals[model].output += usage.outputTokens; + } +} + +console.log('Cached model usage:'); +for (const [model, totals] of Object.entries(modelTotals)) { + console.log(` ${model}: ${totals.input + totals.output} tokens`); +} +``` + +### Example 3: Cache Statistics +```typescript +const cache = context.globalState.get('sessionFileCache'); +const entries = Object.entries(cache || {}); + +const stats = { + totalEntries: entries.length, + totalTokens: 0, + totalInteractions: 0, + oldestEntry: null, + newestEntry: null +}; + +entries.forEach(([path, data]) => { + stats.totalTokens += data.tokens; + stats.totalInteractions += data.interactions; + + if (!stats.oldestEntry || data.mtime < stats.oldestEntry.mtime) { + stats.oldestEntry = { path, mtime: data.mtime }; + } + if (!stats.newestEntry || data.mtime > stats.newestEntry.mtime) { + stats.newestEntry = { path, mtime: data.mtime }; + } +}); + +console.log('Cache Statistics:', stats); +``` + +## Integration with Extension + +The cache is tightly integrated with the extension's token tracking: + +1. **Session File Processing**: `getSessionFileDataCached()` (lines 1414-1450) + - Checks cache validity + - Reads and parses file if needed + - Updates cache with new data + +2. **Statistics Calculation**: `calculateDetailedStats()` (lines 379-693) + - Uses cached data when available + - Aggregates statistics across all cached sessions + - Includes usage analysis from cache + +3. **Performance Optimization**: + - FIFO cache eviction after 1000 entries (line 305) + - Modification time comparison for validation + - Automatic cleanup of expired entries + +## Troubleshooting + +### Cache Not Loading +**Symptoms**: Extension shows no cached data or logs "No cached session files found" +**Solutions**: +1. Check that session files exist via `getCopilotSessionFiles()` +2. Verify global state is accessible +3. Look for errors in Output channel (GitHub Copilot Token Tracker) + +### Cache Out of Sync +**Symptoms**: Token counts don't match session file contents +**Solutions**: +1. Clear cache via Command Palette: "Clear Cache" +2. Check file modification times +3. Manually refresh via "Refresh Token Usage" command + +### Cache Too Large +**Symptoms**: Extension slow to start or save +**Solutions**: +1. Cache automatically limits to 1000 entries +2. Clear expired entries via `clearExpiredCache()` +3. Manually clear cache if needed + +## Related Files + +1. **Cache implementation**: `src/extension.ts` + - Cache interface definition (lines 74-80) + - Cache management methods (lines 285-360) + - Cache usage in statistics (lines 379-693) + +2. **Session file discovery**: `src/extension.ts` + - Session file discovery (lines 975-1073) + - File scanning logic (lines 1078-1110) + +3. **Session parsing**: `src/sessionParser.ts` + - Session file parsing logic + - Token estimation + - Usage analysis extraction + +4. **Skill script**: `.github/skills/load-cache-data/load-cache-data.js` + - Demonstrates cache structure + - Provides example data + - Shows access patterns + +## Notes + +- Cache is stored in VS Code's internal SQLite database (`state.vscdb`) +- Cache entries are validated by file modification time +- Maximum of 1000 entries maintained (FIFO eviction) +- Cache persists between VS Code sessions +- Clearing cache forces re-processing of all session files +- Cache improves performance significantly for large numbers of session files diff --git a/.github/skills/load-cache-data/load-cache-data.js b/.github/skills/load-cache-data/load-cache-data.js new file mode 100755 index 0000000..d0b6fbc --- /dev/null +++ b/.github/skills/load-cache-data/load-cache-data.js @@ -0,0 +1,316 @@ +#!/usr/bin/env node +/** + * Load Cache Data Script + * + * This script loads and displays the GitHub Copilot Token Tracker's local cache data. + * The cache stores pre-computed session file statistics to avoid re-processing unchanged files. + * + * The extension's cache is stored in VS Code's globalState, which is persisted in a SQLite + * database (state.vscdb). This script looks for a cache export file that the extension or + * tests may write to disk in a known location for inspection. + * + * Usage: + * node .github/skills/load-cache-data/load-cache-data.js [--last N] [--json] + * + * Options: + * --last N Show only the last N cache entries (default: 10) + * --json Output as JSON + * --help Show this help message + */ + +const fs = require('fs'); +const path = require('path'); +const os = require('os'); + +// Parse command line arguments +const args = process.argv.slice(2); +const lastCount = (() => { + const lastIndex = args.indexOf('--last'); + if (lastIndex !== -1 && args[lastIndex + 1]) { + return parseInt(args[lastIndex + 1], 10) || 10; + } + return 10; +})(); +const jsonOutput = args.includes('--json'); +const showHelp = args.includes('--help'); + +if (showHelp) { + console.log(` +Load Cache Data Script + +This script loads and displays the GitHub Copilot Token Tracker's local cache data. +The cache contains pre-computed statistics for session files. + +CACHE STRUCTURE: + The cache is stored in VS Code's globalState under the key 'sessionFileCache'. + Each entry contains: + - tokens: total token count + - interactions: number of interactions + - modelUsage: per-model token breakdown + - mtime: file modification time (for cache validation) + - usageAnalysis: detailed usage statistics (optional) + +CACHE FILE LOCATIONS: + This script looks for cache export files in the following locations: + 1. VS Code globalStorage: %APPDATA%\\Code\\User\\globalStorage\\rajbos.copilot-token-tracker\\cache.json + 2. Temp directory: %TEMP%\\copilot-token-tracker-cache.json + 3. Current directory: ./cache-export.json + + To create a cache export for testing or inspection, the extension or tests + can write the cache data to one of these locations. + +USAGE: + node .github/skills/load-cache-data/load-cache-data.js [--last N] [--json] + +OPTIONS: + --last N Show only the last N cache entries (default: 10) + --json Output as JSON format + --help Show this help message + +EXAMPLES: + # Show last 10 cache entries + node .github/skills/load-cache-data/load-cache-data.js + + # Show last 5 cache entries as JSON + node .github/skills/load-cache-data/load-cache-data.js --last 5 --json + + # Show all cache entries + node .github/skills/load-cache-data/load-cache-data.js --last 99999 + +FOR DEVELOPERS: + To access the cache programmatically within the extension: + + // Get cache data from global state + const cacheData = context.globalState.get('sessionFileCache'); + const cacheEntries = Object.entries(cacheData || {}); + + // Get last 10 entries (sorted by modification time) + const last10 = cacheEntries + .sort((a, b) => (b[1].mtime || 0) - (a[1].mtime || 0)) + .slice(0, 10); + + // Display cache entries + for (const [filePath, cacheEntry] of last10) { + console.log({ + file: filePath, + tokens: cacheEntry.tokens, + interactions: cacheEntry.interactions, + modelUsage: cacheEntry.modelUsage, + lastModified: new Date(cacheEntry.mtime).toISOString() + }); + } +`); + process.exit(0); +} + +/** + * Get possible cache file locations + * Returns array of paths where cache export files might be located + */ +function getCacheFilePaths() { + const platform = os.platform(); + const homedir = os.homedir(); + const paths = []; + + // VS Code variants to check + const vscodeVariants = ['Code', 'Code - Insiders', 'Code - Exploration', 'VSCodium', 'Cursor']; + // Support both the original author id and the machine-specific id (robbos) + const extensionId = 'robbos.copilot-token-tracker'; + // Candidate cache file names to look for (include session-cache.json used on the user's machine) + const candidateFiles = ['session-cache.json']; + + if (platform === 'win32') { + // Windows: %APPDATA%\Code\User\globalStorage\\ + const appDataPath = process.env.APPDATA || path.join(homedir, 'AppData', 'Roaming'); + for (const variant of vscodeVariants) { + for (const fileName of candidateFiles) { + paths.push(path.join(appDataPath, variant, 'User', 'globalStorage', extensionId, fileName)); + } + } + // Also check temp directory for common export names + const tempPath = process.env.TEMP || process.env.TMP || path.join(homedir, 'AppData', 'Local', 'Temp'); + paths.push(path.join(tempPath, 'copilot-token-tracker-cache.json')); + paths.push(path.join(tempPath, 'session-cache.json')); + } else if (platform === 'darwin') { + // macOS: ~/Library/Application Support//User/globalStorage// + for (const variant of vscodeVariants) { + for (const fileName of candidateFiles) { + paths.push(path.join(homedir, 'Library', 'Application Support', variant, 'User', 'globalStorage', extensionId, fileName)); + } + } + // Also check temp directory + paths.push(path.join(os.tmpdir(), 'copilot-token-tracker-cache.json')); + paths.push(path.join(os.tmpdir(), 'session-cache.json')); + } else { + // Linux: ~/.config/Code/User/globalStorage/extensionId/cache.json + const xdgConfigHome = process.env.XDG_CONFIG_HOME || path.join(homedir, '.config'); + for (const variant of vscodeVariants) { + for (const fileName of candidateFiles) { + paths.push(path.join(xdgConfigHome, variant, 'User', 'globalStorage', extensionId, fileName)); + } + } + // Also check temp directory + paths.push(path.join(os.tmpdir(), 'copilot-token-tracker-cache.json')); + paths.push(path.join(os.tmpdir(), 'session-cache.json')); + } + + // Also check current directory and common export names + paths.push(path.join(process.cwd(), 'cache-export.json')); + paths.push(path.join(process.cwd(), 'session-cache.json')); + + return paths; +} + +/** + * Try to find and read the cache file + * Returns { success: boolean, data?: any, filePath?: string, error?: string } + */ +function readCacheFile() { + const possiblePaths = getCacheFilePaths(); + + for (const filePath of possiblePaths) { + try { + if (fs.existsSync(filePath)) { + const content = fs.readFileSync(filePath, 'utf8'); + const data = JSON.parse(content); + return { success: true, data, filePath }; + } + } catch (error) { + // Continue to next path if this one fails + continue; + } + } + + return { + success: false, + error: 'No cache file found', + searchedPaths: possiblePaths + }; +} + +/** + * Format cache data for display + */ +function formatCacheEntries(cacheData, limit = 10) { + const entries = Object.entries(cacheData); + + // Sort by modification time (most recent first) + entries.sort((a, b) => (b[1].mtime || 0) - (a[1].mtime || 0)); + + // Take last N entries + const limitedEntries = entries.slice(0, limit); + + return limitedEntries.map(([filePath, cacheEntry]) => ({ + file: path.basename(filePath), + fullPath: filePath, + tokens: cacheEntry.tokens, + interactions: cacheEntry.interactions, + modelUsage: cacheEntry.modelUsage, + lastModified: cacheEntry.mtime ? new Date(cacheEntry.mtime).toISOString() : 'unknown', + usageAnalysis: cacheEntry.usageAnalysis + })); +} + +/** + * Display cache entries in human-readable format + */ +function displayCacheEntries(entries, sourceFile) { + console.log('='.repeat(80)); + console.log('GitHub Copilot Token Tracker - Local Cache Data'); + console.log('='.repeat(80)); + console.log(''); + + if (sourceFile) { + console.log(`Cache file: ${sourceFile}`); + console.log(''); + } + + console.log(`Showing ${entries.length} cache entries (sorted by most recent):`); + console.log(''); + + entries.forEach((entry, index) => { + console.log(`${index + 1}. ${entry.file}`); + console.log(` Path: ${entry.fullPath}`); + console.log(` Tokens: ${entry.tokens.toLocaleString()}`); + console.log(` Interactions: ${entry.interactions}`); + console.log(` Last Modified: ${entry.lastModified}`); + console.log(` Model Usage:`); + + for (const [model, usage] of Object.entries(entry.modelUsage)) { + console.log(` - ${model}:`); + console.log(` Input: ${usage.inputTokens.toLocaleString()} tokens`); + console.log(` Output: ${usage.outputTokens.toLocaleString()} tokens`); + } + + if (entry.usageAnalysis) { + console.log(` Usage Analysis:`); + console.log(` Tool Calls: ${entry.usageAnalysis.toolCalls.total}`); + console.log(` Mode Usage: Ask=${entry.usageAnalysis.modeUsage.ask}, Edit=${entry.usageAnalysis.modeUsage.edit}, Agent=${entry.usageAnalysis.modeUsage.agent}`); + const contextRefs = entry.usageAnalysis.contextReferences; + const totalRefs = Object.values(contextRefs).reduce((sum, val) => sum + val, 0); + console.log(` Context References: ${totalRefs} total`); + } + + console.log(''); + }); + + console.log('='.repeat(80)); +} + +/** + * Display message when no cache file is found + */ +function displayNoCacheFound(searchedPaths) { + console.log('='.repeat(80)); + console.log('GitHub Copilot Token Tracker - Local Cache Data'); + console.log('='.repeat(80)); + console.log(''); + console.log('NO CACHE FILE FOUND'); + console.log(''); + console.log('This script looks for cache export files in the following locations:'); + searchedPaths.forEach(p => console.log(` - ${p}`)); + console.log(''); + console.log('The extension stores its cache in VS Code\'s internal globalState,'); + console.log('which is not directly accessible from external scripts.'); + console.log(''); + console.log('To export cache data for inspection:'); + console.log(' 1. The extension can be modified to write cache to disk'); + console.log(' 2. Tests can export cache data to one of the above locations'); + console.log(' 3. Use the extension\'s API to access cache at runtime'); + console.log(''); + console.log('See --help for more information on cache structure and access patterns.'); + console.log('='.repeat(80)); +} + +// Main execution +(function main() { + // Try to read actual cache file + const cacheResult = readCacheFile(); + + if (cacheResult.success) { + // Return raw cache data (limit to last N entries) as JSON only + const entries = Object.entries(cacheResult.data || {}); + entries.sort((a, b) => (b[1].mtime || 0) - (a[1].mtime || 0)); + const limited = entries.slice(0, lastCount); + const limitedObj = Object.fromEntries(limited); + + const output = { + cacheFile: cacheResult.filePath, + requestedCount: lastCount, + totalCacheEntries: Object.keys(cacheResult.data || {}).length, + entries: limitedObj + }; + + console.log(JSON.stringify(output)); + return; + } + + // No cache found: output JSON error + const errorOut = { + cacheFound: false, + error: cacheResult.error, + searchedPaths: cacheResult.searchedPaths + }; + console.log(JSON.stringify(errorOut)); + process.exit(1); +})(); diff --git a/.vscode/settings.json b/.vscode/settings.json index 170bb0e..0c9407d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -11,14 +11,6 @@ // Turn off tsc task auto detection since we have the necessary tasks as npm scripts "typescript.tsc.autoDetect": "off", "chat.tools.terminal.autoApprove": { - "/^cd c:/Users/RobBos/code/repos/rajbos/github-copilot-token-usage; git show HEAD:src/extension\\.ts \\| powershell -Command \"\\$input \\| Select-Object -First 120\"$/": { - "approve": true, - "matchCommandLine": true - }, - "/^cd c:/Users/RobBos/code/repos/rajbos/github-copilot-token-usage; powershell -Command \"git show HEAD:src/extension\\.ts \\| Select-Object -First 120\"$/": { - "approve": true, - "matchCommandLine": true - }, "/^npx tsc --noEmit 2>&1$/": { "approve": true, "matchCommandLine": true @@ -27,6 +19,10 @@ "approve": true, "matchCommandLine": true }, - "git fetch": true + "git fetch": true, + "/^node \\.github/skills/load-cache-data/load-cache-data\\.js(?: --last \\d+)?(?: --json)?$/": { + "approve": true, + "matchCommandLine": true + } } } \ No newline at end of file