@yeaft/webchat-agent 0.1.84 → 0.1.86

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/conversation.js CHANGED
@@ -607,6 +607,53 @@ export async function handleUserInput(msg) {
607
607
  console.log(`[RolePlay] Human responded, resuming from ${fromRole}'s request`);
608
608
  }
609
609
 
610
+ // ★ RolePlay: handle @mention targetRole routing
611
+ const targetRole = msg.targetRole;
612
+ if (targetRole && rpSession && rpSession._routeInitialized) {
613
+ const roleNames = new Set(rpSession.roles.map(r => r.name));
614
+ if (roleNames.has(targetRole)) {
615
+ const targetRoleConfig = rpSession.roles.find(r => r.name === targetRole);
616
+ const targetLabel = targetRoleConfig
617
+ ? (targetRoleConfig.icon ? `${targetRoleConfig.icon} ${targetRoleConfig.displayName}` : targetRoleConfig.displayName)
618
+ : targetRole;
619
+ const targetClaudeMd = targetRoleConfig?.claudeMd || '';
620
+
621
+ // Prepend ROLE signal so Claude responds as the target role
622
+ let rolePrefix = `---ROLE: ${targetRole}---\n\n`;
623
+ rolePrefix += `用户指定由 ${targetLabel} 来回复。\n`;
624
+ if (targetClaudeMd) {
625
+ rolePrefix += `<role-context>\n${targetClaudeMd}\n</role-context>\n\n`;
626
+ }
627
+ rolePrefix += `请以 ${targetLabel} 的身份回复以下消息:\n\n`;
628
+ effectivePrompt = rolePrefix + effectivePrompt;
629
+
630
+ // Update rpSession state
631
+ const prevRole = rpSession.currentRole;
632
+ rpSession.currentRole = targetRole;
633
+ if (rpSession.roleStates[targetRole]) {
634
+ rpSession.roleStates[targetRole].status = 'active';
635
+ }
636
+ if (prevRole && prevRole !== targetRole && rpSession.roleStates[prevRole]) {
637
+ rpSession.roleStates[prevRole].status = 'idle';
638
+ }
639
+
640
+ // Send roleplay_status update to frontend
641
+ ctx.sendToServer({
642
+ type: 'roleplay_status',
643
+ conversationId,
644
+ currentRole: rpSession.currentRole,
645
+ round: rpSession.round,
646
+ features: rpSession.features ? Array.from(rpSession.features.values()) : [],
647
+ roleStates: rpSession.roleStates || {},
648
+ waitingHuman: false
649
+ });
650
+
651
+ console.log(`[RolePlay] @mention routing: ${prevRole || 'none'} -> ${targetRole}`);
652
+ } else {
653
+ console.warn(`[RolePlay] @mention target role not found: ${targetRole}`);
654
+ }
655
+ }
656
+
610
657
  const userMessage = {
611
658
  type: 'user',
612
659
  message: { role: 'user', content: effectivePrompt }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yeaft/webchat-agent",
3
- "version": "0.1.84",
3
+ "version": "0.1.86",
4
4
  "description": "Remote agent for Yeaft WebChat — connects worker machines to the central server",
5
5
  "main": "index.js",
6
6
  "type": "module",
package/roleplay-dir.js CHANGED
@@ -24,9 +24,9 @@ import { getRolePlayMessages } from './roleplay-i18n.js';
24
24
  // Each entry is a list of role names (keys into roleTemplates in i18n).
25
25
  const TEAM_ROLES = {
26
26
  dev: ['pm', 'dev', 'reviewer', 'tester'],
27
- writing: ['planner', 'writer', 'editor'],
28
- trading: ['strategist', 'analyst', 'macro', 'risk', 'trader'],
29
- video: ['director', 'scriptwriter', 'storyboard'],
27
+ writing: ['editor', 'writer', 'proofreader'],
28
+ trading: ['analyst', 'strategist', 'risk-manager'],
29
+ video: ['director', 'writer', 'producer'],
30
30
  custom: ['pm', 'dev', 'reviewer', 'tester'], // default same as dev
31
31
  };
32
32
 
@@ -193,9 +193,13 @@ export async function writeSessionClaudeMd(projectDir, sessionName, config) {
193
193
  const roleSection = buildRoleSection(teamType, language, customRoles);
194
194
 
195
195
  // Build workflow section
196
- const workflow = (teamType === 'dev')
197
- ? m.devWorkflow
198
- : m.genericWorkflow;
196
+ const workflowMap = {
197
+ dev: m.devWorkflow,
198
+ writing: m.writingWorkflow,
199
+ trading: m.tradingWorkflow,
200
+ video: m.videoWorkflow,
201
+ };
202
+ const workflow = workflowMap[teamType] || m.genericWorkflow;
199
203
 
200
204
  const content = `${m.sessionTitle(sessionName)}
201
205
 
@@ -278,7 +282,7 @@ export function getDefaultRoles(teamType, language = 'zh-CN') {
278
282
  if (!tmpl) return { name, displayName: name, icon: '' };
279
283
 
280
284
  // Extract icon and displayName from heading: "## 📋 PM-乔布斯 (pm)"
281
- const headingMatch = tmpl.heading.match(/^##\s*(\S+)\s+(.+?)\s*\((\w+)\)\s*$/);
285
+ const headingMatch = tmpl.heading.match(/^##\s*(\S+)\s+(.+?)\s*\(([\w-]+)\)\s*$/);
282
286
  if (headingMatch) {
283
287
  return {
284
288
  name: headingMatch[3],
package/roleplay-i18n.js CHANGED
@@ -189,6 +189,37 @@ const messages = {
189
189
 
190
190
  风格:视觉思维,善于用画面讲故事。`,
191
191
  },
192
+ // RolePlay-specific roles (not in Crew templates)
193
+ proofreader: {
194
+ heading: '## 🔎 审校-马伯庸 (proofreader)',
195
+ content: `你是审校-马伯庸。你的职责:
196
+ - 检查内容的逻辑一致性和事实准确性
197
+ - 审核文字质量、错别字和表达规范
198
+ - 核实引用和数据的准确性
199
+ - 提出具体的修改建议
200
+
201
+ 风格:考据成瘾,逻辑洁癖,毒舌但建设性,指出问题必给修改方案。`,
202
+ },
203
+ 'risk-manager': {
204
+ heading: '## 🛡️ 风控官-塔勒布 (risk-manager)',
205
+ content: `你是风控官-塔勒布。你的职责:
206
+ - 对策略进行压力测试和尾部风险评估
207
+ - 检查仓位是否符合风控原则
208
+ - 审核止损设置和对冲方案
209
+ - 如果策略风险不可接受,直接打回并说明原因
210
+
211
+ 风格:尾部风险偏执狂,反脆弱思维,杠铃策略信徒。`,
212
+ },
213
+ producer: {
214
+ heading: '## 🎬 制片-徐克 (producer)',
215
+ content: `你是制片-徐克。你的职责:
216
+ - 审核脚本和分镜的可执行性
217
+ - 评估制作资源需求和技术可行性
218
+ - 把控制作进度和质量标准
219
+ - 生成最终的 AI 视频 prompt 序列
220
+
221
+ 风格:视觉想象力爆棚,技术与艺术兼备。`,
222
+ },
192
223
  },
193
224
 
194
225
  routeProtocol: `# ROUTE 协议
@@ -214,6 +245,18 @@ taskTitle: {任务标题}(可选)
214
245
  3. **审查者** Code Review(不通过 → 返回开发者修复)
215
246
  4. **测试者** 运行测试 & 验证(有 bug → 返回开发者修复)
216
247
  5. **PM** 验收总结`,
248
+ writingWorkflow: `1. **编辑** 分析需求,确定内容方向和框架
249
+ 2. **作者** 根据大纲撰写内容
250
+ 3. **审校** 检查逻辑一致性、事实准确性和文字质量(不通过 → 返回作者修改)
251
+ 4. **编辑** 验收最终成果`,
252
+ tradingWorkflow: `1. **分析师** 研究市场,输出技术分析和关键价位
253
+ 2. **策略师** 综合分析,制定投资策略和仓位方案
254
+ 3. **风控官** 压力测试策略,评估尾部风险(不通过 → 返回策略师调整)
255
+ 4. **策略师** 确认最终方案并总结`,
256
+ videoWorkflow: `1. **导演** 确定主题、情绪基调和视觉风格
257
+ 2. **编剧** 构思故事线,撰写分段脚本
258
+ 3. **制片** 审核可行性,生成最终 prompt 序列(不通过 → 返回编剧调整)
259
+ 4. **导演** 最终审核并验收`,
217
260
  genericWorkflow: '按角色顺序依次完成任务。',
218
261
 
219
262
  projectPathTitle: '# 项目路径',
@@ -399,6 +442,37 @@ Style: Good storytelling, focused on emotional resonance.`,
399
442
 
400
443
  Style: Visual thinking, good at telling stories with images.`,
401
444
  },
445
+ // RolePlay-specific roles (not in Crew templates)
446
+ proofreader: {
447
+ heading: '## 🔎 Proofreader-Tolkien (proofreader)',
448
+ content: `You are Proofreader-Tolkien. Your responsibilities:
449
+ - Check content for logical consistency and factual accuracy
450
+ - Review writing quality, typos, and expression standards
451
+ - Verify accuracy of citations and data
452
+ - Provide specific revision suggestions
453
+
454
+ Style: Research addict, logic purist, sharp but constructive — every critique comes with a fix.`,
455
+ },
456
+ 'risk-manager': {
457
+ heading: '## 🛡️ Risk-Officer-Taleb (risk-manager)',
458
+ content: `You are Risk-Officer-Taleb. Your responsibilities:
459
+ - Stress-test strategies and assess tail risks
460
+ - Verify positions comply with risk principles
461
+ - Review stop-loss settings and hedging plans
462
+ - Reject strategies with unacceptable risk — explain which principle is violated
463
+
464
+ Style: Tail risk obsessive, antifragile thinking, barbell strategy devotee.`,
465
+ },
466
+ producer: {
467
+ heading: '## 🎬 Producer-Spielberg (producer)',
468
+ content: `You are Producer-Spielberg. Your responsibilities:
469
+ - Review script and storyboard feasibility
470
+ - Assess production resource needs and technical viability
471
+ - Control production schedule and quality standards
472
+ - Generate final AI video prompt sequences
473
+
474
+ Style: Visual imagination overflows, art and craft in equal measure.`,
475
+ },
402
476
  },
403
477
 
404
478
  routeProtocol: `# ROUTE Protocol
@@ -424,6 +498,18 @@ Rules:
424
498
  3. **Reviewer** code review (if fails → back to Dev)
425
499
  4. **Tester** runs tests & verifies (if bugs → back to Dev)
426
500
  5. **PM** acceptance & summary`,
501
+ writingWorkflow: `1. **Editor** analyzes requirements, determines content direction and framework
502
+ 2. **Writer** writes content based on outline
503
+ 3. **Proofreader** checks logical consistency, factual accuracy, and writing quality (if fails → back to Writer)
504
+ 4. **Editor** final acceptance of deliverables`,
505
+ tradingWorkflow: `1. **Analyst** researches market, outputs technical analysis and key levels
506
+ 2. **Strategist** synthesizes analysis, formulates investment strategy and position plan
507
+ 3. **Risk Manager** stress-tests strategy, assesses tail risks (if fails → back to Strategist)
508
+ 4. **Strategist** confirms final plan and summarizes`,
509
+ videoWorkflow: `1. **Director** establishes theme, emotional tone, and visual style
510
+ 2. **Screenwriter** conceives storyline, writes segmented script
511
+ 3. **Producer** reviews feasibility, generates final prompt sequence (if fails → back to Screenwriter)
512
+ 4. **Director** final review and acceptance`,
427
513
  genericWorkflow: 'Complete tasks by following the role sequence.',
428
514
 
429
515
  projectPathTitle: '# Project Path',
package/roleplay.js CHANGED
@@ -483,8 +483,17 @@ function getWorkflow(teamType, roles, isZh) {
483
483
  if (teamType === 'dev') {
484
484
  return buildDevWorkflow(roleNames, isZh);
485
485
  }
486
+ if (teamType === 'writing') {
487
+ return buildWritingWorkflow(roleNames, isZh);
488
+ }
489
+ if (teamType === 'trading') {
490
+ return buildTradingWorkflow(roleNames, isZh);
491
+ }
492
+ if (teamType === 'video') {
493
+ return buildVideoWorkflow(roleNames, isZh);
494
+ }
486
495
 
487
- // Generic fallback for other team types
496
+ // Generic fallback for custom / unknown team types
488
497
  return isZh ? '按角色顺序依次完成任务。' : 'Complete tasks by following the role sequence.';
489
498
  }
490
499
 
@@ -516,9 +525,71 @@ function buildDevWorkflow(roleNames, isZh) {
516
525
  return steps.join('\n');
517
526
  }
518
527
 
519
- // ---------------------------------------------------------------------------
520
- // RolePlay ROUTE protocol support
521
- // ---------------------------------------------------------------------------
528
+ function buildWritingWorkflow(roleNames, isZh) {
529
+ const hasEditor = roleNames.includes('editor');
530
+ const hasWriter = roleNames.includes('writer');
531
+ const hasProofreader = roleNames.includes('proofreader');
532
+
533
+ const steps = [];
534
+
535
+ if (isZh) {
536
+ if (hasEditor) steps.push(`${steps.length + 1}. **编辑** 分析需求,确定内容方向和框架`);
537
+ if (hasWriter) steps.push(`${steps.length + 1}. **作者** 根据大纲撰写内容`);
538
+ if (hasProofreader) steps.push(`${steps.length + 1}. **审校** 检查逻辑一致性、事实准确性和文字质量(不通过 → 返回作者修改)`);
539
+ if (hasEditor) steps.push(`${steps.length + 1}. **编辑** 验收最终成果`);
540
+ } else {
541
+ if (hasEditor) steps.push(`${steps.length + 1}. **Editor** analyzes requirements, determines content direction and framework`);
542
+ if (hasWriter) steps.push(`${steps.length + 1}. **Writer** writes content based on outline`);
543
+ if (hasProofreader) steps.push(`${steps.length + 1}. **Proofreader** checks logical consistency, factual accuracy, and writing quality (if fails → back to Writer)`);
544
+ if (hasEditor) steps.push(`${steps.length + 1}. **Editor** final acceptance of deliverables`);
545
+ }
546
+
547
+ return steps.join('\n');
548
+ }
549
+
550
+ function buildTradingWorkflow(roleNames, isZh) {
551
+ const hasAnalyst = roleNames.includes('analyst');
552
+ const hasStrategist = roleNames.includes('strategist');
553
+ const hasRiskManager = roleNames.includes('risk-manager');
554
+
555
+ const steps = [];
556
+
557
+ if (isZh) {
558
+ if (hasAnalyst) steps.push(`${steps.length + 1}. **分析师** 研究市场,输出技术分析和关键价位`);
559
+ if (hasStrategist) steps.push(`${steps.length + 1}. **策略师** 综合分析,制定投资策略和仓位方案`);
560
+ if (hasRiskManager) steps.push(`${steps.length + 1}. **风控官** 压力测试策略,评估尾部风险(不通过 → 返回策略师调整)`);
561
+ if (hasStrategist) steps.push(`${steps.length + 1}. **策略师** 确认最终方案并总结`);
562
+ } else {
563
+ if (hasAnalyst) steps.push(`${steps.length + 1}. **Analyst** researches market, outputs technical analysis and key levels`);
564
+ if (hasStrategist) steps.push(`${steps.length + 1}. **Strategist** synthesizes analysis, formulates investment strategy and position plan`);
565
+ if (hasRiskManager) steps.push(`${steps.length + 1}. **Risk Manager** stress-tests strategy, assesses tail risks (if fails → back to Strategist)`);
566
+ if (hasStrategist) steps.push(`${steps.length + 1}. **Strategist** confirms final plan and summarizes`);
567
+ }
568
+
569
+ return steps.join('\n');
570
+ }
571
+
572
+ function buildVideoWorkflow(roleNames, isZh) {
573
+ const hasDirector = roleNames.includes('director');
574
+ const hasWriter = roleNames.includes('writer');
575
+ const hasProducer = roleNames.includes('producer');
576
+
577
+ const steps = [];
578
+
579
+ if (isZh) {
580
+ if (hasDirector) steps.push(`${steps.length + 1}. **导演** 确定主题、情绪基调和视觉风格`);
581
+ if (hasWriter) steps.push(`${steps.length + 1}. **编剧** 构思故事线,撰写分段脚本`);
582
+ if (hasProducer) steps.push(`${steps.length + 1}. **制片** 审核可行性,生成最终 prompt 序列(不通过 → 返回编剧调整)`);
583
+ if (hasDirector) steps.push(`${steps.length + 1}. **导演** 最终审核并验收`);
584
+ } else {
585
+ if (hasDirector) steps.push(`${steps.length + 1}. **Director** establishes theme, emotional tone, and visual style`);
586
+ if (hasWriter) steps.push(`${steps.length + 1}. **Screenwriter** conceives storyline, writes segmented script`);
587
+ if (hasProducer) steps.push(`${steps.length + 1}. **Producer** reviews feasibility, generates final prompt sequence (if fails → back to Screenwriter)`);
588
+ if (hasDirector) steps.push(`${steps.length + 1}. **Director** final review and acceptance`);
589
+ }
590
+
591
+ return steps.join('\n');
592
+ }
522
593
 
523
594
  // Re-export parseRoutes for use by claude.js and tests
524
595
  export { parseRoutes } from './crew/routing.js';