@ynhcj/xiaoyi-channel 0.0.149-beta → 0.0.151-beta

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.
Files changed (76) hide show
  1. package/dist/index.js +3 -69
  2. package/dist/src/approval-bridge.d.ts +48 -0
  3. package/dist/src/approval-bridge.js +382 -0
  4. package/dist/src/bot.js +64 -68
  5. package/dist/src/client.js +13 -23
  6. package/dist/src/cspl/call_api.d.ts +2 -0
  7. package/dist/src/cspl/call_api.js +107 -0
  8. package/dist/src/cspl/config.d.ts +4 -17
  9. package/dist/src/cspl/config.js +80 -70
  10. package/dist/src/cspl/configs.json +10 -0
  11. package/dist/src/cspl/constants.d.ts +46 -24
  12. package/dist/src/cspl/constants.js +41 -16
  13. package/dist/src/cspl/sentinel_hook.d.ts +2 -0
  14. package/dist/src/cspl/sentinel_hook.js +84 -0
  15. package/dist/src/cspl/steer-context.js +1 -1
  16. package/dist/src/cspl/upload_file.d.ts +1 -0
  17. package/dist/src/cspl/upload_file.js +211 -0
  18. package/dist/src/cspl/utils.d.ts +11 -2
  19. package/dist/src/cspl/utils.js +265 -15
  20. package/dist/src/formatter.js +92 -37
  21. package/dist/src/monitor.js +18 -21
  22. package/dist/src/outbound.js +8 -9
  23. package/dist/src/push.js +8 -15
  24. package/dist/src/reply-dispatcher.js +39 -48
  25. package/dist/src/self-evolution-handler.js +1 -1
  26. package/dist/src/sensitive-redactor.d.ts +4 -0
  27. package/dist/src/sensitive-redactor.js +364 -0
  28. package/dist/src/task-manager.js +6 -10
  29. package/dist/src/tools/agent-as-skill-tool.d.ts +7 -0
  30. package/dist/src/tools/agent-as-skill-tool.js +138 -0
  31. package/dist/src/tools/calendar-tool.js +1 -1
  32. package/dist/src/tools/call-device-tool.js +3 -0
  33. package/dist/src/tools/call-phone-tool.js +1 -1
  34. package/dist/src/tools/create-alarm-tool.js +1 -1
  35. package/dist/src/tools/create-all-tools.js +5 -1
  36. package/dist/src/tools/delete-alarm-tool.js +1 -1
  37. package/dist/src/tools/find-pc-devices-tool.d.ts +2 -1
  38. package/dist/src/tools/find-pc-devices-tool.js +84 -88
  39. package/dist/src/tools/get-device-file-tool-schema.js +3 -2
  40. package/dist/src/tools/image-reading-tool.js +4 -4
  41. package/dist/src/tools/location-tool.js +1 -1
  42. package/dist/src/tools/modify-alarm-tool.js +1 -1
  43. package/dist/src/tools/modify-note-tool.js +1 -1
  44. package/dist/src/tools/note-tool.js +1 -1
  45. package/dist/src/tools/query-app-message-tool.js +1 -1
  46. package/dist/src/tools/query-memory-data-tool.js +1 -1
  47. package/dist/src/tools/query-todo-task-tool.js +1 -1
  48. package/dist/src/tools/save-file-to-phone-tool.js +1 -1
  49. package/dist/src/tools/save-media-to-gallery-tool.js +1 -1
  50. package/dist/src/tools/search-alarm-tool.js +1 -1
  51. package/dist/src/tools/search-calendar-tool.js +1 -1
  52. package/dist/src/tools/search-contact-tool.js +1 -1
  53. package/dist/src/tools/search-email-tool.js +1 -1
  54. package/dist/src/tools/search-file-tool.js +11 -8
  55. package/dist/src/tools/search-message-tool.js +1 -1
  56. package/dist/src/tools/search-note-tool.js +1 -1
  57. package/dist/src/tools/search-photo-gallery-tool.js +1 -1
  58. package/dist/src/tools/send-email-tool.js +1 -1
  59. package/dist/src/tools/send-file-to-user-tool.js +2 -2
  60. package/dist/src/tools/send-message-tool.js +1 -1
  61. package/dist/src/tools/session-manager.js +5 -0
  62. package/dist/src/tools/upload-file-tool.js +15 -5
  63. package/dist/src/tools/upload-photo-tool.js +1 -1
  64. package/dist/src/tools/xiaoyi-add-collection-tool.js +1 -1
  65. package/dist/src/tools/xiaoyi-collection-tool.js +1 -1
  66. package/dist/src/tools/xiaoyi-delete-collection-tool.js +1 -1
  67. package/dist/src/tools/xiaoyi-gui-tool.js +1 -1
  68. package/dist/src/trigger-handler.js +4 -7
  69. package/dist/src/utils/config-manager.js +3 -6
  70. package/dist/src/utils/logger.d.ts +8 -0
  71. package/dist/src/utils/logger.js +69 -34
  72. package/dist/src/utils/pushdata-manager.js +1 -5
  73. package/dist/src/utils/pushid-manager.js +1 -2
  74. package/dist/src/utils/runtime-manager.js +1 -4
  75. package/dist/src/websocket.js +37 -25
  76. package/package.json +1 -1
@@ -51,7 +51,7 @@ export async function monitorXYProvider(opts = {}) {
51
51
  }
52
52
  : undefined;
53
53
  // 🔍 Diagnose WebSocket managers before gateway start
54
- logger.log("🔍 [DIAGNOSTICS] Checking WebSocket managers before gateway start...");
54
+ logger.log("[DIAGNOSTICS] Checking WebSocket managers before gateway start...");
55
55
  diagnoseAllManagers();
56
56
  // Get WebSocket manager (cached)
57
57
  const wsManager = getXYWebSocketManager(account, runtime);
@@ -77,12 +77,12 @@ export async function monitorXYProvider(opts = {}) {
77
77
  // Event handlers (defined early so they can be referenced in cleanup)
78
78
  const messageHandler = (message, sessionId, serverId) => {
79
79
  const messageKey = `${sessionId}::${message.id}`;
80
- logger.log(`[MONITOR-HANDLER] ####### messageHandler triggered: sessionId=${sessionId}, messageId=${message.id} #######`);
80
+ logger.log(`[MONITOR-HANDLER] messageHandler triggered: messageId=${message.id}`);
81
81
  // ✅ Report health: received a message
82
82
  trackEvent?.();
83
83
  // Check for duplicate message handling
84
84
  if (activeMessages.has(messageKey)) {
85
- logger.error(`[MONITOR-HANDLER] ⚠️ WARNING: Duplicate message detected! messageKey=${messageKey}, this may cause duplicate dispatchers!`);
85
+ logger.error(`[MONITOR-HANDLER] WARNING: Duplicate message detected, messageKey=${messageKey}`);
86
86
  }
87
87
  activeMessages.add(messageKey);
88
88
  const task = async () => {
@@ -119,8 +119,7 @@ export async function monitorXYProvider(opts = {}) {
119
119
  const hasActiveRun = hasActiveTask(parsed.sessionId);
120
120
  if (steerMode && hasActiveRun) {
121
121
  // Steer模式且有活跃任务:不入队列,直接并发执行
122
- logger.log(`[MONITOR-HANDLER] 🔄 STEER MODE: Executing concurrently for messageKey=${messageKey}`);
123
- logger.log(`[MONITOR-HANDLER] - sessionId: ${parsed.sessionId}`);
122
+ logger.log(`[MONITOR-HANDLER] STEER MODE: Executing concurrently for messageKey=${messageKey}`);
124
123
  void task().catch((err) => {
125
124
  logger.error(`XY gateway: concurrent steer task failed for ${messageKey}: ${String(err)}`);
126
125
  activeMessages.delete(messageKey);
@@ -129,7 +128,7 @@ export async function monitorXYProvider(opts = {}) {
129
128
  else {
130
129
  // 正常模式:入队列串行执行
131
130
  void enqueue(sessionId, task).catch((err) => {
132
- logger.error(`XY gateway: queue processing failed for session ${sessionId}: ${String(err)}`);
131
+ logger.error(`XY gateway: queue processing failed: ${String(err)}`);
133
132
  activeMessages.delete(messageKey);
134
133
  });
135
134
  }
@@ -138,7 +137,7 @@ export async function monitorXYProvider(opts = {}) {
138
137
  // 解析失败,回退到正常队列模式
139
138
  logger.error(`[MONITOR-HANDLER] Failed to parse message for steer detection: ${String(parseErr)}`);
140
139
  void enqueue(sessionId, task).catch((err) => {
141
- logger.error(`XY gateway: queue processing failed for session ${sessionId}: ${String(err)}`);
140
+ logger.error(`XY gateway: queue processing failed: ${String(err)}`);
142
141
  activeMessages.delete(messageKey);
143
142
  });
144
143
  }
@@ -164,9 +163,7 @@ export async function monitorXYProvider(opts = {}) {
164
163
  logger.error(`XY gateway: ${serverId} error: ${String(err)}`);
165
164
  };
166
165
  const triggerEventHandler = (context) => {
167
- logger.log(`[MONITOR] 📌 Received trigger-event, dispatching to handler...`);
168
- logger.log(`[MONITOR] - sessionId: ${context.sessionId}`);
169
- logger.log(`[MONITOR] - taskId: ${context.taskId}`);
166
+ logger.log(`[MONITOR] Received trigger-event, dispatching to handler...`);
170
167
  // 异步处理 Trigger 事件,不阻塞主流程
171
168
  handleTriggerEvent(context, cfg, runtime, accountId).catch((err) => {
172
169
  logger.error(`[MONITOR] Failed to handle trigger-event:`, err);
@@ -189,13 +186,13 @@ export async function monitorXYProvider(opts = {}) {
189
186
  const cleanup = () => {
190
187
  logger.log("XY gateway: cleaning up...");
191
188
  // 🔍 Diagnose before cleanup
192
- logger.log("🔍 [DIAGNOSTICS] Checking WebSocket managers before cleanup...");
189
+ logger.log("[DIAGNOSTICS] Checking WebSocket managers before cleanup...");
193
190
  diagnoseAllManagers();
194
191
  // Stop health check interval
195
192
  if (healthCheckInterval) {
196
193
  clearInterval(healthCheckInterval);
197
194
  healthCheckInterval = null;
198
- logger.log("⏸️ Stopped periodic health check");
195
+ logger.log("Stopped periodic health check");
199
196
  }
200
197
  // Remove event handlers to prevent duplicate calls on gateway restart
201
198
  wsManager.off("message", messageHandler);
@@ -215,9 +212,9 @@ export async function monitorXYProvider(opts = {}) {
215
212
  cleanupAllSessions();
216
213
  loggedServers.clear();
217
214
  activeMessages.clear();
218
- logger.log(`[MONITOR-HANDLER] 🧹 Cleanup complete, cleared active messages and sessions`);
215
+ logger.log(`[MONITOR-HANDLER] Cleanup complete, cleared active messages and sessions`);
219
216
  // 🔍 Diagnose after cleanup
220
- logger.log("🔍 [DIAGNOSTICS] Checking WebSocket managers after cleanup...");
217
+ logger.log("[DIAGNOSTICS] Checking WebSocket managers after cleanup...");
221
218
  diagnoseAllManagers();
222
219
  };
223
220
  const handleAbort = async () => {
@@ -228,7 +225,7 @@ export async function monitorXYProvider(opts = {}) {
228
225
  if (activeBindings.length > 0) {
229
226
  const config = resolveXYConfig(cfg);
230
227
  const notificationText = "Gateway即将重启,重启期间可能短暂出现\u201c环境异常\u201d提示,请稍候并耐心重试~";
231
- logger.log(`[MONITOR] 📤 Sending restart notifications to ${activeBindings.length} active session(s)`);
228
+ logger.log(`[MONITOR] Sending restart notifications to ${activeBindings.length} active session(s)`);
232
229
  const sendPromises = activeBindings.map(binding => sendA2AResponse({
233
230
  config,
234
231
  sessionId: binding.sessionId,
@@ -238,10 +235,10 @@ export async function monitorXYProvider(opts = {}) {
238
235
  append: false,
239
236
  final: true,
240
237
  }).catch(err => {
241
- logger.error(`[MONITOR] Failed to send restart notification to session ${binding.sessionId}: ${String(err)}`);
238
+ logger.error(`[MONITOR] Failed to send restart notification: ${String(err)}`);
242
239
  }));
243
240
  await Promise.all(sendPromises);
244
- logger.log(`[MONITOR] Restart notifications sent to ${activeBindings.length} session(s)`);
241
+ logger.log(`[MONITOR] Restart notifications sent to ${activeBindings.length} session(s)`);
245
242
  }
246
243
  else {
247
244
  logger.log(`[MONITOR] No active sessions, skipping restart notifications`);
@@ -270,20 +267,20 @@ export async function monitorXYProvider(opts = {}) {
270
267
  wsManager.on("self-evolution-state-get-event", selfEvolutionStateGetHandler);
271
268
  wsManager.on("login-token-event", loginTokenEventHandler);
272
269
  // Start periodic health check (every 6 hours)
273
- logger.log("🏥 Starting periodic health check (every 6 hours)...");
270
+ logger.log("Starting periodic health check (every 6 hours)...");
274
271
  healthCheckInterval = setInterval(() => {
275
- logger.log("🏥 [HEALTH CHECK] Periodic WebSocket diagnostics...");
272
+ logger.log("[HEALTH CHECK] Periodic WebSocket diagnostics...");
276
273
  diagnoseAllManagers();
277
274
  // Auto-cleanup orphan connections
278
275
  const cleaned = cleanupOrphanConnections();
279
276
  if (cleaned > 0) {
280
- logger.log(`🧹 [HEALTH CHECK] Auto-cleaned ${cleaned} manager(s) with orphan connections`);
277
+ logger.log(`[HEALTH CHECK] Auto-cleaned ${cleaned} manager(s) with orphan connections`);
281
278
  }
282
279
  // Cleanup stale sessions (older than 10min TTL)
283
280
  const cleanedSessions = cleanupStaleSessions();
284
281
  const remainingSessions = getActiveSessionCount();
285
282
  if (cleanedSessions > 0 || remainingSessions > 0) {
286
- logger.log(`🧹 [HEALTH CHECK] Sessions: cleaned=${cleanedSessions}, active=${remainingSessions}`);
283
+ logger.log(`[HEALTH CHECK] Sessions: cleaned=${cleanedSessions}, active=${remainingSessions}`);
287
284
  }
288
285
  // Cleanup stale temp files (older than 24 hours)
289
286
  void cleanupStaleTempFiles();
@@ -106,10 +106,10 @@ export const xyOutbound = {
106
106
  let pushDataId;
107
107
  try {
108
108
  pushDataId = await savePushData(text);
109
- logger.log(`[xyOutbound.sendText] Push data saved with ID: ${pushDataId.substring(0, 20)}`);
109
+ logger.log(`[xyOutbound.sendText] Push data saved with ID: ${pushDataId.substring(0, 20)}`);
110
110
  }
111
111
  catch (error) {
112
- logger.error(`[xyOutbound.sendText] Failed to save push data:`, error);
112
+ logger.error(`[xyOutbound.sendText] Failed to save push data:`, error);
113
113
  // 如果持久化失败,仍然继续发送(不阻塞主流程)
114
114
  pushDataId = "";
115
115
  }
@@ -118,14 +118,14 @@ export const xyOutbound = {
118
118
  let pushIdList = [];
119
119
  try {
120
120
  pushIdList = await getAllPushIds();
121
- logger.log(`[xyOutbound.sendText] Loaded ${pushIdList.length} pushIds`);
121
+ logger.log(`[xyOutbound.sendText] Loaded ${pushIdList.length} pushIds`);
122
122
  }
123
123
  catch (error) {
124
- logger.error(`[xyOutbound.sendText] Failed to load pushIds:`, error);
124
+ logger.error(`[xyOutbound.sendText] Failed to load pushIds:`, error);
125
125
  }
126
126
  // 3. 如果 pushIdList 为空,回退到原有逻辑(使用 config pushId)
127
127
  if (pushIdList.length === 0) {
128
- logger.log(`[xyOutbound.sendText] ⚠️ No pushIds found, falling back to config pushId`);
128
+ logger.log(`[xyOutbound.sendText] No pushIds found, falling back to config pushId`);
129
129
  pushIdList = [config.pushId];
130
130
  }
131
131
  // Create push service
@@ -135,7 +135,7 @@ export const xyOutbound = {
135
135
  // Truncate push content to max length 1000
136
136
  const pushText = text.length > 1000 ? text.slice(0, 1000) : text;
137
137
  // 4. 遍历所有 pushId,依次发送推送通知
138
- logger.log(`[xyOutbound.sendText] 📤 Broadcasting to ${pushIdList.length} pushId(s)...`);
138
+ logger.log(`[xyOutbound.sendText] Broadcasting to ${pushIdList.length} pushId(s)...`);
139
139
  let successCount = 0;
140
140
  let failureCount = 0;
141
141
  for (const pushId of pushIdList) {
@@ -143,11 +143,11 @@ export const xyOutbound = {
143
143
  // 传入 pushId 和 pushDataId,使用 kind="data" 格式
144
144
  await pushService.sendPush(pushText, title, undefined, actualTo, pushDataId, pushId);
145
145
  successCount++;
146
- logger.log(`[xyOutbound.sendText] Sent successfully to pushId: ${pushId.substring(0, 20)}...`);
146
+ logger.log(`[xyOutbound.sendText] Sent successfully to pushId: ${pushId.substring(0, 20)}...`);
147
147
  }
148
148
  catch (error) {
149
149
  failureCount++;
150
- logger.error(`[xyOutbound.sendText] Failed to send to pushId: ${pushId.substring(0, 20)}...`, error);
150
+ logger.error(`[xyOutbound.sendText] Failed to send to pushId: ${pushId.substring(0, 20)}...`, error);
151
151
  // 单个 pushId 发送失败不影响其他,继续处理下一个
152
152
  }
153
153
  }
@@ -184,7 +184,6 @@ export const xyOutbound = {
184
184
  }
185
185
  logger.log(`[xyOutbound.sendMedia] File uploaded:`, {
186
186
  fileId,
187
- sessionId,
188
187
  taskId,
189
188
  });
190
189
  // Get filename and mime type from mediaUrl
package/dist/src/push.js CHANGED
@@ -34,8 +34,7 @@ export class XYPushService {
34
34
  const traceId = this.generateTraceId();
35
35
  // Use provided pushId or fall back to config pushId
36
36
  const actualPushId = pushId || this.config.pushId;
37
- logger.log(`[PUSH] 📤 Preparing to send push message`);
38
- logger.log(`[PUSH] - Using pushId: ${actualPushId.substring(0, 20)}...`);
37
+ logger.log(`[PUSH] Preparing to send push message with pushId: ${actualPushId.substring(0, 20)}...`);
39
38
  try {
40
39
  const requestBody = {
41
40
  jsonrpc: "2.0",
@@ -81,12 +80,10 @@ export class XYPushService {
81
80
  body: JSON.stringify(requestBody),
82
81
  });
83
82
  // Log response status and headers
84
- logger.log(`[PUSH] 📥 Response received`);
85
- logger.log(`[PUSH] - HTTP Status: ${response.status} ${response.statusText}`);
83
+ logger.log(`[PUSH] Response received, HTTP Status: ${response.status} ${response.statusText}`);
86
84
  if (!response.ok) {
87
85
  const errorText = await response.text();
88
- logger.error(`[PUSH] Push request failed`);
89
- logger.error(`[PUSH] - HTTP Status: ${response.status}`);
86
+ logger.error(`[PUSH] Push request failed, HTTP Status: ${response.status}`);
90
87
  throw new Error(`Push failed: HTTP ${response.status} - ${errorText}`);
91
88
  }
92
89
  // Try to parse JSON response with detailed error handling
@@ -94,7 +91,7 @@ export class XYPushService {
94
91
  try {
95
92
  const responseText = await response.text();
96
93
  if (!responseText || responseText.trim() === '') {
97
- logger.error(`[PUSH] ⚠️ Received empty response body`);
94
+ logger.error(`[PUSH] Received empty response body`);
98
95
  result = {};
99
96
  }
100
97
  else {
@@ -102,21 +99,17 @@ export class XYPushService {
102
99
  }
103
100
  }
104
101
  catch (parseError) {
105
- logger.error(`[PUSH] Failed to parse JSON response`);
106
- logger.error(`[PUSH] - Parse error: ${parseError instanceof Error ? parseError.message : String(parseError)}`);
102
+ logger.error(`[PUSH] Failed to parse JSON response: ${parseError instanceof Error ? parseError.message : String(parseError)}`);
107
103
  throw new Error(`Invalid JSON response from push service: ${parseError instanceof Error ? parseError.message : String(parseError)}`);
108
104
  }
109
- logger.log(`[PUSH] Push message sent successfully`);
110
- logger.log(`[PUSH] - Trace ID: ${traceId}`);
105
+ logger.log(`[PUSH] Push message sent successfully, Trace ID: ${traceId}`);
111
106
  }
112
107
  catch (error) {
113
- logger.error(`[PUSH] ❌ Failed to send push message`);
114
108
  if (error instanceof Error) {
115
- logger.error(`[PUSH] - Error name: ${error.name}`);
116
- logger.error(`[PUSH] - Error message: ${error.message}`);
109
+ logger.error(`[PUSH] Failed to send push message: ${error.name} - ${error.message}`);
117
110
  }
118
111
  else {
119
- logger.error(`[PUSH] - Error:`, error);
112
+ logger.error(`[PUSH] Failed to send push message:`, error);
120
113
  }
121
114
  throw error;
122
115
  }
@@ -32,11 +32,11 @@ export async function cleanupStaleTempFiles(tempDir = "/tmp/xy_channel") {
32
32
  }
33
33
  }
34
34
  if (cleanedCount > 0) {
35
- logger.log(`[CLEANUP] 🧹 Cleaned ${cleanedCount} stale files (>${TEMP_FILE_TTL_MS / 1000 / 3600}h) from ${tempDir}`);
35
+ logger.log(`[CLEANUP] Cleaned ${cleanedCount} stale files (>${TEMP_FILE_TTL_MS / 1000 / 3600}h) from ${tempDir}`);
36
36
  }
37
37
  }
38
38
  catch (err) {
39
- logger.error(`[CLEANUP] Failed to cleanup temp dir:`, err);
39
+ logger.error(`[CLEANUP] Failed to cleanup temp dir:`, err);
40
40
  }
41
41
  }
42
42
  /**
@@ -46,21 +46,19 @@ export async function cleanupStaleTempFiles(tempDir = "/tmp/xy_channel") {
46
46
  */
47
47
  export function createXYReplyDispatcher(params) {
48
48
  const { cfg, runtime, sessionId, taskId, messageId, accountId, steerState } = params;
49
- logger.log(`[DISPATCHER-CREATE] ******* Creating dispatcher *******`);
50
- logger.log(`[DISPATCHER-CREATE] - taskId: ${taskId}`);
51
49
  // 初始taskId和messageId(作为fallback)
52
50
  const initialTaskId = taskId;
53
51
  const initialMessageId = messageId;
54
- /**
55
- * 🔑 核心改造:动态获取当前活跃的taskId和messageId
56
- * 每次需要taskId时,都从TaskManager获取最新值
57
- */
58
52
  const getActiveTaskId = () => {
59
53
  return getCurrentTaskId(sessionId) ?? initialTaskId;
60
54
  };
61
55
  const getActiveMessageId = () => {
62
56
  return getCurrentMessageId(sessionId) ?? initialMessageId;
63
57
  };
58
+ // Create a scoped logger that always uses this session's sessionId
59
+ // and dynamically resolves the latest taskId
60
+ const scopedLog = () => logger.withContext(sessionId, getActiveTaskId());
61
+ scopedLog().log(`[DISPATCHER-CREATE] Creating dispatcher`);
64
62
  const core = getXYRuntime();
65
63
  const config = resolveXYConfig(cfg);
66
64
  // Simplified prefix context for single-account Xiaoyi channel
@@ -77,14 +75,12 @@ export function createXYReplyDispatcher(params) {
77
75
  * Start the status update interval
78
76
  */
79
77
  const startStatusInterval = () => {
80
- logger.log(`[STATUS INTERVAL] Starting interval for session ${sessionId}`);
78
+ scopedLog().log(`[STATUS-INTERVAL] Starting interval`);
81
79
  statusUpdateInterval = setInterval(() => {
82
80
  // 🔑 使用动态taskId
83
81
  const currentTaskId = getActiveTaskId();
84
82
  const currentMessageId = getActiveMessageId();
85
- logger.log(`[STATUS INTERVAL] Triggering status update`);
86
- logger.log(`[STATUS INTERVAL] - sessionId: ${sessionId}`);
87
- logger.log(`[STATUS INTERVAL] - currentTaskId: ${currentTaskId}`);
83
+ scopedLog().log(`[STATUS-INTERVAL] Triggering status update, taskId=${currentTaskId}`);
88
84
  void sendStatusUpdate({
89
85
  config,
90
86
  sessionId,
@@ -93,13 +89,13 @@ export function createXYReplyDispatcher(params) {
93
89
  text: "任务正在处理中,请稍候~",
94
90
  state: "working",
95
91
  }).catch((err) => {
96
- logger.error(`Failed to send status update:`, err);
92
+ scopedLog().error(`Failed to send status update:`, err);
97
93
  });
98
94
  }, 30000); // 30 seconds
99
95
  };
100
96
  const stopStatusInterval = () => {
101
97
  if (statusUpdateInterval) {
102
- logger.log(`[STATUS INTERVAL] Stopping interval for session ${sessionId}`);
98
+ scopedLog().log(`[STATUS-INTERVAL] Stopping interval`);
103
99
  clearInterval(statusUpdateInterval);
104
100
  statusUpdateInterval = null;
105
101
  }
@@ -110,26 +106,26 @@ export function createXYReplyDispatcher(params) {
110
106
  humanDelay: core.channel.reply.resolveHumanDelayConfig(cfg, accountId),
111
107
  onReplyStart: () => {
112
108
  const currentTaskId = getActiveTaskId();
113
- logger.log(`[REPLY START] Reply started for session ${sessionId}, taskId=${currentTaskId}, steered=${steerState.steered}`);
109
+ scopedLog().log(`[REPLY-START] Reply started, taskId=${currentTaskId}, steered=${steerState.steered}`);
114
110
  },
115
111
  deliver: async (payload, info) => {
116
112
  // 🔑 steered dispatch不发送内容(让主dispatcher处理)
117
113
  if (steerState.steered) {
118
- logger.log(`[DELIVER] Steered dispatch - skipping deliver, info.kind=${info?.kind}`);
114
+ scopedLog().log(`[DELIVER] Steered dispatch, skipping, kind=${info?.kind}`);
119
115
  return;
120
116
  }
121
117
  const text = payload.text ?? "";
122
118
  const currentTaskId = getActiveTaskId();
123
119
  const currentMessageId = getActiveMessageId();
124
- logger.log(`[DELIVER] sessionId=${sessionId}, taskId=${currentTaskId}, info.kind=${info?.kind}, text.length=${text.length}`);
120
+ scopedLog().log(`[DELIVER] kind=${info?.kind}, text.length=${text.length}`);
125
121
  try {
126
122
  if (!text.trim()) {
127
- logger.log(`[DELIVER SKIP] Empty text, skipping`);
123
+ scopedLog().log(`[DELIVER SKIP] Empty text, skipping`);
128
124
  return;
129
125
  }
130
126
  accumulatedText += text;
131
127
  hasSentResponse = true;
132
- logger.log(`[DELIVER ACCUMULATE] Accumulated text, current length=${accumulatedText.length}`);
128
+ scopedLog().log(`[DELIVER] Accumulated text, length=${accumulatedText.length}`);
133
129
  // 🔑 使用动态taskId发送reasoningText更新
134
130
  await sendReasoningTextUpdate({
135
131
  config,
@@ -138,10 +134,10 @@ export function createXYReplyDispatcher(params) {
138
134
  messageId: currentMessageId,
139
135
  text,
140
136
  });
141
- logger.log(`[DELIVER] Sent deliver text as reasoningText update`);
137
+ scopedLog().log(`[DELIVER] Sent deliver text as reasoningText update`);
142
138
  }
143
139
  catch (deliverError) {
144
- logger.error(`Failed to deliver message:`, deliverError);
140
+ scopedLog().error(`Failed to deliver message:`, deliverError);
145
141
  }
146
142
  },
147
143
  onError: async (err, info) => {
@@ -149,7 +145,7 @@ export function createXYReplyDispatcher(params) {
149
145
  stopStatusInterval();
150
146
  // 🔑 steered dispatcher不发送错误状态(让主dispatcher处理)
151
147
  if (steerState.steered) {
152
- logger.log(`[ON_ERROR] Steered dispatch - skipping error response`);
148
+ scopedLog().log(`[ON-ERROR] Steered dispatch, skipping error response`);
153
149
  return;
154
150
  }
155
151
  if (!hasSentResponse) {
@@ -166,28 +162,23 @@ export function createXYReplyDispatcher(params) {
166
162
  });
167
163
  }
168
164
  catch (statusError) {
169
- logger.error(`Failed to send error status:`, statusError);
165
+ scopedLog().error(`Failed to send error status:`, statusError);
170
166
  }
171
167
  }
172
168
  },
173
169
  onIdle: async () => {
174
170
  const currentTaskId = getActiveTaskId();
175
171
  const currentMessageId = getActiveMessageId();
176
- logger.log(`[ON_IDLE] Reply idle`);
177
- logger.log(`[ON_IDLE] - sessionId: ${sessionId}`);
178
- logger.log(`[ON_IDLE] - taskId: ${currentTaskId}`);
179
- logger.log(`[ON_IDLE] - steered: ${steerState.steered}`);
180
- logger.log(`[ON_IDLE] - hasSentResponse: ${hasSentResponse}`);
181
- logger.log(`[ON_IDLE] - finalSent: ${finalSent}`);
172
+ scopedLog().log(`[ON-IDLE] Reply idle, steered=${steerState.steered}, hasSentResponse=${hasSentResponse}, finalSent=${finalSent}`);
182
173
  // 🔑 steered dispatch不发送final响应(核心已注入到活跃 Pi run)
183
174
  if (steerState.steered) {
184
- logger.log(`[ON_IDLE] Steered dispatch - skipping final response`);
175
+ scopedLog().log(`[ON-IDLE] Steered dispatch, skipping final response`);
185
176
  stopStatusInterval();
186
177
  return; // ← 直接返回,不发送任何东西!
187
178
  }
188
179
  // 正常模式(或未被steer的dispatch)
189
180
  if (hasSentResponse && !finalSent) {
190
- logger.log(`[ON_IDLE] Sending accumulated text, length=${accumulatedText.length}`);
181
+ scopedLog().log(`[ON-IDLE] Sending accumulated text, length=${accumulatedText.length}`);
191
182
  try {
192
183
  // 🔑 使用动态taskId发送完成状态
193
184
  await sendStatusUpdate({
@@ -198,7 +189,7 @@ export function createXYReplyDispatcher(params) {
198
189
  text: "任务处理已完成~",
199
190
  state: "completed",
200
191
  });
201
- logger.log(`[ON_IDLE] Sent completion status update`);
192
+ scopedLog().log(`[ON-IDLE] Sent completion status update`);
202
193
  // 🔑 使用动态taskId发送最终响应
203
194
  await sendA2AResponse({
204
195
  config,
@@ -210,15 +201,15 @@ export function createXYReplyDispatcher(params) {
210
201
  final: true,
211
202
  });
212
203
  finalSent = true;
213
- logger.log(`[ON_IDLE] Sent final response with taskId=${currentTaskId}`);
204
+ scopedLog().log(`[ON-IDLE] Sent final response`);
214
205
  }
215
206
  catch (err) {
216
- logger.error(`[ON_IDLE] Failed to send final response:`, err);
207
+ scopedLog().error(`[ON-IDLE] Failed to send final response:`, err);
217
208
  }
218
209
  }
219
210
  else {
220
211
  // 正常失败场景(非steered)
221
- logger.log(`[ON_IDLE] Skipping final message: hasSentResponse=${hasSentResponse}, finalSent=${finalSent}`);
212
+ scopedLog().log(`[ON-IDLE] Skipping final message: hasSentResponse=${hasSentResponse}, finalSent=${finalSent}`);
222
213
  try {
223
214
  await sendStatusUpdate({
224
215
  config,
@@ -228,7 +219,7 @@ export function createXYReplyDispatcher(params) {
228
219
  text: "任务处理中断了~",
229
220
  state: "failed",
230
221
  });
231
- logger.log(`[ON_IDLE] Sent failure status update`);
222
+ scopedLog().log(`[ON-IDLE] Sent failure status update`);
232
223
  await sendA2AResponse({
233
224
  config,
234
225
  sessionId,
@@ -241,17 +232,17 @@ export function createXYReplyDispatcher(params) {
241
232
  errorMessage: "任务执行异常,请重试",
242
233
  });
243
234
  finalSent = true;
244
- logger.log(`[ON_IDLE] Sent error response with code: 99921111`);
235
+ scopedLog().log(`[ON-IDLE] Sent error response, code=99921111`);
245
236
  }
246
237
  catch (err) {
247
- logger.error(`[ON_IDLE] Failed to send error response:`, err);
238
+ scopedLog().error(`[ON-IDLE] Failed to send error response:`, err);
248
239
  }
249
240
  }
250
241
  stopStatusInterval();
251
242
  },
252
243
  onCleanup: () => {
253
244
  const currentTaskId = getActiveTaskId();
254
- logger.log(`[ON_CLEANUP] Reply cleanup, taskId=${currentTaskId}, steered=${steerState.steered}`);
245
+ scopedLog().log(`[ON-CLEANUP] Reply cleanup, steered=${steerState.steered}`);
255
246
  },
256
247
  });
257
248
  return {
@@ -266,13 +257,13 @@ export function createXYReplyDispatcher(params) {
266
257
  }
267
258
  const currentTaskId = getActiveTaskId();
268
259
  const currentMessageId = getActiveMessageId();
269
- logger.log(`[TOOL START] Tool: ${name}, phase: ${phase}, taskId: ${currentTaskId}`);
260
+ scopedLog().log(`[TOOL-START] Tool: ${name}, phase: ${phase}`);
270
261
  if (phase === "start") {
271
262
  const toolName = name || "unknown";
272
263
  // call_device_tool 由自身 execute() 内部发送具体子工具名的状态更新
273
264
  // get_xxx_tool_schema 是给 LLM 查 schema 用的,无需向用户展示
274
265
  if (toolName === "call_device_tool" || toolName.endsWith("_tool_schema") || toolName === "huawei_id_tool") {
275
- logger.log(`[TOOL START] Skipping generic status for ${toolName}`);
266
+ scopedLog().log(`[TOOL-START] Skipping generic status for ${toolName}`);
276
267
  return;
277
268
  }
278
269
  try {
@@ -284,10 +275,10 @@ export function createXYReplyDispatcher(params) {
284
275
  text: `正在使用工具: ${toolName}...`,
285
276
  state: "working",
286
277
  });
287
- logger.log(`[TOOL START] Sent status update for tool start: ${toolName}`);
278
+ scopedLog().log(`[TOOL-START] Sent status update for tool start: ${toolName}`);
288
279
  }
289
280
  catch (err) {
290
- logger.error(`[TOOL START] Failed to send tool start status:`, err);
281
+ scopedLog().error(`[TOOL-START] Failed to send tool start status:`, err);
291
282
  }
292
283
  }
293
284
  },
@@ -300,7 +291,7 @@ export function createXYReplyDispatcher(params) {
300
291
  const currentMessageId = getActiveMessageId();
301
292
  const text = payload.text ?? "";
302
293
  const hasMedia = Boolean(payload.mediaUrl || (payload.mediaUrls?.length ?? 0) > 0);
303
- logger.log(`[TOOL RESULT] Tool result, taskId: ${currentTaskId}, text.length: ${text.length}`);
294
+ scopedLog().log(`[TOOL-RESULT] Tool result, text.length: ${text.length}`);
304
295
  try {
305
296
  if (text.length > 0 || hasMedia) {
306
297
  const resultText = text.length > 0 ? text : "工具执行完成";
@@ -312,11 +303,11 @@ export function createXYReplyDispatcher(params) {
312
303
  text: resultText,
313
304
  state: "working",
314
305
  });
315
- logger.log(`[TOOL RESULT] Sent tool result as status update`);
306
+ scopedLog().log(`[TOOL-RESULT] Sent tool result as status update`);
316
307
  }
317
308
  }
318
309
  catch (err) {
319
- logger.error(`[TOOL RESULT] Failed to send tool result status:`, err);
310
+ scopedLog().error(`[TOOL-RESULT] Failed to send tool result status:`, err);
320
311
  }
321
312
  },
322
313
  onReasoningStream: async (payload) => {
@@ -325,7 +316,7 @@ export function createXYReplyDispatcher(params) {
325
316
  return;
326
317
  }
327
318
  const text = payload.text ?? "";
328
- logger.log(`[REASONING STREAM] Reasoning chunk received, text.length: ${text.length}`);
319
+ scopedLog().log(`[REASONING-STREAM] Reasoning chunk received, text.length: ${text.length}`);
329
320
  // Reasoning stream 目前被注释掉
330
321
  // 如果需要可以启用
331
322
  },
@@ -350,7 +341,7 @@ export function createXYReplyDispatcher(params) {
350
341
  }
351
342
  }
352
343
  catch (err) {
353
- logger.error(`[PARTIAL REPLY] Failed to send partial reply:`, err);
344
+ scopedLog().error(`[PARTIAL REPLY] Failed to send partial reply:`, err);
354
345
  }
355
346
  },
356
347
  },
@@ -127,7 +127,7 @@ export async function handleSelfEvolutionStateGetEvent(context, cfg, runtime, ws
127
127
  taskId,
128
128
  msgDetail: JSON.stringify(jsonRpcResponse),
129
129
  };
130
- logger.log(`[A2A_COMMAND] 📤 Sending A2A command: taskId: ${taskId}`);
130
+ logger.log(`[A2A_COMMAND] Sending A2A command, taskId: ${taskId}`);
131
131
  await wsManager.sendMessage(sessionId, outboundMessage);
132
132
  logger.log(`[SELF_EVOLUTION_GET] command sent successfully`);
133
133
  }
@@ -0,0 +1,4 @@
1
+ export declare function refreshSensitivePatterns(): void;
2
+ export declare function redactSensitiveText(text: any): any;
3
+ export declare function redactSensitiveObject(obj: any): any;
4
+ export declare function containsSensitiveInfo(text: any): boolean;