@redonvn/open-claw-sdk 0.1.0

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.
@@ -0,0 +1,380 @@
1
+ // src/openapi.ts
2
+ import { promises as fs } from "fs";
3
+
4
+ // src/utils.ts
5
+ var HTTP_METHODS = [
6
+ "get",
7
+ "post",
8
+ "put",
9
+ "patch",
10
+ "delete",
11
+ "options",
12
+ "head"
13
+ ];
14
+ var AUTH_HEADER_NAMES = /* @__PURE__ */ new Set([
15
+ "authorization",
16
+ "x-api-key",
17
+ "api-key",
18
+ "dt-jwt"
19
+ ]);
20
+ var sanitizeIdentifier = (value) => value.trim().replace(/[^a-zA-Z0-9]+/g, "_").replace(/^_+|_+$/g, "").replace(/_{2,}/g, "_").toLowerCase() || "tool";
21
+ var toTitleCase = (value) => value.split(/[^a-zA-Z0-9]+/).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
22
+ var buildToolName = (toolPrefix, rawName) => {
23
+ const base = sanitizeIdentifier(rawName);
24
+ const prefix = sanitizeIdentifier(toolPrefix ?? "");
25
+ return prefix ? `${prefix}_${base}` : base;
26
+ };
27
+ var buildOperationId = (method, path2, operationId) => {
28
+ if (operationId?.trim()) {
29
+ return sanitizeIdentifier(operationId);
30
+ }
31
+ const pathPart = path2.replace(/\{([^}]+)\}/g, "by_$1").replace(/\/+/g, "_");
32
+ return sanitizeIdentifier(`${method}_${pathPart}`);
33
+ };
34
+ var pickContentSchema = (content) => content?.["application/json"]?.schema ?? content?.["application/*+json"]?.schema ?? Object.values(content ?? {})[0]?.schema;
35
+ var dedupeParameters = (pathLevel, operationLevel) => {
36
+ const byKey = /* @__PURE__ */ new Map();
37
+ for (const param of [...pathLevel ?? [], ...operationLevel ?? []]) {
38
+ byKey.set(`${param.in}:${param.name}`, param);
39
+ }
40
+ return [...byKey.values()];
41
+ };
42
+ var compactObject = (value) => {
43
+ const output = {};
44
+ for (const [key, item] of Object.entries(value)) {
45
+ if (item !== void 0) {
46
+ output[key] = item;
47
+ }
48
+ }
49
+ return output;
50
+ };
51
+ var hasSchemaContent = (schema) => Boolean(
52
+ schema && (schema.properties && Object.keys(schema.properties).length > 0 || schema.required && schema.required.length > 0 || schema.type || schema.oneOf || schema.anyOf || schema.allOf)
53
+ );
54
+
55
+ // src/openapi.ts
56
+ var isHttpUrl = (value) => /^https?:\/\//i.test(value);
57
+ var readUrl = async (url) => {
58
+ const response = await fetch(url);
59
+ if (!response.ok) {
60
+ throw new Error(`Unable to load OpenAPI document from ${url}: ${response.status} ${response.statusText}`);
61
+ }
62
+ return response.text();
63
+ };
64
+ var loadOpenApiDocument = async (source) => {
65
+ const raw = isHttpUrl(source) ? await readUrl(source) : await fs.readFile(source, "utf8");
66
+ const document = JSON.parse(raw);
67
+ if (!document.openapi || !document.paths) {
68
+ throw new Error("Invalid OpenAPI document: missing `openapi` or `paths`.");
69
+ }
70
+ return document;
71
+ };
72
+ var resolveRefName = (ref) => ref.split("/").pop() ?? "UnknownSchema";
73
+ var resolveSchemaRef = (document, ref) => {
74
+ const schemaName = resolveRefName(ref);
75
+ return document.components?.schemas?.[schemaName];
76
+ };
77
+ var openApiSchemaToJsonSchema = (schema, document, seen = /* @__PURE__ */ new Set()) => {
78
+ if (!schema) {
79
+ return { type: "object", additionalProperties: true };
80
+ }
81
+ if (schema.$ref) {
82
+ if (seen.has(schema.$ref)) {
83
+ return { type: "object", additionalProperties: true };
84
+ }
85
+ const resolved = resolveSchemaRef(document, schema.$ref);
86
+ if (!resolved) {
87
+ return { type: "object", additionalProperties: true };
88
+ }
89
+ const nextSeen = new Set(seen);
90
+ nextSeen.add(schema.$ref);
91
+ return openApiSchemaToJsonSchema(resolved, document, nextSeen);
92
+ }
93
+ const jsonSchema = compactObject({
94
+ type: Array.isArray(schema.type) ? [...schema.type] : schema.type,
95
+ description: schema.description,
96
+ default: schema.default,
97
+ enum: schema.enum ? [...schema.enum] : void 0
98
+ });
99
+ if (schema.oneOf?.length) {
100
+ jsonSchema.oneOf = schema.oneOf.map((item) => openApiSchemaToJsonSchema(item, document, seen));
101
+ }
102
+ if (schema.anyOf?.length) {
103
+ jsonSchema.anyOf = schema.anyOf.map((item) => openApiSchemaToJsonSchema(item, document, seen));
104
+ }
105
+ if (schema.allOf?.length) {
106
+ jsonSchema.allOf = schema.allOf.map((item) => openApiSchemaToJsonSchema(item, document, seen));
107
+ }
108
+ if (schema.items) {
109
+ jsonSchema.items = openApiSchemaToJsonSchema(schema.items, document, seen);
110
+ }
111
+ if (schema.properties) {
112
+ jsonSchema.properties = Object.fromEntries(
113
+ Object.entries(schema.properties).map(([key, value]) => [
114
+ key,
115
+ openApiSchemaToJsonSchema(value, document, seen)
116
+ ])
117
+ );
118
+ }
119
+ if (schema.required?.length) {
120
+ jsonSchema.required = [...schema.required];
121
+ }
122
+ if (schema.additionalProperties !== void 0) {
123
+ jsonSchema.additionalProperties = schema.additionalProperties === true || schema.additionalProperties === false ? schema.additionalProperties : openApiSchemaToJsonSchema(schema.additionalProperties, document, seen);
124
+ }
125
+ if (schema.nullable) {
126
+ const currentType = jsonSchema.type;
127
+ if (Array.isArray(currentType)) {
128
+ jsonSchema.type = currentType.includes("null") ? currentType : [...currentType, "null"];
129
+ } else if (currentType) {
130
+ jsonSchema.type = currentType === "null" ? "null" : [currentType, "null"];
131
+ } else {
132
+ jsonSchema.type = ["object", "null"];
133
+ }
134
+ }
135
+ return jsonSchema;
136
+ };
137
+ var buildParameterSection = (sectionName, parameters, document) => {
138
+ if (!parameters.length) {
139
+ return null;
140
+ }
141
+ const properties = {};
142
+ const required = [];
143
+ for (const parameter of parameters) {
144
+ properties[parameter.name] = compactObject({
145
+ ...openApiSchemaToJsonSchema(parameter.schema, document),
146
+ description: parameter.description ?? parameter.schema?.description
147
+ });
148
+ if (parameter.required) {
149
+ required.push(parameter.name);
150
+ }
151
+ }
152
+ return {
153
+ name: sectionName,
154
+ required: required.length > 0,
155
+ schema: compactObject({
156
+ type: "object",
157
+ properties,
158
+ required: required.length ? required : void 0,
159
+ additionalProperties: false
160
+ })
161
+ };
162
+ };
163
+ var buildToolParameters = (document, path2, operation, options, pathParameters, queryParameters, headerParameters) => {
164
+ const requestBodySchema = pickContentSchema(operation.requestBody?.content);
165
+ const properties = {};
166
+ const required = [];
167
+ const sections = [
168
+ buildParameterSection("path", pathParameters, document),
169
+ buildParameterSection("query", queryParameters, document),
170
+ options.includeHeaders ? buildParameterSection("headers", headerParameters, document) : null
171
+ ].filter((value) => Boolean(value));
172
+ for (const section of sections) {
173
+ if (hasSchemaContent(section.schema)) {
174
+ properties[section.name] = section.schema;
175
+ if (section.required) {
176
+ required.push(section.name);
177
+ }
178
+ }
179
+ }
180
+ if (requestBodySchema) {
181
+ properties.body = openApiSchemaToJsonSchema(requestBodySchema, document);
182
+ if (operation.requestBody?.required) {
183
+ required.push("body");
184
+ }
185
+ }
186
+ return compactObject({
187
+ type: "object",
188
+ properties,
189
+ required: required.length ? required : void 0,
190
+ additionalProperties: false,
191
+ description: `${operation.summary ?? operation.operationId ?? `${path2} request`} tool arguments`
192
+ });
193
+ };
194
+ var buildToolDescription = (path2, method, operation) => {
195
+ const summary = operation.summary?.trim();
196
+ const description = operation.description?.trim();
197
+ if (summary && description && description !== summary) {
198
+ return `${summary}. ${description}`;
199
+ }
200
+ if (summary) {
201
+ return summary;
202
+ }
203
+ if (description) {
204
+ return description;
205
+ }
206
+ return `${method.toUpperCase()} ${path2}`;
207
+ };
208
+ var buildToolDefinition = (document, path2, method, operation, options, pathParameters, queryParameters, headerParameters) => {
209
+ const operationId = buildOperationId(method, path2, operation.operationId);
210
+ return {
211
+ name: buildToolName(options.toolPrefix, operationId),
212
+ description: buildToolDescription(path2, method, operation),
213
+ method: method.toUpperCase(),
214
+ path: path2,
215
+ operationId,
216
+ parameters: buildToolParameters(
217
+ document,
218
+ path2,
219
+ operation,
220
+ options,
221
+ pathParameters,
222
+ queryParameters,
223
+ headerParameters
224
+ ),
225
+ tags: operation.tags ?? []
226
+ };
227
+ };
228
+ var convertOpenApiToTools = (document, options) => {
229
+ const tools = [];
230
+ for (const [path2, pathItem] of Object.entries(document.paths)) {
231
+ for (const method of HTTP_METHODS) {
232
+ const operation = pathItem[method];
233
+ if (!operation) {
234
+ continue;
235
+ }
236
+ const parameters = dedupeParameters(pathItem.parameters, operation.parameters);
237
+ const pathParameters = parameters.filter((parameter) => parameter.in === "path");
238
+ const queryParameters = parameters.filter((parameter) => parameter.in === "query");
239
+ const headerParameters = parameters.filter(
240
+ (parameter) => parameter.in === "header" && !AUTH_HEADER_NAMES.has(parameter.name.toLowerCase())
241
+ );
242
+ tools.push(
243
+ buildToolDefinition(
244
+ document,
245
+ path2,
246
+ method,
247
+ operation,
248
+ options,
249
+ pathParameters,
250
+ queryParameters,
251
+ headerParameters
252
+ )
253
+ );
254
+ }
255
+ }
256
+ tools.sort((left, right) => left.name.localeCompare(right.name));
257
+ return {
258
+ pluginId: options.pluginId,
259
+ pluginName: options.pluginName ?? toTitleCase(options.pluginId),
260
+ description: document.info?.description?.trim() ?? `Generated OpenClaw tool plugin for ${document.info?.title ?? options.pluginId}`,
261
+ serverUrl: options.defaultServerUrl ?? document.servers?.[0]?.url,
262
+ optional: options.optional ?? true,
263
+ tools
264
+ };
265
+ };
266
+
267
+ // src/generator.ts
268
+ import { promises as fs2 } from "fs";
269
+ import path from "path";
270
+ var serialize = (value) => JSON.stringify(value, null, 2);
271
+ var renderPluginManifest = (catalog) => `${serialize({
272
+ id: catalog.pluginId,
273
+ name: catalog.pluginName,
274
+ version: "0.1.0",
275
+ description: catalog.description,
276
+ configSchema: {
277
+ type: "object",
278
+ additionalProperties: false,
279
+ properties: {
280
+ baseUrl: {
281
+ type: "string",
282
+ description: "Base URL of the target HTTP API"
283
+ },
284
+ bearerToken: {
285
+ type: "string",
286
+ description: "Bearer token used for Authorization header"
287
+ },
288
+ apiKey: {
289
+ type: "string",
290
+ description: "Static API key for the upstream API"
291
+ },
292
+ apiKeyHeader: {
293
+ type: "string",
294
+ description: "Header name used when apiKey is set",
295
+ default: "x-api-key"
296
+ },
297
+ timeoutMs: {
298
+ type: "number",
299
+ description: "Timeout in milliseconds for outbound tool calls"
300
+ },
301
+ defaultHeaders: {
302
+ type: "object",
303
+ additionalProperties: {
304
+ type: "string"
305
+ },
306
+ description: "Additional headers added to every request"
307
+ }
308
+ }
309
+ },
310
+ uiHints: {
311
+ baseUrl: {
312
+ label: "Base URL",
313
+ placeholder: catalog.serverUrl ?? "https://api.example.com"
314
+ },
315
+ bearerToken: {
316
+ label: "Bearer Token",
317
+ sensitive: true
318
+ },
319
+ apiKey: {
320
+ label: "API Key",
321
+ sensitive: true
322
+ },
323
+ apiKeyHeader: {
324
+ label: "API Key Header"
325
+ },
326
+ timeoutMs: {
327
+ label: "Timeout (ms)"
328
+ }
329
+ }
330
+ })}
331
+ `;
332
+ var renderPluginModule = (catalog) => `import { createOpenApiPlugin } from "@redonvn/open-claw-sdk";
333
+
334
+ export const catalog = ${serialize(catalog)} as const;
335
+
336
+ export default createOpenApiPlugin(catalog);
337
+ `;
338
+ var renderCatalogFile = (catalog) => `${serialize(catalog)}
339
+ `;
340
+ var ensureDir = async (dirPath) => {
341
+ await fs2.mkdir(dirPath, { recursive: true });
342
+ };
343
+ var writeGeneratedPlugin = async (catalog, outDir) => {
344
+ await ensureDir(outDir);
345
+ const manifestPath = path.join(outDir, "openclaw.plugin.json");
346
+ const indexPath = path.join(outDir, "index.ts");
347
+ const catalogPath = path.join(outDir, "tool-catalog.json");
348
+ await Promise.all([
349
+ fs2.writeFile(manifestPath, renderPluginManifest(catalog), "utf8"),
350
+ fs2.writeFile(indexPath, renderPluginModule(catalog), "utf8"),
351
+ fs2.writeFile(catalogPath, renderCatalogFile(catalog), "utf8")
352
+ ]);
353
+ return { manifestPath, indexPath, catalogPath };
354
+ };
355
+ var generatePluginFromOpenApi = async (options) => {
356
+ const document = await loadOpenApiDocument(options.input);
357
+ const convertOptions = {
358
+ pluginId: options.pluginId,
359
+ pluginName: options.pluginName,
360
+ toolPrefix: options.toolPrefix,
361
+ optional: options.optional,
362
+ includeHeaders: options.includeHeaders,
363
+ defaultServerUrl: options.defaultServerUrl
364
+ };
365
+ const catalog = convertOpenApiToTools(document, convertOptions);
366
+ const files = await writeGeneratedPlugin(catalog, options.outDir);
367
+ return { catalog, files };
368
+ };
369
+
370
+ export {
371
+ loadOpenApiDocument,
372
+ openApiSchemaToJsonSchema,
373
+ convertOpenApiToTools,
374
+ renderPluginManifest,
375
+ renderPluginModule,
376
+ renderCatalogFile,
377
+ writeGeneratedPlugin,
378
+ generatePluginFromOpenApi
379
+ };
380
+ //# sourceMappingURL=chunk-VZE5THET.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/openapi.ts","../src/utils.ts","../src/generator.ts"],"sourcesContent":["import { promises as fs } from \"node:fs\";\nimport {\n ConvertOpenApiOptions,\n JsonSchema,\n OpenApiDocument,\n OpenApiOperationObject,\n OpenClawPluginCatalog,\n OpenClawToolDefinition\n} from \"./types\";\nimport {\n AUTH_HEADER_NAMES,\n HTTP_METHODS,\n buildOperationId,\n buildToolName,\n compactObject,\n dedupeParameters,\n hasSchemaContent,\n pickContentSchema,\n toTitleCase\n} from \"./utils\";\n\nconst isHttpUrl = (value: string): boolean => /^https?:\\/\\//i.test(value);\n\nconst readUrl = async (url: string): Promise<string> => {\n const response = await fetch(url);\n\n if (!response.ok) {\n throw new Error(`Unable to load OpenAPI document from ${url}: ${response.status} ${response.statusText}`);\n }\n\n return response.text();\n};\n\nexport const loadOpenApiDocument = async (source: string): Promise<OpenApiDocument> => {\n const raw = isHttpUrl(source)\n ? await readUrl(source)\n : await fs.readFile(source, \"utf8\");\n\n const document = JSON.parse(raw) as OpenApiDocument;\n\n if (!document.openapi || !document.paths) {\n throw new Error(\"Invalid OpenAPI document: missing `openapi` or `paths`.\");\n }\n\n return document;\n};\n\nconst cloneJsonSchema = (value: JsonSchema): JsonSchema => JSON.parse(JSON.stringify(value)) as JsonSchema;\n\nconst resolveRefName = (ref: string): string => ref.split(\"/\").pop() ?? \"UnknownSchema\";\n\nconst resolveSchemaRef = (\n document: OpenApiDocument,\n ref: string\n): import(\"./types\").OpenApiSchemaObject | undefined => {\n const schemaName = resolveRefName(ref);\n return document.components?.schemas?.[schemaName];\n};\n\nexport const openApiSchemaToJsonSchema = (\n schema: import(\"./types\").OpenApiSchemaObject | undefined,\n document: OpenApiDocument,\n seen = new Set<string>()\n): JsonSchema => {\n if (!schema) {\n return { type: \"object\", additionalProperties: true };\n }\n\n if (schema.$ref) {\n if (seen.has(schema.$ref)) {\n return { type: \"object\", additionalProperties: true };\n }\n\n const resolved = resolveSchemaRef(document, schema.$ref);\n\n if (!resolved) {\n return { type: \"object\", additionalProperties: true };\n }\n\n const nextSeen = new Set(seen);\n nextSeen.add(schema.$ref);\n return openApiSchemaToJsonSchema(resolved, document, nextSeen);\n }\n\n const jsonSchema: JsonSchema = compactObject({\n type: Array.isArray(schema.type) ? [...schema.type] : schema.type,\n description: schema.description,\n default: schema.default,\n enum: schema.enum ? [...schema.enum] : undefined\n });\n\n if (schema.oneOf?.length) {\n jsonSchema.oneOf = schema.oneOf.map((item) => openApiSchemaToJsonSchema(item, document, seen));\n }\n\n if (schema.anyOf?.length) {\n jsonSchema.anyOf = schema.anyOf.map((item) => openApiSchemaToJsonSchema(item, document, seen));\n }\n\n if (schema.allOf?.length) {\n jsonSchema.allOf = schema.allOf.map((item) => openApiSchemaToJsonSchema(item, document, seen));\n }\n\n if (schema.items) {\n jsonSchema.items = openApiSchemaToJsonSchema(schema.items, document, seen);\n }\n\n if (schema.properties) {\n jsonSchema.properties = Object.fromEntries(\n Object.entries(schema.properties).map(([key, value]) => [\n key,\n openApiSchemaToJsonSchema(value, document, seen)\n ])\n );\n }\n\n if (schema.required?.length) {\n jsonSchema.required = [...schema.required];\n }\n\n if (schema.additionalProperties !== undefined) {\n jsonSchema.additionalProperties =\n schema.additionalProperties === true || schema.additionalProperties === false\n ? schema.additionalProperties\n : openApiSchemaToJsonSchema(schema.additionalProperties, document, seen);\n }\n\n if (schema.nullable) {\n const currentType = jsonSchema.type;\n\n if (Array.isArray(currentType)) {\n jsonSchema.type = currentType.includes(\"null\") ? currentType : [...currentType, \"null\"];\n } else if (currentType) {\n jsonSchema.type = currentType === \"null\" ? \"null\" : [currentType, \"null\"];\n } else {\n jsonSchema.type = [\"object\", \"null\"];\n }\n }\n\n return jsonSchema;\n};\n\nconst buildParameterSection = (\n sectionName: string,\n parameters: import(\"./types\").OpenApiParameterObject[],\n document: OpenApiDocument\n): { name: string; schema: JsonSchema; required: boolean } | null => {\n if (!parameters.length) {\n return null;\n }\n\n const properties: Record<string, JsonSchema> = {};\n const required: string[] = [];\n\n for (const parameter of parameters) {\n properties[parameter.name] = compactObject({\n ...openApiSchemaToJsonSchema(parameter.schema, document),\n description: parameter.description ?? parameter.schema?.description\n });\n\n if (parameter.required) {\n required.push(parameter.name);\n }\n }\n\n return {\n name: sectionName,\n required: required.length > 0,\n schema: compactObject({\n type: \"object\",\n properties,\n required: required.length ? required : undefined,\n additionalProperties: false\n })\n };\n};\n\nconst buildToolParameters = (\n document: OpenApiDocument,\n path: string,\n operation: OpenApiOperationObject,\n options: ConvertOpenApiOptions,\n pathParameters: import(\"./types\").OpenApiParameterObject[],\n queryParameters: import(\"./types\").OpenApiParameterObject[],\n headerParameters: import(\"./types\").OpenApiParameterObject[]\n): JsonSchema => {\n const requestBodySchema = pickContentSchema(operation.requestBody?.content);\n const properties: Record<string, JsonSchema> = {};\n const required: string[] = [];\n\n const sections = [\n buildParameterSection(\"path\", pathParameters, document),\n buildParameterSection(\"query\", queryParameters, document),\n options.includeHeaders ? buildParameterSection(\"headers\", headerParameters, document) : null\n ].filter((value): value is { name: string; schema: JsonSchema; required: boolean } => Boolean(value));\n\n for (const section of sections) {\n if (hasSchemaContent(section.schema)) {\n properties[section.name] = section.schema;\n if (section.required) {\n required.push(section.name);\n }\n }\n }\n\n if (requestBodySchema) {\n properties.body = openApiSchemaToJsonSchema(requestBodySchema, document);\n if (operation.requestBody?.required) {\n required.push(\"body\");\n }\n }\n\n return compactObject({\n type: \"object\",\n properties,\n required: required.length ? required : undefined,\n additionalProperties: false,\n description: `${operation.summary ?? operation.operationId ?? `${path} request`} tool arguments`\n });\n};\n\nconst buildToolDescription = (path: string, method: string, operation: OpenApiOperationObject): string => {\n const summary = operation.summary?.trim();\n const description = operation.description?.trim();\n\n if (summary && description && description !== summary) {\n return `${summary}. ${description}`;\n }\n\n if (summary) {\n return summary;\n }\n\n if (description) {\n return description;\n }\n\n return `${method.toUpperCase()} ${path}`;\n};\n\nconst buildToolDefinition = (\n document: OpenApiDocument,\n path: string,\n method: import(\"./types\").HttpMethod,\n operation: OpenApiOperationObject,\n options: ConvertOpenApiOptions,\n pathParameters: import(\"./types\").OpenApiParameterObject[],\n queryParameters: import(\"./types\").OpenApiParameterObject[],\n headerParameters: import(\"./types\").OpenApiParameterObject[]\n): OpenClawToolDefinition => {\n const operationId = buildOperationId(method, path, operation.operationId);\n\n return {\n name: buildToolName(options.toolPrefix, operationId),\n description: buildToolDescription(path, method, operation),\n method: method.toUpperCase() as Uppercase<typeof method>,\n path,\n operationId,\n parameters: buildToolParameters(\n document,\n path,\n operation,\n options,\n pathParameters,\n queryParameters,\n headerParameters\n ),\n tags: operation.tags ?? []\n };\n};\n\nexport const convertOpenApiToTools = (\n document: OpenApiDocument,\n options: ConvertOpenApiOptions\n): OpenClawPluginCatalog => {\n const tools: OpenClawToolDefinition[] = [];\n\n for (const [path, pathItem] of Object.entries(document.paths)) {\n for (const method of HTTP_METHODS) {\n const operation = pathItem[method];\n\n if (!operation) {\n continue;\n }\n\n const parameters = dedupeParameters(pathItem.parameters, operation.parameters);\n const pathParameters = parameters.filter((parameter) => parameter.in === \"path\");\n const queryParameters = parameters.filter((parameter) => parameter.in === \"query\");\n const headerParameters = parameters.filter(\n (parameter) =>\n parameter.in === \"header\" &&\n !AUTH_HEADER_NAMES.has(parameter.name.toLowerCase())\n );\n\n tools.push(\n buildToolDefinition(\n document,\n path,\n method,\n operation,\n options,\n pathParameters,\n queryParameters,\n headerParameters\n )\n );\n }\n }\n\n tools.sort((left, right) => left.name.localeCompare(right.name));\n\n return {\n pluginId: options.pluginId,\n pluginName: options.pluginName ?? toTitleCase(options.pluginId),\n description:\n document.info?.description?.trim() ??\n `Generated OpenClaw tool plugin for ${document.info?.title ?? options.pluginId}`,\n serverUrl: options.defaultServerUrl ?? document.servers?.[0]?.url,\n optional: options.optional ?? true,\n tools\n };\n};\n","import { HttpMethod, JsonSchema, OpenApiParameterObject } from \"./types\";\n\nexport const HTTP_METHODS: HttpMethod[] = [\n \"get\",\n \"post\",\n \"put\",\n \"patch\",\n \"delete\",\n \"options\",\n \"head\"\n];\n\nexport const AUTH_HEADER_NAMES = new Set([\n \"authorization\",\n \"x-api-key\",\n \"api-key\",\n \"dt-jwt\"\n]);\n\nexport const sanitizeIdentifier = (value: string): string =>\n value\n .trim()\n .replace(/[^a-zA-Z0-9]+/g, \"_\")\n .replace(/^_+|_+$/g, \"\")\n .replace(/_{2,}/g, \"_\")\n .toLowerCase() || \"tool\";\n\nexport const toTitleCase = (value: string): string =>\n value\n .split(/[^a-zA-Z0-9]+/)\n .filter(Boolean)\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join(\" \");\n\nexport const buildToolName = (toolPrefix: string | undefined, rawName: string): string => {\n const base = sanitizeIdentifier(rawName);\n const prefix = sanitizeIdentifier(toolPrefix ?? \"\");\n return prefix ? `${prefix}_${base}` : base;\n};\n\nexport const buildOperationId = (method: HttpMethod, path: string, operationId?: string): string => {\n if (operationId?.trim()) {\n return sanitizeIdentifier(operationId);\n }\n\n const pathPart = path\n .replace(/\\{([^}]+)\\}/g, \"by_$1\")\n .replace(/\\/+/g, \"_\");\n\n return sanitizeIdentifier(`${method}_${pathPart}`);\n};\n\nexport const pickContentSchema = (\n content: Record<string, { schema?: import(\"./types\").OpenApiSchemaObject | undefined }> | undefined\n): import(\"./types\").OpenApiSchemaObject | undefined =>\n content?.[\"application/json\"]?.schema ??\n content?.[\"application/*+json\"]?.schema ??\n Object.values(content ?? {})[0]?.schema;\n\nexport const dedupeParameters = (\n pathLevel: OpenApiParameterObject[] | undefined,\n operationLevel: OpenApiParameterObject[] | undefined\n): OpenApiParameterObject[] => {\n const byKey = new Map<string, OpenApiParameterObject>();\n\n for (const param of [...(pathLevel ?? []), ...(operationLevel ?? [])]) {\n byKey.set(`${param.in}:${param.name}`, param);\n }\n\n return [...byKey.values()];\n};\n\nexport const compactObject = <T extends Record<string, unknown>>(value: T): T => {\n const output = {} as T;\n\n for (const [key, item] of Object.entries(value)) {\n if (item !== undefined) {\n output[key as keyof T] = item as T[keyof T];\n }\n }\n\n return output;\n};\n\nexport const hasSchemaContent = (schema: JsonSchema | undefined): boolean =>\n Boolean(\n schema &&\n ((schema.properties && Object.keys(schema.properties).length > 0) ||\n (schema.required && schema.required.length > 0) ||\n schema.type ||\n schema.oneOf ||\n schema.anyOf ||\n schema.allOf)\n );\n","import { promises as fs } from \"node:fs\";\nimport path from \"node:path\";\nimport {\n ConvertOpenApiOptions,\n GeneratedPluginFiles,\n GeneratePluginOptions,\n OpenClawPluginCatalog\n} from \"./types\";\nimport { convertOpenApiToTools, loadOpenApiDocument } from \"./openapi\";\n\nconst serialize = (value: unknown): string => JSON.stringify(value, null, 2);\n\nexport const renderPluginManifest = (catalog: OpenClawPluginCatalog): string =>\n `${serialize({\n id: catalog.pluginId,\n name: catalog.pluginName,\n version: \"0.1.0\",\n description: catalog.description,\n configSchema: {\n type: \"object\",\n additionalProperties: false,\n properties: {\n baseUrl: {\n type: \"string\",\n description: \"Base URL of the target HTTP API\"\n },\n bearerToken: {\n type: \"string\",\n description: \"Bearer token used for Authorization header\"\n },\n apiKey: {\n type: \"string\",\n description: \"Static API key for the upstream API\"\n },\n apiKeyHeader: {\n type: \"string\",\n description: \"Header name used when apiKey is set\",\n default: \"x-api-key\"\n },\n timeoutMs: {\n type: \"number\",\n description: \"Timeout in milliseconds for outbound tool calls\"\n },\n defaultHeaders: {\n type: \"object\",\n additionalProperties: {\n type: \"string\"\n },\n description: \"Additional headers added to every request\"\n }\n }\n },\n uiHints: {\n baseUrl: {\n label: \"Base URL\",\n placeholder: catalog.serverUrl ?? \"https://api.example.com\"\n },\n bearerToken: {\n label: \"Bearer Token\",\n sensitive: true\n },\n apiKey: {\n label: \"API Key\",\n sensitive: true\n },\n apiKeyHeader: {\n label: \"API Key Header\"\n },\n timeoutMs: {\n label: \"Timeout (ms)\"\n }\n }\n })}\\n`;\n\nexport const renderPluginModule = (catalog: OpenClawPluginCatalog): string =>\n `import { createOpenApiPlugin } from \"@redonvn/open-claw-sdk\";\n\nexport const catalog = ${serialize(catalog)} as const;\n\nexport default createOpenApiPlugin(catalog);\n`;\n\nexport const renderCatalogFile = (catalog: OpenClawPluginCatalog): string =>\n `${serialize(catalog)}\\n`;\n\nconst ensureDir = async (dirPath: string): Promise<void> => {\n await fs.mkdir(dirPath, { recursive: true });\n};\n\nexport const writeGeneratedPlugin = async (\n catalog: OpenClawPluginCatalog,\n outDir: string\n): Promise<GeneratedPluginFiles> => {\n await ensureDir(outDir);\n\n const manifestPath = path.join(outDir, \"openclaw.plugin.json\");\n const indexPath = path.join(outDir, \"index.ts\");\n const catalogPath = path.join(outDir, \"tool-catalog.json\");\n\n await Promise.all([\n fs.writeFile(manifestPath, renderPluginManifest(catalog), \"utf8\"),\n fs.writeFile(indexPath, renderPluginModule(catalog), \"utf8\"),\n fs.writeFile(catalogPath, renderCatalogFile(catalog), \"utf8\")\n ]);\n\n return { manifestPath, indexPath, catalogPath };\n};\n\nexport const generatePluginFromOpenApi = async (\n options: GeneratePluginOptions\n): Promise<{ catalog: OpenClawPluginCatalog; files: GeneratedPluginFiles }> => {\n const document = await loadOpenApiDocument(options.input);\n const convertOptions: ConvertOpenApiOptions = {\n pluginId: options.pluginId,\n pluginName: options.pluginName,\n toolPrefix: options.toolPrefix,\n optional: options.optional,\n includeHeaders: options.includeHeaders,\n defaultServerUrl: options.defaultServerUrl\n };\n const catalog = convertOpenApiToTools(document, convertOptions);\n const files = await writeGeneratedPlugin(catalog, options.outDir);\n\n return { catalog, files };\n};\n"],"mappings":"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","names":["path","path","fs","fs"]}