mirror of
https://github.com/affaan-m/ECC.git
synced 2026-10-15 04:35:29 +02:00
245 lines
8.1 KiB
JavaScript
245 lines
8.1 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
const assert = require('assert');
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
const { spawnSync } = require('child_process');
|
|
|
|
const ROOT = path.join(__dirname, '..', '..');
|
|
const { resolveInstallPlan } = require(path.join(ROOT, 'scripts', 'lib', 'install-manifests.js'));
|
|
|
|
// Every file that carries a language selector linking to the Bengali README.
|
|
// Root-level files link via `docs/bn/README.md`; translated docs link via `../bn/README.md`.
|
|
const SELECTOR_FILES = [
|
|
'README.md',
|
|
'README.zh-CN.md',
|
|
'docs/de-DE/README.md',
|
|
'docs/es/README.md',
|
|
'docs/ja-JP/README.md',
|
|
'docs/ko-KR/README.md',
|
|
'docs/pt-BR/README.md',
|
|
'docs/ru/README.md',
|
|
'docs/th/README.md',
|
|
'docs/tr/README.md',
|
|
'docs/uk-UA/README.md',
|
|
'docs/ur/README.md',
|
|
'docs/vi-VN/README.md',
|
|
'docs/zh-CN/README.md',
|
|
'docs/zh-TW/README.md',
|
|
];
|
|
|
|
function read(relativePath) {
|
|
return fs.readFileSync(path.join(ROOT, relativePath), 'utf8');
|
|
}
|
|
|
|
function readJson(relativePath) {
|
|
return JSON.parse(read(relativePath));
|
|
}
|
|
|
|
let passed = 0;
|
|
let failed = 0;
|
|
let skipped = 0;
|
|
|
|
function test(name, fn) {
|
|
try {
|
|
fn();
|
|
console.log(` ✓ ${name}`);
|
|
passed++;
|
|
} catch (error) {
|
|
if (error instanceof SkipError) {
|
|
console.log(` ○ ${name} (SKIPPED: ${error.message})`);
|
|
skipped++;
|
|
return;
|
|
}
|
|
console.log(` ✗ ${name}`);
|
|
console.error(` ${error.message}`);
|
|
failed++;
|
|
}
|
|
}
|
|
|
|
class SkipError extends Error {}
|
|
|
|
function findPython() {
|
|
for (const command of process.platform === 'win32' ? ['python', 'py'] : ['python3', 'python']) {
|
|
const args = command === 'py' ? ['-3', '--version'] : ['--version'];
|
|
const result = spawnSync(command, args, { encoding: 'utf8' });
|
|
if (result.status === 0) {
|
|
return { command, prefix: command === 'py' ? ['-3'] : [] };
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
// Walks every fence in the document so an unclosed ```python block fails loudly
|
|
// instead of being silently dropped by a non-greedy regex.
|
|
function extractFencedBlocks(markdown) {
|
|
const lines = markdown.split('\n');
|
|
const blocks = [];
|
|
let open = null;
|
|
let buffer = [];
|
|
|
|
lines.forEach((line, index) => {
|
|
const fence = /^\s*```(.*)$/.exec(line);
|
|
if (!fence) {
|
|
if (open) buffer.push(line);
|
|
return;
|
|
}
|
|
|
|
const info = fence[1].trim();
|
|
if (!open) {
|
|
open = { language: info.split(/\s+/)[0] || '', line: index + 1 };
|
|
buffer = [];
|
|
return;
|
|
}
|
|
|
|
if (info !== '') {
|
|
throw new Error(
|
|
`Fence opened at line ${open.line} is closed by an info-string fence at line ${index + 1}`,
|
|
);
|
|
}
|
|
|
|
blocks.push({ language: open.language, code: buffer.join('\n'), line: open.line });
|
|
open = null;
|
|
buffer = [];
|
|
});
|
|
|
|
if (open) {
|
|
throw new Error(`Unclosed \`\`\`${open.language} fence opened at line ${open.line}`);
|
|
}
|
|
|
|
return blocks;
|
|
}
|
|
|
|
function run() {
|
|
console.log('\n=== Testing Bengali language surfaces ===\n');
|
|
|
|
test('Bengali Python examples are syntactically valid', () => {
|
|
const skill = read('skills/bengali-nlp/SKILL.md');
|
|
const blocks = extractFencedBlocks(skill);
|
|
const snippets = blocks.filter(block => block.language === 'python');
|
|
assert.ok(snippets.length > 0, 'Expected at least one Python example');
|
|
|
|
const python = findPython();
|
|
if (!python) {
|
|
throw new SkipError('no Python 3 interpreter on PATH');
|
|
}
|
|
|
|
snippets.forEach(snippet => {
|
|
const encoded = Buffer.from(snippet.code, 'utf8').toString('base64');
|
|
const result = spawnSync(
|
|
python.command,
|
|
[
|
|
...python.prefix,
|
|
'-c',
|
|
"import base64, sys; compile(base64.b64decode(sys.stdin.buffer.read()).decode('utf-8'), '<bengali-nlp>', 'exec')",
|
|
],
|
|
{ input: encoded, encoding: 'utf8' },
|
|
);
|
|
assert.strictEqual(
|
|
result.status,
|
|
0,
|
|
`Python example at line ${snippet.line} does not compile:\n${result.stderr || result.stdout}`,
|
|
);
|
|
});
|
|
});
|
|
|
|
test('Bengali tokenizer preserves decimal quantities', () => {
|
|
const skill = read('skills/bengali-nlp/SKILL.md');
|
|
const tokenizer = extractFencedBlocks(skill)
|
|
.filter(block => block.language === 'python')
|
|
.find(block => block.code.includes('def tokenize_bangla'));
|
|
assert.ok(tokenizer, 'Expected the Bengali tokenizer example');
|
|
|
|
const python = findPython();
|
|
if (!python) {
|
|
throw new SkipError('no Python 3 interpreter on PATH');
|
|
}
|
|
|
|
const check = [
|
|
tokenizer.code,
|
|
"assert tokenize_bangla('ওজন ৩.৫ কেজি। মূল্য 12.75 টাকা.') == ['ওজন', '৩.৫', 'কেজি', 'মূল্য', '12.75', 'টাকা']",
|
|
].join('\n');
|
|
const result = spawnSync(python.command, [...python.prefix, '-c', check], {
|
|
encoding: 'utf8',
|
|
});
|
|
assert.strictEqual(
|
|
result.status,
|
|
0,
|
|
`Bengali tokenizer changed decimal quantities:\n${result.stderr || result.stdout}`,
|
|
);
|
|
});
|
|
|
|
test('Bengali skill is exported and installable', () => {
|
|
const agentYaml = read('agent.yaml');
|
|
const modules = readJson('manifests/install-modules.json').modules;
|
|
const packageFiles = readJson('package.json').files;
|
|
const frameworkModule = modules.find(module => module.id === 'framework-language');
|
|
|
|
assert.match(agentYaml, /^\s+- bengali-nlp\s*$/m);
|
|
assert.ok(frameworkModule?.paths.includes('skills/bengali-nlp'));
|
|
assert.ok(packageFiles.includes('skills/bengali-nlp/'));
|
|
});
|
|
|
|
test('Selecting the Bengali skill installs only the Bengali skill', () => {
|
|
const plan = resolveInstallPlan({ includeComponentIds: ['skill:bengali-nlp'] });
|
|
const paths = plan.selectedModules.flatMap(module => module.paths || []);
|
|
|
|
assert.deepStrictEqual(plan.selectedModuleIds, ['skill-bengali-nlp']);
|
|
assert.deepStrictEqual(paths, ['skills/bengali-nlp']);
|
|
});
|
|
|
|
test('Bengali reviewer is discoverable through the shared agent surface', () => {
|
|
const agentsGuide = read('AGENTS.md');
|
|
const modules = readJson('manifests/install-modules.json').modules;
|
|
const agentsModule = modules.find(module => module.id === 'agents-core');
|
|
|
|
assert.ok(fs.existsSync(path.join(ROOT, 'agents', 'bengali-reviewer.md')));
|
|
assert.match(agentsGuide, /^\| bengali-reviewer \|/m);
|
|
assert.ok(agentsModule?.paths.includes('agents'));
|
|
});
|
|
|
|
test('Bengali documentation has an installable locale route', () => {
|
|
const modules = readJson('manifests/install-modules.json').modules;
|
|
const components = readJson('manifests/install-components.json').components;
|
|
const packageFiles = readJson('package.json').files;
|
|
const docsModule = modules.find(module => module.id === 'docs-bn');
|
|
const localeComponent = components.find(component => component.id === 'locale:bn');
|
|
|
|
assert.ok(fs.existsSync(path.join(ROOT, 'docs', 'bn', 'README.md')));
|
|
assert.deepStrictEqual(docsModule?.paths, ['docs/bn']);
|
|
assert.ok(localeComponent?.modules.includes('docs-bn'));
|
|
assert.ok(packageFiles.includes('docs/bn/'));
|
|
});
|
|
|
|
test('Every language selector links to the Bengali README', () => {
|
|
SELECTOR_FILES.forEach(relativePath => {
|
|
const contents = read(relativePath);
|
|
const route = relativePath.includes('/') ? '../bn/README.md' : 'docs/bn/README.md';
|
|
assert.ok(
|
|
contents.includes(`](${route})`) || contents.includes(`href="${route}"`),
|
|
`${relativePath} is missing the Bengali language link (${route})`,
|
|
);
|
|
assert.ok(contents.includes('বাংলা'), `${relativePath} is missing the বাংলা label`);
|
|
});
|
|
});
|
|
|
|
test('Bengali README offers the same languages as the root README', () => {
|
|
const rootLabels = [...read('README.md')
|
|
.matchAll(/<a href="(?:docs\/[\w-]+\/)?README(?:\.[\w-]+)?\.md">([^<]+)<\/a>/g)]
|
|
.map(match => match[1].trim());
|
|
assert.ok(rootLabels.length > 5, 'Expected the root README language selector to be parsed');
|
|
|
|
const bengali = read('docs/bn/README.md');
|
|
rootLabels.forEach(label => {
|
|
assert.ok(bengali.includes(label), `docs/bn/README.md is missing the ${label} link`);
|
|
});
|
|
});
|
|
|
|
console.log(`\nPassed: ${passed}`);
|
|
if (skipped > 0) console.log(`Skipped: ${skipped}`);
|
|
console.log(`Failed: ${failed}`);
|
|
process.exit(failed > 0 ? 1 : 0);
|
|
}
|
|
|
|
run();
|