@ynhcj/xiaoyi-channel 0.0.178-beta → 0.0.178-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 +50 -33
- package/dist/src/channel.js +59 -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 +45 -8
- 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 +66 -28
- 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/parser.d.ts +12 -0
- package/dist/src/parser.js +39 -13
- package/dist/src/provider.js +65 -67
- package/dist/src/reply-dispatcher.d.ts +3 -0
- package/dist/src/reply-dispatcher.js +149 -124
- 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 +122 -125
- package/dist/src/tools/modify-alarm-tool.d.ts +47 -2
- package/dist/src/tools/modify-alarm-tool.js +252 -237
- 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 +214 -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 +172 -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 -239
- 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
|
},
|
|
@@ -139,16 +130,20 @@ export const xyPlugin = {
|
|
|
139
130
|
reload: {
|
|
140
131
|
configPrefixes: ["channels.xiaoyi-channel"],
|
|
141
132
|
},
|
|
142
|
-
// Gateway adapter for receiving messages
|
|
143
133
|
gateway: {
|
|
144
134
|
async startAccount(context) {
|
|
145
135
|
const { monitorXYProvider } = await import("./monitor.js");
|
|
136
|
+
const { createXyAcpBindingManager } = await import("./acp-session-binding.js");
|
|
146
137
|
const account = resolveXYConfig(context.cfg);
|
|
147
138
|
context.setStatus?.({
|
|
148
139
|
accountId: context.accountId,
|
|
149
140
|
wsUrl: account.wsUrl,
|
|
150
141
|
});
|
|
151
142
|
context.log?.info(`[${context.accountId}] starting xiaoyi channel (wsUrl: ${account.wsUrl})`);
|
|
143
|
+
// Register ACP session binding adapter for this account.
|
|
144
|
+
// Enables sessions_spawn(runtime="acp") to bind subagent sessions
|
|
145
|
+
// to the current A2A conversation.
|
|
146
|
+
createXyAcpBindingManager({ accountId: context.accountId, cfg: context.cfg });
|
|
152
147
|
return monitorXYProvider({
|
|
153
148
|
config: context.cfg,
|
|
154
149
|
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";
|
|
@@ -19,7 +21,8 @@ const GATEWAY_TIMEOUT_MS = 60_000;
|
|
|
19
21
|
*/
|
|
20
22
|
export async function handleCronQueryEvent(context, cfg) {
|
|
21
23
|
const { action, jobId, params, sessionId, taskId, messageId } = context;
|
|
22
|
-
logger.
|
|
24
|
+
const log = logger.withContext(sessionId ?? "", taskId ?? "");
|
|
25
|
+
log.log(`[CRON-QUERY] Received event: action=${action}, jobId=${jobId ?? "(none)"}`);
|
|
23
26
|
let result;
|
|
24
27
|
let error;
|
|
25
28
|
try {
|
|
@@ -38,6 +41,11 @@ export async function handleCronQueryEvent(context, cfg) {
|
|
|
38
41
|
break;
|
|
39
42
|
case "add":
|
|
40
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
|
+
});
|
|
41
49
|
break;
|
|
42
50
|
case "update":
|
|
43
51
|
result = await callGatewayTool("cron.update", { timeoutMs: GATEWAY_TIMEOUT_MS }, {
|
|
@@ -62,17 +70,17 @@ export async function handleCronQueryEvent(context, cfg) {
|
|
|
62
70
|
break;
|
|
63
71
|
default:
|
|
64
72
|
error = `Unknown action: ${context.action}`;
|
|
65
|
-
|
|
73
|
+
log.error(`[CRON-QUERY] ${error}`);
|
|
66
74
|
result = { error };
|
|
67
75
|
}
|
|
68
76
|
}
|
|
69
77
|
catch (err) {
|
|
70
78
|
error = err instanceof Error ? err.message : String(err);
|
|
71
|
-
|
|
79
|
+
log.error(`[CRON-QUERY] RPC call failed for action=${action}:`, err);
|
|
72
80
|
result = { error };
|
|
73
81
|
}
|
|
74
82
|
// Log the result
|
|
75
|
-
|
|
83
|
+
log.log(`[CRON-QUERY] RPC result for action=${action}: ${JSON.stringify(result, null, 2)}`);
|
|
76
84
|
// Send result back via sendCommand as System.CronQuery with payload.ans
|
|
77
85
|
if (cfg && sessionId && taskId && messageId) {
|
|
78
86
|
try {
|
|
@@ -93,17 +101,46 @@ export async function handleCronQueryEvent(context, cfg) {
|
|
|
93
101
|
taskId,
|
|
94
102
|
messageId,
|
|
95
103
|
command,
|
|
96
|
-
final:
|
|
104
|
+
final: sessionId.toLowerCase().endsWith("cronquery"),
|
|
97
105
|
});
|
|
98
|
-
|
|
106
|
+
log.log(`[CRON-QUERY] Sent response via sendCommand, action=${action}`);
|
|
99
107
|
}
|
|
100
108
|
catch (sendErr) {
|
|
101
|
-
|
|
109
|
+
log.error(`[CRON-QUERY] Failed to send response via sendCommand:`, sendErr);
|
|
102
110
|
}
|
|
103
111
|
}
|
|
104
112
|
else {
|
|
105
|
-
|
|
113
|
+
log.warn(`[CRON-QUERY] Missing cfg/sessionId/taskId/messageId, skipping sendCommand`);
|
|
114
|
+
}
|
|
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;
|
|
106
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`);
|
|
107
144
|
}
|
|
108
145
|
/**
|
|
109
146
|
* Read local cron folder directly (bypassing openclaw RPC) and return
|
|
@@ -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
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
import { v4 as uuidv4 } from "uuid";
|
|
3
3
|
import { getXYWebSocketManager } from "./client.js";
|
|
4
4
|
import { logger } from "./utils/logger.js";
|
|
5
|
-
import { getCurrentTaskId, getCurrentMessageId } from "./task-manager.js";
|
|
6
5
|
import { redactSensitiveText, containsSensitiveInfo } from "./sensitive-redactor.js";
|
|
7
6
|
import { rewriteOutboundApprovalText } from "./approval-bridge.js";
|
|
8
|
-
import { isCronToolCall } from "./tools/session-manager.js";
|
|
7
|
+
import { isCronToolCall, getCurrentCronJobId } from "./tools/session-manager.js";
|
|
8
|
+
import { configManager } from "./utils/config-manager.js";
|
|
9
|
+
import { getPushIdByJobId } from "./utils/cron-push-map.js";
|
|
10
|
+
import { getAllPushIds } from "./utils/pushid-manager.js";
|
|
9
11
|
// ─────────────────────────────────────────────────────────────
|
|
10
12
|
// 敏感信息脱敏辅助函数
|
|
11
13
|
// ─────────────────────────────────────────────────────────────
|
|
@@ -139,6 +141,8 @@ export async function sendReasoningTextUpdate(params) {
|
|
|
139
141
|
id: messageId,
|
|
140
142
|
result: artifact,
|
|
141
143
|
};
|
|
144
|
+
const redactedText = redactSensitiveText(bridgedText);
|
|
145
|
+
log.log(`[A2A_REASONING] Sending reasoning update, append=${append}, taskId=${taskId}, messageId=${messageId}, text=${buildTextPreview(redactedText)}, sensitive=${containsSensitiveInfo(bridgedText)}`);
|
|
142
146
|
const wsManager = getXYWebSocketManager(config);
|
|
143
147
|
const outboundMessage = {
|
|
144
148
|
msgType: "agent_response",
|
|
@@ -148,6 +152,7 @@ export async function sendReasoningTextUpdate(params) {
|
|
|
148
152
|
msgDetail: JSON.stringify(jsonRpcResponse),
|
|
149
153
|
};
|
|
150
154
|
await wsManager.sendMessage(sessionId, outboundMessage);
|
|
155
|
+
log.log(`[A2A_REASONING] Reasoning update sent successfully`);
|
|
151
156
|
}
|
|
152
157
|
/**
|
|
153
158
|
* Send an A2A task status update.
|
|
@@ -155,11 +160,7 @@ export async function sendReasoningTextUpdate(params) {
|
|
|
155
160
|
*/
|
|
156
161
|
export async function sendStatusUpdate(params) {
|
|
157
162
|
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);
|
|
163
|
+
const log = logger.withContext(sessionId, taskId);
|
|
163
164
|
// 审批桥接和脱敏
|
|
164
165
|
const bridgedText = rewriteOutboundApprovalText(sessionId, text);
|
|
165
166
|
const redactedText = redactSensitiveText(bridgedText);
|
|
@@ -174,7 +175,7 @@ export async function sendStatusUpdate(params) {
|
|
|
174
175
|
],
|
|
175
176
|
});
|
|
176
177
|
const statusUpdate = {
|
|
177
|
-
taskId
|
|
178
|
+
taskId,
|
|
178
179
|
kind: "status-update",
|
|
179
180
|
final: false, // Status updates should not end the stream
|
|
180
181
|
status: {
|
|
@@ -185,7 +186,7 @@ export async function sendStatusUpdate(params) {
|
|
|
185
186
|
// Build JSON-RPC response
|
|
186
187
|
const jsonRpcResponse = {
|
|
187
188
|
jsonrpc: "2.0",
|
|
188
|
-
id:
|
|
189
|
+
id: messageId,
|
|
189
190
|
result: statusUpdate,
|
|
190
191
|
};
|
|
191
192
|
// Send via WebSocket
|
|
@@ -194,13 +195,52 @@ export async function sendStatusUpdate(params) {
|
|
|
194
195
|
msgType: "agent_response",
|
|
195
196
|
agentId: config.agentId,
|
|
196
197
|
sessionId,
|
|
197
|
-
taskId
|
|
198
|
+
taskId,
|
|
198
199
|
msgDetail: JSON.stringify(jsonRpcResponse),
|
|
199
200
|
};
|
|
200
201
|
// Log complete response body
|
|
201
202
|
log.log(`[A2A_STATUS] Sending status-update, text="${redactedText}"`);
|
|
202
203
|
await wsManager.sendMessage(sessionId, outboundMessage);
|
|
203
204
|
}
|
|
205
|
+
/**
|
|
206
|
+
* 解析 cron fire 时应使用的 pushId(多设备路由)。
|
|
207
|
+
*
|
|
208
|
+
* 查询链(逐级回退):
|
|
209
|
+
* 1. 合成 sessionId → jobId → cron-push-map.json → 创建时记录的设备 pushId
|
|
210
|
+
* 2. configManager 同进程的 sessionId→pushId(进程未重启时兜底)
|
|
211
|
+
* 3. getAllPushIds()[0](单设备兼容旧行为)
|
|
212
|
+
* 返回 undefined 表示走兜底(由 sendCommandViaPush 内部处理)。
|
|
213
|
+
*/
|
|
214
|
+
async function resolveCronPushId(sessionId, config) {
|
|
215
|
+
// 1. jobId → 持久化映射
|
|
216
|
+
const jobId = getCurrentCronJobId(sessionId);
|
|
217
|
+
if (jobId) {
|
|
218
|
+
const hit = await getPushIdByJobId(jobId);
|
|
219
|
+
if (hit?.pushId) {
|
|
220
|
+
logger.log(`[CRON-PUSH] Resolved pushId via map, jobId=${jobId}`);
|
|
221
|
+
return hit.pushId;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
// 2. 同进程 configManager 兜底
|
|
225
|
+
const sessionPushId = configManager.getPushId(sessionId);
|
|
226
|
+
if (sessionPushId) {
|
|
227
|
+
logger.log(`[CRON-PUSH] Resolved pushId via configManager (fallback)`);
|
|
228
|
+
return sessionPushId;
|
|
229
|
+
}
|
|
230
|
+
// 3. config.pushId / getAllPushIds()[0] 交给 sendCommandViaPush 内部处理
|
|
231
|
+
void config;
|
|
232
|
+
try {
|
|
233
|
+
const all = await getAllPushIds();
|
|
234
|
+
if (all.length > 0) {
|
|
235
|
+
logger.log(`[CRON-PUSH] Resolved pushId via getAllPushIds[0] (legacy fallback)`);
|
|
236
|
+
return all[0];
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
catch (error) {
|
|
240
|
+
logger.error(`[CRON-PUSH] getAllPushIds failed:`, error);
|
|
241
|
+
}
|
|
242
|
+
return undefined;
|
|
243
|
+
}
|
|
204
244
|
/**
|
|
205
245
|
* Send a command as an artifact update (final=false).
|
|
206
246
|
*
|
|
@@ -217,22 +257,22 @@ export async function sendCommand(params) {
|
|
|
217
257
|
if (commands.length === 0) {
|
|
218
258
|
throw new Error("sendCommand requires command or commands.");
|
|
219
259
|
}
|
|
220
|
-
// ── Cron mode:
|
|
221
|
-
//
|
|
222
|
-
//
|
|
260
|
+
// ── Cron mode: route through push channel ──────────────────────
|
|
261
|
+
// Detected via: (a) sessionId "cron-" prefix from synthetic session, OR
|
|
262
|
+
// (b) toolCallId marked by before_tool_call hook from openclaw's sessionKey.
|
|
223
263
|
if (sessionId.startsWith("cron-") || isCronToolCall(toolCallId)) {
|
|
224
|
-
|
|
264
|
+
const { sendCommandViaPush } = await import("./cron-command.js");
|
|
265
|
+
// 解析正确设备的 pushId:合成 sessionId → jobId → cron-push-map。
|
|
266
|
+
// provider.ts 在 isCron 分支已把 jobId 绑定到该 sessionId。
|
|
267
|
+
const pushId = await resolveCronPushId(sessionId, config);
|
|
268
|
+
return sendCommandViaPush({ config, command: commands[0], pushId });
|
|
225
269
|
}
|
|
226
270
|
// ── 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);
|
|
271
|
+
const log = logger.withContext(sessionId, taskId);
|
|
232
272
|
// Build artifact update with command as data
|
|
233
273
|
// Wrap command in commands array as per protocol requirement
|
|
234
274
|
const artifact = {
|
|
235
|
-
taskId
|
|
275
|
+
taskId,
|
|
236
276
|
kind: "artifact-update",
|
|
237
277
|
append: false,
|
|
238
278
|
lastChunk: true,
|
|
@@ -254,7 +294,7 @@ export async function sendCommand(params) {
|
|
|
254
294
|
// Build JSON-RPC response
|
|
255
295
|
const jsonRpcResponse = {
|
|
256
296
|
jsonrpc: "2.0",
|
|
257
|
-
id:
|
|
297
|
+
id: messageId,
|
|
258
298
|
result: artifact,
|
|
259
299
|
};
|
|
260
300
|
// Send via WebSocket
|
|
@@ -263,7 +303,7 @@ export async function sendCommand(params) {
|
|
|
263
303
|
msgType: "agent_response",
|
|
264
304
|
agentId: config.agentId,
|
|
265
305
|
sessionId,
|
|
266
|
-
taskId
|
|
306
|
+
taskId,
|
|
267
307
|
msgDetail: JSON.stringify(jsonRpcResponse),
|
|
268
308
|
};
|
|
269
309
|
// Log complete response body
|
|
@@ -283,12 +323,10 @@ export async function sendCard(params) {
|
|
|
283
323
|
throw new Error("sendCard does not support cron mode");
|
|
284
324
|
}
|
|
285
325
|
// ── Normal mode: WebSocket ─────────────────────────────────────
|
|
286
|
-
const
|
|
287
|
-
const currentMessageId = getCurrentMessageId(sessionId) ?? messageId;
|
|
288
|
-
const log = logger.withContext(sessionId, currentTaskId);
|
|
326
|
+
const log = logger.withContext(sessionId, taskId);
|
|
289
327
|
// Build artifact update with cardsInfo as data
|
|
290
328
|
const artifact = {
|
|
291
|
-
taskId
|
|
329
|
+
taskId,
|
|
292
330
|
kind: "artifact-update",
|
|
293
331
|
append: false,
|
|
294
332
|
lastChunk: true,
|
|
@@ -308,7 +346,7 @@ export async function sendCard(params) {
|
|
|
308
346
|
// Build JSON-RPC response
|
|
309
347
|
const jsonRpcResponse = {
|
|
310
348
|
jsonrpc: "2.0",
|
|
311
|
-
id:
|
|
349
|
+
id: messageId,
|
|
312
350
|
result: artifact,
|
|
313
351
|
};
|
|
314
352
|
// Send via WebSocket
|
|
@@ -317,7 +355,7 @@ export async function sendCard(params) {
|
|
|
317
355
|
msgType: "agent_response",
|
|
318
356
|
agentId: config.agentId,
|
|
319
357
|
sessionId,
|
|
320
|
-
taskId
|
|
358
|
+
taskId,
|
|
321
359
|
msgDetail: JSON.stringify(jsonRpcResponse),
|
|
322
360
|
};
|
|
323
361
|
log.log(`[A2A_CARD] Sending card`);
|
|
@@ -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[];
|