@ynhcj/xiaoyi-channel 0.0.154-next → 0.0.155-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.
@@ -310,6 +310,7 @@ export class XYFileUploadService {
310
310
  objectId,
311
311
  draftId,
312
312
  needPreview: true,
313
+ expireTime: 259200,
313
314
  }),
314
315
  });
315
316
  if (!completeResp.ok) {
@@ -52,7 +52,7 @@ export declare function extractPushId(parts: A2AMessagePart[]): string | null;
52
52
  export declare function extractDeviceType(parts: A2AMessagePart[]): string | null;
53
53
  /**
54
54
  * Extract modelName from message parts.
55
- * Looks for modelName in data parts under variables.memoryVariables.modelName
55
+ * Looks for modelName in data parts under variables.clientVariables.modelName
56
56
  * (same level as systemVariables).
57
57
  */
58
58
  export declare function extractModelName(parts: A2AMessagePart[]): string | null;
@@ -145,13 +145,13 @@ export function extractDeviceType(parts) {
145
145
  }
146
146
  /**
147
147
  * Extract modelName from message parts.
148
- * Looks for modelName in data parts under variables.memoryVariables.modelName
148
+ * Looks for modelName in data parts under variables.clientVariables.modelName
149
149
  * (same level as systemVariables).
150
150
  */
151
151
  export function extractModelName(parts) {
152
152
  for (const part of parts) {
153
153
  if (part.kind === "data" && part.data) {
154
- const modelName = part.data.variables?.memoryVariables?.modelName;
154
+ const modelName = part.data.variables?.clientVariables?.modelName;
155
155
  if (modelName && typeof modelName === "string" && modelName.trim() !== "" && modelName.toLowerCase() !== "none") {
156
156
  return modelName;
157
157
  }
@@ -116,6 +116,10 @@ export function createXYReplyDispatcher(params) {
116
116
  let hasSentResponse = false;
117
117
  let finalSent = false;
118
118
  let accumulatedText = "";
119
+ let accumulatedReasoningHistory = "";
120
+ let lastReasoningText = "";
121
+ let accumulatedReplyHistory = "";
122
+ let lastReplyText = "";
119
123
  const initialRunCrossTaskContext = getCurrentSessionContext()?.runCrossTaskContext;
120
124
  const getRunCrossTaskContext = () => {
121
125
  return getCurrentSessionContext()?.runCrossTaskContext ?? initialRunCrossTaskContext;
@@ -263,7 +267,7 @@ export function createXYReplyDispatcher(params) {
263
267
  taskId: currentTaskId,
264
268
  messageId: currentMessageId,
265
269
  text: "",
266
- append: false,
270
+ append: true,
267
271
  final: true,
268
272
  });
269
273
  finalSent = true;
@@ -304,7 +308,7 @@ export function createXYReplyDispatcher(params) {
304
308
  taskId: currentTaskId,
305
309
  messageId: currentMessageId,
306
310
  text: "任务执行异常,请重试~",
307
- append: false,
311
+ append: true,
308
312
  final: true,
309
313
  errorCode: 99921111,
310
314
  errorMessage: "任务执行异常,请重试",
@@ -404,13 +408,27 @@ export function createXYReplyDispatcher(params) {
404
408
  }
405
409
  try {
406
410
  if (text.length > 0) {
411
+ // 🔑 检测是否是新一轮思考:当前text比上一次短,或不以上次内容开头
412
+ const isNewRound = lastReasoningText.length > 0 &&
413
+ (text.length < lastReasoningText.length || !text.startsWith(lastReasoningText));
414
+ if (isNewRound) {
415
+ // 将上一轮思考追加到历史
416
+ accumulatedReasoningHistory += (accumulatedReasoningHistory ? "\n\n" : "") + lastReasoningText;
417
+ console.log(`[onReasoningStream] new round detected, lastReasoningText: ${lastReasoningText.substring(0, 100)}, text: ${text.substring(0, 100)}`);
418
+ }
419
+ // 更新当前轮最后一次text
420
+ lastReasoningText = text;
421
+ // 🔑 拼接历史 + 当前轮内容
422
+ const fullText = accumulatedReasoningHistory
423
+ ? accumulatedReasoningHistory + "\n\n" + text
424
+ : text;
407
425
  // 🔑 将模型真实的thinking/reasoning内容通过reasoningText转发
408
426
  await sendReasoningTextUpdate({
409
427
  config,
410
428
  sessionId,
411
429
  taskId: currentTaskId,
412
430
  messageId: currentMessageId,
413
- text,
431
+ text: fullText,
414
432
  append: false,
415
433
  });
416
434
  }
@@ -426,9 +444,22 @@ export function createXYReplyDispatcher(params) {
426
444
  }
427
445
  const currentTaskId = getActiveTaskId();
428
446
  const currentMessageId = getActiveMessageId();
429
- const text = payload.text ?? "";
447
+ let text = payload.text ?? "";
430
448
  try {
431
449
  if (text.length > 0) {
450
+ // 🔑 检测是否是新一轮回复:当前text比上一次短,或不以上次内容开头
451
+ const isNewRound = lastReplyText.length > 0 &&
452
+ (text.length < lastReplyText.length || !text.startsWith(lastReplyText));
453
+ if (isNewRound) {
454
+ // 将上一轮回复追加到历史
455
+ accumulatedReplyHistory += (accumulatedReplyHistory ? "\n\n" : "") + lastReplyText;
456
+ }
457
+ // 更新当前轮最后一次text
458
+ lastReplyText = text;
459
+ // 🔑 拼接历史 + 当前轮内容
460
+ const fullText = accumulatedReplyHistory
461
+ ? accumulatedReplyHistory + "\n\n" + text
462
+ : text;
432
463
  accumulatedText += text;
433
464
  hasSentResponse = true;
434
465
  // 🔑 流式文本通过 A2A text 通道发送(而非 reasoningText)
@@ -437,7 +468,7 @@ export function createXYReplyDispatcher(params) {
437
468
  sessionId,
438
469
  taskId: currentTaskId,
439
470
  messageId: currentMessageId,
440
- text,
471
+ text: fullText,
441
472
  append: false,
442
473
  final: false,
443
474
  log: false,
@@ -107,7 +107,7 @@ export function createCheckPluginPrivilegeTool(ctx) {
107
107
  executeMode: "background",
108
108
  intentName: "CheckPlugInPrivilege",
109
109
  intentParam: {
110
- checkIntentName: "CheckPluginPrivilege",
110
+ checkIntentName,
111
111
  permissionId,
112
112
  },
113
113
  needUnlock: false,
@@ -21,7 +21,9 @@ c. htmlLocal 是本地HTML文件路径,会先上传获取预览链接再以卡
21
21
 
22
22
  注意事项:
23
23
  a. 操作超时时间为2分钟(120秒),请勿重复调用此工具,如果超时或失败,最多重试一次
24
- b. 最后要把最终的html的公网地址作为工具执行结果返回回去,要以markdown超链接的形式返回给用户`,
24
+ b. 最后要把最终的html的公网地址作为工具执行结果返回回去,要以markdown超链接的形式返回给用户,必须严格保留完整的url,包含url的鉴权鉴权信息,返回给用户的url必须是完整的
25
+ c. html类型的文件回传给用户优先用这个工具
26
+ d. 如果使用这个工具把html文件回传,则生成的html要尽可能适配用户的设备,如果用户使用的是手机,则尽可能生成竖屏的html的预览效果`,
25
27
  parameters: {
26
28
  type: "object",
27
29
  properties: {
@@ -8,7 +8,7 @@ export interface SessionContext {
8
8
  messageId: string;
9
9
  agentId: string;
10
10
  deviceType?: string;
11
- /** Model name extracted from A2A user variables (variables.memoryVariables.modelName).
11
+ /** Model name extracted from A2A user variables (variables.clientVariables.modelName).
12
12
  * When set, provider.ts replaces model.id in the OpenAI request body. */
13
13
  modelName?: string;
14
14
  runCrossTaskContext?: RunCrossTaskContext;
@@ -71,7 +71,7 @@ export function createXiaoyiGuiTool(ctx) {
71
71
  wsManager.off("gui-agent-response", handler);
72
72
  logger.error("超时: XiaoYi GUI Agent 操作超时(5分钟)", { toolCallId });
73
73
  reject(new Error("XiaoYi GUI Agent 操作超时(5分钟)"));
74
- }, 180000); // 5 minutes timeout
74
+ }, 300000); // 5 minutes timeout
75
75
  // Listen for GUI agent response events
76
76
  const handler = (event) => {
77
77
  // Check if this is the InvokeJarvisGUIAgentResponse we're waiting for
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ynhcj/xiaoyi-channel",
3
- "version": "0.0.154-next",
3
+ "version": "0.0.155-next",
4
4
  "description": "OpenClaw Xiaoyi Channel plugin - Xiaoyi A2A protocol integration",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",