@ynhcj/xiaoyi-channel 0.0.51-next → 0.0.52-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 +21 -40
- package/dist/src/file-download.js +1 -1
- package/dist/src/parser.d.ts +4 -7
- package/dist/src/parser.js +2 -7
- package/dist/src/provider.js +2 -20
- package/dist/src/tools/upload-file-tool.js +2 -2
- package/dist/src/tools/xiaoyi-add-collection-tool.js +1 -0
- package/dist/src/utils/pushdata-manager.d.ts +0 -5
- package/dist/src/utils/pushdata-manager.js +0 -33
- package/package.json +1 -1
package/dist/src/bot.js
CHANGED
|
@@ -8,7 +8,7 @@ import { sendStatusUpdate, sendClearContextResponse, sendTasksCancelResponse, se
|
|
|
8
8
|
import { registerSession, unregisterSession, runWithSessionContext } from "./tools/session-manager.js";
|
|
9
9
|
import { configManager } from "./utils/config-manager.js";
|
|
10
10
|
import { addPushId } from "./utils/pushid-manager.js";
|
|
11
|
-
import { getPushDataById
|
|
11
|
+
import { getPushDataById } from "./utils/pushdata-manager.js";
|
|
12
12
|
import { saveRuntimeInfo } from "./utils/runtime-manager.js";
|
|
13
13
|
import { registerTaskId, decrementTaskIdRef, lockTaskId, unlockTaskId, hasActiveTask, } from "./task-manager.js";
|
|
14
14
|
/**
|
|
@@ -61,53 +61,34 @@ export async function handleXYMessage(params) {
|
|
|
61
61
|
}
|
|
62
62
|
// Parse the A2A message (for regular messages)
|
|
63
63
|
const parsed = parseA2AMessage(message);
|
|
64
|
+
console.log("Parsed A2A message:", JSON.stringify(parsed, null, 2));
|
|
64
65
|
// ========== 检测 Trigger 消息 ==========
|
|
65
66
|
// 如果消息中包含 Trigger 事件数据,直接返回 pushData 内容,不走正常流程
|
|
66
67
|
const triggerData = extractTriggerData(parsed.parts);
|
|
67
68
|
if (triggerData) {
|
|
68
|
-
log(`[BOT] 📌 Detected Trigger message`);
|
|
69
|
+
log(`[BOT] 📌 Detected Trigger message with pushDataId: ${triggerData.pushDataId}`);
|
|
69
70
|
log(`[BOT] - Session ID: ${parsed.sessionId}`);
|
|
70
71
|
log(`[BOT] - Task ID: ${parsed.taskId}`);
|
|
71
72
|
try {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
if (!pushDataItem) {
|
|
78
|
-
error(`[BOT] ❌ pushData not found for ID: ${triggerData.pushDataId}`);
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
log(`[BOT] ✅ Found pushData, sending direct response`);
|
|
82
|
-
await sendA2AResponse({
|
|
83
|
-
config,
|
|
84
|
-
sessionId: parsed.sessionId,
|
|
85
|
-
taskId: parsed.taskId,
|
|
86
|
-
messageId: parsed.messageId,
|
|
87
|
-
text: pushDataItem.dataDetail,
|
|
88
|
-
append: false,
|
|
89
|
-
final: true,
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
else {
|
|
93
|
-
// 批量查询:按 timestamp 返回所有之后的 push 数据
|
|
94
|
-
log(`[BOT] - Type: timestamp = ${triggerData.timestamp}`);
|
|
95
|
-
const items = await getPushDataAfterTimestamp(triggerData.timestamp);
|
|
96
|
-
const result = items.map(item => ({
|
|
97
|
-
pushDataId: item.pushDataId,
|
|
98
|
-
pushData: item.dataDetail,
|
|
99
|
-
}));
|
|
100
|
-
log(`[BOT] ✅ Found ${result.length} pushData items after timestamp, sending response`);
|
|
101
|
-
await sendA2AResponse({
|
|
102
|
-
config,
|
|
103
|
-
sessionId: parsed.sessionId,
|
|
104
|
-
taskId: parsed.taskId,
|
|
105
|
-
messageId: parsed.messageId,
|
|
106
|
-
text: JSON.stringify(result),
|
|
107
|
-
append: false,
|
|
108
|
-
final: true,
|
|
109
|
-
});
|
|
73
|
+
// 读取 pushData
|
|
74
|
+
const pushDataItem = await getPushDataById(triggerData.pushDataId);
|
|
75
|
+
if (!pushDataItem) {
|
|
76
|
+
error(`[BOT] ❌ pushData not found for ID: ${triggerData.pushDataId}`);
|
|
77
|
+
return;
|
|
110
78
|
}
|
|
79
|
+
log(`[BOT] ✅ Found pushData, sending direct response`);
|
|
80
|
+
log(`[BOT] - pushDataId: ${pushDataItem.pushDataId}`);
|
|
81
|
+
const config = resolveXYConfig(cfg);
|
|
82
|
+
// 直接发送响应(final=true,不走 openclaw 流程)
|
|
83
|
+
await sendA2AResponse({
|
|
84
|
+
config,
|
|
85
|
+
sessionId: parsed.sessionId,
|
|
86
|
+
taskId: parsed.taskId,
|
|
87
|
+
messageId: parsed.messageId,
|
|
88
|
+
text: pushDataItem.dataDetail,
|
|
89
|
+
append: false,
|
|
90
|
+
final: true,
|
|
91
|
+
});
|
|
111
92
|
log(`[BOT] ✅ Trigger response sent successfully, exiting early`);
|
|
112
93
|
return; // 提前返回,不继续处理
|
|
113
94
|
}
|
|
@@ -7,7 +7,7 @@ import { logger } from "./utils/logger.js";
|
|
|
7
7
|
* Download a file from URL to local path.
|
|
8
8
|
*/
|
|
9
9
|
export async function downloadFile(url, destPath) {
|
|
10
|
-
|
|
10
|
+
console.log(`Downloading file from ${url} to ${destPath}`);
|
|
11
11
|
const controller = new AbortController();
|
|
12
12
|
const timeout = setTimeout(() => controller.abort(), 30000); // 30 seconds timeout
|
|
13
13
|
try {
|
package/dist/src/parser.d.ts
CHANGED
|
@@ -49,16 +49,13 @@ export declare function extractPushId(parts: A2AMessagePart[]): string | null;
|
|
|
49
49
|
* (same level as push_id).
|
|
50
50
|
*/
|
|
51
51
|
export declare function extractDeviceType(parts: A2AMessagePart[]): string | null;
|
|
52
|
-
export type TriggerData = {
|
|
53
|
-
pushDataId: string;
|
|
54
|
-
} | {
|
|
55
|
-
timestamp: string;
|
|
56
|
-
};
|
|
57
52
|
/**
|
|
58
53
|
* Extract Trigger event data from message parts.
|
|
59
|
-
* Looks for Trigger events with pushDataId
|
|
54
|
+
* Looks for Trigger events with pushDataId in data parts.
|
|
60
55
|
*/
|
|
61
|
-
export declare function extractTriggerData(parts: A2AMessagePart[]):
|
|
56
|
+
export declare function extractTriggerData(parts: A2AMessagePart[]): {
|
|
57
|
+
pushDataId: string;
|
|
58
|
+
} | null;
|
|
62
59
|
/**
|
|
63
60
|
* Validate A2A request structure.
|
|
64
61
|
*/
|
package/dist/src/parser.js
CHANGED
|
@@ -90,7 +90,7 @@ export function extractDeviceType(parts) {
|
|
|
90
90
|
}
|
|
91
91
|
/**
|
|
92
92
|
* Extract Trigger event data from message parts.
|
|
93
|
-
* Looks for Trigger events with pushDataId
|
|
93
|
+
* Looks for Trigger events with pushDataId in data parts.
|
|
94
94
|
*/
|
|
95
95
|
export function extractTriggerData(parts) {
|
|
96
96
|
for (const part of parts) {
|
|
@@ -99,15 +99,10 @@ export function extractTriggerData(parts) {
|
|
|
99
99
|
if (Array.isArray(events)) {
|
|
100
100
|
for (const event of events) {
|
|
101
101
|
if (event.header?.namespace === "Common" && event.header?.name === "Trigger") {
|
|
102
|
-
const
|
|
103
|
-
const pushDataId = dataMap?.pushDataId;
|
|
102
|
+
const pushDataId = event.payload?.dataMap?.pushDataId;
|
|
104
103
|
if (pushDataId && typeof pushDataId === "string") {
|
|
105
104
|
return { pushDataId };
|
|
106
105
|
}
|
|
107
|
-
const timestamp = dataMap?.timestamp;
|
|
108
|
-
if (timestamp && typeof timestamp === "string") {
|
|
109
|
-
return { timestamp };
|
|
110
|
-
}
|
|
111
106
|
}
|
|
112
107
|
}
|
|
113
108
|
}
|
package/dist/src/provider.js
CHANGED
|
@@ -117,26 +117,8 @@ export const xiaoyiProvider = {
|
|
|
117
117
|
// 异步监听输出(不阻塞 stream 返回)
|
|
118
118
|
stream.result().then((result) => {
|
|
119
119
|
console.log(`[xiaoyiprovider] stream completed, usage: input=${result.usage?.input} output=${result.usage?.output}`);
|
|
120
|
-
}, (err) => console.log(`[xiaoyiprovider] stream error: ${err}`));
|
|
121
|
-
|
|
122
|
-
return new Proxy(stream, {
|
|
123
|
-
get(target, prop, receiver) {
|
|
124
|
-
if (prop === "result") {
|
|
125
|
-
const originalResult = target.result.bind(target);
|
|
126
|
-
return () => originalResult().then((result) => {
|
|
127
|
-
if (result?.usage?.input === 0 && result?.usage?.output === 0) {
|
|
128
|
-
const error = new Error("This model's maximum context length was exceeded.");
|
|
129
|
-
error.type = "invalid_request_error";
|
|
130
|
-
error.code = "context_length_exceeded";
|
|
131
|
-
error.param = "messages";
|
|
132
|
-
throw error;
|
|
133
|
-
}
|
|
134
|
-
return result;
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
return Reflect.get(target, prop, receiver);
|
|
138
|
-
},
|
|
139
|
-
});
|
|
120
|
+
}, (err) => console.log(`[xiaoyiprovider] stream error: ${JSON.stringify(err)}`));
|
|
121
|
+
return stream;
|
|
140
122
|
};
|
|
141
123
|
},
|
|
142
124
|
};
|
|
@@ -18,10 +18,10 @@ export const uploadFileTool = {
|
|
|
18
18
|
label: "Upload File",
|
|
19
19
|
description: `工具能力描述:将手机本地文件上传并获取可公网访问的 URL。
|
|
20
20
|
|
|
21
|
-
前置工具调用:此工具使用前必须先调用 search_file 或者
|
|
21
|
+
前置工具调用:此工具使用前必须先调用 search_file 或者 query_collection 工具获取文件的 uri=
|
|
22
22
|
|
|
23
23
|
工具参数说明:
|
|
24
|
-
a. 入参中的fileInfos数组,每个元素必须包含mediaUri字段(对应于search_file工具或者
|
|
24
|
+
a. 入参中的fileInfos数组,每个元素必须包含mediaUri字段(对应于search_file工具或者query_collection返回结果中的uri),必须与search_file或者query_collection结果中对应的uri完全保持一致,不要自行修改。
|
|
25
25
|
b. fileInfos中的timeout字段是可选的,表示上传文件超时时间,单位是毫秒,默认是20000(20秒)。
|
|
26
26
|
c. fileInfos 是文件在手机本地的信息数组(从 search_file 工具响应中获取)。限制:每次最多支持传入 5 条文件信息。
|
|
27
27
|
|
|
@@ -28,6 +28,7 @@ export const xiaoyiAddCollectionTool = {
|
|
|
28
28
|
● dataType:必填字段,数据类型为string,功能描述是标识数据类型。HYPER_LINK标识网页,TEXT标识文本,IMAGE标识图片,FILE标识文件。
|
|
29
29
|
● title:非必填字段,数据类型为string,功能描述是标识文件类型数据的文件名称。适用于FILE类型。
|
|
30
30
|
说明:如果dataType为HYPER_LINK或TEXT,则content字段必填且不能为空;如果dataType为IMAGE或FILE,则uri字段必填且不能为空。当用户希望收藏海报、截图等图片类数据时,请将数据以图片IMAGE的形式存入到小艺帮记;当用户希望收藏电子书、笔记、报告、素材、文档、合同、协议、简历、证书、报表、日志、安装包、压缩包等描述的文件时,请将数据以文件FILE的形式存入到小艺帮记。
|
|
31
|
+
当你成功收藏这个数据到小艺帮记后,请在最后显示"已成功把数据添加到[小艺帮记](vassistant://voice/main?page=CollectionPage&jumpHomePageTab=myCollection)",
|
|
31
32
|
注意:
|
|
32
33
|
a. 操作超时时间为60秒,请勿重复调用此工具
|
|
33
34
|
b. 如果遇到各类调用失败场景,最多只能重试一次,不可以重复调用多次。
|
|
@@ -22,11 +22,6 @@ export declare function searchPushData(keywords?: string): Promise<PushDataItem[
|
|
|
22
22
|
* 获取所有推送数据
|
|
23
23
|
*/
|
|
24
24
|
export declare function getAllPushData(): Promise<PushDataItem[]>;
|
|
25
|
-
/**
|
|
26
|
-
* 获取指定时间戳之后的所有推送数据
|
|
27
|
-
* @param timestamp - Unix 时间戳(秒或毫秒)
|
|
28
|
-
*/
|
|
29
|
-
export declare function getPushDataAfterTimestamp(timestamp: string): Promise<PushDataItem[]>;
|
|
30
25
|
/**
|
|
31
26
|
* 清空所有推送数据(用于测试或重置)
|
|
32
27
|
*/
|
|
@@ -157,39 +157,6 @@ export async function getAllPushData() {
|
|
|
157
157
|
return [];
|
|
158
158
|
}
|
|
159
159
|
}
|
|
160
|
-
/**
|
|
161
|
-
* 将 Unix 时间戳(秒或毫秒)转为 YYYYMMDD HHmmss 北京时间字符串
|
|
162
|
-
*/
|
|
163
|
-
function unixToBeijingStr(ts) {
|
|
164
|
-
let ms = Number(ts);
|
|
165
|
-
if (isNaN(ms))
|
|
166
|
-
return "";
|
|
167
|
-
// 秒级时间戳(小于 1e12)转为毫秒
|
|
168
|
-
if (ms < 1e12)
|
|
169
|
-
ms *= 1000;
|
|
170
|
-
return formatBeijingTime(new Date(ms));
|
|
171
|
-
}
|
|
172
|
-
/**
|
|
173
|
-
* 获取指定时间戳之后的所有推送数据
|
|
174
|
-
* @param timestamp - Unix 时间戳(秒或毫秒)
|
|
175
|
-
*/
|
|
176
|
-
export async function getPushDataAfterTimestamp(timestamp) {
|
|
177
|
-
try {
|
|
178
|
-
const target = unixToBeijingStr(timestamp);
|
|
179
|
-
if (!target) {
|
|
180
|
-
logger.warn(`[PushDataManager] Invalid timestamp: ${timestamp}`);
|
|
181
|
-
return [];
|
|
182
|
-
}
|
|
183
|
-
const list = await readPushDataList();
|
|
184
|
-
const results = list.filter(item => item.time >= target);
|
|
185
|
-
logger.log(`[PushDataManager] Query after timestamp ${timestamp} (UTC+8: ${target}): found ${results.length} items`);
|
|
186
|
-
return results;
|
|
187
|
-
}
|
|
188
|
-
catch (error) {
|
|
189
|
-
logger.error(`[PushDataManager] Failed to get pushData after timestamp:`, error);
|
|
190
|
-
return [];
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
160
|
/**
|
|
194
161
|
* 清空所有推送数据(用于测试或重置)
|
|
195
162
|
*/
|