@yeaft/webchat-agent 0.0.131 → 0.0.133

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 (3) hide show
  1. package/connection.js +4 -0
  2. package/crew.js +83 -10
  3. package/package.json +1 -1
package/connection.js CHANGED
@@ -308,6 +308,10 @@ async function handleMessage(msg) {
308
308
  (await import('./conversation.js')).sendConversationList();
309
309
  break;
310
310
 
311
+ case 'update_crew_session':
312
+ await (await import('./crew.js')).handleUpdateCrewSession(msg);
313
+ break;
314
+
311
315
  // Port proxy
312
316
  case 'proxy_request':
313
317
  handleProxyHttpRequest(msg);
package/crew.js CHANGED
@@ -254,6 +254,7 @@ function sessionToIndexEntry(session) {
254
254
  sharedDir: session.sharedDir,
255
255
  status: session.status,
256
256
  goal: session.goal,
257
+ name: session.name || '',
257
258
  userId: session.userId,
258
259
  username: session.username,
259
260
  createdAt: session.createdAt,
@@ -306,6 +307,8 @@ async function saveSessionMeta(session) {
306
307
  projectDir: session.projectDir,
307
308
  sharedDir: session.sharedDir,
308
309
  goal: session.goal,
310
+ name: session.name || '',
311
+ sharedKnowledge: session.sharedKnowledge || '',
309
312
  status: session.status,
310
313
  roles: Array.from(session.roles.values()).map(r => ({
311
314
  name: r.name, displayName: r.displayName, icon: r.icon,
@@ -385,12 +388,20 @@ export async function resumeCrewSession(msg) {
385
388
  if ((!session.uiMessages || session.uiMessages.length === 0) && session.sharedDir) {
386
389
  session.uiMessages = await loadSessionMessages(session.sharedDir);
387
390
  }
391
+ // 发送前清理 _streaming 标记(跟磁盘保存逻辑保持一致)
392
+ const cleanedMessages = (session.uiMessages || []).map(m => {
393
+ const { _streaming, ...rest } = m;
394
+ return rest;
395
+ });
396
+
388
397
  sendCrewMessage({
389
398
  type: 'crew_session_restored',
390
399
  sessionId,
391
400
  projectDir: session.projectDir,
392
401
  sharedDir: session.sharedDir,
393
402
  goal: session.goal,
403
+ name: session.name || '',
404
+ sharedKnowledge: session.sharedKnowledge || '',
394
405
  roles: roles.map(r => ({
395
406
  name: r.name, displayName: r.displayName, icon: r.icon,
396
407
  description: r.description, isDecisionMaker: r.isDecisionMaker || false
@@ -399,7 +410,7 @@ export async function resumeCrewSession(msg) {
399
410
  maxRounds: session.maxRounds,
400
411
  userId: session.userId,
401
412
  username: session.username,
402
- uiMessages: session.uiMessages || []
413
+ uiMessages: cleanedMessages
403
414
  });
404
415
  sendStatusUpdate(session);
405
416
  return;
@@ -428,6 +439,8 @@ export async function resumeCrewSession(msg) {
428
439
  projectDir: meta.projectDir,
429
440
  sharedDir: meta.sharedDir || indexEntry.sharedDir,
430
441
  goal: meta.goal,
442
+ name: meta.name || '',
443
+ sharedKnowledge: meta.sharedKnowledge || '',
431
444
  roles: new Map(roles.map(r => [r.name, r])),
432
445
  roleStates: new Map(),
433
446
  decisionMaker,
@@ -458,6 +471,8 @@ export async function resumeCrewSession(msg) {
458
471
  projectDir: session.projectDir,
459
472
  sharedDir: session.sharedDir,
460
473
  goal: session.goal,
474
+ name: session.name || '',
475
+ sharedKnowledge: session.sharedKnowledge || '',
461
476
  roles: roles.map(r => ({
462
477
  name: r.name, displayName: r.displayName, icon: r.icon,
463
478
  description: r.description, isDecisionMaker: r.isDecisionMaker || false
@@ -491,6 +506,8 @@ export async function createCrewSession(msg) {
491
506
  projectDir,
492
507
  sharedDir: sharedDirRel,
493
508
  goal,
509
+ name,
510
+ sharedKnowledge,
494
511
  roles: rawRoles = [], // [{ name, displayName, icon, description, claudeMd, model, budget, isDecisionMaker, count }]
495
512
  maxRounds = 20,
496
513
  userId,
@@ -506,7 +523,7 @@ export async function createCrewSession(msg) {
506
523
  : join(projectDir, sharedDirRel || '.crew');
507
524
 
508
525
  // 初始化共享区
509
- await initSharedDir(sharedDir, goal, roles, projectDir);
526
+ await initSharedDir(sharedDir, goal, roles, projectDir, sharedKnowledge);
510
527
 
511
528
  // 初始化 git worktrees(仅多实例时)
512
529
  const worktreeMap = await initWorktrees(projectDir, roles);
@@ -527,6 +544,8 @@ export async function createCrewSession(msg) {
527
544
  projectDir,
528
545
  sharedDir,
529
546
  goal,
547
+ name: name || '',
548
+ sharedKnowledge: sharedKnowledge || '',
530
549
  roles: new Map(roles.map(r => [r.name, r])),
531
550
  roleStates: new Map(),
532
551
  decisionMaker,
@@ -555,6 +574,8 @@ export async function createCrewSession(msg) {
555
574
  projectDir,
556
575
  sharedDir,
557
576
  goal,
577
+ name: name || '',
578
+ sharedKnowledge: sharedKnowledge || '',
558
579
  roles: roles.map(r => ({
559
580
  name: r.name,
560
581
  displayName: r.displayName,
@@ -723,6 +744,23 @@ export async function removeRoleFromSession(msg) {
723
744
  sendStatusUpdate(session);
724
745
  }
725
746
 
747
+ /**
748
+ * 更新 crew session 的 name 和 sharedKnowledge
749
+ */
750
+ export async function handleUpdateCrewSession(msg) {
751
+ const { sessionId, name, sharedKnowledge } = msg;
752
+ const session = crewSessions.get(sessionId);
753
+ if (!session) {
754
+ console.warn(`[Crew] Session not found for update: ${sessionId}`);
755
+ return;
756
+ }
757
+ if (name !== undefined) session.name = name;
758
+ if (sharedKnowledge !== undefined) session.sharedKnowledge = sharedKnowledge;
759
+ await updateSharedClaudeMd(session);
760
+ await saveSessionMeta(session);
761
+ await upsertCrewIndex(session);
762
+ }
763
+
726
764
  // =====================================================================
727
765
  // Shared Directory & Memory
728
766
  // =====================================================================
@@ -738,7 +776,7 @@ export async function removeRoleFromSession(msg) {
738
776
  * └── {roleName}/
739
777
  * └── CLAUDE.md ← 角色定义 + 个人记忆
740
778
  */
741
- async function initSharedDir(sharedDir, goal, roles, projectDir) {
779
+ async function initSharedDir(sharedDir, goal, roles, projectDir, sharedKnowledge = '') {
742
780
  await fs.mkdir(sharedDir, { recursive: true });
743
781
  await fs.mkdir(join(sharedDir, 'context'), { recursive: true });
744
782
  await fs.mkdir(join(sharedDir, 'sessions'), { recursive: true });
@@ -750,7 +788,7 @@ async function initSharedDir(sharedDir, goal, roles, projectDir) {
750
788
  }
751
789
 
752
790
  // 生成 .crew/CLAUDE.md(共享级)
753
- await writeSharedClaudeMd(sharedDir, goal, roles, projectDir);
791
+ await writeSharedClaudeMd(sharedDir, goal, roles, projectDir, sharedKnowledge);
754
792
  }
755
793
 
756
794
  /**
@@ -774,7 +812,11 @@ async function initRoleDir(sharedDir, role) {
774
812
  * 写入 .crew/CLAUDE.md — 共享级(所有角色自动继承)
775
813
  * 记忆直接写在 CLAUDE.md 中,Claude Code 会自动加载
776
814
  */
777
- async function writeSharedClaudeMd(sharedDir, goal, roles, projectDir) {
815
+ async function writeSharedClaudeMd(sharedDir, goal, roles, projectDir, sharedKnowledge = '') {
816
+ const sharedMemoryContent = sharedKnowledge
817
+ ? `# 共享记忆\n${sharedKnowledge}\n`
818
+ : `# 共享记忆\n_团队共同维护,记录重要的共识、决策和信息。_\n`;
819
+
778
820
  const claudeMd = `# 项目目标
779
821
  ${goal}
780
822
 
@@ -809,9 +851,7 @@ ${roles.length > 0 ? roles.map(r => `- ${roleLabel(r)}(${r.name}): ${r.descripti
809
851
  - 每次新任务/新 feature 必须基于最新的 main 分支创建新的 worktree,确保在最新代码上开发
810
852
  - 禁止复用旧的 worktree 开发新任务,因为旧 worktree 的代码基线可能已过时
811
853
 
812
- # 共享记忆
813
- _团队共同维护,记录重要的共识、决策和信息。_
814
- `;
854
+ ${sharedMemoryContent}`;
815
855
 
816
856
  await fs.writeFile(join(sharedDir, 'CLAUDE.md'), claudeMd);
817
857
  }
@@ -852,7 +892,7 @@ _在这里记录重要的信息、决策、进展和待办事项。_
852
892
  */
853
893
  async function updateSharedClaudeMd(session) {
854
894
  const roles = Array.from(session.roles.values());
855
- await writeSharedClaudeMd(session.sharedDir, session.goal, roles, session.projectDir);
895
+ await writeSharedClaudeMd(session.sharedDir, session.goal, roles, session.projectDir, session.sharedKnowledge);
856
896
  }
857
897
 
858
898
  // =====================================================================
@@ -1814,7 +1854,9 @@ function sendCrewOutput(session, roleName, outputType, rawMessage, extra = {}) {
1814
1854
  session.uiMessages.push({
1815
1855
  role: roleName, roleIcon, roleName: displayName,
1816
1856
  type: 'route', routeTo: extra.routeTo,
1857
+ routeSummary: extra.routeSummary || '',
1817
1858
  content: `→ @${extra.routeTo} ${extra.routeSummary || ''}`,
1859
+ taskId, taskTitle,
1818
1860
  timestamp: Date.now()
1819
1861
  });
1820
1862
  } else if (outputType === 'system') {
@@ -1831,8 +1873,39 @@ function sendCrewOutput(session, roleName, outputType, rawMessage, extra = {}) {
1831
1873
  type: 'system', content: text,
1832
1874
  timestamp: Date.now()
1833
1875
  });
1876
+ } else if (outputType === 'tool_use') {
1877
+ // 结束该角色前一条 streaming
1878
+ endRoleStreaming(session, roleName);
1879
+ const content = rawMessage?.message?.content;
1880
+ if (Array.isArray(content)) {
1881
+ for (const block of content) {
1882
+ if (block.type === 'tool_use') {
1883
+ session.uiMessages.push({
1884
+ role: roleName, roleIcon, roleName: displayName,
1885
+ type: 'tool',
1886
+ toolName: block.name,
1887
+ toolId: block.id,
1888
+ content: `${block.name} ${block.input?.file_path || block.input?.command?.substring(0, 60) || ''}`,
1889
+ hasResult: false,
1890
+ taskId, taskTitle,
1891
+ timestamp: Date.now()
1892
+ });
1893
+ }
1894
+ }
1895
+ }
1896
+ } else if (outputType === 'tool_result') {
1897
+ // 标记对应 tool 的 hasResult
1898
+ const toolId = rawMessage?.message?.tool_use_id;
1899
+ if (toolId) {
1900
+ for (let i = session.uiMessages.length - 1; i >= 0; i--) {
1901
+ if (session.uiMessages[i].type === 'tool' && session.uiMessages[i].toolId === toolId) {
1902
+ session.uiMessages[i].hasResult = true;
1903
+ break;
1904
+ }
1905
+ }
1906
+ }
1834
1907
  }
1835
- // tool_use tool_result 不记录(太大,恢复时不需要)
1908
+ // tool 只保存精简信息(toolName + 摘要),不存完整 toolInput/toolResult
1836
1909
  }
1837
1910
 
1838
1911
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yeaft/webchat-agent",
3
- "version": "0.0.131",
3
+ "version": "0.0.133",
4
4
  "description": "Remote agent for Yeaft WebChat — connects worker machines to the central server",
5
5
  "main": "index.js",
6
6
  "type": "module",