@yeaft/webchat-agent 0.1.436 → 0.1.438
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/connection/index.js +3 -1
- package/connection/message-router.js +7 -0
- package/conversation.js +4 -1
- package/expert-roles.js +36 -0
- package/package.json +1 -1
- package/unify/web-bridge.js +42 -2
package/connection/index.js
CHANGED
|
@@ -332,5 +332,12 @@ export async function handleMessage(msg) {
|
|
|
332
332
|
case 'unify_reset':
|
|
333
333
|
await resetUnifySession();
|
|
334
334
|
break;
|
|
335
|
+
|
|
336
|
+
// Expert roles definition (for ExpertPanel detail view)
|
|
337
|
+
case 'get_expert_roles': {
|
|
338
|
+
const { getExpertRolesDefinition } = await import('../expert-roles.js');
|
|
339
|
+
sendToServer({ type: 'expert_roles_list', roles: getExpertRolesDefinition() });
|
|
340
|
+
break;
|
|
341
|
+
}
|
|
335
342
|
}
|
|
336
343
|
}
|
package/conversation.js
CHANGED
|
@@ -719,7 +719,10 @@ export async function handleUserInput(msg) {
|
|
|
719
719
|
|
|
720
720
|
// ★ Expert Panel: construct expert message if selections provided
|
|
721
721
|
const expertSelections = msg.expertSelections;
|
|
722
|
-
if (
|
|
722
|
+
if (msg.expertMessage) {
|
|
723
|
+
// Custom expert role: frontend already built the full prompt
|
|
724
|
+
effectivePrompt = msg.expertMessage;
|
|
725
|
+
} else if (expertSelections?.length > 0) {
|
|
723
726
|
const { buildExpertMessage } = await import('./expert-roles.js');
|
|
724
727
|
const expertResult = buildExpertMessage(expertSelections, effectivePrompt, msg.language || 'zh-CN');
|
|
725
728
|
effectivePrompt = expertResult.effectivePrompt;
|
package/expert-roles.js
CHANGED
|
@@ -877,4 +877,40 @@ export function buildExpertMessage(selections, userText, language = 'zh-CN') {
|
|
|
877
877
|
return buildMultiExpertMessage(selections, userText, isZh);
|
|
878
878
|
}
|
|
879
879
|
|
|
880
|
+
/**
|
|
881
|
+
* Return the full EXPERT_ROLES definition (including prompt content)
|
|
882
|
+
* for the web debug/admin panel.
|
|
883
|
+
*
|
|
884
|
+
* Format per role:
|
|
885
|
+
* {
|
|
886
|
+
* name, messagePrefix, messagePrefixEn,
|
|
887
|
+
* actions: { [actionId]: { name, nameEn, messageTemplate, messageTemplateEn, defaultMessage, defaultMessageEn } }
|
|
888
|
+
* }
|
|
889
|
+
*
|
|
890
|
+
* @returns {Object.<string, object>}
|
|
891
|
+
*/
|
|
892
|
+
export function getExpertRolesDefinition() {
|
|
893
|
+
const result = {};
|
|
894
|
+
for (const [roleId, roleDef] of Object.entries(EXPERT_ROLES)) {
|
|
895
|
+
const actions = {};
|
|
896
|
+
for (const [actionId, actionDef] of Object.entries(roleDef.actions)) {
|
|
897
|
+
actions[actionId] = {
|
|
898
|
+
name: actionDef.name,
|
|
899
|
+
nameEn: actionDef.nameEn,
|
|
900
|
+
messageTemplate: actionDef.messageTemplate,
|
|
901
|
+
messageTemplateEn: actionDef.messageTemplateEn,
|
|
902
|
+
defaultMessage: actionDef.defaultMessage,
|
|
903
|
+
defaultMessageEn: actionDef.defaultMessageEn,
|
|
904
|
+
};
|
|
905
|
+
}
|
|
906
|
+
result[roleId] = {
|
|
907
|
+
name: roleDef.name,
|
|
908
|
+
messagePrefix: roleDef.messagePrefix,
|
|
909
|
+
messagePrefixEn: roleDef.messagePrefixEn,
|
|
910
|
+
actions,
|
|
911
|
+
};
|
|
912
|
+
}
|
|
913
|
+
return result;
|
|
914
|
+
}
|
|
915
|
+
|
|
880
916
|
export { EXPERT_ROLES };
|
package/package.json
CHANGED
package/unify/web-bridge.js
CHANGED
|
@@ -23,6 +23,9 @@ let session = null;
|
|
|
23
23
|
/** @type {AbortController | null} */
|
|
24
24
|
let currentAbort = null;
|
|
25
25
|
|
|
26
|
+
/** Query timeout in ms — abort if LLM doesn't respond within this window */
|
|
27
|
+
const QUERY_TIMEOUT_MS = 120_000;
|
|
28
|
+
|
|
26
29
|
/** Virtual conversationId for the Unify session */
|
|
27
30
|
let unifyConversationId = null;
|
|
28
31
|
|
|
@@ -100,12 +103,29 @@ export async function handleUnifyChat(msg) {
|
|
|
100
103
|
|
|
101
104
|
currentAbort = new AbortController();
|
|
102
105
|
|
|
106
|
+
// ─── Timeout guard: abort query if LLM hangs beyond threshold ──
|
|
107
|
+
// Resets on every event — fires only after prolonged silence.
|
|
108
|
+
let queryTimer = null;
|
|
109
|
+
const resetQueryTimer = () => {
|
|
110
|
+
if (queryTimer) clearTimeout(queryTimer);
|
|
111
|
+
queryTimer = setTimeout(() => {
|
|
112
|
+
if (currentAbort) {
|
|
113
|
+
console.error(`[Unify] query timeout after ${QUERY_TIMEOUT_MS / 1000}s of silence — aborting`);
|
|
114
|
+
currentAbort.abort();
|
|
115
|
+
}
|
|
116
|
+
}, QUERY_TIMEOUT_MS);
|
|
117
|
+
};
|
|
118
|
+
resetQueryTimer();
|
|
119
|
+
|
|
120
|
+
try {
|
|
103
121
|
// ─── Stream Engine events → claude_output format ──
|
|
104
122
|
for await (const event of session.engine.query({
|
|
105
123
|
prompt,
|
|
106
124
|
mode: currentMode,
|
|
107
125
|
signal: currentAbort.signal,
|
|
108
126
|
})) {
|
|
127
|
+
// Reset timeout on every event — activity means the query is alive
|
|
128
|
+
resetQueryTimer();
|
|
109
129
|
switch (event.type) {
|
|
110
130
|
// ── Text streaming ──
|
|
111
131
|
case 'text_delta':
|
|
@@ -261,9 +281,29 @@ export async function handleUnifyChat(msg) {
|
|
|
261
281
|
result_text: '',
|
|
262
282
|
});
|
|
263
283
|
|
|
284
|
+
} finally {
|
|
285
|
+
// Always clear the timeout guard
|
|
286
|
+
if (queryTimer) clearTimeout(queryTimer);
|
|
287
|
+
}
|
|
288
|
+
|
|
264
289
|
} catch (err) {
|
|
265
|
-
// Don't report abort errors
|
|
266
|
-
if (err.name === 'AbortError')
|
|
290
|
+
// Don't report abort errors — but still send result to unblock frontend
|
|
291
|
+
if (err.name === 'AbortError') {
|
|
292
|
+
sendUnifyOutput({
|
|
293
|
+
type: 'assistant',
|
|
294
|
+
message: {
|
|
295
|
+
content: [{
|
|
296
|
+
type: 'text',
|
|
297
|
+
text: '⚠️ Query timed out — no response from LLM. Please try again.',
|
|
298
|
+
}],
|
|
299
|
+
},
|
|
300
|
+
});
|
|
301
|
+
sendUnifyOutput({
|
|
302
|
+
type: 'result',
|
|
303
|
+
result_text: '',
|
|
304
|
+
});
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
267
307
|
|
|
268
308
|
console.error('[Unify] query error:', err.message);
|
|
269
309
|
sendUnifyOutput({
|