@jrpool/kilotest 63.2.0 → 63.2.2
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/README.md +2 -2
- package/content.ts +2 -2
- package/docs/AI-TOOLS.md +3 -1
- package/lhm.plugin.json +4 -3
- package/llms-full.txt +7 -0
- package/llms.txt +1 -1
- package/mcp.ts +1 -2
- package/openapi-3.0.yaml +1 -1
- package/openapi.yaml +1 -1
- package/package.json +3 -3
- package/scripts/check-docs.ts +59 -0
- package/scripts/generate-lhm.ts +16 -13
- package/scripts/generate-llms.ts +34 -0
- package/scripts/prePR.ts +1 -1
- package/server.json +1 -1
package/README.md
CHANGED
|
@@ -88,8 +88,8 @@ When you make a change in a feature branch **without** any API or tool contract
|
|
|
88
88
|
|
|
89
89
|
When you **make an API or tool contract change** in a feature branch:
|
|
90
90
|
|
|
91
|
-
1. `
|
|
92
|
-
2. `
|
|
91
|
+
1. `llms.txt`, `llms-full.txt`: Update narrative descriptions of the changed tools or parameters.
|
|
92
|
+
2. `capability.md` and `README.md`: Update their prose to describe the changed behavior.
|
|
93
93
|
3. Stage, commit, and optionally push all changes.
|
|
94
94
|
4. Execute `npm run prePR -- <level>` (`major`, `minor`, or `patch`).
|
|
95
95
|
5. Submit a pull request.
|
package/content.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*
|
|
2
2
|
content.ts
|
|
3
|
-
Canonical prose describing what Kilotest is and does, reused verbatim by mcp.ts, scripts/generate-openapi.ts, and scripts/generate-
|
|
3
|
+
Canonical prose describing what Kilotest is and does, reused verbatim by mcp.ts, scripts/generate-openapi.ts, scripts/generate-lhm.ts, and scripts/generate-llms.ts, so the sentences are written once instead of being hand-copied into mcp.ts, lhm.plugin.json, llms.txt, and openapi.yaml.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
// CONSTANTS
|
|
@@ -8,5 +8,5 @@
|
|
|
8
8
|
// Brief description of the Kilotest tool collection. Used as the MCP server description and as lhm.plugin.json’s top-level description. No length limit.
|
|
9
9
|
export const collectionDescription = 'Tools that test web pages with an ensemble of 12 rule engines for front-end quality (accessibility, usability, and W3C web standards, including HTML, CSS, ARIA, and WCAG)';
|
|
10
10
|
|
|
11
|
-
// Description of the Kilotest domain and data hierarchy. Used as (1) the
|
|
11
|
+
// Description of the Kilotest domain and data hierarchy. Used as (1) the McpServer instructions, which is the only place most tools' own descriptions (everything but getKilotestOverview) get this context from, since repeating it in each of their descriptions would dilute how models read each tool, (2) the first paragraph of the kilotestOverview prose that mcp.ts returns from the getKilotestOverview tool and the kilotest-overview resource, (3) the opening paragraph of llms.txt, (4) the start of the openapi.yaml info.description, and (5) the getKilotestOverview tool's own description and the kilotest-overview resource's own description, because some MCP clients do not propagate the McpServer instructions to their models, so getKilotestOverview and the kilotest-overview resource (unlike the other tools) carry the context redundantly, in both their own description and their returned body.
|
|
12
12
|
export const sharedContext = 'Kilotest integrates an ensemble of 12 rule engines, with about 1,300 rules, to test web pages for front-end quality (accessibility, usability, and W3C web standards, including HTML, CSS, ARIA, and WCAG). Each test job generates a standardized report describing which elements violated which rules and grouping the violations into about 380 issues. Kilotest can list the tested pages, the reports about each page, the issues in each report, the violators of each issue, and the diagnoses of each violation. Kilotest also accepts requests to test pages not yet tested and to retest already tested pages.';
|
package/docs/AI-TOOLS.md
CHANGED
|
@@ -97,8 +97,10 @@ A change to the tool or API contract (tool names, parameter names, schemas, resp
|
|
|
97
97
|
- `openapi-3.0.yaml`: an OpenAPI 3.0.3 conversion of `openapi.yaml`, regenerated by the same hook, for registries whose importers reject 3.1 documents; never edit it by hand.
|
|
98
98
|
- `server.json`: contains only the server descriptor (name, description, repository, remotes, version), no tool schemas. Its version is synced by `update-versions.ts`; edit it manually only if the server description or remote URL changes.
|
|
99
99
|
- `lhm.plugin.json`: embeds every tool’s input and output schema and its descriptions, in the LobeHub manifest format. Its `description` and every tool’s `description`, `inputSchema`, `outputSchema`, and `annotations` are regenerated from `mcp.ts`/`api/schemas.ts` by `scripts/generate-lhm.ts` (run by `npm run generate`, part of `npm run prePR`); never edit those fields by hand. The remaining fields (`author`, `cloudEndpoint`, `homepage`, `identifier`, `name`, `prompts`, `resources`, `tags`, `version`, and each tool’s `execution` block) have no canonical source elsewhere and are still edited manually. See `docs/decisions/010-content-generation.md`.
|
|
100
|
-
- `content.ts`: canonical prose shared verbatim by `mcp.ts`, `scripts/generate-openapi.ts`,
|
|
100
|
+
- `content.ts`: canonical prose shared verbatim by `mcp.ts`, `scripts/generate-openapi.ts`, `scripts/generate-lhm.ts`, and `scripts/generate-llms.ts` (which regenerates `llms.txt`'s opening paragraph from `sharedContext`); all four are run by `npm run generate`, so no hand-checking is needed there. `scripts/check-docs.ts` (also run by `npm run lint`) separately verifies that `llms.txt` and `llms-full.txt`'s quoted `/api/...` paths and parameters still match `api/routes.ts`.
|
|
101
101
|
- `llms-full.txt`, `capability.md`, `README.md`, `docs/openai-plugin/skills/kilotest-overview/SKILL.md`: hand-maintained, intentionally paraphrased rather than copied verbatim; search them for stale parameter and path names after a contract change.
|
|
102
|
+
- `docs/openai-plugin/plugin.json`: hand-maintained, submitted to OpenAI's plugin review (see "Registrations" above); its `review.test_cases[].tools_triggered` fields name actual tools verbatim (e.g. `"listPages, listIssues"`), so check them, not just the paraphrased prose fields, after a contract change. Its `version` and `release_notes` track revisions to this plugin submission (the manifest, the skill, and the test cases) and are unrelated to `package.json`'s version; `update-versions.ts` does not touch this file, so bump `version` and add a `release_notes` entry by hand whenever the submission changes.
|
|
103
|
+
- `docs/openai-plugin/mcp.json`: hand-maintained, but contains only the server's type and URL, so a contract change never requires editing it.
|
|
102
104
|
|
|
103
105
|
#### External registries that update themselves, needing no maintainer action
|
|
104
106
|
|
package/lhm.plugin.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
|
+
"_generated": "Do not edit the _generated, version, description, or tools property. They are automatically generated from content.ts, api/schemas.ts/mcp.ts, scripts/generate-lhm.ts, and scripts/update-versions.ts.",
|
|
2
3
|
"author": "Jonathan Robert Pool",
|
|
3
4
|
"cloudEndpoint": "https://kilotest.com/mcp",
|
|
4
|
-
"description": "Tools that test web pages with an ensemble of 12 rule engines for front-end quality (accessibility, usability, and W3C web standards, including HTML, CSS, ARIA, and WCAG)",
|
|
5
5
|
"homepage": "https://github.com/jrpool/kilotest",
|
|
6
6
|
"identifier": "jrpool-kilotest",
|
|
7
7
|
"name": "Kilotest",
|
|
@@ -18,6 +18,8 @@
|
|
|
18
18
|
"wcag",
|
|
19
19
|
"web standards"
|
|
20
20
|
],
|
|
21
|
+
"version": "63.2.2",
|
|
22
|
+
"description": "Tools that test web pages with an ensemble of 12 rule engines for front-end quality (accessibility, usability, and W3C web standards, including HTML, CSS, ARIA, and WCAG)",
|
|
21
23
|
"tools": [
|
|
22
24
|
{
|
|
23
25
|
"name": "getKilotestOverview",
|
|
@@ -4860,6 +4862,5 @@
|
|
|
4860
4862
|
"taskSupport": "forbidden"
|
|
4861
4863
|
}
|
|
4862
4864
|
}
|
|
4863
|
-
]
|
|
4864
|
-
"version": "63.2.0"
|
|
4865
|
+
]
|
|
4865
4866
|
}
|
package/llms-full.txt
CHANGED
|
@@ -101,6 +101,13 @@ Kilotest offers these tools:
|
|
|
101
101
|
- `issueID`: identifier of the issue
|
|
102
102
|
- `reportID`: identifier of the report, with YYMMDDTHHmm format for its initial segment (example: 260503T0432-x9z)
|
|
103
103
|
- source of parameters: response to a `listViolators` request
|
|
104
|
+
- `getReport`
|
|
105
|
+
- method: `GET`
|
|
106
|
+
- purpose: get one full report in JSON
|
|
107
|
+
- path: `/api/getReport/{reportID}`
|
|
108
|
+
- parameters
|
|
109
|
+
- `reportID`: identifier of the report, with YYMMDDTHHmm format for its initial segment (example: 260503T0432-x9z)
|
|
110
|
+
- source of parameters: response to a `listIssues` request
|
|
104
111
|
- `requestNewTest`
|
|
105
112
|
- method: `POST`
|
|
106
113
|
- purpose: request testing of one web page about which no report is available
|
package/llms.txt
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Kilotest
|
|
2
2
|
|
|
3
|
-
Kilotest integrates an ensemble of 12 rule engines, with about 1,300 rules, to test web pages for front-end quality (accessibility, usability, and web standards, including HTML, CSS, ARIA, and WCAG). Each test job generates a standardized report describing which elements violated which rules and grouping the violations into about 380 issues. Kilotest can list the tested pages, the reports about each page, the issues in each report, the violators of each issue, and the diagnoses of each violation. Kilotest also accepts requests to test pages not yet tested and to retest already tested pages. Kilotest features are available via a web UI, an API, and an MCP server with streamable HTTP and no authentication.
|
|
3
|
+
Kilotest integrates an ensemble of 12 rule engines, with about 1,300 rules, to test web pages for front-end quality (accessibility, usability, and W3C web standards, including HTML, CSS, ARIA, and WCAG). Each test job generates a standardized report describing which elements violated which rules and grouping the violations into about 380 issues. Kilotest can list the tested pages, the reports about each page, the issues in each report, the violators of each issue, and the diagnoses of each violation. Kilotest also accepts requests to test pages not yet tested and to retest already tested pages. Kilotest features are available via a web UI, an API, and an MCP server with streamable HTTP and no authentication.
|
|
4
4
|
|
|
5
5
|
## API
|
|
6
6
|
|
package/mcp.ts
CHANGED
|
@@ -57,8 +57,7 @@ export const mcpPath = '/mcp';
|
|
|
57
57
|
// Detailed overview of the Kilotest domain, data hierarchy, and tool workflow, returned by
|
|
58
58
|
// the getKilotestOverview tool and served as the docs://kilotest/overview resource.
|
|
59
59
|
const kilotestOverview = [
|
|
60
|
-
|
|
61
|
-
'Kilotest integrates an ensemble of twelve independent rule engines to test a web page and stores the results as a structured report.',
|
|
60
|
+
sharedContext,
|
|
62
61
|
'Results are organized as a hierarchy: tested pages; for each tested page, reports from the tests of the page; for each report, issues reported; for each issue, violators of rules belonging to the issue (a violator is an element or the whole page); for each violator, diagnoses by rule engines of its violations.',
|
|
63
62
|
'Typical workflow: call the listPages tool to learn whether the page has been tested. If it has, drill down from its latest report with the listIssues, listViolators, and listDiagnoses tools, or retrieve the entire report with the getReport tool. The listIssues output also lists all reports about the same page, so you can examine earlier reports. If the page has not been tested, request a test with the requestNewTest tool or order a test with the orderNewTest tool. If the latest report is obsolete, request a retest with the requestRetest tool or order a retest with the orderRetest tool.',
|
|
64
63
|
'The request tools submit requests for manager approval. The order tools obtain automated review and approval or rejection. Approval produces a report identifier and an opportunity to wait for completion. To wait, call the awaitTest tool with that identifier; it blocks until the report is ready, the job fails, or a maximum wait time elapses. To check later instead, call the listIssues tool with the same identifier.',
|
package/openapi-3.0.yaml
CHANGED
|
@@ -2,7 +2,7 @@ openapi: 3.0.3
|
|
|
2
2
|
info:
|
|
3
3
|
title: Kilotest API
|
|
4
4
|
description: 'Kilotest integrates an ensemble of 12 rule engines, with about 1,300 rules, to test web pages for front-end quality (accessibility, usability, and W3C web standards, including HTML, CSS, ARIA, and WCAG). Each test job generates a standardized report describing which elements violated which rules and grouping the violations into about 380 issues. Kilotest can list the tested pages, the reports about each page, the issues in each report, the violators of each issue, and the diagnoses of each violation. Kilotest also accepts requests to test pages not yet tested and to retest already tested pages. Kilotest acts as a web server for human users, an MCP server for AI platforms, and an API for programmatic access. With this API you can request that a page be tested or retested, discover available reports, and incrementally retrieve facts from a report: from what reports are available, to what issues were reported in one report, to what elements violated one issue, to what diagnoses rule engines gave for one violation.'
|
|
5
|
-
version: 63.2.
|
|
5
|
+
version: 63.2.2
|
|
6
6
|
license:
|
|
7
7
|
name: MIT
|
|
8
8
|
url: https://github.com/jrpool/kilotest/blob/main/LICENSE
|
package/openapi.yaml
CHANGED
|
@@ -2,7 +2,7 @@ openapi: 3.1.0
|
|
|
2
2
|
info:
|
|
3
3
|
title: Kilotest API
|
|
4
4
|
description: 'Kilotest integrates an ensemble of 12 rule engines, with about 1,300 rules, to test web pages for front-end quality (accessibility, usability, and W3C web standards, including HTML, CSS, ARIA, and WCAG). Each test job generates a standardized report describing which elements violated which rules and grouping the violations into about 380 issues. Kilotest can list the tested pages, the reports about each page, the issues in each report, the violators of each issue, and the diagnoses of each violation. Kilotest also accepts requests to test pages not yet tested and to retest already tested pages. Kilotest acts as a web server for human users, an MCP server for AI platforms, and an API for programmatic access. With this API you can request that a page be tested or retested, discover available reports, and incrementally retrieve facts from a report: from what reports are available, to what issues were reported in one report, to what elements violated one issue, to what diagnoses rule engines gave for one violation.'
|
|
5
|
-
version: 63.2.
|
|
5
|
+
version: 63.2.2
|
|
6
6
|
license:
|
|
7
7
|
name: MIT
|
|
8
8
|
identifier: MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jrpool/kilotest",
|
|
3
|
-
"version": "63.2.
|
|
3
|
+
"version": "63.2.2",
|
|
4
4
|
"description": "Ensemble testing for front-end web quality",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -10,11 +10,11 @@
|
|
|
10
10
|
"scripts": {
|
|
11
11
|
"start": "node index.ts",
|
|
12
12
|
"typecheck": "tsc --noEmit",
|
|
13
|
-
"lint": "npx eslint && npx htmlhint web error.html && out=$(npx markdownlint-cli2 2>&1); code=$?; if [ $code -ne 0 ]; then echo \"$out\"; exit $code; fi",
|
|
13
|
+
"lint": "npx eslint && npx htmlhint web error.html && out=$(npx markdownlint-cli2 2>&1); code=$?; if [ $code -ne 0 ]; then echo \"$out\"; exit $code; fi && node scripts/check-docs.ts",
|
|
14
14
|
"test": "c8 node --require ./test/setup.ts --experimental-test-module-mocks --test --test-concurrency=1 --test-randomize '**/*.test.ts'",
|
|
15
15
|
"test:smoke": "node smokeTest.ts",
|
|
16
16
|
"checkinfo": "node checkinfo.ts",
|
|
17
|
-
"generate": "node scripts/generate-openapi.ts && node scripts/generate-lhm.ts && node scripts/update-versions.ts",
|
|
17
|
+
"generate": "node scripts/generate-openapi.ts && node scripts/generate-lhm.ts && node scripts/generate-llms.ts && node scripts/update-versions.ts",
|
|
18
18
|
"build:media": "node scripts/buildDemoVideo.ts",
|
|
19
19
|
"publish:lhm": "npx -y @lobehub/market-cli plugin update --dir .",
|
|
20
20
|
"prePR": "node scripts/prePR.ts",
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/*
|
|
2
|
+
check-docs.ts
|
|
3
|
+
Verifies that the `/api/...` path templates (including path-parameter names and order)
|
|
4
|
+
quoted in llms.txt and llms-full.txt match api/routes.ts, the single source of truth for
|
|
5
|
+
API methods and paths. Fails with a listing of mismatches if any API path in those files is
|
|
6
|
+
missing, stale, or renders a route not present in api/routes.ts, and fails if any route in
|
|
7
|
+
api/routes.ts is not documented in a file. Run via `npm run lint`.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// IMPORTS
|
|
11
|
+
|
|
12
|
+
import fs from 'node:fs';
|
|
13
|
+
import path from 'node:path';
|
|
14
|
+
import {routes} from '../api/routes.ts';
|
|
15
|
+
|
|
16
|
+
// CONSTANTS
|
|
17
|
+
|
|
18
|
+
const rootDir = path.join(import.meta.dirname, '..');
|
|
19
|
+
const targetFiles = ['llms.txt', 'llms-full.txt'];
|
|
20
|
+
const apiPathPattern = /\/api\/[A-Za-z]+(?:\/\{[A-Za-z]+\})*/g;
|
|
21
|
+
const expectedPaths = new Set(routes.map(route => route.path));
|
|
22
|
+
|
|
23
|
+
// FUNCTIONS
|
|
24
|
+
|
|
25
|
+
// Returns the operationId of a path template, i.e. the segment right after "/api/".
|
|
26
|
+
const operationIdOf = (apiPath: string): string => apiPath.split('/')[2] ?? '';
|
|
27
|
+
|
|
28
|
+
// EXECUTION
|
|
29
|
+
|
|
30
|
+
const errors: string[] = [];
|
|
31
|
+
for (const fileName of targetFiles) {
|
|
32
|
+
const filePath = path.join(rootDir, fileName);
|
|
33
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
34
|
+
const found = new Set(content.match(apiPathPattern) ?? []);
|
|
35
|
+
for (const apiPath of found) {
|
|
36
|
+
if (!expectedPaths.has(apiPath)) {
|
|
37
|
+
const operationId = operationIdOf(apiPath);
|
|
38
|
+
const route = routes.find(candidate => candidate.operationId === operationId);
|
|
39
|
+
errors.push(
|
|
40
|
+
route
|
|
41
|
+
? `${fileName}: "${apiPath}" does not match api/routes.ts, which defines ${operationId} as "${route.path}"`
|
|
42
|
+
: `${fileName}: "${apiPath}" does not match any operationId in api/routes.ts`
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
for (const route of routes) {
|
|
47
|
+
if (!found.has(route.path)) {
|
|
48
|
+
errors.push(`${fileName}: missing the path "${route.path}" documented in api/routes.ts for ${route.operationId}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
if (errors.length) {
|
|
53
|
+
console.error('Documentation path/parameter mismatches found:');
|
|
54
|
+
for (const error of errors) {
|
|
55
|
+
console.error(` ${error}`);
|
|
56
|
+
}
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
console.log(`API paths in ${targetFiles.join(' and ')} match api/routes.ts.`);
|
package/scripts/generate-lhm.ts
CHANGED
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
generate-lhm.ts
|
|
3
3
|
Regenerates the description and tool entries (description, inputSchema, outputSchema,
|
|
4
4
|
annotations) of lhm.plugin.json from the single sources of truth: content.ts for prose and
|
|
5
|
-
api/schemas.ts (via the same registrations mcp.ts makes) for schemas
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
api/schemas.ts (via the same registrations mcp.ts makes) for schemas, and (re)writes a
|
|
6
|
+
"_generated" warning property so editors of the raw JSON see that those fields are
|
|
7
|
+
overwritten on the next generation. version has its own generator, update-versions.ts, which
|
|
8
|
+
copies it from package.json. Every remaining property (author, cloudEndpoint, homepage,
|
|
9
|
+
identifier, name, prompts, resources, tags, and each tool's execution block) has no
|
|
10
|
+
generator anywhere in the repository, so it is left untouched here and is meant to be
|
|
11
|
+
edited by hand.
|
|
10
12
|
*/
|
|
11
13
|
|
|
12
14
|
// IMPORTS
|
|
@@ -50,10 +52,10 @@ type ZodRawShape = Record<string, z.ZodTypeAny>;
|
|
|
50
52
|
|
|
51
53
|
const outputPath = path.join(import.meta.dirname, '..', 'lhm.plugin.json');
|
|
52
54
|
const jsonSchemaOptions = {target: 'draft-7' as const, unrepresentable: 'any' as const};
|
|
55
|
+
// Edit warning (disregarded on publication per https://market.lobehub.com/s/publish-mcp/references/manifest.md).
|
|
56
|
+
const generatedWarning = 'Do not edit the _generated, version, description, or tools property. They are automatically generated from content.ts, api/schemas.ts/mcp.ts, scripts/generate-lhm.ts, and scripts/update-versions.ts.';
|
|
53
57
|
|
|
54
|
-
// The input and output schemas mcp.ts passes to registerTool for each tool, keyed by tool
|
|
55
|
-
// name, matching mcp.ts's own registerTool calls exactly (mcp.ts remains the source for
|
|
56
|
-
// descriptions and annotations, read at runtime below via createMCPServer).
|
|
58
|
+
// The input and output schemas mcp.ts passes to registerTool for each tool, keyed by tool name, matching mcp.ts's own registerTool calls (mcp.ts remains the source for descriptions and annotations, read at runtime below via createMCPServer).
|
|
57
59
|
const toolSchemas: Record<string, {input: ZodRawShape; output?: z.ZodTypeAny}> = {
|
|
58
60
|
getKilotestOverview: {input: {}},
|
|
59
61
|
listPages: {input: {}, output: listPagesResponseSchema},
|
|
@@ -72,16 +74,14 @@ const toolSchemas: Record<string, {input: ZodRawShape; output?: z.ZodTypeAny}> =
|
|
|
72
74
|
|
|
73
75
|
// FUNCTIONS
|
|
74
76
|
|
|
75
|
-
// Builds the lhm.plugin.json inputSchema for a tool: like outputSchema below, but LobeHub
|
|
76
|
-
// existing input schemas never carry additionalProperties, so that key is dropped.
|
|
77
|
+
// Builds the lhm.plugin.json inputSchema for a tool: like outputSchema below, but LobeHub’sexisting input schemas never carry additionalProperties, so that key is dropped.
|
|
77
78
|
const buildInputSchema = (shape: ZodRawShape): Record<string, unknown> => {
|
|
78
79
|
const generated = z.toJSONSchema(z.object(shape), jsonSchemaOptions) as Record<string, unknown>;
|
|
79
80
|
delete generated.additionalProperties;
|
|
80
81
|
const {$schema, ...withoutSchemaKeyword} = generated;
|
|
81
82
|
return {...withoutSchemaKeyword, $schema};
|
|
82
83
|
};
|
|
83
|
-
// Builds the lhm.plugin.json outputSchema for a tool, reordering keys to match the file
|
|
84
|
-
// existing convention ($schema placed just before additionalProperties and definitions).
|
|
84
|
+
// Builds the lhm.plugin.json outputSchema for a tool, reordering keys to match the file’s existing convention ($schema placed just before additionalProperties and definitions).
|
|
85
85
|
const buildOutputSchema = (schema: z.ZodTypeAny): Record<string, unknown> => {
|
|
86
86
|
const generated = z.toJSONSchema(schema, jsonSchemaOptions) as Record<string, unknown>;
|
|
87
87
|
const {$schema, additionalProperties, definitions, ...rest} = generated;
|
|
@@ -97,7 +97,10 @@ const buildOutputSchema = (schema: z.ZodTypeAny): Record<string, unknown> => {
|
|
|
97
97
|
|
|
98
98
|
const server = createMCPServer();
|
|
99
99
|
const registeredTools = (server as unknown as {_registeredTools: Record<string, {description: string; annotations: unknown}>})._registeredTools;
|
|
100
|
-
const
|
|
100
|
+
const parsedManifest = JSON.parse(fs.readFileSync(outputPath, 'utf8'));
|
|
101
|
+
// Places "_generated" first regardless of where (or whether) it already appears, so it is the first thing a reader of the raw JSON sees. The explicit reassignment after the spread is required even though "_generated" is already a key: were the input file's own (possibly stale) "_generated" value to spread in after it, the spread’s last-write-wins rule would silently keep that stale value in place, even though the key's position stays first either way. Reassigning the other keys below does not move their position, since they already exist on this object.
|
|
102
|
+
const manifest = {_generated: generatedWarning, ...parsedManifest};
|
|
103
|
+
manifest._generated = generatedWarning;
|
|
101
104
|
manifest.description = collectionDescription;
|
|
102
105
|
manifest.tools = manifest.tools.map((tool: {name: string; execution: unknown}) => {
|
|
103
106
|
const registered = registeredTools[tool.name];
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/*
|
|
2
|
+
generate-llms.ts
|
|
3
|
+
Regenerates the opening paragraph of llms.txt from content.ts's sharedContext, the single
|
|
4
|
+
source of truth content.ts already documents that paragraph as reusing (along with the MCP
|
|
5
|
+
server instructions, the openapi.yaml description, and the getKilotestOverview tool
|
|
6
|
+
description). Leaves the rest of llms.txt untouched, because it has no canonical source
|
|
7
|
+
elsewhere in the repository.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// IMPORTS
|
|
11
|
+
|
|
12
|
+
import fs from 'node:fs';
|
|
13
|
+
import path from 'node:path';
|
|
14
|
+
import {sharedContext} from '../content.ts';
|
|
15
|
+
|
|
16
|
+
// CONSTANTS
|
|
17
|
+
|
|
18
|
+
const outputPath = path.join(import.meta.dirname, '..', 'llms.txt');
|
|
19
|
+
// Text appended after sharedContext to form the full opening paragraph; unlike sharedContext,
|
|
20
|
+
// this sentence is specific to llms.txt (it is not reused anywhere else), so it lives here
|
|
21
|
+
// rather than in content.ts.
|
|
22
|
+
const openingSuffix = ' Kilotest features are available via a web UI, an API, and an MCP server with streamable HTTP and no authentication.';
|
|
23
|
+
const openingParagraph = `${sharedContext}${openingSuffix}`;
|
|
24
|
+
|
|
25
|
+
// EXECUTION
|
|
26
|
+
|
|
27
|
+
const lines = fs.readFileSync(outputPath, 'utf8').split('\n');
|
|
28
|
+
const paragraphIndex = lines.findIndex(line => line.startsWith('Kilotest integrates an ensemble of'));
|
|
29
|
+
if (paragraphIndex === -1) {
|
|
30
|
+
throw new Error(`Could not find the opening paragraph to regenerate in ${outputPath}`);
|
|
31
|
+
}
|
|
32
|
+
lines[paragraphIndex] = openingParagraph;
|
|
33
|
+
fs.writeFileSync(outputPath, lines.join('\n'));
|
|
34
|
+
console.log(`Wrote ${outputPath}`);
|
package/scripts/prePR.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*
|
|
2
2
|
prePR.ts
|
|
3
|
-
Prepares a release pull request on the current feature branch: verifies a clean working tree, bumps the package version, regenerates the generated files (openapi.yaml, openapi-3.0.yaml, server.json, and lhm.plugin.json), commits and pushes the result, records the branch name for postPR.ts, and prints the remaining manual steps. The generation is run explicitly because the project's .npmrc sets ignore-scripts=true, which disables the npm "version" lifecycle hook that would otherwise run it.
|
|
3
|
+
Prepares a release pull request on the current feature branch: verifies a clean working tree, bumps the package version, regenerates the generated files (openapi.yaml, openapi-3.0.yaml, lhm.plugin.json, the opening paragraph of llms.txt, server.json, and the version field of lhm.plugin.json), commits and pushes the result, records the branch name for postPR.ts, and prints the remaining manual steps. The generation is run explicitly because the project's .npmrc sets ignore-scripts=true, which disables the npm "version" lifecycle hook that would otherwise run it.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
// IMPORTS
|