agent-messenger 2.10.0 → 2.10.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.
- package/.claude-plugin/plugin.json +1 -1
- package/dist/package.json +1 -1
- package/dist/src/platforms/teams/token-extractor.d.ts.map +1 -1
- package/dist/src/platforms/teams/token-extractor.js +15 -2
- package/dist/src/platforms/teams/token-extractor.js.map +1 -1
- package/dist/src/shared/chromium/decryptor.d.ts +6 -0
- package/dist/src/shared/chromium/decryptor.d.ts.map +1 -1
- package/dist/src/shared/chromium/decryptor.js +26 -6
- package/dist/src/shared/chromium/decryptor.js.map +1 -1
- package/e2e/channeltalk.e2e.test.ts +13 -13
- package/e2e/channeltalkbot.e2e.test.ts +13 -13
- package/e2e/discord.e2e.test.ts +24 -24
- package/e2e/discordbot.e2e.test.ts +16 -16
- package/e2e/instagram.e2e.test.ts +10 -10
- package/e2e/kakaotalk.e2e.test.ts +7 -7
- package/e2e/line.e2e.test.ts +8 -8
- package/e2e/slack.e2e.test.ts +34 -34
- package/e2e/slackbot.e2e.test.ts +14 -14
- package/e2e/teams.e2e.test.ts +23 -23
- package/e2e/telegram.e2e.test.ts +8 -8
- package/e2e/webex.e2e.test.ts +14 -14
- package/e2e/whatsapp.e2e.test.ts +8 -8
- package/e2e/whatsappbot.e2e.test.ts +6 -6
- package/package.json +1 -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 +1 -1
- 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/channeltalk/client.test.ts +26 -26
- package/src/platforms/channeltalk/commands/auth.test.ts +16 -16
- package/src/platforms/channeltalk/commands/bot.test.ts +2 -2
- package/src/platforms/channeltalk/commands/chat.test.ts +3 -3
- package/src/platforms/channeltalk/commands/group.test.ts +4 -4
- package/src/platforms/channeltalk/commands/manager.test.ts +2 -2
- package/src/platforms/channeltalk/commands/message.test.ts +17 -17
- package/src/platforms/channeltalk/commands/snapshot.test.ts +7 -7
- package/src/platforms/channeltalk/commands/whoami.test.ts +3 -3
- package/src/platforms/channeltalk/credential-manager.test.ts +18 -18
- package/src/platforms/channeltalk/ensure-auth.test.ts +5 -5
- package/src/platforms/channeltalk/index.test.ts +23 -23
- package/src/platforms/channeltalk/token-extractor.test.ts +21 -21
- package/src/platforms/channeltalk/types.test.ts +12 -12
- package/src/platforms/channeltalkbot/client.test.ts +14 -14
- package/src/platforms/channeltalkbot/commands/auth.test.ts +16 -16
- package/src/platforms/channeltalkbot/commands/bot.test.ts +6 -6
- package/src/platforms/channeltalkbot/commands/chat.test.ts +9 -9
- package/src/platforms/channeltalkbot/commands/group.test.ts +6 -6
- package/src/platforms/channeltalkbot/commands/manager.test.ts +3 -3
- package/src/platforms/channeltalkbot/commands/message.test.ts +10 -10
- package/src/platforms/channeltalkbot/commands/snapshot.test.ts +7 -7
- package/src/platforms/channeltalkbot/commands/whoami.test.ts +4 -4
- package/src/platforms/channeltalkbot/credential-manager.test.ts +27 -27
- package/src/platforms/channeltalkbot/index.test.ts +15 -15
- package/src/platforms/discord/client.test.ts +28 -28
- package/src/platforms/discord/commands/auth.test.ts +7 -7
- package/src/platforms/discord/commands/channel.test.ts +7 -7
- package/src/platforms/discord/commands/dm.test.ts +4 -4
- package/src/platforms/discord/commands/file.test.ts +4 -4
- package/src/platforms/discord/commands/friend.test.ts +6 -6
- package/src/platforms/discord/commands/member.test.ts +5 -5
- package/src/platforms/discord/commands/mention.test.ts +5 -5
- package/src/platforms/discord/commands/message.test.ts +9 -9
- package/src/platforms/discord/commands/note.test.ts +6 -6
- package/src/platforms/discord/commands/profile.test.ts +4 -4
- package/src/platforms/discord/commands/reaction.test.ts +5 -5
- package/src/platforms/discord/commands/server.test.ts +7 -7
- package/src/platforms/discord/commands/snapshot.test.ts +6 -6
- package/src/platforms/discord/commands/thread.test.ts +6 -6
- package/src/platforms/discord/commands/user.test.ts +5 -5
- package/src/platforms/discord/commands/whoami.test.ts +6 -6
- package/src/platforms/discord/credential-manager.test.ts +16 -16
- package/src/platforms/discord/ensure-auth.test.ts +8 -8
- package/src/platforms/discord/index.test.ts +17 -17
- package/src/platforms/discord/listener.test.ts +33 -33
- package/src/platforms/discord/token-extractor.test.ts +53 -53
- package/src/platforms/discord/types.test.ts +26 -26
- package/src/platforms/discordbot/client.test.ts +31 -31
- package/src/platforms/discordbot/commands/auth.test.ts +18 -18
- package/src/platforms/discordbot/commands/channel.test.ts +11 -11
- package/src/platforms/discordbot/commands/file.test.ts +7 -7
- package/src/platforms/discordbot/commands/message.test.ts +25 -25
- package/src/platforms/discordbot/commands/reaction.test.ts +6 -6
- package/src/platforms/discordbot/commands/server.test.ts +12 -12
- package/src/platforms/discordbot/commands/snapshot.test.ts +13 -13
- package/src/platforms/discordbot/commands/thread.test.ts +10 -10
- package/src/platforms/discordbot/commands/user.test.ts +9 -9
- package/src/platforms/discordbot/commands/whoami.test.ts +4 -4
- package/src/platforms/discordbot/credential-manager.test.ts +28 -28
- package/src/platforms/instagram/client.test.ts +18 -18
- package/src/platforms/instagram/commands/auth.test.ts +11 -11
- package/src/platforms/instagram/commands/chat.test.ts +6 -6
- package/src/platforms/instagram/commands/message.test.ts +11 -11
- package/src/platforms/instagram/commands/shared.test.ts +12 -12
- package/src/platforms/instagram/commands/whoami.test.ts +3 -3
- package/src/platforms/instagram/credential-manager.test.ts +21 -21
- package/src/platforms/instagram/ensure-auth.test.ts +4 -4
- package/src/platforms/instagram/index.test.ts +9 -9
- package/src/platforms/instagram/listener.test.ts +8 -8
- package/src/platforms/instagram/token-extractor.test.ts +35 -35
- package/src/platforms/kakaotalk/client.test.ts +33 -33
- package/src/platforms/kakaotalk/commands/auth.test.ts +11 -11
- package/src/platforms/kakaotalk/commands/chat.test.ts +6 -6
- package/src/platforms/kakaotalk/commands/message.test.ts +7 -7
- package/src/platforms/kakaotalk/commands/whoami.test.ts +5 -5
- package/src/platforms/kakaotalk/credential-manager.test.ts +15 -15
- package/src/platforms/kakaotalk/index.test.ts +15 -15
- package/src/platforms/kakaotalk/listener.test.ts +17 -17
- package/src/platforms/line/client.test.ts +17 -17
- package/src/platforms/line/commands/auth.test.ts +8 -8
- package/src/platforms/line/commands/chat.test.ts +7 -7
- package/src/platforms/line/commands/friend.test.ts +6 -6
- package/src/platforms/line/commands/message.test.ts +7 -7
- package/src/platforms/line/commands/whoami.test.ts +6 -6
- package/src/platforms/line/credential-manager.test.ts +17 -17
- package/src/platforms/line/index.test.ts +10 -10
- package/src/platforms/line/listener.test.ts +15 -15
- package/src/platforms/line/types.test.ts +14 -14
- package/src/platforms/slack/cli.test.ts +8 -8
- package/src/platforms/slack/client.test.ts +151 -151
- package/src/platforms/slack/commands/activity.test.ts +13 -13
- package/src/platforms/slack/commands/auth.test.ts +34 -34
- package/src/platforms/slack/commands/bookmark.test.ts +9 -9
- package/src/platforms/slack/commands/channel.test.ts +17 -17
- package/src/platforms/slack/commands/drafts.test.ts +7 -7
- package/src/platforms/slack/commands/emoji.test.ts +3 -3
- package/src/platforms/slack/commands/file.test.ts +12 -12
- package/src/platforms/slack/commands/message.test.ts +19 -19
- package/src/platforms/slack/commands/pin.test.ts +7 -7
- package/src/platforms/slack/commands/reaction.test.ts +10 -10
- package/src/platforms/slack/commands/reminder.test.ts +9 -9
- package/src/platforms/slack/commands/saved.test.ts +7 -7
- package/src/platforms/slack/commands/sections.test.ts +5 -5
- package/src/platforms/slack/commands/snapshot.test.ts +13 -13
- package/src/platforms/slack/commands/unread.test.ts +6 -6
- package/src/platforms/slack/commands/user.test.ts +10 -10
- package/src/platforms/slack/commands/usergroup.test.ts +15 -15
- package/src/platforms/slack/commands/whoami.test.ts +6 -6
- package/src/platforms/slack/commands/workspace.test.ts +26 -26
- package/src/platforms/slack/credential-manager.test.ts +14 -14
- package/src/platforms/slack/ensure-auth.test.ts +21 -21
- package/src/platforms/slack/index.test.ts +12 -12
- package/src/platforms/slack/listener.test.ts +17 -17
- package/src/platforms/slack/token-extractor-node.test.ts +2 -2
- package/src/platforms/slack/token-extractor.test.ts +37 -37
- package/src/platforms/slack/types.test.ts +21 -21
- package/src/platforms/slackbot/client.test.ts +22 -22
- package/src/platforms/slackbot/commands/auth.test.ts +14 -14
- package/src/platforms/slackbot/commands/channel.test.ts +7 -7
- package/src/platforms/slackbot/commands/message.test.ts +13 -13
- package/src/platforms/slackbot/commands/reaction.test.ts +6 -6
- package/src/platforms/slackbot/commands/user.test.ts +7 -7
- package/src/platforms/slackbot/commands/whoami.test.ts +4 -4
- package/src/platforms/slackbot/credential-manager.test.ts +22 -22
- package/src/platforms/slackbot/types.test.ts +7 -7
- package/src/platforms/teams/client.test.ts +30 -30
- package/src/platforms/teams/commands/auth.test.ts +8 -8
- package/src/platforms/teams/commands/channel.test.ts +7 -7
- package/src/platforms/teams/commands/file.test.ts +4 -4
- package/src/platforms/teams/commands/message.test.ts +5 -5
- package/src/platforms/teams/commands/reaction.test.ts +4 -4
- package/src/platforms/teams/commands/snapshot.test.ts +7 -7
- package/src/platforms/teams/commands/team.test.ts +8 -8
- package/src/platforms/teams/commands/user.test.ts +4 -4
- package/src/platforms/teams/commands/whoami.test.ts +6 -6
- package/src/platforms/teams/credential-manager.test.ts +17 -17
- package/src/platforms/teams/ensure-auth.test.ts +13 -13
- package/src/platforms/teams/index.test.ts +15 -15
- package/src/platforms/teams/token-extractor.test.ts +219 -145
- package/src/platforms/teams/token-extractor.ts +13 -2
- package/src/platforms/teams/types.test.ts +26 -26
- package/src/platforms/telegram/app-config.test.ts +4 -4
- package/src/platforms/telegram/chat-utils.test.ts +12 -12
- package/src/platforms/telegram/client.test.ts +4 -4
- package/src/platforms/telegram/commands/auth.test.ts +16 -16
- package/src/platforms/telegram/commands/chat.test.ts +9 -9
- package/src/platforms/telegram/commands/message.test.ts +6 -6
- package/src/platforms/telegram/commands/shared.test.ts +3 -3
- package/src/platforms/telegram/commands/whoami.test.ts +3 -3
- package/src/platforms/telegram/credential-manager.test.ts +10 -10
- package/src/platforms/telegram/types.test.ts +6 -6
- package/src/platforms/webex/app-config.test.ts +8 -8
- package/src/platforms/webex/cli.test.ts +5 -5
- package/src/platforms/webex/client.test.ts +65 -65
- package/src/platforms/webex/commands/auth.test.ts +18 -18
- package/src/platforms/webex/commands/member.test.ts +5 -5
- package/src/platforms/webex/commands/message.test.ts +12 -12
- package/src/platforms/webex/commands/snapshot.test.ts +5 -5
- package/src/platforms/webex/commands/space.test.ts +10 -10
- package/src/platforms/webex/commands/whoami.test.ts +6 -6
- package/src/platforms/webex/credential-manager.test.ts +22 -22
- package/src/platforms/webex/encryption.test.ts +4 -4
- package/src/platforms/webex/ensure-auth.test.ts +5 -5
- package/src/platforms/webex/index.test.ts +5 -5
- package/src/platforms/webex/markdown-to-html.test.ts +33 -33
- package/src/platforms/webex/token-extractor.test.ts +23 -23
- package/src/platforms/webex/types.test.ts +27 -27
- package/src/platforms/wechatbot/client.test.ts +27 -27
- package/src/platforms/wechatbot/commands/auth.test.ts +15 -15
- package/src/platforms/wechatbot/commands/message.test.ts +8 -8
- package/src/platforms/wechatbot/commands/template.test.ts +9 -9
- package/src/platforms/wechatbot/commands/user.test.ts +7 -7
- package/src/platforms/wechatbot/commands/whoami.test.ts +5 -5
- package/src/platforms/wechatbot/credential-manager.test.ts +18 -18
- package/src/platforms/wechatbot/index.test.ts +10 -10
- package/src/platforms/wechatbot/types.test.ts +25 -25
- package/src/platforms/whatsapp/commands/auth.test.ts +13 -13
- package/src/platforms/whatsapp/commands/chat.test.ts +8 -8
- package/src/platforms/whatsapp/commands/message.test.ts +10 -10
- package/src/platforms/whatsapp/commands/whoami.test.ts +3 -3
- package/src/platforms/whatsapp/credential-manager.test.ts +23 -23
- package/src/platforms/whatsapp/ensure-auth.test.ts +4 -4
- package/src/platforms/whatsapp/index.test.ts +8 -8
- package/src/platforms/whatsapp/types.test.ts +42 -42
- package/src/platforms/whatsappbot/client.test.ts +27 -27
- package/src/platforms/whatsappbot/commands/auth.test.ts +14 -14
- package/src/platforms/whatsappbot/commands/message.test.ts +16 -16
- package/src/platforms/whatsappbot/commands/template.test.ts +9 -9
- package/src/platforms/whatsappbot/commands/whoami.test.ts +5 -5
- package/src/platforms/whatsappbot/credential-manager.test.ts +18 -18
- package/src/platforms/whatsappbot/index.test.ts +7 -7
- package/src/platforms/whatsappbot/types.test.ts +18 -18
- package/src/shared/chromium/browsers.test.ts +22 -22
- package/src/shared/chromium/cookie-reader.test.ts +13 -13
- package/src/shared/chromium/decryptor.test.ts +97 -32
- package/src/shared/chromium/decryptor.ts +27 -6
- package/src/shared/utils/concurrency.test.ts +6 -6
- package/src/shared/utils/derived-key-cache.test.ts +11 -11
- package/src/tui/utils.test.ts +31 -31
|
@@ -187,22 +187,43 @@ export class ChromiumCookieDecryptor {
|
|
|
187
187
|
if (this.platform !== 'win32') return null
|
|
188
188
|
try {
|
|
189
189
|
const b64Input = encrypted.toString('base64')
|
|
190
|
+
// Silence progress/information/warning streams so PowerShell doesn't emit CLIXML
|
|
191
|
+
// ("#< CLIXML ...") alongside our base64 payload when modules auto-load on first use.
|
|
192
|
+
// Wrap the payload in explicit markers so we can recover it even if stray output leaks in.
|
|
190
193
|
const script = [
|
|
194
|
+
"$ProgressPreference='SilentlyContinue'",
|
|
195
|
+
"$InformationPreference='SilentlyContinue'",
|
|
196
|
+
"$WarningPreference='SilentlyContinue'",
|
|
191
197
|
'Add-Type -AssemblyName System.Security',
|
|
192
198
|
`$d=[System.Security.Cryptography.ProtectedData]::Unprotect([Convert]::FromBase64String("${b64Input}"),$null,[System.Security.Cryptography.DataProtectionScope]::CurrentUser)`,
|
|
193
|
-
'[Convert]::ToBase64String($d)',
|
|
199
|
+
"Write-Host ('<<<B64>>>'+[Convert]::ToBase64String($d)+'<<<END>>>')",
|
|
194
200
|
].join(';')
|
|
195
201
|
const encodedCommand = Buffer.from(script, 'utf16le').toString('base64')
|
|
196
|
-
const
|
|
197
|
-
|
|
198
|
-
timeout: 10000,
|
|
199
|
-
|
|
200
|
-
|
|
202
|
+
const rawResult = execSync(
|
|
203
|
+
`powershell -NoProfile -NonInteractive -OutputFormat Text -EncodedCommand ${encodedCommand}`,
|
|
204
|
+
{ encoding: 'utf8', timeout: 10000 },
|
|
205
|
+
)
|
|
206
|
+
const b64 = ChromiumCookieDecryptor.extractDPAPIPayload(rawResult)
|
|
207
|
+
if (!b64) return null
|
|
208
|
+
return Buffer.from(b64, 'base64')
|
|
201
209
|
} catch {
|
|
202
210
|
return null
|
|
203
211
|
}
|
|
204
212
|
}
|
|
205
213
|
|
|
214
|
+
/**
|
|
215
|
+
* Extract the base64-encoded DPAPI payload from PowerShell stdout, stripping any
|
|
216
|
+
* CLIXML progress-stream contamination or other stray output. Returns null if
|
|
217
|
+
* no valid payload is found.
|
|
218
|
+
*/
|
|
219
|
+
static extractDPAPIPayload(stdout: string): string | null {
|
|
220
|
+
const match = stdout.match(/<<<B64>>>([A-Za-z0-9+/=\r\n]*)<<<END>>>/)
|
|
221
|
+
if (!match) return null
|
|
222
|
+
const b64 = match[1].replace(/\s+/g, '')
|
|
223
|
+
if (!b64) return null
|
|
224
|
+
return b64
|
|
225
|
+
}
|
|
226
|
+
|
|
206
227
|
static stripIntegrityHash(decrypted: Buffer): Buffer {
|
|
207
228
|
if (decrypted.length <= 32) return decrypted
|
|
208
229
|
const hasNonPrintablePrefix = decrypted.subarray(0, 32).some((b) => b < 0x20 || b > 0x7e)
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { describe, expect,
|
|
1
|
+
import { describe, expect, it } from 'bun:test'
|
|
2
2
|
|
|
3
3
|
import { parallelMap } from './concurrency'
|
|
4
4
|
|
|
5
5
|
describe('parallelMap', () => {
|
|
6
|
-
|
|
6
|
+
it('processes items in parallel', async () => {
|
|
7
7
|
const items = [1, 2, 3, 4, 5]
|
|
8
8
|
const results = await parallelMap(items, async (n) => n * 2)
|
|
9
9
|
expect(results).toEqual([2, 4, 6, 8, 10])
|
|
10
10
|
})
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
it('maintains order of results', async () => {
|
|
13
13
|
const items = [100, 50, 10]
|
|
14
14
|
const results = await parallelMap(
|
|
15
15
|
items,
|
|
@@ -22,7 +22,7 @@ describe('parallelMap', () => {
|
|
|
22
22
|
expect(results).toEqual([100, 50, 10])
|
|
23
23
|
})
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
it('respects concurrency limit', async () => {
|
|
26
26
|
let concurrent = 0
|
|
27
27
|
let maxConcurrent = 0
|
|
28
28
|
const items = [1, 2, 3, 4, 5, 6]
|
|
@@ -41,12 +41,12 @@ describe('parallelMap', () => {
|
|
|
41
41
|
expect(maxConcurrent).toBe(2)
|
|
42
42
|
})
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
it('handles empty array', async () => {
|
|
45
45
|
const results = await parallelMap([], async (n: number) => n * 2)
|
|
46
46
|
expect(results).toEqual([])
|
|
47
47
|
})
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
it('passes index to function', async () => {
|
|
50
50
|
const items = ['a', 'b', 'c']
|
|
51
51
|
const results = await parallelMap(items, async (item, index) => `${item}${index}`)
|
|
52
52
|
expect(results).toEqual(['a0', 'b1', 'c2'])
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect,
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it } from 'bun:test'
|
|
2
2
|
import { existsSync, mkdirSync, rmSync } from 'node:fs'
|
|
3
3
|
import { tmpdir } from 'node:os'
|
|
4
4
|
import { join } from 'node:path'
|
|
@@ -22,12 +22,12 @@ describe('DerivedKeyCache', () => {
|
|
|
22
22
|
})
|
|
23
23
|
|
|
24
24
|
describe('get', () => {
|
|
25
|
-
|
|
25
|
+
it('returns null when no cached key exists', async () => {
|
|
26
26
|
const result = await cache.get('slack')
|
|
27
27
|
expect(result).toBeNull()
|
|
28
28
|
})
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
it('returns cached key when it exists', async () => {
|
|
31
31
|
// given
|
|
32
32
|
const key = Buffer.from('test-key-16bytes')
|
|
33
33
|
await cache.set('slack', key)
|
|
@@ -39,7 +39,7 @@ describe('DerivedKeyCache', () => {
|
|
|
39
39
|
expect(result).toEqual(key)
|
|
40
40
|
})
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
it('returns different keys for different platforms', async () => {
|
|
43
43
|
// given
|
|
44
44
|
const slackKey = Buffer.from('slack-key-16byte')
|
|
45
45
|
const discordKey = Buffer.from('discord-key-16by')
|
|
@@ -53,7 +53,7 @@ describe('DerivedKeyCache', () => {
|
|
|
53
53
|
})
|
|
54
54
|
|
|
55
55
|
describe('set', () => {
|
|
56
|
-
|
|
56
|
+
it('creates cache directory if it does not exist', async () => {
|
|
57
57
|
// given
|
|
58
58
|
const nestedDir = join(testDir, 'nested', 'cache')
|
|
59
59
|
const nestedCache = new DerivedKeyCache(nestedDir)
|
|
@@ -65,7 +65,7 @@ describe('DerivedKeyCache', () => {
|
|
|
65
65
|
expect(existsSync(nestedDir)).toBe(true)
|
|
66
66
|
})
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
it('overwrites existing cached key', async () => {
|
|
69
69
|
// given
|
|
70
70
|
const oldKey = Buffer.from('old-key-16bytes!')
|
|
71
71
|
const newKey = Buffer.from('new-key-16bytes!')
|
|
@@ -80,7 +80,7 @@ describe('DerivedKeyCache', () => {
|
|
|
80
80
|
})
|
|
81
81
|
|
|
82
82
|
describe('clear', () => {
|
|
83
|
-
|
|
83
|
+
it('removes cached key for platform', async () => {
|
|
84
84
|
// given
|
|
85
85
|
await cache.set('slack', Buffer.from('test-key'))
|
|
86
86
|
|
|
@@ -91,7 +91,7 @@ describe('DerivedKeyCache', () => {
|
|
|
91
91
|
expect(await cache.get('slack')).toBeNull()
|
|
92
92
|
})
|
|
93
93
|
|
|
94
|
-
|
|
94
|
+
it('does not affect other platforms', async () => {
|
|
95
95
|
// given
|
|
96
96
|
const discordKey = Buffer.from('discord-key')
|
|
97
97
|
await cache.set('slack', Buffer.from('slack-key'))
|
|
@@ -105,13 +105,13 @@ describe('DerivedKeyCache', () => {
|
|
|
105
105
|
expect(await cache.get('discord')).toEqual(discordKey)
|
|
106
106
|
})
|
|
107
107
|
|
|
108
|
-
|
|
108
|
+
it('does not throw when key does not exist', async () => {
|
|
109
109
|
await expect(cache.clear('slack')).resolves.toBeUndefined()
|
|
110
110
|
})
|
|
111
111
|
})
|
|
112
112
|
|
|
113
113
|
describe('clearAll', () => {
|
|
114
|
-
|
|
114
|
+
it('removes all cached keys', async () => {
|
|
115
115
|
// given
|
|
116
116
|
await cache.set('slack', Buffer.from('slack-key'))
|
|
117
117
|
await cache.set('discord', Buffer.from('discord-key'))
|
|
@@ -126,7 +126,7 @@ describe('DerivedKeyCache', () => {
|
|
|
126
126
|
expect(await cache.get('teams')).toBeNull()
|
|
127
127
|
})
|
|
128
128
|
|
|
129
|
-
|
|
129
|
+
it('does not throw when cache directory does not exist', async () => {
|
|
130
130
|
// given
|
|
131
131
|
const emptyCache = new DerivedKeyCache(join(testDir, 'nonexistent'))
|
|
132
132
|
|
package/src/tui/utils.test.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { describe,
|
|
1
|
+
import { describe, it, expect } from 'bun:test'
|
|
2
2
|
|
|
3
3
|
import { formatTimestamp, truncate, fuzzyMatch, stripHtml } from './utils'
|
|
4
4
|
|
|
5
5
|
describe('formatTimestamp', () => {
|
|
6
|
-
|
|
6
|
+
it("returns HH:MM for today's date", () => {
|
|
7
7
|
const now = new Date()
|
|
8
8
|
const epochSeconds = (now.getTime() / 1000).toFixed(6)
|
|
9
9
|
const result = formatTimestamp(epochSeconds)
|
|
10
10
|
expect(result).toMatch(/^\d{2}:\d{2}$/)
|
|
11
11
|
})
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
it("returns MM/DD HH:MM for yesterday's date", () => {
|
|
14
14
|
const yesterday = new Date()
|
|
15
15
|
yesterday.setDate(yesterday.getDate() - 1)
|
|
16
16
|
const epochSeconds = (yesterday.getTime() / 1000).toFixed(6)
|
|
@@ -18,24 +18,24 @@ describe('formatTimestamp', () => {
|
|
|
18
18
|
expect(result).toMatch(/^\d{2}\/\d{2} \d{2}:\d{2}$/)
|
|
19
19
|
})
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
it('ISO 8601 string for today returns HH:MM', () => {
|
|
22
22
|
const now = new Date()
|
|
23
23
|
const iso = now.toISOString()
|
|
24
24
|
const result = formatTimestamp(iso)
|
|
25
25
|
expect(result).toMatch(/^\d{2}:\d{2}$/)
|
|
26
26
|
})
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
it('ISO 8601 string for past date returns MM/DD HH:MM', () => {
|
|
29
29
|
const result = formatTimestamp('2024-03-15T10:30:00Z')
|
|
30
30
|
expect(result).toMatch(/^\d{2}\/\d{2} \d{2}:\d{2}$/)
|
|
31
31
|
})
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
it('invalid string returns original', () => {
|
|
34
34
|
expect(formatTimestamp('not-a-date')).toBe('not-a-date')
|
|
35
35
|
expect(formatTimestamp('abc123')).toBe('abc123')
|
|
36
36
|
})
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
it('formats Slack-style epoch with microseconds as HH:MM', () => {
|
|
39
39
|
const now = new Date()
|
|
40
40
|
const slackTs = `${Math.floor(now.getTime() / 1000)}.123456`
|
|
41
41
|
const result = formatTimestamp(slackTs)
|
|
@@ -44,105 +44,105 @@ describe('formatTimestamp', () => {
|
|
|
44
44
|
})
|
|
45
45
|
|
|
46
46
|
describe('truncate', () => {
|
|
47
|
-
|
|
47
|
+
it('returns short string unchanged', () => {
|
|
48
48
|
expect(truncate('hello', 10)).toBe('hello')
|
|
49
49
|
})
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
it('returns string unchanged when length equals maxLen', () => {
|
|
52
52
|
expect(truncate('hello', 5)).toBe('hello')
|
|
53
53
|
})
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
it('long string gets truncated with ellipsis', () => {
|
|
56
56
|
expect(truncate('hello world', 8)).toBe('hello...')
|
|
57
57
|
})
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
it('truncates without ellipsis when maxLen is 3', () => {
|
|
60
60
|
expect(truncate('hello', 3)).toBe('hel')
|
|
61
61
|
})
|
|
62
62
|
|
|
63
|
-
|
|
63
|
+
it('truncates without ellipsis when maxLen is 1', () => {
|
|
64
64
|
expect(truncate('hello', 1)).toBe('h')
|
|
65
65
|
})
|
|
66
66
|
|
|
67
|
-
|
|
67
|
+
it('returns empty string when maxLen is 0', () => {
|
|
68
68
|
expect(truncate('hello', 0)).toBe('')
|
|
69
69
|
})
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
it('adds ellipsis when maxLen is 4', () => {
|
|
72
72
|
expect(truncate('hello', 4)).toBe('h...')
|
|
73
73
|
})
|
|
74
74
|
})
|
|
75
75
|
|
|
76
76
|
describe('fuzzyMatch', () => {
|
|
77
|
-
|
|
77
|
+
it('exact match returns true', () => {
|
|
78
78
|
expect(fuzzyMatch('general', 'general')).toBe(true)
|
|
79
79
|
})
|
|
80
80
|
|
|
81
|
-
|
|
81
|
+
it('partial match in order returns true', () => {
|
|
82
82
|
expect(fuzzyMatch('gnrl', 'general')).toBe(true)
|
|
83
83
|
})
|
|
84
84
|
|
|
85
|
-
|
|
85
|
+
it('matches case-insensitively', () => {
|
|
86
86
|
expect(fuzzyMatch('GNRL', 'general')).toBe(true)
|
|
87
87
|
expect(fuzzyMatch('gnrl', 'GENERAL')).toBe(true)
|
|
88
88
|
})
|
|
89
89
|
|
|
90
|
-
|
|
90
|
+
it('empty query returns true', () => {
|
|
91
91
|
expect(fuzzyMatch('', 'anything')).toBe(true)
|
|
92
92
|
expect(fuzzyMatch('', '')).toBe(true)
|
|
93
93
|
})
|
|
94
94
|
|
|
95
|
-
|
|
95
|
+
it('no match returns false', () => {
|
|
96
96
|
expect(fuzzyMatch('xyz', 'general')).toBe(false)
|
|
97
97
|
})
|
|
98
98
|
|
|
99
|
-
|
|
99
|
+
it('characters out of order returns false', () => {
|
|
100
100
|
expect(fuzzyMatch('lrng', 'general')).toBe(false)
|
|
101
101
|
})
|
|
102
102
|
|
|
103
|
-
|
|
103
|
+
it('query longer than text returns false', () => {
|
|
104
104
|
expect(fuzzyMatch('generalgeneral', 'general')).toBe(false)
|
|
105
105
|
})
|
|
106
106
|
})
|
|
107
107
|
|
|
108
108
|
describe('stripHtml', () => {
|
|
109
|
-
|
|
109
|
+
it('removes simple tags', () => {
|
|
110
110
|
expect(stripHtml('<p>hello</p>')).toBe('hello')
|
|
111
111
|
})
|
|
112
112
|
|
|
113
|
-
|
|
113
|
+
it('removes nested tags', () => {
|
|
114
114
|
expect(stripHtml('<div><p><strong>hello</strong></p></div>')).toBe('hello')
|
|
115
115
|
})
|
|
116
116
|
|
|
117
|
-
|
|
117
|
+
it('decodes &', () => {
|
|
118
118
|
expect(stripHtml('a & b')).toBe('a & b')
|
|
119
119
|
})
|
|
120
120
|
|
|
121
|
-
|
|
121
|
+
it('decodes < and >', () => {
|
|
122
122
|
expect(stripHtml('<tag>')).toBe('<tag>')
|
|
123
123
|
})
|
|
124
124
|
|
|
125
|
-
|
|
125
|
+
it('decodes "', () => {
|
|
126
126
|
expect(stripHtml('say "hello"')).toBe('say "hello"')
|
|
127
127
|
})
|
|
128
128
|
|
|
129
|
-
|
|
129
|
+
it('decodes '', () => {
|
|
130
130
|
expect(stripHtml('it's')).toBe("it's")
|
|
131
131
|
})
|
|
132
132
|
|
|
133
|
-
|
|
133
|
+
it('collapses multiple whitespace', () => {
|
|
134
134
|
expect(stripHtml('hello world')).toBe('hello world')
|
|
135
135
|
})
|
|
136
136
|
|
|
137
|
-
|
|
137
|
+
it('trims leading and trailing whitespace', () => {
|
|
138
138
|
expect(stripHtml(' hello ')).toBe('hello')
|
|
139
139
|
})
|
|
140
140
|
|
|
141
|
-
|
|
141
|
+
it('handles multiple entities and tags together', () => {
|
|
142
142
|
expect(stripHtml('<p>Hello & <strong>World</strong></p>')).toBe('Hello & World')
|
|
143
143
|
})
|
|
144
144
|
|
|
145
|
-
|
|
145
|
+
it('collapses whitespace left by tag removal', () => {
|
|
146
146
|
expect(stripHtml('<p>hello</p> <p>world</p>')).toBe('hello world')
|
|
147
147
|
})
|
|
148
148
|
})
|