{"version":3,"file":"index.mjs","sources":["../../server/src/bootstrap.ts","../../server/src/destroy.ts","../../server/src/register.ts","../../server/src/config/constants.ts","../../server/src/config/index.ts","../../server/src/content-types/index.ts","../../server/src/controllers/admin.controller.ts","../../server/src/controllers/index.ts","../../server/src/middlewares/index.ts","../../server/src/policies/index.ts","../../server/src/routes/admin.ts","../../server/src/routes/index.ts","../../server/src/utils/json-utils.ts","../../server/src/services/llm-service.ts","../../server/src/services/index.ts","../../server/src/index.ts"],"sourcesContent":["import type { Core } from '@strapi/strapi';\n\nconst bootstrap = ({ strapi }: { strapi: Core.Strapi }) => {\n  // bootstrap phase\n};\n\nexport default bootstrap;\n","import type { Core } from '@strapi/strapi';\n\nconst destroy = ({ strapi }: { strapi: Core.Strapi }) => {\n  // destroy phase\n};\n\nexport default destroy;\n","import type { Core } from '@strapi/strapi';\n\nconst register = ({ strapi }: { strapi: Core.Strapi }) => {\n  // register phase\n};\n\nexport default register;\n","// Translator Prompts\nexport const DEFAULT_SYSTEM_PROMPT =\n  'You are a professional translator. Your task is to translate the provided content accurately while preserving the original meaning and tone.';\nexport const SYSTEM_PROMPT_APPENDIX = `The user asks you to translate the text to a specific language, the language is provided via short code like \"en\", \"fr\", \"de\", etc.`;\n\n// Default LLM Settings\nexport const DEFAULT_LLM_TEMPERATURE = 0.3;\nexport const DEFAULT_LLM_MODEL = 'gpt-4o';\nexport const DEFAULT_LLM_BASE_URL = 'https://api.openai.com/v1';\n\n// Fix JSON Prompts\nexport const SYSTEM_PROMPT_FIX = `You are a JSON correction assistant. Only return valid, corrected JSON.`;\nexport const USER_PROMPT_FIX_PREFIX =\n  'Fix this invalid JSON and return ONLY the corrected JSON. No explanations allowed. The JSON is:';\n","import { DEFAULT_LLM_BASE_URL, DEFAULT_LLM_MODEL } from './constants';\n\nexport default {\n  default: ({ env }) => ({\n    llmApiKey: env('LLM_TRANSLATOR_LLM_API_KEY'),\n    llmEndpoint: env('STRAPI_ADMIN_LLM_TRANSLATOR_LLM_BASE_URL'),\n    llmModel: env('STRAPI_ADMIN_LLM_TRANSLATOR_LLM_MODEL'),\n    llmAzureApiVersion: env('STRAPI_ADMIN_LLM_TRANSLATOR_AZURE_API_VERSION'),\n  }),\n  validator(config) {\n    const PLUGIN_NAME = 'Strapi LLM Translator';\n    console.info(`\\n==== ${PLUGIN_NAME} Configuration Validation ====`);\n\n    // Validate API Key\n    if (!config?.llmApiKey) {\n      console.warn('⚠️  LLM API Key: Missing');\n      console.info('   → Translation features requiring API keys will be disabled');\n    } else {\n      console.info('✅ LLM API Key: Configured');\n    }\n\n    // Validate API Endpoint\n    const endpoint = config?.llmEndpoint || DEFAULT_LLM_BASE_URL;\n    if (!config?.llmEndpoint) {\n      console.warn(`⚠️  API Endpoint: Using default (${DEFAULT_LLM_BASE_URL})`);\n    } else {\n      console.info(`✅ API Endpoint: Configured (${endpoint})`);\n    }\n\n    // Validate LLM Model\n    const model = config?.llmModel || DEFAULT_LLM_MODEL;\n    if (!config?.llmModel) {\n      console.warn(`⚠️  LLM Model: Using default (${DEFAULT_LLM_MODEL})`);\n    } else {\n      console.info(`✅ LLM Model: Configured (${model})`);\n    }\n\n    // Validate LLM Azure API Version\n    const apiVersion = config?.llmAzureApiVersion;\n    if (!config?.llmAzureApiVersion) {\n      console.info(`✅ Using default OpenAI => no API Version configured`);\n      console.warn(\n        `⚠️  LLM Azure API Version : If you wish to use Azure OpenAI, please configure an API Version`\n      );\n    } else {\n      console.info(`✅ Using Azure OpenAI`);\n      console.info(`✅ LLM Azure API Version : Configured (${apiVersion})`);\n    }\n\n    console.info('========================================================\\n');\n  },\n};\n","export default {};\n","import { GenerateRequestBody, PluginUserConfig, RequestContext, StrapiContext } from 'src/types';\n\nconst controllers = ({ strapi }: StrapiContext) => ({\n  // Genertate translations\n  async generate(ctx: RequestContext & { request: { body: GenerateRequestBody } }) {\n    try {\n      const { fields, components, targetLanguage, contentType } = ctx.request.body;\n      const result = await strapi\n        .plugin('strapi-llm-translator')\n        .service('llm-service')\n        .generateWithLLM(contentType, fields, components, {\n          targetLanguage,\n        });\n\n      ctx.status = result.meta.status;\n      ctx.body = result;\n    } catch (error) {\n      console.error('Error in generate controller:', error);\n      ctx.status = 500;\n      ctx.body = {\n        meta: {\n          ok: false,\n          status: 500,\n          message: 'Internal server error',\n        },\n      };\n    }\n  },\n\n  // Get the configuration\n  async getConfig(ctx: RequestContext) {\n    const pluginStore = strapi.store({\n      environment: strapi.config.environment,\n      type: 'plugin',\n      name: 'strapi-llm-translator', // replace with your plugin name\n    });\n\n    const config = await pluginStore.get({ key: 'configuration' });\n    ctx.body = (config as PluginUserConfig) || {}; // Return empty object if no config exists yet\n  },\n\n  // Save the configuration\n  async setConfig(ctx: RequestContext) {\n    const { body } = ctx.request;\n\n    // Optional: Add validation for your configuration here\n    const pluginStore = strapi.store({\n      environment: strapi.config.environment,\n      type: 'plugin',\n      name: 'strapi-llm-translator', // replace with your plugin name\n    });\n\n    await pluginStore.set({\n      key: 'configuration',\n      value: { ...body },\n    });\n\n    ctx.body = (await pluginStore.get({ key: 'configuration' })) as PluginUserConfig;\n  },\n});\n\nexport default controllers;\n","import adminController from './admin.controller';\n\nexport default {\n  admin: adminController,\n};\n","export default {};\n","export default {};\n","export default [\n  {\n    method: 'POST',\n    path: '/generate',\n    handler: 'admin.generate',\n    config: {\n      policies: [],\n    },\n  },\n  {\n    method: 'GET',\n    path: '/config',\n    handler: 'admin.getConfig',\n    config: {\n      policies: [],\n    },\n  },\n  {\n    method: 'POST',\n    path: '/config',\n    handler: 'admin.setConfig',\n    config: {\n      policies: [],\n    },\n  },\n];\n","import adminRoutes from './admin';\n\nconst routes = {\n  admin: {\n    type: 'admin',\n    routes: adminRoutes,\n  },\n};\n\nexport default routes;\n","export const cleanJSONString = (content: string): string => {\n  return content\n    .replace(/^```json\\s*\\n/, '')\n    .replace(/^```\\s*\\n/, '')\n    .replace(/\\n\\s*```$/, '')\n    .replace(/\\u200B/g, '')\n    .replace(/[\\u2018\\u2019]/g, \"'\")\n    .replace(/[\\u201C\\u201D]/g, '\"')\n    .trim();\n};\n\nexport const balanceJSONBraces = (content: string): string => {\n   let openBraces = 0;\n  let closeBraces = 0;\n  let inString = false;\n\n  for (let i = 0; i < content.length; i += 1) {\n    const char = content[i];\n    if (char === '\"' && content[i - 1] !== '\\\\') {\n      inString = !inString;\n    }\n\n    if (!inString) {\n      if (char === '{') openBraces += 1;\n      if (char === '}') closeBraces += 1;\n    }\n  }\n\n  if (openBraces > closeBraces) {\n    return content + '}'.repeat(openBraces - closeBraces);\n  }\n  return content;\n};\n\nexport const extractJSONObject = (content: string): string => {\n  const firstBrace = content.indexOf('{');\n  const lastBrace = content.lastIndexOf('}');\n  if (firstBrace !== -1 && lastBrace !== -1 && lastBrace > firstBrace) {\n    return content.slice(firstBrace, lastBrace + 1);\n  }\n  return content;\n};\n\nexport const safeJSONParse = (content: string): Record<string, any> => {\n  const parsed = JSON.parse(content);\n  if (typeof parsed === 'object' && parsed !== null) {\n    return parsed;\n  }\n  throw new Error('Invalid response format - not an object');\n};","import type { Core } from '@strapi/strapi';\nimport { OpenAI, AzureOpenAI } from 'openai';\n\nimport {\n  LLMServiceType,\n  PluginUserConfig,\n  TranslatableField,\n  TranslationConfig,\n  TranslationResponse,\n  UIDField,\n} from '../../src/types';\nimport {\n  DEFAULT_LLM_BASE_URL,\n  DEFAULT_LLM_MODEL,\n  DEFAULT_LLM_TEMPERATURE,\n  DEFAULT_SYSTEM_PROMPT,\n  SYSTEM_PROMPT_APPENDIX,\n  SYSTEM_PROMPT_FIX,\n  USER_PROMPT_FIX_PREFIX,\n} from '../config/constants';\nimport {\n  balanceJSONBraces,\n  cleanJSONString,\n  extractJSONObject,\n  safeJSONParse,\n} from '../utils/json-utils';\n\nconst llmClient = process.env.STRAPI_ADMIN_LLM_TRANSLATOR_AZURE_API_VERSION\n  ? new AzureOpenAI({\n      baseURL: process.env.STRAPI_ADMIN_LLM_TRANSLATOR_LLM_BASE_URL ?? DEFAULT_LLM_BASE_URL,\n      apiKey: process.env.LLM_TRANSLATOR_LLM_API_KEY ?? 'not_set',\n      apiVersion: process.env.STRAPI_ADMIN_LLM_TRANSLATOR_AZURE_API_VERSION,\n    })\n  : new OpenAI({\n      baseURL: process.env.STRAPI_ADMIN_LLM_TRANSLATOR_LLM_BASE_URL ?? DEFAULT_LLM_BASE_URL,\n      apiKey: process.env.LLM_TRANSLATOR_LLM_API_KEY ?? 'not_set',\n    });\n\nconst LLM_MODEL = process.env.STRAPI_ADMIN_LLM_TRANSLATOR_LLM_MODEL ?? DEFAULT_LLM_MODEL;\n\nconst BATCH_SIZE = 10; // TODO\n\n// helper to merge batches safely\nconst deepMerge = (target: any, source: any): any => {\n  const output = { ...target };\n  for (const key in source) {\n    const sourceValue = source[key];\n    const targetValue = target[key];\n\n    if (\n      sourceValue instanceof Object &&\n      !Array.isArray(sourceValue) &&\n      targetValue instanceof Object &&\n      !Array.isArray(targetValue)\n    ) {\n      output[key] = deepMerge(targetValue, sourceValue);\n    } else {\n      output[key] = sourceValue;\n    }\n  }\n  return output;\n};\n\nconst extractTranslatableFields = (\n  contentType: Record<string, any>,\n  fields: Record<string, any>,\n  components: Record<string, any> = {}\n): TranslatableField[] => {\n  const translatableFields: TranslatableField[] = [];\n\n  const isTranslatableFieldSchema = (\n    schema: Record<string, any> | undefined,\n    value: any\n  ): boolean => {\n    if (!schema) {\n      return false;\n    }\n\n    const { type } = schema;\n\n    const isStringType = ['string', 'text'].includes(type) && typeof value === 'string';\n\n    const isRichTextType =\n      ['richtext', 'richText', 'blocks'].includes(type) &&\n      (typeof value === 'string' || typeof value === 'object');\n\n    const isJSONType = type === 'json' && typeof value === 'object';\n    const isNotUID = type !== 'uid';\n    const isLocalizable = schema.pluginOptions?.i18n?.localized !== false;\n\n    return (isStringType || isRichTextType || isJSONType) && isNotUID && isLocalizable;\n  };\n\n  const traverse = (\n    schema: Record<string, any>,\n    data: Record<string, any>,\n    path: string[] = [],\n    originalPath: string[] = []\n  ) => {\n    Object.entries(schema.attributes || {}).forEach(([fieldName, fieldSchemaRaw]) => {\n      const fieldSchema = fieldSchemaRaw as Record<string, any>;\n      const value = data?.[fieldName];\n      if (value === undefined || value === null) {\n        return;\n      }\n\n      if (isTranslatableFieldSchema(fieldSchema, value)) {\n        translatableFields.push({\n          path: [...path, fieldName],\n          value,\n          originalPath: [...originalPath, fieldName],\n        });\n        return;\n      }\n\n      if (fieldSchema.type === 'component') {\n        const componentSchema = components[fieldSchema.component];\n        if (!componentSchema) return;\n\n        if (fieldSchema.repeatable && Array.isArray(value)) {\n          value.forEach((item: any, index: number) =>\n            traverse(\n              componentSchema,\n              item,\n              [...path, fieldName, String(index)],\n              [...originalPath, fieldName, String(index)]\n            )\n          );\n        } else if (typeof value === 'object') {\n          traverse(componentSchema, value, [...path, fieldName], [...originalPath, fieldName]);\n        }\n      } else if (fieldSchema.type === 'dynamiczone' && Array.isArray(value)) {\n        value.forEach((item: any, index: number) => {\n          const compSchema = components[item.__component];\n          if (compSchema) {\n            traverse(\n              compSchema,\n              item,\n              [...path, fieldName, String(index)],\n              [...originalPath, fieldName, String(index)]\n            );\n          }\n        });\n      }\n    });\n  };\n\n  traverse(contentType, fields, [], []);\n\n  return translatableFields;\n};\n\nconst prepareTranslationPayload = (fields: TranslatableField[]): Record<string, any> => {\n  const payload: Record<string, any> = {};\n\n  fields.forEach((field) => {\n    let current = payload;\n    field.path.forEach((part, index) => {\n      if (index === field.path.length - 1) {\n        current[part] = field.value;\n      } else {\n        current[part] = current[part] || {};\n        current = current[part];\n      }\n    });\n  });\n\n  return payload;\n};\n\nconst mergeTranslatedContent = (\n  originalData: Record<string, any>,\n  translatedData: Record<string, any>,\n  translatableFields: TranslatableField[]\n): Record<string, any> => {\n  const result = JSON.parse(JSON.stringify(originalData));\n\n  translatableFields.forEach((field) => {\n    let translatedValue = translatedData;\n    for (const part of field.path) {\n      translatedValue = translatedValue?.[part];\n      if (translatedValue === undefined) break;\n    }\n\n    if (translatedValue !== undefined) {\n      let current = result;\n      field.originalPath.forEach((part, index) => {\n        if (index === field.originalPath.length - 1) {\n          current[part] = translatedValue;\n        } else {\n          current = current[part];\n        }\n      });\n    }\n  });\n\n  return result;\n};\n\nconst generateSlug = async (\n  data: Record<string, any>,\n  field: string,\n  contentTypeUID: string\n): Promise<string> => {\n  // Get the UID service\n  const uidService = strapi.service('plugin::content-manager.uid');\n\n  // Generate a unique UID based on the title field\n  const slug = await uidService.generateUIDField({\n    contentTypeUID,\n    field,\n    data,\n  });\n\n  return slug;\n};\n\nconst findUIDFields = (contentType: Record<string, any>): UIDField[] => {\n  const uidFields: UIDField[] = [];\n\n  Object.entries(contentType.attributes || {}).forEach(([fieldName, schema]: [string, any]) => {\n    if (schema.type === 'uid' && schema.targetField) {\n      uidFields.push({\n        fieldName,\n        targetField: schema.targetField,\n      });\n    }\n  });\n\n  return uidFields;\n};\n\nconst generateUIDsForTranslatedFields = async (\n  uidFields: UIDField[],\n  translatedData: Record<string, any>,\n  contentTypeUID: string,\n  mergedContent: Record<string, any>\n): Promise<Record<string, any>> => {\n  const translatedUIDs: Record<string, any> = {};\n\n  for (const { fieldName, targetField } of uidFields) {\n    // Only generate new UID if the target field was translated\n    if (translatedData[targetField] !== undefined) {\n      try {\n        const newUID = await generateSlug(\n          {\n            ...mergedContent,\n            [targetField]: translatedData[targetField],\n          },\n          fieldName,\n          contentTypeUID\n        );\n        translatedUIDs[fieldName] = newUID;\n      } catch (error) {\n        console.error(`Failed to generate UID for field ${fieldName}:`, error);\n      }\n    }\n  }\n\n  return translatedUIDs;\n};\n\nconst llmService = ({ strapi }: { strapi: Core.Strapi }): LLMServiceType => ({\n  async generateWithLLM(\n    contentType: Record<string, any>,\n    fields: Record<string, any>,\n    components: Record<string, any>,\n    config: TranslationConfig\n  ): Promise<TranslationResponse> {\n    try {\n      const userConfig = await getUserConfig();\n\n      const translatableFields = extractTranslatableFields(contentType, fields, components);\n\n      // Split translatableFields in batches\n      const batches: TranslatableField[][] = [];\n      for (let i = 0; i < translatableFields.length; i += BATCH_SIZE) {\n        batches.push(translatableFields.slice(i, i + BATCH_SIZE));\n      }\n\n      const systemPrompt = await buildSystemPrompt(userConfig);\n\n      // Process all batches parallel\n      const translatedResults = await Promise.all(\n        batches.map(async (batch) => {\n          const translationPayload = prepareTranslationPayload(batch);\n          const prompt = buildPrompt(translationPayload, config.targetLanguage);\n          const response = await callLLMProvider(prompt, systemPrompt, userConfig);\n          return await parseLLMResponse(response);\n        })\n      );\n\n      // Merge translated batch results into one object\n      const translatedData = translatedResults.reduce((acc, curr) => {\n        return deepMerge(acc, curr);\n      }, {});\n\n      // Merge original content payload with translation\n      const mergedContent = mergeTranslatedContent(fields, translatedData, translatableFields);\n\n      // Handle UID fields as they might have a relation base to another translated field\n      const uidFields = findUIDFields(contentType);\n      const translatedUIDs = await generateUIDsForTranslatedFields(\n        uidFields,\n        translatedData,\n        contentType.uid,\n        mergedContent\n      );\n\n      return {\n        data: {\n          ...mergedContent,\n          ...translatedUIDs,\n        },\n        meta: {\n          ok: true,\n          status: 200,\n          message: 'Translation completed successfully',\n        },\n      };\n    } catch (error) {\n      strapi.log.error('LLM translation error:', error);\n      return {\n        data: fields, // Return original fields in case of error\n        meta: {\n          ok: false,\n          status: 500,\n          message: error instanceof Error ? error.message : 'Translation failed',\n        },\n      };\n    }\n  },\n});\n\nconst buildPrompt = (fields: Record<string, any>, targetLanguage: string): string => {\n  return `You are translating content from a CMS. Please translate the following JSON data to ${targetLanguage}.\n\nIMPORTANT RULES:\n1. Preserve all JSON structure and keys exactly as provided\n2. Only translate string values\n3. Maintain any markdown formatting within the text\n4. Keep HTML tags intact if present\n5. Preserve any special characters or placeholders\n6. Return ONLY the translated JSON object\n7. Ensure the JSON is valid and well-formed. Keep arrays and nested objects intact\n8. Do not add any explanations or comments\n9. Ensure professional and culturally appropriate translations\n\nSOURCE JSON:\n${JSON.stringify(fields, null, 2)}`;\n};\n\nconst getUserConfig = async (): Promise<PluginUserConfig> => {\n  // Get configuration from plugin store\n  const pluginStore = strapi.store({\n    environment: strapi.config.environment,\n    type: 'plugin',\n    name: 'strapi-llm-translator',\n  });\n\n  const config = (await pluginStore.get({ key: 'configuration' })) as PluginUserConfig;\n\n  return config;\n};\n\nconst buildSystemPrompt = async (userConfig: PluginUserConfig): Promise<string> => {\n  return `${userConfig?.systemPrompt || DEFAULT_SYSTEM_PROMPT} ${SYSTEM_PROMPT_APPENDIX}`;\n};\n\nconst createLLMRequest = (\n  messages: Array<{ role: 'system' | 'user' | 'assistant'; content: string }>,\n  temperature = 0.1\n) => {\n  return llmClient.chat.completions.create({\n    model: LLM_MODEL,\n    messages,\n    temperature,\n    response_format: { type: 'json_object' },\n  });\n};\n\nconst callLLMProvider = async (\n  prompt: string,\n  systemPrompt: string,\n  userConfig: PluginUserConfig\n): Promise<any> => {\n  return createLLMRequest(\n    [\n      {\n        role: 'system',\n        content: systemPrompt,\n      },\n      {\n        role: 'user',\n        content: prompt,\n      },\n    ],\n    userConfig?.temperature ?? DEFAULT_LLM_TEMPERATURE\n  );\n};\n\nconst requestJSONCorrection = async (invalidJson: string): Promise<Record<string, any>> => {\n  const response = await createLLMRequest([\n    {\n      role: 'system',\n      content: SYSTEM_PROMPT_FIX,\n    },\n    {\n      role: 'user',\n      content: `${USER_PROMPT_FIX_PREFIX} ${invalidJson}`,\n    },\n  ]);\n\n  const correctedContent = response.choices[0]?.message?.content;\n  if (!correctedContent) throw new Error('No content in correction response');\n\n  return safeJSONParse(correctedContent.trim());\n};\n\nconst parseLLMResponse = async (response: any): Promise<Record<string, any>> => {\n  try {\n    const content = response.choices[0]?.message?.content;\n    if (!content) throw new Error('No content in response');\n\n    const cleanContent = cleanJSONString(content);\n    const jsonContent = extractJSONObject(cleanContent);\n\n    try {\n      return safeJSONParse(jsonContent);\n    } catch (parseError) {\n      const balancedContent = balanceJSONBraces(jsonContent);\n\n      try {\n        return safeJSONParse(balancedContent);\n      } catch (secondError) {\n        console.error('Second parse attempt failed:', secondError);\n        return await requestJSONCorrection(cleanContent);\n      }\n    }\n  } catch (error) {\n    const errorMessage = error instanceof Error ? error.message : 'Unknown error';\n    throw new Error(`Translation failed: ${errorMessage}`);\n  }\n};\n\nexport default llmService;\n","import service from './llm-service';\n\nexport default {\n  'llm-service': service,\n};\n","/**\n * Application methods\n */\nimport bootstrap from './bootstrap';\nimport destroy from './destroy';\nimport register from './register';\n\n/**\n * Plugin server methods\n */\nimport config from './config';\nimport contentTypes from './content-types';\nimport controllers from './controllers';\nimport middlewares from './middlewares';\nimport policies from './policies';\nimport routes from './routes';\nimport services from './services';\n\nexport default {\n  register,\n  bootstrap,\n  destroy,\n  config,\n  controllers,\n  routes,\n  services,\n  contentTypes,\n  policies,\n  middlewares,\n};\n"],"names":["strapi","config","controllers","adminController","index","service"],"mappings":"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"}