@vibe-forge/core 1.0.0 → 2.0.1
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 +12 -3
- package/src/config-schema.ts +513 -0
- package/src/env.ts +1 -1
- package/src/index.ts +1 -0
- package/src/tools.ts +1 -1
- package/src/types.ts +2 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibe-forge/core",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"imports": {
|
|
5
5
|
"#~/*.js": {
|
|
6
6
|
"__vibe-forge__": {
|
|
@@ -31,6 +31,15 @@
|
|
|
31
31
|
"require": "./dist/channel.js"
|
|
32
32
|
}
|
|
33
33
|
},
|
|
34
|
+
"./config-schema": {
|
|
35
|
+
"__vibe-forge__": {
|
|
36
|
+
"default": "./src/config-schema.ts"
|
|
37
|
+
},
|
|
38
|
+
"default": {
|
|
39
|
+
"import": "./dist/config-schema.mjs",
|
|
40
|
+
"require": "./dist/config-schema.js"
|
|
41
|
+
}
|
|
42
|
+
},
|
|
34
43
|
"./schema": {
|
|
35
44
|
"__vibe-forge__": {
|
|
36
45
|
"default": "./src/schema.ts"
|
|
@@ -44,7 +53,7 @@
|
|
|
44
53
|
},
|
|
45
54
|
"dependencies": {
|
|
46
55
|
"zod": "^3.24.1",
|
|
47
|
-
"@vibe-forge/
|
|
48
|
-
"@vibe-forge/
|
|
56
|
+
"@vibe-forge/utils": "^2.0.1",
|
|
57
|
+
"@vibe-forge/types": "^2.0.0"
|
|
49
58
|
}
|
|
50
59
|
}
|
|
@@ -0,0 +1,513 @@
|
|
|
1
|
+
/* eslint-disable max-lines -- central config schema registry */
|
|
2
|
+
import { z } from 'zod'
|
|
3
|
+
|
|
4
|
+
import type {
|
|
5
|
+
ConfigUiField,
|
|
6
|
+
ConfigUiFieldType,
|
|
7
|
+
ConfigUiObjectSchema,
|
|
8
|
+
ConfigUiRecordFieldSchema
|
|
9
|
+
} from '@vibe-forge/types'
|
|
10
|
+
|
|
11
|
+
import { channelBaseSchema } from './channel'
|
|
12
|
+
|
|
13
|
+
export interface ConfigSemanticIssue {
|
|
14
|
+
path?: string[]
|
|
15
|
+
message: string
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
type AdapterConfigSchemaKey<TSchema extends z.AnyZodObject> = Extract<keyof z.infer<TSchema>, string>
|
|
19
|
+
|
|
20
|
+
export interface AdapterConfigEntryMetadata<
|
|
21
|
+
TSchema extends z.AnyZodObject = z.AnyZodObject,
|
|
22
|
+
TExtraCommonKey extends AdapterConfigSchemaKey<TSchema> = never,
|
|
23
|
+
> {
|
|
24
|
+
extraCommonKeys?: readonly TExtraCommonKey[]
|
|
25
|
+
deepMergeKeys?: readonly AdapterConfigSchemaKey<TSchema>[]
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface AdapterConfigContribution<
|
|
29
|
+
TSchema extends z.AnyZodObject = z.AnyZodObject,
|
|
30
|
+
TExtraCommonKey extends AdapterConfigSchemaKey<TSchema> = never,
|
|
31
|
+
> {
|
|
32
|
+
adapterKey: string
|
|
33
|
+
title?: string
|
|
34
|
+
description?: string
|
|
35
|
+
schema: TSchema
|
|
36
|
+
uiSchema?: ConfigUiObjectSchema
|
|
37
|
+
configEntry?: AdapterConfigEntryMetadata<TSchema, TExtraCommonKey>
|
|
38
|
+
validate?: (value: z.infer<TSchema>) => readonly ConfigSemanticIssue[] | void
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const defineAdapterConfigContribution = <
|
|
42
|
+
TSchema extends z.AnyZodObject,
|
|
43
|
+
TExtraCommonKey extends AdapterConfigSchemaKey<TSchema> = never,
|
|
44
|
+
>(
|
|
45
|
+
contribution: AdapterConfigContribution<TSchema, TExtraCommonKey>
|
|
46
|
+
) => contribution
|
|
47
|
+
|
|
48
|
+
export const jsonValueSchema: z.ZodType<unknown> = z.lazy(() =>
|
|
49
|
+
z.union([
|
|
50
|
+
z.string(),
|
|
51
|
+
z.number(),
|
|
52
|
+
z.boolean(),
|
|
53
|
+
z.null(),
|
|
54
|
+
z.array(jsonValueSchema),
|
|
55
|
+
z.record(z.string(), jsonValueSchema)
|
|
56
|
+
])
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
export const effortLevelSchema = z.enum(['low', 'medium', 'high', 'max'])
|
|
60
|
+
export const languageCodeSchema = z.enum(['zh', 'en'])
|
|
61
|
+
|
|
62
|
+
export const adapterAccountConfigCommonSchema = z.object({
|
|
63
|
+
title: z.string().optional().describe('Display title'),
|
|
64
|
+
description: z.string().optional().describe('Display description')
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
export const adapterConfigCommonSchema = z.object({
|
|
68
|
+
defaultModel: z.string().optional().describe('Default model override for this adapter'),
|
|
69
|
+
includeModels: z.array(z.string()).optional().describe('Allowed model IDs for this adapter'),
|
|
70
|
+
excludeModels: z.array(z.string()).optional().describe('Blocked model IDs for this adapter'),
|
|
71
|
+
defaultAccount: z.string().optional().describe('Default account override for this adapter'),
|
|
72
|
+
accounts: z.record(z.string(), adapterAccountConfigCommonSchema).optional()
|
|
73
|
+
.describe('Adapter account display metadata')
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
export const adapterNativeCliConfigSchema = z.object({
|
|
77
|
+
source: z.enum(['managed', 'system', 'path']).optional().describe('Native CLI source'),
|
|
78
|
+
path: z.string().optional().describe('Native CLI binary path when source is path'),
|
|
79
|
+
package: z.string().optional().describe('Managed npm package name'),
|
|
80
|
+
version: z.string().optional().describe('Managed npm package version'),
|
|
81
|
+
autoInstall: z.boolean().optional().describe('Install the managed CLI when no usable binary is found'),
|
|
82
|
+
prepareOnInstall: z.boolean().optional().describe('Preinstall this managed CLI during Vibe Forge package install'),
|
|
83
|
+
npmPath: z.string().optional().describe('npm binary used for managed installs')
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
export const modelServiceConfigSchema = z.object({
|
|
87
|
+
title: z.string().optional().describe('Display title'),
|
|
88
|
+
description: z.string().optional().describe('Display description'),
|
|
89
|
+
apiBaseUrl: z.string().min(1).describe('Provider API base URL'),
|
|
90
|
+
apiKey: z.string().min(1).describe('Provider API key'),
|
|
91
|
+
models: z.array(z.string()).optional().describe('Supported model IDs'),
|
|
92
|
+
timeoutMs: z.number().int().positive().optional().describe('Request timeout in milliseconds'),
|
|
93
|
+
maxOutputTokens: z.number().int().positive().optional().describe('Default max output tokens'),
|
|
94
|
+
extra: z.record(z.string(), jsonValueSchema).optional().describe('Provider-specific extra config')
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
export const recommendedModelConfigSchema = z.object({
|
|
98
|
+
service: z.string().optional().describe('Model service key'),
|
|
99
|
+
model: z.string().min(1).describe('Model ID'),
|
|
100
|
+
title: z.string().optional().describe('Display title'),
|
|
101
|
+
description: z.string().optional().describe('Display description'),
|
|
102
|
+
placement: z.enum(['modelSelector']).optional().describe('UI placement')
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
export const modelMetadataConfigSchema = z.object({
|
|
106
|
+
alias: z.union([z.string(), z.array(z.string())]).optional().describe('Model aliases'),
|
|
107
|
+
title: z.string().optional().describe('Display title'),
|
|
108
|
+
description: z.string().optional().describe('Display description'),
|
|
109
|
+
defaultAdapter: z.string().optional().describe('Preferred adapter key'),
|
|
110
|
+
effort: effortLevelSchema.optional().describe('Recommended effort level')
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
export const notificationEventConfigSchema = z.object({
|
|
114
|
+
title: z.string().optional().describe('Notification title override'),
|
|
115
|
+
description: z.string().optional().describe('Notification description override'),
|
|
116
|
+
disabled: z.boolean().optional().describe('Disable this notification event'),
|
|
117
|
+
sound: z.string().optional().describe('Custom sound asset')
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
export const notificationConfigSchema = z.object({
|
|
121
|
+
disabled: z.boolean().optional().describe('Disable notifications'),
|
|
122
|
+
volume: z.number().min(0).max(100).optional().describe('Notification volume'),
|
|
123
|
+
events: z.object({
|
|
124
|
+
completed: notificationEventConfigSchema.optional(),
|
|
125
|
+
failed: notificationEventConfigSchema.optional(),
|
|
126
|
+
terminated: notificationEventConfigSchema.optional(),
|
|
127
|
+
waiting_input: notificationEventConfigSchema.optional()
|
|
128
|
+
}).optional().describe('Per-event notification overrides')
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
export const permissionsConfigSchema = z.object({
|
|
132
|
+
allow: z.array(z.string()).optional().describe('Allowed tools'),
|
|
133
|
+
deny: z.array(z.string()).optional().describe('Denied tools'),
|
|
134
|
+
ask: z.array(z.string()).optional().describe('Tools that always ask'),
|
|
135
|
+
defaultMode: z.enum(['default', 'acceptEdits', 'plan', 'dontAsk', 'bypassPermissions']).optional()
|
|
136
|
+
.describe('Default permission mode')
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
export const shortcutsConfigSchema = z.object({
|
|
140
|
+
newSession: z.string().optional().describe('Shortcut for creating a new session'),
|
|
141
|
+
openConfig: z.string().optional().describe('Shortcut for opening config'),
|
|
142
|
+
sendMessage: z.string().optional().describe('Shortcut for sending a message'),
|
|
143
|
+
clearInput: z.string().optional().describe('Shortcut for clearing the composer'),
|
|
144
|
+
switchModel: z.string().optional().describe('Shortcut for switching models'),
|
|
145
|
+
switchEffort: z.string().optional().describe('Shortcut for switching effort'),
|
|
146
|
+
switchPermissionMode: z.string().optional().describe('Shortcut for switching permission mode')
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
export const conversationConfigSchema = z.object({
|
|
150
|
+
style: z.enum(['friendly', 'programmatic']).optional().describe('Conversation style'),
|
|
151
|
+
customInstructions: z.string().optional().describe('Extra system instructions'),
|
|
152
|
+
injectDefaultSystemPrompt: z.boolean().optional().describe('Inject the default system prompt')
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
export const webAuthAccountConfigSchema = z.object({
|
|
156
|
+
username: z.string().min(1).describe('Login username'),
|
|
157
|
+
password: z.string().min(1).describe('Login password')
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
export const webAuthConfigSchema = z.object({
|
|
161
|
+
enabled: z.boolean().optional().describe('Enable Web UI login protection'),
|
|
162
|
+
username: z.string().optional().describe('Fallback single-account username'),
|
|
163
|
+
password: z.string().optional().describe('Fallback single-account password'),
|
|
164
|
+
accounts: z.array(webAuthAccountConfigSchema).optional().describe('Allowed Web UI login accounts'),
|
|
165
|
+
sessionTtlHours: z.number().positive().optional().describe('Browser session token lifetime in hours'),
|
|
166
|
+
rememberDeviceTtlDays: z.number().positive().optional().describe('Remember-device token lifetime in days')
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
export const skillRegistryConfigSchema = z.object({
|
|
170
|
+
enabled: z.boolean().optional().describe('Enable remote skill registry resolution'),
|
|
171
|
+
url: z.string().optional().describe('Base URL for remote skill registry search and download'),
|
|
172
|
+
searchUrl: z.string().optional().describe('Remote skill registry search endpoint'),
|
|
173
|
+
downloadUrl: z.string().optional().describe('Remote skill registry download endpoint')
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
export const skillsConfigSchema = z.object({
|
|
177
|
+
registry: z.union([z.string(), skillRegistryConfigSchema]).optional().describe('Remote skill registry settings')
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
const pluginInstanceConfigSchema: z.ZodType<unknown> = z.lazy(() =>
|
|
181
|
+
z.object({
|
|
182
|
+
id: z.string().min(1).describe('Plugin package name or short id'),
|
|
183
|
+
enabled: z.boolean().optional().describe('Disable this plugin instance'),
|
|
184
|
+
scope: z.string().optional().describe('User-defined plugin scope'),
|
|
185
|
+
options: z.record(z.string(), jsonValueSchema).optional().describe('Plugin instance options'),
|
|
186
|
+
children: z.array(pluginInstanceConfigSchema).optional().describe('Nested child plugin overrides')
|
|
187
|
+
})
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
export const pluginConfigSchema = z.array(pluginInstanceConfigSchema).describe('Plugin instance list')
|
|
191
|
+
|
|
192
|
+
const marketplacePluginSourceSchema = z.union([
|
|
193
|
+
z.string().min(1),
|
|
194
|
+
z.object({
|
|
195
|
+
source: z.literal('github'),
|
|
196
|
+
repo: z.string().min(1),
|
|
197
|
+
ref: z.string().optional(),
|
|
198
|
+
sha: z.string().optional()
|
|
199
|
+
}),
|
|
200
|
+
z.object({
|
|
201
|
+
source: z.literal('url'),
|
|
202
|
+
url: z.string().min(1),
|
|
203
|
+
ref: z.string().optional(),
|
|
204
|
+
sha: z.string().optional()
|
|
205
|
+
}),
|
|
206
|
+
z.object({
|
|
207
|
+
source: z.literal('git-subdir'),
|
|
208
|
+
url: z.string().min(1),
|
|
209
|
+
path: z.string().min(1),
|
|
210
|
+
ref: z.string().optional(),
|
|
211
|
+
sha: z.string().optional()
|
|
212
|
+
}),
|
|
213
|
+
z.object({
|
|
214
|
+
source: z.literal('npm'),
|
|
215
|
+
package: z.string().min(1),
|
|
216
|
+
version: z.string().optional(),
|
|
217
|
+
registry: z.string().optional()
|
|
218
|
+
})
|
|
219
|
+
])
|
|
220
|
+
|
|
221
|
+
const marketplacePluginDefinitionSchema = z.object({
|
|
222
|
+
name: z.string().min(1),
|
|
223
|
+
description: z.string().optional(),
|
|
224
|
+
version: z.string().optional(),
|
|
225
|
+
strict: z.boolean().optional(),
|
|
226
|
+
skills: z.union([z.string(), z.array(z.string())]).optional(),
|
|
227
|
+
commands: z.union([z.string(), z.array(z.string())]).optional(),
|
|
228
|
+
agents: z.union([z.string(), z.array(z.string())]).optional(),
|
|
229
|
+
hooks: z.union([z.string(), z.array(z.string()), z.record(z.string(), jsonValueSchema)]).optional(),
|
|
230
|
+
mcpServers: z.union([z.string(), z.array(z.string()), z.record(z.string(), jsonValueSchema)]).optional(),
|
|
231
|
+
userConfig: jsonValueSchema.optional(),
|
|
232
|
+
source: marketplacePluginSourceSchema
|
|
233
|
+
})
|
|
234
|
+
|
|
235
|
+
const marketplaceSourceSchema = z.union([
|
|
236
|
+
z.object({
|
|
237
|
+
source: z.literal('github'),
|
|
238
|
+
repo: z.string().min(1),
|
|
239
|
+
ref: z.string().optional(),
|
|
240
|
+
path: z.string().optional()
|
|
241
|
+
}),
|
|
242
|
+
z.object({
|
|
243
|
+
source: z.literal('git'),
|
|
244
|
+
url: z.string().min(1),
|
|
245
|
+
ref: z.string().optional(),
|
|
246
|
+
path: z.string().optional()
|
|
247
|
+
}),
|
|
248
|
+
z.object({
|
|
249
|
+
source: z.literal('directory'),
|
|
250
|
+
path: z.string().min(1)
|
|
251
|
+
}),
|
|
252
|
+
z.object({
|
|
253
|
+
source: z.literal('url'),
|
|
254
|
+
url: z.string().min(1)
|
|
255
|
+
}),
|
|
256
|
+
z.object({
|
|
257
|
+
source: z.literal('settings'),
|
|
258
|
+
name: z.string().optional(),
|
|
259
|
+
metadata: z.object({
|
|
260
|
+
pluginRoot: z.string().optional()
|
|
261
|
+
}).optional(),
|
|
262
|
+
plugins: z.array(marketplacePluginDefinitionSchema)
|
|
263
|
+
}),
|
|
264
|
+
z.object({
|
|
265
|
+
source: z.literal('hostPattern'),
|
|
266
|
+
hostPattern: z.string().min(1)
|
|
267
|
+
})
|
|
268
|
+
])
|
|
269
|
+
|
|
270
|
+
const marketplaceDeclaredPluginConfigSchema = z.union([
|
|
271
|
+
z.boolean().transform(enabled => ({ enabled })),
|
|
272
|
+
z.object({
|
|
273
|
+
enabled: z.boolean().optional(),
|
|
274
|
+
scope: z.string().optional()
|
|
275
|
+
})
|
|
276
|
+
])
|
|
277
|
+
|
|
278
|
+
export const marketplaceConfigSchema = z.record(
|
|
279
|
+
z.string(),
|
|
280
|
+
z.object({
|
|
281
|
+
type: z.literal('claude-code'),
|
|
282
|
+
enabled: z.boolean().optional(),
|
|
283
|
+
syncOnRun: z.boolean().optional(),
|
|
284
|
+
plugins: z.record(z.string(), marketplaceDeclaredPluginConfigSchema).optional(),
|
|
285
|
+
options: z.object({
|
|
286
|
+
source: marketplaceSourceSchema
|
|
287
|
+
}).optional()
|
|
288
|
+
})
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
const mcpServerCommonSchema = z.object({
|
|
292
|
+
enabled: z.boolean().optional().describe('Enable this MCP server'),
|
|
293
|
+
env: z.record(z.string(), z.string()).optional().describe('Environment variables')
|
|
294
|
+
})
|
|
295
|
+
|
|
296
|
+
const mcpServerCommandSchema = mcpServerCommonSchema.extend({
|
|
297
|
+
command: z.string().min(1).describe('Executable command'),
|
|
298
|
+
args: z.array(z.string()).optional().describe('Command arguments')
|
|
299
|
+
})
|
|
300
|
+
|
|
301
|
+
const mcpServerSseSchema = mcpServerCommonSchema.extend({
|
|
302
|
+
type: z.literal('sse'),
|
|
303
|
+
url: z.string().min(1).describe('SSE endpoint URL'),
|
|
304
|
+
headers: z.record(z.string(), z.string()).describe('HTTP headers')
|
|
305
|
+
})
|
|
306
|
+
|
|
307
|
+
const mcpServerHttpSchema = mcpServerCommonSchema.extend({
|
|
308
|
+
type: z.literal('http'),
|
|
309
|
+
url: z.string().min(1).describe('HTTP endpoint URL'),
|
|
310
|
+
headers: z.record(z.string(), z.string()).optional().describe('HTTP headers')
|
|
311
|
+
})
|
|
312
|
+
|
|
313
|
+
export const mcpServerConfigSchema = z.union([
|
|
314
|
+
mcpServerCommandSchema,
|
|
315
|
+
mcpServerSseSchema,
|
|
316
|
+
mcpServerHttpSchema
|
|
317
|
+
])
|
|
318
|
+
|
|
319
|
+
export const generalConfigSectionSchema = z.object({
|
|
320
|
+
baseDir: z.string().optional(),
|
|
321
|
+
effort: effortLevelSchema.optional(),
|
|
322
|
+
defaultAdapter: z.string().optional(),
|
|
323
|
+
defaultModelService: z.string().optional(),
|
|
324
|
+
defaultModel: z.string().optional(),
|
|
325
|
+
recommendedModels: z.array(recommendedModelConfigSchema).optional(),
|
|
326
|
+
interfaceLanguage: languageCodeSchema.optional(),
|
|
327
|
+
modelLanguage: languageCodeSchema.optional(),
|
|
328
|
+
announcements: z.array(z.string()).optional(),
|
|
329
|
+
permissions: permissionsConfigSchema.optional(),
|
|
330
|
+
env: z.record(z.string(), z.string()).optional(),
|
|
331
|
+
notifications: notificationConfigSchema.optional(),
|
|
332
|
+
skills: skillsConfigSchema.optional(),
|
|
333
|
+
webAuth: webAuthConfigSchema.optional()
|
|
334
|
+
})
|
|
335
|
+
|
|
336
|
+
export const pluginSectionSchema = z.object({
|
|
337
|
+
plugins: pluginConfigSchema.optional(),
|
|
338
|
+
marketplaces: marketplaceConfigSchema.optional()
|
|
339
|
+
})
|
|
340
|
+
|
|
341
|
+
export const mcpConfigSectionSchema = z.object({
|
|
342
|
+
mcpServers: z.record(z.string(), mcpServerConfigSchema).optional(),
|
|
343
|
+
defaultIncludeMcpServers: z.array(z.string()).optional(),
|
|
344
|
+
defaultExcludeMcpServers: z.array(z.string()).optional(),
|
|
345
|
+
noDefaultVibeForgeMcpServer: z.boolean().optional()
|
|
346
|
+
})
|
|
347
|
+
|
|
348
|
+
export const baseAdapterEntrySchema = adapterConfigCommonSchema.passthrough()
|
|
349
|
+
export const baseChannelEntrySchema = channelBaseSchema.passthrough()
|
|
350
|
+
|
|
351
|
+
export const configSectionSchemas = {
|
|
352
|
+
general: generalConfigSectionSchema,
|
|
353
|
+
conversation: conversationConfigSchema,
|
|
354
|
+
models: z.record(z.string(), modelMetadataConfigSchema),
|
|
355
|
+
modelServices: z.record(z.string(), modelServiceConfigSchema),
|
|
356
|
+
channels: z.record(z.string(), baseChannelEntrySchema),
|
|
357
|
+
adapters: z.object({}).catchall(baseAdapterEntrySchema),
|
|
358
|
+
plugins: pluginSectionSchema,
|
|
359
|
+
mcp: mcpConfigSectionSchema,
|
|
360
|
+
auth: webAuthConfigSchema,
|
|
361
|
+
shortcuts: shortcutsConfigSchema
|
|
362
|
+
} as const
|
|
363
|
+
|
|
364
|
+
export const baseConfigFileSchema = z.object({
|
|
365
|
+
$schema: z.string().optional().describe('JSON Schema URL'),
|
|
366
|
+
extend: z.union([z.string().min(1), z.array(z.string().min(1))]).optional(),
|
|
367
|
+
baseDir: z.string().optional(),
|
|
368
|
+
effort: effortLevelSchema.optional(),
|
|
369
|
+
adapters: z.object({}).catchall(baseAdapterEntrySchema).optional(),
|
|
370
|
+
models: z.record(z.string(), modelMetadataConfigSchema).optional(),
|
|
371
|
+
defaultAdapter: z.string().optional(),
|
|
372
|
+
modelServices: z.record(z.string(), modelServiceConfigSchema).optional(),
|
|
373
|
+
channels: z.record(z.string(), baseChannelEntrySchema).optional(),
|
|
374
|
+
defaultModelService: z.string().optional(),
|
|
375
|
+
defaultModel: z.string().optional(),
|
|
376
|
+
recommendedModels: z.array(recommendedModelConfigSchema).optional(),
|
|
377
|
+
interfaceLanguage: languageCodeSchema.optional(),
|
|
378
|
+
modelLanguage: languageCodeSchema.optional(),
|
|
379
|
+
mcpServers: z.record(z.string(), mcpServerConfigSchema).optional(),
|
|
380
|
+
defaultIncludeMcpServers: z.array(z.string()).optional(),
|
|
381
|
+
defaultExcludeMcpServers: z.array(z.string()).optional(),
|
|
382
|
+
noDefaultVibeForgeMcpServer: z.boolean().optional(),
|
|
383
|
+
permissions: permissionsConfigSchema.optional(),
|
|
384
|
+
env: z.record(z.string(), z.string()).optional(),
|
|
385
|
+
announcements: z.array(z.string()).optional(),
|
|
386
|
+
shortcuts: shortcutsConfigSchema.optional(),
|
|
387
|
+
notifications: notificationConfigSchema.optional(),
|
|
388
|
+
skills: skillsConfigSchema.optional(),
|
|
389
|
+
webAuth: webAuthConfigSchema.optional(),
|
|
390
|
+
conversation: conversationConfigSchema.optional(),
|
|
391
|
+
plugins: pluginConfigSchema.optional(),
|
|
392
|
+
marketplaces: marketplaceConfigSchema.optional()
|
|
393
|
+
}).strict()
|
|
394
|
+
|
|
395
|
+
const getZodTypeName = (schema: z.ZodTypeAny) => (
|
|
396
|
+
(schema as { _def?: { typeName?: string } })._def?.typeName
|
|
397
|
+
)
|
|
398
|
+
|
|
399
|
+
const isZodType = (schema: z.ZodTypeAny, typeName: string) => getZodTypeName(schema) === typeName
|
|
400
|
+
|
|
401
|
+
const unwrapUiSchema = (schema: z.ZodTypeAny): z.ZodTypeAny => {
|
|
402
|
+
if (isZodType(schema, 'ZodOptional') || isZodType(schema, 'ZodNullable')) {
|
|
403
|
+
return unwrapUiSchema((schema as unknown as { unwrap: () => z.ZodTypeAny }).unwrap())
|
|
404
|
+
}
|
|
405
|
+
if (isZodType(schema, 'ZodDefault')) {
|
|
406
|
+
return unwrapUiSchema((schema as unknown as { removeDefault: () => z.ZodTypeAny }).removeDefault())
|
|
407
|
+
}
|
|
408
|
+
if (isZodType(schema, 'ZodEffects')) {
|
|
409
|
+
return unwrapUiSchema((schema as unknown as { innerType: () => z.ZodTypeAny }).innerType())
|
|
410
|
+
}
|
|
411
|
+
return schema
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
const getUiDefaultValue = (schema: z.ZodTypeAny): unknown => {
|
|
415
|
+
if (isZodType(schema, 'ZodDefault')) {
|
|
416
|
+
return (schema as unknown as { _def: { defaultValue: () => unknown } })._def.defaultValue()
|
|
417
|
+
}
|
|
418
|
+
if (isZodType(schema, 'ZodOptional')) return undefined
|
|
419
|
+
if (isZodType(schema, 'ZodNullable')) return null
|
|
420
|
+
|
|
421
|
+
const unwrapped = unwrapUiSchema(schema)
|
|
422
|
+
if (isZodType(unwrapped, 'ZodLiteral')) return (unwrapped as unknown as { value: unknown }).value
|
|
423
|
+
if (isZodType(unwrapped, 'ZodEnum')) return (unwrapped as unknown as { options: string[] }).options[0]
|
|
424
|
+
if (isZodType(unwrapped, 'ZodNativeEnum')) {
|
|
425
|
+
const values = Object.values((unwrapped as unknown as { enum: Record<string, unknown> }).enum)
|
|
426
|
+
return values.length > 0 ? values[0] : undefined
|
|
427
|
+
}
|
|
428
|
+
if (isZodType(unwrapped, 'ZodString')) return ''
|
|
429
|
+
if (isZodType(unwrapped, 'ZodNumber')) return 0
|
|
430
|
+
if (isZodType(unwrapped, 'ZodBoolean')) return false
|
|
431
|
+
if (isZodType(unwrapped, 'ZodArray')) return []
|
|
432
|
+
if (isZodType(unwrapped, 'ZodObject') || isZodType(unwrapped, 'ZodRecord')) return {}
|
|
433
|
+
return undefined
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
const inferUiFieldType = (schema: z.ZodTypeAny): ConfigUiFieldType => {
|
|
437
|
+
const unwrapped = unwrapUiSchema(schema)
|
|
438
|
+
if (isZodType(unwrapped, 'ZodString')) return 'string'
|
|
439
|
+
if (isZodType(unwrapped, 'ZodNumber')) return 'number'
|
|
440
|
+
if (isZodType(unwrapped, 'ZodBoolean')) return 'boolean'
|
|
441
|
+
if (
|
|
442
|
+
isZodType(unwrapped, 'ZodEnum') ||
|
|
443
|
+
isZodType(unwrapped, 'ZodNativeEnum') ||
|
|
444
|
+
isZodType(unwrapped, 'ZodLiteral')
|
|
445
|
+
) {
|
|
446
|
+
return 'select'
|
|
447
|
+
}
|
|
448
|
+
if (isZodType(unwrapped, 'ZodArray')) {
|
|
449
|
+
const element = unwrapUiSchema((unwrapped as unknown as { element: z.ZodTypeAny }).element)
|
|
450
|
+
return isZodType(element, 'ZodString') ? 'string[]' : 'json'
|
|
451
|
+
}
|
|
452
|
+
return 'json'
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
const inferUiOptions = (schema: z.ZodTypeAny) => {
|
|
456
|
+
const unwrapped = unwrapUiSchema(schema)
|
|
457
|
+
if (isZodType(unwrapped, 'ZodLiteral')) {
|
|
458
|
+
return [{ value: String((unwrapped as unknown as { value: unknown }).value) }]
|
|
459
|
+
}
|
|
460
|
+
if (isZodType(unwrapped, 'ZodEnum')) {
|
|
461
|
+
return (unwrapped as unknown as { options: string[] }).options.map(value => ({ value }))
|
|
462
|
+
}
|
|
463
|
+
if (isZodType(unwrapped, 'ZodNativeEnum')) {
|
|
464
|
+
return Object.values((unwrapped as unknown as { enum: Record<string, string | number> }).enum)
|
|
465
|
+
.map(value => ({ value: String(value) }))
|
|
466
|
+
}
|
|
467
|
+
return undefined
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
export const buildConfigUiObjectSchema = (schema: z.ZodTypeAny): ConfigUiObjectSchema => {
|
|
471
|
+
const unwrapped = unwrapUiSchema(schema)
|
|
472
|
+
if (!isZodType(unwrapped, 'ZodObject')) {
|
|
473
|
+
return { fields: [] }
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
const shapeEntries = Object.entries((unwrapped as unknown as { shape: Record<string, z.ZodTypeAny> }).shape) as Array<
|
|
477
|
+
[string, z.ZodTypeAny]
|
|
478
|
+
>
|
|
479
|
+
const fields = shapeEntries.map(([key, value]) => {
|
|
480
|
+
const uiField: ConfigUiField = {
|
|
481
|
+
path: [key],
|
|
482
|
+
type: inferUiFieldType(value),
|
|
483
|
+
defaultValue: getUiDefaultValue(value),
|
|
484
|
+
description: unwrapUiSchema(value).description,
|
|
485
|
+
options: inferUiOptions(value)
|
|
486
|
+
}
|
|
487
|
+
return uiField
|
|
488
|
+
})
|
|
489
|
+
|
|
490
|
+
const recordFields = Object.fromEntries(
|
|
491
|
+
shapeEntries.flatMap(([key, value]): Array<[string, ConfigUiRecordFieldSchema]> => {
|
|
492
|
+
const recordSchema = unwrapUiSchema(value)
|
|
493
|
+
if (!isZodType(recordSchema, 'ZodRecord')) {
|
|
494
|
+
return []
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
const itemSchema = (recordSchema as unknown as { _def: { valueType: z.ZodTypeAny } })._def.valueType
|
|
498
|
+
const itemObjectSchema = buildConfigUiObjectSchema(itemSchema)
|
|
499
|
+
if ((itemObjectSchema.fields.length === 0) && itemObjectSchema.recordFields == null) {
|
|
500
|
+
return []
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
return [[key, {
|
|
504
|
+
itemSchema: itemObjectSchema
|
|
505
|
+
}]]
|
|
506
|
+
})
|
|
507
|
+
)
|
|
508
|
+
|
|
509
|
+
return {
|
|
510
|
+
fields,
|
|
511
|
+
...(Object.keys(recordFields).length > 0 ? { recordFields } : {})
|
|
512
|
+
}
|
|
513
|
+
}
|
package/src/env.ts
CHANGED
|
@@ -17,7 +17,7 @@ export interface ServerEnv {
|
|
|
17
17
|
__VF_PROJECT_AI_SERVER_LOG_LEVEL__: LogLevel
|
|
18
18
|
__VF_PROJECT_AI_SERVER_DEBUG__: boolean
|
|
19
19
|
__VF_PROJECT_AI_SERVER_ALLOW_CORS__: boolean
|
|
20
|
-
__VF_PROJECT_AI_CLIENT_MODE__?: 'dev' | 'static'
|
|
20
|
+
__VF_PROJECT_AI_CLIENT_MODE__?: 'dev' | 'none' | 'static' | 'standalone' | 'independent' | 'desktop'
|
|
21
21
|
__VF_PROJECT_AI_CLIENT_BASE__?: string
|
|
22
22
|
__VF_PROJECT_AI_CLIENT_DIST_PATH__?: string
|
|
23
23
|
}
|
package/src/index.ts
CHANGED
package/src/tools.ts
CHANGED
|
@@ -5,7 +5,7 @@ export interface StopTaskToolInput {
|
|
|
5
5
|
export interface StartTasksToolInput {
|
|
6
6
|
tasks: Array<{
|
|
7
7
|
description?: string
|
|
8
|
-
type?: 'default' | 'spec' | 'entity'
|
|
8
|
+
type?: 'default' | 'spec' | 'entity' | 'workspace'
|
|
9
9
|
name?: string
|
|
10
10
|
adapter?: string
|
|
11
11
|
permissionMode?: 'default' | 'acceptEdits' | 'plan' | 'dontAsk' | 'bypassPermissions'
|
package/src/types.ts
CHANGED
|
@@ -8,11 +8,13 @@ export type {
|
|
|
8
8
|
Session,
|
|
9
9
|
SessionMessageQueueState,
|
|
10
10
|
SessionPermissionMode,
|
|
11
|
+
SessionPromptType,
|
|
11
12
|
SessionQueuedMessage,
|
|
12
13
|
SessionQueuedMessageMode,
|
|
13
14
|
SessionStatus,
|
|
14
15
|
SessionWorkspace,
|
|
15
16
|
SessionWorkspaceCleanupPolicy,
|
|
17
|
+
SessionWorkspaceFileState,
|
|
16
18
|
SessionWorkspaceKind,
|
|
17
19
|
SessionWorkspaceState,
|
|
18
20
|
TaskDetail,
|