{"version":3,"sources":["../../src/formats/index.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 type { JSONSchema } from '@genkit-ai/core';\nimport type { Registry } from '@genkit-ai/core/registry';\nimport type { OutputOptions } from '../generate.js';\nimport type { MessageData, TextPart } from '../model.js';\nimport { arrayFormatter } from './array.js';\nimport { enumFormatter } from './enum.js';\nimport { jsonFormatter } from './json.js';\nimport { jsonlFormatter } from './jsonl.js';\nimport { textFormatter } from './text.js';\nimport type { Formatter } from './types.js';\n\nexport type { Formatter };\n\nexport function defineFormat(\n  registry: Registry,\n  options: { name: string } & Formatter['config'],\n  handler: Formatter['handler']\n): { config: Formatter['config']; handler: Formatter['handler'] } {\n  const { name, ...config } = options;\n  const formatter = { config, handler };\n  registry.registerValue('format', name, formatter);\n  return formatter;\n}\n\nexport type FormatArgument =\n  | keyof typeof DEFAULT_FORMATS\n  | Omit<string, keyof typeof DEFAULT_FORMATS>\n  | undefined\n  | null;\n\nexport async function resolveFormat(\n  registry: Registry,\n  outputOpts: OutputOptions | undefined\n): Promise<Formatter<any, any> | undefined> {\n  if (!outputOpts) return undefined;\n  // If schema is set but no explicit format is set we default to json.\n  if ((outputOpts.jsonSchema || outputOpts.schema) && !outputOpts.format) {\n    return registry.lookupValue<Formatter>('format', 'json');\n  }\n  if (outputOpts.format) {\n    return registry.lookupValue<Formatter>('format', outputOpts.format);\n  }\n  return undefined;\n}\n\nexport function resolveInstructions(\n  format?: Formatter,\n  schema?: JSONSchema,\n  instructionsOption?: boolean | string\n): string | undefined {\n  if (typeof instructionsOption === 'string') return instructionsOption; // user provided instructions\n  if (instructionsOption === false) return undefined; // user says no instructions\n  if (!format) return undefined;\n  return format.handler(schema).instructions;\n}\n\nexport function injectInstructions(\n  messages: MessageData[],\n  instructions: string | false | undefined\n): MessageData[] {\n  if (!instructions) return messages;\n\n  // bail out if a non-pending output part is already present\n  if (\n    messages.find((m) =>\n      m.content.find(\n        (p) => p.metadata?.purpose === 'output' && !p.metadata?.pending\n      )\n    )\n  ) {\n    return messages;\n  }\n\n  const newPart: TextPart = {\n    text: instructions,\n    metadata: { purpose: 'output' },\n  };\n\n  // find the system message or the last user message\n  let targetIndex = messages.findIndex((m) => m.role === 'system');\n  if (targetIndex < 0)\n    targetIndex = messages.map((m) => m.role).lastIndexOf('user');\n  if (targetIndex < 0) return messages;\n\n  const m = {\n    ...messages[targetIndex],\n    content: [...messages[targetIndex].content],\n  };\n\n  const partIndex = m.content.findIndex(\n    (p) => p.metadata?.purpose === 'output' && p.metadata?.pending\n  );\n  if (partIndex > 0) {\n    m.content.splice(partIndex, 1, newPart);\n  } else {\n    m.content.push(newPart);\n  }\n\n  const outMessages = [...messages];\n  outMessages.splice(targetIndex, 1, m);\n  return outMessages;\n}\n\nexport const DEFAULT_FORMATS: Formatter<any, any>[] = [\n  jsonFormatter,\n  arrayFormatter,\n  textFormatter,\n  enumFormatter,\n  jsonlFormatter,\n];\n\n/**\n * configureFormats registers the default built-in formats on a registry.\n */\nexport function configureFormats(registry: Registry) {\n  for (const format of DEFAULT_FORMATS) {\n    defineFormat(\n      registry,\n      { name: format.name, ...format.config },\n      format.handler\n    );\n  }\n}\n"],"mappings":"AAoBA,SAAS,sBAAsB;AAC/B,SAAS,qBAAqB;AAC9B,SAAS,qBAAqB;AAC9B,SAAS,sBAAsB;AAC/B,SAAS,qBAAqB;AAKvB,SAAS,aACd,UACA,SACA,SACgE;AAChE,QAAM,EAAE,MAAM,GAAG,OAAO,IAAI;AAC5B,QAAM,YAAY,EAAE,QAAQ,QAAQ;AACpC,WAAS,cAAc,UAAU,MAAM,SAAS;AAChD,SAAO;AACT;AAQA,eAAsB,cACpB,UACA,YAC0C;AAC1C,MAAI,CAAC,WAAY,QAAO;AAExB,OAAK,WAAW,cAAc,WAAW,WAAW,CAAC,WAAW,QAAQ;AACtE,WAAO,SAAS,YAAuB,UAAU,MAAM;AAAA,EACzD;AACA,MAAI,WAAW,QAAQ;AACrB,WAAO,SAAS,YAAuB,UAAU,WAAW,MAAM;AAAA,EACpE;AACA,SAAO;AACT;AAEO,SAAS,oBACd,QACA,QACA,oBACoB;AACpB,MAAI,OAAO,uBAAuB,SAAU,QAAO;AACnD,MAAI,uBAAuB,MAAO,QAAO;AACzC,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO,OAAO,QAAQ,MAAM,EAAE;AAChC;AAEO,SAAS,mBACd,UACA,cACe;AACf,MAAI,CAAC,aAAc,QAAO;AAG1B,MACE,SAAS;AAAA,IAAK,CAACA,OACbA,GAAE,QAAQ;AAAA,MACR,CAAC,MAAM,EAAE,UAAU,YAAY,YAAY,CAAC,EAAE,UAAU;AAAA,IAC1D;AAAA,EACF,GACA;AACA,WAAO;AAAA,EACT;AAEA,QAAM,UAAoB;AAAA,IACxB,MAAM;AAAA,IACN,UAAU,EAAE,SAAS,SAAS;AAAA,EAChC;AAGA,MAAI,cAAc,SAAS,UAAU,CAACA,OAAMA,GAAE,SAAS,QAAQ;AAC/D,MAAI,cAAc;AAChB,kBAAc,SAAS,IAAI,CAACA,OAAMA,GAAE,IAAI,EAAE,YAAY,MAAM;AAC9D,MAAI,cAAc,EAAG,QAAO;AAE5B,QAAM,IAAI;AAAA,IACR,GAAG,SAAS,WAAW;AAAA,IACvB,SAAS,CAAC,GAAG,SAAS,WAAW,EAAE,OAAO;AAAA,EAC5C;AAEA,QAAM,YAAY,EAAE,QAAQ;AAAA,IAC1B,CAAC,MAAM,EAAE,UAAU,YAAY,YAAY,EAAE,UAAU;AAAA,EACzD;AACA,MAAI,YAAY,GAAG;AACjB,MAAE,QAAQ,OAAO,WAAW,GAAG,OAAO;AAAA,EACxC,OAAO;AACL,MAAE,QAAQ,KAAK,OAAO;AAAA,EACxB;AAEA,QAAM,cAAc,CAAC,GAAG,QAAQ;AAChC,cAAY,OAAO,aAAa,GAAG,CAAC;AACpC,SAAO;AACT;AAEO,MAAM,kBAAyC;AAAA,EACpD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAKO,SAAS,iBAAiB,UAAoB;AACnD,aAAW,UAAU,iBAAiB;AACpC;AAAA,MACE;AAAA,MACA,EAAE,MAAM,OAAO,MAAM,GAAG,OAAO,OAAO;AAAA,MACtC,OAAO;AAAA,IACT;AAAA,EACF;AACF;","names":["m"]}