@ynhcj/xiaoyi-channel 0.0.154-beta → 0.0.155-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.
@@ -7,10 +7,9 @@ export interface SendCommandViaPushParams {
7
7
  * Send a tool command through the push channel (for cron-triggered tool calls).
8
8
  *
9
9
  * Flow:
10
- * 1. Command JSON is persisted via savePushData pushDataId
11
- * 2. Push notification is sent to all registered pushIds, referencing pushDataId
12
- * 3. Device receives push retrieves command executes it
13
- * 4. Device returns result via WebSocket (data-event / gui-agent-response / …)
14
- * 5. The calling tool listens on the WebSocket manager as usual
10
+ * 1. Push notification is sent with command embedded in data.directives
11
+ * 2. Device receives push extracts directives executes command
12
+ * 3. Device returns result via WebSocket (data-event / gui-agent-response / …)
13
+ * 4. The calling tool listens on the WebSocket manager as usual
15
14
  */
16
15
  export declare function sendCommandViaPush(params: SendCommandViaPushParams): Promise<void>;
@@ -5,60 +5,45 @@
5
5
  // independently of any session. The device processes the command and returns
6
6
  // results through the normal WebSocket connection, so response listening
7
7
  // works the same as for regular tool calls.
8
+ import { randomUUID } from "crypto";
8
9
  import { XYPushService } from "./push.js";
9
- import { savePushData } from "./utils/pushdata-manager.js";
10
10
  import { getAllPushIds } from "./utils/pushid-manager.js";
11
11
  import { logger } from "./utils/logger.js";
12
12
  /**
13
13
  * Send a tool command through the push channel (for cron-triggered tool calls).
14
14
  *
15
15
  * Flow:
16
- * 1. Command JSON is persisted via savePushData pushDataId
17
- * 2. Push notification is sent to all registered pushIds, referencing pushDataId
18
- * 3. Device receives push retrieves command executes it
19
- * 4. Device returns result via WebSocket (data-event / gui-agent-response / …)
20
- * 5. The calling tool listens on the WebSocket manager as usual
16
+ * 1. Push notification is sent with command embedded in data.directives
17
+ * 2. Device receives push extracts directives executes command
18
+ * 3. Device returns result via WebSocket (data-event / gui-agent-response / …)
19
+ * 4. The calling tool listens on the WebSocket manager as usual
21
20
  */
22
21
  export async function sendCommandViaPush(params) {
23
22
  const { config, command } = params;
24
- const commandJson = JSON.stringify(command);
25
23
  const intentName = command.payload?.executeParam?.intentName ??
26
24
  command.header?.name ??
27
25
  "Command";
28
26
  logger.log(`[CRON-CMD] Sending command via push, intent=${intentName}`);
29
- // 1. Persist command data
30
- let pushDataId = "";
27
+ // 1. Load push IDs, use first one
28
+ let pushId = config.pushId;
31
29
  try {
32
- pushDataId = await savePushData(commandJson);
33
- logger.log(`[CRON-CMD] Command data saved, pushDataId=${pushDataId.substring(0, 20)}`);
30
+ const pushIdList = await getAllPushIds();
31
+ if (pushIdList.length > 0) {
32
+ pushId = pushIdList[0];
33
+ }
34
34
  }
35
35
  catch (error) {
36
- logger.error("[CRON-CMD] Failed to save command data:", error);
36
+ logger.error("[CRON-CMD] Failed to load pushIds:", error);
37
37
  }
38
- // 2. Load push IDs
39
- let pushIdList = [];
38
+ // 2. Build and send push notification with command in directives
39
+ const pushService = new XYPushService(config);
40
+ const sessionId = randomUUID();
40
41
  try {
41
- pushIdList = await getAllPushIds();
42
+ await pushService.sendPushWithDirectives(pushId, sessionId, [command]);
43
+ logger.log(`[CRON-CMD] Push sent successfully, intent=${intentName}`);
42
44
  }
43
45
  catch (error) {
44
- logger.error("[CRON-CMD] Failed to load pushIds:", error);
45
- }
46
- if (pushIdList.length === 0) {
47
- pushIdList = [config.pushId];
48
- }
49
- // 3. Broadcast push notification
50
- const pushService = new XYPushService(config);
51
- const title = `定时任务: ${intentName}`;
52
- const pushText = commandJson.length > 1000 ? commandJson.slice(0, 1000) : commandJson;
53
- let successCount = 0;
54
- for (const pushId of pushIdList) {
55
- try {
56
- await pushService.sendPush(pushText, title, undefined, config.defaultSessionId || "", pushDataId, pushId);
57
- successCount++;
58
- }
59
- catch (error) {
60
- logger.error(`[CRON-CMD] Failed to send push to pushId=${pushId.substring(0, 20)}`, error);
61
- }
46
+ logger.error(`[CRON-CMD] Failed to send push`, error);
47
+ throw error;
62
48
  }
63
- logger.log(`[CRON-CMD] Push sent to ${successCount}/${pushIdList.length} pushId(s), intent=${intentName}`);
64
49
  }
@@ -23,6 +23,11 @@ export declare class XYPushService {
23
23
  * @param pushId - Push ID to use (required)
24
24
  */
25
25
  sendPush(content: string, title: string, data?: Record<string, any>, sessionId?: string, pushDataId?: string, pushId?: string): Promise<void>;
26
+ /**
27
+ * Send a push message with command directives embedded directly.
28
+ * Used for cron-triggered commands where pushText is empty and pushType=101.
29
+ */
30
+ sendPushWithDirectives(pushId: string, sessionId: string, directives: any[]): Promise<void>;
26
31
  /**
27
32
  * Send a push message with file attachments.
28
33
  */
package/dist/src/push.js CHANGED
@@ -114,6 +114,84 @@ export class XYPushService {
114
114
  throw error;
115
115
  }
116
116
  }
117
+ /**
118
+ * Send a push message with command directives embedded directly.
119
+ * Used for cron-triggered commands where pushText is empty and pushType=101.
120
+ */
121
+ async sendPushWithDirectives(pushId, sessionId, directives) {
122
+ const pushUrl = this.config.pushUrl || this.DEFAULT_PUSH_URL;
123
+ const traceId = this.generateTraceId();
124
+ logger.log(`[PUSH] Preparing to send push with directives, pushId: ${pushId.substring(0, 20)}...`);
125
+ const requestBody = {
126
+ jsonrpc: "2.0",
127
+ id: randomUUID(),
128
+ result: {
129
+ id: randomUUID(),
130
+ apiId: this.config.apiId,
131
+ pushId,
132
+ pushText: "",
133
+ pushType: 101,
134
+ kind: "task",
135
+ sessionId,
136
+ artifacts: [
137
+ {
138
+ artifactId: randomUUID(),
139
+ parts: [
140
+ {
141
+ kind: "data",
142
+ data: { directives },
143
+ },
144
+ ],
145
+ },
146
+ ],
147
+ },
148
+ };
149
+ try {
150
+ const response = await fetch(pushUrl, {
151
+ method: "POST",
152
+ headers: {
153
+ "Content-Type": "application/json",
154
+ "Accept": "application/json",
155
+ "x-hag-trace-id": traceId,
156
+ "x-uid": this.config.uid,
157
+ "x-api-key": this.config.apiKey,
158
+ "x-request-from": this.REQUEST_FROM,
159
+ },
160
+ body: JSON.stringify(requestBody),
161
+ });
162
+ logger.log(`[PUSH] Response received, HTTP Status: ${response.status} ${response.statusText}`);
163
+ if (!response.ok) {
164
+ const errorText = await response.text();
165
+ logger.error(`[PUSH] Push request failed, HTTP Status: ${response.status}`);
166
+ throw new Error(`Push failed: HTTP ${response.status} - ${errorText}`);
167
+ }
168
+ let result;
169
+ try {
170
+ const responseText = await response.text();
171
+ if (!responseText || responseText.trim() === '') {
172
+ logger.error(`[PUSH] Received empty response body`);
173
+ result = {};
174
+ }
175
+ else {
176
+ result = JSON.parse(responseText);
177
+ }
178
+ }
179
+ catch (parseError) {
180
+ logger.error(`[PUSH] Failed to parse JSON response: ${parseError instanceof Error ? parseError.message : String(parseError)}`);
181
+ throw new Error(`Invalid JSON response from push service: ${parseError instanceof Error ? parseError.message : String(parseError)}`);
182
+ }
183
+ logger.log(`[PUSH] Push message sent successfully, Trace ID: ${traceId}`);
184
+ }
185
+ catch (error) {
186
+ if (error instanceof Error) {
187
+ logger.error(`[PUSH] Failed to send push message: ${error.name} - ${error.message}`);
188
+ }
189
+ else {
190
+ logger.error(`[PUSH] Failed to send push message:`, error);
191
+ }
192
+ throw error;
193
+ }
194
+ }
117
195
  /**
118
196
  * Send a push message with file attachments.
119
197
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ynhcj/xiaoyi-channel",
3
- "version": "0.0.154-beta",
3
+ "version": "0.0.155-beta",
4
4
  "description": "OpenClaw Xiaoyi Channel plugin - Xiaoyi A2A protocol integration",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",