@yeaft/webchat-agent 0.1.957 → 0.1.959

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.957",
3
+ "version": "0.1.959",
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
@@ -97,25 +97,28 @@ function readTemplate(name, { required = true } = {}) {
97
97
  function extractLangSection(content, language) {
98
98
  if (!content) return '';
99
99
 
100
- const marker = `<!-- lang:${language} -->`;
101
- const markerIdx = content.indexOf(marker);
100
+ const selected = extractExactLangSection(content, language);
101
+ if (selected !== null) return selected;
102
102
 
103
- if (markerIdx === -1) {
104
- // No marker for this language — if language is 'zh', try 'en' fallback
105
- if (language === 'zh') {
106
- const enMarker = '<!-- lang:en -->';
107
- const enIdx = content.indexOf(enMarker);
108
- if (enIdx !== -1) {
109
- // Has en marker but no zh — return en section as fallback
110
- return extractLangSection(content, 'en');
111
- }
112
- }
113
- // No markers at all — return full content
114
- if (!content.includes('<!-- lang:')) return content;
115
- // Has markers but not for this language — fallback to en
116
- return extractLangSection(content, 'en');
103
+ // No marker for this language — if language is 'zh', try 'en' fallback
104
+ if (language === 'zh') {
105
+ const fallback = extractExactLangSection(content, 'en');
106
+ if (fallback !== null) return fallback;
117
107
  }
118
108
 
109
+ // No markers at all — return full content
110
+ if (!content.includes('<!-- lang:')) return content;
111
+ // Has markers but not for this language — fallback to en
112
+ return extractExactLangSection(content, 'en') || '';
113
+ }
114
+
115
+ function extractExactLangSection(content, language) {
116
+ if (!content) return null;
117
+
118
+ const marker = `<!-- lang:${language} -->`;
119
+ const markerIdx = content.indexOf(marker);
120
+ if (markerIdx === -1) return null;
121
+
119
122
  // Extract from after the marker to the next <!-- lang: marker or EOF
120
123
  const sectionStart = markerIdx + marker.length;
121
124
  const nextMarkerIdx = content.indexOf('<!-- lang:', sectionStart);
@@ -459,12 +462,28 @@ function selectVpPersonaRole(vpPersona, effectiveLang) {
459
462
 
460
463
  function selectVpPersonaBody(vpPersona, effectiveLang) {
461
464
  const body = typeof vpPersona.persona === 'string' ? vpPersona.persona.trim() : '';
465
+ if (!body) return '';
466
+
467
+ if (body.includes('<!-- lang:')) {
468
+ const selected = extractExactLangSection(body, effectiveLang);
469
+ if (selected !== null) return selected;
470
+ return localizedDefaultPersonaBody(vpPersona, effectiveLang);
471
+ }
472
+
462
473
  if (effectiveLang === 'zh') {
463
- // role.md has one persisted persona body today. If that body is Chinese,
464
- // keep it. If it is English-only (the default seeded VP shape), do not glue
465
- // it under a Chinese wrapper and produce a half-translated system prompt.
466
- return hasCjk(body) ? body : '';
474
+ // role.md historically had one persisted persona body. Keep genuinely
475
+ // Chinese bodies, but do not glue English-only or lightly bilingual seeded
476
+ // personas under a Chinese wrapper. That is how "全能助手" ended up with a
477
+ // Chinese heading followed by a large English behavior contract.
478
+ if (isPrimarilyCjk(body)) return body;
479
+ return localizedDefaultPersonaBody(vpPersona, effectiveLang);
480
+ }
481
+
482
+ if (hasCjk(body)) {
483
+ const localized = localizedDefaultPersonaBody(vpPersona, effectiveLang);
484
+ if (localized) return localized;
467
485
  }
486
+
468
487
  return body;
469
488
  }
470
489
 
@@ -472,6 +491,75 @@ function hasCjk(text) {
472
491
  return /[\u3400-\u9fff\uf900-\ufaff]/u.test(String(text || ''));
473
492
  }
474
493
 
494
+ function isPrimarilyCjk(text) {
495
+ const value = String(text || '');
496
+ const cjkCount = (value.match(/[\u3400-\u9fff\uf900-\ufaff]/gu) || []).length;
497
+ if (cjkCount === 0) return false;
498
+ const latinWordCount = (value.match(/[A-Za-z][A-Za-z'-]*/g) || []).length;
499
+ // CJK-heavy prose has many Han characters and few Latin words. Technical
500
+ // terms like API/Markdown/JavaScript are fine; large English paragraphs are
501
+ // not. The threshold is intentionally conservative: mixed seeded personas
502
+ // should fall back to localized defaults instead of leaking English blocks.
503
+ return cjkCount >= latinWordCount * 2;
504
+ }
505
+
506
+ function localizedDefaultPersonaBody(vpPersona, effectiveLang) {
507
+ const vpId = typeof vpPersona?.vpId === 'string' ? vpPersona.vpId.trim().toLowerCase() : '';
508
+ if (effectiveLang === 'zh' && vpId === 'omni') {
509
+ return OMNI_PERSONA_ZH;
510
+ }
511
+ if (effectiveLang === 'en' && vpId === 'omni') {
512
+ return OMNI_PERSONA_EN;
513
+ }
514
+ return '';
515
+ }
516
+
517
+ const OMNI_PERSONA_EN = `You are Omni Assistant, a cross-domain, execution-focused general AI partner.
518
+
519
+ ## Language Policy
520
+
521
+ - Reply in the current user-configured language; use English for English configuration and Chinese for Chinese configuration.
522
+ - If the user explicitly asks to switch language, follow the user's request.
523
+
524
+ ## Core Capabilities
525
+
526
+ - Cross-domain synthesis: handle writing, coding, product thinking, research, planning, analysis, learning, translation, troubleshooting, and creative work without forcing the user to pick a specialist first.
527
+ - Strong execution: when a task needs action, clarify only blocking unknowns, make a short plan, use available tools, produce the deliverable, and verify the result.
528
+ - Goal clarification: distinguish the user's real objective from the literal wording; state assumptions when moving forward without perfect information.
529
+ - Tool use and verification: inspect files, run commands, search sources, test code, or analyze data when the environment allows it. Never claim work was done unless it was actually done.
530
+ - Honest uncertainty: say "I'm not sure" when evidence is missing, then explain how to check.
531
+ - Safety boundaries: refuse illegal, dangerous, deceptive, privacy-invasive, or unauthorized requests. For medical, legal, financial, production, or destructive operations, give general guidance and call out risks.
532
+
533
+ ## Decision and Response Style
534
+
535
+ - Start with the outcome the user needs, then choose the simplest path that can actually be completed and checked.
536
+ - Answer simple questions directly; break down and execute complex work.
537
+ - After execution tasks, briefly report only what changed, what was verified, and any risk or next step.
538
+ - Use concise, structured Markdown; avoid empty praise and false certainty.`;
539
+
540
+ const OMNI_PERSONA_ZH = `你是全能助手,一个跨领域、偏执行的通用 AI 伙伴。
541
+
542
+ ## 语言策略
543
+
544
+ - 使用当前用户配置语言回复;中文配置下用中文,英文配置下用英文。
545
+ - 用户明确要求切换语言时,按用户要求执行。
546
+
547
+ ## 核心能力
548
+
549
+ - 跨领域综合:处理写作、代码、产品、研究、规划、分析、学习、翻译、排障和创意任务,不强迫用户先选择专家。
550
+ - 强执行:任务需要行动时,只澄清真正阻塞的问题,制定短计划,使用可用工具,交付结果并验证。
551
+ - 目标澄清:区分用户真正目标和字面表达;信息不完整但可推进时,说明假设后继续。
552
+ - 工具与验证:环境允许时读取文件、运行命令、搜索资料、测试代码或分析数据;没有实际做过的事不要声称做过。
553
+ - 诚实不确定:证据不足时说“我不确定”,并说明如何检查。
554
+ - 安全边界:拒绝违法、危险、欺骗、侵犯隐私或未授权请求;医疗、法律、金融、生产和破坏性操作只给一般性建议并指出风险。
555
+
556
+ ## 决策与回复风格
557
+
558
+ - 先给用户需要的结果,再选择能完成且能验证的最简单路径。
559
+ - 简单问题直接回答;复杂工作拆步执行。
560
+ - 执行类任务完成后只简要汇报:改了什么、验证了什么、风险或下一步。
561
+ - 使用简洁、结构化的 Markdown;避免空泛夸奖和假装确定。`;
562
+
475
563
 
476
564
  /**
477
565
  * Render `## active_scope` block (DESIGN-PROMPT §3 ④).
@@ -13,6 +13,12 @@ You are Yeaft, an AI companion that maintains a single continuous conversation w
13
13
  - Never add emoji unless the user uses them first
14
14
  - Never start responses with excessive flattery ("Great question!")
15
15
 
16
+ ## Task Replies
17
+
18
+ - For development, debugging, operations, or other execution tasks, default to a compact final reply
19
+ - After completing work, report only: what changed, what was verified, and any risk or next step
20
+ - Write detailed reports only when the user explicitly asks for "detail", "report", or a deeper explanation
21
+
16
22
  ## Output Format
17
23
 
18
24
  - Use GitHub-flavored Markdown
@@ -62,6 +68,12 @@ You are Yeaft, an AI companion that maintains a single continuous conversation w
62
68
  - 除非用户先使用 emoji,否则不要添加
63
69
  - 不要以过度的奉承开头("好问题!")
64
70
 
71
+ ## 任务回复
72
+
73
+ - 开发、修复、运维或其他执行类任务,默认用精简的最终回复
74
+ - 完成后只汇报:改了什么、验证了什么、风险或下一步
75
+ - 只有用户明确要求“详细”、“报告”或深入解释时,才展开长篇说明
76
+
65
77
  ## 输出格式
66
78
 
67
79
  - 使用 GitHub 风格的 Markdown
@@ -9,6 +9,12 @@
9
9
  - Never add emoji unless the user uses them first
10
10
  - Never start responses with excessive flattery ("Great question!")
11
11
 
12
+ ## Task Replies
13
+
14
+ - For development, debugging, operations, or other execution tasks, default to a compact final reply
15
+ - After completing work, report only: what changed, what was verified, and any risk or next step
16
+ - Write detailed reports only when the user explicitly asks for "detail", "report", or a deeper explanation
17
+
12
18
  ## Output Format
13
19
 
14
20
  - Use GitHub-flavored Markdown
@@ -54,6 +60,12 @@
54
60
  - 除非用户先使用 emoji,否则不要添加
55
61
  - 不要以过度的奉承开头("好问题!")
56
62
 
63
+ ## 任务回复
64
+
65
+ - 开发、修复、运维或其他执行类任务,默认用精简的最终回复
66
+ - 完成后只汇报:改了什么、验证了什么、风险或下一步
67
+ - 只有用户明确要求“详细”、“报告”或深入解释时,才展开长篇说明
68
+
57
69
  ## 输出格式
58
70
 
59
71
  - 使用 GitHub 风格的 Markdown