{"version":3,"file":"anthropic-adapter.mjs","names":[],"sources":["../../../src/service-adapters/anthropic/anthropic-adapter.ts"],"sourcesContent":["/**\n * Copilot Runtime adapter for Anthropic.\n *\n * ## Example\n *\n * ```ts\n * import { CopilotRuntime, AnthropicAdapter } from \"@copilotkit/runtime\";\n * import Anthropic from \"@anthropic-ai/sdk\";\n *\n * const copilotKit = new CopilotRuntime();\n *\n * const anthropic = new Anthropic({\n *   apiKey: \"<your-api-key>\",\n * });\n *\n * return new AnthropicAdapter({\n *   anthropic,\n *   promptCaching: {\n *     enabled: true,\n *     debug: true\n *   }\n * });\n * ```\n */\nimport type { LanguageModel } from \"ai\";\nimport { createAnthropic } from \"@ai-sdk/anthropic\";\nimport type Anthropic from \"@anthropic-ai/sdk\";\nimport {\n  CopilotServiceAdapter,\n  CopilotRuntimeChatCompletionRequest,\n  CopilotRuntimeChatCompletionResponse,\n} from \"../service-adapter\";\nimport {\n  convertActionInputToAnthropicTool,\n  convertMessageToAnthropicMessage,\n  limitMessagesToTokenCount,\n} from \"./utils\";\n\nimport { randomId, randomUUID } from \"@copilotkit/shared\";\nimport { convertServiceAdapterError, getSdkClientOptions } from \"../shared\";\n\nconst DEFAULT_MODEL = \"claude-3-5-sonnet-latest\";\n\nexport interface AnthropicPromptCachingConfig {\n  /**\n   * Whether to enable prompt caching.\n   */\n  enabled: boolean;\n\n  /**\n   * Whether to enable debug logging for cache operations.\n   */\n  debug?: boolean;\n}\n\nexport interface AnthropicAdapterParams {\n  /**\n   * An optional Anthropic instance to use.  If not provided, a new instance will be\n   * created.\n   */\n  anthropic?: Anthropic;\n\n  /**\n   * The model to use.\n   */\n  model?: string;\n\n  /**\n   * Configuration for prompt caching.\n   * See: https://docs.anthropic.com/en/docs/build-with-claude/prompt-caching\n   */\n  promptCaching?: AnthropicPromptCachingConfig;\n}\n\nexport class AnthropicAdapter implements CopilotServiceAdapter {\n  public model: string = DEFAULT_MODEL;\n  public provider = \"anthropic\";\n  private promptCaching: AnthropicPromptCachingConfig;\n\n  private _anthropic: Anthropic;\n  public get anthropic(): Anthropic {\n    return this._anthropic;\n  }\n  public get name() {\n    return \"AnthropicAdapter\";\n  }\n\n  constructor(params?: AnthropicAdapterParams) {\n    if (params?.anthropic) {\n      this._anthropic = params.anthropic;\n    }\n    // If no instance provided, we'll lazy-load in ensureAnthropic()\n    if (params?.model) {\n      this.model = params.model;\n    }\n    this.promptCaching = params?.promptCaching || { enabled: false };\n  }\n\n  getLanguageModel(): LanguageModel {\n    const anthropic = this.ensureAnthropic();\n    const options = getSdkClientOptions(anthropic);\n    const provider = createAnthropic({\n      baseURL: anthropic.baseURL,\n      apiKey: anthropic.apiKey,\n      headers: options.defaultHeaders,\n      fetch: options.fetch,\n    });\n    return provider(this.model);\n  }\n\n  private ensureAnthropic(): Anthropic {\n    if (!this._anthropic) {\n      // eslint-disable-next-line @typescript-eslint/no-var-requires\n      const Anthropic = require(\"@anthropic-ai/sdk\").default;\n      this._anthropic = new Anthropic({});\n    }\n    return this._anthropic;\n  }\n\n  /**\n   * Adds cache control to system prompt\n   */\n  private addSystemPromptCaching(\n    system: string,\n    debug: boolean = false,\n  ):\n    | string\n    | Array<{\n        type: \"text\";\n        text: string;\n        cache_control?: { type: \"ephemeral\" };\n      }> {\n    if (!this.promptCaching.enabled || !system) {\n      return system;\n    }\n\n    const originalTextLength = system.length;\n\n    if (debug) {\n      console.log(\n        `[ANTHROPIC CACHE DEBUG] Added cache control to system prompt (${originalTextLength} chars).`,\n      );\n    }\n\n    return [\n      {\n        type: \"text\",\n        text: system,\n        cache_control: { type: \"ephemeral\" },\n      },\n    ];\n  }\n\n  /**\n   * Adds cache control to the final message\n   */\n  private addIncrementalMessageCaching(\n    messages: Anthropic.Messages.MessageParam[],\n    debug: boolean = false,\n  ): any[] {\n    if (!this.promptCaching.enabled || messages.length === 0) {\n      return messages;\n    }\n\n    const finalMessage = messages[messages.length - 1];\n    const messageNumber = messages.length;\n\n    if (\n      Array.isArray(finalMessage.content) &&\n      finalMessage.content.length > 0\n    ) {\n      const finalBlock = finalMessage.content[finalMessage.content.length - 1];\n\n      const updatedMessages = [\n        ...messages.slice(0, -1),\n        {\n          ...finalMessage,\n          content: [\n            ...finalMessage.content.slice(0, -1),\n            { ...finalBlock, cache_control: { type: \"ephemeral\" } } as any,\n          ],\n        },\n      ];\n\n      if (debug) {\n        console.log(\n          `[ANTHROPIC CACHE DEBUG] Added cache control to final message (message ${messageNumber}).`,\n        );\n      }\n\n      return updatedMessages;\n    }\n\n    return messages;\n  }\n\n  private shouldGenerateFallbackResponse(\n    messages: Anthropic.Messages.MessageParam[],\n  ): boolean {\n    if (messages.length === 0) return false;\n\n    const lastMessage = messages[messages.length - 1];\n\n    // Check if the last message is a tool result\n    const endsWithToolResult =\n      lastMessage.role === \"user\" &&\n      Array.isArray(lastMessage.content) &&\n      lastMessage.content.some(\n        (content: any) => content.type === \"tool_result\",\n      );\n\n    // Also check if we have a recent pattern of user message -> assistant tool use -> user tool result\n    // This indicates a completed action that might not need a response\n    if (messages.length >= 3 && endsWithToolResult) {\n      const lastThree = messages.slice(-3);\n      const hasRecentToolPattern =\n        lastThree[0]?.role === \"user\" && // Initial user message\n        lastThree[1]?.role === \"assistant\" && // Assistant tool use\n        Array.isArray(lastThree[1].content) &&\n        lastThree[1].content.some(\n          (content: any) => content.type === \"tool_use\",\n        ) &&\n        lastThree[2]?.role === \"user\" && // Tool result\n        Array.isArray(lastThree[2].content) &&\n        lastThree[2].content.some(\n          (content: any) => content.type === \"tool_result\",\n        );\n\n      return hasRecentToolPattern;\n    }\n\n    return endsWithToolResult;\n  }\n\n  async process(\n    request: CopilotRuntimeChatCompletionRequest,\n  ): Promise<CopilotRuntimeChatCompletionResponse> {\n    const {\n      threadId,\n      model = this.model,\n      messages: rawMessages,\n      actions,\n      eventSource,\n      forwardedParameters,\n    } = request;\n    const tools = actions.map(convertActionInputToAnthropicTool);\n\n    const messages = [...rawMessages];\n\n    // get the instruction message\n    const instructionsMessage = messages.shift();\n    const instructions = instructionsMessage.isTextMessage()\n      ? instructionsMessage.content\n      : \"\";\n\n    // ALLOWLIST APPROACH:\n    // 1. First, identify all valid tool_use calls (from assistant)\n    // 2. Then, only keep tool_result blocks that correspond to these valid tool_use IDs\n    // 3. Discard any other tool_result blocks\n\n    // Step 1: Extract valid tool_use IDs\n    const validToolUseIds = new Set<string>();\n\n    for (const message of messages) {\n      if (message.isActionExecutionMessage()) {\n        validToolUseIds.add(message.id);\n      }\n    }\n\n    // Step 2: Map each message to an Anthropic message, eliminating invalid tool_results\n    const processedToolResultIds = new Set<string>();\n    const anthropicMessages = messages\n      .map((message) => {\n        // For tool results, only include if they match a valid tool_use ID AND haven't been processed\n        if (message.isResultMessage()) {\n          // Skip if there's no corresponding tool_use\n          if (!validToolUseIds.has(message.actionExecutionId)) {\n            return null; // Will be filtered out later\n          }\n\n          // Skip if we've already processed a result for this tool_use ID\n          if (processedToolResultIds.has(message.actionExecutionId)) {\n            return null; // Will be filtered out later\n          }\n\n          // Mark this tool result as processed\n          processedToolResultIds.add(message.actionExecutionId);\n\n          return {\n            role: \"user\",\n            content: [\n              {\n                type: \"tool_result\",\n                content: message.result || \"Action completed successfully\",\n                tool_use_id: message.actionExecutionId,\n              },\n            ],\n          };\n        }\n\n        // For non-tool-result messages, convert normally\n        return convertMessageToAnthropicMessage(message);\n      })\n      .filter(Boolean) // Remove nulls\n      .filter((msg) => {\n        // Filter out assistant messages with empty text content\n        if (msg.role === \"assistant\" && Array.isArray(msg.content)) {\n          const hasEmptyTextOnly =\n            msg.content.length === 1 &&\n            msg.content[0].type === \"text\" &&\n            (!(msg.content[0] as any).text ||\n              (msg.content[0] as any).text.trim() === \"\");\n\n          // Keep messages that have tool_use or non-empty text\n          return !hasEmptyTextOnly;\n        }\n        return true;\n      }) as Anthropic.Messages.MessageParam[];\n\n    // Apply token limits\n    const limitedMessages = limitMessagesToTokenCount(\n      anthropicMessages,\n      tools,\n      model,\n    );\n\n    // Apply prompt caching if enabled\n    const cachedSystemPrompt = this.addSystemPromptCaching(\n      instructions,\n      this.promptCaching.debug,\n    );\n    const cachedMessages = this.addIncrementalMessageCaching(\n      limitedMessages,\n      this.promptCaching.debug,\n    );\n\n    // We'll check if we need a fallback response after seeing what Anthropic returns\n    // We skip grouping by role since we've already ensured uniqueness of tool_results\n\n    let toolChoice: any = forwardedParameters?.toolChoice;\n    if (forwardedParameters?.toolChoice === \"function\") {\n      toolChoice = {\n        type: \"tool\",\n        name: forwardedParameters.toolChoiceFunctionName,\n      };\n    }\n\n    try {\n      const createParams = {\n        system: cachedSystemPrompt,\n        model: this.model,\n        messages: cachedMessages,\n        max_tokens: forwardedParameters?.maxTokens || 1024,\n        ...(forwardedParameters?.temperature\n          ? { temperature: forwardedParameters.temperature }\n          : {}),\n        ...(tools.length > 0 && { tools }),\n        ...(toolChoice && { tool_choice: toolChoice }),\n        stream: true,\n      };\n\n      const anthropic = this.ensureAnthropic();\n      const stream = await anthropic.messages.create(createParams);\n\n      eventSource.stream(async (eventStream$) => {\n        let mode: \"function\" | \"message\" | null = null;\n        let didOutputText = false;\n        let currentMessageId = randomId();\n        let currentToolCallId = randomId();\n        let filterThinkingTextBuffer = new FilterThinkingTextBuffer();\n        let hasReceivedContent = false;\n\n        try {\n          for await (const chunk of stream as AsyncIterable<any>) {\n            if (chunk.type === \"message_start\") {\n              currentMessageId = chunk.message.id;\n            } else if (chunk.type === \"content_block_start\") {\n              hasReceivedContent = true;\n              if (chunk.content_block.type === \"text\") {\n                didOutputText = false;\n                filterThinkingTextBuffer.reset();\n                mode = \"message\";\n              } else if (chunk.content_block.type === \"tool_use\") {\n                currentToolCallId = chunk.content_block.id;\n                eventStream$.sendActionExecutionStart({\n                  actionExecutionId: currentToolCallId,\n                  actionName: chunk.content_block.name,\n                  parentMessageId: currentMessageId,\n                });\n                mode = \"function\";\n              }\n            } else if (chunk.type === \"content_block_delta\") {\n              if (chunk.delta.type === \"text_delta\") {\n                const text = filterThinkingTextBuffer.onTextChunk(\n                  chunk.delta.text,\n                );\n                if (text.length > 0) {\n                  if (!didOutputText) {\n                    eventStream$.sendTextMessageStart({\n                      messageId: currentMessageId,\n                    });\n                    didOutputText = true;\n                  }\n                  eventStream$.sendTextMessageContent({\n                    messageId: currentMessageId,\n                    content: text,\n                  });\n                }\n              } else if (chunk.delta.type === \"input_json_delta\") {\n                eventStream$.sendActionExecutionArgs({\n                  actionExecutionId: currentToolCallId,\n                  args: chunk.delta.partial_json,\n                });\n              }\n            } else if (chunk.type === \"content_block_stop\") {\n              if (mode === \"message\") {\n                if (didOutputText) {\n                  eventStream$.sendTextMessageEnd({\n                    messageId: currentMessageId,\n                  });\n                }\n              } else if (mode === \"function\") {\n                eventStream$.sendActionExecutionEnd({\n                  actionExecutionId: currentToolCallId,\n                });\n              }\n            }\n          }\n        } catch (error) {\n          throw convertServiceAdapterError(error, \"Anthropic\");\n        }\n\n        // Generate fallback response only if Anthropic produced no content\n        if (\n          !hasReceivedContent &&\n          this.shouldGenerateFallbackResponse(cachedMessages)\n        ) {\n          // Extract the tool result content for a more contextual response\n          let fallbackContent = \"Task completed successfully.\";\n          const lastMessage = cachedMessages[cachedMessages.length - 1];\n          if (\n            lastMessage?.role === \"user\" &&\n            Array.isArray(lastMessage.content)\n          ) {\n            const toolResult = lastMessage.content.find(\n              (c: any) => c.type === \"tool_result\",\n            );\n            if (\n              toolResult?.content &&\n              toolResult.content !== \"Action completed successfully\"\n            ) {\n              fallbackContent = toolResult.content;\n            }\n          }\n\n          currentMessageId = randomId();\n          eventStream$.sendTextMessageStart({ messageId: currentMessageId });\n          eventStream$.sendTextMessageContent({\n            messageId: currentMessageId,\n            content: fallbackContent,\n          });\n          eventStream$.sendTextMessageEnd({ messageId: currentMessageId });\n        }\n\n        eventStream$.complete();\n      });\n    } catch (error) {\n      throw convertServiceAdapterError(error, \"Anthropic\");\n    }\n\n    return {\n      threadId: threadId || randomUUID(),\n    };\n  }\n}\n\nconst THINKING_TAG = \"<thinking>\";\nconst THINKING_TAG_END = \"</thinking>\";\n\nclass FilterThinkingTextBuffer {\n  private buffer: string;\n  private didFilterThinkingTag: boolean = false;\n\n  constructor() {\n    this.buffer = \"\";\n  }\n\n  onTextChunk(text: string): string {\n    this.buffer += text;\n    if (this.didFilterThinkingTag) {\n      return text;\n    }\n    const potentialTag = this.buffer.slice(0, THINKING_TAG.length);\n    if (THINKING_TAG.startsWith(potentialTag)) {\n      if (this.buffer.includes(THINKING_TAG_END)) {\n        const end = this.buffer.indexOf(THINKING_TAG_END);\n        const filteredText = this.buffer.slice(end + THINKING_TAG_END.length);\n        this.buffer = filteredText;\n        this.didFilterThinkingTag = true;\n        return filteredText;\n      } else {\n        return \"\";\n      }\n    }\n    return text;\n  }\n\n  reset() {\n    this.buffer = \"\";\n    this.didFilterThinkingTag = false;\n  }\n}\n"],"mappings":"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"}