KaiCE基于 VS Code 解决的问题Web 版本的 VS Code 将 本扩展将模型配置与 API Key 明文保存在
然后在 VS Code 中通过「开发主机:重新加载窗口」或 F5 调试加载本扩展目录。 配置
在
外部文件形态示例(密钥与配置分离,不进 settings.json):
从
|
| 字段 | 说明 |
|---|---|
vendor |
固定为 customendpoint(致敬官方命名;本扩展注册 ID 为 kaicustomendpoint) |
name |
分组名称,模型选择器中用于区分同供应商的多个分组 |
apiKey |
API Key,支持两种写法:明文(如 "sk-xxxx")或引用("${input:chat.lm.secret.<id>}",从 kaicustomendpoint.secrets 查找);留空则不带 Authorization 头 |
apiType |
chat-completions(默认)/ responses / messages(均完整支持) |
url |
Base URL,支持显式 API 路径;自动拼接 /v1 + API 路径 |
models[] |
模型列表,字段与 customendpoint 一致(id / name / url / apiType / maxInputTokens / maxOutputTokens / contextWindow / toolCalling(默认 true,仅显式 false 时禁用)/ vision(默认 false)/ thinking / streaming / requestHeaders / modelOptions / metadata) |
注:内联补全的
model.apiType(fim/chat)是独立的字段,含义与对话模型的apiType(chat-completions/responses/messages)不同,详见内联补全配置。
如果不想将 API Key 直接写在模型配置中,可以使用引用语法将密钥分离到 kaicustomendpoint.secrets:
引用语法 ${input:chat.lm.secret.<id>} 与 VS Code Copilot 的 chatLanguageModels.json 兼容,迁移时无需修改 apiKey 引用。
自定义请求头
requestHeaders 可用于自定义网关的鉴权方式(如 x-api-key),并允许覆盖 authorization 与 api-key:
{
"id": "my-model",
"requestHeaders": {
"x-api-key": "my-secret"
}
}
扩展字段(metadata)
用于补充协议未覆盖的请求体字段,按协议自适应注入:
- Anthropic 协议(
messages):作为请求体的metadata字段发送(如{"user_id":"xxx"})- Anthropic 顶层为封闭 schema,扩展字段须进
metadata容器
- Anthropic 顶层为封闭 schema,扩展字段须进
- OpenAI 协议(
chat-completions/responses/ FIM 补全):作为extraBody展开,合并到请求体顶层(如{"user":"xxx"})- OpenAI 采用顶层平铺设计,扩展字段为顶层命名参数
已存在的请求体字段优先,不被覆盖。
{
"id": "my-model",
"metadata": {"user_id": "log-user-0001"}
}
调试:-op 推理级别
defaultReasoningEffort(及 supportsReasoningEffort 条目)支持一种特殊的 *-op 写法:以全小写 -op 结尾时(大小写敏感,如 high-op;high-OP 不生效;op 为 output 缩写),KaiCE 会在 VS Code 的 OUTPUT 面板「KaiCE」通道打印本次请求的完整调试信息:
- 请求 Headers(鉴权头部分打码)
- 请求 Body:完整请求体(含
model/messages/max_tokens/stream/reasoning_effort等参数,FIM 补全则为prompt+suffix) - 响应 Status + Headers
- 响应 Body(含 SSE 原始流)
每次请求会生成一个 UID(如 [UID lzw4f-3kf9xq]),同一请求的请求日志、响应日志与异常日志共用该 UID,便于在 OUTPUT 面板中关联定位。
-op 后缀仅作为调试开关,不会写入请求体:high-op 实际发送 reasoning_effort: "high"(或对应协议的 effort 字段)。high 与 high-op 是两个独立条目,可同时存在于 supportsReasoningEffort 列表中,picker 各自独立显示;是否启用调试日志完全由用户选择带 -op 后缀的条目决定。
{
"id": "my-model",
// high 与 high-op 并存:picker 各自独立显示,用户选哪个用哪个
"supportsReasoningEffort": ["low", "medium", "high", "high-op"],
// 默认启用调试日志:打印请求/响应详情到 OUTPUT 面板「KaiCE」,实际发送 reasoning_effort: "high"
"defaultReasoningEffort": "high-op"
}
内联补全(kaicustomendpoint.inlineCompletion.model.defaultReasoningEffort)同样支持 -op 写法。
当前支持范围
- ✅
chat-completionsAPI:文本、工具调用(tool calls)、图片输入(vision)、流式输出 - ✅
responsesAPI:文本、工具调用(function call)、图片输入(vision)、流式输出 - ✅
messagesAPI(Anthropic 兼容):文本、工具调用(tool use)、图片输入(vision)、流式输出 - ✅ 内联补全(inline completion / ghost text):FIM(prompt+suffix)格式,独立于 Copilot 登录/订阅
- ✅ Copilot Agent 免登录使用(BYOK):将 KaiCE 模型标记为「本机自备密钥(BYOK)」模型,让 Copilot Agent 会话(agent-host 的 Copilot agent)直接发现并调用,无需登录 GitHub Copilot(详见下文)
Copilot Agent 免登录使用(BYOK)
BYOK = Bring Your Own Key,即"自带密钥调用自己的模型服务"
KaiCE 默认把所有模型注册为 BYOK 模型(isBYOK),使它们能进入 Copilot Agent 的模型目录。由于模型使用你自己的 API Key,底层并不需要 GitHub Copilot 订阅,因此未登录 GitHub 时也能在 Copilot Agent 中选择并使用这些模型。
原理
- Copilot Agent(agent-host 会话)通过
AgentHostByokLmHandler.listModels()枚举isBYOK且不带targetChatSessionType的模型 - 这些模型经 BYOK 桥接进入
CopilotAgent的模型目录(_byokModels),不依赖 GitHub 登录 token - 会话调用时经
IAgentHostByokLmHandler.chat()→ KaiCE 的 LM provider → 你配置的真实端点(deepseek/qwen/glm 等) - 关键开关
github.copilot.clientByokEnabled:未登录 GitHub 用户默认启用(isClientBYOKAllowed在!hasGitHubSession时直接返回true),因此 BYOK 模型列表不会被清空
配置
默认所有模型都会以 BYOK 身份出现在 Copilot Agent 中。若想排除某模型(或整个分组),设置 byok: false:
{
"name": "deepseek",
"apiKey": "${input:chat.lm.secret.deepseek}",
// 分组级:关闭本分组所有模型的 BYOK 暴露
// "byok": false,
"models": [
{
"id": "deepseek-flash",
"name": "kai-deepseek-flash",
"url": "https://api.deepseek.com/anthropic",
// 模型级:单独排除该模型(优先生效)
// "byok": false
}
]
}
说明:
byok同时接受模型级(优先)与分组级,默认true。模型设为 BYOK 后仍在 Local 通用模型池可选,不会因为标记 BYOK 而消失。
内联补全配置
通过 kaicustomendpoint.inlineCompletion 配置补全(可选,未配置则不注册补全 provider):
{
"kaicustomendpoint.inlineCompletion": {
"pattern": "**",
// 可选:限定语言(字符串或数组)
// "language": ["typescript", "javascript"],
// 可选:提示词模板,支持 {prefix} / {suffix} / {languageId}
// - fim 格式:渲染结果写入 prompt 字段,suffix 置空
// - chat 格式:渲染结果作为整条 user content
// "prompt": "You are a coding assistant, good at completing concise and efficient {languageId} code.\nprefix: {prefix}\nsuffix: {suffix}",
"model": {
"apiKey": "${input:chat.lm.secret.deepseek}",
"id": "deepseek-flash",
"name": "fim-deepseek",
"url": "https://api.deepseek.com/beta/completions",
"defaultReasoningEffort": ""
}
}
}
默认使用 FIM(Fill-in-the-Middle)格式,body 为 { model, prompt, suffix, max_tokens, stream }:
prompt为光标前的文本(前缀),suffix为光标后的文本(后缀)url必须是全地址(如https://api.deepseek.com/beta/completions),不做路径拼接- 自定义
prompt模板时,渲染结果写入prompt字段,suffix字段置空 - 前缀默认保留 2048 token、后缀 512 token(按完整行裁剪,保持代码结构)
- 请求失败静默(不弹错误提示),与 Copilot 无订阅时行为一致
对话接口(apiType: "chat")
模型不支持 FIM 补全接口(仅有 chat 接口的网关/模型)时,可将 model.apiType 设为 chat,
改用 OpenAI /chat/completions 对话格式,上下文组织为单条 user 消息(user + content 格式):
{
"kaicustomendpoint.inlineCompletion": {
"pattern": "**",
// prompt 与 model 平级(外层),chat 格式下渲染结果作为整条 user content
"prompt": "Continue the {languageId} code at <CURSOR>. Code before cursor:\n{prefix}\nCode after cursor:\n{suffix}\nOutput only the code to insert at <CURSOR>, no explanations.",
"model": {
"apiType": "chat",
"apiKey": "${input:chat.lm.secret.bigmodel}",
"id": "glm-5.3-flash",
"name": "fim-glm-chat",
"url": "https://open.bigmodel.cn/api/paas/v4/chat/completions",
"maxOutputTokens": 256
}
}
}
- 请求体为
{ model, messages: [{ role: "user", content: ... }], stream: true, max_tokens, ... } - 配置了
prompt模板时,渲染结果作为整条 usercontent(模板含{suffix}时后缀一并带入) - 未配置
prompt模板时,content仅为光标前缀(不携带后缀,避免模型把后缀内容误当作待补全文本输出;需要控制后缀时请配置模板) - 响应流解析 chat 的
choices[].delta.content增量(同时兼容 FIM 的choices[].text) apiType缺省为fim;仅chat走对话接口,其余取值均按 FIM 处理
已知限制
- API Key 明文存储(设计使然,解决 Web 刷新丢失问题);可通过
kaicustomendpoint.secrets+ 引用语法分离密钥 - 部分能力依赖 proposed API(
chatProvider),本扩展已声明enabledApiProposals: ["chatProvider"](含isBYOK、editTools、Thinking Effort picker、configurationSchema)。若目标 VS Code 版本不支持该 proposal,isBYOK可能不被识别、影响 Copilot Agent 的 BYOK 枚举 - 内联补全为一次性返回完整补全(stable API 不支持 AsyncIterable 渐进式渲染,那是 Copilot 内部私有通道)