新增任務相關的 prompt 生成器及模板,包括刪除任務、清除所有任務和更新任務內容,提升任務管理的靈活性與可讀性。

This commit is contained in:
siage 2025-04-26 23:04:02 +08:00
parent 52994d5582
commit a51110f4fa
20 changed files with 377 additions and 109 deletions

View File

@ -0,0 +1,64 @@
/**
* clearAllTasks prompt
* prompt
*/
import {
loadPrompt,
generatePrompt,
loadPromptFromTemplate,
} from "../loader.js";
/**
* clearAllTasks prompt
*/
export interface ClearAllTasksPromptParams {
confirm?: boolean;
success?: boolean;
message?: string;
backupFile?: string;
isEmpty?: boolean;
}
/**
* clearAllTasks prompt
* @param params prompt
* @returns prompt
*/
export function getClearAllTasksPrompt(
params: ClearAllTasksPromptParams
): string {
const { confirm, success, message, backupFile, isEmpty } = params;
// 處理未確認的情況
if (confirm === false) {
const cancelTemplate = loadPromptFromTemplate("clearAllTasks/cancel.md");
return generatePrompt(cancelTemplate, {});
}
// 處理無任務需要清除的情況
if (isEmpty) {
const emptyTemplate = loadPromptFromTemplate("clearAllTasks/empty.md");
return generatePrompt(emptyTemplate, {});
}
// 處理清除成功或失敗的情況
const responseTitle = success ? "Success" : "Failure";
// 使用模板生成 backupInfo
const backupInfo = backupFile
? generatePrompt(loadPromptFromTemplate("clearAllTasks/backupInfo.md"), {
backupFile,
})
: "";
const indexTemplate = loadPromptFromTemplate("clearAllTasks/index.md");
const prompt = generatePrompt(indexTemplate, {
responseTitle,
message,
backupInfo,
});
// 載入可能的自定義 prompt
return loadPrompt(prompt, "CLEAR_ALL_TASKS");
}

View File

@ -0,0 +1,59 @@
/**
* deleteTask prompt
* prompt
*/
import {
loadPrompt,
generatePrompt,
loadPromptFromTemplate,
} from "../loader.js";
import { Task } from "../../types/index.js";
/**
* deleteTask prompt
*/
export interface DeleteTaskPromptParams {
taskId: string;
task?: Task;
success?: boolean;
message?: string;
isTaskCompleted?: boolean;
}
/**
* deleteTask prompt
* @param params prompt
* @returns prompt
*/
export function getDeleteTaskPrompt(params: DeleteTaskPromptParams): string {
const { taskId, task, success, message, isTaskCompleted } = params;
// 處理任務不存在的情況
if (!task) {
const notFoundTemplate = loadPromptFromTemplate("deleteTask/notFound.md");
return generatePrompt(notFoundTemplate, {
taskId,
});
}
// 處理任務已完成的情況
if (isTaskCompleted) {
const completedTemplate = loadPromptFromTemplate("deleteTask/completed.md");
return generatePrompt(completedTemplate, {
taskId: task.id,
taskName: task.name,
});
}
// 處理刪除成功或失敗的情況
const responseTitle = success ? "Success" : "Failure";
const indexTemplate = loadPromptFromTemplate("deleteTask/index.md");
const prompt = generatePrompt(indexTemplate, {
responseTitle,
message,
});
// 載入可能的自定義 prompt
return loadPrompt(prompt, "DELETE_TASK");
}

View File

@ -0,0 +1,141 @@
/**
* updateTaskContent prompt
* prompt
*/
import {
loadPrompt,
generatePrompt,
loadPromptFromTemplate,
} from "../loader.js";
import { Task, RelatedFile } from "../../types/index.js";
/**
* updateTaskContent prompt
*/
export interface UpdateTaskContentPromptParams {
taskId: string;
task?: Task;
success?: boolean;
message?: string;
validationError?: string;
emptyUpdate?: boolean;
updatedTask?: Task;
}
/**
* updateTaskContent prompt
* @param params prompt
* @returns prompt
*/
export function getUpdateTaskContentPrompt(
params: UpdateTaskContentPromptParams
): string {
const {
taskId,
task,
success,
message,
validationError,
emptyUpdate,
updatedTask,
} = params;
// 處理任務不存在的情況
if (!task) {
const notFoundTemplate = loadPromptFromTemplate(
"updateTaskContent/notFound.md"
);
return generatePrompt(notFoundTemplate, {
taskId,
});
}
// 處理驗證錯誤的情況
if (validationError) {
const validationTemplate = loadPromptFromTemplate(
"updateTaskContent/validation.md"
);
return generatePrompt(validationTemplate, {
error: validationError,
});
}
// 處理空更新的情況
if (emptyUpdate) {
const emptyUpdateTemplate = loadPromptFromTemplate(
"updateTaskContent/emptyUpdate.md"
);
return generatePrompt(emptyUpdateTemplate, {});
}
// 處理更新成功或失敗的情況
const responseTitle = success ? "Success" : "Failure";
let content = message || "";
// 更新成功且有更新後的任務詳情
if (success && updatedTask) {
const successTemplate = loadPromptFromTemplate(
"updateTaskContent/success.md"
);
// 編合相關文件信息
let filesContent = "";
if (updatedTask.relatedFiles && updatedTask.relatedFiles.length > 0) {
const fileDetailsTemplate = loadPromptFromTemplate(
"updateTaskContent/fileDetails.md"
);
// 按文件類型分組
const filesByType = updatedTask.relatedFiles.reduce((acc, file) => {
if (!acc[file.type]) {
acc[file.type] = [];
}
acc[file.type].push(file);
return acc;
}, {} as Record<string, RelatedFile[]>);
// 為每種文件類型生成內容
for (const [type, files] of Object.entries(filesByType)) {
const filesList = files.map((file) => `\`${file.path}\``).join(", ");
filesContent += generatePrompt(fileDetailsTemplate, {
fileType: type,
fileCount: files.length,
filesList,
});
}
}
// 處理任務備註
const taskNotesPrefix = "- **Notes:** ";
const taskNotes = updatedTask.notes
? `${taskNotesPrefix}${
updatedTask.notes.length > 100
? `${updatedTask.notes.substring(0, 100)}...`
: updatedTask.notes
}\n`
: "";
// 生成成功更新的詳細信息
content += generatePrompt(successTemplate, {
taskName: updatedTask.name,
taskDescription:
updatedTask.description.length > 100
? `${updatedTask.description.substring(0, 100)}...`
: updatedTask.description,
taskNotes: taskNotes,
taskStatus: updatedTask.status,
taskUpdatedAt: new Date(updatedTask.updatedAt).toISOString(),
filesContent,
});
}
const indexTemplate = loadPromptFromTemplate("updateTaskContent/index.md");
const prompt = generatePrompt(indexTemplate, {
responseTitle,
message: content,
});
// 載入可能的自定義 prompt
return loadPrompt(prompt, "UPDATE_TASK_CONTENT");
}

View File

@ -19,3 +19,6 @@ export { getListTasksPrompt } from "./generators/listTasks.js";
export { getQueryTaskPrompt } from "./generators/queryTask.js";
export { getGetTaskDetailPrompt } from "./generators/getTaskDetail.js";
export { getInitProjectRulesPrompt } from "./generators/initProjectRules.js";
export { getDeleteTaskPrompt } from "./generators/deleteTask.js";
export { getClearAllTasksPrompt } from "./generators/clearAllTasks.js";
export { getUpdateTaskContentPrompt } from "./generators/updateTaskContent.js";

View File

@ -0,0 +1 @@
已自動創建備份: `{{backupFile}}`

View File

@ -0,0 +1,7 @@
# 清除所有任務結果
## 操作取消
未確認清除操作。如要清除所有任務,請將 confirm 參數設為 true。
⚠️ 此操作將刪除所有未完成的任務且無法恢復。

View File

@ -0,0 +1,5 @@
# 清除所有任務結果
## 操作提示
系統中沒有任何任務需要清除。

View File

@ -0,0 +1,5 @@
# 清除所有任務結果
## {responseTitle}
{message}{backupInfo}

View File

@ -0,0 +1,5 @@
# 清除所有任務結果
## 操作成功
所有未完成的任務已被清除。{backupInfo}

View File

@ -0,0 +1,5 @@
# 任務刪除結果
## 操作被拒絕
任務 "{taskName}" (ID: `{taskId}`) 已完成,不允許刪除已完成的任務。

View File

@ -0,0 +1,5 @@
# 任務刪除結果
## {responseTitle}
{message}

View File

@ -0,0 +1,5 @@
# 任務刪除結果
## 系統錯誤
找不到 ID 為 `{taskId}` 的任務。請使用「list_tasks」工具確認有效的任務 ID 後再試。

View File

@ -0,0 +1,5 @@
# 任務刪除結果
## 操作成功
任務已成功刪除。

View File

@ -0,0 +1,5 @@
# 任務更新結果
## 操作失敗
至少需要更新一個字段(名稱、描述、注記或相關文件)

View File

@ -0,0 +1 @@
- **相關文件:** {fileType} ({fileCount} 個): {filesList}

View File

@ -0,0 +1,5 @@
# 任務更新結果
## {responseTitle}
{message}

View File

@ -0,0 +1,5 @@
# 任務更新結果
## 系統錯誤
找不到 ID 為 `{taskId}` 的任務。請使用「list_tasks」工具確認有效的任務 ID 後再試。

View File

@ -0,0 +1,9 @@
### 更新後的任務詳情
- **名稱:** {taskName}
- **描述:** {taskDescription}
{taskNotes}
- **狀態:** {taskStatus}
- **更新時間:** {taskUpdatedAt}
{filesContent}

View File

@ -0,0 +1,5 @@
# 任務更新結果
## 操作失敗
{error}

View File

@ -40,6 +40,9 @@ import {
getListTasksPrompt,
getQueryTaskPrompt,
getGetTaskDetailPrompt,
getDeleteTaskPrompt,
getClearAllTasksPrompt,
getUpdateTaskContentPrompt,
} from "../prompts/index.js";
/**
@ -832,7 +835,7 @@ export async function deleteTask({ taskId }: z.infer<typeof deleteTaskSchema>) {
content: [
{
type: "text" as const,
text: `## 系統錯誤\n\n找不到ID為 \`${taskId}\` 的任務。請使用「list_tasks」工具確認有效的任務ID後再試。`,
text: getDeleteTaskPrompt({ taskId }),
},
],
isError: true,
@ -844,7 +847,7 @@ export async function deleteTask({ taskId }: z.infer<typeof deleteTaskSchema>) {
content: [
{
type: "text" as const,
text: `## 操作被拒絕\n\n任務 "${task.name}" (ID: \`${task.id}\`) 已完成,不允許刪除已完成的任務。`,
text: getDeleteTaskPrompt({ taskId, task, isTaskCompleted: true }),
},
],
isError: true,
@ -857,9 +860,12 @@ export async function deleteTask({ taskId }: z.infer<typeof deleteTaskSchema>) {
content: [
{
type: "text" as const,
text: `## ${result.success ? "操作成功" : "操作失敗"}\n\n${
result.message
}`,
text: getDeleteTaskPrompt({
taskId,
task,
success: result.success,
message: result.message,
}),
},
],
isError: !result.success,
@ -886,7 +892,7 @@ export async function clearAllTasks({
content: [
{
type: "text" as const,
text: `## 操作取消\n\n未確認清除操作。如要清除所有任務請將 confirm 參數設為 true。\n\n⚠ 此操作將刪除所有未完成的任務且無法恢復。`,
text: getClearAllTasksPrompt({ confirm: false }),
},
],
};
@ -899,7 +905,7 @@ export async function clearAllTasks({
content: [
{
type: "text" as const,
text: `## 操作提示\n\n系統中沒有任何任務需要清除。`,
text: getClearAllTasksPrompt({ isEmpty: true }),
},
],
};
@ -912,13 +918,11 @@ export async function clearAllTasks({
content: [
{
type: "text" as const,
text: `## ${result.success ? "操作成功" : "操作失敗"}\n\n${
result.message
}${
result.backupFile
? `\n\n已自動創建備份: \`${result.backupFile}\``
: ""
}`,
text: getClearAllTasksPrompt({
success: result.success,
message: result.message,
backupFile: result.backupFile,
}),
},
],
isError: !result.success,
@ -1000,7 +1004,11 @@ export async function updateTaskContent({
content: [
{
type: "text" as const,
text: `## 操作失敗\n\n行號設置無效必須同時設置起始行和結束行且起始行必須小於結束行`,
text: getUpdateTaskContentPrompt({
taskId,
validationError:
"行號設置無效:必須同時設置起始行和結束行,且起始行必須小於結束行",
}),
},
],
};
@ -1023,7 +1031,10 @@ export async function updateTaskContent({
content: [
{
type: "text" as const,
text: `## 操作失敗\n\n至少需要更新一個字段名稱、描述、注記或相關文件`,
text: getUpdateTaskContentPrompt({
taskId,
emptyUpdate: true,
}),
},
],
};
@ -1037,7 +1048,9 @@ export async function updateTaskContent({
content: [
{
type: "text" as const,
text: `## 系統錯誤\n\n找不到ID為 \`${taskId}\` 的任務。請使用「list_tasks」工具確認有效的任務ID後再試。`,
text: getUpdateTaskContentPrompt({
taskId,
}),
},
],
isError: true,
@ -1067,56 +1080,17 @@ export async function updateTaskContent({
verificationCriteria,
});
// 構建響應消息
const responseTitle = result.success ? "操作成功" : "操作失敗";
let responseMessage = result.message;
if (result.success && result.task) {
// 顯示更新後的任務詳情
responseMessage += "\n\n### 更新後的任務詳情\n";
responseMessage += `- **名稱:** ${result.task.name}\n`;
responseMessage += `- **描述:** ${result.task.description.substring(
0,
100
)}${result.task.description.length > 100 ? "..." : ""}\n`;
if (result.task.notes) {
responseMessage += `- **注記:** ${result.task.notes.substring(0, 100)}${
result.task.notes.length > 100 ? "..." : ""
}\n`;
}
responseMessage += `- **狀態:** ${result.task.status}\n`;
responseMessage += `- **更新時間:** ${new Date(
result.task.updatedAt
).toISOString()}\n`;
// 顯示相關文件信息
if (result.task.relatedFiles && result.task.relatedFiles.length > 0) {
responseMessage += `- **相關文件:** ${result.task.relatedFiles.length}\n`;
// 按文件類型分組
const filesByType = result.task.relatedFiles.reduce((acc, file) => {
if (!acc[file.type]) {
acc[file.type] = [];
}
acc[file.type].push(file);
return acc;
}, {} as Record<string, RelatedFile[]>);
for (const [type, files] of Object.entries(filesByType)) {
responseMessage += ` - ${type} (${files.length} 個): `;
responseMessage += files.map((file) => `\`${file.path}\``).join(", ");
responseMessage += "\n";
}
}
}
return {
content: [
{
type: "text" as const,
text: `## ${responseTitle}\n\n${responseMessage}`,
text: getUpdateTaskContentPrompt({
taskId,
task,
success: result.success,
message: result.message,
updatedTask: result.task,
}),
},
],
isError: !result.success,
@ -1199,52 +1173,6 @@ export async function queryTask({
}
}
// 格式化任務顯示內容的輔助函數
function formatTaskForDisplay(task: Task): string {
let taskInfo = `### ${task.name}\n**ID:** \`${task.id}\`\n**狀態:** ${task.status}\n**描述:** ${task.description}\n`;
if (task.notes) {
taskInfo += `**注記:** ${task.notes}\n`;
}
if (task.implementationGuide) {
taskInfo += `**實現指南:** ${
task.implementationGuide.length > 300
? task.implementationGuide.substring(0, 300) + "..."
: task.implementationGuide
}\n`;
}
if (task.verificationCriteria) {
taskInfo += `**驗證標準:** ${
task.verificationCriteria.length > 300
? task.verificationCriteria.substring(0, 300) + "..."
: task.verificationCriteria
}\n`;
}
if (task.summary) {
taskInfo += `**完成摘要:** ${task.summary}\n`;
}
taskInfo += `**創建時間:** ${new Date(task.createdAt).toLocaleString(
"zh-TW"
)}\n`;
taskInfo += `**更新時間:** ${new Date(task.updatedAt).toLocaleString(
"zh-TW"
)}\n`;
if (task.completedAt) {
taskInfo += `**完成時間:** ${new Date(task.completedAt).toLocaleString(
"zh-TW"
)}\n`;
}
taskInfo += `**詳細內容:** 請使用「get_task_detail」工具查看 ${task.id} 完整任務詳情`;
return taskInfo;
}
// 取得完整任務詳情的參數
export const getTaskDetailSchema = z.object({
taskId: z