@yeaft/webchat-agent 0.0.177 → 0.0.179

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.
Files changed (2) hide show
  1. package/crew.js +115 -83
  2. package/package.json +1 -1
package/crew.js CHANGED
@@ -985,49 +985,12 @@ ${roles.length > 0 ? roles.map(r => `- ${roleLabel(r)}(${r.name}): ${r.descripti
985
985
  - PM 不做 cherry-pick,只负责打 tag
986
986
  - 每次新任务/新 feature 必须基于最新的 main 分支创建新的 worktree,确保在最新代码上开发
987
987
 
988
- # Feature 进度管理
989
- 每个 Feature 使用独立的进度文件来跟踪状态,存放在 context/features/ 目录下。
990
-
991
- ## 文件命名规范
992
- - 文件名格式: \`context/features/{task-id}.md\`(如 \`context/features/task-1.md\`)
993
- - 由 PM 在分配任务时指示 developer 创建初始文件
994
-
995
- ## 文件格式
996
- \`\`\`markdown
997
- # Feature: {taskTitle}
998
- - task-id: {task-id}
999
- - 状态: 待开发 | 开发中 | 待审查 | 审查中 | 已完成 | 已阻塞
1000
- - 负责人: {dev角色name}
1001
- - 审查者: {reviewer角色name}
1002
- - 测试者: {tester角色name}
1003
- - 创建时间: {ISO时间}
1004
-
1005
- ## 需求描述
1006
- {PM写的需求}
1007
-
1008
- ## 实现记录
1009
- _由开发者填写_
1010
-
1011
- ## 审查记录
1012
- _由审查者填写_
1013
-
1014
- ## 测试记录
1015
- _由测试者填写_
1016
- \`\`\`
1017
-
1018
- ## 状态流转规则
1019
- 1. PM 创建文件 → 状态「待开发」
1020
- 2. dev 开始工作 → 更新为「开发中」,填写实现方案
1021
- 3. dev 完成 → 更新为「待审查」,记录改动摘要(reviewer 和 tester 并行工作)
1022
- 4. reviewer/tester 开始工作 → 更新为「审查中」,各自填写审查/测试记录
1023
- 5. 发现问题需返工 → 更新回「开发中」
1024
- 6. 全部通过 → PM 更新为「已完成」
1025
-
1026
- ## 角色职责
1027
- - **PM**: 规划 feature 文件(通过 ROUTE 让 dev 创建),填写需求描述,最终标记完成
1028
- - **Developer**: 更新开发状态,填写「实现记录」(方案、改动文件、注意事项)
1029
- - **Reviewer**: 填写「审查记录」(评分、问题列表、是否通过)
1030
- - **Tester**: 填写「测试记录」(测试用例、结果、发现的 Bug)
988
+ # Feature 工作记录
989
+ 系统自动管理 \`context/features/{task-id}.md\` 工作记录文件:
990
+ - PM 通过 ROUTE 分配任务(带 task + taskTitle 字段)时自动创建
991
+ - 每次角色 ROUTE 传递时自动追加工作记录
992
+ - 角色收到消息时自动注入对应 task 文件内容作为上下文
993
+ 角色不需要手动创建或更新这些文件。
1031
994
 
1032
995
  ${sharedMemoryContent}`;
1033
996
 
@@ -1070,6 +1033,86 @@ async function updateSharedClaudeMd(session) {
1070
1033
  await writeSharedClaudeMd(session.sharedDir, session.goal, roles, session.projectDir, session.sharedKnowledge);
1071
1034
  }
1072
1035
 
1036
+ // =====================================================================
1037
+ // Task File Management (auto-managed by system)
1038
+ // =====================================================================
1039
+
1040
+ /**
1041
+ * 自动创建 task 进度文件
1042
+ * 当 ROUTE 带有 taskId + taskTitle 时,如果文件不存在则自动创建
1043
+ */
1044
+ async function ensureTaskFile(session, taskId, taskTitle, assignee, summary) {
1045
+ const featuresDir = join(session.sharedDir, 'context', 'features');
1046
+ const filePath = join(featuresDir, `${taskId}.md`);
1047
+
1048
+ try {
1049
+ await fs.access(filePath);
1050
+ // 文件已存在,不覆盖
1051
+ return;
1052
+ } catch {
1053
+ // 文件不存在,创建
1054
+ }
1055
+
1056
+ await fs.mkdir(featuresDir, { recursive: true });
1057
+
1058
+ const now = new Date().toISOString();
1059
+ const content = `# Feature: ${taskTitle}
1060
+ - task-id: ${taskId}
1061
+ - 状态: 待开发
1062
+ - 负责人: ${assignee}
1063
+ - 创建时间: ${now}
1064
+
1065
+ ## 需求描述
1066
+ ${summary}
1067
+
1068
+ ## 工作记录
1069
+ `;
1070
+
1071
+ await fs.writeFile(filePath, content);
1072
+
1073
+ // 同步到 session.features
1074
+ if (!session.features.has(taskId)) {
1075
+ session.features.set(taskId, { taskId, taskTitle, createdAt: Date.now() });
1076
+ }
1077
+
1078
+ console.log(`[Crew] Task file created: ${taskId} (${taskTitle})`);
1079
+ }
1080
+
1081
+ /**
1082
+ * 追加工作记录到 task 文件
1083
+ * 当角色 ROUTE 时,自动将 summary 追加到对应 task 文件
1084
+ */
1085
+ async function appendTaskRecord(session, taskId, roleName, summary) {
1086
+ const filePath = join(session.sharedDir, 'context', 'features', `${taskId}.md`);
1087
+
1088
+ try {
1089
+ await fs.access(filePath);
1090
+ } catch {
1091
+ // 文件不存在,跳过(不应该发生,但防御性处理)
1092
+ return;
1093
+ }
1094
+
1095
+ const role = session.roles.get(roleName);
1096
+ const label = role ? roleLabel(role) : roleName;
1097
+ const now = new Date().toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' });
1098
+ const record = `\n### ${label} - ${now}\n${summary}\n`;
1099
+
1100
+ await fs.appendFile(filePath, record);
1101
+ console.log(`[Crew] Task record appended: ${taskId} by ${roleName}`);
1102
+ }
1103
+
1104
+ /**
1105
+ * 读取 task 文件内容(用于注入上下文)
1106
+ */
1107
+ async function readTaskFile(session, taskId) {
1108
+ const filePath = join(session.sharedDir, 'context', 'features', `${taskId}.md`);
1109
+ try {
1110
+ return await fs.readFile(filePath, 'utf-8');
1111
+ } catch {
1112
+ return null;
1113
+ }
1114
+ }
1115
+
1073
1116
  // =====================================================================
1074
1117
  // Session Persistence
1075
1118
  // =====================================================================
@@ -1359,46 +1402,13 @@ summary: 请实现注册页面,包括邮箱验证
1359
1402
  - TASKS 块不需要在回复最末尾,可以放在任意位置`;
1360
1403
  }
1361
1404
 
1362
- // Feature 进度记录要求(按角色类型注入)
1363
- if (role.isDecisionMaker) {
1364
- prompt += `\n\n# Feature 进度文件管理
1365
- 当你分配任务时,需要确保对应的 feature 进度文件被创建:
1366
- 1. 文件路径: \`context/features/{task-id}.md\`(如 \`context/features/task-1.md\`)
1367
- 2. 使用共享 CLAUDE.md 中定义的文件格式,填写需求描述
1368
- 3. 初始状态设为「待开发」
1369
- 4. 所有子任务完成后,通过 ROUTE 让 dev 将状态更新为「已完成」
1370
-
1371
- 因为你不能使用 Write/Edit 工具,feature 文件的创建和更新都通过 ROUTE 给 developer 执行。在 ROUTE 的 summary 中明确要求 dev 创建/更新 feature 文件,并提供需求描述内容。`;
1372
- } else if (role.roleType === 'developer') {
1373
- prompt += `\n\n# Feature 进度记录
1374
- 收到任务后,你必须维护 feature 进度文件 \`context/features/{task-id}.md\`:
1375
- 1. 如果 PM 要求创建 feature 文件,先创建它(确保 context/features/ 目录存在)
1376
- 2. 开始开发时:将状态更新为「开发中」
1377
- 3. 开发完成时:将状态更新为「待审查」,在「实现记录」中填写:
1378
- - 实现方案概述
1379
- - 修改的文件列表
1380
- - 需要注意的事项
1381
- 4. 收到审查/测试反馈需要修改时:将状态更新回「开发中」,追加修改记录`;
1382
- } else if (role.roleType === 'reviewer') {
1383
- prompt += `\n\n# Feature 进度记录
1384
- 完成代码审查后,你必须更新 feature 进度文件 \`context/features/{task-id}.md\`:
1385
- 1. 在「审查记录」中填写:
1386
- - 代码质量评分(10分制)
1387
- - 发现的问题列表(如有)
1388
- - 审查结论(通过/需修改)
1389
- 2. 如果审查通过:不修改状态(等测试也通过后由 PM 标记完成)
1390
- 3. 如果需要修改:将状态更新为「开发中」`;
1391
- } else if (role.roleType === 'tester') {
1392
- prompt += `\n\n# Feature 进度记录
1393
- 完成测试后,你必须更新 feature 进度文件 \`context/features/{task-id}.md\`:
1394
- 1. 在「测试记录」中填写:
1395
- - 测试用例列表及结果
1396
- - 发现的 Bug(如有)
1397
- - 测试结论(通过/不通过)
1398
- 2. 如果测试通过:不修改状态(等审查也通过后由 PM 标记完成)
1399
- 3. 如果发现 Bug:将状态更新为「开发中」`;
1400
- }
1401
- // designer 等其他角色不需要维护 feature 进度文件,无需注入额外 prompt
1405
+ // Feature 进度文件说明(系统自动管理,告知角色即可)
1406
+ prompt += `\n\n# Feature 工作记录
1407
+ 系统会自动管理 \`context/features/{task-id}.md\` 工作记录文件:
1408
+ - PM 分配任务时自动创建文件(包含 task-id、标题、需求描述)
1409
+ - 每次 ROUTE 传递时自动追加工作记录(角色名、时间、summary)
1410
+ - 你收到的消息中会包含 <task-context> 标签,里面是该任务的完整工作记录
1411
+ 你不需要手动创建或更新这些文件,专注于你的本职工作即可。`;
1402
1412
 
1403
1413
  // 执行者角色的组绑定 prompt(count > 1 时)
1404
1414
  if (role.groupIndex > 0 && role.roleType === 'developer') {
@@ -1909,6 +1919,19 @@ async function executeRoute(session, fromRole, route) {
1909
1919
  return;
1910
1920
  }
1911
1921
 
1922
+ // ★ Task 文件自动管理(fire-and-forget,不阻塞路由执行)
1923
+ if (taskId && summary) {
1924
+ // 如果是决策者发出的 ROUTE(分配任务),自动创建 task 文件
1925
+ const fromRoleConfig = session.roles.get(fromRole);
1926
+ if (fromRoleConfig?.isDecisionMaker && taskTitle && to !== 'human') {
1927
+ ensureTaskFile(session, taskId, taskTitle, to, summary)
1928
+ .catch(e => console.warn(`[Crew] Failed to create task file ${taskId}:`, e.message));
1929
+ }
1930
+ // 任何角色的 ROUTE 都追加工作记录
1931
+ appendTaskRecord(session, taskId, fromRole, summary)
1932
+ .catch(e => console.warn(`[Crew] Failed to append task record ${taskId}:`, e.message));
1933
+ }
1934
+
1912
1935
  // 发送路由消息(UI 显示 → @xxx)
1913
1936
  sendCrewOutput(session, fromRole, 'route', null, { routeTo: to, routeSummary: summary });
1914
1937
 
@@ -1985,6 +2008,15 @@ async function dispatchToRole(session, roleName, content, fromSource, taskId, ta
1985
2008
  roleState.currentTask = { taskId, taskTitle };
1986
2009
  }
1987
2010
 
2011
+ // ★ Task 上下文注入:如果有 taskId,读取 task 文件注入到消息中
2012
+ const effectiveTaskId = taskId || roleState.currentTask?.taskId;
2013
+ if (effectiveTaskId && typeof content === 'string') {
2014
+ const taskContent = await readTaskFile(session, effectiveTaskId);
2015
+ if (taskContent) {
2016
+ content = `${content}\n\n---\n<task-context file="context/features/${effectiveTaskId}.md">\n${taskContent}\n</task-context>`;
2017
+ }
2018
+ }
2019
+
1988
2020
  // 记录消息历史
1989
2021
  session.messageHistory.push({
1990
2022
  from: fromSource,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yeaft/webchat-agent",
3
- "version": "0.0.177",
3
+ "version": "0.0.179",
4
4
  "description": "Remote agent for Yeaft WebChat — connects worker machines to the central server",
5
5
  "main": "index.js",
6
6
  "type": "module",