agentscore 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +2 -0
- package/dist/index.js +147 -0
- package/package.json +33 -0
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
+
const core_1 = require("@agentscore/core");
|
|
10
|
+
const RULE_LABELS = {
|
|
11
|
+
'semantic-html': 'Semantic HTML',
|
|
12
|
+
'aria-coverage': 'ARIA Coverage',
|
|
13
|
+
'selector-stability': 'Selector Stability',
|
|
14
|
+
'webmcp-support': 'WebMCP / Structured Data',
|
|
15
|
+
'meta-info': 'Meta Information',
|
|
16
|
+
};
|
|
17
|
+
const RULE_WEIGHTS = {
|
|
18
|
+
'semantic-html': 25,
|
|
19
|
+
'aria-coverage': 25,
|
|
20
|
+
'selector-stability': 15,
|
|
21
|
+
'webmcp-support': 20,
|
|
22
|
+
'meta-info': 15,
|
|
23
|
+
};
|
|
24
|
+
const SUGGESTIONS = {
|
|
25
|
+
'semantic-html': [
|
|
26
|
+
'Replace generic <div> containers with <section>, <article>, <nav>, <main>',
|
|
27
|
+
'Ensure a proper heading hierarchy (h1 → h2 → h3)',
|
|
28
|
+
'Associate all form inputs with <label> elements',
|
|
29
|
+
],
|
|
30
|
+
'aria-coverage': [
|
|
31
|
+
'Add aria-label to icon-only buttons and links',
|
|
32
|
+
'Ensure all <img> tags have descriptive alt attributes',
|
|
33
|
+
'Use role attributes for custom interactive components',
|
|
34
|
+
],
|
|
35
|
+
'selector-stability': [
|
|
36
|
+
'Add data-testid attributes to key interactive elements',
|
|
37
|
+
'Prefer semantic class names over CSS-in-JS generated hashes',
|
|
38
|
+
'Use stable IDs for elements that agents need to target',
|
|
39
|
+
],
|
|
40
|
+
'webmcp-support': [
|
|
41
|
+
'Add JSON-LD structured data with schema.org vocabulary',
|
|
42
|
+
'Consider implementing navigator.modelContext (WebMCP)',
|
|
43
|
+
'Add <meta name="mcp-server"> for MCP endpoint discovery',
|
|
44
|
+
],
|
|
45
|
+
'meta-info': [
|
|
46
|
+
'Add a descriptive <title> and <meta name="description">',
|
|
47
|
+
'Include Open Graph tags (og:title, og:description, og:image)',
|
|
48
|
+
'Set lang attribute on <html> element',
|
|
49
|
+
],
|
|
50
|
+
};
|
|
51
|
+
function progressBar(score, width = 20) {
|
|
52
|
+
const filled = Math.round((score / 100) * width);
|
|
53
|
+
const empty = width - filled;
|
|
54
|
+
const bar = '█'.repeat(filled) + '░'.repeat(empty);
|
|
55
|
+
if (score >= 80)
|
|
56
|
+
return chalk_1.default.green(bar);
|
|
57
|
+
if (score >= 60)
|
|
58
|
+
return chalk_1.default.yellow(bar);
|
|
59
|
+
return chalk_1.default.red(bar);
|
|
60
|
+
}
|
|
61
|
+
function colorScore(score) {
|
|
62
|
+
if (score >= 80)
|
|
63
|
+
return chalk_1.default.green.bold(`${score}`);
|
|
64
|
+
if (score >= 60)
|
|
65
|
+
return chalk_1.default.yellow.bold(`${score}`);
|
|
66
|
+
return chalk_1.default.red.bold(`${score}`);
|
|
67
|
+
}
|
|
68
|
+
function gradeEmoji(score) {
|
|
69
|
+
if (score >= 90)
|
|
70
|
+
return '🟢';
|
|
71
|
+
if (score >= 70)
|
|
72
|
+
return '🟡';
|
|
73
|
+
if (score >= 50)
|
|
74
|
+
return '🟠';
|
|
75
|
+
return '🔴';
|
|
76
|
+
}
|
|
77
|
+
function severityIcon(severity) {
|
|
78
|
+
switch (severity) {
|
|
79
|
+
case 'error': return chalk_1.default.red('✗');
|
|
80
|
+
case 'warning': return chalk_1.default.yellow('⚠');
|
|
81
|
+
case 'info': return chalk_1.default.blue('ℹ');
|
|
82
|
+
default: return ' ';
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
const program = new commander_1.Command();
|
|
86
|
+
program
|
|
87
|
+
.name('agentscore')
|
|
88
|
+
.description('Audit web pages for AI-agent readability')
|
|
89
|
+
.version('0.1.0');
|
|
90
|
+
program
|
|
91
|
+
.command('audit <url>')
|
|
92
|
+
.description('Run audit on a URL')
|
|
93
|
+
.option('--json', 'Output results as JSON')
|
|
94
|
+
.action(async (url, opts) => {
|
|
95
|
+
try {
|
|
96
|
+
if (!/^https?:\/\//i.test(url))
|
|
97
|
+
url = `https://${url}`;
|
|
98
|
+
if (!opts.json) {
|
|
99
|
+
console.log(chalk_1.default.dim(`\n 🔍 Auditing ${url}...\n`));
|
|
100
|
+
}
|
|
101
|
+
const report = await (0, core_1.audit)(url);
|
|
102
|
+
if (opts.json) {
|
|
103
|
+
console.log(JSON.stringify(report, null, 2));
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
// Big score display
|
|
107
|
+
console.log(` ${gradeEmoji(report.score)} ${chalk_1.default.bold.white('Agent-Readiness Score:')} ${colorScore(report.score)}${chalk_1.default.dim('/100')}\n`);
|
|
108
|
+
console.log(chalk_1.default.dim(' ─────────────────────────────────────────────\n'));
|
|
109
|
+
// Each dimension with progress bar
|
|
110
|
+
for (const result of report.results) {
|
|
111
|
+
const label = (RULE_LABELS[result.rule] || result.rule).padEnd(24);
|
|
112
|
+
const weight = RULE_WEIGHTS[result.rule] || 0;
|
|
113
|
+
console.log(` ${label} ${progressBar(result.score)} ${colorScore(result.score)} ${chalk_1.default.dim(`(${weight}%)`)}`);
|
|
114
|
+
if (result.issues.length > 0) {
|
|
115
|
+
for (const issue of result.issues) {
|
|
116
|
+
console.log(` ${severityIcon(issue.severity)} ${chalk_1.default.dim(issue.message)}`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
// Top 3 improvement suggestions
|
|
121
|
+
const sorted = [...report.results].sort((a, b) => a.score - b.score);
|
|
122
|
+
const topSuggestions = [];
|
|
123
|
+
for (const r of sorted) {
|
|
124
|
+
const pool = SUGGESTIONS[r.rule] || [];
|
|
125
|
+
for (const s of pool) {
|
|
126
|
+
if (topSuggestions.length >= 3)
|
|
127
|
+
break;
|
|
128
|
+
topSuggestions.push(s);
|
|
129
|
+
}
|
|
130
|
+
if (topSuggestions.length >= 3)
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
if (topSuggestions.length > 0) {
|
|
134
|
+
console.log(`\n${chalk_1.default.dim(' ─────────────────────────────────────────────')}`);
|
|
135
|
+
console.log(`\n ${chalk_1.default.bold('💡 Top Improvements:')}\n`);
|
|
136
|
+
topSuggestions.forEach((s, i) => {
|
|
137
|
+
console.log(` ${chalk_1.default.cyan(`${i + 1}.`)} ${s}`);
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
console.log(chalk_1.default.dim(`\n Audited at ${report.timestamp}\n`));
|
|
141
|
+
}
|
|
142
|
+
catch (err) {
|
|
143
|
+
console.error(chalk_1.default.red(`\n ✗ ${err.message}\n`));
|
|
144
|
+
process.exit(1);
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
program.parse();
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "agentscore",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Audit web pages for AI-agent readability — semantic HTML, ARIA, WebMCP, structured data & more",
|
|
5
|
+
"keywords": ["ai", "agent", "lint", "accessibility", "webmcp", "audit", "seo", "structured-data", "aria"],
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/xiongallen40-design/agentscore"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://github.com/xiongallen40-design/agentscore#readme",
|
|
11
|
+
"bin": {
|
|
12
|
+
"agentscore": "dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"files": ["dist"],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "tsc",
|
|
17
|
+
"clean": "rm -rf dist",
|
|
18
|
+
"prepublishOnly": "npm run build"
|
|
19
|
+
},
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"@agentscore/core": "workspace:*",
|
|
22
|
+
"chalk": "^4.1.2",
|
|
23
|
+
"commander": "^12.0.0"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@types/node": "^25.2.3",
|
|
27
|
+
"typescript": "^5.3.0"
|
|
28
|
+
},
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=18"
|
|
32
|
+
}
|
|
33
|
+
}
|