@ynhcj/xiaoyi-channel 0.0.112-next → 0.0.113-next
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/dist/src/bot.js +1 -5
- package/dist/src/provider.js +44 -51
- package/package.json +1 -1
package/dist/src/bot.js
CHANGED
|
@@ -209,10 +209,6 @@ export async function handleXYMessage(params) {
|
|
|
209
209
|
const envelopeOptions = core.channel.reply.resolveEnvelopeFormatOptions(cfg);
|
|
210
210
|
// Build message body with speaker prefix (following feishu pattern)
|
|
211
211
|
let messageBody = textForAgent;
|
|
212
|
-
// Embed A2A taskId marker before the user query so the provider can
|
|
213
|
-
// extract it from messages without relying on AsyncLocalStorage.
|
|
214
|
-
// The provider strips this marker before sending to the model.
|
|
215
|
-
messageBody = `xiaoyiA2A info[taskId:${parsed.taskId},deviceType:${deviceType}] ${messageBody}`;
|
|
216
212
|
// Add speaker prefix for clarity
|
|
217
213
|
const speaker = parsed.sessionId;
|
|
218
214
|
messageBody = `${speaker}: ${messageBody}`;
|
|
@@ -240,7 +236,7 @@ export async function handleXYMessage(params) {
|
|
|
240
236
|
SenderId: parsed.sessionId,
|
|
241
237
|
Provider: "xiaoyi-channel",
|
|
242
238
|
Surface: "xiaoyi-channel",
|
|
243
|
-
MessageSid: parsed.
|
|
239
|
+
MessageSid: `${parsed.taskId}_${deviceType}`,
|
|
244
240
|
Timestamp: Date.now(),
|
|
245
241
|
WasMentioned: false,
|
|
246
242
|
CommandAuthorized: true,
|
package/dist/src/provider.js
CHANGED
|
@@ -388,6 +388,22 @@ function trimUserMetadata(text) {
|
|
|
388
388
|
text = text.replace(/\n*Sender \(untrusted metadata\):\n```json\n[\s\S]*?\n```\n*/, "\n");
|
|
389
389
|
return text.replace(/\n{3,}/g, "\n\n");
|
|
390
390
|
}
|
|
391
|
+
/**
|
|
392
|
+
* Extract A2A taskId and deviceType from Conversation info JSON.
|
|
393
|
+
* bot.ts stores them as MessageSid = "taskId_deviceType".
|
|
394
|
+
*/
|
|
395
|
+
function extractA2AFromConversationInfo(text) {
|
|
396
|
+
const match = text.match(/Conversation info \(untrusted metadata\):\n```json\n([\s\S]*?)\n```/);
|
|
397
|
+
if (!match)
|
|
398
|
+
return null;
|
|
399
|
+
const msgIdMatch = match[1].match(/"message_id"\s*:\s*"([^"]+)"/);
|
|
400
|
+
if (!msgIdMatch)
|
|
401
|
+
return null;
|
|
402
|
+
const parts = msgIdMatch[1].split("_");
|
|
403
|
+
if (parts.length < 2)
|
|
404
|
+
return null;
|
|
405
|
+
return { taskId: parts[0], deviceType: parts[1] };
|
|
406
|
+
}
|
|
391
407
|
export const xiaoyiProvider = {
|
|
392
408
|
id: "xiaoyiprovider",
|
|
393
409
|
label: "Xiaoyi Provider",
|
|
@@ -442,53 +458,30 @@ export const xiaoyiProvider = {
|
|
|
442
458
|
const underlying = ctx.streamFn;
|
|
443
459
|
if (!underlying)
|
|
444
460
|
return underlying;
|
|
445
|
-
// ── Regex to extract A2A taskId/deviceType from user messages ──
|
|
446
|
-
// bot.ts embeds: xiaoyiA2A info[taskId:<id>,deviceType:<type>]
|
|
447
|
-
const A2A_MARKER_RE = /xiaoyiA2A info\[taskId:([^\],]+)(?:,deviceType:([^\]]+))?\]\s*/;
|
|
448
461
|
return async (model, context, options) => {
|
|
449
462
|
const dynamicHeaders = {};
|
|
450
|
-
// ── Extract A2A taskId/deviceType from
|
|
451
|
-
//
|
|
452
|
-
|
|
453
|
-
let
|
|
463
|
+
// ── Extract A2A taskId/deviceType from Conversation info ──
|
|
464
|
+
// bot.ts stores taskId_deviceType as MessageSid, which the framework
|
|
465
|
+
// renders as message_id in the Conversation info JSON block.
|
|
466
|
+
let extractedTaskId = null;
|
|
467
|
+
let extractedDeviceType = null;
|
|
454
468
|
if (context.messages) {
|
|
455
|
-
console.log(`[xiaoyiprovider] user messages BEFORE strip (count=${context.messages.filter(m => m.role === "user").length}):`);
|
|
456
|
-
for (const msg of context.messages) {
|
|
457
|
-
if (msg.role !== "user")
|
|
458
|
-
continue;
|
|
459
|
-
const preview = typeof msg.content === "string"
|
|
460
|
-
? msg.content.slice(0, 200)
|
|
461
|
-
: JSON.stringify(msg.content).slice(0, 200);
|
|
462
|
-
console.log(`[xiaoyiprovider] user: ${preview}`);
|
|
463
|
-
}
|
|
464
469
|
for (let i = context.messages.length - 1; i >= 0; i--) {
|
|
465
470
|
const msg = context.messages[i];
|
|
466
|
-
if (msg.role !== "user"
|
|
471
|
+
if (msg.role !== "user")
|
|
467
472
|
continue;
|
|
468
|
-
const
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
const stripped = extract(msg.content);
|
|
481
|
-
if (stripped !== null)
|
|
482
|
-
msg.content = stripped;
|
|
483
|
-
}
|
|
484
|
-
else if (Array.isArray(msg.content)) {
|
|
485
|
-
for (const block of msg.content) {
|
|
486
|
-
if (block.type === "text" && typeof block.text === "string") {
|
|
487
|
-
const stripped = extract(block.text);
|
|
488
|
-
if (stripped !== null)
|
|
489
|
-
block.text = stripped;
|
|
490
|
-
}
|
|
491
|
-
}
|
|
473
|
+
const text = typeof msg.content === "string"
|
|
474
|
+
? msg.content
|
|
475
|
+
: Array.isArray(msg.content)
|
|
476
|
+
? msg.content.find((b) => b.type === "text")?.text ?? ""
|
|
477
|
+
: "";
|
|
478
|
+
if (!text)
|
|
479
|
+
continue;
|
|
480
|
+
const extracted = extractA2AFromConversationInfo(text);
|
|
481
|
+
if (extracted) {
|
|
482
|
+
extractedTaskId = extracted.taskId;
|
|
483
|
+
extractedDeviceType = extracted.deviceType;
|
|
484
|
+
break;
|
|
492
485
|
}
|
|
493
486
|
}
|
|
494
487
|
}
|
|
@@ -510,9 +503,9 @@ export const xiaoyiProvider = {
|
|
|
510
503
|
dynamicHeaders["x-cron-flag"] = "begin";
|
|
511
504
|
}
|
|
512
505
|
}
|
|
513
|
-
else if (
|
|
514
|
-
// Session mode: taskId extracted from
|
|
515
|
-
const traceId =
|
|
506
|
+
else if (extractedTaskId) {
|
|
507
|
+
// Session mode: taskId extracted from Conversation info
|
|
508
|
+
const traceId = extractedTaskId;
|
|
516
509
|
const sessionId = traceId.split("&")[0];
|
|
517
510
|
const interactionId = traceId.split("&")[1] ?? "";
|
|
518
511
|
const isCron = isCronTriggered(context.messages);
|
|
@@ -524,13 +517,11 @@ export const xiaoyiProvider = {
|
|
|
524
517
|
if (context.messages?.length === 1)
|
|
525
518
|
dynamicHeaders["x-cron-flag"] = "begin";
|
|
526
519
|
}
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
if (typeof interactionId === "string")
|
|
530
|
-
dynamicHeaders[HEADER_INTERACTION_ID] = interactionId;
|
|
520
|
+
dynamicHeaders[HEADER_SESSION_ID] = sessionId;
|
|
521
|
+
dynamicHeaders[HEADER_INTERACTION_ID] = interactionId;
|
|
531
522
|
}
|
|
532
523
|
else {
|
|
533
|
-
//
|
|
524
|
+
// Fallback: use extraParams cached values
|
|
534
525
|
const traceId = ctx.extraParams[HEADER_TRACE_ID];
|
|
535
526
|
const sessionId = ctx.extraParams[HEADER_SESSION_ID];
|
|
536
527
|
const interactionId = ctx.extraParams[HEADER_INTERACTION_ID];
|
|
@@ -547,9 +538,11 @@ export const xiaoyiProvider = {
|
|
|
547
538
|
if (context.systemPrompt) {
|
|
548
539
|
console.log(`[xiaoyiprovider] system prompt length: ${context.systemPrompt.length}`);
|
|
549
540
|
}
|
|
550
|
-
// deviceType: prefer
|
|
541
|
+
// deviceType: prefer value extracted from Conversation info,
|
|
542
|
+
// then extraParams, then ALS fallback.
|
|
551
543
|
const extraParamsDeviceType = ctx.extraParams?.[DEVICE_TYPE_KEY] || undefined;
|
|
552
|
-
const deviceType =
|
|
544
|
+
const deviceType = (extractedDeviceType || extraParamsDeviceType)
|
|
545
|
+
?? getCurrentSessionContext()?.deviceType;
|
|
553
546
|
// 在发送给模型前,优化 systemPrompt 结构
|
|
554
547
|
if (context.systemPrompt) {
|
|
555
548
|
let sp = context.systemPrompt;
|