aeo-ready 1.7.2 → 1.7.3
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/package.json +1 -1
- package/src/recommendations.js +37 -103
package/package.json
CHANGED
package/src/recommendations.js
CHANGED
|
@@ -93,7 +93,6 @@ const RECOMMENDATION_MAP = [
|
|
|
93
93
|
label: "Add identity and discovery protocols",
|
|
94
94
|
detail:
|
|
95
95
|
"Implement WebFinger, DID Document, A2A Agent Card, and/or WebMCP manifest for agent discovery",
|
|
96
|
-
optional: true,
|
|
97
96
|
match: (id) =>
|
|
98
97
|
/webfinger|did document|nostr|at protocol|agent card.*published|agent card.*verified|webmcp|apple app links|android asset links/i.test(
|
|
99
98
|
id,
|
|
@@ -104,7 +103,6 @@ const RECOMMENDATION_MAP = [
|
|
|
104
103
|
label: "Declare payment information",
|
|
105
104
|
detail:
|
|
106
105
|
"Add x-payment-info header to paid API operations for agent billing awareness",
|
|
107
|
-
apiOnly: true,
|
|
108
106
|
match: (id) => /x-payment-info/i.test(id),
|
|
109
107
|
},
|
|
110
108
|
{
|
|
@@ -112,7 +110,6 @@ const RECOMMENDATION_MAP = [
|
|
|
112
110
|
label: "Add skill.md reference",
|
|
113
111
|
detail:
|
|
114
112
|
"Create a skill.md file describing your API's capabilities for agent consumption",
|
|
115
|
-
apiOnly: true,
|
|
116
113
|
match: (id) => /skill\.md/i.test(id),
|
|
117
114
|
},
|
|
118
115
|
{
|
|
@@ -120,7 +117,6 @@ const RECOMMENDATION_MAP = [
|
|
|
120
117
|
label: "Return rate limit headers",
|
|
121
118
|
detail:
|
|
122
119
|
"Add X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset headers to API responses",
|
|
123
|
-
apiOnly: true,
|
|
124
120
|
match: (id) => /rate limit/i.test(id),
|
|
125
121
|
},
|
|
126
122
|
{
|
|
@@ -128,7 +124,6 @@ const RECOMMENDATION_MAP = [
|
|
|
128
124
|
label: "Publish signatures directory and public keys",
|
|
129
125
|
detail:
|
|
130
126
|
"Serve /.well-known/http-message-signatures-directory with agent identity and public keys (RFC 9421)",
|
|
131
|
-
optional: true,
|
|
132
127
|
match: (id) =>
|
|
133
128
|
/signatures directory|public keys|members declared/i.test(id),
|
|
134
129
|
},
|
|
@@ -175,8 +170,6 @@ function buildRecommendations(result) {
|
|
|
175
170
|
key: rec.key,
|
|
176
171
|
label: rec.label,
|
|
177
172
|
detail: rec.detail,
|
|
178
|
-
apiOnly: rec.apiOnly || false,
|
|
179
|
-
optional: rec.optional || false,
|
|
180
173
|
benchmarks: new Set(),
|
|
181
174
|
checks: [],
|
|
182
175
|
});
|
|
@@ -228,100 +221,39 @@ function tierDescription(count) {
|
|
|
228
221
|
return "flagged by 1 benchmark";
|
|
229
222
|
}
|
|
230
223
|
|
|
231
|
-
function printRecommendations(recs) {
|
|
232
|
-
let currentTier = null;
|
|
233
|
-
let num = 1;
|
|
234
|
-
|
|
235
|
-
console.log("");
|
|
236
|
-
for (const rec of recs) {
|
|
237
|
-
const tier = tierLabel(rec.priority);
|
|
238
|
-
if (tier !== currentTier) {
|
|
239
|
-
currentTier = tier;
|
|
240
|
-
const color =
|
|
241
|
-
rec.priority >= 3
|
|
242
|
-
? chalk.red
|
|
243
|
-
: rec.priority >= 2
|
|
244
|
-
? chalk.yellow
|
|
245
|
-
: chalk.dim;
|
|
246
|
-
console.log(
|
|
247
|
-
` ${color.bold(tier)} ${chalk.dim(`(${tierDescription(rec.priority)})`)}`,
|
|
248
|
-
);
|
|
249
|
-
}
|
|
250
|
-
const benchmarkList = rec.benchmarks
|
|
251
|
-
.map((b) => BENCHMARK_NAMES[b])
|
|
252
|
-
.join(" · ");
|
|
253
|
-
console.log(` ${chalk.dim(`${num}.`)} ${rec.label}`);
|
|
254
|
-
console.log(` ${chalk.dim(benchmarkList)}`);
|
|
255
|
-
num++;
|
|
256
|
-
}
|
|
257
|
-
console.log("");
|
|
258
|
-
}
|
|
259
|
-
|
|
260
224
|
function generateAgentPrompt(result, recs) {
|
|
261
|
-
const core = recs.filter((r) => !r.apiOnly && !r.optional);
|
|
262
|
-
const optional = recs.filter((r) => r.optional && !r.apiOnly);
|
|
263
|
-
const apiOnly = recs.filter((r) => r.apiOnly);
|
|
264
|
-
|
|
265
225
|
const lines = [];
|
|
266
226
|
lines.push(
|
|
267
227
|
`My site ${result.url} scored ${result.averageScore}/100 on aeo-ready (AEO readiness scanner).`,
|
|
268
228
|
);
|
|
269
229
|
lines.push("Fix these issues to improve AI/agent discoverability.");
|
|
270
230
|
lines.push(
|
|
271
|
-
"Items are ordered by priority — issues flagged by multiple benchmarks
|
|
231
|
+
"Items are ordered by priority — issues flagged by multiple benchmarks matter most.",
|
|
232
|
+
);
|
|
233
|
+
lines.push(
|
|
234
|
+
"This scan covers benchmarks across different site types (content sites, APIs, developer platforms).",
|
|
235
|
+
);
|
|
236
|
+
lines.push(
|
|
237
|
+
"Not every recommendation may apply to this site — review each and prioritize accordingly.\n",
|
|
272
238
|
);
|
|
273
239
|
|
|
240
|
+
let currentTier = null;
|
|
274
241
|
let num = 1;
|
|
275
242
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
currentTier = tier;
|
|
282
|
-
lines.push(`## ${tier} (${tierDescription(rec.priority)})`);
|
|
283
|
-
}
|
|
284
|
-
const benchmarkList = rec.benchmarks
|
|
285
|
-
.map((b) => BENCHMARK_NAMES[b])
|
|
286
|
-
.join(", ");
|
|
287
|
-
lines.push(`${num}. ${rec.label} [${benchmarkList}]`);
|
|
288
|
-
if (rec.detail) {
|
|
289
|
-
lines.push(` ${rec.detail}`);
|
|
290
|
-
}
|
|
291
|
-
num++;
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
if (optional.length > 0) {
|
|
296
|
-
lines.push("");
|
|
297
|
-
lines.push("## Optional (advanced agent discovery)");
|
|
298
|
-
for (const rec of optional) {
|
|
299
|
-
const benchmarkList = rec.benchmarks
|
|
300
|
-
.map((b) => BENCHMARK_NAMES[b])
|
|
301
|
-
.join(", ");
|
|
302
|
-
lines.push(`${num}. ${rec.label} [${benchmarkList}]`);
|
|
303
|
-
if (rec.detail) {
|
|
304
|
-
lines.push(` ${rec.detail}`);
|
|
305
|
-
}
|
|
306
|
-
num++;
|
|
243
|
+
for (const rec of recs) {
|
|
244
|
+
const tier = tierLabel(rec.priority);
|
|
245
|
+
if (tier !== currentTier) {
|
|
246
|
+
currentTier = tier;
|
|
247
|
+
lines.push(`## ${tier} (${tierDescription(rec.priority)})`);
|
|
307
248
|
}
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
lines.push(
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
);
|
|
315
|
-
for (const rec of apiOnly) {
|
|
316
|
-
const benchmarkList = rec.benchmarks
|
|
317
|
-
.map((b) => BENCHMARK_NAMES[b])
|
|
318
|
-
.join(", ");
|
|
319
|
-
lines.push(`${num}. ${rec.label} [${benchmarkList}]`);
|
|
320
|
-
if (rec.detail) {
|
|
321
|
-
lines.push(` ${rec.detail}`);
|
|
322
|
-
}
|
|
323
|
-
num++;
|
|
249
|
+
const benchmarkList = rec.benchmarks
|
|
250
|
+
.map((b) => BENCHMARK_NAMES[b])
|
|
251
|
+
.join(", ");
|
|
252
|
+
lines.push(`${num}. ${rec.label} [${benchmarkList}]`);
|
|
253
|
+
if (rec.detail) {
|
|
254
|
+
lines.push(` ${rec.detail}`);
|
|
324
255
|
}
|
|
256
|
+
num++;
|
|
325
257
|
}
|
|
326
258
|
|
|
327
259
|
lines.push("");
|
|
@@ -330,12 +262,11 @@ function generateAgentPrompt(result, recs) {
|
|
|
330
262
|
"- Fix what you can programmatically. For each fix, explain what you changed.",
|
|
331
263
|
);
|
|
332
264
|
lines.push(
|
|
333
|
-
"- For anything that requires infrastructure
|
|
265
|
+
"- For anything that requires infrastructure or configuration changes you can't make,",
|
|
334
266
|
);
|
|
335
267
|
lines.push(
|
|
336
|
-
" list it separately with step-by-step instructions I can follow manually.",
|
|
268
|
+
" list it separately with clear step-by-step instructions I can follow manually.",
|
|
337
269
|
);
|
|
338
|
-
lines.push("- Skip API-only items if this site doesn't expose an API.");
|
|
339
270
|
lines.push("");
|
|
340
271
|
lines.push(`Re-scan after: npx aeo-ready scan ${result.url}`);
|
|
341
272
|
|
|
@@ -389,12 +320,13 @@ export async function showRecommendations(result) {
|
|
|
389
320
|
|
|
390
321
|
console.log(`\n ${chalk.bold(summary)}\n`);
|
|
391
322
|
|
|
392
|
-
const
|
|
393
|
-
options.push(["v", "View"]);
|
|
394
|
-
options.push(["c", "Copy prompt for AI agent"]);
|
|
395
|
-
options.push(["q", "Done"]);
|
|
323
|
+
const prompt = generateAgentPrompt(result, recs);
|
|
396
324
|
|
|
397
|
-
const optStr =
|
|
325
|
+
const optStr = [
|
|
326
|
+
["v", "View prompt"],
|
|
327
|
+
["c", "Copy prompt"],
|
|
328
|
+
["q", "Done"],
|
|
329
|
+
]
|
|
398
330
|
.map(([key, label]) => `${chalk.bold(`[${key}]`)} ${label}`)
|
|
399
331
|
.join(" ");
|
|
400
332
|
|
|
@@ -402,18 +334,20 @@ export async function showRecommendations(result) {
|
|
|
402
334
|
const answer = await ask(` ${optStr} `);
|
|
403
335
|
|
|
404
336
|
if (answer === "v") {
|
|
405
|
-
|
|
337
|
+
console.log("");
|
|
338
|
+
console.log(
|
|
339
|
+
prompt
|
|
340
|
+
.split("\n")
|
|
341
|
+
.map((line) => ` ${line}`)
|
|
342
|
+
.join("\n"),
|
|
343
|
+
);
|
|
344
|
+
console.log("");
|
|
406
345
|
} else if (answer === "c") {
|
|
407
|
-
const prompt = generateAgentPrompt(result, recs);
|
|
408
346
|
const copied = copyToClipboard(prompt);
|
|
409
347
|
if (copied) {
|
|
410
348
|
console.log(chalk.green("\n Copied to clipboard.\n"));
|
|
411
349
|
} else {
|
|
412
|
-
console.log(
|
|
413
|
-
chalk.dim("\n Could not copy — here are the instructions:\n"),
|
|
414
|
-
);
|
|
415
|
-
console.log(prompt);
|
|
416
|
-
console.log("");
|
|
350
|
+
console.log(chalk.dim("\n Could not copy to clipboard.\n"));
|
|
417
351
|
}
|
|
418
352
|
break;
|
|
419
353
|
} else {
|