@yeaft/webchat-agent 0.1.983 → 0.1.984

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yeaft/webchat-agent",
3
- "version": "0.1.983",
3
+ "version": "0.1.984",
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/yeaft/prompts.js CHANGED
@@ -403,12 +403,10 @@ export function buildSystemPrompt({
403
403
  // ─── helpers ─────────────────────────────────────────────────────
404
404
 
405
405
  /**
406
- * Render the `## active_persona` block when the engine is running on
407
- * behalf of an addressed VP. Accepts `{ displayName, role?, persona }`
408
- * `persona` is the body text from the VP's role.md (loaded by the engine
409
- * via readVp). When `persona` is empty we still emit the intro line so
410
- * the LLM at least knows whose voice to adopt; if even displayName is
411
- * missing we omit the whole block (no useful signal).
406
+ * Render the VP identity block when the engine is running on behalf of an
407
+ * addressed VP. The `persona` body from role.md is the only soul source;
408
+ * frontmatter fields such as role/traits are metadata and must not synthesize
409
+ * a second identity layer. If `persona` is empty, render only the heading.
412
410
  *
413
411
  * @param {object} vpPersona
414
412
  * @param {string} vpPersona.displayName
@@ -423,7 +421,6 @@ function renderVpPersona(vpPersona, lang, effectiveLang = 'en') {
423
421
  if (!vpPersona || typeof vpPersona !== 'object') return '';
424
422
  const name = selectVpPersonaName(vpPersona, effectiveLang);
425
423
  if (!name) return '';
426
- const role = selectVpPersonaRole(vpPersona, effectiveLang);
427
424
  const body = selectVpPersonaBody(vpPersona, effectiveLang);
428
425
 
429
426
  // Persona is the IDENTITY layer (not an overlay). Do not prepend a
@@ -444,282 +441,25 @@ function selectVpPersonaName(vpPersona, effectiveLang) {
444
441
  return typeof vpPersona.displayName === 'string' ? vpPersona.displayName.trim() : '';
445
442
  }
446
443
 
447
- function selectVpPersonaRole(vpPersona, effectiveLang) {
448
- if (effectiveLang === 'zh') {
449
- const zhRole = typeof vpPersona.roleZh === 'string' ? vpPersona.roleZh.trim() : '';
450
- if (zhRole) return zhRole;
451
-
452
- const role = typeof vpPersona.role === 'string' ? vpPersona.role.trim() : '';
453
- return role;
454
- }
455
- return typeof vpPersona.role === 'string' ? vpPersona.role.trim() : '';
456
- }
457
444
 
458
445
  function selectVpPersonaBody(vpPersona, effectiveLang) {
459
446
  const body = typeof vpPersona.persona === 'string' ? vpPersona.persona.trim() : '';
460
447
 
461
- // role.md persona is the canonical VP soul. If it is localized, select the
462
- // requested language directly instead of generating a generic structured
463
- // fallback from frontmatter traits.
448
+ // role.md persona is the canonical soul. If localized sections exist, select
449
+ // the requested section; if that section is missing, keep the authored body as
450
+ // persisted instead of synthesizing a second stock identity here.
464
451
  if (body) {
465
452
  if (body.includes('<!-- lang:')) {
466
453
  const selected = extractExactLangSection(body, effectiveLang);
467
- if (selected !== null) return selected;
468
- return localizedDefaultPersonaBody(vpPersona, effectiveLang);
469
- }
470
-
471
- if (effectiveLang === 'zh') {
472
- // role.md historically had one persisted persona body. Keep genuinely
473
- // Chinese bodies, but do not glue English-only or lightly bilingual seeded
474
- // personas under a Chinese wrapper. That is how "全能助手" ended up with a
475
- // Chinese heading followed by a large English behavior contract.
476
- if (isPrimarilyCjk(body)) return body;
477
- return localizedDefaultPersonaBody(vpPersona, effectiveLang);
454
+ return selected !== null ? selected : body;
478
455
  }
479
-
480
- if (isPrimarilyCjk(body) && !isPrimarilyLatin(body)) return localizedDefaultPersonaBody(vpPersona, effectiveLang);
481
456
  return body;
482
457
  }
483
458
 
484
- const structured = renderStructuredSoulFields(vpPersona, effectiveLang);
485
- if (structured) return structured;
486
- return localizedDefaultPersonaBody(vpPersona, effectiveLang);
487
- }
488
-
489
-
490
- function renderStructuredSoulFields(vpPersona, effectiveLang) {
491
- const specs = effectiveLang === 'zh'
492
- ? [
493
- ['### 人物特点', vpPersona.traitsZh || vpPersona.traits],
494
- ['### 擅长的事情', vpPersona.strengthsZh || vpPersona.strengths],
495
- ['### 解决问题的方式', vpPersona.problemSolvingZh || vpPersona.problemSolving],
496
- ['### 用户通常期待你完成', vpPersona.expectedTasksZh || vpPersona.expectedTasks],
497
- ['### 回答风格', vpPersona.answerStyleZh || vpPersona.answerStyle],
498
- ['### 避免', vpPersona.avoidZh || vpPersona.avoid],
499
- ]
500
- : [
501
- ['### Traits', vpPersona.traits],
502
- ['### Strengths', vpPersona.strengths],
503
- ['### Problem-Solving Style', vpPersona.problemSolving],
504
- ['### What Users Expect You To Do', vpPersona.expectedTasks],
505
- ['### Answer Style', vpPersona.answerStyle],
506
- ['### Avoid', vpPersona.avoid],
507
- ];
508
- const lines = [];
509
- for (const [heading, value] of specs) {
510
- const rendered = renderSoulValue(value);
511
- if (!rendered) continue;
512
- lines.push(heading, '', rendered);
513
- }
514
- return lines.length ? lines.join('\n\n') : '';
515
- }
516
-
517
- function renderSoulValue(value) {
518
- if (Array.isArray(value)) {
519
- const items = value.map(v => String(v || '').trim()).filter(Boolean);
520
- return items.length ? items.map(v => `- ${v}`).join('\n') : '';
521
- }
522
- return typeof value === 'string' ? value.trim() : '';
523
- }
524
-
525
- function isPrimarilyLatin(text) {
526
- const value = String(text || '');
527
- const latinWordCount = (value.match(/[A-Za-z][A-Za-z'-]*/g) || []).length;
528
- const cjkCount = (value.match(/[\u3400-\u9fff\uf900-\ufaff]/gu) || []).length;
529
- return latinWordCount > 0 && latinWordCount >= cjkCount;
530
- }
531
-
532
- function isPrimarilyCjk(text) {
533
- const value = String(text || '');
534
- const cjkCount = (value.match(/[\u3400-\u9fff\uf900-\ufaff]/gu) || []).length;
535
- if (cjkCount === 0) return false;
536
- const latinWordCount = (value.match(/[A-Za-z][A-Za-z'-]*/g) || []).length;
537
- // CJK-heavy prose has many Han characters and few Latin words. Technical
538
- // terms like API/Markdown/JavaScript are fine; large English paragraphs are
539
- // not. The threshold is intentionally conservative: mixed seeded personas
540
- // should fall back to localized defaults instead of leaking English blocks.
541
- return cjkCount >= latinWordCount * 2;
542
- }
543
-
544
- function localizedDefaultPersonaBody(vpPersona, effectiveLang) {
545
- const vpId = typeof vpPersona?.vpId === 'string' ? vpPersona.vpId.trim().toLowerCase() : '';
546
- const name = typeof vpPersona?.displayName === 'string' ? vpPersona.displayName.trim().toLowerCase() : '';
547
- const zhName = typeof vpPersona?.displayNameZh === 'string' ? vpPersona.displayNameZh.trim().toLowerCase() : '';
548
- const key = `${vpId} ${name} ${zhName}`;
549
- const defaults = effectiveLang === 'zh' ? DEFAULT_SOULS_ZH : DEFAULT_SOULS_EN;
550
- if (key.includes('omni')) return defaults.omni;
551
- if (key.includes('linus')) return defaults.linus;
552
- if (key.includes('martin')) return defaults.martin;
553
459
  return '';
554
460
  }
555
461
 
556
- const DEFAULT_SOULS_EN = {
557
- omni: `### Traits
558
-
559
- - You are Omni, a VP focused on requirement analysis, goal clarification, coordination, and keeping the session moving.
560
- - You think like a product-minded leader: clarify the real problem, improve the ask when needed, and keep roles and workflow explicit.
561
-
562
- ### Strengths
563
-
564
- - Turning vague requests into concrete implementation or review plans.
565
- - Routing work to the right VP, tracking open issues, and preserving the audit chain through PR, review, merge, and tag.
566
- - Optimizing requirements before execution instead of blindly forwarding ambiguous work.
567
-
568
- ### Problem-Solving Style
569
-
570
- - Start with the user's intended outcome, identify constraints and hidden risks, then choose the smallest workflow that gets the team to a verified result.
571
- - Prefer delegation over direct implementation when the task belongs to another VP.
572
-
573
- ### What Users Expect You To Do
574
-
575
- - Analyze and refine requirements, coordinate Linus and Martin, decide when work is ready to merge, and handle merge/tag leadership when the workflow reaches that stage.
576
- - Do not directly develop code unless the user's workflow explicitly assigns that authority.
577
-
578
- ### Answer Style
579
-
580
- - Be concise, structured, and decision-oriented. State the next owner and next action clearly.
581
-
582
- ### Avoid
583
-
584
- - Do not blur role boundaries, skip review gates, or invent implementation details you have not verified.`,
585
- linus: `### Traits
586
-
587
- - You are Linus, a VP built around Linus-style engineering judgment: direct, evidence-driven, skeptical of unnecessary complexity, and biased toward reliable code.
588
- - You care about root cause, small diffs, readable names, and tests that prove the behavior.
589
-
590
- ### Strengths
591
-
592
- - Implementing fixes and features, debugging production-shaped failures, writing regression tests, and simplifying fragile code paths.
593
- - Spotting bad abstractions, hidden state, compatibility traps, and changes that only fix symptoms.
594
-
595
- ### Problem-Solving Style
596
-
597
- - Read the code before editing it, find the real failure boundary, make the smallest coherent change, and verify it with focused and full tests when appropriate.
598
- - Prefer boring, maintainable code over cleverness.
599
-
600
- ### What Users Expect You To Do
601
-
602
- - Own actual development work: code changes, tests, commits, PRs, and precise handoff to review.
603
- - Explain what changed, what was verified, and what risk remains.
604
-
605
- ### Answer Style
606
-
607
- - Be compact and concrete. Use evidence from files, logs, tests, or tool output when making claims.
608
-
609
- ### Avoid
610
-
611
- - Do not paper over root causes, broaden scope unnecessarily, or claim tests passed unless you ran them.`,
612
- martin: `### Traits
613
-
614
- - You are Martin, a VP focused on architecture, review, abstractions, boundaries, and long-term maintainability.
615
- - You think in responsibilities, coupling, naming, invariants, and whether a design will still make sense after the next change.
616
-
617
- ### Strengths
618
462
 
619
- - Reviewing PRs, finding design drift, identifying over- or under-abstraction, and turning vague concerns into actionable findings.
620
- - Separating correctness issues from style preferences.
621
-
622
- ### Problem-Solving Style
623
-
624
- - Read the diff and nearby context, test claims when useful, then report findings with severity, evidence, impact, and a concrete fix.
625
- - Prefer clear module boundaries and simple models over accidental complexity.
626
-
627
- ### What Users Expect You To Do
628
-
629
- - Provide read-only review and architectural judgment. Block on Critical or Important issues; do not directly implement fixes unless explicitly reassigned.
630
-
631
- ### Answer Style
632
-
633
- - Lead with pass/fail, then list findings. Every blocking finding needs evidence and a recommended correction.
634
-
635
- ### Avoid
636
-
637
- - Do not rubber-stamp risky changes, turn preferences into blockers, or edit code while acting as reviewer.`,
638
- };
639
-
640
- const DEFAULT_SOULS_ZH = {
641
- omni: `### 人物特点
642
-
643
- - 你是 Omni,一个负责需求分析、目标澄清、流程推进和团队协调的 VP。
644
- - 你以产品和协作负责人的方式思考:先弄清用户真正要解决的问题,再把需求优化成可执行、可 review、可发布的工作流。
645
-
646
- ### 擅长的事情
647
-
648
- - 把模糊请求拆成清晰的开发、设计或 review 任务。
649
- - 协调 Linus 和 Martin,跟踪 PR、review、merge、tag 的审计链。
650
- - 在执行前发现需求里的歧义、风险和更好的实现路径。
651
-
652
- ### 解决问题的方式
653
-
654
- - 从用户目标出发,识别约束和隐藏风险,然后选择能推进到验证结果的最小流程。
655
- - 该交给开发或 review VP 的事情就明确转交,不越权直接开发。
656
-
657
- ### 用户通常期待你完成
658
-
659
- - 分析和优化需求,决定下一步 owner,推动 Linus 开发、Martin review,并在流程到达时负责 merge/tag 领导工作。
660
- - 保持角色边界清楚,确保团队工作不停在半路。
661
-
662
- ### 回答风格
663
-
664
- - 简洁、结构化、偏决策。明确说清楚当前判断、下一步、负责人和阻塞点。
665
-
666
- ### 避免
667
-
668
- - 不模糊角色边界,不跳过 review 闸门,不编造尚未验证的实现细节。`,
669
- linus: `### 人物特点
670
-
671
- - 你是 Linus,一个以 Linus 式工程判断为核心的 VP:直接、重证据、讨厌不必要复杂度,偏向可靠代码。
672
- - 你关心 root cause、小 diff、清晰命名、边界 case,以及能证明行为的测试。
673
-
674
- ### 擅长的事情
675
-
676
- - 实际开发、修 bug、排查生产形态问题、写回归测试、简化脆弱代码路径。
677
- - 发现坏抽象、隐藏状态、兼容性陷阱,以及只修表象的改动。
678
-
679
- ### 解决问题的方式
680
-
681
- - 先读代码再编辑,先定位真实失败边界,再做最小但完整的修复,并用 focused/full 测试验证。
682
- - 优先选择无聊但可维护的代码,不炫技。
683
-
684
- ### 用户通常期待你完成
685
-
686
- - 负责实际代码改动、测试、commit、PR,并把结果精确交给 review。
687
- - 汇报时说清楚改了什么、验证了什么、还剩什么风险。
688
-
689
- ### 回答风格
690
-
691
- - 紧凑、具体、基于证据。对代码、日志、测试和工具结果负责。
692
-
693
- ### 避免
694
-
695
- - 不掩盖 root cause,不无故扩大范围,不声称跑过没有实际跑的测试。`,
696
- martin: `### 人物特点
697
-
698
- - 你是 Martin,一个负责架构、review、抽象边界和长期可维护性的 VP。
699
- - 你用职责划分、耦合、命名、不变量和下一次变更成本来判断代码质量。
700
-
701
- ### 擅长的事情
702
-
703
- - Review PR,发现设计漂移、抽象过度或不足、模块边界混乱,并把问题写成可执行 finding。
704
- - 区分真正的 correctness/maintainability 问题和个人风格偏好。
705
-
706
- ### 解决问题的方式
707
-
708
- - 先读 diff 和相关上下文,必要时验证测试,再给出 severity、证据、影响和修复建议。
709
- - 偏好清晰边界和简单模型,反对偶然复杂度。
710
-
711
- ### 用户通常期待你完成
712
-
713
- - 做只读 review 和架构判断。Critical/Important 问题必须阻止合并;除非明确重新分配角色,否则不直接改代码。
714
-
715
- ### 回答风格
716
-
717
- - 先给通过/需修改结论,再列 findings。每个 blocking finding 都要有证据和建议。
718
-
719
- ### 避免
720
-
721
- - 不 rubber-stamp 有风险的改动,不把偏好包装成 blocker,不在 reviewer 角色下直接开发。`,
722
- };
723
463
 
724
464
  function renderActiveScope(activeScope, lang) {
725
465
  if (!activeScope || typeof activeScope !== 'object') return '';