Files
hack/tools/scripts/llm-key-hunter/results/_cache/content/abhiramvishal_clawpilot.json
T

1 line
11 KiB
JSON

{"repo": "abhiramvishal/clawpilot", "files": {"src/api/providers/deepseek.ts": {"fd68808c7a9727eb3adbf523d8013bff699c764a": {"t": 1785746034.4465368, "n": 5187, "h": "ccdf498db6d23c38", "c": "import { Anthropic } from \"@anthropic-ai/sdk\"\nimport OpenAI from \"openai\"\n\nimport {\n\tdeepSeekModels,\n\tdeepSeekDefaultModelId,\n\tDEEP_SEEK_DEFAULT_TEMPERATURE,\n\tOPENAI_AZURE_AI_INFERENCE_PATH,\n} from \"@clawpilot/types\"\n\nimport type { ApiHandlerOptions } from \"../../shared/api\"\n\nimport { ApiStream, ApiStreamUsageChunk } from \"../transform/stream\"\nimport { getModelParams } from \"../transform/model-params\"\nimport { convertToR1Format } from \"../transform/r1-format\"\n\nimport { OpenAiHandler } from \"./openai\"\nimport type { ApiHandlerCreateMessageMetadata } from \"../index\"\n\n// Custom interface for DeepSeek params to support thinking mode\ntype DeepSeekChatCompletionParams = OpenAI.Chat.ChatCompletionCreateParamsStreaming & {\n\tthinking?: { type: \"enabled\" | \"disabled\" }\n}\n\nexport class DeepSeekHandler extends OpenAiHandler {\n\tconstructor(options: ApiHandlerOptions) {\n\t\tsuper({\n\t\t\t...options,\n\t\t\topenAiApiKey: options.deepSeekApiKey ?? \"not-provided\",\n\t\t\topenAiModelId: options.apiModelId ?? deepSeekDefaultModelId,\n\t\t\topenAiBaseUrl: options.deepSeekBaseUrl || \"https://api.deepseek.com\",\n\t\t\topenAiStreamingEnabled: true,\n\t\t\tincludeMaxTokens: true,\n\t\t})\n\t}\n\n\toverride getModel() {\n\t\tconst id = this.options.apiModelId ?? deepSeekDefaultModelId\n\t\tconst info = deepSeekModels[id as keyof typeof deepSeekModels] || deepSeekModels[deepSeekDefaultModelId]\n\t\tconst params = getModelParams({\n\t\t\tformat: \"openai\",\n\t\t\tmodelId: id,\n\t\t\tmodel: info,\n\t\t\tsettings: this.options,\n\t\t\tdefaultTemperature: DEEP_SEEK_DEFAULT_TEMPERATURE,\n\t\t})\n\t\treturn { id, info, ...params }\n\t}\n\n\toverride async *createMessage(\n\t\tsystemPrompt: string,\n\t\tmessages: Anthropic.Messages.MessageParam[],\n\t\tmetadata?: ApiHandlerCreateMessageMetadata,\n\t): ApiStream {\n\t\tconst modelId = this.options.apiModelId ?? deepSeekDefaultModelId\n\t\tconst { info: modelInfo } = this.getModel()\n\n\t\t// Check if this is a thinking-enabled model (deepseek-reasoner)\n\t\tconst isThinkingModel = modelId.includes(\"deepseek-reasoner\")\n\n\t\t// Convert messages to R1 format (merges consecutive same-role messages)\n\t\t// This is required for DeepSeek which does not support successive messages with the same role\n\t\t// For thinking models (deepseek-reasoner), enable mergeToolResultText to preserve reasoning_content\n\t\t// during tool call sequences. Without this, environment_details text after tool_results would\n\t\t// create user messages that cause DeepSeek to drop all previous reasoning_content.\n\t\t// See: https://api-docs.deepseek.com/guides/thinking_mode\n\t\tconst convertedMessages = convertToR1Format([{ role: \"user\", content: systemPrompt }, ...messages], {\n\t\t\tmergeToolResultText: isThinkingModel,\n\t\t})\n\n\t\tconst requestOptions: DeepSeekChatCompletionParams = {\n\t\t\tmodel: modelId,\n\t\t\ttemperature: this.options.modelTemperature ?? DEEP_SEEK_DEFAULT_TEMPERATURE,\n\t\t\tmessages: convertedMessages,\n\t\t\tstream: true as const,\n\t\t\tstream_options: { include_usage: true },\n\t\t\t// Enable thinking mode for deepseek-reasoner or when tools are used with thinking model\n\t\t\t...(isThinkingModel && { thinking: { type: \"enabled\" } }),\n\t\t\ttools: this.convertToolsForOpenAI(metadata?.tools),\n\t\t\ttool_choice: metadata?.tool_choice,\n\t\t\tparallel_tool_calls: metadata?.parallelToolCalls ?? true,\n\t\t}\n\n\t\t// Add max_tokens if needed\n\t\tthis.addMaxTokensIfNeeded(requestOptions, modelInfo)\n\n\t\t// Check if base URL is Azure AI Inference (for DeepSeek via Azure)\n\t\tconst isAzureAiInference = this._isAzureAiInference(this.options.deepSeekBaseUrl)\n\n\t\tlet stream\n\t\ttry {\n\t\t\tstream = await this.client.chat.completions.create(\n\t\t\t\trequestOptions,\n\t\t\t\tisAzureAiInference ? { path: OPENAI_AZURE_AI_INFERENCE_PATH } : {},\n\t\t\t)\n\t\t} catch (error) {\n\t\t\tconst { handleOpenAIError } = await import(\"./utils/openai-error-handler\")\n\t\t\tthrow handleOpenAIError(error, \"DeepSeek\")\n\t\t}\n\n\t\tlet lastUsage\n\n\t\tfor await (const chunk of stream) {\n\t\t\tconst delta = chunk.choices?.[0]?.delta ?? {}\n\n\t\t\t// Handle regular text content\n\t\t\tif (delta.content) {\n\t\t\t\tyield {\n\t\t\t\t\ttype: \"text\",\n\t\t\t\t\ttext: delta.content,\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Handle reasoning_content from DeepSeek's interleaved thinking\n\t\t\t// This is the proper way DeepSeek sends thinking content in streaming\n\t\t\tif (\"reasoning_content\" in delta && delta.reasoning_content) {\n\t\t\t\tyield {\n\t\t\t\t\ttype: \"reasoning\",\n\t\t\t\t\ttext: (delta.reasoning_content as string) || \"\",\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Handle tool calls\n\t\t\tif (delta.tool_calls) {\n\t\t\t\tfor (const toolCall of delta.tool_calls) {\n\t\t\t\t\tyield {\n\t\t\t\t\t\ttype: \"tool_call_partial\",\n\t\t\t\t\t\tindex: toolCall.index,\n\t\t\t\t\t\tid: toolCall.id,\n\t\t\t\t\t\tname: toolCall.function?.name,\n\t\t\t\t\t\targuments: toolCall.function?.arguments,\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (chunk.usage) {\n\t\t\t\tlastUsage = chunk.usage\n\t\t\t}\n\t\t}\n\n\t\tif (lastUsage) {\n\t\t\tyield this.processUsageMetrics(lastUsage, modelInfo)\n\t\t}\n\t}\n\n\t// Override to handle DeepSeek's usage metrics, including caching.\n\tprotected override processUsageMetrics(usage: any, _modelInfo?: any): ApiStreamUsageChunk {\n\t\treturn {\n\t\t\ttype: \"usage\",\n\t\t\tinputTokens: usage?.prompt_tokens || 0,\n\t\t\toutputTokens: usage?.completion_tokens || 0,\n\t\t\tcacheWriteTokens: usage?.prompt_tokens_details?.cache_miss_tokens,\n\t\t\tcacheReadTokens: usage?.prompt_tokens_details?.cached_tokens,\n\t\t}\n\t}\n}\n"}, "ae3ddaf9127a097034c316df5c06b26940cf6310": {"t": 1785759059.5812912, "n": 5187, "h": "ccdf498db6d23c38", "c": "import { Anthropic } from \"@anthropic-ai/sdk\"\nimport OpenAI from \"openai\"\n\nimport {\n\tdeepSeekModels,\n\tdeepSeekDefaultModelId,\n\tDEEP_SEEK_DEFAULT_TEMPERATURE,\n\tOPENAI_AZURE_AI_INFERENCE_PATH,\n} from \"@clawpilot/types\"\n\nimport type { ApiHandlerOptions } from \"../../shared/api\"\n\nimport { ApiStream, ApiStreamUsageChunk } from \"../transform/stream\"\nimport { getModelParams } from \"../transform/model-params\"\nimport { convertToR1Format } from \"../transform/r1-format\"\n\nimport { OpenAiHandler } from \"./openai\"\nimport type { ApiHandlerCreateMessageMetadata } from \"../index\"\n\n// Custom interface for DeepSeek params to support thinking mode\ntype DeepSeekChatCompletionParams = OpenAI.Chat.ChatCompletionCreateParamsStreaming & {\n\tthinking?: { type: \"enabled\" | \"disabled\" }\n}\n\nexport class DeepSeekHandler extends OpenAiHandler {\n\tconstructor(options: ApiHandlerOptions) {\n\t\tsuper({\n\t\t\t...options,\n\t\t\topenAiApiKey: options.deepSeekApiKey ?? \"not-provided\",\n\t\t\topenAiModelId: options.apiModelId ?? deepSeekDefaultModelId,\n\t\t\topenAiBaseUrl: options.deepSeekBaseUrl || \"https://api.deepseek.com\",\n\t\t\topenAiStreamingEnabled: true,\n\t\t\tincludeMaxTokens: true,\n\t\t})\n\t}\n\n\toverride getModel() {\n\t\tconst id = this.options.apiModelId ?? deepSeekDefaultModelId\n\t\tconst info = deepSeekModels[id as keyof typeof deepSeekModels] || deepSeekModels[deepSeekDefaultModelId]\n\t\tconst params = getModelParams({\n\t\t\tformat: \"openai\",\n\t\t\tmodelId: id,\n\t\t\tmodel: info,\n\t\t\tsettings: this.options,\n\t\t\tdefaultTemperature: DEEP_SEEK_DEFAULT_TEMPERATURE,\n\t\t})\n\t\treturn { id, info, ...params }\n\t}\n\n\toverride async *createMessage(\n\t\tsystemPrompt: string,\n\t\tmessages: Anthropic.Messages.MessageParam[],\n\t\tmetadata?: ApiHandlerCreateMessageMetadata,\n\t): ApiStream {\n\t\tconst modelId = this.options.apiModelId ?? deepSeekDefaultModelId\n\t\tconst { info: modelInfo } = this.getModel()\n\n\t\t// Check if this is a thinking-enabled model (deepseek-reasoner)\n\t\tconst isThinkingModel = modelId.includes(\"deepseek-reasoner\")\n\n\t\t// Convert messages to R1 format (merges consecutive same-role messages)\n\t\t// This is required for DeepSeek which does not support successive messages with the same role\n\t\t// For thinking models (deepseek-reasoner), enable mergeToolResultText to preserve reasoning_content\n\t\t// during tool call sequences. Without this, environment_details text after tool_results would\n\t\t// create user messages that cause DeepSeek to drop all previous reasoning_content.\n\t\t// See: https://api-docs.deepseek.com/guides/thinking_mode\n\t\tconst convertedMessages = convertToR1Format([{ role: \"user\", content: systemPrompt }, ...messages], {\n\t\t\tmergeToolResultText: isThinkingModel,\n\t\t})\n\n\t\tconst requestOptions: DeepSeekChatCompletionParams = {\n\t\t\tmodel: modelId,\n\t\t\ttemperature: this.options.modelTemperature ?? DEEP_SEEK_DEFAULT_TEMPERATURE,\n\t\t\tmessages: convertedMessages,\n\t\t\tstream: true as const,\n\t\t\tstream_options: { include_usage: true },\n\t\t\t// Enable thinking mode for deepseek-reasoner or when tools are used with thinking model\n\t\t\t...(isThinkingModel && { thinking: { type: \"enabled\" } }),\n\t\t\ttools: this.convertToolsForOpenAI(metadata?.tools),\n\t\t\ttool_choice: metadata?.tool_choice,\n\t\t\tparallel_tool_calls: metadata?.parallelToolCalls ?? true,\n\t\t}\n\n\t\t// Add max_tokens if needed\n\t\tthis.addMaxTokensIfNeeded(requestOptions, modelInfo)\n\n\t\t// Check if base URL is Azure AI Inference (for DeepSeek via Azure)\n\t\tconst isAzureAiInference = this._isAzureAiInference(this.options.deepSeekBaseUrl)\n\n\t\tlet stream\n\t\ttry {\n\t\t\tstream = await this.client.chat.completions.create(\n\t\t\t\trequestOptions,\n\t\t\t\tisAzureAiInference ? { path: OPENAI_AZURE_AI_INFERENCE_PATH } : {},\n\t\t\t)\n\t\t} catch (error) {\n\t\t\tconst { handleOpenAIError } = await import(\"./utils/openai-error-handler\")\n\t\t\tthrow handleOpenAIError(error, \"DeepSeek\")\n\t\t}\n\n\t\tlet lastUsage\n\n\t\tfor await (const chunk of stream) {\n\t\t\tconst delta = chunk.choices?.[0]?.delta ?? {}\n\n\t\t\t// Handle regular text content\n\t\t\tif (delta.content) {\n\t\t\t\tyield {\n\t\t\t\t\ttype: \"text\",\n\t\t\t\t\ttext: delta.content,\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Handle reasoning_content from DeepSeek's interleaved thinking\n\t\t\t// This is the proper way DeepSeek sends thinking content in streaming\n\t\t\tif (\"reasoning_content\" in delta && delta.reasoning_content) {\n\t\t\t\tyield {\n\t\t\t\t\ttype: \"reasoning\",\n\t\t\t\t\ttext: (delta.reasoning_content as string) || \"\",\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Handle tool calls\n\t\t\tif (delta.tool_calls) {\n\t\t\t\tfor (const toolCall of delta.tool_calls) {\n\t\t\t\t\tyield {\n\t\t\t\t\t\ttype: \"tool_call_partial\",\n\t\t\t\t\t\tindex: toolCall.index,\n\t\t\t\t\t\tid: toolCall.id,\n\t\t\t\t\t\tname: toolCall.function?.name,\n\t\t\t\t\t\targuments: toolCall.function?.arguments,\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (chunk.usage) {\n\t\t\t\tlastUsage = chunk.usage\n\t\t\t}\n\t\t}\n\n\t\tif (lastUsage) {\n\t\t\tyield this.processUsageMetrics(lastUsage, modelInfo)\n\t\t}\n\t}\n\n\t// Override to handle DeepSeek's usage metrics, including caching.\n\tprotected override processUsageMetrics(usage: any, _modelInfo?: any): ApiStreamUsageChunk {\n\t\treturn {\n\t\t\ttype: \"usage\",\n\t\t\tinputTokens: usage?.prompt_tokens || 0,\n\t\t\toutputTokens: usage?.completion_tokens || 0,\n\t\t\tcacheWriteTokens: usage?.prompt_tokens_details?.cache_miss_tokens,\n\t\t\tcacheReadTokens: usage?.prompt_tokens_details?.cached_tokens,\n\t\t}\n\t}\n}\n"}}}}