@pnds/pond 1.7.0 → 1.8.0

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.
Files changed (2) hide show
  1. package/package.json +3 -3
  2. package/src/gateway.ts +29 -13
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pnds/pond",
3
- "version": "1.7.0",
3
+ "version": "1.8.0",
4
4
  "description": "OpenClaw channel plugin for Pond IM",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -15,8 +15,8 @@
15
15
  "openclaw.plugin.json"
16
16
  ],
17
17
  "dependencies": {
18
- "@pnds/cli": "1.7.0",
19
- "@pnds/sdk": "1.7.0"
18
+ "@pnds/sdk": "1.8.0",
19
+ "@pnds/cli": "1.8.0"
20
20
  },
21
21
  "devDependencies": {
22
22
  "@types/node": "^22.0.0",
package/src/gateway.ts CHANGED
@@ -34,7 +34,7 @@ function resolveWsUrl(account: ResolvedPondAccount): string {
34
34
  return `${wsBase}/ws`;
35
35
  }
36
36
 
37
- type ChatInfo = { type: Chat["type"]; name: string | null };
37
+ type ChatInfo = { type: Chat["type"]; name: string | null; agentRoutingMode: Chat["agent_routing_mode"] };
38
38
 
39
39
  /**
40
40
  * Fetch all chats with pagination and populate the info map (type + name).
@@ -49,7 +49,7 @@ async function fetchAllChats(
49
49
  do {
50
50
  const res = await client.getChats(orgId, { limit: 100, cursor });
51
51
  for (const c of res.data) {
52
- chatInfoMap.set(c.id, { type: c.type, name: c.name ?? null });
52
+ chatInfoMap.set(c.id, { type: c.type, name: c.name ?? null, agentRoutingMode: c.agent_routing_mode });
53
53
  }
54
54
  total += res.data.length;
55
55
  cursor = res.has_more ? res.next_cursor : undefined;
@@ -700,13 +700,19 @@ export const pondGateway: ChannelGatewayAdapter<ResolvedPondAccount> = {
700
700
  const changes = data.changes as Record<string, unknown> | undefined;
701
701
  if (!changes) return;
702
702
  const existing = chatInfoMap.get(data.chat_id);
703
- if (typeof changes.type === "string") {
703
+ if (existing) {
704
+ chatInfoMap.set(data.chat_id, {
705
+ ...existing,
706
+ ...(typeof changes.type === "string" ? { type: changes.type as Chat["type"] } : {}),
707
+ ...(typeof changes.name === "string" ? { name: changes.name } : {}),
708
+ ...(typeof changes.agent_routing_mode === "string" ? { agentRoutingMode: changes.agent_routing_mode as Chat["agent_routing_mode"] } : {}),
709
+ });
710
+ } else if (typeof changes.type === "string") {
704
711
  chatInfoMap.set(data.chat_id, {
705
712
  type: changes.type as Chat["type"],
706
- name: (typeof changes.name === "string" ? changes.name : existing?.name) ?? null,
713
+ name: (typeof changes.name === "string" ? changes.name : null),
714
+ agentRoutingMode: (typeof changes.agent_routing_mode === "string" ? changes.agent_routing_mode : "passive") as Chat["agent_routing_mode"],
707
715
  });
708
- } else if (typeof changes.name === "string" && existing) {
709
- chatInfoMap.set(data.chat_id, { ...existing, name: changes.name });
710
716
  }
711
717
  });
712
718
 
@@ -724,7 +730,7 @@ export const pondGateway: ChannelGatewayAdapter<ResolvedPondAccount> = {
724
730
  if (!chatInfo) {
725
731
  try {
726
732
  const chat = await client.getChat(config.org_id, chatId);
727
- chatInfo = { type: chat.type, name: chat.name ?? null };
733
+ chatInfo = { type: chat.type, name: chat.name ?? null, agentRoutingMode: chat.agent_routing_mode };
728
734
  chatInfoMap.set(chatId, chatInfo);
729
735
  } catch (err) {
730
736
  log?.warn(`pond[${ctx.accountId}]: failed to resolve chat for ${chatId}, skipping: ${String(err)}`);
@@ -741,17 +747,27 @@ export const pondGateway: ChannelGatewayAdapter<ResolvedPondAccount> = {
741
747
  body = content.text?.trim() ?? "";
742
748
  if (!body) return;
743
749
 
744
- // In group chats, only respond when @mentioned or @all
745
- if (chatInfo.type === "group") {
750
+ // In group chats, respond based on agent_routing_mode:
751
+ // - passive (default): only when @mentioned or @all
752
+ // - active: all messages dispatched via live handler
753
+ // - smart: skip live handler — server decides routing via inbox items
754
+ if (chatInfo.type === "group" && chatInfo.agentRoutingMode !== "active") {
746
755
  const mentions = content.mentions ?? [];
747
756
  const isMentioned = mentions.some(
748
757
  (m) => m.user_id === agentUserId || m.user_id === MENTION_ALL_USER_ID,
749
758
  );
750
- if (!isMentioned) return;
759
+ if (!isMentioned) {
760
+ // Release claim so catch-up can process this via agent_route inbox items
761
+ dispatchedMessages.delete(data.id);
762
+ return;
763
+ }
751
764
  }
752
765
  } else {
753
766
  const content = data.content as MediaContent;
754
- if (chatInfo.type === "group") return;
767
+ if (chatInfo.type === "group" && chatInfo.agentRoutingMode !== "active") {
768
+ dispatchedMessages.delete(data.id);
769
+ return;
770
+ }
755
771
  body = content.caption?.trim() || `[file: ${content.file_name || "attachment"}]`;
756
772
  if (content.attachment_id) {
757
773
  try {
@@ -873,7 +889,7 @@ export const pondGateway: ChannelGatewayAdapter<ResolvedPondAccount> = {
873
889
 
874
890
  do {
875
891
  const page = await client.getInbox(config.org_id, {
876
- type: "mention,agent_dm,task_assign",
892
+ type: "mention,agent_dm,task_assign,agent_route",
877
893
  read: "false",
878
894
  limit: 50,
879
895
  cursor,
@@ -911,7 +927,7 @@ export const pondGateway: ChannelGatewayAdapter<ResolvedPondAccount> = {
911
927
  if (!chatInfo) {
912
928
  try {
913
929
  const chat = await client.getChat(config.org_id, item.chat_id);
914
- chatInfo = { type: chat.type, name: chat.name ?? null };
930
+ chatInfo = { type: chat.type, name: chat.name ?? null, agentRoutingMode: chat.agent_routing_mode };
915
931
  chatInfoMap.set(item.chat_id, chatInfo);
916
932
  } catch {
917
933
  dispatchedMessages.delete(item.source_id);