{"version":3,"file":"chat_models.cjs","names":["SimpleChatModel","convertEventStreamToIterableReadableDataStream","convertCloudflareStream","ChatGenerationChunk","AIMessageChunk","ChatMessage"],"sources":["../src/chat_models.ts"],"sourcesContent":["import {\n  LangSmithParams,\n  SimpleChatModel,\n  type BaseChatModelParams,\n} from \"@langchain/core/language_models/chat_models\";\nimport type { BaseLanguageModelCallOptions } from \"@langchain/core/language_models/base\";\nimport {\n  AIMessageChunk,\n  BaseMessage,\n  ChatMessage,\n} from \"@langchain/core/messages\";\nimport { ChatGenerationChunk } from \"@langchain/core/outputs\";\nimport { getEnvironmentVariable } from \"@langchain/core/utils/env\";\nimport { CallbackManagerForLLMRun } from \"@langchain/core/callbacks/manager\";\nimport type { ChatModelStreamEvent } from \"@langchain/core/language_models/event\";\nimport { convertCloudflareStream } from \"./utils/stream_events.js\";\n\nimport type { CloudflareWorkersAIInput } from \"./llms.js\";\nimport { convertEventStreamToIterableReadableDataStream } from \"./utils/event_source_parse.js\";\n\n/**\n * An interface defining the options for a Cloudflare Workers AI call. It extends\n * the BaseLanguageModelCallOptions interface.\n */\nexport interface ChatCloudflareWorkersAICallOptions extends BaseLanguageModelCallOptions {}\n\n/**\n * A class that enables calls to the Cloudflare Workers AI API to access large language\n * models in a chat-like fashion. It extends the SimpleChatModel class and\n * implements the CloudflareWorkersAIInput interface.\n * @example\n * ```typescript\n * const model = new ChatCloudflareWorkersAI({\n *   model: \"@cf/meta/llama-2-7b-chat-int8\",\n *   cloudflareAccountId: process.env.CLOUDFLARE_ACCOUNT_ID,\n *   cloudflareApiToken: process.env.CLOUDFLARE_API_TOKEN\n * });\n *\n * const response = await model.invoke([\n *   [\"system\", \"You are a helpful assistant that translates English to German.\"],\n *   [\"human\", `Translate \"I love programming\".`]\n * ]);\n *\n * console.log(response);\n * ```\n */\nexport class ChatCloudflareWorkersAI\n  extends SimpleChatModel\n  implements CloudflareWorkersAIInput\n{\n  static lc_name() {\n    return \"ChatCloudflareWorkersAI\";\n  }\n\n  lc_serializable = true;\n\n  model = \"@cf/meta/llama-2-7b-chat-int8\";\n\n  cloudflareAccountId?: string;\n\n  cloudflareApiToken?: string;\n\n  baseUrl: string;\n\n  streaming = false;\n\n  constructor(\n    model: string,\n    params?: Omit<CloudflareWorkersAIInput & BaseChatModelParams, \"model\">\n  );\n  constructor(fields?: CloudflareWorkersAIInput & BaseChatModelParams);\n  constructor(\n    modelOrFields?: string | (CloudflareWorkersAIInput & BaseChatModelParams),\n    paramsArg?: Omit<CloudflareWorkersAIInput & BaseChatModelParams, \"model\">\n  ) {\n    const fields =\n      typeof modelOrFields === \"string\"\n        ? { ...(paramsArg ?? {}), model: modelOrFields }\n        : (modelOrFields ?? {});\n    super(fields);\n    this._addVersion(\"@langchain/cloudflare\", __PKG_VERSION__);\n\n    this.model = fields.model ?? this.model;\n    this.streaming = fields.streaming ?? this.streaming;\n    this.cloudflareAccountId =\n      fields.cloudflareAccountId ??\n      getEnvironmentVariable(\"CLOUDFLARE_ACCOUNT_ID\");\n    this.cloudflareApiToken =\n      fields.cloudflareApiToken ??\n      getEnvironmentVariable(\"CLOUDFLARE_API_TOKEN\");\n    this.baseUrl =\n      fields.baseUrl ??\n      `https://api.cloudflare.com/client/v4/accounts/${this.cloudflareAccountId}/ai/run`;\n    if (this.baseUrl.endsWith(\"/\")) {\n      this.baseUrl = this.baseUrl.slice(0, -1);\n    }\n  }\n\n  getLsParams(options: this[\"ParsedCallOptions\"]): LangSmithParams {\n    return {\n      ls_provider: \"cloudflare\",\n      ls_model_name: this.model,\n      ls_model_type: \"chat\",\n      ls_stop: options.stop,\n    };\n  }\n\n  get lc_secrets(): { [key: string]: string } | undefined {\n    return {\n      cloudflareApiToken: \"CLOUDFLARE_API_TOKEN\",\n    };\n  }\n\n  _llmType() {\n    return \"cloudflare\";\n  }\n\n  /** Get the identifying parameters for this LLM. */\n  get identifyingParams() {\n    return { model: this.model };\n  }\n\n  /**\n   * Get the parameters used to invoke the model\n   */\n  invocationParams(_options?: this[\"ParsedCallOptions\"]) {\n    return {\n      model: this.model,\n    };\n  }\n\n  _combineLLMOutput() {\n    return {};\n  }\n\n  /**\n   * Method to validate the environment.\n   */\n  validateEnvironment() {\n    if (!this.cloudflareAccountId) {\n      throw new Error(\n        `No Cloudflare account ID found. Please provide it when instantiating the CloudflareWorkersAI class, or set it as \"CLOUDFLARE_ACCOUNT_ID\" in your environment variables.`\n      );\n    }\n    if (!this.cloudflareApiToken) {\n      throw new Error(\n        `No Cloudflare API key found. Please provide it when instantiating the CloudflareWorkersAI class, or set it as \"CLOUDFLARE_API_KEY\" in your environment variables.`\n      );\n    }\n  }\n\n  async _request(\n    messages: BaseMessage[],\n    options: this[\"ParsedCallOptions\"],\n    stream?: boolean\n  ) {\n    this.validateEnvironment();\n    const url = `${this.baseUrl}/${this.model}`;\n    const headers = {\n      Authorization: `Bearer ${this.cloudflareApiToken}`,\n      \"Content-Type\": \"application/json\",\n    };\n\n    const formattedMessages = this._formatMessages(messages);\n\n    const data = { messages: formattedMessages, stream };\n    return this.caller.call(async () => {\n      const response = await fetch(url, {\n        method: \"POST\",\n        headers,\n        body: JSON.stringify(data),\n        signal: options.signal,\n      });\n      if (!response.ok) {\n        const error = new Error(\n          `Cloudflare LLM call failed with status code ${response.status}`\n        );\n        // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n        (error as any).response = response;\n        throw error;\n      }\n      return response;\n    });\n  }\n\n  async *_streamChatModelEvents(\n    messages: BaseMessage[],\n    options: this[\"ParsedCallOptions\"],\n    _runManager?: CallbackManagerForLLMRun\n  ): AsyncGenerator<ChatModelStreamEvent> {\n    const response = await this._request(messages, options, true);\n    if (!response.body) {\n      throw new Error(\"Empty response from Cloudflare. Please try again.\");\n    }\n    const byteStream = convertEventStreamToIterableReadableDataStream(\n      response.body\n    );\n    async function* parseChunks(\n      source: AsyncIterable<string>,\n      signal?: AbortSignal\n    ) {\n      for await (const chunk of source) {\n        if (signal?.aborted) {\n          return;\n        }\n        if (chunk !== \"[DONE]\") {\n          yield JSON.parse(chunk) as { response?: string };\n        }\n      }\n    }\n    yield* convertCloudflareStream(parseChunks(byteStream, options.signal));\n  }\n\n  async *_streamResponseChunks(\n    messages: BaseMessage[],\n    options: this[\"ParsedCallOptions\"],\n    runManager?: CallbackManagerForLLMRun\n  ): AsyncGenerator<ChatGenerationChunk> {\n    const response = await this._request(messages, options, true);\n    if (!response.body) {\n      throw new Error(\"Empty response from Cloudflare. Please try again.\");\n    }\n    const stream = convertEventStreamToIterableReadableDataStream(\n      response.body\n    );\n    for await (const chunk of stream) {\n      if (options.signal?.aborted) {\n        return;\n      }\n      if (chunk !== \"[DONE]\") {\n        const parsedChunk = JSON.parse(chunk);\n        const generationChunk = new ChatGenerationChunk({\n          message: new AIMessageChunk({ content: parsedChunk.response }),\n          text: parsedChunk.response,\n        });\n        yield generationChunk;\n        // oxlint-disable-next-line no-void\n        void runManager?.handleLLMNewToken(generationChunk.text ?? \"\");\n      }\n    }\n  }\n\n  protected _formatMessages(\n    messages: BaseMessage[]\n  ): { role: string; content: string }[] {\n    const formattedMessages = messages.map((message) => {\n      let role;\n      if (message._getType() === \"human\") {\n        role = \"user\";\n      } else if (message._getType() === \"ai\") {\n        role = \"assistant\";\n      } else if (message._getType() === \"system\") {\n        role = \"system\";\n      } else if (ChatMessage.isInstance(message)) {\n        role = message.role;\n      } else {\n        console.warn(\n          `Unsupported message type passed to Cloudflare: \"${message._getType()}\"`\n        );\n        role = \"user\";\n      }\n      if (typeof message.content !== \"string\") {\n        throw new Error(\n          \"ChatCloudflareWorkersAI currently does not support non-string message content.\"\n        );\n      }\n      return {\n        role,\n        content: message.content,\n      };\n    });\n    return formattedMessages;\n  }\n\n  /** @ignore */\n  async _call(\n    messages: BaseMessage[],\n    options: this[\"ParsedCallOptions\"],\n    runManager?: CallbackManagerForLLMRun\n  ): Promise<string> {\n    options.signal?.throwIfAborted();\n    if (!this.streaming) {\n      const response = await this._request(messages, options);\n\n      const responseData = await response.json();\n\n      return responseData.result.response;\n    } else {\n      const stream = this._streamResponseChunks(messages, options, runManager);\n      let finalResult: ChatGenerationChunk | undefined;\n      for await (const chunk of stream) {\n        if (finalResult === undefined) {\n          finalResult = chunk;\n        } else {\n          finalResult = finalResult.concat(chunk);\n        }\n      }\n      const messageContent = finalResult?.message.content;\n      if (messageContent && typeof messageContent !== \"string\") {\n        throw new Error(\n          \"Non-string output for ChatCloudflareWorkersAI is currently not supported.\"\n        );\n      }\n      return messageContent ?? \"\";\n    }\n  }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8CA,IAAa,0BAAb,cACUA,4CAAAA,gBAEV;CACE,OAAO,UAAU;AACf,SAAO;;CAGT,kBAAkB;CAElB,QAAQ;CAER;CAEA;CAEA;CAEA,YAAY;CAOZ,YACE,eACA,WACA;EACA,MAAM,SACJ,OAAO,kBAAkB,WACrB;GAAE,GAAI,aAAa,EAAE;GAAG,OAAO;GAAe,GAC7C,iBAAiB,EAAE;AAC1B,QAAM,OAAO;AACb,OAAK,YAAY,yBAAA,QAAyC;AAE1D,OAAK,QAAQ,OAAO,SAAS,KAAK;AAClC,OAAK,YAAY,OAAO,aAAa,KAAK;AAC1C,OAAK,sBACH,OAAO,wBAAA,GAAA,0BAAA,wBACgB,wBAAwB;AACjD,OAAK,qBACH,OAAO,uBAAA,GAAA,0BAAA,wBACgB,uBAAuB;AAChD,OAAK,UACH,OAAO,WACP,iDAAiD,KAAK,oBAAoB;AAC5E,MAAI,KAAK,QAAQ,SAAS,IAAI,CAC5B,MAAK,UAAU,KAAK,QAAQ,MAAM,GAAG,GAAG;;CAI5C,YAAY,SAAqD;AAC/D,SAAO;GACL,aAAa;GACb,eAAe,KAAK;GACpB,eAAe;GACf,SAAS,QAAQ;GAClB;;CAGH,IAAI,aAAoD;AACtD,SAAO,EACL,oBAAoB,wBACrB;;CAGH,WAAW;AACT,SAAO;;;CAIT,IAAI,oBAAoB;AACtB,SAAO,EAAE,OAAO,KAAK,OAAO;;;;;CAM9B,iBAAiB,UAAsC;AACrD,SAAO,EACL,OAAO,KAAK,OACb;;CAGH,oBAAoB;AAClB,SAAO,EAAE;;;;;CAMX,sBAAsB;AACpB,MAAI,CAAC,KAAK,oBACR,OAAM,IAAI,MACR,0KACD;AAEH,MAAI,CAAC,KAAK,mBACR,OAAM,IAAI,MACR,oKACD;;CAIL,MAAM,SACJ,UACA,SACA,QACA;AACA,OAAK,qBAAqB;EAC1B,MAAM,MAAM,GAAG,KAAK,QAAQ,GAAG,KAAK;EACpC,MAAM,UAAU;GACd,eAAe,UAAU,KAAK;GAC9B,gBAAgB;GACjB;EAID,MAAM,OAAO;GAAE,UAFW,KAAK,gBAAgB,SAEL;GAAE;GAAQ;AACpD,SAAO,KAAK,OAAO,KAAK,YAAY;GAClC,MAAM,WAAW,MAAM,MAAM,KAAK;IAChC,QAAQ;IACR;IACA,MAAM,KAAK,UAAU,KAAK;IAC1B,QAAQ,QAAQ;IACjB,CAAC;AACF,OAAI,CAAC,SAAS,IAAI;IAChB,MAAM,wBAAQ,IAAI,MAChB,+CAA+C,SAAS,SACzD;AAEA,UAAc,WAAW;AAC1B,UAAM;;AAER,UAAO;IACP;;CAGJ,OAAO,uBACL,UACA,SACA,aACsC;EACtC,MAAM,WAAW,MAAM,KAAK,SAAS,UAAU,SAAS,KAAK;AAC7D,MAAI,CAAC,SAAS,KACZ,OAAM,IAAI,MAAM,oDAAoD;EAEtE,MAAM,aAAaC,2BAAAA,+CACjB,SAAS,KACV;EACD,gBAAgB,YACd,QACA,QACA;AACA,cAAW,MAAM,SAAS,QAAQ;AAChC,QAAI,QAAQ,QACV;AAEF,QAAI,UAAU,SACZ,OAAM,KAAK,MAAM,MAAM;;;AAI7B,SAAOC,sBAAAA,wBAAwB,YAAY,YAAY,QAAQ,OAAO,CAAC;;CAGzE,OAAO,sBACL,UACA,SACA,YACqC;EACrC,MAAM,WAAW,MAAM,KAAK,SAAS,UAAU,SAAS,KAAK;AAC7D,MAAI,CAAC,SAAS,KACZ,OAAM,IAAI,MAAM,oDAAoD;EAEtE,MAAM,SAASD,2BAAAA,+CACb,SAAS,KACV;AACD,aAAW,MAAM,SAAS,QAAQ;AAChC,OAAI,QAAQ,QAAQ,QAClB;AAEF,OAAI,UAAU,UAAU;IACtB,MAAM,cAAc,KAAK,MAAM,MAAM;IACrC,MAAM,kBAAkB,IAAIE,wBAAAA,oBAAoB;KAC9C,SAAS,IAAIC,yBAAAA,eAAe,EAAE,SAAS,YAAY,UAAU,CAAC;KAC9D,MAAM,YAAY;KACnB,CAAC;AACF,UAAM;AAED,gBAAY,kBAAkB,gBAAgB,QAAQ,GAAG;;;;CAKpE,gBACE,UACqC;AA2BrC,SA1B0B,SAAS,KAAK,YAAY;GAClD,IAAI;AACJ,OAAI,QAAQ,UAAU,KAAK,QACzB,QAAO;YACE,QAAQ,UAAU,KAAK,KAChC,QAAO;YACE,QAAQ,UAAU,KAAK,SAChC,QAAO;YACEC,yBAAAA,YAAY,WAAW,QAAQ,CACxC,QAAO,QAAQ;QACV;AACL,YAAQ,KACN,mDAAmD,QAAQ,UAAU,CAAC,GACvE;AACD,WAAO;;AAET,OAAI,OAAO,QAAQ,YAAY,SAC7B,OAAM,IAAI,MACR,iFACD;AAEH,UAAO;IACL;IACA,SAAS,QAAQ;IAClB;IAEqB;;;CAI1B,MAAM,MACJ,UACA,SACA,YACiB;AACjB,UAAQ,QAAQ,gBAAgB;AAChC,MAAI,CAAC,KAAK,UAKR,SAAO,OAFoB,MAFJ,KAAK,SAAS,UAAU,QAAQ,EAEnB,MAAM,EAEtB,OAAO;OACtB;GACL,MAAM,SAAS,KAAK,sBAAsB,UAAU,SAAS,WAAW;GACxE,IAAI;AACJ,cAAW,MAAM,SAAS,OACxB,KAAI,gBAAgB,KAAA,EAClB,eAAc;OAEd,eAAc,YAAY,OAAO,MAAM;GAG3C,MAAM,iBAAiB,aAAa,QAAQ;AAC5C,OAAI,kBAAkB,OAAO,mBAAmB,SAC9C,OAAM,IAAI,MACR,4EACD;AAEH,UAAO,kBAAkB"}