From 80aca431061c1f7bf8c3c04af4a8dfc1a0666af9 Mon Sep 17 00:00:00 2001 From: Darwin Pardave Date: Sun, 6 Sep 2026 20:35:50 -0500 Subject: [PATCH] perf: avoid duplicate skill file reads Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- scripts/dashboard-web.js | 36 ++++++++++++++++++----------- tests/scripts/dashboard-web.test.js | 22 ++++++++++++++++++ 2 files changed, 44 insertions(+), 14 deletions(-) diff --git a/scripts/dashboard-web.js b/scripts/dashboard-web.js index 12094fbcf..333e29dbd 100644 --- a/scripts/dashboard-web.js +++ b/scripts/dashboard-web.js @@ -21,24 +21,32 @@ function parsePort(v) { const PORT = parsePort(process.argv[2] || process.env.ECC_DASHBOARD_PORT || '3456'); const ROOT = path.resolve(__dirname, '..'); +function parseFrontmatter(c) { + const m = c.match(/^---\n([\s\S]*?)\n---/); + if (!m) return {}; + const fm = {}; + for (const l of m[1].split('\n')) { + const s = l.indexOf(':'); if (s <= 0) continue; + let k = l.slice(0, s).trim(), v = l.slice(s + 1).trim(); + if ((v.startsWith('"') && v.endsWith('"')) || (v.startsWith("'") && v.endsWith("'"))) v = v.slice(1, -1); + if (v.startsWith('[') && v.endsWith(']')) { try { v = JSON.parse(v); } catch { v = v.slice(1, -1).split(',').map(x => x.trim().replace(/["']/g, '')); } } + fm[k] = v; + } + fm._body = c.replace(/^---[\s\S]*?---\n*/, '').trim(); + return fm; +} function readFrontmatter(p) { try { - const c = fs.readFileSync(p, 'utf8'); - const m = c.match(/^---\n([\s\S]*?)\n---/); - if (!m) return {}; - const fm = {}; - for (const l of m[1].split('\n')) { - const s = l.indexOf(':'); if (s <= 0) continue; - let k = l.slice(0, s).trim(), v = l.slice(s + 1).trim(); - if ((v.startsWith('"') && v.endsWith('"')) || (v.startsWith("'") && v.endsWith("'"))) v = v.slice(1, -1); - if (v.startsWith('[') && v.endsWith(']')) { try { v = JSON.parse(v); } catch { v = v.slice(1, -1).split(',').map(x => x.trim().replace(/["']/g, '')); } } - fm[k] = v; - } - fm._body = c.replace(/^---[\s\S]*?---\n*/, '').trim(); - return fm; + return parseFrontmatter(fs.readFileSync(p, 'utf8')); } catch { return {}; } } -function readSkill(p) { try { const c = fs.readFileSync(p, 'utf8'); const fm = readFrontmatter(p); return { d: fm.description || '', b: c.replace(/^---[\s\S]*?---\n*/, '').trim() }; } catch { return { d: '', b: '' }; } } +function readSkill(p) { + try { + const c = fs.readFileSync(p, 'utf8'); + const fm = parseFrontmatter(c); + return { d: fm.description || '', b: c.replace(/^---[\s\S]*?---\n*/, '').trim() }; + } catch { return { d: '', b: '' }; } +} function loadAgents(_root) { const root = _root || ROOT; diff --git a/tests/scripts/dashboard-web.test.js b/tests/scripts/dashboard-web.test.js index 8118a06ca..3d6a9c8a6 100644 --- a/tests/scripts/dashboard-web.test.js +++ b/tests/scripts/dashboard-web.test.js @@ -179,6 +179,28 @@ test('readSkill parses skill frontmatter and body', () => { cleanup(testRoot); }); +test('readSkill reads each skill file only once', () => { + const { readSkill } = require(SCRIPT); + testRoot = createTempDir('ecc-test-'); + const skillPath = path.join(testRoot, 'SKILL.md'); + writeFile(testRoot, 'SKILL.md', '---\ndescription: A test skill\n---\nbody'); + const originalReadFileSync = fs.readFileSync; + let readCount = 0; + fs.readFileSync = (...args) => { + readCount++; + return originalReadFileSync(...args); + }; + + try { + readSkill(skillPath); + } finally { + fs.readFileSync = originalReadFileSync; + cleanup(testRoot); + } + + assert.strictEqual(readCount, 1); +}); + test('readSkill returns empty defaults for missing file', () => { const { readSkill } = require(SCRIPT); const skill = readSkill('/nonexistent/skill/SKILL.md');