agent-messenger 2.11.2 → 2.12.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 (83) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +11 -0
  3. package/dist/package.json +1 -1
  4. package/dist/src/platforms/channeltalk/credential-manager.js +2 -2
  5. package/dist/src/platforms/channeltalk/credential-manager.js.map +1 -1
  6. package/dist/src/platforms/channeltalkbot/credential-manager.js +2 -2
  7. package/dist/src/platforms/channeltalkbot/credential-manager.js.map +1 -1
  8. package/dist/src/platforms/discord/credential-manager.d.ts.map +1 -1
  9. package/dist/src/platforms/discord/credential-manager.js +2 -2
  10. package/dist/src/platforms/discord/credential-manager.js.map +1 -1
  11. package/dist/src/platforms/discordbot/credential-manager.js +2 -2
  12. package/dist/src/platforms/discordbot/credential-manager.js.map +1 -1
  13. package/dist/src/platforms/instagram/credential-manager.js +2 -2
  14. package/dist/src/platforms/instagram/credential-manager.js.map +1 -1
  15. package/dist/src/platforms/kakaotalk/client.d.ts.map +1 -1
  16. package/dist/src/platforms/kakaotalk/client.js +3 -4
  17. package/dist/src/platforms/kakaotalk/client.js.map +1 -1
  18. package/dist/src/platforms/kakaotalk/credential-manager.js +2 -2
  19. package/dist/src/platforms/kakaotalk/credential-manager.js.map +1 -1
  20. package/dist/src/platforms/line/client.js +2 -2
  21. package/dist/src/platforms/line/client.js.map +1 -1
  22. package/dist/src/platforms/line/credential-manager.js +2 -2
  23. package/dist/src/platforms/line/credential-manager.js.map +1 -1
  24. package/dist/src/platforms/slack/credential-manager.js +2 -2
  25. package/dist/src/platforms/slack/credential-manager.js.map +1 -1
  26. package/dist/src/platforms/slackbot/credential-manager.js +2 -2
  27. package/dist/src/platforms/slackbot/credential-manager.js.map +1 -1
  28. package/dist/src/platforms/teams/credential-manager.js +2 -2
  29. package/dist/src/platforms/teams/credential-manager.js.map +1 -1
  30. package/dist/src/platforms/telegram/credential-manager.js +2 -2
  31. package/dist/src/platforms/telegram/credential-manager.js.map +1 -1
  32. package/dist/src/platforms/webex/credential-manager.js +2 -2
  33. package/dist/src/platforms/webex/credential-manager.js.map +1 -1
  34. package/dist/src/platforms/wechatbot/credential-manager.js +2 -2
  35. package/dist/src/platforms/wechatbot/credential-manager.js.map +1 -1
  36. package/dist/src/platforms/whatsapp/credential-manager.js +2 -2
  37. package/dist/src/platforms/whatsapp/credential-manager.js.map +1 -1
  38. package/dist/src/platforms/whatsappbot/credential-manager.js +2 -2
  39. package/dist/src/platforms/whatsappbot/credential-manager.js.map +1 -1
  40. package/dist/src/shared/utils/config-dir.d.ts +14 -0
  41. package/dist/src/shared/utils/config-dir.d.ts.map +1 -0
  42. package/dist/src/shared/utils/config-dir.js +22 -0
  43. package/dist/src/shared/utils/config-dir.js.map +1 -0
  44. package/dist/src/shared/utils/derived-key-cache.d.ts.map +1 -1
  45. package/dist/src/shared/utils/derived-key-cache.js +2 -2
  46. package/dist/src/shared/utils/derived-key-cache.js.map +1 -1
  47. package/package.json +1 -1
  48. package/skills/agent-channeltalk/SKILL.md +1 -1
  49. package/skills/agent-channeltalkbot/SKILL.md +1 -1
  50. package/skills/agent-discord/SKILL.md +1 -1
  51. package/skills/agent-discordbot/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-webex/SKILL.md +1 -1
  60. package/skills/agent-wechatbot/SKILL.md +1 -1
  61. package/skills/agent-whatsapp/SKILL.md +1 -1
  62. package/skills/agent-whatsappbot/SKILL.md +1 -1
  63. package/src/platforms/channeltalk/credential-manager.ts +2 -2
  64. package/src/platforms/channeltalkbot/credential-manager.ts +2 -2
  65. package/src/platforms/discord/credential-manager.ts +3 -2
  66. package/src/platforms/discordbot/credential-manager.ts +2 -2
  67. package/src/platforms/instagram/credential-manager.ts +2 -2
  68. package/src/platforms/kakaotalk/client.ts +3 -5
  69. package/src/platforms/kakaotalk/credential-manager.ts +2 -2
  70. package/src/platforms/line/client.ts +2 -2
  71. package/src/platforms/line/credential-manager.ts +2 -2
  72. package/src/platforms/slack/credential-manager.ts +2 -2
  73. package/src/platforms/slackbot/credential-manager.ts +2 -2
  74. package/src/platforms/teams/credential-manager.ts +2 -2
  75. package/src/platforms/telegram/commands/whoami.test.ts +1 -0
  76. package/src/platforms/telegram/credential-manager.ts +2 -2
  77. package/src/platforms/webex/credential-manager.ts +2 -2
  78. package/src/platforms/wechatbot/credential-manager.ts +2 -2
  79. package/src/platforms/whatsapp/credential-manager.ts +2 -2
  80. package/src/platforms/whatsappbot/credential-manager.ts +2 -2
  81. package/src/shared/utils/config-dir.test.ts +41 -0
  82. package/src/shared/utils/config-dir.ts +23 -0
  83. package/src/shared/utils/derived-key-cache.ts +3 -2
@@ -1,8 +1,8 @@
1
1
  import { existsSync } from 'node:fs'
2
2
  import { chmod, mkdir, readFile, writeFile } from 'node:fs/promises'
3
- import { homedir } from 'node:os'
4
3
  import { join } from 'node:path'
5
4
 
5
+ import { getConfigDir } from '../../shared/utils/config-dir'
6
6
  import type { DiscordBotConfig, DiscordBotCredentials } from './types'
7
7
  import { DiscordBotConfigSchema } from './types'
8
8
 
@@ -11,7 +11,7 @@ export class DiscordBotCredentialManager {
11
11
  private credentialsPath: string
12
12
 
13
13
  constructor(configDir?: string) {
14
- this.configDir = configDir ?? join(homedir(), '.config', 'agent-messenger')
14
+ this.configDir = configDir ?? getConfigDir()
15
15
  this.credentialsPath = join(this.configDir, 'discordbot-credentials.json')
16
16
  }
17
17
 
@@ -1,8 +1,8 @@
1
1
  import { existsSync } from 'node:fs'
2
2
  import { mkdir, readFile, rm, writeFile } from 'node:fs/promises'
3
- import { homedir } from 'node:os'
4
3
  import { join } from 'node:path'
5
4
 
5
+ import { getConfigDir } from '../../shared/utils/config-dir'
6
6
  import { createAccountId, type InstagramAccount, type InstagramAccountPaths, type InstagramConfig } from './types'
7
7
 
8
8
  export class InstagramCredentialManager {
@@ -11,7 +11,7 @@ export class InstagramCredentialManager {
11
11
  private instagramRootDir: string
12
12
 
13
13
  constructor(configDir?: string) {
14
- this.configDir = configDir ?? join(homedir(), '.config', 'agent-messenger')
14
+ this.configDir = configDir ?? getConfigDir()
15
15
  this.credentialsPath = join(this.configDir, 'instagram-credentials.json')
16
16
  this.instagramRootDir = join(this.configDir, 'instagram')
17
17
  }
@@ -1,10 +1,10 @@
1
1
  import { existsSync } from 'node:fs'
2
2
  import { chmod, mkdir, readFile, writeFile } from 'node:fs/promises'
3
- import { homedir } from 'node:os'
4
3
  import { join } from 'node:path'
5
4
 
6
5
  import { Long } from 'bson'
7
6
 
7
+ import { getConfigDir } from '@/shared/utils/config-dir'
8
8
  import { warn } from '@/shared/utils/stderr'
9
9
 
10
10
  import { LANG, PC_OS_NAME, getLocoDeviceConfig } from './protocol/config'
@@ -105,10 +105,8 @@ function wrapError(error: unknown, code: string): KakaoTalkError {
105
105
 
106
106
  const MAX_PAGES = 50
107
107
 
108
- const CONFIG_DIR = join(homedir(), '.config', 'agent-messenger')
109
-
110
108
  function syncStatePath(deviceUuid: string): string {
111
- return join(CONFIG_DIR, `kakaotalk-sync-state-${deviceUuid}.json`)
109
+ return join(getConfigDir(), `kakaotalk-sync-state-${deviceUuid}.json`)
112
110
  }
113
111
 
114
112
  async function loadSyncState(deviceUuid: string): Promise<SyncState | undefined> {
@@ -133,7 +131,7 @@ async function loadSyncState(deviceUuid: string): Promise<SyncState | undefined>
133
131
  }
134
132
 
135
133
  async function saveSyncState(deviceUuid: string, state: SyncState): Promise<void> {
136
- await mkdir(CONFIG_DIR, { recursive: true })
134
+ await mkdir(getConfigDir(), { recursive: true })
137
135
  const path = syncStatePath(deviceUuid)
138
136
  await writeFile(path, JSON.stringify(state, null, 2))
139
137
  await chmod(path, 0o600)
@@ -1,8 +1,8 @@
1
1
  import { existsSync } from 'node:fs'
2
2
  import { chmod, mkdir, readFile, rm, writeFile } from 'node:fs/promises'
3
- import { homedir } from 'node:os'
4
3
  import { join } from 'node:path'
5
4
 
5
+ import { getConfigDir } from '../../shared/utils/config-dir'
6
6
  import type { KakaoAccountCredentials, KakaoConfig, KakaoDeviceType } from './types'
7
7
 
8
8
  export interface PendingLoginState {
@@ -18,7 +18,7 @@ export class KakaoCredentialManager {
18
18
  private pendingLoginPath: string
19
19
 
20
20
  constructor(configDir?: string) {
21
- this.configDir = configDir ?? join(homedir(), '.config', 'agent-messenger')
21
+ this.configDir = configDir ?? getConfigDir()
22
22
  this.credentialsPath = join(this.configDir, 'kakaotalk-credentials.json')
23
23
  this.pendingLoginPath = join(this.configDir, 'kakaotalk-pending-login.json')
24
24
  }
@@ -1,7 +1,7 @@
1
1
  import { mkdirSync } from 'node:fs'
2
- import { homedir } from 'node:os'
3
2
  import { join } from 'node:path'
4
3
 
4
+ import { getConfigDir } from '@/shared/utils/config-dir'
5
5
  import { FileStorage } from '@/vendor/linejs/base/storage/mod.js'
6
6
  import {
7
7
  loginWithQR as linejsLoginWithQR,
@@ -41,7 +41,7 @@ function getDefaultDevice(): LineDevice {
41
41
  }
42
42
 
43
43
  function createStorage(accountId?: string): FileStorage {
44
- const dir = join(homedir(), '.config', 'agent-messenger', 'line-storage')
44
+ const dir = join(getConfigDir(), 'line-storage')
45
45
  mkdirSync(dir, { recursive: true })
46
46
  return new FileStorage(join(dir, `${accountId ?? 'default'}.json`))
47
47
  }
@@ -1,8 +1,8 @@
1
1
  import { existsSync } from 'node:fs'
2
2
  import { mkdir, rm, writeFile, readFile } from 'node:fs/promises'
3
- import { homedir } from 'node:os'
4
3
  import { join } from 'node:path'
5
4
 
5
+ import { getConfigDir } from '../../shared/utils/config-dir'
6
6
  import type { LineAccountCredentials, LineConfig } from './types'
7
7
 
8
8
  export class LineCredentialManager {
@@ -10,7 +10,7 @@ export class LineCredentialManager {
10
10
  private credentialsPath: string
11
11
 
12
12
  constructor(configDir?: string) {
13
- this.configDir = configDir ?? join(homedir(), '.config', 'agent-messenger')
13
+ this.configDir = configDir ?? getConfigDir()
14
14
  this.credentialsPath = join(this.configDir, 'line-credentials.json')
15
15
  }
16
16
 
@@ -1,8 +1,8 @@
1
1
  import { existsSync } from 'node:fs'
2
2
  import { chmod, mkdir, readFile, writeFile } from 'node:fs/promises'
3
- import { homedir } from 'node:os'
4
3
  import { join } from 'node:path'
5
4
 
5
+ import { getConfigDir } from '../../shared/utils/config-dir'
6
6
  import type { Config, WorkspaceCredentials } from './types'
7
7
 
8
8
  export class SlackCredentialManager {
@@ -10,7 +10,7 @@ export class SlackCredentialManager {
10
10
  private credentialsPath: string
11
11
 
12
12
  constructor(configDir?: string) {
13
- this.configDir = configDir ?? join(homedir(), '.config', 'agent-messenger')
13
+ this.configDir = configDir ?? getConfigDir()
14
14
  this.credentialsPath = join(this.configDir, 'slack-credentials.json')
15
15
  }
16
16
 
@@ -1,8 +1,8 @@
1
1
  import { existsSync } from 'node:fs'
2
2
  import { chmod, mkdir, readFile, writeFile } from 'node:fs/promises'
3
- import { homedir } from 'node:os'
4
3
  import { join } from 'node:path'
5
4
 
5
+ import { getConfigDir } from '../../shared/utils/config-dir'
6
6
  import type { SlackBotConfig, SlackBotCredentials, SlackBotWorkspace } from './types'
7
7
  import { SlackBotConfigSchema } from './types'
8
8
 
@@ -11,7 +11,7 @@ export class SlackBotCredentialManager {
11
11
  private credentialsPath: string
12
12
 
13
13
  constructor(configDir?: string) {
14
- this.configDir = configDir ?? join(homedir(), '.config', 'agent-messenger')
14
+ this.configDir = configDir ?? getConfigDir()
15
15
  this.credentialsPath = join(this.configDir, 'slackbot-credentials.json')
16
16
  }
17
17
 
@@ -1,8 +1,8 @@
1
1
  import { existsSync } from 'node:fs'
2
2
  import { mkdir, readFile, rm, writeFile } from 'node:fs/promises'
3
- import { homedir } from 'node:os'
4
3
  import { join } from 'node:path'
5
4
 
5
+ import { getConfigDir } from '../../shared/utils/config-dir'
6
6
  import type { TeamsAccount, TeamsAccountType, TeamsConfig, TeamsConfigLegacy, TeamsRegion } from './types'
7
7
 
8
8
  export class TeamsCredentialManager {
@@ -12,7 +12,7 @@ export class TeamsCredentialManager {
12
12
  private credentialsPath: string
13
13
 
14
14
  constructor(configDir?: string) {
15
- this.configDir = configDir ?? join(homedir(), '.config', 'agent-messenger')
15
+ this.configDir = configDir ?? getConfigDir()
16
16
  this.credentialsPath = join(this.configDir, 'teams-credentials.json')
17
17
  }
18
18
 
@@ -33,6 +33,7 @@ describe('whoami command', () => {
33
33
  return fn(fakeClient, {} as TelegramAccount, new TelegramCredentialManager())
34
34
  })
35
35
  consoleLogSpy = spyOn(console, 'log').mockImplementation(() => {})
36
+ consoleLogSpy.mockClear()
36
37
  })
37
38
 
38
39
  afterEach(() => {
@@ -1,8 +1,8 @@
1
1
  import { existsSync } from 'node:fs'
2
2
  import { mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises'
3
- import { homedir } from 'node:os'
4
3
  import { join } from 'node:path'
5
4
 
5
+ import { getConfigDir } from '../../shared/utils/config-dir'
6
6
  import {
7
7
  createAccountId,
8
8
  type TelegramAccount,
@@ -21,7 +21,7 @@ export class TelegramCredentialManager {
21
21
  private tdlibRootDir: string
22
22
 
23
23
  constructor(configDir?: string) {
24
- this.configDir = configDir ?? join(homedir(), '.config', 'agent-messenger')
24
+ this.configDir = configDir ?? getConfigDir()
25
25
  this.credentialsPath = join(this.configDir, 'telegram-credentials.json')
26
26
  this.provisioningStatePath = join(this.configDir, 'telegram-provisioning-state.json')
27
27
  this.tdlibRootDir = join(this.configDir, 'telegram')
@@ -1,8 +1,8 @@
1
1
  import { existsSync } from 'node:fs'
2
2
  import { mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises'
3
- import { homedir } from 'node:os'
4
3
  import { join } from 'node:path'
5
4
 
5
+ import { getConfigDir } from '../../shared/utils/config-dir'
6
6
  import { getWebexAppCredentials } from './app-config'
7
7
  import type { WebexConfig } from './types'
8
8
  import { WebexConfigSchema } from './types'
@@ -19,7 +19,7 @@ export class WebexCredentialManager {
19
19
  private credentialsPath: string
20
20
 
21
21
  constructor(configDir?: string) {
22
- this.configDir = configDir ?? join(homedir(), '.config', 'agent-messenger')
22
+ this.configDir = configDir ?? getConfigDir()
23
23
  this.credentialsPath = join(this.configDir, 'webex-credentials.json')
24
24
  }
25
25
 
@@ -1,8 +1,8 @@
1
1
  import { existsSync } from 'node:fs'
2
2
  import { chmod, mkdir, readFile, writeFile } from 'node:fs/promises'
3
- import { homedir } from 'node:os'
4
3
  import { join } from 'node:path'
5
4
 
5
+ import { getConfigDir } from '../../shared/utils/config-dir'
6
6
  import type { WeChatBotAccountEntry, WeChatBotConfig, WeChatBotCredentials } from './types'
7
7
  import { WeChatBotConfigSchema } from './types'
8
8
 
@@ -11,7 +11,7 @@ export class WeChatBotCredentialManager {
11
11
  private credentialsPath: string
12
12
 
13
13
  constructor(configDir?: string) {
14
- this.configDir = configDir ?? join(homedir(), '.config', 'agent-messenger')
14
+ this.configDir = configDir ?? getConfigDir()
15
15
  this.credentialsPath = join(this.configDir, 'wechatbot-credentials.json')
16
16
  }
17
17
 
@@ -1,8 +1,8 @@
1
1
  import { existsSync } from 'node:fs'
2
2
  import { mkdir, readFile, rm, writeFile } from 'node:fs/promises'
3
- import { homedir } from 'node:os'
4
3
  import { join } from 'node:path'
5
4
 
5
+ import { getConfigDir } from '../../shared/utils/config-dir'
6
6
  import { createAccountId, type WhatsAppAccount, type WhatsAppAccountPaths, type WhatsAppConfig } from './types'
7
7
 
8
8
  export class WhatsAppCredentialManager {
@@ -11,7 +11,7 @@ export class WhatsAppCredentialManager {
11
11
  private baileysRootDir: string
12
12
 
13
13
  constructor(configDir?: string) {
14
- this.configDir = configDir ?? join(homedir(), '.config', 'agent-messenger')
14
+ this.configDir = configDir ?? getConfigDir()
15
15
  this.credentialsPath = join(this.configDir, 'whatsapp-credentials.json')
16
16
  this.baileysRootDir = join(this.configDir, 'whatsapp')
17
17
  }
@@ -1,8 +1,8 @@
1
1
  import { existsSync } from 'node:fs'
2
2
  import { chmod, mkdir, readFile, writeFile } from 'node:fs/promises'
3
- import { homedir } from 'node:os'
4
3
  import { join } from 'node:path'
5
4
 
5
+ import { getConfigDir } from '../../shared/utils/config-dir'
6
6
  import type { WhatsAppBotAccountEntry, WhatsAppBotConfig, WhatsAppBotCredentials } from './types'
7
7
  import { WhatsAppBotConfigSchema } from './types'
8
8
 
@@ -11,7 +11,7 @@ export class WhatsAppBotCredentialManager {
11
11
  private credentialsPath: string
12
12
 
13
13
  constructor(configDir?: string) {
14
- this.configDir = configDir ?? join(homedir(), '.config', 'agent-messenger')
14
+ this.configDir = configDir ?? getConfigDir()
15
15
  this.credentialsPath = join(this.configDir, 'whatsappbot-credentials.json')
16
16
  }
17
17
 
@@ -0,0 +1,41 @@
1
+ import { afterEach, beforeEach, describe, expect, it } from 'bun:test'
2
+ import { homedir } from 'node:os'
3
+ import { join } from 'node:path'
4
+
5
+ import { CONFIG_DIR_ENV_VAR, getConfigDir } from './config-dir'
6
+
7
+ describe('getConfigDir', () => {
8
+ let original: string | undefined
9
+
10
+ beforeEach(() => {
11
+ original = process.env[CONFIG_DIR_ENV_VAR]
12
+ delete process.env[CONFIG_DIR_ENV_VAR]
13
+ })
14
+
15
+ afterEach(() => {
16
+ if (original === undefined) {
17
+ delete process.env[CONFIG_DIR_ENV_VAR]
18
+ } else {
19
+ process.env[CONFIG_DIR_ENV_VAR] = original
20
+ }
21
+ })
22
+
23
+ it('returns the default path when the env var is unset', () => {
24
+ expect(getConfigDir()).toBe(join(homedir(), '.config', 'agent-messenger'))
25
+ })
26
+
27
+ it('returns the env var value when set', () => {
28
+ process.env[CONFIG_DIR_ENV_VAR] = '/tmp/custom-config-dir'
29
+ expect(getConfigDir()).toBe('/tmp/custom-config-dir')
30
+ })
31
+
32
+ it('falls back to the default when the env var is empty', () => {
33
+ process.env[CONFIG_DIR_ENV_VAR] = ''
34
+ expect(getConfigDir()).toBe(join(homedir(), '.config', 'agent-messenger'))
35
+ })
36
+
37
+ it('does not append agent-messenger to the override path', () => {
38
+ process.env[CONFIG_DIR_ENV_VAR] = '/var/lib/messenger'
39
+ expect(getConfigDir()).toBe('/var/lib/messenger')
40
+ })
41
+ })
@@ -0,0 +1,23 @@
1
+ import { homedir } from 'node:os'
2
+ import { join } from 'node:path'
3
+
4
+ export const CONFIG_DIR_ENV_VAR = 'AGENT_MESSENGER_CONFIG_DIR'
5
+
6
+ /**
7
+ * Resolves the directory used to persist agent-messenger configuration and
8
+ * credentials.
9
+ *
10
+ * Resolution order:
11
+ * 1. `AGENT_MESSENGER_CONFIG_DIR` environment variable (if set and non-empty)
12
+ * 2. Default: `~/.config/agent-messenger`
13
+ *
14
+ * Used by every platform credential manager so that a single env var override
15
+ * relocates all stored credentials, sync state, and derived-key caches.
16
+ */
17
+ export function getConfigDir(): string {
18
+ const override = process.env[CONFIG_DIR_ENV_VAR]
19
+ if (override && override.length > 0) {
20
+ return override
21
+ }
22
+ return join(homedir(), '.config', 'agent-messenger')
23
+ }
@@ -1,8 +1,9 @@
1
1
  import { existsSync } from 'node:fs'
2
2
  import { mkdir, readFile, rm, writeFile } from 'node:fs/promises'
3
- import { homedir } from 'node:os'
4
3
  import { join } from 'node:path'
5
4
 
5
+ import { getConfigDir } from './config-dir'
6
+
6
7
  export type Platform = 'slack' | 'discord' | 'teams' | 'instagram' | 'channeltalk'
7
8
 
8
9
  /**
@@ -18,7 +19,7 @@ export class DerivedKeyCache {
18
19
  private cacheDir: string
19
20
 
20
21
  constructor(cacheDir?: string) {
21
- this.cacheDir = cacheDir ?? join(homedir(), '.config', 'agent-messenger', '.derived-keys')
22
+ this.cacheDir = cacheDir ?? join(getConfigDir(), '.derived-keys')
22
23
  }
23
24
 
24
25
  private getKeyPath(platform: Platform): string {