agent-messenger 2.37.1 → 2.38.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 (82) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +6 -0
  3. package/dist/package.json +1 -1
  4. package/dist/src/platforms/discord/cli.d.ts.map +1 -1
  5. package/dist/src/platforms/discord/cli.js +3 -1
  6. package/dist/src/platforms/discord/cli.js.map +1 -1
  7. package/dist/src/platforms/discord/client.d.ts +17 -1
  8. package/dist/src/platforms/discord/client.d.ts.map +1 -1
  9. package/dist/src/platforms/discord/client.js +46 -0
  10. package/dist/src/platforms/discord/client.js.map +1 -1
  11. package/dist/src/platforms/discord/commands/emoji.d.ts +13 -0
  12. package/dist/src/platforms/discord/commands/emoji.d.ts.map +1 -0
  13. package/dist/src/platforms/discord/commands/emoji.js +93 -0
  14. package/dist/src/platforms/discord/commands/emoji.js.map +1 -0
  15. package/dist/src/platforms/discord/commands/index.d.ts +2 -0
  16. package/dist/src/platforms/discord/commands/index.d.ts.map +1 -1
  17. package/dist/src/platforms/discord/commands/index.js +2 -0
  18. package/dist/src/platforms/discord/commands/index.js.map +1 -1
  19. package/dist/src/platforms/discord/commands/server.d.ts.map +1 -1
  20. package/dist/src/platforms/discord/commands/server.js +16 -1
  21. package/dist/src/platforms/discord/commands/server.js.map +1 -1
  22. package/dist/src/platforms/discord/commands/sticker.d.ts +15 -0
  23. package/dist/src/platforms/discord/commands/sticker.d.ts.map +1 -0
  24. package/dist/src/platforms/discord/commands/sticker.js +97 -0
  25. package/dist/src/platforms/discord/commands/sticker.js.map +1 -0
  26. package/dist/src/platforms/discord/expression-format.d.ts +41 -0
  27. package/dist/src/platforms/discord/expression-format.d.ts.map +1 -0
  28. package/dist/src/platforms/discord/expression-format.js +107 -0
  29. package/dist/src/platforms/discord/expression-format.js.map +1 -0
  30. package/dist/src/platforms/discord/expression-names.d.ts +9 -0
  31. package/dist/src/platforms/discord/expression-names.d.ts.map +1 -0
  32. package/dist/src/platforms/discord/expression-names.js +33 -0
  33. package/dist/src/platforms/discord/expression-names.js.map +1 -0
  34. package/dist/src/platforms/discord/index.d.ts +1 -1
  35. package/dist/src/platforms/discord/index.d.ts.map +1 -1
  36. package/dist/src/platforms/discord/index.js.map +1 -1
  37. package/dist/src/platforms/discord/types.d.ts +29 -0
  38. package/dist/src/platforms/discord/types.d.ts.map +1 -1
  39. package/dist/src/platforms/discord/types.js.map +1 -1
  40. package/dist/src/platforms/kakaotalk/client.d.ts.map +1 -1
  41. package/dist/src/platforms/kakaotalk/client.js +15 -2
  42. package/dist/src/platforms/kakaotalk/client.js.map +1 -1
  43. package/docs/content/docs/cli/discord.mdx +73 -0
  44. package/docs/content/docs/sdk/discord.mdx +50 -0
  45. package/package.json +1 -1
  46. package/skills/agent-channeltalk/SKILL.md +1 -1
  47. package/skills/agent-channeltalkbot/SKILL.md +1 -1
  48. package/skills/agent-discord/SKILL.md +69 -1
  49. package/skills/agent-discord/references/common-patterns.md +77 -0
  50. package/skills/agent-discordbot/SKILL.md +1 -1
  51. package/skills/agent-imessage/SKILL.md +1 -1
  52. package/skills/agent-instagram/SKILL.md +1 -1
  53. package/skills/agent-kakaotalk/SKILL.md +1 -1
  54. package/skills/agent-line/SKILL.md +1 -1
  55. package/skills/agent-slack/SKILL.md +1 -1
  56. package/skills/agent-slackbot/SKILL.md +1 -1
  57. package/skills/agent-teams/SKILL.md +1 -1
  58. package/skills/agent-telegram/SKILL.md +1 -1
  59. package/skills/agent-telegrambot/SKILL.md +1 -1
  60. package/skills/agent-webex/SKILL.md +1 -1
  61. package/skills/agent-webexbot/SKILL.md +1 -1
  62. package/skills/agent-wechatbot/SKILL.md +1 -1
  63. package/skills/agent-whatsapp/SKILL.md +1 -1
  64. package/skills/agent-whatsappbot/SKILL.md +1 -1
  65. package/src/platforms/discord/cli.ts +4 -0
  66. package/src/platforms/discord/client.test.ts +133 -0
  67. package/src/platforms/discord/client.ts +72 -0
  68. package/src/platforms/discord/commands/emoji.test.ts +122 -0
  69. package/src/platforms/discord/commands/emoji.ts +124 -0
  70. package/src/platforms/discord/commands/index.ts +2 -0
  71. package/src/platforms/discord/commands/server.test.ts +45 -1
  72. package/src/platforms/discord/commands/server.ts +21 -1
  73. package/src/platforms/discord/commands/sticker.test.ts +118 -0
  74. package/src/platforms/discord/commands/sticker.ts +135 -0
  75. package/src/platforms/discord/expression-format.test.ts +107 -0
  76. package/src/platforms/discord/expression-format.ts +117 -0
  77. package/src/platforms/discord/expression-names.test.ts +41 -0
  78. package/src/platforms/discord/expression-names.ts +36 -0
  79. package/src/platforms/discord/index.ts +2 -0
  80. package/src/platforms/discord/types.ts +31 -0
  81. package/src/platforms/kakaotalk/client.test.ts +66 -0
  82. package/src/platforms/kakaotalk/client.ts +14 -2
@@ -8,6 +8,7 @@ export type {
8
8
  DiscordConfig,
9
9
  DiscordCredentials,
10
10
  DiscordDMChannel,
11
+ DiscordEmoji,
11
12
  DiscordFile,
12
13
  DiscordGatewayChannelEvent,
13
14
  DiscordGatewayEvent,
@@ -28,6 +29,7 @@ export type {
28
29
  DiscordReadState,
29
30
  DiscordReadStateSnapshot,
30
31
  DiscordRelationship,
32
+ DiscordSticker,
31
33
  DiscordRole,
32
34
  DiscordRoleColors,
33
35
  DiscordRoleTags,
@@ -8,7 +8,14 @@ export interface DiscordGuild {
8
8
  id: string
9
9
  name: string
10
10
  icon?: string
11
+ /** Only present on GET /users/@me/guilds. */
11
12
  owner?: boolean
13
+ /** Only present on GET /guilds/{id}. */
14
+ owner_id?: string
15
+ premium_tier?: number
16
+ premium_subscription_count?: number
17
+ emojis?: DiscordEmoji[]
18
+ stickers?: DiscordSticker[]
12
19
  }
13
20
 
14
21
  export interface DiscordChannel {
@@ -116,6 +123,30 @@ export interface DiscordFile {
116
123
  width?: number
117
124
  }
118
125
 
126
+ export interface DiscordEmoji {
127
+ id: string
128
+ name: string
129
+ animated?: boolean
130
+ managed?: boolean
131
+ available?: boolean
132
+ roles?: string[]
133
+ user?: DiscordUser
134
+ }
135
+
136
+ export interface DiscordSticker {
137
+ id: string
138
+ name: string
139
+ description?: string | null
140
+ tags: string
141
+ /** STANDARD = 1, GUILD = 2. */
142
+ type: number
143
+ /** PNG = 1, APNG = 2, LOTTIE = 3, GIF = 4. */
144
+ format_type: number
145
+ available?: boolean
146
+ guild_id?: string
147
+ user?: DiscordUser
148
+ }
149
+
119
150
  export interface DiscordMention {
120
151
  id: string
121
152
  channel_id: string
@@ -763,6 +763,72 @@ describe('KakaoTalkClient', () => {
763
763
  client.close()
764
764
  })
765
765
 
766
+ it('advances LCHATLIST pagination when cursor fields are plain numbers', async () => {
767
+ // LOCO sends lastTokenId/lastChatId as plain numbers when they fit in a safe
768
+ // integer (bson promotes them). The mocked session ignores its arguments, so
769
+ // asserting only on the collected chats would pass even while every request
770
+ // re-sent cursor 0. Assert on the cursor that actually reaches getChatList.
771
+ mockLogin.mockResolvedValue({ ...DEFAULT_LOGIN_RESULT, lastTokenId: 7, lastChatId: 200, eof: false })
772
+ mockGetChatList
773
+ .mockResolvedValueOnce({
774
+ statusCode: 0,
775
+ body: {
776
+ status: 0,
777
+ chatDatas: [
778
+ {
779
+ c: 300,
780
+ t: 1,
781
+ k: ['Dave'],
782
+ i: [4],
783
+ a: 1,
784
+ n: 0,
785
+ o: 1698000000,
786
+ l: null,
787
+ ll: makeLong(100),
788
+ },
789
+ ],
790
+ lastTokenId: 8,
791
+ lastChatId: 300,
792
+ eof: false,
793
+ },
794
+ })
795
+ .mockResolvedValueOnce({
796
+ statusCode: 0,
797
+ body: {
798
+ status: 0,
799
+ chatDatas: [
800
+ {
801
+ c: 400,
802
+ t: 1,
803
+ k: ['Erin'],
804
+ i: [5],
805
+ a: 1,
806
+ n: 0,
807
+ o: 1697000000,
808
+ l: null,
809
+ ll: makeLong(90),
810
+ },
811
+ ],
812
+ lastTokenId: 9,
813
+ lastChatId: 400,
814
+ eof: true,
815
+ },
816
+ })
817
+
818
+ const client = await new KakaoTalkClient().login({ oauthToken: 'token', userId: 'user1', deviceUuid: 'device1' })
819
+ const chats = await client.getChats({ all: true })
820
+
821
+ expect(chats.map((chat) => chat.chat_id)).toEqual(['100', '200', '300', '400'])
822
+ expect(mockGetChatList).toHaveBeenCalledTimes(2)
823
+ const cursors = mockGetChatList.mock.calls.map((call) => (call as unknown[]).map((v) => String(v)))
824
+ expect(cursors).toEqual([
825
+ ['7', '200'],
826
+ ['8', '300'],
827
+ ])
828
+
829
+ client.close()
830
+ })
831
+
766
832
  it('fails closed when LCHATLIST has a nonzero response status', async () => {
767
833
  mockLogin.mockResolvedValue({ ...DEFAULT_LOGIN_RESULT, eof: false })
768
834
  mockGetChatList.mockResolvedValueOnce({
@@ -163,6 +163,18 @@ function bsonToLong(v: unknown): Long | undefined {
163
163
  return undefined
164
164
  }
165
165
 
166
+ // LCHATLIST cursor fields (lastTokenId/lastChatId) arrive as plain numbers when the
167
+ // value fits in a safe integer, because bson promotes them, and as { low, high }
168
+ // otherwise. bsonToLong only accepts the object form, so a numeric cursor became
169
+ // undefined and getChatList() re-requested the first page until MAX_PAGES.
170
+ // Kept separate from bsonToLong on purpose: its other callers (log ids, open link
171
+ // ids) rely on a numeric 0 staying absent rather than becoming a Long.
172
+ function cursorToLong(v: unknown): Long | undefined {
173
+ if (typeof v === 'number' && Number.isSafeInteger(v)) return Long.fromNumber(v)
174
+ if (typeof v === 'bigint') return Long.fromBigInt(v)
175
+ return bsonToLong(v)
176
+ }
177
+
166
178
  function longToString(v: unknown): string {
167
179
  if (v && typeof v === 'object' && 'high' in v && 'low' in v) {
168
180
  const { high, low } = v as { high: number; low: number }
@@ -1049,8 +1061,8 @@ export class KakaoTalkClient {
1049
1061
  if (cursor.eof && !snapshotEmpty) break
1050
1062
  if (cursor.eof && snapshotEmpty && pages > 0) break
1051
1063
 
1052
- const lastTokenId = bsonToLong(cursor.lastTokenId)
1053
- const lastChatId = bsonToLong(cursor.lastChatId)
1064
+ const lastTokenId = cursorToLong(cursor.lastTokenId)
1065
+ const lastChatId = cursorToLong(cursor.lastChatId)
1054
1066
 
1055
1067
  const response = await session.getChatList(lastTokenId, lastChatId)
1056
1068
  if (requireCompleteList) assertLocoOk(response, 'LCHATLIST')