mirror of
https://github.com/affaan-m/ECC.git
synced 2026-08-17 21:15:40 +02:00
Normalize scalar Claude agent tool metadata across validators, adapters, dashboards, and generated surfaces with regression coverage.
98 lines
2.2 KiB
JavaScript
98 lines
2.2 KiB
JavaScript
'use strict';
|
|
|
|
function stripSurroundingQuotes(value) {
|
|
const trimmed = value.trim();
|
|
const quote = trimmed[0];
|
|
if ((quote === '"' || quote === "'") && trimmed.endsWith(quote)) {
|
|
return trimmed.slice(1, -1).trim();
|
|
}
|
|
return trimmed;
|
|
}
|
|
|
|
function splitTopLevelToolList(value) {
|
|
const items = [];
|
|
const delimiters = [];
|
|
let quote = null;
|
|
let escaped = false;
|
|
let itemStart = 0;
|
|
|
|
for (let index = 0; index < value.length; index += 1) {
|
|
const character = value[index];
|
|
|
|
if (quote) {
|
|
if (escaped) {
|
|
escaped = false;
|
|
} else if (character === '\\') {
|
|
escaped = true;
|
|
} else if (character === quote) {
|
|
quote = null;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if (character === '"' || character === "'") {
|
|
quote = character;
|
|
continue;
|
|
}
|
|
|
|
if (character === '(' || character === '[' || character === '{') {
|
|
delimiters.push(character);
|
|
continue;
|
|
}
|
|
|
|
const expectedOpener = {
|
|
')': '(',
|
|
']': '[',
|
|
'}': '{',
|
|
}[character];
|
|
if (expectedOpener && delimiters.at(-1) === expectedOpener) {
|
|
delimiters.pop();
|
|
continue;
|
|
}
|
|
|
|
if (character === ',' && delimiters.length === 0) {
|
|
items.push(value.slice(itemStart, index));
|
|
itemStart = index + 1;
|
|
}
|
|
}
|
|
|
|
items.push(value.slice(itemStart));
|
|
return items;
|
|
}
|
|
|
|
/**
|
|
* Normalize Claude agent frontmatter tools to the array shape used internally.
|
|
*
|
|
* Claude Code expects tools to be a comma-separated scalar. Flow sequences are
|
|
* still accepted here so ECC can read legacy or harness-adapted agent files.
|
|
*/
|
|
function normalizeAgentTools(value) {
|
|
if (Array.isArray(value)) {
|
|
return value
|
|
.filter(item => typeof item === 'string')
|
|
.map(stripSurroundingQuotes)
|
|
.filter(Boolean);
|
|
}
|
|
|
|
if (typeof value !== 'string') {
|
|
return [];
|
|
}
|
|
|
|
const trimmed = value.trim();
|
|
const listValue = trimmed.startsWith('[') && trimmed.endsWith(']')
|
|
? trimmed.slice(1, -1)
|
|
: stripSurroundingQuotes(trimmed);
|
|
|
|
if (!listValue.trim()) {
|
|
return [];
|
|
}
|
|
|
|
return splitTopLevelToolList(listValue)
|
|
.map(stripSurroundingQuotes)
|
|
.filter(Boolean);
|
|
}
|
|
|
|
module.exports = {
|
|
normalizeAgentTools,
|
|
};
|