@yeaft/webchat-agent 0.1.182 → 0.1.184

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/session.js +68 -2
  2. package/package.json +1 -1
package/crew/session.js CHANGED
@@ -544,16 +544,82 @@ export async function resumeCrewSession(msg) {
544
544
  }
545
545
 
546
546
  /**
547
- * 更新 crew session 的 name
547
+ * 更新 crew session 的 name 和/或 roles 配置
548
+ * roles 变更时:重新展开角色、初始化新 worktrees、更新 CLAUDE.md、通知前端
548
549
  */
549
550
  export async function handleUpdateCrewSession(msg) {
550
- const { sessionId, name } = msg;
551
+ const { sessionId, name, roles: newRolesConfig } = msg;
551
552
  const session = crewSessions.get(sessionId);
552
553
  if (!session) {
553
554
  console.warn(`[Crew] Session not found for update: ${sessionId}`);
554
555
  return;
555
556
  }
556
557
  if (name !== undefined) session.name = name;
558
+
559
+ // Handle roles update (count changes, etc.)
560
+ if (newRolesConfig && Array.isArray(newRolesConfig) && newRolesConfig.length > 0) {
561
+ const newExpanded = expandRoles(newRolesConfig);
562
+ const oldRoleNames = new Set(session.roles.keys());
563
+ const newRoleNames = new Set(newExpanded.map(r => r.name));
564
+
565
+ // Stop and clean up removed roles
566
+ for (const oldName of oldRoleNames) {
567
+ if (!newRoleNames.has(oldName)) {
568
+ const roleState = session.roleStates.get(oldName);
569
+ if (roleState) {
570
+ if (roleState.abortController) {
571
+ roleState.abortController.abort();
572
+ }
573
+ session.roleStates.delete(oldName);
574
+ }
575
+ session.roles.delete(oldName);
576
+ console.log(`[Crew] Role removed during update: ${oldName}`);
577
+ }
578
+ }
579
+
580
+ // Add new roles and update existing ones
581
+ for (const r of newExpanded) {
582
+ if (!oldRoleNames.has(r.name)) {
583
+ // Brand new role — add it
584
+ session.roles.set(r.name, r);
585
+ console.log(`[Crew] Role added during update: ${r.name} (${r.displayName})`);
586
+ } else {
587
+ // Existing role — update metadata (displayName, icon, etc.) but preserve roleState
588
+ const existing = session.roles.get(r.name);
589
+ existing.displayName = r.displayName;
590
+ existing.icon = r.icon;
591
+ existing.description = r.description;
592
+ existing.isDecisionMaker = r.isDecisionMaker;
593
+ existing.roleType = r.roleType;
594
+ existing.groupIndex = r.groupIndex;
595
+ }
596
+ }
597
+
598
+ // Update decision maker
599
+ const dm = newExpanded.find(r => r.isDecisionMaker);
600
+ if (dm) session.decisionMaker = dm.name;
601
+
602
+ // Initialize worktrees for any new dev groups
603
+ const allRoles = Array.from(session.roles.values());
604
+ const worktreeMap = await initWorktrees(session.projectDir, allRoles);
605
+ for (const role of allRoles) {
606
+ if (role.groupIndex > 0 && worktreeMap.has(role.groupIndex) && !role.workDir) {
607
+ role.workDir = worktreeMap.get(role.groupIndex);
608
+ }
609
+ }
610
+
611
+ // Regenerate shared CLAUDE.md and role-specific CLAUDE.md files
612
+ await updateSharedClaudeMd(session);
613
+ for (const role of allRoles) {
614
+ if (role.groupIndex > 0 && role.workDir) {
615
+ await writeRoleClaudeMd(session.sharedDir, role, session.language || 'zh-CN', allRoles);
616
+ }
617
+ }
618
+
619
+ // Notify frontend about role changes
620
+ sendStatusUpdate(session);
621
+ }
622
+
557
623
  await saveSessionMeta(session);
558
624
  await upsertCrewIndex(session);
559
625
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yeaft/webchat-agent",
3
- "version": "0.1.182",
3
+ "version": "0.1.184",
4
4
  "description": "Remote agent for Yeaft WebChat — connects worker machines to the central server",
5
5
  "main": "index.js",
6
6
  "type": "module",