@ai-setting/roy-agent-cli 1.7.38 → 1.7.40

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.
@@ -9461,7 +9461,7 @@ class CliQuietModeService {
9461
9461
  // package.json
9462
9462
  var package_default = {
9463
9463
  name: "@ai-setting/roy-agent-cli",
9464
- version: "1.7.38",
9464
+ version: "1.7.40",
9465
9465
  type: "module",
9466
9466
  description: "CLI for roy-agent - Non-interactive command execution",
9467
9467
  main: "./dist/index.js",
@@ -11535,6 +11535,24 @@ import { EventStoreImpl, setSharedEventStore } from "@ai-setting/roy-agent-core/
11535
11535
 
11536
11536
  // src/commands/shared/event-handler.ts
11537
11537
  import { TracedAs as TracedAs5 } from "@ai-setting/roy-agent-core";
11538
+ function parseLarkPerTaskChatId(contextJson) {
11539
+ if (!contextJson)
11540
+ return;
11541
+ try {
11542
+ const obj = JSON.parse(contextJson);
11543
+ const id = obj?.larkPerTaskChatId;
11544
+ return typeof id === "string" && id.length > 0 ? id : undefined;
11545
+ } catch {
11546
+ return;
11547
+ }
11548
+ }
11549
+ var NOTIFY_V2_TERMINAL_TYPES = new Set([
11550
+ "task.background.completed",
11551
+ "task.background.failed",
11552
+ "task.background.timeout",
11553
+ "task.background.stopped"
11554
+ ]);
11555
+
11538
11556
  class EventHandler {
11539
11557
  env;
11540
11558
  eventTypes;
@@ -11549,6 +11567,7 @@ class EventHandler {
11549
11567
  unsubscribe = null;
11550
11568
  sessionComponent = null;
11551
11569
  activeEventSessionId = null;
11570
+ resolvedSessionByTrigger = new Map;
11552
11571
  eventStore = null;
11553
11572
  getHandlerForEsType = null;
11554
11573
  constructor(options) {
@@ -11607,7 +11626,7 @@ class EventHandler {
11607
11626
  this.enqueue(formatted);
11608
11627
  }
11609
11628
  async formatEvent(event) {
11610
- if (event.type.startsWith("task.background.") && event.metadata?.triggerEventId && this.eventStore && this.getHandlerForEsType) {
11629
+ if (NOTIFY_V2_TERMINAL_TYPES.has(event.type) && event.metadata?.triggerEventId && this.eventStore && this.getHandlerForEsType) {
11611
11630
  try {
11612
11631
  const v2Formatted = await this.formatEventViaESPluginV2(event);
11613
11632
  if (v2Formatted) {
@@ -11655,13 +11674,17 @@ class EventHandler {
11655
11674
  error: typeof payload?.error === "string" ? payload.error : undefined
11656
11675
  };
11657
11676
  setTimeout(() => {
11658
- Promise.resolve(handler.postProcessNotifyEvent({
11659
- notifyEvent: notifyEventForHook,
11660
- triggerEvent,
11661
- subAgentResult,
11662
- formattedPrompt: prompt.promptText,
11663
- profile
11664
- })).catch((err) => {
11677
+ (async () => {
11678
+ const resolvedChatIds = await this.resolveNotifyChatIds(notifyEventForHook.taskId);
11679
+ await handler.postProcessNotifyEvent({
11680
+ notifyEvent: notifyEventForHook,
11681
+ triggerEvent,
11682
+ subAgentResult,
11683
+ formattedPrompt: prompt.promptText,
11684
+ profile,
11685
+ resolvedChatIds
11686
+ });
11687
+ })().catch((err) => {
11665
11688
  console.error(`[EventHandler] postProcessNotifyEvent hook failed (swallowed)`, err);
11666
11689
  });
11667
11690
  }, 0);
@@ -11677,6 +11700,33 @@ class EventHandler {
11677
11700
  ...triggerMessageId ? { triggerMessageId } : {}
11678
11701
  };
11679
11702
  }
11703
+ async resolveNotifyChatIds(taskId) {
11704
+ if (!taskId)
11705
+ return [];
11706
+ const taskComp = this.env.getComponent("task");
11707
+ if (!taskComp?.getTask)
11708
+ return [];
11709
+ const seen = new Set;
11710
+ let id = taskId;
11711
+ while (id !== undefined && id !== null && !seen.has(id) && seen.size < 8) {
11712
+ seen.add(id);
11713
+ let task;
11714
+ try {
11715
+ task = await taskComp.getTask(id);
11716
+ } catch (err) {
11717
+ console.error(`[EventHandler] resolveNotifyChatIds: getTask(${id}) failed`, err);
11718
+ return [];
11719
+ }
11720
+ if (!task)
11721
+ return [];
11722
+ const chatId = parseLarkPerTaskChatId(task.context);
11723
+ if (chatId)
11724
+ return [chatId];
11725
+ const parent = task.parent_task_id;
11726
+ id = typeof parent === "number" && parent > 0 ? parent : undefined;
11727
+ }
11728
+ return [];
11729
+ }
11680
11730
  async handleNotifyEventForTest(event) {
11681
11731
  if (this.isStopped)
11682
11732
  return;
@@ -11753,7 +11803,12 @@ class EventHandler {
11753
11803
  async ensureActiveSession(triggerSessionIdOverride) {
11754
11804
  if (!this.sessionComponent)
11755
11805
  return null;
11756
- if (this.activeEventSessionId) {
11806
+ if (triggerSessionIdOverride) {
11807
+ const cached = this.resolvedSessionByTrigger.get(triggerSessionIdOverride);
11808
+ if (cached) {
11809
+ return cached;
11810
+ }
11811
+ } else if (this.activeEventSessionId) {
11757
11812
  return this.activeEventSessionId;
11758
11813
  }
11759
11814
  const triggerSessionId = triggerSessionIdOverride ?? this.queue.map((item) => item.triggerSessionId).find((id) => !!id);
@@ -11765,6 +11820,7 @@ class EventHandler {
11765
11820
  return null;
11766
11821
  }
11767
11822
  this.activeEventSessionId = existing.id;
11823
+ this.cacheResolvedSession(triggerSessionIdOverride, existing.id);
11768
11824
  await this.sessionComponent.setActiveSession(existing.id);
11769
11825
  return existing.id;
11770
11826
  }
@@ -11782,13 +11838,16 @@ class EventHandler {
11782
11838
  return null;
11783
11839
  }
11784
11840
  this.activeEventSessionId = existing.id;
11841
+ this.cacheResolvedSession(triggerSessionIdOverride, existing.id);
11785
11842
  return existing.id;
11786
11843
  }
11787
11844
  }
11788
11845
  } catch (error) {
11789
11846
  console.error(`[EventHandler] Failed to lookup global active session:`, error);
11790
11847
  }
11791
- return this.createNewEventSession();
11848
+ const created = await this.createNewEventSession();
11849
+ this.cacheResolvedSession(triggerSessionIdOverride, created);
11850
+ return created;
11792
11851
  }
11793
11852
  async ensureChatSession(chatId) {
11794
11853
  if (!this.sessionComponent)
@@ -11848,6 +11907,12 @@ class EventHandler {
11848
11907
  }
11849
11908
  clearActiveSession() {
11850
11909
  this.activeEventSessionId = null;
11910
+ this.resolvedSessionByTrigger.clear();
11911
+ }
11912
+ cacheResolvedSession(triggerSessionIdOverride, sessionId) {
11913
+ if (triggerSessionIdOverride && sessionId) {
11914
+ this.resolvedSessionByTrigger.set(triggerSessionIdOverride, sessionId);
11915
+ }
11851
11916
  }
11852
11917
  getActiveEventSessionId() {
11853
11918
  return this.activeEventSessionId;
@@ -11886,7 +11951,7 @@ __legacyDecorateClassTS([
11886
11951
  __legacyMetadataTS("design:returntype", typeof Promise === "undefined" ? Object : Promise)
11887
11952
  ], EventHandler.prototype, "formatEventViaESPluginV2", null);
11888
11953
  __legacyDecorateClassTS([
11889
- TracedAs5("cli.event-handler.ensureActiveSession", { recordParams: true }),
11954
+ TracedAs5("cli.event-handler.ensureActiveSession", { recordParams: true, recordResult: true }),
11890
11955
  __legacyMetadataTS("design:type", Function),
11891
11956
  __legacyMetadataTS("design:paramtypes", [
11892
11957
  String
@@ -13121,16 +13186,23 @@ ${COLORS.system("[通知2] ❯ " + message.replace(/\n/g, `
13121
13186
  const agentFromEvent = envEvent.metadata?.agent;
13122
13187
  let envEventForAgent = envEvent;
13123
13188
  const eventReplyChannel = envEvent?.metadata?.replyChannel;
13189
+ const eventChatId = eventReplyChannel?.chatId ?? formattedEvent.chatId ?? envEvent?.payload?.replyChannel?.chatId;
13124
13190
  if (eventReplyChannel) {
13125
13191
  this.lastReplyChannel = eventReplyChannel;
13126
- } else if (this.lastReplyChannel) {
13127
- envEventForAgent = {
13128
- ...envEvent,
13129
- metadata: {
13130
- ...envEvent?.metadata ?? {},
13131
- replyChannel: this.lastReplyChannel
13132
- }
13133
- };
13192
+ const rcChatId = eventReplyChannel.chatId;
13193
+ if (rcChatId)
13194
+ this.rememberReplyChannelForChat(rcChatId, eventReplyChannel);
13195
+ } else {
13196
+ const fallbackChannel = (eventChatId ? this.lastReplyChannelByChat?.get(eventChatId) : undefined) ?? this.lastReplyChannel;
13197
+ if (fallbackChannel) {
13198
+ envEventForAgent = {
13199
+ ...envEvent,
13200
+ metadata: {
13201
+ ...envEvent?.metadata ?? {},
13202
+ replyChannel: fallbackChannel
13203
+ }
13204
+ };
13205
+ }
13134
13206
  }
13135
13207
  this.currentAgentContext = {
13136
13208
  agentType: agentFromEvent,
@@ -13144,6 +13216,22 @@ ${COLORS.system("[通知2] ❯ " + message.replace(/\n/g, `
13144
13216
  }
13145
13217
  currentAgentContext = undefined;
13146
13218
  lastReplyChannel = undefined;
13219
+ lastReplyChannelByChat = new Map;
13220
+ static REPLY_CHANNEL_CHAT_CACHE_MAX = 100;
13221
+ rememberReplyChannelForChat(chatId, channel) {
13222
+ if (!this.lastReplyChannelByChat)
13223
+ this.lastReplyChannelByChat = new Map;
13224
+ if (this.lastReplyChannelByChat.has(chatId)) {
13225
+ this.lastReplyChannelByChat.delete(chatId);
13226
+ }
13227
+ this.lastReplyChannelByChat.set(chatId, channel);
13228
+ while (this.lastReplyChannelByChat.size > REPL.REPLY_CHANNEL_CHAT_CACHE_MAX) {
13229
+ const oldest = this.lastReplyChannelByChat.keys().next().value;
13230
+ if (oldest === undefined)
13231
+ break;
13232
+ this.lastReplyChannelByChat.delete(oldest);
13233
+ }
13234
+ }
13147
13235
  isIdle() {
13148
13236
  return !this.isExecuting;
13149
13237
  }
package/dist/index.js CHANGED
@@ -9460,7 +9460,7 @@ class CliQuietModeService {
9460
9460
  // package.json
9461
9461
  var package_default = {
9462
9462
  name: "@ai-setting/roy-agent-cli",
9463
- version: "1.7.38",
9463
+ version: "1.7.40",
9464
9464
  type: "module",
9465
9465
  description: "CLI for roy-agent - Non-interactive command execution",
9466
9466
  main: "./dist/index.js",
@@ -11534,6 +11534,24 @@ import { EventStoreImpl, setSharedEventStore } from "@ai-setting/roy-agent-core/
11534
11534
 
11535
11535
  // src/commands/shared/event-handler.ts
11536
11536
  import { TracedAs as TracedAs5 } from "@ai-setting/roy-agent-core";
11537
+ function parseLarkPerTaskChatId(contextJson) {
11538
+ if (!contextJson)
11539
+ return;
11540
+ try {
11541
+ const obj = JSON.parse(contextJson);
11542
+ const id = obj?.larkPerTaskChatId;
11543
+ return typeof id === "string" && id.length > 0 ? id : undefined;
11544
+ } catch {
11545
+ return;
11546
+ }
11547
+ }
11548
+ var NOTIFY_V2_TERMINAL_TYPES = new Set([
11549
+ "task.background.completed",
11550
+ "task.background.failed",
11551
+ "task.background.timeout",
11552
+ "task.background.stopped"
11553
+ ]);
11554
+
11537
11555
  class EventHandler {
11538
11556
  env;
11539
11557
  eventTypes;
@@ -11548,6 +11566,7 @@ class EventHandler {
11548
11566
  unsubscribe = null;
11549
11567
  sessionComponent = null;
11550
11568
  activeEventSessionId = null;
11569
+ resolvedSessionByTrigger = new Map;
11551
11570
  eventStore = null;
11552
11571
  getHandlerForEsType = null;
11553
11572
  constructor(options) {
@@ -11606,7 +11625,7 @@ class EventHandler {
11606
11625
  this.enqueue(formatted);
11607
11626
  }
11608
11627
  async formatEvent(event) {
11609
- if (event.type.startsWith("task.background.") && event.metadata?.triggerEventId && this.eventStore && this.getHandlerForEsType) {
11628
+ if (NOTIFY_V2_TERMINAL_TYPES.has(event.type) && event.metadata?.triggerEventId && this.eventStore && this.getHandlerForEsType) {
11610
11629
  try {
11611
11630
  const v2Formatted = await this.formatEventViaESPluginV2(event);
11612
11631
  if (v2Formatted) {
@@ -11654,13 +11673,17 @@ class EventHandler {
11654
11673
  error: typeof payload?.error === "string" ? payload.error : undefined
11655
11674
  };
11656
11675
  setTimeout(() => {
11657
- Promise.resolve(handler.postProcessNotifyEvent({
11658
- notifyEvent: notifyEventForHook,
11659
- triggerEvent,
11660
- subAgentResult,
11661
- formattedPrompt: prompt.promptText,
11662
- profile
11663
- })).catch((err) => {
11676
+ (async () => {
11677
+ const resolvedChatIds = await this.resolveNotifyChatIds(notifyEventForHook.taskId);
11678
+ await handler.postProcessNotifyEvent({
11679
+ notifyEvent: notifyEventForHook,
11680
+ triggerEvent,
11681
+ subAgentResult,
11682
+ formattedPrompt: prompt.promptText,
11683
+ profile,
11684
+ resolvedChatIds
11685
+ });
11686
+ })().catch((err) => {
11664
11687
  console.error(`[EventHandler] postProcessNotifyEvent hook failed (swallowed)`, err);
11665
11688
  });
11666
11689
  }, 0);
@@ -11676,6 +11699,33 @@ class EventHandler {
11676
11699
  ...triggerMessageId ? { triggerMessageId } : {}
11677
11700
  };
11678
11701
  }
11702
+ async resolveNotifyChatIds(taskId) {
11703
+ if (!taskId)
11704
+ return [];
11705
+ const taskComp = this.env.getComponent("task");
11706
+ if (!taskComp?.getTask)
11707
+ return [];
11708
+ const seen = new Set;
11709
+ let id = taskId;
11710
+ while (id !== undefined && id !== null && !seen.has(id) && seen.size < 8) {
11711
+ seen.add(id);
11712
+ let task;
11713
+ try {
11714
+ task = await taskComp.getTask(id);
11715
+ } catch (err) {
11716
+ console.error(`[EventHandler] resolveNotifyChatIds: getTask(${id}) failed`, err);
11717
+ return [];
11718
+ }
11719
+ if (!task)
11720
+ return [];
11721
+ const chatId = parseLarkPerTaskChatId(task.context);
11722
+ if (chatId)
11723
+ return [chatId];
11724
+ const parent = task.parent_task_id;
11725
+ id = typeof parent === "number" && parent > 0 ? parent : undefined;
11726
+ }
11727
+ return [];
11728
+ }
11679
11729
  async handleNotifyEventForTest(event) {
11680
11730
  if (this.isStopped)
11681
11731
  return;
@@ -11752,7 +11802,12 @@ class EventHandler {
11752
11802
  async ensureActiveSession(triggerSessionIdOverride) {
11753
11803
  if (!this.sessionComponent)
11754
11804
  return null;
11755
- if (this.activeEventSessionId) {
11805
+ if (triggerSessionIdOverride) {
11806
+ const cached = this.resolvedSessionByTrigger.get(triggerSessionIdOverride);
11807
+ if (cached) {
11808
+ return cached;
11809
+ }
11810
+ } else if (this.activeEventSessionId) {
11756
11811
  return this.activeEventSessionId;
11757
11812
  }
11758
11813
  const triggerSessionId = triggerSessionIdOverride ?? this.queue.map((item) => item.triggerSessionId).find((id) => !!id);
@@ -11764,6 +11819,7 @@ class EventHandler {
11764
11819
  return null;
11765
11820
  }
11766
11821
  this.activeEventSessionId = existing.id;
11822
+ this.cacheResolvedSession(triggerSessionIdOverride, existing.id);
11767
11823
  await this.sessionComponent.setActiveSession(existing.id);
11768
11824
  return existing.id;
11769
11825
  }
@@ -11781,13 +11837,16 @@ class EventHandler {
11781
11837
  return null;
11782
11838
  }
11783
11839
  this.activeEventSessionId = existing.id;
11840
+ this.cacheResolvedSession(triggerSessionIdOverride, existing.id);
11784
11841
  return existing.id;
11785
11842
  }
11786
11843
  }
11787
11844
  } catch (error) {
11788
11845
  console.error(`[EventHandler] Failed to lookup global active session:`, error);
11789
11846
  }
11790
- return this.createNewEventSession();
11847
+ const created = await this.createNewEventSession();
11848
+ this.cacheResolvedSession(triggerSessionIdOverride, created);
11849
+ return created;
11791
11850
  }
11792
11851
  async ensureChatSession(chatId) {
11793
11852
  if (!this.sessionComponent)
@@ -11847,6 +11906,12 @@ class EventHandler {
11847
11906
  }
11848
11907
  clearActiveSession() {
11849
11908
  this.activeEventSessionId = null;
11909
+ this.resolvedSessionByTrigger.clear();
11910
+ }
11911
+ cacheResolvedSession(triggerSessionIdOverride, sessionId) {
11912
+ if (triggerSessionIdOverride && sessionId) {
11913
+ this.resolvedSessionByTrigger.set(triggerSessionIdOverride, sessionId);
11914
+ }
11850
11915
  }
11851
11916
  getActiveEventSessionId() {
11852
11917
  return this.activeEventSessionId;
@@ -11885,7 +11950,7 @@ __legacyDecorateClassTS([
11885
11950
  __legacyMetadataTS("design:returntype", typeof Promise === "undefined" ? Object : Promise)
11886
11951
  ], EventHandler.prototype, "formatEventViaESPluginV2", null);
11887
11952
  __legacyDecorateClassTS([
11888
- TracedAs5("cli.event-handler.ensureActiveSession", { recordParams: true }),
11953
+ TracedAs5("cli.event-handler.ensureActiveSession", { recordParams: true, recordResult: true }),
11889
11954
  __legacyMetadataTS("design:type", Function),
11890
11955
  __legacyMetadataTS("design:paramtypes", [
11891
11956
  String
@@ -13120,16 +13185,23 @@ ${COLORS.system("[通知2] ❯ " + message.replace(/\n/g, `
13120
13185
  const agentFromEvent = envEvent.metadata?.agent;
13121
13186
  let envEventForAgent = envEvent;
13122
13187
  const eventReplyChannel = envEvent?.metadata?.replyChannel;
13188
+ const eventChatId = eventReplyChannel?.chatId ?? formattedEvent.chatId ?? envEvent?.payload?.replyChannel?.chatId;
13123
13189
  if (eventReplyChannel) {
13124
13190
  this.lastReplyChannel = eventReplyChannel;
13125
- } else if (this.lastReplyChannel) {
13126
- envEventForAgent = {
13127
- ...envEvent,
13128
- metadata: {
13129
- ...envEvent?.metadata ?? {},
13130
- replyChannel: this.lastReplyChannel
13131
- }
13132
- };
13191
+ const rcChatId = eventReplyChannel.chatId;
13192
+ if (rcChatId)
13193
+ this.rememberReplyChannelForChat(rcChatId, eventReplyChannel);
13194
+ } else {
13195
+ const fallbackChannel = (eventChatId ? this.lastReplyChannelByChat?.get(eventChatId) : undefined) ?? this.lastReplyChannel;
13196
+ if (fallbackChannel) {
13197
+ envEventForAgent = {
13198
+ ...envEvent,
13199
+ metadata: {
13200
+ ...envEvent?.metadata ?? {},
13201
+ replyChannel: fallbackChannel
13202
+ }
13203
+ };
13204
+ }
13133
13205
  }
13134
13206
  this.currentAgentContext = {
13135
13207
  agentType: agentFromEvent,
@@ -13143,6 +13215,22 @@ ${COLORS.system("[通知2] ❯ " + message.replace(/\n/g, `
13143
13215
  }
13144
13216
  currentAgentContext = undefined;
13145
13217
  lastReplyChannel = undefined;
13218
+ lastReplyChannelByChat = new Map;
13219
+ static REPLY_CHANNEL_CHAT_CACHE_MAX = 100;
13220
+ rememberReplyChannelForChat(chatId, channel) {
13221
+ if (!this.lastReplyChannelByChat)
13222
+ this.lastReplyChannelByChat = new Map;
13223
+ if (this.lastReplyChannelByChat.has(chatId)) {
13224
+ this.lastReplyChannelByChat.delete(chatId);
13225
+ }
13226
+ this.lastReplyChannelByChat.set(chatId, channel);
13227
+ while (this.lastReplyChannelByChat.size > REPL.REPLY_CHANNEL_CHAT_CACHE_MAX) {
13228
+ const oldest = this.lastReplyChannelByChat.keys().next().value;
13229
+ if (oldest === undefined)
13230
+ break;
13231
+ this.lastReplyChannelByChat.delete(oldest);
13232
+ }
13233
+ }
13146
13234
  isIdle() {
13147
13235
  return !this.isExecuting;
13148
13236
  }
@@ -1,4 +1,4 @@
1
1
  [diffend] Oversized file quarantined before diffing.
2
2
  name: package/dist/roy-agent-linux-x64/bin/roy-agent
3
- size: 109602944 bytes
4
- sha256: 4bff7951c55594175f880f2caca477359a3c55c89b5b973d9ba7cf8e721d8928
3
+ size: 109627520 bytes
4
+ sha256: 70e2598656125685dba913f210bd2d2f5d7a41a7e80c3969b259fef85b7b61f1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-setting/roy-agent-cli",
3
- "version": "1.7.38",
3
+ "version": "1.7.40",
4
4
  "type": "module",
5
5
  "description": "CLI for roy-agent - Non-interactive command execution",
6
6
  "main": "./dist/index.js",