@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/src/utils.ts DELETED
@@ -1,182 +0,0 @@
1
- /**
2
- * Milky 事件/消息段与 zhin Message 的转换
3
- */
4
- import type { MessageBase, SendContent } from 'zhin.js';
5
- import { Message, applyQqSenderRoleToMessageSender } from 'zhin.js';
6
- import type { MilkyEvent, MilkyIncomingMessage, MilkyIncomingSegment } from './types.js';
7
- import { toCanonicalSegments } from './segment-mapper.js';
8
-
9
- /** 将 Milky 接收消息段转为 zhin 的 $content(MessageSegment[]) */
10
- export function formatMilkySegments(segments: MilkyIncomingSegment[]): Array<{ type: string; data: Record<string, unknown> }> {
11
- return segments.map((seg) => {
12
- const type = seg.type;
13
- const data = seg.data ?? {};
14
- switch (type) {
15
- case 'text':
16
- return { type: 'text', data: { text: (data as { text?: string }).text ?? '' } };
17
- case 'mention':
18
- return { type: 'at', data: { id: String((data as { user_id?: number }).user_id ?? '') } };
19
- case 'mention_all':
20
- return { type: 'at', data: { type: 'all' } };
21
- case 'face':
22
- return { type: 'face', data: { id: (data as { face_id?: string }).face_id ?? '' } };
23
- case 'reply':
24
- return {
25
- type: 'reply',
26
- data: { message_seq: (data as { message_seq?: number }).message_seq },
27
- };
28
- case 'image':
29
- return {
30
- type: 'image',
31
- data: {
32
- url: (data as { temp_url?: string }).temp_url ?? (data as { resource_id?: string }).resource_id ?? '',
33
- },
34
- };
35
- case 'record':
36
- return {
37
- type: 'record',
38
- data: {
39
- url: (data as { temp_url?: string }).temp_url ?? (data as { resource_id?: string }).resource_id ?? '',
40
- },
41
- };
42
- case 'video':
43
- return {
44
- type: 'video',
45
- data: {
46
- url: (data as { temp_url?: string }).temp_url ?? (data as { resource_id?: string }).resource_id ?? '',
47
- },
48
- };
49
- case 'file':
50
- return {
51
- type: 'file',
52
- data: {
53
- file_id: (data as { file_id?: string }).file_id,
54
- name: (data as { file_name?: string }).file_name,
55
- },
56
- };
57
- default:
58
- return { type, data: data as Record<string, unknown> };
59
- }
60
- });
61
- }
62
-
63
- /** message_receive 事件的 data 转为 zhin Message 的构造参数(含 $adapter、$endpoint) */
64
- export function formatMilkyMessagePayload(
65
- event: MilkyEvent,
66
- data: MilkyIncomingMessage,
67
- recallFn: (msgId: string) => Promise<void>,
68
- replyFn: (channel: { id: string; type: 'group' | 'private' }, content: (string | { type: string; data?: Record<string, unknown> })[], quote?: boolean | string) => Promise<string>,
69
- adapterName: 'milky',
70
- endpointName: string,
71
- ): MessageBase {
72
- const scene = data.message_scene;
73
- const isGroup = scene === 'group';
74
- const channelId = data.peer_id.toString();
75
- const msgId = `${data.message_scene}:${data.peer_id}:${data.message_seq}`;
76
- const channel = { id: channelId, type: (isGroup ? 'group' : 'private') as 'group' | 'private' };
77
- const senderId = data.sender_id.toString();
78
- const senderName =
79
- (isGroup ? data.group_member?.card ?? data.group_member?.nickname : data.friend?.nickname) ?? senderId;
80
- const content = toCanonicalSegments(formatMilkySegments(data.segments));
81
- const raw = content.map((c) => (c.type === 'text' ? (c.data as { text?: string }).text : '')).join('');
82
-
83
- return {
84
- $id: msgId,
85
- $adapter: 'milky',
86
- $endpoint: endpointName,
87
- $channel: channel,
88
- $sender: (() => {
89
- const sender: { id: string; name: string; role?: string; permissions?: string[] } = {
90
- id: senderId,
91
- name: senderName,
92
- };
93
- applyQqSenderRoleToMessageSender(sender, data.group_member?.role);
94
- return sender;
95
- })(),
96
- $content: content,
97
- $raw: raw,
98
- $timestamp: data.time,
99
- $recall: () => recallFn(msgId),
100
- $reply: (cnt: SendContent, quote?: boolean | string) =>
101
- replyFn(channel, (Array.isArray(cnt) ? cnt : [cnt]) as (string | { type: string; data?: Record<string, unknown> })[], quote),
102
- };
103
- }
104
-
105
- /** 根据 event_type 判断是否为 message_receive,并解析 data 为 MilkyIncomingMessage */
106
- export function parseMessageReceiveData(event: MilkyEvent): MilkyIncomingMessage | null {
107
- if (event.event_type !== 'message_receive' || !event.data) return null;
108
- const data = event.data as unknown as MilkyIncomingMessage;
109
- if (!data.message_scene || !Number.isInteger(data.peer_id) || !Array.isArray(data.segments)) return null;
110
- return data;
111
- }
112
-
113
- /** zhin SendContent(string | MessageElement 或数组)转为 Milky OutgoingSegment[](发送用) */
114
- export function toMilkyOutgoingSegments(
115
- content: (string | { type: string; data?: Record<string, unknown> })[],
116
- ): Array<{ type: string; data: Record<string, unknown> }> {
117
- const out: Array<{ type: string; data: Record<string, unknown> }> = [];
118
- for (const seg of content) {
119
- const type = typeof seg === 'string' ? 'text' : seg.type;
120
- const data = typeof seg === 'string' ? { text: seg } : (seg.data ?? {});
121
- switch (type) {
122
- case 'text':
123
- out.push({ type: 'text', data: { text: String((data as { text?: string }).text ?? '') } });
124
- break;
125
- case 'at':
126
- if ((data as { type?: string }).type === 'all') {
127
- out.push({ type: 'mention_all', data: {} });
128
- } else {
129
- const id = (data as { id?: string }).id;
130
- if (id) out.push({ type: 'mention', data: { user_id: Number(id) || 0 } });
131
- }
132
- break;
133
- case 'face':
134
- out.push({ type: 'face', data: { face_id: String((data as { id?: string }).id ?? ''), is_large: false } });
135
- break;
136
- case 'reply':
137
- // message_id 可能为 scene:peer:seq 或仅 message_seq
138
- const mid = (data as { message_id?: string; message_seq?: number }).message_id ?? (data as { message_seq?: number }).message_seq;
139
- const seq = typeof mid === 'number' ? mid : parseInt(String(mid).split(':').pop() ?? '0', 10);
140
- out.push({ type: 'reply', data: { message_seq: seq } });
141
- break;
142
- case 'image':
143
- out.push({
144
- type: 'image',
145
- data: { uri: String((data as { url?: string }).url ?? (data as { uri?: string }).uri ?? '') },
146
- });
147
- break;
148
- case 'record':
149
- out.push({
150
- type: 'record',
151
- data: { uri: String((data as { url?: string }).url ?? (data as { uri?: string }).uri ?? '') },
152
- });
153
- break;
154
- case 'video':
155
- out.push({
156
- type: 'video',
157
- data: {
158
- uri: String((data as { url?: string }).url ?? (data as { uri?: string }).uri ?? ''),
159
- thumb_uri: (data as { thumb_uri?: string }).thumb_uri,
160
- },
161
- });
162
- break;
163
- default:
164
- out.push({ type, data: data as Record<string, unknown> });
165
- }
166
- }
167
- return out;
168
- }
169
-
170
- /** 解析 $id 为 message_scene、peer_id、message_seq(用于撤回) */
171
- export function parseMilkyMessageId(
172
- msgId: string,
173
- ): { message_scene: 'friend' | 'group' | 'temp'; peer_id: number; message_seq: number } | null {
174
- const parts = msgId.split(':');
175
- if (parts.length < 3) return null;
176
- const [scene, peer, seq] = parts;
177
- if (scene !== 'friend' && scene !== 'group' && scene !== 'temp') return null;
178
- const peerId = parseInt(peer, 10);
179
- const messageSeq = parseInt(seq, 10);
180
- if (Number.isNaN(peerId) || Number.isNaN(messageSeq)) return null;
181
- return { message_scene: scene, peer_id: peerId, message_seq: messageSeq };
182
- }
File without changes