openpets 1.0.5 → 1.0.7
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 +6658 -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 +392 -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 +12 -0
- package/dist/src/core/index.d.ts.map +1 -0
- package/dist/src/core/index.js +12 -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/mautrix-bridge.d.ts +93 -0
- package/dist/src/core/mautrix-bridge.d.ts.map +1 -0
- package/dist/src/core/mautrix-bridge.js +1046 -0
- package/dist/src/core/mautrix-bridge.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 +30 -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 +15 -28
- 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/build-pet.ts
DELETED
|
@@ -1,429 +0,0 @@
|
|
|
1
|
-
import { join, dirname } from 'path'
|
|
2
|
-
import { fileURLToPath } from 'url'
|
|
3
|
-
import { existsSync, readdirSync, readFileSync, statSync, writeFileSync } from 'fs'
|
|
4
|
-
import { pathToFileURL } from 'url'
|
|
5
|
-
import { PluginValidator } from './validate-pet.js'
|
|
6
|
-
|
|
7
|
-
const __filename = fileURLToPath(import.meta.url)
|
|
8
|
-
const __dirname = dirname(__filename)
|
|
9
|
-
const projectRoot = dirname(dirname(__dirname))
|
|
10
|
-
|
|
11
|
-
const DEBUG = process.env.PETS_DEBUG === 'true'
|
|
12
|
-
|
|
13
|
-
function debug(...msgs: any[]) {
|
|
14
|
-
if (DEBUG) {
|
|
15
|
-
console.log('[BUILD-PET]', ...msgs)
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
interface ToolDefinition {
|
|
20
|
-
name: string
|
|
21
|
-
description: string
|
|
22
|
-
schema: any
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
async function extractToolsFromIndexFile(indexPath: string): Promise<ToolDefinition[]> {
|
|
26
|
-
debug('=== EXTRACTING TOOLS FROM INDEX FILE ===')
|
|
27
|
-
debug('Index path:', indexPath)
|
|
28
|
-
debug('File exists:', existsSync(indexPath))
|
|
29
|
-
|
|
30
|
-
try {
|
|
31
|
-
const indexUrl = pathToFileURL(indexPath).href
|
|
32
|
-
debug('Index URL:', indexUrl)
|
|
33
|
-
|
|
34
|
-
debug('Attempting dynamic import...')
|
|
35
|
-
const indexModule = await import(/* @vite-ignore */ indexUrl)
|
|
36
|
-
debug('Import successful')
|
|
37
|
-
debug('Module keys:', Object.keys(indexModule))
|
|
38
|
-
|
|
39
|
-
if (indexModule.toolsMetadata && Array.isArray(indexModule.toolsMetadata)) {
|
|
40
|
-
console.log(` Found ${indexModule.toolsMetadata.length} tools from exported toolsMetadata`)
|
|
41
|
-
debug('Tools metadata:', JSON.stringify(indexModule.toolsMetadata, null, 2))
|
|
42
|
-
return indexModule.toolsMetadata
|
|
43
|
-
} else {
|
|
44
|
-
debug('toolsMetadata not found or not an array')
|
|
45
|
-
debug('indexModule.toolsMetadata:', indexModule.toolsMetadata)
|
|
46
|
-
}
|
|
47
|
-
} catch (error) {
|
|
48
|
-
console.warn(` ⚠️ Could not import toolsMetadata, falling back to file parsing`)
|
|
49
|
-
console.warn(` Error: ${error instanceof Error ? error.message : String(error)}`)
|
|
50
|
-
debug('Import error details:', {
|
|
51
|
-
name: error instanceof Error ? error.name : 'Unknown',
|
|
52
|
-
message: error instanceof Error ? error.message : String(error),
|
|
53
|
-
stack: error instanceof Error ? error.stack : 'No stack trace'
|
|
54
|
-
})
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
debug('Falling back to file parsing')
|
|
58
|
-
return extractToolsFromIndexFileByParsing(indexPath)
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function extractToolsFromIndexFileByParsing(indexPath: string): ToolDefinition[] {
|
|
62
|
-
const content = readFileSync(indexPath, 'utf8')
|
|
63
|
-
|
|
64
|
-
const toolsMatch = content.match(/const\s+tools:\s*ToolDefinition\[\]\s*=\s*\[([\s\S]*?)\n\s*\]/m)
|
|
65
|
-
if (!toolsMatch) {
|
|
66
|
-
console.warn('⚠️ Could not find tools array in index.ts')
|
|
67
|
-
return []
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const toolsArray = toolsMatch[1]
|
|
71
|
-
const toolNames: ToolDefinition[] = []
|
|
72
|
-
|
|
73
|
-
const toolsSeparated = toolsArray.split(/\n\s*\{/).filter(part => part.includes('name:'))
|
|
74
|
-
const toolBlocks = toolsSeparated.map((part, idx) => {
|
|
75
|
-
if (idx === 0) return part
|
|
76
|
-
return '{' + part
|
|
77
|
-
})
|
|
78
|
-
|
|
79
|
-
for (const block of toolBlocks) {
|
|
80
|
-
const nameMatch = block.match(/name:\s*["']([^"']+)["']/)
|
|
81
|
-
const descMatch = block.match(/description:\s*["']([^"']+)["']/)
|
|
82
|
-
|
|
83
|
-
const schemaMatch = block.match(/schema:\s*z\.object\(\{([\s\S]*?)\}\),?\s*(?:async\s+execute|$)/)
|
|
84
|
-
|
|
85
|
-
if (nameMatch && descMatch) {
|
|
86
|
-
let schemaProperties: any = {}
|
|
87
|
-
|
|
88
|
-
if (schemaMatch) {
|
|
89
|
-
const schemaContent = schemaMatch[1]
|
|
90
|
-
|
|
91
|
-
const lines = schemaContent.split('\n').filter(l => l.trim() && !l.trim().startsWith('//'))
|
|
92
|
-
|
|
93
|
-
for (const line of lines) {
|
|
94
|
-
const propMatch = line.match(/^\s*(\w+):\s*z\.(.+?),?\s*$/)
|
|
95
|
-
if (!propMatch) continue
|
|
96
|
-
|
|
97
|
-
const [, propName, zodDef] = propMatch
|
|
98
|
-
let propSchema: any = {}
|
|
99
|
-
|
|
100
|
-
if (zodDef.includes('string(')) {
|
|
101
|
-
propSchema.type = 'string'
|
|
102
|
-
} else if (zodDef.includes('number(')) {
|
|
103
|
-
propSchema.type = 'number'
|
|
104
|
-
const minMatch = zodDef.match(/\.min\((\d+)\)/)
|
|
105
|
-
const maxMatch = zodDef.match(/\.max\((\d+)\)/)
|
|
106
|
-
if (minMatch) propSchema.minimum = parseInt(minMatch[1])
|
|
107
|
-
if (maxMatch) propSchema.maximum = parseInt(maxMatch[1])
|
|
108
|
-
} else if (zodDef.includes('boolean(')) {
|
|
109
|
-
propSchema.type = 'boolean'
|
|
110
|
-
} else if (zodDef.includes('enum(')) {
|
|
111
|
-
propSchema.type = 'string'
|
|
112
|
-
const enumMatch = zodDef.match(/enum\(\[([^\]]+)\]\)/)
|
|
113
|
-
if (enumMatch) {
|
|
114
|
-
const enumValues = enumMatch[1].match(/["']([^"']+)["']/g)?.map(v => v.replace(/["']/g, ''))
|
|
115
|
-
if (enumValues) propSchema.enum = enumValues
|
|
116
|
-
}
|
|
117
|
-
} else if (zodDef.includes('array(')) {
|
|
118
|
-
propSchema.type = 'array'
|
|
119
|
-
const arrayTypeMatch = zodDef.match(/array\(z\.(\w+)\(\)\)/)
|
|
120
|
-
if (arrayTypeMatch) {
|
|
121
|
-
propSchema.items = { type: arrayTypeMatch[1].toLowerCase() }
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
if (zodDef.includes('.optional()')) {
|
|
126
|
-
propSchema.optional = true
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
const descMatch = zodDef.match(/\.describe\(["']([^"']+)["']\)/)
|
|
130
|
-
if (descMatch) {
|
|
131
|
-
propSchema.description = descMatch[1]
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
schemaProperties[propName] = propSchema
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
toolNames.push({
|
|
139
|
-
name: nameMatch[1],
|
|
140
|
-
description: descMatch[1],
|
|
141
|
-
schema: {
|
|
142
|
-
type: 'object',
|
|
143
|
-
properties: schemaProperties
|
|
144
|
-
}
|
|
145
|
-
})
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
console.log(` Found ${toolNames.length} tools in index.ts`)
|
|
150
|
-
return toolNames
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
function formatZodSchema(schema: any, depth: number = 0): any {
|
|
154
|
-
if (!schema || !schema._def) {
|
|
155
|
-
return { type: 'object', properties: {} }
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
const def = schema._def
|
|
159
|
-
const zodType = def.typeName || def.type || schema.constructor?.name || 'unknown'
|
|
160
|
-
|
|
161
|
-
if (zodType === 'ZodObject' || zodType === 'object') {
|
|
162
|
-
const properties: any = {}
|
|
163
|
-
const shapeObj = typeof def.shape === 'function' ? def.shape() : def.shape || {}
|
|
164
|
-
|
|
165
|
-
for (const [key, value] of Object.entries(shapeObj)) {
|
|
166
|
-
properties[key] = formatZodSchema(value, depth + 1)
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
return {
|
|
170
|
-
type: 'object',
|
|
171
|
-
properties
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
if (zodType === 'ZodString' || zodType === 'string') {
|
|
176
|
-
return { type: 'string' }
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
if (zodType === 'ZodNumber' || zodType === 'number') {
|
|
180
|
-
const result: any = { type: 'number' }
|
|
181
|
-
if (def.checks) {
|
|
182
|
-
for (const check of def.checks) {
|
|
183
|
-
if (check.kind === 'min') result.minimum = check.value
|
|
184
|
-
if (check.kind === 'max') result.maximum = check.value
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
return result
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
if (zodType === 'ZodBoolean' || zodType === 'boolean') {
|
|
191
|
-
return { type: 'boolean' }
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
if (zodType === 'ZodArray' || zodType === 'array') {
|
|
195
|
-
return {
|
|
196
|
-
type: 'array',
|
|
197
|
-
items: formatZodSchema(def.type, depth + 1)
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
if (zodType === 'ZodEnum' || zodType === 'enum') {
|
|
202
|
-
let values = def.values
|
|
203
|
-
if (!values && schema._def?.values) {
|
|
204
|
-
values = schema._def.values
|
|
205
|
-
}
|
|
206
|
-
if (!values && schema.options) {
|
|
207
|
-
values = schema.options
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
const enumArray = Array.isArray(values) ? values : Object.values(values || {})
|
|
211
|
-
return {
|
|
212
|
-
type: 'string',
|
|
213
|
-
enum: enumArray
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
if (zodType === 'ZodOptional' || zodType === 'optional') {
|
|
218
|
-
return {
|
|
219
|
-
...formatZodSchema(def.innerType, depth + 1),
|
|
220
|
-
optional: true
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
return { type: zodType }
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
function generateToolsMetadata(tools: ToolDefinition[]): Array<{ name: string; description: string; schema: any }> {
|
|
228
|
-
return tools.map(tool => ({
|
|
229
|
-
name: tool.name,
|
|
230
|
-
description: tool.description,
|
|
231
|
-
schema: tool.schema._def ? formatZodSchema(tool.schema) : tool.schema
|
|
232
|
-
}))
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
function generateScriptsFromTools(tools: ToolDefinition[], petName: string): Record<string, string> {
|
|
236
|
-
const scripts: Record<string, string> = {
|
|
237
|
-
build: 'pets build',
|
|
238
|
-
'build:tsc': 'tsc',
|
|
239
|
-
quickstart: `opencode run "list available ${petName} commands"`,
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
for (const tool of tools) {
|
|
243
|
-
let scriptName = tool.name
|
|
244
|
-
|
|
245
|
-
if (scriptName.startsWith(`${petName}-`)) {
|
|
246
|
-
scriptName = scriptName.replace(new RegExp(`^${petName}-`), 'test:')
|
|
247
|
-
} else {
|
|
248
|
-
scriptName = `test:${scriptName}`
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
const command = `opencode run "${tool.description}"`
|
|
252
|
-
scripts[scriptName] = command
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
scripts['test:all'] = 'echo "Run individual test scripts to test specific tools"'
|
|
256
|
-
|
|
257
|
-
return scripts
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
export async function buildPet(petName?: string): Promise<void> {
|
|
261
|
-
debug('=== BUILD PET STARTING ===')
|
|
262
|
-
debug('Initial petName:', petName)
|
|
263
|
-
debug('CWD:', process.cwd())
|
|
264
|
-
debug('Project root:', projectRoot)
|
|
265
|
-
|
|
266
|
-
if (!petName) {
|
|
267
|
-
const cwd = process.cwd()
|
|
268
|
-
const petsDir = join(projectRoot, 'pets')
|
|
269
|
-
|
|
270
|
-
debug('Auto-detecting pet from CWD:', cwd)
|
|
271
|
-
debug('Pets directory:', petsDir)
|
|
272
|
-
|
|
273
|
-
if (cwd.includes('/pets/')) {
|
|
274
|
-
petName = cwd.split('/pets/')[1].split('/')[0]
|
|
275
|
-
console.log(`📦 Auto-detected pet: ${petName}`)
|
|
276
|
-
debug('Auto-detected pet:', petName)
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
if (!petName) {
|
|
280
|
-
console.error('Usage: pets build <pet-name>')
|
|
281
|
-
console.error('Example: pets build postgres')
|
|
282
|
-
console.error('')
|
|
283
|
-
console.error('Available pets:')
|
|
284
|
-
if (existsSync(petsDir)) {
|
|
285
|
-
const pets = readdirSync(petsDir).filter(dir => {
|
|
286
|
-
const petPath = join(petsDir, dir)
|
|
287
|
-
return statSync(petPath).isDirectory() && dir !== '_TEMPLATE_'
|
|
288
|
-
})
|
|
289
|
-
pets.forEach(pet => console.error(` - ${pet}`))
|
|
290
|
-
debug('Available pets:', pets)
|
|
291
|
-
} else {
|
|
292
|
-
debug('Pets directory does not exist:', petsDir)
|
|
293
|
-
}
|
|
294
|
-
process.exit(1)
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
const petDir = join(projectRoot, 'pets', petName)
|
|
299
|
-
const packageJsonPath = join(petDir, 'package.json')
|
|
300
|
-
const indexPath = join(petDir, 'index.ts')
|
|
301
|
-
|
|
302
|
-
debug('Pet directory:', petDir)
|
|
303
|
-
debug('Package.json path:', packageJsonPath)
|
|
304
|
-
debug('Index.ts path:', indexPath)
|
|
305
|
-
|
|
306
|
-
if (!existsSync(petDir)) {
|
|
307
|
-
console.error(`❌ Pet '${petName}' not found in pets/ directory`)
|
|
308
|
-
debug('Pet directory does not exist:', petDir)
|
|
309
|
-
process.exit(1)
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
if (!existsSync(packageJsonPath)) {
|
|
313
|
-
console.error(`❌ package.json not found for pet '${petName}'`)
|
|
314
|
-
debug('Package.json does not exist:', packageJsonPath)
|
|
315
|
-
process.exit(1)
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
if (!existsSync(indexPath)) {
|
|
319
|
-
console.error(`❌ index.ts not found for pet '${petName}'`)
|
|
320
|
-
debug('Index.ts does not exist:', indexPath)
|
|
321
|
-
process.exit(1)
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
console.log(`🔨 Building ${petName}...`)
|
|
325
|
-
debug('All required files found, proceeding with build')
|
|
326
|
-
|
|
327
|
-
const packageJsonContent = readFileSync(packageJsonPath, 'utf8')
|
|
328
|
-
debug('Package.json content length:', packageJsonContent.length)
|
|
329
|
-
const packageJson = JSON.parse(packageJsonContent)
|
|
330
|
-
debug('Package.json parsed successfully')
|
|
331
|
-
debug('Package name:', packageJson.name)
|
|
332
|
-
debug('Package version:', packageJson.version)
|
|
333
|
-
|
|
334
|
-
// Auto-generate repository field if missing
|
|
335
|
-
if (!packageJson.repository) {
|
|
336
|
-
packageJson.repository = {
|
|
337
|
-
type: 'git',
|
|
338
|
-
url: `https://github.com/raggle-ai/pets/pets/${petName}`
|
|
339
|
-
}
|
|
340
|
-
debug('Auto-generated repository field:', packageJson.repository.url)
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
console.log(` Name: ${packageJson.name}`)
|
|
344
|
-
console.log(` Version: ${packageJson.version}`)
|
|
345
|
-
console.log(` Description: ${packageJson.description || 'No description'}`)
|
|
346
|
-
|
|
347
|
-
console.log(`\n🔍 Validating plugin structure...`)
|
|
348
|
-
const validator = new PluginValidator()
|
|
349
|
-
const validation = validator.validatePlugin(petDir)
|
|
350
|
-
|
|
351
|
-
if (validation.result.errors.length > 0) {
|
|
352
|
-
console.log(`\n❌ Validation failed with ${validation.result.errors.length} error(s):`)
|
|
353
|
-
validation.result.errors.forEach(error => {
|
|
354
|
-
console.log(` ❌ ${error}`)
|
|
355
|
-
})
|
|
356
|
-
console.log(`\n💥 Build aborted due to validation errors.`)
|
|
357
|
-
process.exit(1)
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
if (validation.result.warnings.length > 0) {
|
|
361
|
-
console.log(`\n⚠️ Found ${validation.result.warnings.length} warning(s):`)
|
|
362
|
-
validation.result.warnings.forEach(warning => {
|
|
363
|
-
console.log(` ⚠️ ${warning}`)
|
|
364
|
-
})
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
if (validation.result.codePatternWarnings && validation.result.codePatternWarnings.length > 0) {
|
|
368
|
-
console.log(`\n📋 Code pattern analysis:`)
|
|
369
|
-
validation.result.codePatternWarnings.forEach(warning => {
|
|
370
|
-
console.log(` ${warning}`)
|
|
371
|
-
})
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
if (validation.result.errors.length === 0 && validation.result.warnings.length === 0 && (!validation.result.codePatternWarnings || validation.result.codePatternWarnings.length === 0)) {
|
|
375
|
-
console.log(` ✓ All validation checks passed`)
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
debug('Extracting tools from index file...')
|
|
379
|
-
const tools = await extractToolsFromIndexFile(indexPath)
|
|
380
|
-
debug(`Extracted ${tools.length} tools`)
|
|
381
|
-
|
|
382
|
-
if (tools.length > 0) {
|
|
383
|
-
console.log(`\n📝 Generating scripts and metadata for ${tools.length} tools...`)
|
|
384
|
-
debug('Tools extracted:', tools.map(t => t.name))
|
|
385
|
-
|
|
386
|
-
const scripts = generateScriptsFromTools(tools, petName)
|
|
387
|
-
debug('Generated scripts:', Object.keys(scripts))
|
|
388
|
-
|
|
389
|
-
const toolsMetadata = generateToolsMetadata(tools)
|
|
390
|
-
debug('Generated tools metadata count:', toolsMetadata.length)
|
|
391
|
-
|
|
392
|
-
packageJson.scripts = scripts
|
|
393
|
-
delete packageJson.tools
|
|
394
|
-
|
|
395
|
-
const commandsJsonPath = join(petDir, 'commands.json')
|
|
396
|
-
debug('Commands.json path:', commandsJsonPath)
|
|
397
|
-
|
|
398
|
-
const commandsData = {
|
|
399
|
-
name: packageJson.name,
|
|
400
|
-
version: packageJson.version,
|
|
401
|
-
description: packageJson.description,
|
|
402
|
-
tools: toolsMetadata,
|
|
403
|
-
generatedAt: new Date().toISOString()
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
debug('Writing package.json...')
|
|
407
|
-
writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\n', 'utf8')
|
|
408
|
-
debug('Package.json written successfully')
|
|
409
|
-
|
|
410
|
-
debug('Writing commands.json...')
|
|
411
|
-
writeFileSync(commandsJsonPath, JSON.stringify(commandsData, null, 2) + '\n', 'utf8')
|
|
412
|
-
debug('Commands.json written successfully')
|
|
413
|
-
|
|
414
|
-
console.log(` ✓ Updated package.json with ${Object.keys(scripts).length} scripts`)
|
|
415
|
-
console.log(` ✓ Generated commands.json with ${tools.length} tools`)
|
|
416
|
-
|
|
417
|
-
console.log(`\n🔧 Generated test scripts:`)
|
|
418
|
-
Object.entries(scripts).forEach(([name, cmd]) => {
|
|
419
|
-
if (name.startsWith('test:')) {
|
|
420
|
-
console.log(` - npm run ${name}`)
|
|
421
|
-
}
|
|
422
|
-
})
|
|
423
|
-
} else {
|
|
424
|
-
debug('No tools found in index file')
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
console.log(`\n✅ ${petName} built successfully!`)
|
|
428
|
-
debug('=== BUILD COMPLETE ===')
|
|
429
|
-
}
|
package/cli.ts
DELETED
|
@@ -1,268 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bun
|
|
2
|
-
|
|
3
|
-
import { buildPet } from './build-pet.js'
|
|
4
|
-
import { deployPet } from './deploy-pet.js'
|
|
5
|
-
import { addFolderToHistory } from './config-manager.js'
|
|
6
|
-
import { spawn } from 'child_process'
|
|
7
|
-
import { resolve } from 'path'
|
|
8
|
-
import { readFileSync, existsSync } from 'fs'
|
|
9
|
-
|
|
10
|
-
async function publishPet(petName: string | undefined, options: { preview?: boolean; channel?: string } = {}) {
|
|
11
|
-
const { preview = false, channel = 'latest' } = options
|
|
12
|
-
|
|
13
|
-
// Find the script path - try multiple locations
|
|
14
|
-
let scriptPath = resolve(__dirname, '../../scripts/publish-pet.ts')
|
|
15
|
-
if (!existsSync(scriptPath)) {
|
|
16
|
-
// We might be in a different location, try relative to cwd
|
|
17
|
-
scriptPath = resolve(process.cwd(), '../../scripts/publish-pet.ts')
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
if (!existsSync(scriptPath)) {
|
|
21
|
-
console.error(`❌ Publish script not found: ${scriptPath}`)
|
|
22
|
-
console.error(` Tried: ${resolve(__dirname, '../../scripts/publish-pet.ts')}`)
|
|
23
|
-
console.error(` And: ${resolve(process.cwd(), '../../scripts/publish-pet.ts')}`)
|
|
24
|
-
process.exit(1)
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// If no petName provided, try to infer from current directory
|
|
28
|
-
let finalPetName = petName
|
|
29
|
-
if (!finalPetName) {
|
|
30
|
-
const cwd = process.cwd()
|
|
31
|
-
const pkgPath = resolve(cwd, 'package.json')
|
|
32
|
-
|
|
33
|
-
if (existsSync(pkgPath)) {
|
|
34
|
-
try {
|
|
35
|
-
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'))
|
|
36
|
-
// Extract pet name from @openpets/maps -> maps
|
|
37
|
-
if (pkg.name && pkg.name.startsWith('@openpets/')) {
|
|
38
|
-
finalPetName = pkg.name.replace('@openpets/', '')
|
|
39
|
-
console.log(`📦 Detected pet: ${finalPetName}`)
|
|
40
|
-
}
|
|
41
|
-
} catch (e) {
|
|
42
|
-
// Ignore parse errors
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (!finalPetName) {
|
|
47
|
-
console.error('❌ Could not determine pet name. Run from pet directory or specify pet name.')
|
|
48
|
-
process.exit(1)
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const bunArgs = [scriptPath, finalPetName]
|
|
53
|
-
if (preview) bunArgs.push('--preview')
|
|
54
|
-
if (channel && channel !== 'latest') bunArgs.push('--channel', channel)
|
|
55
|
-
|
|
56
|
-
return new Promise<void>((resolve, reject) => {
|
|
57
|
-
const child = spawn('bun', bunArgs, {
|
|
58
|
-
stdio: 'inherit',
|
|
59
|
-
shell: true,
|
|
60
|
-
env: {
|
|
61
|
-
...process.env,
|
|
62
|
-
OPENPETS_PREVIEW: preview ? 'true' : 'false',
|
|
63
|
-
OPENPETS_CHANNEL: channel
|
|
64
|
-
}
|
|
65
|
-
})
|
|
66
|
-
|
|
67
|
-
child.on('error', reject)
|
|
68
|
-
child.on('exit', (code) => {
|
|
69
|
-
if (code !== 0) {
|
|
70
|
-
reject(new Error(`Publish exited with code ${code}`))
|
|
71
|
-
} else {
|
|
72
|
-
resolve()
|
|
73
|
-
}
|
|
74
|
-
})
|
|
75
|
-
})
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const args = process.argv.slice(2)
|
|
79
|
-
const command = args[0]
|
|
80
|
-
|
|
81
|
-
const DEBUG = process.env.PETS_DEBUG === 'true'
|
|
82
|
-
|
|
83
|
-
function log(...msgs: any[]) {
|
|
84
|
-
if (DEBUG) {
|
|
85
|
-
console.log('[PETS-CLI]', ...msgs)
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
function displayInstalledPlugins() {
|
|
90
|
-
const opencodeJsonPath = resolve(process.cwd(), 'opencode.json')
|
|
91
|
-
|
|
92
|
-
log('Looking for opencode.json at:', opencodeJsonPath)
|
|
93
|
-
|
|
94
|
-
if (!existsSync(opencodeJsonPath)) {
|
|
95
|
-
log('opencode.json not found')
|
|
96
|
-
return
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
try {
|
|
100
|
-
const content = readFileSync(opencodeJsonPath, 'utf-8')
|
|
101
|
-
log('opencode.json content length:', content.length)
|
|
102
|
-
|
|
103
|
-
const config = JSON.parse(content)
|
|
104
|
-
log('Parsed opencode.json config:', Object.keys(config))
|
|
105
|
-
|
|
106
|
-
if (config.plugin && Array.isArray(config.plugin) && config.plugin.length > 0) {
|
|
107
|
-
const plugins = config.plugin.filter((p: string) => typeof p === 'string' && p.trim())
|
|
108
|
-
log('Found plugins:', plugins)
|
|
109
|
-
|
|
110
|
-
if (plugins.length > 0) {
|
|
111
|
-
console.log('\x1b[36m%s\x1b[0m', '📦 Installed plugins:')
|
|
112
|
-
console.log('\x1b[2m%s\x1b[0m', ` ${plugins.join(', ')}`)
|
|
113
|
-
console.log('')
|
|
114
|
-
}
|
|
115
|
-
} else {
|
|
116
|
-
log('No plugins found in config')
|
|
117
|
-
}
|
|
118
|
-
} catch (error) {
|
|
119
|
-
log('Error reading opencode.json:', error)
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
function killPort(port: number) {
|
|
124
|
-
log(`Attempting to kill processes on port ${port}`)
|
|
125
|
-
try {
|
|
126
|
-
const { execSync } = require('child_process')
|
|
127
|
-
execSync(`lsof -ti:${port} | xargs kill -9 2>/dev/null || true`, { stdio: 'ignore' })
|
|
128
|
-
log(`Successfully killed processes on port ${port}`)
|
|
129
|
-
} catch (error) {
|
|
130
|
-
log(`No processes to kill on port ${port} or error occurred:`, error)
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
function launchManager() {
|
|
135
|
-
const startTime = Date.now()
|
|
136
|
-
const uiDir = resolve(__dirname, '../../apps/desktop')
|
|
137
|
-
const projectDir = process.cwd()
|
|
138
|
-
|
|
139
|
-
addFolderToHistory(projectDir)
|
|
140
|
-
|
|
141
|
-
console.log('Launching OpenPets Plugin Manager...')
|
|
142
|
-
console.log(`Project directory: ${projectDir}`)
|
|
143
|
-
console.log(`UI directory: ${uiDir}`)
|
|
144
|
-
|
|
145
|
-
log('Launch details:', {
|
|
146
|
-
__dirname,
|
|
147
|
-
uiDir,
|
|
148
|
-
projectDir,
|
|
149
|
-
uiDirExists: existsSync(uiDir),
|
|
150
|
-
timestamp: new Date().toISOString()
|
|
151
|
-
})
|
|
152
|
-
|
|
153
|
-
if (!existsSync(uiDir)) {
|
|
154
|
-
console.error(`❌ UI directory not found: ${uiDir}`)
|
|
155
|
-
log('Contents of parent directory:', require('fs').readdirSync(resolve(__dirname, '../../apps')))
|
|
156
|
-
process.exit(1)
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
log('Checking for package.json in UI directory')
|
|
160
|
-
const packageJsonPath = resolve(uiDir, 'package.json')
|
|
161
|
-
if (!existsSync(packageJsonPath)) {
|
|
162
|
-
console.error(`❌ package.json not found in UI directory: ${packageJsonPath}`)
|
|
163
|
-
process.exit(1)
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
killPort(1420)
|
|
167
|
-
|
|
168
|
-
log('Spawning npm process with tauri:dev')
|
|
169
|
-
const child = spawn('npm', ['run', 'tauri:dev'], {
|
|
170
|
-
cwd: uiDir,
|
|
171
|
-
stdio: 'inherit',
|
|
172
|
-
shell: true,
|
|
173
|
-
env: {
|
|
174
|
-
...process.env,
|
|
175
|
-
OPENPETS_PROJECT_DIR: projectDir,
|
|
176
|
-
PETS_DEBUG: DEBUG ? 'true' : 'false'
|
|
177
|
-
}
|
|
178
|
-
})
|
|
179
|
-
|
|
180
|
-
log('Child process spawned with PID:', child.pid)
|
|
181
|
-
|
|
182
|
-
child.on('error', (error) => {
|
|
183
|
-
console.error('Failed to launch manager:', error)
|
|
184
|
-
log('Error details:', {
|
|
185
|
-
message: error.message,
|
|
186
|
-
stack: error.stack,
|
|
187
|
-
elapsed: Date.now() - startTime
|
|
188
|
-
})
|
|
189
|
-
process.exit(1)
|
|
190
|
-
})
|
|
191
|
-
|
|
192
|
-
child.on('exit', (code) => {
|
|
193
|
-
const elapsed = Date.now() - startTime
|
|
194
|
-
log(`Manager process exited with code ${code} after ${elapsed}ms`)
|
|
195
|
-
if (code !== 0) {
|
|
196
|
-
console.error(`Manager exited with code ${code}`)
|
|
197
|
-
process.exit(code || 1)
|
|
198
|
-
}
|
|
199
|
-
})
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
log('=== PETS CLI STARTUP ===')
|
|
203
|
-
log('Command:', command)
|
|
204
|
-
log('Args:', args)
|
|
205
|
-
log('CWD:', process.cwd())
|
|
206
|
-
log('ENV.OPENPETS_PROJECT_DIR:', process.env.OPENPETS_PROJECT_DIR)
|
|
207
|
-
log('ENV.PETS_DEBUG:', process.env.PETS_DEBUG)
|
|
208
|
-
|
|
209
|
-
displayInstalledPlugins()
|
|
210
|
-
|
|
211
|
-
if (command === 'build') {
|
|
212
|
-
const petName = args[1]
|
|
213
|
-
log('Building pet:', petName)
|
|
214
|
-
buildPet(petName).catch(error => {
|
|
215
|
-
console.error('Error building pet:', error)
|
|
216
|
-
log('Build error details:', error)
|
|
217
|
-
process.exit(1)
|
|
218
|
-
})
|
|
219
|
-
} else if (command === 'deploy') {
|
|
220
|
-
const petName = args[1]
|
|
221
|
-
log('Deploying pet:', petName)
|
|
222
|
-
deployPet(petName).catch(error => {
|
|
223
|
-
console.error('Error deploying pet:', error)
|
|
224
|
-
log('Deploy error details:', error)
|
|
225
|
-
process.exit(1)
|
|
226
|
-
})
|
|
227
|
-
} else if (command === 'publish') {
|
|
228
|
-
const petName = args[1] && !args[1].startsWith('--') ? args[1] : undefined
|
|
229
|
-
const preview = args.includes('--preview')
|
|
230
|
-
const channelIndex = args.indexOf('--channel')
|
|
231
|
-
const channel = channelIndex >= 0 ? args[channelIndex + 1] : 'latest'
|
|
232
|
-
|
|
233
|
-
log('Publishing pet:', petName || '(auto-detect)', { preview, channel })
|
|
234
|
-
publishPet(petName, { preview, channel }).catch(error => {
|
|
235
|
-
console.error('Error publishing pet:', error)
|
|
236
|
-
log('Publish error details:', error)
|
|
237
|
-
process.exit(1)
|
|
238
|
-
})
|
|
239
|
-
} else if (!command) {
|
|
240
|
-
log('No command provided, launching manager UI')
|
|
241
|
-
launchManager()
|
|
242
|
-
} else {
|
|
243
|
-
log('Unknown command:', command)
|
|
244
|
-
console.error('Usage: pets [command] [options]')
|
|
245
|
-
console.error('')
|
|
246
|
-
console.error('Commands:')
|
|
247
|
-
console.error(' (none) Launch the plugin manager UI (default)')
|
|
248
|
-
console.error(' build <pet-name> Build and validate a pet package')
|
|
249
|
-
console.error(' deploy <pet-name> Build and deploy a pet package with metadata')
|
|
250
|
-
console.error(' publish [pet-name] Publish a pet package to npm (auto-detects if in pet dir)')
|
|
251
|
-
console.error('')
|
|
252
|
-
console.error('Publish Options:')
|
|
253
|
-
console.error(' --preview Dry-run mode (no actual publish)')
|
|
254
|
-
console.error(' --channel <name> Publish to a specific npm tag (default: latest)')
|
|
255
|
-
console.error('')
|
|
256
|
-
console.error('Examples:')
|
|
257
|
-
console.error(' pets # Launch the desktop plugin manager')
|
|
258
|
-
console.error(' pets build postgres')
|
|
259
|
-
console.error(' pets deploy maps')
|
|
260
|
-
console.error(' pets publish maps # From root directory')
|
|
261
|
-
console.error(' cd pets/maps && pets publish # From pet directory')
|
|
262
|
-
console.error(' pets publish --preview # Dry-run from pet directory')
|
|
263
|
-
console.error(' pets publish maps --channel beta')
|
|
264
|
-
console.error('')
|
|
265
|
-
console.error('Environment:')
|
|
266
|
-
console.error(' PETS_DEBUG=true Enable detailed debug logging')
|
|
267
|
-
process.exit(1)
|
|
268
|
-
}
|