@yeaft/webchat-agent 0.1.81 → 0.1.83

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.
package/crew/session.js CHANGED
@@ -87,8 +87,19 @@ function isValidProjectDir(dir) {
87
87
  // Session Lifecycle
88
88
  // =====================================================================
89
89
 
90
+ /**
91
+ * 生成角色配置的规范化签名(sorted role name list)
92
+ * 用于比较新旧 session 的角色配置是否一致
93
+ */
94
+ export function getRolesSignature(roles) {
95
+ if (!roles || roles.length === 0) return '';
96
+ const names = roles.map(r => r.name).sort();
97
+ return names.join(',');
98
+ }
99
+
90
100
  /**
91
101
  * 查找指定 projectDir 的已有 crew session
102
+ * 返回 { sessionId, source, roles } 或 null
92
103
  */
93
104
  async function findExistingSessionByProjectDir(projectDir) {
94
105
  const normalizedDir = projectDir.replace(/\/+$/, '');
@@ -96,7 +107,11 @@ async function findExistingSessionByProjectDir(projectDir) {
96
107
  for (const [, session] of crewSessions) {
97
108
  if (session.projectDir.replace(/\/+$/, '') === normalizedDir
98
109
  && session.status !== 'completed') {
99
- return { sessionId: session.id, source: 'active' };
110
+ return {
111
+ sessionId: session.id,
112
+ source: 'active',
113
+ roles: Array.from(session.roles.values())
114
+ };
100
115
  }
101
116
  }
102
117
 
@@ -110,7 +125,7 @@ async function findExistingSessionByProjectDir(projectDir) {
110
125
 
111
126
  if (match) {
112
127
  const meta = await loadSessionMeta(match.sharedDir);
113
- if (meta) return { sessionId: match.sessionId, source: 'index' };
128
+ if (meta) return { sessionId: match.sessionId, source: 'index', roles: meta.roles || [] };
114
129
  await removeFromCrewIndex(match.sessionId);
115
130
  }
116
131
 
@@ -133,12 +148,26 @@ export async function createCrewSession(msg) {
133
148
  username
134
149
  } = msg;
135
150
 
136
- // 同目录检查
151
+ // 同目录检查:如果已有同目录的 session,比较角色配置
137
152
  const existingSession = await findExistingSessionByProjectDir(projectDir);
138
153
  if (existingSession) {
139
- console.log(`[Crew] Found existing session for ${projectDir}: ${existingSession.sessionId}, auto-resuming`);
140
- await resumeCrewSession({ sessionId: existingSession.sessionId, userId, username });
141
- return;
154
+ const newRoles = expandRoles(rawRoles);
155
+ const newSig = getRolesSignature(newRoles);
156
+ const oldSig = getRolesSignature(existingSession.roles);
157
+
158
+ if (newSig === oldSig) {
159
+ // 角色配置相同,安全 auto-resume
160
+ console.log(`[Crew] Found existing session for ${projectDir}: ${existingSession.sessionId}, roles match, auto-resuming`);
161
+ await resumeCrewSession({ sessionId: existingSession.sessionId, userId, username });
162
+ return;
163
+ }
164
+
165
+ // 角色配置不同 → 清理旧 session,用新配置走正常创建流程
166
+ console.log(`[Crew] Roles changed for ${projectDir}: old=[${oldSig}] new=[${newSig}], discarding old session ${existingSession.sessionId}`);
167
+ if (existingSession.source === 'active') {
168
+ crewSessions.delete(existingSession.sessionId);
169
+ }
170
+ await removeFromCrewIndex(existingSession.sessionId);
142
171
  }
143
172
 
144
173
  const roles = expandRoles(rawRoles);
@@ -40,7 +40,7 @@ function extractMemorySection(fileContent, titles, defaults) {
40
40
  }
41
41
 
42
42
  /**
43
- * Backup memory content from .crew/CLAUDE.md and .crew/roles/*/CLAUDE.md
43
+ * Backup memory content from .crew/CLAUDE.md and .crew/roles/<role>/CLAUDE.md
44
44
  * before deletion. Writes .crew/.memory-backup.json.
45
45
  */
46
46
  export async function backupMemoryContent(crewDir) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yeaft/webchat-agent",
3
- "version": "0.1.81",
3
+ "version": "0.1.83",
4
4
  "description": "Remote agent for Yeaft WebChat — connects worker machines to the central server",
5
5
  "main": "index.js",
6
6
  "type": "module",