get_package_details
Retrieve detailed information about Typst packages, including descriptions, authors, categories, repository links, import code, and version history.
Instructions
Get detailed information about a specific Typst package, including its description, authors, categories, repository link, import code, and version history.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| packageName | Yes | The exact name of the package (e.g., "cetz", "polylux", "fletcher") |
Implementation Reference
- src/scraper.ts:113-199 (handler)The core handler function that scrapes the Typst Universe package page to extract detailed information including version, description, authors, categories, repository, homepage, import code, and version history.export async function getPackageDetails(packageName: string): Promise<PackageDetails | null> { const packageUrl = `${UNIVERSE_URL}/package/${packageName}`; try { const html = await fetchPage(packageUrl); const $ = cheerio.load(html); // Extract package name and version from the header const headerText = $('h1').first().text().trim(); // Get the description from meta tag or first paragraph const metaDescription = $('meta[name="description"]').attr('content') || $('meta[property="og:description"]').attr('content') || ''; // Extract the full description from the main content const mainContent = $('main').text().trim(); // Find version in the page const versionMatch = mainContent.match(/(\d+\.\d+\.\d+)/); const version = versionMatch ? versionMatch[1] : 'unknown'; // Extract authors const authors: string[] = []; $('a[href*="author"]').each((_, el) => { const authorName = $(el).text().trim(); if (authorName && !authors.includes(authorName)) { authors.push(authorName); } }); // Extract categories const categories: string[] = []; $('a[href*="category="]').each((_, el) => { const category = $(el).text().trim(); if (category && !categories.includes(category)) { categories.push(category); } }); // Extract repository link let repository: string | undefined; const githubLink = $('a[href*="github.com"]').first().attr('href'); if (githubLink && !githubLink.includes('typst/packages')) { repository = githubLink; } // Extract homepage let homepage: string | undefined; $('a').each((_, el) => { const href = $(el).attr('href'); const text = $(el).text().toLowerCase(); if (href && (text.includes('.io') || text.includes('.com') || text.includes('homepage')) && !href.includes('github.com') && !href.includes('typst.app')) { homepage = href; } }); // Build import code const importCode = `#import "@preview/${packageName}:${version}"`; // Extract version history const versionHistory: string[] = []; $(`a[href^="/universe/package/${packageName}/"]`).each((_, el) => { const versionText = $(el).text().trim(); if (versionText.match(/^\d+\.\d+\.\d+$/)) { versionHistory.push(versionText); } }); return { name: packageName, version, description: metaDescription, fullDescription: mainContent.substring(0, 2000), // Limit full description length authors, categories, repository, homepage, importCode, versionHistory, url: packageUrl, }; } catch (error) { console.error(`Failed to fetch package details for ${packageName}:`, error); return null; } }
- src/index.ts:51-63 (registration)Registration of the 'get_package_details' tool in the TOOLS array, including name, description, and input schema.name: 'get_package_details', description: 'Get detailed information about a specific Typst package, including its description, authors, categories, repository link, import code, and version history.', inputSchema: { type: 'object', properties: { packageName: { type: 'string', description: 'The exact name of the package (e.g., "cetz", "polylux", "fletcher")', }, }, required: ['packageName'], }, },
- src/index.ts:90-92 (schema)Zod schema used for validating the input arguments to the getPackageDetails function.const GetPackageDetailsSchema = z.object({ packageName: z.string().min(1, 'Package name is required'), });
- src/index.ts:204-228 (handler)Tool dispatch handler in the switch statement that validates arguments and calls the getPackageDetails function.case 'get_package_details': { const validatedArgs = GetPackageDetailsSchema.parse(args); const details = await getPackageDetails(validatedArgs.packageName); if (!details) { return { content: [ { type: 'text', text: `Package "${validatedArgs.packageName}" not found. Please check the package name and try again.`, }, ], isError: true, }; } return { content: [ { type: 'text', text: formatPackageDetails(details), }, ], }; }
- src/scraper.ts:13-25 (schema)TypeScript interface defining the structure of the PackageDetails return type.export interface PackageDetails { name: string; version: string; description: string; fullDescription: string; authors: string[]; categories: string[]; repository?: string; homepage?: string; importCode: string; versionHistory: string[]; url: string; }