openpets 1.0.5 → 1.0.6
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/dist/data/api.json +3172 -0
- package/dist/src/core/ai-client-base/index.d.ts +47 -0
- package/dist/src/core/ai-client-base/index.d.ts.map +1 -0
- package/dist/src/core/ai-client-base/index.js +168 -0
- package/dist/src/core/ai-client-base/index.js.map +1 -0
- package/dist/src/core/browser.d.ts +10 -0
- package/dist/src/core/browser.d.ts.map +1 -0
- package/{browser.ts → dist/src/core/browser.js} +4 -4
- package/dist/src/core/browser.js.map +1 -0
- package/dist/src/core/build-pet.d.ts +2 -0
- package/dist/src/core/build-pet.d.ts.map +1 -0
- package/dist/src/core/build-pet.js +364 -0
- package/dist/src/core/build-pet.js.map +1 -0
- package/dist/src/core/cli.d.ts +3 -0
- package/dist/src/core/cli.d.ts.map +1 -0
- package/dist/src/core/cli.js +244 -0
- package/dist/src/core/cli.js.map +1 -0
- package/dist/src/core/config-manager.d.ts +13 -0
- package/dist/src/core/config-manager.d.ts.map +1 -0
- package/dist/src/core/config-manager.js +59 -0
- package/dist/src/core/config-manager.js.map +1 -0
- package/dist/src/core/deploy-pet.d.ts +2 -0
- package/dist/src/core/deploy-pet.d.ts.map +1 -0
- package/dist/src/core/deploy-pet.js +66 -0
- package/dist/src/core/deploy-pet.js.map +1 -0
- package/dist/src/core/index.d.ts +11 -0
- package/dist/src/core/index.d.ts.map +1 -0
- package/dist/src/core/index.js +11 -0
- package/dist/src/core/index.js.map +1 -0
- package/dist/src/core/local-cache.d.ts +69 -0
- package/dist/src/core/local-cache.d.ts.map +1 -0
- package/dist/src/core/local-cache.js +212 -0
- package/dist/src/core/local-cache.js.map +1 -0
- package/dist/src/core/logger.d.ts.map +1 -0
- package/{logger.js → dist/src/core/logger.js} +8 -9
- package/dist/src/core/logger.js.map +1 -0
- package/dist/src/core/mcp-factory.d.ts +12 -0
- package/dist/src/core/mcp-factory.d.ts.map +1 -0
- package/dist/src/core/mcp-factory.js +143 -0
- package/dist/src/core/mcp-factory.js.map +1 -0
- package/dist/src/core/mcp-server.d.ts +3 -0
- package/dist/src/core/mcp-server.d.ts.map +1 -0
- package/dist/src/core/mcp-server.js +55 -0
- package/dist/src/core/mcp-server.js.map +1 -0
- package/dist/src/core/migrate-plugin.d.ts +15 -0
- package/dist/src/core/migrate-plugin.d.ts.map +1 -0
- package/dist/src/core/migrate-plugin.js +181 -0
- package/dist/src/core/migrate-plugin.js.map +1 -0
- package/dist/src/core/pets-registry.d.ts +47 -0
- package/dist/src/core/pets-registry.d.ts.map +1 -0
- package/dist/src/core/pets-registry.js +109 -0
- package/dist/src/core/pets-registry.js.map +1 -0
- package/dist/src/core/plugin-factory.d.ts +58 -0
- package/dist/src/core/plugin-factory.d.ts.map +1 -0
- package/dist/src/core/plugin-factory.js +212 -0
- package/dist/src/core/plugin-factory.js.map +1 -0
- package/dist/src/core/prompt-utils.d.ts +14 -0
- package/dist/src/core/prompt-utils.d.ts.map +1 -0
- package/dist/src/core/prompt-utils.js +106 -0
- package/dist/src/core/prompt-utils.js.map +1 -0
- package/dist/src/core/schema-helpers.d.ts +33 -0
- package/dist/src/core/schema-helpers.d.ts.map +1 -0
- package/dist/src/core/schema-helpers.js +46 -0
- package/dist/src/core/schema-helpers.js.map +1 -0
- package/dist/src/core/search-pets.d.ts +29 -0
- package/dist/src/core/search-pets.d.ts.map +1 -0
- package/dist/src/core/search-pets.js +196 -0
- package/dist/src/core/search-pets.js.map +1 -0
- package/dist/src/core/types.d.ts +63 -0
- package/dist/src/core/types.d.ts.map +1 -0
- package/dist/src/core/types.js +2 -0
- package/dist/src/core/types.js.map +1 -0
- package/dist/src/core/validate-pet.d.ts +40 -0
- package/dist/src/core/validate-pet.d.ts.map +1 -0
- package/dist/src/core/validate-pet.js +650 -0
- package/dist/src/core/validate-pet.js.map +1 -0
- package/package.json +8 -21
- package/ai-client-base/index.ts +0 -229
- package/build-pet.ts +0 -429
- package/cli.ts +0 -268
- package/config-manager.ts +0 -82
- package/deploy-pet.ts +0 -91
- package/index.ts +0 -10
- package/local-cache.ts +0 -280
- package/logger.ts +0 -143
- package/mcp-factory.ts +0 -180
- package/mcp-server.ts +0 -69
- package/migrate-plugin.ts +0 -220
- package/pets-registry.ts +0 -160
- package/plugin-factory.ts +0 -300
- package/prompt-utils.ts +0 -130
- package/schema-helpers.ts +0 -59
- package/search-pets.ts +0 -267
- package/types.ts +0 -68
- package/validate-pet.ts +0 -749
- /package/{logger.d.ts → dist/src/core/logger.d.ts} +0 -0
package/mcp-factory.ts
DELETED
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
2
|
-
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
|
-
import {
|
|
4
|
-
CallToolRequestSchema,
|
|
5
|
-
ListToolsRequestSchema,
|
|
6
|
-
Tool,
|
|
7
|
-
} from "@modelcontextprotocol/sdk/types.js";
|
|
8
|
-
import type { ToolDefinition, ToolRecord } from "./plugin-factory";
|
|
9
|
-
import { createLogger } from "./logger";
|
|
10
|
-
|
|
11
|
-
const logger = createLogger("mcp-factory");
|
|
12
|
-
|
|
13
|
-
export interface MCPServerConfig {
|
|
14
|
-
name: string;
|
|
15
|
-
version: string;
|
|
16
|
-
description?: string;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function extractToolsFromPlugin(pluginModule: any): ToolDefinition[] {
|
|
20
|
-
const tools: ToolDefinition[] = [];
|
|
21
|
-
|
|
22
|
-
if (pluginModule.tool && typeof pluginModule.tool === "object") {
|
|
23
|
-
const toolRecord = pluginModule.tool as ToolRecord;
|
|
24
|
-
|
|
25
|
-
for (const [name, toolDef] of Object.entries(toolRecord)) {
|
|
26
|
-
tools.push({
|
|
27
|
-
name: name,
|
|
28
|
-
description: toolDef.description,
|
|
29
|
-
schema: toolDef.args,
|
|
30
|
-
execute: toolDef.execute,
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
return tools;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function convertToolToMCPSchema(tool: ToolDefinition): Tool {
|
|
39
|
-
const schema = tool.schema as any;
|
|
40
|
-
const shape = schema.shape || schema._def?.shape?.();
|
|
41
|
-
|
|
42
|
-
const properties: Record<string, any> = {};
|
|
43
|
-
const required: string[] = [];
|
|
44
|
-
|
|
45
|
-
if (shape) {
|
|
46
|
-
for (const [key, value] of Object.entries(shape)) {
|
|
47
|
-
const fieldSchema = value as any;
|
|
48
|
-
const fieldType = fieldSchema._def?.typeName;
|
|
49
|
-
|
|
50
|
-
if (fieldType === "ZodString") {
|
|
51
|
-
properties[key] = {
|
|
52
|
-
type: "string",
|
|
53
|
-
description: fieldSchema._def?.description || "",
|
|
54
|
-
};
|
|
55
|
-
} else if (fieldType === "ZodNumber") {
|
|
56
|
-
properties[key] = {
|
|
57
|
-
type: "number",
|
|
58
|
-
description: fieldSchema._def?.description || "",
|
|
59
|
-
};
|
|
60
|
-
} else if (fieldType === "ZodBoolean") {
|
|
61
|
-
properties[key] = {
|
|
62
|
-
type: "boolean",
|
|
63
|
-
description: fieldSchema._def?.description || "",
|
|
64
|
-
};
|
|
65
|
-
} else if (fieldType === "ZodArray") {
|
|
66
|
-
const elementType = fieldSchema._def?.type?._def?.typeName;
|
|
67
|
-
properties[key] = {
|
|
68
|
-
type: "array",
|
|
69
|
-
items: {
|
|
70
|
-
type: elementType === "ZodString" ? "string" : elementType === "ZodNumber" ? "number" : "string",
|
|
71
|
-
},
|
|
72
|
-
description: fieldSchema._def?.description || "",
|
|
73
|
-
};
|
|
74
|
-
} else {
|
|
75
|
-
properties[key] = {
|
|
76
|
-
type: "string",
|
|
77
|
-
description: fieldSchema._def?.description || "",
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
if (!fieldSchema._def?.checks?.some((check: any) => check.kind === "optional")) {
|
|
82
|
-
if (fieldSchema._def?.typeName !== "ZodOptional") {
|
|
83
|
-
required.push(key);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
return {
|
|
90
|
-
name: tool.name.replace(/-/g, "_"),
|
|
91
|
-
description: tool.description,
|
|
92
|
-
inputSchema: {
|
|
93
|
-
type: "object",
|
|
94
|
-
properties,
|
|
95
|
-
...(required.length > 0 ? { required } : {}),
|
|
96
|
-
},
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export function createMCPServer(
|
|
101
|
-
config: MCPServerConfig,
|
|
102
|
-
tools: ToolDefinition[]
|
|
103
|
-
): Server {
|
|
104
|
-
const server = new Server(
|
|
105
|
-
{
|
|
106
|
-
name: config.name,
|
|
107
|
-
version: config.version,
|
|
108
|
-
},
|
|
109
|
-
{
|
|
110
|
-
capabilities: {
|
|
111
|
-
tools: {},
|
|
112
|
-
},
|
|
113
|
-
}
|
|
114
|
-
);
|
|
115
|
-
|
|
116
|
-
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
117
|
-
tools: tools.map((tool) => convertToolToMCPSchema(tool)),
|
|
118
|
-
}));
|
|
119
|
-
|
|
120
|
-
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
121
|
-
const { name, arguments: args } = request.params as {
|
|
122
|
-
name: string;
|
|
123
|
-
arguments: any;
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
const tool = tools.find((t) => t.name.replace(/-/g, "_") === name);
|
|
127
|
-
|
|
128
|
-
if (!tool) {
|
|
129
|
-
return {
|
|
130
|
-
content: [
|
|
131
|
-
{
|
|
132
|
-
type: "text",
|
|
133
|
-
text: `Error: Unknown tool: ${name}`,
|
|
134
|
-
},
|
|
135
|
-
],
|
|
136
|
-
isError: true,
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
try {
|
|
141
|
-
const result = await tool.execute(args);
|
|
142
|
-
return {
|
|
143
|
-
content: [
|
|
144
|
-
{
|
|
145
|
-
type: "text",
|
|
146
|
-
text: result,
|
|
147
|
-
},
|
|
148
|
-
],
|
|
149
|
-
};
|
|
150
|
-
} catch (error) {
|
|
151
|
-
return {
|
|
152
|
-
content: [
|
|
153
|
-
{
|
|
154
|
-
type: "text",
|
|
155
|
-
text: `Error executing ${name}: ${error}`,
|
|
156
|
-
},
|
|
157
|
-
],
|
|
158
|
-
isError: true,
|
|
159
|
-
};
|
|
160
|
-
}
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
return server;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
export async function startMCPServer(server: Server): Promise<void> {
|
|
167
|
-
const transport = new StdioServerTransport();
|
|
168
|
-
await server.connect(transport);
|
|
169
|
-
console.error(`MCP server running on stdio`);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
export function createMCPServerFromTools(
|
|
173
|
-
config: MCPServerConfig,
|
|
174
|
-
tools: ToolDefinition[]
|
|
175
|
-
): () => Promise<void> {
|
|
176
|
-
return async () => {
|
|
177
|
-
const server = createMCPServer(config, tools);
|
|
178
|
-
await startMCPServer(server);
|
|
179
|
-
};
|
|
180
|
-
}
|
package/mcp-server.ts
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { createMCPServer, startMCPServer, extractToolsFromPlugin } from "./mcp-factory";
|
|
4
|
-
import { createLogger } from "./logger";
|
|
5
|
-
import { resolve } from "path";
|
|
6
|
-
import { readFileSync } from "fs";
|
|
7
|
-
|
|
8
|
-
const logger = createLogger("mcp-server");
|
|
9
|
-
|
|
10
|
-
async function main() {
|
|
11
|
-
const petName = process.argv[2] || process.env.PET_NAME;
|
|
12
|
-
|
|
13
|
-
if (!petName) {
|
|
14
|
-
logger.error("Pet name is required. Usage: node mcp-server.js <pet-name>");
|
|
15
|
-
logger.error("Example: node mcp-server.js polar");
|
|
16
|
-
logger.error("Or set PET_NAME environment variable");
|
|
17
|
-
process.exit(1);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
logger.info("Starting MCP server for pet", { petName });
|
|
21
|
-
|
|
22
|
-
try {
|
|
23
|
-
const petPath = resolve(__dirname, `../../pets/${petName}`);
|
|
24
|
-
const packageJsonPath = resolve(petPath, "package.json");
|
|
25
|
-
|
|
26
|
-
let packageJson: any;
|
|
27
|
-
try {
|
|
28
|
-
packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
29
|
-
} catch (error) {
|
|
30
|
-
logger.error("Failed to read package.json", { petPath: packageJsonPath, error: String(error) });
|
|
31
|
-
process.exit(1);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const pluginModule = await import(`../../pets/${petName}/index.js`);
|
|
35
|
-
|
|
36
|
-
let plugin;
|
|
37
|
-
if (typeof pluginModule.default === "function") {
|
|
38
|
-
plugin = await pluginModule.default();
|
|
39
|
-
} else {
|
|
40
|
-
plugin = pluginModule.default;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const tools = extractToolsFromPlugin(plugin);
|
|
44
|
-
|
|
45
|
-
if (tools.length === 0) {
|
|
46
|
-
logger.error("No tools found in plugin", { petName });
|
|
47
|
-
process.exit(1);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
logger.info("Extracted tools from plugin", { petName, toolCount: tools.length });
|
|
51
|
-
|
|
52
|
-
const server = createMCPServer(
|
|
53
|
-
{
|
|
54
|
-
name: packageJson.name || `openpets/${petName}`,
|
|
55
|
-
version: packageJson.version || "1.0.0",
|
|
56
|
-
description: packageJson.description || `${petName} MCP server`,
|
|
57
|
-
},
|
|
58
|
-
tools
|
|
59
|
-
);
|
|
60
|
-
|
|
61
|
-
await startMCPServer(server);
|
|
62
|
-
} catch (error) {
|
|
63
|
-
logger.error("Fatal error starting MCP server", { petName, error: String(error) });
|
|
64
|
-
console.error(error);
|
|
65
|
-
process.exit(1);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
main();
|
package/migrate-plugin.ts
DELETED
|
@@ -1,220 +0,0 @@
|
|
|
1
|
-
import { readFileSync, writeFileSync, existsSync } from 'fs'
|
|
2
|
-
import { join } from 'path'
|
|
3
|
-
|
|
4
|
-
export interface MigrationResult {
|
|
5
|
-
success: boolean
|
|
6
|
-
changes: string[]
|
|
7
|
-
errors: string[]
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export class PluginMigrator {
|
|
11
|
-
migratePlugin(pluginPath: string): MigrationResult {
|
|
12
|
-
const indexPath = join(pluginPath, 'index.ts')
|
|
13
|
-
const changes: string[] = []
|
|
14
|
-
const errors: string[] = []
|
|
15
|
-
|
|
16
|
-
if (!existsSync(indexPath)) {
|
|
17
|
-
return {
|
|
18
|
-
success: false,
|
|
19
|
-
changes,
|
|
20
|
-
errors: ['index.ts not found']
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
try {
|
|
25
|
-
let code = readFileSync(indexPath, 'utf-8')
|
|
26
|
-
const original = code
|
|
27
|
-
|
|
28
|
-
code = this.addImports(code, changes)
|
|
29
|
-
code = this.convertInputSchemaToToolBuilder(code, changes)
|
|
30
|
-
|
|
31
|
-
if (code !== original) {
|
|
32
|
-
writeFileSync(indexPath, code, 'utf-8')
|
|
33
|
-
return { success: true, changes, errors }
|
|
34
|
-
} else {
|
|
35
|
-
return { success: true, changes: ['No changes needed'], errors }
|
|
36
|
-
}
|
|
37
|
-
} catch (error) {
|
|
38
|
-
errors.push(`Migration failed: ${error instanceof Error ? error.message : String(error)}`)
|
|
39
|
-
return { success: false, changes, errors }
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
private addImports(code: string, changes: string[]): string {
|
|
44
|
-
const hasToolImport = /import\s+{\s*tool\s*}\s+from\s+['"]@opencode-ai\/plugin['"]/.test(code)
|
|
45
|
-
const hasZodImport = /import.*from\s+['"]zod['"]/.test(code)
|
|
46
|
-
const hasPluginImport = /import.*from\s+['"]@opencode-ai\/plugin['"]/.test(code)
|
|
47
|
-
|
|
48
|
-
if (!hasPluginImport) {
|
|
49
|
-
code = `import type { Plugin } from "@opencode-ai/plugin"\n${code}`
|
|
50
|
-
changes.push('Added Plugin type import')
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
if (!hasToolImport) {
|
|
54
|
-
if (hasPluginImport) {
|
|
55
|
-
code = code.replace(
|
|
56
|
-
/import\s+(type\s+)?\{([^}]+)\}\s+from\s+['"]@opencode-ai\/plugin['"]/,
|
|
57
|
-
(match, typeKeyword, imports) => {
|
|
58
|
-
if (typeKeyword) {
|
|
59
|
-
return match.replace('}', ', tool }').replace('type ', '')
|
|
60
|
-
}
|
|
61
|
-
const cleanImports = imports.split(',').map((s: string) => s.trim()).filter(Boolean)
|
|
62
|
-
if (!cleanImports.includes('tool')) {
|
|
63
|
-
cleanImports.push('tool')
|
|
64
|
-
}
|
|
65
|
-
return `import { ${cleanImports.join(', ')} } from "@opencode-ai/plugin"`
|
|
66
|
-
}
|
|
67
|
-
)
|
|
68
|
-
} else {
|
|
69
|
-
code = `import { tool } from "@opencode-ai/plugin"\n${code}`
|
|
70
|
-
}
|
|
71
|
-
changes.push('Added tool import from @opencode-ai/plugin')
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
if (!hasZodImport) {
|
|
75
|
-
const pluginImportIndex = code.indexOf('import')
|
|
76
|
-
const firstNewline = code.indexOf('\n', pluginImportIndex)
|
|
77
|
-
code = code.slice(0, firstNewline + 1) + `import { z } from "zod"\n` + code.slice(firstNewline + 1)
|
|
78
|
-
changes.push('Added Zod import')
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
return code
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
private convertInputSchemaToToolBuilder(code: string, changes: string[]): string {
|
|
85
|
-
const toolPattern = /"([^"]+)":\s*{\s*description:\s*"([^"]+)",\s*inputSchema:\s*(\{[\s\S]*?\}),\s*async\s+execute\s*\(([^)]*)\)\s*(\{[\s\S]*?\n\s*\})\s*\}/g
|
|
86
|
-
|
|
87
|
-
let matchCount = 0
|
|
88
|
-
code = code.replace(toolPattern, (match, toolName, description, inputSchemaStr, argsParam, executeBody) => {
|
|
89
|
-
matchCount++
|
|
90
|
-
|
|
91
|
-
try {
|
|
92
|
-
const inputSchema = this.parseInputSchema(inputSchemaStr)
|
|
93
|
-
const zodArgs = this.convertToZodSchema(inputSchema)
|
|
94
|
-
|
|
95
|
-
const converted = `"${toolName}": tool({
|
|
96
|
-
description: "${description}",
|
|
97
|
-
args: ${zodArgs},
|
|
98
|
-
async execute(${argsParam}) ${executeBody}
|
|
99
|
-
})`
|
|
100
|
-
|
|
101
|
-
return converted
|
|
102
|
-
} catch (error) {
|
|
103
|
-
console.warn(`Failed to convert tool "${toolName}": ${error}`)
|
|
104
|
-
return match
|
|
105
|
-
}
|
|
106
|
-
})
|
|
107
|
-
|
|
108
|
-
if (matchCount > 0) {
|
|
109
|
-
changes.push(`Converted ${matchCount} tool(s) from inputSchema to tool() builder`)
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
return code
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
private parseInputSchema(schemaStr: string): any {
|
|
116
|
-
const cleaned = schemaStr
|
|
117
|
-
.replace(/\/\/.*$/gm, '')
|
|
118
|
-
.replace(/\/\*[\s\S]*?\*\//g, '')
|
|
119
|
-
.trim()
|
|
120
|
-
|
|
121
|
-
try {
|
|
122
|
-
const jsonStr = cleaned
|
|
123
|
-
.replace(/(\w+):/g, '"$1":')
|
|
124
|
-
.replace(/'/g, '"')
|
|
125
|
-
|
|
126
|
-
return JSON.parse(jsonStr)
|
|
127
|
-
} catch (error) {
|
|
128
|
-
return eval(`(${cleaned})`)
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
private convertToZodSchema(inputSchema: any): string {
|
|
133
|
-
if (!inputSchema.properties) {
|
|
134
|
-
return '{}'
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
const required = new Set(inputSchema.required || [])
|
|
138
|
-
const properties = inputSchema.properties
|
|
139
|
-
|
|
140
|
-
const zodFields: string[] = []
|
|
141
|
-
|
|
142
|
-
for (const [key, propDef] of Object.entries<any>(properties)) {
|
|
143
|
-
const isRequired = required.has(key)
|
|
144
|
-
let zodType = this.getZodType(propDef, isRequired)
|
|
145
|
-
|
|
146
|
-
const description = propDef.description
|
|
147
|
-
if (description) {
|
|
148
|
-
zodType += `.describe("${description.replace(/"/g, '\\"')}")`
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
zodFields.push(`${key}: ${zodType}`)
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
return `{\n ${zodFields.join(',\n ')}\n }`
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
private getZodType(propDef: any, isRequired: boolean): string {
|
|
158
|
-
let zodType: string
|
|
159
|
-
|
|
160
|
-
switch (propDef.type) {
|
|
161
|
-
case 'string':
|
|
162
|
-
if (propDef.enum && Array.isArray(propDef.enum)) {
|
|
163
|
-
zodType = `z.enum([${propDef.enum.map((v: string) => `"${v}"`).join(', ')}])`
|
|
164
|
-
} else {
|
|
165
|
-
zodType = 'z.string()'
|
|
166
|
-
}
|
|
167
|
-
break
|
|
168
|
-
|
|
169
|
-
case 'number':
|
|
170
|
-
zodType = 'z.number()'
|
|
171
|
-
break
|
|
172
|
-
|
|
173
|
-
case 'boolean':
|
|
174
|
-
zodType = 'z.boolean()'
|
|
175
|
-
break
|
|
176
|
-
|
|
177
|
-
case 'array':
|
|
178
|
-
if (propDef.items) {
|
|
179
|
-
const itemType = this.getZodType(propDef.items, true)
|
|
180
|
-
zodType = `z.array(${itemType})`
|
|
181
|
-
} else {
|
|
182
|
-
zodType = 'z.array(z.any())'
|
|
183
|
-
}
|
|
184
|
-
break
|
|
185
|
-
|
|
186
|
-
case 'object':
|
|
187
|
-
if (propDef.additionalProperties) {
|
|
188
|
-
const valueType = this.getZodType(propDef.additionalProperties, true)
|
|
189
|
-
zodType = `z.record(${valueType})`
|
|
190
|
-
} else {
|
|
191
|
-
zodType = 'z.object({})'
|
|
192
|
-
}
|
|
193
|
-
break
|
|
194
|
-
|
|
195
|
-
default:
|
|
196
|
-
zodType = 'z.any()'
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
if (!isRequired) {
|
|
200
|
-
zodType += '.optional()'
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
return zodType
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
printMigrationResult(pluginName: string, result: MigrationResult): void {
|
|
207
|
-
const status = result.success ? '✅' : '❌'
|
|
208
|
-
console.log(`\n${status} ${pluginName}`)
|
|
209
|
-
|
|
210
|
-
if (result.changes.length > 0) {
|
|
211
|
-
console.log(' Changes:')
|
|
212
|
-
result.changes.forEach(change => console.log(` • ${change}`))
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
if (result.errors.length > 0) {
|
|
216
|
-
console.log(' Errors:')
|
|
217
|
-
result.errors.forEach(error => console.log(` ❌ ${error}`))
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
}
|
package/pets-registry.ts
DELETED
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
import { readdirSync, existsSync, readFileSync } from "fs"
|
|
2
|
-
import { join, resolve } from "path"
|
|
3
|
-
import { createLogger } from "./logger"
|
|
4
|
-
|
|
5
|
-
const logger = createLogger("pets-registry")
|
|
6
|
-
|
|
7
|
-
export interface PetMetadata {
|
|
8
|
-
id: string
|
|
9
|
-
name: string
|
|
10
|
-
description: string
|
|
11
|
-
version: string
|
|
12
|
-
keywords: string[]
|
|
13
|
-
author?: string
|
|
14
|
-
repository?: {
|
|
15
|
-
type: string
|
|
16
|
-
url: string
|
|
17
|
-
directory?: string
|
|
18
|
-
}
|
|
19
|
-
queries?: string[]
|
|
20
|
-
scenarios?: Record<string, string[]>
|
|
21
|
-
envVariables?: {
|
|
22
|
-
required?: Array<{ name: string; description: string; provider?: string }>
|
|
23
|
-
optional?: Array<{ name: string; description: string; provider?: string }>
|
|
24
|
-
}
|
|
25
|
-
utils?: {
|
|
26
|
-
dependencies?: string[]
|
|
27
|
-
paths?: string[]
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export class PetsRegistry {
|
|
32
|
-
private pets: Map<string, PetMetadata> = new Map()
|
|
33
|
-
private petsDir: string
|
|
34
|
-
|
|
35
|
-
constructor(petsDir?: string) {
|
|
36
|
-
this.petsDir = petsDir || resolve(__dirname, "../../pets")
|
|
37
|
-
this.loadPets()
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
private loadPets(): void {
|
|
41
|
-
try {
|
|
42
|
-
if (!existsSync(this.petsDir)) {
|
|
43
|
-
logger.warn(`Pets directory not found: ${this.petsDir}`)
|
|
44
|
-
return
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const entries = readdirSync(this.petsDir, { withFileTypes: true })
|
|
48
|
-
|
|
49
|
-
for (const entry of entries) {
|
|
50
|
-
if (!entry.isDirectory() || entry.name.startsWith('.') || entry.name === 'node_modules') {
|
|
51
|
-
continue
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const petDir = join(this.petsDir, entry.name)
|
|
55
|
-
const packageJsonPath = join(petDir, 'package.json')
|
|
56
|
-
|
|
57
|
-
if (!existsSync(packageJsonPath)) {
|
|
58
|
-
continue
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
try {
|
|
62
|
-
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'))
|
|
63
|
-
|
|
64
|
-
const metadata: PetMetadata = {
|
|
65
|
-
id: entry.name,
|
|
66
|
-
name: packageJson.name || entry.name,
|
|
67
|
-
description: packageJson.description || '',
|
|
68
|
-
version: packageJson.version || '1.0.0',
|
|
69
|
-
keywords: packageJson.keywords || [],
|
|
70
|
-
author: packageJson.author,
|
|
71
|
-
repository: packageJson.repository,
|
|
72
|
-
queries: packageJson.queries,
|
|
73
|
-
scenarios: packageJson.scenarios,
|
|
74
|
-
envVariables: packageJson.envVariables,
|
|
75
|
-
utils: packageJson.utils
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
this.pets.set(entry.name, metadata)
|
|
79
|
-
logger.debug(`Loaded pet: ${entry.name}`)
|
|
80
|
-
} catch (error: any) {
|
|
81
|
-
logger.error(`Failed to load pet ${entry.name}: ${error.message}`)
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
logger.info(`Loaded ${this.pets.size} pets`)
|
|
86
|
-
} catch (error: any) {
|
|
87
|
-
logger.error(`Failed to load pets: ${error.message}`)
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
getAllPets(): PetMetadata[] {
|
|
92
|
-
return Array.from(this.pets.values())
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
getPet(id: string): PetMetadata | undefined {
|
|
96
|
-
return this.pets.get(id)
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
searchPets(query: string): PetMetadata[] {
|
|
100
|
-
if (!query || query.trim() === '') {
|
|
101
|
-
return this.getAllPets()
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
const normalizedQuery = query.toLowerCase().trim()
|
|
105
|
-
const results: PetMetadata[] = []
|
|
106
|
-
|
|
107
|
-
for (const pet of this.pets.values()) {
|
|
108
|
-
const searchableText = [
|
|
109
|
-
pet.id,
|
|
110
|
-
pet.name,
|
|
111
|
-
pet.description,
|
|
112
|
-
...(pet.keywords || []),
|
|
113
|
-
pet.author || '',
|
|
114
|
-
].join(' ').toLowerCase()
|
|
115
|
-
|
|
116
|
-
if (searchableText.includes(normalizedQuery)) {
|
|
117
|
-
results.push(pet)
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
return results
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
getPetsByCategory(keywords: string[]): PetMetadata[] {
|
|
125
|
-
return this.getAllPets().filter(pet =>
|
|
126
|
-
keywords.some(keyword =>
|
|
127
|
-
pet.keywords?.some(k => k.toLowerCase().includes(keyword.toLowerCase()))
|
|
128
|
-
)
|
|
129
|
-
)
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
reload(): void {
|
|
133
|
-
this.pets.clear()
|
|
134
|
-
this.loadPets()
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
let defaultRegistry: PetsRegistry | null = null
|
|
139
|
-
|
|
140
|
-
export function getPetsRegistry(petsDir?: string): PetsRegistry {
|
|
141
|
-
if (!defaultRegistry) {
|
|
142
|
-
defaultRegistry = new PetsRegistry(petsDir)
|
|
143
|
-
}
|
|
144
|
-
return defaultRegistry
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
export function searchPetsInRegistry(query: string, petsDir?: string): PetMetadata[] {
|
|
148
|
-
const registry = getPetsRegistry(petsDir)
|
|
149
|
-
return registry.searchPets(query)
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
export function getAllPetsFromRegistry(petsDir?: string): PetMetadata[] {
|
|
153
|
-
const registry = getPetsRegistry(petsDir)
|
|
154
|
-
return registry.getAllPets()
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
export function getPetFromRegistry(id: string, petsDir?: string): PetMetadata | undefined {
|
|
158
|
-
const registry = getPetsRegistry(petsDir)
|
|
159
|
-
return registry.getPet(id)
|
|
160
|
-
}
|