History

Migrate sources to IR catalog snapshots

Rhys Sullivan committed 8 months ago

Commit 5e6d0591 parent 31ad09078 files · +7562 −3187Browse files

Showing the changes to packages/codemode-openapi/src (8 of 78 files). Show all

Unified · Split

8 files
  1. packages/codemode-openapi/src/index.ts +3 −3
  2. packages/codemode-openapi/src/openapi-definitions.ts +2 −3
  3. packages/codemode-openapi/src/openapi-extraction.real-specs.test.ts +3 −3
  4. packages/codemode-openapi/src/openapi-schema-refs.ts +15 −25
  5. packages/codemode-openapi/src/openapi-tool-presentation.ts +71 −49
  6. packages/codemode-openapi/src/openapi-tools.test.ts +2 −2
  7. packages/codemode-openapi/src/openapi-tools.ts +23 −15
  8. packages/codemode-openapi/src/openapi-types.ts +2 −2
packages/codemode-openapi/src/index.ts+3−3
@@ -8,13 +8,13 @@ export { · 7 unmodified lines
88 } from "./openapi-extraction";
99 export {
1010 compileOpenApiToolDefinitions,
11− openApiProviderDataJsonFromDefinition,
11+ openApiProviderDataFromDefinition,
1212 OpenApiToolDefinitionSchema,
1313 type OpenApiToolDefinition,
1414 } from "./openapi-definitions";
1515 export {
1616 buildOpenApiToolPresentation,
17− openApiOutputTypeSignatureFromSchemaJson,
17+ openApiOutputTypeSignatureFromSchema,
1818 type OpenApiToolPresentation,
1919 } from "./openapi-tool-presentation";
2020 export {
@@ -23,7 +23,7 @@ export { · 2 unmodified lines
2323 createOpenApiToolsFromManifest,
2424 createOpenApiToolsFromSpec,
2525 } from "./openapi-tools";
26−export { resolveSchemaJsonWithRefHints, resolveTypingSchemasWithRefHints } from "./openapi-schema-refs";
26+export { resolveSchemaWithRefHints, resolveTypingSchemasWithRefHints } from "./openapi-schema-refs";
2727 export {
2828 OPEN_API_HTTP_METHODS,
2929 OPEN_API_PARAMETER_LOCATIONS,
packages/codemode-openapi/src/openapi-definitions.ts+2−3
@@ -236,10 +236,9 @@ export const compileOpenApiToolDefinitions = ( · 235 unmodified lines
236236 );
237237 };
238238
239−export const openApiProviderDataJsonFromDefinition = (
239+export const openApiProviderDataFromDefinition = (
240240 definition: OpenApiToolDefinition,
241−): string =>
242− JSON.stringify({
241+): typeof OpenApiToolProviderDataSchema.Type => ({
243242 kind: "openapi",
244243 toolId: definition.toolId,
245244 rawToolId: definition.rawToolId,
packages/codemode-openapi/src/openapi-extraction.real-specs.test.ts+3−3
@@ -26,8 +26,8 @@ type ParsedInputSchema = { · 25 unmodified lines
2626 required?: Array<string>;
2727 };
2828
29−const parseInputSchema = (inputSchemaJson: string | undefined): ParsedInputSchema | null =>
30− inputSchemaJson ? (JSON.parse(inputSchemaJson) as ParsedInputSchema) : null;
29+const parseInputSchema = (inputSchema: unknown): ParsedInputSchema | null =>
30+ inputSchema ? (inputSchema as ParsedInputSchema) : null;
3131
3232 const expectedTools = [
3333 {
@@ -89,7 +89,7 @@ describe("openapi-extraction real specs", () => { · 55 unmodified lines
8989 expect(tool?.path).toBe(expectedTool.path);
9090 expect(tool?.tags).toEqual(expectedTool.tags);
9191
92− const inputSchema = parseInputSchema(tool?.typing?.inputSchemaJson);
92+ const inputSchema = parseInputSchema(tool?.typing?.inputSchema);
9393 expect(inputSchema?.type).toBe("object");
9494 expect(Object.keys(inputSchema?.properties ?? {})).toEqual(
9595 expect.arrayContaining([...expectedTool.requiredInputs]),
packages/codemode-openapi/src/openapi-schema-refs.ts+15−25
@@ -2,8 +2,8 @@ type JsonObject = Record<string, unknown>; · 1 unmodified line
22 type RefHintValue = string | JsonObject;
33
44 type DiscoveryTypingLike = {
5− inputSchemaJson?: string;
6− outputSchemaJson?: string;
5+ inputSchema?: unknown;
6+ outputSchema?: unknown;
77 };
88
99 const isJsonObject = (value: unknown): value is JsonObject =>
@@ -92,50 +92,40 @@ const resolveSchemaNode = ( · 82 unmodified lines
9292 return next;
9393 };
9494
95−export const resolveSchemaJsonWithRefHints = (
96− schemaJson: string | undefined,
95+export const resolveSchemaWithRefHints = (
96+ schema: unknown,
9797 refHintTable: Readonly<Record<string, RefHintValue>> | undefined,
98−): string | null => {
99− if (!schemaJson) {
98+): unknown | null => {
99+ if (schema === undefined || schema === null) {
100100 return null;
101101 }
102102
103− const parsedSchema = parseJson(schemaJson);
104− if (parsedSchema === null) {
105− return schemaJson;
106− }
107−
108103 if (!refHintTable || Object.keys(refHintTable).length === 0) {
109− return schemaJson;
104+ return schema;
110105 }
111106
112107 const resolved = resolveSchemaNode(
113− parsedSchema,
108+ schema,
114109 refHintTable,
115110 new Map<string, unknown>(),
116111 new Set<string>(),
117112 );
118−
119− try {
120− return JSON.stringify(resolved);
121− } catch {
122− return schemaJson;
123− }
113+ return resolved;
124114 };
125115
126116 export const resolveTypingSchemasWithRefHints = (
127117 typing: DiscoveryTypingLike | undefined,
128118 refHintTable: Readonly<Record<string, RefHintValue>> | undefined,
129119 ): {
130− inputSchemaJson: string | null;
131− outputSchemaJson: string | null;
120+ inputSchema: unknown | null;
121+ outputSchema: unknown | null;
132122 } => ({
133− inputSchemaJson: resolveSchemaJsonWithRefHints(
134− typing?.inputSchemaJson,
123+ inputSchema: resolveSchemaWithRefHints(
124+ typing?.inputSchema,
135125 refHintTable,
136126 ),
137− outputSchemaJson: resolveSchemaJsonWithRefHints(
138− typing?.outputSchemaJson,
127+ outputSchema: resolveSchemaWithRefHints(
128+ typing?.outputSchema,
139129 refHintTable,
140130 ),
141131 });
packages/codemode-openapi/src/openapi-tool-presentation.ts+71−49
@@ -1,22 +1,16 @@
1−import { typeSignatureFromSchemaJson } from "@executor/codemode-core";
1+import { typeSignatureFromSchema } from "@executor/codemode-core";
22
33 import type {
44 OpenApiExample,
5+ OpenApiInvocationPayload,
56 OpenApiToolDocumentation,
7+ OpenApiToolProviderData,
68 } from "./openapi-types";
79 import {
8− openApiProviderDataJsonFromDefinition,
10+ openApiProviderDataFromDefinition,
911 type OpenApiToolDefinition,
1012 } from "./openapi-definitions";
1113
12−const parseJson = (value: string): unknown | undefined => {
13− try {
14− return JSON.parse(value) as unknown;
15− } catch {
16− return undefined;
17− }
18−};
19−
2014 const asRecord = (value: unknown): Record<string, unknown> =>
2115 typeof value === "object" && value !== null && !Array.isArray(value)
2216 ? (value as Record<string, unknown>)
@@ -32,33 +26,62 @@ const isStrictEmptyObjectSchema = (value: unknown): boolean => { · 9 unmodified lines
3226 return Object.keys(properties).length === 0 && schema.additionalProperties === false;
3327 };
3428
35−export const openApiOutputTypeSignatureFromSchemaJson = (
36− schemaJson: string | undefined,
29+export const openApiOutputTypeSignatureFromSchema = (
30+ schema: unknown,
3731 maxLength: number = 320,
3832 ): string => {
39− if (!schemaJson) {
33+ if (schema === undefined || schema === null) {
4034 return "void";
4135 }
4236
43− const parsed = parseJson(schemaJson);
44− if (parsed === undefined) {
45− return "unknown";
46− }
47−
48− if (isStrictEmptyObjectSchema(parsed)) {
37+ if (isStrictEmptyObjectSchema(schema)) {
4938 return "{}";
5039 }
5140
52− return typeSignatureFromSchemaJson(schemaJson, "unknown", maxLength);
41+ return typeSignatureFromSchema(schema, "unknown", maxLength);
5342 };
5443
5544 const firstExample = (
5645 examples: ReadonlyArray<OpenApiExample> | undefined,
5746 ): OpenApiExample | undefined => examples?.[0];
5847
59−const buildExampleInputJson = (
48+const fallbackInputSchemaFromInvocation = (
49+ invocation: OpenApiInvocationPayload,
50+): Record<string, unknown> | undefined => {
51+ const properties: Record<string, unknown> = {};
52+ const required: string[] = [];
53+
54+ for (const parameter of invocation.parameters) {
55+ properties[parameter.name] = {
56+ type: "string",
57+ };
58+ if (parameter.required) {
59+ required.push(parameter.name);
60+ }
61+ }
62+
63+ if (invocation.requestBody) {
64+ properties.body = {
65+ type: "object",
66+ };
67+ if (invocation.requestBody.required) {
68+ required.push("body");
69+ }
70+ }
71+
72+ return Object.keys(properties).length > 0
73+ ? {
74+ type: "object",
75+ properties,
76+ ...(required.length > 0 ? { required } : {}),
77+ additionalProperties: false,
78+ }
79+ : undefined;
80+};
81+
82+const buildExampleInput = (
6083 documentation: OpenApiToolDocumentation | undefined,
61−): string | undefined => {
84+): Record<string, unknown> | undefined => {
6285 if (!documentation) {
6386 return undefined;
6487 }
@@ -71,52 +94,51 @@ const buildExampleInputJson = ( · 6 unmodified lines
7194 continue;
7295 }
7396
74− const parsedValue = parseJson(example.valueJson);
75− if (parsedValue !== undefined) {
76− input[parameter.name] = parsedValue;
77− }
97+ input[parameter.name] = JSON.parse(example.valueJson) as unknown;
7898 }
7999
80100 const requestBodyExample = firstExample(documentation.requestBody?.examples);
81101 if (requestBodyExample) {
82− const parsedValue = parseJson(requestBodyExample.valueJson);
83− if (parsedValue !== undefined) {
84− input.body = parsedValue;
85− }
102+ input.body = JSON.parse(requestBodyExample.valueJson) as unknown;
86103 }
87104
88− return Object.keys(input).length > 0 ? JSON.stringify(input) : undefined;
105+ return Object.keys(input).length > 0 ? input : undefined;
89106 };
90107
91−const buildExampleOutputJson = (
108+const buildExampleOutput = (
92109 documentation: OpenApiToolDocumentation | undefined,
93−): string | undefined => firstExample(documentation?.response?.examples)?.valueJson;
110+): unknown | undefined => {
111+ const example = firstExample(documentation?.response?.examples)?.valueJson;
112+ return example ? JSON.parse(example) as unknown : undefined;
113+};
94114
95115 export type OpenApiToolPresentation = {
96116 inputType: string;
97117 outputType: string;
98− inputSchemaJson?: string;
99− outputSchemaJson?: string;
100− exampleInputJson?: string;
101− exampleOutputJson?: string;
102− providerDataJson: string;
118+ inputSchema?: unknown;
119+ outputSchema?: unknown;
120+ exampleInput?: unknown;
121+ exampleOutput?: unknown;
122+ providerData: OpenApiToolProviderData;
103123 };
104124
105125 export const buildOpenApiToolPresentation = (input: {
106126 definition: OpenApiToolDefinition;
107127 }): OpenApiToolPresentation => {
108− const inputSchemaJson = input.definition.typing?.inputSchemaJson;
109− const outputSchemaJson = input.definition.typing?.outputSchemaJson;
110− const exampleInputJson = buildExampleInputJson(input.definition.documentation);
111− const exampleOutputJson = buildExampleOutputJson(input.definition.documentation);
128+ const inputSchema =
129+ input.definition.typing?.inputSchema
130+ ?? fallbackInputSchemaFromInvocation(input.definition.invocation);
131+ const outputSchema = input.definition.typing?.outputSchema;
132+ const exampleInput = buildExampleInput(input.definition.documentation);
133+ const exampleOutput = buildExampleOutput(input.definition.documentation);
112134
113135 return {
114− inputType: typeSignatureFromSchemaJson(inputSchemaJson, "unknown", Infinity),
115− outputType: openApiOutputTypeSignatureFromSchemaJson(outputSchemaJson, Infinity),
116− ...(inputSchemaJson ? { inputSchemaJson } : {}),
117− ...(outputSchemaJson ? { outputSchemaJson } : {}),
118− ...(exampleInputJson ? { exampleInputJson } : {}),
119− ...(exampleOutputJson ? { exampleOutputJson } : {}),
120− providerDataJson: openApiProviderDataJsonFromDefinition(input.definition),
136+ inputType: typeSignatureFromSchema(inputSchema, "unknown", Infinity),
137+ outputType: openApiOutputTypeSignatureFromSchema(outputSchema, Infinity),
138+ ...(inputSchema !== undefined ? { inputSchema } : {}),
139+ ...(outputSchema !== undefined ? { outputSchema } : {}),
140+ ...(exampleInput !== undefined ? { exampleInput } : {}),
141+ ...(exampleOutput !== undefined ? { exampleOutput } : {}),
142+ providerData: openApiProviderDataFromDefinition(input.definition),
121143 };
122144 };
packages/codemode-openapi/src/openapi-tools.test.ts+2−2
@@ -291,8 +291,8 @@ describe("openapi-tools", () => { · 290 unmodified lines
291291 const resolvedGet = resolveToolDefinition(tools["source.demo.repos.getRepo"]!);
292292 expect(resolvedGet.metadata?.sourceKey).toBe("api.demo");
293293 expect(resolvedGet.metadata?.providerKind).toBe("openapi");
294− expect(resolvedGet.metadata?.providerDataJson).toContain('"group":"repos"');
295− expect(resolvedGet.metadata?.inputSchemaJson).toBeDefined();
294+ expect(resolvedGet.metadata?.providerData).toMatchObject({ group: "repos" });
295+ expect(resolvedGet.metadata?.inputSchema).toBeDefined();
296296 }),
297297 );
298298
packages/codemode-openapi/src/openapi-tools.ts+23−15
@@ -23,7 +23,7 @@ import { · 22 unmodified lines
2323 type OpenApiToolDefinition,
2424 } from "./openapi-definitions";
2525 import { buildOpenApiToolPresentation } from "./openapi-tool-presentation";
26−import { resolveSchemaJsonWithRefHints } from "./openapi-schema-refs";
26+import { resolveSchemaWithRefHints } from "./openapi-schema-refs";
2727 import {
2828 extractOpenApiManifest,
2929 type OpenApiExtractionError,
@@ -262,21 +262,21 @@ const summarizeHttpResponseBody = (body: unknown): string | null => { · 232 unmodified lines
262262 }
263263 };
264264
265−const inputSchemaFromTypingJson = (input: {
266− inputSchemaJson: string | undefined;
265+const inputSchemaFromTyping = (input: {
266+ inputSchema: unknown;
267267 refHintTable?: Readonly<OpenApiRefHintTable>;
268268 }) => {
269− const resolvedSchemaJson = resolveSchemaJsonWithRefHints(
270− input.inputSchemaJson,
269+ const resolvedSchema = resolveSchemaWithRefHints(
270+ input.inputSchema,
271271 input.refHintTable,
272− ) ?? input.inputSchemaJson;
272+ ) ?? input.inputSchema;
273273
274− if (!resolvedSchemaJson) {
274+ if (resolvedSchema === undefined || resolvedSchema === null) {
275275 return unknownInputSchema;
276276 }
277277
278278 try {
279− return standardSchemaFromJsonSchema(JSON.parse(resolvedSchemaJson), {
279+ return standardSchemaFromJsonSchema(resolvedSchema, {
280280 vendor: "openapi",
281281 fallback: unknownInputSchema,
282282 });
@@ -469,8 +469,8 @@ export const createOpenApiToolFromDefinition = ( · 186 unmodified lines
469469 return toTool({
470470 tool: {
471471 description: input.definition.description,
472− inputSchema: inputSchemaFromTypingJson({
473− inputSchemaJson: presentation.inputSchemaJson ?? input.definition.typing?.inputSchemaJson,
472+ inputSchema: inputSchemaFromTyping({
473+ inputSchema: presentation.inputSchema ?? input.definition.typing?.inputSchema,
474474 refHintTable: input.refHintTable,
475475 }),
476476 execute: async (args: unknown) => {
@@ -526,12 +526,20 @@ export const createOpenApiToolFromDefinition = ( · 49 unmodified lines
526526 sourceKey: input.sourceKey,
527527 inputType: presentation.inputType,
528528 outputType: presentation.outputType,
529− inputSchemaJson: presentation.inputSchemaJson,
530− outputSchemaJson: presentation.outputSchemaJson,
531− exampleInputJson: presentation.exampleInputJson,
532− exampleOutputJson: presentation.exampleOutputJson,
529+ ...((presentation.inputSchema ?? input.definition.typing?.inputSchema) !== undefined
530+ ? { inputSchema: presentation.inputSchema ?? input.definition.typing?.inputSchema }
531+ : {}),
532+ ...((presentation.outputSchema ?? input.definition.typing?.outputSchema) !== undefined
533+ ? { outputSchema: presentation.outputSchema ?? input.definition.typing?.outputSchema }
534+ : {}),
535+ ...(presentation.exampleInput !== undefined
536+ ? { exampleInput: presentation.exampleInput }
537+ : {}),
538+ ...(presentation.exampleOutput !== undefined
539+ ? { exampleOutput: presentation.exampleOutput }
540+ : {}),
533541 providerKind: "openapi",
534− providerDataJson: presentation.providerDataJson,
542+ providerData: presentation.providerData,
535543 },
536544 });
537545 };
packages/codemode-openapi/src/openapi-types.ts+2−2
@@ -58,8 +58,8 @@ export const OpenApiInvocationPayloadSchema = Schema.Struct({ · 57 unmodified lines
5858 });
5959
6060 export const DiscoveryTypingPayloadSchema = Schema.Struct({
61− inputSchemaJson: Schema.optional(Schema.String),
62− outputSchemaJson: Schema.optional(Schema.String),
61+ inputSchema: Schema.optional(Schema.Unknown),
62+ outputSchema: Schema.optional(Schema.Unknown),
6363 refHintKeys: Schema.optional(Schema.Array(Schema.String)),
6464 });
6565