@vibe-forge/core 0.3.0 → 0.5.0
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/package.json +29 -10
- package/src/adapter/type.ts +10 -1
- package/src/channel.ts +132 -0
- package/src/config/load.ts +122 -0
- package/src/config/types.ts +269 -0
- package/src/config.ts +2 -375
- package/src/controllers/benchmark/discover.ts +89 -0
- package/src/controllers/benchmark/index.ts +24 -0
- package/src/controllers/benchmark/result-store.ts +46 -0
- package/src/controllers/benchmark/runner.ts +415 -0
- package/src/controllers/benchmark/schema.ts +60 -0
- package/src/controllers/benchmark/types.ts +80 -0
- package/src/controllers/benchmark/utils.ts +144 -0
- package/src/controllers/benchmark/workspace.ts +179 -0
- package/src/controllers/config/index.ts +7 -0
- package/src/controllers/task/generate-adapter-query-options.ts +12 -2
- package/src/controllers/task/prepare.ts +1 -1
- package/src/controllers/task/run.ts +115 -35
- package/src/env.ts +9 -8
- package/src/hooks/type.ts +35 -88
- package/src/index.ts +2 -1
- package/src/tools.ts +46 -0
- package/src/types.ts +2 -1
- package/src/utils/api.ts +32 -0
- package/src/utils/definition-loader.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibe-forge/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"imports": {
|
|
5
5
|
"#~/*.js": {
|
|
6
6
|
"__vibe-forge__": {
|
|
@@ -22,22 +22,22 @@
|
|
|
22
22
|
"require": "./dist/index.js"
|
|
23
23
|
}
|
|
24
24
|
},
|
|
25
|
-
"./
|
|
25
|
+
"./adapter": {
|
|
26
26
|
"__vibe-forge__": {
|
|
27
|
-
"default": "./src/
|
|
27
|
+
"default": "./src/adapter/index.ts"
|
|
28
28
|
},
|
|
29
29
|
"default": {
|
|
30
|
-
"import": "./dist/
|
|
31
|
-
"require": "./dist/
|
|
30
|
+
"import": "./dist/adapter.mjs",
|
|
31
|
+
"require": "./dist/adapter.js"
|
|
32
32
|
}
|
|
33
33
|
},
|
|
34
|
-
"./
|
|
34
|
+
"./channel": {
|
|
35
35
|
"__vibe-forge__": {
|
|
36
|
-
"default": "./src/
|
|
36
|
+
"default": "./src/channel.ts"
|
|
37
37
|
},
|
|
38
38
|
"default": {
|
|
39
|
-
"import": "./dist/
|
|
40
|
-
"require": "./dist/
|
|
39
|
+
"import": "./dist/channel.mjs",
|
|
40
|
+
"require": "./dist/channel.js"
|
|
41
41
|
}
|
|
42
42
|
},
|
|
43
43
|
"./schema": {
|
|
@@ -57,7 +57,26 @@
|
|
|
57
57
|
"import": "./dist/hooks/index.mjs",
|
|
58
58
|
"require": "./dist/hooks/index.js"
|
|
59
59
|
}
|
|
60
|
-
}
|
|
60
|
+
},
|
|
61
|
+
"./utils/*": {
|
|
62
|
+
"__vibe-forge__": {
|
|
63
|
+
"default": "./src/utils/*.ts"
|
|
64
|
+
},
|
|
65
|
+
"default": {
|
|
66
|
+
"import": "./dist/utils/*.mjs",
|
|
67
|
+
"require": "./dist/utils/*.js"
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
"./controllers/*": {
|
|
71
|
+
"__vibe-forge__": {
|
|
72
|
+
"default": "./src/controllers/*/index.ts"
|
|
73
|
+
},
|
|
74
|
+
"default": {
|
|
75
|
+
"import": "./dist/controllers/*/index.mjs",
|
|
76
|
+
"require": "./dist/controllers/*/index.js"
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
"./package.json": "./package.json"
|
|
61
80
|
},
|
|
62
81
|
"dependencies": {
|
|
63
82
|
"fast-glob": "^3.3.3",
|
package/src/adapter/type.ts
CHANGED
|
@@ -10,7 +10,7 @@ export type AdapterOutputEvent =
|
|
|
10
10
|
| { type: 'init'; data: SessionInitInfo }
|
|
11
11
|
| { type: 'summary'; data: SessionSummaryInfo }
|
|
12
12
|
| { type: 'message'; data: ChatMessage }
|
|
13
|
-
| { type: 'exit'; data: { exitCode
|
|
13
|
+
| { type: 'exit'; data: { exitCode?: number; stderr?: string } }
|
|
14
14
|
| { type: 'stop'; data?: ChatMessage }
|
|
15
15
|
|
|
16
16
|
export type SessionInfo =
|
|
@@ -66,6 +66,7 @@ export interface AdapterQueryOptions {
|
|
|
66
66
|
|
|
67
67
|
systemPrompt?: string
|
|
68
68
|
appendSystemPrompt?: boolean
|
|
69
|
+
permissionMode?: 'default' | 'acceptEdits' | 'plan' | 'dontAsk' | 'bypassPermissions'
|
|
69
70
|
|
|
70
71
|
mcpServers?: {
|
|
71
72
|
include?: string[]
|
|
@@ -85,6 +86,10 @@ export interface AdapterQueryOptions {
|
|
|
85
86
|
onEvent: (event: AdapterOutputEvent) => void
|
|
86
87
|
}
|
|
87
88
|
|
|
89
|
+
export interface AdapterInitOptions {
|
|
90
|
+
force?: boolean
|
|
91
|
+
}
|
|
92
|
+
|
|
88
93
|
export interface AdapterSession {
|
|
89
94
|
kill: () => void
|
|
90
95
|
emit: (event: AdapterEvent) => void
|
|
@@ -92,6 +97,10 @@ export interface AdapterSession {
|
|
|
92
97
|
}
|
|
93
98
|
|
|
94
99
|
export interface Adapter {
|
|
100
|
+
init?: (
|
|
101
|
+
ctx: AdapterCtx,
|
|
102
|
+
options: AdapterInitOptions
|
|
103
|
+
) => Promise<void>
|
|
95
104
|
query: (
|
|
96
105
|
ctx: AdapterCtx,
|
|
97
106
|
options: AdapterQueryOptions
|
package/src/channel.ts
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
|
|
3
|
+
export interface ChannelMap {}
|
|
4
|
+
|
|
5
|
+
export type ChannelType = keyof ChannelMap
|
|
6
|
+
|
|
7
|
+
export const channelAccessSchema = z.object({
|
|
8
|
+
// 管理员
|
|
9
|
+
admins: z.array(z.string()).optional().describe(
|
|
10
|
+
'频道管理员账号(sender ID),管理员拥有管理操作权限且不受以下访问控制限制'
|
|
11
|
+
),
|
|
12
|
+
// 会话类型控制
|
|
13
|
+
allowPrivateChat: z.boolean().optional().describe('是否允许私聊消息,默认 true'),
|
|
14
|
+
allowGroupChat: z.boolean().optional().describe('是否允许群聊消息,默认 true'),
|
|
15
|
+
// 群组访问控制
|
|
16
|
+
allowedGroups: z.array(z.string()).optional().describe('群组白名单(channel ID),设置后仅在指定群中响应'),
|
|
17
|
+
blockedGroups: z.array(z.string()).optional().describe('群组黑名单(channel ID),在指定群中不响应'),
|
|
18
|
+
// 用户访问控制
|
|
19
|
+
allowedSenders: z.array(z.string()).optional().describe('发送者白名单(sender ID),设置后仅白名单内的用户可交互'),
|
|
20
|
+
blockedSenders: z.array(z.string()).optional().describe('发送者黑名单(sender ID),黑名单内的用户消息将被忽略')
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
export type ChannelAccessConfig = z.infer<typeof channelAccessSchema>
|
|
24
|
+
|
|
25
|
+
export const channelBaseSchema = z.object({
|
|
26
|
+
// 基础配置
|
|
27
|
+
type: z
|
|
28
|
+
.string().min(1)
|
|
29
|
+
.describe('频道类型'),
|
|
30
|
+
title: z
|
|
31
|
+
.string().optional()
|
|
32
|
+
.describe('频道标题'),
|
|
33
|
+
description: z
|
|
34
|
+
.string().optional()
|
|
35
|
+
.describe('频道说明'),
|
|
36
|
+
enabled: z
|
|
37
|
+
.boolean().optional()
|
|
38
|
+
.describe('是否启用'),
|
|
39
|
+
// 会话行为
|
|
40
|
+
systemPrompt: z
|
|
41
|
+
.string().optional()
|
|
42
|
+
.describe('在此频道启动会话时注入的系统提示词'),
|
|
43
|
+
// 访问权限控制
|
|
44
|
+
access: channelAccessSchema
|
|
45
|
+
.optional()
|
|
46
|
+
.describe('频道访问权限配置')
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
export type ChannelBaseConfig = z.infer<typeof channelBaseSchema>
|
|
50
|
+
|
|
51
|
+
export type ChannelConfigByType<K extends ChannelType> = ChannelBaseConfig & { type: K } & ChannelMap[K]
|
|
52
|
+
|
|
53
|
+
export type ChannelConfig = {
|
|
54
|
+
[K in ChannelType]: ChannelConfigByType<K>
|
|
55
|
+
}[ChannelType]
|
|
56
|
+
|
|
57
|
+
export interface ChannelConnection<TMessage> {
|
|
58
|
+
sendMessage: (message: TMessage) => Promise<void>
|
|
59
|
+
startReceiving?: (options: {
|
|
60
|
+
handlers: ChannelEventHandlers
|
|
61
|
+
}) => Promise<void>
|
|
62
|
+
/**
|
|
63
|
+
* Called when a new session is being created for this channel.
|
|
64
|
+
* The channel implementation can use this to inject channel-specific context
|
|
65
|
+
* (e.g. bot profile fetched from platform API) into the system prompt.
|
|
66
|
+
*/
|
|
67
|
+
generateSystemPrompt?: (inbound: ChannelInboundEvent) => Promise<string | undefined>
|
|
68
|
+
close?: () => Promise<void>
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export interface ChannelLogger {
|
|
72
|
+
error: (...msg: unknown[]) => void | Promise<void>
|
|
73
|
+
warn: (...msg: unknown[]) => void | Promise<void>
|
|
74
|
+
info: (...msg: unknown[]) => void | Promise<void>
|
|
75
|
+
debug: (...msg: unknown[]) => void | Promise<void>
|
|
76
|
+
trace: (...msg: unknown[]) => void | Promise<void>
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export interface ChannelConnectionOptions {
|
|
80
|
+
logger?: ChannelLogger
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export interface ChannelInboundEvent {
|
|
84
|
+
channelType: string
|
|
85
|
+
sessionType: string
|
|
86
|
+
channelId: string
|
|
87
|
+
senderId?: string
|
|
88
|
+
messageId?: string
|
|
89
|
+
text?: string
|
|
90
|
+
replyTo?: {
|
|
91
|
+
receiveId: string
|
|
92
|
+
receiveIdType: string
|
|
93
|
+
}
|
|
94
|
+
ack?: () => Promise<void>
|
|
95
|
+
unack?: () => Promise<void>
|
|
96
|
+
raw: unknown
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export type ChannelEventHandler<TPayload = unknown> = (payload: TPayload) => void | Promise<void>
|
|
100
|
+
|
|
101
|
+
export interface ChannelEventHandlers {
|
|
102
|
+
message?: ChannelEventHandler<ChannelInboundEvent>
|
|
103
|
+
[event: string]: ChannelEventHandler | ChannelEventHandler<ChannelInboundEvent> | undefined
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export interface ChannelDescriptor<
|
|
107
|
+
TConfigSchema extends z.ZodTypeAny = z.ZodTypeAny,
|
|
108
|
+
TMessageSchema extends z.ZodTypeAny = z.ZodTypeAny,
|
|
109
|
+
> {
|
|
110
|
+
type: string
|
|
111
|
+
label: string
|
|
112
|
+
description?: string
|
|
113
|
+
configSchema: TConfigSchema
|
|
114
|
+
messageSchema: TMessageSchema
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export const defineChannelDescriptor = <TConfigSchema extends z.ZodTypeAny, TMessageSchema extends z.ZodTypeAny>(
|
|
118
|
+
descriptor: ChannelDescriptor<TConfigSchema, TMessageSchema>
|
|
119
|
+
) => descriptor
|
|
120
|
+
|
|
121
|
+
export const defineChannel = <TConfigSchema extends z.ZodTypeAny, TMessageSchema extends z.ZodTypeAny>(
|
|
122
|
+
descriptor: ChannelDescriptor<TConfigSchema, TMessageSchema>
|
|
123
|
+
) => descriptor
|
|
124
|
+
|
|
125
|
+
export type ChannelCreateFn<TConfig = unknown, TMessage = unknown> = (
|
|
126
|
+
config: TConfig,
|
|
127
|
+
options?: ChannelConnectionOptions
|
|
128
|
+
) => Promise<ChannelConnection<TMessage>>
|
|
129
|
+
|
|
130
|
+
export const defineCreateChannelConnection = <TConfigSchema extends z.ZodTypeAny, TMessageSchema extends z.ZodTypeAny>(
|
|
131
|
+
connect: ChannelCreateFn<z.infer<TConfigSchema>, z.infer<TMessageSchema>>
|
|
132
|
+
): ChannelCreateFn<z.infer<TConfigSchema>, z.infer<TMessageSchema>> => connect
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs'
|
|
2
|
+
import { readFile } from 'node:fs/promises'
|
|
3
|
+
import { resolve } from 'node:path'
|
|
4
|
+
import process from 'node:process'
|
|
5
|
+
|
|
6
|
+
import { load } from 'js-yaml'
|
|
7
|
+
|
|
8
|
+
import type { AdapterMap, Config } from './types'
|
|
9
|
+
|
|
10
|
+
const loadJSConfig = async (paths: string[]) => {
|
|
11
|
+
for (const path of paths) {
|
|
12
|
+
try {
|
|
13
|
+
const configPath = resolve(process.cwd(), path)
|
|
14
|
+
if (!existsSync(configPath)) {
|
|
15
|
+
continue
|
|
16
|
+
}
|
|
17
|
+
// eslint-disable-next-line ts/no-require-imports
|
|
18
|
+
return (require(configPath)?.default ?? {}) as Config
|
|
19
|
+
} catch (e) {
|
|
20
|
+
console.error(`Failed to load config file ${path}: ${e}`)
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const loadJSONConfig = async (paths: string[], jsonVariables: Record<string, string | null | undefined>) => {
|
|
26
|
+
for (const path of paths) {
|
|
27
|
+
try {
|
|
28
|
+
const configPath = resolve(process.cwd(), path)
|
|
29
|
+
if (!existsSync(configPath)) {
|
|
30
|
+
continue
|
|
31
|
+
}
|
|
32
|
+
const configContent = await readFile(configPath, 'utf-8')
|
|
33
|
+
const configResolvedContent = configContent
|
|
34
|
+
.replace(/\$\{(\w+)\}/g, (_, key) => jsonVariables[key] ?? `$\{${key}}`)
|
|
35
|
+
return JSON.parse(configResolvedContent) as Config
|
|
36
|
+
} catch (e) {
|
|
37
|
+
console.error(`Failed to load config file ${path}: ${e}`)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const loadYAMLConfig = async (paths: string[], jsonVariables: Record<string, string | null | undefined>) => {
|
|
43
|
+
for (const path of paths) {
|
|
44
|
+
try {
|
|
45
|
+
const configPath = resolve(process.cwd(), path)
|
|
46
|
+
if (!existsSync(configPath)) {
|
|
47
|
+
continue
|
|
48
|
+
}
|
|
49
|
+
const configContent = await readFile(configPath, 'utf-8')
|
|
50
|
+
const configResolvedContent = configContent
|
|
51
|
+
.replace(/\$\{(\w+)\}/g, (_, key) => jsonVariables[key] ?? `$\{${key}}`)
|
|
52
|
+
return load(configResolvedContent) as Config
|
|
53
|
+
} catch (e) {
|
|
54
|
+
console.error(`Failed to load config file ${path}: ${e}`)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
let configCache: Promise<readonly [Config | undefined, Config | undefined]> | null = null
|
|
60
|
+
|
|
61
|
+
export const resetConfigCache = () => {
|
|
62
|
+
configCache = null
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export const loadConfig = (options: {
|
|
66
|
+
jsonVariables?: Record<string, string | null | undefined>
|
|
67
|
+
}) => {
|
|
68
|
+
if (configCache) {
|
|
69
|
+
return configCache
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
configCache = (async () =>
|
|
73
|
+
[
|
|
74
|
+
await loadJSONConfig(
|
|
75
|
+
[
|
|
76
|
+
'./.ai.config.json',
|
|
77
|
+
'./infra/.ai.config.json'
|
|
78
|
+
],
|
|
79
|
+
options.jsonVariables ?? {}
|
|
80
|
+
) ??
|
|
81
|
+
await loadYAMLConfig(
|
|
82
|
+
[
|
|
83
|
+
'./.ai.config.yaml',
|
|
84
|
+
'./.ai.config.yml',
|
|
85
|
+
'./infra/.ai.config.yaml',
|
|
86
|
+
'./infra/.ai.config.yml'
|
|
87
|
+
],
|
|
88
|
+
options.jsonVariables ?? {}
|
|
89
|
+
),
|
|
90
|
+
await loadJSONConfig(
|
|
91
|
+
[
|
|
92
|
+
'./.ai.dev.config.json',
|
|
93
|
+
'./infra/.ai.dev.config.json'
|
|
94
|
+
],
|
|
95
|
+
options.jsonVariables ?? {}
|
|
96
|
+
) ??
|
|
97
|
+
await loadYAMLConfig(
|
|
98
|
+
[
|
|
99
|
+
'./.ai.dev.config.yaml',
|
|
100
|
+
'./.ai.dev.config.yml',
|
|
101
|
+
'./infra/.ai.dev.config.yaml',
|
|
102
|
+
'./infra/.ai.dev.config.yml'
|
|
103
|
+
],
|
|
104
|
+
options.jsonVariables ?? {}
|
|
105
|
+
)
|
|
106
|
+
] as const)()
|
|
107
|
+
return configCache
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export const loadAdapterConfig = async <
|
|
111
|
+
K extends keyof AdapterMap,
|
|
112
|
+
>(
|
|
113
|
+
name: K,
|
|
114
|
+
options: { jsonVariables?: Record<string, string> }
|
|
115
|
+
) => {
|
|
116
|
+
const [projectConfig, userConfig] = await loadConfig(options)
|
|
117
|
+
return {
|
|
118
|
+
...(projectConfig?.adapters?.[name] ?? {}),
|
|
119
|
+
...(userConfig?.adapters?.[name] ?? {})
|
|
120
|
+
} as unknown as NonNullable<Config['adapters']>[K]
|
|
121
|
+
}
|
|
122
|
+
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import type { ChannelConfig } from '../channel'
|
|
2
|
+
import type { PluginConfig } from '../hooks'
|
|
3
|
+
|
|
4
|
+
export interface AdapterMap {}
|
|
5
|
+
|
|
6
|
+
export interface AdapterBuiltinModel {
|
|
7
|
+
value: string
|
|
8
|
+
title: string
|
|
9
|
+
description: string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface ModelServiceConfig {
|
|
13
|
+
/**
|
|
14
|
+
* 模型服务展示标题
|
|
15
|
+
*/
|
|
16
|
+
title?: string
|
|
17
|
+
/**
|
|
18
|
+
* 模型服务展示描述
|
|
19
|
+
*/
|
|
20
|
+
description?: string
|
|
21
|
+
/**
|
|
22
|
+
* 模型服务 API 基础 URL
|
|
23
|
+
*/
|
|
24
|
+
apiBaseUrl: string
|
|
25
|
+
/**
|
|
26
|
+
* 模型服务 API 密钥
|
|
27
|
+
*/
|
|
28
|
+
apiKey: string
|
|
29
|
+
/**
|
|
30
|
+
* 模型服务支持的模型列表
|
|
31
|
+
*/
|
|
32
|
+
models?: string[]
|
|
33
|
+
/**
|
|
34
|
+
* 模型服务支持的模型别名
|
|
35
|
+
*/
|
|
36
|
+
modelsAlias?: Record<string, string[]>
|
|
37
|
+
/**
|
|
38
|
+
* 拓展配置,由下游自行消费
|
|
39
|
+
*/
|
|
40
|
+
extra?: Record<string, unknown>
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface RecommendedModelConfig {
|
|
44
|
+
service?: string
|
|
45
|
+
model: string
|
|
46
|
+
title?: string
|
|
47
|
+
description?: string
|
|
48
|
+
placement?: 'modelSelector'
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export type LanguageCode = 'zh' | 'en'
|
|
52
|
+
|
|
53
|
+
export type NotificationTrigger = 'completed' | 'failed' | 'terminated' | 'waiting_input'
|
|
54
|
+
|
|
55
|
+
export interface NotificationEventConfig {
|
|
56
|
+
title?: string
|
|
57
|
+
description?: string
|
|
58
|
+
disabled?: boolean
|
|
59
|
+
sound?: string
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface NotificationConfig {
|
|
63
|
+
disabled?: boolean
|
|
64
|
+
volume?: number
|
|
65
|
+
events?: Partial<Record<NotificationTrigger, NotificationEventConfig>>
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface Config {
|
|
69
|
+
/**
|
|
70
|
+
* 配置目录
|
|
71
|
+
*/
|
|
72
|
+
baseDir?: string
|
|
73
|
+
/**
|
|
74
|
+
* 适配器配置
|
|
75
|
+
*/
|
|
76
|
+
adapters?: Partial<AdapterMap>
|
|
77
|
+
/**
|
|
78
|
+
* 默认适配器名称
|
|
79
|
+
*/
|
|
80
|
+
defaultAdapter?: keyof AdapterMap
|
|
81
|
+
/**
|
|
82
|
+
* 模型服务配置
|
|
83
|
+
*/
|
|
84
|
+
modelServices?: Record<string, ModelServiceConfig>
|
|
85
|
+
/**
|
|
86
|
+
* 频道配置
|
|
87
|
+
*/
|
|
88
|
+
channels?: Record<string, ChannelConfig>
|
|
89
|
+
/**
|
|
90
|
+
* 默认模型服务名称
|
|
91
|
+
*/
|
|
92
|
+
defaultModelService?: string
|
|
93
|
+
/**
|
|
94
|
+
* 默认模型名称
|
|
95
|
+
*/
|
|
96
|
+
defaultModel?: string
|
|
97
|
+
recommendedModels?: RecommendedModelConfig[]
|
|
98
|
+
interfaceLanguage?: LanguageCode
|
|
99
|
+
modelLanguage?: LanguageCode
|
|
100
|
+
/**
|
|
101
|
+
* MCP 服务器配置
|
|
102
|
+
*/
|
|
103
|
+
mcpServers?: Record<
|
|
104
|
+
string,
|
|
105
|
+
& {
|
|
106
|
+
/**
|
|
107
|
+
* 是否启用
|
|
108
|
+
*/
|
|
109
|
+
enabled?: boolean
|
|
110
|
+
/**
|
|
111
|
+
* 环境变量配置
|
|
112
|
+
*/
|
|
113
|
+
env?: Record<string, string>
|
|
114
|
+
}
|
|
115
|
+
& (
|
|
116
|
+
| {
|
|
117
|
+
type?: undefined
|
|
118
|
+
command: string
|
|
119
|
+
args: string[]
|
|
120
|
+
}
|
|
121
|
+
| {
|
|
122
|
+
type: 'sse'
|
|
123
|
+
url: string
|
|
124
|
+
headers: Record<string, string>
|
|
125
|
+
}
|
|
126
|
+
| {
|
|
127
|
+
type: 'http'
|
|
128
|
+
url: string
|
|
129
|
+
headers?: Record<string, string>
|
|
130
|
+
}
|
|
131
|
+
)
|
|
132
|
+
>
|
|
133
|
+
/**
|
|
134
|
+
* 默认启用的 MCP 服务器列表
|
|
135
|
+
*/
|
|
136
|
+
defaultIncludeMcpServers?: string[]
|
|
137
|
+
/**
|
|
138
|
+
* 默认禁用的 MCP 服务器列表
|
|
139
|
+
*/
|
|
140
|
+
defaultExcludeMcpServers?: string[]
|
|
141
|
+
noDefaultVibeForgeMcpServer?: boolean
|
|
142
|
+
/**
|
|
143
|
+
* 权限配置
|
|
144
|
+
*/
|
|
145
|
+
permissions?: {
|
|
146
|
+
allow?: string[]
|
|
147
|
+
deny?: string[]
|
|
148
|
+
ask?: string[]
|
|
149
|
+
defaultMode?: 'default' | 'acceptEdits' | 'plan' | 'dontAsk' | 'bypassPermissions'
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* 环境变量配置
|
|
153
|
+
*/
|
|
154
|
+
env?: Record<string, string>
|
|
155
|
+
/**
|
|
156
|
+
* 公告配置
|
|
157
|
+
*/
|
|
158
|
+
announcements?: string[]
|
|
159
|
+
/**
|
|
160
|
+
* 快捷键配置
|
|
161
|
+
*/
|
|
162
|
+
shortcuts?: {
|
|
163
|
+
newSession?: string
|
|
164
|
+
openConfig?: string
|
|
165
|
+
}
|
|
166
|
+
notifications?: NotificationConfig
|
|
167
|
+
/**
|
|
168
|
+
* 会话配置
|
|
169
|
+
*/
|
|
170
|
+
conversation?: {
|
|
171
|
+
/**
|
|
172
|
+
* 对话风格
|
|
173
|
+
* - `friendly`: 友好的对话风格,适合用户与助手交互
|
|
174
|
+
* - `programmatic`: 程序化的对话风格,适合助手执行任务
|
|
175
|
+
*/
|
|
176
|
+
style?: 'friendly' | 'programmatic'
|
|
177
|
+
/**
|
|
178
|
+
* 自定义对话风格。通过指定提示词约束对话风格。
|
|
179
|
+
*/
|
|
180
|
+
customInstructions?: string
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* 插件配置
|
|
184
|
+
*/
|
|
185
|
+
plugins?: PluginConfig
|
|
186
|
+
enabledPlugins?: Record<string, boolean>
|
|
187
|
+
extraKnownMarketplaces?: Record<
|
|
188
|
+
string,
|
|
189
|
+
{
|
|
190
|
+
source:
|
|
191
|
+
| {
|
|
192
|
+
source: 'github'
|
|
193
|
+
repo: string
|
|
194
|
+
}
|
|
195
|
+
| {
|
|
196
|
+
source: 'git'
|
|
197
|
+
url: string
|
|
198
|
+
}
|
|
199
|
+
| {
|
|
200
|
+
source: 'directory'
|
|
201
|
+
path: string
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
>
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export interface AboutInfo {
|
|
208
|
+
version?: string
|
|
209
|
+
lastReleaseAt?: string
|
|
210
|
+
urls?: {
|
|
211
|
+
repo?: string
|
|
212
|
+
docs?: string
|
|
213
|
+
contact?: string
|
|
214
|
+
issues?: string
|
|
215
|
+
releases?: string
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export interface ConfigSection {
|
|
220
|
+
general?: {
|
|
221
|
+
baseDir?: Config['baseDir']
|
|
222
|
+
defaultAdapter?: Config['defaultAdapter']
|
|
223
|
+
defaultModelService?: Config['defaultModelService']
|
|
224
|
+
defaultModel?: Config['defaultModel']
|
|
225
|
+
recommendedModels?: Config['recommendedModels']
|
|
226
|
+
interfaceLanguage?: Config['interfaceLanguage']
|
|
227
|
+
modelLanguage?: Config['modelLanguage']
|
|
228
|
+
announcements?: Config['announcements']
|
|
229
|
+
permissions?: Config['permissions']
|
|
230
|
+
env?: Config['env']
|
|
231
|
+
notifications?: Config['notifications']
|
|
232
|
+
}
|
|
233
|
+
conversation?: Config['conversation']
|
|
234
|
+
modelServices?: Config['modelServices']
|
|
235
|
+
channels?: Config['channels']
|
|
236
|
+
adapters?: Config['adapters']
|
|
237
|
+
adapterBuiltinModels?: Record<string, AdapterBuiltinModel[]>
|
|
238
|
+
plugins?: {
|
|
239
|
+
plugins?: Config['plugins']
|
|
240
|
+
enabledPlugins?: Config['enabledPlugins']
|
|
241
|
+
extraKnownMarketplaces?: Config['extraKnownMarketplaces']
|
|
242
|
+
}
|
|
243
|
+
mcp?: {
|
|
244
|
+
mcpServers?: Config['mcpServers']
|
|
245
|
+
defaultIncludeMcpServers?: Config['defaultIncludeMcpServers']
|
|
246
|
+
defaultExcludeMcpServers?: Config['defaultExcludeMcpServers']
|
|
247
|
+
noDefaultVibeForgeMcpServer?: Config['noDefaultVibeForgeMcpServer']
|
|
248
|
+
}
|
|
249
|
+
shortcuts?: Config['shortcuts']
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
export interface ConfigResponse {
|
|
253
|
+
sources?: {
|
|
254
|
+
project?: ConfigSection
|
|
255
|
+
user?: ConfigSection
|
|
256
|
+
merged?: ConfigSection
|
|
257
|
+
}
|
|
258
|
+
meta?: {
|
|
259
|
+
workspaceFolder?: string
|
|
260
|
+
configPresent?: {
|
|
261
|
+
project?: boolean
|
|
262
|
+
user?: boolean
|
|
263
|
+
}
|
|
264
|
+
experiments?: Record<string, unknown>
|
|
265
|
+
about?: AboutInfo
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
export const defineConfig = (config: Config) => config
|