fix: require name field in TPMJS spec, add workflow permissions
Breaking change for TPMJS spec: - Remove `exportName` field support from TpmjsToolDefinitionSchema - Make `name` field required (replaces deprecated `exportName`) - Update create-basic-tools to generate `name` field - Update sync routes to use `name` from validated schema - Add `permissions: contents: write` to Vercel registry sync workflow Packages using the old `exportName` field must update to use `name`.
This commit is contained in:
parent
b7ea9bf4d6
commit
5e795bc086
5 changed files with 22 additions and 38 deletions
3
.github/workflows/sync-vercel-registry.yml
vendored
3
.github/workflows/sync-vercel-registry.yml
vendored
|
|
@ -12,6 +12,9 @@ on:
|
|||
paths:
|
||||
- 'sync-vercel-registry.ts'
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
sync-vercel:
|
||||
runs-on: ubuntu-latest
|
||||
|
|
|
|||
|
|
@ -167,8 +167,8 @@ export async function POST(request: NextRequest) {
|
|||
|
||||
// Upsert each tool
|
||||
for (const toolDef of toolsToProcess) {
|
||||
// Use 'name' field (new) or fall back to 'exportName' (legacy support)
|
||||
const toolName = toolDef.name || (toolDef as { exportName?: string }).exportName;
|
||||
// Get tool name from validated schema
|
||||
const toolName = toolDef.name;
|
||||
if (!toolName) {
|
||||
console.warn(`Skipping tool without name in ${pkg.name}`);
|
||||
continue;
|
||||
|
|
@ -255,10 +255,7 @@ export async function POST(request: NextRequest) {
|
|||
// Delete orphaned tools (tools removed from package.json)
|
||||
const orphanedTools = existingTools.filter(
|
||||
(existingTool) =>
|
||||
!toolsToProcess.some((toolDef) => {
|
||||
const toolName = toolDef.name || (toolDef as { exportName?: string }).exportName;
|
||||
return toolName === existingTool.exportName;
|
||||
})
|
||||
!toolsToProcess.some((toolDef) => toolDef.name === existingTool.exportName)
|
||||
);
|
||||
|
||||
if (orphanedTools.length > 0) {
|
||||
|
|
|
|||
|
|
@ -186,8 +186,8 @@ export async function POST(request: NextRequest) {
|
|||
|
||||
// Upsert each tool
|
||||
for (const toolDef of toolsToProcess) {
|
||||
// Use 'name' field (new) or fall back to 'exportName' (legacy support)
|
||||
const toolName = toolDef.name || (toolDef as { exportName?: string }).exportName;
|
||||
// Get tool name from validated schema
|
||||
const toolName = toolDef.name;
|
||||
if (!toolName) {
|
||||
console.warn(`Skipping tool without name in ${pkg.name}`);
|
||||
continue;
|
||||
|
|
@ -274,10 +274,7 @@ export async function POST(request: NextRequest) {
|
|||
// Delete orphaned tools (tools removed from package.json)
|
||||
const orphanedTools = existingTools.filter(
|
||||
(existingTool) =>
|
||||
!toolsToProcess.some((toolDef) => {
|
||||
const toolName = toolDef.name || (toolDef as { exportName?: string }).exportName;
|
||||
return toolName === existingTool.exportName;
|
||||
})
|
||||
!toolsToProcess.some((toolDef) => toolDef.name === existingTool.exportName)
|
||||
);
|
||||
|
||||
if (orphanedTools.length > 0) {
|
||||
|
|
|
|||
|
|
@ -24,11 +24,8 @@ export function generatePackageJson(config: GeneratorConfig): string {
|
|||
tpmjs: {
|
||||
category: packageInfo.category,
|
||||
tools: tools.map((tool) => ({
|
||||
exportName: tool.exportName,
|
||||
name: tool.exportName,
|
||||
description: tool.description,
|
||||
...(tool.parameters && { parameters: tool.parameters }),
|
||||
...(tool.returns && { returns: tool.returns }),
|
||||
...(tool.aiAgent && { aiAgent: tool.aiAgent }),
|
||||
})),
|
||||
...(tools.some((t) => t.env) && {
|
||||
env: tools.flatMap((t) => t.env || []),
|
||||
|
|
|
|||
|
|
@ -90,28 +90,18 @@ export type TpmjsAiAgent = z.infer<typeof TpmjsAiAgentSchema>;
|
|||
* - returns: Tool return type - auto-extracted from tool
|
||||
* - aiAgent: AI agent guidance - auto-extracted from tool
|
||||
*/
|
||||
export const TpmjsToolDefinitionSchema = z
|
||||
.object({
|
||||
// New field name (preferred)
|
||||
name: z.string().min(1).optional(),
|
||||
// @deprecated - use 'name' instead. Kept for backward compatibility.
|
||||
exportName: z.string().min(1).optional(),
|
||||
// Optional - auto-extracted from tool if not provided
|
||||
description: z
|
||||
.string()
|
||||
.min(20, 'Description must be at least 20 characters')
|
||||
.max(500)
|
||||
.optional(),
|
||||
// @deprecated - now auto-extracted from tool's inputSchema
|
||||
parameters: z.array(TpmjsParameterSchema).optional(),
|
||||
// @deprecated - now auto-extracted from tool
|
||||
returns: TpmjsReturnsSchema.optional(),
|
||||
// @deprecated - now auto-extracted from tool
|
||||
aiAgent: TpmjsAiAgentSchema.optional(),
|
||||
})
|
||||
.refine((data) => data.name || data.exportName, {
|
||||
message: 'Either name or exportName is required',
|
||||
});
|
||||
export const TpmjsToolDefinitionSchema = z.object({
|
||||
// Required: The export name of the tool from the package
|
||||
name: z.string().min(1),
|
||||
// Optional - auto-extracted from tool if not provided
|
||||
description: z.string().min(20, 'Description must be at least 20 characters').max(500).optional(),
|
||||
// @deprecated - now auto-extracted from tool's inputSchema
|
||||
parameters: z.array(TpmjsParameterSchema).optional(),
|
||||
// @deprecated - now auto-extracted from tool
|
||||
returns: TpmjsReturnsSchema.optional(),
|
||||
// @deprecated - now auto-extracted from tool
|
||||
aiAgent: TpmjsAiAgentSchema.optional(),
|
||||
});
|
||||
|
||||
export type TpmjsToolDefinition = z.infer<typeof TpmjsToolDefinitionSchema>;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue