@ynhcj/xiaoyi 0.0.1-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.
- package/README.md +207 -0
- package/dist/auth.d.ts +36 -0
- package/dist/auth.js +111 -0
- package/dist/channel.d.ts +189 -0
- package/dist/channel.js +354 -0
- package/dist/config-schema.d.ts +46 -0
- package/dist/config-schema.js +28 -0
- package/dist/file-download.d.ts +17 -0
- package/dist/file-download.js +69 -0
- package/dist/file-handler.d.ts +36 -0
- package/dist/file-handler.js +113 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.js +49 -0
- package/dist/onboarding.d.ts +6 -0
- package/dist/onboarding.js +167 -0
- package/dist/push.d.ts +28 -0
- package/dist/push.js +135 -0
- package/dist/runtime.d.ts +191 -0
- package/dist/runtime.js +438 -0
- package/dist/types.d.ts +280 -0
- package/dist/types.js +8 -0
- package/dist/websocket.d.ts +219 -0
- package/dist/websocket.js +1068 -0
- package/dist/xiaoyi-media.d.ts +81 -0
- package/dist/xiaoyi-media.js +216 -0
- package/dist/xy-bot.d.ts +19 -0
- package/dist/xy-bot.js +277 -0
- package/dist/xy-client.d.ts +26 -0
- package/dist/xy-client.js +78 -0
- package/dist/xy-config.d.ts +18 -0
- package/dist/xy-config.js +37 -0
- package/dist/xy-formatter.d.ts +94 -0
- package/dist/xy-formatter.js +303 -0
- package/dist/xy-monitor.d.ts +17 -0
- package/dist/xy-monitor.js +194 -0
- package/dist/xy-parser.d.ts +49 -0
- package/dist/xy-parser.js +109 -0
- package/dist/xy-reply-dispatcher.d.ts +17 -0
- package/dist/xy-reply-dispatcher.js +308 -0
- package/dist/xy-tools/session-manager.d.ts +29 -0
- package/dist/xy-tools/session-manager.js +80 -0
- package/dist/xy-utils/config-manager.d.ts +26 -0
- package/dist/xy-utils/config-manager.js +61 -0
- package/dist/xy-utils/crypto.d.ts +8 -0
- package/dist/xy-utils/crypto.js +21 -0
- package/dist/xy-utils/logger.d.ts +6 -0
- package/dist/xy-utils/logger.js +37 -0
- package/dist/xy-utils/session.d.ts +34 -0
- package/dist/xy-utils/session.js +55 -0
- package/openclaw.plugin.json +9 -0
- package/package.json +73 -0
- package/xiaoyi.js +1 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.setClientRuntime = setClientRuntime;
|
|
4
|
+
exports.getXYWebSocketManager = getXYWebSocketManager;
|
|
5
|
+
exports.removeXYWebSocketManager = removeXYWebSocketManager;
|
|
6
|
+
exports.clearXYWebSocketManagers = clearXYWebSocketManagers;
|
|
7
|
+
exports.getCachedManagerCount = getCachedManagerCount;
|
|
8
|
+
// WebSocket client cache management
|
|
9
|
+
// Adapted for xiaoyi - uses xiaoyi's WebSocket manager with aksk auth
|
|
10
|
+
const websocket_js_1 = require("./websocket.js");
|
|
11
|
+
// Runtime reference for logging
|
|
12
|
+
let runtime;
|
|
13
|
+
/**
|
|
14
|
+
* Set the runtime for logging in client module.
|
|
15
|
+
*/
|
|
16
|
+
function setClientRuntime(rt) {
|
|
17
|
+
runtime = rt;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Global cache for WebSocket managers.
|
|
21
|
+
* Key format: `${ak}-${agentId}` (using xiaoyi's aksk auth)
|
|
22
|
+
*/
|
|
23
|
+
const wsManagerCache = new Map();
|
|
24
|
+
/**
|
|
25
|
+
* Get or create a WebSocket manager for the given configuration.
|
|
26
|
+
* Reuses existing managers if config matches.
|
|
27
|
+
* Adapted for xiaoyi - uses aksk instead of apiKey/uid
|
|
28
|
+
*/
|
|
29
|
+
function getXYWebSocketManager(config) {
|
|
30
|
+
const cacheKey = `${config.ak}-${config.agentId}`;
|
|
31
|
+
let cached = wsManagerCache.get(cacheKey);
|
|
32
|
+
if (cached) {
|
|
33
|
+
const log = runtime?.log ?? console.log;
|
|
34
|
+
log(`[WS-MANAGER-CACHE] ✅ Reusing cached WebSocket manager: ${cacheKey}, total managers: ${wsManagerCache.size}`);
|
|
35
|
+
return cached;
|
|
36
|
+
}
|
|
37
|
+
// Create new manager with xiaoyi's config (aksk auth)
|
|
38
|
+
const log = runtime?.log ?? console.log;
|
|
39
|
+
log(`[WS-MANAGER-CACHE] 🆕 Creating new WebSocket manager: ${cacheKey}, total managers before: ${wsManagerCache.size}`);
|
|
40
|
+
cached = new websocket_js_1.XiaoYiWebSocketManager(config);
|
|
41
|
+
wsManagerCache.set(cacheKey, cached);
|
|
42
|
+
log(`[WS-MANAGER-CACHE] 📊 Total managers after creation: ${wsManagerCache.size}`);
|
|
43
|
+
return cached;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Remove a specific WebSocket manager from cache.
|
|
47
|
+
* Disconnects the manager and removes it from the cache.
|
|
48
|
+
*/
|
|
49
|
+
function removeXYWebSocketManager(config) {
|
|
50
|
+
const cacheKey = `${config.ak}-${config.agentId}`;
|
|
51
|
+
const manager = wsManagerCache.get(cacheKey);
|
|
52
|
+
if (manager) {
|
|
53
|
+
console.log(`🗑️ [WS-MANAGER-CACHE] Removing manager from cache: ${cacheKey}`);
|
|
54
|
+
manager.disconnect();
|
|
55
|
+
wsManagerCache.delete(cacheKey);
|
|
56
|
+
console.log(`🗑️ [WS-MANAGER-CACHE] Manager removed, remaining managers: ${wsManagerCache.size}`);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
console.log(`⚠️ [WS-MANAGER-CACHE] Manager not found in cache: ${cacheKey}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Clear all cached WebSocket managers.
|
|
64
|
+
*/
|
|
65
|
+
function clearXYWebSocketManagers() {
|
|
66
|
+
const log = runtime?.log ?? console.log;
|
|
67
|
+
log("Clearing all WebSocket manager caches");
|
|
68
|
+
for (const manager of wsManagerCache.values()) {
|
|
69
|
+
manager.disconnect();
|
|
70
|
+
}
|
|
71
|
+
wsManagerCache.clear();
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Get the number of cached managers.
|
|
75
|
+
*/
|
|
76
|
+
function getCachedManagerCount() {
|
|
77
|
+
return wsManagerCache.size;
|
|
78
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { OpenClawConfig } from "openclaw/dist/plugin-sdk/index.js";
|
|
2
|
+
import type { XiaoYiChannelConfig } from "./types.js";
|
|
3
|
+
type ClawdbotConfig = OpenClawConfig;
|
|
4
|
+
/**
|
|
5
|
+
* Resolve XiaoYi channel configuration from OpenClaw config.
|
|
6
|
+
*/
|
|
7
|
+
export declare function resolveXYConfig(cfg: ClawdbotConfig): XiaoYiChannelConfig;
|
|
8
|
+
/**
|
|
9
|
+
* List XiaoYi channel account IDs.
|
|
10
|
+
* Single account mode - always returns ["default"].
|
|
11
|
+
*/
|
|
12
|
+
export declare function listXYAccountIds(cfg: ClawdbotConfig): string[];
|
|
13
|
+
/**
|
|
14
|
+
* Get default XiaoYi channel account ID.
|
|
15
|
+
* Single account mode - always returns "default".
|
|
16
|
+
*/
|
|
17
|
+
export declare function getDefaultXYAccountId(cfg: ClawdbotConfig): string | undefined;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveXYConfig = resolveXYConfig;
|
|
4
|
+
exports.listXYAccountIds = listXYAccountIds;
|
|
5
|
+
exports.getDefaultXYAccountId = getDefaultXYAccountId;
|
|
6
|
+
/**
|
|
7
|
+
* Resolve XiaoYi channel configuration from OpenClaw config.
|
|
8
|
+
*/
|
|
9
|
+
function resolveXYConfig(cfg) {
|
|
10
|
+
const channelConfig = cfg?.channels?.xiaoyi;
|
|
11
|
+
if (!channelConfig) {
|
|
12
|
+
throw new Error("XiaoYi channel configuration not found");
|
|
13
|
+
}
|
|
14
|
+
return channelConfig;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* List XiaoYi channel account IDs.
|
|
18
|
+
* Single account mode - always returns ["default"].
|
|
19
|
+
*/
|
|
20
|
+
function listXYAccountIds(cfg) {
|
|
21
|
+
const channelConfig = cfg?.channels?.xiaoyi;
|
|
22
|
+
if (!channelConfig || !channelConfig.enabled) {
|
|
23
|
+
return [];
|
|
24
|
+
}
|
|
25
|
+
return ["default"];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Get default XiaoYi channel account ID.
|
|
29
|
+
* Single account mode - always returns "default".
|
|
30
|
+
*/
|
|
31
|
+
function getDefaultXYAccountId(cfg) {
|
|
32
|
+
const channelConfig = cfg?.channels?.xiaoyi;
|
|
33
|
+
if (!channelConfig || !channelConfig.enabled) {
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
return "default";
|
|
37
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import type { XiaoYiChannelConfig, A2ACommand } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Parameters for sending an A2A response.
|
|
4
|
+
*/
|
|
5
|
+
export interface SendA2AResponseParams {
|
|
6
|
+
config: XiaoYiChannelConfig;
|
|
7
|
+
sessionId: string;
|
|
8
|
+
taskId: string;
|
|
9
|
+
messageId: string;
|
|
10
|
+
text?: string;
|
|
11
|
+
append: boolean;
|
|
12
|
+
final: boolean;
|
|
13
|
+
files?: Array<{
|
|
14
|
+
fileName: string;
|
|
15
|
+
fileType: string;
|
|
16
|
+
fileId: string;
|
|
17
|
+
}>;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Send an A2A artifact update response.
|
|
21
|
+
*/
|
|
22
|
+
export declare function sendA2AResponse(params: SendA2AResponseParams): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Parameters for sending a reasoning text update (intermediate, streamed).
|
|
25
|
+
*/
|
|
26
|
+
export interface SendReasoningTextUpdateParams {
|
|
27
|
+
config: XiaoYiChannelConfig;
|
|
28
|
+
sessionId: string;
|
|
29
|
+
taskId: string;
|
|
30
|
+
messageId: string;
|
|
31
|
+
text: string;
|
|
32
|
+
append?: boolean;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Send an A2A artifact-update with reasoningText part.
|
|
36
|
+
* Used for onToolStart, onToolResult, onReasoningStream, onReasoningEnd, onPartialReply.
|
|
37
|
+
* append=true, final=false, lastChunk=true, text is suffixed with newline for markdown rendering.
|
|
38
|
+
*/
|
|
39
|
+
export declare function sendReasoningTextUpdate(params: SendReasoningTextUpdateParams): Promise<void>;
|
|
40
|
+
/**
|
|
41
|
+
* Parameters for sending a status update.
|
|
42
|
+
*/
|
|
43
|
+
export interface SendStatusUpdateParams {
|
|
44
|
+
config: XiaoYiChannelConfig;
|
|
45
|
+
sessionId: string;
|
|
46
|
+
taskId: string;
|
|
47
|
+
messageId: string;
|
|
48
|
+
text: string;
|
|
49
|
+
state: "submitted" | "working" | "input-required" | "completed" | "canceled" | "failed" | "unknown";
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Send an A2A task status update.
|
|
53
|
+
* Follows A2A protocol standard format with nested status object.
|
|
54
|
+
*/
|
|
55
|
+
export declare function sendStatusUpdate(params: SendStatusUpdateParams): Promise<void>;
|
|
56
|
+
/**
|
|
57
|
+
* Parameters for sending a command.
|
|
58
|
+
*/
|
|
59
|
+
export interface SendCommandParams {
|
|
60
|
+
config: XiaoYiChannelConfig;
|
|
61
|
+
sessionId: string;
|
|
62
|
+
taskId: string;
|
|
63
|
+
messageId: string;
|
|
64
|
+
command: A2ACommand;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Send a command as an artifact update (final=false).
|
|
68
|
+
*/
|
|
69
|
+
export declare function sendCommand(params: SendCommandParams): Promise<void>;
|
|
70
|
+
/**
|
|
71
|
+
* Parameters for sending a clearContext response.
|
|
72
|
+
*/
|
|
73
|
+
export interface SendClearContextResponseParams {
|
|
74
|
+
config: XiaoYiChannelConfig;
|
|
75
|
+
sessionId: string;
|
|
76
|
+
messageId: string;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Send a clearContext response.
|
|
80
|
+
*/
|
|
81
|
+
export declare function sendClearContextResponse(params: SendClearContextResponseParams): Promise<void>;
|
|
82
|
+
/**
|
|
83
|
+
* Parameters for sending a tasks/cancel response.
|
|
84
|
+
*/
|
|
85
|
+
export interface SendTasksCancelResponseParams {
|
|
86
|
+
config: XiaoYiChannelConfig;
|
|
87
|
+
sessionId: string;
|
|
88
|
+
taskId: string;
|
|
89
|
+
messageId: string;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Send a tasks/cancel response.
|
|
93
|
+
*/
|
|
94
|
+
export declare function sendTasksCancelResponse(params: SendTasksCancelResponseParams): Promise<void>;
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.sendA2AResponse = sendA2AResponse;
|
|
4
|
+
exports.sendReasoningTextUpdate = sendReasoningTextUpdate;
|
|
5
|
+
exports.sendStatusUpdate = sendStatusUpdate;
|
|
6
|
+
exports.sendCommand = sendCommand;
|
|
7
|
+
exports.sendClearContextResponse = sendClearContextResponse;
|
|
8
|
+
exports.sendTasksCancelResponse = sendTasksCancelResponse;
|
|
9
|
+
// OpenClaw → A2A format conversion
|
|
10
|
+
const uuid_1 = require("uuid");
|
|
11
|
+
const xy_client_js_1 = require("./xy-client.js");
|
|
12
|
+
const runtime_js_1 = require("./runtime.js");
|
|
13
|
+
/**
|
|
14
|
+
* Send an A2A artifact update response.
|
|
15
|
+
*/
|
|
16
|
+
async function sendA2AResponse(params) {
|
|
17
|
+
const { config, sessionId, taskId, messageId, text, append, final, files } = params;
|
|
18
|
+
const runtime = (0, runtime_js_1.getXiaoYiRuntime)();
|
|
19
|
+
const log = runtime?.log ?? console.log;
|
|
20
|
+
const error = runtime?.error ?? console.error;
|
|
21
|
+
// Build artifact update event
|
|
22
|
+
const artifact = {
|
|
23
|
+
taskId,
|
|
24
|
+
kind: "artifact-update",
|
|
25
|
+
append,
|
|
26
|
+
lastChunk: true,
|
|
27
|
+
final,
|
|
28
|
+
artifact: {
|
|
29
|
+
artifactId: (0, uuid_1.v4)(),
|
|
30
|
+
parts: [],
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
// Add text part (even if empty string, to maintain parts structure)
|
|
34
|
+
if (text !== undefined) {
|
|
35
|
+
artifact.artifact.parts.push({
|
|
36
|
+
kind: "text",
|
|
37
|
+
text,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
// Add file parts if provided
|
|
41
|
+
if (files && files.length > 0) {
|
|
42
|
+
artifact.artifact.parts.push({
|
|
43
|
+
kind: "data",
|
|
44
|
+
data: { fileInfo: files },
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
// Build JSON-RPC response
|
|
48
|
+
const jsonRpcResponse = {
|
|
49
|
+
jsonrpc: "2.0",
|
|
50
|
+
id: messageId,
|
|
51
|
+
result: artifact,
|
|
52
|
+
};
|
|
53
|
+
// Send via WebSocket
|
|
54
|
+
const wsManager = (0, xy_client_js_1.getXYWebSocketManager)(config);
|
|
55
|
+
const outboundMessage = {
|
|
56
|
+
msgType: "agent_response",
|
|
57
|
+
agentId: config.agentId,
|
|
58
|
+
sessionId,
|
|
59
|
+
taskId,
|
|
60
|
+
msgDetail: JSON.stringify(jsonRpcResponse),
|
|
61
|
+
};
|
|
62
|
+
// 📋 Log complete response body
|
|
63
|
+
log(`[A2A_RESPONSE] 📤 Sending A2A artifact-update response:`);
|
|
64
|
+
log(`[A2A_RESPONSE] - sessionId: ${sessionId}`);
|
|
65
|
+
log(`[A2A_RESPONSE] - taskId: ${taskId}`);
|
|
66
|
+
log(`[A2A_RESPONSE] - messageId: ${messageId}`);
|
|
67
|
+
log(`[A2A_RESPONSE] - append: ${append}`);
|
|
68
|
+
log(`[A2A_RESPONSE] - final: ${final}`);
|
|
69
|
+
log(`[A2A_RESPONSE] - text length: ${text?.length ?? 0}`);
|
|
70
|
+
log(`[A2A_RESPONSE] - files count: ${files?.length ?? 0}`);
|
|
71
|
+
log(`[A2A_RESPONSE] 📦 Complete outbound message:`);
|
|
72
|
+
log(JSON.stringify(outboundMessage, null, 2));
|
|
73
|
+
log(`[A2A_RESPONSE] 📦 JSON-RPC response body:`);
|
|
74
|
+
log(JSON.stringify(jsonRpcResponse, null, 2));
|
|
75
|
+
await wsManager.sendMessage(sessionId, outboundMessage);
|
|
76
|
+
log(`[A2A_RESPONSE] ✅ Message sent successfully`);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Send an A2A artifact-update with reasoningText part.
|
|
80
|
+
* Used for onToolStart, onToolResult, onReasoningStream, onReasoningEnd, onPartialReply.
|
|
81
|
+
* append=true, final=false, lastChunk=true, text is suffixed with newline for markdown rendering.
|
|
82
|
+
*/
|
|
83
|
+
async function sendReasoningTextUpdate(params) {
|
|
84
|
+
const { config, sessionId, taskId, messageId, text, append = true } = params;
|
|
85
|
+
const runtime = (0, runtime_js_1.getXiaoYiRuntime)();
|
|
86
|
+
const log = runtime?.log ?? console.log;
|
|
87
|
+
const error = runtime?.error ?? console.error;
|
|
88
|
+
const artifact = {
|
|
89
|
+
taskId,
|
|
90
|
+
kind: "artifact-update",
|
|
91
|
+
append,
|
|
92
|
+
lastChunk: true,
|
|
93
|
+
final: false,
|
|
94
|
+
artifact: {
|
|
95
|
+
artifactId: (0, uuid_1.v4)(),
|
|
96
|
+
parts: [
|
|
97
|
+
{
|
|
98
|
+
kind: "reasoningText",
|
|
99
|
+
reasoningText: text,
|
|
100
|
+
},
|
|
101
|
+
],
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
const jsonRpcResponse = {
|
|
105
|
+
jsonrpc: "2.0",
|
|
106
|
+
id: messageId,
|
|
107
|
+
result: artifact,
|
|
108
|
+
};
|
|
109
|
+
const wsManager = (0, xy_client_js_1.getXYWebSocketManager)(config);
|
|
110
|
+
const outboundMessage = {
|
|
111
|
+
msgType: "agent_response",
|
|
112
|
+
agentId: config.agentId,
|
|
113
|
+
sessionId,
|
|
114
|
+
taskId,
|
|
115
|
+
msgDetail: JSON.stringify(jsonRpcResponse),
|
|
116
|
+
};
|
|
117
|
+
log(`[REASONING_TEXT] 📤 Sending reasoningText update: sessionId=${sessionId}, taskId=${taskId}, text.length=${text.length}`);
|
|
118
|
+
await wsManager.sendMessage(sessionId, outboundMessage);
|
|
119
|
+
log(`[REASONING_TEXT] ✅ Sent successfully`);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Send an A2A task status update.
|
|
123
|
+
* Follows A2A protocol standard format with nested status object.
|
|
124
|
+
*/
|
|
125
|
+
async function sendStatusUpdate(params) {
|
|
126
|
+
const { config, sessionId, taskId, messageId, text, state } = params;
|
|
127
|
+
const runtime = (0, runtime_js_1.getXiaoYiRuntime)();
|
|
128
|
+
const log = runtime?.log ?? console.log;
|
|
129
|
+
const error = runtime?.error ?? console.error;
|
|
130
|
+
// Build status update event following A2A protocol standard
|
|
131
|
+
const statusUpdate = {
|
|
132
|
+
taskId,
|
|
133
|
+
kind: "status-update",
|
|
134
|
+
final: false, // Status updates should not end the stream
|
|
135
|
+
status: {
|
|
136
|
+
message: {
|
|
137
|
+
role: "agent",
|
|
138
|
+
parts: [
|
|
139
|
+
{
|
|
140
|
+
kind: "text",
|
|
141
|
+
text,
|
|
142
|
+
},
|
|
143
|
+
],
|
|
144
|
+
},
|
|
145
|
+
state,
|
|
146
|
+
},
|
|
147
|
+
};
|
|
148
|
+
// Build JSON-RPC response
|
|
149
|
+
const jsonRpcResponse = {
|
|
150
|
+
jsonrpc: "2.0",
|
|
151
|
+
id: messageId,
|
|
152
|
+
result: statusUpdate,
|
|
153
|
+
};
|
|
154
|
+
// Send via WebSocket
|
|
155
|
+
const wsManager = (0, xy_client_js_1.getXYWebSocketManager)(config);
|
|
156
|
+
const outboundMessage = {
|
|
157
|
+
msgType: "agent_response",
|
|
158
|
+
agentId: config.agentId,
|
|
159
|
+
sessionId,
|
|
160
|
+
taskId,
|
|
161
|
+
msgDetail: JSON.stringify(jsonRpcResponse),
|
|
162
|
+
};
|
|
163
|
+
// 📋 Log complete response body
|
|
164
|
+
log(`[A2A_STATUS] 📤 Sending A2A status-update:`);
|
|
165
|
+
log(`[A2A_STATUS] - sessionId: ${sessionId}`);
|
|
166
|
+
log(`[A2A_STATUS] - taskId: ${taskId}`);
|
|
167
|
+
log(`[A2A_STATUS] - messageId: ${messageId}`);
|
|
168
|
+
log(`[A2A_STATUS] - state: ${state}`);
|
|
169
|
+
log(`[A2A_STATUS] - text: "${text}"`);
|
|
170
|
+
log(`[A2A_STATUS] 📦 Complete outbound message:`);
|
|
171
|
+
log(JSON.stringify(outboundMessage, null, 2));
|
|
172
|
+
log(`[A2A_STATUS] 📦 JSON-RPC response body:`);
|
|
173
|
+
log(JSON.stringify(jsonRpcResponse, null, 2));
|
|
174
|
+
await wsManager.sendMessage(sessionId, outboundMessage);
|
|
175
|
+
log(`[A2A_STATUS] ✅ Status update sent successfully`);
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Send a command as an artifact update (final=false).
|
|
179
|
+
*/
|
|
180
|
+
async function sendCommand(params) {
|
|
181
|
+
const { config, sessionId, taskId, messageId, command } = params;
|
|
182
|
+
const runtime = (0, runtime_js_1.getXiaoYiRuntime)();
|
|
183
|
+
const log = runtime?.log ?? console.log;
|
|
184
|
+
const error = runtime?.error ?? console.error;
|
|
185
|
+
// Build artifact update with command as data
|
|
186
|
+
// Wrap command in commands array as per protocol requirement
|
|
187
|
+
const artifact = {
|
|
188
|
+
taskId,
|
|
189
|
+
kind: "artifact-update",
|
|
190
|
+
append: false,
|
|
191
|
+
lastChunk: true,
|
|
192
|
+
final: false, // Commands are not final
|
|
193
|
+
artifact: {
|
|
194
|
+
artifactId: (0, uuid_1.v4)(),
|
|
195
|
+
parts: [
|
|
196
|
+
{
|
|
197
|
+
kind: "data",
|
|
198
|
+
data: {
|
|
199
|
+
commands: [command],
|
|
200
|
+
},
|
|
201
|
+
},
|
|
202
|
+
],
|
|
203
|
+
},
|
|
204
|
+
};
|
|
205
|
+
// Build JSON-RPC response
|
|
206
|
+
const jsonRpcResponse = {
|
|
207
|
+
jsonrpc: "2.0",
|
|
208
|
+
id: messageId,
|
|
209
|
+
result: artifact,
|
|
210
|
+
};
|
|
211
|
+
// Send via WebSocket
|
|
212
|
+
const wsManager = (0, xy_client_js_1.getXYWebSocketManager)(config);
|
|
213
|
+
const outboundMessage = {
|
|
214
|
+
msgType: "agent_response",
|
|
215
|
+
agentId: config.agentId,
|
|
216
|
+
sessionId,
|
|
217
|
+
taskId,
|
|
218
|
+
msgDetail: JSON.stringify(jsonRpcResponse),
|
|
219
|
+
};
|
|
220
|
+
// 📋 Log complete response body
|
|
221
|
+
log(`[A2A_COMMAND] 📤 Sending A2A command:`);
|
|
222
|
+
log(`[A2A_COMMAND] - sessionId: ${sessionId}`);
|
|
223
|
+
log(`[A2A_COMMAND] - taskId: ${taskId}`);
|
|
224
|
+
log(`[A2A_COMMAND] - messageId: ${messageId}`);
|
|
225
|
+
log(`[A2A_COMMAND] - command: ${command.header.namespace}::${command.header.name}`);
|
|
226
|
+
log(`[A2A_COMMAND] 📦 Complete outbound message:`);
|
|
227
|
+
log(JSON.stringify(outboundMessage, null, 2));
|
|
228
|
+
log(`[A2A_COMMAND] 📦 JSON-RPC response body:`);
|
|
229
|
+
log(JSON.stringify(jsonRpcResponse, null, 2));
|
|
230
|
+
await wsManager.sendMessage(sessionId, outboundMessage);
|
|
231
|
+
log(`[A2A_COMMAND] ✅ Command sent successfully`);
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Send a clearContext response.
|
|
235
|
+
*/
|
|
236
|
+
async function sendClearContextResponse(params) {
|
|
237
|
+
const { config, sessionId, messageId } = params;
|
|
238
|
+
const runtime = (0, runtime_js_1.getXiaoYiRuntime)();
|
|
239
|
+
const log = runtime?.log ?? console.log;
|
|
240
|
+
const error = runtime?.error ?? console.error;
|
|
241
|
+
// Build JSON-RPC response for clearContext
|
|
242
|
+
const jsonRpcResponse = {
|
|
243
|
+
jsonrpc: "2.0",
|
|
244
|
+
id: messageId,
|
|
245
|
+
result: {
|
|
246
|
+
status: {
|
|
247
|
+
state: "cleared",
|
|
248
|
+
},
|
|
249
|
+
},
|
|
250
|
+
error: {
|
|
251
|
+
code: 0,
|
|
252
|
+
// Note: Using any to bypass type check as the response format differs from standard A2A types
|
|
253
|
+
message: "",
|
|
254
|
+
},
|
|
255
|
+
};
|
|
256
|
+
// Send via WebSocket
|
|
257
|
+
const wsManager = (0, xy_client_js_1.getXYWebSocketManager)(config);
|
|
258
|
+
const outboundMessage = {
|
|
259
|
+
msgType: "agent_response",
|
|
260
|
+
agentId: config.agentId,
|
|
261
|
+
sessionId,
|
|
262
|
+
taskId: sessionId, // Use sessionId as taskId for clearContext
|
|
263
|
+
msgDetail: JSON.stringify(jsonRpcResponse),
|
|
264
|
+
};
|
|
265
|
+
await wsManager.sendMessage(sessionId, outboundMessage);
|
|
266
|
+
log(`Sent clearContext response: sessionId=${sessionId}`);
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Send a tasks/cancel response.
|
|
270
|
+
*/
|
|
271
|
+
async function sendTasksCancelResponse(params) {
|
|
272
|
+
const { config, sessionId, taskId, messageId } = params;
|
|
273
|
+
const runtime = (0, runtime_js_1.getXiaoYiRuntime)();
|
|
274
|
+
const log = runtime?.log ?? console.log;
|
|
275
|
+
const error = runtime?.error ?? console.error;
|
|
276
|
+
// Build JSON-RPC response for tasks/cancel
|
|
277
|
+
// Note: Using any to bypass type check as the response format differs from standard A2A types
|
|
278
|
+
const jsonRpcResponse = {
|
|
279
|
+
jsonrpc: "2.0",
|
|
280
|
+
id: messageId,
|
|
281
|
+
result: {
|
|
282
|
+
id: taskId,
|
|
283
|
+
status: {
|
|
284
|
+
state: "canceled",
|
|
285
|
+
},
|
|
286
|
+
},
|
|
287
|
+
error: {
|
|
288
|
+
code: 0,
|
|
289
|
+
message: "",
|
|
290
|
+
},
|
|
291
|
+
};
|
|
292
|
+
// Send via WebSocket
|
|
293
|
+
const wsManager = (0, xy_client_js_1.getXYWebSocketManager)(config);
|
|
294
|
+
const outboundMessage = {
|
|
295
|
+
msgType: "agent_response",
|
|
296
|
+
agentId: config.agentId,
|
|
297
|
+
sessionId,
|
|
298
|
+
taskId,
|
|
299
|
+
msgDetail: JSON.stringify(jsonRpcResponse),
|
|
300
|
+
};
|
|
301
|
+
await wsManager.sendMessage(sessionId, outboundMessage);
|
|
302
|
+
log(`Sent tasks/cancel response: sessionId=${sessionId}, taskId=${taskId}`);
|
|
303
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { RuntimeEnv } from "openclaw/dist/plugin-sdk/index.js";
|
|
2
|
+
export type MonitorXYOpts = {
|
|
3
|
+
config?: any;
|
|
4
|
+
runtime?: RuntimeEnv;
|
|
5
|
+
abortSignal?: AbortSignal;
|
|
6
|
+
accountId?: string;
|
|
7
|
+
setStatus?: (status: {
|
|
8
|
+
lastEventAt?: number;
|
|
9
|
+
lastInboundAt?: number;
|
|
10
|
+
connected?: boolean;
|
|
11
|
+
}) => void;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Monitor XY channel WebSocket connections.
|
|
15
|
+
* Keeps the connection alive until abortSignal is triggered.
|
|
16
|
+
*/
|
|
17
|
+
export declare function monitorXYProvider(opts?: MonitorXYOpts): Promise<void>;
|