{"version":3,"file":"tool-operations.mjs","names":[],"sources":["../../src/tool-operations.ts"],"sourcesContent":["import type { Client } from \"./core/client.ts\";\nimport { InvalidPURLError, PkioError } from \"./core/errors.ts\";\nimport { parsePURL } from \"./core/purl.ts\";\nimport { ecosystems } from \"./core/registry.ts\";\nimport type { Package } from \"./core/types.ts\";\nimport {\n  bulkFetchPackages,\n  fetchDependenciesFromPURL,\n  fetchMaintainersFromPURL,\n  fetchPackageFromPURL,\n  fetchVersionsFromPURL,\n} from \"./helpers.ts\";\n\nexport const MAX_PURL_LENGTH = 2_048;\nexport const MAX_BULK_PACKAGES = 50;\nexport const DEFAULT_BULK_CONCURRENCY = 15;\nexport const MAX_BULK_CONCURRENCY = 50;\n\nexport interface ToolResult<T> {\n  content: Array<{ type: \"text\"; text: string }>;\n  details: T;\n  isError?: boolean;\n}\n\nexport interface PURLParams {\n  readonly purl: string;\n}\n\nexport interface BulkPackagesParams {\n  readonly purls: readonly string[];\n  readonly concurrency?: number;\n}\n\nfunction jsonResult<T>(details: T): ToolResult<T> {\n  return {\n    content: [{ type: \"text\", text: JSON.stringify(details) }],\n    details,\n  };\n}\n\nfunction assertPURL(purl: string): void {\n  if (typeof purl !== \"string\" || purl.length === 0) {\n    throw new InvalidPURLError(String(purl), \"must be a non-empty string\");\n  }\n  if (purl.length > MAX_PURL_LENGTH) {\n    throw new InvalidPURLError(\n      purl.slice(0, MAX_PURL_LENGTH),\n      `must not exceed ${MAX_PURL_LENGTH} characters`,\n    );\n  }\n\n  const parsed = parsePURL(purl);\n  if (Object.hasOwn(parsed.qualifiers, \"repository_url\")) {\n    throw new InvalidPURLError(purl, \"repository_url is not allowed in agent tools\");\n  }\n}\n\nfunction isPURLArray(value: unknown): value is readonly string[] {\n  return Array.isArray(value) && value.every((item: unknown) => typeof item === \"string\");\n}\n\nfunction assertBulkParams(params: Readonly<BulkPackagesParams>): void {\n  if (!isPURLArray(params.purls) || params.purls.length === 0) {\n    throw new PkioError(\"Bulk package lookup needs at least one PURL\");\n  }\n  if (params.purls.length > MAX_BULK_PACKAGES) {\n    throw new PkioError(`Bulk package lookup accepts at most ${MAX_BULK_PACKAGES} PURLs`);\n  }\n  for (const purl of params.purls) assertPURL(purl);\n\n  const concurrency = params.concurrency ?? DEFAULT_BULK_CONCURRENCY;\n  if (!Number.isInteger(concurrency) || concurrency < 1 || concurrency > MAX_BULK_CONCURRENCY) {\n    throw new PkioError(`Concurrency must be an integer from 1 through ${MAX_BULK_CONCURRENCY}`);\n  }\n}\n\nexport async function packageOperation(\n  params: Readonly<PURLParams>,\n  signal?: AbortSignal,\n  client?: Client,\n): Promise<ToolResult<Package>> {\n  assertPURL(params.purl);\n  return jsonResult(await fetchPackageFromPURL(params.purl, signal, client));\n}\n\nexport async function versionsOperation(\n  params: Readonly<PURLParams>,\n  signal?: AbortSignal,\n  client?: Client,\n) {\n  assertPURL(params.purl);\n  return jsonResult(await fetchVersionsFromPURL(params.purl, signal, client));\n}\n\nexport async function dependenciesOperation(\n  params: Readonly<PURLParams>,\n  signal?: AbortSignal,\n  client?: Client,\n) {\n  assertPURL(params.purl);\n  return jsonResult(await fetchDependenciesFromPURL(params.purl, signal, client));\n}\n\nexport async function maintainersOperation(\n  params: Readonly<PURLParams>,\n  signal?: AbortSignal,\n  client?: Client,\n) {\n  assertPURL(params.purl);\n  return jsonResult(await fetchMaintainersFromPURL(params.purl, signal, client));\n}\n\nexport async function bulkPackagesOperation(\n  params: Readonly<BulkPackagesParams>,\n  signal?: AbortSignal,\n  client?: Client,\n): Promise<ToolResult<Record<string, Package>>> {\n  assertBulkParams(params);\n  const packages = await bulkFetchPackages(params.purls, {\n    concurrency: params.concurrency ?? DEFAULT_BULK_CONCURRENCY,\n    signal,\n    client,\n  });\n  return jsonResult(Object.fromEntries(packages));\n}\n\nexport async function ecosystemsOperation(): Promise<ToolResult<{ ecosystems: string[] }>> {\n  return jsonResult({ ecosystems: ecosystems().sort() });\n}\n"],"mappings":";;;AAaA,MAAa,kBAAkB;AAC/B,MAAa,oBAAoB;AACjC,MAAa,2BAA2B;AACxC,MAAa,uBAAuB;AAiBpC,SAAS,WAAc,SAA2B;CAChD,OAAO;EACL,SAAS,CAAC;GAAE,MAAM;GAAQ,MAAM,KAAK,UAAU,OAAO;EAAE,CAAC;EACzD;CACF;AACF;AAEA,SAAS,WAAW,MAAoB;CACtC,IAAI,OAAO,SAAS,YAAY,KAAK,WAAW,GAC9C,MAAM,IAAI,iBAAiB,OAAO,IAAI,GAAG,4BAA4B;CAEvE,IAAI,KAAK,SAAA,MACP,MAAM,IAAI,iBACR,KAAK,MAAM,GAAG,eAAe,GAC7B,mBAAmB,gBAAgB,YACrC;CAGF,MAAM,SAAS,UAAU,IAAI;CAC7B,IAAI,OAAO,OAAO,OAAO,YAAY,gBAAgB,GACnD,MAAM,IAAI,iBAAiB,MAAM,8CAA8C;AAEnF;AAEA,SAAS,YAAY,OAA4C;CAC/D,OAAO,MAAM,QAAQ,KAAK,KAAK,MAAM,OAAO,SAAkB,OAAO,SAAS,QAAQ;AACxF;AAEA,SAAS,iBAAiB,QAA4C;CACpE,IAAI,CAAC,YAAY,OAAO,KAAK,KAAK,OAAO,MAAM,WAAW,GACxD,MAAM,IAAI,UAAU,6CAA6C;CAEnE,IAAI,OAAO,MAAM,SAAA,IACf,MAAM,IAAI,UAAU,8CAAgE;CAEtF,KAAK,MAAM,QAAQ,OAAO,OAAO,WAAW,IAAI;CAEhD,MAAM,cAAc,OAAO,eAAA;CAC3B,IAAI,CAAC,OAAO,UAAU,WAAW,KAAK,cAAc,KAAK,cAAA,IACvD,MAAM,IAAI,UAAU,kDAAuE;AAE/F;AAEA,eAAsB,iBACpB,QACA,QACA,QAC8B;CAC9B,WAAW,OAAO,IAAI;CACtB,OAAO,WAAW,MAAM,qBAAqB,OAAO,MAAM,QAAQ,MAAM,CAAC;AAC3E;AAEA,eAAsB,kBACpB,QACA,QACA,QACA;CACA,WAAW,OAAO,IAAI;CACtB,OAAO,WAAW,MAAM,sBAAsB,OAAO,MAAM,QAAQ,MAAM,CAAC;AAC5E;AAEA,eAAsB,sBACpB,QACA,QACA,QACA;CACA,WAAW,OAAO,IAAI;CACtB,OAAO,WAAW,MAAM,0BAA0B,OAAO,MAAM,QAAQ,MAAM,CAAC;AAChF;AAEA,eAAsB,qBACpB,QACA,QACA,QACA;CACA,WAAW,OAAO,IAAI;CACtB,OAAO,WAAW,MAAM,yBAAyB,OAAO,MAAM,QAAQ,MAAM,CAAC;AAC/E;AAEA,eAAsB,sBACpB,QACA,QACA,QAC8C;CAC9C,iBAAiB,MAAM;CACvB,MAAM,WAAW,MAAM,kBAAkB,OAAO,OAAO;EACrD,aAAa,OAAO,eAAA;EACpB;EACA;CACF,CAAC;CACD,OAAO,WAAW,OAAO,YAAY,QAAQ,CAAC;AAChD;AAEA,eAAsB,sBAAqE;CACzF,OAAO,WAAW,EAAE,YAAY,WAAW,CAAC,CAAC,KAAK,EAAE,CAAC;AACvD"}