@ai-setting/roy-agent-core 1.7.41 → 1.7.42

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.
@@ -11,7 +11,7 @@ import {
11
11
  larkCliHandler,
12
12
  resolveBountyIMSystemPrompt,
13
13
  timerHandler
14
- } from "../../shared/@ai-setting/roy-agent-core-wqbpddyr.js";
14
+ } from "../../shared/@ai-setting/roy-agent-core-2f2nqx7g.js";
15
15
  import"../../shared/@ai-setting/roy-agent-core-jawzpf5k.js";
16
16
  import {
17
17
  BUILT_IN_EVENT_SOURCE_TYPES,
@@ -22,7 +22,7 @@ import {
22
22
  isValidEventSourceType,
23
23
  validateEventSourceConfig
24
24
  } from "../../shared/@ai-setting/roy-agent-core-ck60j1q9.js";
25
- import"../../shared/@ai-setting/roy-agent-core-zmr3jzpe.js";
25
+ import"../../shared/@ai-setting/roy-agent-core-0zgcfcnq.js";
26
26
  import {
27
27
  EventStoreImpl,
28
28
  getSharedEventStore,
package/dist/env/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  BaseEnvironment
3
- } from "../shared/@ai-setting/roy-agent-core-ncydpb6b.js";
3
+ } from "../shared/@ai-setting/roy-agent-core-qhw8jp6j.js";
4
4
  import {
5
5
  TaskComponent
6
6
  } from "../shared/@ai-setting/roy-agent-core-8xgk89y4.js";
@@ -15,7 +15,7 @@ import {
15
15
  EventSourceComponent,
16
16
  builtInHandlers,
17
17
  larkCliHandler
18
- } from "../shared/@ai-setting/roy-agent-core-wqbpddyr.js";
18
+ } from "../shared/@ai-setting/roy-agent-core-2f2nqx7g.js";
19
19
  import"../shared/@ai-setting/roy-agent-core-jawzpf5k.js";
20
20
  import {
21
21
  EventSourceInitHooks,
@@ -24,7 +24,7 @@ import {
24
24
  isValidEventSourceType,
25
25
  validateEventSourceConfig
26
26
  } from "../shared/@ai-setting/roy-agent-core-ck60j1q9.js";
27
- import"../shared/@ai-setting/roy-agent-core-zmr3jzpe.js";
27
+ import"../shared/@ai-setting/roy-agent-core-0zgcfcnq.js";
28
28
  import"../shared/@ai-setting/roy-agent-core-xyys5m1a.js";
29
29
  import"../shared/@ai-setting/roy-agent-core-1pg0fepg.js";
30
30
  import"../shared/@ai-setting/roy-agent-core-223v204d.js";
@@ -10,7 +10,7 @@ import {
10
10
  formatExtractorInput,
11
11
  formatExtractorInputFromDescription,
12
12
  parseExtractorOutput
13
- } from "../../../shared/@ai-setting/roy-agent-core-zmr3jzpe.js";
13
+ } from "../../../shared/@ai-setting/roy-agent-core-0zgcfcnq.js";
14
14
  import"../../../shared/@ai-setting/roy-agent-core-xyys5m1a.js";
15
15
  import"../../../shared/@ai-setting/roy-agent-core-1pg0fepg.js";
16
16
  import"../../../shared/@ai-setting/roy-agent-core-223v204d.js";
package/dist/index.js CHANGED
@@ -66,7 +66,7 @@ import {
66
66
  BaseEnvironment,
67
67
  generateDescendingId,
68
68
  generateId
69
- } from "./shared/@ai-setting/roy-agent-core-ncydpb6b.js";
69
+ } from "./shared/@ai-setting/roy-agent-core-qhw8jp6j.js";
70
70
  import {
71
71
  TaskComponent
72
72
  } from "./shared/@ai-setting/roy-agent-core-8xgk89y4.js";
@@ -92,7 +92,7 @@ import {
92
92
  larkCliHandler,
93
93
  resolveBountyIMSystemPrompt,
94
94
  timerHandler
95
- } from "./shared/@ai-setting/roy-agent-core-wqbpddyr.js";
95
+ } from "./shared/@ai-setting/roy-agent-core-2f2nqx7g.js";
96
96
  import {
97
97
  LogTraceComponent,
98
98
  LogTraceConfigSchema
@@ -109,7 +109,7 @@ import {
109
109
  import {
110
110
  TaskTagPlugin,
111
111
  createAutoTaskPlugin
112
- } from "./shared/@ai-setting/roy-agent-core-zmr3jzpe.js";
112
+ } from "./shared/@ai-setting/roy-agent-core-0zgcfcnq.js";
113
113
  import {
114
114
  EventStoreImpl,
115
115
  getSharedEventStore,
@@ -377,6 +377,24 @@ init_decorator();
377
377
  init_logger();
378
378
  init_context();
379
379
  import { spawn } from "child_process";
380
+
381
+ // src/env/event-source/idempotency-key.ts
382
+ var MAX_KEY_LEN = 50;
383
+ var KEY_PREFIX = "roy-";
384
+ function deriveIdempotencyKey(parts) {
385
+ const source = parts.filter((p) => p !== undefined && p !== null).map((p) => String(p)).join("-");
386
+ let key;
387
+ try {
388
+ key = `${KEY_PREFIX}${Bun.hash(source).toString(36).slice(0, 16)}`;
389
+ } catch {
390
+ key = `${KEY_PREFIX}${source.replace(/[^a-zA-Z0-9-]/g, "_").slice(0, 40)}`;
391
+ }
392
+ if (key.length > MAX_KEY_LEN)
393
+ key = key.slice(0, MAX_KEY_LEN);
394
+ return key;
395
+ }
396
+
397
+ // src/env/task/plugins/lark-cli-task-notify-plugin.ts
380
398
  var logger3 = createLogger("lark-cli:task-notify");
381
399
  function isTaskNotifyDebugEnabled() {
382
400
  return process.env.ROY_TASK_NOTIFY_DEBUG === "1" || process.env.ROY_TRACE_DEBUG === "1";
@@ -608,35 +626,51 @@ ${content}`;
608
626
  logger3.error(`Failed to send notification: ${error}`);
609
627
  }
610
628
  }
629
+ buildReplyArgs(options) {
630
+ const { messageId, content, profile, taskId, type } = options;
631
+ const normalizedContent = normalizeLarkAtMentions(content);
632
+ const idempotencyKey = deriveIdempotencyKey([
633
+ "notify",
634
+ taskId,
635
+ type,
636
+ normalizedContent
637
+ ]);
638
+ let args;
639
+ if (messageId) {
640
+ args = [
641
+ "im",
642
+ "+messages-reply",
643
+ "--message-id",
644
+ messageId,
645
+ "--markdown",
646
+ normalizedContent,
647
+ "--as",
648
+ "bot",
649
+ "--idempotency-key",
650
+ idempotencyKey
651
+ ];
652
+ } else {
653
+ args = [
654
+ "im",
655
+ "+messages-send",
656
+ "--chat-id",
657
+ options.chatId,
658
+ "--markdown",
659
+ normalizedContent,
660
+ "--as",
661
+ "bot",
662
+ "--idempotency-key",
663
+ idempotencyKey
664
+ ];
665
+ }
666
+ if (profile) {
667
+ args.unshift("--profile", profile);
668
+ }
669
+ return args;
670
+ }
611
671
  sendLarkMessage(options) {
612
672
  return new Promise((resolve, reject) => {
613
- const { chatId, messageId, content, profile } = options;
614
- let args;
615
- const normalizedContent = normalizeLarkAtMentions(content);
616
- if (messageId) {
617
- args = [
618
- "im",
619
- "+messages-reply",
620
- "--message-id",
621
- messageId,
622
- "--markdown",
623
- normalizedContent,
624
- "--as",
625
- "bot"
626
- ];
627
- } else {
628
- args = [
629
- "im",
630
- "+messages-send",
631
- "--chat-id",
632
- chatId,
633
- "--markdown",
634
- normalizedContent
635
- ];
636
- }
637
- if (profile) {
638
- args.unshift("--profile", profile);
639
- }
673
+ const args = this.buildReplyArgs(options);
640
674
  const proc = spawn("lark-cli", args, {
641
675
  shell: false,
642
676
  stdio: ["pipe", "pipe", "pipe"]
@@ -1235,15 +1269,19 @@ class PerTaskGroupChatPlugin {
1235
1269
  }
1236
1270
  }
1237
1271
  buildSendToChatArgs(opts) {
1272
+ const normalized = normalizeLarkAtMentions(opts.content);
1273
+ const idempotencyKey = opts.idempotencyKey ?? deriveIdempotencyKey(["chat", opts.chatId, normalized]);
1238
1274
  const args = [
1239
1275
  "im",
1240
1276
  "+messages-send",
1241
1277
  "--chat-id",
1242
1278
  opts.chatId,
1243
1279
  "--markdown",
1244
- normalizeLarkAtMentions(opts.content),
1280
+ normalized,
1245
1281
  "--as",
1246
- "bot"
1282
+ "bot",
1283
+ "--idempotency-key",
1284
+ idempotencyKey
1247
1285
  ];
1248
1286
  if (opts.profile) {
1249
1287
  args.unshift("--profile", opts.profile);
@@ -5,7 +5,7 @@ import {
5
5
  TaskTagPlugin,
6
6
  createLarkCliTaskNotifyHook,
7
7
  createPerTaskGroupChatPlugin
8
- } from "./roy-agent-core-zmr3jzpe.js";
8
+ } from "./roy-agent-core-0zgcfcnq.js";
9
9
  import {
10
10
  getSharedEventStore
11
11
  } from "./roy-agent-core-xyys5m1a.js";
@@ -919,6 +919,29 @@ function buildLarkRecommendedAction(opts) {
919
919
  `- 禁止字面反斜杠+n(即 \\n 两个字符,不是 0x0A 控制字符)`,
920
920
  `- 禁止 bash ANSI-C 引号语法(dollar 符号紧跟单引号)`,
921
921
  ``,
922
+ `## ⭐ 关键 3:出站必须显式 --as bot,禁止走 api POST`,
923
+ `所有出站命令**照抄下面模板**(--as bot 已写死在命令里,不要自己重写、不要省 flag):`,
924
+ ``,
925
+ ` # 回复某条消息(有 replyTo.messageId 时)`,
926
+ ` lark-cli ${profileFlag}im +messages-reply --message-id <取自 replyTo.messageId> --as bot --msg-type post --content "$content"`,
927
+ ``,
928
+ ` # 发到会话(无 messageId,只有 chatId 时)`,
929
+ ` lark-cli ${profileFlag}im +messages-send --chat-id <取自 replyTo.chatId> --as bot --msg-type post --content "$content"`,
930
+ ``,
931
+ `- 两条模板都必须满足:显式 --as bot、带对应 profile、--content 是结构化 post JSON`,
932
+ `- 出站身份必须是 bot;以 user 身份发出 → 飞书又把消息回灌给自己 → 形成持续回声`,
933
+ `- 禁止使用 \`lark-cli api POST /open-apis/im/v1/messages\` 直接发消息`,
934
+ ` - api POST 路径默认 identity=user(即 user-identity 路径)→ 自我回灌`,
935
+ `- 如果 lark-cli 报 99992402 字段校验错误,**不要换路径**,而应检查 --content JSON 结构(必须用 --msg-type post + 结构化 content)`,
936
+ `- 出口处判定发送成功**只看 exit code**(见下方"成功判定"),不要 parse stdout JSON`,
937
+ ``,
938
+ `## 成功判定:只看退出码,禁止 parse stdout JSON`,
939
+ `- \`lark-cli … ; rc=$?; [ $rc -eq 0 ] || echo "FAIL rc=$rc"\``,
940
+ `- 禁止用 \`python json.load\` / \`python json.tool\` / \`jq\` 解析 lark-cli 发送响应`,
941
+ ` - 飞书消息正文里常含裸 \`"\`、\`|\`、Markdown 表格分隔符 → json.load 会报 \`Expecting ',' delimiter\` 假失败`,
942
+ ` - 假失败 → 重发 → 形成 3 份相同消息`,
943
+ `- 重试建议:固定 idempotency-key(飞书层面去重),不要靠内容 hash 自检`,
944
+ ``,
922
945
  `## 必须使用 replyTo 里给定的值`,
923
946
  `profile / chatId / messageId / --as bot 必须原样取自 recommendedAction.replyTo;不要凭印象自己拼接。`
924
947
  ].join(`
@@ -1005,6 +1028,12 @@ class LarkCliInstance {
1005
1028
  child;
1006
1029
  buffer = "";
1007
1030
  eventHandler;
1031
+ static SHARED_SEEN = new Map;
1032
+ static SHARED_MSG_TTL_MS = 10 * 60 * 1000;
1033
+ static SHARED_MSG_MAX = 1000;
1034
+ static __resetDedupForTest() {
1035
+ LarkCliInstance.SHARED_SEEN.clear();
1036
+ }
1008
1037
  recentEventIds = new Map;
1009
1038
  DEDUP_WINDOW_MS = 60000;
1010
1039
  DEDUP_MAX_SIZE = 100;
@@ -1337,12 +1366,25 @@ class LarkCliInstance {
1337
1366
  } catch {}
1338
1367
  if (dedupKey) {
1339
1368
  const now = Date.now();
1369
+ const lastShared = LarkCliInstance.SHARED_SEEN.get(dedupKey);
1370
+ if (lastShared !== undefined && now - lastShared < LarkCliInstance.SHARED_MSG_TTL_MS) {
1371
+ logger.warn(`[LarkCliInstance] duplicate lark-cli event suppressed across instances (event_id=${dedupKey}, ` + `lastSeen=${now - lastShared}ms ago). ` + `Task #4137: SHARED_SEEN 跨实例去重。`);
1372
+ return;
1373
+ }
1340
1374
  const last = this.recentEventIds.get(dedupKey);
1341
1375
  if (last !== undefined && now - last < this.DEDUP_WINDOW_MS) {
1342
1376
  logger.warn(`[LarkCliInstance] duplicate lark-cli event suppressed (event_id=${dedupKey}, ` + `lastSeen=${now - last}ms ago). ` + `Task #3977/3978: 防止同一飞书事件触发两次任务创建。`);
1343
1377
  return;
1344
1378
  }
1379
+ LarkCliInstance.SHARED_SEEN.set(dedupKey, now);
1345
1380
  this.recentEventIds.set(dedupKey, now);
1381
+ if (LarkCliInstance.SHARED_SEEN.size > LarkCliInstance.SHARED_MSG_MAX) {
1382
+ const cutoff = now - LarkCliInstance.SHARED_MSG_TTL_MS;
1383
+ for (const [k, t] of LarkCliInstance.SHARED_SEEN) {
1384
+ if (t < cutoff)
1385
+ LarkCliInstance.SHARED_SEEN.delete(k);
1386
+ }
1387
+ }
1346
1388
  if (this.recentEventIds.size > this.DEDUP_MAX_SIZE) {
1347
1389
  const cutoff = now - this.DEDUP_WINDOW_MS;
1348
1390
  for (const [k, t] of this.recentEventIds) {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createAutoTaskPlugin
3
- } from "./roy-agent-core-zmr3jzpe.js";
3
+ } from "./roy-agent-core-0zgcfcnq.js";
4
4
  import {
5
5
  ContextError,
6
6
  ErrorCodes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-setting/roy-agent-core",
3
- "version": "1.7.41",
3
+ "version": "1.7.42",
4
4
  "type": "module",
5
5
  "description": "Core SDK for roy-agent - Environment, Components, Tools, Sessions, Tasks",
6
6
  "main": "./dist/index.js",