@vibe-forge/mcp 3.0.0-alpha.9 → 3.1.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.
|
@@ -197,6 +197,40 @@ describe('taskManager fatal error scenarios', () => {
|
|
|
197
197
|
}))
|
|
198
198
|
})
|
|
199
199
|
|
|
200
|
+
it('uses the task id as the adapter cache context instead of an inherited parent context', async () => {
|
|
201
|
+
process.env.__VF_PROJECT_AI_CTX_ID__ = 'parent-ctx'
|
|
202
|
+
const { TaskManager } = await import('#~/tools/task/manager.js')
|
|
203
|
+
|
|
204
|
+
mocks.run.mockResolvedValueOnce({
|
|
205
|
+
session: {
|
|
206
|
+
emit: vi.fn(),
|
|
207
|
+
kill: vi.fn()
|
|
208
|
+
}
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
try {
|
|
212
|
+
const managedTaskManager = new TaskManager()
|
|
213
|
+
await managedTaskManager.startTask({
|
|
214
|
+
taskId: 'task-stable-context',
|
|
215
|
+
description: 'trigger',
|
|
216
|
+
adapter: 'codex'
|
|
217
|
+
})
|
|
218
|
+
} finally {
|
|
219
|
+
delete process.env.__VF_PROJECT_AI_CTX_ID__
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
expect(mocks.run).toHaveBeenCalledWith(
|
|
223
|
+
expect.objectContaining({
|
|
224
|
+
env: expect.objectContaining({
|
|
225
|
+
__VF_PROJECT_AI_CTX_ID__: 'task-stable-context'
|
|
226
|
+
})
|
|
227
|
+
}),
|
|
228
|
+
expect.objectContaining({
|
|
229
|
+
sessionId: 'task-stable-context'
|
|
230
|
+
})
|
|
231
|
+
)
|
|
232
|
+
})
|
|
233
|
+
|
|
200
234
|
it('responds to pending interactions and syncs the response', async () => {
|
|
201
235
|
const { TaskManager } = await import('#~/tools/task/manager.js')
|
|
202
236
|
const respondInteraction = vi.fn()
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibe-forge/mcp",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "Vibe Forge MCP server",
|
|
5
5
|
"imports": {
|
|
6
6
|
"#~/*.js": {
|
|
@@ -33,13 +33,13 @@
|
|
|
33
33
|
"@modelcontextprotocol/sdk": "^1.25.3",
|
|
34
34
|
"commander": "^12.1.0",
|
|
35
35
|
"zod": "^3.24.1",
|
|
36
|
-
"@vibe-forge/
|
|
37
|
-
"@vibe-forge/
|
|
38
|
-
"@vibe-forge/
|
|
39
|
-
"@vibe-forge/
|
|
40
|
-
"@vibe-forge/
|
|
41
|
-
"@vibe-forge/
|
|
42
|
-
"@vibe-forge/utils": "3.
|
|
36
|
+
"@vibe-forge/cli-helper": "3.0.1",
|
|
37
|
+
"@vibe-forge/config": "3.1.0",
|
|
38
|
+
"@vibe-forge/hooks": "3.1.0",
|
|
39
|
+
"@vibe-forge/register": "3.0.1",
|
|
40
|
+
"@vibe-forge/task": "3.1.0",
|
|
41
|
+
"@vibe-forge/types": "3.1.0",
|
|
42
|
+
"@vibe-forge/utils": "3.1.0"
|
|
43
43
|
},
|
|
44
44
|
"scripts": {
|
|
45
45
|
"test": "pnpm -C ../.. exec vitest run --workspace vitest.workspace.ts --project bundler packages/mcp/__tests__"
|
|
@@ -342,7 +342,7 @@ export class TaskManager {
|
|
|
342
342
|
task.workspaceCwd = resolvedConfig.workspace?.cwd
|
|
343
343
|
const env = {
|
|
344
344
|
...process.env,
|
|
345
|
-
__VF_PROJECT_AI_CTX_ID__:
|
|
345
|
+
__VF_PROJECT_AI_CTX_ID__: task.taskId,
|
|
346
346
|
__VF_PROJECT_WORKSPACE_FOLDER__: taskCwd,
|
|
347
347
|
__VF_PROJECT_PRIMARY_WORKSPACE_FOLDER__: rootCwd
|
|
348
348
|
}
|
|
@@ -355,7 +355,7 @@ export class TaskManager {
|
|
|
355
355
|
}, env)
|
|
356
356
|
|
|
357
357
|
const injectDefaultSystemPrompt = await loadInjectDefaultSystemPromptValue(taskCwd)
|
|
358
|
-
const ctxId =
|
|
358
|
+
const ctxId = task.taskId
|
|
359
359
|
const { session, resolvedAdapter } = await run({
|
|
360
360
|
adapter: task.adapter,
|
|
361
361
|
cwd: taskCwd,
|
|
@@ -78,7 +78,9 @@ const buildTaskGuidance = (task: {
|
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
if (task.status === 'failed' && hints.length === 0) {
|
|
81
|
-
hints.push(
|
|
81
|
+
hints.push(
|
|
82
|
+
'Task failed. Inspect logs and lastError, then use SendTaskMessage to resume it or StartTasks to replace it if needed.'
|
|
83
|
+
)
|
|
82
84
|
}
|
|
83
85
|
|
|
84
86
|
return hints
|
|
@@ -11,10 +11,14 @@ import {
|
|
|
11
11
|
STOP_TASK_DESCRIPTION,
|
|
12
12
|
SUBMIT_TASK_INPUT_DESCRIPTION,
|
|
13
13
|
TASK_LOG_LIMIT_DESCRIPTION,
|
|
14
|
-
TASK_LOG_ORDER_DESCRIPTION,
|
|
15
14
|
TASK_LOG_ORDERS,
|
|
16
|
-
|
|
15
|
+
TASK_LOG_ORDER_DESCRIPTION
|
|
17
16
|
} from './presentation'
|
|
17
|
+
import {
|
|
18
|
+
createSerializedTaskInfoContent,
|
|
19
|
+
createSerializedTaskListContent,
|
|
20
|
+
createTextContent
|
|
21
|
+
} from './task-tool-responses'
|
|
18
22
|
|
|
19
23
|
export const registerTaskRuntimeTools = (
|
|
20
24
|
server: Parameters<Register>[0],
|
|
@@ -43,15 +47,12 @@ export const registerTaskRuntimeTools = (
|
|
|
43
47
|
const task = taskManager.getTask(taskId)
|
|
44
48
|
if (!task) {
|
|
45
49
|
return {
|
|
46
|
-
content:
|
|
50
|
+
content: createTextContent(`Task ${taskId} not found.`),
|
|
47
51
|
isError: true
|
|
48
52
|
}
|
|
49
53
|
}
|
|
50
54
|
return {
|
|
51
|
-
content:
|
|
52
|
-
type: 'text',
|
|
53
|
-
text: JSON.stringify([serializeTaskInfo({ taskId, info: task, logLimit, logOrder })])
|
|
54
|
-
}]
|
|
55
|
+
content: createSerializedTaskInfoContent({ taskId, info: task, logLimit, logOrder })
|
|
55
56
|
}
|
|
56
57
|
}
|
|
57
58
|
)
|
|
@@ -82,15 +83,7 @@ export const registerTaskRuntimeTools = (
|
|
|
82
83
|
})
|
|
83
84
|
const task = taskManager.getTask(taskId)
|
|
84
85
|
return {
|
|
85
|
-
content:
|
|
86
|
-
type: 'text',
|
|
87
|
-
text: JSON.stringify([serializeTaskInfo({
|
|
88
|
-
taskId,
|
|
89
|
-
info: task,
|
|
90
|
-
logLimit: DEFAULT_TASK_LOG_LIMIT,
|
|
91
|
-
logOrder: 'desc'
|
|
92
|
-
})])
|
|
93
|
-
}]
|
|
86
|
+
content: createSerializedTaskInfoContent({ taskId, info: task })
|
|
94
87
|
}
|
|
95
88
|
}
|
|
96
89
|
)
|
|
@@ -119,15 +112,7 @@ export const registerTaskRuntimeTools = (
|
|
|
119
112
|
})
|
|
120
113
|
const task = taskManager.getTask(taskId)
|
|
121
114
|
return {
|
|
122
|
-
content:
|
|
123
|
-
type: 'text',
|
|
124
|
-
text: JSON.stringify([serializeTaskInfo({
|
|
125
|
-
taskId,
|
|
126
|
-
info: task,
|
|
127
|
-
logLimit: DEFAULT_TASK_LOG_LIMIT,
|
|
128
|
-
logOrder: 'desc'
|
|
129
|
-
})])
|
|
130
|
-
}]
|
|
115
|
+
content: createSerializedTaskInfoContent({ taskId, info: task })
|
|
131
116
|
}
|
|
132
117
|
}
|
|
133
118
|
)
|
|
@@ -156,15 +141,7 @@ export const registerTaskRuntimeTools = (
|
|
|
156
141
|
})
|
|
157
142
|
const task = taskManager.getTask(taskId)
|
|
158
143
|
return {
|
|
159
|
-
content:
|
|
160
|
-
type: 'text',
|
|
161
|
-
text: JSON.stringify([serializeTaskInfo({
|
|
162
|
-
taskId,
|
|
163
|
-
info: task,
|
|
164
|
-
logLimit: DEFAULT_TASK_LOG_LIMIT,
|
|
165
|
-
logOrder: 'desc'
|
|
166
|
-
})])
|
|
167
|
-
}]
|
|
144
|
+
content: createSerializedTaskInfoContent({ taskId, info: task })
|
|
168
145
|
}
|
|
169
146
|
}
|
|
170
147
|
)
|
|
@@ -181,10 +158,9 @@ export const registerTaskRuntimeTools = (
|
|
|
181
158
|
async ({ taskId }) => {
|
|
182
159
|
const success = taskManager.stopTask(taskId)
|
|
183
160
|
return {
|
|
184
|
-
content:
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
}]
|
|
161
|
+
content: createTextContent(
|
|
162
|
+
success ? `Task ${taskId} stopped.` : `Failed to stop task ${taskId} (not found or already stopped).`
|
|
163
|
+
)
|
|
188
164
|
}
|
|
189
165
|
}
|
|
190
166
|
)
|
|
@@ -210,15 +186,7 @@ export const registerTaskRuntimeTools = (
|
|
|
210
186
|
async ({ logLimit, logOrder }) => {
|
|
211
187
|
const tasks = taskManager.getAllTasks()
|
|
212
188
|
return {
|
|
213
|
-
content:
|
|
214
|
-
type: 'text',
|
|
215
|
-
text: JSON.stringify(tasks.map(task => serializeTaskInfo({
|
|
216
|
-
taskId: task.taskId,
|
|
217
|
-
info: task,
|
|
218
|
-
logLimit,
|
|
219
|
-
logOrder
|
|
220
|
-
})))
|
|
221
|
-
}]
|
|
189
|
+
content: createSerializedTaskListContent(tasks, logLimit, logOrder)
|
|
222
190
|
}
|
|
223
191
|
}
|
|
224
192
|
)
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { TaskInfo } from './manager'
|
|
2
|
+
import { DEFAULT_TASK_LOG_LIMIT, serializeTaskInfo } from './presentation'
|
|
3
|
+
import type { TaskLogsOrder } from './presentation'
|
|
4
|
+
|
|
5
|
+
interface TextContent {
|
|
6
|
+
type: 'text'
|
|
7
|
+
text: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const createTextContent = (text: string): TextContent[] => [{
|
|
11
|
+
type: 'text',
|
|
12
|
+
text
|
|
13
|
+
}]
|
|
14
|
+
|
|
15
|
+
export const createSerializedTaskInfoContent = (params: {
|
|
16
|
+
taskId: string
|
|
17
|
+
info?: TaskInfo
|
|
18
|
+
logLimit?: number
|
|
19
|
+
logOrder?: TaskLogsOrder
|
|
20
|
+
}) =>
|
|
21
|
+
createTextContent(JSON.stringify([serializeTaskInfo({
|
|
22
|
+
taskId: params.taskId,
|
|
23
|
+
info: params.info,
|
|
24
|
+
logLimit: params.logLimit ?? DEFAULT_TASK_LOG_LIMIT,
|
|
25
|
+
logOrder: params.logOrder ?? 'desc'
|
|
26
|
+
})]))
|
|
27
|
+
|
|
28
|
+
export const createSerializedTaskListContent = (
|
|
29
|
+
tasks: TaskInfo[],
|
|
30
|
+
logLimit: number,
|
|
31
|
+
logOrder: TaskLogsOrder
|
|
32
|
+
) =>
|
|
33
|
+
createTextContent(JSON.stringify(tasks.map(task =>
|
|
34
|
+
serializeTaskInfo({
|
|
35
|
+
taskId: task.taskId,
|
|
36
|
+
info: task,
|
|
37
|
+
logLimit,
|
|
38
|
+
logOrder
|
|
39
|
+
})
|
|
40
|
+
)))
|