@executor-js/plugin-openapi 1.5.16 → 1.5.18
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/{AddOpenApiSource-U7AYB224.js → AddOpenApiSource-IBZQRCTW.js} +4 -4
- package/dist/{OpenApiAccountsPanel-GHFHHE6P.js → OpenApiAccountsPanel-U47OVLYG.js} +3 -3
- package/dist/{UpdateSpecSection-PLCBUU4I.js → UpdateSpecSection-FFYVB3VH.js} +3 -3
- package/dist/{chunk-CPPTKUOW.js → chunk-2RNIMASA.js} +2 -2
- package/dist/{chunk-CKBX4SXK.js → chunk-5IDND4UF.js} +2 -2
- package/dist/{chunk-3FM2SWM4.js → chunk-ELCKZJE4.js} +236 -210
- package/dist/chunk-ELCKZJE4.js.map +1 -0
- package/dist/{chunk-KVPUDOJZ.js → chunk-R3X27XS6.js} +587 -77
- package/dist/chunk-R3X27XS6.js.map +1 -0
- package/dist/client.js +3 -3
- package/dist/core.js +27 -3
- package/dist/core.js.map +1 -1
- package/dist/index.js +3 -3
- package/dist/sdk/backing.d.ts +91 -1
- package/dist/sdk/definitions.d.ts +33 -1
- package/dist/sdk/extract.d.ts +66 -0
- package/dist/sdk/index.d.ts +3 -2
- package/dist/sdk/request-user-agent.test.d.ts +1 -0
- package/dist/sdk/split.d.ts +84 -0
- package/dist/sdk/store.d.ts +19 -0
- package/package.json +3 -3
- package/dist/chunk-3FM2SWM4.js.map +0 -1
- package/dist/chunk-KVPUDOJZ.js.map +0 -1
- /package/dist/{AddOpenApiSource-U7AYB224.js.map → AddOpenApiSource-IBZQRCTW.js.map} +0 -0
- /package/dist/{OpenApiAccountsPanel-GHFHHE6P.js.map → OpenApiAccountsPanel-U47OVLYG.js.map} +0 -0
- /package/dist/{UpdateSpecSection-PLCBUU4I.js.map → UpdateSpecSection-FFYVB3VH.js.map} +0 -0
- /package/dist/{chunk-CPPTKUOW.js.map → chunk-2RNIMASA.js.map} +0 -0
- /package/dist/{chunk-CKBX4SXK.js.map → chunk-5IDND4UF.js.map} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
deriveAuthenticationTemplateFromPreview,
|
|
3
3
|
firstBaseUrlForPreview
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-5IDND4UF.js";
|
|
5
5
|
import {
|
|
6
6
|
openApiPresets
|
|
7
7
|
} from "./chunk-QQFCICLX.js";
|
|
@@ -11,13 +11,19 @@ import {
|
|
|
11
11
|
OpenApiInvocationError,
|
|
12
12
|
OpenApiParseError,
|
|
13
13
|
OperationBinding,
|
|
14
|
+
buildInputSchema,
|
|
15
|
+
compileToolDefinitions,
|
|
14
16
|
extract,
|
|
15
17
|
normalizeOpenApiAuthInputs,
|
|
16
18
|
parse,
|
|
19
|
+
parseEntry,
|
|
17
20
|
previewSpecText,
|
|
18
21
|
resolveServerUrl,
|
|
19
|
-
resolveSpecText
|
|
20
|
-
|
|
22
|
+
resolveSpecText,
|
|
23
|
+
streamOperationBindings,
|
|
24
|
+
streamOperationBindingsFromStructure,
|
|
25
|
+
structuralSplit
|
|
26
|
+
} from "./chunk-R3X27XS6.js";
|
|
21
27
|
|
|
22
28
|
// src/sdk/config.ts
|
|
23
29
|
import { Option, Schema } from "effect";
|
|
@@ -78,7 +84,12 @@ var toJsonRecord = (value) => value;
|
|
|
78
84
|
var OperationStorage = Schema2.Struct({
|
|
79
85
|
integration: Schema2.String,
|
|
80
86
|
toolName: Schema2.String,
|
|
81
|
-
binding: Schema2.Unknown
|
|
87
|
+
binding: Schema2.Unknown,
|
|
88
|
+
// Resolved tool description (operation description / summary / method+path
|
|
89
|
+
// fallback), persisted so the serve path can rebuild the tool def without
|
|
90
|
+
// re-parsing the spec. Optional: legacy rows predate it and resolve via the
|
|
91
|
+
// parse fallback.
|
|
92
|
+
description: Schema2.optional(Schema2.String)
|
|
82
93
|
});
|
|
83
94
|
var decodeOperationStorage = Schema2.decodeUnknownOption(OperationStorage);
|
|
84
95
|
var rowToOperation = (row) => {
|
|
@@ -90,7 +101,8 @@ var rowToOperation = (row) => {
|
|
|
90
101
|
toolName: operation.toolName,
|
|
91
102
|
binding: decodeBinding(
|
|
92
103
|
typeof operation.binding === "string" ? decodeBindingJson(operation.binding) : operation.binding
|
|
93
|
-
)
|
|
104
|
+
),
|
|
105
|
+
...operation.description !== void 0 ? { description: operation.description } : {}
|
|
94
106
|
};
|
|
95
107
|
};
|
|
96
108
|
var stableKeyHash = (value) => {
|
|
@@ -106,11 +118,13 @@ var stableKeyHash = (value) => {
|
|
|
106
118
|
var operationKey = (integration, toolName) => `${OPERATION_KEY_VERSION}.${stableKeyHash(integration)}.${stableKeyHash(toolName)}`;
|
|
107
119
|
var legacyOperationKey = (integration, toolName) => `${integration}.${toolName}`;
|
|
108
120
|
var specBlobKey = (specHash) => `spec/${specHash}`;
|
|
121
|
+
var defsBlobKey = (specHash) => `defs/${specHash}`;
|
|
109
122
|
var makeDefaultOpenapiStore = ({ pluginStorage, blobs }) => {
|
|
110
123
|
const operationData = (operation) => ({
|
|
111
124
|
integration: operation.integration,
|
|
112
125
|
toolName: operation.toolName,
|
|
113
|
-
binding: toJsonRecord(encodeBinding(operation.binding))
|
|
126
|
+
binding: toJsonRecord(encodeBinding(operation.binding)),
|
|
127
|
+
...operation.description !== void 0 ? { description: operation.description } : {}
|
|
114
128
|
});
|
|
115
129
|
const listRows = (integration) => pluginStorage.list({ collection: OPERATION_COLLECTION }).pipe(
|
|
116
130
|
Effect.map(
|
|
@@ -124,18 +138,20 @@ var makeDefaultOpenapiStore = ({ pluginStorage, blobs }) => {
|
|
|
124
138
|
entries: rows.map((row) => ({ collection: OPERATION_COLLECTION, key: row.key }))
|
|
125
139
|
});
|
|
126
140
|
});
|
|
141
|
+
const appendOperations = (integration, operations) => pluginStorage.putMany({
|
|
142
|
+
owner: STORE_OWNER,
|
|
143
|
+
entries: operations.map((operation) => ({
|
|
144
|
+
collection: OPERATION_COLLECTION,
|
|
145
|
+
key: operationKey(integration, operation.toolName),
|
|
146
|
+
data: operationData(operation)
|
|
147
|
+
}))
|
|
148
|
+
});
|
|
127
149
|
return {
|
|
128
150
|
putOperations: (integration, operations) => Effect.gen(function* () {
|
|
129
151
|
yield* removeOperations(integration);
|
|
130
|
-
yield*
|
|
131
|
-
owner: STORE_OWNER,
|
|
132
|
-
entries: operations.map((operation) => ({
|
|
133
|
-
collection: OPERATION_COLLECTION,
|
|
134
|
-
key: operationKey(integration, operation.toolName),
|
|
135
|
-
data: operationData(operation)
|
|
136
|
-
}))
|
|
137
|
-
});
|
|
152
|
+
yield* appendOperations(integration, operations);
|
|
138
153
|
}),
|
|
154
|
+
appendOperations,
|
|
139
155
|
getOperation: (integration, toolName) => Effect.gen(function* () {
|
|
140
156
|
const row = yield* pluginStorage.get({
|
|
141
157
|
collection: OPERATION_COLLECTION,
|
|
@@ -155,7 +171,9 @@ var makeDefaultOpenapiStore = ({ pluginStorage, blobs }) => {
|
|
|
155
171
|
),
|
|
156
172
|
removeOperations,
|
|
157
173
|
putSpec: (specHash, specText) => blobs.put(specBlobKey(specHash), specText, { owner: STORE_OWNER }),
|
|
158
|
-
getSpec: (specHash) => blobs.get(specBlobKey(specHash))
|
|
174
|
+
getSpec: (specHash) => blobs.get(specBlobKey(specHash)),
|
|
175
|
+
putDefs: (specHash, defsJson) => blobs.put(defsBlobKey(specHash), defsJson, { owner: STORE_OWNER }),
|
|
176
|
+
getDefs: (specHash) => blobs.get(defsBlobKey(specHash))
|
|
159
177
|
};
|
|
160
178
|
};
|
|
161
179
|
|
|
@@ -236,6 +254,7 @@ var resolvePath = Effect2.fn("OpenApi.resolvePath")(function* (pathTemplate, arg
|
|
|
236
254
|
}
|
|
237
255
|
return resolved;
|
|
238
256
|
});
|
|
257
|
+
var DEFAULT_USER_AGENT = "executor";
|
|
239
258
|
var applyHeaders = (request, headers) => {
|
|
240
259
|
let req = request;
|
|
241
260
|
for (const [name, value] of Object.entries(headers)) {
|
|
@@ -535,6 +554,7 @@ var invoke = Effect2.fn("OpenApi.invoke")(function* (operation, args, resolvedHe
|
|
|
535
554
|
const resolvedPath = yield* resolvePath(operation.pathTemplate, args, operation.parameters);
|
|
536
555
|
const path = resolvedPath.startsWith("/") ? resolvedPath : `/${resolvedPath}`;
|
|
537
556
|
let request = HttpClientRequest.make(operation.method.toUpperCase())(path);
|
|
557
|
+
request = HttpClientRequest.setHeader(request, "User-Agent", DEFAULT_USER_AGENT);
|
|
538
558
|
for (const [name, value] of Object.entries(sourceQueryParams)) {
|
|
539
559
|
request = HttpClientRequest.setUrlParam(request, name, value);
|
|
540
560
|
}
|
|
@@ -654,160 +674,13 @@ var annotationsForOperation = (method, pathTemplate) => {
|
|
|
654
674
|
};
|
|
655
675
|
|
|
656
676
|
// src/sdk/backing.ts
|
|
657
|
-
import { Effect as Effect3, Option as
|
|
677
|
+
import { Effect as Effect3, Option as Option4, Schema as Schema3 } from "effect";
|
|
658
678
|
import {
|
|
659
679
|
ToolFileJsonSchema,
|
|
660
680
|
ToolName,
|
|
661
681
|
ToolResult,
|
|
662
682
|
authToolFailure
|
|
663
683
|
} from "@executor-js/sdk/core";
|
|
664
|
-
|
|
665
|
-
// src/sdk/definitions.ts
|
|
666
|
-
import { Option as Option4 } from "effect";
|
|
667
|
-
var splitWords = (value) => value.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z0-9]+)/g, "$1 $2").replace(/[^a-zA-Z0-9]+/g, " ").trim().split(/\s+/).filter((part) => part.length > 0);
|
|
668
|
-
var normalizeWord = (value) => value.toLowerCase();
|
|
669
|
-
var toCamelCase = (value) => {
|
|
670
|
-
const words = splitWords(value).map(normalizeWord);
|
|
671
|
-
if (words.length === 0) return "tool";
|
|
672
|
-
const [first, ...rest] = words;
|
|
673
|
-
return `${first}${rest.map((p) => `${p[0]?.toUpperCase() ?? ""}${p.slice(1)}`).join("")}`;
|
|
674
|
-
};
|
|
675
|
-
var toPascalCase = (value) => {
|
|
676
|
-
const camel = toCamelCase(value);
|
|
677
|
-
return `${camel[0]?.toUpperCase() ?? ""}${camel.slice(1)}`;
|
|
678
|
-
};
|
|
679
|
-
var VERSION_SEGMENT_REGEX = /^v\d+(?:[._-]\d+)?$/i;
|
|
680
|
-
var IGNORED_PATH_SEGMENTS = /* @__PURE__ */ new Set(["api"]);
|
|
681
|
-
var pathSegmentsFromTemplate = (pathTemplate) => pathTemplate.split("/").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
682
|
-
var isPathParameterSegment = (segment) => segment.startsWith("{") && segment.endsWith("}");
|
|
683
|
-
var normalizeGroupSegment = (value) => {
|
|
684
|
-
const candidate = value?.trim();
|
|
685
|
-
if (!candidate) return null;
|
|
686
|
-
return toCamelCase(candidate);
|
|
687
|
-
};
|
|
688
|
-
var deriveVersionSegment = (pathTemplate) => pathSegmentsFromTemplate(pathTemplate).map((s) => s.toLowerCase()).find((s) => VERSION_SEGMENT_REGEX.test(s));
|
|
689
|
-
var derivePathGroup = (pathTemplate) => {
|
|
690
|
-
for (const segment of pathSegmentsFromTemplate(pathTemplate)) {
|
|
691
|
-
const lower = segment.toLowerCase();
|
|
692
|
-
if (VERSION_SEGMENT_REGEX.test(lower)) continue;
|
|
693
|
-
if (IGNORED_PATH_SEGMENTS.has(lower)) continue;
|
|
694
|
-
if (isPathParameterSegment(segment)) continue;
|
|
695
|
-
return normalizeGroupSegment(segment) ?? "root";
|
|
696
|
-
}
|
|
697
|
-
return "root";
|
|
698
|
-
};
|
|
699
|
-
var splitOperationIdSegments = (value) => value.split(/[/.]+/).map((s) => s.trim()).filter((s) => s.length > 0);
|
|
700
|
-
var deriveLeafSeed = (operationId, group) => {
|
|
701
|
-
const segments = splitOperationIdSegments(operationId);
|
|
702
|
-
if (segments.length > 1) {
|
|
703
|
-
const [first, ...rest] = segments;
|
|
704
|
-
if ((normalizeGroupSegment(first) ?? first) === group && rest.length > 0) {
|
|
705
|
-
return rest.join(" ");
|
|
706
|
-
}
|
|
707
|
-
}
|
|
708
|
-
return operationId;
|
|
709
|
-
};
|
|
710
|
-
var fallbackLeafSeed = (method, pathTemplate, group) => {
|
|
711
|
-
const relevantSegments = pathSegmentsFromTemplate(pathTemplate).filter((s) => !VERSION_SEGMENT_REGEX.test(s.toLowerCase())).filter((s) => !IGNORED_PATH_SEGMENTS.has(s.toLowerCase())).filter((s) => !isPathParameterSegment(s)).map((s) => normalizeGroupSegment(s) ?? s).filter((s) => s !== group);
|
|
712
|
-
const segmentSuffix = relevantSegments.map((s) => toPascalCase(s)).join("");
|
|
713
|
-
return `${method}${segmentSuffix || "Operation"}`;
|
|
714
|
-
};
|
|
715
|
-
var deriveLeaf = (operationId, method, pathTemplate, group) => {
|
|
716
|
-
const preferred = toCamelCase(deriveLeafSeed(operationId, group));
|
|
717
|
-
if (preferred.length > 0 && preferred !== group) return preferred;
|
|
718
|
-
return toCamelCase(fallbackLeafSeed(method, pathTemplate, group));
|
|
719
|
-
};
|
|
720
|
-
var resolveCollisions = (definitions) => {
|
|
721
|
-
const staged = definitions.map((d) => ({ ...d }));
|
|
722
|
-
const applyFactory = (items, factory) => {
|
|
723
|
-
const byPath = /* @__PURE__ */ new Map();
|
|
724
|
-
for (const item of items) {
|
|
725
|
-
const bucket = byPath.get(item.toolPath) ?? [];
|
|
726
|
-
bucket.push(item);
|
|
727
|
-
byPath.set(item.toolPath, bucket);
|
|
728
|
-
}
|
|
729
|
-
for (const bucket of byPath.values()) {
|
|
730
|
-
if (bucket.length < 2) continue;
|
|
731
|
-
for (const d of bucket) {
|
|
732
|
-
d.toolPath = factory(d);
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
|
-
};
|
|
736
|
-
applyFactory(
|
|
737
|
-
staged,
|
|
738
|
-
(d) => d.versionSegment ? `${d.group}.${d.versionSegment}.${d.leaf}` : d.toolPath
|
|
739
|
-
);
|
|
740
|
-
applyFactory(staged, (d) => {
|
|
741
|
-
const prefix = d.versionSegment ? `${d.group}.${d.versionSegment}` : d.group;
|
|
742
|
-
return `${prefix}.${d.leaf}${toPascalCase(d.method)}`;
|
|
743
|
-
});
|
|
744
|
-
applyFactory(staged, (d) => {
|
|
745
|
-
const prefix = d.versionSegment ? `${d.group}.${d.versionSegment}` : d.group;
|
|
746
|
-
return `${prefix}.${d.leaf}${toPascalCase(d.method)}${d.operationHash.slice(0, 8)}`;
|
|
747
|
-
});
|
|
748
|
-
return staged.map((d) => ({
|
|
749
|
-
toolPath: d.toolPath,
|
|
750
|
-
group: d.group,
|
|
751
|
-
leaf: d.leaf,
|
|
752
|
-
operationIndex: d.operationIndex,
|
|
753
|
-
operation: d.operation
|
|
754
|
-
}));
|
|
755
|
-
};
|
|
756
|
-
var stableHash = (value) => {
|
|
757
|
-
const str = JSON.stringify(value, Object.keys(value).sort());
|
|
758
|
-
let hash = 0;
|
|
759
|
-
for (let i = 0; i < str.length; i++) {
|
|
760
|
-
hash = (hash << 5) - hash + str.charCodeAt(i) | 0;
|
|
761
|
-
}
|
|
762
|
-
return Math.abs(hash).toString(36).padStart(8, "0");
|
|
763
|
-
};
|
|
764
|
-
var compileToolDefinitions = (operations) => {
|
|
765
|
-
const raw = operations.map((op, index) => {
|
|
766
|
-
const operationId = op.operationId;
|
|
767
|
-
const explicitToolPath = Option4.getOrUndefined(op.toolPath);
|
|
768
|
-
if (explicitToolPath) {
|
|
769
|
-
const [group2 = "root", ...leafParts] = explicitToolPath.split(".").filter(Boolean);
|
|
770
|
-
const leaf2 = leafParts.join(".") || group2;
|
|
771
|
-
const versionSegment2 = deriveVersionSegment(op.pathTemplate);
|
|
772
|
-
const operationHash2 = stableHash({
|
|
773
|
-
method: op.method,
|
|
774
|
-
path: op.pathTemplate,
|
|
775
|
-
operationId
|
|
776
|
-
});
|
|
777
|
-
return {
|
|
778
|
-
toolPath: explicitToolPath,
|
|
779
|
-
group: group2,
|
|
780
|
-
leaf: leaf2,
|
|
781
|
-
versionSegment: versionSegment2,
|
|
782
|
-
method: op.method,
|
|
783
|
-
operationHash: operationHash2,
|
|
784
|
-
operationIndex: index,
|
|
785
|
-
operation: op
|
|
786
|
-
};
|
|
787
|
-
}
|
|
788
|
-
const group = normalizeGroupSegment(op.tags[0]) ?? derivePathGroup(op.pathTemplate);
|
|
789
|
-
const leaf = deriveLeaf(operationId, op.method, op.pathTemplate, group);
|
|
790
|
-
const versionSegment = deriveVersionSegment(op.pathTemplate);
|
|
791
|
-
const operationHash = stableHash({
|
|
792
|
-
method: op.method,
|
|
793
|
-
path: op.pathTemplate,
|
|
794
|
-
operationId
|
|
795
|
-
});
|
|
796
|
-
return {
|
|
797
|
-
toolPath: `${group}.${leaf}`,
|
|
798
|
-
group,
|
|
799
|
-
leaf,
|
|
800
|
-
versionSegment,
|
|
801
|
-
method: op.method,
|
|
802
|
-
operationHash,
|
|
803
|
-
operationIndex: index,
|
|
804
|
-
operation: op
|
|
805
|
-
};
|
|
806
|
-
});
|
|
807
|
-
return resolveCollisions(raw).sort((a, b) => a.toolPath.localeCompare(b.toolPath));
|
|
808
|
-
};
|
|
809
|
-
|
|
810
|
-
// src/sdk/backing.ts
|
|
811
684
|
var STRINGIFIED_BODY_CAP = 1024;
|
|
812
685
|
var UpstreamMessageBody = Schema3.Struct({ message: Schema3.String });
|
|
813
686
|
var UpstreamErrorMessageBody = Schema3.Struct({ errorMessage: Schema3.String });
|
|
@@ -845,11 +718,11 @@ var extractOpenApiUpstreamMessage = (body, status) => {
|
|
|
845
718
|
if (typeof body === "string") {
|
|
846
719
|
return body.length > 0 ? body : `Upstream returned HTTP ${status}`;
|
|
847
720
|
}
|
|
848
|
-
const nested =
|
|
849
|
-
const messageBody =
|
|
850
|
-
const errorMessageBody =
|
|
851
|
-
const errorsBody =
|
|
852
|
-
const descriptionBody =
|
|
721
|
+
const nested = Option4.getOrUndefined(decodeUpstreamNestedErrorBody(body));
|
|
722
|
+
const messageBody = Option4.getOrUndefined(decodeUpstreamMessageBody(body));
|
|
723
|
+
const errorMessageBody = Option4.getOrUndefined(decodeUpstreamErrorMessageBody(body));
|
|
724
|
+
const errorsBody = Option4.getOrUndefined(decodeUpstreamErrorsArrayBody(body));
|
|
725
|
+
const descriptionBody = Option4.getOrUndefined(decodeUpstreamDescriptionBody(body));
|
|
853
726
|
const arrayMessage = errorsBody?.errors.map(
|
|
854
727
|
({
|
|
855
728
|
detail,
|
|
@@ -924,11 +797,15 @@ var toBinding = (def) => OperationBinding.make({
|
|
|
924
797
|
});
|
|
925
798
|
var descriptionFor = (def) => {
|
|
926
799
|
const op = def.operation;
|
|
927
|
-
return
|
|
800
|
+
return Option4.getOrElse(
|
|
928
801
|
op.description,
|
|
929
|
-
() =>
|
|
802
|
+
() => Option4.getOrElse(op.summary, () => `${op.method.toUpperCase()} ${op.pathTemplate}`)
|
|
930
803
|
);
|
|
931
804
|
};
|
|
805
|
+
var FILE_OUTPUT_HINT = `Returns a ToolFile: the file bytes already decoded into { _tag: "ToolFile", mimeType, encoding, data, byteLength }. To display or forward it, pass the result's data straight to emit(result.data). Do not rebuild the envelope or read upstream fields like size.`;
|
|
806
|
+
var withFileEmitHint = (description, returnsFile) => returnsFile ? `${description}
|
|
807
|
+
|
|
808
|
+
${FILE_OUTPUT_HINT}` : description;
|
|
932
809
|
var compileOpenApiDocument = (doc) => Effect3.gen(function* () {
|
|
933
810
|
const result = yield* extract(doc);
|
|
934
811
|
const hoistedDefs = {};
|
|
@@ -940,38 +817,181 @@ var compileOpenApiDocument = (doc) => Effect3.gen(function* () {
|
|
|
940
817
|
return {
|
|
941
818
|
definitions: compileToolDefinitions(result.operations),
|
|
942
819
|
hoistedDefs,
|
|
943
|
-
title:
|
|
944
|
-
description:
|
|
820
|
+
title: Option4.getOrUndefined(result.title),
|
|
821
|
+
description: Option4.getOrUndefined(result.description)
|
|
945
822
|
};
|
|
946
823
|
});
|
|
947
824
|
var compileOpenApiSpec = (specText) => Effect3.gen(function* () {
|
|
948
825
|
const doc = yield* parse(specText);
|
|
949
826
|
return yield* compileOpenApiDocument(doc);
|
|
950
827
|
});
|
|
951
|
-
var openApiToolDefsFromCompiled = (compiled) => compiled.definitions.map(
|
|
952
|
-
(def
|
|
828
|
+
var openApiToolDefsFromCompiled = (compiled) => compiled.definitions.map((def) => {
|
|
829
|
+
const returnsFile = Option4.match(def.operation.responseBody, {
|
|
830
|
+
onNone: () => false,
|
|
831
|
+
onSome: (responseBody) => Option4.isSome(responseBody.fileHint)
|
|
832
|
+
});
|
|
833
|
+
return {
|
|
953
834
|
name: ToolName.make(def.toolPath),
|
|
954
|
-
description: descriptionFor(def),
|
|
955
|
-
inputSchema: normalizeOpenApiRefs(
|
|
956
|
-
outputSchema:
|
|
957
|
-
onNone: () => normalizeOpenApiRefs(Option5.getOrUndefined(def.operation.outputSchema)),
|
|
958
|
-
onSome: (responseBody) => Option5.isSome(responseBody.fileHint) ? ToolFileJsonSchema : normalizeOpenApiRefs(Option5.getOrUndefined(def.operation.outputSchema))
|
|
959
|
-
}),
|
|
835
|
+
description: withFileEmitHint(descriptionFor(def), returnsFile),
|
|
836
|
+
inputSchema: normalizeOpenApiRefs(Option4.getOrUndefined(def.operation.inputSchema)),
|
|
837
|
+
outputSchema: returnsFile ? ToolFileJsonSchema : normalizeOpenApiRefs(Option4.getOrUndefined(def.operation.outputSchema)),
|
|
960
838
|
annotations: annotationsForOperation(def.operation.method, def.operation.pathTemplate)
|
|
961
|
-
}
|
|
962
|
-
);
|
|
839
|
+
};
|
|
840
|
+
});
|
|
963
841
|
var openApiStoredOperationsFromCompiled = (integration, compiled) => compiled.definitions.map((def) => ({
|
|
964
842
|
integration,
|
|
965
843
|
toolName: def.toolPath,
|
|
966
|
-
binding: toBinding(def)
|
|
844
|
+
binding: toBinding(def),
|
|
845
|
+
description: descriptionFor(def)
|
|
967
846
|
}));
|
|
847
|
+
var buildDefsJson = (doc) => {
|
|
848
|
+
const schemas = doc.components?.schemas;
|
|
849
|
+
if (!schemas) return "{}";
|
|
850
|
+
let json = "{";
|
|
851
|
+
let first = true;
|
|
852
|
+
for (const [name, schema] of Object.entries(schemas)) {
|
|
853
|
+
const serialized = JSON.stringify(normalizeOpenApiRefs(schema));
|
|
854
|
+
if (serialized === void 0) continue;
|
|
855
|
+
json += `${first ? "" : ","}${JSON.stringify(name)}:${serialized}`;
|
|
856
|
+
first = false;
|
|
857
|
+
}
|
|
858
|
+
return `${json}}`;
|
|
859
|
+
};
|
|
860
|
+
var buildDefsJsonStreaming = (structure) => {
|
|
861
|
+
let json = "{";
|
|
862
|
+
let first = true;
|
|
863
|
+
for (const range of structure.schemas) {
|
|
864
|
+
const entry = parseEntry(structure.text, range, 4);
|
|
865
|
+
if (!entry) continue;
|
|
866
|
+
const [name, schema] = entry;
|
|
867
|
+
const serialized = JSON.stringify(normalizeOpenApiRefs(schema));
|
|
868
|
+
if (serialized === void 0) continue;
|
|
869
|
+
json += `${first ? "" : ","}${JSON.stringify(name)}:${serialized}`;
|
|
870
|
+
first = false;
|
|
871
|
+
}
|
|
872
|
+
return `${json}}`;
|
|
873
|
+
};
|
|
874
|
+
var DefsJson = Schema3.Record(Schema3.String, Schema3.Unknown);
|
|
875
|
+
var decodeDefsJson = Schema3.decodeUnknownOption(Schema3.fromJsonString(DefsJson));
|
|
876
|
+
var toolDefFromStoredOperation = (op) => {
|
|
877
|
+
const binding = op.binding;
|
|
878
|
+
const returnsFile = Option4.match(binding.responseBody, {
|
|
879
|
+
onNone: () => false,
|
|
880
|
+
onSome: (responseBody) => Option4.isSome(responseBody.fileHint)
|
|
881
|
+
});
|
|
882
|
+
return {
|
|
883
|
+
name: ToolName.make(op.toolName),
|
|
884
|
+
description: withFileEmitHint(
|
|
885
|
+
op.description ?? `${binding.method.toUpperCase()} ${binding.pathTemplate}`,
|
|
886
|
+
returnsFile
|
|
887
|
+
),
|
|
888
|
+
inputSchema: normalizeOpenApiRefs(
|
|
889
|
+
buildInputSchema(
|
|
890
|
+
binding.parameters,
|
|
891
|
+
Option4.getOrUndefined(binding.requestBody),
|
|
892
|
+
binding.servers ?? []
|
|
893
|
+
)
|
|
894
|
+
),
|
|
895
|
+
outputSchema: returnsFile ? ToolFileJsonSchema : Option4.match(binding.responseBody, {
|
|
896
|
+
onNone: () => void 0,
|
|
897
|
+
onSome: (responseBody) => normalizeOpenApiRefs(Option4.getOrUndefined(responseBody.schema))
|
|
898
|
+
}),
|
|
899
|
+
annotations: annotationsForOperation(binding.method, binding.pathTemplate)
|
|
900
|
+
};
|
|
901
|
+
};
|
|
902
|
+
var compileAndPersistOpenApiOperations = ({
|
|
903
|
+
doc,
|
|
904
|
+
integration,
|
|
905
|
+
storage,
|
|
906
|
+
specHash,
|
|
907
|
+
chunkSize
|
|
908
|
+
}) => Effect3.gen(function* () {
|
|
909
|
+
yield* storage.removeOperations(integration);
|
|
910
|
+
const result = yield* streamOperationBindings(
|
|
911
|
+
doc,
|
|
912
|
+
chunkSize ?? 500,
|
|
913
|
+
(chunk) => storage.appendOperations(
|
|
914
|
+
integration,
|
|
915
|
+
chunk.map((item) => ({
|
|
916
|
+
integration,
|
|
917
|
+
toolName: item.toolName,
|
|
918
|
+
binding: item.binding,
|
|
919
|
+
description: item.description
|
|
920
|
+
}))
|
|
921
|
+
)
|
|
922
|
+
);
|
|
923
|
+
if (specHash != null) {
|
|
924
|
+
yield* storage.putDefs(specHash, buildDefsJson(doc));
|
|
925
|
+
}
|
|
926
|
+
return result;
|
|
927
|
+
});
|
|
928
|
+
var compileAndPersistOpenApiSpec = ({
|
|
929
|
+
specText,
|
|
930
|
+
integration,
|
|
931
|
+
storage,
|
|
932
|
+
specHash,
|
|
933
|
+
chunkSize
|
|
934
|
+
}) => Effect3.gen(function* () {
|
|
935
|
+
const doc = yield* parse(specText);
|
|
936
|
+
return yield* compileAndPersistOpenApiOperations({
|
|
937
|
+
doc,
|
|
938
|
+
integration,
|
|
939
|
+
storage,
|
|
940
|
+
specHash,
|
|
941
|
+
chunkSize
|
|
942
|
+
});
|
|
943
|
+
});
|
|
944
|
+
var compileAndPersistOpenApiSpecStreaming = ({
|
|
945
|
+
specText,
|
|
946
|
+
integration,
|
|
947
|
+
storage,
|
|
948
|
+
specHash,
|
|
949
|
+
chunkSize,
|
|
950
|
+
keepPathItem
|
|
951
|
+
}) => Effect3.gen(function* () {
|
|
952
|
+
const structure = structuralSplit(specText);
|
|
953
|
+
if (!structure) {
|
|
954
|
+
return yield* new OpenApiExtractionError({
|
|
955
|
+
message: "OpenAPI spec is not in the streamable block-YAML profile (no top-level `paths:` block); cannot stream-compile a spec this large in-band."
|
|
956
|
+
});
|
|
957
|
+
}
|
|
958
|
+
yield* storage.removeOperations(integration);
|
|
959
|
+
const result = yield* streamOperationBindingsFromStructure(
|
|
960
|
+
structure,
|
|
961
|
+
{ chunkSize: chunkSize ?? 500, keepPathItem },
|
|
962
|
+
(chunk) => storage.appendOperations(
|
|
963
|
+
integration,
|
|
964
|
+
chunk.map((item) => ({
|
|
965
|
+
integration,
|
|
966
|
+
toolName: item.toolName,
|
|
967
|
+
binding: item.binding,
|
|
968
|
+
description: item.description
|
|
969
|
+
}))
|
|
970
|
+
)
|
|
971
|
+
);
|
|
972
|
+
if (specHash != null) {
|
|
973
|
+
yield* storage.putDefs(specHash, buildDefsJsonStreaming(structure));
|
|
974
|
+
}
|
|
975
|
+
return result;
|
|
976
|
+
});
|
|
968
977
|
var loadOpenApiSpecText = (storage, config) => config.specHash != null ? storage.getSpec(config.specHash) : Effect3.succeed(null);
|
|
969
978
|
var resolveOpenApiBackedTools = ({
|
|
979
|
+
integration,
|
|
970
980
|
config,
|
|
971
981
|
storage
|
|
972
982
|
}) => Effect3.gen(function* () {
|
|
973
983
|
const openApiConfig = decodeOpenApiIntegrationConfig(config);
|
|
974
984
|
if (!openApiConfig) return { tools: [], definitions: {} };
|
|
985
|
+
if (openApiConfig.specHash != null) {
|
|
986
|
+
const defsJson = yield* storage.getDefs(openApiConfig.specHash);
|
|
987
|
+
if (defsJson != null) {
|
|
988
|
+
const definitions = Option4.getOrNull(decodeDefsJson(defsJson));
|
|
989
|
+
if (definitions != null) {
|
|
990
|
+
const ops = yield* storage.listOperations(String(integration.slug));
|
|
991
|
+
return { tools: ops.map(toolDefFromStoredOperation), definitions };
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
}
|
|
975
995
|
const specText = yield* loadOpenApiSpecText(storage, openApiConfig);
|
|
976
996
|
if (specText == null) return { tools: [], definitions: {} };
|
|
977
997
|
const compiled = yield* compileOpenApiSpec(specText).pipe(
|
|
@@ -987,7 +1007,7 @@ var invokeOpenApiBackedTool = (input) => Effect3.gen(function* () {
|
|
|
987
1007
|
const integration = input.toolRow.integration;
|
|
988
1008
|
const config = decodeOpenApiIntegrationConfig(input.credential.config);
|
|
989
1009
|
let binding = (yield* input.ctx.storage.getOperation(integration, input.toolRow.name))?.binding;
|
|
990
|
-
if (
|
|
1010
|
+
if (!binding && config) {
|
|
991
1011
|
const specText = yield* loadOpenApiSpecText(input.ctx.storage, config).pipe(
|
|
992
1012
|
Effect3.catch(() => Effect3.succeed(null))
|
|
993
1013
|
);
|
|
@@ -1076,7 +1096,7 @@ var resolveOpenApiBackedAnnotations = (input) => Effect3.gen(function* () {
|
|
|
1076
1096
|
});
|
|
1077
1097
|
|
|
1078
1098
|
// src/sdk/plugin.ts
|
|
1079
|
-
import { Effect as Effect4, Option as
|
|
1099
|
+
import { Effect as Effect4, Option as Option5, Schema as Schema4 } from "effect";
|
|
1080
1100
|
import {
|
|
1081
1101
|
IntegrationAlreadyExistsError,
|
|
1082
1102
|
IntegrationDetectionResult,
|
|
@@ -1207,18 +1227,18 @@ var openApiToolFailure = (code, message, details) => ToolResult2.fail({
|
|
|
1207
1227
|
...details === void 0 ? {} : { details }
|
|
1208
1228
|
});
|
|
1209
1229
|
var staticPreviewOutput = (preview) => ({
|
|
1210
|
-
title:
|
|
1211
|
-
version:
|
|
1230
|
+
title: Option5.getOrNull(preview.title),
|
|
1231
|
+
version: Option5.getOrNull(preview.version),
|
|
1212
1232
|
servers: preview.servers.map((server) => ({
|
|
1213
1233
|
url: server.url,
|
|
1214
|
-
description:
|
|
1215
|
-
variables:
|
|
1216
|
-
Object.entries(
|
|
1234
|
+
description: Option5.getOrNull(server.description),
|
|
1235
|
+
variables: Option5.getOrNull(server.variables) ? Object.fromEntries(
|
|
1236
|
+
Object.entries(Option5.getOrNull(server.variables) ?? {}).map(([name, variable]) => [
|
|
1217
1237
|
name,
|
|
1218
1238
|
{
|
|
1219
1239
|
default: variable.default,
|
|
1220
|
-
enum:
|
|
1221
|
-
description:
|
|
1240
|
+
enum: Option5.getOrNull(variable.enum),
|
|
1241
|
+
description: Option5.getOrNull(variable.description)
|
|
1222
1242
|
}
|
|
1223
1243
|
])
|
|
1224
1244
|
) : null
|
|
@@ -1228,25 +1248,25 @@ var staticPreviewOutput = (preview) => ({
|
|
|
1228
1248
|
securitySchemes: preview.securitySchemes.map((scheme) => ({
|
|
1229
1249
|
name: scheme.name,
|
|
1230
1250
|
type: scheme.type,
|
|
1231
|
-
scheme:
|
|
1232
|
-
bearerFormat:
|
|
1233
|
-
in:
|
|
1234
|
-
headerName:
|
|
1235
|
-
description:
|
|
1236
|
-
flows:
|
|
1237
|
-
authorizationCode:
|
|
1251
|
+
scheme: Option5.getOrNull(scheme.scheme),
|
|
1252
|
+
bearerFormat: Option5.getOrNull(scheme.bearerFormat),
|
|
1253
|
+
in: Option5.getOrNull(scheme.in),
|
|
1254
|
+
headerName: Option5.getOrNull(scheme.headerName),
|
|
1255
|
+
description: Option5.getOrNull(scheme.description),
|
|
1256
|
+
flows: Option5.isSome(scheme.flows) ? {
|
|
1257
|
+
authorizationCode: Option5.isSome(scheme.flows.value.authorizationCode) ? {
|
|
1238
1258
|
authorizationUrl: scheme.flows.value.authorizationCode.value.authorizationUrl,
|
|
1239
1259
|
tokenUrl: scheme.flows.value.authorizationCode.value.tokenUrl,
|
|
1240
|
-
refreshUrl:
|
|
1260
|
+
refreshUrl: Option5.getOrNull(scheme.flows.value.authorizationCode.value.refreshUrl),
|
|
1241
1261
|
scopes: scheme.flows.value.authorizationCode.value.scopes
|
|
1242
1262
|
} : null,
|
|
1243
|
-
clientCredentials:
|
|
1263
|
+
clientCredentials: Option5.isSome(scheme.flows.value.clientCredentials) ? {
|
|
1244
1264
|
tokenUrl: scheme.flows.value.clientCredentials.value.tokenUrl,
|
|
1245
|
-
refreshUrl:
|
|
1265
|
+
refreshUrl: Option5.getOrNull(scheme.flows.value.clientCredentials.value.refreshUrl),
|
|
1246
1266
|
scopes: scheme.flows.value.clientCredentials.value.scopes
|
|
1247
1267
|
} : null
|
|
1248
1268
|
} : null,
|
|
1249
|
-
openIdConnectUrl:
|
|
1269
|
+
openIdConnectUrl: Option5.getOrNull(scheme.openIdConnectUrl)
|
|
1250
1270
|
})),
|
|
1251
1271
|
authStrategies: preview.authStrategies,
|
|
1252
1272
|
headerPresets: preview.headerPresets,
|
|
@@ -1254,9 +1274,9 @@ var staticPreviewOutput = (preview) => ({
|
|
|
1254
1274
|
label: preset.label,
|
|
1255
1275
|
securitySchemeName: preset.securitySchemeName,
|
|
1256
1276
|
flow: preset.flow,
|
|
1257
|
-
authorizationUrl:
|
|
1277
|
+
authorizationUrl: Option5.getOrNull(preset.authorizationUrl),
|
|
1258
1278
|
tokenUrl: preset.tokenUrl,
|
|
1259
|
-
refreshUrl:
|
|
1279
|
+
refreshUrl: Option5.getOrNull(preset.refreshUrl),
|
|
1260
1280
|
scopes: preset.scopes,
|
|
1261
1281
|
identityScopes: preset.identityScopes
|
|
1262
1282
|
}))
|
|
@@ -1342,6 +1362,7 @@ var openApiPlugin = definePlugin((options) => {
|
|
|
1342
1362
|
} : derivedAuthenticationTemplate && derivedAuthenticationTemplate.length > 0 ? { authenticationTemplate: derivedAuthenticationTemplate } : {}
|
|
1343
1363
|
};
|
|
1344
1364
|
yield* ctx.storage.putSpec(specHash, resolved.specText);
|
|
1365
|
+
yield* ctx.storage.putDefs(specHash, JSON.stringify(compiled.hoistedDefs));
|
|
1345
1366
|
yield* ctx.transaction(
|
|
1346
1367
|
Effect4.gen(function* () {
|
|
1347
1368
|
yield* ctx.core.integrations.register({
|
|
@@ -1380,6 +1401,7 @@ var openApiPlugin = definePlugin((options) => {
|
|
|
1380
1401
|
const nextNames = new Set(compiled.definitions.map((def) => def.toolPath));
|
|
1381
1402
|
const specHash = yield* sha256Hex(resolved.specText);
|
|
1382
1403
|
yield* ctx.storage.putSpec(specHash, resolved.specText);
|
|
1404
|
+
yield* ctx.storage.putDefs(specHash, JSON.stringify(compiled.hoistedDefs));
|
|
1383
1405
|
const nextConfig = {
|
|
1384
1406
|
...current,
|
|
1385
1407
|
specHash,
|
|
@@ -1541,7 +1563,7 @@ var openApiPlugin = definePlugin((options) => {
|
|
|
1541
1563
|
// operation bindings invokeTool needs are persisted at addSpec time; this
|
|
1542
1564
|
// hook only shapes the per-connection ToolDefs from the spec blob the
|
|
1543
1565
|
// catalog config points at.
|
|
1544
|
-
resolveTools: ({ config, storage }) => resolveOpenApiBackedTools({ config, storage }),
|
|
1566
|
+
resolveTools: ({ integration, config, storage }) => resolveOpenApiBackedTools({ integration, config, storage }),
|
|
1545
1567
|
invokeTool: ({ ctx: invokeCtx, toolRow, credential, args }) => {
|
|
1546
1568
|
const httpClientLayer = options?.httpClientLayer ?? invokeCtx.httpClientLayer;
|
|
1547
1569
|
return invokeOpenApiBackedTool({
|
|
@@ -1569,7 +1591,7 @@ var openApiPlugin = definePlugin((options) => {
|
|
|
1569
1591
|
try: () => new URL(trimmed),
|
|
1570
1592
|
catch: (error) => error
|
|
1571
1593
|
}).pipe(Effect4.option);
|
|
1572
|
-
if (
|
|
1594
|
+
if (Option5.isNone(parsed)) return null;
|
|
1573
1595
|
const specText = yield* resolveSpecText(trimmed).pipe(
|
|
1574
1596
|
Effect4.provide(httpClientLayer),
|
|
1575
1597
|
Effect4.catch(() => Effect4.succeed(null))
|
|
@@ -1579,8 +1601,8 @@ var openApiPlugin = definePlugin((options) => {
|
|
|
1579
1601
|
if (!doc) return null;
|
|
1580
1602
|
const result = yield* extract(doc).pipe(Effect4.catch(() => Effect4.succeed(null)));
|
|
1581
1603
|
if (!result) return null;
|
|
1582
|
-
const slug =
|
|
1583
|
-
const name =
|
|
1604
|
+
const slug = Option5.getOrElse(result.title, () => "api").toLowerCase().replace(/[^a-z0-9]+/g, "_");
|
|
1605
|
+
const name = Option5.getOrElse(result.title, () => slug);
|
|
1584
1606
|
return IntegrationDetectionResult.make({
|
|
1585
1607
|
kind: "openapi",
|
|
1586
1608
|
confidence: "high",
|
|
@@ -1607,10 +1629,14 @@ export {
|
|
|
1607
1629
|
compileOpenApiSpec,
|
|
1608
1630
|
openApiToolDefsFromCompiled,
|
|
1609
1631
|
openApiStoredOperationsFromCompiled,
|
|
1632
|
+
buildDefsJsonStreaming,
|
|
1633
|
+
compileAndPersistOpenApiOperations,
|
|
1634
|
+
compileAndPersistOpenApiSpec,
|
|
1635
|
+
compileAndPersistOpenApiSpecStreaming,
|
|
1610
1636
|
loadOpenApiSpecText,
|
|
1611
1637
|
resolveOpenApiBackedTools,
|
|
1612
1638
|
invokeOpenApiBackedTool,
|
|
1613
1639
|
resolveOpenApiBackedAnnotations,
|
|
1614
1640
|
openApiPlugin
|
|
1615
1641
|
};
|
|
1616
|
-
//# sourceMappingURL=chunk-
|
|
1642
|
+
//# sourceMappingURL=chunk-ELCKZJE4.js.map
|