openpets 1.0.4 → 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.
Files changed (96) hide show
  1. package/dist/data/api.json +3172 -0
  2. package/dist/src/core/ai-client-base/index.d.ts +47 -0
  3. package/dist/src/core/ai-client-base/index.d.ts.map +1 -0
  4. package/dist/src/core/ai-client-base/index.js +168 -0
  5. package/dist/src/core/ai-client-base/index.js.map +1 -0
  6. package/dist/src/core/browser.d.ts +10 -0
  7. package/dist/src/core/browser.d.ts.map +1 -0
  8. package/{browser.ts → dist/src/core/browser.js} +4 -4
  9. package/dist/src/core/browser.js.map +1 -0
  10. package/dist/src/core/build-pet.d.ts +2 -0
  11. package/dist/src/core/build-pet.d.ts.map +1 -0
  12. package/dist/src/core/build-pet.js +364 -0
  13. package/dist/src/core/build-pet.js.map +1 -0
  14. package/dist/src/core/cli.d.ts +3 -0
  15. package/dist/src/core/cli.d.ts.map +1 -0
  16. package/dist/src/core/cli.js +244 -0
  17. package/dist/src/core/cli.js.map +1 -0
  18. package/dist/src/core/config-manager.d.ts +13 -0
  19. package/dist/src/core/config-manager.d.ts.map +1 -0
  20. package/dist/src/core/config-manager.js +59 -0
  21. package/dist/src/core/config-manager.js.map +1 -0
  22. package/dist/src/core/deploy-pet.d.ts +2 -0
  23. package/dist/src/core/deploy-pet.d.ts.map +1 -0
  24. package/dist/src/core/deploy-pet.js +66 -0
  25. package/dist/src/core/deploy-pet.js.map +1 -0
  26. package/dist/src/core/index.d.ts +11 -0
  27. package/dist/src/core/index.d.ts.map +1 -0
  28. package/dist/src/core/index.js +11 -0
  29. package/dist/src/core/index.js.map +1 -0
  30. package/dist/src/core/local-cache.d.ts +69 -0
  31. package/dist/src/core/local-cache.d.ts.map +1 -0
  32. package/dist/src/core/local-cache.js +212 -0
  33. package/dist/src/core/local-cache.js.map +1 -0
  34. package/dist/src/core/logger.d.ts.map +1 -0
  35. package/{logger.js → dist/src/core/logger.js} +8 -9
  36. package/dist/src/core/logger.js.map +1 -0
  37. package/dist/src/core/mcp-factory.d.ts +12 -0
  38. package/dist/src/core/mcp-factory.d.ts.map +1 -0
  39. package/dist/src/core/mcp-factory.js +143 -0
  40. package/dist/src/core/mcp-factory.js.map +1 -0
  41. package/dist/src/core/mcp-server.d.ts +3 -0
  42. package/dist/src/core/mcp-server.d.ts.map +1 -0
  43. package/dist/src/core/mcp-server.js +55 -0
  44. package/dist/src/core/mcp-server.js.map +1 -0
  45. package/dist/src/core/migrate-plugin.d.ts +15 -0
  46. package/dist/src/core/migrate-plugin.d.ts.map +1 -0
  47. package/dist/src/core/migrate-plugin.js +181 -0
  48. package/dist/src/core/migrate-plugin.js.map +1 -0
  49. package/dist/src/core/pets-registry.d.ts +47 -0
  50. package/dist/src/core/pets-registry.d.ts.map +1 -0
  51. package/dist/src/core/pets-registry.js +109 -0
  52. package/dist/src/core/pets-registry.js.map +1 -0
  53. package/dist/src/core/plugin-factory.d.ts +58 -0
  54. package/dist/src/core/plugin-factory.d.ts.map +1 -0
  55. package/dist/src/core/plugin-factory.js +212 -0
  56. package/dist/src/core/plugin-factory.js.map +1 -0
  57. package/dist/src/core/prompt-utils.d.ts +14 -0
  58. package/dist/src/core/prompt-utils.d.ts.map +1 -0
  59. package/dist/src/core/prompt-utils.js +106 -0
  60. package/dist/src/core/prompt-utils.js.map +1 -0
  61. package/dist/src/core/schema-helpers.d.ts +33 -0
  62. package/dist/src/core/schema-helpers.d.ts.map +1 -0
  63. package/dist/src/core/schema-helpers.js +46 -0
  64. package/dist/src/core/schema-helpers.js.map +1 -0
  65. package/dist/src/core/search-pets.d.ts +29 -0
  66. package/dist/src/core/search-pets.d.ts.map +1 -0
  67. package/dist/src/core/search-pets.js +196 -0
  68. package/dist/src/core/search-pets.js.map +1 -0
  69. package/dist/src/core/types.d.ts +63 -0
  70. package/dist/src/core/types.d.ts.map +1 -0
  71. package/dist/src/core/types.js +2 -0
  72. package/dist/src/core/types.js.map +1 -0
  73. package/dist/src/core/validate-pet.d.ts +40 -0
  74. package/dist/src/core/validate-pet.d.ts.map +1 -0
  75. package/dist/src/core/validate-pet.js +650 -0
  76. package/dist/src/core/validate-pet.js.map +1 -0
  77. package/package.json +7 -11
  78. package/ai-client-base/index.ts +0 -117
  79. package/build-pet.ts +0 -429
  80. package/cli.ts +0 -179
  81. package/config-manager.ts +0 -82
  82. package/deploy-pet.ts +0 -91
  83. package/index.ts +0 -10
  84. package/local-cache.ts +0 -280
  85. package/logger.ts +0 -143
  86. package/mcp-factory.ts +0 -180
  87. package/mcp-server.ts +0 -69
  88. package/migrate-plugin.ts +0 -220
  89. package/pets-registry.ts +0 -160
  90. package/plugin-factory.ts +0 -309
  91. package/prompt-utils.ts +0 -130
  92. package/schema-helpers.ts +0 -59
  93. package/search-pets.ts +0 -267
  94. package/types.ts +0 -68
  95. package/validate-pet.ts +0 -594
  96. /package/{logger.d.ts → dist/src/core/logger.d.ts} +0 -0
package/logger.ts DELETED
@@ -1,143 +0,0 @@
1
- export enum LogLevel {
2
- DEBUG = 0,
3
- INFO = 1,
4
- WARN = 2,
5
- ERROR = 3,
6
- NONE = 4
7
- }
8
-
9
- const LOG_LEVEL_NAMES: Record<LogLevel, string> = {
10
- [LogLevel.DEBUG]: 'DEBUG',
11
- [LogLevel.INFO]: 'INFO',
12
- [LogLevel.WARN]: 'WARN',
13
- [LogLevel.ERROR]: 'ERROR',
14
- [LogLevel.NONE]: 'NONE'
15
- }
16
-
17
- interface LoggerOptions {
18
- namespace: string
19
- level?: LogLevel
20
- enabled?: boolean
21
- }
22
-
23
- export class Logger {
24
- private namespace: string
25
- private level: LogLevel
26
- private enabled: boolean
27
-
28
- constructor(options: LoggerOptions) {
29
- this.namespace = options.namespace
30
- this.enabled = options.enabled ?? this.detectLoggingEnabled()
31
- this.level = options.level ?? this.detectLogLevel()
32
- }
33
-
34
- private detectLoggingEnabled(): boolean {
35
- return process.env.ENABLE_LOGGING === 'true' ||
36
- process.env.DEBUG === 'true' ||
37
- process.argv.includes('--print-logs')
38
- }
39
-
40
- private detectLogLevel(): LogLevel {
41
- const envLevel = process.env.LOG_LEVEL?.toUpperCase()
42
- const argLevel = this.getArgLogLevel()
43
-
44
- const levelStr = argLevel || envLevel || 'INFO'
45
-
46
- switch (levelStr) {
47
- case 'DEBUG':
48
- return LogLevel.DEBUG
49
- case 'INFO':
50
- return LogLevel.INFO
51
- case 'WARN':
52
- return LogLevel.WARN
53
- case 'ERROR':
54
- return LogLevel.ERROR
55
- case 'NONE':
56
- return LogLevel.NONE
57
- default:
58
- return LogLevel.INFO
59
- }
60
- }
61
-
62
- private getArgLogLevel(): string | undefined {
63
- const logLevelIndex = process.argv.indexOf('--log-level')
64
- if (logLevelIndex !== -1 && process.argv[logLevelIndex + 1]) {
65
- return process.argv[logLevelIndex + 1].toUpperCase()
66
- }
67
- return undefined
68
- }
69
-
70
- private shouldLog(level: LogLevel): boolean {
71
- return this.enabled && level >= this.level
72
- }
73
-
74
- private formatTimestamp(): string {
75
- const now = new Date()
76
- const year = now.getFullYear()
77
- const month = String(now.getMonth() + 1).padStart(2, '0')
78
- const day = String(now.getDate()).padStart(2, '0')
79
- const hours = String(now.getHours()).padStart(2, '0')
80
- const minutes = String(now.getMinutes()).padStart(2, '0')
81
- const seconds = String(now.getSeconds()).padStart(2, '0')
82
- return `${year}-${month}-${day}T${hours}:${minutes}:${seconds}`
83
- }
84
-
85
- private formatMessage(level: LogLevel, message: string, ...args: any[]): string {
86
- const timestamp = this.formatTimestamp()
87
- const levelName = LOG_LEVEL_NAMES[level].padEnd(5, ' ')
88
- const prefix = `${levelName} ${timestamp} service=${this.namespace}`
89
-
90
- if (args.length === 0) {
91
- return `${prefix} ${message}`
92
- }
93
-
94
- const formattedArgs = args.map(arg => {
95
- if (typeof arg === 'object') {
96
- return JSON.stringify(arg, null, 2)
97
- }
98
- return String(arg)
99
- }).join(' ')
100
-
101
- return `${prefix} ${message} ${formattedArgs}`
102
- }
103
-
104
- debug(message: string, ...args: any[]): void {
105
- if (this.shouldLog(LogLevel.DEBUG)) {
106
- console.log(this.formatMessage(LogLevel.DEBUG, message, ...args))
107
- }
108
- }
109
-
110
- info(message: string, ...args: any[]): void {
111
- if (this.shouldLog(LogLevel.INFO)) {
112
- console.log(this.formatMessage(LogLevel.INFO, message, ...args))
113
- }
114
- }
115
-
116
- warn(message: string, ...args: any[]): void {
117
- if (this.shouldLog(LogLevel.WARN)) {
118
- console.warn(this.formatMessage(LogLevel.WARN, message, ...args))
119
- }
120
- }
121
-
122
- error(message: string, ...args: any[]): void {
123
- if (this.shouldLog(LogLevel.ERROR)) {
124
- console.error(this.formatMessage(LogLevel.ERROR, message, ...args))
125
- }
126
- }
127
-
128
- child(subNamespace: string): Logger {
129
- return new Logger({
130
- namespace: `${this.namespace}:${subNamespace}`,
131
- level: this.level,
132
- enabled: this.enabled
133
- })
134
- }
135
- }
136
-
137
- export function createLogger(namespace: string, options?: Partial<LoggerOptions>): Logger {
138
- return new Logger({
139
- namespace,
140
- level: options?.level,
141
- enabled: options?.enabled
142
- })
143
- }
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
- }