mirror of
https://github.com/cjo4m06/mcp-shrimp-task-manager.git
synced 2025-07-27 00:12:26 +08:00
parent
313e338f7b
commit
5d1c28dd97
@ -25,6 +25,8 @@ import {
|
|||||||
reflectTaskSchema,
|
reflectTaskSchema,
|
||||||
splitTasks,
|
splitTasks,
|
||||||
splitTasksSchema,
|
splitTasksSchema,
|
||||||
|
splitTasksRaw,
|
||||||
|
splitTasksRawSchema,
|
||||||
listTasksSchema,
|
listTasksSchema,
|
||||||
listTasks,
|
listTasks,
|
||||||
executeTask,
|
executeTask,
|
||||||
@ -207,7 +209,7 @@ async function main() {
|
|||||||
description: loadPromptFromTemplate(
|
description: loadPromptFromTemplate(
|
||||||
"toolsDescription/splitTasks.md"
|
"toolsDescription/splitTasks.md"
|
||||||
),
|
),
|
||||||
inputSchema: zodToJsonSchema(splitTasksSchema),
|
inputSchema: zodToJsonSchema(splitTasksRawSchema),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "list_tasks",
|
name: "list_tasks",
|
||||||
@ -324,7 +326,7 @@ async function main() {
|
|||||||
}
|
}
|
||||||
return await reflectTask(parsedArgs.data);
|
return await reflectTask(parsedArgs.data);
|
||||||
case "split_tasks":
|
case "split_tasks":
|
||||||
parsedArgs = await splitTasksSchema.safeParseAsync(
|
parsedArgs = await splitTasksRawSchema.safeParseAsync(
|
||||||
request.params.arguments
|
request.params.arguments
|
||||||
);
|
);
|
||||||
if (!parsedArgs.success) {
|
if (!parsedArgs.success) {
|
||||||
@ -332,7 +334,7 @@ async function main() {
|
|||||||
`Invalid arguments for tool ${request.params.name}: ${parsedArgs.error.message}`
|
`Invalid arguments for tool ${request.params.name}: ${parsedArgs.error.message}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return await splitTasks(parsedArgs.data);
|
return await splitTasksRaw(parsedArgs.data);
|
||||||
case "list_tasks":
|
case "list_tasks":
|
||||||
parsedArgs = await listTasksSchema.safeParseAsync(
|
parsedArgs = await listTasksSchema.safeParseAsync(
|
||||||
request.params.arguments
|
request.params.arguments
|
||||||
|
@ -39,6 +39,9 @@ After receiving the solution and suggestions, conduct self-reflection and final
|
|||||||
- Ensure that the task group after splitting still maintains overall architectural consistency
|
- Ensure that the task group after splitting still maintains overall architectural consistency
|
||||||
|
|
||||||
7. **Submit Final Results**
|
7. **Submit Final Results**
|
||||||
|
- **No Comments Allowed**: JSON does not support comments — Any use of `#` or `//` will cause parsing failures
|
||||||
|
- **Proper Escaping Required**: All special characters (e.g., double quotes `\"`, backslashes `\\`) must be properly escaped, or they will be considered invalid.
|
||||||
|
- **Line Breaks**: If you need line breaks, use escape sequences like \\n or \\r. Direct line breaks will cause parsing errors.
|
||||||
- Adjusted final solution + reflection report
|
- Adjusted final solution + reflection report
|
||||||
- Call tool:
|
- Call tool:
|
||||||
```
|
```
|
||||||
|
@ -37,6 +37,15 @@ Break down complex tasks into independent subtasks, establishing dependencies an
|
|||||||
- Only outline high-level logic and key steps.
|
- Only outline high-level logic and key steps.
|
||||||
- Avoid providing complete source code.
|
- Avoid providing complete source code.
|
||||||
- Check **dependencies** between subtasks and specify them in the `dependencies` field.
|
- Check **dependencies** between subtasks and specify them in the `dependencies` field.
|
||||||
|
- If the task involves interface design, always provide a complete and consistent definition, including:
|
||||||
|
|
||||||
|
- Function/class/schema definitions (including names, parameters, return values)
|
||||||
|
- Data types, usage descriptions, and optional/required status for each item
|
||||||
|
- Error handling methods and expected exception scenarios
|
||||||
|
- Dependency and naming conventions (if any)
|
||||||
|
- Sample data and usage examples
|
||||||
|
|
||||||
|
This ensures consistency, readability, and development precision between tasks.
|
||||||
|
|
||||||
## 3. **Dependencies and Prioritization**
|
## 3. **Dependencies and Prioritization**
|
||||||
|
|
||||||
@ -64,3 +73,11 @@ When you need to create a new task that is not related to the current task list,
|
|||||||
- ### **Proper Escaping Required**
|
- ### **Proper Escaping Required**
|
||||||
All special characters (e.g., double quotes `\"`, backslashes `\\`) must be properly escaped,
|
All special characters (e.g., double quotes `\"`, backslashes `\\`) must be properly escaped,
|
||||||
or they will be considered invalid.
|
or they will be considered invalid.
|
||||||
|
|
||||||
|
## 6. **Important Notes**
|
||||||
|
|
||||||
|
These tasks will be executed by low-intelligence models, so please follow the guidelines below:
|
||||||
|
|
||||||
|
- `Clear and Explicit Instructions`: This prevents the model from producing incorrect or inconsistent architecture/code styles. Provide clear commands or specifications.
|
||||||
|
- `Encapsulated Interfaces`: Each task runs independently. Define the interfaces clearly — such as function names, parameters, return values — so that other task-executing models can easily understand how to interact with or integrate these functions.
|
||||||
|
- `Dependencies`: If there are dependencies between tasks, define the interaction interfaces first. Tasks do not need to know each other's implementation, but must know how to interact with one another.
|
||||||
|
@ -39,8 +39,13 @@
|
|||||||
- 確保拆分後的任務群組仍維持架構的整體一致性
|
- 確保拆分後的任務群組仍維持架構的整體一致性
|
||||||
|
|
||||||
7. **提交最終結果**
|
7. **提交最終結果**
|
||||||
|
|
||||||
|
- **禁止註解**:JSON 本身不支援註解,任何 `#` 或 `//` 都會導致解析失敗
|
||||||
|
- **注意轉義**:所有特殊字元(如雙引號 `\"`、反斜線 `\\`)必須正確轉義,否則視為非法字元
|
||||||
|
- **換行符號**:如果需要換行請使用跳脫符號`\\n` 或 `\\r`,直接換行會導致解析失敗
|
||||||
- 調整後的最終方案 + 反思報告
|
- 調整後的最終方案 + 反思報告
|
||||||
- 呼叫工具:
|
- 呼叫工具:
|
||||||
|
|
||||||
```
|
```
|
||||||
split_tasks( ... )
|
split_tasks( ... )
|
||||||
```
|
```
|
||||||
|
@ -19,6 +19,15 @@
|
|||||||
- 在每個子任務下標註「輸入/輸出」與「驗收標準」
|
- 在每個子任務下標註「輸入/輸出」與「驗收標準」
|
||||||
- 如果需要請提供「pseudocode」,僅提供高級邏輯流程和關鍵步驟避免完整代碼
|
- 如果需要請提供「pseudocode」,僅提供高級邏輯流程和關鍵步驟避免完整代碼
|
||||||
- 檢查子任務間「前後依賴」,並在 `dependencies` 欄位標明
|
- 檢查子任務間「前後依賴」,並在 `dependencies` 欄位標明
|
||||||
|
- 若任務涉及介面設計,請務必提供完整且一致的定義,包括:
|
||||||
|
|
||||||
|
- function / class / schema 定義(含名稱、參數、回傳值)
|
||||||
|
- 各項目之資料型別、用途描述、是否為選填
|
||||||
|
- 錯誤處理方式與預期異常情境
|
||||||
|
- 依賴關係與命名規範(如有)
|
||||||
|
- 範例資料與使用方式
|
||||||
|
|
||||||
|
這將有助於任務之間的連貫性、可讀性與開發精確性。
|
||||||
|
|
||||||
3. **依賴與優先順序**
|
3. **依賴與優先順序**
|
||||||
|
|
||||||
@ -35,5 +44,14 @@
|
|||||||
- `clearAllTasks`:清除所有任務並自動備份現有列表
|
- `clearAllTasks`:清除所有任務並自動備份現有列表
|
||||||
|
|
||||||
5. **JSON 嚴謹規則**
|
5. **JSON 嚴謹規則**
|
||||||
|
|
||||||
- **禁止註解**:JSON 本身不支援註解,任何 `#` 或 `//` 都會導致解析失敗
|
- **禁止註解**:JSON 本身不支援註解,任何 `#` 或 `//` 都會導致解析失敗
|
||||||
- **注意轉義**:所有特殊字元(如雙引號 `\"`、反斜線 `\\`)必須正確轉義,否則視為非法字元
|
- **注意轉義**:所有特殊字元(如雙引號 `\"`、反斜線 `\\`)必須正確轉義,否則視為非法字元
|
||||||
|
|
||||||
|
6. **重要訊息**
|
||||||
|
|
||||||
|
這些任務將會分配給**低智能模型**執行,所以你必須參考以下幾點
|
||||||
|
|
||||||
|
- `明確且清楚的指導`:這將避免**低智能模型**設計出錯誤或架構風格不一致的程式碼,所以請給予明確的指令或規範
|
||||||
|
- `封裝接口`:每個任務都會是獨立執行,所以需要定義好接口,例如你會暴露出什麼 function name 有什麼參數,會回傳什麼等等的資訊,方便其他任務執行模型可以快速的知道如何使用或穿接相關功能
|
||||||
|
- `依賴性`:如果任務與任務之間有依賴性,那應該是先定義好交互的介面,任務之間不需要知道各自的實作,但需要知道如何與對方交互
|
||||||
|
@ -35,3 +35,5 @@ export { queryTask, queryTaskSchema } from "./queryTask.js";
|
|||||||
|
|
||||||
// getTaskDetail
|
// getTaskDetail
|
||||||
export { getTaskDetail, getTaskDetailSchema } from "./getTaskDetail.js";
|
export { getTaskDetail, getTaskDetailSchema } from "./getTaskDetail.js";
|
||||||
|
|
||||||
|
export { splitTasksRaw, splitTasksRawSchema } from "./splitTasksRaw.js";
|
||||||
|
285
src/tools/task/splitTasksRaw.ts
Normal file
285
src/tools/task/splitTasksRaw.ts
Normal file
@ -0,0 +1,285 @@
|
|||||||
|
import { z } from "zod";
|
||||||
|
import {
|
||||||
|
getAllTasks,
|
||||||
|
batchCreateOrUpdateTasks,
|
||||||
|
clearAllTasks as modelClearAllTasks,
|
||||||
|
} from "../../models/taskModel.js";
|
||||||
|
import { RelatedFileType, Task } from "../../types/index.js";
|
||||||
|
import { getSplitTasksPrompt } from "../../prompts/index.js";
|
||||||
|
|
||||||
|
// 拆分任務工具
|
||||||
|
export const splitTasksRawSchema = z.object({
|
||||||
|
updateMode: z
|
||||||
|
.enum(["append", "overwrite", "selective", "clearAllTasks"])
|
||||||
|
.describe(
|
||||||
|
"任務更新模式選擇:'append'(保留所有現有任務並添加新任務)、'overwrite'(清除所有未完成任務並完全替換,保留已完成任務)、'selective'(智能更新:根據任務名稱匹配更新現有任務,保留不在列表中的任務,推薦用於任務微調)、'clearAllTasks'(清除所有任務並創建備份)。\n預設為'clearAllTasks'模式,只有用戶要求變更或修改計劃內容才使用其他模式"
|
||||||
|
),
|
||||||
|
tasksRaw: z
|
||||||
|
.string()
|
||||||
|
.describe(
|
||||||
|
"結構化的任務清單,每個任務應保持原子性且有明確的完成標準,避免過於簡單的任務,簡單修改可與其他任務整合,避免任務過多,範例:[{name: '簡潔明確的任務名稱,應能清晰表達任務目的', description: '詳細的任務描述,包含實施要點、技術細節和驗收標準', implementationGuide: '此特定任務的具體實現方法和步驟,請參考之前的分析結果提供精簡pseudocode', notes: '補充說明、特殊處理要求或實施建議(選填)', dependencies: ['此任務依賴的前置任務完整名稱'], relatedFiles: [{path: '文件路徑', type: '文件類型 (TO_MODIFY: 待修改, REFERENCE: 參考資料, CREATE: 待建立, DEPENDENCY: 依賴文件, OTHER: 其他)', description: '文件描述', lineStart: 1, lineEnd: 100}], verificationCriteria: '此特定任務的驗證標準和檢驗方法'}, {name: '任務2', description: '任務2描述', implementationGuide: '任務2實現方法', notes: '補充說明、特殊處理要求或實施建議(選填)', dependencies: ['任務1'], relatedFiles: [{path: '文件路徑', type: '文件類型 (TO_MODIFY: 待修改, REFERENCE: 參考資料, CREATE: 待建立, DEPENDENCY: 依賴文件, OTHER: 其他)', description: '文件描述', lineStart: 1, lineEnd: 100}], verificationCriteria: '此特定任務的驗證標準和檢驗方法'}]"
|
||||||
|
),
|
||||||
|
globalAnalysisResult: z
|
||||||
|
.string()
|
||||||
|
.optional()
|
||||||
|
.describe(
|
||||||
|
"全局分析結果:來自 reflect_task 的完整分析結果,適用於所有任務的通用部分"
|
||||||
|
),
|
||||||
|
});
|
||||||
|
|
||||||
|
const tasksSchema = z
|
||||||
|
.array(
|
||||||
|
z.object({
|
||||||
|
name: z
|
||||||
|
.string()
|
||||||
|
.max(100, {
|
||||||
|
message: "任務名稱過長,請限制在100個字符以內",
|
||||||
|
})
|
||||||
|
.describe("簡潔明確的任務名稱,應能清晰表達任務目的"),
|
||||||
|
description: z
|
||||||
|
.string()
|
||||||
|
.min(10, {
|
||||||
|
message: "任務描述過短,請提供更詳細的內容以確保理解",
|
||||||
|
})
|
||||||
|
.describe("詳細的任務描述,包含實施要點、技術細節和驗收標準"),
|
||||||
|
implementationGuide: z
|
||||||
|
.string()
|
||||||
|
.describe(
|
||||||
|
"此特定任務的具體實現方法和步驟,請參考之前的分析結果提供精簡pseudocode"
|
||||||
|
),
|
||||||
|
dependencies: z
|
||||||
|
.array(z.string())
|
||||||
|
.optional()
|
||||||
|
.describe(
|
||||||
|
"此任務依賴的前置任務ID或任務名稱列表,支持兩種引用方式,名稱引用更直觀,是一個字串陣列"
|
||||||
|
),
|
||||||
|
notes: z
|
||||||
|
.string()
|
||||||
|
.optional()
|
||||||
|
.describe("補充說明、特殊處理要求或實施建議(選填)"),
|
||||||
|
relatedFiles: z
|
||||||
|
.array(
|
||||||
|
z.object({
|
||||||
|
path: z
|
||||||
|
.string()
|
||||||
|
.min(1, {
|
||||||
|
message: "文件路徑不能為空",
|
||||||
|
})
|
||||||
|
.describe("文件路徑,可以是相對於項目根目錄的路徑或絕對路徑"),
|
||||||
|
type: z
|
||||||
|
.nativeEnum(RelatedFileType)
|
||||||
|
.describe(
|
||||||
|
"文件類型 (TO_MODIFY: 待修改, REFERENCE: 參考資料, CREATE: 待建立, DEPENDENCY: 依賴文件, OTHER: 其他)"
|
||||||
|
),
|
||||||
|
description: z
|
||||||
|
.string()
|
||||||
|
.min(1, {
|
||||||
|
message: "文件描述不能為空",
|
||||||
|
})
|
||||||
|
.describe("文件描述,用於說明文件的用途和內容"),
|
||||||
|
lineStart: z
|
||||||
|
.number()
|
||||||
|
.int()
|
||||||
|
.positive()
|
||||||
|
.optional()
|
||||||
|
.describe("相關代碼區塊的起始行(選填)"),
|
||||||
|
lineEnd: z
|
||||||
|
.number()
|
||||||
|
.int()
|
||||||
|
.positive()
|
||||||
|
.optional()
|
||||||
|
.describe("相關代碼區塊的結束行(選填)"),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.optional()
|
||||||
|
.describe(
|
||||||
|
"與任務相關的文件列表,用於記錄與任務相關的代碼文件、參考資料、要建立的文件等(選填)"
|
||||||
|
),
|
||||||
|
verificationCriteria: z
|
||||||
|
.string()
|
||||||
|
.optional()
|
||||||
|
.describe("此特定任務的驗證標準和檢驗方法"),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.min(1, {
|
||||||
|
message: "請至少提供一個任務",
|
||||||
|
})
|
||||||
|
.describe(
|
||||||
|
"結構化的任務清單,每個任務應保持原子性且有明確的完成標準,避免過於簡單的任務,簡單修改可與其他任務整合,避免任務過多"
|
||||||
|
);
|
||||||
|
|
||||||
|
export async function splitTasksRaw({
|
||||||
|
updateMode,
|
||||||
|
tasksRaw,
|
||||||
|
globalAnalysisResult,
|
||||||
|
}: z.infer<typeof splitTasksRawSchema>) {
|
||||||
|
let tasks: Task[] = [];
|
||||||
|
try {
|
||||||
|
tasks = JSON.parse(tasksRaw);
|
||||||
|
} catch (error) {
|
||||||
|
return {
|
||||||
|
content: [
|
||||||
|
{
|
||||||
|
type: "text" as const,
|
||||||
|
text:
|
||||||
|
"tasks 參數格式錯誤,請確保格式正確,錯誤訊息:" +
|
||||||
|
(error instanceof Error ? error.message : String(error)),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用 tasksSchema 驗證 tasks
|
||||||
|
const tasksResult = tasksSchema.safeParse(tasks);
|
||||||
|
if (!tasksResult.success) {
|
||||||
|
// 返回錯誤訊息
|
||||||
|
return {
|
||||||
|
content: [
|
||||||
|
{
|
||||||
|
type: "text" as const,
|
||||||
|
text:
|
||||||
|
"tasks 參數格式錯誤,請確保格式正確,錯誤訊息:" +
|
||||||
|
tasksResult.error.message,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 檢查 tasks 裡面的 name 是否有重複
|
||||||
|
const nameSet = new Set();
|
||||||
|
for (const task of tasks) {
|
||||||
|
if (nameSet.has(task.name)) {
|
||||||
|
return {
|
||||||
|
content: [
|
||||||
|
{
|
||||||
|
type: "text" as const,
|
||||||
|
text: "tasks 參數中存在重複的任務名稱,請確保每個任務名稱是唯一的",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
nameSet.add(task.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根據不同的更新模式處理任務
|
||||||
|
let message = "";
|
||||||
|
let actionSuccess = true;
|
||||||
|
let backupFile = null;
|
||||||
|
let createdTasks: Task[] = [];
|
||||||
|
let allTasks: Task[] = [];
|
||||||
|
|
||||||
|
// 將任務資料轉換為符合batchCreateOrUpdateTasks的格式
|
||||||
|
const convertedTasks = tasks.map((task) => ({
|
||||||
|
name: task.name,
|
||||||
|
description: task.description,
|
||||||
|
notes: task.notes,
|
||||||
|
dependencies: task.dependencies as unknown as string[],
|
||||||
|
implementationGuide: task.implementationGuide,
|
||||||
|
verificationCriteria: task.verificationCriteria,
|
||||||
|
relatedFiles: task.relatedFiles?.map((file) => ({
|
||||||
|
path: file.path,
|
||||||
|
type: file.type as RelatedFileType,
|
||||||
|
description: file.description,
|
||||||
|
lineStart: file.lineStart,
|
||||||
|
lineEnd: file.lineEnd,
|
||||||
|
})),
|
||||||
|
}));
|
||||||
|
|
||||||
|
// 處理 clearAllTasks 模式
|
||||||
|
if (updateMode === "clearAllTasks") {
|
||||||
|
const clearResult = await modelClearAllTasks();
|
||||||
|
|
||||||
|
if (clearResult.success) {
|
||||||
|
message = clearResult.message;
|
||||||
|
backupFile = clearResult.backupFile;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 清空任務後再創建新任務
|
||||||
|
createdTasks = await batchCreateOrUpdateTasks(
|
||||||
|
convertedTasks,
|
||||||
|
"append",
|
||||||
|
globalAnalysisResult
|
||||||
|
);
|
||||||
|
message += `\n成功創建了 ${createdTasks.length} 個新任務。`;
|
||||||
|
} catch (error) {
|
||||||
|
actionSuccess = false;
|
||||||
|
message += `\n創建新任務時發生錯誤: ${
|
||||||
|
error instanceof Error ? error.message : String(error)
|
||||||
|
}`;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
actionSuccess = false;
|
||||||
|
message = clearResult.message;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 對於其他模式,直接使用 batchCreateOrUpdateTasks
|
||||||
|
try {
|
||||||
|
createdTasks = await batchCreateOrUpdateTasks(
|
||||||
|
convertedTasks,
|
||||||
|
updateMode,
|
||||||
|
globalAnalysisResult
|
||||||
|
);
|
||||||
|
|
||||||
|
// 根據不同的更新模式生成消息
|
||||||
|
switch (updateMode) {
|
||||||
|
case "append":
|
||||||
|
message = `成功追加了 ${createdTasks.length} 個新任務。`;
|
||||||
|
break;
|
||||||
|
case "overwrite":
|
||||||
|
message = `成功清除未完成任務並創建了 ${createdTasks.length} 個新任務。`;
|
||||||
|
break;
|
||||||
|
case "selective":
|
||||||
|
message = `成功選擇性更新/創建了 ${createdTasks.length} 個任務。`;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
actionSuccess = false;
|
||||||
|
message = `任務創建失敗:${
|
||||||
|
error instanceof Error ? error.message : String(error)
|
||||||
|
}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 獲取所有任務用於顯示依賴關係
|
||||||
|
try {
|
||||||
|
allTasks = await getAllTasks();
|
||||||
|
} catch (error) {
|
||||||
|
allTasks = [...createdTasks]; // 如果獲取失敗,至少使用剛創建的任務
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用prompt生成器獲取最終prompt
|
||||||
|
const prompt = getSplitTasksPrompt({
|
||||||
|
updateMode,
|
||||||
|
createdTasks,
|
||||||
|
allTasks,
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
content: [
|
||||||
|
{
|
||||||
|
type: "text" as const,
|
||||||
|
text: prompt,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
ephemeral: {
|
||||||
|
taskCreationResult: {
|
||||||
|
success: actionSuccess,
|
||||||
|
message,
|
||||||
|
backupFilePath: backupFile,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
return {
|
||||||
|
content: [
|
||||||
|
{
|
||||||
|
type: "text" as const,
|
||||||
|
text:
|
||||||
|
"執行任務拆分時發生錯誤: " +
|
||||||
|
(error instanceof Error ? error.message : String(error)),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user