@executor-js/plugin-openapi 1.5.15 → 1.5.16

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.
Files changed (59) hide show
  1. package/dist/AddOpenApiSource-U7AYB224.js +369 -0
  2. package/dist/AddOpenApiSource-U7AYB224.js.map +1 -0
  3. package/dist/{OpenApiAccountsPanel-X5Z5XKRM.js → OpenApiAccountsPanel-GHFHHE6P.js} +15 -39
  4. package/dist/OpenApiAccountsPanel-GHFHHE6P.js.map +1 -0
  5. package/dist/{UpdateSpecSection-Z2DEEWZW.js → UpdateSpecSection-PLCBUU4I.js} +4 -4
  6. package/dist/UpdateSpecSection-PLCBUU4I.js.map +1 -0
  7. package/dist/api/group.d.ts +0 -21
  8. package/dist/api/index.d.ts +0 -21
  9. package/dist/{chunk-ZTOOUP67.js → chunk-3FM2SWM4.js} +542 -580
  10. package/dist/chunk-3FM2SWM4.js.map +1 -0
  11. package/dist/chunk-CKBX4SXK.js +95 -0
  12. package/dist/chunk-CKBX4SXK.js.map +1 -0
  13. package/dist/{chunk-NJ4Q3VF4.js → chunk-CPPTKUOW.js} +5 -14
  14. package/dist/chunk-CPPTKUOW.js.map +1 -0
  15. package/dist/{chunk-O54VFSWE.js → chunk-KVPUDOJZ.js} +18 -4
  16. package/dist/chunk-KVPUDOJZ.js.map +1 -0
  17. package/dist/{chunk-PAHWRRS3.js → chunk-QQFCICLX.js} +4 -13
  18. package/dist/chunk-QQFCICLX.js.map +1 -0
  19. package/dist/client.js +4 -5
  20. package/dist/client.js.map +1 -1
  21. package/dist/core.js +25 -15
  22. package/dist/core.js.map +1 -1
  23. package/dist/index.js +4 -5
  24. package/dist/index.js.map +1 -1
  25. package/dist/react/atoms.d.ts +0 -22
  26. package/dist/react/client.d.ts +0 -21
  27. package/dist/react/index.d.ts +2 -0
  28. package/dist/sdk/backing.d.ts +54 -0
  29. package/dist/sdk/config.d.ts +0 -2
  30. package/dist/sdk/derive-auth.d.ts +5 -3
  31. package/dist/sdk/index.d.ts +2 -1
  32. package/dist/sdk/plugin.d.ts +4 -10
  33. package/dist/sdk/presets.d.ts +0 -1
  34. package/dist/sdk/preview.d.ts +79 -0
  35. package/dist/testing/index.d.ts +0 -6
  36. package/package.json +6 -5
  37. package/dist/AddOpenApiSource-IRMLVLDK.js +0 -765
  38. package/dist/AddOpenApiSource-IRMLVLDK.js.map +0 -1
  39. package/dist/OpenApiAccountsPanel-X5Z5XKRM.js.map +0 -1
  40. package/dist/UpdateSpecSection-Z2DEEWZW.js.map +0 -1
  41. package/dist/chunk-MZWZQ24W.js +0 -226
  42. package/dist/chunk-MZWZQ24W.js.map +0 -1
  43. package/dist/chunk-NJ4Q3VF4.js.map +0 -1
  44. package/dist/chunk-O54VFSWE.js.map +0 -1
  45. package/dist/chunk-PAHWRRS3.js.map +0 -1
  46. package/dist/chunk-UOLBAX5D.js +0 -712
  47. package/dist/chunk-UOLBAX5D.js.map +0 -1
  48. package/dist/chunk-ZTOOUP67.js.map +0 -1
  49. package/dist/react/GoogleProductPicker.d.ts +0 -9
  50. package/dist/sdk/google-discovery.d.ts +0 -43
  51. package/dist/sdk/google-discovery.test.d.ts +0 -1
  52. package/dist/sdk/google-oauth-batches.d.ts +0 -13
  53. package/dist/sdk/google-oauth-batches.test.d.ts +0 -1
  54. package/dist/sdk/google-oauth-scopes.d.ts +0 -3
  55. package/dist/sdk/google-oauth-scopes.test.d.ts +0 -1
  56. package/dist/sdk/google-presets.d.ts +0 -16
  57. package/dist/sdk/google-presets.test.d.ts +0 -1
  58. package/dist/sdk/google-product-picker-scopes.test.d.ts +0 -1
  59. /package/dist/sdk/{google-bundle.test.d.ts → store.test.d.ts} +0 -0
@@ -1,14 +1,10 @@
1
1
  import {
2
- convertGoogleDiscoveryBundleToOpenApi,
3
- convertGoogleDiscoveryToOpenApi,
4
2
  deriveAuthenticationTemplateFromPreview,
5
- fetchGoogleDiscoveryDocument,
6
- firstBaseUrlForPreview,
7
- isGoogleDiscoveryUrl
8
- } from "./chunk-UOLBAX5D.js";
3
+ firstBaseUrlForPreview
4
+ } from "./chunk-CKBX4SXK.js";
9
5
  import {
10
6
  openApiPresets
11
- } from "./chunk-PAHWRRS3.js";
7
+ } from "./chunk-QQFCICLX.js";
12
8
  import {
13
9
  InvocationResult,
14
10
  OpenApiExtractionError,
@@ -18,11 +14,10 @@ import {
18
14
  extract,
19
15
  normalizeOpenApiAuthInputs,
20
16
  parse,
21
- previewSpec,
22
17
  previewSpecText,
23
18
  resolveServerUrl,
24
19
  resolveSpecText
25
- } from "./chunk-O54VFSWE.js";
20
+ } from "./chunk-KVPUDOJZ.js";
26
21
 
27
22
  // src/sdk/config.ts
28
23
  import { Option, Schema } from "effect";
@@ -46,8 +41,6 @@ var OpenApiIntegrationConfigSchema = Schema.Struct({
46
41
  specHash: Schema.optional(Schema.String),
47
42
  /** Origin URL the spec was fetched from, when known. Enables refresh. */
48
43
  sourceUrl: Schema.optional(Schema.String),
49
- /** Google Discovery bundle URLs, when the spec came from a Google bundle. */
50
- googleDiscoveryUrls: Schema.optional(Schema.Array(Schema.String)),
51
44
  /** Optional base URL override. */
52
45
  baseUrl: Schema.optional(Schema.String),
53
46
  /** Static headers applied to every request (no secret material). */
@@ -73,8 +66,101 @@ var requiredTemplateVariables = (template) => {
73
66
  return requiredPlacementVariables(template.placements);
74
67
  };
75
68
 
69
+ // src/sdk/store.ts
70
+ import { Effect, Option as Option2, Predicate, Schema as Schema2 } from "effect";
71
+ var OPERATION_COLLECTION = "operation";
72
+ var STORE_OWNER = "org";
73
+ var OPERATION_KEY_VERSION = "op";
74
+ var encodeBinding = Schema2.encodeSync(OperationBinding);
75
+ var decodeBinding = Schema2.decodeUnknownSync(OperationBinding);
76
+ var decodeBindingJson = Schema2.decodeUnknownSync(Schema2.fromJsonString(OperationBinding));
77
+ var toJsonRecord = (value) => value;
78
+ var OperationStorage = Schema2.Struct({
79
+ integration: Schema2.String,
80
+ toolName: Schema2.String,
81
+ binding: Schema2.Unknown
82
+ });
83
+ var decodeOperationStorage = Schema2.decodeUnknownOption(OperationStorage);
84
+ var rowToOperation = (row) => {
85
+ const decoded = decodeOperationStorage(row.data);
86
+ if (Option2.isNone(decoded)) return null;
87
+ const operation = decoded.value;
88
+ return {
89
+ integration: operation.integration,
90
+ toolName: operation.toolName,
91
+ binding: decodeBinding(
92
+ typeof operation.binding === "string" ? decodeBindingJson(operation.binding) : operation.binding
93
+ )
94
+ };
95
+ };
96
+ var stableKeyHash = (value) => {
97
+ let hash = 0xcbf29ce484222325n;
98
+ const prime = 0x100000001b3n;
99
+ const mask = 0xffffffffffffffffn;
100
+ for (let index = 0; index < value.length; index += 1) {
101
+ hash ^= BigInt(value.charCodeAt(index));
102
+ hash = hash * prime & mask;
103
+ }
104
+ return hash.toString(36).padStart(13, "0");
105
+ };
106
+ var operationKey = (integration, toolName) => `${OPERATION_KEY_VERSION}.${stableKeyHash(integration)}.${stableKeyHash(toolName)}`;
107
+ var legacyOperationKey = (integration, toolName) => `${integration}.${toolName}`;
108
+ var specBlobKey = (specHash) => `spec/${specHash}`;
109
+ var makeDefaultOpenapiStore = ({ pluginStorage, blobs }) => {
110
+ const operationData = (operation) => ({
111
+ integration: operation.integration,
112
+ toolName: operation.toolName,
113
+ binding: toJsonRecord(encodeBinding(operation.binding))
114
+ });
115
+ const listRows = (integration) => pluginStorage.list({ collection: OPERATION_COLLECTION }).pipe(
116
+ Effect.map(
117
+ (rows) => rows.filter((row) => rowToOperation(row)?.integration === integration)
118
+ )
119
+ );
120
+ const removeOperations = (integration) => Effect.gen(function* () {
121
+ const rows = yield* listRows(integration);
122
+ yield* pluginStorage.removeMany({
123
+ owner: STORE_OWNER,
124
+ entries: rows.map((row) => ({ collection: OPERATION_COLLECTION, key: row.key }))
125
+ });
126
+ });
127
+ return {
128
+ putOperations: (integration, operations) => Effect.gen(function* () {
129
+ yield* removeOperations(integration);
130
+ yield* pluginStorage.putMany({
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
+ });
138
+ }),
139
+ getOperation: (integration, toolName) => Effect.gen(function* () {
140
+ const row = yield* pluginStorage.get({
141
+ collection: OPERATION_COLLECTION,
142
+ key: operationKey(integration, toolName)
143
+ });
144
+ if (row) return rowToOperation(row);
145
+ const legacyKey = legacyOperationKey(integration, toolName);
146
+ if (legacyKey.length > 255) return null;
147
+ const legacyRow = yield* pluginStorage.get({
148
+ collection: OPERATION_COLLECTION,
149
+ key: legacyKey
150
+ });
151
+ return legacyRow ? rowToOperation(legacyRow) : null;
152
+ }),
153
+ listOperations: (integration) => listRows(integration).pipe(
154
+ Effect.map((rows) => rows.map(rowToOperation).filter(Predicate.isNotNull))
155
+ ),
156
+ removeOperations,
157
+ putSpec: (specHash, specText) => blobs.put(specBlobKey(specHash), specText, { owner: STORE_OWNER }),
158
+ getSpec: (specHash) => blobs.get(specBlobKey(specHash))
159
+ };
160
+ };
161
+
76
162
  // src/sdk/invoke.ts
77
- import { Effect, Layer, Option as Option2 } from "effect";
163
+ import { Effect as Effect2, Layer, Option as Option3 } from "effect";
78
164
  import { HttpClient, HttpClientRequest } from "effect/unstable/http";
79
165
  var CONTAINER_KEYS = {
80
166
  path: ["path", "pathParams", "params"],
@@ -107,13 +193,13 @@ var encodeReservedAware = (raw, allowReserved) => {
107
193
  var queryParamValues = (value, param) => {
108
194
  if (value === void 0 || value === null) return [];
109
195
  if (!Array.isArray(value)) return [primitiveToString(value)];
110
- const style = Option2.getOrUndefined(param.style) ?? "form";
111
- const explode = Option2.getOrElse(param.explode, () => true);
196
+ const style = Option3.getOrUndefined(param.style) ?? "form";
197
+ const explode = Option3.getOrElse(param.explode, () => true);
112
198
  if (explode) return value.map(primitiveToString);
113
199
  const separator = style === "spaceDelimited" ? " " : style === "pipeDelimited" ? "|" : ",";
114
200
  return [value.map(primitiveToString).join(separator)];
115
201
  };
116
- var resolvePath = Effect.fn("OpenApi.resolvePath")(function* (pathTemplate, args, parameters) {
202
+ var resolvePath = Effect2.fn("OpenApi.resolvePath")(function* (pathTemplate, args, parameters) {
117
203
  let resolved = pathTemplate;
118
204
  for (const param of parameters) {
119
205
  if (param.location !== "path") continue;
@@ -122,14 +208,14 @@ var resolvePath = Effect.fn("OpenApi.resolvePath")(function* (pathTemplate, args
122
208
  if (param.required) {
123
209
  return yield* new OpenApiInvocationError({
124
210
  message: `Missing required path parameter: ${param.name}`,
125
- statusCode: Option2.none()
211
+ statusCode: Option3.none()
126
212
  });
127
213
  }
128
214
  continue;
129
215
  }
130
216
  const encoded = encodeReservedAware(
131
217
  String(value),
132
- Option2.getOrElse(param.allowReserved, () => false)
218
+ Option3.getOrElse(param.allowReserved, () => false)
133
219
  );
134
220
  resolved = resolved.replaceAll(`{${param.name}}`, encoded);
135
221
  resolved = resolved.replaceAll(`{+${param.name}}`, encoded);
@@ -145,7 +231,7 @@ var resolvePath = Effect.fn("OpenApi.resolvePath")(function* (pathTemplate, args
145
231
  if (unresolved.length > 0) {
146
232
  return yield* new OpenApiInvocationError({
147
233
  message: `Unresolved path parameters: ${[...new Set(unresolved)].join(", ")}`,
148
- statusCode: Option2.none()
234
+ statusCode: Option3.none()
149
235
  });
150
236
  }
151
237
  return resolved;
@@ -250,9 +336,9 @@ var toUint8Array = (value) => {
250
336
  }
251
337
  return null;
252
338
  };
253
- var readHintString = (option, fallback) => Option2.getOrElse(option, () => fallback);
254
- var readHintMimeType = (hint, fallback) => Option2.getOrElse(hint.mimeType, () => fallback);
255
- var readHintEncoding = (hint) => Option2.getOrElse(hint.encoding, () => "base64");
339
+ var readHintString = (option, fallback) => Option3.getOrElse(option, () => fallback);
340
+ var readHintMimeType = (hint, fallback) => Option3.getOrElse(hint.mimeType, () => fallback);
341
+ var readHintEncoding = (hint) => Option3.getOrElse(hint.encoding, () => "base64");
256
342
  var fileFromByteField = (body, hint) => {
257
343
  if (typeof body !== "object" || body === null || Array.isArray(body)) return null;
258
344
  const record = body;
@@ -260,7 +346,7 @@ var fileFromByteField = (body, hint) => {
260
346
  const rawData = record[dataField];
261
347
  if (typeof rawData !== "string") return null;
262
348
  const data = normalizeBase64(rawData, readHintEncoding(hint));
263
- const sizeField = Option2.getOrUndefined(hint.sizeField);
349
+ const sizeField = Option3.getOrUndefined(hint.sizeField);
264
350
  const byteLength = sizeField && typeof record[sizeField] === "number" ? record[sizeField] : byteLengthFromBase64(data);
265
351
  const hintedMimeType = readHintMimeType(hint, "application/octet-stream");
266
352
  return {
@@ -294,9 +380,9 @@ var DEFAULT_FORM_STYLE = {
294
380
  var resolveStyleExplode = (e) => {
295
381
  if (!e) return DEFAULT_FORM_STYLE;
296
382
  return {
297
- style: Option2.getOrElse(e.style, () => DEFAULT_FORM_STYLE.style),
298
- explode: Option2.getOrElse(e.explode, () => DEFAULT_FORM_STYLE.explode),
299
- allowReserved: Option2.getOrElse(e.allowReserved, () => DEFAULT_FORM_STYLE.allowReserved)
383
+ style: Option3.getOrElse(e.style, () => DEFAULT_FORM_STYLE.style),
384
+ explode: Option3.getOrElse(e.explode, () => DEFAULT_FORM_STYLE.explode),
385
+ allowReserved: Option3.getOrElse(e.allowReserved, () => DEFAULT_FORM_STYLE.allowReserved)
300
386
  };
301
387
  };
302
388
  var encodeFormValue = (v, allowReserved) => {
@@ -356,7 +442,7 @@ var coerceFormDataRecord = (value, encoding) => {
356
442
  const out = {};
357
443
  for (const [key, raw] of Object.entries(value)) {
358
444
  if (raw === void 0 || raw === null) continue;
359
- const partType = encoding?.[key] ? Option2.getOrUndefined(encoding[key].contentType) : void 0;
445
+ const partType = encoding?.[key] ? Option3.getOrUndefined(encoding[key].contentType) : void 0;
360
446
  if (partType) {
361
447
  const isJson = partType.startsWith("application/json") || partType.includes("+json");
362
448
  const serialized = typeof raw === "string" ? raw : isJson ? JSON.stringify(raw) : typeof raw === "object" ? JSON.stringify(raw) : String(raw);
@@ -437,9 +523,9 @@ var applyRequestBody = (request, contentType, bodyValue, encoding) => {
437
523
  if (bytes) return HttpClientRequest.bodyUint8Array(request, bytes, contentType);
438
524
  return HttpClientRequest.bodyText(request, JSON.stringify(bodyValue), contentType);
439
525
  };
440
- var invoke = Effect.fn("OpenApi.invoke")(function* (operation, args, resolvedHeaders, sourceQueryParams = {}) {
526
+ var invoke = Effect2.fn("OpenApi.invoke")(function* (operation, args, resolvedHeaders, sourceQueryParams = {}) {
441
527
  const client = yield* HttpClient.HttpClient;
442
- yield* Effect.annotateCurrentSpan({
528
+ yield* Effect2.annotateCurrentSpan({
443
529
  "http.method": operation.method.toUpperCase(),
444
530
  "http.route": operation.pathTemplate,
445
531
  "plugin.openapi.method": operation.method.toUpperCase(),
@@ -465,50 +551,50 @@ var invoke = Effect.fn("OpenApi.invoke")(function* (operation, args, resolvedHea
465
551
  if (value === void 0 || value === null) continue;
466
552
  request = HttpClientRequest.setHeader(request, param.name, String(value));
467
553
  }
468
- if (Option2.isSome(operation.requestBody)) {
554
+ if (Option3.isSome(operation.requestBody)) {
469
555
  const rb = operation.requestBody.value;
470
556
  const bodyValue = args.body ?? args.input;
471
557
  if (bodyValue !== void 0) {
472
- const contentsOpt = Option2.getOrUndefined(rb.contents);
558
+ const contentsOpt = Option3.getOrUndefined(rb.contents);
473
559
  const requestedCt = typeof args.contentType === "string" ? args.contentType : void 0;
474
560
  const selected = contentsOpt && requestedCt ? contentsOpt.find((c) => c.contentType === requestedCt) : void 0;
475
561
  const chosenCt = selected?.contentType ?? rb.contentType;
476
- const chosenEncoding = selected ? Option2.getOrUndefined(selected.encoding) : contentsOpt && contentsOpt[0] ? Option2.getOrUndefined(contentsOpt[0].encoding) : void 0;
562
+ const chosenEncoding = selected ? Option3.getOrUndefined(selected.encoding) : contentsOpt && contentsOpt[0] ? Option3.getOrUndefined(contentsOpt[0].encoding) : void 0;
477
563
  request = applyRequestBody(request, chosenCt, bodyValue, chosenEncoding);
478
564
  }
479
565
  }
480
566
  request = applyHeaders(request, resolvedHeaders);
481
567
  const response = yield* client.execute(request).pipe(
482
- Effect.mapError(
568
+ Effect2.mapError(
483
569
  (err) => new OpenApiInvocationError({
484
570
  message: "HTTP request failed",
485
- statusCode: Option2.none(),
571
+ statusCode: Option3.none(),
486
572
  cause: err
487
573
  })
488
574
  )
489
575
  );
490
576
  const status = response.status;
491
- yield* Effect.annotateCurrentSpan({
577
+ yield* Effect2.annotateCurrentSpan({
492
578
  "http.status_code": status
493
579
  });
494
580
  const responseHeaders = { ...response.headers };
495
581
  const contentType = response.headers["content-type"] ?? null;
496
- const mapBodyError = Effect.mapError(
582
+ const mapBodyError = Effect2.mapError(
497
583
  (err) => new OpenApiInvocationError({
498
584
  message: "Failed to read response body",
499
- statusCode: Option2.some(status),
585
+ statusCode: Option3.some(status),
500
586
  cause: err
501
587
  })
502
588
  );
503
- const responseBodyBinding = Option2.getOrUndefined(operation.responseBody);
504
- const fileHint = responseBodyBinding ? Option2.getOrUndefined(responseBodyBinding.fileHint) : void 0;
589
+ const responseBodyBinding = Option3.getOrUndefined(operation.responseBody);
590
+ const fileHint = responseBodyBinding ? Option3.getOrUndefined(responseBodyBinding.fileHint) : void 0;
505
591
  const ok = status >= 200 && status < 300;
506
592
  const responseBody = status === 204 ? null : ok && fileHint?.kind === "binaryResponse" ? fileFromBinaryBytes(
507
593
  new Uint8Array(yield* response.arrayBuffer.pipe(mapBodyError)),
508
594
  fileHint,
509
595
  contentType
510
596
  ) : isJsonContentType(contentType) ? yield* response.json.pipe(
511
- Effect.catch(() => response.text),
597
+ Effect2.catch(() => response.text),
512
598
  mapBodyError
513
599
  ) : yield* response.text.pipe(mapBodyError);
514
600
  const dataBody = ok && fileHint?.kind === "byteField" ? fileFromByteField(responseBody, fileHint) ?? responseBody : responseBody;
@@ -530,25 +616,25 @@ var resolveRequestHost = (servers, serverArg, baseUrl) => {
530
616
  if (value != null && value !== "") overrides[name] = String(value);
531
617
  }
532
618
  }
533
- return resolveServerUrl(chosen.url, Option2.getOrUndefined(chosen.variables), overrides);
619
+ return resolveServerUrl(chosen.url, Option3.getOrUndefined(chosen.variables), overrides);
534
620
  };
535
621
  var invokeWithLayer = (operation, args, baseUrl, resolvedHeaders, sourceQueryParams, httpClientLayer) => {
536
622
  const effectiveBaseUrl = resolveRequestHost(operation.servers ?? [], args.server, baseUrl);
537
623
  const clientWithBaseUrl = effectiveBaseUrl ? Layer.effect(
538
624
  HttpClient.HttpClient,
539
- Effect.map(
540
- Effect.service(HttpClient.HttpClient),
625
+ Effect2.map(
626
+ Effect2.service(HttpClient.HttpClient),
541
627
  HttpClient.mapRequest(HttpClientRequest.prependUrl(effectiveBaseUrl))
542
628
  )
543
629
  ).pipe(Layer.provide(httpClientLayer)) : httpClientLayer;
544
630
  return invoke(operation, args, resolvedHeaders, sourceQueryParams).pipe(
545
- Effect.provide(clientWithBaseUrl),
631
+ Effect2.provide(clientWithBaseUrl),
546
632
  // `invoke` annotates http.status_code on ITS span (`OpenApi.invoke`,
547
633
  // via Effect.fn) — annotateCurrentSpan inside it never reaches this
548
634
  // wrapper span. Stamp the status here too so queries against
549
635
  // `plugin.openapi.invoke` see the upstream outcome directly.
550
- Effect.tap((result) => Effect.annotateCurrentSpan({ "http.status_code": result.status })),
551
- Effect.withSpan("plugin.openapi.invoke", {
636
+ Effect2.tap((result) => Effect2.annotateCurrentSpan({ "http.status_code": result.status })),
637
+ Effect2.withSpan("plugin.openapi.invoke", {
552
638
  attributes: {
553
639
  "plugin.openapi.method": operation.method.toUpperCase(),
554
640
  "plugin.openapi.path_template": operation.pathTemplate,
@@ -567,89 +653,13 @@ var annotationsForOperation = (method, pathTemplate) => {
567
653
  };
568
654
  };
569
655
 
570
- // src/sdk/store.ts
571
- import { Effect as Effect2, Option as Option3, Predicate, Schema as Schema2 } from "effect";
572
- var OPERATION_COLLECTION = "operation";
573
- var STORE_OWNER = "org";
574
- var encodeBinding = Schema2.encodeSync(OperationBinding);
575
- var decodeBinding = Schema2.decodeUnknownSync(OperationBinding);
576
- var decodeBindingJson = Schema2.decodeUnknownSync(Schema2.fromJsonString(OperationBinding));
577
- var toJsonRecord = (value) => value;
578
- var OperationStorage = Schema2.Struct({
579
- integration: Schema2.String,
580
- toolName: Schema2.String,
581
- binding: Schema2.Unknown
582
- });
583
- var decodeOperationStorage = Schema2.decodeUnknownOption(OperationStorage);
584
- var rowToOperation = (row) => {
585
- const decoded = decodeOperationStorage(row.data);
586
- if (Option3.isNone(decoded)) return null;
587
- const operation = decoded.value;
588
- return {
589
- integration: operation.integration,
590
- toolName: operation.toolName,
591
- binding: decodeBinding(
592
- typeof operation.binding === "string" ? decodeBindingJson(operation.binding) : operation.binding
593
- )
594
- };
595
- };
596
- var operationKey = (integration, toolName) => `${integration}.${toolName}`;
597
- var specBlobKey = (specHash) => `spec/${specHash}`;
598
- var makeDefaultOpenapiStore = ({ pluginStorage, blobs }) => {
599
- const operationData = (operation) => ({
600
- integration: operation.integration,
601
- toolName: operation.toolName,
602
- binding: toJsonRecord(encodeBinding(operation.binding))
603
- });
604
- const listRows = (integration) => pluginStorage.list({ collection: OPERATION_COLLECTION, keyPrefix: `${integration}.` }).pipe(
605
- Effect2.map(
606
- (rows) => rows.filter((row) => rowToOperation(row)?.integration === integration)
607
- )
608
- );
609
- const removeOperations = (integration) => Effect2.gen(function* () {
610
- const rows = yield* listRows(integration);
611
- yield* pluginStorage.removeMany({
612
- owner: STORE_OWNER,
613
- entries: rows.map((row) => ({ collection: OPERATION_COLLECTION, key: row.key }))
614
- });
615
- });
616
- return {
617
- putOperations: (integration, operations) => Effect2.gen(function* () {
618
- yield* removeOperations(integration);
619
- yield* pluginStorage.putMany({
620
- owner: STORE_OWNER,
621
- entries: operations.map((operation) => ({
622
- collection: OPERATION_COLLECTION,
623
- key: operationKey(integration, operation.toolName),
624
- data: operationData(operation)
625
- }))
626
- });
627
- }),
628
- getOperation: (integration, toolName) => pluginStorage.get({ collection: OPERATION_COLLECTION, key: operationKey(integration, toolName) }).pipe(Effect2.map((row) => row ? rowToOperation(row) : null)),
629
- listOperations: (integration) => listRows(integration).pipe(
630
- Effect2.map((rows) => rows.map(rowToOperation).filter(Predicate.isNotNull))
631
- ),
632
- removeOperations,
633
- putSpec: (specHash, specText) => blobs.put(specBlobKey(specHash), specText, { owner: STORE_OWNER }),
634
- getSpec: (specHash) => blobs.get(specBlobKey(specHash))
635
- };
636
- };
637
-
638
- // src/sdk/plugin.ts
656
+ // src/sdk/backing.ts
639
657
  import { Effect as Effect3, Option as Option5, Schema as Schema3 } from "effect";
640
658
  import {
641
- IntegrationAlreadyExistsError,
642
- IntegrationDetectionResult,
643
- IntegrationNotFoundError,
644
- IntegrationSlug,
645
- ToolName,
646
659
  ToolFileJsonSchema,
660
+ ToolName,
647
661
  ToolResult,
648
- authToolFailure,
649
- definePlugin,
650
- mergeAuthTemplates,
651
- sha256Hex,
652
- tool
662
+ authToolFailure
653
663
  } from "@executor-js/sdk/core";
654
664
 
655
665
  // src/sdk/definitions.ts
@@ -797,8 +807,7 @@ var compileToolDefinitions = (operations) => {
797
807
  return resolveCollisions(raw).sort((a, b) => a.toolPath.localeCompare(b.toolPath));
798
808
  };
799
809
 
800
- // src/sdk/plugin.ts
801
- import { ApiKeyAuthTemplate, describeApiKeyAuthMethod } from "@executor-js/sdk/http-auth";
810
+ // src/sdk/backing.ts
802
811
  var STRINGIFIED_BODY_CAP = 1024;
803
812
  var UpstreamMessageBody = Schema3.Struct({ message: Schema3.String });
804
813
  var UpstreamErrorMessageBody = Schema3.Struct({ errorMessage: Schema3.String });
@@ -832,7 +841,7 @@ var clampedStringify = (value) => {
832
841
  return s.length > STRINGIFIED_BODY_CAP ? `${s.slice(0, STRINGIFIED_BODY_CAP)}\u2026` : s;
833
842
  };
834
843
  var firstNonEmpty = (...values) => values.find((value) => value !== void 0 && value.length > 0);
835
- var extractUpstreamMessage = (body, status) => {
844
+ var extractOpenApiUpstreamMessage = (body, status) => {
836
845
  if (typeof body === "string") {
837
846
  return body.length > 0 ? body : `Upstream returned HTTP ${status}`;
838
847
  }
@@ -863,162 +872,353 @@ var extractUpstreamMessage = (body, status) => {
863
872
  }
864
873
  return `Upstream returned HTTP ${status}`;
865
874
  };
866
- var PreviewSpecInputSchema = Schema3.Struct({
867
- spec: Schema3.String
875
+ var openApiAuthToolFailure = (failure) => authToolFailure({
876
+ code: failure.code,
877
+ message: failure.message,
878
+ source: { id: failure.integration, scope: failure.owner },
879
+ credential: {
880
+ kind: failure.credentialKind,
881
+ ...failure.credentialLabel ? { label: failure.credentialLabel } : {}
882
+ },
883
+ ...failure.status !== void 0 ? { status: failure.status } : {},
884
+ ...failure.details !== void 0 ? {
885
+ upstream: {
886
+ ...failure.status !== void 0 ? { status: failure.status } : {},
887
+ details: failure.details
888
+ }
889
+ } : {}
890
+ });
891
+ var normalizeOpenApiRefs = (node) => {
892
+ if (node == null || typeof node !== "object") return node;
893
+ if (Array.isArray(node)) {
894
+ let changed2 = false;
895
+ const out = node.map((item) => {
896
+ const n = normalizeOpenApiRefs(item);
897
+ if (n !== item) changed2 = true;
898
+ return n;
899
+ });
900
+ return changed2 ? out : node;
901
+ }
902
+ const obj = node;
903
+ if (typeof obj.$ref === "string") {
904
+ const match = obj.$ref.match(/^#\/components\/schemas\/(.+)$/);
905
+ if (match) return { ...obj, $ref: `#/$defs/${match[1]}` };
906
+ return obj;
907
+ }
908
+ let changed = false;
909
+ const result = {};
910
+ for (const [k, v] of Object.entries(obj)) {
911
+ const n = normalizeOpenApiRefs(v);
912
+ if (n !== v) changed = true;
913
+ result[k] = n;
914
+ }
915
+ return changed ? result : obj;
916
+ };
917
+ var toBinding = (def) => OperationBinding.make({
918
+ method: def.operation.method,
919
+ servers: def.operation.servers,
920
+ pathTemplate: def.operation.pathTemplate,
921
+ parameters: [...def.operation.parameters],
922
+ requestBody: def.operation.requestBody,
923
+ responseBody: def.operation.responseBody
924
+ });
925
+ var descriptionFor = (def) => {
926
+ const op = def.operation;
927
+ return Option5.getOrElse(
928
+ op.description,
929
+ () => Option5.getOrElse(op.summary, () => `${op.method.toUpperCase()} ${op.pathTemplate}`)
930
+ );
931
+ };
932
+ var compileOpenApiDocument = (doc) => Effect3.gen(function* () {
933
+ const result = yield* extract(doc);
934
+ const hoistedDefs = {};
935
+ if (doc.components?.schemas) {
936
+ for (const [k, v] of Object.entries(doc.components.schemas)) {
937
+ hoistedDefs[k] = normalizeOpenApiRefs(v);
938
+ }
939
+ }
940
+ return {
941
+ definitions: compileToolDefinitions(result.operations),
942
+ hoistedDefs,
943
+ title: Option5.getOrUndefined(result.title),
944
+ description: Option5.getOrUndefined(result.description)
945
+ };
946
+ });
947
+ var compileOpenApiSpec = (specText) => Effect3.gen(function* () {
948
+ const doc = yield* parse(specText);
949
+ return yield* compileOpenApiDocument(doc);
950
+ });
951
+ var openApiToolDefsFromCompiled = (compiled) => compiled.definitions.map(
952
+ (def) => ({
953
+ name: ToolName.make(def.toolPath),
954
+ description: descriptionFor(def),
955
+ inputSchema: normalizeOpenApiRefs(Option5.getOrUndefined(def.operation.inputSchema)),
956
+ outputSchema: Option5.match(def.operation.responseBody, {
957
+ onNone: () => normalizeOpenApiRefs(Option5.getOrUndefined(def.operation.outputSchema)),
958
+ onSome: (responseBody) => Option5.isSome(responseBody.fileHint) ? ToolFileJsonSchema : normalizeOpenApiRefs(Option5.getOrUndefined(def.operation.outputSchema))
959
+ }),
960
+ annotations: annotationsForOperation(def.operation.method, def.operation.pathTemplate)
961
+ })
962
+ );
963
+ var openApiStoredOperationsFromCompiled = (integration, compiled) => compiled.definitions.map((def) => ({
964
+ integration,
965
+ toolName: def.toolPath,
966
+ binding: toBinding(def)
967
+ }));
968
+ var loadOpenApiSpecText = (storage, config) => config.specHash != null ? storage.getSpec(config.specHash) : Effect3.succeed(null);
969
+ var resolveOpenApiBackedTools = ({
970
+ config,
971
+ storage
972
+ }) => Effect3.gen(function* () {
973
+ const openApiConfig = decodeOpenApiIntegrationConfig(config);
974
+ if (!openApiConfig) return { tools: [], definitions: {} };
975
+ const specText = yield* loadOpenApiSpecText(storage, openApiConfig);
976
+ if (specText == null) return { tools: [], definitions: {} };
977
+ const compiled = yield* compileOpenApiSpec(specText).pipe(
978
+ Effect3.catch(() => Effect3.succeed(null))
979
+ );
980
+ if (!compiled) return { tools: [], definitions: {} };
981
+ return {
982
+ tools: openApiToolDefsFromCompiled(compiled),
983
+ definitions: compiled.hoistedDefs
984
+ };
985
+ });
986
+ var invokeOpenApiBackedTool = (input) => Effect3.gen(function* () {
987
+ const integration = input.toolRow.integration;
988
+ const config = decodeOpenApiIntegrationConfig(input.credential.config);
989
+ let binding = (yield* input.ctx.storage.getOperation(integration, input.toolRow.name))?.binding;
990
+ if ((!binding || Option5.isNone(binding.responseBody)) && config) {
991
+ const specText = yield* loadOpenApiSpecText(input.ctx.storage, config).pipe(
992
+ Effect3.catch(() => Effect3.succeed(null))
993
+ );
994
+ const compiled = specText == null ? null : yield* compileOpenApiSpec(specText).pipe(Effect3.catch(() => Effect3.succeed(null)));
995
+ binding = compiled ? openApiStoredOperationsFromCompiled(integration, compiled).find(
996
+ (op) => op.toolName === input.toolRow.name
997
+ )?.binding : void 0;
998
+ }
999
+ if (!binding) {
1000
+ return yield* new OpenApiExtractionError({
1001
+ message: `No OpenAPI operation found for tool "${input.toolRow.name}" on "${integration}"`
1002
+ });
1003
+ }
1004
+ const headers = { ...config?.headers ?? {} };
1005
+ const queryParams = {
1006
+ ...config?.queryParams ?? {}
1007
+ };
1008
+ const template = (config?.authenticationTemplate ?? []).find(
1009
+ (entry) => String(entry.slug) === String(input.credential.template)
1010
+ );
1011
+ if (template) {
1012
+ const missing = requiredTemplateVariables(template).filter((name) => {
1013
+ const value = input.credential.values[name];
1014
+ return value == null || value === "";
1015
+ });
1016
+ if (missing.length > 0) {
1017
+ return openApiAuthToolFailure({
1018
+ code: template.kind === "oauth2" ? "oauth_connection_missing" : "connection_value_missing",
1019
+ message: `Connection "${input.credential.connection}" for "${integration}" has no resolvable credential value. Re-authenticate or update the connection.`,
1020
+ owner: input.credential.owner,
1021
+ integration,
1022
+ connection: String(input.credential.connection),
1023
+ credentialKind: template.kind === "oauth2" ? "oauth" : "secret"
1024
+ });
1025
+ }
1026
+ const rendered = renderAuthTemplate(template, input.credential.values);
1027
+ Object.assign(headers, rendered.headers);
1028
+ Object.assign(queryParams, rendered.queryParams);
1029
+ }
1030
+ const result = yield* invokeWithLayer(
1031
+ binding,
1032
+ input.args ?? {},
1033
+ config?.baseUrl ?? "",
1034
+ headers,
1035
+ queryParams,
1036
+ input.httpClientLayer
1037
+ );
1038
+ const ok = result.status >= 200 && result.status < 300;
1039
+ if (!ok) {
1040
+ if (result.status === 401 || result.status === 403) {
1041
+ return openApiAuthToolFailure({
1042
+ code: "connection_rejected",
1043
+ status: result.status,
1044
+ message: `Upstream rejected credentials for "${integration}" with HTTP ${result.status}. Re-authenticate or update the connection "${input.credential.connection}" before retrying this tool.`,
1045
+ owner: input.credential.owner,
1046
+ integration,
1047
+ connection: String(input.credential.connection),
1048
+ credentialKind: "upstream",
1049
+ credentialLabel: "Upstream authorization",
1050
+ details: result.error
1051
+ });
1052
+ }
1053
+ return ToolResult.fail({
1054
+ code: "upstream_http_error",
1055
+ status: result.status,
1056
+ message: extractOpenApiUpstreamMessage(result.error, result.status),
1057
+ details: result.error
1058
+ });
1059
+ }
1060
+ return ToolResult.ok(result.data, {
1061
+ http: { status: result.status, headers: result.headers }
1062
+ });
1063
+ });
1064
+ var resolveOpenApiBackedAnnotations = (input) => Effect3.gen(function* () {
1065
+ const ops = yield* input.ctx.storage.listOperations(String(input.integration));
1066
+ const byName = /* @__PURE__ */ new Map();
1067
+ for (const op of ops) byName.set(op.toolName, op.binding);
1068
+ const out = {};
1069
+ for (const row of input.toolRows) {
1070
+ const binding = byName.get(row.name);
1071
+ if (binding) {
1072
+ out[row.name] = annotationsForOperation(binding.method, binding.pathTemplate);
1073
+ }
1074
+ }
1075
+ return out;
868
1076
  });
869
- var StaticPreviewServerVariableSchema = Schema3.Struct({
870
- default: Schema3.String,
871
- enum: Schema3.NullOr(Schema3.Array(Schema3.String)),
872
- description: Schema3.NullOr(Schema3.String)
1077
+
1078
+ // src/sdk/plugin.ts
1079
+ import { Effect as Effect4, Option as Option6, Schema as Schema4 } from "effect";
1080
+ import {
1081
+ IntegrationAlreadyExistsError,
1082
+ IntegrationDetectionResult,
1083
+ IntegrationNotFoundError,
1084
+ IntegrationSlug,
1085
+ ToolResult as ToolResult2,
1086
+ definePlugin,
1087
+ mergeAuthTemplates,
1088
+ sha256Hex,
1089
+ tool
1090
+ } from "@executor-js/sdk/core";
1091
+ import { ApiKeyAuthTemplate, describeApiKeyAuthMethod } from "@executor-js/sdk/http-auth";
1092
+ var PreviewSpecInputSchema = Schema4.Struct({
1093
+ spec: Schema4.String
1094
+ });
1095
+ var StaticPreviewServerVariableSchema = Schema4.Struct({
1096
+ default: Schema4.String,
1097
+ enum: Schema4.NullOr(Schema4.Array(Schema4.String)),
1098
+ description: Schema4.NullOr(Schema4.String)
873
1099
  });
874
- var StaticPreviewServerSchema = Schema3.Struct({
875
- url: Schema3.String,
876
- description: Schema3.NullOr(Schema3.String),
877
- variables: Schema3.NullOr(Schema3.Record(Schema3.String, StaticPreviewServerVariableSchema))
1100
+ var StaticPreviewServerSchema = Schema4.Struct({
1101
+ url: Schema4.String,
1102
+ description: Schema4.NullOr(Schema4.String),
1103
+ variables: Schema4.NullOr(Schema4.Record(Schema4.String, StaticPreviewServerVariableSchema))
878
1104
  });
879
- var StaticPreviewOAuthAuthorizationCodeFlowSchema = Schema3.Struct({
880
- authorizationUrl: Schema3.String,
881
- tokenUrl: Schema3.String,
882
- refreshUrl: Schema3.NullOr(Schema3.String),
883
- scopes: Schema3.Record(Schema3.String, Schema3.String)
1105
+ var StaticPreviewOAuthAuthorizationCodeFlowSchema = Schema4.Struct({
1106
+ authorizationUrl: Schema4.String,
1107
+ tokenUrl: Schema4.String,
1108
+ refreshUrl: Schema4.NullOr(Schema4.String),
1109
+ scopes: Schema4.Record(Schema4.String, Schema4.String)
884
1110
  });
885
- var StaticPreviewOAuthClientCredentialsFlowSchema = Schema3.Struct({
886
- tokenUrl: Schema3.String,
887
- refreshUrl: Schema3.NullOr(Schema3.String),
888
- scopes: Schema3.Record(Schema3.String, Schema3.String)
1111
+ var StaticPreviewOAuthClientCredentialsFlowSchema = Schema4.Struct({
1112
+ tokenUrl: Schema4.String,
1113
+ refreshUrl: Schema4.NullOr(Schema4.String),
1114
+ scopes: Schema4.Record(Schema4.String, Schema4.String)
889
1115
  });
890
- var StaticPreviewOAuthFlowsSchema = Schema3.Struct({
891
- authorizationCode: Schema3.NullOr(StaticPreviewOAuthAuthorizationCodeFlowSchema),
892
- clientCredentials: Schema3.NullOr(StaticPreviewOAuthClientCredentialsFlowSchema)
1116
+ var StaticPreviewOAuthFlowsSchema = Schema4.Struct({
1117
+ authorizationCode: Schema4.NullOr(StaticPreviewOAuthAuthorizationCodeFlowSchema),
1118
+ clientCredentials: Schema4.NullOr(StaticPreviewOAuthClientCredentialsFlowSchema)
893
1119
  });
894
- var StaticPreviewSecuritySchemeSchema = Schema3.Struct({
895
- name: Schema3.String,
896
- type: Schema3.Literals(["http", "apiKey", "oauth2", "openIdConnect"]),
897
- scheme: Schema3.NullOr(Schema3.String),
898
- bearerFormat: Schema3.NullOr(Schema3.String),
899
- in: Schema3.NullOr(Schema3.Literals(["header", "query", "cookie"])),
900
- headerName: Schema3.NullOr(Schema3.String),
901
- description: Schema3.NullOr(Schema3.String),
902
- flows: Schema3.NullOr(StaticPreviewOAuthFlowsSchema),
903
- openIdConnectUrl: Schema3.NullOr(Schema3.String)
1120
+ var StaticPreviewSecuritySchemeSchema = Schema4.Struct({
1121
+ name: Schema4.String,
1122
+ type: Schema4.Literals(["http", "apiKey", "oauth2", "openIdConnect"]),
1123
+ scheme: Schema4.NullOr(Schema4.String),
1124
+ bearerFormat: Schema4.NullOr(Schema4.String),
1125
+ in: Schema4.NullOr(Schema4.Literals(["header", "query", "cookie"])),
1126
+ headerName: Schema4.NullOr(Schema4.String),
1127
+ description: Schema4.NullOr(Schema4.String),
1128
+ flows: Schema4.NullOr(StaticPreviewOAuthFlowsSchema),
1129
+ openIdConnectUrl: Schema4.NullOr(Schema4.String)
904
1130
  });
905
- var StaticPreviewOAuth2PresetSchema = Schema3.Struct({
906
- label: Schema3.String,
907
- securitySchemeName: Schema3.String,
908
- flow: Schema3.Literals(["authorizationCode", "clientCredentials"]),
909
- authorizationUrl: Schema3.NullOr(Schema3.String),
910
- tokenUrl: Schema3.String,
911
- refreshUrl: Schema3.NullOr(Schema3.String),
912
- scopes: Schema3.Record(Schema3.String, Schema3.String),
913
- identityScopes: Schema3.Union([
914
- Schema3.Literal("auto"),
915
- Schema3.Literal(false),
916
- Schema3.Array(Schema3.String)
1131
+ var StaticPreviewOAuth2PresetSchema = Schema4.Struct({
1132
+ label: Schema4.String,
1133
+ securitySchemeName: Schema4.String,
1134
+ flow: Schema4.Literals(["authorizationCode", "clientCredentials"]),
1135
+ authorizationUrl: Schema4.NullOr(Schema4.String),
1136
+ tokenUrl: Schema4.String,
1137
+ refreshUrl: Schema4.NullOr(Schema4.String),
1138
+ scopes: Schema4.Record(Schema4.String, Schema4.String),
1139
+ identityScopes: Schema4.Union([
1140
+ Schema4.Literal("auto"),
1141
+ Schema4.Literal(false),
1142
+ Schema4.Array(Schema4.String)
917
1143
  ])
918
1144
  });
919
- var StaticPreviewSpecOutputSchema = Schema3.Struct({
920
- title: Schema3.NullOr(Schema3.String),
921
- version: Schema3.NullOr(Schema3.String),
922
- servers: Schema3.Array(StaticPreviewServerSchema),
923
- operationCount: Schema3.Number,
924
- tags: Schema3.Array(Schema3.String),
925
- securitySchemes: Schema3.Array(StaticPreviewSecuritySchemeSchema),
926
- authStrategies: Schema3.Array(Schema3.Struct({ schemes: Schema3.Array(Schema3.String) })),
927
- headerPresets: Schema3.Array(
928
- Schema3.Struct({
929
- label: Schema3.String,
930
- headers: Schema3.Record(Schema3.String, Schema3.NullOr(Schema3.String)),
931
- secretHeaders: Schema3.Array(Schema3.String)
1145
+ var StaticPreviewSpecOutputSchema = Schema4.Struct({
1146
+ title: Schema4.NullOr(Schema4.String),
1147
+ version: Schema4.NullOr(Schema4.String),
1148
+ servers: Schema4.Array(StaticPreviewServerSchema),
1149
+ operationCount: Schema4.Number,
1150
+ tags: Schema4.Array(Schema4.String),
1151
+ securitySchemes: Schema4.Array(StaticPreviewSecuritySchemeSchema),
1152
+ authStrategies: Schema4.Array(Schema4.Struct({ schemes: Schema4.Array(Schema4.String) })),
1153
+ headerPresets: Schema4.Array(
1154
+ Schema4.Struct({
1155
+ label: Schema4.String,
1156
+ headers: Schema4.Record(Schema4.String, Schema4.NullOr(Schema4.String)),
1157
+ secretHeaders: Schema4.Array(Schema4.String)
932
1158
  })
933
1159
  ),
934
- oauth2Presets: Schema3.Array(StaticPreviewOAuth2PresetSchema)
1160
+ oauth2Presets: Schema4.Array(StaticPreviewOAuth2PresetSchema)
935
1161
  });
936
- var OpenApiSpecInputSchema = Schema3.Union([
937
- Schema3.Struct({ kind: Schema3.Literal("url"), url: Schema3.String }),
938
- Schema3.Struct({ kind: Schema3.Literal("blob"), value: Schema3.String }),
939
- Schema3.Struct({
940
- kind: Schema3.Literal("googleDiscovery"),
941
- url: Schema3.String
942
- }),
943
- Schema3.Struct({
944
- kind: Schema3.Literal("googleDiscoveryBundle"),
945
- urls: Schema3.Array(Schema3.String)
946
- })
1162
+ var OpenApiSpecInputSchema = Schema4.Union([
1163
+ Schema4.Struct({ kind: Schema4.Literal("url"), url: Schema4.String }),
1164
+ Schema4.Struct({ kind: Schema4.Literal("blob"), value: Schema4.String })
947
1165
  ]);
948
- var AuthenticationSchema2 = Schema3.Union([
949
- Schema3.Struct({
950
- slug: Schema3.String,
951
- kind: Schema3.Literal("oauth2"),
952
- authorizationUrl: Schema3.String,
953
- tokenUrl: Schema3.String,
954
- scopes: Schema3.Array(Schema3.String)
1166
+ var AuthenticationSchema2 = Schema4.Union([
1167
+ Schema4.Struct({
1168
+ slug: Schema4.String,
1169
+ kind: Schema4.Literal("oauth2"),
1170
+ authorizationUrl: Schema4.String,
1171
+ tokenUrl: Schema4.String,
1172
+ scopes: Schema4.Array(Schema4.String)
955
1173
  }),
956
- // Credential methods are authored request-shaped the ONE apikey input
1174
+ // Credential methods are authored request-shaped - the ONE apikey input
957
1175
  // dialect: `{ type: "apiKey", headers: { Authorization: ["Bearer ",
958
1176
  // variable("token")] }, queryParams: { … } }`.
959
1177
  ApiKeyAuthTemplate
960
1178
  ]);
961
- var AddSourceInputSchema = Schema3.Struct({
1179
+ var AddSourceInputSchema = Schema4.Struct({
962
1180
  spec: OpenApiSpecInputSchema,
963
- slug: Schema3.String,
964
- description: Schema3.optional(Schema3.String),
965
- baseUrl: Schema3.optional(Schema3.String),
966
- headers: Schema3.optional(Schema3.Record(Schema3.String, Schema3.String)),
967
- queryParams: Schema3.optional(Schema3.Record(Schema3.String, Schema3.String)),
968
- authenticationTemplate: Schema3.optional(Schema3.Array(AuthenticationSchema2))
1181
+ slug: Schema4.String,
1182
+ description: Schema4.optional(Schema4.String),
1183
+ baseUrl: Schema4.optional(Schema4.String),
1184
+ headers: Schema4.optional(Schema4.Record(Schema4.String, Schema4.String)),
1185
+ queryParams: Schema4.optional(Schema4.Record(Schema4.String, Schema4.String)),
1186
+ authenticationTemplate: Schema4.optional(Schema4.Array(AuthenticationSchema2))
969
1187
  });
970
- var AddSourceOutputSchema = Schema3.Struct({
971
- slug: Schema3.String,
972
- toolCount: Schema3.Number
1188
+ var AddSourceOutputSchema = Schema4.Struct({
1189
+ slug: Schema4.String,
1190
+ toolCount: Schema4.Number
973
1191
  });
974
- var PreviewSpecInputStandardSchema = Schema3.toStandardSchemaV1(
975
- Schema3.toStandardJSONSchemaV1(PreviewSpecInputSchema)
1192
+ var PreviewSpecInputStandardSchema = Schema4.toStandardSchemaV1(
1193
+ Schema4.toStandardJSONSchemaV1(PreviewSpecInputSchema)
976
1194
  );
977
- var PreviewSpecOutputStandardSchema = Schema3.toStandardSchemaV1(
978
- Schema3.toStandardJSONSchemaV1(StaticPreviewSpecOutputSchema)
1195
+ var PreviewSpecOutputStandardSchema = Schema4.toStandardSchemaV1(
1196
+ Schema4.toStandardJSONSchemaV1(StaticPreviewSpecOutputSchema)
979
1197
  );
980
- var AddSourceInputStandardSchema = Schema3.toStandardSchemaV1(
981
- Schema3.toStandardJSONSchemaV1(AddSourceInputSchema)
1198
+ var AddSourceInputStandardSchema = Schema4.toStandardSchemaV1(
1199
+ Schema4.toStandardJSONSchemaV1(AddSourceInputSchema)
982
1200
  );
983
- var AddSourceOutputStandardSchema = Schema3.toStandardSchemaV1(
984
- Schema3.toStandardJSONSchemaV1(AddSourceOutputSchema)
1201
+ var AddSourceOutputStandardSchema = Schema4.toStandardSchemaV1(
1202
+ Schema4.toStandardJSONSchemaV1(AddSourceOutputSchema)
985
1203
  );
986
- var openApiToolFailure = (code, message, details) => ToolResult.fail({
1204
+ var openApiToolFailure = (code, message, details) => ToolResult2.fail({
987
1205
  code,
988
1206
  message,
989
1207
  ...details === void 0 ? {} : { details }
990
1208
  });
991
- var openApiAuthToolFailure = (failure) => authToolFailure({
992
- // The auth-tool-failure helper's code set is shared with v1; keep the
993
- // string but reference the connection rather than v1's source/slot.
994
- code: failure.code,
995
- message: failure.message,
996
- source: { id: failure.integration, scope: failure.owner },
997
- credential: {
998
- kind: failure.credentialKind,
999
- ...failure.credentialLabel ? { label: failure.credentialLabel } : {}
1000
- },
1001
- ...failure.status !== void 0 ? { status: failure.status } : {},
1002
- ...failure.details !== void 0 ? {
1003
- upstream: {
1004
- ...failure.status !== void 0 ? { status: failure.status } : {},
1005
- details: failure.details
1006
- }
1007
- } : {}
1008
- });
1009
1209
  var staticPreviewOutput = (preview) => ({
1010
- title: Option5.getOrNull(preview.title),
1011
- version: Option5.getOrNull(preview.version),
1210
+ title: Option6.getOrNull(preview.title),
1211
+ version: Option6.getOrNull(preview.version),
1012
1212
  servers: preview.servers.map((server) => ({
1013
1213
  url: server.url,
1014
- description: Option5.getOrNull(server.description),
1015
- variables: Option5.getOrNull(server.variables) ? Object.fromEntries(
1016
- Object.entries(Option5.getOrNull(server.variables) ?? {}).map(([name, variable]) => [
1214
+ description: Option6.getOrNull(server.description),
1215
+ variables: Option6.getOrNull(server.variables) ? Object.fromEntries(
1216
+ Object.entries(Option6.getOrNull(server.variables) ?? {}).map(([name, variable]) => [
1017
1217
  name,
1018
1218
  {
1019
1219
  default: variable.default,
1020
- enum: Option5.getOrNull(variable.enum),
1021
- description: Option5.getOrNull(variable.description)
1220
+ enum: Option6.getOrNull(variable.enum),
1221
+ description: Option6.getOrNull(variable.description)
1022
1222
  }
1023
1223
  ])
1024
1224
  ) : null
@@ -1028,25 +1228,25 @@ var staticPreviewOutput = (preview) => ({
1028
1228
  securitySchemes: preview.securitySchemes.map((scheme) => ({
1029
1229
  name: scheme.name,
1030
1230
  type: scheme.type,
1031
- scheme: Option5.getOrNull(scheme.scheme),
1032
- bearerFormat: Option5.getOrNull(scheme.bearerFormat),
1033
- in: Option5.getOrNull(scheme.in),
1034
- headerName: Option5.getOrNull(scheme.headerName),
1035
- description: Option5.getOrNull(scheme.description),
1036
- flows: Option5.isSome(scheme.flows) ? {
1037
- authorizationCode: Option5.isSome(scheme.flows.value.authorizationCode) ? {
1231
+ scheme: Option6.getOrNull(scheme.scheme),
1232
+ bearerFormat: Option6.getOrNull(scheme.bearerFormat),
1233
+ in: Option6.getOrNull(scheme.in),
1234
+ headerName: Option6.getOrNull(scheme.headerName),
1235
+ description: Option6.getOrNull(scheme.description),
1236
+ flows: Option6.isSome(scheme.flows) ? {
1237
+ authorizationCode: Option6.isSome(scheme.flows.value.authorizationCode) ? {
1038
1238
  authorizationUrl: scheme.flows.value.authorizationCode.value.authorizationUrl,
1039
1239
  tokenUrl: scheme.flows.value.authorizationCode.value.tokenUrl,
1040
- refreshUrl: Option5.getOrNull(scheme.flows.value.authorizationCode.value.refreshUrl),
1240
+ refreshUrl: Option6.getOrNull(scheme.flows.value.authorizationCode.value.refreshUrl),
1041
1241
  scopes: scheme.flows.value.authorizationCode.value.scopes
1042
1242
  } : null,
1043
- clientCredentials: Option5.isSome(scheme.flows.value.clientCredentials) ? {
1243
+ clientCredentials: Option6.isSome(scheme.flows.value.clientCredentials) ? {
1044
1244
  tokenUrl: scheme.flows.value.clientCredentials.value.tokenUrl,
1045
- refreshUrl: Option5.getOrNull(scheme.flows.value.clientCredentials.value.refreshUrl),
1245
+ refreshUrl: Option6.getOrNull(scheme.flows.value.clientCredentials.value.refreshUrl),
1046
1246
  scopes: scheme.flows.value.clientCredentials.value.scopes
1047
1247
  } : null
1048
1248
  } : null,
1049
- openIdConnectUrl: Option5.getOrNull(scheme.openIdConnectUrl)
1249
+ openIdConnectUrl: Option6.getOrNull(scheme.openIdConnectUrl)
1050
1250
  })),
1051
1251
  authStrategies: preview.authStrategies,
1052
1252
  headerPresets: preview.headerPresets,
@@ -1054,56 +1254,14 @@ var staticPreviewOutput = (preview) => ({
1054
1254
  label: preset.label,
1055
1255
  securitySchemeName: preset.securitySchemeName,
1056
1256
  flow: preset.flow,
1057
- authorizationUrl: Option5.getOrNull(preset.authorizationUrl),
1257
+ authorizationUrl: Option6.getOrNull(preset.authorizationUrl),
1058
1258
  tokenUrl: preset.tokenUrl,
1059
- refreshUrl: Option5.getOrNull(preset.refreshUrl),
1259
+ refreshUrl: Option6.getOrNull(preset.refreshUrl),
1060
1260
  scopes: preset.scopes,
1061
1261
  identityScopes: preset.identityScopes
1062
1262
  }))
1063
1263
  });
1064
- var normalizeOpenApiRefs = (node) => {
1065
- if (node == null || typeof node !== "object") return node;
1066
- if (Array.isArray(node)) {
1067
- let changed2 = false;
1068
- const out = node.map((item) => {
1069
- const n = normalizeOpenApiRefs(item);
1070
- if (n !== item) changed2 = true;
1071
- return n;
1072
- });
1073
- return changed2 ? out : node;
1074
- }
1075
- const obj = node;
1076
- if (typeof obj.$ref === "string") {
1077
- const match = obj.$ref.match(/^#\/components\/schemas\/(.+)$/);
1078
- if (match) return { ...obj, $ref: `#/$defs/${match[1]}` };
1079
- return obj;
1080
- }
1081
- let changed = false;
1082
- const result = {};
1083
- for (const [k, v] of Object.entries(obj)) {
1084
- const n = normalizeOpenApiRefs(v);
1085
- if (n !== v) changed = true;
1086
- result[k] = n;
1087
- }
1088
- return changed ? result : obj;
1089
- };
1090
- var toBinding = (def) => OperationBinding.make({
1091
- method: def.operation.method,
1092
- servers: def.operation.servers,
1093
- pathTemplate: def.operation.pathTemplate,
1094
- parameters: [...def.operation.parameters],
1095
- requestBody: def.operation.requestBody,
1096
- responseBody: def.operation.responseBody
1097
- });
1098
- var descriptionFor = (def) => {
1099
- const op = def.operation;
1100
- return Option5.getOrElse(
1101
- op.description,
1102
- () => Option5.getOrElse(op.summary, () => `${op.method.toUpperCase()} ${op.pathTemplate}`)
1103
- );
1104
- };
1105
- var specInputToSourceUrl = (spec) => spec.kind === "url" || spec.kind === "googleDiscovery" ? spec.url : void 0;
1106
- var specInputToGoogleBundle = (spec) => spec.kind === "googleDiscoveryBundle" ? spec.urls : void 0;
1264
+ var specInputToSourceUrl = (spec) => spec.kind === "url" ? spec.url : void 0;
1107
1265
  var describeOpenApiAuthMethods = (record) => {
1108
1266
  const config = decodeOpenApiIntegrationConfig(record.config);
1109
1267
  if (!config) return [];
@@ -1130,79 +1288,10 @@ var describeOpenApiIntegrationDisplay = (record) => {
1130
1288
  const config = decodeOpenApiIntegrationConfig(record.config);
1131
1289
  return { url: config?.baseUrl ?? config?.sourceUrl };
1132
1290
  };
1133
- var loadSpecText = (storage, config) => config.specHash != null ? storage.getSpec(config.specHash) : Effect3.succeed(null);
1134
- var compileSpec = (specText) => Effect3.gen(function* () {
1135
- const doc = yield* parse(specText);
1136
- const result = yield* extract(doc);
1137
- const hoistedDefs = {};
1138
- if (doc.components?.schemas) {
1139
- for (const [k, v] of Object.entries(doc.components.schemas)) {
1140
- hoistedDefs[k] = normalizeOpenApiRefs(v);
1141
- }
1142
- }
1143
- return {
1144
- definitions: compileToolDefinitions(result.operations),
1145
- hoistedDefs,
1146
- title: Option5.getOrUndefined(result.title),
1147
- description: Option5.getOrUndefined(result.description)
1148
- };
1149
- });
1150
- var toolDefsFromCompiled = (compiled) => compiled.definitions.map(
1151
- (def) => ({
1152
- name: ToolName.make(def.toolPath),
1153
- description: descriptionFor(def),
1154
- inputSchema: normalizeOpenApiRefs(Option5.getOrUndefined(def.operation.inputSchema)),
1155
- // The output schema is the upstream response body only — transport
1156
- // status/headers live in the ToolResult `http` side channel, not the
1157
- // payload (see the invoke handler).
1158
- outputSchema: Option5.match(def.operation.responseBody, {
1159
- onNone: () => normalizeOpenApiRefs(Option5.getOrUndefined(def.operation.outputSchema)),
1160
- onSome: (responseBody) => Option5.isSome(responseBody.fileHint) ? ToolFileJsonSchema : normalizeOpenApiRefs(Option5.getOrUndefined(def.operation.outputSchema))
1161
- }),
1162
- annotations: annotationsForOperation(def.operation.method, def.operation.pathTemplate)
1163
- })
1164
- );
1165
- var storedOperationsFromCompiled = (integration, compiled) => compiled.definitions.map((def) => ({
1166
- integration,
1167
- toolName: def.toolPath,
1168
- binding: toBinding(def)
1169
- }));
1170
- var fetchGoogleDiscoveryBundleConversion = (urls, httpClientLayer) => Effect3.forEach(
1171
- urls,
1172
- (url) => fetchGoogleDiscoveryDocument(url).pipe(
1173
- Effect3.provide(httpClientLayer),
1174
- Effect3.map((documentText) => ({ discoveryUrl: url, documentText }))
1175
- ),
1176
- { concurrency: 4 }
1177
- ).pipe(Effect3.flatMap((documents) => convertGoogleDiscoveryBundleToOpenApi({ documents })));
1178
1291
  var openApiPlugin = definePlugin((options) => {
1179
- const resolveSpecForInput = (spec, httpClientLayer) => Effect3.gen(function* () {
1180
- if (spec.kind === "googleDiscovery") {
1181
- const conversion = yield* fetchGoogleDiscoveryDocument(spec.url).pipe(
1182
- Effect3.provide(httpClientLayer),
1183
- Effect3.flatMap(
1184
- (documentText) => convertGoogleDiscoveryToOpenApi({
1185
- discoveryUrl: spec.url,
1186
- documentText
1187
- })
1188
- )
1189
- );
1190
- return {
1191
- specText: conversion.specText,
1192
- baseUrl: conversion.baseUrl,
1193
- ...conversion.authenticationTemplate ? { authenticationTemplate: conversion.authenticationTemplate } : {}
1194
- };
1195
- }
1196
- if (spec.kind === "googleDiscoveryBundle") {
1197
- const conversion = yield* fetchGoogleDiscoveryBundleConversion(spec.urls, httpClientLayer);
1198
- return {
1199
- specText: conversion.specText,
1200
- baseUrl: conversion.baseUrl,
1201
- ...conversion.authenticationTemplate ? { authenticationTemplate: conversion.authenticationTemplate } : {}
1202
- };
1203
- }
1292
+ const resolveSpecForInput = (spec, httpClientLayer) => Effect4.gen(function* () {
1204
1293
  if (spec.kind === "url") {
1205
- const specText = yield* resolveSpecText(spec.url).pipe(Effect3.provide(httpClientLayer));
1294
+ const specText = yield* resolveSpecText(spec.url).pipe(Effect4.provide(httpClientLayer));
1206
1295
  return { specText };
1207
1296
  }
1208
1297
  return { specText: spec.value };
@@ -1221,12 +1310,12 @@ var openApiPlugin = definePlugin((options) => {
1221
1310
  storage: (deps) => makeDefaultOpenapiStore(deps),
1222
1311
  extension: (ctx) => {
1223
1312
  const httpClientLayer = options?.httpClientLayer ?? ctx.httpClientLayer;
1224
- const addSpec = (config) => Effect3.gen(function* () {
1313
+ const addSpec = (config) => Effect4.gen(function* () {
1225
1314
  const resolved = yield* resolveSpecForInput(config.spec, httpClientLayer);
1226
- const compiled = yield* compileSpec(resolved.specText);
1227
- const explicitBaseUrl = config.baseUrl ?? resolved.baseUrl;
1315
+ const compiled = yield* compileOpenApiSpec(resolved.specText);
1316
+ const explicitBaseUrl = config.baseUrl;
1228
1317
  const needsDerivedBaseUrl = explicitBaseUrl == null;
1229
- const needsDerivedAuth = config.authenticationTemplate == null && resolved.authenticationTemplate == null;
1318
+ const needsDerivedAuth = config.authenticationTemplate == null;
1230
1319
  const preview = needsDerivedBaseUrl || needsDerivedAuth ? yield* previewSpecText(resolved.specText) : void 0;
1231
1320
  const derivedBaseUrl = needsDerivedBaseUrl && preview ? firstBaseUrlForPreview(preview) : void 0;
1232
1321
  const effectiveBaseUrl = explicitBaseUrl ?? (derivedBaseUrl || void 0);
@@ -1240,55 +1329,52 @@ var openApiPlugin = definePlugin((options) => {
1240
1329
  const integrationConfig = {
1241
1330
  specHash,
1242
1331
  ...specInputToSourceUrl(config.spec) !== void 0 ? { sourceUrl: specInputToSourceUrl(config.spec) } : {},
1243
- ...specInputToGoogleBundle(config.spec) !== void 0 ? { googleDiscoveryUrls: specInputToGoogleBundle(config.spec) } : {},
1244
1332
  // baseUrl is an optional override only. The host is otherwise
1245
1333
  // resolved per call from the operation's `servers` (extracted from
1246
1334
  // the spec), so we never bake a derived base URL into the config.
1247
1335
  ...config.baseUrl ? { baseUrl: config.baseUrl } : {},
1248
1336
  ...config.headers ? { headers: config.headers } : {},
1249
1337
  ...config.queryParams ? { queryParams: config.queryParams } : {},
1250
- // Prefer the caller's explicit template; otherwise adopt the one the
1251
- // Google Discovery converter derived from the spec (the bundle add
1252
- // path relies on this — it has no preview to detect auth from);
1253
- // otherwise derive from the spec's declared security schemes.
1338
+ // Prefer the caller's explicit template; otherwise derive from the
1339
+ // spec's declared security schemes.
1254
1340
  ...config.authenticationTemplate ? {
1255
1341
  authenticationTemplate: normalizeOpenApiAuthInputs(config.authenticationTemplate)
1256
- } : resolved.authenticationTemplate ? { authenticationTemplate: resolved.authenticationTemplate } : derivedAuthenticationTemplate && derivedAuthenticationTemplate.length > 0 ? { authenticationTemplate: derivedAuthenticationTemplate } : {}
1342
+ } : derivedAuthenticationTemplate && derivedAuthenticationTemplate.length > 0 ? { authenticationTemplate: derivedAuthenticationTemplate } : {}
1257
1343
  };
1258
1344
  yield* ctx.storage.putSpec(specHash, resolved.specText);
1259
1345
  yield* ctx.transaction(
1260
- Effect3.gen(function* () {
1346
+ Effect4.gen(function* () {
1261
1347
  yield* ctx.core.integrations.register({
1262
1348
  slug,
1263
1349
  name: config.name?.trim() || compiled.title || config.slug,
1264
1350
  description: config.description ?? compiled.description ?? compiled.title ?? config.slug,
1265
1351
  config: integrationConfig,
1266
1352
  canRemove: true,
1267
- canRefresh: specInputToSourceUrl(config.spec) != null || specInputToGoogleBundle(config.spec) != null
1353
+ canRefresh: specInputToSourceUrl(config.spec) != null
1268
1354
  });
1269
1355
  yield* ctx.storage.putOperations(
1270
1356
  config.slug,
1271
- storedOperationsFromCompiled(config.slug, compiled)
1357
+ openApiStoredOperationsFromCompiled(config.slug, compiled)
1272
1358
  );
1273
1359
  })
1274
1360
  );
1275
1361
  return { slug, toolCount: compiled.definitions.length };
1276
1362
  });
1277
- const updateSpec = (rawSlug, input) => Effect3.gen(function* () {
1363
+ const updateSpec = (rawSlug, input) => Effect4.gen(function* () {
1278
1364
  const slug = IntegrationSlug.make(rawSlug);
1279
1365
  const record = yield* ctx.core.integrations.get(slug);
1280
1366
  const current = record ? decodeOpenApiIntegrationConfig(record.config) : null;
1281
1367
  if (!record || !current) {
1282
1368
  return yield* new IntegrationNotFoundError({ slug });
1283
1369
  }
1284
- const specInput = input?.spec ?? (current.googleDiscoveryUrls ? { kind: "googleDiscoveryBundle", urls: current.googleDiscoveryUrls } : current.sourceUrl ? isGoogleDiscoveryUrl(current.sourceUrl) ? { kind: "googleDiscovery", url: current.sourceUrl } : { kind: "url", url: current.sourceUrl } : null);
1370
+ const specInput = input?.spec ?? (current.sourceUrl ? { kind: "url", url: current.sourceUrl } : null);
1285
1371
  if (specInput === null) {
1286
1372
  return yield* new OpenApiParseError({
1287
1373
  message: "This integration's spec was pasted inline and has no source URL to re-fetch. Provide the updated spec content."
1288
1374
  });
1289
1375
  }
1290
1376
  const resolved = yield* resolveSpecForInput(specInput, httpClientLayer);
1291
- const compiled = yield* compileSpec(resolved.specText);
1377
+ const compiled = yield* compileOpenApiSpec(resolved.specText);
1292
1378
  const previousOperations = yield* ctx.storage.listOperations(rawSlug);
1293
1379
  const previousNames = new Set(previousOperations.map((op) => op.toolName));
1294
1380
  const nextNames = new Set(compiled.definitions.map((def) => def.toolPath));
@@ -1297,32 +1383,31 @@ var openApiPlugin = definePlugin((options) => {
1297
1383
  const nextConfig = {
1298
1384
  ...current,
1299
1385
  specHash,
1300
- ...specInputToSourceUrl(specInput) !== void 0 ? { sourceUrl: specInputToSourceUrl(specInput) } : {},
1301
- ...specInputToGoogleBundle(specInput) !== void 0 ? { googleDiscoveryUrls: specInputToGoogleBundle(specInput) } : {}
1386
+ ...specInputToSourceUrl(specInput) !== void 0 ? { sourceUrl: specInputToSourceUrl(specInput) } : {}
1302
1387
  };
1303
1388
  yield* ctx.transaction(
1304
- Effect3.gen(function* () {
1389
+ Effect4.gen(function* () {
1305
1390
  yield* ctx.core.integrations.update(slug, {
1306
1391
  config: nextConfig
1307
1392
  });
1308
1393
  yield* ctx.storage.putOperations(
1309
1394
  rawSlug,
1310
- storedOperationsFromCompiled(rawSlug, compiled)
1395
+ openApiStoredOperationsFromCompiled(rawSlug, compiled)
1311
1396
  );
1312
1397
  })
1313
1398
  );
1314
1399
  const connections = yield* ctx.connections.list({ integration: slug });
1315
- yield* Effect3.forEach(
1400
+ yield* Effect4.forEach(
1316
1401
  connections,
1317
1402
  (connection) => ctx.connections.refresh({
1318
1403
  owner: connection.owner,
1319
1404
  integration: connection.integration,
1320
1405
  name: connection.name
1321
- }).pipe(Effect3.catchTag("ConnectionNotFoundError", () => Effect3.succeed([]))),
1406
+ }).pipe(Effect4.catchTag("ConnectionNotFoundError", () => Effect4.succeed([]))),
1322
1407
  { discard: true }
1323
1408
  ).pipe(
1324
- Effect3.catchTag("IntegrationNotFoundError", () => Effect3.void),
1325
- Effect3.withSpan("openapi.plugin.update_spec.refresh_connections", {
1409
+ Effect4.catchTag("IntegrationNotFoundError", () => Effect4.void),
1410
+ Effect4.withSpan("openapi.plugin.update_spec.refresh_connections", {
1326
1411
  attributes: { "openapi.connection_count": connections.length }
1327
1412
  })
1328
1413
  );
@@ -1333,35 +1418,28 @@ var openApiPlugin = definePlugin((options) => {
1333
1418
  removedTools: [...previousNames].filter((name) => !nextNames.has(name)).sort()
1334
1419
  };
1335
1420
  }).pipe(
1336
- Effect3.withSpan("openapi.plugin.update_spec", {
1421
+ Effect4.withSpan("openapi.plugin.update_spec", {
1337
1422
  attributes: { "openapi.integration.slug": rawSlug }
1338
1423
  })
1339
1424
  );
1340
1425
  return {
1341
- previewSpec: (input) => Effect3.gen(function* () {
1426
+ previewSpec: (input) => Effect4.gen(function* () {
1342
1427
  const previewInput = typeof input === "string" ? { spec: input } : input;
1343
- const specText = isGoogleDiscoveryUrl(previewInput.spec) ? yield* fetchGoogleDiscoveryDocument(previewInput.spec).pipe(
1344
- Effect3.provide(httpClientLayer),
1345
- Effect3.flatMap(
1346
- (documentText) => convertGoogleDiscoveryToOpenApi({
1347
- discoveryUrl: previewInput.spec,
1348
- documentText
1349
- })
1350
- ),
1351
- Effect3.map((conversion) => conversion.specText)
1352
- ) : yield* resolveSpecText(previewInput.spec).pipe(Effect3.provide(httpClientLayer));
1353
- return yield* previewSpec(specText).pipe(Effect3.provide(httpClientLayer));
1428
+ const specText = yield* resolveSpecText(previewInput.spec).pipe(
1429
+ Effect4.provide(httpClientLayer)
1430
+ );
1431
+ return yield* previewSpecText(specText);
1354
1432
  }),
1355
1433
  addSpec,
1356
1434
  updateSpec,
1357
1435
  removeSpec: (slug) => ctx.transaction(
1358
- Effect3.gen(function* () {
1436
+ Effect4.gen(function* () {
1359
1437
  yield* ctx.storage.removeOperations(slug);
1360
- yield* ctx.core.integrations.remove(IntegrationSlug.make(slug)).pipe(Effect3.catchTag("IntegrationRemovalNotAllowedError", () => Effect3.void));
1438
+ yield* ctx.core.integrations.remove(IntegrationSlug.make(slug)).pipe(Effect4.catchTag("IntegrationRemovalNotAllowedError", () => Effect4.void));
1361
1439
  })
1362
1440
  ),
1363
1441
  getIntegration: (slug) => ctx.core.integrations.get(IntegrationSlug.make(slug)).pipe(
1364
- Effect3.map(
1442
+ Effect4.map(
1365
1443
  (record) => record ? {
1366
1444
  slug: record.slug,
1367
1445
  description: record.description,
@@ -1372,12 +1450,12 @@ var openApiPlugin = definePlugin((options) => {
1372
1450
  )
1373
1451
  ),
1374
1452
  getConfig: (slug) => ctx.core.integrations.get(IntegrationSlug.make(slug)).pipe(
1375
- Effect3.map(
1453
+ Effect4.map(
1376
1454
  (record) => record ? decodeOpenApiIntegrationConfig(record.config) : null
1377
1455
  )
1378
1456
  ),
1379
1457
  configure: (slug, input) => ctx.transaction(
1380
- Effect3.gen(function* () {
1458
+ Effect4.gen(function* () {
1381
1459
  const record = yield* ctx.core.integrations.get(IntegrationSlug.make(slug));
1382
1460
  if (!record) return [];
1383
1461
  const current = decodeOpenApiIntegrationConfig(record.config);
@@ -1408,17 +1486,17 @@ var openApiPlugin = definePlugin((options) => {
1408
1486
  inputSchema: PreviewSpecInputStandardSchema,
1409
1487
  outputSchema: PreviewSpecOutputStandardSchema,
1410
1488
  execute: (input) => self.previewSpec(input).pipe(
1411
- Effect3.map((preview) => ToolResult.ok(staticPreviewOutput(preview))),
1412
- Effect3.catchTags({
1413
- OpenApiParseError: ({ message }) => Effect3.succeed(openApiToolFailure("openapi_parse_failed", message)),
1414
- OpenApiExtractionError: ({ message }) => Effect3.succeed(openApiToolFailure("openapi_extraction_failed", message)),
1415
- OpenApiOAuthError: ({ message }) => Effect3.succeed(openApiToolFailure("openapi_oauth_failed", message))
1489
+ Effect4.map((preview) => ToolResult2.ok(staticPreviewOutput(preview))),
1490
+ Effect4.catchTags({
1491
+ OpenApiParseError: ({ message }) => Effect4.succeed(openApiToolFailure("openapi_parse_failed", message)),
1492
+ OpenApiExtractionError: ({ message }) => Effect4.succeed(openApiToolFailure("openapi_extraction_failed", message)),
1493
+ OpenApiOAuthError: ({ message }) => Effect4.succeed(openApiToolFailure("openapi_oauth_failed", message))
1416
1494
  })
1417
1495
  )
1418
1496
  }),
1419
1497
  tool({
1420
1498
  name: "addSpec",
1421
- description: "Add an OpenAPI integration to the catalog and persist its operations as tools. Recommended flow: call `previewSpec`, choose a `slug`, then create a connection for that integration with the user's API key or via `oauth.start`. When `baseUrl` is omitted it defaults to the spec's first server; when `authenticationTemplate` is omitted the auth methods are derived from the spec's declared security schemes (pass an explicit template to override how a credential is applied \u2014 apiKey header/query, or oauth bearer \u2014 or an empty array for no auth methods).",
1499
+ description: "Add an OpenAPI integration to the catalog and persist its operations as tools. Recommended flow: call `previewSpec`, choose a `slug`, then create a connection for that integration with the user's API key or via `oauth.start`. When `baseUrl` is omitted it defaults to the spec's first server; when `authenticationTemplate` is omitted the auth methods are derived from the spec's declared security schemes (pass an explicit template to override how a credential is applied - apiKey header/query, or oauth bearer - or an empty array for no auth methods).",
1422
1500
  annotations: {
1423
1501
  requiresApproval: true,
1424
1502
  approvalDescription: "Add an OpenAPI integration"
@@ -1434,17 +1512,17 @@ var openApiPlugin = definePlugin((options) => {
1434
1512
  queryParams: input.queryParams,
1435
1513
  authenticationTemplate: input.authenticationTemplate
1436
1514
  }).pipe(
1437
- Effect3.map(
1438
- (result) => ToolResult.ok({
1515
+ Effect4.map(
1516
+ (result) => ToolResult2.ok({
1439
1517
  slug: String(result.slug),
1440
1518
  toolCount: result.toolCount
1441
1519
  })
1442
1520
  ),
1443
- Effect3.catchTags({
1444
- OpenApiParseError: ({ message }) => Effect3.succeed(openApiToolFailure("openapi_parse_failed", message)),
1445
- OpenApiExtractionError: ({ message }) => Effect3.succeed(openApiToolFailure("openapi_extraction_failed", message)),
1446
- OpenApiOAuthError: ({ message }) => Effect3.succeed(openApiToolFailure("openapi_oauth_failed", message)),
1447
- IntegrationAlreadyExistsError: ({ slug }) => Effect3.succeed(
1521
+ Effect4.catchTags({
1522
+ OpenApiParseError: ({ message }) => Effect4.succeed(openApiToolFailure("openapi_parse_failed", message)),
1523
+ OpenApiExtractionError: ({ message }) => Effect4.succeed(openApiToolFailure("openapi_extraction_failed", message)),
1524
+ OpenApiOAuthError: ({ message }) => Effect4.succeed(openApiToolFailure("openapi_oauth_failed", message)),
1525
+ IntegrationAlreadyExistsError: ({ slug }) => Effect4.succeed(
1448
1526
  openApiToolFailure(
1449
1527
  "integration_already_exists",
1450
1528
  `Integration ${slug} already exists; update it instead of re-adding.`
@@ -1459,176 +1537,50 @@ var openApiPlugin = definePlugin((options) => {
1459
1537
  describeAuthMethods: describeOpenApiAuthMethods,
1460
1538
  describeIntegrationDisplay: describeOpenApiIntegrationDisplay,
1461
1539
  // Produce one tool per spec operation. Spec-derived, identical for every
1462
- // connection on the integration so `getValue` is never called here. The
1540
+ // connection on the integration - so `getValue` is never called here. The
1463
1541
  // operation bindings invokeTool needs are persisted at addSpec time; this
1464
1542
  // hook only shapes the per-connection ToolDefs from the spec blob the
1465
1543
  // catalog config points at.
1466
- resolveTools: ({
1467
- config,
1468
- storage
1469
- }) => Effect3.gen(function* () {
1470
- const openApiConfig = decodeOpenApiIntegrationConfig(config);
1471
- if (!openApiConfig) return { tools: [], definitions: {} };
1472
- const specText = yield* loadSpecText(storage, openApiConfig);
1473
- if (specText == null) return { tools: [], definitions: {} };
1474
- const compiled = yield* compileSpec(specText).pipe(
1475
- Effect3.catch(() => Effect3.succeed(null))
1476
- );
1477
- if (!compiled) return { tools: [], definitions: {} };
1478
- return {
1479
- tools: toolDefsFromCompiled(compiled),
1480
- definitions: compiled.hoistedDefs
1481
- };
1482
- }),
1483
- invokeTool: ({
1484
- ctx: invokeCtx,
1485
- toolRow,
1486
- credential,
1487
- args
1488
- }) => Effect3.gen(function* () {
1544
+ resolveTools: ({ config, storage }) => resolveOpenApiBackedTools({ config, storage }),
1545
+ invokeTool: ({ ctx: invokeCtx, toolRow, credential, args }) => {
1489
1546
  const httpClientLayer = options?.httpClientLayer ?? invokeCtx.httpClientLayer;
1490
- const integration = toolRow.integration;
1491
- const config = decodeOpenApiIntegrationConfig(credential.config);
1492
- const bindingFromSpec = config ? Effect3.gen(function* () {
1493
- const specText = yield* loadSpecText(invokeCtx.storage, config).pipe(
1494
- Effect3.catch(() => Effect3.succeed(null))
1495
- );
1496
- const compiled = specText == null ? null : yield* compileSpec(specText).pipe(Effect3.catch(() => Effect3.succeed(null)));
1497
- return compiled ? storedOperationsFromCompiled(integration, compiled).find(
1498
- (op) => op.toolName === toolRow.name
1499
- )?.binding : void 0;
1500
- }) : Effect3.succeed(void 0);
1501
- let binding = (yield* invokeCtx.storage.getOperation(integration, toolRow.name))?.binding;
1502
- if ((!binding || Option5.isNone(binding.responseBody)) && config) {
1503
- binding = (yield* bindingFromSpec) ?? binding;
1504
- }
1505
- if (!binding) {
1506
- return yield* new OpenApiExtractionError({
1507
- message: `No OpenAPI operation found for tool "${toolRow.name}" on "${integration}"`
1508
- });
1509
- }
1510
- const headers = { ...config?.headers ?? {} };
1511
- const queryParams = {
1512
- ...config?.queryParams ?? {}
1513
- };
1514
- const template = (config?.authenticationTemplate ?? []).find(
1515
- (entry) => String(entry.slug) === String(credential.template)
1516
- );
1517
- if (template) {
1518
- const missing = requiredTemplateVariables(template).filter((name) => {
1519
- const value = credential.values[name];
1520
- return value == null || value === "";
1521
- });
1522
- if (missing.length > 0) {
1523
- return openApiAuthToolFailure({
1524
- code: template.kind === "oauth2" ? "oauth_connection_missing" : "connection_value_missing",
1525
- message: `Connection "${credential.connection}" for "${integration}" has no resolvable credential value. Re-authenticate or update the connection.`,
1526
- owner: credential.owner,
1527
- integration,
1528
- connection: String(credential.connection),
1529
- credentialKind: template.kind === "oauth2" ? "oauth" : "secret"
1530
- });
1531
- }
1532
- const rendered = renderAuthTemplate(template, credential.values);
1533
- Object.assign(headers, rendered.headers);
1534
- Object.assign(queryParams, rendered.queryParams);
1535
- }
1536
- const result = yield* invokeWithLayer(
1537
- binding,
1538
- args ?? {},
1539
- config?.baseUrl ?? "",
1540
- headers,
1541
- queryParams,
1547
+ return invokeOpenApiBackedTool({
1548
+ ctx: invokeCtx,
1549
+ toolRow,
1550
+ credential,
1551
+ args,
1542
1552
  httpClientLayer
1543
- );
1544
- const ok = result.status >= 200 && result.status < 300;
1545
- if (!ok) {
1546
- if (result.status === 401 || result.status === 403) {
1547
- return openApiAuthToolFailure({
1548
- code: "connection_rejected",
1549
- status: result.status,
1550
- message: `Upstream rejected credentials for "${integration}" with HTTP ${result.status}. Re-authenticate or update the connection "${credential.connection}" before retrying this tool.`,
1551
- owner: credential.owner,
1552
- integration,
1553
- connection: String(credential.connection),
1554
- credentialKind: "upstream",
1555
- credentialLabel: "Upstream authorization",
1556
- details: result.error
1557
- });
1558
- }
1559
- return ToolResult.fail({
1560
- code: "upstream_http_error",
1561
- status: result.status,
1562
- message: extractUpstreamMessage(result.error, result.status),
1563
- details: result.error
1564
- });
1565
- }
1566
- return ToolResult.ok(result.data, {
1567
- http: { status: result.status, headers: result.headers }
1568
1553
  });
1569
- }),
1570
- resolveAnnotations: ({
1554
+ },
1555
+ resolveAnnotations: ({ ctx: annotationsCtx, integration, toolRows }) => resolveOpenApiBackedAnnotations({
1571
1556
  ctx: annotationsCtx,
1572
- integration,
1557
+ integration: String(integration),
1573
1558
  toolRows
1574
- }) => Effect3.gen(function* () {
1575
- const ops = yield* annotationsCtx.storage.listOperations(String(integration));
1576
- const byName = /* @__PURE__ */ new Map();
1577
- for (const op of ops) byName.set(op.toolName, op.binding);
1578
- const out = {};
1579
- for (const row of toolRows) {
1580
- const binding = byName.get(row.name);
1581
- if (binding) {
1582
- out[row.name] = annotationsForOperation(binding.method, binding.pathTemplate);
1583
- }
1584
- }
1585
- return out;
1586
1559
  }),
1587
- removeConnection: () => Effect3.void,
1560
+ removeConnection: () => Effect4.void,
1588
1561
  detect: ({
1589
1562
  ctx: detectCtx,
1590
1563
  url
1591
- }) => Effect3.gen(function* () {
1564
+ }) => Effect4.gen(function* () {
1592
1565
  const httpClientLayer = options?.httpClientLayer ?? detectCtx.httpClientLayer;
1593
1566
  const trimmed = url.trim();
1594
1567
  if (!trimmed) return null;
1595
- const parsed = yield* Effect3.try({
1568
+ const parsed = yield* Effect4.try({
1596
1569
  try: () => new URL(trimmed),
1597
1570
  catch: (error) => error
1598
- }).pipe(Effect3.option);
1599
- if (Option5.isNone(parsed)) return null;
1600
- if (isGoogleDiscoveryUrl(trimmed)) {
1601
- const conversion = yield* fetchGoogleDiscoveryDocument(trimmed).pipe(
1602
- Effect3.provide(httpClientLayer),
1603
- Effect3.flatMap(
1604
- (documentText) => convertGoogleDiscoveryToOpenApi({
1605
- discoveryUrl: trimmed,
1606
- documentText
1607
- })
1608
- ),
1609
- Effect3.catch(() => Effect3.succeed(null))
1610
- );
1611
- if (conversion) {
1612
- return IntegrationDetectionResult.make({
1613
- kind: "openapi",
1614
- confidence: "high",
1615
- endpoint: trimmed,
1616
- name: conversion.title,
1617
- slug: conversion.title.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "") || `google_${conversion.service}`
1618
- });
1619
- }
1620
- }
1571
+ }).pipe(Effect4.option);
1572
+ if (Option6.isNone(parsed)) return null;
1621
1573
  const specText = yield* resolveSpecText(trimmed).pipe(
1622
- Effect3.provide(httpClientLayer),
1623
- Effect3.catch(() => Effect3.succeed(null))
1574
+ Effect4.provide(httpClientLayer),
1575
+ Effect4.catch(() => Effect4.succeed(null))
1624
1576
  );
1625
1577
  if (specText === null) return null;
1626
- const doc = yield* parse(specText).pipe(Effect3.catch(() => Effect3.succeed(null)));
1578
+ const doc = yield* parse(specText).pipe(Effect4.catch(() => Effect4.succeed(null)));
1627
1579
  if (!doc) return null;
1628
- const result = yield* extract(doc).pipe(Effect3.catch(() => Effect3.succeed(null)));
1580
+ const result = yield* extract(doc).pipe(Effect4.catch(() => Effect4.succeed(null)));
1629
1581
  if (!result) return null;
1630
- const slug = Option5.getOrElse(result.title, () => "api").toLowerCase().replace(/[^a-z0-9]+/g, "_");
1631
- const name = Option5.getOrElse(result.title, () => slug);
1582
+ const slug = Option6.getOrElse(result.title, () => "api").toLowerCase().replace(/[^a-z0-9]+/g, "_");
1583
+ const name = Option6.getOrElse(result.title, () => slug);
1632
1584
  return IntegrationDetectionResult.make({
1633
1585
  kind: "openapi",
1634
1586
  confidence: "high",
@@ -1645,10 +1597,20 @@ export {
1645
1597
  OpenApiIntegrationConfigSchema,
1646
1598
  decodeOpenApiIntegrationConfig,
1647
1599
  renderAuthTemplate,
1600
+ makeDefaultOpenapiStore,
1648
1601
  invoke,
1649
1602
  invokeWithLayer,
1650
1603
  annotationsForOperation,
1651
- makeDefaultOpenapiStore,
1604
+ extractOpenApiUpstreamMessage,
1605
+ normalizeOpenApiRefs,
1606
+ compileOpenApiDocument,
1607
+ compileOpenApiSpec,
1608
+ openApiToolDefsFromCompiled,
1609
+ openApiStoredOperationsFromCompiled,
1610
+ loadOpenApiSpecText,
1611
+ resolveOpenApiBackedTools,
1612
+ invokeOpenApiBackedTool,
1613
+ resolveOpenApiBackedAnnotations,
1652
1614
  openApiPlugin
1653
1615
  };
1654
- //# sourceMappingURL=chunk-ZTOOUP67.js.map
1616
+ //# sourceMappingURL=chunk-3FM2SWM4.js.map