Skip to content

Commit eec6bde

Browse files
authored
fix(provider): stabilize DeepSeek tool list handling (#77)
Pre-activate VS Code/Copilot activate_* virtual tools behind an experimental setting, filter provider-owned preflight artifacts from request history, and enforce DeepSeek's 128-tool request limit.
1 parent 39a1cf6 commit eec6bde

23 files changed

Lines changed: 913 additions & 42 deletions

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ Both support optional thinking mode, tool calling, and 1M token context.
105105
| `deepseek-copilot.debugMode` | `minimal` | Diagnostic mode: `minimal` for token usage only, `metadata` for privacy-preserving logs, or `verbose` for full request dumps and pipeline snapshots under extension global storage. Full dumps may include sensitive prompt text, tool schemas, file snippets, and image descriptions. Use `DeepSeek: Open Request Dumps Folder` to open the dump location |
106106
| `deepseek-copilot.visionModel` | *(auto)* | Which Copilot model to proxy images through |
107107
| `deepseek-copilot.visionPrompt` | *(built-in)* | Prompt used to describe image attachments |
108+
| `deepseek-copilot.experimental.stabilizeToolList` | `false` | Experimental. Tries to pre-activate VS Code/Copilot virtual tools so the DeepSeek API `tools` parameter is more complete and stable across turns. May improve context-cache hit rate when enabled tools change between turns. Can increase input tokens because more function definitions may be included; cache-hit input tokens are cheaper but still count toward usage. Usually leave it off with 64 or fewer enabled tools unless the tool list still changes across turns; do not enable it with more than 128 enabled tools |
108109

109110
Thinking Effort is configured from Copilot Chat's model picker for each DeepSeek model.
110111

README.zh-cn.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ API Key 存储在 VS Code 的 `SecretStorage` 中(macOS 钥匙串 / Windows
105105
| `deepseek-copilot.debugMode` | `minimal` | 诊断模式:`minimal` 仅上报 token 用量,`metadata` 输出隐私安全日志,`verbose` 将完整请求 dump 和 pipeline snapshot 写入扩展 global storage。完整 dump 可能包含敏感提示词文本、工具定义、文件片段和图片描述。使用 `DeepSeek: 打开请求 Dump 目录` 打开 dump 位置 |
106106
| `deepseek-copilot.visionModel` | *(自动)* | 用作视觉代理的 Copilot 模型 |
107107
| `deepseek-copilot.visionPrompt` | *(内置)* | 用于描述图片附件的提示词 |
108+
| `deepseek-copilot.experimental.stabilizeToolList` | `false` | 实验性设置。尝试预先激活 VS Code/Copilot 的虚拟工具,让传给 DeepSeek API 的 `tools` 参数在多轮对话中更完整、更稳定。当已启用工具跨轮次变化时,可能提高上下文缓存命中率。代价是 input tokens 可能增加;缓存命中的 input tokens 单价更低,但仍会计入用量。64 个或更少已启用工具时通常无需开启,除非工具列表仍在跨轮次变化;超过 128 个已启用工具时不建议开启 |
108109

109110
思考深度可通过 Copilot Chat 的模型选择器对每个 DeepSeek 模型单独设置。
110111

docs/notices/tool-drift.en.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Unstable Tools List
2+
3+
DeepSeek V4 for Copilot Chat detected that the Tools list in the current chat may be unstable across turns.
4+
5+
## Why This Happens
6+
7+
The DeepSeek Chat Completions API supports at most **128 tools** in one request. VS Code's Language Model API also lets a model declare the maximum number of tools it can receive per request.
8+
9+
When the experimental `deepseek-copilot.experimental.stabilizeToolList` setting is enabled, the extension tries to pre-activate VS Code/Copilot `activate_*` virtual tools before sending the request, so the DeepSeek API `tools` parameter is more complete and stable across turns.
10+
11+
If too many tools are available in the current environment, Copilot may trim, group, or defer tool expansion. The resulting Tools array may differ between turns.
12+
13+
## Impact
14+
15+
DeepSeek uses a context KVCache for the input prefix. The Tools array is part of the request input; if it changes, the cache may not hit.
16+
17+
With this experimental setting enabled, each request may include more function definitions (names, descriptions, and JSON schemas), so **input tokens** can increase. Cache-hit input tokens are billed at a lower price but still count toward usage. It is usually unnecessary with fewer than **64 enabled tools**. Do not enable it with more than **128 enabled tools**, because DeepSeek supports at most **128 functions** in one `tools` request.
18+
19+
## What You Can Do
20+
21+
1. Run the VS Code command `workbench.action.chat.configureTools` and disable tools or MCP tools you do not currently need.
22+
2. Turn off `deepseek-copilot.experimental.stabilizeToolList`.
23+
3. If a lower cache hit rate is acceptable, you can continue sending messages in this chat.
24+
25+
If you have a better solution, please join the discussion in [issue #56](https://github.com/Vizards/deepseek-v4-for-copilot/issues/56).

docs/notices/tool-drift.zh.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Tools 列表不稳定
2+
3+
DeepSeek V4 for Copilot Chat 检测到当前会话中的 Tools(工具)列表在不同轮次之间可能不稳定。
4+
5+
## 为什么会发生
6+
7+
DeepSeek Chat Completions API 单次请求最多支持 **128 个 tools**。VS Code 的 Language Model API 也允许模型声明单次请求可接收的最大工具数。
8+
9+
当启用实验性设置 `deepseek-copilot.experimental.stabilizeToolList` 时,扩展会尝试预先激活 VS Code/Copilot 的 `activate_*` 虚拟工具,让传给 DeepSeek API 的 `tools` 参数在多轮对话中更完整、更稳定。
10+
11+
如果当前环境中可用工具太多,Copilot 可能会对工具列表进行裁剪、分组或延迟展开。不同轮次得到的 Tools 数组可能不完全一致。
12+
13+
## 影响
14+
15+
DeepSeek 对输入前缀使用上下文 KV 缓存(KVCache)。Tools 数组是请求输入的一部分;如果 Tools 数组变化,缓存可能无法命中。
16+
17+
开启这个实验性设置后,请求中可能包含更多函数工具定义(名称、说明和 JSON Schema),因此 **input tokens** 可能增加。缓存命中的 input tokens 单价更低,但仍会计入用量。少于 **64 个已启用工具** 时通常无需开启;超过 **128 个已启用工具** 时不建议开启,因为 DeepSeek 单次 `tools` 请求最多支持 **128 个 functions**
18+
19+
## 你可以怎么做
20+
21+
1. 运行 VS Code 命令 `workbench.action.chat.configureTools`,关闭暂时不需要的工具或 MCP 工具。
22+
2. 关闭 `deepseek-copilot.experimental.stabilizeToolList`
23+
3. 如果你不介意缓存命中率下降,也可以继续在当前会话发送消息。
24+
25+
如果你有更好的解决方案,欢迎在 [issue #56](https://github.com/Vizards/deepseek-v4-for-copilot/issues/56) 讨论。

package.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,14 @@
103103
"media": {
104104
"markdown": "resources/walkthrough/show-models.md"
105105
}
106+
},
107+
{
108+
"id": "advancedSettings",
109+
"title": "%deepseek-copilot.walkthrough.advancedSettings.title%",
110+
"description": "%deepseek-copilot.walkthrough.advancedSettings.description%",
111+
"media": {
112+
"markdown": "resources/walkthrough/advanced-settings.md"
113+
}
106114
}
107115
]
108116
}
@@ -121,6 +129,14 @@
121129
"minimum": 0,
122130
"description": "%deepseek-copilot.config.maxTokens.description%"
123131
},
132+
"deepseek-copilot.experimental.stabilizeToolList": {
133+
"type": "boolean",
134+
"default": false,
135+
"markdownDescription": "%deepseek-copilot.config.experimental.stabilizeToolList.description%",
136+
"tags": [
137+
"experimental"
138+
]
139+
},
124140
"deepseek-copilot.modelIdOverrides": {
125141
"type": "object",
126142
"default": {

package.nls.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,12 @@
1212
"deepseek-copilot.walkthrough.setApiKey.description": "[Get an API key](command:deepseek-copilot.getApiKey) from deepseek.com.\n[Set API Key](command:deepseek-copilot.setApiKey)",
1313
"deepseek-copilot.walkthrough.showModels.title": "Show DeepSeek models",
1414
"deepseek-copilot.walkthrough.showModels.description": "If the models are hidden, open VS Code's Language Models manager and show the DeepSeek models.\n[Open Language Models](command:workbench.action.chat.manage)",
15+
"deepseek-copilot.walkthrough.advancedSettings.title": "Try advanced settings",
16+
"deepseek-copilot.walkthrough.advancedSettings.description": "Customize providers and model names, configure the vision proxy, enable experimental settings, and more in the extension settings.\n[Open settings](command:deepseek-copilot.openSettings)",
1517
"deepseek-copilot.config.title": "DeepSeek Copilot",
1618
"deepseek-copilot.config.baseUrl.description": "DeepSeek API base URL. Defaults to official DeepSeek API endpoint.",
1719
"deepseek-copilot.config.maxTokens.description": "Maximum number of output tokens per request. Set to 0 to use the API default (no limit). Useful for controlling costs.",
20+
"deepseek-copilot.config.experimental.stabilizeToolList.description": "**Experimental**: improve DeepSeek context-cache hit rate by pre-activating available tools.\n- When the enabled tools list changes across turns, this may improve DeepSeek context-cache hit rate.\n- Requests will include more function definitions, so input tokens may increase. Cache-hit input tokens are billed at a lower price, but still count toward usage.\n\nUse [Configure Tools](command:workbench.action.chat.configureTools) to **view and manage** your tool list:\n\n- 64 or fewer enabled tools: usually no need to enable this unless the tool list still changes across turns.\n- More than 128 enabled tools: not recommended. DeepSeek supports at most 128 functions in one `tools` request. Consider disabling tools you rarely use.",
1821
"deepseek-copilot.config.debugMode.description": "Controls what diagnostic information DeepSeek Copilot writes. Token usage is always reported to Copilot regardless of this setting.\n\n- **Minimal** — Token usage only. No diagnostic logs or request dumps.\n- **Metadata** — Privacy-safe diagnostic metadata (request hashes, prefix overlap, tool schema changes). Does not contain prompt text — safe to share in public issue reports. View with [`DeepSeek: Show Logs`](command:deepseek-copilot.showLogs).\n- **Verbose** — Complete request payloads written to disk for local debugging. **Warning: contains sensitive prompt content.** View with [`DeepSeek: Open Request Dumps Folder`](command:deepseek-copilot.openRequestDumpsFolder).",
1922
"deepseek-copilot.config.debugMode.minimal.label": "Minimal",
2023
"deepseek-copilot.config.debugMode.minimal.description": "Token usage only. No diagnostic logs or dumps.",

package.nls.zh-cn.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,12 @@
1212
"deepseek-copilot.walkthrough.setApiKey.description": "从 deepseek.com [获取 API Key](command:deepseek-copilot.getApiKey)。\n[设置 API Key](command:deepseek-copilot.setApiKey)",
1313
"deepseek-copilot.walkthrough.showModels.title": "显示 DeepSeek 模型",
1414
"deepseek-copilot.walkthrough.showModels.description": "如果模型被隐藏,打开 VS Code 的语言模型管理器并显示 DeepSeek 模型。\n[打开语言模型管理](command:workbench.action.chat.manage)",
15+
"deepseek-copilot.walkthrough.advancedSettings.title": "尝试高级设置",
16+
"deepseek-copilot.walkthrough.advancedSettings.description": "可以在插件设置中自定义提供方与模型名称、自定义视觉代理、开启实验性设置等。\n[打开设置](command:deepseek-copilot.openSettings)",
1517
"deepseek-copilot.config.title": "DeepSeek 助手",
1618
"deepseek-copilot.config.baseUrl.description": "DeepSeek API 基础 URL,默认为官方 DeepSeek API 端点。",
1719
"deepseek-copilot.config.maxTokens.description": "每次请求的最大输出 Token 数,设为 0 则不限制,可用于控制成本。",
20+
"deepseek-copilot.config.experimental.stabilizeToolList.description": "**实验性功能**:通过预先激活可用的工具来提升 DeepSeek 上下文缓存命中率。\n- 当已启用工具列表跨轮次变化时,这可能提高 DeepSeek 上下文缓存命中率;\n- 请求中将包含更多函数工具定义,input tokens 可能增加,虽然缓存命中的 input tokens 单价更低,但仍会计入用量。\n\n 通过 [配置工具](command:workbench.action.chat.configureTools) **查看和管理**工具列表:\n\n- 64 个或更少已启用工具时通常无需开启,除非工具列表仍在跨轮次变化;\n- 超过 128 个已启用工具时不建议开启:DeepSeek 单次 `tools` 请求最多支持 128 个 functions。考虑禁用部分不常用工具。",
1821
"deepseek-copilot.config.debugMode.description": "控制 DeepSeek Copilot 写入的诊断信息量。无论此设置如何,token 用量始终上报给 Copilot。\n\n- **基本** — 仅上报 token 用量,不输出诊断日志或请求 dump。\n- **元数据** — 隐私安全的诊断元数据(请求哈希、前缀重合度、工具定义变更)。不含提示词原文,可安全附在公开 issue 中反馈问题。使用 [`DeepSeek: 显示日志`](command:deepseek-copilot.showLogs) 查看。\n- **详细** — 将完整请求体写入磁盘,供本地调试。**警告:包含敏感的提示词内容。** 使用 [`DeepSeek: 打开请求 Dump 目录`](command:deepseek-copilot.openRequestDumpsFolder) 浏览。",
1922
"deepseek-copilot.config.debugMode.minimal.label": "基本",
2023
"deepseek-copilot.config.debugMode.minimal.description": "仅上报 token 用量,不输出诊断日志或 dump。",
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
## Stabilize Tool List (Experimental)
2+
3+
First, open VS Code's Tools configuration and check how many tools are enabled for chat.
4+
5+
[Configure Tools](command:workbench.action.chat.configureTools)
6+
7+
- 64 or fewer enabled tools: there is usually no need to turn this on unless the tool list still changes across turns.
8+
- More than 128 enabled tools: not recommended. DeepSeek supports at most 128 functions in one `tools` request, so DeepSeek Copilot cannot guarantee a stable `tools` list above that limit. Disable rarely used tools first, then consider enabling this setting.
9+
- Between 64 and 128 enabled tools: consider this setting only if the tools list changes between turns and DeepSeek context-cache hits are poor.
10+
11+
This setting may improve cache hits by making the DeepSeek API `tools` parameter more complete and stable across turns. It may also increase input tokens because more function definitions can be included in each request.
12+
13+
[Open DeepSeek setting](command:workbench.action.openSettings?%5B%22%40id%3Adeepseek-copilot.experimental.stabilizeToolList%22%5D)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
## 稳定工具列表(实验性)
2+
3+
先打开 VS Code 的 Tools 配置,查看当前聊天启用了多少个工具。
4+
5+
[配置 Tools](command:workbench.action.chat.configureTools)
6+
7+
- 64 个或更少已启用工具:通常无需开启,除非工具列表仍在跨轮次变化。
8+
- 超过 128 个已启用工具:不建议开启。因为 DeepSeek 单次 `tools` 请求最多支持 128 个 functions,超过这个数量后,DeepSeek Copilot 无法保证传给 DeepSeek 的 `tools` 列表稳定。请先 disable 掉一些不常用的工具,再考虑开启。
9+
- 介于 64 到 128 个已启用工具:仅在工具列表跨轮次变化、DeepSeek 上下文缓存命中率不理想时,再考虑开启。
10+
11+
这个设置可能通过让 DeepSeek API 的 `tools` 参数在多轮对话中更完整、更稳定来提高缓存命中率。代价是每次请求可能包含更多函数工具定义,因此 input tokens 可能增加。
12+
13+
[打开插件设置](command:workbench.action.openSettings?%5B%22%40id%3Adeepseek-copilot.experimental.stabilizeToolList%22%5D)

src/config.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,11 @@ export function getRequestDumpEnabled(): boolean {
6464
return getDebugMode() === 'verbose';
6565
}
6666

67+
export function getStabilizeToolListEnabled(): boolean {
68+
const config = vscode.workspace.getConfiguration(CONFIG_SECTION);
69+
return config.get<boolean>('experimental.stabilizeToolList', false);
70+
}
71+
6772
/**
6873
* Migrate the legacy boolean `deepseek-copilot.debug` setting to `debugMode`.
6974
*

0 commit comments

Comments
 (0)