@zhin.js/adapter-milky 3.0.1 → 4.0.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.
Files changed (89) hide show
  1. package/CHANGELOG.md +443 -0
  2. package/README.md +36 -117
  3. package/adapters/milky.ts +68 -0
  4. package/lib/endpoint.d.ts +7 -0
  5. package/lib/endpoint.js +6 -0
  6. package/lib/index.d.ts +3 -20
  7. package/lib/index.js +3 -35
  8. package/lib/milky-agent-deps.d.ts +24 -0
  9. package/lib/milky-agent-deps.js +30 -0
  10. package/lib/milky-auth.d.ts +3 -0
  11. package/lib/milky-auth.js +30 -0
  12. package/lib/protocol.d.ts +162 -0
  13. package/lib/protocol.js +337 -0
  14. package/lib/sse-client.d.ts +20 -0
  15. package/lib/sse-client.js +85 -0
  16. package/lib/sse-endpoint.d.ts +50 -0
  17. package/lib/sse-endpoint.js +261 -0
  18. package/lib/webhook-endpoint.d.ts +40 -0
  19. package/lib/webhook-endpoint.js +212 -0
  20. package/lib/ws-endpoint.d.ts +42 -0
  21. package/lib/ws-endpoint.js +320 -0
  22. package/lib/ws-types.d.ts +11 -0
  23. package/lib/ws-types.js +1 -0
  24. package/lib/wss-endpoint.d.ts +40 -0
  25. package/lib/wss-endpoint.js +263 -0
  26. package/package.json +52 -19
  27. package/plugin.ts +8 -0
  28. package/schema.json +36 -0
  29. package/src/endpoint.ts +26 -0
  30. package/src/index.ts +59 -48
  31. package/src/milky-agent-deps.ts +53 -0
  32. package/src/milky-auth.ts +29 -0
  33. package/src/protocol.ts +491 -0
  34. package/src/sse-client.ts +106 -0
  35. package/src/sse-endpoint.ts +318 -0
  36. package/src/webhook-endpoint.ts +262 -0
  37. package/src/ws-endpoint.ts +373 -0
  38. package/src/ws-types.ts +12 -0
  39. package/src/wss-endpoint.ts +305 -0
  40. package/lib/adapter.d.ts +0 -37
  41. package/lib/adapter.d.ts.map +0 -1
  42. package/lib/adapter.js +0 -99
  43. package/lib/adapter.js.map +0 -1
  44. package/lib/api.d.ts +0 -10
  45. package/lib/api.d.ts.map +0 -1
  46. package/lib/api.js +0 -48
  47. package/lib/api.js.map +0 -1
  48. package/lib/endpoint-sse.d.ts +0 -31
  49. package/lib/endpoint-sse.d.ts.map +0 -1
  50. package/lib/endpoint-sse.js +0 -197
  51. package/lib/endpoint-sse.js.map +0 -1
  52. package/lib/endpoint-webhook.d.ts +0 -34
  53. package/lib/endpoint-webhook.d.ts.map +0 -1
  54. package/lib/endpoint-webhook.js +0 -189
  55. package/lib/endpoint-webhook.js.map +0 -1
  56. package/lib/endpoint-ws.d.ts +0 -35
  57. package/lib/endpoint-ws.d.ts.map +0 -1
  58. package/lib/endpoint-ws.js +0 -264
  59. package/lib/endpoint-ws.js.map +0 -1
  60. package/lib/endpoint-wss.d.ts +0 -34
  61. package/lib/endpoint-wss.d.ts.map +0 -1
  62. package/lib/endpoint-wss.js +0 -227
  63. package/lib/endpoint-wss.js.map +0 -1
  64. package/lib/index.d.ts.map +0 -1
  65. package/lib/index.js.map +0 -1
  66. package/lib/segment-mapper.d.ts +0 -2
  67. package/lib/segment-mapper.d.ts.map +0 -1
  68. package/lib/segment-mapper.js +0 -2
  69. package/lib/segment-mapper.js.map +0 -1
  70. package/lib/types.d.ts +0 -75
  71. package/lib/types.d.ts.map +0 -1
  72. package/lib/types.js +0 -5
  73. package/lib/types.js.map +0 -1
  74. package/lib/utils.d.ts +0 -35
  75. package/lib/utils.d.ts.map +0 -1
  76. package/lib/utils.js +0 -166
  77. package/lib/utils.js.map +0 -1
  78. package/plugin.yml +0 -3
  79. package/src/adapter.ts +0 -111
  80. package/src/api.ts +0 -63
  81. package/src/endpoint-sse.ts +0 -232
  82. package/src/endpoint-webhook.ts +0 -225
  83. package/src/endpoint-ws.ts +0 -300
  84. package/src/endpoint-wss.ts +0 -272
  85. package/src/segment-mapper.ts +0 -1
  86. package/src/types.ts +0 -73
  87. package/src/utils.ts +0 -182
  88. /package/{skills/milky → agent}/PERMITS.md +0 -0
  89. /package/{skills/milky/SKILL.md → agent/skills/milky.md} +0 -0
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@zhin.js/adapter-milky",
3
- "version": "3.0.1",
4
- "description": "Zhin.js adapter for Milky protocol",
3
+ "version": "4.0.1",
4
+ "description": "Zhin.js Milky adapter for Plugin Runtime (WebSocket client)",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
7
7
  "types": "./lib/index.d.ts",
@@ -13,13 +13,14 @@
13
13
  }
14
14
  },
15
15
  "files": [
16
+ "adapters",
17
+ "plugin.ts",
18
+ "schema.json",
16
19
  "src",
17
20
  "lib",
18
- "client",
19
- "dist",
20
- "skills",
21
- "plugin.yml",
22
- "README.md"
21
+ "agent",
22
+ "README.md",
23
+ "CHANGELOG.md"
23
24
  ],
24
25
  "keywords": [
25
26
  "zhin",
@@ -37,25 +38,38 @@
37
38
  "directory": "plugins/adapters/milky"
38
39
  },
39
40
  "dependencies": {
40
- "eventsource": "^2.0.2",
41
- "ws": "^8.21.0"
41
+ "ws": "^8.21.0",
42
+ "@zhin.js/adapter": "1.0.1",
43
+ "@zhin.js/core": "1.3.5",
44
+ "@zhin.js/host-http": "1.0.1",
45
+ "@zhin.js/logger": "1.0.75",
46
+ "@zhin.js/plugin-runtime": "1.0.1"
42
47
  },
43
48
  "devDependencies": {
44
- "@types/eventsource": "^1.1.15",
45
49
  "@types/node": "^26.1.0",
46
50
  "@types/ws": "^8.18.1",
47
51
  "typescript": "^6.0.3",
48
- "@zhin.js/cli": "1.0.92",
49
- "@zhin.js/client": "2.0.4",
50
- "@zhin.js/host-router": "2.0.2",
51
- "zhin.js": "4.1.1"
52
+ "vitest": "^4.1.10",
53
+ "zod": "^4.4.3",
54
+ "@zhin.js/agent": "1.0.4",
55
+ "@zhin.js/host-http": "1.0.1"
52
56
  },
53
57
  "peerDependencies": {
54
- "@zhin.js/host-router": "2.0.2",
55
- "zhin.js": "4.1.1"
58
+ "zod": "^4.0.0",
59
+ "@zhin.js/adapter": "1.0.1",
60
+ "@zhin.js/core": "1.3.5",
61
+ "@zhin.js/plugin-runtime": "1.0.1",
62
+ "zhin.js": "4.1.3",
63
+ "@zhin.js/agent": "1.0.4"
56
64
  },
57
65
  "peerDependenciesMeta": {
58
- "@zhin.js/host-router": {
66
+ "zhin.js": {
67
+ "optional": true
68
+ },
69
+ "@zhin.js/agent": {
70
+ "optional": true
71
+ },
72
+ "zod": {
59
73
  "optional": true
60
74
  }
61
75
  },
@@ -64,11 +78,30 @@
64
78
  "email": "admin@liucl.cn",
65
79
  "url": "https://github.com/lc-cn"
66
80
  },
81
+ "publishConfig": {
82
+ "access": "public",
83
+ "registry": "https://registry.npmjs.org"
84
+ },
67
85
  "engines": {
68
86
  "node": "^20.19.0 || >=22.12.0"
69
87
  },
88
+ "zhin": {
89
+ "protocol": 1,
90
+ "type": "plugin",
91
+ "entry": "./plugin.ts",
92
+ "engine": "^1.0.0",
93
+ "runtime": "trusted",
94
+ "features": [
95
+ {
96
+ "package": "@zhin.js/adapter",
97
+ "api": "^1.0.0"
98
+ }
99
+ ],
100
+ "plugins": []
101
+ },
70
102
  "scripts": {
71
- "build": "zhin build",
72
- "clean": "rimraf lib"
103
+ "build": "tsc",
104
+ "clean": "rimraf lib",
105
+ "test": "NODE_OPTIONS=--experimental-strip-types vitest run --root ../../.. plugins/adapters/milky/tests"
73
106
  }
74
107
  }
package/plugin.ts ADDED
@@ -0,0 +1,8 @@
1
+ import { definePlugin } from '@zhin.js/plugin-runtime';
2
+
3
+ export default definePlugin({
4
+ name: 'milky',
5
+ metadata: {
6
+ displayName: 'Milky Adapter',
7
+ },
8
+ });
package/schema.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "type": "object",
4
+ "additionalProperties": false,
5
+ "properties": {
6
+ "connection": {
7
+ "type": "string",
8
+ "enum": ["ws", "sse", "webhook", "wss"],
9
+ "default": "ws",
10
+ "description": "ws (default), sse (EventSource client), webhook or wss (webhook/wss via httpHostToken)"
11
+ },
12
+ "name": {
13
+ "type": "string",
14
+ "default": "milky-bot"
15
+ },
16
+ "baseUrl": {
17
+ "type": "string",
18
+ "description": "Milky HTTP API base URL (required); WS event path is derived as ws(s)://host/event"
19
+ },
20
+ "path": {
21
+ "type": "string",
22
+ "description": "Path for webhook / reverse-wss"
23
+ },
24
+ "access_token": {
25
+ "type": "string"
26
+ },
27
+ "reconnect_interval": {
28
+ "type": "number",
29
+ "default": 5000
30
+ },
31
+ "heartbeat_interval": {
32
+ "type": "number",
33
+ "default": 30000
34
+ }
35
+ }
36
+ }
@@ -0,0 +1,26 @@
1
+ export {
2
+ MilkyWsEndpoint,
3
+ type MilkyWsEndpointOptions,
4
+ } from './ws-endpoint.js';
5
+
6
+ export {
7
+ MilkyWebhookEndpoint,
8
+ type MilkyWebhookEndpointOptions,
9
+ } from './webhook-endpoint.js';
10
+
11
+ export {
12
+ MilkyWssEndpoint,
13
+ type MilkyWssEndpointOptions,
14
+ } from './wss-endpoint.js';
15
+
16
+ export {
17
+ MilkySseEndpoint,
18
+ type MilkySseEndpointOptions,
19
+ type CreateMilkySseStream,
20
+ } from './sse-endpoint.js';
21
+
22
+ export type { MilkyWsSocket, MilkyWsCreateOptions } from './ws-types.js';
23
+
24
+ export { verifyMilkyAccessToken, readRequestBody } from './milky-auth.js';
25
+
26
+ export { openSseStream, consumeSseBuffer } from './sse-client.js';
package/src/index.ts CHANGED
@@ -1,50 +1,61 @@
1
- /**
2
- * Milky 适配器入口:单一适配器,支持 WS/SSE/Webhook/反向 WS,依赖 router 注册
3
- */
4
- import { usePlugin, type Plugin, type Context, createSceneManagementTools, registerDefaultScenePlatformPermitChecker, type ToolFeature } from 'zhin.js';
5
- import type { Router } from '@zhin.js/host-router';
6
- import { MilkyAdapter } from './adapter.js';
7
- import type { ISceneManagement } from 'zhin.js';
1
+ export {
2
+ buildSendAction,
3
+ buildSseConnectOptions,
4
+ buildWsConnectOptions,
5
+ callApi,
6
+ extractInboundAudioUrl,
7
+ formatInboundContent,
8
+ formatInboundMessageId,
9
+ formatInboundTarget,
10
+ formatOutboundMessageId,
11
+ formatOutboundSegments,
12
+ isMentioned,
13
+ isMessageReceiveEvent,
14
+ parseMessageReceiveData,
15
+ parseMilkyMessageId,
16
+ parseSendTarget,
17
+ resolveMilkyConfig,
18
+ senderNickname,
19
+ type MilkyAdapterConfig,
20
+ type MilkyApiClientOptions,
21
+ type MilkyApiResponse,
22
+ type MilkyConfigBase,
23
+ type MilkyEndpointConfig,
24
+ type MilkyEvent,
25
+ type MilkyIncomingMessage,
26
+ type MilkyIncomingSegment,
27
+ type MilkyOutgoingSegment,
28
+ type MilkySseConfig,
29
+ type MilkyWebhookConfig,
30
+ type MilkyWireSegment,
31
+ type MilkyWsConfig,
32
+ type MilkyWssConfig,
33
+ type ParsedSendTarget,
34
+ type ResolvedMilkyConfig,
35
+ } from './protocol.js';
8
36
 
9
- export * from './types.js';
10
- export { callApi } from './api.js';
11
- export * from './utils.js';
12
- export { MilkyWsClient } from './endpoint-ws.js';
13
- export { MilkySseClient } from './endpoint-sse.js';
14
- export { MilkyWebhookEndpoint } from './endpoint-webhook.js';
15
- export { MilkyWssServer } from './endpoint-wss.js';
16
- export { MilkyAdapter, type MilkyBot } from './adapter.js';
37
+ export {
38
+ MilkySseEndpoint,
39
+ MilkyWebhookEndpoint,
40
+ MilkyWssEndpoint,
41
+ MilkyWsEndpoint,
42
+ consumeSseBuffer,
43
+ openSseStream,
44
+ readRequestBody,
45
+ verifyMilkyAccessToken,
46
+ type CreateMilkySseStream,
47
+ type MilkySseEndpointOptions,
48
+ type MilkyWebhookEndpointOptions,
49
+ type MilkyWssEndpointOptions,
50
+ type MilkyWsCreateOptions,
51
+ type MilkyWsEndpointOptions,
52
+ type MilkyWsSocket,
53
+ } from './endpoint.js';
17
54
 
18
- declare module 'zhin.js' {
19
- namespace Plugin {
20
- interface Contexts {
21
- router: import('@zhin.js/host-router').Router;
22
- }
23
- }
24
- interface Adapters {
25
- milky: MilkyAdapter;
26
- }
27
- }
28
-
29
- const plugin = usePlugin();
30
- const { provide, useContext } = plugin;
31
- provide({
32
- name: 'milky',
33
- description: 'Milky Adapter(WS 正向 / SSE / Webhook / 反向 WS)',
34
- mounted: async (p: Plugin) => {
35
- const adapter = new MilkyAdapter(p);
36
- await adapter.start();
37
- return adapter;
38
- },
39
- dispose: async (adapter: MilkyAdapter) => {
40
- await adapter.stop();
41
- },
42
- } as unknown as Context<'milky'>);
43
-
44
- useContext('tool', 'milky', (toolService: ToolFeature, milky: MilkyAdapter) => {
45
- const disposers: (() => void)[] = [];
46
- disposers.push(registerDefaultScenePlatformPermitChecker('milky'));
47
- const sceneTools = createSceneManagementTools(milky as unknown as ISceneManagement, 'milky');
48
- disposers.push(...sceneTools.map(t => toolService.addTool(t, plugin.name)));
49
- return () => disposers.forEach(d => d());
50
- });
55
+ export {
56
+ getMilkyAgentDeps,
57
+ registerMilkyAgentEndpoint,
58
+ setMilkyAgentDeps,
59
+ type MilkyAgentDeps,
60
+ type MilkyAgentEndpoint,
61
+ } from './milky-agent-deps.js';
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Agent tool deps for milky (scene management / callApi).
3
+ * Endpoints register themselves on start; tools look up by config name / endpoint id.
4
+ */
5
+
6
+ export interface MilkyAgentEndpoint {
7
+ callApi(action: string, params?: Record<string, unknown>): Promise<unknown>;
8
+ kickMember(groupId: number, userId: number, rejectAddRequest?: boolean): Promise<boolean>;
9
+ muteMember(groupId: number, userId: number, duration?: number): Promise<boolean>;
10
+ muteAll(groupId: number, enable?: boolean): Promise<boolean>;
11
+ setAdmin(groupId: number, userId: number, enable?: boolean): Promise<boolean>;
12
+ setCard(groupId: number, userId: number, card: string): Promise<boolean>;
13
+ setTitle(groupId: number, userId: number, title: string): Promise<boolean>;
14
+ setGroupName(groupId: number, name: string): Promise<boolean>;
15
+ getMemberList(groupId: number): Promise<unknown[]>;
16
+ getGroupInfo(groupId: number): Promise<unknown>;
17
+ recallMessage?(id: string): Promise<void>;
18
+ }
19
+
20
+ export interface MilkyAgentDeps {
21
+ getEndpoint: (endpointId: string) => MilkyAgentEndpoint;
22
+ }
23
+
24
+ const endpoints = new Map<string, MilkyAgentEndpoint>();
25
+ let override: MilkyAgentDeps | null = null;
26
+
27
+ export function registerMilkyAgentEndpoint(
28
+ endpointId: string,
29
+ endpoint: MilkyAgentEndpoint,
30
+ ): () => void {
31
+ endpoints.set(endpointId, endpoint);
32
+ return () => {
33
+ if (endpoints.get(endpointId) === endpoint) {
34
+ endpoints.delete(endpointId);
35
+ }
36
+ };
37
+ }
38
+
39
+ /** Optional override used by tests / transitional callers. Pass `null` to clear. */
40
+ export function setMilkyAgentDeps(deps: MilkyAgentDeps | null): void {
41
+ override = deps;
42
+ }
43
+
44
+ export function getMilkyAgentDeps(): MilkyAgentDeps {
45
+ if (override) return override;
46
+ return {
47
+ getEndpoint(endpointId: string): MilkyAgentEndpoint {
48
+ const registered = endpoints.get(endpointId);
49
+ if (!registered) throw new Error(`Endpoint ${endpointId} 不存在`);
50
+ return registered;
51
+ },
52
+ };
53
+ }
@@ -0,0 +1,29 @@
1
+ import type { IncomingMessage } from 'node:http';
2
+
3
+ export function verifyMilkyAccessToken(accessToken: string | undefined, request: IncomingMessage): boolean {
4
+ if (!accessToken) return true;
5
+ const auth = request.headers.authorization ?? '';
6
+ if (auth === `Bearer ${accessToken}`) return true;
7
+ try {
8
+ const url = new URL(request.url ?? '/', 'http://localhost');
9
+ if (url.searchParams.get('access_token') === accessToken) return true;
10
+ } catch {
11
+ /* ignore */
12
+ }
13
+ return false;
14
+ }
15
+
16
+ export async function readRequestBody(request: IncomingMessage): Promise<string> {
17
+ const chunks: Buffer[] = [];
18
+ let size = 0;
19
+ for await (const chunk of request) {
20
+ const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
21
+ size += buffer.length;
22
+ if (size > 1_048_576) {
23
+ request.destroy();
24
+ throw new Error('Request body exceeds 1MB');
25
+ }
26
+ chunks.push(buffer);
27
+ }
28
+ return Buffer.concat(chunks).toString('utf8');
29
+ }