@yeaft/webchat-agent 0.1.452 → 0.1.454

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.
@@ -30,6 +30,9 @@ export function _detectRouteIntent(text) {
30
30
  /请\s*\S+\s*审查/,
31
31
  /转给\s*\S+/,
32
32
  /发给\s*\S+/,
33
+ /请\s*(?:rev|test)-\d+/i, // 请 rev-1/test-2 (explicit role mention with request)
34
+ /PR\s*#\d+.*(?:请|review|审查)/i, // PR #123 + review request
35
+ /(?:rev|test)-\d+\s*(?:审查|review|check|测试)/i, // rev-1 审查 / test-2 测试
33
36
  /route\s+to\s+\S+/i,
34
37
  /submit\s+to\s+\S+/i,
35
38
  /forward\s+to\s+\S+/i,
@@ -252,11 +255,17 @@ export async function processRoleOutput(session, roleName, roleQuery, roleState)
252
255
  });
253
256
  sendStatusUpdate(session);
254
257
  } else {
255
- // ★ Route intent detection: if no ROUTE block but text suggests routing intent,
256
- // auto-forward to PM so the message doesn't get lost
257
- if (_detectRouteIntent(roleState.lastTurnText) && roleName !== session.decisionMaker) {
258
- console.log(`[Crew] ${roleName} turn ended without ROUTE but has routing intent — auto-forwarding to PM`);
259
- const autoSummary = `[auto-forward: ${roleName} 的输出包含路由意图但缺少 ROUTE 块]\n${(roleState.lastTurnText || '').slice(-500).trim()}`;
258
+ // ★ No ROUTE found decide whether to auto-forward to PM
259
+ const isNonPM = roleName !== session.decisionMaker;
260
+ const hasActiveTask = !!roleState.currentTask;
261
+ const hasRouteIntent = _detectRouteIntent(roleState.lastTurnText);
262
+
263
+ if (isNonPM && (hasActiveTask || hasRouteIntent)) {
264
+ // Non-PM role with active task OR routing intent but no ROUTE block:
265
+ // auto-forward to PM so the message doesn't get lost
266
+ const reason = hasActiveTask ? 'has active task' : 'has routing intent';
267
+ console.log(`[Crew] ${roleName} turn ended without ROUTE (${reason}) — auto-forwarding to PM`);
268
+ const autoSummary = `[auto-forward: ${roleName} turn 结束但未输出 ROUTE 块 (${reason})]\n${(roleState.lastTurnText || '').slice(-800).trim()}`;
260
269
  await executeRoute(session, roleName, {
261
270
  to: session.decisionMaker,
262
271
  summary: autoSummary,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yeaft/webchat-agent",
3
- "version": "0.1.452",
3
+ "version": "0.1.454",
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/unify/engine.js CHANGED
@@ -374,6 +374,7 @@ export class Engine {
374
374
  });
375
375
 
376
376
  const startTime = Date.now();
377
+ let ttfbMs = null; // Time to first token
377
378
  let responseText = '';
378
379
  const toolCalls = [];
379
380
  let stopReason = 'end_turn';
@@ -393,6 +394,7 @@ export class Engine {
393
394
  })) {
394
395
  switch (event.type) {
395
396
  case 'text_delta':
397
+ if (ttfbMs === null) ttfbMs = Date.now() - startTime;
396
398
  responseText += event.text;
397
399
  yield event;
398
400
  break;
@@ -439,6 +441,7 @@ export class Engine {
439
441
  toolCalls: toolCalls.map(tc => ({ id: tc.id, name: tc.name, input: tc.input })),
440
442
  usage: { inputTokens: totalUsage.inputTokens, outputTokens: totalUsage.outputTokens },
441
443
  latencyMs,
444
+ ttfbMs,
442
445
  stopReason: 'error',
443
446
  };
444
447
 
@@ -495,6 +498,7 @@ export class Engine {
495
498
  toolCalls: toolCalls.map(tc => ({ id: tc.id, name: tc.name, input: tc.input })),
496
499
  usage: { inputTokens: totalUsage.inputTokens, outputTokens: totalUsage.outputTokens },
497
500
  latencyMs,
501
+ ttfbMs,
498
502
  stopReason,
499
503
  };
500
504
 
@@ -280,6 +280,7 @@ export async function handleUnifyChat(msg) {
280
280
  toolCalls: event.toolCalls,
281
281
  usage: event.usage,
282
282
  latencyMs: event.latencyMs,
283
+ ttfbMs: event.ttfbMs,
283
284
  stopReason: event.stopReason,
284
285
  });
285
286
  break;