@aexol/spectral 0.9.125 → 0.9.127

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.
Files changed (75) hide show
  1. package/dist/agent/index.d.ts.map +1 -1
  2. package/dist/agent/index.js +5 -0
  3. package/dist/cli.js +6 -0
  4. package/dist/commands/update.d.ts +17 -0
  5. package/dist/commands/update.d.ts.map +1 -0
  6. package/dist/commands/update.js +292 -0
  7. package/dist/extensions/seo/analyzers/content.d.ts +29 -6
  8. package/dist/extensions/seo/analyzers/content.d.ts.map +1 -1
  9. package/dist/extensions/seo/analyzers/content.js +243 -8
  10. package/dist/extensions/seo/analyzers/crawler.d.ts.map +1 -1
  11. package/dist/extensions/seo/analyzers/crawler.js +133 -7
  12. package/dist/extensions/seo/analyzers/drift.d.ts.map +1 -1
  13. package/dist/extensions/seo/analyzers/drift.js +86 -29
  14. package/dist/extensions/seo/analyzers/images.d.ts +10 -4
  15. package/dist/extensions/seo/analyzers/images.d.ts.map +1 -1
  16. package/dist/extensions/seo/analyzers/images.js +153 -5
  17. package/dist/extensions/seo/analyzers/performance.d.ts +3 -3
  18. package/dist/extensions/seo/analyzers/performance.d.ts.map +1 -1
  19. package/dist/extensions/seo/analyzers/performance.js +77 -6
  20. package/dist/extensions/seo/analyzers/readability.d.ts.map +1 -1
  21. package/dist/extensions/seo/analyzers/readability.js +17 -9
  22. package/dist/extensions/seo/analyzers/schema.d.ts.map +1 -1
  23. package/dist/extensions/seo/analyzers/schema.js +99 -10
  24. package/dist/extensions/seo/analyzers/sitemap.d.ts.map +1 -1
  25. package/dist/extensions/seo/analyzers/sitemap.js +57 -16
  26. package/dist/extensions/seo/analyzers/technical.d.ts +0 -7
  27. package/dist/extensions/seo/analyzers/technical.d.ts.map +1 -1
  28. package/dist/extensions/seo/analyzers/technical.js +408 -37
  29. package/dist/extensions/seo/config.d.ts +2 -0
  30. package/dist/extensions/seo/config.d.ts.map +1 -1
  31. package/dist/extensions/seo/config.js +2 -0
  32. package/dist/extensions/seo/tools/batch.js +1 -1
  33. package/dist/extensions/seo/tools/content.d.ts.map +1 -1
  34. package/dist/extensions/seo/tools/content.js +5 -3
  35. package/dist/extensions/seo/tools/full-audit.d.ts +1 -1
  36. package/dist/extensions/seo/tools/full-audit.d.ts.map +1 -1
  37. package/dist/extensions/seo/tools/full-audit.js +391 -66
  38. package/dist/extensions/seo/tools/helpers.d.ts +15 -4
  39. package/dist/extensions/seo/tools/helpers.d.ts.map +1 -1
  40. package/dist/extensions/seo/tools/helpers.js +57 -6
  41. package/dist/extensions/seo/tools/performance.d.ts.map +1 -1
  42. package/dist/extensions/seo/tools/performance.js +17 -11
  43. package/dist/extensions/seo/tools/report.d.ts.map +1 -1
  44. package/dist/extensions/seo/tools/report.js +513 -47
  45. package/dist/extensions/seo/types.d.ts +295 -3
  46. package/dist/extensions/seo/types.d.ts.map +1 -1
  47. package/dist/extensions/seo/utils/fetcher.d.ts +4 -0
  48. package/dist/extensions/seo/utils/fetcher.d.ts.map +1 -1
  49. package/dist/extensions/seo/utils/fetcher.js +77 -11
  50. package/dist/extensions/seo/utils/parser.d.ts +3 -1
  51. package/dist/extensions/seo/utils/parser.d.ts.map +1 -1
  52. package/dist/extensions/seo/utils/parser.js +105 -25
  53. package/dist/extensions/seo/utils/renderer.d.ts +6 -1
  54. package/dist/extensions/seo/utils/renderer.d.ts.map +1 -1
  55. package/dist/extensions/seo/utils/renderer.js +207 -1
  56. package/dist/extensions/seo/utils/url-safety.d.ts.map +1 -1
  57. package/dist/extensions/seo/utils/url-safety.js +19 -3
  58. package/dist/extensions/web/tools/fetch.js +2 -2
  59. package/dist/memory/tools/compact-context.d.ts.map +1 -1
  60. package/dist/memory/tools/compact-context.js +10 -3
  61. package/dist/sdk/agent-core/agent-loop.d.ts.map +1 -1
  62. package/dist/sdk/agent-core/agent-loop.js +87 -4
  63. package/dist/sdk/agent-core/types.d.ts +1 -0
  64. package/dist/sdk/agent-core/types.d.ts.map +1 -1
  65. package/dist/sdk/ai/utils/validation.d.ts +0 -7
  66. package/dist/sdk/ai/utils/validation.d.ts.map +1 -1
  67. package/dist/sdk/ai/utils/validation.js +21 -1
  68. package/dist/server/session-stream.d.ts.map +1 -1
  69. package/dist/server/session-stream.js +41 -0
  70. package/dist/server/storage.d.ts +9 -0
  71. package/dist/server/storage.d.ts.map +1 -1
  72. package/dist/server/storage.js +35 -9
  73. package/dist/server/wire.d.ts +2 -0
  74. package/dist/server/wire.d.ts.map +1 -1
  75. package/package.json +1 -1
@@ -1,15 +1,56 @@
1
- /** Create a text-only tool result. */
2
- export function textResult(text, details = {}) {
1
+ /** Version of the SEO tool result schema. Increment on breaking changes. */
2
+ export const SEO_RESULT_VERSION = 2;
3
+ /** Create a text tool result. Accepts either legacy (text, details) or new (text, result, warnings). */
4
+ export function textResult(text, detailsOrResult, warnings) {
5
+ // Detect legacy call: second arg is a plain object with string keys.
6
+ const isLegacy = detailsOrResult !== undefined
7
+ && typeof detailsOrResult === "object"
8
+ && detailsOrResult !== null
9
+ && !Array.isArray(detailsOrResult);
10
+ if (isLegacy) {
11
+ const details = detailsOrResult;
12
+ return {
13
+ content: [{ type: "text", text }],
14
+ details: {
15
+ ...details,
16
+ metadata: { ...(details.metadata ?? {}), version: SEO_RESULT_VERSION },
17
+ },
18
+ };
19
+ }
3
20
  return {
4
21
  content: [{ type: "text", text }],
5
- details,
22
+ details: {
23
+ result: detailsOrResult,
24
+ warnings: warnings ?? [],
25
+ metadata: { version: SEO_RESULT_VERSION },
26
+ },
6
27
  };
7
28
  }
8
- /** Create an error tool result. */
9
- export function errorResult(message, details = {}) {
29
+ /** Create an error tool result. Accepts either legacy (msg, details) or new (msg, result, warnings). */
30
+ export function errorResult(message, detailsOrResult, warnings) {
31
+ const isLegacy = detailsOrResult !== undefined
32
+ && typeof detailsOrResult === "object"
33
+ && detailsOrResult !== null
34
+ && !Array.isArray(detailsOrResult);
35
+ if (isLegacy) {
36
+ const details = detailsOrResult;
37
+ return {
38
+ content: [{ type: "text", text: `❌ ${message}` }],
39
+ details: {
40
+ isError: true,
41
+ ...details,
42
+ metadata: { ...(details.metadata ?? {}), version: SEO_RESULT_VERSION },
43
+ },
44
+ };
45
+ }
10
46
  return {
11
47
  content: [{ type: "text", text: `❌ ${message}` }],
12
- details: { isError: true, ...details },
48
+ details: {
49
+ isError: true,
50
+ result: detailsOrResult,
51
+ warnings: warnings ?? [],
52
+ metadata: { version: SEO_RESULT_VERSION },
53
+ },
13
54
  };
14
55
  }
15
56
  /** Format a JSON object as pretty-printed text for tool output. */
@@ -22,3 +63,13 @@ export function truncate(text, maxLen) {
22
63
  return text;
23
64
  return text.slice(0, maxLen) + "... (truncated)";
24
65
  }
66
+ /** Validate and normalize a tool URL input, enforcing length limits. */
67
+ export function validateToolUrl(raw, maxLen = 4096) {
68
+ const trimmed = raw.trim();
69
+ if (trimmed.length > maxLen) {
70
+ throw new Error(`URL exceeds maximum length of ${maxLen} characters.`);
71
+ }
72
+ if (!trimmed)
73
+ throw new Error("URL is required.");
74
+ return trimmed;
75
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"performance.d.ts","sourceRoot":"","sources":["../../../../src/extensions/seo/tools/performance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAkB,MAAM,oCAAoC,CAAC;AACvF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAW9C,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,YAAY,EAAE,MAAM,EAAE,SAAS,GAAG,IAAI,CA4NnF"}
1
+ {"version":3,"file":"performance.d.ts","sourceRoot":"","sources":["../../../../src/extensions/seo/tools/performance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAkB,MAAM,oCAAoC,CAAC;AACvF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAS9C,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,YAAY,EAAE,MAAM,EAAE,SAAS,GAAG,IAAI,CA8MnF"}
@@ -2,14 +2,13 @@ import { fetchPage } from "../utils/fetcher.js";
2
2
  import { calculatePerformanceFromFetch, analyzePageWeight, analyzeRenderBlocking, analyzeFonts, } from "../analyzers/performance.js";
3
3
  import { errorResult, textResult } from "./helpers.js";
4
4
  export function registerPerformanceTools(ext, config) {
5
- // === seo_performance ===
6
5
  const perfTool = {
7
6
  name: "seo_performance",
8
7
  label: "SEO Performance Audit (Core Web Vitals)",
9
8
  description: "Estimate Core Web Vitals metrics from page structure analysis. " +
10
9
  "Reports LCP (Largest Contentful Paint), CLS (Cumulative Layout Shift), TBT (Total Blocking Time), FCP, and TTFB. " +
11
10
  "Each metric is rated: good, needs-improvement, or poor against Google's thresholds. " +
12
- "Note: These are heuristic estimates based on page complexity. For accurate numbers use Lighthouse or PageSpeed Insights.",
11
+ "When a browser is available, real Web Vitals are measured via Playwright.",
13
12
  promptSnippet: "`seo_performance { url }` — estimate Core Web Vitals (LCP, CLS, TBT) with ratings",
14
13
  parameters: {
15
14
  type: "object",
@@ -22,7 +21,17 @@ export function registerPerformanceTools(ext, config) {
22
21
  const { url } = params;
23
22
  try {
24
23
  const fetchResult = await fetchPage(url, config);
25
- const perf = calculatePerformanceFromFetch(fetchResult, url);
24
+ let measuredPerformance = undefined;
25
+ try {
26
+ const { isRendererAvailable, renderPage } = await import("../utils/renderer.js");
27
+ if (await isRendererAvailable()) {
28
+ const rendered = await renderPage(url, config, { capturePerformance: true });
29
+ if (rendered.measuredPerformance)
30
+ measuredPerformance = rendered.measuredPerformance;
31
+ }
32
+ }
33
+ catch { /* renderer not available */ }
34
+ const perf = calculatePerformanceFromFetch(fetchResult, url, measuredPerformance);
26
35
  const lines = [
27
36
  `✓ Performance Estimate: ${perf.url}`,
28
37
  ``,
@@ -34,8 +43,8 @@ export function registerPerformanceTools(ext, config) {
34
43
  ` TBT: ${perf.tbt.value}ms — ${perf.tbt.rating.toUpperCase()}`,
35
44
  ``,
36
45
  `Other Metrics:`,
37
- ` FCP: ${perf.fcp}ms`,
38
- ` TTFB: ${perf.ttfb}ms`,
46
+ ` FCP: ${perf.fcp.value}ms (${perf.fcp.rating})`,
47
+ ` TTFB: ${perf.ttfb.value}ms (${perf.ttfb.rating})`,
39
48
  ``,
40
49
  `Google Thresholds:`,
41
50
  ` LCP: good ≤ 2500ms, poor > 4000ms`,
@@ -49,7 +58,6 @@ export function registerPerformanceTools(ext, config) {
49
58
  }
50
59
  },
51
60
  };
52
- // === seo_page_weight ===
53
61
  const weightTool = {
54
62
  name: "seo_page_weight",
55
63
  label: "SEO Page Weight Analysis",
@@ -84,11 +92,11 @@ export function registerPerformanceTools(ext, config) {
84
92
  if (weight.topHeavyResources.length > 0) {
85
93
  lines.push(``, `Heaviest resources:`);
86
94
  for (const r of weight.topHeavyResources) {
87
- lines.push(` ${r.type.toUpperCase()}: ${r.sizeKb} KB — ${r.url}`);
95
+ lines.push(` ${r.type.toUpperCase()}: ${r.url} (${r.sizeKb} KB)`);
88
96
  }
89
97
  }
90
- if (weight.totalKb > 5000) {
91
- lines.push(``, `⚠ Page exceeds 5MB — may impact mobile performance.`);
98
+ if (weight.totalKb < 500) {
99
+ lines.push(``, `✓ Page weight is excellent.`);
92
100
  }
93
101
  else if (weight.totalKb > 2000) {
94
102
  lines.push(``, `⚡ Page weight is above average. Consider optimizing assets.`);
@@ -100,7 +108,6 @@ export function registerPerformanceTools(ext, config) {
100
108
  }
101
109
  },
102
110
  };
103
- // === seo_render_blocking ===
104
111
  const blockingTool = {
105
112
  name: "seo_render_blocking",
106
113
  label: "SEO Render-Blocking Resource Audit",
@@ -151,7 +158,6 @@ export function registerPerformanceTools(ext, config) {
151
158
  }
152
159
  },
153
160
  };
154
- // === seo_font_audit ===
155
161
  const fontTool = {
156
162
  name: "seo_font_audit",
157
163
  label: "SEO Font Optimization Audit",
@@ -1 +1 @@
1
- {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../../../src/extensions/seo/tools/report.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAkB,MAAM,oCAAoC,CAAC;AACvF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAI9C,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,YAAY,EAAE,MAAM,EAAE,SAAS,GAAG,IAAI,CA+E9E"}
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../../../src/extensions/seo/tools/report.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAkB,MAAM,oCAAoC,CAAC;AACvF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAqB9C,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,YAAY,EAAE,MAAM,EAAE,SAAS,GAAG,IAAI,CAgH9E"}