@vibe-forge/workspace-assets 0.9.2 → 0.10.1-alpha.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/__tests__/bundle.spec.ts +54 -1
- package/__tests__/prompt-selection.spec.ts +140 -0
- package/package.json +10 -10
- package/src/adapter-asset-plan.ts +5 -2
- package/src/adapter-capabilities.ts +12 -0
- package/src/bundle-internal.ts +11 -5
- package/src/bundle.ts +1 -0
- package/src/prompt-selection.ts +10 -4
- package/src/selection-internal.ts +1 -5
- package/LICENSE +0 -21
- package/__tests__/selection-internal.spec.ts +0 -42
package/__tests__/bundle.spec.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import process from 'node:process'
|
|
2
|
+
import { join } from 'node:path'
|
|
2
3
|
|
|
3
4
|
import { describe, expect, it } from 'vitest'
|
|
4
5
|
|
|
5
6
|
import { resolveWorkspaceAssetBundle } from '#~/index.js'
|
|
6
7
|
|
|
7
|
-
import { createWorkspace, installPluginPackage } from './test-helpers'
|
|
8
|
+
import { createWorkspace, installPluginPackage, writeDocument } from './test-helpers'
|
|
8
9
|
|
|
9
10
|
describe('resolveWorkspaceAssetBundle', () => {
|
|
10
11
|
it('loads npm plugin assets via the package-id fallback and exposes OpenCode overlays', async () => {
|
|
@@ -67,6 +68,58 @@ describe('resolveWorkspaceAssetBundle', () => {
|
|
|
67
68
|
]))
|
|
68
69
|
})
|
|
69
70
|
|
|
71
|
+
it('auto-loads managed Claude plugins from .ai/plugins as directory plugins', async () => {
|
|
72
|
+
const workspace = await createWorkspace()
|
|
73
|
+
|
|
74
|
+
await writeDocument(
|
|
75
|
+
join(workspace, '.ai/plugins/demo/.vf-plugin.json'),
|
|
76
|
+
JSON.stringify(
|
|
77
|
+
{
|
|
78
|
+
version: 1,
|
|
79
|
+
adapter: 'claude',
|
|
80
|
+
name: 'demo',
|
|
81
|
+
scope: 'demo',
|
|
82
|
+
installedAt: new Date().toISOString(),
|
|
83
|
+
source: {
|
|
84
|
+
type: 'path',
|
|
85
|
+
path: './demo'
|
|
86
|
+
},
|
|
87
|
+
nativePluginPath: 'native',
|
|
88
|
+
vibeForgePluginPath: 'vibe-forge'
|
|
89
|
+
},
|
|
90
|
+
null,
|
|
91
|
+
2
|
|
92
|
+
)
|
|
93
|
+
)
|
|
94
|
+
await writeDocument(
|
|
95
|
+
join(workspace, '.ai/plugins/demo/vibe-forge/skills/research/SKILL.md'),
|
|
96
|
+
'---\ndescription: 检索资料\n---\n阅读 README.md'
|
|
97
|
+
)
|
|
98
|
+
await writeDocument(
|
|
99
|
+
join(workspace, '.ai/plugins/demo/vibe-forge/mcp/browser.json'),
|
|
100
|
+
JSON.stringify({ command: 'npx', args: ['browser-server'] }, null, 2)
|
|
101
|
+
)
|
|
102
|
+
await writeDocument(
|
|
103
|
+
join(workspace, '.ai/plugins/demo/vibe-forge/hooks.js'),
|
|
104
|
+
'module.exports = { name: "demo-managed" }\n'
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
const bundle = await resolveWorkspaceAssetBundle({
|
|
108
|
+
cwd: workspace,
|
|
109
|
+
configs: [undefined, undefined],
|
|
110
|
+
useDefaultVibeForgeMcpServer: false
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
expect(bundle.skills.map(asset => asset.displayName)).toContain('demo/research')
|
|
114
|
+
expect(Object.keys(bundle.mcpServers)).toContain('demo/browser')
|
|
115
|
+
expect(bundle.hookPlugins).toEqual(expect.arrayContaining([
|
|
116
|
+
expect.objectContaining({
|
|
117
|
+
scope: 'demo',
|
|
118
|
+
origin: 'plugin'
|
|
119
|
+
})
|
|
120
|
+
]))
|
|
121
|
+
})
|
|
122
|
+
|
|
70
123
|
it('adds the built-in Vibe Forge MCP server when enabled and omits it when disabled', async () => {
|
|
71
124
|
const workspace = await createWorkspace()
|
|
72
125
|
|
|
@@ -241,6 +241,90 @@ describe('resolvePromptAssetSelection', () => {
|
|
|
241
241
|
expect(options.systemPrompt).not.toContain('先读 README.md')
|
|
242
242
|
})
|
|
243
243
|
|
|
244
|
+
it('omits route-only project skills when the adapter provides native skill loading', async () => {
|
|
245
|
+
const workspace = await createWorkspace()
|
|
246
|
+
|
|
247
|
+
await writeDocument(
|
|
248
|
+
join(workspace, '.ai/skills/research/SKILL.md'),
|
|
249
|
+
[
|
|
250
|
+
'---',
|
|
251
|
+
'description: 检索项目信息',
|
|
252
|
+
'---',
|
|
253
|
+
'先读 README.md'
|
|
254
|
+
].join('\n')
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
const bundle = await resolveWorkspaceAssetBundle({
|
|
258
|
+
cwd: workspace,
|
|
259
|
+
useDefaultVibeForgeMcpServer: false
|
|
260
|
+
})
|
|
261
|
+
const [data, options] = await resolvePromptAssetSelection({
|
|
262
|
+
bundle,
|
|
263
|
+
adapter: 'claude-code',
|
|
264
|
+
type: undefined
|
|
265
|
+
})
|
|
266
|
+
|
|
267
|
+
expect(data.targetSkills).toEqual([])
|
|
268
|
+
expect(options.systemPrompt).not.toContain('<skills>')
|
|
269
|
+
expect(options.systemPrompt).not.toContain('# research')
|
|
270
|
+
expect(options.systemPrompt).not.toContain('Skill file path: .ai/skills/research/SKILL.md')
|
|
271
|
+
expect(options.promptAssetIds).not.toContain(bundle.skills[0]?.id)
|
|
272
|
+
})
|
|
273
|
+
|
|
274
|
+
it('keeps explicitly referenced skills embedded for adapters with native project skills', async () => {
|
|
275
|
+
const workspace = await createWorkspace()
|
|
276
|
+
|
|
277
|
+
await writeDocument(
|
|
278
|
+
join(workspace, '.ai/skills/research/SKILL.md'),
|
|
279
|
+
[
|
|
280
|
+
'---',
|
|
281
|
+
'description: 检索项目信息',
|
|
282
|
+
'---',
|
|
283
|
+
'先读 README.md'
|
|
284
|
+
].join('\n')
|
|
285
|
+
)
|
|
286
|
+
await writeDocument(
|
|
287
|
+
join(workspace, '.ai/skills/review/SKILL.md'),
|
|
288
|
+
[
|
|
289
|
+
'---',
|
|
290
|
+
'description: 评审代码改动',
|
|
291
|
+
'---',
|
|
292
|
+
'检查回归风险'
|
|
293
|
+
].join('\n')
|
|
294
|
+
)
|
|
295
|
+
await writeDocument(
|
|
296
|
+
join(workspace, '.ai/specs/release/index.md'),
|
|
297
|
+
[
|
|
298
|
+
'---',
|
|
299
|
+
'description: 发布流程',
|
|
300
|
+
'skills:',
|
|
301
|
+
' - research',
|
|
302
|
+
'---',
|
|
303
|
+
'执行发布'
|
|
304
|
+
].join('\n')
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
const bundle = await resolveWorkspaceAssetBundle({
|
|
308
|
+
cwd: workspace,
|
|
309
|
+
useDefaultVibeForgeMcpServer: false
|
|
310
|
+
})
|
|
311
|
+
const [data, options] = await resolvePromptAssetSelection({
|
|
312
|
+
bundle,
|
|
313
|
+
adapter: 'claude-code',
|
|
314
|
+
type: 'spec',
|
|
315
|
+
name: 'release'
|
|
316
|
+
})
|
|
317
|
+
|
|
318
|
+
expect(data.targetSkills.map(skill => skill.resolvedName ?? skill.attributes.name)).toEqual(['research'])
|
|
319
|
+
expect(options.systemPrompt).toContain('The following skill modules are loaded for the project')
|
|
320
|
+
expect(options.systemPrompt).toContain('# research')
|
|
321
|
+
expect(options.systemPrompt).toContain('<skill-content>')
|
|
322
|
+
expect(options.systemPrompt).toContain('先读 README.md')
|
|
323
|
+
expect(options.systemPrompt).not.toContain('<skills>')
|
|
324
|
+
expect(options.systemPrompt).not.toContain('# review')
|
|
325
|
+
expect(options.systemPrompt).not.toContain('Skill file path: .ai/skills/review/SKILL.md')
|
|
326
|
+
})
|
|
327
|
+
|
|
244
328
|
it('keeps spec route guidance without default identity in normal mode', async () => {
|
|
245
329
|
const workspace = await createWorkspace()
|
|
246
330
|
|
|
@@ -389,4 +473,60 @@ describe('resolvePromptAssetSelection', () => {
|
|
|
389
473
|
expect(options.systemPrompt).toContain('> Skill file path: .ai/skills/research/SKILL.md')
|
|
390
474
|
expect(options.systemPrompt).not.toContain('先读 README.md')
|
|
391
475
|
})
|
|
476
|
+
|
|
477
|
+
it('lets spec plugin overrides exclude managed plugins when mode is override', async () => {
|
|
478
|
+
const workspace = await createWorkspace()
|
|
479
|
+
|
|
480
|
+
await writeDocument(
|
|
481
|
+
join(workspace, '.ai/plugins/demo/.vf-plugin.json'),
|
|
482
|
+
JSON.stringify({
|
|
483
|
+
version: 1,
|
|
484
|
+
adapter: 'claude',
|
|
485
|
+
name: 'demo',
|
|
486
|
+
scope: 'demo',
|
|
487
|
+
installedAt: new Date().toISOString(),
|
|
488
|
+
source: {
|
|
489
|
+
type: 'path',
|
|
490
|
+
path: './demo'
|
|
491
|
+
},
|
|
492
|
+
nativePluginPath: 'native',
|
|
493
|
+
vibeForgePluginPath: 'vibe-forge'
|
|
494
|
+
}, null, 2)
|
|
495
|
+
)
|
|
496
|
+
await writeDocument(
|
|
497
|
+
join(workspace, '.ai/plugins/demo/vibe-forge/skills/research/SKILL.md'),
|
|
498
|
+
[
|
|
499
|
+
'---',
|
|
500
|
+
'description: 托管插件技能',
|
|
501
|
+
'---',
|
|
502
|
+
'先读插件文档'
|
|
503
|
+
].join('\n')
|
|
504
|
+
)
|
|
505
|
+
await writeDocument(
|
|
506
|
+
join(workspace, '.ai/specs/isolated/index.md'),
|
|
507
|
+
[
|
|
508
|
+
'---',
|
|
509
|
+
'description: 隔离 spec',
|
|
510
|
+
'plugins:',
|
|
511
|
+
' mode: override',
|
|
512
|
+
' list: []',
|
|
513
|
+
'---',
|
|
514
|
+
'执行隔离流程'
|
|
515
|
+
].join('\n')
|
|
516
|
+
)
|
|
517
|
+
|
|
518
|
+
const bundle = await resolveWorkspaceAssetBundle({
|
|
519
|
+
cwd: workspace,
|
|
520
|
+
useDefaultVibeForgeMcpServer: false
|
|
521
|
+
})
|
|
522
|
+
const [, options] = await resolvePromptAssetSelection({
|
|
523
|
+
bundle,
|
|
524
|
+
type: 'spec',
|
|
525
|
+
name: 'isolated'
|
|
526
|
+
})
|
|
527
|
+
|
|
528
|
+
expect(bundle.skills.map(asset => asset.displayName)).toContain('demo/research')
|
|
529
|
+
expect(options.assetBundle?.skills).toEqual([])
|
|
530
|
+
expect(options.systemPrompt).not.toContain('demo/research')
|
|
531
|
+
})
|
|
392
532
|
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibe-forge/workspace-assets",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.1-alpha.0",
|
|
4
4
|
"description": "Workspace asset resolution and adapter asset planning for Vibe Forge",
|
|
5
5
|
"imports": {
|
|
6
6
|
"#~/*.js": {
|
|
@@ -25,19 +25,19 @@
|
|
|
25
25
|
},
|
|
26
26
|
"./package.json": "./package.json"
|
|
27
27
|
},
|
|
28
|
+
"scripts": {
|
|
29
|
+
"test": "pnpm -C ../.. exec vitest run --workspace vitest.workspace.ts --project bundler packages/workspace-assets/__tests__"
|
|
30
|
+
},
|
|
28
31
|
"dependencies": {
|
|
32
|
+
"@vibe-forge/config": "workspace:^",
|
|
33
|
+
"@vibe-forge/definition-core": "workspace:^",
|
|
34
|
+
"@vibe-forge/types": "workspace:^",
|
|
35
|
+
"@vibe-forge/utils": "workspace:^",
|
|
29
36
|
"fast-glob": "^3.3.3",
|
|
30
37
|
"front-matter": "^4.0.2",
|
|
31
|
-
"js-yaml": "^4.1.1"
|
|
32
|
-
"@vibe-forge/config": "^0.9.0",
|
|
33
|
-
"@vibe-forge/definition-core": "^0.9.0",
|
|
34
|
-
"@vibe-forge/utils": "^0.9.0",
|
|
35
|
-
"@vibe-forge/types": "^0.9.0"
|
|
38
|
+
"js-yaml": "^4.1.1"
|
|
36
39
|
},
|
|
37
40
|
"devDependencies": {
|
|
38
41
|
"@types/js-yaml": "^4.0.9"
|
|
39
|
-
},
|
|
40
|
-
"scripts": {
|
|
41
|
-
"test": "pnpm -C ../.. exec vitest run --workspace vitest.workspace.ts --project bundler packages/workspace-assets/__tests__"
|
|
42
42
|
}
|
|
43
|
-
}
|
|
43
|
+
}
|
|
@@ -10,6 +10,7 @@ import type {
|
|
|
10
10
|
WorkspaceSkillSelection
|
|
11
11
|
} from '@vibe-forge/types'
|
|
12
12
|
|
|
13
|
+
import { resolveNativeSkillDiagnosticReason, supportsNativeProjectSkills } from './adapter-capabilities'
|
|
13
14
|
import { resolveSelectedMcpNames, resolveSelectedSkillAssets } from './selection-internal'
|
|
14
15
|
|
|
15
16
|
export function buildAdapterAssetPlan(params: {
|
|
@@ -83,13 +84,13 @@ export function buildAdapterAssetPlan(params: {
|
|
|
83
84
|
})
|
|
84
85
|
|
|
85
86
|
const selectedSkillAssets = resolveSelectedSkillAssets(params.bundle.skills, params.options.skills)
|
|
86
|
-
if (params.adapter
|
|
87
|
+
if (supportsNativeProjectSkills(params.adapter)) {
|
|
87
88
|
selectedSkillAssets.forEach((asset) => {
|
|
88
89
|
diagnostics.push({
|
|
89
90
|
assetId: asset.id,
|
|
90
91
|
adapter: params.adapter,
|
|
91
92
|
status: 'native',
|
|
92
|
-
reason:
|
|
93
|
+
reason: resolveNativeSkillDiagnosticReason(params.adapter),
|
|
93
94
|
packageId: asset.packageId,
|
|
94
95
|
scope: asset.scope,
|
|
95
96
|
instancePath: asset.instancePath,
|
|
@@ -98,6 +99,8 @@ export function buildAdapterAssetPlan(params: {
|
|
|
98
99
|
taskOverlaySource: asset.taskOverlaySource
|
|
99
100
|
})
|
|
100
101
|
})
|
|
102
|
+
}
|
|
103
|
+
if (params.adapter === 'opencode') {
|
|
101
104
|
params.bundle.opencodeOverlayAssets.forEach((asset) => {
|
|
102
105
|
diagnostics.push({
|
|
103
106
|
assetId: asset.id,
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { WorkspaceAssetAdapter } from '@vibe-forge/types'
|
|
2
|
+
|
|
3
|
+
const NATIVE_SKILL_ADAPTERS = new Set<WorkspaceAssetAdapter>(['claude-code', 'opencode'])
|
|
4
|
+
|
|
5
|
+
export const supportsNativeProjectSkills = (adapter?: string): adapter is WorkspaceAssetAdapter =>
|
|
6
|
+
adapter != null && NATIVE_SKILL_ADAPTERS.has(adapter as WorkspaceAssetAdapter)
|
|
7
|
+
|
|
8
|
+
export const resolveNativeSkillDiagnosticReason = (adapter: WorkspaceAssetAdapter) => (
|
|
9
|
+
adapter === 'claude-code'
|
|
10
|
+
? 'Synced into the Claude mock home as a native skill.'
|
|
11
|
+
: 'Mirrored into OPENCODE_CONFIG_DIR as a native skill.'
|
|
12
|
+
)
|
package/src/bundle-internal.ts
CHANGED
|
@@ -10,11 +10,12 @@ import {
|
|
|
10
10
|
} from '@vibe-forge/config'
|
|
11
11
|
import type { Config, Definition, Entity, PluginConfig, WorkspaceAsset, WorkspaceAssetKind } from '@vibe-forge/types'
|
|
12
12
|
import { resolveRelativePath } from '@vibe-forge/utils'
|
|
13
|
+
import { listManagedPluginInstalls, toManagedPluginConfig } from '@vibe-forge/utils/managed-plugin'
|
|
13
14
|
import {
|
|
14
15
|
flattenPluginInstances,
|
|
15
16
|
mergePluginConfigs,
|
|
16
17
|
resolveConfiguredPluginInstances,
|
|
17
|
-
|
|
18
|
+
resolvePluginHooksEntryPathForInstance
|
|
18
19
|
} from '@vibe-forge/utils/plugin-resolver'
|
|
19
20
|
import type { ResolvedPluginInstance } from '@vibe-forge/utils/plugin-resolver'
|
|
20
21
|
import { glob } from 'fast-glob'
|
|
@@ -341,6 +342,7 @@ export async function collectWorkspaceAssets(params: {
|
|
|
341
342
|
configs?: [Config?, Config?]
|
|
342
343
|
plugins?: PluginConfig
|
|
343
344
|
overlaySource?: string
|
|
345
|
+
includeManagedPlugins?: boolean
|
|
344
346
|
useDefaultVibeForgeMcpServer?: boolean
|
|
345
347
|
}): Promise<{
|
|
346
348
|
assets: WorkspaceAsset[]
|
|
@@ -357,7 +359,13 @@ export async function collectWorkspaceAssets(params: {
|
|
|
357
359
|
specs: Array<Extract<WorkspaceAsset, { kind: 'spec' }>>
|
|
358
360
|
}> {
|
|
359
361
|
const [config, userConfig] = params.configs ?? await loadWorkspaceConfig(params.cwd)
|
|
360
|
-
const
|
|
362
|
+
const managedPluginConfigs = params.includeManagedPlugins === false
|
|
363
|
+
? undefined
|
|
364
|
+
: toManagedPluginConfig(await listManagedPluginInstalls(params.cwd))
|
|
365
|
+
const pluginConfigs = mergePluginConfigs(
|
|
366
|
+
params.plugins ?? mergePluginConfigs(config?.plugins, userConfig?.plugins),
|
|
367
|
+
managedPluginConfigs
|
|
368
|
+
)
|
|
361
369
|
const pluginInstances = await resolveConfiguredPluginInstances({
|
|
362
370
|
cwd: params.cwd,
|
|
363
371
|
plugins: pluginConfigs,
|
|
@@ -493,9 +501,7 @@ export async function collectWorkspaceAssets(params: {
|
|
|
493
501
|
}
|
|
494
502
|
|
|
495
503
|
const hookPlugins = flattenedPluginInstances
|
|
496
|
-
.filter(instance =>
|
|
497
|
-
instance.packageId != null && resolvePluginHooksEntryPath(params.cwd, instance.packageId) != null
|
|
498
|
-
)
|
|
504
|
+
.filter(instance => resolvePluginHooksEntryPathForInstance(params.cwd, instance) != null)
|
|
499
505
|
.map(instance => createHookPluginAsset(instance))
|
|
500
506
|
assets.push(...hookPlugins)
|
|
501
507
|
|
package/src/bundle.ts
CHANGED
|
@@ -7,6 +7,7 @@ export async function resolveWorkspaceAssetBundle(params: {
|
|
|
7
7
|
configs?: [Config?, Config?]
|
|
8
8
|
plugins?: PluginConfig
|
|
9
9
|
overlaySource?: string
|
|
10
|
+
includeManagedPlugins?: boolean
|
|
10
11
|
useDefaultVibeForgeMcpServer?: boolean
|
|
11
12
|
}): Promise<WorkspaceAssetBundle> {
|
|
12
13
|
const collected = await collectWorkspaceAssets(params)
|
package/src/prompt-selection.ts
CHANGED
|
@@ -11,6 +11,7 @@ import type {
|
|
|
11
11
|
WorkspaceSkillSelection
|
|
12
12
|
} from '@vibe-forge/types'
|
|
13
13
|
|
|
14
|
+
import { supportsNativeProjectSkills } from './adapter-capabilities'
|
|
14
15
|
import { resolveWorkspaceAssetBundle } from './bundle'
|
|
15
16
|
import {
|
|
16
17
|
generateEntitiesRoutePrompt,
|
|
@@ -35,6 +36,7 @@ export async function resolvePromptAssetSelection(params: {
|
|
|
35
36
|
bundle: WorkspaceAssetBundle
|
|
36
37
|
type: 'spec' | 'entity' | undefined
|
|
37
38
|
name?: string
|
|
39
|
+
adapter?: string
|
|
38
40
|
input?: {
|
|
39
41
|
skills?: WorkspaceSkillSelection
|
|
40
42
|
}
|
|
@@ -69,7 +71,8 @@ export async function resolvePromptAssetSelection(params: {
|
|
|
69
71
|
effectiveBundle = await resolveWorkspaceAssetBundle({
|
|
70
72
|
cwd: params.bundle.cwd,
|
|
71
73
|
plugins: resolvePluginOverlay(params.bundle.pluginConfigs, pluginOverlay),
|
|
72
|
-
overlaySource: `${params.type}:${baseTarget.displayName}
|
|
74
|
+
overlaySource: `${params.type}:${baseTarget.displayName}`,
|
|
75
|
+
includeManagedPlugins: pluginOverlay.mode !== 'override'
|
|
73
76
|
})
|
|
74
77
|
}
|
|
75
78
|
|
|
@@ -82,10 +85,11 @@ export async function resolvePromptAssetSelection(params: {
|
|
|
82
85
|
}
|
|
83
86
|
|
|
84
87
|
const selectedSkillAssets = resolveSelectedSkillAssets(effectiveBundle.skills, params.input?.skills)
|
|
88
|
+
const useNativeProjectSkills = supportsNativeProjectSkills(params.adapter)
|
|
85
89
|
const promptAssetIds = new Set<string>([
|
|
86
90
|
...effectiveBundle.rules.map(asset => asset.id),
|
|
87
91
|
...effectiveBundle.specs.map(asset => asset.id),
|
|
88
|
-
...selectedSkillAssets.map(asset => asset.id),
|
|
92
|
+
...(useNativeProjectSkills ? [] : selectedSkillAssets.map(asset => asset.id)),
|
|
89
93
|
...(params.type !== 'entity' ? effectiveBundle.entities.map(asset => asset.id) : [])
|
|
90
94
|
])
|
|
91
95
|
const ruleDefinitions = new Map<string, Definition<Rule>>(
|
|
@@ -163,10 +167,12 @@ export async function resolvePromptAssetSelection(params: {
|
|
|
163
167
|
generateRulesPrompt(effectiveBundle.cwd, rules),
|
|
164
168
|
generateSkillsPrompt(effectiveBundle.cwd, targetSkills),
|
|
165
169
|
generateEntitiesRoutePrompt(entities),
|
|
166
|
-
generateSkillsRoutePrompt(effectiveBundle.cwd, routedSkills),
|
|
170
|
+
useNativeProjectSkills ? '' : generateSkillsRoutePrompt(effectiveBundle.cwd, routedSkills),
|
|
167
171
|
generateSpecRoutePrompt(specs, { active: params.type === 'spec' }),
|
|
168
172
|
targetBody
|
|
169
|
-
]
|
|
173
|
+
]
|
|
174
|
+
.filter(section => section !== '')
|
|
175
|
+
.join('\n\n')
|
|
170
176
|
|
|
171
177
|
if (targetToolsFilter != null) {
|
|
172
178
|
options.tools = targetToolsFilter
|
|
@@ -219,11 +219,7 @@ export const resolveSelectedMcpNames = (
|
|
|
219
219
|
const includeRefs = selection?.include ??
|
|
220
220
|
(bundle.defaultIncludeMcpServers.length > 0 ? bundle.defaultIncludeMcpServers : undefined)
|
|
221
221
|
const excludeRefs = selection?.exclude ??
|
|
222
|
-
(
|
|
223
|
-
selection?.include == null && bundle.defaultExcludeMcpServers.length > 0
|
|
224
|
-
? bundle.defaultExcludeMcpServers
|
|
225
|
-
: undefined
|
|
226
|
-
)
|
|
222
|
+
(bundle.defaultExcludeMcpServers.length > 0 ? bundle.defaultExcludeMcpServers : undefined)
|
|
227
223
|
|
|
228
224
|
const resolveRefs = (refs: string[] | undefined) => {
|
|
229
225
|
if (refs == null || refs.length === 0) return undefined
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2025-present Vibe-Forge.ai
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest'
|
|
2
|
-
|
|
3
|
-
import type { WorkspaceAssetBundle } from '@vibe-forge/types'
|
|
4
|
-
|
|
5
|
-
import { resolveSelectedMcpNames } from '#~/selection-internal.js'
|
|
6
|
-
|
|
7
|
-
const createBundle = (): WorkspaceAssetBundle => ({
|
|
8
|
-
cwd: '/tmp/workspace',
|
|
9
|
-
pluginConfigs: [],
|
|
10
|
-
pluginInstances: [],
|
|
11
|
-
assets: [],
|
|
12
|
-
rules: [],
|
|
13
|
-
specs: [],
|
|
14
|
-
entities: [],
|
|
15
|
-
skills: [],
|
|
16
|
-
hookPlugins: [],
|
|
17
|
-
opencodeOverlayAssets: [],
|
|
18
|
-
defaultIncludeMcpServers: [],
|
|
19
|
-
defaultExcludeMcpServers: ['TypeScriptLanguageService'],
|
|
20
|
-
mcpServers: {
|
|
21
|
-
TypeScriptLanguageService: {
|
|
22
|
-
kind: 'mcpServer',
|
|
23
|
-
id: 'mcp:TypeScriptLanguageService',
|
|
24
|
-
scope: 'workspace',
|
|
25
|
-
name: 'TypeScriptLanguageService',
|
|
26
|
-
displayName: 'TypeScriptLanguageService',
|
|
27
|
-
source: '/tmp/workspace/.ai.config.json',
|
|
28
|
-
command: 'node',
|
|
29
|
-
args: ['tslspmcp']
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
describe('resolveSelectedMcpNames', () => {
|
|
35
|
-
it('lets an explicit include override default excludes', () => {
|
|
36
|
-
const selected = resolveSelectedMcpNames(createBundle(), {
|
|
37
|
-
include: ['TypeScriptLanguageService']
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
expect(selected).toEqual(['TypeScriptLanguageService'])
|
|
41
|
-
})
|
|
42
|
-
})
|