@executor-js/plugin-openapi 1.5.15 → 1.5.17

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-CKBX4SXK.js +95 -0
  10. package/dist/chunk-CKBX4SXK.js.map +1 -0
  11. package/dist/{chunk-NJ4Q3VF4.js → chunk-CPPTKUOW.js} +5 -14
  12. package/dist/chunk-CPPTKUOW.js.map +1 -0
  13. package/dist/{chunk-O54VFSWE.js → chunk-KVPUDOJZ.js} +18 -4
  14. package/dist/chunk-KVPUDOJZ.js.map +1 -0
  15. package/dist/{chunk-PAHWRRS3.js → chunk-QQFCICLX.js} +4 -13
  16. package/dist/chunk-QQFCICLX.js.map +1 -0
  17. package/dist/{chunk-ZTOOUP67.js → chunk-UEKOP6NZ.js} +544 -580
  18. package/dist/chunk-UEKOP6NZ.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-oauth-batches.d.ts +0 -13
  52. package/dist/sdk/google-oauth-batches.test.d.ts +0 -1
  53. package/dist/sdk/google-oauth-scopes.d.ts +0 -3
  54. package/dist/sdk/google-oauth-scopes.test.d.ts +0 -1
  55. package/dist/sdk/google-presets.d.ts +0 -16
  56. package/dist/sdk/google-presets.test.d.ts +0 -1
  57. package/dist/sdk/google-product-picker-scopes.test.d.ts +0 -1
  58. /package/dist/sdk/{google-bundle.test.d.ts → request-user-agent.test.d.ts} +0 -0
  59. /package/dist/sdk/{google-discovery.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,11 +231,12 @@ 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;
152
238
  });
239
+ var DEFAULT_USER_AGENT = "executor";
153
240
  var applyHeaders = (request, headers) => {
154
241
  let req = request;
155
242
  for (const [name, value] of Object.entries(headers)) {
@@ -250,9 +337,9 @@ var toUint8Array = (value) => {
250
337
  }
251
338
  return null;
252
339
  };
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");
340
+ var readHintString = (option, fallback) => Option3.getOrElse(option, () => fallback);
341
+ var readHintMimeType = (hint, fallback) => Option3.getOrElse(hint.mimeType, () => fallback);
342
+ var readHintEncoding = (hint) => Option3.getOrElse(hint.encoding, () => "base64");
256
343
  var fileFromByteField = (body, hint) => {
257
344
  if (typeof body !== "object" || body === null || Array.isArray(body)) return null;
258
345
  const record = body;
@@ -260,7 +347,7 @@ var fileFromByteField = (body, hint) => {
260
347
  const rawData = record[dataField];
261
348
  if (typeof rawData !== "string") return null;
262
349
  const data = normalizeBase64(rawData, readHintEncoding(hint));
263
- const sizeField = Option2.getOrUndefined(hint.sizeField);
350
+ const sizeField = Option3.getOrUndefined(hint.sizeField);
264
351
  const byteLength = sizeField && typeof record[sizeField] === "number" ? record[sizeField] : byteLengthFromBase64(data);
265
352
  const hintedMimeType = readHintMimeType(hint, "application/octet-stream");
266
353
  return {
@@ -294,9 +381,9 @@ var DEFAULT_FORM_STYLE = {
294
381
  var resolveStyleExplode = (e) => {
295
382
  if (!e) return DEFAULT_FORM_STYLE;
296
383
  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)
384
+ style: Option3.getOrElse(e.style, () => DEFAULT_FORM_STYLE.style),
385
+ explode: Option3.getOrElse(e.explode, () => DEFAULT_FORM_STYLE.explode),
386
+ allowReserved: Option3.getOrElse(e.allowReserved, () => DEFAULT_FORM_STYLE.allowReserved)
300
387
  };
301
388
  };
302
389
  var encodeFormValue = (v, allowReserved) => {
@@ -356,7 +443,7 @@ var coerceFormDataRecord = (value, encoding) => {
356
443
  const out = {};
357
444
  for (const [key, raw] of Object.entries(value)) {
358
445
  if (raw === void 0 || raw === null) continue;
359
- const partType = encoding?.[key] ? Option2.getOrUndefined(encoding[key].contentType) : void 0;
446
+ const partType = encoding?.[key] ? Option3.getOrUndefined(encoding[key].contentType) : void 0;
360
447
  if (partType) {
361
448
  const isJson = partType.startsWith("application/json") || partType.includes("+json");
362
449
  const serialized = typeof raw === "string" ? raw : isJson ? JSON.stringify(raw) : typeof raw === "object" ? JSON.stringify(raw) : String(raw);
@@ -437,9 +524,9 @@ var applyRequestBody = (request, contentType, bodyValue, encoding) => {
437
524
  if (bytes) return HttpClientRequest.bodyUint8Array(request, bytes, contentType);
438
525
  return HttpClientRequest.bodyText(request, JSON.stringify(bodyValue), contentType);
439
526
  };
440
- var invoke = Effect.fn("OpenApi.invoke")(function* (operation, args, resolvedHeaders, sourceQueryParams = {}) {
527
+ var invoke = Effect2.fn("OpenApi.invoke")(function* (operation, args, resolvedHeaders, sourceQueryParams = {}) {
441
528
  const client = yield* HttpClient.HttpClient;
442
- yield* Effect.annotateCurrentSpan({
529
+ yield* Effect2.annotateCurrentSpan({
443
530
  "http.method": operation.method.toUpperCase(),
444
531
  "http.route": operation.pathTemplate,
445
532
  "plugin.openapi.method": operation.method.toUpperCase(),
@@ -449,6 +536,7 @@ var invoke = Effect.fn("OpenApi.invoke")(function* (operation, args, resolvedHea
449
536
  const resolvedPath = yield* resolvePath(operation.pathTemplate, args, operation.parameters);
450
537
  const path = resolvedPath.startsWith("/") ? resolvedPath : `/${resolvedPath}`;
451
538
  let request = HttpClientRequest.make(operation.method.toUpperCase())(path);
539
+ request = HttpClientRequest.setHeader(request, "User-Agent", DEFAULT_USER_AGENT);
452
540
  for (const [name, value] of Object.entries(sourceQueryParams)) {
453
541
  request = HttpClientRequest.setUrlParam(request, name, value);
454
542
  }
@@ -465,50 +553,50 @@ var invoke = Effect.fn("OpenApi.invoke")(function* (operation, args, resolvedHea
465
553
  if (value === void 0 || value === null) continue;
466
554
  request = HttpClientRequest.setHeader(request, param.name, String(value));
467
555
  }
468
- if (Option2.isSome(operation.requestBody)) {
556
+ if (Option3.isSome(operation.requestBody)) {
469
557
  const rb = operation.requestBody.value;
470
558
  const bodyValue = args.body ?? args.input;
471
559
  if (bodyValue !== void 0) {
472
- const contentsOpt = Option2.getOrUndefined(rb.contents);
560
+ const contentsOpt = Option3.getOrUndefined(rb.contents);
473
561
  const requestedCt = typeof args.contentType === "string" ? args.contentType : void 0;
474
562
  const selected = contentsOpt && requestedCt ? contentsOpt.find((c) => c.contentType === requestedCt) : void 0;
475
563
  const chosenCt = selected?.contentType ?? rb.contentType;
476
- const chosenEncoding = selected ? Option2.getOrUndefined(selected.encoding) : contentsOpt && contentsOpt[0] ? Option2.getOrUndefined(contentsOpt[0].encoding) : void 0;
564
+ const chosenEncoding = selected ? Option3.getOrUndefined(selected.encoding) : contentsOpt && contentsOpt[0] ? Option3.getOrUndefined(contentsOpt[0].encoding) : void 0;
477
565
  request = applyRequestBody(request, chosenCt, bodyValue, chosenEncoding);
478
566
  }
479
567
  }
480
568
  request = applyHeaders(request, resolvedHeaders);
481
569
  const response = yield* client.execute(request).pipe(
482
- Effect.mapError(
570
+ Effect2.mapError(
483
571
  (err) => new OpenApiInvocationError({
484
572
  message: "HTTP request failed",
485
- statusCode: Option2.none(),
573
+ statusCode: Option3.none(),
486
574
  cause: err
487
575
  })
488
576
  )
489
577
  );
490
578
  const status = response.status;
491
- yield* Effect.annotateCurrentSpan({
579
+ yield* Effect2.annotateCurrentSpan({
492
580
  "http.status_code": status
493
581
  });
494
582
  const responseHeaders = { ...response.headers };
495
583
  const contentType = response.headers["content-type"] ?? null;
496
- const mapBodyError = Effect.mapError(
584
+ const mapBodyError = Effect2.mapError(
497
585
  (err) => new OpenApiInvocationError({
498
586
  message: "Failed to read response body",
499
- statusCode: Option2.some(status),
587
+ statusCode: Option3.some(status),
500
588
  cause: err
501
589
  })
502
590
  );
503
- const responseBodyBinding = Option2.getOrUndefined(operation.responseBody);
504
- const fileHint = responseBodyBinding ? Option2.getOrUndefined(responseBodyBinding.fileHint) : void 0;
591
+ const responseBodyBinding = Option3.getOrUndefined(operation.responseBody);
592
+ const fileHint = responseBodyBinding ? Option3.getOrUndefined(responseBodyBinding.fileHint) : void 0;
505
593
  const ok = status >= 200 && status < 300;
506
594
  const responseBody = status === 204 ? null : ok && fileHint?.kind === "binaryResponse" ? fileFromBinaryBytes(
507
595
  new Uint8Array(yield* response.arrayBuffer.pipe(mapBodyError)),
508
596
  fileHint,
509
597
  contentType
510
598
  ) : isJsonContentType(contentType) ? yield* response.json.pipe(
511
- Effect.catch(() => response.text),
599
+ Effect2.catch(() => response.text),
512
600
  mapBodyError
513
601
  ) : yield* response.text.pipe(mapBodyError);
514
602
  const dataBody = ok && fileHint?.kind === "byteField" ? fileFromByteField(responseBody, fileHint) ?? responseBody : responseBody;
@@ -530,25 +618,25 @@ var resolveRequestHost = (servers, serverArg, baseUrl) => {
530
618
  if (value != null && value !== "") overrides[name] = String(value);
531
619
  }
532
620
  }
533
- return resolveServerUrl(chosen.url, Option2.getOrUndefined(chosen.variables), overrides);
621
+ return resolveServerUrl(chosen.url, Option3.getOrUndefined(chosen.variables), overrides);
534
622
  };
535
623
  var invokeWithLayer = (operation, args, baseUrl, resolvedHeaders, sourceQueryParams, httpClientLayer) => {
536
624
  const effectiveBaseUrl = resolveRequestHost(operation.servers ?? [], args.server, baseUrl);
537
625
  const clientWithBaseUrl = effectiveBaseUrl ? Layer.effect(
538
626
  HttpClient.HttpClient,
539
- Effect.map(
540
- Effect.service(HttpClient.HttpClient),
627
+ Effect2.map(
628
+ Effect2.service(HttpClient.HttpClient),
541
629
  HttpClient.mapRequest(HttpClientRequest.prependUrl(effectiveBaseUrl))
542
630
  )
543
631
  ).pipe(Layer.provide(httpClientLayer)) : httpClientLayer;
544
632
  return invoke(operation, args, resolvedHeaders, sourceQueryParams).pipe(
545
- Effect.provide(clientWithBaseUrl),
633
+ Effect2.provide(clientWithBaseUrl),
546
634
  // `invoke` annotates http.status_code on ITS span (`OpenApi.invoke`,
547
635
  // via Effect.fn) — annotateCurrentSpan inside it never reaches this
548
636
  // wrapper span. Stamp the status here too so queries against
549
637
  // `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", {
638
+ Effect2.tap((result) => Effect2.annotateCurrentSpan({ "http.status_code": result.status })),
639
+ Effect2.withSpan("plugin.openapi.invoke", {
552
640
  attributes: {
553
641
  "plugin.openapi.method": operation.method.toUpperCase(),
554
642
  "plugin.openapi.path_template": operation.pathTemplate,
@@ -567,89 +655,13 @@ var annotationsForOperation = (method, pathTemplate) => {
567
655
  };
568
656
  };
569
657
 
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
658
+ // src/sdk/backing.ts
639
659
  import { Effect as Effect3, Option as Option5, Schema as Schema3 } from "effect";
640
660
  import {
641
- IntegrationAlreadyExistsError,
642
- IntegrationDetectionResult,
643
- IntegrationNotFoundError,
644
- IntegrationSlug,
645
- ToolName,
646
661
  ToolFileJsonSchema,
662
+ ToolName,
647
663
  ToolResult,
648
- authToolFailure,
649
- definePlugin,
650
- mergeAuthTemplates,
651
- sha256Hex,
652
- tool
664
+ authToolFailure
653
665
  } from "@executor-js/sdk/core";
654
666
 
655
667
  // src/sdk/definitions.ts
@@ -797,8 +809,7 @@ var compileToolDefinitions = (operations) => {
797
809
  return resolveCollisions(raw).sort((a, b) => a.toolPath.localeCompare(b.toolPath));
798
810
  };
799
811
 
800
- // src/sdk/plugin.ts
801
- import { ApiKeyAuthTemplate, describeApiKeyAuthMethod } from "@executor-js/sdk/http-auth";
812
+ // src/sdk/backing.ts
802
813
  var STRINGIFIED_BODY_CAP = 1024;
803
814
  var UpstreamMessageBody = Schema3.Struct({ message: Schema3.String });
804
815
  var UpstreamErrorMessageBody = Schema3.Struct({ errorMessage: Schema3.String });
@@ -832,7 +843,7 @@ var clampedStringify = (value) => {
832
843
  return s.length > STRINGIFIED_BODY_CAP ? `${s.slice(0, STRINGIFIED_BODY_CAP)}\u2026` : s;
833
844
  };
834
845
  var firstNonEmpty = (...values) => values.find((value) => value !== void 0 && value.length > 0);
835
- var extractUpstreamMessage = (body, status) => {
846
+ var extractOpenApiUpstreamMessage = (body, status) => {
836
847
  if (typeof body === "string") {
837
848
  return body.length > 0 ? body : `Upstream returned HTTP ${status}`;
838
849
  }
@@ -863,162 +874,353 @@ var extractUpstreamMessage = (body, status) => {
863
874
  }
864
875
  return `Upstream returned HTTP ${status}`;
865
876
  };
866
- var PreviewSpecInputSchema = Schema3.Struct({
867
- spec: Schema3.String
877
+ var openApiAuthToolFailure = (failure) => authToolFailure({
878
+ code: failure.code,
879
+ message: failure.message,
880
+ source: { id: failure.integration, scope: failure.owner },
881
+ credential: {
882
+ kind: failure.credentialKind,
883
+ ...failure.credentialLabel ? { label: failure.credentialLabel } : {}
884
+ },
885
+ ...failure.status !== void 0 ? { status: failure.status } : {},
886
+ ...failure.details !== void 0 ? {
887
+ upstream: {
888
+ ...failure.status !== void 0 ? { status: failure.status } : {},
889
+ details: failure.details
890
+ }
891
+ } : {}
892
+ });
893
+ var normalizeOpenApiRefs = (node) => {
894
+ if (node == null || typeof node !== "object") return node;
895
+ if (Array.isArray(node)) {
896
+ let changed2 = false;
897
+ const out = node.map((item) => {
898
+ const n = normalizeOpenApiRefs(item);
899
+ if (n !== item) changed2 = true;
900
+ return n;
901
+ });
902
+ return changed2 ? out : node;
903
+ }
904
+ const obj = node;
905
+ if (typeof obj.$ref === "string") {
906
+ const match = obj.$ref.match(/^#\/components\/schemas\/(.+)$/);
907
+ if (match) return { ...obj, $ref: `#/$defs/${match[1]}` };
908
+ return obj;
909
+ }
910
+ let changed = false;
911
+ const result = {};
912
+ for (const [k, v] of Object.entries(obj)) {
913
+ const n = normalizeOpenApiRefs(v);
914
+ if (n !== v) changed = true;
915
+ result[k] = n;
916
+ }
917
+ return changed ? result : obj;
918
+ };
919
+ var toBinding = (def) => OperationBinding.make({
920
+ method: def.operation.method,
921
+ servers: def.operation.servers,
922
+ pathTemplate: def.operation.pathTemplate,
923
+ parameters: [...def.operation.parameters],
924
+ requestBody: def.operation.requestBody,
925
+ responseBody: def.operation.responseBody
926
+ });
927
+ var descriptionFor = (def) => {
928
+ const op = def.operation;
929
+ return Option5.getOrElse(
930
+ op.description,
931
+ () => Option5.getOrElse(op.summary, () => `${op.method.toUpperCase()} ${op.pathTemplate}`)
932
+ );
933
+ };
934
+ var compileOpenApiDocument = (doc) => Effect3.gen(function* () {
935
+ const result = yield* extract(doc);
936
+ const hoistedDefs = {};
937
+ if (doc.components?.schemas) {
938
+ for (const [k, v] of Object.entries(doc.components.schemas)) {
939
+ hoistedDefs[k] = normalizeOpenApiRefs(v);
940
+ }
941
+ }
942
+ return {
943
+ definitions: compileToolDefinitions(result.operations),
944
+ hoistedDefs,
945
+ title: Option5.getOrUndefined(result.title),
946
+ description: Option5.getOrUndefined(result.description)
947
+ };
948
+ });
949
+ var compileOpenApiSpec = (specText) => Effect3.gen(function* () {
950
+ const doc = yield* parse(specText);
951
+ return yield* compileOpenApiDocument(doc);
952
+ });
953
+ var openApiToolDefsFromCompiled = (compiled) => compiled.definitions.map(
954
+ (def) => ({
955
+ name: ToolName.make(def.toolPath),
956
+ description: descriptionFor(def),
957
+ inputSchema: normalizeOpenApiRefs(Option5.getOrUndefined(def.operation.inputSchema)),
958
+ outputSchema: Option5.match(def.operation.responseBody, {
959
+ onNone: () => normalizeOpenApiRefs(Option5.getOrUndefined(def.operation.outputSchema)),
960
+ onSome: (responseBody) => Option5.isSome(responseBody.fileHint) ? ToolFileJsonSchema : normalizeOpenApiRefs(Option5.getOrUndefined(def.operation.outputSchema))
961
+ }),
962
+ annotations: annotationsForOperation(def.operation.method, def.operation.pathTemplate)
963
+ })
964
+ );
965
+ var openApiStoredOperationsFromCompiled = (integration, compiled) => compiled.definitions.map((def) => ({
966
+ integration,
967
+ toolName: def.toolPath,
968
+ binding: toBinding(def)
969
+ }));
970
+ var loadOpenApiSpecText = (storage, config) => config.specHash != null ? storage.getSpec(config.specHash) : Effect3.succeed(null);
971
+ var resolveOpenApiBackedTools = ({
972
+ config,
973
+ storage
974
+ }) => Effect3.gen(function* () {
975
+ const openApiConfig = decodeOpenApiIntegrationConfig(config);
976
+ if (!openApiConfig) return { tools: [], definitions: {} };
977
+ const specText = yield* loadOpenApiSpecText(storage, openApiConfig);
978
+ if (specText == null) return { tools: [], definitions: {} };
979
+ const compiled = yield* compileOpenApiSpec(specText).pipe(
980
+ Effect3.catch(() => Effect3.succeed(null))
981
+ );
982
+ if (!compiled) return { tools: [], definitions: {} };
983
+ return {
984
+ tools: openApiToolDefsFromCompiled(compiled),
985
+ definitions: compiled.hoistedDefs
986
+ };
987
+ });
988
+ var invokeOpenApiBackedTool = (input) => Effect3.gen(function* () {
989
+ const integration = input.toolRow.integration;
990
+ const config = decodeOpenApiIntegrationConfig(input.credential.config);
991
+ let binding = (yield* input.ctx.storage.getOperation(integration, input.toolRow.name))?.binding;
992
+ if ((!binding || Option5.isNone(binding.responseBody)) && config) {
993
+ const specText = yield* loadOpenApiSpecText(input.ctx.storage, config).pipe(
994
+ Effect3.catch(() => Effect3.succeed(null))
995
+ );
996
+ const compiled = specText == null ? null : yield* compileOpenApiSpec(specText).pipe(Effect3.catch(() => Effect3.succeed(null)));
997
+ binding = compiled ? openApiStoredOperationsFromCompiled(integration, compiled).find(
998
+ (op) => op.toolName === input.toolRow.name
999
+ )?.binding : void 0;
1000
+ }
1001
+ if (!binding) {
1002
+ return yield* new OpenApiExtractionError({
1003
+ message: `No OpenAPI operation found for tool "${input.toolRow.name}" on "${integration}"`
1004
+ });
1005
+ }
1006
+ const headers = { ...config?.headers ?? {} };
1007
+ const queryParams = {
1008
+ ...config?.queryParams ?? {}
1009
+ };
1010
+ const template = (config?.authenticationTemplate ?? []).find(
1011
+ (entry) => String(entry.slug) === String(input.credential.template)
1012
+ );
1013
+ if (template) {
1014
+ const missing = requiredTemplateVariables(template).filter((name) => {
1015
+ const value = input.credential.values[name];
1016
+ return value == null || value === "";
1017
+ });
1018
+ if (missing.length > 0) {
1019
+ return openApiAuthToolFailure({
1020
+ code: template.kind === "oauth2" ? "oauth_connection_missing" : "connection_value_missing",
1021
+ message: `Connection "${input.credential.connection}" for "${integration}" has no resolvable credential value. Re-authenticate or update the connection.`,
1022
+ owner: input.credential.owner,
1023
+ integration,
1024
+ connection: String(input.credential.connection),
1025
+ credentialKind: template.kind === "oauth2" ? "oauth" : "secret"
1026
+ });
1027
+ }
1028
+ const rendered = renderAuthTemplate(template, input.credential.values);
1029
+ Object.assign(headers, rendered.headers);
1030
+ Object.assign(queryParams, rendered.queryParams);
1031
+ }
1032
+ const result = yield* invokeWithLayer(
1033
+ binding,
1034
+ input.args ?? {},
1035
+ config?.baseUrl ?? "",
1036
+ headers,
1037
+ queryParams,
1038
+ input.httpClientLayer
1039
+ );
1040
+ const ok = result.status >= 200 && result.status < 300;
1041
+ if (!ok) {
1042
+ if (result.status === 401 || result.status === 403) {
1043
+ return openApiAuthToolFailure({
1044
+ code: "connection_rejected",
1045
+ status: result.status,
1046
+ message: `Upstream rejected credentials for "${integration}" with HTTP ${result.status}. Re-authenticate or update the connection "${input.credential.connection}" before retrying this tool.`,
1047
+ owner: input.credential.owner,
1048
+ integration,
1049
+ connection: String(input.credential.connection),
1050
+ credentialKind: "upstream",
1051
+ credentialLabel: "Upstream authorization",
1052
+ details: result.error
1053
+ });
1054
+ }
1055
+ return ToolResult.fail({
1056
+ code: "upstream_http_error",
1057
+ status: result.status,
1058
+ message: extractOpenApiUpstreamMessage(result.error, result.status),
1059
+ details: result.error
1060
+ });
1061
+ }
1062
+ return ToolResult.ok(result.data, {
1063
+ http: { status: result.status, headers: result.headers }
1064
+ });
1065
+ });
1066
+ var resolveOpenApiBackedAnnotations = (input) => Effect3.gen(function* () {
1067
+ const ops = yield* input.ctx.storage.listOperations(String(input.integration));
1068
+ const byName = /* @__PURE__ */ new Map();
1069
+ for (const op of ops) byName.set(op.toolName, op.binding);
1070
+ const out = {};
1071
+ for (const row of input.toolRows) {
1072
+ const binding = byName.get(row.name);
1073
+ if (binding) {
1074
+ out[row.name] = annotationsForOperation(binding.method, binding.pathTemplate);
1075
+ }
1076
+ }
1077
+ return out;
868
1078
  });
869
- var StaticPreviewServerVariableSchema = Schema3.Struct({
870
- default: Schema3.String,
871
- enum: Schema3.NullOr(Schema3.Array(Schema3.String)),
872
- description: Schema3.NullOr(Schema3.String)
1079
+
1080
+ // src/sdk/plugin.ts
1081
+ import { Effect as Effect4, Option as Option6, Schema as Schema4 } from "effect";
1082
+ import {
1083
+ IntegrationAlreadyExistsError,
1084
+ IntegrationDetectionResult,
1085
+ IntegrationNotFoundError,
1086
+ IntegrationSlug,
1087
+ ToolResult as ToolResult2,
1088
+ definePlugin,
1089
+ mergeAuthTemplates,
1090
+ sha256Hex,
1091
+ tool
1092
+ } from "@executor-js/sdk/core";
1093
+ import { ApiKeyAuthTemplate, describeApiKeyAuthMethod } from "@executor-js/sdk/http-auth";
1094
+ var PreviewSpecInputSchema = Schema4.Struct({
1095
+ spec: Schema4.String
1096
+ });
1097
+ var StaticPreviewServerVariableSchema = Schema4.Struct({
1098
+ default: Schema4.String,
1099
+ enum: Schema4.NullOr(Schema4.Array(Schema4.String)),
1100
+ description: Schema4.NullOr(Schema4.String)
873
1101
  });
874
- var StaticPreviewServerSchema = Schema3.Struct({
875
- url: Schema3.String,
876
- description: Schema3.NullOr(Schema3.String),
877
- variables: Schema3.NullOr(Schema3.Record(Schema3.String, StaticPreviewServerVariableSchema))
1102
+ var StaticPreviewServerSchema = Schema4.Struct({
1103
+ url: Schema4.String,
1104
+ description: Schema4.NullOr(Schema4.String),
1105
+ variables: Schema4.NullOr(Schema4.Record(Schema4.String, StaticPreviewServerVariableSchema))
878
1106
  });
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)
1107
+ var StaticPreviewOAuthAuthorizationCodeFlowSchema = Schema4.Struct({
1108
+ authorizationUrl: Schema4.String,
1109
+ tokenUrl: Schema4.String,
1110
+ refreshUrl: Schema4.NullOr(Schema4.String),
1111
+ scopes: Schema4.Record(Schema4.String, Schema4.String)
884
1112
  });
885
- var StaticPreviewOAuthClientCredentialsFlowSchema = Schema3.Struct({
886
- tokenUrl: Schema3.String,
887
- refreshUrl: Schema3.NullOr(Schema3.String),
888
- scopes: Schema3.Record(Schema3.String, Schema3.String)
1113
+ var StaticPreviewOAuthClientCredentialsFlowSchema = Schema4.Struct({
1114
+ tokenUrl: Schema4.String,
1115
+ refreshUrl: Schema4.NullOr(Schema4.String),
1116
+ scopes: Schema4.Record(Schema4.String, Schema4.String)
889
1117
  });
890
- var StaticPreviewOAuthFlowsSchema = Schema3.Struct({
891
- authorizationCode: Schema3.NullOr(StaticPreviewOAuthAuthorizationCodeFlowSchema),
892
- clientCredentials: Schema3.NullOr(StaticPreviewOAuthClientCredentialsFlowSchema)
1118
+ var StaticPreviewOAuthFlowsSchema = Schema4.Struct({
1119
+ authorizationCode: Schema4.NullOr(StaticPreviewOAuthAuthorizationCodeFlowSchema),
1120
+ clientCredentials: Schema4.NullOr(StaticPreviewOAuthClientCredentialsFlowSchema)
893
1121
  });
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)
1122
+ var StaticPreviewSecuritySchemeSchema = Schema4.Struct({
1123
+ name: Schema4.String,
1124
+ type: Schema4.Literals(["http", "apiKey", "oauth2", "openIdConnect"]),
1125
+ scheme: Schema4.NullOr(Schema4.String),
1126
+ bearerFormat: Schema4.NullOr(Schema4.String),
1127
+ in: Schema4.NullOr(Schema4.Literals(["header", "query", "cookie"])),
1128
+ headerName: Schema4.NullOr(Schema4.String),
1129
+ description: Schema4.NullOr(Schema4.String),
1130
+ flows: Schema4.NullOr(StaticPreviewOAuthFlowsSchema),
1131
+ openIdConnectUrl: Schema4.NullOr(Schema4.String)
904
1132
  });
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)
1133
+ var StaticPreviewOAuth2PresetSchema = Schema4.Struct({
1134
+ label: Schema4.String,
1135
+ securitySchemeName: Schema4.String,
1136
+ flow: Schema4.Literals(["authorizationCode", "clientCredentials"]),
1137
+ authorizationUrl: Schema4.NullOr(Schema4.String),
1138
+ tokenUrl: Schema4.String,
1139
+ refreshUrl: Schema4.NullOr(Schema4.String),
1140
+ scopes: Schema4.Record(Schema4.String, Schema4.String),
1141
+ identityScopes: Schema4.Union([
1142
+ Schema4.Literal("auto"),
1143
+ Schema4.Literal(false),
1144
+ Schema4.Array(Schema4.String)
917
1145
  ])
918
1146
  });
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)
1147
+ var StaticPreviewSpecOutputSchema = Schema4.Struct({
1148
+ title: Schema4.NullOr(Schema4.String),
1149
+ version: Schema4.NullOr(Schema4.String),
1150
+ servers: Schema4.Array(StaticPreviewServerSchema),
1151
+ operationCount: Schema4.Number,
1152
+ tags: Schema4.Array(Schema4.String),
1153
+ securitySchemes: Schema4.Array(StaticPreviewSecuritySchemeSchema),
1154
+ authStrategies: Schema4.Array(Schema4.Struct({ schemes: Schema4.Array(Schema4.String) })),
1155
+ headerPresets: Schema4.Array(
1156
+ Schema4.Struct({
1157
+ label: Schema4.String,
1158
+ headers: Schema4.Record(Schema4.String, Schema4.NullOr(Schema4.String)),
1159
+ secretHeaders: Schema4.Array(Schema4.String)
932
1160
  })
933
1161
  ),
934
- oauth2Presets: Schema3.Array(StaticPreviewOAuth2PresetSchema)
1162
+ oauth2Presets: Schema4.Array(StaticPreviewOAuth2PresetSchema)
935
1163
  });
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
- })
1164
+ var OpenApiSpecInputSchema = Schema4.Union([
1165
+ Schema4.Struct({ kind: Schema4.Literal("url"), url: Schema4.String }),
1166
+ Schema4.Struct({ kind: Schema4.Literal("blob"), value: Schema4.String })
947
1167
  ]);
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)
1168
+ var AuthenticationSchema2 = Schema4.Union([
1169
+ Schema4.Struct({
1170
+ slug: Schema4.String,
1171
+ kind: Schema4.Literal("oauth2"),
1172
+ authorizationUrl: Schema4.String,
1173
+ tokenUrl: Schema4.String,
1174
+ scopes: Schema4.Array(Schema4.String)
955
1175
  }),
956
- // Credential methods are authored request-shaped the ONE apikey input
1176
+ // Credential methods are authored request-shaped - the ONE apikey input
957
1177
  // dialect: `{ type: "apiKey", headers: { Authorization: ["Bearer ",
958
1178
  // variable("token")] }, queryParams: { … } }`.
959
1179
  ApiKeyAuthTemplate
960
1180
  ]);
961
- var AddSourceInputSchema = Schema3.Struct({
1181
+ var AddSourceInputSchema = Schema4.Struct({
962
1182
  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))
1183
+ slug: Schema4.String,
1184
+ description: Schema4.optional(Schema4.String),
1185
+ baseUrl: Schema4.optional(Schema4.String),
1186
+ headers: Schema4.optional(Schema4.Record(Schema4.String, Schema4.String)),
1187
+ queryParams: Schema4.optional(Schema4.Record(Schema4.String, Schema4.String)),
1188
+ authenticationTemplate: Schema4.optional(Schema4.Array(AuthenticationSchema2))
969
1189
  });
970
- var AddSourceOutputSchema = Schema3.Struct({
971
- slug: Schema3.String,
972
- toolCount: Schema3.Number
1190
+ var AddSourceOutputSchema = Schema4.Struct({
1191
+ slug: Schema4.String,
1192
+ toolCount: Schema4.Number
973
1193
  });
974
- var PreviewSpecInputStandardSchema = Schema3.toStandardSchemaV1(
975
- Schema3.toStandardJSONSchemaV1(PreviewSpecInputSchema)
1194
+ var PreviewSpecInputStandardSchema = Schema4.toStandardSchemaV1(
1195
+ Schema4.toStandardJSONSchemaV1(PreviewSpecInputSchema)
976
1196
  );
977
- var PreviewSpecOutputStandardSchema = Schema3.toStandardSchemaV1(
978
- Schema3.toStandardJSONSchemaV1(StaticPreviewSpecOutputSchema)
1197
+ var PreviewSpecOutputStandardSchema = Schema4.toStandardSchemaV1(
1198
+ Schema4.toStandardJSONSchemaV1(StaticPreviewSpecOutputSchema)
979
1199
  );
980
- var AddSourceInputStandardSchema = Schema3.toStandardSchemaV1(
981
- Schema3.toStandardJSONSchemaV1(AddSourceInputSchema)
1200
+ var AddSourceInputStandardSchema = Schema4.toStandardSchemaV1(
1201
+ Schema4.toStandardJSONSchemaV1(AddSourceInputSchema)
982
1202
  );
983
- var AddSourceOutputStandardSchema = Schema3.toStandardSchemaV1(
984
- Schema3.toStandardJSONSchemaV1(AddSourceOutputSchema)
1203
+ var AddSourceOutputStandardSchema = Schema4.toStandardSchemaV1(
1204
+ Schema4.toStandardJSONSchemaV1(AddSourceOutputSchema)
985
1205
  );
986
- var openApiToolFailure = (code, message, details) => ToolResult.fail({
1206
+ var openApiToolFailure = (code, message, details) => ToolResult2.fail({
987
1207
  code,
988
1208
  message,
989
1209
  ...details === void 0 ? {} : { details }
990
1210
  });
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
1211
  var staticPreviewOutput = (preview) => ({
1010
- title: Option5.getOrNull(preview.title),
1011
- version: Option5.getOrNull(preview.version),
1212
+ title: Option6.getOrNull(preview.title),
1213
+ version: Option6.getOrNull(preview.version),
1012
1214
  servers: preview.servers.map((server) => ({
1013
1215
  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]) => [
1216
+ description: Option6.getOrNull(server.description),
1217
+ variables: Option6.getOrNull(server.variables) ? Object.fromEntries(
1218
+ Object.entries(Option6.getOrNull(server.variables) ?? {}).map(([name, variable]) => [
1017
1219
  name,
1018
1220
  {
1019
1221
  default: variable.default,
1020
- enum: Option5.getOrNull(variable.enum),
1021
- description: Option5.getOrNull(variable.description)
1222
+ enum: Option6.getOrNull(variable.enum),
1223
+ description: Option6.getOrNull(variable.description)
1022
1224
  }
1023
1225
  ])
1024
1226
  ) : null
@@ -1028,25 +1230,25 @@ var staticPreviewOutput = (preview) => ({
1028
1230
  securitySchemes: preview.securitySchemes.map((scheme) => ({
1029
1231
  name: scheme.name,
1030
1232
  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) ? {
1233
+ scheme: Option6.getOrNull(scheme.scheme),
1234
+ bearerFormat: Option6.getOrNull(scheme.bearerFormat),
1235
+ in: Option6.getOrNull(scheme.in),
1236
+ headerName: Option6.getOrNull(scheme.headerName),
1237
+ description: Option6.getOrNull(scheme.description),
1238
+ flows: Option6.isSome(scheme.flows) ? {
1239
+ authorizationCode: Option6.isSome(scheme.flows.value.authorizationCode) ? {
1038
1240
  authorizationUrl: scheme.flows.value.authorizationCode.value.authorizationUrl,
1039
1241
  tokenUrl: scheme.flows.value.authorizationCode.value.tokenUrl,
1040
- refreshUrl: Option5.getOrNull(scheme.flows.value.authorizationCode.value.refreshUrl),
1242
+ refreshUrl: Option6.getOrNull(scheme.flows.value.authorizationCode.value.refreshUrl),
1041
1243
  scopes: scheme.flows.value.authorizationCode.value.scopes
1042
1244
  } : null,
1043
- clientCredentials: Option5.isSome(scheme.flows.value.clientCredentials) ? {
1245
+ clientCredentials: Option6.isSome(scheme.flows.value.clientCredentials) ? {
1044
1246
  tokenUrl: scheme.flows.value.clientCredentials.value.tokenUrl,
1045
- refreshUrl: Option5.getOrNull(scheme.flows.value.clientCredentials.value.refreshUrl),
1247
+ refreshUrl: Option6.getOrNull(scheme.flows.value.clientCredentials.value.refreshUrl),
1046
1248
  scopes: scheme.flows.value.clientCredentials.value.scopes
1047
1249
  } : null
1048
1250
  } : null,
1049
- openIdConnectUrl: Option5.getOrNull(scheme.openIdConnectUrl)
1251
+ openIdConnectUrl: Option6.getOrNull(scheme.openIdConnectUrl)
1050
1252
  })),
1051
1253
  authStrategies: preview.authStrategies,
1052
1254
  headerPresets: preview.headerPresets,
@@ -1054,56 +1256,14 @@ var staticPreviewOutput = (preview) => ({
1054
1256
  label: preset.label,
1055
1257
  securitySchemeName: preset.securitySchemeName,
1056
1258
  flow: preset.flow,
1057
- authorizationUrl: Option5.getOrNull(preset.authorizationUrl),
1259
+ authorizationUrl: Option6.getOrNull(preset.authorizationUrl),
1058
1260
  tokenUrl: preset.tokenUrl,
1059
- refreshUrl: Option5.getOrNull(preset.refreshUrl),
1261
+ refreshUrl: Option6.getOrNull(preset.refreshUrl),
1060
1262
  scopes: preset.scopes,
1061
1263
  identityScopes: preset.identityScopes
1062
1264
  }))
1063
1265
  });
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;
1266
+ var specInputToSourceUrl = (spec) => spec.kind === "url" ? spec.url : void 0;
1107
1267
  var describeOpenApiAuthMethods = (record) => {
1108
1268
  const config = decodeOpenApiIntegrationConfig(record.config);
1109
1269
  if (!config) return [];
@@ -1130,79 +1290,10 @@ var describeOpenApiIntegrationDisplay = (record) => {
1130
1290
  const config = decodeOpenApiIntegrationConfig(record.config);
1131
1291
  return { url: config?.baseUrl ?? config?.sourceUrl };
1132
1292
  };
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
1293
  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
- }
1294
+ const resolveSpecForInput = (spec, httpClientLayer) => Effect4.gen(function* () {
1204
1295
  if (spec.kind === "url") {
1205
- const specText = yield* resolveSpecText(spec.url).pipe(Effect3.provide(httpClientLayer));
1296
+ const specText = yield* resolveSpecText(spec.url).pipe(Effect4.provide(httpClientLayer));
1206
1297
  return { specText };
1207
1298
  }
1208
1299
  return { specText: spec.value };
@@ -1221,12 +1312,12 @@ var openApiPlugin = definePlugin((options) => {
1221
1312
  storage: (deps) => makeDefaultOpenapiStore(deps),
1222
1313
  extension: (ctx) => {
1223
1314
  const httpClientLayer = options?.httpClientLayer ?? ctx.httpClientLayer;
1224
- const addSpec = (config) => Effect3.gen(function* () {
1315
+ const addSpec = (config) => Effect4.gen(function* () {
1225
1316
  const resolved = yield* resolveSpecForInput(config.spec, httpClientLayer);
1226
- const compiled = yield* compileSpec(resolved.specText);
1227
- const explicitBaseUrl = config.baseUrl ?? resolved.baseUrl;
1317
+ const compiled = yield* compileOpenApiSpec(resolved.specText);
1318
+ const explicitBaseUrl = config.baseUrl;
1228
1319
  const needsDerivedBaseUrl = explicitBaseUrl == null;
1229
- const needsDerivedAuth = config.authenticationTemplate == null && resolved.authenticationTemplate == null;
1320
+ const needsDerivedAuth = config.authenticationTemplate == null;
1230
1321
  const preview = needsDerivedBaseUrl || needsDerivedAuth ? yield* previewSpecText(resolved.specText) : void 0;
1231
1322
  const derivedBaseUrl = needsDerivedBaseUrl && preview ? firstBaseUrlForPreview(preview) : void 0;
1232
1323
  const effectiveBaseUrl = explicitBaseUrl ?? (derivedBaseUrl || void 0);
@@ -1240,55 +1331,52 @@ var openApiPlugin = definePlugin((options) => {
1240
1331
  const integrationConfig = {
1241
1332
  specHash,
1242
1333
  ...specInputToSourceUrl(config.spec) !== void 0 ? { sourceUrl: specInputToSourceUrl(config.spec) } : {},
1243
- ...specInputToGoogleBundle(config.spec) !== void 0 ? { googleDiscoveryUrls: specInputToGoogleBundle(config.spec) } : {},
1244
1334
  // baseUrl is an optional override only. The host is otherwise
1245
1335
  // resolved per call from the operation's `servers` (extracted from
1246
1336
  // the spec), so we never bake a derived base URL into the config.
1247
1337
  ...config.baseUrl ? { baseUrl: config.baseUrl } : {},
1248
1338
  ...config.headers ? { headers: config.headers } : {},
1249
1339
  ...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.
1340
+ // Prefer the caller's explicit template; otherwise derive from the
1341
+ // spec's declared security schemes.
1254
1342
  ...config.authenticationTemplate ? {
1255
1343
  authenticationTemplate: normalizeOpenApiAuthInputs(config.authenticationTemplate)
1256
- } : resolved.authenticationTemplate ? { authenticationTemplate: resolved.authenticationTemplate } : derivedAuthenticationTemplate && derivedAuthenticationTemplate.length > 0 ? { authenticationTemplate: derivedAuthenticationTemplate } : {}
1344
+ } : derivedAuthenticationTemplate && derivedAuthenticationTemplate.length > 0 ? { authenticationTemplate: derivedAuthenticationTemplate } : {}
1257
1345
  };
1258
1346
  yield* ctx.storage.putSpec(specHash, resolved.specText);
1259
1347
  yield* ctx.transaction(
1260
- Effect3.gen(function* () {
1348
+ Effect4.gen(function* () {
1261
1349
  yield* ctx.core.integrations.register({
1262
1350
  slug,
1263
1351
  name: config.name?.trim() || compiled.title || config.slug,
1264
1352
  description: config.description ?? compiled.description ?? compiled.title ?? config.slug,
1265
1353
  config: integrationConfig,
1266
1354
  canRemove: true,
1267
- canRefresh: specInputToSourceUrl(config.spec) != null || specInputToGoogleBundle(config.spec) != null
1355
+ canRefresh: specInputToSourceUrl(config.spec) != null
1268
1356
  });
1269
1357
  yield* ctx.storage.putOperations(
1270
1358
  config.slug,
1271
- storedOperationsFromCompiled(config.slug, compiled)
1359
+ openApiStoredOperationsFromCompiled(config.slug, compiled)
1272
1360
  );
1273
1361
  })
1274
1362
  );
1275
1363
  return { slug, toolCount: compiled.definitions.length };
1276
1364
  });
1277
- const updateSpec = (rawSlug, input) => Effect3.gen(function* () {
1365
+ const updateSpec = (rawSlug, input) => Effect4.gen(function* () {
1278
1366
  const slug = IntegrationSlug.make(rawSlug);
1279
1367
  const record = yield* ctx.core.integrations.get(slug);
1280
1368
  const current = record ? decodeOpenApiIntegrationConfig(record.config) : null;
1281
1369
  if (!record || !current) {
1282
1370
  return yield* new IntegrationNotFoundError({ slug });
1283
1371
  }
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);
1372
+ const specInput = input?.spec ?? (current.sourceUrl ? { kind: "url", url: current.sourceUrl } : null);
1285
1373
  if (specInput === null) {
1286
1374
  return yield* new OpenApiParseError({
1287
1375
  message: "This integration's spec was pasted inline and has no source URL to re-fetch. Provide the updated spec content."
1288
1376
  });
1289
1377
  }
1290
1378
  const resolved = yield* resolveSpecForInput(specInput, httpClientLayer);
1291
- const compiled = yield* compileSpec(resolved.specText);
1379
+ const compiled = yield* compileOpenApiSpec(resolved.specText);
1292
1380
  const previousOperations = yield* ctx.storage.listOperations(rawSlug);
1293
1381
  const previousNames = new Set(previousOperations.map((op) => op.toolName));
1294
1382
  const nextNames = new Set(compiled.definitions.map((def) => def.toolPath));
@@ -1297,32 +1385,31 @@ var openApiPlugin = definePlugin((options) => {
1297
1385
  const nextConfig = {
1298
1386
  ...current,
1299
1387
  specHash,
1300
- ...specInputToSourceUrl(specInput) !== void 0 ? { sourceUrl: specInputToSourceUrl(specInput) } : {},
1301
- ...specInputToGoogleBundle(specInput) !== void 0 ? { googleDiscoveryUrls: specInputToGoogleBundle(specInput) } : {}
1388
+ ...specInputToSourceUrl(specInput) !== void 0 ? { sourceUrl: specInputToSourceUrl(specInput) } : {}
1302
1389
  };
1303
1390
  yield* ctx.transaction(
1304
- Effect3.gen(function* () {
1391
+ Effect4.gen(function* () {
1305
1392
  yield* ctx.core.integrations.update(slug, {
1306
1393
  config: nextConfig
1307
1394
  });
1308
1395
  yield* ctx.storage.putOperations(
1309
1396
  rawSlug,
1310
- storedOperationsFromCompiled(rawSlug, compiled)
1397
+ openApiStoredOperationsFromCompiled(rawSlug, compiled)
1311
1398
  );
1312
1399
  })
1313
1400
  );
1314
1401
  const connections = yield* ctx.connections.list({ integration: slug });
1315
- yield* Effect3.forEach(
1402
+ yield* Effect4.forEach(
1316
1403
  connections,
1317
1404
  (connection) => ctx.connections.refresh({
1318
1405
  owner: connection.owner,
1319
1406
  integration: connection.integration,
1320
1407
  name: connection.name
1321
- }).pipe(Effect3.catchTag("ConnectionNotFoundError", () => Effect3.succeed([]))),
1408
+ }).pipe(Effect4.catchTag("ConnectionNotFoundError", () => Effect4.succeed([]))),
1322
1409
  { discard: true }
1323
1410
  ).pipe(
1324
- Effect3.catchTag("IntegrationNotFoundError", () => Effect3.void),
1325
- Effect3.withSpan("openapi.plugin.update_spec.refresh_connections", {
1411
+ Effect4.catchTag("IntegrationNotFoundError", () => Effect4.void),
1412
+ Effect4.withSpan("openapi.plugin.update_spec.refresh_connections", {
1326
1413
  attributes: { "openapi.connection_count": connections.length }
1327
1414
  })
1328
1415
  );
@@ -1333,35 +1420,28 @@ var openApiPlugin = definePlugin((options) => {
1333
1420
  removedTools: [...previousNames].filter((name) => !nextNames.has(name)).sort()
1334
1421
  };
1335
1422
  }).pipe(
1336
- Effect3.withSpan("openapi.plugin.update_spec", {
1423
+ Effect4.withSpan("openapi.plugin.update_spec", {
1337
1424
  attributes: { "openapi.integration.slug": rawSlug }
1338
1425
  })
1339
1426
  );
1340
1427
  return {
1341
- previewSpec: (input) => Effect3.gen(function* () {
1428
+ previewSpec: (input) => Effect4.gen(function* () {
1342
1429
  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));
1430
+ const specText = yield* resolveSpecText(previewInput.spec).pipe(
1431
+ Effect4.provide(httpClientLayer)
1432
+ );
1433
+ return yield* previewSpecText(specText);
1354
1434
  }),
1355
1435
  addSpec,
1356
1436
  updateSpec,
1357
1437
  removeSpec: (slug) => ctx.transaction(
1358
- Effect3.gen(function* () {
1438
+ Effect4.gen(function* () {
1359
1439
  yield* ctx.storage.removeOperations(slug);
1360
- yield* ctx.core.integrations.remove(IntegrationSlug.make(slug)).pipe(Effect3.catchTag("IntegrationRemovalNotAllowedError", () => Effect3.void));
1440
+ yield* ctx.core.integrations.remove(IntegrationSlug.make(slug)).pipe(Effect4.catchTag("IntegrationRemovalNotAllowedError", () => Effect4.void));
1361
1441
  })
1362
1442
  ),
1363
1443
  getIntegration: (slug) => ctx.core.integrations.get(IntegrationSlug.make(slug)).pipe(
1364
- Effect3.map(
1444
+ Effect4.map(
1365
1445
  (record) => record ? {
1366
1446
  slug: record.slug,
1367
1447
  description: record.description,
@@ -1372,12 +1452,12 @@ var openApiPlugin = definePlugin((options) => {
1372
1452
  )
1373
1453
  ),
1374
1454
  getConfig: (slug) => ctx.core.integrations.get(IntegrationSlug.make(slug)).pipe(
1375
- Effect3.map(
1455
+ Effect4.map(
1376
1456
  (record) => record ? decodeOpenApiIntegrationConfig(record.config) : null
1377
1457
  )
1378
1458
  ),
1379
1459
  configure: (slug, input) => ctx.transaction(
1380
- Effect3.gen(function* () {
1460
+ Effect4.gen(function* () {
1381
1461
  const record = yield* ctx.core.integrations.get(IntegrationSlug.make(slug));
1382
1462
  if (!record) return [];
1383
1463
  const current = decodeOpenApiIntegrationConfig(record.config);
@@ -1408,17 +1488,17 @@ var openApiPlugin = definePlugin((options) => {
1408
1488
  inputSchema: PreviewSpecInputStandardSchema,
1409
1489
  outputSchema: PreviewSpecOutputStandardSchema,
1410
1490
  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))
1491
+ Effect4.map((preview) => ToolResult2.ok(staticPreviewOutput(preview))),
1492
+ Effect4.catchTags({
1493
+ OpenApiParseError: ({ message }) => Effect4.succeed(openApiToolFailure("openapi_parse_failed", message)),
1494
+ OpenApiExtractionError: ({ message }) => Effect4.succeed(openApiToolFailure("openapi_extraction_failed", message)),
1495
+ OpenApiOAuthError: ({ message }) => Effect4.succeed(openApiToolFailure("openapi_oauth_failed", message))
1416
1496
  })
1417
1497
  )
1418
1498
  }),
1419
1499
  tool({
1420
1500
  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).",
1501
+ 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
1502
  annotations: {
1423
1503
  requiresApproval: true,
1424
1504
  approvalDescription: "Add an OpenAPI integration"
@@ -1434,17 +1514,17 @@ var openApiPlugin = definePlugin((options) => {
1434
1514
  queryParams: input.queryParams,
1435
1515
  authenticationTemplate: input.authenticationTemplate
1436
1516
  }).pipe(
1437
- Effect3.map(
1438
- (result) => ToolResult.ok({
1517
+ Effect4.map(
1518
+ (result) => ToolResult2.ok({
1439
1519
  slug: String(result.slug),
1440
1520
  toolCount: result.toolCount
1441
1521
  })
1442
1522
  ),
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(
1523
+ Effect4.catchTags({
1524
+ OpenApiParseError: ({ message }) => Effect4.succeed(openApiToolFailure("openapi_parse_failed", message)),
1525
+ OpenApiExtractionError: ({ message }) => Effect4.succeed(openApiToolFailure("openapi_extraction_failed", message)),
1526
+ OpenApiOAuthError: ({ message }) => Effect4.succeed(openApiToolFailure("openapi_oauth_failed", message)),
1527
+ IntegrationAlreadyExistsError: ({ slug }) => Effect4.succeed(
1448
1528
  openApiToolFailure(
1449
1529
  "integration_already_exists",
1450
1530
  `Integration ${slug} already exists; update it instead of re-adding.`
@@ -1459,176 +1539,50 @@ var openApiPlugin = definePlugin((options) => {
1459
1539
  describeAuthMethods: describeOpenApiAuthMethods,
1460
1540
  describeIntegrationDisplay: describeOpenApiIntegrationDisplay,
1461
1541
  // Produce one tool per spec operation. Spec-derived, identical for every
1462
- // connection on the integration so `getValue` is never called here. The
1542
+ // connection on the integration - so `getValue` is never called here. The
1463
1543
  // operation bindings invokeTool needs are persisted at addSpec time; this
1464
1544
  // hook only shapes the per-connection ToolDefs from the spec blob the
1465
1545
  // 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* () {
1546
+ resolveTools: ({ config, storage }) => resolveOpenApiBackedTools({ config, storage }),
1547
+ invokeTool: ({ ctx: invokeCtx, toolRow, credential, args }) => {
1489
1548
  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,
1549
+ return invokeOpenApiBackedTool({
1550
+ ctx: invokeCtx,
1551
+ toolRow,
1552
+ credential,
1553
+ args,
1542
1554
  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
1555
  });
1569
- }),
1570
- resolveAnnotations: ({
1556
+ },
1557
+ resolveAnnotations: ({ ctx: annotationsCtx, integration, toolRows }) => resolveOpenApiBackedAnnotations({
1571
1558
  ctx: annotationsCtx,
1572
- integration,
1559
+ integration: String(integration),
1573
1560
  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
1561
  }),
1587
- removeConnection: () => Effect3.void,
1562
+ removeConnection: () => Effect4.void,
1588
1563
  detect: ({
1589
1564
  ctx: detectCtx,
1590
1565
  url
1591
- }) => Effect3.gen(function* () {
1566
+ }) => Effect4.gen(function* () {
1592
1567
  const httpClientLayer = options?.httpClientLayer ?? detectCtx.httpClientLayer;
1593
1568
  const trimmed = url.trim();
1594
1569
  if (!trimmed) return null;
1595
- const parsed = yield* Effect3.try({
1570
+ const parsed = yield* Effect4.try({
1596
1571
  try: () => new URL(trimmed),
1597
1572
  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
- }
1573
+ }).pipe(Effect4.option);
1574
+ if (Option6.isNone(parsed)) return null;
1621
1575
  const specText = yield* resolveSpecText(trimmed).pipe(
1622
- Effect3.provide(httpClientLayer),
1623
- Effect3.catch(() => Effect3.succeed(null))
1576
+ Effect4.provide(httpClientLayer),
1577
+ Effect4.catch(() => Effect4.succeed(null))
1624
1578
  );
1625
1579
  if (specText === null) return null;
1626
- const doc = yield* parse(specText).pipe(Effect3.catch(() => Effect3.succeed(null)));
1580
+ const doc = yield* parse(specText).pipe(Effect4.catch(() => Effect4.succeed(null)));
1627
1581
  if (!doc) return null;
1628
- const result = yield* extract(doc).pipe(Effect3.catch(() => Effect3.succeed(null)));
1582
+ const result = yield* extract(doc).pipe(Effect4.catch(() => Effect4.succeed(null)));
1629
1583
  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);
1584
+ const slug = Option6.getOrElse(result.title, () => "api").toLowerCase().replace(/[^a-z0-9]+/g, "_");
1585
+ const name = Option6.getOrElse(result.title, () => slug);
1632
1586
  return IntegrationDetectionResult.make({
1633
1587
  kind: "openapi",
1634
1588
  confidence: "high",
@@ -1645,10 +1599,20 @@ export {
1645
1599
  OpenApiIntegrationConfigSchema,
1646
1600
  decodeOpenApiIntegrationConfig,
1647
1601
  renderAuthTemplate,
1602
+ makeDefaultOpenapiStore,
1648
1603
  invoke,
1649
1604
  invokeWithLayer,
1650
1605
  annotationsForOperation,
1651
- makeDefaultOpenapiStore,
1606
+ extractOpenApiUpstreamMessage,
1607
+ normalizeOpenApiRefs,
1608
+ compileOpenApiDocument,
1609
+ compileOpenApiSpec,
1610
+ openApiToolDefsFromCompiled,
1611
+ openApiStoredOperationsFromCompiled,
1612
+ loadOpenApiSpecText,
1613
+ resolveOpenApiBackedTools,
1614
+ invokeOpenApiBackedTool,
1615
+ resolveOpenApiBackedAnnotations,
1652
1616
  openApiPlugin
1653
1617
  };
1654
- //# sourceMappingURL=chunk-ZTOOUP67.js.map
1618
+ //# sourceMappingURL=chunk-UEKOP6NZ.js.map