Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,9 @@ Both support optional thinking mode, tool calling, and 1M token context.
| Setting | Default | Description |
|---|---|---|
| `deepseek-copilot.baseUrl` | `https://api.deepseek.com` | API endpoint — change for self-hosted / proxied deployments |
| `deepseek-copilot.maxTokens` | `0` | Max output tokens (`0` = no limit). Useful for cost control |
| `deepseek-copilot.maxInputTokens` | `0` | Context window (input + output) override advertised to VS Code (`0` = model default, 1M). Advertised input = window − output reserve (the reserve is capped at half the window, so advertised output never exceeds input). Lower it to make Copilot auto-compact sooner and save input tokens |
| `deepseek-copilot.maxTokens` | `0` | Max output tokens sent to the API as `max_tokens` (`0` = API default) |
| `deepseek-copilot.maxTokensAsOutputReserve` | `false` | When enabled, `maxTokens` is also advertised as the output token reserve so auto-compact targets the remaining input budget (window − `maxTokens`). When disabled, the model's maximum output is reserved |
| `deepseek-copilot.modelIdOverrides` | prefilled official ID map | API model IDs to send for DeepSeek V4 Flash / Pro. Change only for compatible third-party APIs with different model names |
| `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 |
| `deepseek-copilot.visionModel` | *(auto)* | VS Code vision model used to proxy images. Configure from `DeepSeek: Configure Vision Proxy`; new saves use `vendor/id`, while legacy bare model IDs are still read |
Expand Down
11 changes: 11 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -121,12 +121,23 @@
"default": "https://api.deepseek.com",
"description": "%deepseek-copilot.config.baseUrl.description%"
},
"deepseek-copilot.maxInputTokens": {
"type": "number",
"default": 0,
"minimum": 0,
"description": "%deepseek-copilot.config.maxInputTokens.description%"
},
"deepseek-copilot.maxTokens": {
"type": "number",
"default": 0,
"minimum": 0,
"description": "%deepseek-copilot.config.maxTokens.description%"
},
"deepseek-copilot.maxTokensAsOutputReserve": {
"type": "boolean",
"default": false,
"description": "%deepseek-copilot.config.maxTokensAsOutputReserve.description%"
},
"deepseek-copilot.experimental.stabilizeToolList": {
"type": "boolean",
"default": false,
Expand Down
4 changes: 3 additions & 1 deletion package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
"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)",
"deepseek-copilot.config.title": "DeepSeek Copilot",
"deepseek-copilot.config.baseUrl.description": "DeepSeek API base URL. Defaults to official DeepSeek API endpoint.",
"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.",
"deepseek-copilot.config.maxTokens.description": "Maximum number of output tokens per request, sent to the API as `max_tokens`. Set to 0 to use the API default (no limit).",
"deepseek-copilot.config.maxInputTokens.description": "Context window (input + output) override advertised to VS Code. Set to 0 to advertise each model's configured window (1M for DeepSeek V4). The advertised input budget is the window minus the output reserve (see `maxTokensAsOutputReserve`). The reserve is capped at half the window, so advertised output never exceeds advertised input. Lower values make Copilot Chat auto-compact conversation history sooner, saving input tokens.",
"deepseek-copilot.config.maxTokensAsOutputReserve.description": "Advertise `maxTokens` to Copilot Chat as the output token reserve. When enabled, the advertised input budget becomes the context window minus `maxTokens`, so auto-compact targets the remaining input budget. When disabled, the model's maximum output is reserved.",
"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- This may add internal preflight tool calls to the current Copilot chat history. If you switch to another model in the same conversation, that model provider may reject or mishandle the replayed history. Start a new chat if model switching behaves unexpectedly.\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.",
"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).",
"deepseek-copilot.config.debugMode.minimal.label": "Minimal",
Expand Down
4 changes: 3 additions & 1 deletion package.nls.zh-cn.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
"deepseek-copilot.walkthrough.advancedSettings.description": "可以在插件设置中自定义提供方与模型名称、自定义视觉代理、开启实验性设置等。\n[打开设置](command:deepseek-copilot.openSettings)",
"deepseek-copilot.config.title": "DeepSeek 助手",
"deepseek-copilot.config.baseUrl.description": "DeepSeek API 基础 URL,默认为官方 DeepSeek API 端点。",
"deepseek-copilot.config.maxTokens.description": "每次请求的最大输出 Token 数,设为 0 则不限制,可用于控制成本。",
"deepseek-copilot.config.maxTokens.description": "每次请求的最大输出 Token 数,以 `max_tokens` 发送给 API。设为 0 则使用 API 默认值(不限制)。",
"deepseek-copilot.config.maxInputTokens.description": "上报给 VS Code 的上下文窗口(输入 + 输出)覆盖值。设为 0 时使用各模型配置的窗口(DeepSeek V4 为 1M)。上报的输入预算 = 窗口 − 输出预留(见 `maxTokensAsOutputReserve`)。输出预留上限为窗口的一半,因此上报的输出不会超过上报的输入。调低此值会让 Copilot Chat 更早自动压缩对话历史,节省输入 Token。",
"deepseek-copilot.config.maxTokensAsOutputReserve.description": "将 `maxTokens` 作为输出 Token 预留上报给 Copilot Chat。启用后,上报的输入预算 = 上下文窗口 − `maxTokens`,自动压缩将针对剩余的输入预算进行。禁用时预留模型的最大输出。",
"deepseek-copilot.config.experimental.stabilizeToolList.description": "**实验性功能**:通过预先激活可用的工具来提升 DeepSeek 上下文缓存命中率。\n- 当已启用工具列表跨轮次变化时,这可能提高 DeepSeek 上下文缓存命中率;\n- 请求中将包含更多函数工具定义,input tokens 可能增加,虽然缓存命中的 input tokens 单价更低,但仍会计入用量;\n- 此设置可能会在当前 Copilot 对话历史中加入内部预检工具调用。在同一对话中切换到其他模型时,部分模型提供方可能无法正确重放这段历史;如果切换模型后请求异常,请新建对话后重试。\n\n 通过 [配置工具](command:workbench.action.chat.configureTools) **查看和管理**工具列表:\n\n- 64 个或更少已启用工具时通常无需开启,除非工具列表仍在跨轮次变化;\n- 超过 128 个已启用工具时不建议开启:DeepSeek 单次 `tools` 请求最多支持 128 个 functions。考虑禁用部分不常用工具。",
"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) 浏览。",
"deepseek-copilot.config.debugMode.minimal.label": "基本",
Expand Down
30 changes: 29 additions & 1 deletion src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,43 @@ export function getApiModelId(vscodeModelId: string): string {
}

/**
* Get the configured max output tokens limit.
* Get the configured max output tokens limit (`max_tokens` sent to the API).
* Returns `undefined` when set to 0 (API default — no limit).
* When `maxTokensAsOutputReserve` is enabled, this value is also the output
* reserve subtracted from the context window advertised to VS Code (see
* `toChatInfo` in `provider/models.ts`).
*/
export function getMaxTokens(): number | undefined {
const config = vscode.workspace.getConfiguration(CONFIG_SECTION);
const value = config.get<number>('maxTokens', 0);
return value > 0 ? value : undefined;
}

/**
* Get the configured context window override (input + output tokens).
* Returns `undefined` when set to 0 (use each model's configured window —
* 1M for DeepSeek V4). The advertised input budget is the window minus the
* output reserve, and Copilot Chat computes auto-compact thresholds against
* it, so lower values compact conversation history sooner.
*/
export function getMaxInputTokens(): number | undefined {
const config = vscode.workspace.getConfiguration(CONFIG_SECTION);
const value = config.get<number>('maxInputTokens', 0);
return value > 0 ? value : undefined;
}

/**
* Whether `maxTokens` is also advertised to VS Code as the output token
* reserve. When enabled, the advertised input budget becomes the context
* window minus `maxTokens`, so Copilot Chat auto-compacts against the
* remaining input budget. When disabled, the model's maximum output is
* reserved instead.
*/
export function getMaxTokensAsOutputReserveEnabled(): boolean {
const config = vscode.workspace.getConfiguration(CONFIG_SECTION);
return config.get<boolean>('maxTokensAsOutputReserve', false);
}

/**
* Diagnostic mode. `verbose` also enables metadata logs.
*
Expand Down
8 changes: 8 additions & 0 deletions src/provider/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,14 @@ export class DeepSeekChatProvider implements vscode.LanguageModelChatProvider {
e.affectsConfiguration('deepseek-copilot.baseUrl')
) {
this.invalidateCurrencyAndRefreshModels();
} else if (
e.affectsConfiguration('deepseek-copilot.maxInputTokens') ||
e.affectsConfiguration('deepseek-copilot.maxTokens') ||
e.affectsConfiguration('deepseek-copilot.maxTokensAsOutputReserve')
) {
// Token-limit settings change advertised model info; refresh the
// picker directly (no currency invalidation needed).
this.refreshModelPicker();
}
}),
// Multi-window: SecretStorage changes don't fire onDidChangeConfiguration.
Expand Down
28 changes: 25 additions & 3 deletions src/provider/models.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import vscode from 'vscode';
import { getMaxInputTokens, getMaxTokens, getMaxTokensAsOutputReserveEnabled } from '../config';
import { t } from '../i18n';
import type {
ModelDefinition,
Expand Down Expand Up @@ -44,16 +45,37 @@ export function toChatInfo(
const modelDetail = resolveModelText(m, 'detail') ?? m.detail;
const modelTooltip = resolveModelText(m, 'tooltip');
const thinkingCapability = m.capabilities.thinking;
// `maxInputTokens` is a context window override (input + output). The
// advertised input budget is the window minus the output reserve
// (`maxTokens` when `maxTokensAsOutputReserve` is enabled, otherwise the
// model maximum), mirroring how Copilot advertises its own models.
// Copilot Chat computes auto-compact thresholds against this value, so a
// smaller window compacts sooner.
//
// Advertised invariants: output ≤ input, and input + output ≤ window.
// The output reserve is capped at half the window so that when the window
// override is smaller than the model's maximum output, the reserve shrinks
// and input keeps the other half instead of collapsing to 1.
const fullWindow = m.maxInputTokens + m.maxOutputTokens;
const window = getMaxInputTokens() ?? fullWindow;
const configuredReserve = getMaxTokensAsOutputReserveEnabled()
? (getMaxTokens() ?? m.maxOutputTokens)
: m.maxOutputTokens;
const maxOutputReserve = Math.max(1, Math.floor(window / 2));
const outputReserve = Math.min(configuredReserve, m.maxOutputTokens, maxOutputReserve);
const maxInputTokens = Math.max(1, window - outputReserve);
return {
id: m.id,
name: m.name,
family: m.family,
version: m.version,
// Include the effective limits in the version so VS Code refreshes
// stale picker metadata after settings change.
version: `${m.version}-${maxInputTokens}-${outputReserve}`,
detail: hasApiKey ? modelDetail : t('auth.apiKeyRequiredDetail'),
tooltip: hasApiKey ? modelTooltip : t('auth.apiKeyRequiredDetail'),
statusIcon: hasApiKey ? undefined : new vscode.ThemeIcon('warning'),
maxInputTokens: m.maxInputTokens,
maxOutputTokens: m.maxOutputTokens,
maxInputTokens,
maxOutputTokens: outputReserve,
isBYOK: true,
isUserSelectable: true,
capabilities: {
Expand Down