@yeaft/webchat-agent 0.1.572 → 0.1.574

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.572",
3
+ "version": "0.1.574",
4
4
  "description": "Remote agent for Yeaft WebChat — connects worker machines to the central server",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -34,6 +34,8 @@ export const DEFAULT_VPS = Object.freeze([
34
34
  {
35
35
  vpId: 'steve',
36
36
  displayName: 'Steve Jobs',
37
+ displayNameZh: '史蒂夫·乔布斯',
38
+ aliases: ['steve', 'jobs', 'shidifu', 'qiaobusi', 'qbs'],
37
39
  role: 'Product Strategist',
38
40
  traits: ['minimalist', 'uncompromising', 'taste-first'],
39
41
  modelHint: 'primary',
@@ -55,6 +57,8 @@ Bad for: incremental A/B testing, compromise negotiations, anything that rewards
55
57
  {
56
58
  vpId: 'linus',
57
59
  displayName: 'Linus Torvalds',
60
+ displayNameZh: '林纳斯·托瓦兹',
61
+ aliases: ['linus', 'torvalds', 'linasi', 'tuowazi', 'lnx'],
58
62
  role: 'Systems Engineer',
59
63
  traits: ['data-structures-first', 'no-workarounds', 'blunt'],
60
64
  modelHint: 'primary',
@@ -76,6 +80,8 @@ Bad for: soothing egos, PM sync meetings, anything that rewards diplomacy over t
76
80
  {
77
81
  vpId: 'martin',
78
82
  displayName: 'Martin Fowler',
83
+ displayNameZh: '马丁·福勒',
84
+ aliases: ['martin', 'fowler', 'mading', 'fule'],
79
85
  role: 'Code Reviewer',
80
86
  traits: ['refactoring', 'code-smells', 'readability'],
81
87
  modelHint: 'primary',
@@ -97,6 +103,8 @@ Bad for: greenfield scaffolding from zero, raw performance tuning, UI design.`,
97
103
  {
98
104
  vpId: 'dieter',
99
105
  displayName: 'Dieter Rams',
106
+ displayNameZh: '迪特·拉姆斯',
107
+ aliases: ['dieter', 'rams', 'dite', 'lamusi'],
100
108
  role: 'UX Designer',
101
109
  traits: ['less-but-better', 'honest', 'pixel-obsessive'],
102
110
  modelHint: 'primary',
@@ -118,6 +126,8 @@ Bad for: wild brainstorms, marketing sizzle, maximalist visual languages.`,
118
126
  {
119
127
  vpId: 'ada',
120
128
  displayName: 'Ada Lovelace',
129
+ displayNameZh: '阿达·洛芙莱斯',
130
+ aliases: ['ada', 'lovelace', 'ada', 'luofulaisi'],
121
131
  role: 'Algorithm Specialist',
122
132
  traits: ['first-principles', 'rigorous', 'imaginative'],
123
133
  modelHint: 'primary',
@@ -139,6 +149,8 @@ Bad for: production firefighting, ops triage, team-velocity debates.`,
139
149
  {
140
150
  vpId: 'grace',
141
151
  displayName: 'Grace Hopper',
152
+ displayNameZh: '葛丽丝·霍普',
153
+ aliases: ['grace', 'hopper', 'gelisi', 'huopu'],
142
154
  role: 'Debug Expert',
143
155
  traits: ['systems-thinking', 'pragmatic', 'teacher'],
144
156
  modelHint: 'primary',
@@ -160,6 +172,8 @@ Bad for: UI polish, marketing copy, pure-theory derivations.`,
160
172
  {
161
173
  vpId: 'alice',
162
174
  displayName: 'Alice Security',
175
+ displayNameZh: '爱丽丝·安全官',
176
+ aliases: ['alice', 'security', 'ailisi', 'anquan'],
163
177
  role: 'Security Analyst',
164
178
  traits: ['threat-modeling', 'trust-nothing', 'adversarial'],
165
179
  modelHint: 'primary',
@@ -181,6 +195,8 @@ Bad for: greenfield UX explorations, creative copy, cost-optimisation tradeoffs.
181
195
  {
182
196
  vpId: 'ken',
183
197
  displayName: 'Ken Thompson',
198
+ displayNameZh: '肯·汤普逊',
199
+ aliases: ['ken', 'thompson', 'ken', 'tangpuxun', 'unix'],
184
200
  role: 'Unix Philosopher',
185
201
  traits: ['do-one-thing-well', 'composable', 'terse'],
186
202
  modelHint: 'primary',
@@ -202,6 +218,8 @@ Bad for: rich GUIs, stateful sessions, anything that resists the pipeline model.
202
218
  {
203
219
  vpId: 'margaret',
204
220
  displayName: 'Margaret Hamilton',
221
+ displayNameZh: '玛格丽特·汉密尔顿',
222
+ aliases: ['margaret', 'hamilton', 'magelite', 'hanmierdun'],
205
223
  role: 'QA Lead',
206
224
  traits: ['safety-first', 'edge-cases', 'defensive'],
207
225
  modelHint: 'primary',
@@ -223,6 +241,8 @@ Bad for: rapid prototyping where failure is cheap, pixel-hunt design reviews.`,
223
241
  {
224
242
  vpId: 'shannon',
225
243
  displayName: 'Shannon',
244
+ displayNameZh: '克劳德·香农',
245
+ aliases: ['shannon', 'claude', 'xiangnong', 'kelaode'],
226
246
  role: 'Data Analyst',
227
247
  traits: ['information-theory', 'signal-vs-noise', 'probabilistic'],
228
248
  modelHint: 'primary',
@@ -244,6 +264,8 @@ Bad for: qualitative UX research, narrative-first presentations.`,
244
264
  {
245
265
  vpId: 'alan',
246
266
  displayName: 'Alan Kay',
267
+ displayNameZh: '艾伦·凯',
268
+ aliases: ['alan', 'kay', 'ailun', 'kai'],
247
269
  role: 'Futurist',
248
270
  traits: ['paradigm-shift', 'analogies', 'long-view'],
249
271
  modelHint: 'primary',
@@ -265,6 +287,8 @@ Bad for: today's bug, next Tuesday's ship date, conservative refactors.`,
265
287
  {
266
288
  vpId: 'norman',
267
289
  displayName: 'Don Norman',
290
+ displayNameZh: '唐纳德·诺曼',
291
+ aliases: ['norman', 'don', 'donald', 'nuoman', 'tangnade'],
268
292
  role: 'UX Researcher',
269
293
  traits: ['human-centered', 'affordances', 'cognitive-load'],
270
294
  modelHint: 'primary',
@@ -182,6 +182,10 @@ export function serializeVpForWire(vp) {
182
182
  return {
183
183
  vpId: vp.id,
184
184
  displayName: vp.name,
185
+ // task-fix (5-bugs): carry bilingual name + aliases (incl. pinyin) to
186
+ // the frontend so @ mention matching + localised rendering work.
187
+ displayNameZh: typeof vp.nameZh === 'string' ? vp.nameZh : '',
188
+ aliases: Array.isArray(vp.aliases) ? vp.aliases.slice() : [],
185
189
  role: vp.role || '',
186
190
  subtitle: vp.role || '',
187
191
  traits: Array.isArray(vp.traits) ? vp.traits.slice() : [],
@@ -57,17 +57,25 @@ function vpRolePathFor(libDir, vpId) {
57
57
  export function buildRoleMd(p) {
58
58
  const id = String(p.vpId);
59
59
  const name = p.displayName != null ? String(p.displayName) : id;
60
+ const nameZh = p.displayNameZh != null ? String(p.displayNameZh) : '';
61
+ const aliases = Array.isArray(p.aliases) ? p.aliases.map(a => String(a)).filter(Boolean) : [];
60
62
  const role = p.role != null ? String(p.role) : '';
61
63
  const traits = Array.isArray(p.traits) ? p.traits.map(t => String(t)).filter(Boolean) : [];
62
64
  const modelHint = p.modelHint === 'primary' || p.modelHint === 'fast' ? p.modelHint : null;
63
65
  const body = typeof p.persona === 'string' ? p.persona : '';
64
66
 
65
- const lines = ['---', `id: ${id}`, `name: ${yamlScalar(name)}`, `role: ${yamlScalar(role)}`];
67
+ const lines = ['---', `id: ${id}`, `name: ${yamlScalar(name)}`];
68
+ if (nameZh) lines.push(`nameZh: ${yamlScalar(nameZh)}`);
69
+ lines.push(`role: ${yamlScalar(role)}`);
66
70
  if (modelHint) lines.push(`modelHint: ${modelHint}`);
67
71
  if (traits.length > 0) {
68
72
  lines.push('traits:');
69
73
  for (const t of traits) lines.push(` - ${yamlScalar(t)}`);
70
74
  }
75
+ if (aliases.length > 0) {
76
+ lines.push('aliases:');
77
+ for (const a of aliases) lines.push(` - ${yamlScalar(a)}`);
78
+ }
71
79
  lines.push('---', '', body.trim(), '');
72
80
  return lines.join('\n');
73
81
  }
@@ -193,6 +201,8 @@ export function readVp(vpId, options = {}) {
193
201
  return {
194
202
  vpId: id,
195
203
  displayName: String(meta.name || id),
204
+ displayNameZh: typeof meta.nameZh === 'string' ? String(meta.nameZh) : '',
205
+ aliases: Array.isArray(meta.aliases) ? meta.aliases.map(String) : [],
196
206
  role: String(meta.role || ''),
197
207
  traits: Array.isArray(meta.traits) ? meta.traits.map(String) : [],
198
208
  modelHint,
@@ -127,6 +127,13 @@ export function loadVpFromDir(dir) {
127
127
  return {
128
128
  id,
129
129
  name: String(meta.name || id),
130
+ // task-fix (5-bugs): optional localized names + pinyin aliases for
131
+ // bilingual display + @-mention pinyin-prefix matching. Missing fields
132
+ // degrade gracefully to [] / ''.
133
+ nameZh: typeof meta.nameZh === 'string' ? String(meta.nameZh) : '',
134
+ aliases: Array.isArray(meta.aliases)
135
+ ? meta.aliases.map(String).map(s => s.trim()).filter(Boolean)
136
+ : [],
130
137
  role: String(meta.role || ''),
131
138
  traits: Array.isArray(meta.traits) ? meta.traits.map(String) : [],
132
139
  modelHint,
@@ -1130,6 +1130,11 @@ export async function handleUnifyGroupChat(msg) {
1130
1130
  // Per target: emit `group_message` tagged with `speakerVpId` (the VP
1131
1131
  // being addressed — F3's GroupSelector binding consumes this) + dispatch
1132
1132
  // through the Engine via handleUnifyChat with an `@vp-<id>` prompt prefix.
1133
+ //
1134
+ // task-fix: bracket each per-VP dispatch with `vp_typing_start` /
1135
+ // `vp_typing_end` events so the frontend can render a per-speaker typing
1136
+ // dot next to that VP's avatar (matching IM apps). Avoids the old
1137
+ // "one global running cat for N concurrent speakers" ambiguity.
1133
1138
  for (const { vpId, envelope } of captured) {
1134
1139
  try {
1135
1140
  sendUnifyEvent({
@@ -1144,6 +1149,15 @@ export async function handleUnifyGroupChat(msg) {
1144
1149
  });
1145
1150
  } catch { /* never crash WS pipeline */ }
1146
1151
 
1152
+ try {
1153
+ sendUnifyEvent({
1154
+ type: 'vp_typing_start',
1155
+ groupId,
1156
+ vpId,
1157
+ ts: Date.now(),
1158
+ });
1159
+ } catch { /* never crash WS pipeline */ }
1160
+
1147
1161
  try {
1148
1162
  await handleUnifyChat({
1149
1163
  ...msg,
@@ -1154,6 +1168,15 @@ export async function handleUnifyGroupChat(msg) {
1154
1168
  });
1155
1169
  } catch (err) {
1156
1170
  console.warn('[Unify] unify_group_chat: per-vp dispatch failed', vpId, err?.message || err);
1171
+ } finally {
1172
+ try {
1173
+ sendUnifyEvent({
1174
+ type: 'vp_typing_end',
1175
+ groupId,
1176
+ vpId,
1177
+ ts: Date.now(),
1178
+ });
1179
+ } catch { /* never crash WS pipeline */ }
1157
1180
  }
1158
1181
  }
1159
1182
  }