1060 lines · 32.9 KB · TypeScript
RawDownload
import {  type ToolCatalogEntry,  type ToolDescriptor as CatalogToolDescriptor,} from "@executor/codemode-core";import type {  AccountId,  Source,  StoredSourceRecord,  StoredSourceCatalogRevisionRecord,  WorkspaceId,} from "#schema";import * as Context from "effect/Context";import * as Effect from "effect/Effect";import * as Layer from "effect/Layer";import * as Match from "effect/Match"; import {  decodeCatalogSnapshotV1,  projectCatalogForAgentSdk,  type ProjectedCatalog,} from "../ir/catalog";import type {  Capability,  CatalogSnapshotV1,  CatalogV1,  Executable,  GraphQLExecutable,  HttpExecutable,  McpExecutable,  ShapeSymbol,  Symbol as IrSymbol,} from "../ir/model";import { LocalSourceArtifactMissingError } from "./local-errors";import {  createCatalogTypeProjector,  joinTypeNameSegments,  projectedCatalogTypeRoots,  type CatalogTypeProjector,} from "./catalog-typescript";import {  RuntimeLocalWorkspaceService,  type RuntimeLocalWorkspaceState,} from "./local-runtime-context";import type { LocalSourceArtifact } from "./local-source-artifacts";import {  SourceArtifactStore,  type SourceArtifactStoreShape,} from "./local-storage";import { namespaceFromSourceName } from "./source-names";import {  RuntimeSourceStoreService,  type RuntimeSourceStore,} from "./source-store"; type CatalogImportMetadata = CatalogSnapshotV1["import"]; type ProjectedToolDescriptor = ProjectedCatalog["toolDescriptors"][keyof ProjectedCatalog["toolDescriptors"]]; export type LoadedSourceCatalog = {  source: Source;  sourceRecord: StoredSourceRecord;  revision: StoredSourceCatalogRevisionRecord;  snapshot: CatalogSnapshotV1;  catalog: CatalogV1;  projected: ProjectedCatalog;  typeProjector: CatalogTypeProjector;  importMetadata: CatalogImportMetadata;}; export type LoadedSourceCatalogTool = {  path: string;  searchNamespace: string;  searchText: string;  source: Source;  sourceRecord: StoredSourceRecord;  revision: StoredSourceCatalogRevisionRecord;  capabilityId: keyof CatalogV1["capabilities"];  executableId: keyof CatalogV1["executables"];  capability: Capability;  executable: Executable;  projectedDescriptor: ProjectedToolDescriptor;  descriptor: CatalogToolDescriptor;  projectedCatalog: CatalogV1;  typeProjector: CatalogTypeProjector;}; export type LoadedSourceCatalogToolIndexEntry = Omit<  LoadedSourceCatalogTool,  "revision" | "projectedDescriptor" | "typeProjector">; export const catalogToolCatalogEntry = (input: {  tool: LoadedSourceCatalogToolIndexEntry;  score: (queryTokens: readonly string[]) => number;}): ToolCatalogEntry => ({  descriptor: input.tool.descriptor,  namespace: input.tool.searchNamespace,  searchText: input.tool.searchText,  score: input.score,}); const catalogNamespaceFromPath = (path: string): string => {  const [first, second] = path.split(".");  return second ? `${first}.${second}` : first;}; const descriptorPath = (descriptor: CatalogToolDescriptor): string => descriptor.path; const projectedToolPath = (projected: ProjectedCatalog, capability: Capability): string =>  projected.toolDescriptors[capability.id]?.toolPath.join(".") ?? ""; const chooseExecutable = (catalog: CatalogV1, capability: Capability): Executable => {  const preferred =    capability.preferredExecutableId !== undefined      ? catalog.executables[capability.preferredExecutableId]      : undefined;  if (preferred) {    return preferred;  }   const first = capability.executableIds    .map((id) => catalog.executables[id])    .find((entry): entry is Executable => entry !== undefined);  if (!first) {    throw new Error(`Capability ${capability.id} has no executable`);  }  return first;}; const asShape = (catalog: CatalogV1, shapeId: string | undefined): ShapeSymbol | undefined => {  if (!shapeId) {    return undefined;  }   const symbol = catalog.symbols[shapeId];  return symbol?.kind === "shape" ? symbol : undefined;}; const asJsonRecord = (value: unknown): Record<string, unknown> =>  typeof value === "object" && value !== null && !Array.isArray(value)    ? (value as Record<string, unknown>)    : {}; const symbolDocsSummary = (symbol: IrSymbol | undefined): string | undefined => {  if (!symbol || !("docs" in symbol)) {    return undefined;  }   return symbol.docs?.summary ?? symbol.docs?.description;}; export const shapeToJsonSchema = (catalog: CatalogV1, rootShapeId: string): unknown => {  const defs: Record<string, unknown> = {};  const inlineStack = new Set<string>();  const buildingDefs = new Set<string>();  const builtDefs = new Set<string>();  const defNameByShapeId = new Map<string, string>();  const usedDefNames = new Set<string>();   const sanitizeDefName = (value: string): string | null => {    const trimmed = value.trim();    if (trimmed.length === 0) {      return null;    }     const sanitized = trimmed      .replace(/[^A-Za-z0-9_]+/g, "_")      .replace(/_+/g, "_")      .replace(/^_+|_+$/g, "");     if (sanitized.length === 0) {      return null;    }     return /^[A-Za-z_]/.test(sanitized) ? sanitized : `shape_${sanitized}`;  };   const shapeLabelCandidates = (shapeId: string, suggestions: readonly string[]): string[] => {    const shape = asShape(catalog, shapeId);    return [      ...suggestions,      shape?.title,      shapeId,    ].flatMap((candidate) =>      typeof candidate === "string" && candidate.trim().length > 0        ? [candidate]        : [],    );  };   const defNameFor = (shapeId: string, suggestions: readonly string[]): string => {    const existing = defNameByShapeId.get(shapeId);    if (existing) {      return existing;    }     const candidates = shapeLabelCandidates(shapeId, suggestions);    for (const candidate of candidates) {      const sanitized = sanitizeDefName(candidate);      if (!sanitized) {        continue;      }       if (!usedDefNames.has(sanitized)) {        defNameByShapeId.set(shapeId, sanitized);        usedDefNames.add(sanitized);        return sanitized;      }    }     const fallbackBase = sanitizeDefName(shapeId) ?? "shape";    let fallback = fallbackBase;    let index = 2;    while (usedDefNames.has(fallback)) {      fallback = `${fallbackBase}_${String(index)}`;      index += 1;    }     defNameByShapeId.set(shapeId, fallback);    usedDefNames.add(fallback);    return fallback;  };   const primaryLabel = (shapeId: string, suggestions: readonly string[], fallback: string): string =>    shapeLabelCandidates(shapeId, suggestions)[0] ?? fallback;   const isShallowInlineCandidate = (    shapeId: string,    depth: number,    seen: ReadonlySet<string>,  ): boolean => {    const shape = asShape(catalog, shapeId);    if (!shape) {      return true;    }     if (depth < 0 || seen.has(shapeId)) {      return false;    }     const nextSeen = new Set(seen);    nextSeen.add(shapeId);     return Match.value(shape.node).pipe(      Match.when({ type: "unknown" }, () => true),      Match.when({ type: "const" }, () => true),      Match.when({ type: "enum" }, () => true),      Match.when({ type: "scalar" }, () => true),      Match.when({ type: "ref" }, (node) =>        isShallowInlineCandidate(node.target, depth, nextSeen)),      Match.when({ type: "nullable" }, (node) =>        isShallowInlineCandidate(node.itemShapeId, depth - 1, nextSeen)),      Match.when({ type: "array" }, (node) =>        isShallowInlineCandidate(node.itemShapeId, depth - 1, nextSeen)),      Match.when({ type: "object" }, (node) => {        const fields = Object.values(node.fields);        return fields.length <= 8          && fields.every((field) =>            isShallowInlineCandidate(field.shapeId, depth - 1, nextSeen));      }),      Match.orElse(() => false),    );  };   const shouldInlineRefTarget = (shapeId: string): boolean =>    isShallowInlineCandidate(shapeId, 2, new Set<string>());   const buildInline = (    shapeId: string,    suggestions: readonly string[] = [],  ): Record<string, unknown> => {    if (inlineStack.has(shapeId)) {      return buildRef(shapeId, suggestions);    }     const shape = asShape(catalog, shapeId);    if (!shape) {      return {};    }     inlineStack.add(shapeId);    try {      return buildSchema(shapeId, suggestions);    } finally {      inlineStack.delete(shapeId);    }  };   const buildRef = (    shapeId: string,    suggestions: readonly string[] = [],  ): { $ref: string } => {    const defName = defNameFor(shapeId, suggestions);    if (builtDefs.has(shapeId) || buildingDefs.has(shapeId)) {      return { $ref: `#/$defs/${defName}` };    }     const shape = asShape(catalog, shapeId);    buildingDefs.add(shapeId);    const alreadyInline = inlineStack.has(shapeId);    if (!alreadyInline) {      inlineStack.add(shapeId);    }     try {      defs[defName] = shape        ? buildSchema(shapeId, suggestions)        : {};      builtDefs.add(shapeId);    } finally {      buildingDefs.delete(shapeId);      if (!alreadyInline) {        inlineStack.delete(shapeId);      }    }     return { $ref: `#/$defs/${defName}` };  };   const buildSchema = (    shapeId: string,    suggestions: readonly string[] = [],  ): Record<string, unknown> => {    const shape = asShape(catalog, shapeId);    if (!shape) {      return {};    }     const label = primaryLabel(shapeId, suggestions, "shape");    const withDocs = (schemaValue: Record<string, unknown>): Record<string, unknown> => ({      ...(shape.title ? { title: shape.title } : {}),      ...(shape.docs?.description ? { description: shape.docs.description } : {}),      ...schemaValue,    });     return Match.value(shape.node).pipe(      Match.when({ type: "unknown" }, () => withDocs({})),      Match.when({ type: "const" }, (node) => withDocs({ const: node.value })),      Match.when({ type: "enum" }, (node) => withDocs({ enum: node.values })),      Match.when({ type: "scalar" }, (node) =>        withDocs({          type: node.scalar === "bytes" ? "string" : node.scalar,          ...(node.scalar === "bytes" ? { format: "binary" } : {}),          ...(node.format ? { format: node.format } : {}),          ...(node.constraints ?? {}),        })),      Match.when({ type: "ref" }, (node) =>        shouldInlineRefTarget(node.target)          ? buildInline(node.target, suggestions)          : buildRef(node.target, suggestions)),      Match.when({ type: "nullable" }, (node) =>        withDocs({          anyOf: [            buildInline(node.itemShapeId, suggestions),            { type: "null" },          ],        })),      Match.when({ type: "allOf" }, (node) =>        withDocs({          allOf: node.items.map((entry, index) =>            buildInline(entry, [`${label}_allOf_${String(index + 1)}`])),        })),      Match.when({ type: "anyOf" }, (node) =>        withDocs({          anyOf: node.items.map((entry, index) =>            buildInline(entry, [`${label}_anyOf_${String(index + 1)}`])),        })),      Match.when({ type: "oneOf" }, (node) =>        withDocs({          oneOf: node.items.map((entry, index) =>            buildInline(entry, [`${label}_option_${String(index + 1)}`])),          ...(node.discriminator            ? {                discriminator: {                  propertyName: node.discriminator.propertyName,                  ...(node.discriminator.mapping                    ? {                        mapping: Object.fromEntries(                          Object.entries(node.discriminator.mapping).map(([key, value]) => [                            key,                            buildRef(value, [key, `${label}_${key}`]).$ref,                          ]),                        ),                      }                    : {}),                },              }            : {}),        })),      Match.when({ type: "not" }, (node) =>        withDocs({          not: buildInline(node.itemShapeId, [`${label}_not`]),        })),      Match.when({ type: "conditional" }, (node) =>        withDocs({          if: buildInline(node.ifShapeId, [`${label}_if`]),          ...(node.thenShapeId            ? { then: buildInline(node.thenShapeId, [`${label}_then`]) }            : {}),          ...(node.elseShapeId            ? { else: buildInline(node.elseShapeId, [`${label}_else`]) }            : {}),        })),      Match.when({ type: "array" }, (node) =>        withDocs({          type: "array",          items: buildInline(node.itemShapeId, [`${label}_item`]),          ...(node.minItems !== undefined ? { minItems: node.minItems } : {}),          ...(node.maxItems !== undefined ? { maxItems: node.maxItems } : {}),        })),      Match.when({ type: "tuple" }, (node) =>        withDocs({          type: "array",          prefixItems: node.itemShapeIds.map((entry, index) =>            buildInline(entry, [`${label}_item_${String(index + 1)}`])),          ...(node.additionalItems !== undefined            ? {                items:                  typeof node.additionalItems === "boolean"                    ? node.additionalItems                    : buildInline(node.additionalItems, [`${label}_item_rest`]),              }            : {}),        })),      Match.when({ type: "map" }, (node) =>        withDocs({          type: "object",          additionalProperties: buildInline(node.valueShapeId, [`${label}_value`]),        })),      Match.when({ type: "object" }, (node) =>        withDocs({          type: "object",          properties: Object.fromEntries(            Object.entries(node.fields).map(([key, field]) => [              key,              {                ...buildInline(field.shapeId, [key]),                ...(field.docs?.description ? { description: field.docs.description } : {}),              },            ]),          ),          ...(node.required && node.required.length > 0            ? { required: node.required }            : {}),          ...(node.additionalProperties !== undefined            ? {                additionalProperties:                  typeof node.additionalProperties === "boolean"                    ? node.additionalProperties                    : buildInline(node.additionalProperties, [`${label}_additionalProperty`]),              }            : {}),          ...(node.patternProperties            ? {                patternProperties: Object.fromEntries(                  Object.entries(node.patternProperties).map(([key, value]) => [                    key,                    buildInline(value, [`${label}_patternProperty`]),                  ]),                ),              }            : {}),        })),      Match.when({ type: "graphqlInterface" }, (node) =>        withDocs({          type: "object",          properties: Object.fromEntries(            Object.entries(node.fields).map(([key, field]) => [              key,              buildInline(field.shapeId, [key]),            ]),          ),        })),      Match.when({ type: "graphqlUnion" }, (node) =>        withDocs({          oneOf: node.memberTypeIds.map((entry, index) =>            buildInline(entry, [`${label}_member_${String(index + 1)}`])),        })),      Match.exhaustive,    );  };   const buildRootSchema = (    shapeId: string,    suggestions: readonly string[] = [],  ): Record<string, unknown> => {    const shape = asShape(catalog, shapeId);    if (!shape) {      return {};    }     return Match.value(shape.node).pipe(      Match.when({ type: "ref" }, (node) => buildRootSchema(node.target, suggestions)),      Match.orElse(() => buildInline(shapeId, suggestions)),    );  };   const rootSchema = buildRootSchema(rootShapeId, ["input"]);  return Object.keys(defs).length > 0    ? {

Lines 1–500 of 1060.