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.
- 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 +7 -11
- package/ai-client-base/index.ts +0 -117
- package/build-pet.ts +0 -429
- package/cli.ts +0 -179
- 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 -309
- 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 -594
- /package/{logger.d.ts → dist/src/core/logger.d.ts} +0 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export interface AIImageResult {
|
|
2
|
+
success: boolean;
|
|
3
|
+
images?: Array<{
|
|
4
|
+
url: string;
|
|
5
|
+
width?: number;
|
|
6
|
+
height?: number;
|
|
7
|
+
}>;
|
|
8
|
+
error?: string;
|
|
9
|
+
metadata?: Record<string, any>;
|
|
10
|
+
requestId?: string;
|
|
11
|
+
credits?: Record<string, any>;
|
|
12
|
+
}
|
|
13
|
+
export interface AIVideoResult {
|
|
14
|
+
success: boolean;
|
|
15
|
+
videos?: Array<{
|
|
16
|
+
url: string;
|
|
17
|
+
duration?: number;
|
|
18
|
+
width?: number;
|
|
19
|
+
height?: number;
|
|
20
|
+
}>;
|
|
21
|
+
error?: string;
|
|
22
|
+
metadata?: Record<string, any>;
|
|
23
|
+
requestId?: string;
|
|
24
|
+
credits?: Record<string, any>;
|
|
25
|
+
}
|
|
26
|
+
export interface BaseAIClientConfig {
|
|
27
|
+
apiKey: string;
|
|
28
|
+
baseUrl?: string;
|
|
29
|
+
debug?: boolean;
|
|
30
|
+
}
|
|
31
|
+
export declare abstract class BaseAIClient {
|
|
32
|
+
protected apiKey: string;
|
|
33
|
+
protected baseUrl?: string;
|
|
34
|
+
protected debug: boolean;
|
|
35
|
+
constructor(config: BaseAIClientConfig);
|
|
36
|
+
abstract get providerName(): string;
|
|
37
|
+
protected log(message: string, level?: "info" | "warn" | "error" | "debug"): void;
|
|
38
|
+
protected ensureApiKey(envVarName: string): void;
|
|
39
|
+
protected downloadMedia(url: string, outputDir: string, prefix: string): Promise<string>;
|
|
40
|
+
protected openInDefaultViewer(filepath: string): Promise<void>;
|
|
41
|
+
protected getMimeType(filename: string): string;
|
|
42
|
+
protected downloadAndOpen<T extends AIImageResult | AIVideoResult>(result: T, mediaType: "image" | "video", fileExtension: string, openInViewer?: boolean): Promise<T & {
|
|
43
|
+
localPath?: string;
|
|
44
|
+
}>;
|
|
45
|
+
protected extractCreditsFromResponse(response: any): any;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../ai-client-base/index.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAA;IAChB,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAChE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;CAC9B;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAA;IAChB,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACnF,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;CAC9B;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED,8BAAsB,YAAY;IAChC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAA;IACxB,SAAS,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IAC1B,SAAS,CAAC,KAAK,EAAE,OAAO,CAAA;gBAEZ,MAAM,EAAE,kBAAkB;IAMtC,QAAQ,KAAK,YAAY,IAAI,MAAM,CAAA;IAEnC,SAAS,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,GAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAgB,GAAG,IAAI;IAqBzF,SAAS,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;cAMhC,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;cA6B9E,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBpE,SAAS,CAAC,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;cAgB/B,eAAe,CAAC,CAAC,SAAS,aAAa,GAAG,aAAa,EACrE,MAAM,EAAE,CAAC,EACT,SAAS,EAAE,OAAO,GAAG,OAAO,EAC5B,aAAa,EAAE,MAAM,EACrB,YAAY,GAAE,OAAc,GAC3B,OAAO,CAAC,CAAC,GAAG;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAsDtC,SAAS,CAAC,0BAA0B,CAAC,QAAQ,EAAE,GAAG,GAAG,GAAG;CA+BzD"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { createLogger } from "../logger";
|
|
2
|
+
import * as fs from "fs";
|
|
3
|
+
import * as path from "path";
|
|
4
|
+
import { exec } from "child_process";
|
|
5
|
+
import { promisify } from "util";
|
|
6
|
+
const execAsync = promisify(exec);
|
|
7
|
+
const logger = createLogger("base-ai-client");
|
|
8
|
+
export class BaseAIClient {
|
|
9
|
+
apiKey;
|
|
10
|
+
baseUrl;
|
|
11
|
+
debug;
|
|
12
|
+
constructor(config) {
|
|
13
|
+
this.apiKey = config.apiKey;
|
|
14
|
+
this.baseUrl = config.baseUrl;
|
|
15
|
+
this.debug = config.debug || false;
|
|
16
|
+
}
|
|
17
|
+
log(message, level = "info") {
|
|
18
|
+
if (!this.debug && level === "debug")
|
|
19
|
+
return;
|
|
20
|
+
const timestamp = new Date().toISOString();
|
|
21
|
+
const prefix = `[${this.providerName.toUpperCase()}] ${timestamp}`;
|
|
22
|
+
switch (level) {
|
|
23
|
+
case "error":
|
|
24
|
+
console.error(`${prefix} ERROR:`, message);
|
|
25
|
+
break;
|
|
26
|
+
case "warn":
|
|
27
|
+
console.warn(`${prefix} WARN:`, message);
|
|
28
|
+
break;
|
|
29
|
+
case "debug":
|
|
30
|
+
console.debug(`${prefix} DEBUG:`, message);
|
|
31
|
+
break;
|
|
32
|
+
default:
|
|
33
|
+
console.log(`${prefix} INFO:`, message);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
ensureApiKey(envVarName) {
|
|
37
|
+
if (!this.apiKey || this.apiKey.trim() === "") {
|
|
38
|
+
throw new Error(`${envVarName} environment variable is required but not set`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async downloadMedia(url, outputDir, prefix) {
|
|
42
|
+
try {
|
|
43
|
+
if (!fs.existsSync(outputDir)) {
|
|
44
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
45
|
+
}
|
|
46
|
+
const timestamp = Date.now();
|
|
47
|
+
const extension = url.includes('.mp4') || url.includes('video') ? 'mp4' : 'png';
|
|
48
|
+
const filename = `${prefix}-${timestamp}.${extension}`;
|
|
49
|
+
const filepath = path.join(outputDir, filename);
|
|
50
|
+
logger.info(`Downloading media from ${url}`);
|
|
51
|
+
const response = await fetch(url);
|
|
52
|
+
if (!response.ok) {
|
|
53
|
+
throw new Error(`Failed to download: ${response.statusText}`);
|
|
54
|
+
}
|
|
55
|
+
const buffer = await response.arrayBuffer();
|
|
56
|
+
fs.writeFileSync(filepath, Buffer.from(buffer));
|
|
57
|
+
logger.info(`Media saved to ${filepath}`);
|
|
58
|
+
return filepath;
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
logger.error(`Failed to download media: ${error.message}`);
|
|
62
|
+
throw error;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
async openInDefaultViewer(filepath) {
|
|
66
|
+
try {
|
|
67
|
+
const platform = process.platform;
|
|
68
|
+
let command;
|
|
69
|
+
if (platform === "darwin") {
|
|
70
|
+
command = `open "${filepath}"`;
|
|
71
|
+
}
|
|
72
|
+
else if (platform === "win32") {
|
|
73
|
+
command = `start "" "${filepath}"`;
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
command = `xdg-open "${filepath}"`;
|
|
77
|
+
}
|
|
78
|
+
await execAsync(command);
|
|
79
|
+
logger.info(`Opened ${filepath} in default viewer`);
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
logger.warn(`Failed to open in viewer: ${error.message}`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
getMimeType(filename) {
|
|
86
|
+
const ext = path.extname(filename).toLowerCase();
|
|
87
|
+
const mimeTypes = {
|
|
88
|
+
'.jpg': 'image/jpeg',
|
|
89
|
+
'.jpeg': 'image/jpeg',
|
|
90
|
+
'.png': 'image/png',
|
|
91
|
+
'.gif': 'image/gif',
|
|
92
|
+
'.webp': 'image/webp',
|
|
93
|
+
'.mp4': 'video/mp4',
|
|
94
|
+
'.mov': 'video/quicktime',
|
|
95
|
+
'.avi': 'video/x-msvideo',
|
|
96
|
+
'.webm': 'video/webm'
|
|
97
|
+
};
|
|
98
|
+
return mimeTypes[ext] || 'application/octet-stream';
|
|
99
|
+
}
|
|
100
|
+
async downloadAndOpen(result, mediaType, fileExtension, openInViewer = true) {
|
|
101
|
+
if (!result.success) {
|
|
102
|
+
return result;
|
|
103
|
+
}
|
|
104
|
+
const mediaArray = mediaType === "image"
|
|
105
|
+
? result.images
|
|
106
|
+
: result.videos;
|
|
107
|
+
if (!mediaArray || mediaArray.length === 0) {
|
|
108
|
+
return result;
|
|
109
|
+
}
|
|
110
|
+
try {
|
|
111
|
+
const downloadsDir = path.join(process.cwd(), "output");
|
|
112
|
+
if (!fs.existsSync(downloadsDir)) {
|
|
113
|
+
fs.mkdirSync(downloadsDir, { recursive: true });
|
|
114
|
+
}
|
|
115
|
+
const timestamp = Date.now();
|
|
116
|
+
const filename = `${this.providerName}-${mediaType}-${timestamp}.${fileExtension}`;
|
|
117
|
+
const localPath = path.join(downloadsDir, filename);
|
|
118
|
+
const response = await fetch(mediaArray[0].url);
|
|
119
|
+
if (!response.ok) {
|
|
120
|
+
throw new Error(`Failed to download: ${response.statusText}`);
|
|
121
|
+
}
|
|
122
|
+
const buffer = await response.arrayBuffer();
|
|
123
|
+
fs.writeFileSync(localPath, Buffer.from(buffer));
|
|
124
|
+
logger.info(`${mediaType} saved to ${localPath}`);
|
|
125
|
+
if (openInViewer) {
|
|
126
|
+
await this.openInDefaultViewer(localPath);
|
|
127
|
+
}
|
|
128
|
+
return {
|
|
129
|
+
...result,
|
|
130
|
+
localPath
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
this.log(`${mediaType.charAt(0).toUpperCase() + mediaType.slice(1)} generated successfully but post-processing failed: ${error.message}`, "error");
|
|
135
|
+
return {
|
|
136
|
+
...result,
|
|
137
|
+
localPath: undefined
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
extractCreditsFromResponse(response) {
|
|
142
|
+
const credits = {};
|
|
143
|
+
if (response?.credits !== undefined) {
|
|
144
|
+
credits.balance = response.credits.balance;
|
|
145
|
+
credits.cost = response.credits.cost;
|
|
146
|
+
credits.currency = response.credits.currency;
|
|
147
|
+
credits.remaining = response.credits.remaining;
|
|
148
|
+
credits.limit = response.credits.limit;
|
|
149
|
+
credits.used = response.credits.used;
|
|
150
|
+
}
|
|
151
|
+
if (response?.billing !== undefined) {
|
|
152
|
+
credits.balance = response.billing.balance;
|
|
153
|
+
credits.cost = response.billing.cost;
|
|
154
|
+
credits.currency = response.billing.currency;
|
|
155
|
+
credits.remaining = response.billing.remaining;
|
|
156
|
+
}
|
|
157
|
+
if (response?.usage !== undefined) {
|
|
158
|
+
credits.used = response.usage.total_tokens || response.usage.used;
|
|
159
|
+
credits.limit = response.usage.limit;
|
|
160
|
+
credits.remaining = response.usage.remaining;
|
|
161
|
+
}
|
|
162
|
+
if (Object.keys(credits).length === 0) {
|
|
163
|
+
return undefined;
|
|
164
|
+
}
|
|
165
|
+
return credits;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../ai-client-base/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser-safe exports from openpets
|
|
3
|
+
*
|
|
4
|
+
* This module only exports code that doesn't use Node.js APIs like fs, path, etc.
|
|
5
|
+
* Use this entry point when importing from browser/frontend code.
|
|
6
|
+
*/
|
|
7
|
+
export * from './types';
|
|
8
|
+
export * from './search-pets';
|
|
9
|
+
export * from './schema-helpers';
|
|
10
|
+
//# sourceMappingURL=browser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../../browser.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,SAAS,CAAA;AACvB,cAAc,eAAe,CAAA;AAC7B,cAAc,kBAAkB,CAAA"}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* This module only exports code that doesn't use Node.js APIs like fs, path, etc.
|
|
5
5
|
* Use this entry point when importing from browser/frontend code.
|
|
6
6
|
*/
|
|
7
|
-
|
|
8
|
-
export * from './
|
|
9
|
-
export * from './
|
|
10
|
-
|
|
7
|
+
export * from './types';
|
|
8
|
+
export * from './search-pets';
|
|
9
|
+
export * from './schema-helpers';
|
|
10
|
+
//# sourceMappingURL=browser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser.js","sourceRoot":"","sources":["../../../browser.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,SAAS,CAAA;AACvB,cAAc,eAAe,CAAA;AAC7B,cAAc,kBAAkB,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-pet.d.ts","sourceRoot":"","sources":["../../../build-pet.ts"],"names":[],"mappings":"AAmQA,wBAAsB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAyK9D"}
|
|
@@ -0,0 +1,364 @@
|
|
|
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
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
+
const __dirname = dirname(__filename);
|
|
8
|
+
const projectRoot = dirname(dirname(__dirname));
|
|
9
|
+
const DEBUG = process.env.PETS_DEBUG === 'true';
|
|
10
|
+
function debug(...msgs) {
|
|
11
|
+
if (DEBUG) {
|
|
12
|
+
console.log('[BUILD-PET]', ...msgs);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
async function extractToolsFromIndexFile(indexPath) {
|
|
16
|
+
debug('=== EXTRACTING TOOLS FROM INDEX FILE ===');
|
|
17
|
+
debug('Index path:', indexPath);
|
|
18
|
+
debug('File exists:', existsSync(indexPath));
|
|
19
|
+
try {
|
|
20
|
+
const indexUrl = pathToFileURL(indexPath).href;
|
|
21
|
+
debug('Index URL:', indexUrl);
|
|
22
|
+
debug('Attempting dynamic import...');
|
|
23
|
+
const indexModule = await import(/* @vite-ignore */ indexUrl);
|
|
24
|
+
debug('Import successful');
|
|
25
|
+
debug('Module keys:', Object.keys(indexModule));
|
|
26
|
+
if (indexModule.toolsMetadata && Array.isArray(indexModule.toolsMetadata)) {
|
|
27
|
+
console.log(` Found ${indexModule.toolsMetadata.length} tools from exported toolsMetadata`);
|
|
28
|
+
debug('Tools metadata:', JSON.stringify(indexModule.toolsMetadata, null, 2));
|
|
29
|
+
return indexModule.toolsMetadata;
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
debug('toolsMetadata not found or not an array');
|
|
33
|
+
debug('indexModule.toolsMetadata:', indexModule.toolsMetadata);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
console.warn(` ⚠️ Could not import toolsMetadata, falling back to file parsing`);
|
|
38
|
+
console.warn(` Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
39
|
+
debug('Import error details:', {
|
|
40
|
+
name: error instanceof Error ? error.name : 'Unknown',
|
|
41
|
+
message: error instanceof Error ? error.message : String(error),
|
|
42
|
+
stack: error instanceof Error ? error.stack : 'No stack trace'
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
debug('Falling back to file parsing');
|
|
46
|
+
return extractToolsFromIndexFileByParsing(indexPath);
|
|
47
|
+
}
|
|
48
|
+
function extractToolsFromIndexFileByParsing(indexPath) {
|
|
49
|
+
const content = readFileSync(indexPath, 'utf8');
|
|
50
|
+
const toolsMatch = content.match(/const\s+tools:\s*ToolDefinition\[\]\s*=\s*\[([\s\S]*?)\n\s*\]/m);
|
|
51
|
+
if (!toolsMatch) {
|
|
52
|
+
console.warn('⚠️ Could not find tools array in index.ts');
|
|
53
|
+
return [];
|
|
54
|
+
}
|
|
55
|
+
const toolsArray = toolsMatch[1];
|
|
56
|
+
const toolNames = [];
|
|
57
|
+
const toolsSeparated = toolsArray.split(/\n\s*\{/).filter(part => part.includes('name:'));
|
|
58
|
+
const toolBlocks = toolsSeparated.map((part, idx) => {
|
|
59
|
+
if (idx === 0)
|
|
60
|
+
return part;
|
|
61
|
+
return '{' + part;
|
|
62
|
+
});
|
|
63
|
+
for (const block of toolBlocks) {
|
|
64
|
+
const nameMatch = block.match(/name:\s*["']([^"']+)["']/);
|
|
65
|
+
const descMatch = block.match(/description:\s*["']([^"']+)["']/);
|
|
66
|
+
const schemaMatch = block.match(/schema:\s*z\.object\(\{([\s\S]*?)\}\),?\s*(?:async\s+execute|$)/);
|
|
67
|
+
if (nameMatch && descMatch) {
|
|
68
|
+
let schemaProperties = {};
|
|
69
|
+
if (schemaMatch) {
|
|
70
|
+
const schemaContent = schemaMatch[1];
|
|
71
|
+
const lines = schemaContent.split('\n').filter(l => l.trim() && !l.trim().startsWith('//'));
|
|
72
|
+
for (const line of lines) {
|
|
73
|
+
const propMatch = line.match(/^\s*(\w+):\s*z\.(.+?),?\s*$/);
|
|
74
|
+
if (!propMatch)
|
|
75
|
+
continue;
|
|
76
|
+
const [, propName, zodDef] = propMatch;
|
|
77
|
+
let propSchema = {};
|
|
78
|
+
if (zodDef.includes('string(')) {
|
|
79
|
+
propSchema.type = 'string';
|
|
80
|
+
}
|
|
81
|
+
else if (zodDef.includes('number(')) {
|
|
82
|
+
propSchema.type = 'number';
|
|
83
|
+
const minMatch = zodDef.match(/\.min\((\d+)\)/);
|
|
84
|
+
const maxMatch = zodDef.match(/\.max\((\d+)\)/);
|
|
85
|
+
if (minMatch)
|
|
86
|
+
propSchema.minimum = parseInt(minMatch[1]);
|
|
87
|
+
if (maxMatch)
|
|
88
|
+
propSchema.maximum = parseInt(maxMatch[1]);
|
|
89
|
+
}
|
|
90
|
+
else if (zodDef.includes('boolean(')) {
|
|
91
|
+
propSchema.type = 'boolean';
|
|
92
|
+
}
|
|
93
|
+
else if (zodDef.includes('enum(')) {
|
|
94
|
+
propSchema.type = 'string';
|
|
95
|
+
const enumMatch = zodDef.match(/enum\(\[([^\]]+)\]\)/);
|
|
96
|
+
if (enumMatch) {
|
|
97
|
+
const enumValues = enumMatch[1].match(/["']([^"']+)["']/g)?.map(v => v.replace(/["']/g, ''));
|
|
98
|
+
if (enumValues)
|
|
99
|
+
propSchema.enum = enumValues;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
else if (zodDef.includes('array(')) {
|
|
103
|
+
propSchema.type = 'array';
|
|
104
|
+
const arrayTypeMatch = zodDef.match(/array\(z\.(\w+)\(\)\)/);
|
|
105
|
+
if (arrayTypeMatch) {
|
|
106
|
+
propSchema.items = { type: arrayTypeMatch[1].toLowerCase() };
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
if (zodDef.includes('.optional()')) {
|
|
110
|
+
propSchema.optional = true;
|
|
111
|
+
}
|
|
112
|
+
const descMatch = zodDef.match(/\.describe\(["']([^"']+)["']\)/);
|
|
113
|
+
if (descMatch) {
|
|
114
|
+
propSchema.description = descMatch[1];
|
|
115
|
+
}
|
|
116
|
+
schemaProperties[propName] = propSchema;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
toolNames.push({
|
|
120
|
+
name: nameMatch[1],
|
|
121
|
+
description: descMatch[1],
|
|
122
|
+
schema: {
|
|
123
|
+
type: 'object',
|
|
124
|
+
properties: schemaProperties
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
console.log(` Found ${toolNames.length} tools in index.ts`);
|
|
130
|
+
return toolNames;
|
|
131
|
+
}
|
|
132
|
+
function formatZodSchema(schema, depth = 0) {
|
|
133
|
+
if (!schema || !schema._def) {
|
|
134
|
+
return { type: 'object', properties: {} };
|
|
135
|
+
}
|
|
136
|
+
const def = schema._def;
|
|
137
|
+
const zodType = def.typeName || def.type || schema.constructor?.name || 'unknown';
|
|
138
|
+
if (zodType === 'ZodObject' || zodType === 'object') {
|
|
139
|
+
const properties = {};
|
|
140
|
+
const shapeObj = typeof def.shape === 'function' ? def.shape() : def.shape || {};
|
|
141
|
+
for (const [key, value] of Object.entries(shapeObj)) {
|
|
142
|
+
properties[key] = formatZodSchema(value, depth + 1);
|
|
143
|
+
}
|
|
144
|
+
return {
|
|
145
|
+
type: 'object',
|
|
146
|
+
properties
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
if (zodType === 'ZodString' || zodType === 'string') {
|
|
150
|
+
return { type: 'string' };
|
|
151
|
+
}
|
|
152
|
+
if (zodType === 'ZodNumber' || zodType === 'number') {
|
|
153
|
+
const result = { type: 'number' };
|
|
154
|
+
if (def.checks) {
|
|
155
|
+
for (const check of def.checks) {
|
|
156
|
+
if (check.kind === 'min')
|
|
157
|
+
result.minimum = check.value;
|
|
158
|
+
if (check.kind === 'max')
|
|
159
|
+
result.maximum = check.value;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return result;
|
|
163
|
+
}
|
|
164
|
+
if (zodType === 'ZodBoolean' || zodType === 'boolean') {
|
|
165
|
+
return { type: 'boolean' };
|
|
166
|
+
}
|
|
167
|
+
if (zodType === 'ZodArray' || zodType === 'array') {
|
|
168
|
+
return {
|
|
169
|
+
type: 'array',
|
|
170
|
+
items: formatZodSchema(def.type, depth + 1)
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
if (zodType === 'ZodEnum' || zodType === 'enum') {
|
|
174
|
+
let values = def.values;
|
|
175
|
+
if (!values && schema._def?.values) {
|
|
176
|
+
values = schema._def.values;
|
|
177
|
+
}
|
|
178
|
+
if (!values && schema.options) {
|
|
179
|
+
values = schema.options;
|
|
180
|
+
}
|
|
181
|
+
const enumArray = Array.isArray(values) ? values : Object.values(values || {});
|
|
182
|
+
return {
|
|
183
|
+
type: 'string',
|
|
184
|
+
enum: enumArray
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
if (zodType === 'ZodOptional' || zodType === 'optional') {
|
|
188
|
+
return {
|
|
189
|
+
...formatZodSchema(def.innerType, depth + 1),
|
|
190
|
+
optional: true
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
return { type: zodType };
|
|
194
|
+
}
|
|
195
|
+
function generateToolsMetadata(tools) {
|
|
196
|
+
return tools.map(tool => ({
|
|
197
|
+
name: tool.name,
|
|
198
|
+
description: tool.description,
|
|
199
|
+
schema: tool.schema._def ? formatZodSchema(tool.schema) : tool.schema
|
|
200
|
+
}));
|
|
201
|
+
}
|
|
202
|
+
function generateScriptsFromTools(tools, petName) {
|
|
203
|
+
const scripts = {
|
|
204
|
+
build: 'pets build',
|
|
205
|
+
'build:tsc': 'tsc',
|
|
206
|
+
quickstart: `opencode run "list available ${petName} commands"`,
|
|
207
|
+
};
|
|
208
|
+
for (const tool of tools) {
|
|
209
|
+
let scriptName = tool.name;
|
|
210
|
+
if (scriptName.startsWith(`${petName}-`)) {
|
|
211
|
+
scriptName = scriptName.replace(new RegExp(`^${petName}-`), 'test:');
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
scriptName = `test:${scriptName}`;
|
|
215
|
+
}
|
|
216
|
+
const command = `opencode run "${tool.description}"`;
|
|
217
|
+
scripts[scriptName] = command;
|
|
218
|
+
}
|
|
219
|
+
scripts['test:all'] = 'echo "Run individual test scripts to test specific tools"';
|
|
220
|
+
return scripts;
|
|
221
|
+
}
|
|
222
|
+
export async function buildPet(petName) {
|
|
223
|
+
debug('=== BUILD PET STARTING ===');
|
|
224
|
+
debug('Initial petName:', petName);
|
|
225
|
+
debug('CWD:', process.cwd());
|
|
226
|
+
debug('Project root:', projectRoot);
|
|
227
|
+
if (!petName) {
|
|
228
|
+
const cwd = process.cwd();
|
|
229
|
+
const petsDir = join(projectRoot, 'pets');
|
|
230
|
+
debug('Auto-detecting pet from CWD:', cwd);
|
|
231
|
+
debug('Pets directory:', petsDir);
|
|
232
|
+
if (cwd.includes('/pets/')) {
|
|
233
|
+
petName = cwd.split('/pets/')[1].split('/')[0];
|
|
234
|
+
console.log(`📦 Auto-detected pet: ${petName}`);
|
|
235
|
+
debug('Auto-detected pet:', petName);
|
|
236
|
+
}
|
|
237
|
+
if (!petName) {
|
|
238
|
+
console.error('Usage: pets build <pet-name>');
|
|
239
|
+
console.error('Example: pets build postgres');
|
|
240
|
+
console.error('');
|
|
241
|
+
console.error('Available pets:');
|
|
242
|
+
if (existsSync(petsDir)) {
|
|
243
|
+
const pets = readdirSync(petsDir).filter(dir => {
|
|
244
|
+
const petPath = join(petsDir, dir);
|
|
245
|
+
return statSync(petPath).isDirectory() && dir !== '_TEMPLATE_';
|
|
246
|
+
});
|
|
247
|
+
pets.forEach(pet => console.error(` - ${pet}`));
|
|
248
|
+
debug('Available pets:', pets);
|
|
249
|
+
}
|
|
250
|
+
else {
|
|
251
|
+
debug('Pets directory does not exist:', petsDir);
|
|
252
|
+
}
|
|
253
|
+
process.exit(1);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
const petDir = join(projectRoot, 'pets', petName);
|
|
257
|
+
const packageJsonPath = join(petDir, 'package.json');
|
|
258
|
+
const indexPath = join(petDir, 'index.ts');
|
|
259
|
+
debug('Pet directory:', petDir);
|
|
260
|
+
debug('Package.json path:', packageJsonPath);
|
|
261
|
+
debug('Index.ts path:', indexPath);
|
|
262
|
+
if (!existsSync(petDir)) {
|
|
263
|
+
console.error(`❌ Pet '${petName}' not found in pets/ directory`);
|
|
264
|
+
debug('Pet directory does not exist:', petDir);
|
|
265
|
+
process.exit(1);
|
|
266
|
+
}
|
|
267
|
+
if (!existsSync(packageJsonPath)) {
|
|
268
|
+
console.error(`❌ package.json not found for pet '${petName}'`);
|
|
269
|
+
debug('Package.json does not exist:', packageJsonPath);
|
|
270
|
+
process.exit(1);
|
|
271
|
+
}
|
|
272
|
+
if (!existsSync(indexPath)) {
|
|
273
|
+
console.error(`❌ index.ts not found for pet '${petName}'`);
|
|
274
|
+
debug('Index.ts does not exist:', indexPath);
|
|
275
|
+
process.exit(1);
|
|
276
|
+
}
|
|
277
|
+
console.log(`🔨 Building ${petName}...`);
|
|
278
|
+
debug('All required files found, proceeding with build');
|
|
279
|
+
const packageJsonContent = readFileSync(packageJsonPath, 'utf8');
|
|
280
|
+
debug('Package.json content length:', packageJsonContent.length);
|
|
281
|
+
const packageJson = JSON.parse(packageJsonContent);
|
|
282
|
+
debug('Package.json parsed successfully');
|
|
283
|
+
debug('Package name:', packageJson.name);
|
|
284
|
+
debug('Package version:', packageJson.version);
|
|
285
|
+
// Auto-generate repository field if missing
|
|
286
|
+
if (!packageJson.repository) {
|
|
287
|
+
packageJson.repository = {
|
|
288
|
+
type: 'git',
|
|
289
|
+
url: `https://github.com/raggle-ai/pets/pets/${petName}`
|
|
290
|
+
};
|
|
291
|
+
debug('Auto-generated repository field:', packageJson.repository.url);
|
|
292
|
+
}
|
|
293
|
+
console.log(` Name: ${packageJson.name}`);
|
|
294
|
+
console.log(` Version: ${packageJson.version}`);
|
|
295
|
+
console.log(` Description: ${packageJson.description || 'No description'}`);
|
|
296
|
+
console.log(`\n🔍 Validating plugin structure...`);
|
|
297
|
+
const validator = new PluginValidator();
|
|
298
|
+
const validation = validator.validatePlugin(petDir);
|
|
299
|
+
if (validation.result.errors.length > 0) {
|
|
300
|
+
console.log(`\n❌ Validation failed with ${validation.result.errors.length} error(s):`);
|
|
301
|
+
validation.result.errors.forEach(error => {
|
|
302
|
+
console.log(` ❌ ${error}`);
|
|
303
|
+
});
|
|
304
|
+
console.log(`\n💥 Build aborted due to validation errors.`);
|
|
305
|
+
process.exit(1);
|
|
306
|
+
}
|
|
307
|
+
if (validation.result.warnings.length > 0) {
|
|
308
|
+
console.log(`\n⚠️ Found ${validation.result.warnings.length} warning(s):`);
|
|
309
|
+
validation.result.warnings.forEach(warning => {
|
|
310
|
+
console.log(` ⚠️ ${warning}`);
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
if (validation.result.codePatternWarnings && validation.result.codePatternWarnings.length > 0) {
|
|
314
|
+
console.log(`\n📋 Code pattern analysis:`);
|
|
315
|
+
validation.result.codePatternWarnings.forEach(warning => {
|
|
316
|
+
console.log(` ${warning}`);
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
if (validation.result.errors.length === 0 && validation.result.warnings.length === 0 && (!validation.result.codePatternWarnings || validation.result.codePatternWarnings.length === 0)) {
|
|
320
|
+
console.log(` ✓ All validation checks passed`);
|
|
321
|
+
}
|
|
322
|
+
debug('Extracting tools from index file...');
|
|
323
|
+
const tools = await extractToolsFromIndexFile(indexPath);
|
|
324
|
+
debug(`Extracted ${tools.length} tools`);
|
|
325
|
+
if (tools.length > 0) {
|
|
326
|
+
console.log(`\n📝 Generating scripts and metadata for ${tools.length} tools...`);
|
|
327
|
+
debug('Tools extracted:', tools.map(t => t.name));
|
|
328
|
+
const scripts = generateScriptsFromTools(tools, petName);
|
|
329
|
+
debug('Generated scripts:', Object.keys(scripts));
|
|
330
|
+
const toolsMetadata = generateToolsMetadata(tools);
|
|
331
|
+
debug('Generated tools metadata count:', toolsMetadata.length);
|
|
332
|
+
packageJson.scripts = scripts;
|
|
333
|
+
delete packageJson.tools;
|
|
334
|
+
const commandsJsonPath = join(petDir, 'commands.json');
|
|
335
|
+
debug('Commands.json path:', commandsJsonPath);
|
|
336
|
+
const commandsData = {
|
|
337
|
+
name: packageJson.name,
|
|
338
|
+
version: packageJson.version,
|
|
339
|
+
description: packageJson.description,
|
|
340
|
+
tools: toolsMetadata,
|
|
341
|
+
generatedAt: new Date().toISOString()
|
|
342
|
+
};
|
|
343
|
+
debug('Writing package.json...');
|
|
344
|
+
writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\n', 'utf8');
|
|
345
|
+
debug('Package.json written successfully');
|
|
346
|
+
debug('Writing commands.json...');
|
|
347
|
+
writeFileSync(commandsJsonPath, JSON.stringify(commandsData, null, 2) + '\n', 'utf8');
|
|
348
|
+
debug('Commands.json written successfully');
|
|
349
|
+
console.log(` ✓ Updated package.json with ${Object.keys(scripts).length} scripts`);
|
|
350
|
+
console.log(` ✓ Generated commands.json with ${tools.length} tools`);
|
|
351
|
+
console.log(`\n🔧 Generated test scripts:`);
|
|
352
|
+
Object.entries(scripts).forEach(([name, cmd]) => {
|
|
353
|
+
if (name.startsWith('test:')) {
|
|
354
|
+
console.log(` - npm run ${name}`);
|
|
355
|
+
}
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
else {
|
|
359
|
+
debug('No tools found in index file');
|
|
360
|
+
}
|
|
361
|
+
console.log(`\n✅ ${petName} built successfully!`);
|
|
362
|
+
debug('=== BUILD COMPLETE ===');
|
|
363
|
+
}
|
|
364
|
+
//# sourceMappingURL=build-pet.js.map
|