Skip to content

Commit 021e94b

Browse files
committed
Merge branch 'origin/main' into feat/selectable-context-window
Resolve conflict in src/provider/models.ts: main added isBYOK: true to toChatInfo return, while this branch replaced individual maxInputTokens/maxOutputTokens with ...resolveContextWindow(). Keep both.
2 parents ed441a6 + 5263ab2 commit 021e94b

19 files changed

Lines changed: 275 additions & 110 deletions
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
".": "0.6.1"
2+
".": "0.6.2"
33
}

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Changelog
22

3+
## [0.6.2](https://github.com/Vizards/deepseek-v4-for-copilot/compare/v0.6.1...v0.6.2) (2026-06-16)
4+
5+
6+
### Bug Fixes
7+
8+
* **provider:** mark DeepSeek models as BYOK ([#162](https://github.com/Vizards/deepseek-v4-for-copilot/issues/162)) ([50ff6ba](https://github.com/Vizards/deepseek-v4-for-copilot/commit/50ff6ba85b2c8d7911d7f6dddb6492c2ebdb1b17))
9+
* **vision:** disambiguate VS Code LM model selection ([#161](https://github.com/Vizards/deepseek-v4-for-copilot/issues/161)) ([1d7b668](https://github.com/Vizards/deepseek-v4-for-copilot/commit/1d7b6685649b1ee05f3f49f7cd2008b237734c18)), closes [#149](https://github.com/Vizards/deepseek-v4-for-copilot/issues/149)
10+
311
## [0.6.1](https://github.com/Vizards/deepseek-v4-for-copilot/compare/v0.6.0...v0.6.1) (2026-06-12)
412

513

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ Both support optional thinking mode, tool calling, and 1M token context.
103103
| `deepseek-copilot.maxTokens` | `0` | Max output tokens (`0` = no limit). Useful for cost control |
104104
| `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 |
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 |
106-
| `deepseek-copilot.visionModel` | *(auto)* | Which Copilot model to proxy images through |
106+
| `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 |
107107
| `deepseek-copilot.visionPrompt` | *(built-in)* | Prompt used to describe image attachments |
108108
| `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 |
109109

README.zh-cn.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ API Key 存储在 VS Code 的 `SecretStorage` 中(macOS 钥匙串 / Windows
103103
| `deepseek-copilot.maxTokens` | `0` | 最大输出 Token 数(`0` = 不限制)。可用于成本控制 |
104104
| `deepseek-copilot.modelIdOverrides` | 预填官方 ID 映射 | DeepSeek V4 Flash / Pro 对应的 API 模型 ID。仅在使用模型名不同的兼容第三方 API 时修改 |
105105
| `deepseek-copilot.debugMode` | `minimal` | 诊断模式:`minimal` 仅上报 token 用量,`metadata` 输出隐私安全日志,`verbose` 将完整请求 dump 和 pipeline snapshot 写入扩展 global storage。完整 dump 可能包含敏感提示词文本、工具定义、文件片段和图片描述。使用 `DeepSeek: 打开请求 Dump 目录` 打开 dump 位置 |
106-
| `deepseek-copilot.visionModel` | *(自动)* | 用作视觉代理的 Copilot 模型 |
106+
| `deepseek-copilot.visionModel` | *(自动)* | 用作图片代理的 VS Code 视觉模型。请通过 `DeepSeek: 配置视觉代理` 设置;新版保存为 `vendor/id`,旧版裸模型 ID 仍兼容读取 |
107107
| `deepseek-copilot.visionPrompt` | *(内置)* | 用于描述图片附件的提示词 |
108108
| `deepseek-copilot.experimental.stabilizeToolList` | `false` | 实验性设置。尝试预先激活 VS Code/Copilot 的虚拟工具,让传给 DeepSeek API 的 `tools` 参数在多轮对话中更完整、更稳定。当已启用工具跨轮次变化时,可能提高上下文缓存命中率。代价是 input tokens 可能增加;缓存命中的 input tokens 单价更低,但仍会计入用量。64 个或更少已启用工具时通常无需开启,除非工具列表仍在跨轮次变化;超过 128 个已启用工具时不建议开启 |
109109

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"displayName": "DeepSeek V4 for Copilot Chat",
44
"description": "Pick DeepSeek V4 Pro & Flash from the Copilot Chat model picker. Vision, thinking mode, agent tools — zero config, BYOK.",
55
"icon": "resources/icon.png",
6-
"version": "0.6.1",
6+
"version": "0.6.2",
77
"publisher": "Vizards",
88
"license": "MIT",
99
"repository": {

package.nls.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,6 @@
3333
"deepseek-copilot.config.modelIdOverrides.description": "Override the API model ID sent for each DeepSeek model. Defaults are prefilled with official DeepSeek IDs; change them only when using a compatible third-party API that uses different model names.",
3434
"deepseek-copilot.config.modelIdOverrides.deepseek-v4-flash.description": "API model ID for DeepSeek V4 Flash",
3535
"deepseek-copilot.config.modelIdOverrides.deepseek-v4-pro.description": "API model ID for DeepSeek V4 Pro",
36-
"deepseek-copilot.config.visionModel.description": "Compatibility setting managed by [Configure Vision Proxy](command:deepseek-copilot.setVisionModel). Stores the selected VS Code vision model when that source is active.",
36+
"deepseek-copilot.config.visionModel.description": "Compatibility setting managed by [Configure Vision Proxy](command:deepseek-copilot.setVisionModel). Stores the selected VS Code vision model as `vendor/id` when that source is active. Legacy bare model IDs are read for compatibility.",
3737
"deepseek-copilot.config.visionPrompt.description": "Prompt sent to the vision proxy model when describing image attachments before forwarding them to DeepSeek.\n\n[Configure Vision Proxy](command:deepseek-copilot.setVisionModel)"
3838
}

package.nls.zh-cn.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,6 @@
2828
"deepseek-copilot.config.modelIdOverrides.description": "覆盖各 DeepSeek 模型实际使用的 API 模型 ID,默认使用官方 DeepSeek ID,仅在对接不同模型名称的第三方 API 时需要修改。",
2929
"deepseek-copilot.config.modelIdOverrides.deepseek-v4-flash.description": "DeepSeek V4 Flash 的 API 模型 ID。",
3030
"deepseek-copilot.config.modelIdOverrides.deepseek-v4-pro.description": "DeepSeek V4 Pro 的 API 模型 ID。",
31-
"deepseek-copilot.config.visionModel.description": "由[配置视觉代理](command:deepseek-copilot.setVisionModel)管理的兼容设置;当选择 VS Code 视觉模型来源时,用于保存所选模型",
31+
"deepseek-copilot.config.visionModel.description": "由[配置视觉代理](command:deepseek-copilot.setVisionModel)管理的兼容设置;当选择 VS Code 视觉模型来源时,以 `vendor/id` 保存所选模型。旧版裸模型 ID 仍会兼容读取",
3232
"deepseek-copilot.config.visionPrompt.description": "在将图片附件转发给 DeepSeek 之前,发送给视觉代理模型的提示词。\n\n[配置视觉代理](command:deepseek-copilot.setVisionModel)"
3333
}

src/provider/models.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ import { toModelCostInfo, type ModelCostInformation } from './pricing/costs';
77
* NOTE: Non-public API surface.
88
*
99
* The fields below (`configurationSchema` on chat info, cost metadata,
10-
* `modelConfiguration` on response options, plus `isUserSelectable` / `statusIcon`)
10+
* `modelConfiguration` on response options, plus `isBYOK` / `isUserSelectable` /
11+
* `statusIcon`)
1112
* are not part of the stable `vscode.LanguageModelChat*` typings yet. They are
1213
* the same shape currently consumed by GitHub Copilot Chat to render model picker
1314
* metadata and per-model configuration controls.
@@ -27,6 +28,7 @@ type ModelConfigurationSchema = ReturnType<typeof buildModelConfigurationSchema>
2728
export type ModelPickerChatInformation = vscode.LanguageModelChatInformation &
2829
ModelCostInformation & {
2930
readonly isUserSelectable: boolean;
31+
readonly isBYOK: true;
3032
readonly statusIcon?: vscode.ThemeIcon;
3133
readonly configurationSchema?: ModelConfigurationSchema;
3234
};
@@ -48,6 +50,7 @@ export function toChatInfo(
4850
tooltip: hasApiKey ? modelTooltip : t('auth.apiKeyRequiredDetail'),
4951
statusIcon: hasApiKey ? undefined : new vscode.ThemeIcon('warning'),
5052
...resolveContextWindow(m, contextSize),
53+
isBYOK: true,
5154
isUserSelectable: true,
5255
capabilities: {
5356
toolCalling: m.capabilities.toolCalling,

src/provider/vision/log.ts

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import type vscode from 'vscode';
2+
import { t } from '../../i18n';
3+
import { safeStringify } from '../../json';
4+
import { logger } from '../../logger';
5+
import { formatVisionProxyError } from './protocols/errors';
6+
import { getVSCodeVisionTargetChatSessionType } from './sources/vscode/model';
7+
import type { VisionProxyConfig } from './types';
8+
9+
export function showVisionLogs(): void {
10+
logger.show();
11+
}
12+
13+
export function logVSCodeVisionModelSelected(model: vscode.LanguageModelChat): void {
14+
logger.info(
15+
`${t('vision.proxyUsing', model.id)} selected=${formatVSCodeVisionModelIdentity(model)}`,
16+
);
17+
}
18+
19+
export function logVSCodeVisionModelNotFound(modelId: string): void {
20+
logger.warn(t('vision.notFound', modelId));
21+
}
22+
23+
export function logVisionApiEndpointSelected(modelId: string): void {
24+
logger.info(`Vision proxy: ${modelId} source=api-endpoint`);
25+
}
26+
27+
export function logInvalidVisionProxyApiEndpointConfig(
28+
source: string | undefined,
29+
explicitApiEndpointSource: boolean,
30+
error: unknown,
31+
): void {
32+
logger.warn(
33+
`Invalid vision proxy API endpoint configuration; source=${source ?? 'unset'} fallback=${explicitApiEndpointSource ? 'none' : 'vscode-lm'}`,
34+
error,
35+
);
36+
}
37+
38+
export function logVisionProxyUnavailable(): void {
39+
logger.warn(t('vision.unavailable'));
40+
}
41+
42+
export function logVisionProxyDescribeFailed(error: unknown): void {
43+
logger.error(t('vision.proxyError'), formatVisionProxyError(error));
44+
}
45+
46+
export function logVisionProxyTestSucceeded(
47+
config: VisionProxyConfig,
48+
apiKey: string | undefined,
49+
description: string,
50+
): void {
51+
logger.info(
52+
'Vision proxy test succeeded:',
53+
formatVisionProxyTestDiagnostics(config, apiKey, description),
54+
);
55+
}
56+
57+
export function logVisionProxyTestFailed(error: unknown): void {
58+
logger.error('Vision proxy test failed:', formatVisionProxyError(error));
59+
}
60+
61+
function formatVSCodeVisionModelIdentity(model: vscode.LanguageModelChat): string {
62+
return [
63+
formatLogField('id', model.id),
64+
formatLogField('vendor', model.vendor),
65+
formatLogField('name', model.name),
66+
formatLogField('family', model.family),
67+
formatLogField('version', model.version),
68+
formatLogField('targetChatSessionType', getVSCodeVisionTargetChatSessionType(model)),
69+
].join(' ');
70+
}
71+
72+
function formatLogField(name: string, value: unknown): string {
73+
return `${name}=${formatLogValue(value)}`;
74+
}
75+
76+
function formatLogValue(value: unknown): string {
77+
const text = asString(value);
78+
return text ? JSON.stringify(text) : 'n/a';
79+
}
80+
81+
function formatVisionProxyTestDiagnostics(
82+
config: VisionProxyConfig,
83+
apiKey: string | undefined,
84+
description: string,
85+
): string {
86+
return joinDiagnosticParts(
87+
`kind=vision`,
88+
`phase=describe`,
89+
`providerFamily=${safeStringify(config.providerFamily)}`,
90+
`apiType=${safeStringify(config.apiType)}`,
91+
`model=${safeStringify(config.modelId)}`,
92+
`endpoint=${safeStringify(config.url)}`,
93+
`hasApiKey=${Boolean(apiKey?.trim())}`,
94+
`responseChars=${description.length}`,
95+
config.headers ? `headerNames=${safeStringify(Object.keys(config.headers).sort())}` : undefined,
96+
);
97+
}
98+
99+
function joinDiagnosticParts(...parts: (string | undefined)[]): string {
100+
return parts.filter(Boolean).join(' ');
101+
}
102+
103+
function asString(value: unknown): string | undefined {
104+
return typeof value === 'string' && value.trim() ? value.trim() : undefined;
105+
}

0 commit comments

Comments
 (0)