@sdk-it/typescript 0.27.0 → 0.28.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.
- package/dist/index.js +89 -38
- package/dist/index.js.map +4 -4
- package/dist/lib/generate.d.ts +2 -0
- package/dist/lib/generate.d.ts.map +1 -1
- package/dist/lib/options.d.ts +1 -0
- package/dist/lib/options.d.ts.map +1 -1
- package/dist/lib/readme/prop.emitter.d.ts +1 -1
- package/dist/lib/readme/prop.emitter.d.ts.map +1 -1
- package/dist/lib/readme/readme.d.ts.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -13,11 +13,15 @@ import {
|
|
|
13
13
|
import {
|
|
14
14
|
augmentSpec,
|
|
15
15
|
cleanFiles,
|
|
16
|
+
forEachOperation as forEachOperation4,
|
|
16
17
|
readWriteMetadata,
|
|
17
18
|
sanitizeTag as sanitizeTag4,
|
|
18
19
|
securityToOptions as securityToOptions2
|
|
19
20
|
} from "@sdk-it/spec";
|
|
20
21
|
|
|
22
|
+
// packages/typescript/src/lib/agent/utils.txt
|
|
23
|
+
var utils_default = "function coerceContext(context?: any) {\n if (!context) {\n throw new Error('Context is required');\n }\n return context as {\n client: any\n };\n}\n/**\n * Takes a Zod object schema and makes all optional properties nullable as well.\n * This is useful for APIs where optional fields can be explicitly set to null.\n *\n * @param schema - The Zod object schema to transform\n * @returns A new Zod schema with optional properties made nullable\n */\nfunction makeOptionalPropsNullable<T extends z.ZodRawShape>(\n schema: z.ZodObject<T>,\n) {\n const shape = schema.shape;\n const newShape = {} as Record<string, z.ZodTypeAny>;\n\n for (const [key, value] of Object.entries(shape)) {\n if (value instanceof z.ZodOptional) {\n // Make optional properties also nullable\n newShape[key] = value._def.innerType.nullable().optional();\n } else {\n // Keep non-optional properties as they are\n newShape[key] = value;\n }\n }\n\n return z.object(newShape);\n}";
|
|
24
|
+
|
|
21
25
|
// packages/typescript/src/lib/client.ts
|
|
22
26
|
import { toLitObject } from "@sdk-it/core";
|
|
23
27
|
|
|
@@ -1639,7 +1643,7 @@ var PropEmitter = class {
|
|
|
1639
1643
|
const defaultVal = !isRef4(schema) && schema.default !== void 0 ? ` default: ${JSON.stringify(schema.default)}` : "";
|
|
1640
1644
|
const reqMark = required ? " required" : "";
|
|
1641
1645
|
const summary = `- \`${name}\` ${rawType}${reqMark}${defaultVal}:`;
|
|
1642
|
-
const detailLines = docs.slice(1).filter((
|
|
1646
|
+
const detailLines = docs.slice(1).filter((it) => !it.startsWith("**Default:**")).map((it) => ` ${it}`);
|
|
1643
1647
|
return [summary, ...detailLines];
|
|
1644
1648
|
}
|
|
1645
1649
|
/**
|
|
@@ -1849,35 +1853,29 @@ var PropEmitter = class {
|
|
|
1849
1853
|
* Process a request body and return markdown documentation
|
|
1850
1854
|
*/
|
|
1851
1855
|
requestBody(requestBody) {
|
|
1852
|
-
if (!requestBody) return [];
|
|
1853
1856
|
const lines = [];
|
|
1854
|
-
lines.push(
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
if (
|
|
1859
|
-
const
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
lines.push(
|
|
1857
|
+
lines.push(`#### Input`);
|
|
1858
|
+
lines.push(requestBody.description || "");
|
|
1859
|
+
const contentEntries = Object.entries(requestBody.content);
|
|
1860
|
+
const multipleContentTypes = contentEntries.length > 1;
|
|
1861
|
+
if (multipleContentTypes) {
|
|
1862
|
+
for (const [contentType, mediaType] of contentEntries) {
|
|
1863
|
+
lines.push(`<details>`);
|
|
1864
|
+
lines.push(`<summary>Content Type: \`${contentType}\`</summary>`);
|
|
1865
|
+
lines.push("");
|
|
1863
1866
|
if (mediaType.schema) {
|
|
1864
1867
|
const schemaDocs = this.handle(mediaType.schema);
|
|
1865
|
-
lines.push(...schemaDocs);
|
|
1866
|
-
}
|
|
1867
|
-
} else {
|
|
1868
|
-
for (const [contentType, mediaType] of contentEntries) {
|
|
1869
|
-
lines.push(`<details>`);
|
|
1870
|
-
lines.push(
|
|
1871
|
-
`<summary><b>Content Type:</b> \`${contentType}\`</summary>`
|
|
1872
|
-
);
|
|
1873
|
-
lines.push("");
|
|
1874
|
-
if (mediaType.schema) {
|
|
1875
|
-
const schemaDocs = this.handle(mediaType.schema);
|
|
1876
|
-
lines.push(...schemaDocs.map((l) => l));
|
|
1877
|
-
}
|
|
1878
|
-
lines.push("");
|
|
1879
|
-
lines.push(`</details>`);
|
|
1868
|
+
lines.push(...schemaDocs.map((l) => l));
|
|
1880
1869
|
}
|
|
1870
|
+
lines.push("");
|
|
1871
|
+
lines.push(`</details>`);
|
|
1872
|
+
}
|
|
1873
|
+
} else {
|
|
1874
|
+
const [contentType, mediaType] = contentEntries[0];
|
|
1875
|
+
lines.push(`Content Type: \`${contentType}\``);
|
|
1876
|
+
if (mediaType.schema) {
|
|
1877
|
+
const schemaDocs = this.handle(mediaType.schema);
|
|
1878
|
+
lines.push(...schemaDocs);
|
|
1881
1879
|
}
|
|
1882
1880
|
}
|
|
1883
1881
|
return lines;
|
|
@@ -1915,37 +1913,49 @@ function toReadme(spec, generator) {
|
|
|
1915
1913
|
forEachOperation2(spec, (entry, operation) => {
|
|
1916
1914
|
const { method, path } = entry;
|
|
1917
1915
|
markdown.push(
|
|
1918
|
-
|
|
1916
|
+
`### ${operation["x-fn-name"]} | ${`_${method.toUpperCase()} ${path}_`}`
|
|
1919
1917
|
);
|
|
1920
1918
|
markdown.push(operation.summary || "");
|
|
1921
1919
|
const snippet = generator.snippet(entry, operation);
|
|
1922
|
-
markdown.push(
|
|
1920
|
+
markdown.push(`#### Example usage`);
|
|
1923
1921
|
markdown.push(snippet);
|
|
1924
1922
|
const requestBodyContent = propEmitter.requestBody(operation.requestBody);
|
|
1925
1923
|
if (requestBodyContent.length > 1) {
|
|
1926
1924
|
markdown.push(requestBodyContent.join("\n\n"));
|
|
1927
1925
|
}
|
|
1928
|
-
markdown.push(
|
|
1926
|
+
markdown.push(`#### Output`);
|
|
1929
1927
|
for (const status in operation.responses) {
|
|
1930
1928
|
const response = operation.responses[status];
|
|
1931
|
-
markdown.push(`<details>`);
|
|
1932
|
-
markdown.push(
|
|
1933
|
-
`<summary><b>${status}</b> <i>${response.description}</i></summary>`
|
|
1934
|
-
);
|
|
1935
1929
|
if (!isEmpty3(response.content)) {
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1930
|
+
const contentEntries = Object.entries(response.content);
|
|
1931
|
+
if (contentEntries.length === 1) {
|
|
1932
|
+
const [contentType, mediaType] = contentEntries[0];
|
|
1933
|
+
markdown.push(`**${status}** - ${response.description}`);
|
|
1939
1934
|
markdown.push(`
|
|
1940
1935
|
**Content Type:** \`${contentType}\``);
|
|
1941
1936
|
if (mediaType.schema) {
|
|
1942
1937
|
const schemaDocs = propEmitter.handle(mediaType.schema);
|
|
1943
|
-
markdown.push(...schemaDocs
|
|
1938
|
+
markdown.push(...schemaDocs);
|
|
1939
|
+
}
|
|
1940
|
+
} else {
|
|
1941
|
+
markdown.push(`<details>`);
|
|
1942
|
+
markdown.push(
|
|
1943
|
+
`<summary><b>${status}</b> <i>${response.description}</i></summary>`
|
|
1944
|
+
);
|
|
1945
|
+
for (const [contentType, mediaType] of contentEntries) {
|
|
1946
|
+
markdown.push(`
|
|
1947
|
+
**Content Type:** \`${contentType}\``);
|
|
1948
|
+
if (mediaType.schema) {
|
|
1949
|
+
const schemaDocs = propEmitter.handle(mediaType.schema);
|
|
1950
|
+
markdown.push(...schemaDocs.map((l) => `
|
|
1944
1951
|
${l}`));
|
|
1952
|
+
}
|
|
1945
1953
|
}
|
|
1954
|
+
markdown.push(`</details>`);
|
|
1946
1955
|
}
|
|
1956
|
+
} else {
|
|
1957
|
+
markdown.push(`**${status}** - ${response.description}`);
|
|
1947
1958
|
}
|
|
1948
|
-
markdown.push(`</details>`);
|
|
1949
1959
|
}
|
|
1950
1960
|
});
|
|
1951
1961
|
if (spec.components?.schemas) {
|
|
@@ -3070,6 +3080,12 @@ ${template2(dispatcher_default, {})({ throwError: !style.errorAsValue, outputTyp
|
|
|
3070
3080
|
"models/index.ts": modelsIndex
|
|
3071
3081
|
// ...(modelsImports.length ? { 'models/index.ts': modelsIndex } : {}),
|
|
3072
3082
|
});
|
|
3083
|
+
if (settings.agentTools) {
|
|
3084
|
+
await settings.writer(output, {
|
|
3085
|
+
"agents.ts": `${generateAgentTools(spec)}
|
|
3086
|
+
${utils_default}`
|
|
3087
|
+
});
|
|
3088
|
+
}
|
|
3073
3089
|
await settings.writer(output, {
|
|
3074
3090
|
"index.ts": await getFolderExports(
|
|
3075
3091
|
output,
|
|
@@ -3228,9 +3244,44 @@ function toInputs(operationsSet, commonZod, makeImport) {
|
|
|
3228
3244
|
...inputs
|
|
3229
3245
|
};
|
|
3230
3246
|
}
|
|
3247
|
+
function generateAgentTools(spec) {
|
|
3248
|
+
const groups = {};
|
|
3249
|
+
forEachOperation4(spec, (entry, operation) => {
|
|
3250
|
+
groups[entry.tag] ??= [];
|
|
3251
|
+
groups[entry.tag].push(createTool(entry, operation));
|
|
3252
|
+
});
|
|
3253
|
+
const imports = [
|
|
3254
|
+
`import { z } from 'zod';`,
|
|
3255
|
+
`import { tool } from '@openai/agents';`,
|
|
3256
|
+
`import * as schemas from './inputs/index.ts';`
|
|
3257
|
+
];
|
|
3258
|
+
const tools = Object.entries(groups).map(([group, tools2]) => {
|
|
3259
|
+
return `export const ${spinalcase3(group)} = [${tools2.join(", ")}];`;
|
|
3260
|
+
});
|
|
3261
|
+
return [...imports, ...tools].join("\n\n");
|
|
3262
|
+
}
|
|
3263
|
+
function createTool(entry, operation) {
|
|
3264
|
+
const schemaName = camelcase4(`${operation.operationId} schema`);
|
|
3265
|
+
return `tool({
|
|
3266
|
+
description: \`${operation.description || operation.summary}\`,
|
|
3267
|
+
name: '${operation["x-fn-name"]}',
|
|
3268
|
+
parameters: makeOptionalPropsNullable(schemas.${schemaName}),
|
|
3269
|
+
execute: async (input, maybeContext) => {
|
|
3270
|
+
console.log('Executing ${operation.operationId} tool with input:', input);
|
|
3271
|
+
const context = coerceContext(maybeContext?.context);
|
|
3272
|
+
const client = context.client;
|
|
3273
|
+
const response = await client.request(
|
|
3274
|
+
'${entry.method.toUpperCase()} ${entry.path}' ,
|
|
3275
|
+
input as any,
|
|
3276
|
+
);
|
|
3277
|
+
return JSON.stringify(response);
|
|
3278
|
+
},
|
|
3279
|
+
})`;
|
|
3280
|
+
}
|
|
3231
3281
|
export {
|
|
3232
3282
|
TypeScriptGenerator,
|
|
3233
3283
|
generate,
|
|
3284
|
+
generateAgentTools,
|
|
3234
3285
|
toInputs
|
|
3235
3286
|
};
|
|
3236
3287
|
//# sourceMappingURL=index.js.map
|