agent-messenger 2.23.6 → 2.24.1
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 +4 -0
- package/README.md +12 -1
- package/bun.lock +10 -72
- package/dist/package.json +7 -4
- package/dist/src/platforms/kakaotalk/token-extractor.d.ts.map +1 -1
- package/dist/src/platforms/kakaotalk/token-extractor.js +11 -38
- package/dist/src/platforms/kakaotalk/token-extractor.js.map +1 -1
- package/dist/src/platforms/slack/commands/auth.d.ts.map +1 -1
- package/dist/src/platforms/slack/commands/auth.js +88 -5
- package/dist/src/platforms/slack/commands/auth.js.map +1 -1
- package/dist/src/platforms/slack/ensure-auth.d.ts +2 -1
- package/dist/src/platforms/slack/ensure-auth.d.ts.map +1 -1
- package/dist/src/platforms/slack/ensure-auth.js +49 -2
- package/dist/src/platforms/slack/ensure-auth.js.map +1 -1
- package/dist/src/platforms/slack/index.d.ts +4 -0
- package/dist/src/platforms/slack/index.d.ts.map +1 -1
- package/dist/src/platforms/slack/index.js +2 -0
- package/dist/src/platforms/slack/index.js.map +1 -1
- package/dist/src/platforms/slack/qr-http-login.d.ts +14 -0
- package/dist/src/platforms/slack/qr-http-login.d.ts.map +1 -0
- package/dist/src/platforms/slack/qr-http-login.js +90 -0
- package/dist/src/platforms/slack/qr-http-login.js.map +1 -0
- package/dist/src/platforms/slack/qr-login.d.ts +10 -0
- package/dist/src/platforms/slack/qr-login.d.ts.map +1 -0
- package/dist/src/platforms/slack/qr-login.js +72 -0
- package/dist/src/platforms/slack/qr-login.js.map +1 -0
- package/dist/src/platforms/slack/token-extractor.d.ts.map +1 -1
- package/dist/src/platforms/slack/token-extractor.js +5 -11
- package/dist/src/platforms/slack/token-extractor.js.map +1 -1
- package/dist/src/shared/chromium/cookie-reader.d.ts.map +1 -1
- package/dist/src/shared/chromium/cookie-reader.js +4 -19
- package/dist/src/shared/chromium/cookie-reader.js.map +1 -1
- package/dist/src/shared/sqlite.d.ts +10 -0
- package/dist/src/shared/sqlite.d.ts.map +1 -0
- package/dist/src/shared/sqlite.js +46 -0
- package/dist/src/shared/sqlite.js.map +1 -0
- package/dist/src/vendor/linejs/base/request/mod.js +1 -1
- package/dist/src/vendor/linejs/base/request/mod.test.ts +54 -0
- package/docs/content/docs/cli/slack.mdx +22 -0
- package/docs/content/docs/sdk/slack.mdx +15 -0
- package/package.json +7 -4
- 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 +45 -1
- package/skills/agent-slack/references/authentication.md +29 -0
- 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-telegrambot/SKILL.md +1 -1
- package/skills/agent-webex/SKILL.md +1 -1
- package/skills/agent-webexbot/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/token-extractor.test.ts +2 -2
- package/src/platforms/kakaotalk/token-extractor.ts +13 -36
- package/src/platforms/slack/commands/auth.ts +106 -5
- package/src/platforms/slack/ensure-auth.test.ts +130 -19
- package/src/platforms/slack/ensure-auth.ts +57 -2
- package/src/platforms/slack/index.test.ts +10 -0
- package/src/platforms/slack/index.ts +4 -0
- package/src/platforms/slack/qr-http-login.test.ts +157 -0
- package/src/platforms/slack/qr-http-login.ts +120 -0
- package/src/platforms/slack/qr-login.test.ts +103 -0
- package/src/platforms/slack/qr-login.ts +90 -0
- package/src/platforms/slack/token-extractor-node-test.ts +5 -3
- package/src/platforms/slack/token-extractor.ts +4 -11
- package/src/shared/chromium/cookie-reader-node-test.ts +70 -0
- package/src/shared/chromium/cookie-reader-node.test.ts +10 -0
- package/src/shared/chromium/cookie-reader.ts +4 -21
- package/src/shared/sqlite.ts +61 -0
- package/src/vendor/linejs/base/request/mod.js +1 -1
- package/src/vendor/linejs/base/request/mod.test.ts +54 -0
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { copyFileSync, existsSync, rmSync } from 'node:fs'
|
|
2
|
-
import { createRequire } from 'node:module'
|
|
3
2
|
import { tmpdir } from 'node:os'
|
|
4
3
|
import { join } from 'node:path'
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
import { openReadonlyDatabase } from '@/shared/sqlite'
|
|
7
6
|
|
|
8
7
|
/**
|
|
9
8
|
* Reads Chromium SQLite cookie databases with Bun/Node dual-runtime support.
|
|
@@ -70,24 +69,7 @@ export class ChromiumCookieReader {
|
|
|
70
69
|
params: unknown[] | undefined,
|
|
71
70
|
mode: 'all' | 'first',
|
|
72
71
|
): T[] | T | null {
|
|
73
|
-
|
|
74
|
-
const { Database } = require('bun:sqlite')
|
|
75
|
-
const db = new Database(tempPath, { readonly: true })
|
|
76
|
-
|
|
77
|
-
try {
|
|
78
|
-
const stmt = db.query(sql)
|
|
79
|
-
if (mode === 'all') {
|
|
80
|
-
return (params ? stmt.all(...params) : stmt.all()) as T[]
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
return (params ? stmt.get(...params) : stmt.get()) as T | null
|
|
84
|
-
} finally {
|
|
85
|
-
db.close()
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const Database = require('better-sqlite3')
|
|
90
|
-
const db = new Database(tempPath, { readonly: true })
|
|
72
|
+
const db = openReadonlyDatabase(tempPath)
|
|
91
73
|
|
|
92
74
|
try {
|
|
93
75
|
const stmt = db.prepare(sql)
|
|
@@ -95,7 +77,8 @@ export class ChromiumCookieReader {
|
|
|
95
77
|
return (params ? stmt.all(...params) : stmt.all()) as T[]
|
|
96
78
|
}
|
|
97
79
|
|
|
98
|
-
|
|
80
|
+
const row = params ? stmt.get(...params) : stmt.get()
|
|
81
|
+
return (row ?? null) as T | null
|
|
99
82
|
} finally {
|
|
100
83
|
db.close()
|
|
101
84
|
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { createRequire } from 'node:module'
|
|
2
|
+
|
|
3
|
+
const require = createRequire(import.meta.url)
|
|
4
|
+
|
|
5
|
+
export interface ReadonlyStatement {
|
|
6
|
+
get(...params: unknown[]): unknown
|
|
7
|
+
all(...params: unknown[]): unknown[]
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface ReadonlyDatabase {
|
|
11
|
+
prepare(sql: string): ReadonlyStatement
|
|
12
|
+
close(): void
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
type ReadonlyDatabaseConstructor = new (path: string, options: { readOnly: boolean }) => ReadonlyDatabase
|
|
16
|
+
|
|
17
|
+
// Uses the runtime's built-in driver (bun:sqlite on Bun, node:sqlite on Node >= 22.13)
|
|
18
|
+
// to avoid a native addon dependency.
|
|
19
|
+
//
|
|
20
|
+
// Runtime quirks callers must respect (both drivers behave this way):
|
|
21
|
+
// - BLOB columns are returned as Uint8Array, not Buffer. Wrap with Buffer.from()
|
|
22
|
+
// before any Buffer-specific call (e.g. .toString('utf8'), node:crypto helpers).
|
|
23
|
+
// - node:sqlite throws ERR_OUT_OF_RANGE when reading an INTEGER above
|
|
24
|
+
// Number.MAX_SAFE_INTEGER, so never SELECT raw microsecond timestamps such as
|
|
25
|
+
// Chromium's *_utc columns; use them only in WHERE / ORDER BY clauses.
|
|
26
|
+
export function openReadonlyDatabase(path: string): ReadonlyDatabase {
|
|
27
|
+
if (typeof globalThis.Bun !== 'undefined') {
|
|
28
|
+
const { Database } = require('bun:sqlite')
|
|
29
|
+
return new Database(path, { readonly: true }) as ReadonlyDatabase
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
let DatabaseSync: ReadonlyDatabaseConstructor
|
|
33
|
+
// node:sqlite emits a one-time ExperimentalWarning to stderr on load
|
|
34
|
+
// (Node < 24.15) that clutters the CLI's output. Suppress just that warning
|
|
35
|
+
// while loading the module, then restore the original handler.
|
|
36
|
+
const originalEmitWarning = process.emitWarning
|
|
37
|
+
const filteredEmitWarning = (...args: unknown[]): void => {
|
|
38
|
+
const [warning, second] = args
|
|
39
|
+
const name =
|
|
40
|
+
warning instanceof Error
|
|
41
|
+
? warning.name
|
|
42
|
+
: typeof second === 'string'
|
|
43
|
+
? second
|
|
44
|
+
: (second as { type?: string } | undefined)?.type
|
|
45
|
+
const message = warning instanceof Error ? warning.message : String(warning)
|
|
46
|
+
if (name === 'ExperimentalWarning' && message.includes('SQLite')) return
|
|
47
|
+
;(originalEmitWarning as (...forwarded: unknown[]) => void).apply(process, args)
|
|
48
|
+
}
|
|
49
|
+
process.emitWarning = filteredEmitWarning as typeof process.emitWarning
|
|
50
|
+
try {
|
|
51
|
+
DatabaseSync = require('node:sqlite').DatabaseSync
|
|
52
|
+
} catch {
|
|
53
|
+
throw new Error(
|
|
54
|
+
'SQLite support requires Node.js >= 22.13.0 (the built-in node:sqlite module) or Bun. Please upgrade Node.js.',
|
|
55
|
+
)
|
|
56
|
+
} finally {
|
|
57
|
+
process.emitWarning = originalEmitWarning
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return new DatabaseSync(path, { readOnly: true })
|
|
61
|
+
}
|
|
@@ -158,7 +158,7 @@ const square = [
|
|
|
158
158
|
throw new InternalError("RequestError", `Request internal failed, ${methodName}(${path}) -> ` + JSON.stringify(res.data.e), res.data.e);
|
|
159
159
|
}
|
|
160
160
|
if (hasError && !isRefresh) {
|
|
161
|
-
if (res.data.e.code === "NOT_AUTHORIZED_DEVICE") {
|
|
161
|
+
if (res.data.e && res.data.e.code === "NOT_AUTHORIZED_DEVICE") {
|
|
162
162
|
delete this.client.authToken;
|
|
163
163
|
this.client.emit("end", this.client.profile);
|
|
164
164
|
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { describe, expect, it } from 'bun:test'
|
|
2
|
+
|
|
3
|
+
import { InternalError } from '../core/mod.js'
|
|
4
|
+
import { RequestClient } from './mod.js'
|
|
5
|
+
|
|
6
|
+
// Regression: a thrift error response can set hasError (empty res.data[0]) while
|
|
7
|
+
// omitting the exception struct (res.data[1] absent), leaving res.data.e undefined.
|
|
8
|
+
function createClient(readThriftResult: { data: Record<string, unknown> }) {
|
|
9
|
+
const deviceDetails = {
|
|
10
|
+
device: 'TEST',
|
|
11
|
+
appVersion: '0.0.0',
|
|
12
|
+
systemName: 'TEST',
|
|
13
|
+
systemVersion: '0.0.0',
|
|
14
|
+
}
|
|
15
|
+
const stubClient = {
|
|
16
|
+
deviceDetails,
|
|
17
|
+
endpoint: 'legy.line-apps.test',
|
|
18
|
+
authToken: 'expired-token',
|
|
19
|
+
config: { timeout: 1000 },
|
|
20
|
+
storage: { get: async () => undefined },
|
|
21
|
+
log: () => {},
|
|
22
|
+
emit: () => {},
|
|
23
|
+
fetch: async () => ({
|
|
24
|
+
headers: { get: () => null },
|
|
25
|
+
arrayBuffer: async () => new ArrayBuffer(0),
|
|
26
|
+
}),
|
|
27
|
+
thrift: {
|
|
28
|
+
writeThrift: () => new Uint8Array(),
|
|
29
|
+
readThrift: () => readThriftResult,
|
|
30
|
+
rename_data: () => {},
|
|
31
|
+
},
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return new RequestClient(stubClient as never)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
describe('RequestClient.requestCore error handling', () => {
|
|
38
|
+
it('throws a clean RequestError when hasError is set but no exception struct is present', async () => {
|
|
39
|
+
// given: an error response with an empty success slot and no exception struct
|
|
40
|
+
const client = createClient({ data: { 0: undefined, someField: 1 } })
|
|
41
|
+
|
|
42
|
+
// when / then: the error branch must throw InternalError, not a TypeError
|
|
43
|
+
let thrown: unknown
|
|
44
|
+
try {
|
|
45
|
+
await client.requestCore('/S3', [], 'testMethod', 3)
|
|
46
|
+
} catch (error) {
|
|
47
|
+
thrown = error
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
expect(thrown).toBeInstanceOf(InternalError)
|
|
51
|
+
expect((thrown as InternalError).type).toBe('RequestError')
|
|
52
|
+
expect(thrown).not.toBeInstanceOf(TypeError)
|
|
53
|
+
})
|
|
54
|
+
})
|