Files
OpenCode 68a9071cf1 feat: reconcile local master with origin (exa/hot-platform hunters, leaks ledger, latest results)
Local branch had diverged from origin/master (sibling commits on the same base). Rewrote local history linearly on top of origin/master, folding in all local content: exa/hot-platform discovery hunters, leaks ledger, nightly sweep orchestrator, updated .gitignore and skill docs, plus the latest hunt output and vault state. Remote-only files (vault keys, channel scripts) were restored rather than dropped, so the resulting tree is a full union of both sides.
2026-08-07 12:53:47 +08:00

1 line
20 KiB
JSON

{"repo": "aschenmo/aschenmo-academic", "files": {"anything-llm-master/server/utils/agents/aibitat/providers/deepseek.js": {"aeff540ca5b93ecf934c2f766658dd707ae5bc24": {"t": 1785745556.7012382, "n": 4398, "h": "5281d18d3b387e09", "c": "const OpenAI = require(\"openai\");\nconst Provider = require(\"./ai-provider.js\");\nconst InheritMultiple = require(\"./helpers/classes.js\");\nconst UnTooled = require(\"./helpers/untooled.js\");\nconst { tooledStream, tooledComplete } = require(\"./helpers/tooled.js\");\nconst { RetryError } = require(\"../error.js\");\nconst { toValidNumber } = require(\"../../../http/index.js\");\n\nclass DeepSeekProvider extends InheritMultiple([Provider, UnTooled]) {\n model;\n\n constructor(config = {}) {\n super();\n const { model = \"deepseek-chat\" } = config;\n const client = new OpenAI({\n baseURL: \"https://api.deepseek.com/v1\",\n apiKey: process.env.DEEPSEEK_API_KEY ?? null,\n maxRetries: 3,\n });\n\n this._client = client;\n this.model = model;\n this.verbose = true;\n this.maxTokens = process.env.DEEPSEEK_MAX_TOKENS\n ? toValidNumber(process.env.DEEPSEEK_MAX_TOKENS, 1024)\n : 1024;\n }\n\n get client() {\n return this._client;\n }\n\n get supportsAgentStreaming() {\n return true;\n }\n\n /**\n * All current DeepSeek models (deepseek-chat and deepseek-reasoner)\n * support native OpenAI-compatible tool calling.\n * @returns {boolean}\n */\n supportsNativeToolCalling() {\n return true;\n }\n\n get #isThinkingModel() {\n return this.model === \"deepseek-reasoner\";\n }\n\n get #tooledOptions() {\n return this.#isThinkingModel ? { injectReasoningContent: true } : {};\n }\n\n async #handleFunctionCallChat({ messages = [] }) {\n return await this.client.chat.completions\n .create({\n model: this.model,\n messages,\n max_tokens: this.maxTokens,\n })\n .then((result) => {\n if (!result.hasOwnProperty(\"choices\"))\n throw new Error(\"DeepSeek chat: No results!\");\n if (result.choices.length === 0)\n throw new Error(\"DeepSeek chat: No results length!\");\n return result.choices[0].message.content;\n })\n .catch((_) => {\n return null;\n });\n }\n\n async #handleFunctionCallStream({ messages = [] }) {\n return await this.client.chat.completions.create({\n model: this.model,\n stream: true,\n messages,\n });\n }\n\n async stream(messages, functions = [], eventHandler = null) {\n const useNative = functions.length > 0 && this.supportsNativeToolCalling();\n\n if (!useNative) {\n return await UnTooled.prototype.stream.call(\n this,\n messages,\n functions,\n this.#handleFunctionCallStream.bind(this),\n eventHandler\n );\n }\n\n this.providerLog(\n \"Provider.stream (tooled) - will process this chat completion.\"\n );\n\n try {\n return await tooledStream(\n this.client,\n this.model,\n messages,\n functions,\n eventHandler,\n this.#tooledOptions\n );\n } catch (error) {\n console.error(error.message, error);\n if (error instanceof OpenAI.AuthenticationError) throw error;\n if (\n error instanceof OpenAI.RateLimitError ||\n error instanceof OpenAI.InternalServerError ||\n error instanceof OpenAI.APIError\n ) {\n throw new RetryError(error.message);\n }\n throw error;\n }\n }\n\n async complete(messages, functions = []) {\n const useNative = functions.length > 0 && this.supportsNativeToolCalling();\n\n if (!useNative) {\n return await UnTooled.prototype.complete.call(\n this,\n messages,\n functions,\n this.#handleFunctionCallChat.bind(this)\n );\n }\n\n try {\n const result = await tooledComplete(\n this.client,\n this.model,\n messages,\n functions,\n this.getCost.bind(this),\n this.#tooledOptions\n );\n\n if (result.retryWithError) {\n return this.complete([...messages, result.retryWithError], functions);\n }\n\n return result;\n } catch (error) {\n if (error instanceof OpenAI.AuthenticationError) throw error;\n if (\n error instanceof OpenAI.RateLimitError ||\n error instanceof OpenAI.InternalServerError ||\n error instanceof OpenAI.APIError\n ) {\n throw new RetryError(error.message);\n }\n throw error;\n }\n }\n\n /**\n * Get the cost of the completion.\n *\n * @param _usage The completion to get the cost for.\n * @returns The cost of the completion.\n */\n getCost(_usage) {\n return 0;\n }\n}\n\nmodule.exports = DeepSeekProvider;\n"}, "82c1cd0cee7a11d2c6f9e2ca819523dc086f0a9b": {"t": 1785754181.4899442, "n": 4398, "h": "5281d18d3b387e09", "c": "const OpenAI = require(\"openai\");\nconst Provider = require(\"./ai-provider.js\");\nconst InheritMultiple = require(\"./helpers/classes.js\");\nconst UnTooled = require(\"./helpers/untooled.js\");\nconst { tooledStream, tooledComplete } = require(\"./helpers/tooled.js\");\nconst { RetryError } = require(\"../error.js\");\nconst { toValidNumber } = require(\"../../../http/index.js\");\n\nclass DeepSeekProvider extends InheritMultiple([Provider, UnTooled]) {\n model;\n\n constructor(config = {}) {\n super();\n const { model = \"deepseek-chat\" } = config;\n const client = new OpenAI({\n baseURL: \"https://api.deepseek.com/v1\",\n apiKey: process.env.DEEPSEEK_API_KEY ?? null,\n maxRetries: 3,\n });\n\n this._client = client;\n this.model = model;\n this.verbose = true;\n this.maxTokens = process.env.DEEPSEEK_MAX_TOKENS\n ? toValidNumber(process.env.DEEPSEEK_MAX_TOKENS, 1024)\n : 1024;\n }\n\n get client() {\n return this._client;\n }\n\n get supportsAgentStreaming() {\n return true;\n }\n\n /**\n * All current DeepSeek models (deepseek-chat and deepseek-reasoner)\n * support native OpenAI-compatible tool calling.\n * @returns {boolean}\n */\n supportsNativeToolCalling() {\n return true;\n }\n\n get #isThinkingModel() {\n return this.model === \"deepseek-reasoner\";\n }\n\n get #tooledOptions() {\n return this.#isThinkingModel ? { injectReasoningContent: true } : {};\n }\n\n async #handleFunctionCallChat({ messages = [] }) {\n return await this.client.chat.completions\n .create({\n model: this.model,\n messages,\n max_tokens: this.maxTokens,\n })\n .then((result) => {\n if (!result.hasOwnProperty(\"choices\"))\n throw new Error(\"DeepSeek chat: No results!\");\n if (result.choices.length === 0)\n throw new Error(\"DeepSeek chat: No results length!\");\n return result.choices[0].message.content;\n })\n .catch((_) => {\n return null;\n });\n }\n\n async #handleFunctionCallStream({ messages = [] }) {\n return await this.client.chat.completions.create({\n model: this.model,\n stream: true,\n messages,\n });\n }\n\n async stream(messages, functions = [], eventHandler = null) {\n const useNative = functions.length > 0 && this.supportsNativeToolCalling();\n\n if (!useNative) {\n return await UnTooled.prototype.stream.call(\n this,\n messages,\n functions,\n this.#handleFunctionCallStream.bind(this),\n eventHandler\n );\n }\n\n this.providerLog(\n \"Provider.stream (tooled) - will process this chat completion.\"\n );\n\n try {\n return await tooledStream(\n this.client,\n this.model,\n messages,\n functions,\n eventHandler,\n this.#tooledOptions\n );\n } catch (error) {\n console.error(error.message, error);\n if (error instanceof OpenAI.AuthenticationError) throw error;\n if (\n error instanceof OpenAI.RateLimitError ||\n error instanceof OpenAI.InternalServerError ||\n error instanceof OpenAI.APIError\n ) {\n throw new RetryError(error.message);\n }\n throw error;\n }\n }\n\n async complete(messages, functions = []) {\n const useNative = functions.length > 0 && this.supportsNativeToolCalling();\n\n if (!useNative) {\n return await UnTooled.prototype.complete.call(\n this,\n messages,\n functions,\n this.#handleFunctionCallChat.bind(this)\n );\n }\n\n try {\n const result = await tooledComplete(\n this.client,\n this.model,\n messages,\n functions,\n this.getCost.bind(this),\n this.#tooledOptions\n );\n\n if (result.retryWithError) {\n return this.complete([...messages, result.retryWithError], functions);\n }\n\n return result;\n } catch (error) {\n if (error instanceof OpenAI.AuthenticationError) throw error;\n if (\n error instanceof OpenAI.RateLimitError ||\n error instanceof OpenAI.InternalServerError ||\n error instanceof OpenAI.APIError\n ) {\n throw new RetryError(error.message);\n }\n throw error;\n }\n }\n\n /**\n * Get the cost of the completion.\n *\n * @param _usage The completion to get the cost for.\n * @returns The cost of the completion.\n */\n getCost(_usage) {\n return 0;\n }\n}\n\nmodule.exports = DeepSeekProvider;\n"}}, "anything-llm-master/server/utils/AiProviders/deepseek/index.js": {"aeff540ca5b93ecf934c2f766658dd707ae5bc24": {"t": 1786068266.1855066, "n": 10438, "h": "ebc2383675aa6384", "c": "const { NativeEmbedder } = require(\"../../EmbeddingEngines/native\");\nconst {\n LLMPerformanceMonitor,\n} = require(\"../../helpers/chat/LLMPerformanceMonitor\");\nconst { v4: uuidv4 } = require(\"uuid\");\nconst { MODEL_MAP } = require(\"../modelMap\");\nconst {\n writeResponseChunk,\n clientAbortedHandler,\n} = require(\"../../helpers/chat/responses\");\n\nclass DeepSeekLLM {\n constructor(embedder = null, modelPreference = null) {\n if (!process.env.DEEPSEEK_API_KEY)\n throw new Error(\"No DeepSeek API key was set.\");\n this.className = \"DeepSeekLLM\";\n const { OpenAI: OpenAIApi } = require(\"openai\");\n\n this.openai = new OpenAIApi({\n apiKey: process.env.DEEPSEEK_API_KEY,\n baseURL: \"https://api.deepseek.com/v1\",\n });\n this.model =\n modelPreference || process.env.DEEPSEEK_MODEL_PREF || \"deepseek-chat\";\n this.limits = {\n history: this.promptWindowLimit() * 0.15,\n system: this.promptWindowLimit() * 0.15,\n user: this.promptWindowLimit() * 0.7,\n };\n\n this.embedder = embedder ?? new NativeEmbedder();\n this.defaultTemp = 0.7;\n this.log(\n `Initialized ${this.model} with context window ${this.promptWindowLimit()}`\n );\n }\n\n log(text, ...args) {\n console.log(`\\x1b[36m[${this.className}]\\x1b[0m ${text}`, ...args);\n }\n\n #appendContext(contextTexts = []) {\n if (!contextTexts || !contextTexts.length) return \"\";\n return (\n \"\\nContext:\\n\" +\n contextTexts\n .map((text, i) => {\n return `[CONTEXT ${i}]:\\n${text}\\n[END CONTEXT ${i}]\\n\\n`;\n })\n .join(\"\")\n );\n }\n\n streamingEnabled() {\n return \"streamGetChatCompletion\" in this;\n }\n\n static promptWindowLimit(modelName) {\n return MODEL_MAP.get(\"deepseek\", modelName) ?? 8192;\n }\n\n promptWindowLimit() {\n return MODEL_MAP.get(\"deepseek\", this.model) ?? 8192;\n }\n\n async isValidChatCompletionModel(modelName = \"\") {\n const models = await this.openai.models.list().catch(() => ({ data: [] }));\n return models.data.some((model) => model.id === modelName);\n }\n\n constructPrompt({\n systemPrompt = \"\",\n contextTexts = [],\n chatHistory = [],\n userPrompt = \"\",\n }) {\n const prompt = {\n role: \"system\",\n content: `${systemPrompt}${this.#appendContext(contextTexts)}`,\n };\n return [prompt, ...chatHistory, { role: \"user\", content: userPrompt }];\n }\n\n /**\n * Parses and prepends reasoning from the response and returns the full text response.\n * @param {Object} response\n * @returns {string}\n */\n #parseReasoningFromResponse({ message }) {\n let textResponse = message?.content;\n if (\n !!message?.reasoning_content &&\n message.reasoning_content.trim().length > 0\n )\n textResponse = `<think>${message.reasoning_content}</think>${textResponse}`;\n return textResponse;\n }\n\n async getChatCompletion(messages = null, { temperature = 0.7 }) {\n if (!(await this.isValidChatCompletionModel(this.model)))\n throw new Error(\n `DeepSeek chat: ${this.model} is not valid for chat completion!`\n );\n\n const result = await LLMPerformanceMonitor.measureAsyncFunction(\n this.openai.chat.completions\n .create({\n model: this.model,\n messages,\n temperature,\n })\n .catch((e) => {\n throw new Error(e.message);\n })\n );\n\n if (\n !result?.output?.hasOwnProperty(\"choices\") ||\n result?.output?.choices?.length === 0\n )\n throw new Error(\n `Invalid response body returned from DeepSeek: ${JSON.stringify(result.output)}`\n );\n\n return {\n textResponse: this.#parseReasoningFromResponse(result.output.choices[0]),\n metrics: {\n prompt_tokens: result.output.usage.prompt_tokens || 0,\n completion_tokens: result.output.usage.completion_tokens || 0,\n total_tokens: result.output.usage.total_tokens || 0,\n outputTps: result.output.usage.completion_tokens / result.duration,\n duration: result.duration,\n model: this.model,\n provider: this.className,\n timestamp: new Date(),\n },\n };\n }\n\n async streamGetChatCompletion(messages = null, { temperature = 0.7 }) {\n if (!(await this.isValidChatCompletionModel(this.model)))\n throw new Error(\n `DeepSeek chat: ${this.model} is not valid for chat completion!`\n );\n\n const measuredStreamRequest = await LLMPerformanceMonitor.measureStream({\n func: this.openai.chat.completions.create({\n model: this.model,\n stream: true,\n messages,\n temperature,\n }),\n messages,\n runPromptTokenCalculation: false,\n modelTag: this.model,\n provider: this.className,\n });\n\n return measuredStreamRequest;\n }\n\n // TODO: This is a copy of the generic handleStream function in responses.js\n // to specifically handle the DeepSeek reasoning model `reasoning_content` field.\n // When or if ever possible, we should refactor this to be in the generic function.\n handleStream(response, stream, responseProps) {\n const { uuid = uuidv4(), sources = [] } = responseProps;\n let hasUsageMetrics = false;\n let usage = {\n completion_tokens: 0,\n };\n\n return new Promise(async (resolve) => {\n let fullText = \"\";\n let reasoningText = \"\";\n\n // Establish listener to early-abort a streaming response\n // in case things go sideways or the user does not like the response.\n // We preserve the generated text but continue as if chat was completed\n // to preserve previously generated content.\n const handleAbort = () => {\n stream?.endMeasurement(usage);\n clientAbortedHandler(resolve, fullText);\n };\n response.on(\"close\", handleAbort);\n\n try {\n for await (const chunk of stream) {\n const message = chunk?.choices?.[0];\n const token = message?.delta?.content;\n const reasoningToken = message?.delta?.reasoning_content;\n\n if (\n chunk.hasOwnProperty(\"usage\") && // exists\n !!chunk.usage && // is not null\n Object.values(chunk.usage).length > 0 // has values\n ) {\n if (chunk.usage.hasOwnProperty(\"prompt_tokens\")) {\n usage.prompt_tokens = Number(chunk.usage.prompt_tokens);\n }\n\n if (chunk.usage.hasOwnProperty(\"completion_tokens\")) {\n hasUsageMetrics = true; // to stop estimating counter\n usage.completion_tokens = Number(chunk.usage.completion_tokens);\n }\n }\n\n // Reasoning models will always return the reasoning text before the token text.\n if (reasoningToken) {\n // If the reasoning text is empty (''), we need to initialize it\n // and send the first chunk of reasoning text.\n if (reasoningText.length === 0) {\n writeResponseChunk(response, {\n uuid,\n sources: [],\n type: \"textResponseChunk\",\n textResponse: `<think>${reasoningToken}`,\n close: false,\n error: false,\n });\n reasoningText += `<think>${reasoningToken}`;\n continue;\n } else {\n writeResponseChunk(response, {\n uuid,\n sources: [],\n type: \"textResponseChunk\",\n textResponse: reasoningToken,\n close: false,\n error: false,\n });\n reasoningText += reasoningToken;\n }\n }\n\n // If the reasoning text is not empty, but the reasoning token is empty\n // and the token text is not empty we need to close the reasoning text and begin sending the token text.\n if (!!reasoningText && !reasoningToken && token) {\n writeResponseChunk(response, {\n uuid,\n sources: [],\n type: \"textResponseChunk\",\n textResponse: `</think>`,\n close: false,\n error: false,\n });\n fullText += `${reasoningText}</think>`;\n reasoningText = \"\";\n }\n\n if (token) {\n fullText += token;\n // If we never saw a usage metric, we can estimate them by number of completion chunks\n if (!hasUsageMetrics) usage.completion_tokens++;\n writeResponseChunk(response, {\n uuid,\n sources: [],\n type: \"textResponseChunk\",\n textResponse: token,\n close: false,\n error: false,\n });\n }\n\n // LocalAi returns '' and others return null on chunks - the last chunk is not \"\" or null.\n // Either way, the key `finish_reason` must be present to determine ending chunk.\n if (\n message?.hasOwnProperty(\"finish_reason\") && // Got valid message and it is an object with finish_reason\n message.finish_reason !== \"\" &&\n message.finish_reason !== null\n ) {\n writeResponseChunk(response, {\n uuid,\n sources,\n type: \"textResponseChunk\",\n textResponse: \"\",\n close: true,\n error: false,\n });\n response.removeListener(\"close\", handleAbort);\n stream?.endMeasurement(usage);\n resolve(fullText);\n break; // Break streaming when a valid finish_reason is first encountered\n }\n }\n } catch (e) {\n console.log(`\\x1b[43m\\x1b[34m[STREAMING ERROR]\\x1b[0m ${e.message}`);\n writeResponseChunk(response, {\n uuid,\n type: \"abort\",\n textResponse: null,\n sources: [],\n close: true,\n error: e.message,\n });\n stream?.endMeasurement(usage);\n resolve(fullText); // Return what we currently have - if anything.\n }\n });\n }\n\n async embedTextInput(textInput) {\n return await this.embedder.embedTextInput(textInput);\n }\n async embedChunks(textChunks = []) {\n return await this.embedder.embedChunks(textChunks);\n }\n\n async compressMessages(promptArgs = {}, rawHistory = []) {\n const { messageArrayCompressor } = require(\"../../helpers/chat\");\n const messageArray = this.constructPrompt(promptArgs);\n return await messageArrayCompressor(this, messageArray, rawHistory);\n }\n}\n\nmodule.exports = {\n DeepSeekLLM,\n};\n"}}}}