Skip to content
Merged
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
38 changes: 33 additions & 5 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,50 @@ title: Wave 代码智聊

[下载最新版本](https://github.com/netease-lcap/wave-vsce/releases) · [查看产品规格](/spec)

## 鉴权配置说明(以下两种方案二选一
## 鉴权配置说明(以下三种方案三选一

### 方案一:OpenAI 兼容格式的 KEY
插件提供三种认证方式,选择其一即可:

### 方案一:SSO 单点登录(推荐内部使用)

填写 **服务端链接** 后,点击 `SSO 登录` 按钮完成认证。支持网易内部 SSO,无需手动管理密钥。

### 方案二:API Key 鉴权

只要是 OpenAI 兼容格式都可以。网易内部推荐使用互娱服务:[AIGW 文档](https://aigw.doc.nie.netease.com/)。外网可使用 OpenAI 或 DeepSeek 官方服务。

### 方案二:用户维度(网易内部)
配置项:

| 字段 | 说明 | 示例 |
| --- | --- | --- |
| **Base URL** | API 服务地址 | `https://api.openai.com/v1` |
| **API Key** | 访问密钥 | `sk-xxxxxxxxxxxxxxxx` |
| **Model** | 主模型名称 | `gpt-4` |
| **Fast Model** | 快速模型名称 | `gpt-3.5-turbo` |

### 方案三:Headers 自定义鉴权(网易内部 AIGW)

1. 打开 [ModelSpace App 管理](https://modelspace.netease.com/model_access/app_manage),新建 App,生成的 **App Code** 将作为 `X-AIGW-APP`。
2. 给 App 添加成员。
3. 每个成员访问 [权限控制台](https://console-auth.nie.netease.com/mymessage/mymessage),复制 **v2 Token** 内容,作为 `X-Access-Token`。
4. 在插件配置中添加 Headers(每行一个 `Key: Value`):
4. 选择 `Headers` 认证方式,在 Headers 配置中添加(每行一个 `Key: Value`):

```
X-AIGW-APP: your_app_code
X-Access-Token: your_access_token
```

5. 将 **BASE URL** 配置为:`https://aigw.netease.com/v1`
5. 将 **Base URL** 配置为:`https://aigw.netease.com/v1`

## 环境变量配置(可选)

以上配置项均可通过环境变量预设,表单中会显示为占位符(敏感信息已脱敏):

| 环境变量 | 对应配置项 |
| --- | --- |
| `WAVE_SERVER_URL` | 服务端链接 |
| `WAVE_API_KEY` | API Key(占位符中显示为 `****`) |
| `WAVE_CUSTOM_HEADERS` | Headers |
| `WAVE_BASE_URL` | Base URL |
| `WAVE_MODEL` | Model |
| `WAVE_FAST_MODEL` | Fast Model |
3 changes: 2 additions & 1 deletion docs/spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -594,7 +594,8 @@ Wave 在后台自动维护项目记忆,帮助 AI 持续了解项目演变:

**主要特性:**

- **服务端链接**:配置 Wave AI 服务端地址,用于 SSO 认证。支持环境变量 `WAVE_AI_URL` 作为 fallback,默认 placeholder 提示"请联系管理员获取"。
- **服务端链接**:配置 Wave AI 服务端地址,用于 SSO 认证。支持环境变量 `WAVE_SERVER_URL` 作为 fallback,默认 placeholder 提示"请联系管理员获取"。
- **Model / Fast Model**:SSO 模式下也可配置主模型和快速模型名称,支持环境变量 `WAVE_MODEL` / `WAVE_FAST_MODEL` 作为 placeholder 提示。
- **SSO 登录/登出**:当配置了服务端链接后,用户可通过 SSO 认证进行登录,无需手动配置 API Key。登录后所有 API 请求自动通过 Wave AI 代理路由。
- **浏览器登录**:点击"SSO 登录"后自动打开浏览器,用户在 Wave AI 登录页完成认证(支持 SSO 企业身份提供商或账号密码登录),授权码通过 localhost 回调自动交换为 JWT 并保存。VS Code Remote SSH 环境会自动转发端口,远程服务器体验与本地一致。
- **登录状态显示**:已认证时显示用户邮箱/ID 和登出按钮;登出后自动恢复为直接 LLM API 模式。
Expand Down
12 changes: 6 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "wave-vscode-chat",
"displayName": "Wave 代码智聊",
"description": "Wave code for VS Code",
"version": "0.4.6",
"version": "0.4.7",
"publisher": "wave-code",
"icon": "LOGO.png",
"repository": {
Expand Down Expand Up @@ -127,6 +127,6 @@
"dompurify": "^3.3.0",
"marked": "^9.1.6",
"mermaid": "^11.12.2",
"wave-agent-sdk": "^0.16.3"
"wave-agent-sdk": "^0.16.4"
}
}
14 changes: 12 additions & 2 deletions src/services/configurationService.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as vscode from 'vscode';

export interface ConfigurationData {
authMethod?: 'sso' | 'apiKey' | 'headers';
aiUrl?: string;
apiKey?: string;
headers?: string;
Expand All @@ -17,20 +18,27 @@ export interface ConfigurationData {
envFastModel?: string;
}

/** Mask a secret value, keeping first 4 and last 4 characters visible */
function maskSecret(value: string): string {
if (value.length <= 10) return '****';
return value.slice(0, 4) + '****' + value.slice(-4);
}

export class ConfigurationService {
constructor(private context: vscode.ExtensionContext) {}

public async loadConfiguration(): Promise<ConfigurationData> {
return {
authMethod: this.context.globalState.get<'sso' | 'apiKey' | 'headers'>('authMethod') || 'sso',
aiUrl: this.context.globalState.get<string>('aiUrl') || '',
apiKey: this.context.globalState.get<string>('apiKey') || '',
headers: this.context.globalState.get<string>('headers') || '',
baseURL: this.context.globalState.get<string>('baseURL') || '',
model: this.context.globalState.get<string>('model') || '',
fastModel: this.context.globalState.get<string>('fastModel') || '',
language: this.context.globalState.get<string>('language') || 'Chinese',
envAiUrl: process.env.WAVE_AI_URL || undefined,
envApiKey: process.env.WAVE_API_KEY || undefined,
envAiUrl: process.env.WAVE_SERVER_URL || undefined,
envApiKey: process.env.WAVE_API_KEY ? maskSecret(process.env.WAVE_API_KEY) : undefined,
envHeaders: process.env.WAVE_CUSTOM_HEADERS || undefined,
envBaseUrl: process.env.WAVE_BASE_URL || undefined,
envModel: process.env.WAVE_MODEL || undefined,
Expand All @@ -40,6 +48,8 @@ export class ConfigurationService {

public async saveConfiguration(configData: Partial<ConfigurationData>): Promise<void> {
try {
if (configData.authMethod !== undefined) await this.context.globalState.update('authMethod', configData.authMethod);
if (configData.aiUrl !== undefined) await this.context.globalState.update('aiUrl', configData.aiUrl);
if (configData.apiKey !== undefined) await this.context.globalState.update('apiKey', configData.apiKey);
if (configData.headers !== undefined) await this.context.globalState.update('headers', configData.headers);
if (configData.baseURL !== undefined) await this.context.globalState.update('baseURL', configData.baseURL);
Expand Down
4 changes: 2 additions & 2 deletions src/session/chatSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ export class ChatSession {

const isAuthValid = (!!config.apiKey || !!process.env.WAVE_API_KEY)
|| (!!config.headers || !!process.env.WAVE_CUSTOM_HEADERS)
|| (!!config.aiUrl || !!process.env.WAVE_AI_URL);
const isBaseURLValid = !!config.baseURL || !!process.env.WAVE_BASE_URL || !!config.aiUrl || !!process.env.WAVE_AI_URL;
|| (!!config.aiUrl || !!process.env.WAVE_SERVER_URL);
const isBaseURLValid = !!config.baseURL || !!process.env.WAVE_BASE_URL || !!config.aiUrl || !!process.env.WAVE_SERVER_URL;

const agentCallbacks: AgentCallbacks = {
onMessagesChange: (messages: Message[]) => {
Expand Down
Loading
Loading