ai-world-sdk 1.2.7 → 1.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/example.test.js +27 -0
- package/dist/__tests__/vscode-login.test.d.ts +1 -0
- package/dist/__tests__/vscode-login.test.js +447 -0
- package/dist/agent-skills.d.ts +96 -0
- package/dist/agent-skills.js +186 -0
- package/dist/config.d.ts +3 -3
- package/dist/config.js +2 -2
- package/dist/database-requests.d.ts +151 -0
- package/dist/database-requests.js +242 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +7 -1
- package/dist/llm.js +5 -0
- package/dist/login.d.ts +6 -0
- package/dist/login.js +33 -1
- package/dist/openai_video_generation.d.ts +5 -4
- package/dist/provider_config.d.ts +1 -1
- package/dist/provider_config.js +2 -0
- package/dist/vscode-login.d.ts +102 -0
- package/dist/vscode-login.js +517 -0
- package/package.json +7 -1
- package/skills/ai-world-sdk/SKILL.md +65 -2
- package/skills/ai-world-sdk/docs/agent-skills.md +78 -0
- package/skills/ai-world-sdk/docs/common-mistakes.md +3 -0
- package/skills/ai-world-sdk/docs/database-requests.md +68 -0
- package/skills/ai-world-sdk/docs/provider-and-models.md +28 -8
- package/skills/ai-world-sdk/docs/vscode-login.md +198 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Agent Skills 管理
|
|
2
|
+
|
|
3
|
+
通过 `AgentSkillClient` 上传、下载、删除、列出 Agent Skills。Skills 存储在后端文件系统 `backend/skills/` 目录。
|
|
4
|
+
|
|
5
|
+
## 基本用法
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
import { AgentSkillClient } from 'ai-world-sdk';
|
|
9
|
+
|
|
10
|
+
const skills = new AgentSkillClient();
|
|
11
|
+
|
|
12
|
+
// 列出所有 skills(支持分页和名称搜索)
|
|
13
|
+
const list = await skills.list({ page: 1, pageSize: 20, name: 'search' });
|
|
14
|
+
// list.items: AgentSkillInfo[], list.total, list.page, list.page_size
|
|
15
|
+
|
|
16
|
+
// 获取 skill 详情
|
|
17
|
+
const detail = await skills.get('web-search');
|
|
18
|
+
// { skill_name, name, description, user_id, created_at, updated_at }
|
|
19
|
+
|
|
20
|
+
// 上传 skill(zip 文件,必须包含 SKILL.md)
|
|
21
|
+
const zipFile = new File([zipContent], 'web-search.zip', { type: 'application/zip' });
|
|
22
|
+
await skills.upload('web-search', zipFile);
|
|
23
|
+
// { message, skill_name, is_update }
|
|
24
|
+
|
|
25
|
+
// 下载 skill(返回 Blob)
|
|
26
|
+
const blob = await skills.download('web-search');
|
|
27
|
+
|
|
28
|
+
// 删除 skill(需要是创建者或管理员)
|
|
29
|
+
await skills.delete('web-search');
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Skill 名称规则
|
|
33
|
+
|
|
34
|
+
- 仅允许小写字母、数字和连字符: `[a-z0-9-]`
|
|
35
|
+
- 不能以连字符开头或结尾
|
|
36
|
+
- 示例: `web-search`, `database`, `llm`
|
|
37
|
+
|
|
38
|
+
## Skill 目录结构
|
|
39
|
+
|
|
40
|
+
每个 Skill 是一个包含 `SKILL.md` 的目录:
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
web-search/
|
|
44
|
+
├── SKILL.md # 必须存在,YAML frontmatter 含 name + description
|
|
45
|
+
├── typescript/ # 可选子目录
|
|
46
|
+
│ └── README.md
|
|
47
|
+
└── python/
|
|
48
|
+
└── README.md
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## SKILL.md 格式
|
|
52
|
+
|
|
53
|
+
```markdown
|
|
54
|
+
---
|
|
55
|
+
name: web-search
|
|
56
|
+
description: 实现 Web 搜索功能...
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
# Web Search Skill
|
|
60
|
+
|
|
61
|
+
详细说明...
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## 权限
|
|
65
|
+
|
|
66
|
+
- 任何登录用户可上传 Skill
|
|
67
|
+
- 创建者和管理员可删除/更新
|
|
68
|
+
- 列表和下载无需登录
|
|
69
|
+
|
|
70
|
+
## API 端点
|
|
71
|
+
|
|
72
|
+
| 方法 | 路径 | 说明 |
|
|
73
|
+
|------|------|------|
|
|
74
|
+
| GET | `/api/agent-skills/` | 列出 skills(分页 + 搜索) |
|
|
75
|
+
| POST | `/api/agent-skills/upload` | 上传 skill(FormData: skill_name + skill_zip) |
|
|
76
|
+
| GET | `/api/agent-skills/{name}` | 获取详情 |
|
|
77
|
+
| GET | `/api/agent-skills/{name}/download` | 下载 zip |
|
|
78
|
+
| DELETE | `/api/agent-skills/{name}` | 删除 |
|
|
@@ -13,3 +13,6 @@
|
|
|
13
13
|
| MinIO 路径包含前导斜杠 | 路径不要以 `/` 开头,如 `docs/file.txt` 而非 `/docs/file.txt` |
|
|
14
14
|
| 资源管理与 MinIO 混用 | `MinioStorageClient` 是原始存储(无权限控制),`ResourceClient` 带 ACL |
|
|
15
15
|
| 资源管理忘记权限 | 上传默认 `private`,需显式设 `accessLevel: 'public'` 才能被他人访问 |
|
|
16
|
+
| 建表请求忘设 pluginId | 先调 `sdkConfig.setPluginId('xxx')`,表名会自动加 `{pluginId}_` 前缀 |
|
|
17
|
+
| Agent Skill 名称含大写 | Skill 名称只允许 `[a-z0-9-]`,全小写 |
|
|
18
|
+
| Agent Skill zip 缺 SKILL.md | zip 中必须包含 `SKILL.md` 文件(含 YAML frontmatter) |
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# 数据库请求
|
|
2
|
+
|
|
3
|
+
通过 `DatabaseRequestClient` 提交建表/迁移请求、查看请求列表和详情。所有登录用户可提交请求,管理员审核通过后自动执行。
|
|
4
|
+
|
|
5
|
+
## 基本用法
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
import { DatabaseRequestClient, sdkConfig } from 'ai-world-sdk';
|
|
9
|
+
|
|
10
|
+
sdkConfig.setPluginId('my-plugin');
|
|
11
|
+
const dbRequests = new DatabaseRequestClient();
|
|
12
|
+
|
|
13
|
+
// 提交建表请求
|
|
14
|
+
const req = await dbRequests.submitCreateRequest({
|
|
15
|
+
tableName: 'user_scores',
|
|
16
|
+
schemaDefinition: {
|
|
17
|
+
columns: [
|
|
18
|
+
{ name: 'id', type: 'integer', primary_key: true, auto_increment: true, nullable: false },
|
|
19
|
+
{ name: 'user_id', type: 'integer', nullable: false },
|
|
20
|
+
{ name: 'score', type: 'float', nullable: false },
|
|
21
|
+
],
|
|
22
|
+
indexes: [{ name: 'idx_user_id', columns: ['user_id'] }],
|
|
23
|
+
},
|
|
24
|
+
description: '用户评分表',
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// 提交迁移请求
|
|
28
|
+
await dbRequests.submitMigrateRequest({
|
|
29
|
+
tableName: 'user_scores',
|
|
30
|
+
migrationSql: 'ALTER TABLE my_plugin_user_scores ADD COLUMN level INTEGER DEFAULT 0;',
|
|
31
|
+
description: '添加 level 字段',
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// 列出请求(普通用户看自己的,管理员看全部)
|
|
35
|
+
const list = await dbRequests.listRequests({ status: 'pending', page: 1, pageSize: 20 });
|
|
36
|
+
|
|
37
|
+
// 获取请求总数
|
|
38
|
+
const total = await dbRequests.getRequestCount({ status: 'pending' });
|
|
39
|
+
|
|
40
|
+
// 获取请求详情
|
|
41
|
+
const detail = await dbRequests.getRequest(req.id);
|
|
42
|
+
|
|
43
|
+
// 审核请求(需 can_manage_database 权限)
|
|
44
|
+
await dbRequests.reviewRequest(req.id, 'approve', '审核通过');
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## 表名规则
|
|
48
|
+
|
|
49
|
+
- 实际表名 = `{pluginId}_{tableName}`
|
|
50
|
+
- 只允许 `[a-z0-9_]`
|
|
51
|
+
|
|
52
|
+
## 列类型白名单
|
|
53
|
+
|
|
54
|
+
integer, bigint, varchar, text, boolean, float, decimal, date, datetime, timestamp, json, jsonb
|
|
55
|
+
|
|
56
|
+
## 迁移 SQL 限制
|
|
57
|
+
|
|
58
|
+
禁止: DROP DATABASE, TRUNCATE, DROP SCHEMA
|
|
59
|
+
|
|
60
|
+
## API 端点
|
|
61
|
+
|
|
62
|
+
| 方法 | 路径 | 说明 |
|
|
63
|
+
|------|------|------|
|
|
64
|
+
| POST | `/api/database/table-requests` | 提交建表/迁移请求 |
|
|
65
|
+
| GET | `/api/database/table-requests` | 列出请求 |
|
|
66
|
+
| GET | `/api/database/table-requests/count` | 请求总数 |
|
|
67
|
+
| GET | `/api/database/table-requests/{id}` | 请求详情 |
|
|
68
|
+
| PATCH | `/api/database/table-requests/{id}` | 审核请求 |
|
|
@@ -5,11 +5,27 @@
|
|
|
5
5
|
| Provider | EndpointType | 说明 |
|
|
6
6
|
|----------|-------------|------|
|
|
7
7
|
| `api2img` | `openai` | **推荐**,聚合所有模型(GPT、Gemini、Claude 等) |
|
|
8
|
-
| `
|
|
8
|
+
| `api2img` | `gemini` | Google Gemini 原生 |
|
|
9
|
+
| `api2img` | `anthropic` | Anthropic Claude 原生 |
|
|
9
10
|
| `shubiaobiao` | `openai` | 数标标 |
|
|
10
|
-
| `
|
|
11
|
+
| `shubiaobiao` | `gemini` | 数标标 Gemini |
|
|
12
|
+
| `shubiaobiao` | `anthropic` | 数标标 Claude |
|
|
13
|
+
| `aiping` | `openai` | 平音 |
|
|
14
|
+
| `aiping` | `gemini` | 平音 Gemini |
|
|
15
|
+
| `aiping` | `anthropic` | 平音 Claude |
|
|
16
|
+
| `gemini` | `gemini` | Google 原生,仅限 Gemini 系列模型 |
|
|
17
|
+
| `openrouter` | `openrouter` | OpenRouter 兼容,模型兼容 OpenRouter 格式,可包括 GPT、以及经聚合的 Gemini/Claude 等(视 provider 能力),模型ID必须以gateway方式设置,如openai/gpt-4o-mini |
|
|
11
18
|
|
|
12
|
-
|
|
19
|
+
## EndpointType 与模型对应关系
|
|
20
|
+
|
|
21
|
+
| EndpointType | 适用模型 | 说明 |
|
|
22
|
+
|--------------|----------|------|
|
|
23
|
+
| `gemini` | Google Gemini | 必须使用 Google 的 Gemini 模型(如 `gemini-2.5-flash`、`gemini-2.5-pro`) |
|
|
24
|
+
| `anthropic` | Claude | 必须使用 Anthropic 的 Claude 模型(如 `claude-sonnet-4-5`、`claude-3-5-sonnet`);**仅 api2img、shubiaobiao、aiping 支持此 endpoint** |
|
|
25
|
+
| `openai` | OpenAI 兼容 | 模型兼容 OpenAI 格式,可包括 GPT、以及经聚合的 Gemini/Claude 等(视 provider 能力) |
|
|
26
|
+
| `openrouter` | OpenRouter 兼容 | OpenRouter 兼容,模型兼容 OpenRouter 格式,可包括 GPT、以及经聚合的 Gemini/Claude 等(视 provider 能力),模型ID必须以gateway方式设置,如openai/gpt-4o-mini |
|
|
27
|
+
|
|
28
|
+
规则:**anthropic 不是 provider**,仅 **api2img**、**shubiaobiao**、**aiping** 支持 EndpointType 为 `anthropic`(调用 Claude);`gemini` provider 用 `gemini` endpoint,其余按上表组合。
|
|
13
29
|
|
|
14
30
|
> `doubao` 不通过 `createProvider` 使用,豆包有专用客户端(见 image-generation.md / video-generation.md)。
|
|
15
31
|
|
|
@@ -26,10 +42,13 @@ const model = provider.languageModel('gpt-4o-mini');
|
|
|
26
42
|
### 不同供应商
|
|
27
43
|
|
|
28
44
|
```typescript
|
|
29
|
-
// Gemini
|
|
45
|
+
// Google Gemini(EndpointType = gemini,仅 Google 模型)
|
|
30
46
|
createProvider('gemini', 'gemini', 'my-plugin').languageModel('gemini-2.5-flash');
|
|
31
47
|
|
|
32
|
-
// api2img
|
|
48
|
+
// Anthropic Claude(仅 api2img / shubiaobiao / aiping 支持 endpointType = anthropic,仅 Claude 模型)
|
|
49
|
+
createProvider('api2img', 'anthropic', 'my-plugin').languageModel('claude-sonnet-4-5');
|
|
50
|
+
|
|
51
|
+
// OpenAI 兼容(EndpointType = openai,模型兼容 OpenAI 格式;api2img 可聚合多模型)
|
|
33
52
|
const p = createProvider('api2img', 'openai', 'my-plugin');
|
|
34
53
|
p.languageModel('gpt-4o-mini');
|
|
35
54
|
p.languageModel('gemini-2.5-flash');
|
|
@@ -47,9 +66,10 @@ const ok = await checkModel('api2img', 'openai', 'gpt-4o-mini', 'my-plugin');
|
|
|
47
66
|
|
|
48
67
|
| 模型 | 类型 | Provider | EndpointType |
|
|
49
68
|
|------|------|----------|-------------|
|
|
50
|
-
| `gpt-4o-mini` / `gpt-4o` / `gpt-5.1` | 文本 | `api2img` | `openai
|
|
51
|
-
| `gemini-2.5-flash` / `gemini-2.5-pro` | 文本 | `gemini` | `gemini
|
|
52
|
-
| `
|
|
69
|
+
| `gpt-4o-mini` / `gpt-4o` / `gpt-5.1` | 文本 | `api2img` | `openai`(OpenAI 兼容) |
|
|
70
|
+
| `gemini-2.5-flash` / `gemini-2.5-pro` | 文本 | `gemini` | `gemini`(仅 Google) |
|
|
71
|
+
| `claude-sonnet-4-6` / `claude-opus-4-6` | 文本 | `api2img`、`shubiaobiao` 或 `aiping` | `anthropic`(仅 Claude) |
|
|
72
|
+
| `dall-e-3` / `gpt-image-1` | 图像 | `api2img`、`shubiaobiao` 或 `aiping` | `openai` |
|
|
53
73
|
| `doubao-seedream-4-5-251128` | 图像 | — | 专用客户端 |
|
|
54
74
|
|
|
55
75
|
## AI SDK 函数速查
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# VSCode 扩展登录集成
|
|
2
|
+
|
|
3
|
+
通过 `ai-world-sdk/vscode` 为 VSCode 扩展插件提供一步到位的 AI World 认证集成。
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
VSCode 扩展的 `package.json`:
|
|
8
|
+
|
|
9
|
+
```json
|
|
10
|
+
{
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"ai-world-sdk": "latest",
|
|
13
|
+
"ai": "^6.0.85"
|
|
14
|
+
},
|
|
15
|
+
"devDependencies": {
|
|
16
|
+
"@types/vscode": "^1.85.0"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## 最简初始化(一步到位)
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
import * as vscode from 'vscode';
|
|
25
|
+
import { initAIWorld } from 'ai-world-sdk/vscode';
|
|
26
|
+
|
|
27
|
+
export async function activate(context: vscode.ExtensionContext) {
|
|
28
|
+
const ai = await initAIWorld(context);
|
|
29
|
+
// 完成!sdkConfig 已自动配置,可直接使用所有 SDK 功能
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function deactivate() {}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
`initAIWorld` 自动完成:
|
|
36
|
+
1. 从 `vscode.SecretStorage` 读取缓存的 token / user / baseUrl
|
|
37
|
+
2. 验证 token 有效性(有效则复用,无效则弹窗提示登录)
|
|
38
|
+
3. 配置 `sdkConfig`(token / baseUrl / pluginId / headers)
|
|
39
|
+
4. 注册命令:`aiWorld.login` / `aiWorld.logout` / `aiWorld.showLoginPanel`
|
|
40
|
+
5. 显示状态栏登录状态
|
|
41
|
+
6. 将认证信息持久化到 `vscode.SecretStorage`
|
|
42
|
+
|
|
43
|
+
## pluginId 规则
|
|
44
|
+
|
|
45
|
+
`pluginId` 默认取扩展 `package.json` 的 `name` 字段(即 `context.extension.packageJSON.name`)。也可通过选项手动指定:
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
const ai = await initAIWorld(context, { pluginId: 'custom-id' });
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## 带选项的初始化
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
const ai = await initAIWorld(context, {
|
|
55
|
+
pluginId: 'my-extension', // 可选,默认取 package.json name
|
|
56
|
+
baseUrl: 'https://aiworld.local:8000', // 可选,默认值
|
|
57
|
+
autoLogin: true, // 可选,默认 true(弹窗提示登录)
|
|
58
|
+
debug: false, // 可选,默认 false
|
|
59
|
+
timeout: 120000, // 登录超时 ms,默认 120000
|
|
60
|
+
callbackPort: 18000, // OAuth 回调端口,默认 18000
|
|
61
|
+
});
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## 返回实例 API
|
|
65
|
+
|
|
66
|
+
`initAIWorld` 返回 `AIWorldExtension` 实例:
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
const ai = await initAIWorld(context);
|
|
70
|
+
|
|
71
|
+
// ── 属性 ──
|
|
72
|
+
ai.token // string | undefined - 当前 JWT token
|
|
73
|
+
ai.user // AuthenticatedUser | undefined - 当前用户
|
|
74
|
+
ai.pluginId // string - 插件 ID(默认 = package.json name)
|
|
75
|
+
ai.baseUrl // string - 后端地址
|
|
76
|
+
ai.isAuthenticated // boolean - 是否已认证
|
|
77
|
+
|
|
78
|
+
// ── 方法 ──
|
|
79
|
+
await ai.login() // 执行登录(有缓存则复用)
|
|
80
|
+
await ai.logout() // 退出登录(清除 SecretStorage)
|
|
81
|
+
ai.showLoginPanel() // 打开 Webview 登录管理面板
|
|
82
|
+
|
|
83
|
+
// ── 事件 ──
|
|
84
|
+
ai.onDidChangeAuthentication((authenticated: boolean) => {
|
|
85
|
+
console.log('认证状态:', authenticated);
|
|
86
|
+
});
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## 在任意位置获取实例
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
import { getAIWorld } from 'ai-world-sdk/vscode';
|
|
93
|
+
|
|
94
|
+
// 在 initAIWorld 调用后,任何地方都可以获取实例
|
|
95
|
+
const ai = getAIWorld();
|
|
96
|
+
const token = ai.token;
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## 登录后使用 SDK 功能
|
|
100
|
+
|
|
101
|
+
`initAIWorld` 登录成功后会自动调用 `sdkConfig.setToken()` / `sdkConfig.setBaseUrl()` / `sdkConfig.setPluginId()`,因此所有 SDK 模块都可直接使用:
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
import { initAIWorld } from 'ai-world-sdk/vscode';
|
|
105
|
+
import { createProvider, MinioStorageClient, ResourceClient } from 'ai-world-sdk';
|
|
106
|
+
import { generateText } from 'ai';
|
|
107
|
+
|
|
108
|
+
export async function activate(context: vscode.ExtensionContext) {
|
|
109
|
+
const ai = await initAIWorld(context);
|
|
110
|
+
|
|
111
|
+
// 使用 LLM
|
|
112
|
+
const provider = createProvider('api2img', 'openai', ai.pluginId);
|
|
113
|
+
const model = provider.languageModel('gpt-4o-mini');
|
|
114
|
+
const result = await generateText({ model, prompt: '你好' });
|
|
115
|
+
|
|
116
|
+
// 使用 MinIO 存储
|
|
117
|
+
const storage = new MinioStorageClient();
|
|
118
|
+
await storage.upload('path/to/file.txt', someFile);
|
|
119
|
+
|
|
120
|
+
// 使用资源管理
|
|
121
|
+
const resources = new ResourceClient();
|
|
122
|
+
const myFiles = await resources.listMy();
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## 命令注册
|
|
127
|
+
|
|
128
|
+
`initAIWorld` 自动注册以下命令(需在扩展 `package.json` 的 `contributes.commands` 中声明):
|
|
129
|
+
|
|
130
|
+
```json
|
|
131
|
+
{
|
|
132
|
+
"contributes": {
|
|
133
|
+
"commands": [
|
|
134
|
+
{ "command": "aiWorld.login", "title": "AI World: 登录" },
|
|
135
|
+
{ "command": "aiWorld.logout", "title": "AI World: 退出登录" },
|
|
136
|
+
{ "command": "aiWorld.showLoginPanel", "title": "AI World: 登录面板" }
|
|
137
|
+
]
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## 存储方式
|
|
143
|
+
|
|
144
|
+
认证信息通过 `vscode.SecretStorage`(`context.secrets`)安全存储,包括:
|
|
145
|
+
|
|
146
|
+
| Key | 内容 |
|
|
147
|
+
|-----|------|
|
|
148
|
+
| `ai-world:token` | JWT token |
|
|
149
|
+
| `ai-world:user` | JSON 序列化的用户信息 |
|
|
150
|
+
| `ai-world:baseUrl` | 后端地址 |
|
|
151
|
+
|
|
152
|
+
SecretStorage 由 VSCode 管理,数据加密存储在系统密钥链中,无需手动管理文件。登出时自动清除。
|
|
153
|
+
|
|
154
|
+
## 登录流程详解
|
|
155
|
+
|
|
156
|
+
```
|
|
157
|
+
扩展 activate → initAIWorld(context)
|
|
158
|
+
├─ 从 SecretStorage 读取缓存
|
|
159
|
+
├─ 有 token?→ validateToken(baseUrl, token)
|
|
160
|
+
│ ├─ 有效 → 获取用户信息 → 配置 sdkConfig → 保存 SecretStorage → ✅ 完成
|
|
161
|
+
│ └─ 无效 → 清除 SecretStorage → 继续下一步
|
|
162
|
+
├─ autoLogin=true?
|
|
163
|
+
│ ├─ 弹出通知提示 "AI World: 未登录,部分功能不可用"
|
|
164
|
+
│ ├─ 用户点击"登录" →
|
|
165
|
+
│ │ ├─ 启动本地回调服务器 (端口 18000)
|
|
166
|
+
│ │ ├─ 打开浏览器 → 飞书 OAuth 登录
|
|
167
|
+
│ │ ├─ 回调返回 token
|
|
168
|
+
│ │ ├─ 获取用户信息 → 配置 sdkConfig
|
|
169
|
+
│ │ └─ 持久化到 SecretStorage → ✅ 完成
|
|
170
|
+
│ └─ 用户点击"稍后" → 等待手动触发 aiWorld.login
|
|
171
|
+
└─ autoLogin=false?→ 等待用户手动触发 aiWorld.login
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## 构建 VSCode 扩展
|
|
175
|
+
|
|
176
|
+
推荐使用 esbuild 打包,将 `vscode` 标记为 external:
|
|
177
|
+
|
|
178
|
+
```javascript
|
|
179
|
+
// esbuild.js
|
|
180
|
+
require('esbuild').build({
|
|
181
|
+
entryPoints: ['src/extension.ts'],
|
|
182
|
+
bundle: true,
|
|
183
|
+
outfile: 'dist/extension.js',
|
|
184
|
+
external: ['vscode'],
|
|
185
|
+
format: 'cjs',
|
|
186
|
+
platform: 'node',
|
|
187
|
+
});
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
打包为 .vsix:
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
npx @vscode/vsce package --no-dependencies
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## 完整示例
|
|
197
|
+
|
|
198
|
+
参见 `ai-world-sdk/examples/vscode-test-extension/`,包含完整的 VSCode 扩展示例代码。
|