@vibe-forge/mcp 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.
@@ -94,6 +94,28 @@ describe('task tool integration', () => {
94
94
  }))
95
95
  })
96
96
 
97
+ it('accepts workspace tasks without a separate workspace tool', async () => {
98
+ const { createTaskRegister } = await import('#~/tools/task/index.js')
99
+
100
+ const tester = createToolTester()
101
+ createTaskRegister()(tester.mockRegister)
102
+
103
+ await tester.callTool('StartTasks', {
104
+ tasks: [{
105
+ description: 'fix billing',
106
+ type: 'workspace',
107
+ name: 'billing'
108
+ }]
109
+ })
110
+
111
+ expect(mocks.startTask).toHaveBeenCalledWith(expect.objectContaining({
112
+ taskId: 'task-1',
113
+ description: 'fix billing',
114
+ type: 'workspace',
115
+ name: 'billing'
116
+ }))
117
+ })
118
+
97
119
  it('inherits the parent permission mode when the task does not specify one', async () => {
98
120
  process.env.__VF_PROJECT_AI_PERMISSION_MODE__ = 'dontAsk'
99
121
  mocks.getParentSessionId.mockReturnValue('parent-session')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibe-forge/mcp",
3
- "version": "1.0.0",
3
+ "version": "2.0.1",
4
4
  "description": "Vibe Forge MCP server",
5
5
  "imports": {
6
6
  "#~/*.js": {
@@ -31,15 +31,15 @@
31
31
  },
32
32
  "dependencies": {
33
33
  "@modelcontextprotocol/sdk": "^1.25.3",
34
+ "@vibe-forge/config": "^2.0.2",
34
35
  "commander": "^12.1.0",
35
36
  "zod": "^3.24.1",
36
- "@vibe-forge/hooks": "^1.0.0",
37
- "@vibe-forge/config": "^1.0.0",
38
- "@vibe-forge/register": "^1.0.0",
39
- "@vibe-forge/task": "^1.0.0",
40
- "@vibe-forge/cli-helper": "^1.0.0",
41
- "@vibe-forge/types": "^1.0.0",
42
- "@vibe-forge/utils": "^1.0.0"
37
+ "@vibe-forge/hooks": "^2.0.1",
38
+ "@vibe-forge/register": "^2.0.1",
39
+ "@vibe-forge/cli-helper": "^2.0.1",
40
+ "@vibe-forge/utils": "^2.0.1",
41
+ "@vibe-forge/types": "^2.0.1",
42
+ "@vibe-forge/task": "^2.0.1"
43
43
  },
44
44
  "scripts": {
45
45
  "test": "pnpm -C ../.. exec vitest run --workspace vitest.workspace.ts --project bundler packages/mcp/__tests__"
@@ -38,9 +38,10 @@ export const createTaskRegister = () => {
38
38
  .enum([
39
39
  'default',
40
40
  'spec',
41
- 'entity'
41
+ 'entity',
42
+ 'workspace'
42
43
  ])
43
- .describe('The type of definition to load (default, spec or entity)'),
44
+ .describe('The type of definition to load (default, spec, entity or workspace)'),
44
45
  name: z
45
46
  .string()
46
47
  .describe('The name of the spec or entity to load, if type is spec or entity. Otherwise, ignored.')
@@ -52,8 +52,9 @@ export interface TaskInfo {
52
52
  taskId: string
53
53
  adapter?: string
54
54
  description: string
55
- type?: 'default' | 'spec' | 'entity'
55
+ type?: 'default' | 'spec' | 'entity' | 'workspace'
56
56
  name?: string
57
+ workspaceCwd?: string
57
58
  permissionMode?: SessionPermissionMode
58
59
  background?: boolean
59
60
  status: 'running' | 'waiting_input' | 'completed' | 'failed'
@@ -230,7 +231,7 @@ export class TaskManager {
230
231
  public async startTask(options: {
231
232
  taskId: string
232
233
  description: string
233
- type?: 'default' | 'spec' | 'entity'
234
+ type?: 'default' | 'spec' | 'entity' | 'workspace'
234
235
  name?: string
235
236
  permissionMode?: 'default' | 'acceptEdits' | 'plan' | 'dontAsk' | 'bypassPermissions'
236
237
  adapter?: string
@@ -286,6 +287,7 @@ export class TaskManager {
286
287
 
287
288
  private async launchTask(task: TaskInfo, runType: 'create' | 'resume') {
288
289
  try {
290
+ const rootCwd = process.cwd()
289
291
  const promptType = task.type !== 'default' ? task.type : undefined
290
292
  const promptName = task.name
291
293
  const promptCWD = process.cwd()
@@ -297,25 +299,29 @@ export class TaskManager {
297
299
  adapter: task.adapter
298
300
  }
299
301
  )
302
+ const taskCwd = resolvedConfig.workspace?.cwd ?? promptCWD
303
+ task.workspaceCwd = resolvedConfig.workspace?.cwd
300
304
  const env = {
301
305
  ...process.env,
302
- __VF_PROJECT_AI_CTX_ID__: process.env.__VF_PROJECT_AI_CTX_ID__ ?? task.taskId
306
+ __VF_PROJECT_AI_CTX_ID__: process.env.__VF_PROJECT_AI_CTX_ID__ ?? task.taskId,
307
+ __VF_PROJECT_WORKSPACE_FOLDER__: taskCwd,
308
+ __VF_PROJECT_PRIMARY_WORKSPACE_FOLDER__: rootCwd
303
309
  }
304
310
  await callHook('GenerateSystemPrompt', {
305
- cwd: promptCWD,
311
+ cwd: taskCwd,
306
312
  sessionId: task.taskId,
307
313
  type: promptType,
308
314
  name: promptName,
309
315
  data
310
316
  }, env)
311
317
 
312
- const injectDefaultSystemPrompt = await loadInjectDefaultSystemPromptValue(promptCWD)
318
+ const injectDefaultSystemPrompt = await loadInjectDefaultSystemPromptValue(taskCwd)
313
319
  const ctxId = process.env.__VF_PROJECT_AI_CTX_ID__ ?? task.taskId
314
320
  const { session, resolvedAdapter } = await run({
315
321
  adapter: task.adapter,
316
- cwd: process.cwd(),
322
+ cwd: taskCwd,
317
323
  env: {
318
- ...process.env,
324
+ ...env,
319
325
  __VF_PROJECT_AI_CTX_ID__: ctxId
320
326
  }
321
327
  }, {
@@ -352,7 +358,7 @@ export class TaskManager {
352
358
  current.lastError = undefined
353
359
  try {
354
360
  await syncTaskPermissionStateMirror({
355
- cwd: process.cwd(),
361
+ cwd: taskCwd,
356
362
  adapter: current.adapter,
357
363
  sessionId: current.taskId,
358
364
  permissionState: current.permissionState
@@ -7,7 +7,7 @@ import type { TaskInfo } from './manager'
7
7
  export const SESSION_PERMISSION_MODES = ['default', 'acceptEdits', 'plan', 'dontAsk', 'bypassPermissions'] as const
8
8
 
9
9
  export const START_TASKS_DESCRIPTION =
10
- 'Start multiple tasks in background or foreground. If a task stalls, fails, or asks for permission/input, call GetTaskInfo. If GetTaskInfo returns pendingInput or pendingInteraction, resolve it with SubmitTaskInput. If logs show permission_required, you can answer the recovery prompt with SubmitTaskInput instead of restarting manually.'
10
+ 'Start multiple tasks in background or foreground. Use type "workspace" plus name to run in a configured workspace. If a task stalls, fails, or asks for permission/input, call GetTaskInfo. If GetTaskInfo returns pendingInput or pendingInteraction, resolve it with SubmitTaskInput. If logs show permission_required, you can answer the recovery prompt with SubmitTaskInput instead of restarting manually.'
11
11
 
12
12
  export const GET_TASK_INFO_DESCRIPTION =
13
13
  'Get the detailed status, logs, pendingInput, pendingInteraction, lastError, and guidance for a task. Use this when a task seems stuck, is waiting for permission/input, or has failed. If pendingInput is present, answer it with SubmitTaskInput.'