ultra11y 2.22.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/LICENSE +21 -0
- package/README.md +223 -0
- package/docker/Dockerfile +7 -0
- package/docker/package.json +9 -0
- package/docker/runner.mjs +23 -0
- package/package.json +73 -0
- package/scripts/bench.mjs +151 -0
- package/scripts/build-act-corpus.mjs +143 -0
- package/scripts/build-adjudication.mjs +503 -0
- package/scripts/build-pack-rgaa.mjs +397 -0
- package/scripts/build-standards.mjs +548 -0
- package/scripts/copy-bundle.mjs +39 -0
- package/scripts/import-pack.mjs +107 -0
- package/scripts/sync-engine.mjs +84 -0
- package/scripts/sync-version.mjs +43 -0
- package/scripts/ultra11y.mjs +52739 -0
- package/scripts/vendor/act-testcases.json +12297 -0
- package/scripts/vendor/rgaa/SOURCE.json +8 -0
- package/scripts/vendor/rgaa/criteres.json +4144 -0
- package/scripts/vendor/rgaa/glossaire.json +480 -0
- package/scripts/vendor/wcag-2.2-fr.json +82 -0
- package/scripts/vendor/wcag-2.2-sc-universe.json +950 -0
- package/scripts/vendor/wcag-2.2-sc.json +574 -0
- package/scripts/verify-rgaa-source.mjs +126 -0
- package/scripts/verify-skill-bundle.mjs +91 -0
- package/skills/review-a11y/SKILL.md +123 -0
- package/skills/review-a11y/scripts/ultra11y.mjs +52739 -0
- package/skills/ultra11y/SKILL.md +292 -0
- package/skills/ultra11y/references/act.md +163 -0
- package/skills/ultra11y/references/adjudication.md +599 -0
- package/skills/ultra11y/references/audit.md +100 -0
- package/skills/ultra11y/references/authoring.md +37 -0
- package/skills/ultra11y/references/automation.md +113 -0
- package/skills/ultra11y/references/correction.md +41 -0
- package/skills/ultra11y/references/criteria.md +129 -0
- package/skills/ultra11y/references/cross-file.md +82 -0
- package/skills/ultra11y/references/dynamic.md +152 -0
- package/skills/ultra11y/references/false-positives.md +81 -0
- package/skills/ultra11y/references/fix.md +46 -0
- package/skills/ultra11y/references/focus-and-logic.md +64 -0
- package/skills/ultra11y/references/forbidden-patterns.md +61 -0
- package/skills/ultra11y/references/forms-and-errors.md +147 -0
- package/skills/ultra11y/references/guidance.md +55 -0
- package/skills/ultra11y/references/judgment.md +90 -0
- package/skills/ultra11y/references/media-and-motion.md +116 -0
- package/skills/ultra11y/references/methodology.md +72 -0
- package/skills/ultra11y/references/naming.md +117 -0
- package/skills/ultra11y/references/orchestration.md +44 -0
- package/skills/ultra11y/references/packs.md +193 -0
- package/skills/ultra11y/references/prd.md +104 -0
- package/skills/ultra11y/references/rendered.md +110 -0
- package/skills/ultra11y/references/scale.md +49 -0
- package/skills/ultra11y/references/standards.md +97 -0
- package/skills/ultra11y/references/structure.md +138 -0
- package/skills/ultra11y/references/verify.md +88 -0
- package/skills/ultra11y/references/widgets.md +106 -0
- package/skills/ultra11y/scripts/ultra11y.mjs +52739 -0
- package/src/act.ts +441 -0
- package/src/adjudicate.ts +630 -0
- package/src/aria.ts +230 -0
- package/src/audit.ts +396 -0
- package/src/auditor.ts +399 -0
- package/src/autofill.ts +102 -0
- package/src/axe-map.ts +294 -0
- package/src/baseline.ts +75 -0
- package/src/capture.ts +182 -0
- package/src/check.ts +243 -0
- package/src/cli.ts +1927 -0
- package/src/color.ts +102 -0
- package/src/config.ts +182 -0
- package/src/crawl.ts +75 -0
- package/src/criteria.ts +183 -0
- package/src/data/adjudication.json +770 -0
- package/src/data/guidance/rgaa.json +2395 -0
- package/src/data/standards/rgaa.glossary.json +478 -0
- package/src/data/standards/rgaa.json +3454 -0
- package/src/data/wcag-universe.json +530 -0
- package/src/data/wcag.json +1178 -0
- package/src/discover.ts +203 -0
- package/src/fix/codemods.ts +76 -0
- package/src/fix/diff.ts +64 -0
- package/src/fix/edits.ts +126 -0
- package/src/fix.ts +215 -0
- package/src/gh.ts +214 -0
- package/src/glob.ts +206 -0
- package/src/graph/build.ts +114 -0
- package/src/graph/engine-resolve.ts +0 -0
- package/src/graph/graph.ts +126 -0
- package/src/graph/imports.ts +359 -0
- package/src/graph/resolve.ts +73 -0
- package/src/graph/tsconfig.ts +113 -0
- package/src/grounding.ts +119 -0
- package/src/guidance/index.ts +45 -0
- package/src/guidance/types.ts +36 -0
- package/src/init.ts +113 -0
- package/src/mcp/handlers.ts +388 -0
- package/src/mcp/http.ts +260 -0
- package/src/mcp/prompts.ts +183 -0
- package/src/mcp/protocol.ts +187 -0
- package/src/mcp/resources.ts +136 -0
- package/src/mcp/server.ts +228 -0
- package/src/mcp/stdio.ts +119 -0
- package/src/mcp/tools.ts +347 -0
- package/src/messages.ts +1011 -0
- package/src/name.ts +174 -0
- package/src/orchestrate-templates.ts +231 -0
- package/src/orchestrate.ts +186 -0
- package/src/output.ts +108 -0
- package/src/pack.ts +187 -0
- package/src/parse/html.ts +258 -0
- package/src/parse/jsx-ast.ts +67 -0
- package/src/parse/jsx-bridge.ts +247 -0
- package/src/parse/jsx.ts +19 -0
- package/src/parse/source.ts +75 -0
- package/src/prd.ts +406 -0
- package/src/project-lock.ts +42 -0
- package/src/render.ts +307 -0
- package/src/report.ts +399 -0
- package/src/rules/colors.ts +125 -0
- package/src/rules/cross-registry.ts +264 -0
- package/src/rules/cross-rule.ts +83 -0
- package/src/rules/forms.ts +590 -0
- package/src/rules/frames.ts +33 -0
- package/src/rules/headings.ts +227 -0
- package/src/rules/images.ts +200 -0
- package/src/rules/links.ts +193 -0
- package/src/rules/mandatory.ts +173 -0
- package/src/rules/multimedia.ts +77 -0
- package/src/rules/navigation.ts +190 -0
- package/src/rules/presentation.ts +75 -0
- package/src/rules/registry.ts +57 -0
- package/src/rules/rule.ts +122 -0
- package/src/rules/scripts-aria.ts +636 -0
- package/src/rules/tables.ts +264 -0
- package/src/rules/timing.ts +55 -0
- package/src/sample.ts +176 -0
- package/src/scan-local.ts +866 -0
- package/src/scan.ts +538 -0
- package/src/standards/derive.ts +195 -0
- package/src/standards/index.ts +31 -0
- package/src/standards/pack-rules.ts +111 -0
- package/src/standards/pack.ts +81 -0
- package/src/standards/registry.ts +100 -0
- package/src/standards/types.ts +202 -0
- package/src/standards/validate.ts +544 -0
- package/src/standards/vocabulary.ts +75 -0
- package/src/types.ts +355 -0
- package/src/util.ts +32 -0
- package/src/vendor/codeindex-engine.d.mts +1009 -0
- package/src/vendor/codeindex-engine.mjs +13701 -0
- package/src/vendor/engine.meta.json +9 -0
- package/src/verify.ts +275 -0
- package/src/wcag.ts +128 -0
package/src/mcp/tools.ts
ADDED
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
import { ANNOTATIONS_SINCE, RICH_TOOLS_SINCE, type JsonSchema, type JsonSchemaProp, type ProtocolVersion } from "./protocol.js";
|
|
2
|
+
|
|
3
|
+
// What the server advertises. Pure data — nothing here imports the audit
|
|
4
|
+
// engine, so the declarations can be asserted in a test without parsing any
|
|
5
|
+
// markup. handlers.ts is where these names become work.
|
|
6
|
+
|
|
7
|
+
export interface ToolDecl {
|
|
8
|
+
name: string;
|
|
9
|
+
description: string;
|
|
10
|
+
inputSchema: JsonSchema;
|
|
11
|
+
title?: string;
|
|
12
|
+
outputSchema?: JsonSchema;
|
|
13
|
+
annotations?: Record<string, boolean>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const cwdProp: JsonSchemaProp = { type: "string", description: "Absolute path to the project root the paths are relative to." };
|
|
17
|
+
const globsProp: JsonSchemaProp = {
|
|
18
|
+
type: "array",
|
|
19
|
+
items: { type: "string" },
|
|
20
|
+
description: "Files or globs to audit (e.g. ['src/**/*.tsx']). Relative to the project root.",
|
|
21
|
+
};
|
|
22
|
+
const standardProp: JsonSchemaProp = {
|
|
23
|
+
type: "string",
|
|
24
|
+
enum: ["wcag", "rgaa"],
|
|
25
|
+
description: "Which standard to report against. Default: wcag (WCAG 2.2 AA).",
|
|
26
|
+
};
|
|
27
|
+
const langProp: JsonSchemaProp = { type: "string", enum: ["en", "fr"], description: "Language for the rendered prose. Default: en." };
|
|
28
|
+
|
|
29
|
+
// The sentence that keeps this server honest. The engine decides 3 of the 55
|
|
30
|
+
// WCAG 2.2 AA criteria on its own; `scan` decides 14 from a real browser; the
|
|
31
|
+
// remaining 38 are judgment calls that only the model can make. A client that
|
|
32
|
+
// misses this reads a clean static audit as a clean audit.
|
|
33
|
+
const COVERAGE_NOTE =
|
|
34
|
+
"Static analysis alone decides only a few of the 55 WCAG 2.2 AA criteria — most need YOUR judgment (is this alt text actually relevant? " +
|
|
35
|
+
"is this link's purpose clear in context?) and some need a real browser (ultra11y_scan). A silent criterion is untested, never conformant.";
|
|
36
|
+
|
|
37
|
+
export const TOOLS: ToolDecl[] = [
|
|
38
|
+
{
|
|
39
|
+
name: "ultra11y_audit",
|
|
40
|
+
title: "Audit markup against WCAG 2.2 AA",
|
|
41
|
+
description:
|
|
42
|
+
"Run the static engine over HTML/CSS/JSX and return the findings keyed by WCAG success criterion. Fast and offline — no browser, no network, no keys. " +
|
|
43
|
+
"This is the entry point. " +
|
|
44
|
+
COVERAGE_NOTE,
|
|
45
|
+
inputSchema: {
|
|
46
|
+
type: "object",
|
|
47
|
+
properties: {
|
|
48
|
+
cwd: cwdProp,
|
|
49
|
+
globs: globsProp,
|
|
50
|
+
changed: { type: "boolean", description: "Audit only the files git reports as changed." },
|
|
51
|
+
since: { type: "string", description: "Audit only what changed since this git ref." },
|
|
52
|
+
staged: { type: "boolean", description: "Audit exactly the staged index snapshot." },
|
|
53
|
+
include: { type: "array", items: { type: "string" }, description: "Extra globs to include." },
|
|
54
|
+
exclude: { type: "array", items: { type: "string" }, description: "Globs to skip." },
|
|
55
|
+
jsx: { type: "boolean", description: "Force JSX parsing for files the extension does not imply." },
|
|
56
|
+
graph: { type: "boolean", description: "Also run cross-file rules over the dependency graph — catches a label defined in another file." },
|
|
57
|
+
max_files: { type: "number", description: "Hard cap on files audited (truncation is reported, never silent)." },
|
|
58
|
+
},
|
|
59
|
+
required: ["cwd"],
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: "ultra11y_report",
|
|
64
|
+
title: "Render a dated conformance report",
|
|
65
|
+
description:
|
|
66
|
+
"Turn an audit into the auditor-facing conformance report: one section per success criterion, with the evidence and the verdict. Says explicitly " +
|
|
67
|
+
"which criteria were not tested, because a report silent about its own coverage reads as a clean bill of health.",
|
|
68
|
+
inputSchema: {
|
|
69
|
+
type: "object",
|
|
70
|
+
properties: { cwd: cwdProp, globs: globsProp, standard: standardProp, lang: langProp },
|
|
71
|
+
required: ["cwd"],
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: "ultra11y_prd",
|
|
76
|
+
title: "Turn findings into a remediation backlog",
|
|
77
|
+
description:
|
|
78
|
+
"Convert an audit into actionable work: one unit per non-conformity, with the criterion it violates, the fix, and an effort estimate. Use it to hand " +
|
|
79
|
+
"accessibility debt to a team rather than a wall of violations.",
|
|
80
|
+
inputSchema: {
|
|
81
|
+
type: "object",
|
|
82
|
+
properties: {
|
|
83
|
+
cwd: cwdProp,
|
|
84
|
+
globs: globsProp,
|
|
85
|
+
standard: standardProp,
|
|
86
|
+
lang: langProp,
|
|
87
|
+
split: { type: "string", enum: ["criterion"], description: "Emit one unit per criterion instead of one document." },
|
|
88
|
+
},
|
|
89
|
+
required: ["cwd"],
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
name: "ultra11y_criteria",
|
|
94
|
+
title: "The offline standards reference",
|
|
95
|
+
description:
|
|
96
|
+
"Look up what a success criterion actually requires — its exact wording, how it is tested, and what counts as a failure. Offline and authoritative; " +
|
|
97
|
+
"use it instead of recalling a criterion from memory, which is how invented non-conformities get written.",
|
|
98
|
+
inputSchema: {
|
|
99
|
+
type: "object",
|
|
100
|
+
properties: {
|
|
101
|
+
sc: { type: "string", description: "A success criterion number (e.g. '1.1.1'). Omit to list them all." },
|
|
102
|
+
standard: standardProp,
|
|
103
|
+
lang: langProp,
|
|
104
|
+
},
|
|
105
|
+
required: [],
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
name: "ultra11y_check",
|
|
110
|
+
title: "The anti-hallucination gate",
|
|
111
|
+
description:
|
|
112
|
+
"Validate a report you wrote: every criterion it cites must exist, every non-conformity must trace to a real finding, and nothing may be asserted " +
|
|
113
|
+
"conformant that was never tested. A result with ok:false is a real verdict, not a tool failure — it means the report claims more than the evidence carries.",
|
|
114
|
+
inputSchema: {
|
|
115
|
+
type: "object",
|
|
116
|
+
properties: {
|
|
117
|
+
cwd: cwdProp,
|
|
118
|
+
report_text: { type: "string", description: "The report markdown to validate. Preferred over report_file." },
|
|
119
|
+
report_file: { type: "string", description: "Absolute path to a report file to validate instead." },
|
|
120
|
+
standard: standardProp,
|
|
121
|
+
lang: langProp,
|
|
122
|
+
},
|
|
123
|
+
required: ["cwd"],
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
name: "ultra11y_verify",
|
|
128
|
+
title: "Build a claim-evidence worklist",
|
|
129
|
+
description:
|
|
130
|
+
"Emit a claim-by-evidence worklist from a report, for you to adjudicate each pair. This is where the 38 judgment criteria get decided: read the real " +
|
|
131
|
+
"markup and rule on whether the alt text is relevant, the link purpose is clear, the reading order makes sense.",
|
|
132
|
+
inputSchema: {
|
|
133
|
+
type: "object",
|
|
134
|
+
properties: {
|
|
135
|
+
cwd: cwdProp,
|
|
136
|
+
report_text: { type: "string", description: "The report markdown to build the worklist from." },
|
|
137
|
+
report_file: { type: "string", description: "Absolute path to a report file to use instead." },
|
|
138
|
+
standard: standardProp,
|
|
139
|
+
max_verify: { type: "number", description: "Cap on the number of claim/evidence pairs emitted." },
|
|
140
|
+
lang: langProp,
|
|
141
|
+
},
|
|
142
|
+
required: ["cwd"],
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
name: "ultra11y_adjudicate",
|
|
147
|
+
title: "Worklist for the judgment criteria",
|
|
148
|
+
description:
|
|
149
|
+
"Emit the criteria the engine CANNOT decide, with the evidence needed to decide them: alt-text relevance, link purpose in context, heading structure, " +
|
|
150
|
+
"reading order, label-in-name. Most of WCAG lives here — this is the tool that makes an audit real rather than a lint run.",
|
|
151
|
+
inputSchema: {
|
|
152
|
+
type: "object",
|
|
153
|
+
properties: { cwd: cwdProp, globs: globsProp, standard: standardProp, lang: langProp },
|
|
154
|
+
required: ["cwd"],
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
name: "ultra11y_pack_check",
|
|
159
|
+
title: "Validate a country standards pack",
|
|
160
|
+
description:
|
|
161
|
+
"Check that a country standards pack (RGAA and friends) matches what the published standard actually ships, so a localized audit cannot be graded " +
|
|
162
|
+
"against invented criteria. Reads the pack; changes nothing.",
|
|
163
|
+
inputSchema: {
|
|
164
|
+
type: "object",
|
|
165
|
+
properties: {
|
|
166
|
+
cwd: cwdProp,
|
|
167
|
+
pack: { type: "string", description: "Absolute path to the pack JSON." },
|
|
168
|
+
guidance: { type: "string", description: "Absolute path to its guidance file." },
|
|
169
|
+
},
|
|
170
|
+
required: ["cwd", "pack"],
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
name: "ultra11y_sample_check",
|
|
175
|
+
title: "Lint the normative page sample",
|
|
176
|
+
description:
|
|
177
|
+
"Validate a project's `.ultra11yrc.json` page sample against the methodology: a conformance claim covering only the pages that happened to be easy " +
|
|
178
|
+
"is not a conformance claim. Reads the config; changes nothing.",
|
|
179
|
+
inputSchema: { type: "object", properties: { cwd: cwdProp }, required: ["cwd"] },
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
name: "ultra11y_read",
|
|
183
|
+
title: "Read a file from the project",
|
|
184
|
+
description:
|
|
185
|
+
"Read a file, or a line range of one, from the audited project. Use it to see the real markup behind a finding before judging it. Reads are confined " +
|
|
186
|
+
"to the project root; anything else is your own file tool's job.",
|
|
187
|
+
inputSchema: {
|
|
188
|
+
type: "object",
|
|
189
|
+
properties: {
|
|
190
|
+
cwd: cwdProp,
|
|
191
|
+
path: { type: "string", description: "Path relative to the project root, or an absolute path inside it." },
|
|
192
|
+
start_line: { type: "number", description: "First line to return, 1-based (default 1)." },
|
|
193
|
+
end_line: { type: "number", description: "Last line to return, inclusive (default: end of file, capped)." },
|
|
194
|
+
},
|
|
195
|
+
required: ["cwd", "path"],
|
|
196
|
+
},
|
|
197
|
+
outputSchema: {
|
|
198
|
+
type: "object",
|
|
199
|
+
properties: {
|
|
200
|
+
path: { type: "string" },
|
|
201
|
+
start_line: { type: "number" },
|
|
202
|
+
end_line: { type: "number" },
|
|
203
|
+
total_lines: { type: "number" },
|
|
204
|
+
truncated: { type: "boolean" },
|
|
205
|
+
content: { type: "string" },
|
|
206
|
+
},
|
|
207
|
+
required: ["path", "start_line", "end_line", "total_lines", "truncated", "content"],
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
];
|
|
211
|
+
|
|
212
|
+
// Registered only when the server is started with --allow-write. All three
|
|
213
|
+
// change the USER'S project, and `scan` additionally drives a real browser.
|
|
214
|
+
export const WRITE_TOOLS: ToolDecl[] = [
|
|
215
|
+
{
|
|
216
|
+
name: "ultra11y_fix",
|
|
217
|
+
title: "Apply safe accessibility codemods",
|
|
218
|
+
description:
|
|
219
|
+
"WRITES TO THE PROJECT: apply the mechanical fixes — the ones with exactly one correct answer, like a missing lang attribute or a button with no " +
|
|
220
|
+
"accessible name. Dry-run by default; with write:true it re-audits afterwards and refuses to keep a change that introduced a new non-conformity. " +
|
|
221
|
+
"It never invents alt text: that is a judgment call and it leaves a TODO for you.",
|
|
222
|
+
inputSchema: {
|
|
223
|
+
type: "object",
|
|
224
|
+
properties: {
|
|
225
|
+
cwd: cwdProp,
|
|
226
|
+
globs: globsProp,
|
|
227
|
+
write: { type: "boolean", description: "Actually apply the changes (default: dry-run, returns the diff)." },
|
|
228
|
+
only: { type: "array", items: { type: "string" }, description: "Apply only these rule ids." },
|
|
229
|
+
changed: { type: "boolean", description: "Fix only the files git reports as changed." },
|
|
230
|
+
},
|
|
231
|
+
required: ["cwd"],
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
name: "ultra11y_scan",
|
|
236
|
+
title: "Audit the rendered page in a real browser",
|
|
237
|
+
description:
|
|
238
|
+
"SLOW: launches a headless browser (optionally via Docker) and runs axe-core against the RENDERED DOM, then merges the result into the static audit. " +
|
|
239
|
+
"This is the only way to decide the 14 rendering criteria — contrast, focus visibility, zoom, reflow, hover, target size — which no static analysis " +
|
|
240
|
+
"can reach. Expect tens of seconds per page, more on a first run that pulls an image.",
|
|
241
|
+
inputSchema: {
|
|
242
|
+
type: "object",
|
|
243
|
+
properties: {
|
|
244
|
+
cwd: cwdProp,
|
|
245
|
+
target: { type: "string", description: "A URL or a local HTML file to render." },
|
|
246
|
+
runtime: { type: "string", enum: ["auto", "local", "docker"], description: "Where to get the browser. Default: auto." },
|
|
247
|
+
merge: { type: "boolean", description: "Merge the rendered findings into the existing static audit." },
|
|
248
|
+
},
|
|
249
|
+
required: ["cwd", "target"],
|
|
250
|
+
},
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
name: "ultra11y_init",
|
|
254
|
+
title: "Install the accessibility gate",
|
|
255
|
+
description:
|
|
256
|
+
"WRITES TO THE PROJECT: install a git pre-commit hook, a CI job, and/or a baseline so accessibility regressions fail the build instead of accumulating. " +
|
|
257
|
+
"Modifies files in the repository — review the result before committing it.",
|
|
258
|
+
inputSchema: {
|
|
259
|
+
type: "object",
|
|
260
|
+
properties: {
|
|
261
|
+
cwd: cwdProp,
|
|
262
|
+
hook: { type: "boolean", description: "Install the git pre-commit hook." },
|
|
263
|
+
ci: { type: "boolean", description: "Install the CI workflow." },
|
|
264
|
+
baseline: { type: "boolean", description: "Record the current findings as the accepted baseline." },
|
|
265
|
+
fail_on: { type: "string", enum: ["error", "warning", "notice"], description: "Severity that fails the gate." },
|
|
266
|
+
},
|
|
267
|
+
required: ["cwd"],
|
|
268
|
+
},
|
|
269
|
+
},
|
|
270
|
+
];
|
|
271
|
+
|
|
272
|
+
// Behavioural hints clients use to decide what needs a confirmation prompt.
|
|
273
|
+
//
|
|
274
|
+
// The read-only line is drawn at the USER'S project. Every tool in TOOLS reads
|
|
275
|
+
// markup and returns a result; `fix`, `scan` and `init` change files there.
|
|
276
|
+
export const TOOL_META: Record<string, { write?: boolean; destructive?: boolean; idempotent?: boolean; openWorld?: boolean }> = {
|
|
277
|
+
ultra11y_audit: { openWorld: false },
|
|
278
|
+
ultra11y_report: { openWorld: false },
|
|
279
|
+
ultra11y_prd: { openWorld: false },
|
|
280
|
+
ultra11y_criteria: { openWorld: false },
|
|
281
|
+
ultra11y_check: { openWorld: false },
|
|
282
|
+
ultra11y_verify: { openWorld: false },
|
|
283
|
+
ultra11y_adjudicate: { openWorld: false },
|
|
284
|
+
ultra11y_pack_check: { openWorld: false },
|
|
285
|
+
ultra11y_sample_check: { openWorld: false },
|
|
286
|
+
ultra11y_read: { openWorld: false },
|
|
287
|
+
// Rewrites source files. Not destructive in the delete sense, and it verifies
|
|
288
|
+
// its own work — but it is the user's code.
|
|
289
|
+
ultra11y_fix: { write: true, destructive: false, idempotent: true, openWorld: false },
|
|
290
|
+
// Fetches a URL and may pull a Docker image.
|
|
291
|
+
ultra11y_scan: { write: true, destructive: false, idempotent: false, openWorld: true },
|
|
292
|
+
ultra11y_init: { write: true, destructive: false, idempotent: true, openWorld: false },
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
export function annotationsFor(name: string): Record<string, boolean> | undefined {
|
|
296
|
+
const meta = TOOL_META[name];
|
|
297
|
+
if (!meta) return undefined;
|
|
298
|
+
return {
|
|
299
|
+
readOnlyHint: !meta.write,
|
|
300
|
+
...(meta.write ? { destructiveHint: meta.destructive === true, idempotentHint: meta.idempotent === true } : {}),
|
|
301
|
+
openWorldHint: meta.openWorld === true,
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
export interface ToolsForOptions {
|
|
306
|
+
defaultCwd?: string;
|
|
307
|
+
allowWrite?: boolean;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// The tool list as one client should see it: gated on what the server was
|
|
311
|
+
// started with, and on how new the negotiated protocol is.
|
|
312
|
+
export function toolsFor(protocolVersion: ProtocolVersion, opts: ToolsForOptions = {}): ToolDecl[] {
|
|
313
|
+
const base = opts.allowWrite ? [...TOOLS, ...WRITE_TOOLS] : TOOLS;
|
|
314
|
+
const withAnnotations = protocolVersion >= ANNOTATIONS_SINCE;
|
|
315
|
+
const withRich = protocolVersion >= RICH_TOOLS_SINCE;
|
|
316
|
+
|
|
317
|
+
return base.map((t) => {
|
|
318
|
+
const decl: ToolDecl = {
|
|
319
|
+
name: t.name,
|
|
320
|
+
description: t.description,
|
|
321
|
+
inputSchema: applyDefaultCwd(t.inputSchema, opts.defaultCwd),
|
|
322
|
+
};
|
|
323
|
+
if (withRich && t.title) decl.title = t.title;
|
|
324
|
+
if (withRich && t.outputSchema) decl.outputSchema = t.outputSchema;
|
|
325
|
+
if (withAnnotations) {
|
|
326
|
+
const a = annotationsFor(t.name);
|
|
327
|
+
if (a) decl.annotations = a;
|
|
328
|
+
}
|
|
329
|
+
return decl;
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// With a server-level default project root, `cwd` stops being required and its
|
|
334
|
+
// description names the default — so a client can call every tool with no cwd
|
|
335
|
+
// argument at all.
|
|
336
|
+
function applyDefaultCwd(schema: JsonSchema, defaultCwd?: string): JsonSchema {
|
|
337
|
+
const existing = schema.properties.cwd;
|
|
338
|
+
if (!defaultCwd || !existing) return schema;
|
|
339
|
+
return {
|
|
340
|
+
type: "object",
|
|
341
|
+
properties: {
|
|
342
|
+
...schema.properties,
|
|
343
|
+
cwd: { ...existing, description: `${existing.description} Optional — defaults to ${defaultCwd}.` },
|
|
344
|
+
},
|
|
345
|
+
required: schema.required.filter((r) => r !== "cwd"),
|
|
346
|
+
};
|
|
347
|
+
}
|