@ynhcj/xiaoyi-channel 0.0.163-next → 0.0.164-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 CHANGED
@@ -37,18 +37,19 @@ function registerCronDetectionHook(api) {
37
37
  }
38
38
  /** 从 cron add 工具结果中提取 jobId 并写入 pushId 映射。 */
39
39
  async function captureCronAddMapping(event, ctx) {
40
- // 诊断:先看 after_tool_call 是否为 cron 工具触发
41
- if (event.toolName !== "cron")
40
+ // 两条创建路径都要捕获:
41
+ // 1) cron agent 工具:toolName==="cron", params.action==="add"
42
+ // 2) exec 跑 CLI:toolName==="exec", params.command 含 "cron add"
43
+ // (agent 实际用的是这条:openclaw cron add --name ... --cron ... --message ...)
44
+ const isCronAddTool = event.toolName === "cron" &&
45
+ (event.params?.action === "add" || event.params?.action === "create");
46
+ const isExecCronAdd = event.toolName === "exec" && isExecCronAddCommand(event.params?.command);
47
+ if (!isCronAddTool && !isExecCronAdd)
42
48
  return;
43
- const action = typeof event.params?.action === "string" ? event.params.action : "";
44
- console.log(`[CRONMAP] after_tool_call cron, action=${action}, resultType=${typeof event.result}`);
45
- if (action !== "add") {
46
- console.log(`[CRONMAP] skip: action !== "add" (got ${action})`);
47
- return;
48
- }
49
+ console.log(`[CRONMAP] after_tool_call path=${event.toolName}, resultType=${typeof event.result}`);
49
50
  const jobId = readJobIdFromResult(event.result);
50
51
  if (!jobId) {
51
- console.log(`[CRONMAP] skip: could not extract jobId from result. preview=${preview(event.result)}`);
52
+ console.log(`[CRONMAP] skip: could not extract jobId. preview=${preview(event.result)}`);
52
53
  return;
53
54
  }
54
55
  console.log(`[CRONMAP] extracted jobId=${jobId}`);
@@ -68,10 +69,16 @@ async function captureCronAddMapping(event, ctx) {
68
69
  pushId,
69
70
  sessionId,
70
71
  deviceType: sessionCtx?.deviceType,
71
- source: "conversation",
72
+ source: event.toolName === "exec" ? "exec-cli" : "conversation",
72
73
  });
73
74
  console.log(`[CRONMAP] map written OK`);
74
75
  }
76
+ /** 判断 exec 命令是否为 cron add(匹配 "openclaw cron add" 或裸 "cron add",排除 list/remove 等)。 */
77
+ function isExecCronAddCommand(command) {
78
+ if (typeof command !== "string")
79
+ return false;
80
+ return /\bcron\s+add\b/.test(command);
81
+ }
75
82
  /** 取结果的短预览,用于诊断。 */
76
83
  function preview(value) {
77
84
  if (value == null)
@@ -79,18 +86,27 @@ function preview(value) {
79
86
  const s = typeof value === "string" ? value : JSON.stringify(value);
80
87
  return s.length > 200 ? s.slice(0, 200) + "…" : s;
81
88
  }
82
- /** 防御性地从 cron add 结果中取 job id(可能是对象、JSON 字符串或工具输出文本)。 */
89
+ /** 防御性地从 cron add 结果中取 job id
90
+ * 覆盖:裸 job 对象、JSON 字符串、exec 输出文本、{stdout}/data/result/job 嵌套。 */
83
91
  function readJobIdFromResult(result) {
84
92
  if (!result)
85
93
  return undefined;
94
+ // exec 工具结果常把命令输出包在 {stdout, stderr, exitCode} 里
95
+ if (result && typeof result === "object") {
96
+ const stdout = result.stdout;
97
+ if (typeof stdout === "string" && stdout.trim()) {
98
+ const fromStdout = readJobIdFromResult(stdout);
99
+ if (fromStdout)
100
+ return fromStdout;
101
+ }
102
+ }
86
103
  let obj = result;
87
104
  if (typeof result === "string") {
88
- // 优先尝试 JSON 解析
89
105
  try {
90
106
  obj = JSON.parse(result);
91
107
  }
92
108
  catch {
93
- // 解析失败:可能是纯文本工具输出,尝试从文本里抓 "id":"..." 或 id=...
109
+ // 纯文本:从文本里抓 "id":"..." 或 id=...
94
110
  const m = result.match(/"id"\s*:\s*"([^"]+)"/);
95
111
  if (m)
96
112
  return m[1];
@@ -101,7 +117,6 @@ function readJobIdFromResult(result) {
101
117
  const id = obj.id;
102
118
  if (typeof id === "string" && id.trim())
103
119
  return id.trim();
104
- // 兜底:result 可能把 job 包在 data/result 字段里
105
120
  for (const k of ["data", "result", "job"]) {
106
121
  const inner = obj[k];
107
122
  if (inner && typeof inner === "object") {
@@ -1,5 +1,5 @@
1
1
  /** 映射来源,区分两种创建路径。 */
2
- export type CronPushMapSource = "conversation" | "cron-query";
2
+ export type CronPushMapSource = "conversation" | "cron-query" | "exec-cli";
3
3
  export interface CronPushMapEntry {
4
4
  pushId: string;
5
5
  /** 创建该 cron 时的 xy sessionId,便于同进程兜底。 */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ynhcj/xiaoyi-channel",
3
- "version": "0.0.163-next",
3
+ "version": "0.0.164-next",
4
4
  "description": "OpenClaw Xiaoyi Channel plugin - Xiaoyi A2A protocol integration",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",