@jrpool/kilotest 36.2.0 → 37.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/alerts.js CHANGED
@@ -19,7 +19,7 @@ const ALERT_FROM = process.env.ALERT_FROM;
19
19
  // FUNCTIONS
20
20
 
21
21
  // Sends an email alert to a manager.
22
- exports.sendAlert = (subject, body) => new Promise((resolve, reject) => {
22
+ exports.sendAlert = (subject, body) => new Promise(resolve => {
23
23
  // If the alert configuration is complete:
24
24
  if (MANAGER_EMAIL && ALERT_API_HOST && ALERT_API_PATH && ALERT_API_KEY && ALERT_FROM) {
25
25
  const payload = JSON.stringify({
@@ -185,4 +185,4 @@ The [Perplexity documentation](https://www.perplexity.ai/help-center/en/articles
185
185
 
186
186
  Once the compatibility of Kilotest as a connector with AI platforms of two different vendors had been confirmed, the focus of work returned to completion of the missing endpoints of the API. The first was an endpoint that would let a model efficiently search for an available report about a particular web page.
187
187
 
188
- The new `identifyReportsAboutMatchingWebPages` tool provides inputs for fragments of a description and of a URL hostname of a web page and responds with summary data about all and only the available reports of pages that match at least one of those fragments, where matching means either including or being included by the provided fragment, case-insensitively.
188
+ The new `summarizeQualityOfMatchingWebPages` tool provides inputs for fragments of a description and of a URL hostname of a web page and responds with summary data about all and only the available reports of pages that match at least one of those fragments, where matching means either including or being included by the provided fragment, case-insensitively.
package/eslint.config.mjs CHANGED
@@ -3,7 +3,7 @@ import globals from "globals";
3
3
  import json from "@eslint/json";
4
4
  import markdown from "@eslint/markdown";
5
5
  import css from "@eslint/css";
6
- import { defineConfig } from "eslint/config";
6
+ import {defineConfig} from "eslint/config";
7
7
 
8
8
  export default defineConfig([
9
9
  {
@@ -18,6 +18,9 @@ export default defineConfig([
18
18
  extends: ["js/recommended"],
19
19
  languageOptions: {
20
20
  globals: globals.node
21
+ },
22
+ rules: {
23
+ "no-control-regex": "off"
21
24
  }
22
25
  },
23
26
  {
package/index.js CHANGED
@@ -30,6 +30,7 @@ const {
30
30
  } = require('./util');
31
31
  const {handleMCP, mcpPath} = require('./mcp');
32
32
  const fs = require('fs/promises');
33
+ const {handleComment} = require('./tutorial/index');
33
34
  const http = require('http');
34
35
  const https = require('https');
35
36
  const path = require('path');
@@ -342,10 +343,10 @@ const requestHandler = async (request, response) => {
342
343
  // Otherwise, if it is for an API service:
343
344
  else if (pageName === 'api') {
344
345
  const [service, ... specs] = pathTail.split('/');
345
- // If the service is provision of facts about the available reports:
346
- if (service === 'targets') {
346
+ // If the service is provision of a list of all available reports:
347
+ if (service === 'reportList') {
347
348
  // Get the response (potentially error) data.
348
- const responseData = await require(path.join(__dirname, 'targets', 'api')).response(specs);
349
+ const responseData = await require(path.join(__dirname, 'reportList', 'api')).response(specs);
349
350
  // Send them.
350
351
  setHeaders('application/json', null, 'ultra');
351
352
  response.end(JSON.stringify(responseData));
@@ -702,7 +703,7 @@ const requestHandler = async (request, response) => {
702
703
  // Otherwise, if the first segment is the report finding service:
703
704
  else if (segments[0] === 'target') {
704
705
  const {what = '', hostname = ''} = postData;
705
- // If the payload contains a description fragment or URL fragment:
706
+ // If the payload contains a description fragment or hostname fragment:
706
707
  if (what || hostname) {
707
708
  // Process the request and get the response data.
708
709
  const responseData = await require(path.join(__dirname, 'target', 'api'))
@@ -762,7 +763,7 @@ const requestHandler = async (request, response) => {
762
763
  else if (pageName === 'tutorialComment.html') {
763
764
  const {content} = postData;
764
765
  setHeaders('application/json', null, 'low');
765
- const answerData = await require(path.join(__dirname, 'tutorial', 'index')).saveComment(content);
766
+ const answerData = await handleComment(content);
766
767
  if (answerData.status === 'ok') {
767
768
  response.end(JSON.stringify({status: 'ok'}));
768
769
  }
package/llms-full.txt CHANGED
@@ -82,10 +82,10 @@ The implementation is currently in an alpha phase and offers 4 tools:
82
82
  - payload properties
83
83
  - `what`: all or part of a description of the page
84
84
  - `hostname`: all or part of the hostname of the page
85
- - `summarizeQualityOfAllTestedWebPages`
85
+ - `getListOfAllAvailableReports`
86
86
  - method: `GET`
87
- - purpose: summarize front-end quality test results from all available reports
88
- - path: `/api/targets`
87
+ - purpose: get a list of all available reports
88
+ - path: `/api/reportList`
89
89
  - caveat: Cached results are likely to be stale and should not be used
90
90
  - `describeQualityOfOneWebPage`
91
91
  - method: `GET`
@@ -94,7 +94,7 @@ The implementation is currently in an alpha phase and offers 4 tools:
94
94
  - parameters
95
95
  - `timeStamp`: initial segment of report identifier
96
96
  - `jobID`: final segment of report identifier
97
- - source of parameters: response to a `summarizeQualityOfAllTestedWebPages` request
97
+ - source of parameters: response to a `getListOfAllAvailableReports` request
98
98
  - `describeOneIssueFromOneReport`
99
99
  - method: `GET`
100
100
  - purpose: provide details about one issue from one report
@@ -156,7 +156,7 @@ More information about Kilotest features and internals:
156
156
 
157
157
  ### For language models and AI platforms
158
158
 
159
- - [AI-TOOL file](https://github.com/jrpool/kilotest/blob/main/AI-TOOL.md)
159
+ - [AI-TOOL file](https://github.com/jrpool/kilotest/blob/main/docs/AI-TOOL.md)
160
160
  - [OpenAPI specification for Kilotest](https://kilotest.com/openapi.yaml)
161
161
  - [Tool caller for testing](https://github.com/jrpool/kilotest/blob/main/researchAgent.js)
162
162
 
package/llms.txt CHANGED
@@ -8,8 +8,8 @@ There is a [detailed explanation of Kilotest and its capabilities for LLMs](http
8
8
 
9
9
  ## API
10
10
 
11
- - [Find any available reports about a specified web page](/api/identifyReportsAboutMatchingWebPages)
12
- - [Get summaries of all available reports](/api/targets)
11
+ - [Get summaries of reports about a specified web page](/api/target)
12
+ - [Get a list of all available reports](/api/reportList)
13
13
  - Get summarized test results from one report: `/api/reportIssues/{timeStamp}/{jobID}`
14
14
  - Get details about one issue from one report: `/api/reportIssue/{issueID}/{timeStamp}/{jobID}`
15
15
  - Recommend testing of a web page: `/api/testRecForm` (requires `POST` request)
package/mcp.js CHANGED
@@ -10,7 +10,7 @@ const {StreamableHTTPServerTransport} = require('@modelcontextprotocol/sdk/serve
10
10
  const {z} = require('zod');
11
11
  const {isReportAvailable, isURL} = require('./util');
12
12
  const targetAPI = require('./target/api');
13
- const targetsAPI = require('./targets/api');
13
+ const reportListAPI = require('./reportList/api');
14
14
  const reportIssuesAPI = require('./reportIssues/api');
15
15
  const reportIssueAPI = require('./reportIssue/api');
16
16
  const testRecFormAPI = require('./testRecForm/api');
@@ -27,10 +27,10 @@ const createMCPServer = () => {
27
27
  server.registerTool(
28
28
  'summarizeQualityOfMatchingWebPages',
29
29
  {
30
- description: 'Returns summary data from every available Kilotest report about the front-end quality (i.e. accessibility, usability, and standards conformity) of web pages that match the description or hostname fragment of a web page that you have provided. Matching is case-insensitive and succeeds if the page property either is included by or includes the specified fragmant. Before calling recommendQualityTestingOfOneWebPage and waiting for testing to occur, call this tool to check whether a report about the page is available now.',
30
+ description: 'Returns summary data from every available Kilotest report about the front-end quality (i.e. accessibility, usability, and standards conformity) of web pages that match the description or hostname fragment of a web page that you have provided. Matching is case-insensitive and succeeds if the page property either is included by or includes the specified fragment.',
31
31
  inputSchema: {
32
32
  what: z.string().describe('All or part of a description of the web page.'),
33
- url: z.string().describe('All or part of the hostname of the URL of the web page.')
33
+ hostname: z.string().describe('All or part of the hostname of the URL of the web page.')
34
34
  },
35
35
  annotations: {
36
36
  title: 'Summarize the quality of matching web pages',
@@ -40,18 +40,18 @@ const createMCPServer = () => {
40
40
  openWorldHint: false
41
41
  }
42
42
  },
43
- async ({what, url}) => {
44
- const result = await targetAPI.response([what, url]);
43
+ async ({what, hostname}) => {
44
+ const result = await targetAPI.response([what, hostname]);
45
45
  return {content: [{type: 'text', text: JSON.stringify(result)}]};
46
46
  }
47
47
  );
48
48
  server.registerTool(
49
- 'summarizeQualityOfAllTestedWebPages',
49
+ 'getListOfAllAvailableReports',
50
50
  {
51
- description: 'Returns summary data from every available Kilotest report about the front-end quality (i.e. accessibility, usability, and standards conformity) of a web page.',
51
+ description: 'Returns a list of all available Kilotest reports; each report describes the results of a job that tested one web page for front-end quality (i.e. accessibility, usability, and standards conformity).',
52
52
  inputSchema: {},
53
53
  annotations: {
54
- title: 'Summarize the quality of all tested web pages',
54
+ title: 'Get a list of all available reports',
55
55
  readOnlyHint: true,
56
56
  idempotentHint: true,
57
57
  destructiveHint: false,
@@ -59,14 +59,14 @@ const createMCPServer = () => {
59
59
  }
60
60
  },
61
61
  async () => {
62
- const result = await targetsAPI.response();
62
+ const result = await reportListAPI.response();
63
63
  return {content: [{type: 'text', text: JSON.stringify(result)}]};
64
64
  }
65
65
  );
66
66
  server.registerTool(
67
67
  'describeQualityOfOneWebPage',
68
68
  {
69
- description: 'Returns data from a specified Kilotest report about issues for the front-end quality (i.e. accessibility, usability, and standards conformity) of a web page. The required timeStamp and jobID parameters identify the report and are obtained from a summarizeQualityOfAllTestedWebPages response.',
69
+ description: 'Returns data from a specified Kilotest report about issues for the front-end quality (i.e. accessibility, usability, and standards conformity) of a web page. The required timeStamp and jobID parameters identify the report and are obtained from a getListOfAllAvailableReports response.',
70
70
  inputSchema: {
71
71
  timeStamp: z.string().describe('Report timestamp in YYMMDDTHHMM format, e.g. 260503T0432'),
72
72
  jobID: z.string().describe('Job identifier, e.g. x9z')
@@ -109,9 +109,9 @@ const createMCPServer = () => {
109
109
  server.registerTool(
110
110
  'recommendQualityTestingOfOneWebPage',
111
111
  {
112
- description: 'Recommends a web page for Kilotest to test for front-end quality (i.e. accessibility, usability, and standards conformity). Do not call this tool until after you call summarizeQualityOfAllTestedWebPages to check whether a report about the page, or a related page that satisfies your requirements, is available.',
112
+ description: 'Recommends a web page for Kilotest to test for front-end quality (i.e. accessibility, usability, and standards conformity). Do not call this tool until after you call getListOfAllAvailableReports to check whether a report about the page, or a related page that satisfies your requirements, is available and to understand the naming conventions for pages.',
113
113
  inputSchema: {
114
- what: z.string().describe('Short description of the page, following the naming conventions visible in the summarizeQualityOfAllTestedWebPages response'),
114
+ what: z.string().describe('Short description of the page, following the naming conventions visible in the getListOfAllAvailableReports response'),
115
115
  url: z.string().describe('Full HTTPS URL of the page to test'),
116
116
  why: z.string().describe('Reason for recommending this page for testing')
117
117
  },
package/openapi.yaml CHANGED
@@ -17,7 +17,7 @@ paths:
17
17
  post:
18
18
  operationId: summarizeQualityOfMatchingWebPages
19
19
  summary: Summarize the quality of matching web pages
20
- description: Get summary data from the available reports about web pages whose descriptions or hostnames match your specifications. Matching is case-insensitive and succeeds at least 1 specification is included by or includes the corresponding property of a tested page. The data include the name and URL of each tested web page, when the testing was performed, how many front-end quality (i.e. accessibility, usability, and standards conformity) issues were reported, and URLs for retrieving more detailed data from the report. Before calling the recommendQualityTestingOfOneWebPage tool and waiting for testing to occur, call this tool to check whether a report about the page is available now. If so, you can retrieve data from it. If not, you can use the recommendQualityTestingOfOneWebPage tool to recommend the page for testing.
20
+ description: Get summary data from the available reports about web pages whose descriptions or hostnames match your specifications. Matching is case-insensitive and succeeds if at least 1 specification is included by or includes the corresponding property of a tested page. The data include the name and URL of each tested web page, when the testing was performed, how many front-end quality (i.e. accessibility, usability, and standards conformity) issues were reported, and URLs for retrieving more detailed data from the report.
21
21
  requestBody:
22
22
  description: Page specifications
23
23
  required: true
@@ -33,24 +33,24 @@ paths:
33
33
  schema:
34
34
  $ref: '#/components/schemas/TargetsResponse'
35
35
 
36
- /api/targets:
36
+ /api/reportList:
37
37
  get:
38
- operationId: summarizeQualityOfAllTestedWebPages
39
- summary: Summarize the quality of all tested web pages
40
- description: Get summary data about every non-hidden report available from Kilotest, including the name and URL of the tested web page, when the testing was performed, how many front-end quality (i.e. accessibility, usability, and standard-conformity) issues were reported, and URLs for retrieving more detailed data from the report.
38
+ operationId: getListOfAllAvailableReports
39
+ summary: Get a list of all available reports
40
+ description: Get a list of all available reports. Each report describes the results of a job that tested a web page for front-end quality (i.e. accessibility, usability, and standards conformity). For each report, the list identifies which page was tested and when and provides URLs to begin incremental retrieval of the test results.
41
41
  responses:
42
42
  '200':
43
- description: Summaries of available reports
43
+ description: List of all available reports
44
44
  content:
45
45
  application/json:
46
46
  schema:
47
- $ref: '#/components/schemas/TargetsResponse'
47
+ $ref: '#/components/schemas/ReportListResponse'
48
48
 
49
49
  /api/testRecForm:
50
50
  post:
51
51
  operationId: recommendQualityTestingOfOneWebPage
52
52
  summary: Recommend quality testing of one web page
53
- description: Submit a recommendation for Kilotest to test, for the first time, a particular web page for front-end quality (i.e. accessibility, usability, and standards conformity). Recommendations are typically approved and the testing completed within a day, whereupon the results can be found with the summarizeQualityOfAllTestedWebPages operation. Before submitting a recommendation, use the summarizeQualityOfAllTestedWebPages operation to ensure that no report about the page is available, and also to see the stylistic rules for the naming of pages. An attempt to recommend a page for testing will fail if a report about the page is already available.
53
+ description: Submit a recommendation for Kilotest to test, for the first time, a particular web page for front-end quality (i.e. accessibility, usability, and standards conformity). Recommendations are typically approved and the testing completed within a day, whereupon the results can be found with the getListOfAllAvailableReports operation. Before submitting a recommendation, use the getListOfAllAvailableReports operation to ensure that no report about the page is available, and also to see the stylistic rules for the naming of pages. An attempt to recommend a page for testing will fail if a report about the page is already available.
54
54
  requestBody:
55
55
  description: Test recommendation specifications
56
56
  required: true
@@ -70,7 +70,7 @@ paths:
70
70
  get:
71
71
  operationId: describeQualityOfOneWebPage
72
72
  summary: Describe quality of one web page
73
- description: Get data about the quality of a specified Kilotest report. The data about each issue include its priority, the rule engines that reported it, the number of HTML elements exhibiting it, and URLs for retrieving element-level detail. The timeStamp and jobID parameters identify the report and are available in the response from the summarizeQualityOfAllTestedWebPages operation.
73
+ description: Get data about the quality of a specified Kilotest report. The data about each issue include its priority, the rule engines that reported it, the number of HTML elements exhibiting it, and URLs for retrieving element-level detail. The timeStamp and jobID parameters identify the report and are available in the response from the getListOfAllAvailableReports operation.
74
74
  parameters:
75
75
  - name: timeStamp
76
76
  in: path
@@ -146,10 +146,14 @@ components:
146
146
  summary:
147
147
  type: string
148
148
  description: Natural-language description of this response and of Kilotest. Provides context for an agent encountering Kilotest for the first time.
149
- tool name:
149
+ tool collection name:
150
150
  type: string
151
151
  examples:
152
152
  - Kilotest
153
+ tool name:
154
+ type: string
155
+ examples:
156
+ - getListOfAllAvailableReports
153
157
  request:
154
158
  type: object
155
159
  properties:
@@ -158,6 +162,8 @@ components:
158
162
  properties:
159
163
  identifier:
160
164
  type: string
165
+ examples:
166
+ - reportList
161
167
  description:
162
168
  type: string
163
169
  method:
@@ -167,7 +173,7 @@ components:
167
173
  - POST
168
174
  payload:
169
175
  type: object
170
- description: Present only for POST requests. The request payload.
176
+ description: The request payload, if method type is POST, or otherwise omitted.
171
177
  URLs:
172
178
  type: object
173
179
  properties:
@@ -197,6 +203,7 @@ components:
197
203
  description: Unique identifier for this response instance.
198
204
  date and time:
199
205
  type: string
206
+ description: UTC date and time when the response was generated, in ISO 8601 format.
200
207
  format: date-time
201
208
 
202
209
  TestRecForm:
@@ -306,12 +313,44 @@ components:
306
313
  $ref: '#/components/schemas/RuleEnginesSummary'
307
314
  rule engines that reported issues:
308
315
  $ref: '#/components/schemas/RuleEnginesSummary'
309
- URLs for getting data on the reported issues:
316
+ URLs for getting data about the reported issues:
310
317
  $ref: '#/components/schemas/NextTierURLs'
311
318
  URL for getting the full technical report as JSON:
312
319
  type: string
313
320
  format: uri
314
321
 
322
+ ReportListItem:
323
+ type: object
324
+ description: Summary data about a single available report.
325
+ properties:
326
+ identifier:
327
+ type: string
328
+ examples:
329
+ - 260504T1659-029
330
+ creation date and time:
331
+ type: string
332
+ format: date-time
333
+ days since the creation date:
334
+ type: integer
335
+ tested web page:
336
+ type: object
337
+ properties:
338
+ description:
339
+ type: string
340
+ URL:
341
+ type: string
342
+ format: uri
343
+ whether a later report about the same page exists:
344
+ type: boolean
345
+ description: If true, a more recent report about this page is available. If you want the latest results, use that report instead.
346
+ URLs for incrementally getting facts from the report:
347
+ $ref: '#/components/schemas/NextTierURLs'
348
+ size of the report in bytes:
349
+ type: integer
350
+ URL to get the entire report as machine-oriented JSON:
351
+ type: string
352
+ format: uri
353
+
315
354
  Target:
316
355
  type: object
317
356
  properties:
@@ -322,7 +361,7 @@ components:
322
361
  type: string
323
362
  description: All or part of the hostname of the web page. The hostname omits the scheme and the path.
324
363
 
325
- TargetsResponse:
364
+ ReportListResponse:
326
365
  allOf:
327
366
  - $ref: '#/components/schemas/CommonResponseFields'
328
367
  - type: object
@@ -330,6 +369,17 @@ components:
330
369
  available reports:
331
370
  type: array
332
371
  description: One entry per available Kilotest report, in alphabetical order by page description and, in case of multiple reports per page, in order of creation date and time. Reports are matched by page description, not page URL, so, if only the URL of a page has changed between reports, the reports are treated as reports about the same page.
372
+ items:
373
+ $ref: '#/components/schemas/ReportListItem'
374
+
375
+ TargetsResponse:
376
+ allOf:
377
+ - $ref: '#/components/schemas/CommonResponseFields'
378
+ - type: object
379
+ properties:
380
+ matching reports:
381
+ type: array
382
+ description: One entry per available matching Kilotest report. A report is matching if its page description or hostname contains or is contained by a specified description or hostname fragment, respectively.
333
383
  items:
334
384
  $ref: '#/components/schemas/TargetsItem'
335
385
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jrpool/kilotest",
3
- "version": "36.2.0",
3
+ "version": "37.1.0",
4
4
  "description": "An ensemble testing service with a focus on accessibility",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -106,13 +106,13 @@ exports.response = async args => {
106
106
  const thisHost = process.env.THIS_KILOTEST_HOST;
107
107
  // Get a response.
108
108
  const content = {
109
- summary: `This document fulfills a request made by a language model to a Kilotest tool. The model requested data, drawn from a Kilotest report, about one of the issues for the front-end quality (i.e. accessibility, usability, and standard-conformity) of a web page. Kilotest, with the help of Testaro, Testilo, and an ensemble of ten rule engines, performs tests on web pages, using a combination of rule- and machine-learning-based methods, and produces reports. Kilotest exposes several API endpoints to recommend web pages for testing and to obtain information from Kilotest reports. To learn more about Kilotest and the advangages of testing with an ensemble of rule engines, visit the deployed instance of Kilotest (${process.env.DEPLOYED_KILOTEST_HOST}), which contains an introduction on its home page and a tutorial.`,
109
+ summary: `This document fulfills a request made by a language model to a Kilotest tool. The model requested data, drawn from a Kilotest report, about one of the issues for the front-end quality (i.e. accessibility, usability, and standards conformity) of a web page. Kilotest, with the help of Testaro, Testilo, and an ensemble of ten rule engines, performs tests on web pages, using a combination of rule- and machine-learning-based methods, and produces reports. Kilotest exposes several API endpoints to recommend web pages for testing and to obtain information from Kilotest reports. To learn more about Kilotest and the advantages of testing with an ensemble of rule engines, visit the deployed instance of Kilotest (${process.env.DEPLOYED_KILOTEST_HOST}), which contains an introduction on its home page and a tutorial.`,
110
110
  'tool collection name': 'Kilotest',
111
111
  'tool name': 'describeOneIssueFromOneReport',
112
112
  request: {
113
113
  'type of request': {
114
114
  identifier: 'reportIssue',
115
- description: 'Describe one issue from one repeort.'
115
+ description: 'Describe one issue from one report.'
116
116
  },
117
117
  method: 'GET',
118
118
  URLs: {
@@ -123,8 +123,8 @@ exports.response = async args => {
123
123
  identifier: 'describeQualityOfOneWebPage',
124
124
  description: 'Describe the quality of one web page.',
125
125
  URLs: {
126
- 'for you': `${thisHost}/api/reportIssues`,
127
- 'for humans': `${thisHost}/reportIssues.html`
126
+ 'for you': `${thisHost}/api/reportIssues/${timeStamp}/${jobID}`,
127
+ 'for humans': `${thisHost}/reportIssues.html/${timeStamp}/${jobID}`
128
128
  }
129
129
  }
130
130
  },
@@ -63,7 +63,7 @@ exports.response = async args => {
63
63
  const thisHost = process.env.THIS_KILOTEST_HOST;
64
64
  // Get a response.
65
65
  const content = {
66
- summary: `This document fulfills a request made by a language model to a Kilotest tool. The model requested data from a Kilotest report about the front-end quality (i.e. accessibility, usability, and standard-conformity) of a web page. Kilotest, with the help of Testaro, Testilo, and an ensemble of ten rule engines, performs tests on web pages, using a combination of rule- and machine-learning-based methods, and produces reports. Kilotest exposes several API endpoints to recommend web pages for testing and to obtain information from Kilotest reports. To learn more about Kilotest and the advangages of testing with an ensemble of rule engines, visit the deployed instance of Kilotest (${process.env.DEPLOYED_KILOTEST_HOST}), which contains an introduction on its home page and a tutorial.`,
66
+ summary: `This document fulfills a request made by a language model to a Kilotest tool. The model requested data from a Kilotest report about the front-end quality (i.e. accessibility, usability, and standards conformity) of a web page. Kilotest, with the help of Testaro, Testilo, and an ensemble of ten rule engines, performs tests on web pages, using a combination of rule- and machine-learning-based methods, and produces reports. Kilotest exposes several API endpoints to recommend web pages for testing and to obtain information from Kilotest reports. To learn more about Kilotest and the advantages of testing with an ensemble of rule engines, visit the deployed instance of Kilotest (${process.env.DEPLOYED_KILOTEST_HOST}), which contains an introduction on its home page and a tutorial.`,
67
67
  'tool collection name': 'Kilotest',
68
68
  'tool name': 'describeQualityOfOneWebPage',
69
69
  request: {
@@ -77,10 +77,10 @@ exports.response = async args => {
77
77
  'equivalent URL for humans': `${thisHost}/reportIssues.html/${timeStamp}/${jobID}`
78
78
  },
79
79
  'closest ancestor request': {
80
- identifier: 'summarizeQualityOfAllTestedWebPages',
81
- description: 'Summarize the quality of all tested web pages.',
80
+ identifier: 'getListOfAllAvailableReports',
81
+ description: 'Get a list of all available reports.',
82
82
  URLs: {
83
- 'for you': `${thisHost}/api/targets`,
83
+ 'for you': `${thisHost}/api/reportList`,
84
84
  'for humans': `${thisHost}/targets.html`
85
85
  }
86
86
  }
@@ -0,0 +1,75 @@
1
+ /*
2
+ api.js
3
+ Responds to the reportList API request.
4
+ */
5
+
6
+ // IMPORTS
7
+
8
+ const {
9
+ getAgoDays,
10
+ getDateTime,
11
+ getLogs,
12
+ getNowStamp,
13
+ getRandomString,
14
+ getReportSize
15
+ } = require('../util');
16
+
17
+ // CONSTANTS
18
+
19
+ const thisHost = process.env.THIS_KILOTEST_HOST;
20
+
21
+ // FUNCTIONS
22
+
23
+ // Returns a response to an API request for reports.
24
+ exports.response = async () => {
25
+ const reportsFacts = [];
26
+ // Get the available logs, with added job names.
27
+ const availableLogs = await getLogs();
28
+ // For each of them:
29
+ for (const availableLog of availableLogs) {
30
+ const {jobName} = availableLog;
31
+ const [timeStamp, jobID] = jobName.split('-');
32
+ const reportSize = await getReportSize(timeStamp, jobID);
33
+ const {superseded, url, what} = availableLog;
34
+ reportsFacts.push({
35
+ identifier: jobName,
36
+ 'creation date and time': getDateTime(timeStamp),
37
+ 'days since the creation date': getAgoDays(timeStamp),
38
+ 'tested web page': {
39
+ description: what,
40
+ URL: url
41
+ },
42
+ 'whether a later report about the same page exists': !! superseded,
43
+ 'URLs for incrementally getting facts from the report': {
44
+ 'for you': `${thisHost}/api/reportIssues/${timeStamp}/${jobID}`,
45
+ 'for humans': `${thisHost}/reportIssues.html/${timeStamp}/${jobID}`
46
+ },
47
+ 'size of the report in bytes': reportSize,
48
+ 'URL to get the entire report as machine-oriented JSON': `${thisHost}/fullReport.json/${timeStamp}/${jobID}`
49
+ });
50
+ }
51
+ // Get a response.
52
+ const content = {
53
+ summary: `This document fulfills a request made by a language model to a Kilotest tool. The model asked which reports about the front-end quality (i.e. accessibility, usability, and standards conformity) of web pages are available from Kilotest. Each report describes the results of a job that tested one web page. Kilotest, with the help of Testaro, Testilo, and an ensemble of ten rule engines, performs more than a thousand tests on a public web page, using a combination of rule- and machine-learning-based methods. Kilotest exposes API endpoints and web UI URLs to recommend web pages for testing and to obtain information from Kilotest reports. You and your users can learn more about Kilotest and the advantages of testing with an ensemble of rule engines at the deployed instance of Kilotest (${process.env.DEPLOYED_KILOTEST_HOST}).`,
54
+ 'tool collection name': 'Kilotest',
55
+ 'tool name': 'getListOfAllAvailableReports',
56
+ request: {
57
+ 'type of request': {
58
+ identifier: 'reportList',
59
+ description: 'Get a list of all available reports. Each report describes the results of a job that tested a web page for front-end quality (i.e. accessibility, usability, and standards conformity). For each report, the list identifies which page was tested and when and provides URLs to begin incremental retrieval of the test results.'
60
+ },
61
+ method: 'GET',
62
+ URLs: {
63
+ 'URL of your request': `${thisHost}/api/reportList`,
64
+ 'equivalent URL for humans': `${thisHost}/targets.html`
65
+ },
66
+ 'closest ancestor request': null
67
+ },
68
+ 'response metadata': {
69
+ identifier: `${getNowStamp()}-${getRandomString(3)}`,
70
+ 'date and time': new Date().toISOString(),
71
+ },
72
+ 'available reports': reportsFacts
73
+ };
74
+ return content;
75
+ };
package/researchAgent.js CHANGED
@@ -115,9 +115,9 @@ const requestService = async () => {
115
115
  if (content.error) {
116
116
  return;
117
117
  }
118
- console.log('======================\nRequest 2: Summarize all available reports');
118
+ console.log('======================\nRequest 2: List all available reports');
119
119
  method = 'GET';
120
- path = '/api/targets';
120
+ path = '/api/reportList';
121
121
  content = await submitRequest(results, path, method);
122
122
  reports = content?.['available reports'] ?? [];
123
123
  if (content.error || ! Array.isArray(reports) || ! reports.length) {
package/target/api.js CHANGED
@@ -78,7 +78,7 @@ exports.response = async args => {
78
78
  'number of HTML elements reported as exhibiting issues': violatorCount,
79
79
  'URLs for getting data about the reported issues': {
80
80
  'for you': `${thisHost}/api/reportIssues/${timeStamp}/${jobID}`,
81
- 'for humans': `${thisHost}/reportIssues/${timeStamp}/${jobID}`
81
+ 'for humans': `${thisHost}/reportIssues.html/${timeStamp}/${jobID}`
82
82
  },
83
83
  'URL for getting the full technical report as JSON': `${thisHost}/fullReport.json/${timeStamp}/${jobID}`
84
84
  });
@@ -86,13 +86,13 @@ exports.response = async args => {
86
86
  }
87
87
  // Get a response.
88
88
  const content = {
89
- summary: `This document fulfills a request made by a language model to the Kilotest API. The model asked whether Kilotest had tested a specified web page for front-end quality (i.e. accessibility, usability, and standards conformity) and had made a report of the test results available. The response provides summary information about all and only the available reports of pages that match at least one of the provided fragments, where matching means either including or being included by the provided fragment, case-insensitively. Kilotest, with the help of Testaro, Testilo, and an ensemble of ten rule engines, performs tests on web pages, using a combination of rule- and machine-learning-based methods, and produces reports. Kilotest exposes API endpoints to recommend web pages for testing and to obtain information from Kilotest reports. To learn more about Kilotest and the advangages of testing with an ensemble of rule engines, visit the deployed instance of Kilotest (${process.env.DEPLOYED_KILOTEST_HOST}), whose home page contains an introduction and a link to a tutorial.`,
89
+ summary: `This document fulfills a request made by a language model to the Kilotest API. The model asked whether Kilotest had tested a specified web page for front-end quality (i.e. accessibility, usability, and standards conformity) and had made a report of the test results available. The response provides summary information about all and only the available reports of pages that match at least one of the provided fragments, where matching means either including or being included by the provided fragment, case-insensitively. Kilotest, with the help of Testaro, Testilo, and an ensemble of ten rule engines, performs tests on web pages, using a combination of rule- and machine-learning-based methods, and produces reports. Kilotest exposes API endpoints to recommend web pages for testing and to obtain information from Kilotest reports. To learn more about Kilotest and the advantages of testing with an ensemble of rule engines, visit the deployed instance of Kilotest (${process.env.DEPLOYED_KILOTEST_HOST}), whose home page contains an introduction and a link to a tutorial.`,
90
90
  'tool collection name': 'Kilotest',
91
- 'tool name': 'identifyReportsAboutMatchingWebPages',
91
+ 'tool name': 'summarizeQualityOfMatchingWebPages',
92
92
  request: {
93
93
  'type of request': {
94
- identifier: 'targets',
95
- description: 'Identify reports about matching web pages.'
94
+ identifier: 'target',
95
+ description: 'Summarize the quality of matching web pages.'
96
96
  },
97
97
  method: 'POST',
98
98
  payload: {
@@ -109,7 +109,7 @@ exports.response = async args => {
109
109
  identifier: `${getNowStamp()}-${getRandomString(3)}`,
110
110
  'date and time': new Date().toISOString(),
111
111
  },
112
- 'reports, if any, that may match your page specifications': matchingReports
112
+ 'matching reports': matchingReports
113
113
  };
114
114
  return content;
115
115
  };
@@ -26,7 +26,7 @@ exports.response = async (what, url, why) => {
26
26
  );
27
27
  // Get a response.
28
28
  const content = {
29
- summary: `This response acknowledges a request made by a language model to a Kilotest tool. The model recommended that Kilotest test, for the first time, the ${what} web page at ${url} for front-end quality (i.e. accessibility, usability, and standards conformity). A Kilotest manager usually approves a recommendation within a day. When the recommendation is approved, the testing will be performed and results will become available. You can check for the availability of the results at ${thisHost}/api/targets. Kilotest performs its testing with the help of Testaro, Testilo, and an ensemble of ten rule engines, using a combination of rule- and machine-learning-based methods. Kilotest exposes several API endpoints and several web UI URLs to obtain information from Kilotest reports. To learn more about Kilotest and the advangages of testing with an ensemble of rule engines, visit the deployed instance of Kilotest (${process.env.DEPLOYED_KILOTEST_HOST}), which contains an introduction on its home page and a tutorial.`,
29
+ summary: `This response acknowledges a request made by a language model to a Kilotest tool. The model recommended that Kilotest test, for the first time, the ${what} web page at ${url} for front-end quality (i.e. accessibility, usability, and standards conformity). A Kilotest manager usually approves a recommendation within a day. When the recommendation is approved, the testing will be performed and results will become available. You can check for the availability of the results at ${thisHost}/api/reportList. Kilotest performs its testing with the help of Testaro, Testilo, and an ensemble of ten rule engines, using a combination of rule- and machine-learning-based methods. Kilotest exposes several API endpoints and several web UI URLs to obtain information from Kilotest reports. To learn more about Kilotest and the advantages of testing with an ensemble of rule engines, visit the deployed instance of Kilotest (${process.env.DEPLOYED_KILOTEST_HOST}), which contains an introduction on its home page and a tutorial.`,
30
30
  'tool collection name': 'Kilotest',
31
31
  'tool name': 'recommendQualityTestingOfOneWebPage',
32
32
  request: {
package/tutorial/index.js CHANGED
@@ -5,7 +5,8 @@
5
5
 
6
6
  // IMPORTS
7
7
 
8
- const {getJSON} = require('../util');
8
+ const {sendAlert} = require('../alerts');
9
+ const {getJSON, getNowStamp} = require('../util');
9
10
  const fs = require('fs/promises');
10
11
  const path = require('path');
11
12
 
@@ -31,7 +32,7 @@ exports.answer = async () => {
31
32
  };
32
33
  };
33
34
  // Sanitizes and saves a tutorial comment to comments.json.
34
- exports.saveComment = async content => {
35
+ exports.handleComment = async content => {
35
36
  if (!content || typeof content !== 'string') {
36
37
  return {status: 'error', message: 'No content provided'};
37
38
  }
@@ -41,13 +42,22 @@ exports.saveComment = async content => {
41
42
  }
42
43
  let comments = [];
43
44
  try {
45
+ // Get the existing comments.
44
46
  const existing = await fs.readFile(commentsPath, 'utf8');
45
47
  comments = JSON.parse(existing);
46
48
  }
47
- catch (_) {
48
- // File absent or unparsable; start a fresh array.
49
+ // If there are none:
50
+ catch {
51
+ // Initialize a comments array.
49
52
  }
50
- comments.push({timeStamp: new Date().toISOString(), content: sanitized});
53
+ // Add the comment to the existing ones.
54
+ comments.push({
55
+ timeStamp: getNowStamp(),
56
+ content: sanitized
57
+ });
58
+ // Save the revised comments.
51
59
  await fs.writeFile(commentsPath, getJSON(comments));
60
+ // Send an alert to the manager.
61
+ await sendAlert('New tutorial comment received', 'A new tutorial comment has been received.');
52
62
  return {status: 'ok'};
53
63
  };
package/util.js CHANGED
@@ -489,7 +489,7 @@ exports.getPOSTData = request => new Promise(resolve => {
489
489
  });
490
490
  // Returns the waiting test and retest recommendations.
491
491
  const getRecs = exports.getRecs = async () => {
492
- let recs = {};
492
+ let recs;
493
493
  let recsJSON;
494
494
  try {
495
495
  recsJSON = await fs.readFile(recsPath, 'utf8');
@@ -764,3 +764,9 @@ exports.isReportAvailable = async (what, url) => {
764
764
  const miniURLs = logs.map(log => minifyURL(log.url));
765
765
  return whats.includes(what) || miniURLs.includes(minifyURL(url));
766
766
  };
767
+ // Returns the size of a report.
768
+ exports.getReportSize = async (timeStamp, jobID) => {
769
+ const reportStat = await fs.stat(path.join(reportsPath, `${timeStamp}-${jobID}.json`));
770
+ const reportSize = reportStat.size;
771
+ return reportSize;
772
+ };
package/targets/api.js DELETED
@@ -1,99 +0,0 @@
1
- /*
2
- api.js
3
- Responds to the targets request.
4
- */
5
-
6
- // IMPORTS
7
-
8
- const {
9
- getLogs,
10
- getNowStamp,
11
- getRandomString,
12
- getReportData
13
- } = require('../util');
14
-
15
- // CONSTANTS
16
-
17
- const thisHost = process.env.THIS_KILOTEST_HOST;
18
-
19
- // FUNCTIONS
20
-
21
- // Returns a response to a targets request.
22
- exports.response = async () => {
23
- const availableReports = [];
24
- // Get the non-hidden logs.
25
- const targetLogs = await getLogs();
26
- // For each log:
27
- for (const targetLog of targetLogs) {
28
- const {jobName} = targetLog;
29
- const [timeStamp, jobID] = jobName.split('-');
30
- const {superseded, url, what} = targetLog;
31
- // Get data about its report.
32
- const data = await getReportData(timeStamp, jobID);
33
- const {
34
- creationDate,
35
- daysAgo,
36
- issueCount,
37
- toolNames,
38
- toolCount,
39
- reporterNames,
40
- reporterCount,
41
- violatorCount,
42
- preventedToolNames,
43
- preventedToolCount
44
- } = data;
45
- availableReports.push({
46
- identifier: jobName,
47
- 'creation date': creationDate,
48
- 'days since the creation date': daysAgo,
49
- 'tested web page': {
50
- description: what,
51
- URL: url
52
- },
53
- 'whether a later report about the same page exists': !! superseded,
54
- 'rule engines that tried to test the page': {
55
- number: toolCount,
56
- names: toolNames
57
- },
58
- 'rule engines that were unable to test the page': {
59
- number: preventedToolCount,
60
- names: preventedToolNames
61
- },
62
- 'rule engines that reported issues': {
63
- number: reporterCount,
64
- names: reporterNames
65
- },
66
- 'number of issues reported': issueCount,
67
- 'number of HTML elements reported as exhibiting issues': violatorCount,
68
- 'URLs for getting data about the reported issues': {
69
- 'for you': `${thisHost}/api/reportIssues/${timeStamp}/${jobID}`,
70
- 'for humans': `${thisHost}/reportIssues/${timeStamp}/${jobID}`
71
- },
72
- 'URL for getting the full technical report as JSON': `${thisHost}/fullReport.json/${timeStamp}/${jobID}`
73
- });
74
- }
75
- // Get a response.
76
- const content = {
77
- summary: `This document fulfills a request made by a language model to a Kilotest tool. The model requested data about the web pages that Kilotest had tested for front-end quality (i.e. accessibility, usability, and standards conformity) and, for each page, statistics about the results of the tests. Kilotest, with the help of Testaro, Testilo, and an ensemble of ten rule engines, performs tests on web pages, using a combination of rule- and machine-learning-based methods, and produces reports. Kilotest exposes API endpoints and web UI URLs to recommend web pages for testing and to obtain information from Kilotest reports. To learn more about Kilotest and the advangages of testing with an ensemble of rule engines, visit the deployed instance of Kilotest (${process.env.DEPLOYED_KILOTEST_HOST}), whose home page contains an introduction and a link to a tutorial.`,
78
- 'tool collection name': 'Kilotest',
79
- 'tool name': 'summarizeQualityOfAllTestedWebPages',
80
- request: {
81
- 'type of request': {
82
- identifier: 'targets',
83
- description: 'Summarize the quality of all tested web pages.'
84
- },
85
- method: 'GET',
86
- URLs: {
87
- 'URL of your request': `${thisHost}/api/targets`,
88
- 'equivalent URL for humans': `${thisHost}/targets.html`
89
- },
90
- 'closest ancestor request': null
91
- },
92
- 'response metadata': {
93
- identifier: `${getNowStamp()}-${getRandomString(3)}`,
94
- 'date and time': new Date().toISOString(),
95
- },
96
- 'available reports': availableReports
97
- };
98
- return content;
99
- };
File without changes
File without changes