@ynhcj/xiaoyi-channel 0.0.185-beta → 0.0.185-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/index.js +141 -1
- package/dist/src/acp-session-binding.d.ts +37 -0
- package/dist/src/acp-session-binding.js +237 -0
- package/dist/src/bot.js +62 -33
- package/dist/src/channel.js +68 -64
- package/dist/src/client.d.ts +5 -0
- package/dist/src/client.js +10 -0
- package/dist/src/cron-command.d.ts +2 -0
- package/dist/src/cron-command.js +14 -8
- package/dist/src/cron-query-handler.js +36 -0
- package/dist/src/cspl/call_api.js +4 -2
- package/dist/src/cspl/sentinel_hook.js +9 -8
- package/dist/src/cspl/upload_file.js +2 -2
- package/dist/src/formatter.js +72 -36
- package/dist/src/log-reporter/config-loader.d.ts +11 -0
- package/dist/src/log-reporter/config-loader.js +68 -0
- package/dist/src/log-reporter/cursor-store.d.ts +5 -0
- package/dist/src/log-reporter/cursor-store.js +26 -0
- package/dist/src/log-reporter/index.d.ts +10 -0
- package/dist/src/log-reporter/index.js +77 -0
- package/dist/src/log-reporter/reporter.d.ts +6 -0
- package/dist/src/log-reporter/reporter.js +17 -0
- package/dist/src/log-reporter/scanner.d.ts +6 -0
- package/dist/src/log-reporter/scanner.js +82 -0
- package/dist/src/log-reporter/types.d.ts +59 -0
- package/dist/src/log-reporter/types.js +2 -0
- package/dist/src/log-reporter/uploader.d.ts +6 -0
- package/dist/src/log-reporter/uploader.js +32 -0
- package/dist/src/memory-query-handler.d.ts +1 -0
- package/dist/src/memory-query-handler.js +283 -0
- package/dist/src/monitor.js +29 -9
- package/dist/src/outbound.js +5 -0
- package/dist/src/parser.d.ts +12 -0
- package/dist/src/parser.js +39 -13
- package/dist/src/provider.js +79 -16
- package/dist/src/reply-dispatcher.d.ts +3 -0
- package/dist/src/reply-dispatcher.js +166 -164
- package/dist/src/self-evolution-handler.js +2 -1
- package/dist/src/task-manager.d.ts +5 -6
- package/dist/src/task-manager.js +5 -9
- package/dist/src/tools/agent-as-skill-tool.d.ts +41 -2
- package/dist/src/tools/agent-as-skill-tool.js +144 -151
- package/dist/src/tools/calendar-tool.d.ts +24 -2
- package/dist/src/tools/calendar-tool.js +115 -117
- package/dist/src/tools/call-device-tool.d.ts +20 -6
- package/dist/src/tools/call-device-tool.js +116 -138
- package/dist/src/tools/call-phone-tool.d.ts +21 -2
- package/dist/src/tools/call-phone-tool.js +112 -114
- package/dist/src/tools/check-plugin-privilege-tool.d.ts +16 -2
- package/dist/src/tools/check-plugin-privilege-tool.js +141 -143
- package/dist/src/tools/create-alarm-tool.d.ts +39 -2
- package/dist/src/tools/create-alarm-tool.js +229 -231
- package/dist/src/tools/create-all-tools.js +8 -4
- package/dist/src/tools/delete-alarm-tool.d.ts +15 -2
- package/dist/src/tools/delete-alarm-tool.js +134 -136
- package/dist/src/tools/device-tool-map.d.ts +1 -1
- package/dist/src/tools/device-tool-map.js +9 -2
- package/dist/src/tools/discover-cross-devices-tool.d.ts +16 -2
- package/dist/src/tools/discover-cross-devices-tool.js +121 -124
- package/dist/src/tools/display-a2ui-card-bypath-tool.d.ts +21 -0
- package/dist/src/tools/display-a2ui-card-bypath-tool.js +65 -0
- package/dist/src/tools/get-alarm-tool-schema.d.ts +1 -2
- package/dist/src/tools/get-alarm-tool-schema.js +10 -16
- package/dist/src/tools/get-calendar-tool-schema.d.ts +1 -2
- package/dist/src/tools/get-calendar-tool-schema.js +8 -12
- package/dist/src/tools/get-collection-tool-schema.d.ts +1 -2
- package/dist/src/tools/get-collection-tool-schema.js +9 -11
- package/dist/src/tools/get-contact-tool-schema.d.ts +1 -2
- package/dist/src/tools/get-contact-tool-schema.js +10 -16
- package/dist/src/tools/get-device-file-tool-schema.d.ts +1 -2
- package/dist/src/tools/get-device-file-tool-schema.js +9 -13
- package/dist/src/tools/get-email-tool-schema.d.ts +1 -2
- package/dist/src/tools/get-email-tool-schema.js +8 -11
- package/dist/src/tools/get-note-tool-schema.d.ts +1 -2
- package/dist/src/tools/get-note-tool-schema.js +9 -14
- package/dist/src/tools/get-photo-tool-schema.d.ts +1 -2
- package/dist/src/tools/get-photo-tool-schema.js +9 -12
- package/dist/src/tools/image-reading-tool.d.ts +28 -2
- package/dist/src/tools/image-reading-tool.js +76 -76
- package/dist/src/tools/location-tool.d.ts +11 -2
- package/dist/src/tools/location-tool.js +93 -92
- package/dist/src/tools/login-token-tool.d.ts +20 -2
- package/dist/src/tools/login-token-tool.js +123 -125
- package/dist/src/tools/modify-alarm-tool.d.ts +47 -2
- package/dist/src/tools/modify-alarm-tool.js +250 -252
- package/dist/src/tools/modify-note-tool.d.ts +20 -2
- package/dist/src/tools/modify-note-tool.js +107 -109
- package/dist/src/tools/note-tool.d.ts +20 -2
- package/dist/src/tools/note-tool.js +106 -108
- package/dist/src/tools/query-app-message-tool.d.ts +28 -2
- package/dist/src/tools/query-app-message-tool.js +111 -113
- package/dist/src/tools/query-memory-data-tool.d.ts +28 -2
- package/dist/src/tools/query-memory-data-tool.js +112 -114
- package/dist/src/tools/query-todo-task-tool.d.ts +24 -2
- package/dist/src/tools/query-todo-task-tool.js +106 -108
- package/dist/src/tools/save-file-to-phone-tool.d.ts +24 -2
- package/dist/src/tools/save-file-to-phone-tool.js +130 -132
- package/dist/src/tools/save-media-to-gallery-tool.d.ts +24 -2
- package/dist/src/tools/save-media-to-gallery-tool.js +137 -139
- package/dist/src/tools/save-self-evolution-skill-tool.d.ts +54 -2
- package/dist/src/tools/save-self-evolution-skill-tool.js +194 -194
- package/dist/src/tools/search-alarm-tool.d.ts +34 -2
- package/dist/src/tools/search-alarm-tool.js +174 -176
- package/dist/src/tools/search-calendar-tool.d.ts +24 -2
- package/dist/src/tools/search-calendar-tool.js +148 -150
- package/dist/src/tools/search-contact-tool.d.ts +16 -2
- package/dist/src/tools/search-contact-tool.js +101 -103
- package/dist/src/tools/search-email-tool.d.ts +21 -2
- package/dist/src/tools/search-email-tool.js +110 -112
- package/dist/src/tools/search-file-tool.d.ts +16 -2
- package/dist/src/tools/search-file-tool.js +104 -106
- package/dist/src/tools/search-message-tool.d.ts +16 -2
- package/dist/src/tools/search-message-tool.js +103 -105
- package/dist/src/tools/search-note-tool.d.ts +16 -2
- package/dist/src/tools/search-note-tool.js +98 -100
- package/dist/src/tools/search-photo-gallery-tool.d.ts +21 -2
- package/dist/src/tools/search-photo-gallery-tool.js +35 -37
- package/dist/src/tools/send-cross-device-task-tool.d.ts +35 -2
- package/dist/src/tools/send-cross-device-task-tool.js +216 -150
- package/dist/src/tools/send-email-tool.d.ts +24 -2
- package/dist/src/tools/send-email-tool.js +108 -110
- package/dist/src/tools/send-file-to-user-tool.d.ts +20 -2
- package/dist/src/tools/send-file-to-user-tool.js +174 -178
- package/dist/src/tools/send-html-card-tool.d.ts +20 -2
- package/dist/src/tools/send-html-card-tool.js +85 -87
- package/dist/src/tools/send-message-tool.d.ts +20 -2
- package/dist/src/tools/send-message-tool.js +122 -124
- package/dist/src/tools/session-manager.d.ts +19 -52
- package/dist/src/tools/session-manager.js +95 -247
- package/dist/src/tools/upload-file-tool.d.ts +20 -2
- package/dist/src/tools/upload-file-tool.js +80 -82
- package/dist/src/tools/upload-photo-tool.d.ts +20 -2
- package/dist/src/tools/upload-photo-tool.js +68 -70
- package/dist/src/tools/xiaoyi-add-collection-tool.d.ts +32 -2
- package/dist/src/tools/xiaoyi-add-collection-tool.js +146 -148
- package/dist/src/tools/xiaoyi-collection-tool.d.ts +20 -2
- package/dist/src/tools/xiaoyi-collection-tool.js +114 -116
- package/dist/src/tools/xiaoyi-delete-collection-tool.d.ts +15 -2
- package/dist/src/tools/xiaoyi-delete-collection-tool.js +127 -129
- package/dist/src/tools/xiaoyi-gui-tool.d.ts +16 -2
- package/dist/src/tools/xiaoyi-gui-tool.js +92 -95
- package/dist/src/types.d.ts +6 -6
- package/dist/src/utils/config-manager.d.ts +3 -2
- package/dist/src/utils/config-manager.js +22 -2
- package/dist/src/utils/cron-push-map.d.ts +26 -0
- package/dist/src/utils/cron-push-map.js +131 -0
- package/dist/src/utils/logger.js +3 -14
- package/dist/src/websocket.d.ts +1 -1
- package/dist/src/websocket.js +29 -13
- package/package.json +1 -1
package/dist/src/channel.js
CHANGED
|
@@ -2,15 +2,55 @@ import { resolveXYConfig, listXYAccountIds, getDefaultXYAccountId } from "./conf
|
|
|
2
2
|
import { xyConfigSchema } from "./config-schema.js";
|
|
3
3
|
import { xyOutbound } from "./outbound.js";
|
|
4
4
|
import { filterToolsByDevice } from "./tools/device-tool-map.js";
|
|
5
|
-
import { getCurrentSessionContext
|
|
6
|
-
import { createAllTools } from "./tools/create-all-tools.js";
|
|
5
|
+
import { getCurrentSessionContext } from "./tools/session-manager.js";
|
|
7
6
|
import { logger } from "./utils/logger.js";
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
7
|
+
// Static tool imports (3.24 pattern)
|
|
8
|
+
import { locationTool } from "./tools/location-tool.js";
|
|
9
|
+
import { xiaoyiGuiTool } from "./tools/xiaoyi-gui-tool.js";
|
|
10
|
+
import { sendFileToUserTool } from "./tools/send-file-to-user-tool.js";
|
|
11
|
+
import { sendHtmlCardTool } from "./tools/send-html-card-tool.js";
|
|
12
|
+
import { viewPushResultTool } from "./tools/view-push-result-tool.js";
|
|
13
|
+
import { imageReadingTool } from "./tools/image-reading-tool.js";
|
|
14
|
+
import { timestampToUtc8Tool } from "./tools/timestamp-to-utc8-tool.js";
|
|
15
|
+
import { saveSelfEvolutionSkillTool } from "./tools/save-self-evolution-skill-tool.js";
|
|
16
|
+
import { callDeviceTool } from "./tools/call-device-tool.js";
|
|
17
|
+
import { getNoteToolSchemaTool } from "./tools/get-note-tool-schema.js";
|
|
18
|
+
import { getCalendarToolSchemaTool } from "./tools/get-calendar-tool-schema.js";
|
|
19
|
+
import { getContactToolSchemaTool } from "./tools/get-contact-tool-schema.js";
|
|
20
|
+
import { getPhotoToolSchemaTool } from "./tools/get-photo-tool-schema.js";
|
|
21
|
+
import { getDeviceFileToolSchemaTool } from "./tools/get-device-file-tool-schema.js";
|
|
22
|
+
import { getAlarmToolSchemaTool } from "./tools/get-alarm-tool-schema.js";
|
|
23
|
+
import { getCollectionToolSchemaTool } from "./tools/get-collection-tool-schema.js";
|
|
24
|
+
import { loginTokenTool } from "./tools/login-token-tool.js";
|
|
25
|
+
import { agentAsSkillTool } from "./tools/agent-as-skill-tool.js";
|
|
26
|
+
import { discoverCrossDevicesTool } from "./tools/discover-cross-devices-tool.js";
|
|
27
|
+
import { sendCrossDeviceTaskTool } from "./tools/send-cross-device-task-tool.js";
|
|
28
|
+
import { displayA2UICardByPathTool } from "./tools/display-a2ui-card-bypath-tool.js";
|
|
29
|
+
import { checkPluginPrivilegeTool } from "./tools/check-plugin-privilege-tool.js";
|
|
30
|
+
const ALL_TOOLS = [
|
|
31
|
+
locationTool,
|
|
32
|
+
discoverCrossDevicesTool,
|
|
33
|
+
sendCrossDeviceTaskTool,
|
|
34
|
+
displayA2UICardByPathTool,
|
|
35
|
+
callDeviceTool,
|
|
36
|
+
getNoteToolSchemaTool,
|
|
37
|
+
getCalendarToolSchemaTool,
|
|
38
|
+
getContactToolSchemaTool,
|
|
39
|
+
getPhotoToolSchemaTool,
|
|
40
|
+
xiaoyiGuiTool,
|
|
41
|
+
getDeviceFileToolSchemaTool,
|
|
42
|
+
getAlarmToolSchemaTool,
|
|
43
|
+
getCollectionToolSchemaTool,
|
|
44
|
+
sendFileToUserTool,
|
|
45
|
+
sendHtmlCardTool,
|
|
46
|
+
viewPushResultTool,
|
|
47
|
+
imageReadingTool,
|
|
48
|
+
timestampToUtc8Tool,
|
|
49
|
+
saveSelfEvolutionSkillTool,
|
|
50
|
+
loginTokenTool,
|
|
51
|
+
agentAsSkillTool,
|
|
52
|
+
checkPluginPrivilegeTool,
|
|
53
|
+
];
|
|
14
54
|
/**
|
|
15
55
|
* Xiaoyi Channel Plugin for OpenClaw.
|
|
16
56
|
* Implements Xiaoyi A2A protocol with dual WebSocket connections.
|
|
@@ -32,7 +72,7 @@ export const xyPlugin = {
|
|
|
32
72
|
],
|
|
33
73
|
},
|
|
34
74
|
capabilities: {
|
|
35
|
-
chatTypes: ["direct"],
|
|
75
|
+
chatTypes: ["direct"],
|
|
36
76
|
polls: false,
|
|
37
77
|
threads: false,
|
|
38
78
|
media: true,
|
|
@@ -49,59 +89,11 @@ export const xyPlugin = {
|
|
|
49
89
|
schema: xyConfigSchema,
|
|
50
90
|
},
|
|
51
91
|
outbound: xyOutbound,
|
|
52
|
-
/**
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
* 1. **Normal (WebSocket) session** – `getCurrentSessionContext()` returns
|
|
58
|
-
* a context that was registered by bot.ts during message processing.
|
|
59
|
-
* Tools send commands through the WebSocket and listen for responses.
|
|
60
|
-
*
|
|
61
|
-
* 2. **Cron / scheduled-task session** – openclaw's cron runner calls
|
|
62
|
-
* `agentTools({ cfg })` without an active WebSocket session. When no
|
|
63
|
-
* session context exists but `cfg` is provided, we create a synthetic
|
|
64
|
-
* "cron session" with `isCron: true` and a `cron-`-prefixed sessionId.
|
|
65
|
-
* `sendCommand()` detects this prefix and routes commands through the
|
|
66
|
-
* push channel. Response listening (WebSocket events) works unchanged
|
|
67
|
-
* because the gateway WebSocket connection is always active.
|
|
68
|
-
*/
|
|
69
|
-
agentTools: (params) => {
|
|
70
|
-
let ctx = getCurrentSessionContext();
|
|
71
|
-
// ── Cron / non-session fallback ──────────────────────────────
|
|
72
|
-
// When no active xy WebSocket session exists but the openclaw cfg
|
|
73
|
-
// is provided (framework calls agentTools({ cfg })), create a
|
|
74
|
-
// synthetic "cron session". This enables cron-triggered agent
|
|
75
|
-
// turns and cross-channel tool calls to use xiaoyi tools via the
|
|
76
|
-
// push channel. sendCommand() detects the "cron-" sessionId
|
|
77
|
-
// prefix and routes commands through push instead of WebSocket.
|
|
78
|
-
if (!ctx && params?.cfg) {
|
|
79
|
-
try {
|
|
80
|
-
const config = resolveXYConfig(params.cfg);
|
|
81
|
-
const cronId = `${CRON_SESSION_PREFIX}${Date.now()}-${Math.random().toString(36).substring(2, 8)}`;
|
|
82
|
-
ctx = {
|
|
83
|
-
config,
|
|
84
|
-
sessionId: cronId,
|
|
85
|
-
taskId: cronId,
|
|
86
|
-
messageId: cronId,
|
|
87
|
-
agentId: "default",
|
|
88
|
-
isCron: true,
|
|
89
|
-
};
|
|
90
|
-
// Register so getCurrentSessionContext() fallback can find it
|
|
91
|
-
registerSession(`__cron__${cronId}`, ctx);
|
|
92
|
-
logger.log(`[CRON-TOOLS] Created cron session context: ${cronId}`);
|
|
93
|
-
}
|
|
94
|
-
catch (err) {
|
|
95
|
-
logger.error("[CRON-TOOLS] Failed to create cron context:", err);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
if (!ctx) {
|
|
99
|
-
logger.log("[CREATE-ALL-TOOLS] no session context, returning empty tools list");
|
|
100
|
-
return [];
|
|
101
|
-
}
|
|
102
|
-
const allTools = createAllTools(ctx);
|
|
103
|
-
const filtered = filterToolsByDevice(allTools, ctx.deviceType);
|
|
104
|
-
logger.log(`[DEVICE-FILTER] deviceType=${ctx.deviceType ?? "(none)"}, tools: ${allTools.length} → ${filtered.length} (${filtered.map(t => t.name).join(", ")})`);
|
|
92
|
+
/** Static tool list (3.24 pattern). Tools read SessionContext at execute time via ALS. */
|
|
93
|
+
agentTools: () => {
|
|
94
|
+
const ctx = getCurrentSessionContext();
|
|
95
|
+
const filtered = filterToolsByDevice(ALL_TOOLS, ctx?.deviceType);
|
|
96
|
+
logger.log(`[DEVICE-FILTER] deviceType=${ctx?.deviceType ?? "(none)"}, tools: ${ALL_TOOLS.length} → ${filtered.length} (${filtered.map(t => t.name).join(", ")})`);
|
|
105
97
|
return filtered;
|
|
106
98
|
},
|
|
107
99
|
messaging: {
|
|
@@ -113,7 +105,6 @@ export const xyPlugin = {
|
|
|
113
105
|
},
|
|
114
106
|
targetResolver: {
|
|
115
107
|
looksLikeId: (raw) => {
|
|
116
|
-
// 信任所有非空字符串作为有效的 sessionId
|
|
117
108
|
const trimmed = raw.trim();
|
|
118
109
|
return trimmed.length > 0;
|
|
119
110
|
},
|
|
@@ -135,20 +126,33 @@ export const xyPlugin = {
|
|
|
135
126
|
? { conversationId, matchPriority: 2 }
|
|
136
127
|
: null;
|
|
137
128
|
},
|
|
129
|
+
resolveCommandConversation: ({ accountId }) => {
|
|
130
|
+
// xiaoyi-channel: the A2A sessionId IS the conversationId.
|
|
131
|
+
// Read from the current ALS session context.
|
|
132
|
+
const ctx = getCurrentSessionContext();
|
|
133
|
+
const sessionId = ctx?.sessionId?.trim();
|
|
134
|
+
if (!sessionId)
|
|
135
|
+
return null;
|
|
136
|
+
return { conversationId: sessionId };
|
|
137
|
+
},
|
|
138
138
|
},
|
|
139
139
|
reload: {
|
|
140
140
|
configPrefixes: ["channels.xiaoyi-channel"],
|
|
141
141
|
},
|
|
142
|
-
// Gateway adapter for receiving messages
|
|
143
142
|
gateway: {
|
|
144
143
|
async startAccount(context) {
|
|
145
144
|
const { monitorXYProvider } = await import("./monitor.js");
|
|
145
|
+
const { createXyAcpBindingManager } = await import("./acp-session-binding.js");
|
|
146
146
|
const account = resolveXYConfig(context.cfg);
|
|
147
147
|
context.setStatus?.({
|
|
148
148
|
accountId: context.accountId,
|
|
149
149
|
wsUrl: account.wsUrl,
|
|
150
150
|
});
|
|
151
151
|
context.log?.info(`[${context.accountId}] starting xiaoyi channel (wsUrl: ${account.wsUrl})`);
|
|
152
|
+
// Register ACP session binding adapter for this account.
|
|
153
|
+
// Enables sessions_spawn(runtime="acp") to bind subagent sessions
|
|
154
|
+
// to the current A2A conversation.
|
|
155
|
+
createXyAcpBindingManager({ accountId: context.accountId, cfg: context.cfg });
|
|
152
156
|
return monitorXYProvider({
|
|
153
157
|
config: context.cfg,
|
|
154
158
|
runtime: context.runtime,
|
package/dist/src/client.d.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { XYWebSocketManager } from "./websocket.js";
|
|
2
2
|
import type { XYChannelConfig } from "./types.js";
|
|
3
3
|
import type { RuntimeEnv } from "openclaw/plugin-sdk";
|
|
4
|
+
/**
|
|
5
|
+
* Get a cached WebSocket manager without requiring config.
|
|
6
|
+
* Returns the first available manager. Use when ALS has no SessionContext.
|
|
7
|
+
*/
|
|
8
|
+
export declare function getCachedXYWebSocketManager(): XYWebSocketManager;
|
|
4
9
|
/**
|
|
5
10
|
* Get or create a WebSocket manager for the given configuration.
|
|
6
11
|
* Reuses existing managers if config matches.
|
package/dist/src/client.js
CHANGED
|
@@ -13,6 +13,16 @@ if (!_g.__xyWsManagerCache) {
|
|
|
13
13
|
_g.__xyWsManagerCache = new Map();
|
|
14
14
|
}
|
|
15
15
|
const wsManagerCache = _g.__xyWsManagerCache;
|
|
16
|
+
/**
|
|
17
|
+
* Get a cached WebSocket manager without requiring config.
|
|
18
|
+
* Returns the first available manager. Use when ALS has no SessionContext.
|
|
19
|
+
*/
|
|
20
|
+
export function getCachedXYWebSocketManager() {
|
|
21
|
+
if (wsManagerCache.size === 0) {
|
|
22
|
+
throw new Error("No WebSocket manager available in cache");
|
|
23
|
+
}
|
|
24
|
+
return wsManagerCache.values().next().value;
|
|
25
|
+
}
|
|
16
26
|
/**
|
|
17
27
|
* Get or create a WebSocket manager for the given configuration.
|
|
18
28
|
* Reuses existing managers if config matches.
|
|
@@ -2,6 +2,8 @@ import type { XYChannelConfig, A2ACommand } from "./types.js";
|
|
|
2
2
|
export interface SendCommandViaPushParams {
|
|
3
3
|
config: XYChannelConfig;
|
|
4
4
|
command: A2ACommand;
|
|
5
|
+
/** 指定设备的 pushId(多设备路由)。未传时回退到 getAllPushIds()[0]。 */
|
|
6
|
+
pushId?: string;
|
|
5
7
|
}
|
|
6
8
|
/**
|
|
7
9
|
* Send a tool command through the push channel (for cron-triggered tool calls).
|
package/dist/src/cron-command.js
CHANGED
|
@@ -24,16 +24,22 @@ export async function sendCommandViaPush(params) {
|
|
|
24
24
|
command.header?.name ??
|
|
25
25
|
"Command";
|
|
26
26
|
logger.log(`[CRON-CMD] Sending command via push, intent=${intentName}`);
|
|
27
|
-
// 1.
|
|
27
|
+
// 1. 选 pushId:优先用调用方解析出的设备 pushId(多设备路由正确);
|
|
28
|
+
// 未提供时回退到 getAllPushIds()[0](单设备兼容旧行为)。
|
|
28
29
|
let pushId = config.pushId;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
if (pushIdList.length > 0) {
|
|
32
|
-
pushId = pushIdList[0];
|
|
33
|
-
}
|
|
30
|
+
if (params.pushId) {
|
|
31
|
+
pushId = params.pushId;
|
|
34
32
|
}
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
else {
|
|
34
|
+
try {
|
|
35
|
+
const pushIdList = await getAllPushIds();
|
|
36
|
+
if (pushIdList.length > 0) {
|
|
37
|
+
pushId = pushIdList[0];
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
logger.error("[CRON-CMD] Failed to load pushIds:", error);
|
|
42
|
+
}
|
|
37
43
|
}
|
|
38
44
|
// 2. Build and send push notification with command in directives
|
|
39
45
|
const pushService = new XYPushService(config);
|
|
@@ -7,6 +7,8 @@ import { callGatewayTool } from "openclaw/plugin-sdk/agent-harness-runtime";
|
|
|
7
7
|
import * as os from "os";
|
|
8
8
|
import { sendCommand } from "./formatter.js";
|
|
9
9
|
import { resolveXYConfig } from "./config.js";
|
|
10
|
+
import { configManager } from "./utils/config-manager.js";
|
|
11
|
+
import { setJobPushId } from "./utils/cron-push-map.js";
|
|
10
12
|
import { logger } from "./utils/logger.js";
|
|
11
13
|
import { readFileSync, readdirSync } from "fs";
|
|
12
14
|
import { join } from "path";
|
|
@@ -39,6 +41,11 @@ export async function handleCronQueryEvent(context, cfg) {
|
|
|
39
41
|
break;
|
|
40
42
|
case "add":
|
|
41
43
|
result = await callGatewayTool("cron.add", { timeoutMs: GATEWAY_TIMEOUT_MS }, params ?? {});
|
|
44
|
+
// 捕获 jobId↔pushId:cron-query 路径由 channel 自己建 job,
|
|
45
|
+
// 此处 context 握着 sessionId,configManager 有对应设备 pushId。
|
|
46
|
+
await persistCronPushMap(context.sessionId, result).catch((err) => {
|
|
47
|
+
logger.error(`[CRON-QUERY] Failed to persist cron-push-map:`, err);
|
|
48
|
+
});
|
|
42
49
|
break;
|
|
43
50
|
case "update":
|
|
44
51
|
result = await callGatewayTool("cron.update", { timeoutMs: GATEWAY_TIMEOUT_MS }, {
|
|
@@ -106,6 +113,35 @@ export async function handleCronQueryEvent(context, cfg) {
|
|
|
106
113
|
log.warn(`[CRON-QUERY] Missing cfg/sessionId/taskId/messageId, skipping sendCommand`);
|
|
107
114
|
}
|
|
108
115
|
}
|
|
116
|
+
/**
|
|
117
|
+
* 从 cron.add 结果中提取 jobId,配合 sessionId 对应的 pushId 写入映射。
|
|
118
|
+
*/
|
|
119
|
+
async function persistCronPushMap(sessionId, result) {
|
|
120
|
+
logger.log(`[CRONMAP] cron-query persist: sessionId=${sessionId ?? "(none)"}, resultType=${typeof result}`);
|
|
121
|
+
if (!sessionId) {
|
|
122
|
+
logger.log(`[CRONMAP] cron-query skip: no sessionId in context`);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
let jobId;
|
|
126
|
+
if (result && typeof result === "object") {
|
|
127
|
+
const id = result.id;
|
|
128
|
+
if (typeof id === "string" && id.trim())
|
|
129
|
+
jobId = id.trim();
|
|
130
|
+
}
|
|
131
|
+
if (!jobId) {
|
|
132
|
+
const preview = typeof result === "string" ? result.slice(0, 200) : JSON.stringify(result)?.slice(0, 200);
|
|
133
|
+
logger.log(`[CRONMAP] cron-query skip: no jobId in result. preview=${preview ?? "(empty)"}`);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
const pushId = configManager.getPushId(sessionId);
|
|
137
|
+
if (!pushId) {
|
|
138
|
+
logger.log(`[CRONMAP] cron-query skip: configManager has no pushId for sessionId=${sessionId}`);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
logger.log(`[CRONMAP] cron-query writing map: jobId=${jobId}, pushId=${pushId.substring(0, 16)}...`);
|
|
142
|
+
await setJobPushId(jobId, { pushId, sessionId, source: "cron-query" });
|
|
143
|
+
logger.log(`[CRONMAP] cron-query map written OK`);
|
|
144
|
+
}
|
|
109
145
|
/**
|
|
110
146
|
* Read local cron folder directly (bypassing openclaw RPC) and return
|
|
111
147
|
* run records from the last 7 days, grouped by date and sorted by time.
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
import https from 'https';
|
|
5
5
|
import { URL } from 'url';
|
|
6
6
|
import { getConfig } from './config.js';
|
|
7
|
-
import {
|
|
7
|
+
import { DEFAULT_HTTPS_PORT, HTTP_STATUS_BAD_REQUEST, API_URL_SUFFIX } from './constants.js';
|
|
8
|
+
import { logger } from '../utils/logger.js';
|
|
8
9
|
function buildHeadersForCelia(config, sessionId) {
|
|
9
10
|
if (!config.uid || !config.apiKey || !config.skillId || !config.requestFrom) {
|
|
10
11
|
throw new Error('[SENTINEL HOOK] Missing required configuration: uid, apiKey, skillId, or requestFrom is not defined');
|
|
@@ -22,7 +23,7 @@ function buildRequestOptions(url, headers, timeout) {
|
|
|
22
23
|
const urlObj = new URL(url);
|
|
23
24
|
return {
|
|
24
25
|
hostname: urlObj.hostname,
|
|
25
|
-
port: urlObj.port ||
|
|
26
|
+
port: urlObj.port || DEFAULT_HTTPS_PORT,
|
|
26
27
|
path: urlObj.pathname,
|
|
27
28
|
method: "POST",
|
|
28
29
|
headers: headers,
|
|
@@ -89,6 +90,7 @@ export async function callApi(questionText, api, sessionId, action) {
|
|
|
89
90
|
};
|
|
90
91
|
const httpBody = JSON.stringify(payload);
|
|
91
92
|
const apiUrl = `${config.api.url}${API_URL_SUFFIX}`;
|
|
93
|
+
logger.log(`[SENTINEL HOOK] callApi: action=${action}, x-hag-trace-id=${sessionId}, url=${apiUrl}`);
|
|
92
94
|
return new Promise((resolve, reject) => {
|
|
93
95
|
const options = buildRequestOptions(apiUrl, headersForCelia, config.api.timeout);
|
|
94
96
|
const req = https.request(options, (res) => {
|
|
@@ -6,15 +6,16 @@ import { callApi } from './call_api.js';
|
|
|
6
6
|
import { processText, extractResultText, validateAndTruncateText, parseSecurityResult, handleExecToolInput, handleMessageToolInput, handleOtherToolInput } from './utils.js';
|
|
7
7
|
import { ALLOWED_TOOLS, MAX_TEXT_LENGTH, MAX_TOTAL_LENGTH, MIN_TEXT_LENGTH, STEER_ABORT_MESSAGE, TOOL_OUTPUT_ACTION } from './constants.js';
|
|
8
8
|
import { logger } from '../utils/logger.js';
|
|
9
|
-
import {
|
|
9
|
+
import { getCurrentSessionContext } from '../tools/session-manager.js';
|
|
10
10
|
import { tryInjectSteer } from './steer-context.js';
|
|
11
11
|
// 主入口模块
|
|
12
12
|
export default function register(api) {
|
|
13
13
|
api.on("before_tool_call", async (event, ctx) => {
|
|
14
14
|
logger.log(`[SENTINEL HOOK] before_tool_call_event toolName: ${event.toolName}`);
|
|
15
|
-
//
|
|
16
|
-
const
|
|
17
|
-
|
|
15
|
+
// 获取真实sessionID:优先使用ALS中的A2A sessionId,降级到OpenClaw runId或随机值
|
|
16
|
+
const sessionCtx = getCurrentSessionContext();
|
|
17
|
+
const sessionId = sessionCtx?.sessionId || (event.runId?.replace(/-/g, '') || crypto.randomBytes(16).toString('hex'));
|
|
18
|
+
logger.log(`[SENTINEL HOOK] Session ID: ${sessionId} (fromALS: ${!!sessionCtx?.sessionId})`);
|
|
18
19
|
// 处理 TOOL_INPUT 数据采集、发送数据,根据扫描结果决定是否阻塞
|
|
19
20
|
try {
|
|
20
21
|
let scanResult = null;
|
|
@@ -43,9 +44,10 @@ export default function register(api) {
|
|
|
43
44
|
}
|
|
44
45
|
try {
|
|
45
46
|
logger.log(`[SENTINEL HOOK] after_tool_call_event toolName: ${event.toolName}`);
|
|
46
|
-
//
|
|
47
|
-
const
|
|
48
|
-
|
|
47
|
+
// 获取真实sessionID:优先使用ALS中的A2A sessionId,降级到OpenClaw runId或随机值
|
|
48
|
+
const sessionCtx = getCurrentSessionContext();
|
|
49
|
+
const sessionId = sessionCtx?.sessionId || (event.runId?.replace(/-/g, '') || crypto.randomBytes(16).toString('hex'));
|
|
50
|
+
logger.log(`[SENTINEL HOOK] Session ID: ${sessionId} (fromALS: ${!!sessionCtx?.sessionId})`);
|
|
49
51
|
// 处理TOOL_OUTPUT数据采集(保持现有逻辑)
|
|
50
52
|
const resultText = extractResultText(event, event.toolName);
|
|
51
53
|
const resultTextLength = resultText.length;
|
|
@@ -78,7 +80,6 @@ export default function register(api) {
|
|
|
78
80
|
logger.log(`[SENTINEL HOOK] TOOL_OUTPUT response: status=${result.status}.`);
|
|
79
81
|
if (result.status === 'REJECT') {
|
|
80
82
|
logger.warn('[SENTINEL HOOK] REJECT detected, attempting steer injection');
|
|
81
|
-
const sessionCtx = ctx.sessionKey ? getSessionContext(ctx.sessionKey) : null;
|
|
82
83
|
if (sessionCtx?.sessionId && sessionCtx?.taskId) {
|
|
83
84
|
await tryInjectSteer({
|
|
84
85
|
sessionId: sessionCtx.sessionId,
|
|
@@ -6,7 +6,7 @@ import path from 'path';
|
|
|
6
6
|
import https from 'https';
|
|
7
7
|
import { URL } from 'url';
|
|
8
8
|
import { getConfig } from './config.js';
|
|
9
|
-
import {
|
|
9
|
+
import { DEFAULT_HTTPS_PORT, MAX_TIMES, CONNECT_TIMEOUT, READ_TIMEOUT, EXPIRE_TIME, OSMS_PREPARE_URL, OSMS_COMPLETE_URL, TEMPORARY_MATERIAL_PACKAGE, FILE_OWNER_UID, FILE_OWNER_TEAM_ID } from './constants.js';
|
|
10
10
|
function buildOsmsHeaders(config, traceId) {
|
|
11
11
|
return {
|
|
12
12
|
'content-type': 'application/json',
|
|
@@ -22,7 +22,7 @@ function httpRequest(url, method, headers, body, timeout) {
|
|
|
22
22
|
const urlObj = new URL(url);
|
|
23
23
|
const options = {
|
|
24
24
|
hostname: urlObj.hostname,
|
|
25
|
-
port: urlObj.port ||
|
|
25
|
+
port: urlObj.port || DEFAULT_HTTPS_PORT,
|
|
26
26
|
path: urlObj.pathname + urlObj.search,
|
|
27
27
|
method: method,
|
|
28
28
|
headers: headers,
|
package/dist/src/formatter.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
// OpenClaw → A2A format conversion
|
|
2
|
+
import os from "os";
|
|
2
3
|
import { v4 as uuidv4 } from "uuid";
|
|
3
4
|
import { getXYWebSocketManager } from "./client.js";
|
|
4
5
|
import { logger } from "./utils/logger.js";
|
|
5
|
-
import { getCurrentTaskId, getCurrentMessageId } from "./task-manager.js";
|
|
6
6
|
import { redactSensitiveText, containsSensitiveInfo } from "./sensitive-redactor.js";
|
|
7
7
|
import { rewriteOutboundApprovalText } from "./approval-bridge.js";
|
|
8
|
-
import { isCronToolCall } from "./tools/session-manager.js";
|
|
8
|
+
import { isCronToolCall, getCurrentCronJobId } from "./tools/session-manager.js";
|
|
9
|
+
import { configManager } from "./utils/config-manager.js";
|
|
10
|
+
import { getPushIdByJobId } from "./utils/cron-push-map.js";
|
|
11
|
+
import { getAllPushIds } from "./utils/pushid-manager.js";
|
|
9
12
|
// ─────────────────────────────────────────────────────────────
|
|
10
13
|
// 敏感信息脱敏辅助函数
|
|
11
14
|
// ─────────────────────────────────────────────────────────────
|
|
@@ -95,7 +98,7 @@ export async function sendA2AResponse(params) {
|
|
|
95
98
|
agentId: config.agentId,
|
|
96
99
|
sessionId,
|
|
97
100
|
taskId,
|
|
98
|
-
msgDetail: JSON.stringify(jsonRpcResponse),
|
|
101
|
+
msgDetail: JSON.stringify({ ...jsonRpcResponse, hostname: os.hostname() }),
|
|
99
102
|
};
|
|
100
103
|
if (shouldLog) {
|
|
101
104
|
const redactedText = redactSensitiveText(bridgedText ?? "");
|
|
@@ -145,7 +148,7 @@ export async function sendReasoningTextUpdate(params) {
|
|
|
145
148
|
agentId: config.agentId,
|
|
146
149
|
sessionId,
|
|
147
150
|
taskId,
|
|
148
|
-
msgDetail: JSON.stringify(jsonRpcResponse),
|
|
151
|
+
msgDetail: JSON.stringify({ ...jsonRpcResponse, hostname: os.hostname() }),
|
|
149
152
|
};
|
|
150
153
|
await wsManager.sendMessage(sessionId, outboundMessage);
|
|
151
154
|
}
|
|
@@ -155,11 +158,7 @@ export async function sendReasoningTextUpdate(params) {
|
|
|
155
158
|
*/
|
|
156
159
|
export async function sendStatusUpdate(params) {
|
|
157
160
|
const { config, sessionId, taskId, messageId, text, state } = params;
|
|
158
|
-
|
|
159
|
-
// fall back to closure-captured values
|
|
160
|
-
const currentTaskId = getCurrentTaskId(sessionId) ?? taskId;
|
|
161
|
-
const currentMessageId = getCurrentMessageId(sessionId) ?? messageId;
|
|
162
|
-
const log = logger.withContext(sessionId, currentTaskId);
|
|
161
|
+
const log = logger.withContext(sessionId, taskId);
|
|
163
162
|
// 审批桥接和脱敏
|
|
164
163
|
const bridgedText = rewriteOutboundApprovalText(sessionId, text);
|
|
165
164
|
const redactedText = redactSensitiveText(bridgedText);
|
|
@@ -174,7 +173,7 @@ export async function sendStatusUpdate(params) {
|
|
|
174
173
|
],
|
|
175
174
|
});
|
|
176
175
|
const statusUpdate = {
|
|
177
|
-
taskId
|
|
176
|
+
taskId,
|
|
178
177
|
kind: "status-update",
|
|
179
178
|
final: false, // Status updates should not end the stream
|
|
180
179
|
status: {
|
|
@@ -185,7 +184,7 @@ export async function sendStatusUpdate(params) {
|
|
|
185
184
|
// Build JSON-RPC response
|
|
186
185
|
const jsonRpcResponse = {
|
|
187
186
|
jsonrpc: "2.0",
|
|
188
|
-
id:
|
|
187
|
+
id: messageId,
|
|
189
188
|
result: statusUpdate,
|
|
190
189
|
};
|
|
191
190
|
// Send via WebSocket
|
|
@@ -194,13 +193,52 @@ export async function sendStatusUpdate(params) {
|
|
|
194
193
|
msgType: "agent_response",
|
|
195
194
|
agentId: config.agentId,
|
|
196
195
|
sessionId,
|
|
197
|
-
taskId
|
|
198
|
-
msgDetail: JSON.stringify(jsonRpcResponse),
|
|
196
|
+
taskId,
|
|
197
|
+
msgDetail: JSON.stringify({ ...jsonRpcResponse, hostname: os.hostname() }),
|
|
199
198
|
};
|
|
200
199
|
// Log complete response body
|
|
201
200
|
log.log(`[A2A_STATUS] Sending status-update, text="${redactedText}"`);
|
|
202
201
|
await wsManager.sendMessage(sessionId, outboundMessage);
|
|
203
202
|
}
|
|
203
|
+
/**
|
|
204
|
+
* 解析 cron fire 时应使用的 pushId(多设备路由)。
|
|
205
|
+
*
|
|
206
|
+
* 查询链(逐级回退):
|
|
207
|
+
* 1. 合成 sessionId → jobId → cron-push-map.json → 创建时记录的设备 pushId
|
|
208
|
+
* 2. configManager 同进程的 sessionId→pushId(进程未重启时兜底)
|
|
209
|
+
* 3. getAllPushIds()[0](单设备兼容旧行为)
|
|
210
|
+
* 返回 undefined 表示走兜底(由 sendCommandViaPush 内部处理)。
|
|
211
|
+
*/
|
|
212
|
+
async function resolveCronPushId(sessionId, config) {
|
|
213
|
+
// 1. jobId → 持久化映射
|
|
214
|
+
const jobId = getCurrentCronJobId(sessionId);
|
|
215
|
+
if (jobId) {
|
|
216
|
+
const hit = await getPushIdByJobId(jobId);
|
|
217
|
+
if (hit?.pushId) {
|
|
218
|
+
logger.log(`[CRON-PUSH] Resolved pushId via map, jobId=${jobId}`);
|
|
219
|
+
return hit.pushId;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
// 2. 同进程 configManager 兜底
|
|
223
|
+
const sessionPushId = configManager.getPushId(sessionId);
|
|
224
|
+
if (sessionPushId) {
|
|
225
|
+
logger.log(`[CRON-PUSH] Resolved pushId via configManager (fallback)`);
|
|
226
|
+
return sessionPushId;
|
|
227
|
+
}
|
|
228
|
+
// 3. config.pushId / getAllPushIds()[0] 交给 sendCommandViaPush 内部处理
|
|
229
|
+
void config;
|
|
230
|
+
try {
|
|
231
|
+
const all = await getAllPushIds();
|
|
232
|
+
if (all.length > 0) {
|
|
233
|
+
logger.log(`[CRON-PUSH] Resolved pushId via getAllPushIds[0] (legacy fallback)`);
|
|
234
|
+
return all[0];
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
catch (error) {
|
|
238
|
+
logger.error(`[CRON-PUSH] getAllPushIds failed:`, error);
|
|
239
|
+
}
|
|
240
|
+
return undefined;
|
|
241
|
+
}
|
|
204
242
|
/**
|
|
205
243
|
* Send a command as an artifact update (final=false).
|
|
206
244
|
*
|
|
@@ -217,22 +255,22 @@ export async function sendCommand(params) {
|
|
|
217
255
|
if (commands.length === 0) {
|
|
218
256
|
throw new Error("sendCommand requires command or commands.");
|
|
219
257
|
}
|
|
220
|
-
// ── Cron mode:
|
|
221
|
-
//
|
|
222
|
-
//
|
|
258
|
+
// ── Cron mode: route through push channel ──────────────────────
|
|
259
|
+
// Detected via: (a) sessionId "cron-" prefix from synthetic session, OR
|
|
260
|
+
// (b) toolCallId marked by before_tool_call hook from openclaw's sessionKey.
|
|
223
261
|
if (sessionId.startsWith("cron-") || isCronToolCall(toolCallId)) {
|
|
224
|
-
|
|
262
|
+
const { sendCommandViaPush } = await import("./cron-command.js");
|
|
263
|
+
// 解析正确设备的 pushId:合成 sessionId → jobId → cron-push-map。
|
|
264
|
+
// provider.ts 在 isCron 分支已把 jobId 绑定到该 sessionId。
|
|
265
|
+
const pushId = await resolveCronPushId(sessionId, config);
|
|
266
|
+
return sendCommandViaPush({ config, command: commands[0], pushId });
|
|
225
267
|
}
|
|
226
268
|
// ── Normal mode: WebSocket ─────────────────────────────────────
|
|
227
|
-
|
|
228
|
-
// fall back to closure-captured values
|
|
229
|
-
const currentTaskId = getCurrentTaskId(sessionId) ?? taskId;
|
|
230
|
-
const currentMessageId = getCurrentMessageId(sessionId) ?? messageId;
|
|
231
|
-
const log = logger.withContext(sessionId, currentTaskId);
|
|
269
|
+
const log = logger.withContext(sessionId, taskId);
|
|
232
270
|
// Build artifact update with command as data
|
|
233
271
|
// Wrap command in commands array as per protocol requirement
|
|
234
272
|
const artifact = {
|
|
235
|
-
taskId
|
|
273
|
+
taskId,
|
|
236
274
|
kind: "artifact-update",
|
|
237
275
|
append: false,
|
|
238
276
|
lastChunk: true,
|
|
@@ -254,7 +292,7 @@ export async function sendCommand(params) {
|
|
|
254
292
|
// Build JSON-RPC response
|
|
255
293
|
const jsonRpcResponse = {
|
|
256
294
|
jsonrpc: "2.0",
|
|
257
|
-
id:
|
|
295
|
+
id: messageId,
|
|
258
296
|
result: artifact,
|
|
259
297
|
};
|
|
260
298
|
// Send via WebSocket
|
|
@@ -263,8 +301,8 @@ export async function sendCommand(params) {
|
|
|
263
301
|
msgType: "agent_response",
|
|
264
302
|
agentId: config.agentId,
|
|
265
303
|
sessionId,
|
|
266
|
-
taskId
|
|
267
|
-
msgDetail: JSON.stringify(jsonRpcResponse),
|
|
304
|
+
taskId,
|
|
305
|
+
msgDetail: JSON.stringify({ ...jsonRpcResponse, hostname: os.hostname() }),
|
|
268
306
|
};
|
|
269
307
|
// Log complete response body
|
|
270
308
|
log.log(`[A2A_COMMAND] Sending command`);
|
|
@@ -283,12 +321,10 @@ export async function sendCard(params) {
|
|
|
283
321
|
throw new Error("sendCard does not support cron mode");
|
|
284
322
|
}
|
|
285
323
|
// ── Normal mode: WebSocket ─────────────────────────────────────
|
|
286
|
-
const
|
|
287
|
-
const currentMessageId = getCurrentMessageId(sessionId) ?? messageId;
|
|
288
|
-
const log = logger.withContext(sessionId, currentTaskId);
|
|
324
|
+
const log = logger.withContext(sessionId, taskId);
|
|
289
325
|
// Build artifact update with cardsInfo as data
|
|
290
326
|
const artifact = {
|
|
291
|
-
taskId
|
|
327
|
+
taskId,
|
|
292
328
|
kind: "artifact-update",
|
|
293
329
|
append: false,
|
|
294
330
|
lastChunk: true,
|
|
@@ -308,7 +344,7 @@ export async function sendCard(params) {
|
|
|
308
344
|
// Build JSON-RPC response
|
|
309
345
|
const jsonRpcResponse = {
|
|
310
346
|
jsonrpc: "2.0",
|
|
311
|
-
id:
|
|
347
|
+
id: messageId,
|
|
312
348
|
result: artifact,
|
|
313
349
|
};
|
|
314
350
|
// Send via WebSocket
|
|
@@ -317,8 +353,8 @@ export async function sendCard(params) {
|
|
|
317
353
|
msgType: "agent_response",
|
|
318
354
|
agentId: config.agentId,
|
|
319
355
|
sessionId,
|
|
320
|
-
taskId
|
|
321
|
-
msgDetail: JSON.stringify(jsonRpcResponse),
|
|
356
|
+
taskId,
|
|
357
|
+
msgDetail: JSON.stringify({ ...jsonRpcResponse, hostname: os.hostname() }),
|
|
322
358
|
};
|
|
323
359
|
log.log(`[A2A_CARD] Sending card`);
|
|
324
360
|
await wsManager.sendMessage(sessionId, outboundMessage);
|
|
@@ -352,7 +388,7 @@ export async function sendClearContextResponse(params) {
|
|
|
352
388
|
agentId: config.agentId,
|
|
353
389
|
sessionId,
|
|
354
390
|
taskId: sessionId, // Use sessionId as taskId for clearContext
|
|
355
|
-
msgDetail: JSON.stringify(jsonRpcResponse),
|
|
391
|
+
msgDetail: JSON.stringify({ ...jsonRpcResponse, hostname: os.hostname() }),
|
|
356
392
|
};
|
|
357
393
|
await wsManager.sendMessage(sessionId, outboundMessage);
|
|
358
394
|
log.log(`[CLEAR_CONTEXT] Sent clearContext response`);
|
|
@@ -386,7 +422,7 @@ export async function sendTasksCancelResponse(params) {
|
|
|
386
422
|
agentId: config.agentId,
|
|
387
423
|
sessionId,
|
|
388
424
|
taskId,
|
|
389
|
-
msgDetail: JSON.stringify(jsonRpcResponse),
|
|
425
|
+
msgDetail: JSON.stringify({ ...jsonRpcResponse, hostname: os.hostname() }),
|
|
390
426
|
};
|
|
391
427
|
await wsManager.sendMessage(sessionId, outboundMessage);
|
|
392
428
|
log.log(`[TASKS_CANCEL] Sent tasks/cancel response`);
|
|
@@ -434,7 +470,7 @@ export async function sendTriggerResponse(params) {
|
|
|
434
470
|
agentId: config.agentId,
|
|
435
471
|
sessionId,
|
|
436
472
|
taskId,
|
|
437
|
-
msgDetail: JSON.stringify(jsonRpcResponse),
|
|
473
|
+
msgDetail: JSON.stringify({ ...jsonRpcResponse, hostname: os.hostname() }),
|
|
438
474
|
};
|
|
439
475
|
log.log(`[TRIGGER_RESPONSE] Sending Trigger response, text=${buildTextPreview(redactedContent)}`);
|
|
440
476
|
await wsManager.sendMessage(sessionId, outboundMessage);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { LogReporterConfig } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Load and validate the JSON config file.
|
|
4
|
+
* Falls back to defaults for optional fields.
|
|
5
|
+
*/
|
|
6
|
+
export declare function loadConfig(configPath: string): LogReporterConfig;
|
|
7
|
+
/**
|
|
8
|
+
* Resolve a path template with date wildcards to actual file paths on disk.
|
|
9
|
+
* Scans the directory and returns all files matching the pattern.
|
|
10
|
+
*/
|
|
11
|
+
export declare function resolveLogFiles(templatePath: string): string[];
|