agent-messenger 2.12.1 → 2.12.2

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 (32) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/dist/package.json +1 -1
  3. package/dist/src/platforms/kakaotalk/client.d.ts +22 -0
  4. package/dist/src/platforms/kakaotalk/client.d.ts.map +1 -1
  5. package/dist/src/platforms/kakaotalk/client.js +93 -7
  6. package/dist/src/platforms/kakaotalk/client.js.map +1 -1
  7. package/dist/src/platforms/kakaotalk/listener.d.ts +4 -7
  8. package/dist/src/platforms/kakaotalk/listener.d.ts.map +1 -1
  9. package/dist/src/platforms/kakaotalk/listener.js +43 -72
  10. package/dist/src/platforms/kakaotalk/listener.js.map +1 -1
  11. package/package.json +1 -1
  12. package/skills/agent-channeltalk/SKILL.md +1 -1
  13. package/skills/agent-channeltalkbot/SKILL.md +1 -1
  14. package/skills/agent-discord/SKILL.md +1 -1
  15. package/skills/agent-discordbot/SKILL.md +1 -1
  16. package/skills/agent-instagram/SKILL.md +1 -1
  17. package/skills/agent-kakaotalk/SKILL.md +1 -1
  18. package/skills/agent-line/SKILL.md +1 -1
  19. package/skills/agent-slack/SKILL.md +1 -1
  20. package/skills/agent-slackbot/SKILL.md +1 -1
  21. package/skills/agent-teams/SKILL.md +1 -1
  22. package/skills/agent-telegram/SKILL.md +1 -1
  23. package/skills/agent-telegrambot/SKILL.md +1 -1
  24. package/skills/agent-webex/SKILL.md +1 -1
  25. package/skills/agent-wechatbot/SKILL.md +1 -1
  26. package/skills/agent-whatsapp/SKILL.md +1 -1
  27. package/skills/agent-whatsappbot/SKILL.md +1 -1
  28. package/src/platforms/kakaotalk/client-listener-integration.test.ts +411 -0
  29. package/src/platforms/kakaotalk/client.test.ts +3 -0
  30. package/src/platforms/kakaotalk/client.ts +108 -9
  31. package/src/platforms/kakaotalk/listener.test.ts +155 -149
  32. package/src/platforms/kakaotalk/listener.ts +46 -80
@@ -1,7 +1,6 @@
1
1
  import { EventEmitter } from 'events'
2
2
 
3
- import type { KakaoTalkClient } from './client'
4
- import { LocoSession } from './protocol/session'
3
+ import type { KakaoSessionEvent, KakaoTalkClient } from './client'
5
4
  import type { LocoPacket } from './protocol/types'
6
5
  import type {
7
6
  KakaoTalkListenerEventMap,
@@ -11,9 +10,6 @@ import type {
11
10
  KakaoTalkPushReadEvent,
12
11
  } from './types'
13
12
 
14
- const RECONNECT_BASE_DELAY = 1_000
15
- const RECONNECT_MAX_DELAY = 30_000
16
-
17
13
  type EventKey = keyof KakaoTalkListenerEventMap
18
14
 
19
15
  function longToString(v: unknown): string {
@@ -27,11 +23,9 @@ function longToString(v: unknown): string {
27
23
  export class KakaoTalkListener {
28
24
  private client: KakaoTalkClient
29
25
  private running = false
30
- private session: LocoSession | null = null
31
26
  private emitter = new EventEmitter()
32
- private reconnectTimer: ReturnType<typeof setTimeout> | null = null
33
- private reconnectAttempts = 0
34
- private userId: string | null = null
27
+ private unsubscribePush: (() => void) | null = null
28
+ private unsubscribeSession: (() => void) | null = null
35
29
 
36
30
  constructor(client: KakaoTalkClient) {
37
31
  this.client = client
@@ -40,17 +34,33 @@ export class KakaoTalkListener {
40
34
  async start(): Promise<void> {
41
35
  if (this.running) return
42
36
  this.running = true
43
- this.reconnectAttempts = 0
44
- await this.connect()
37
+
38
+ this.unsubscribePush = this.client.onPush((packet) => this.handlePush(packet))
39
+ this.unsubscribeSession = this.client.onSessionEvent((event) => this.handleSessionEvent(event))
40
+
41
+ const alreadyConnected = this.client.isConnected()
42
+
43
+ try {
44
+ await this.client.acquireSession()
45
+ if (!this.running) return
46
+ if (alreadyConnected) {
47
+ const { userId } = this.client.getCredentials()
48
+ this.emitter.emit('connected', { userId })
49
+ }
50
+ } catch (error) {
51
+ this.emitter.emit('error', error instanceof Error ? error : new Error(String(error)))
52
+ this.running = false
53
+ this.teardown()
54
+ }
45
55
  }
46
56
 
47
57
  stop(): void {
48
- this.running = false
49
- this.clearTimers()
50
- if (this.session) {
51
- this.session.close()
52
- this.session = null
58
+ if (!this.running) {
59
+ this.teardown()
60
+ return
53
61
  }
62
+ this.running = false
63
+ this.teardown()
54
64
  }
55
65
 
56
66
  on<K extends EventKey>(event: K, listener: (...args: KakaoTalkListenerEventMap[K]) => void): this {
@@ -68,41 +78,28 @@ export class KakaoTalkListener {
68
78
  return this
69
79
  }
70
80
 
71
- private async connect(): Promise<void> {
72
- if (!this.running) return
73
-
74
- try {
75
- const { oauthToken, userId, deviceUuid, deviceType } = this.client.getCredentials()
76
- if (!this.running) return
77
-
78
- this.userId = userId
79
- const session = new LocoSession()
80
-
81
- session.onPush((packet) => this.handlePush(packet))
82
- session.onClose(() => {
83
- if (this.session !== session) return
84
- this.session = null
85
- if (this.running) {
86
- this.emitter.emit('disconnected')
87
- this.scheduleReconnect()
88
- }
89
- })
90
-
91
- await session.login(oauthToken, userId, deviceUuid, undefined, deviceType)
81
+ private teardown(): void {
82
+ this.unsubscribePush?.()
83
+ this.unsubscribePush = null
84
+ this.unsubscribeSession?.()
85
+ this.unsubscribeSession = null
86
+ }
92
87
 
93
- if (!this.running) {
94
- session.close()
95
- return
96
- }
88
+ private handleSessionEvent(event: KakaoSessionEvent): void {
89
+ if (!this.running) return
97
90
 
98
- this.reconnectAttempts = 0
99
- this.session = session
100
- this.emitter.emit('connected', { userId })
101
- } catch (error) {
102
- this.emitter.emit('error', error instanceof Error ? error : new Error(String(error)))
103
- if (this.running) {
104
- this.scheduleReconnect()
105
- }
91
+ switch (event.type) {
92
+ case 'connected':
93
+ this.emitter.emit('connected', { userId: event.userId })
94
+ break
95
+ case 'disconnected':
96
+ this.emitter.emit('disconnected')
97
+ break
98
+ case 'kicked':
99
+ this.emitter.emit('error', new Error(event.reason))
100
+ this.running = false
101
+ this.teardown()
102
+ break
106
103
  }
107
104
  }
108
105
 
@@ -162,23 +159,6 @@ export class KakaoTalkListener {
162
159
  break
163
160
  }
164
161
 
165
- case 'CHANGESVR': {
166
- this.reconnectAttempts = 0
167
- const prev = this.session
168
- this.session = null
169
- prev?.close()
170
- this.connect()
171
- break
172
- }
173
-
174
- case 'KICKOUT': {
175
- this.emitter.emit('error', new Error('Session kicked — another device logged in'))
176
- this.running = false
177
- this.session?.close()
178
- this.session = null
179
- break
180
- }
181
-
182
162
  default: {
183
163
  const event: KakaoTalkPushGenericEvent = { type: method, ...body }
184
164
  this.emitter.emit('kakaotalk_event', event)
@@ -186,18 +166,4 @@ export class KakaoTalkListener {
186
166
  }
187
167
  }
188
168
  }
189
-
190
- private scheduleReconnect(): void {
191
- this.clearTimers()
192
- const delay = Math.min(RECONNECT_BASE_DELAY * 2 ** this.reconnectAttempts, RECONNECT_MAX_DELAY)
193
- this.reconnectAttempts++
194
- this.reconnectTimer = setTimeout(() => this.connect(), delay)
195
- }
196
-
197
- private clearTimers(): void {
198
- if (this.reconnectTimer) {
199
- clearTimeout(this.reconnectTimer)
200
- this.reconnectTimer = null
201
- }
202
- }
203
169
  }