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

Function updateSpec

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

Source from the content-addressed store, hash-verified

760 // the curated description, connections, and policies are all untouched -
761 // this is the "spec changed upstream" path, not a re-add.
762 const updateSpec = (rawSlug: string, input?: OpenApiUpdateSpecInput) =>
763 Effect.gen(function* () {
764 const slug = IntegrationSlug.make(rawSlug);
765 const record = yield* ctx.core.integrations.get(slug);
766 const current = record ? decodeOpenApiIntegrationConfig(record.config) : null;
767 if (!record || !current) {
768 return yield* new IntegrationNotFoundError({ slug });
769 }
770
771 // The new spec source: explicit input wins; otherwise re-fetch from
772 // where the spec originally came from. A pasted-blob integration has
773 // no origin, so updating it requires a new input.
774 const specInput: OpenApiSpecInput | null =
775 input?.spec ?? (current.sourceUrl ? { kind: "url", url: current.sourceUrl } : null);
776 if (specInput === null) {
777 return yield* new OpenApiParseError({
778 message:
779 "This integration's spec was pasted inline and has no source URL to re-fetch. Provide the updated spec content.",
780 });
781 }
782
783 // Resolve + compile BEFORE the transaction (same Hyperdrive-deadlock
784 // rule as addSpec: never hold BEGIN across a network fetch).
785 const resolved = yield* resolveSpecForInput(specInput, httpClientLayer);
786 const compiled = yield* compileOpenApiSpec(resolved.specText);
787
788 const previousOperations = yield* ctx.storage.listOperations(rawSlug);
789 const previousNames = new Set(previousOperations.map((op) => op.toolName));
790 const nextNames = new Set(compiled.definitions.map((def) => def.toolPath));
791
792 // The resolved spec text lives in the plugin blob store keyed by its
793 // content hash (`spec/<hash>`); the config carries only the hash. Put
794 // the blob outside the transaction - re-puts are idempotent and an
795 // aborted config update just leaves an unreferenced blob.
796 const specHash = yield* sha256Hex(resolved.specText);
797 yield* ctx.storage.putSpec(specHash, resolved.specText);
798 yield* ctx.storage.putDefs(specHash, JSON.stringify(compiled.hoistedDefs));
799
800 const nextConfig: OpenApiIntegrationConfig = {
801 ...current,
802 specHash,
803 ...(specInputToSourceUrl(specInput) !== undefined
804 ? { sourceUrl: specInputToSourceUrl(specInput) }
805 : {}),
806 };
807
808 yield* ctx.transaction(
809 Effect.gen(function* () {
810 yield* ctx.core.integrations.update(slug, {
811 config: nextConfig satisfies OpenApiIntegrationConfig as IntegrationConfig,
812 });
813 yield* ctx.storage.putOperations(
814 rawSlug,
815 openApiStoredOperationsFromCompiled(rawSlug, compiled),
816 );
817 }),
818 );
819

Callers

nothing calls this directly

Calls 10

compileOpenApiSpecFunction · 0.90
sha256HexFunction · 0.90
resolveSpecForInputFunction · 0.85
specInputToSourceUrlFunction · 0.85
transactionMethod · 0.80
getMethod · 0.65
updateMethod · 0.65
listMethod · 0.65

Tested by

no test coverage detected