2025-04-21 20:22:57 +02:00
|
|
|
#!/usr/bin/env node
|
|
|
|
/**
|
|
|
|
* Copyright (c) Microsoft Corporation.
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
// @ts-check
|
|
|
|
|
2025-04-30 23:06:56 +02:00
|
|
|
import fs from 'node:fs'
|
|
|
|
import path from 'node:path'
|
|
|
|
import url from 'node:url'
|
|
|
|
import zodToJsonSchema from 'zod-to-json-schema'
|
|
|
|
|
|
|
|
import commonTools from '../lib/tools/common.js';
|
|
|
|
import consoleTools from '../lib/tools/console.js';
|
|
|
|
import dialogsTools from '../lib/tools/dialogs.js';
|
|
|
|
import filesTools from '../lib/tools/files.js';
|
|
|
|
import installTools from '../lib/tools/install.js';
|
|
|
|
import keyboardTools from '../lib/tools/keyboard.js';
|
|
|
|
import navigateTools from '../lib/tools/navigate.js';
|
2025-05-05 17:38:22 -07:00
|
|
|
import networkTools from '../lib/tools/network.js';
|
2025-04-30 23:06:56 +02:00
|
|
|
import pdfTools from '../lib/tools/pdf.js';
|
|
|
|
import snapshotTools from '../lib/tools/snapshot.js';
|
|
|
|
import tabsTools from '../lib/tools/tabs.js';
|
2025-05-12 16:42:47 -07:00
|
|
|
import screenshotTools from '../lib/tools/screenshot.js';
|
2025-05-02 17:41:58 -07:00
|
|
|
import testTools from '../lib/tools/testing.js';
|
2025-05-12 16:42:47 -07:00
|
|
|
import visionTools from '../lib/tools/vision.js';
|
|
|
|
import waitTools from '../lib/tools/wait.js';
|
2025-04-21 20:22:57 +02:00
|
|
|
|
|
|
|
// Category definitions for tools
|
|
|
|
const categories = {
|
2025-05-12 16:42:47 -07:00
|
|
|
'Interactions': [
|
2025-04-21 20:22:57 +02:00
|
|
|
...snapshotTools,
|
2025-05-12 16:42:47 -07:00
|
|
|
...keyboardTools(true),
|
|
|
|
...waitTools(true),
|
|
|
|
...filesTools(true),
|
|
|
|
...dialogsTools(true),
|
2025-04-21 20:22:57 +02:00
|
|
|
],
|
|
|
|
'Navigation': [
|
|
|
|
...navigateTools(true),
|
|
|
|
],
|
2025-05-12 16:42:47 -07:00
|
|
|
'Resources': [
|
|
|
|
...screenshotTools,
|
|
|
|
...pdfTools,
|
|
|
|
...networkTools,
|
|
|
|
...consoleTools,
|
2025-04-21 20:22:57 +02:00
|
|
|
],
|
|
|
|
'Utilities': [
|
|
|
|
...installTools,
|
2025-05-12 16:42:47 -07:00
|
|
|
...commonTools(true),
|
|
|
|
],
|
|
|
|
'Tabs': [
|
|
|
|
...tabsTools(true),
|
2025-04-21 20:22:57 +02:00
|
|
|
],
|
2025-05-02 17:41:58 -07:00
|
|
|
'Testing': [
|
|
|
|
...testTools,
|
|
|
|
],
|
2025-05-12 16:42:47 -07:00
|
|
|
'Vision mode': [
|
|
|
|
...visionTools,
|
|
|
|
...keyboardTools(),
|
|
|
|
...waitTools(false),
|
|
|
|
...filesTools(false),
|
|
|
|
...dialogsTools(false),
|
|
|
|
],
|
2025-04-21 20:22:57 +02:00
|
|
|
};
|
|
|
|
|
2025-04-30 23:06:56 +02:00
|
|
|
// NOTE: Can be removed when we drop Node.js 18 support and changed to import.meta.filename.
|
|
|
|
const __filename = url.fileURLToPath(import.meta.url);
|
|
|
|
|
2025-04-21 20:22:57 +02:00
|
|
|
const kStartMarker = `<!--- Generated by ${path.basename(__filename)} -->`;
|
|
|
|
const kEndMarker = `<!--- End of generated section -->`;
|
|
|
|
|
|
|
|
/**
|
2025-05-05 17:38:22 -07:00
|
|
|
* @param {import('../src/tools/tool.js').ToolSchema<any>} tool
|
2025-04-21 20:22:57 +02:00
|
|
|
* @returns {string}
|
|
|
|
*/
|
|
|
|
function formatToolForReadme(tool) {
|
|
|
|
const lines = /** @type {string[]} */ ([]);
|
|
|
|
lines.push(`<!-- NOTE: This has been generated via ${path.basename(__filename)} -->\n\n`);
|
|
|
|
lines.push(`- **${tool.name}**\n`);
|
2025-05-05 17:38:22 -07:00
|
|
|
lines.push(` - Title: ${tool.title}\n`);
|
2025-04-21 20:22:57 +02:00
|
|
|
lines.push(` - Description: ${tool.description}\n`);
|
|
|
|
|
2025-05-05 17:38:22 -07:00
|
|
|
const inputSchema = /** @type {any} */ (zodToJsonSchema(tool.inputSchema || {}));
|
|
|
|
const requiredParams = inputSchema.required || [];
|
|
|
|
if (inputSchema.properties && Object.keys(inputSchema.properties).length) {
|
2025-04-21 20:22:57 +02:00
|
|
|
lines.push(` - Parameters:\n`);
|
2025-05-05 17:38:22 -07:00
|
|
|
Object.entries(inputSchema.properties).forEach(([name, param]) => {
|
|
|
|
const optional = !requiredParams.includes(name);
|
2025-04-21 20:22:57 +02:00
|
|
|
const meta = /** @type {string[]} */ ([]);
|
|
|
|
if (param.type)
|
|
|
|
meta.push(param.type);
|
2025-05-05 17:38:22 -07:00
|
|
|
if (optional)
|
2025-04-21 20:22:57 +02:00
|
|
|
meta.push('optional');
|
2025-05-05 17:38:22 -07:00
|
|
|
lines.push(` - \`${name}\` ${meta.length ? `(${meta.join(', ')})` : ''}: ${param.description}\n`);
|
2025-04-21 20:22:57 +02:00
|
|
|
});
|
|
|
|
} else {
|
|
|
|
lines.push(` - Parameters: None\n`);
|
|
|
|
}
|
2025-05-05 17:38:22 -07:00
|
|
|
lines.push(` - Read-only: **${tool.type === 'readOnly'}**\n`);
|
2025-04-21 20:22:57 +02:00
|
|
|
lines.push('\n');
|
|
|
|
return lines.join('');
|
|
|
|
}
|
|
|
|
|
|
|
|
async function updateReadme() {
|
|
|
|
console.log('Loading tool information from compiled modules...');
|
|
|
|
|
|
|
|
// Count the tools processed
|
|
|
|
const totalTools = Object.values(categories).flat().length;
|
|
|
|
console.log(`Found ${totalTools} tools`);
|
|
|
|
|
|
|
|
const generatedLines = /** @type {string[]} */ ([]);
|
|
|
|
|
|
|
|
for (const [category, categoryTools] of Object.entries(categories)) {
|
2025-05-12 16:42:47 -07:00
|
|
|
generatedLines.push(`<details>\n<summary><b>${category}</b></summary>\n\n`);
|
|
|
|
|
2025-05-05 17:38:22 -07:00
|
|
|
for (const tool of categoryTools)
|
|
|
|
generatedLines.push(formatToolForReadme(tool.schema));
|
2025-05-12 16:42:47 -07:00
|
|
|
|
|
|
|
generatedLines.push(`</details>\n\n`);
|
2025-04-21 20:22:57 +02:00
|
|
|
}
|
|
|
|
|
2025-04-30 23:06:56 +02:00
|
|
|
const readmePath = path.join(path.dirname(__filename), '..', 'README.md');
|
2025-04-21 20:22:57 +02:00
|
|
|
const readmeContent = await fs.promises.readFile(readmePath, 'utf-8');
|
|
|
|
const startMarker = readmeContent.indexOf(kStartMarker);
|
|
|
|
const endMarker = readmeContent.indexOf(kEndMarker);
|
|
|
|
if (startMarker === -1 || endMarker === -1)
|
|
|
|
throw new Error('Markers for generated section not found in README');
|
|
|
|
|
|
|
|
const newReadmeContent = [
|
|
|
|
readmeContent.slice(0, startMarker),
|
|
|
|
kStartMarker + '\n\n',
|
|
|
|
generatedLines.join(''),
|
|
|
|
kEndMarker,
|
|
|
|
readmeContent.slice(endMarker + kEndMarker.length),
|
|
|
|
].join('');
|
|
|
|
|
|
|
|
// Write updated README
|
|
|
|
await fs.promises.writeFile(readmePath, newReadmeContent, 'utf-8');
|
|
|
|
console.log('README updated successfully');
|
|
|
|
}
|
|
|
|
|
|
|
|
// Run the update
|
|
|
|
updateReadme().catch(err => {
|
|
|
|
console.error('Error updating README:', err);
|
|
|
|
process.exit(1);
|
|
|
|
});
|