MCPcopy Create free account
hub / github.com/UsefulSoftwareCo/executor / updateSpec

Function updateSpec

packages/plugins/openapi/src/sdk/plugin.ts:861–978  ·  view source on GitHub ↗
(rawSlug: string, input?: OpenApiUpdateSpecInput)

Source from the content-addressed store, hash-verified

859 // the curated description, connections, and policies are all untouched -
860 // this is the "spec changed upstream" path, not a re-add.
861 const updateSpec = (rawSlug: string, input?: OpenApiUpdateSpecInput) =>
862 Effect.gen(function* () {
863 const slug = IntegrationSlug.make(rawSlug);
864 const record = yield* ctx.core.integrations.get(slug);
865 const current = record ? decodeOpenApiIntegrationConfig(record.config) : null;
866 if (!record || !current) {
867 return yield* new IntegrationNotFoundError({ slug });
868 }
869
870 // The new spec source: explicit input wins; otherwise re-fetch from
871 // where the spec originally came from. A pasted-blob integration has
872 // no origin, so updating it requires a new input.
873 const specInput: OpenApiSpecInput | null =
874 input?.spec ?? (current.specUrl ? { kind: "url", url: current.specUrl } : null);
875 if (specInput === null) {
876 return yield* new OpenApiParseError({
877 message:
878 "This integration's spec was pasted inline and has no source URL to re-fetch. Provide the updated spec content.",
879 });
880 }
881
882 // Resolve + compile BEFORE the transaction (same Hyperdrive-deadlock
883 // rule as addSpec: never hold BEGIN across a network fetch).
884 const resolved = yield* resolveSpecForInput(
885 {
886 spec: specInput,
887 specFormat: current.specFormat,
888 headers: current.headers,
889 queryParams: current.queryParams,
890 baseUrl: current.baseUrl,
891 },
892 httpClientLayer,
893 );
894 const compiled = resolved.keepPathItem
895 ? undefined
896 : yield* compileOpenApiSpec(resolved.specText);
897
898 const previousOperations = yield* ctx.storage.listOperations(rawSlug);
899 const previousNames = new Set(previousOperations.map((op) => op.toolName));
900
901 // The resolved spec text lives in the plugin blob store keyed by its
902 // content hash (`spec/<hash>`); the config carries only the hash. Put
903 // the blob outside the transaction - re-puts are idempotent and an
904 // aborted config update just leaves an unreferenced blob.
905 const specHash = yield* sha256Hex(resolved.specText);
906 yield* ctx.storage.putSpec(specHash, resolved.specText);
907 if (compiled) {
908 yield* ctx.storage.putDefs(specHash, JSON.stringify(compiled.hoistedDefs));
909 }
910
911 const nextConfig: OpenApiIntegrationConfig = {
912 ...current,
913 specHash,
914 ...((resolved.specUrl ?? specInputToSpecUrl(specInput)) !== undefined
915 ? { specUrl: resolved.specUrl ?? specInputToSpecUrl(specInput) }
916 : {}),
917 };
918

Callers

nothing calls this directly

Calls 11

compileOpenApiSpecFunction · 0.90
sha256HexFunction · 0.90
resolveSpecForInputFunction · 0.85
specInputToSpecUrlFunction · 0.85
getMethod · 0.65
transactionMethod · 0.65
updateMethod · 0.65
listMethod · 0.65

Tested by

no test coverage detected