agent-messenger 2.5.0 → 2.6.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.
- package/.claude-plugin/plugin.json +1 -1
- package/.github/workflows/ci.yml +35 -0
- package/bun.lock +10 -2
- package/dist/package.json +3 -1
- package/dist/src/platforms/kakaotalk/client.d.ts +4 -1
- package/dist/src/platforms/kakaotalk/client.d.ts.map +1 -1
- package/dist/src/platforms/kakaotalk/client.js +21 -7
- package/dist/src/platforms/kakaotalk/client.js.map +1 -1
- package/dist/src/platforms/kakaotalk/commands/auth.d.ts.map +1 -1
- package/dist/src/platforms/kakaotalk/commands/auth.js +24 -55
- package/dist/src/platforms/kakaotalk/commands/auth.js.map +1 -1
- package/dist/src/platforms/kakaotalk/credential-manager.d.ts.map +1 -1
- package/dist/src/platforms/kakaotalk/credential-manager.js +1 -0
- package/dist/src/platforms/kakaotalk/credential-manager.js.map +1 -1
- package/dist/src/platforms/kakaotalk/index.d.ts +1 -1
- package/dist/src/platforms/kakaotalk/index.d.ts.map +1 -1
- package/dist/src/platforms/kakaotalk/index.js.map +1 -1
- package/dist/src/platforms/kakaotalk/listener.js +2 -2
- package/dist/src/platforms/kakaotalk/listener.js.map +1 -1
- package/dist/src/platforms/kakaotalk/protocol/config.d.ts +8 -2
- package/dist/src/platforms/kakaotalk/protocol/config.d.ts.map +1 -1
- package/dist/src/platforms/kakaotalk/protocol/config.js +15 -2
- package/dist/src/platforms/kakaotalk/protocol/config.js.map +1 -1
- package/dist/src/platforms/kakaotalk/protocol/session.d.ts +3 -1
- package/dist/src/platforms/kakaotalk/protocol/session.d.ts.map +1 -1
- package/dist/src/platforms/kakaotalk/protocol/session.js +13 -10
- package/dist/src/platforms/kakaotalk/protocol/session.js.map +1 -1
- package/dist/src/platforms/kakaotalk/types.d.ts +10 -0
- package/dist/src/platforms/kakaotalk/types.d.ts.map +1 -1
- package/dist/src/platforms/kakaotalk/types.js +1 -0
- package/dist/src/platforms/kakaotalk/types.js.map +1 -1
- package/dist/src/tui/adapters/kakaotalk-adapter.d.ts.map +1 -1
- package/dist/src/tui/adapters/kakaotalk-adapter.js +5 -2
- package/dist/src/tui/adapters/kakaotalk-adapter.js.map +1 -1
- package/docs/content/docs/cli/kakaotalk.mdx +3 -39
- package/e2e/config.ts +1 -1
- package/package.json +3 -1
- package/skills/agent-channeltalk/SKILL.md +1 -1
- package/skills/agent-channeltalkbot/SKILL.md +1 -1
- package/skills/agent-discord/SKILL.md +1 -1
- package/skills/agent-discordbot/SKILL.md +1 -1
- package/skills/agent-instagram/SKILL.md +1 -1
- package/skills/agent-kakaotalk/SKILL.md +11 -63
- package/skills/agent-kakaotalk/references/authentication.md +4 -69
- package/skills/agent-kakaotalk/references/common-patterns.md +13 -0
- package/skills/agent-line/SKILL.md +1 -1
- package/skills/agent-slack/SKILL.md +1 -1
- package/skills/agent-slackbot/SKILL.md +1 -1
- package/skills/agent-teams/SKILL.md +1 -1
- package/skills/agent-telegram/SKILL.md +1 -1
- package/skills/agent-webex/SKILL.md +1 -1
- package/skills/agent-wechatbot/SKILL.md +1 -1
- package/skills/agent-whatsapp/SKILL.md +1 -1
- package/skills/agent-whatsappbot/SKILL.md +1 -1
- package/src/platforms/kakaotalk/client.ts +25 -10
- package/src/platforms/kakaotalk/commands/auth.ts +22 -73
- package/src/platforms/kakaotalk/credential-manager.ts +1 -0
- package/src/platforms/kakaotalk/index.ts +1 -0
- package/src/platforms/kakaotalk/listener.test.ts +2 -2
- package/src/platforms/kakaotalk/listener.ts +2 -2
- package/src/platforms/kakaotalk/protocol/config.ts +26 -2
- package/src/platforms/kakaotalk/protocol/session.ts +16 -10
- package/src/platforms/kakaotalk/types.ts +4 -0
- package/src/tui/adapters/kakaotalk-adapter.ts +5 -2
|
@@ -72,7 +72,7 @@ export class KakaoTalkListener {
|
|
|
72
72
|
if (!this.running) return
|
|
73
73
|
|
|
74
74
|
try {
|
|
75
|
-
const { oauthToken, userId, deviceUuid } = this.client.getCredentials()
|
|
75
|
+
const { oauthToken, userId, deviceUuid, deviceType } = this.client.getCredentials()
|
|
76
76
|
if (!this.running) return
|
|
77
77
|
|
|
78
78
|
this.userId = userId
|
|
@@ -88,7 +88,7 @@ export class KakaoTalkListener {
|
|
|
88
88
|
}
|
|
89
89
|
})
|
|
90
90
|
|
|
91
|
-
await session.login(oauthToken, userId, deviceUuid)
|
|
91
|
+
await session.login(oauthToken, userId, deviceUuid, undefined, deviceType)
|
|
92
92
|
|
|
93
93
|
if (!this.running) {
|
|
94
94
|
session.close()
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
// Protocol constants for KakaoTalk LOCO.
|
|
2
2
|
// See protocol/NOTICE.md for attribution of protocol knowledge.
|
|
3
3
|
|
|
4
|
+
import type { KakaoDeviceType } from '../types'
|
|
5
|
+
|
|
4
6
|
// LOCO RSA public key (PKCS#1 DER, base64). RSA-2048, e=3.
|
|
5
7
|
// Source: openkakao (MIT) — extracted from KakaoTalk macOS binary.
|
|
6
8
|
export const LOCO_RSA_PUBLIC_KEY_DER_B64 =
|
|
@@ -17,8 +19,17 @@ export const BOOKING_PORT = 443
|
|
|
17
19
|
export const CHECKIN_HOST = 'ticket-loco.kakao.com'
|
|
18
20
|
export const CHECKIN_PORT = 995
|
|
19
21
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
+
// PC slot identity — platform-aware: 'win' on Windows, 'mac' on macOS
|
|
23
|
+
const PC_APP_VERSION = '26.2.0'
|
|
24
|
+
const PC_OS: string = process.platform === 'win32' ? 'win' : 'mac'
|
|
25
|
+
export const PC_OS_NAME: string = process.platform === 'win32' ? 'Windows' : 'macOS'
|
|
26
|
+
|
|
27
|
+
// Android (tablet slot) identity — must match the Android sub-device agent
|
|
28
|
+
// used in auth/kakao-login.ts so the server sees a consistent tablet session.
|
|
29
|
+
const ANDROID_APP_VERSION = '25.9.2'
|
|
30
|
+
const ANDROID_OS = 'android'
|
|
31
|
+
|
|
32
|
+
// dtype: 2 = sub-device, 1 = main device (ref: node-kakao config.ts)
|
|
22
33
|
export const DTYPE = 2
|
|
23
34
|
export const MCCMNC = '99999'
|
|
24
35
|
export const LANG = 'ko'
|
|
@@ -26,3 +37,16 @@ export const COUNTRY_ISO = 'KR'
|
|
|
26
37
|
export const PROTOCOL_VERSION = '1'
|
|
27
38
|
|
|
28
39
|
export const PING_INTERVAL_MS = 300_000
|
|
40
|
+
|
|
41
|
+
export interface LocoDeviceConfig {
|
|
42
|
+
os: string
|
|
43
|
+
appVersion: string
|
|
44
|
+
useSub: boolean
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function getLocoDeviceConfig(deviceType: KakaoDeviceType): LocoDeviceConfig {
|
|
48
|
+
if (deviceType === 'tablet') {
|
|
49
|
+
return { os: ANDROID_OS, appVersion: ANDROID_APP_VERSION, useSub: true }
|
|
50
|
+
}
|
|
51
|
+
return { os: PC_OS, appVersion: PC_APP_VERSION, useSub: false }
|
|
52
|
+
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Binary, Long } from 'bson'
|
|
2
2
|
|
|
3
|
+
import type { KakaoDeviceType } from '../types'
|
|
4
|
+
|
|
3
5
|
import {
|
|
4
|
-
APP_VERSION,
|
|
5
6
|
BOOKING_HOST,
|
|
6
7
|
BOOKING_PORT,
|
|
7
8
|
CHECKIN_HOST,
|
|
@@ -12,6 +13,7 @@ import {
|
|
|
12
13
|
MCCMNC,
|
|
13
14
|
PING_INTERVAL_MS,
|
|
14
15
|
PROTOCOL_VERSION,
|
|
16
|
+
getLocoDeviceConfig,
|
|
15
17
|
} from './config'
|
|
16
18
|
import { LocoConnection } from './connection'
|
|
17
19
|
import type { BookingResponse, CheckinResponse, LoginListResponse, LocoPacket, SyncState } from './types'
|
|
@@ -21,9 +23,13 @@ export class LocoSession {
|
|
|
21
23
|
private pingTimer: ReturnType<typeof setInterval> | null = null
|
|
22
24
|
private pushHandler: ((packet: LocoPacket) => void) | null = null
|
|
23
25
|
private closeHandler: (() => void) | null = null
|
|
26
|
+
private deviceType: KakaoDeviceType = 'tablet'
|
|
27
|
+
|
|
28
|
+
async login(oauthToken: string, userId: string, deviceUuid: string, syncState?: SyncState, deviceType?: KakaoDeviceType): Promise<LoginListResponse> {
|
|
29
|
+
this.deviceType = deviceType ?? 'tablet'
|
|
30
|
+
const deviceConfig = getLocoDeviceConfig(this.deviceType)
|
|
24
31
|
|
|
25
|
-
|
|
26
|
-
const { host, port } = await this.bookAndCheckin(userId)
|
|
32
|
+
const { host, port } = await this.bookAndCheckin(userId, deviceConfig)
|
|
27
33
|
|
|
28
34
|
this.connection = new LocoConnection()
|
|
29
35
|
await this.connection.connectSecure(host, port)
|
|
@@ -43,9 +49,9 @@ export class LocoSession {
|
|
|
43
49
|
const lbk = syncState?.lbk ?? 0
|
|
44
50
|
|
|
45
51
|
const response = await this.connection.sendPacket('LOGINLIST', {
|
|
46
|
-
appVer:
|
|
52
|
+
appVer: deviceConfig.appVersion,
|
|
47
53
|
prtVer: PROTOCOL_VERSION,
|
|
48
|
-
os:
|
|
54
|
+
os: deviceConfig.os,
|
|
49
55
|
lang: LANG,
|
|
50
56
|
dtype: DTYPE,
|
|
51
57
|
duuid: deviceUuid,
|
|
@@ -65,12 +71,12 @@ export class LocoSession {
|
|
|
65
71
|
return response.body as unknown as LoginListResponse
|
|
66
72
|
}
|
|
67
73
|
|
|
68
|
-
private async bookAndCheckin(userId: string): Promise<{ host: string; port: number }> {
|
|
74
|
+
private async bookAndCheckin(userId: string, deviceConfig: { os: string; appVersion: string; useSub: boolean }): Promise<{ host: string; port: number }> {
|
|
69
75
|
const bookingConn = new LocoConnection()
|
|
70
76
|
await bookingConn.connectTls(BOOKING_HOST, BOOKING_PORT)
|
|
71
77
|
|
|
72
78
|
const bookingResponse = await bookingConn.sendPacket('GETCONF', {
|
|
73
|
-
os:
|
|
79
|
+
os: deviceConfig.os,
|
|
74
80
|
model: '',
|
|
75
81
|
})
|
|
76
82
|
bookingConn.close()
|
|
@@ -86,13 +92,13 @@ export class LocoSession {
|
|
|
86
92
|
|
|
87
93
|
const checkinResponse = await checkinConn.sendPacket('CHECKIN', {
|
|
88
94
|
userId: Number(userId),
|
|
89
|
-
os:
|
|
95
|
+
os: deviceConfig.os,
|
|
90
96
|
ntype: 0,
|
|
91
|
-
appVer:
|
|
97
|
+
appVer: deviceConfig.appVersion,
|
|
92
98
|
MCCMNC: MCCMNC,
|
|
93
99
|
lang: LANG,
|
|
94
100
|
countryISO: COUNTRY_ISO,
|
|
95
|
-
useSub:
|
|
101
|
+
useSub: deviceConfig.useSub,
|
|
96
102
|
})
|
|
97
103
|
checkinConn.close()
|
|
98
104
|
|
|
@@ -11,6 +11,8 @@ export interface ExtractedKakaoToken {
|
|
|
11
11
|
login_form_body?: string
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
export type KakaoAuthMethod = 'login' | 'extract'
|
|
15
|
+
|
|
14
16
|
export interface KakaoAccountCredentials {
|
|
15
17
|
account_id: string
|
|
16
18
|
oauth_token: string
|
|
@@ -18,6 +20,7 @@ export interface KakaoAccountCredentials {
|
|
|
18
20
|
refresh_token?: string
|
|
19
21
|
device_uuid: string
|
|
20
22
|
device_type: KakaoDeviceType
|
|
23
|
+
auth_method?: KakaoAuthMethod
|
|
21
24
|
created_at: string
|
|
22
25
|
updated_at: string
|
|
23
26
|
}
|
|
@@ -162,6 +165,7 @@ export const KakaoAccountCredentialsSchema = z.object({
|
|
|
162
165
|
refresh_token: z.string().optional(),
|
|
163
166
|
device_uuid: z.string(),
|
|
164
167
|
device_type: z.enum(['pc', 'tablet']),
|
|
168
|
+
auth_method: z.enum(['login', 'extract']).optional(),
|
|
165
169
|
created_at: z.string(),
|
|
166
170
|
updated_at: z.string(),
|
|
167
171
|
})
|
|
@@ -64,7 +64,7 @@ export class KakaoTalkAdapter implements PlatformAdapter {
|
|
|
64
64
|
if (!creds) throw new Error(`Account ${accountId} not found`)
|
|
65
65
|
|
|
66
66
|
const client = new KakaoTalkClient()
|
|
67
|
-
await client.login({ oauthToken: creds.oauth_token, userId: creds.user_id, deviceUuid: creds.device_uuid })
|
|
67
|
+
await client.login({ oauthToken: creds.oauth_token, userId: creds.user_id, deviceUuid: creds.device_uuid, deviceType: creds.device_type })
|
|
68
68
|
this.client = client
|
|
69
69
|
this.currentAccount = { id: creds.account_id, name: creds.account_id }
|
|
70
70
|
}
|
|
@@ -86,7 +86,8 @@ export class KakaoTalkAdapter implements PlatformAdapter {
|
|
|
86
86
|
|
|
87
87
|
const existing = await this.credManager.getAccount()
|
|
88
88
|
const pendingState = await this.credManager.loadPendingLogin()
|
|
89
|
-
const
|
|
89
|
+
const existingUuid = existing?.auth_method === 'login' ? existing?.device_uuid : undefined
|
|
90
|
+
const savedDeviceUuid = pendingState?.device_uuid ?? existingUuid ?? generateDeviceUuid()
|
|
90
91
|
|
|
91
92
|
let email: string | undefined
|
|
92
93
|
let password: string | undefined
|
|
@@ -139,6 +140,7 @@ export class KakaoTalkAdapter implements PlatformAdapter {
|
|
|
139
140
|
refresh_token: result.credentials.refresh_token,
|
|
140
141
|
device_uuid: result.credentials.device_uuid,
|
|
141
142
|
device_type: result.credentials.device_type,
|
|
143
|
+
auth_method: 'login',
|
|
142
144
|
created_at: now,
|
|
143
145
|
updated_at: now,
|
|
144
146
|
})
|
|
@@ -149,6 +151,7 @@ export class KakaoTalkAdapter implements PlatformAdapter {
|
|
|
149
151
|
oauthToken: result.credentials.access_token,
|
|
150
152
|
userId: result.credentials.user_id,
|
|
151
153
|
deviceUuid: result.credentials.device_uuid,
|
|
154
|
+
deviceType: result.credentials.device_type,
|
|
152
155
|
})
|
|
153
156
|
this.client = client
|
|
154
157
|
this.currentAccount = { id: result.credentials.user_id, name: email }
|