@ynhcj/xiaoyi-channel 0.0.137-next → 0.0.138-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 CHANGED
@@ -270,7 +270,7 @@ export async function handleXYMessage(params) {
270
270
  SenderId: parsed.sessionId,
271
271
  Provider: "xiaoyi-channel",
272
272
  Surface: "xiaoyi-channel",
273
- MessageSid: `${parsed.taskId}_${deviceType}`,
273
+ MessageSid: `xiaoyi_${parsed.taskId}_${deviceType}`,
274
274
  Timestamp: Date.now(),
275
275
  WasMentioned: false,
276
276
  CommandAuthorized: true,
@@ -532,7 +532,7 @@ async function dispatchSteerWhenReady(params) {
532
532
  SenderId: sessionId,
533
533
  Provider: "xiaoyi-channel",
534
534
  Surface: "xiaoyi-channel",
535
- MessageSid: `${params.parsed.taskId}_${params.deviceType}`,
535
+ MessageSid: `xiaoyi_${params.parsed.taskId}_${params.deviceType}`,
536
536
  Timestamp: Date.now(),
537
537
  WasMentioned: false,
538
538
  CommandAuthorized: true,
@@ -236,8 +236,6 @@ const HEADER_SESSION_ID = "x-session-id";
236
236
  const HEADER_INTERACTION_ID = "x-interaction-id";
237
237
  /** Internal key for passing fallback uid prefix from prepareExtraParams to wrapStreamFn. */
238
238
  const FALLBACK_PREFIX_KEY = "_xiaoyi_fallback_prefix";
239
- /** Internal key for passing deviceType from prepareExtraParams to wrapStreamFn. */
240
- const DEVICE_TYPE_KEY = "_xiaoyi_device_type";
241
239
  const SELF_EVOLUTION_PROMPT_BEGIN = "<self_evolution_prompt>";
242
240
  const SELF_EVOLUTION_PROMPT_END = "</self_evolution_prompt>";
243
241
  const SELF_EVOLUTION_ENABLED_PROMPT_SECTION = `
@@ -397,7 +395,9 @@ function trimUserMetadata(text) {
397
395
  }
398
396
  /**
399
397
  * Extract A2A taskId and deviceType from Conversation info JSON.
400
- * bot.ts stores them as MessageSid = "taskId_deviceType".
398
+ * bot.ts stores them as MessageSid = "xiaoyi_taskId_deviceType".
399
+ * The "xiaoyi_" prefix ensures extraction only happens for messages
400
+ * routed through xiaoyi-channel, not other channels sharing the provider.
401
401
  */
402
402
  function extractA2AFromConversationInfo(text) {
403
403
  const match = text.match(/Conversation info \(untrusted metadata\):\n```json\n([\s\S]*?)\n```/);
@@ -407,9 +407,9 @@ function extractA2AFromConversationInfo(text) {
407
407
  if (!msgIdMatch)
408
408
  return null;
409
409
  const parts = msgIdMatch[1].split("_");
410
- if (parts.length < 2)
410
+ if (parts.length < 3 || parts[0] !== "xiaoyi")
411
411
  return null;
412
- return { taskId: parts[0], deviceType: parts[1] };
412
+ return { taskId: parts[1], deviceType: parts[2] };
413
413
  }
414
414
  export const xiaoyiProvider = {
415
415
  id: "xiaoyiprovider",
@@ -418,31 +418,12 @@ export const xiaoyiProvider = {
418
418
  auth: [],
419
419
  isCacheTtlEligible: () => true,
420
420
  /**
421
- * Inject dynamic session params into extraParams so they flow
422
- * through to wrapStreamFn's ctx.extraParams.
423
- *
424
- * Priority:
425
- * 1. Session context (from AsyncLocalStorage, set by bot.ts)
426
- * 2. uid-based fallback: sha256(uid).hex[:32]_timestamp
427
- * 3. No uid available → return undefined (no headers injected)
421
+ * Store uid-based fallback prefix for lazy timestamp generation in wrapStreamFn.
422
+ * Session-level headers (traceId / sessionId / interactionId) are resolved
423
+ * directly in wrapStreamFn via cron detection, Conversation info extraction,
424
+ * or uid fallback.
428
425
  */
429
426
  prepareExtraParams: (ctx) => {
430
- const sessionCtx = getCurrentSessionContext();
431
- if (sessionCtx) {
432
- const taskId = sessionCtx.taskId;
433
- const sessionId = taskId.split("&")[0];
434
- const interactionId = taskId.split("&")[1] || "";
435
- return {
436
- ...ctx.extraParams,
437
- [HEADER_TRACE_ID]: taskId,
438
- [HEADER_SESSION_ID]: sessionId,
439
- [HEADER_INTERACTION_ID]: interactionId,
440
- [DEVICE_TYPE_KEY]: sessionCtx.deviceType ?? "",
441
- };
442
- }
443
- // Fallback: store uid prefix for lazy timestamp generation in wrapStreamFn.
444
- // This ensures each model call gets a fresh timestamp instead of reusing
445
- // the same one across tool-use loops and retries.
446
427
  const uid = getUidFromConfig(ctx.config);
447
428
  if (!uid)
448
429
  return undefined;
@@ -493,68 +474,46 @@ export const xiaoyiProvider = {
493
474
  }
494
475
  }
495
476
  // ── Build dynamic headers ────────────────────────────
496
- if (ctx.extraParams) {
497
- const fallbackPrefix = ctx.extraParams[FALLBACK_PREFIX_KEY];
477
+ // Priority:
478
+ // 1. Cron-triggered: uid → cronUuid, with cron-specific headers
479
+ // 2. Xiaoyi A2A: taskId extracted from Conversation info (xiaoyi_ prefix)
480
+ // 3. UID-based fallback: sha256(uid).hex[:32]_timestamp
481
+ const isCron = isCronTriggered(context.messages);
482
+ if (isCron) {
483
+ const fallbackPrefix = ctx.extraParams?.[FALLBACK_PREFIX_KEY];
498
484
  if (typeof fallbackPrefix === "string") {
499
- // Fallback mode: generate fresh timestamp per request
500
- const isCron = isCronTriggered(context.messages);
501
485
  const fallbackValue = `${fallbackPrefix}_${Date.now()}`;
502
- dynamicHeaders[HEADER_TRACE_ID] = isCron ? `cron_${fallbackValue}` : fallbackValue;
486
+ dynamicHeaders[HEADER_TRACE_ID] = `cron_${fallbackValue}`;
503
487
  dynamicHeaders[HEADER_SESSION_ID] = fallbackValue;
504
488
  dynamicHeaders[HEADER_INTERACTION_ID] = fallbackValue;
505
- if (isCron) {
506
- const cronTitle = extractCronTitle(context.messages);
507
- if (cronTitle)
508
- dynamicHeaders["x-cron-title"] = encodeURIComponent(cronTitle);
509
- if (context.messages?.length === 1)
510
- dynamicHeaders["x-cron-flag"] = "begin";
511
- }
512
- }
513
- else if (extractedTaskId) {
514
- // Session mode: taskId extracted from Conversation info
515
- const traceId = extractedTaskId;
516
- const sessionId = traceId.split("&")[0];
517
- const interactionId = traceId.split("&")[1] ?? "";
518
- const isCron = isCronTriggered(context.messages);
519
- dynamicHeaders[HEADER_TRACE_ID] = isCron ? `cron_${traceId}_${Date.now()}` : traceId;
520
- if (isCron) {
521
- const cronTitle = extractCronTitle(context.messages);
522
- if (cronTitle)
523
- dynamicHeaders["x-cron-title"] = encodeURIComponent(cronTitle);
524
- if (context.messages?.length === 1)
525
- dynamicHeaders["x-cron-flag"] = "begin";
526
- }
527
- dynamicHeaders[HEADER_SESSION_ID] = sessionId;
528
- dynamicHeaders[HEADER_INTERACTION_ID] = interactionId;
529
489
  }
530
490
  else {
531
- // Fallback: use extraParams cached values
532
- const traceId = ctx.extraParams[HEADER_TRACE_ID];
533
- const sessionId = ctx.extraParams[HEADER_SESSION_ID];
534
- const interactionId = ctx.extraParams[HEADER_INTERACTION_ID];
535
- const isCronCached = isCronTriggered(context.messages);
536
- if (isCronCached) {
537
- // Cron: generate fresh sessionId from cron UUID so each invocation
538
- // is independently tracked, regardless of stale activeSessions state.
539
- const cronUuid = extractCronUuid(context.messages) ?? "cron";
540
- const cronSessionId = `cron_${cronUuid}_${Date.now()}`;
541
- dynamicHeaders[HEADER_TRACE_ID] = cronSessionId;
542
- dynamicHeaders[HEADER_SESSION_ID] = cronUuid;
543
- dynamicHeaders[HEADER_INTERACTION_ID] = cronSessionId;
544
- const cronTitle = extractCronTitle(context.messages);
545
- if (cronTitle)
546
- dynamicHeaders["x-cron-title"] = encodeURIComponent(cronTitle);
547
- if (context.messages?.length === 1)
548
- dynamicHeaders["x-cron-flag"] = "begin";
549
- }
550
- else {
551
- if (typeof traceId === "string")
552
- dynamicHeaders[HEADER_TRACE_ID] = traceId;
553
- if (typeof sessionId === "string")
554
- dynamicHeaders[HEADER_SESSION_ID] = sessionId;
555
- if (typeof interactionId === "string")
556
- dynamicHeaders[HEADER_INTERACTION_ID] = interactionId;
557
- }
491
+ const cronUuid = extractCronUuid(context.messages) ?? "cron";
492
+ const cronSessionId = `cron_${cronUuid}_${Date.now()}`;
493
+ dynamicHeaders[HEADER_TRACE_ID] = cronSessionId;
494
+ dynamicHeaders[HEADER_SESSION_ID] = cronUuid;
495
+ dynamicHeaders[HEADER_INTERACTION_ID] = cronSessionId;
496
+ }
497
+ const cronTitle = extractCronTitle(context.messages);
498
+ if (cronTitle)
499
+ dynamicHeaders["x-cron-title"] = encodeURIComponent(cronTitle);
500
+ if (context.messages?.length === 1)
501
+ dynamicHeaders["x-cron-flag"] = "begin";
502
+ }
503
+ else if (extractedTaskId) {
504
+ const sessionId = extractedTaskId.split("&")[0];
505
+ const interactionId = extractedTaskId.split("&")[1] ?? "";
506
+ dynamicHeaders[HEADER_TRACE_ID] = extractedTaskId;
507
+ dynamicHeaders[HEADER_SESSION_ID] = sessionId;
508
+ dynamicHeaders[HEADER_INTERACTION_ID] = interactionId;
509
+ }
510
+ else {
511
+ const fallbackPrefix = ctx.extraParams?.[FALLBACK_PREFIX_KEY];
512
+ if (typeof fallbackPrefix === "string") {
513
+ const fallbackValue = `${fallbackPrefix}_${Date.now()}`;
514
+ dynamicHeaders[HEADER_TRACE_ID] = fallbackValue;
515
+ dynamicHeaders[HEADER_SESSION_ID] = fallbackValue;
516
+ dynamicHeaders[HEADER_INTERACTION_ID] = fallbackValue;
558
517
  }
559
518
  }
560
519
  // 记录输入
@@ -568,9 +527,8 @@ export const xiaoyiProvider = {
568
527
  logger.log(`[xiaoyiprovider] system prompt length: ${context.systemPrompt.length}`);
569
528
  }
570
529
  // deviceType: prefer value extracted from Conversation info,
571
- // then extraParams, then ALS fallback.
572
- const extraParamsDeviceType = ctx.extraParams?.[DEVICE_TYPE_KEY] || undefined;
573
- const deviceType = (extractedDeviceType || extraParamsDeviceType)
530
+ // then ALS fallback.
531
+ const deviceType = extractedDeviceType
574
532
  ?? getCurrentSessionContext()?.deviceType;
575
533
  // 在发送给模型前,优化 systemPrompt 结构
576
534
  if (context.systemPrompt) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ynhcj/xiaoyi-channel",
3
- "version": "0.0.137-next",
3
+ "version": "0.0.138-next",
4
4
  "description": "OpenClaw Xiaoyi Channel plugin - Xiaoyi A2A protocol integration",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",