@zhin.js/adapter-line 2.0.1 → 2.0.3

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 (45) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/README.md +50 -19
  3. package/adapters/line.ts +26 -0
  4. package/agent/tools/get_group_members.ts +24 -0
  5. package/agent/tools/get_profile.ts +24 -0
  6. package/lib/endpoint.d.ts +45 -37
  7. package/lib/endpoint.js +114 -506
  8. package/lib/index.d.ts +4 -15
  9. package/lib/index.js +4 -83
  10. package/lib/line-agent-deps.d.ts +24 -0
  11. package/lib/line-agent-deps.js +33 -0
  12. package/lib/protocol.d.ts +151 -0
  13. package/lib/protocol.js +212 -0
  14. package/lib/webhook.d.ts +13 -0
  15. package/lib/webhook.js +50 -0
  16. package/package.json +48 -21
  17. package/plugin.ts +8 -0
  18. package/schema.json +22 -0
  19. package/src/endpoint.ts +148 -554
  20. package/src/index.ts +53 -100
  21. package/src/line-agent-deps.ts +47 -0
  22. package/src/protocol.ts +384 -0
  23. package/src/webhook.ts +79 -0
  24. package/lib/adapter.d.ts +0 -17
  25. package/lib/adapter.d.ts.map +0 -1
  26. package/lib/adapter.js +0 -22
  27. package/lib/adapter.js.map +0 -1
  28. package/lib/endpoint.d.ts.map +0 -1
  29. package/lib/endpoint.js.map +0 -1
  30. package/lib/index.d.ts.map +0 -1
  31. package/lib/index.js.map +0 -1
  32. package/lib/segment-mapper.d.ts +0 -2
  33. package/lib/segment-mapper.d.ts.map +0 -1
  34. package/lib/segment-mapper.js +0 -2
  35. package/lib/segment-mapper.js.map +0 -1
  36. package/lib/types.d.ts +0 -112
  37. package/lib/types.d.ts.map +0 -1
  38. package/lib/types.js +0 -5
  39. package/lib/types.js.map +0 -1
  40. package/plugin.yml +0 -3
  41. package/src/adapter.ts +0 -29
  42. package/src/segment-mapper.ts +0 -1
  43. package/src/types.ts +0 -130
  44. /package/{skills/line → agent}/PERMITS.md +0 -0
  45. /package/{skills/line/SKILL.md → agent/skills/line.md} +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,51 @@
1
1
  # @zhin.js/adapter-line
2
2
 
3
+ ## 2.0.3
4
+
5
+ ### Patch Changes
6
+
7
+ - cc5c94d: 约定式插件运行时迁移(breaking):插件与适配器由 `usePlugin()` / `extends Adapter` 迁移为 `definePlugin` / `defineAdapter` + `plugin.ts` + 约定目录(`adapters/`、`commands/`、`components/`、`tools/` 等)。
8
+
9
+ - 新增约定式运行时包:`@zhin.js/plugin-runtime`、`@zhin.js/adapter`、`@zhin.js/runtime`、`@zhin.js/host-http`(首版 1.0.0 走 init-publish,不在本 changeset 内 bump)。
10
+ - 全部 20 个平台适配器改为约定式 `defineAdapter`,旧 `usePlugin` / `extends Adapter` / `segment-mapper` 生产入口已删除;onebot11 反向 WSS、onebot12 webhook/wss、milky sse/webhook/wss、satori webhook、kook webhook、qq webhook/middleware 等 slice 1 推迟的连接模式已补齐。
11
+ - 游戏 / 工具 / 服务插件同步迁移到约定目录结构。
12
+ - CLI 增加 plugin-runtime host installer(http/database/outbound/schedule/console 等)。
13
+
14
+ 后续加固(同批):
15
+
16
+ - CLI:`zhin runtime start --daemon`(pidfile/崩溃拉起/风暴保护),orphan watchdog 防僵尸进程;legacy `zhin dev` / `zhin start` 已移除(含 `zhin restart`),`zhin stop` 兼容新 daemon。
17
+ - 安全:builtin 工具统一走 `security/policy-facade.ts` 的 `runToolPolicies`(声明式策略表,deny 优先);审计日志 close flush + 背压队列;`splitCompoundCommand` 引号感知、`extractCommandName` 去引号堵绕过。
18
+ - 日志:Logger 双堆栈修复、本地时区、`getLogger` 挂树(`setLevel` 递归生效)、第三方库(log4js/discord)桥接、启动人读总结。
19
+ - 结构:`plugins/games/shared` 迁为 `packages/game-kit`(`@zhin.js/game-kit`);死目录 `plugins/adapters/common` 删除。
20
+ - 脚手架:`create-zhin-app` / `zhin new` / scaffold-wizard 生成物改为 Plugin Runtime 形态(minimal-bot 同构,新配置格式)。
21
+ - Console:endpoint.list 真实名称与 phase、schema:get-all 按 instanceKey 映射、db:\* 接 DatabaseHost。
22
+
23
+ 注:按仓库发布惯例(见 1bb345dd2),本次 breaking 迁移统一使用 patch,避免 zhin.js 5.0 级联。
24
+
25
+ - Updated dependencies [16ec4e8]
26
+ - Updated dependencies [cc5c94d]
27
+ - Updated dependencies [447f3e2]
28
+ - @zhin.js/core@1.3.5
29
+ - @zhin.js/agent@1.0.4
30
+ - @zhin.js/host-http@1.0.1
31
+ - zhin.js@4.1.3
32
+ - @zhin.js/logger@1.0.75
33
+ - @zhin.js/plugin-runtime@1.0.1
34
+ - @zhin.js/adapter@1.0.1
35
+
36
+ ## 2.0.2
37
+
38
+ ### Patch Changes
39
+
40
+ - 872c583: fix: 代码格式优化
41
+ - Updated dependencies [872c583]
42
+ - Updated dependencies [872c583]
43
+ - @zhin.js/agent@1.0.3
44
+ - @zhin.js/host-api@2.0.5
45
+ - @zhin.js/host-router@2.0.3
46
+ - @zhin.js/logger@1.0.74
47
+ - zhin.js@4.1.2
48
+
3
49
  ## 2.0.1
4
50
 
5
51
  ### Patch Changes
package/README.md CHANGED
@@ -1,13 +1,31 @@
1
1
  # @zhin.js/adapter-line
2
2
 
3
- Zhin.js 适配器 — LINE Messaging API (Webhook 模式)
3
+ Zhin.js LINE Messaging API 适配器(Plugin Runtime),通过 Runtime Host HTTP Webhook 收发消息。
4
4
 
5
5
  ## 功能
6
6
 
7
- - 接收并解析 LINE Webhook 事件(text、image、video、audio、file、location、sticker)
8
- - 支持私聊、群组、多人聊天(room)三种场景
9
- - Reply API / Push API 发送消息
10
- - HMAC-SHA256 签名验证
7
+ - Webhook 事件接收(`httpHostToken` POST + HMAC-SHA256 签名验证)
8
+ - 解析 text / image / video / audio / file / location / sticker
9
+ - 支持私聊、群组、多人聊天(room)
10
+ - Reply API(有 replyToken 时)/ Push API 发送
11
+ - 约定式 `defineAdapter` / `definePlugin`(无需 `usePlugin`)
12
+
13
+ ## 安装
14
+
15
+ ```bash
16
+ pnpm add @zhin.js/adapter-line
17
+ ```
18
+
19
+ ## Plugin Runtime
20
+
21
+ - `@zhin.js/adapter` — 约定式 `adapters/line.ts`(`defineAdapter`)
22
+ - `@zhin.js/core` — `messageGatewayToken` 入站/出站
23
+ - `@zhin.js/host-http` — `httpHostToken` 注册 Webhook 路由(**非** legacy host-router/Koa)
24
+ - `@zhin.js/plugin-runtime` — `plugin.ts`(`definePlugin`)
25
+ - 配置经插件 `schema.json` 落到 `plugins.<instanceKey>`
26
+
27
+ 入站:`gateway.receive({ adapter, target: channelId, content: text, sender, metadata })`
28
+ 出站:`send({ target, payload })` → Reply API(缓存 replyToken)或 Push API
11
29
 
12
30
  ## 前置条件
13
31
 
@@ -15,13 +33,16 @@ Zhin.js 适配器 — LINE Messaging API (Webhook 模式)
15
33
  2. 获取 **Channel Secret** 和 **Channel Access Token**
16
34
  3. 设置 Webhook URL 为 `https://your-domain/line/webhook`
17
35
  4. 在 Console 中启用 **Use webhooks** 并关闭 **Auto-reply messages**
36
+ 5. Runtime Host(`http`)须已 listen,Webhook 才可达
37
+
38
+ 必填字段:`channelSecret`、`channelAccessToken`。
18
39
 
19
40
  ## 最小配置
20
41
 
21
42
  ```yaml
22
- # zhin.config.yml
23
- adapters:
24
- - context: line
43
+ # zhin.config.yml(Plugin Runtime)
44
+ plugins:
45
+ line:
25
46
  name: my-line-bot
26
47
  channelSecret: ${LINE_CHANNEL_SECRET}
27
48
  channelAccessToken: ${LINE_CHANNEL_ACCESS_TOKEN}
@@ -29,6 +50,8 @@ adapters:
29
50
  apiBaseUrl: https://api.line.me # 可选,调试时可改为 LINE API 沙盒地址
30
51
  ```
31
52
 
53
+ 根插件 `zhin.plugins`(或项目图)需引用 `@zhin.js/adapter-line`(`instanceKey: line`)。
54
+
32
55
  ## 环境变量
33
56
 
34
57
  | 变量 | 说明 |
@@ -40,7 +63,7 @@ adapters:
40
63
 
41
64
  LINE 要求 Webhook URL 以 HTTPS 开头。常见方案:
42
65
 
43
- - **反向代理**:Nginx/Caddy 将 `https://your-domain/line/webhook` 转发到本地 zhIn 端口
66
+ - **反向代理**:Nginx/Caddy 将 `https://your-domain/line/webhook` 转发到本地 zhin 端口
44
67
  - **Cloudflare Tunnel**:`cloudflared tunnel --url http://localhost:端口`
45
68
  - **ngrok**:调试用 `ngrok http 端口`
46
69
 
@@ -48,15 +71,23 @@ LINE 要求 Webhook URL 以 HTTPS 开头。常见方案:
48
71
 
49
72
  ## 消息类型映射
50
73
 
51
- | LINE 类型 | Zhin.js Segment | 说明 |
52
- |-----------|----------------|------|
53
- | text | text | 纯文本 |
54
- | image | image | 图片(暂不支持二次获取) |
55
- | video | video | 视频 |
56
- | audio | audio | 音频 |
57
- | file | file | 文件 |
58
- | location | location | 位置信息 |
59
- | sticker | sticker | 贴纸 |
74
+ | LINE 类型 | 入站 content(文本摘要) | 出站 wire |
75
+ |-----------|--------------------------|-----------|
76
+ | text | 原文 | text |
77
+ | image | `[image]` | image(需 `url`) |
78
+ | video | `[video]` | video(需 `url`) |
79
+ | audio | `[audio]` | audio(需 `url`) |
80
+ | file | `[file: name]` | |
81
+ | location | address 或坐标 | location |
82
+ | sticker | `[sticker: pkg/id]` | sticker |
83
+
84
+ ## AI 工具
85
+
86
+ | 类别 | 路径 |
87
+ |------|------|
88
+ | Permit 词汇 | `agent/PERMITS.md` |
89
+ | 平台工具(2 个) | `agent/tools/`(`line_get_profile`、`line_get_group_members`) |
90
+ | 技能说明 | `agent/skills/line.md` |
60
91
 
61
92
  ## 已知限制
62
93
 
@@ -69,7 +100,7 @@ LINE 要求 Webhook URL 以 HTTPS 开头。常见方案:
69
100
 
70
101
  | 问题 | 排查方法 |
71
102
  |------|---------|
72
- | Webhook Verify 失败 | 检查 HTTPS 证书、域名解析、端口是否可达 |
103
+ | Webhook Verify 失败 | 检查 HTTPS 证书、域名解析、端口是否可达;确认 host-http 已 listen |
73
104
  | 签名验证 403 | 确认 Channel Secret 与 Console 一致 |
74
105
  | 发送 401 | 确认 Channel Access Token 未过期 |
75
106
  | 发送 400 | 检查消息格式是否符合 LINE API 规范 |
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Convention entry: discover `adapters/line.ts` → defineAdapter.
3
+ */
4
+ import { defineAdapter } from '@zhin.js/adapter';
5
+ import { messageGatewayToken } from '@zhin.js/core/runtime';
6
+ import { httpHostToken } from '@zhin.js/host-http';
7
+ import { LineEndpoint } from '../src/endpoint.js';
8
+ import {
9
+ resolveLineConfig,
10
+ type LineAdapterConfig,
11
+ } from '../src/protocol.js';
12
+
13
+ export { LineEndpoint } from '../src/endpoint.js';
14
+ export type { LineEndpointOptions, LineFetch } from '../src/endpoint.js';
15
+
16
+ export default defineAdapter<LineAdapterConfig>({
17
+ capabilities: ['inbound', 'outbound'],
18
+ create(context) {
19
+ return new LineEndpoint({
20
+ id: context.id,
21
+ gateway: context.use(messageGatewayToken),
22
+ http: context.use(httpHostToken),
23
+ config: resolveLineConfig(context.config),
24
+ });
25
+ },
26
+ });
@@ -0,0 +1,24 @@
1
+ import { defineAgentTool } from '@zhin.js/agent/tools';
2
+ import { z } from 'zod';
3
+ import { getLineApiConfig } from '../../src/line-agent-deps.js';
4
+
5
+ export default defineAgentTool<{ groupId: string }>({
6
+ description: 'Get LINE group member IDs',
7
+ inputSchema: z.object({
8
+ groupId: z.string().min(1),
9
+ }),
10
+ async execute({ groupId }) {
11
+ if (!groupId.startsWith('G')) {
12
+ throw new Error(`Invalid groupId "${groupId}": must start with G`);
13
+ }
14
+ const { accessToken, apiBaseUrl } = getLineApiConfig();
15
+ const response = await fetch(`${apiBaseUrl}/v2/bot/group/${groupId}/members/ids`, {
16
+ headers: { Authorization: `Bearer ${accessToken}` },
17
+ });
18
+ if (!response.ok) {
19
+ const errorText = await response.text();
20
+ throw new Error(`LINE Group Members API error ${response.status}: ${errorText}`);
21
+ }
22
+ return await response.json();
23
+ },
24
+ });
@@ -0,0 +1,24 @@
1
+ import { defineAgentTool } from '@zhin.js/agent/tools';
2
+ import { z } from 'zod';
3
+ import { getLineApiConfig } from '../../src/line-agent-deps.js';
4
+
5
+ export default defineAgentTool<{ userId: string }>({
6
+ description: 'Get LINE user profile by userId',
7
+ inputSchema: z.object({
8
+ userId: z.string().min(1),
9
+ }),
10
+ async execute({ userId }) {
11
+ if (!userId.startsWith('U')) {
12
+ throw new Error(`Invalid userId "${userId}": must start with U`);
13
+ }
14
+ const { accessToken, apiBaseUrl } = getLineApiConfig();
15
+ const response = await fetch(`${apiBaseUrl}/v2/profile/${userId}`, {
16
+ headers: { Authorization: `Bearer ${accessToken}` },
17
+ });
18
+ if (!response.ok) {
19
+ const errorText = await response.text();
20
+ throw new Error(`LINE Profile API error ${response.status}: ${errorText}`);
21
+ }
22
+ return await response.json();
23
+ },
24
+ });
package/lib/endpoint.d.ts CHANGED
@@ -1,38 +1,46 @@
1
- import { Endpoint, Message, SendOptions } from 'zhin.js';
2
- import { type Router } from "@zhin.js/host-router/router";
3
- import type { LineEndpointConfig, LineEvent } from "./types.js";
4
- import type { LineAdapter } from "./adapter.js";
5
- export declare class LineEndpoint implements Endpoint<LineEndpointConfig, LineEvent> {
6
- adapter: LineAdapter;
7
- private router;
8
- $config: LineEndpointConfig;
9
- $connected: boolean;
10
- get pluginLogger(): import("zhin.js").Logger;
11
- get $id(): string;
12
- constructor(adapter: LineAdapter, router: Router, $config: LineEndpointConfig);
13
- $connect(): Promise<void>;
14
- $disconnect(): Promise<void>;
15
- private handleWebhook;
16
- private verifySignature;
17
- private handleEvent;
18
- private handleMessageEvent;
19
- private handleFollowEvent;
20
- private handleJoinEvent;
21
- $formatMessage(event: LineEvent): Message<LineEvent>;
22
- private generateMessageId;
23
- private resolveChannel;
24
- private extractRawText;
25
- private parseMessageContent;
26
- $sendMessage(options: SendOptions): Promise<string>;
27
- private replyTokenCache;
28
- /**
29
- * 缓存 replyToken,用于后续发送回复消息
30
- */
31
- cacheReplyToken(channelId: string, replyToken: string): void;
32
- private replyMessage;
33
- private pushMessage;
34
- private buildLineMessages;
35
- private buildTextMessage;
36
- $recallMessage(_id: string): Promise<void>;
1
+ /**
2
+ * LineEndpoint lifecycle, outbound, admit, OpenAPI helpers for agent tools.
3
+ */
4
+ import type { EndpointInstance } from '@zhin.js/adapter';
5
+ import type { MessageGateway } from '@zhin.js/core/runtime';
6
+ import type { HttpHost } from '@zhin.js/host-http';
7
+ import type { CapabilityId } from '@zhin.js/plugin-runtime';
8
+ import { type LineEvent, type ResolvedLineConfig } from './protocol.js';
9
+ export type LineFetch = (url: string, init?: {
10
+ readonly method?: string;
11
+ readonly headers?: Record<string, string>;
12
+ readonly body?: string;
13
+ }) => Promise<{
14
+ readonly ok: boolean;
15
+ readonly status: number;
16
+ text(): Promise<string>;
17
+ json(): Promise<unknown>;
18
+ }>;
19
+ export interface LineEndpointOptions {
20
+ readonly id: CapabilityId;
21
+ readonly gateway: MessageGateway;
22
+ readonly http: HttpHost;
23
+ readonly config: ResolvedLineConfig;
24
+ readonly fetch?: LineFetch;
25
+ }
26
+ export declare class LineEndpoint implements EndpointInstance {
27
+ #private;
28
+ constructor(options: LineEndpointOptions);
29
+ /** Used by webhook handler. */
30
+ get isOpen(): boolean;
31
+ get config(): ResolvedLineConfig;
32
+ getApiConfig(): {
33
+ accessToken: string;
34
+ apiBaseUrl: string;
35
+ };
36
+ start(): Promise<void>;
37
+ open(): void;
38
+ close(): void;
39
+ stop(): Promise<void>;
40
+ send({ target, payload }: {
41
+ readonly target: string;
42
+ readonly payload: unknown;
43
+ }): Promise<string>;
44
+ /** Test / internal: admit a parsed event when open (non-webhook path). */
45
+ admit(event: LineEvent): void;
37
46
  }
38
- //# sourceMappingURL=endpoint.d.ts.map