openpets 1.0.11 → 1.0.12
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 +3758 -7222
- package/dist/src/core/build-pet.d.ts.map +1 -1
- package/dist/src/core/build-pet.js +7 -0
- package/dist/src/core/build-pet.js.map +1 -1
- package/dist/src/core/cli.js +456 -130
- package/dist/src/core/cli.js.map +1 -1
- package/dist/src/core/ensure-npmignore.d.ts +30 -0
- package/dist/src/core/ensure-npmignore.d.ts.map +1 -0
- package/dist/src/core/ensure-npmignore.js +121 -0
- package/dist/src/core/ensure-npmignore.js.map +1 -0
- package/dist/src/core/index.d.ts +6 -3
- package/dist/src/core/index.d.ts.map +1 -1
- package/dist/src/core/index.js +9 -3
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/core/mcp-generator.d.ts +56 -0
- package/dist/src/core/mcp-generator.d.ts.map +1 -0
- package/dist/src/core/mcp-generator.js +1438 -0
- package/dist/src/core/mcp-generator.js.map +1 -0
- package/dist/src/core/mcp-server.js +0 -0
- package/dist/src/core/openapi-generator.d.ts +59 -0
- package/dist/src/core/openapi-generator.d.ts.map +1 -0
- package/dist/src/core/openapi-generator.js +800 -0
- package/dist/src/core/openapi-generator.js.map +1 -0
- package/dist/src/core/pet-config.d.ts +107 -49
- package/dist/src/core/pet-config.d.ts.map +1 -1
- package/dist/src/core/pet-config.js +6 -4
- package/dist/src/core/pet-config.js.map +1 -1
- package/dist/src/core/pet-downloader.d.ts +16 -0
- package/dist/src/core/pet-downloader.d.ts.map +1 -1
- package/dist/src/core/pet-downloader.js +145 -3
- package/dist/src/core/pet-downloader.js.map +1 -1
- package/dist/src/core/publish-pet.d.ts +29 -0
- package/dist/src/core/publish-pet.d.ts.map +1 -0
- package/dist/src/core/publish-pet.js +372 -0
- package/dist/src/core/publish-pet.js.map +1 -0
- package/dist/src/core/sdk-generator.d.ts +92 -0
- package/dist/src/core/sdk-generator.d.ts.map +1 -0
- package/dist/src/core/sdk-generator.js +567 -0
- package/dist/src/core/sdk-generator.js.map +1 -0
- package/dist/src/core/search-pets.d.ts +5 -0
- package/dist/src/core/search-pets.d.ts.map +1 -1
- package/dist/src/core/search-pets.js +43 -0
- package/dist/src/core/search-pets.js.map +1 -1
- package/dist/src/core/security-scanner.d.ts +49 -0
- package/dist/src/core/security-scanner.d.ts.map +1 -0
- package/dist/src/core/security-scanner.js +255 -0
- package/dist/src/core/security-scanner.js.map +1 -0
- package/dist/src/core/tool-lister.d.ts +61 -0
- package/dist/src/core/tool-lister.d.ts.map +1 -0
- package/dist/src/core/tool-lister.js +333 -0
- package/dist/src/core/tool-lister.js.map +1 -0
- package/dist/src/core/validate-pet.d.ts +2 -0
- package/dist/src/core/validate-pet.d.ts.map +1 -1
- package/dist/src/core/validate-pet.js +93 -1
- package/dist/src/core/validate-pet.js.map +1 -1
- package/dist/src/sdk/plugin-factory.d.ts +86 -0
- package/dist/src/sdk/plugin-factory.d.ts.map +1 -1
- package/dist/src/sdk/plugin-factory.js +450 -53
- package/dist/src/sdk/plugin-factory.js.map +1 -1
- package/dist/src/sdk/prompts-manager.d.ts +6 -0
- package/dist/src/sdk/prompts-manager.d.ts.map +1 -0
- package/dist/src/sdk/prompts-manager.js +162 -0
- package/dist/src/sdk/prompts-manager.js.map +1 -0
- package/package.json +1 -1
- package/dist/src/core/local-cache.d.ts +0 -69
- package/dist/src/core/local-cache.d.ts.map +0 -1
- package/dist/src/core/local-cache.js +0 -212
- package/dist/src/core/local-cache.js.map +0 -1
- package/dist/src/core/plugin-factory.d.ts +0 -58
- package/dist/src/core/plugin-factory.d.ts.map +0 -1
- package/dist/src/core/plugin-factory.js +0 -212
- package/dist/src/core/plugin-factory.js.map +0 -1
|
@@ -0,0 +1,567 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SDK Tool Generator
|
|
3
|
+
*
|
|
4
|
+
* Generates OpenPets-compatible tool definitions from TypeScript SDK packages.
|
|
5
|
+
* Similar to how hey-api generates TypeScript clients from OpenAPI specs.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* pets generate-sdk # Run from inside a pet directory with sdkGenerator in package.json
|
|
9
|
+
* pets generate-sdk --output client.ts # Custom output file
|
|
10
|
+
*
|
|
11
|
+
* This tool:
|
|
12
|
+
* 1. Reads SDK configuration from package.json
|
|
13
|
+
* 2. Generates OpenPets-compatible ToolDefinition[] exports
|
|
14
|
+
* 3. Creates a client.ts file that wraps the SDK methods as tools
|
|
15
|
+
*/
|
|
16
|
+
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
17
|
+
import { resolve, basename } from "path";
|
|
18
|
+
import { config as loadDotenv } from "dotenv";
|
|
19
|
+
import { createLogger } from "./logger";
|
|
20
|
+
const logger = createLogger("sdk-generator");
|
|
21
|
+
/**
|
|
22
|
+
* Load SDK configuration from package.json
|
|
23
|
+
*/
|
|
24
|
+
function loadSDKConfigFromPackageJson(dir) {
|
|
25
|
+
const packageJsonPath = resolve(dir, "package.json");
|
|
26
|
+
if (!existsSync(packageJsonPath)) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
try {
|
|
30
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
31
|
+
// Check for explicit sdkGenerator config
|
|
32
|
+
if (packageJson.sdkGenerator) {
|
|
33
|
+
const petName = packageJson.name?.replace(/^@openpets\//, "") || basename(dir);
|
|
34
|
+
return {
|
|
35
|
+
config: packageJson.sdkGenerator,
|
|
36
|
+
petName,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
// Check for sdk-config.json in the pet directory
|
|
40
|
+
const sdkConfigPath = resolve(dir, "sdk-config.json");
|
|
41
|
+
if (existsSync(sdkConfigPath)) {
|
|
42
|
+
const sdkConfig = JSON.parse(readFileSync(sdkConfigPath, "utf-8"));
|
|
43
|
+
const petName = packageJson.name?.replace(/^@openpets\//, "") || basename(dir);
|
|
44
|
+
return {
|
|
45
|
+
config: sdkConfig,
|
|
46
|
+
petName,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
// Try to infer from dependencies (for known SDKs)
|
|
50
|
+
const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
|
|
51
|
+
const petName = packageJson.name?.replace(/^@openpets\//, "") || basename(dir);
|
|
52
|
+
// Check for @polar-sh/sdk
|
|
53
|
+
if (deps["@polar-sh/sdk"]) {
|
|
54
|
+
return {
|
|
55
|
+
config: createPolarSDKConfig(),
|
|
56
|
+
petName,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
// Check for other known SDKs - add more patterns here
|
|
60
|
+
for (const [pkg] of Object.entries(deps)) {
|
|
61
|
+
if (pkg.includes("/sdk") || pkg.endsWith("-sdk")) {
|
|
62
|
+
logger.debug(`Found potential SDK package: ${pkg}`);
|
|
63
|
+
// Return null to indicate manual config needed
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
logger.error(`Error reading package.json: ${error.message}`);
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Built-in Polar SDK configuration
|
|
76
|
+
*/
|
|
77
|
+
function createPolarSDKConfig() {
|
|
78
|
+
return {
|
|
79
|
+
sdkPackage: "@polar-sh/sdk",
|
|
80
|
+
petName: "polar",
|
|
81
|
+
mainClassName: "Polar",
|
|
82
|
+
tokenEnvVar: "POLAR_TOKEN",
|
|
83
|
+
orgIdEnvVar: "POLAR_ORG_ID",
|
|
84
|
+
description: "Polar SDK for payments, subscriptions, and monetization",
|
|
85
|
+
namespaces: [
|
|
86
|
+
{
|
|
87
|
+
name: "organizations",
|
|
88
|
+
methods: ["list", "get", "create", "update"],
|
|
89
|
+
readOnlyMethods: ["list", "get"]
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
name: "products",
|
|
93
|
+
methods: ["list", "get", "create", "update", "updateBenefits"],
|
|
94
|
+
readOnlyMethods: ["list", "get"]
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
name: "customers",
|
|
98
|
+
methods: ["list", "get", "create", "update", "delete", "getExternal", "updateExternal", "deleteExternal", "getState", "getStateExternal"],
|
|
99
|
+
readOnlyMethods: ["list", "get", "getExternal", "getState", "getStateExternal"]
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
name: "orders",
|
|
103
|
+
methods: ["list", "get", "update", "generateInvoice", "invoice", "export"],
|
|
104
|
+
readOnlyMethods: ["list", "get", "invoice", "export"]
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
name: "subscriptions",
|
|
108
|
+
methods: ["list", "get", "create", "update", "revoke", "export"],
|
|
109
|
+
readOnlyMethods: ["list", "get", "export"]
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
name: "benefits",
|
|
113
|
+
methods: ["list", "get", "create", "update", "delete", "grants"],
|
|
114
|
+
readOnlyMethods: ["list", "get", "grants"]
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
name: "checkouts",
|
|
118
|
+
methods: ["list", "get", "create", "update"],
|
|
119
|
+
readOnlyMethods: ["list", "get"]
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
name: "checkoutLinks",
|
|
123
|
+
methods: ["list", "get", "create", "update", "delete"],
|
|
124
|
+
readOnlyMethods: ["list", "get"]
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
name: "discounts",
|
|
128
|
+
methods: ["list", "get", "create", "update", "delete"],
|
|
129
|
+
readOnlyMethods: ["list", "get"]
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
name: "licenseKeys",
|
|
133
|
+
methods: ["list", "get", "update", "getActivation", "validate", "activate", "deactivate"],
|
|
134
|
+
readOnlyMethods: ["list", "get", "getActivation", "validate"]
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
name: "metrics",
|
|
138
|
+
methods: ["get", "limits"],
|
|
139
|
+
readOnlyMethods: ["get", "limits"]
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
name: "webhooks",
|
|
143
|
+
methods: ["listWebhookEndpoints", "getWebhookEndpoint", "createWebhookEndpoint", "updateWebhookEndpoint", "deleteWebhookEndpoint", "listWebhookDeliveries", "redeliverWebhookEvent"],
|
|
144
|
+
readOnlyMethods: ["listWebhookEndpoints", "getWebhookEndpoint", "listWebhookDeliveries"]
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
name: "files",
|
|
148
|
+
methods: ["list", "create", "uploaded", "update", "delete"],
|
|
149
|
+
readOnlyMethods: ["list"]
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
name: "payments",
|
|
153
|
+
methods: ["list", "get"],
|
|
154
|
+
readOnlyMethods: ["list", "get"]
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
name: "refunds",
|
|
158
|
+
methods: ["list", "create"],
|
|
159
|
+
readOnlyMethods: ["list"]
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
name: "meters",
|
|
163
|
+
methods: ["list", "get", "create", "update", "quantities"],
|
|
164
|
+
readOnlyMethods: ["list", "get", "quantities"]
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
name: "customerMeters",
|
|
168
|
+
methods: ["list", "get"],
|
|
169
|
+
readOnlyMethods: ["list", "get"]
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
name: "customFields",
|
|
173
|
+
methods: ["list", "get", "create", "update", "delete"],
|
|
174
|
+
readOnlyMethods: ["list", "get"]
|
|
175
|
+
}
|
|
176
|
+
]
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Convert SDK config namespace to SDKMethod definitions
|
|
181
|
+
*/
|
|
182
|
+
function namespaceToMethods(config) {
|
|
183
|
+
const methods = [];
|
|
184
|
+
for (const ns of config.namespaces) {
|
|
185
|
+
for (const methodName of ns.methods) {
|
|
186
|
+
const isReadOnly = ns.readOnlyMethods?.includes(methodName) ?? false;
|
|
187
|
+
const isPaginated = methodName === "list" || methodName.startsWith("list");
|
|
188
|
+
// Generate sensible input schema based on method name
|
|
189
|
+
const inputSchema = generateInputSchema(methodName, ns.name);
|
|
190
|
+
methods.push({
|
|
191
|
+
name: methodName,
|
|
192
|
+
namespace: ns.name,
|
|
193
|
+
fullPath: `${ns.name}.${methodName}`,
|
|
194
|
+
description: generateMethodDescription(methodName, ns.name),
|
|
195
|
+
inputSchema,
|
|
196
|
+
isPaginated,
|
|
197
|
+
isReadOnly,
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return methods;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Generate input schema based on method name patterns
|
|
205
|
+
*/
|
|
206
|
+
function generateInputSchema(methodName, namespace) {
|
|
207
|
+
const schema = {
|
|
208
|
+
type: "object",
|
|
209
|
+
properties: {},
|
|
210
|
+
required: []
|
|
211
|
+
};
|
|
212
|
+
// List methods typically have optional filter params
|
|
213
|
+
if (methodName === "list" || methodName.startsWith("list")) {
|
|
214
|
+
schema.properties.organizationId = {
|
|
215
|
+
type: "string",
|
|
216
|
+
description: "Filter by organization ID",
|
|
217
|
+
required: false
|
|
218
|
+
};
|
|
219
|
+
schema.properties.limit = {
|
|
220
|
+
type: "number",
|
|
221
|
+
description: "Maximum number of results to return",
|
|
222
|
+
required: false
|
|
223
|
+
};
|
|
224
|
+
return schema;
|
|
225
|
+
}
|
|
226
|
+
// Get methods need an ID
|
|
227
|
+
if (methodName === "get" || methodName.startsWith("get")) {
|
|
228
|
+
schema.properties.id = {
|
|
229
|
+
type: "string",
|
|
230
|
+
description: `${toPascalCase(namespace.slice(0, -1))} ID`,
|
|
231
|
+
required: true
|
|
232
|
+
};
|
|
233
|
+
schema.required = ["id"];
|
|
234
|
+
return schema;
|
|
235
|
+
}
|
|
236
|
+
// Delete/Revoke methods need an ID
|
|
237
|
+
if (methodName === "delete" || methodName === "revoke") {
|
|
238
|
+
schema.properties.id = {
|
|
239
|
+
type: "string",
|
|
240
|
+
description: `${toPascalCase(namespace.slice(0, -1))} ID to ${methodName}`,
|
|
241
|
+
required: true
|
|
242
|
+
};
|
|
243
|
+
schema.required = ["id"];
|
|
244
|
+
return schema;
|
|
245
|
+
}
|
|
246
|
+
// Create methods need various fields
|
|
247
|
+
if (methodName === "create") {
|
|
248
|
+
schema.properties.dataJson = {
|
|
249
|
+
type: "string",
|
|
250
|
+
description: `JSON object with ${namespace.slice(0, -1)} creation data`,
|
|
251
|
+
required: true
|
|
252
|
+
};
|
|
253
|
+
schema.required = ["dataJson"];
|
|
254
|
+
return schema;
|
|
255
|
+
}
|
|
256
|
+
// Update methods need ID and data
|
|
257
|
+
if (methodName === "update" || methodName.startsWith("update")) {
|
|
258
|
+
schema.properties.id = {
|
|
259
|
+
type: "string",
|
|
260
|
+
description: `${toPascalCase(namespace.slice(0, -1))} ID`,
|
|
261
|
+
required: true
|
|
262
|
+
};
|
|
263
|
+
schema.properties.dataJson = {
|
|
264
|
+
type: "string",
|
|
265
|
+
description: `JSON object with update data`,
|
|
266
|
+
required: true
|
|
267
|
+
};
|
|
268
|
+
schema.required = ["id", "dataJson"];
|
|
269
|
+
return schema;
|
|
270
|
+
}
|
|
271
|
+
// Validate method for license keys
|
|
272
|
+
if (methodName === "validate") {
|
|
273
|
+
schema.properties.key = {
|
|
274
|
+
type: "string",
|
|
275
|
+
description: "License key to validate",
|
|
276
|
+
required: true
|
|
277
|
+
};
|
|
278
|
+
schema.properties.organizationId = {
|
|
279
|
+
type: "string",
|
|
280
|
+
description: "Organization ID",
|
|
281
|
+
required: true
|
|
282
|
+
};
|
|
283
|
+
schema.required = ["key", "organizationId"];
|
|
284
|
+
return schema;
|
|
285
|
+
}
|
|
286
|
+
// Default: empty schema
|
|
287
|
+
return schema;
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Generate human-readable method description
|
|
291
|
+
*/
|
|
292
|
+
function generateMethodDescription(methodName, namespace) {
|
|
293
|
+
const singular = namespace.slice(0, -1);
|
|
294
|
+
const pascalSingular = toPascalCase(singular);
|
|
295
|
+
switch (methodName) {
|
|
296
|
+
case "list":
|
|
297
|
+
return `List all ${namespace}`;
|
|
298
|
+
case "get":
|
|
299
|
+
return `Get a ${singular} by ID`;
|
|
300
|
+
case "create":
|
|
301
|
+
return `Create a new ${singular}`;
|
|
302
|
+
case "update":
|
|
303
|
+
return `Update an existing ${singular}`;
|
|
304
|
+
case "delete":
|
|
305
|
+
return `Delete a ${singular}`;
|
|
306
|
+
case "revoke":
|
|
307
|
+
return `Revoke a ${singular}`;
|
|
308
|
+
case "validate":
|
|
309
|
+
return `Validate a ${singular}`;
|
|
310
|
+
case "export":
|
|
311
|
+
return `Export ${namespace} data`;
|
|
312
|
+
default:
|
|
313
|
+
if (methodName.startsWith("list")) {
|
|
314
|
+
return `List ${methodName.replace("list", "").replace(/([A-Z])/g, " $1").toLowerCase().trim()}`;
|
|
315
|
+
}
|
|
316
|
+
if (methodName.startsWith("get")) {
|
|
317
|
+
return `Get ${methodName.replace("get", "").replace(/([A-Z])/g, " $1").toLowerCase().trim()}`;
|
|
318
|
+
}
|
|
319
|
+
return `${pascalSingular}: ${methodName.replace(/([A-Z])/g, " $1").toLowerCase()}`;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Convert property definition to Zod type string
|
|
324
|
+
*/
|
|
325
|
+
function propDefToZod(prop) {
|
|
326
|
+
const desc = prop.description ? `.describe("${prop.description.replace(/"/g, '\\"')}")` : "";
|
|
327
|
+
switch (prop.type) {
|
|
328
|
+
case "string":
|
|
329
|
+
if (prop.enum && prop.enum.length > 0) {
|
|
330
|
+
const enumValues = prop.enum.map(v => `"${v}"`).join(", ");
|
|
331
|
+
return `z.enum([${enumValues}])${desc}`;
|
|
332
|
+
}
|
|
333
|
+
return `z.string()${desc}`;
|
|
334
|
+
case "number":
|
|
335
|
+
case "integer":
|
|
336
|
+
return `z.number()${desc}`;
|
|
337
|
+
case "boolean":
|
|
338
|
+
return `z.boolean()${desc}`;
|
|
339
|
+
case "array":
|
|
340
|
+
return `z.array(z.string())${desc}`;
|
|
341
|
+
case "object":
|
|
342
|
+
return `z.string()${desc.replace('.describe("', '.describe("JSON object: ')}`;
|
|
343
|
+
default:
|
|
344
|
+
return `z.any()${desc}`;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Generate tool definition for an SDK method
|
|
349
|
+
*/
|
|
350
|
+
function generateToolFromMethod(method, petName) {
|
|
351
|
+
const toolName = `${petName}-${method.namespace}-${method.name}`.replace(/_/g, "-");
|
|
352
|
+
const description = method.description || `${method.name} ${method.namespace}`;
|
|
353
|
+
// Generate schema properties
|
|
354
|
+
const schemaFields = [];
|
|
355
|
+
for (const [propName, propDef] of Object.entries(method.inputSchema.properties)) {
|
|
356
|
+
const isRequired = method.inputSchema.required.includes(propName);
|
|
357
|
+
let zodType = propDefToZod(propDef);
|
|
358
|
+
if (!isRequired && !zodType.includes(".optional()")) {
|
|
359
|
+
zodType = zodType + ".optional()";
|
|
360
|
+
}
|
|
361
|
+
schemaFields.push(` ${propName}: ${zodType}`);
|
|
362
|
+
}
|
|
363
|
+
const schemaBody = schemaFields.length > 0
|
|
364
|
+
? `z.object({\n${schemaFields.join(",\n")}\n })`
|
|
365
|
+
: "z.object({})";
|
|
366
|
+
const executeBody = method.isPaginated
|
|
367
|
+
? `try {
|
|
368
|
+
const items: any[] = []
|
|
369
|
+
const result = await client.${method.fullPath}(args)
|
|
370
|
+
for await (const page of result) {
|
|
371
|
+
// Handle different pagination response structures
|
|
372
|
+
const pageData = page as any
|
|
373
|
+
if (pageData?.result?.items) items.push(...pageData.result.items)
|
|
374
|
+
else if (pageData?.items) items.push(...pageData.items)
|
|
375
|
+
else if (Array.isArray(pageData)) items.push(...pageData)
|
|
376
|
+
}
|
|
377
|
+
return JSON.stringify({ total: items.length, items }, null, 2)
|
|
378
|
+
} catch (error: any) {
|
|
379
|
+
return JSON.stringify({ success: false, error: error.message }, null, 2)
|
|
380
|
+
}`
|
|
381
|
+
: `try {
|
|
382
|
+
const result = await client.${method.fullPath}(args)
|
|
383
|
+
return JSON.stringify(result, null, 2)
|
|
384
|
+
} catch (error: any) {
|
|
385
|
+
return JSON.stringify({ success: false, error: error.message }, null, 2)
|
|
386
|
+
}`;
|
|
387
|
+
return ` {
|
|
388
|
+
name: "${toolName}",
|
|
389
|
+
description: "${description.replace(/"/g, '\\"').replace(/\n/g, " ")}",
|
|
390
|
+
schema: ${schemaBody},
|
|
391
|
+
async execute(args) {
|
|
392
|
+
${executeBody}
|
|
393
|
+
}
|
|
394
|
+
}`;
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Generate the client.ts file content
|
|
398
|
+
*/
|
|
399
|
+
function generateClientTs(config, methods) {
|
|
400
|
+
const toolDefinitions = methods.map(m => generateToolFromMethod(m, config.petName)).join(",\n\n");
|
|
401
|
+
const readOnlyTools = methods.filter(m => m.isReadOnly).map(m => `"${config.petName}-${m.namespace}-${m.name}"`.replace(/_/g, "-"));
|
|
402
|
+
return `/**
|
|
403
|
+
* Auto-generated SDK client tools for ${config.petName}
|
|
404
|
+
*
|
|
405
|
+
* Generated from: ${config.sdkPackage}
|
|
406
|
+
* Generated at: ${new Date().toISOString()}
|
|
407
|
+
*
|
|
408
|
+
* DO NOT EDIT MANUALLY - regenerate with:
|
|
409
|
+
* pets generate-sdk
|
|
410
|
+
*/
|
|
411
|
+
|
|
412
|
+
import { z, type ToolDefinition, createLogger, isReadOnly, filterToolsForReadOnly } from "openpets-sdk"
|
|
413
|
+
import { ${config.mainClassName} } from "${config.sdkPackage}"
|
|
414
|
+
|
|
415
|
+
const logger = createLogger("${config.petName}-client")
|
|
416
|
+
|
|
417
|
+
// Read-only tool names (safe to use in read-only mode)
|
|
418
|
+
const READ_ONLY_TOOLS = [
|
|
419
|
+
${readOnlyTools.map(t => ` ${t},`).join('\n')}
|
|
420
|
+
]
|
|
421
|
+
|
|
422
|
+
// Write operation patterns for filtering
|
|
423
|
+
const WRITE_PATTERNS = ['create', 'update', 'delete', 'add', 'remove', 'revoke', 'archive']
|
|
424
|
+
|
|
425
|
+
export interface ${toPascalCase(config.petName)}ClientConfig {
|
|
426
|
+
accessToken: string
|
|
427
|
+
organizationId?: string
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
export function create${toPascalCase(config.petName)}Tools(config: ${toPascalCase(config.petName)}ClientConfig): ToolDefinition[] {
|
|
431
|
+
const { accessToken, organizationId } = config
|
|
432
|
+
const readOnlyMode = isReadOnly("${config.petName}")
|
|
433
|
+
|
|
434
|
+
// Create SDK client
|
|
435
|
+
const client = new ${config.mainClassName}({
|
|
436
|
+
accessToken,
|
|
437
|
+
})
|
|
438
|
+
|
|
439
|
+
if (readOnlyMode) {
|
|
440
|
+
logger.info("READ-ONLY MODE - write operations disabled")
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
const allTools: ToolDefinition[] = [
|
|
444
|
+
// Test connection
|
|
445
|
+
{
|
|
446
|
+
name: "${config.petName}-test-connection",
|
|
447
|
+
description: "Test ${config.petName} SDK connection and configuration",
|
|
448
|
+
schema: z.object({}),
|
|
449
|
+
async execute() {
|
|
450
|
+
try {
|
|
451
|
+
// Simple connectivity test
|
|
452
|
+
const orgs = await client.organizations.list({})
|
|
453
|
+
let orgCount = 0
|
|
454
|
+
for await (const page of orgs) {
|
|
455
|
+
// Handle different pagination response structures
|
|
456
|
+
const pageData = page as any
|
|
457
|
+
if (pageData?.result?.items) orgCount += pageData.result.items.length
|
|
458
|
+
else if (pageData?.items) orgCount += pageData.items.length
|
|
459
|
+
}
|
|
460
|
+
return JSON.stringify({
|
|
461
|
+
success: true,
|
|
462
|
+
status: "connected",
|
|
463
|
+
message: "Connected to ${toPascalCase(config.petName)} API successfully",
|
|
464
|
+
details: { organizationCount: orgCount, readOnlyMode }
|
|
465
|
+
}, null, 2)
|
|
466
|
+
} catch (error: any) {
|
|
467
|
+
return JSON.stringify({
|
|
468
|
+
success: false,
|
|
469
|
+
status: "error",
|
|
470
|
+
message: error.message,
|
|
471
|
+
details: { readOnlyMode }
|
|
472
|
+
}, null, 2)
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
},
|
|
476
|
+
|
|
477
|
+
${toolDefinitions}
|
|
478
|
+
]
|
|
479
|
+
|
|
480
|
+
// Filter tools based on read-only mode
|
|
481
|
+
return filterToolsForReadOnly(allTools, WRITE_PATTERNS, readOnlyMode, logger)
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// Export individual tools array for direct use
|
|
485
|
+
export const ${config.petName}Tools = (config: ${toPascalCase(config.petName)}ClientConfig) => create${toPascalCase(config.petName)}Tools(config)
|
|
486
|
+
|
|
487
|
+
export default create${toPascalCase(config.petName)}Tools
|
|
488
|
+
`;
|
|
489
|
+
}
|
|
490
|
+
function toPascalCase(str) {
|
|
491
|
+
return str
|
|
492
|
+
.split(/[-_]/)
|
|
493
|
+
.map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
|
|
494
|
+
.join("");
|
|
495
|
+
}
|
|
496
|
+
/**
|
|
497
|
+
* Main SDK generation function
|
|
498
|
+
*/
|
|
499
|
+
export async function generateSDKTools(options = {}) {
|
|
500
|
+
const cwd = process.cwd();
|
|
501
|
+
const outputFile = options.outputFile || "client.ts";
|
|
502
|
+
// Load .env files
|
|
503
|
+
loadDotenv({ path: resolve(cwd, ".env") });
|
|
504
|
+
loadDotenv({ path: resolve(cwd, "../.env") });
|
|
505
|
+
loadDotenv({ path: resolve(cwd, "../../.env") });
|
|
506
|
+
// Load SDK config from package.json
|
|
507
|
+
const sdkInfo = loadSDKConfigFromPackageJson(cwd);
|
|
508
|
+
if (!sdkInfo) {
|
|
509
|
+
return {
|
|
510
|
+
success: false,
|
|
511
|
+
message: "No sdkGenerator configuration found in package.json or sdk-config.json. Add sdkGenerator config or create sdk-config.json file."
|
|
512
|
+
};
|
|
513
|
+
}
|
|
514
|
+
const { config, petName } = sdkInfo;
|
|
515
|
+
if (options.verbose) {
|
|
516
|
+
console.log(`SDK Package: ${config.sdkPackage}`);
|
|
517
|
+
console.log(`Pet Name: ${petName}`);
|
|
518
|
+
console.log(`Main Class: ${config.mainClassName}`);
|
|
519
|
+
console.log(`Namespaces: ${config.namespaces.length}`);
|
|
520
|
+
}
|
|
521
|
+
try {
|
|
522
|
+
// Convert namespaces to methods
|
|
523
|
+
const methods = namespaceToMethods(config);
|
|
524
|
+
if (options.verbose) {
|
|
525
|
+
console.log(`Generated ${methods.length} tool definitions from ${config.namespaces.length} namespaces`);
|
|
526
|
+
console.log("\nTools:");
|
|
527
|
+
for (const m of methods) {
|
|
528
|
+
const marker = m.isReadOnly ? "read" : "write";
|
|
529
|
+
console.log(` [${marker}] ${config.petName}-${m.namespace}-${m.name}`);
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
// Generate client.ts content
|
|
533
|
+
const content = generateClientTs(config, methods);
|
|
534
|
+
if (options.dryRun) {
|
|
535
|
+
console.log("\n--- Generated client.ts ---");
|
|
536
|
+
console.log(content.slice(0, 5000));
|
|
537
|
+
if (content.length > 5000) {
|
|
538
|
+
console.log(`\n... (${content.length - 5000} more characters)`);
|
|
539
|
+
}
|
|
540
|
+
console.log("--- End ---\n");
|
|
541
|
+
}
|
|
542
|
+
else {
|
|
543
|
+
const outputPath = resolve(cwd, outputFile);
|
|
544
|
+
writeFileSync(outputPath, content);
|
|
545
|
+
}
|
|
546
|
+
const readOnlyCount = methods.filter(m => m.isReadOnly).length;
|
|
547
|
+
const writeCount = methods.length - readOnlyCount;
|
|
548
|
+
return {
|
|
549
|
+
success: true,
|
|
550
|
+
message: options.dryRun
|
|
551
|
+
? `Would generate ${methods.length} tools (${readOnlyCount} read-only, ${writeCount} write) to ${outputFile}`
|
|
552
|
+
: `Generated ${methods.length} tools (${readOnlyCount} read-only, ${writeCount} write) to ${outputFile}`,
|
|
553
|
+
toolCount: methods.length,
|
|
554
|
+
outputPath: resolve(cwd, outputFile),
|
|
555
|
+
methods,
|
|
556
|
+
};
|
|
557
|
+
}
|
|
558
|
+
catch (error) {
|
|
559
|
+
return {
|
|
560
|
+
success: false,
|
|
561
|
+
message: `Failed to generate SDK tools: ${error.message}`
|
|
562
|
+
};
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
// Export the built-in configs for external use
|
|
566
|
+
export { createPolarSDKConfig };
|
|
567
|
+
//# sourceMappingURL=sdk-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sdk-generator.js","sourceRoot":"","sources":["../../../sdk-generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -24,6 +24,11 @@ export interface PetApiData {
|
|
|
24
24
|
}
|
|
25
25
|
export declare function searchPets(query: string): Promise<SearchResult[]>;
|
|
26
26
|
export declare function clearSearchCache(): void;
|
|
27
|
+
/**
|
|
28
|
+
* Find similar pet names using fuzzy matching.
|
|
29
|
+
* Returns the closest matches to the given query, useful for "did you mean" suggestions.
|
|
30
|
+
*/
|
|
31
|
+
export declare function findSimilarPets(query: string, limit?: number): Promise<SearchResult[]>;
|
|
27
32
|
export declare function createPetFromApiData(petId: string, petData: PetApiData): Pet;
|
|
28
33
|
export declare function getAllPets(): Promise<Pet[]>;
|
|
29
34
|
//# sourceMappingURL=search-pets.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search-pets.d.ts","sourceRoot":"","sources":["../../../search-pets.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,SAAS,CAAC;AAcnC,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,KAAK,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACrD,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IAC9C,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AA2KD,wBAAsB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAkEvE;AAED,wBAAgB,gBAAgB,IAAI,IAAI,CAGvC;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,GAAG,CAgB5E;AAED,wBAAsB,UAAU,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAKjD"}
|
|
1
|
+
{"version":3,"file":"search-pets.d.ts","sourceRoot":"","sources":["../../../search-pets.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,SAAS,CAAC;AAcnC,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,KAAK,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACrD,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IAC9C,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AA2KD,wBAAsB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAkEvE;AAED,wBAAgB,gBAAgB,IAAI,IAAI,CAGvC;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,GAAE,MAAU,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CA+C/F;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,GAAG,CAgB5E;AAED,wBAAsB,UAAU,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAKjD"}
|
|
@@ -202,6 +202,49 @@ export function clearSearchCache() {
|
|
|
202
202
|
searchIndex = null;
|
|
203
203
|
apiDataCache = null;
|
|
204
204
|
}
|
|
205
|
+
/**
|
|
206
|
+
* Find similar pet names using fuzzy matching.
|
|
207
|
+
* Returns the closest matches to the given query, useful for "did you mean" suggestions.
|
|
208
|
+
*/
|
|
209
|
+
export async function findSimilarPets(query, limit = 5) {
|
|
210
|
+
if (!query || query.trim().length === 0) {
|
|
211
|
+
return [];
|
|
212
|
+
}
|
|
213
|
+
const searchTerm = query.toLowerCase().trim();
|
|
214
|
+
const index = await buildSearchIndex();
|
|
215
|
+
const results = [];
|
|
216
|
+
for (const item of index) {
|
|
217
|
+
const namePart = item.id.replace('@openpets/', '').toLowerCase();
|
|
218
|
+
// Calculate Levenshtein distance for fuzzy matching
|
|
219
|
+
const distance = levenshteinDistance(searchTerm, namePart);
|
|
220
|
+
const maxLen = Math.max(searchTerm.length, namePart.length);
|
|
221
|
+
// Calculate similarity score (higher is better)
|
|
222
|
+
// Allow matches with distance <= 3 or <= 40% of the longer string
|
|
223
|
+
const threshold = Math.max(3, Math.floor(maxLen * 0.4));
|
|
224
|
+
if (distance <= threshold) {
|
|
225
|
+
// Score inversely proportional to distance
|
|
226
|
+
// Exact match = 100, each edit reduces score
|
|
227
|
+
const similarityScore = Math.max(0, 100 - (distance * 20));
|
|
228
|
+
// Boost score if query is a prefix of the name
|
|
229
|
+
const prefixBoost = namePart.startsWith(searchTerm) ? 30 : 0;
|
|
230
|
+
// Boost score if name starts with same letter
|
|
231
|
+
const sameStartBoost = namePart[0] === searchTerm[0] ? 10 : 0;
|
|
232
|
+
const finalScore = similarityScore + prefixBoost + sameStartBoost;
|
|
233
|
+
results.push({
|
|
234
|
+
id: item.id,
|
|
235
|
+
name: item.data.name,
|
|
236
|
+
description: item.data.description,
|
|
237
|
+
keywords: item.data.keywords || [],
|
|
238
|
+
matchReason: distance === 0 ? "Exact match" : `Similar name (${distance} edit${distance === 1 ? '' : 's'})`,
|
|
239
|
+
matchScore: finalScore,
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
// Sort by score descending and limit results
|
|
244
|
+
return results
|
|
245
|
+
.sort((a, b) => b.matchScore - a.matchScore)
|
|
246
|
+
.slice(0, limit);
|
|
247
|
+
}
|
|
205
248
|
export function createPetFromApiData(petId, petData) {
|
|
206
249
|
const shortId = petId.replace(/^@?openpets\//, "");
|
|
207
250
|
const { tools, ...restData } = petData;
|