{"version":3,"sources":["../src/registry.ts"],"sourcesContent":["/**\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { PromptAction } from '@genkit-ai/ai';\nimport { GenkitError } from '@genkit-ai/core';\nimport { logger } from '@genkit-ai/core/logging';\nimport { Registry } from '@genkit-ai/core/registry';\nimport { existsSync, readdir, readFileSync } from 'fs';\nimport { basename, join, resolve } from 'path';\nimport { Dotprompt } from './prompt.js';\nimport { definePartial } from './template.js';\n\nexport function registryDefinitionKey(\n  name: string,\n  variant?: string,\n  ns?: string\n) {\n  // \"ns/prompt.variant\" where ns and variant are optional\n  return `${ns ? `${ns}/` : ''}${name}${variant ? `.${variant}` : ''}`;\n}\n\nexport function registryLookupKey(name: string, variant?: string, ns?: string) {\n  return `/prompt/${registryDefinitionKey(name, variant, ns)}`;\n}\n\nexport async function lookupPrompt(\n  registry: Registry,\n  name: string,\n  variant?: string,\n  dir: string = './prompts'\n): Promise<Dotprompt> {\n  let registryPrompt =\n    (await registry.lookupAction(registryLookupKey(name, variant))) ||\n    (await registry.lookupAction(\n      registryLookupKey(name, variant, 'dotprompt')\n    ));\n  if (registryPrompt) {\n    return Dotprompt.fromAction(registry, registryPrompt as PromptAction);\n  } else {\n    // Handle the case where initialization isn't complete\n    // or a file was added after the prompt folder was loaded.\n    return maybeLoadPrompt(registry, dir, name, variant);\n  }\n}\n\nasync function maybeLoadPrompt(\n  registry: Registry,\n  dir: string,\n  name: string,\n  variant?: string\n): Promise<Dotprompt> {\n  const expectedFileName = `${name}${variant ? `.${variant}` : ''}.prompt`;\n  const promptFolder = resolve(dir);\n  const promptExists = existsSync(join(promptFolder, expectedFileName));\n  if (promptExists) {\n    return loadPrompt(registry, promptFolder, expectedFileName);\n  } else {\n    throw new GenkitError({\n      source: 'dotprompt',\n      status: 'NOT_FOUND',\n      message: `Could not find '${expectedFileName}' in the prompts folder.`,\n    });\n  }\n}\n\nexport async function loadPromptFolder(\n  registry: Registry,\n  dir: string = './prompts',\n  ns: string\n): Promise<void> {\n  const promptsPath = resolve(dir);\n  return new Promise<void>((resolve, reject) => {\n    if (existsSync(promptsPath)) {\n      readdir(\n        promptsPath,\n        {\n          withFileTypes: true,\n          recursive: true,\n        },\n        (err, dirEnts) => {\n          if (err) {\n            reject(err);\n          } else {\n            dirEnts.forEach(async (dirEnt) => {\n              if (dirEnt.isFile() && dirEnt.name.endsWith('.prompt')) {\n                if (dirEnt.name.startsWith('_')) {\n                  const partialName = dirEnt.name.substring(\n                    1,\n                    dirEnt.name.length - 7\n                  );\n                  definePartial(\n                    partialName,\n                    readFileSync(join(dirEnt.path, dirEnt.name), {\n                      encoding: 'utf8',\n                    })\n                  );\n                  logger.debug(\n                    `Registered Dotprompt partial \"${partialName}\" from \"${join(dirEnt.path, dirEnt.name)}\"`\n                  );\n                } else {\n                  // If this prompt is in a subdirectory, we need to include that\n                  // in the namespace to prevent naming conflicts.\n                  let prefix = '';\n                  if (promptsPath !== dirEnt.path) {\n                    prefix = dirEnt.path\n                      .replace(`${promptsPath}/`, '')\n                      .replace(/\\//g, '-');\n                  }\n                  loadPrompt(registry, dirEnt.path, dirEnt.name, prefix, ns);\n                }\n              }\n            });\n            resolve();\n          }\n        }\n      );\n    } else {\n      resolve();\n    }\n  });\n}\n\nexport function loadPrompt(\n  registry: Registry,\n  path: string,\n  filename: string,\n  prefix = '',\n  ns = 'dotprompt'\n): Dotprompt {\n  let name = `${prefix ? `${prefix}-` : ''}${basename(filename, '.prompt')}`;\n  let variant: string | null = null;\n  if (name.includes('.')) {\n    const parts = name.split('.');\n    name = parts[0];\n    variant = parts[1];\n  }\n  const source = readFileSync(join(path, filename), 'utf8');\n  const prompt = Dotprompt.parse(registry, name, source);\n  if (variant) {\n    prompt.variant = variant;\n  }\n  prompt.define({ ns });\n  return prompt;\n}\n"],"mappings":"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","names":["resolve"]}