@elizaos/plugin-line 2.0.0-alpha.3 → 2.0.0-alpha.4

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 (61) hide show
  1. package/dist/accounts.d.ts +152 -0
  2. package/dist/accounts.d.ts.map +1 -0
  3. package/dist/accounts.js +258 -0
  4. package/dist/accounts.js.map +1 -0
  5. package/dist/actions/index.d.ts +7 -0
  6. package/dist/actions/index.d.ts.map +1 -0
  7. package/{src/actions/index.ts → dist/actions/index.js} +1 -1
  8. package/dist/actions/index.js.map +1 -0
  9. package/dist/actions/sendFlexMessage.d.ts +6 -0
  10. package/dist/actions/sendFlexMessage.d.ts.map +1 -0
  11. package/dist/actions/sendFlexMessage.js +178 -0
  12. package/dist/actions/sendFlexMessage.js.map +1 -0
  13. package/dist/actions/sendLocation.d.ts +6 -0
  14. package/dist/actions/sendLocation.d.ts.map +1 -0
  15. package/dist/actions/sendLocation.js +155 -0
  16. package/dist/actions/sendLocation.js.map +1 -0
  17. package/dist/actions/sendMessage.d.ts +6 -0
  18. package/dist/actions/sendMessage.d.ts.map +1 -0
  19. package/dist/actions/sendMessage.js +146 -0
  20. package/dist/actions/sendMessage.js.map +1 -0
  21. package/dist/index.d.ts +22 -0
  22. package/dist/index.d.ts.map +1 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/messaging.d.ts +142 -0
  25. package/dist/messaging.d.ts.map +1 -0
  26. package/dist/messaging.js +348 -0
  27. package/dist/messaging.js.map +1 -0
  28. package/dist/providers/chatContext.d.ts +6 -0
  29. package/dist/providers/chatContext.d.ts.map +1 -0
  30. package/dist/providers/chatContext.js +85 -0
  31. package/dist/providers/chatContext.js.map +1 -0
  32. package/dist/providers/index.d.ts +6 -0
  33. package/dist/providers/index.d.ts.map +1 -0
  34. package/{src/providers/index.ts → dist/providers/index.js} +1 -1
  35. package/dist/providers/index.js.map +1 -0
  36. package/dist/providers/userContext.d.ts +6 -0
  37. package/dist/providers/userContext.d.ts.map +1 -0
  38. package/dist/providers/userContext.js +70 -0
  39. package/dist/providers/userContext.js.map +1 -0
  40. package/dist/service.d.ts +102 -0
  41. package/dist/service.d.ts.map +1 -0
  42. package/dist/service.js +433 -0
  43. package/dist/service.js.map +1 -0
  44. package/dist/types.d.ts +279 -0
  45. package/dist/types.d.ts.map +1 -0
  46. package/dist/types.js +106 -0
  47. package/dist/types.js.map +1 -0
  48. package/package.json +21 -6
  49. package/__tests__/integration.test.ts +0 -782
  50. package/build.ts +0 -16
  51. package/src/accounts.ts +0 -462
  52. package/src/actions/sendFlexMessage.ts +0 -243
  53. package/src/actions/sendLocation.ts +0 -223
  54. package/src/actions/sendMessage.ts +0 -202
  55. package/src/index.ts +0 -123
  56. package/src/messaging.ts +0 -507
  57. package/src/providers/chatContext.ts +0 -110
  58. package/src/providers/userContext.ts +0 -99
  59. package/src/service.ts +0 -578
  60. package/src/types.ts +0 -417
  61. package/tsconfig.json +0 -22
package/src/service.ts DELETED
@@ -1,578 +0,0 @@
1
- /**
2
- * LINE service implementation for ElizaOS.
3
- */
4
-
5
- import type { EventPayload, IAgentRuntime } from "@elizaos/core";
6
- import { logger, Service } from "@elizaos/core";
7
- import {
8
- type FlexMessage,
9
- type LocationMessage,
10
- type Message,
11
- type MiddlewareConfig,
12
- messagingApi,
13
- middleware,
14
- type TemplateMessage,
15
- type WebhookEvent,
16
- } from "@line/bot-sdk";
17
- import {
18
- getChatTypeFromId,
19
- type ILineService,
20
- LINE_SERVICE_NAME,
21
- LineApiError,
22
- LineConfigurationError,
23
- LineEventTypes,
24
- type LineFlexMessage,
25
- type LineGroup,
26
- type LineLocationMessage,
27
- type LineMessage,
28
- type LineMessageSendOptions,
29
- type LineSendResult,
30
- type LineSettings,
31
- type LineTemplateMessage,
32
- type LineUser,
33
- MAX_LINE_BATCH_SIZE,
34
- splitMessageForLine,
35
- } from "./types.js";
36
-
37
- /**
38
- * LINE messaging service for ElizaOS agents.
39
- */
40
- export class LineService extends Service implements ILineService {
41
- static serviceType: string = LINE_SERVICE_NAME;
42
- capabilityDescription =
43
- "The agent is able to send and receive messages via LINE";
44
-
45
- private settings: LineSettings | null = null;
46
- private client: messagingApi.MessagingApiClient | null = null;
47
- private connected: boolean = false;
48
-
49
- constructor(runtime?: IAgentRuntime) {
50
- super(runtime);
51
- if (!runtime) return;
52
- this.settings = this.loadSettings();
53
- }
54
-
55
- /**
56
- * Start the LINE service.
57
- */
58
- static async start(runtime: IAgentRuntime): Promise<Service> {
59
- const service = new LineService(runtime);
60
- await service.initialize();
61
- return service;
62
- }
63
-
64
- /**
65
- * Initialize the service.
66
- */
67
- private async initialize(): Promise<void> {
68
- if (!this.runtime) return;
69
- logger.info("Starting LINE service...");
70
-
71
- // Load settings
72
- if (!this.settings) {
73
- this.settings = this.loadSettings();
74
- }
75
- this.validateSettings();
76
-
77
- // Initialize LINE client
78
- this.client = new messagingApi.MessagingApiClient({
79
- channelAccessToken: this.settings.channelAccessToken,
80
- });
81
-
82
- this.connected = true;
83
- logger.info("LINE service started");
84
-
85
- // Emit connection ready event
86
- if (this.runtime) {
87
- this.runtime.emitEvent([LineEventTypes.CONNECTION_READY], {
88
- runtime: this.runtime,
89
- source: "line",
90
- service: this,
91
- } as unknown as EventPayload);
92
- }
93
- }
94
-
95
- /**
96
- * Stop the LINE service.
97
- */
98
- async stop(): Promise<void> {
99
- logger.info("Stopping LINE service...");
100
- this.connected = false;
101
- this.client = null;
102
- this.settings = null;
103
- logger.info("LINE service stopped");
104
- }
105
-
106
- /**
107
- * Check if the service is connected.
108
- */
109
- isConnected(): boolean {
110
- return this.connected && this.client !== null;
111
- }
112
-
113
- /**
114
- * Get bot info.
115
- */
116
- async getBotInfo(): Promise<LineUser | null> {
117
- if (!this.client) {
118
- return null;
119
- }
120
-
121
- const info = await this.client.getBotInfo();
122
- return {
123
- userId: info.userId,
124
- displayName: info.displayName,
125
- pictureUrl: info.pictureUrl,
126
- };
127
- }
128
-
129
- /**
130
- * Send a text message.
131
- */
132
- async sendMessage(
133
- to: string,
134
- text: string,
135
- options?: LineMessageSendOptions,
136
- ): Promise<LineSendResult> {
137
- if (!this.client) {
138
- return { success: false, error: "Service not connected" };
139
- }
140
-
141
- const chunks = splitMessageForLine(text);
142
- const messages: Message[] = chunks.map((chunk) => ({
143
- type: "text" as const,
144
- text: chunk,
145
- }));
146
-
147
- // Add quick replies to last message if provided
148
- if (options?.quickReplyItems && messages.length > 0) {
149
- const lastIdx = messages.length - 1;
150
- // Cast to unknown first to avoid strict type checking with LINE SDK types
151
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
152
- (messages[lastIdx] as { quickReply?: unknown }).quickReply = {
153
- items: options.quickReplyItems,
154
- } as unknown;
155
- }
156
-
157
- return this.pushMessages(to, messages);
158
- }
159
-
160
- /**
161
- * Send multiple messages.
162
- */
163
- async sendMessages(
164
- to: string,
165
- messages: Array<{ type: string; [key: string]: unknown }>,
166
- ): Promise<LineSendResult> {
167
- return this.pushMessages(to, messages as Message[]);
168
- }
169
-
170
- /**
171
- * Send a flex message.
172
- */
173
- async sendFlexMessage(
174
- to: string,
175
- flex: LineFlexMessage,
176
- ): Promise<LineSendResult> {
177
- if (!this.client) {
178
- return { success: false, error: "Service not connected" };
179
- }
180
-
181
- const message: FlexMessage = {
182
- type: "flex",
183
- altText: flex.altText.slice(0, 400),
184
- contents: flex.contents as FlexMessage["contents"],
185
- };
186
-
187
- return this.pushMessages(to, [message]);
188
- }
189
-
190
- /**
191
- * Send a template message.
192
- */
193
- async sendTemplateMessage(
194
- to: string,
195
- template: LineTemplateMessage,
196
- ): Promise<LineSendResult> {
197
- if (!this.client) {
198
- return { success: false, error: "Service not connected" };
199
- }
200
-
201
- const message: TemplateMessage = {
202
- type: "template",
203
- altText: template.altText.slice(0, 400),
204
- template: template.template as TemplateMessage["template"],
205
- };
206
-
207
- return this.pushMessages(to, [message]);
208
- }
209
-
210
- /**
211
- * Send a location message.
212
- */
213
- async sendLocationMessage(
214
- to: string,
215
- location: LineLocationMessage,
216
- ): Promise<LineSendResult> {
217
- if (!this.client) {
218
- return { success: false, error: "Service not connected" };
219
- }
220
-
221
- const message: LocationMessage = {
222
- type: "location",
223
- title: location.title.slice(0, 100),
224
- address: location.address.slice(0, 100),
225
- latitude: location.latitude,
226
- longitude: location.longitude,
227
- };
228
-
229
- return this.pushMessages(to, [message]);
230
- }
231
-
232
- /**
233
- * Reply to a message using reply token.
234
- */
235
- async replyMessage(
236
- replyToken: string,
237
- messages: Array<{ type: string; [key: string]: unknown }>,
238
- ): Promise<LineSendResult> {
239
- if (!this.client) {
240
- return { success: false, error: "Service not connected" };
241
- }
242
-
243
- await this.client.replyMessage({
244
- replyToken,
245
- messages: messages.slice(
246
- 0,
247
- MAX_LINE_BATCH_SIZE,
248
- ) as unknown as messagingApi.Message[],
249
- });
250
-
251
- return {
252
- success: true,
253
- messageId: "reply",
254
- chatId: "reply",
255
- };
256
- }
257
-
258
- /**
259
- * Get user profile.
260
- */
261
- async getUserProfile(userId: string): Promise<LineUser | null> {
262
- if (!this.client) {
263
- return null;
264
- }
265
-
266
- const profile = await this.client.getProfile(userId);
267
- return {
268
- userId: profile.userId,
269
- displayName: profile.displayName,
270
- pictureUrl: profile.pictureUrl,
271
- statusMessage: profile.statusMessage,
272
- language: profile.language,
273
- };
274
- }
275
-
276
- /**
277
- * Get group info.
278
- */
279
- async getGroupInfo(groupId: string): Promise<LineGroup | null> {
280
- if (!this.client) {
281
- return null;
282
- }
283
-
284
- const chatType = getChatTypeFromId(groupId);
285
- if (chatType === "group") {
286
- const summary = await this.client.getGroupSummary(groupId);
287
- return {
288
- groupId: summary.groupId,
289
- groupName: summary.groupName,
290
- pictureUrl: summary.pictureUrl,
291
- type: "group",
292
- };
293
- } else if (chatType === "room") {
294
- // Rooms don't have summary, just return ID
295
- return {
296
- groupId,
297
- type: "room",
298
- };
299
- }
300
-
301
- return null;
302
- }
303
-
304
- /**
305
- * Leave a group or room.
306
- */
307
- async leaveChat(chatId: string, chatType: "group" | "room"): Promise<void> {
308
- if (!this.client) {
309
- throw new LineApiError("Service not connected");
310
- }
311
-
312
- if (chatType === "group") {
313
- await this.client.leaveGroup(chatId);
314
- } else {
315
- await this.client.leaveRoom(chatId);
316
- }
317
- }
318
-
319
- /**
320
- * Get the middleware config for webhook verification.
321
- */
322
- getMiddlewareConfig(): MiddlewareConfig {
323
- if (!this.settings) {
324
- throw new LineConfigurationError("Service not configured");
325
- }
326
-
327
- return {
328
- channelSecret: this.settings.channelSecret,
329
- };
330
- }
331
-
332
- /**
333
- * Create Express middleware for webhook handling.
334
- */
335
- createMiddleware(): ReturnType<typeof middleware> {
336
- return middleware(this.getMiddlewareConfig());
337
- }
338
-
339
- /**
340
- * Handle webhook events.
341
- */
342
- async handleWebhookEvents(events: WebhookEvent[]): Promise<void> {
343
- if (!this.runtime) {
344
- return;
345
- }
346
-
347
- for (const event of events) {
348
- await this.handleWebhookEvent(event);
349
- }
350
- }
351
-
352
- /**
353
- * Get current settings.
354
- */
355
- getSettings(): LineSettings | null {
356
- return this.settings;
357
- }
358
-
359
- // Private methods
360
-
361
- private loadSettings(): LineSettings {
362
- if (!this.runtime) {
363
- throw new LineConfigurationError("Runtime not initialized");
364
- }
365
-
366
- const getStringSetting = (key: string): string => {
367
- const value = this.runtime?.getSetting(key);
368
- return typeof value === "string" ? value : "";
369
- };
370
-
371
- const channelAccessToken =
372
- getStringSetting("LINE_CHANNEL_ACCESS_TOKEN") ||
373
- process.env.LINE_CHANNEL_ACCESS_TOKEN ||
374
- "";
375
-
376
- const channelSecret =
377
- getStringSetting("LINE_CHANNEL_SECRET") ||
378
- process.env.LINE_CHANNEL_SECRET ||
379
- "";
380
-
381
- const webhookPath =
382
- getStringSetting("LINE_WEBHOOK_PATH") ||
383
- process.env.LINE_WEBHOOK_PATH ||
384
- "/webhooks/line";
385
-
386
- const dmPolicyRaw =
387
- getStringSetting("LINE_DM_POLICY") ||
388
- process.env.LINE_DM_POLICY ||
389
- "pairing";
390
- const dmPolicy = dmPolicyRaw as LineSettings["dmPolicy"];
391
-
392
- const groupPolicyRaw =
393
- getStringSetting("LINE_GROUP_POLICY") ||
394
- process.env.LINE_GROUP_POLICY ||
395
- "allowlist";
396
- const groupPolicy = groupPolicyRaw as LineSettings["groupPolicy"];
397
-
398
- const allowFromRaw =
399
- getStringSetting("LINE_ALLOW_FROM") || process.env.LINE_ALLOW_FROM || "";
400
- const allowFrom = allowFromRaw
401
- .split(",")
402
- .map((s: string) => s.trim())
403
- .filter(Boolean);
404
-
405
- const enabledRaw =
406
- getStringSetting("LINE_ENABLED") || process.env.LINE_ENABLED || "true";
407
- const enabled = enabledRaw !== "false";
408
-
409
- return {
410
- channelAccessToken,
411
- channelSecret,
412
- webhookPath,
413
- dmPolicy,
414
- groupPolicy,
415
- allowFrom,
416
- enabled,
417
- };
418
- }
419
-
420
- private validateSettings(): void {
421
- if (!this.settings) {
422
- throw new LineConfigurationError("Settings not loaded");
423
- }
424
-
425
- if (!this.settings.channelAccessToken) {
426
- throw new LineConfigurationError(
427
- "LINE_CHANNEL_ACCESS_TOKEN is required",
428
- "LINE_CHANNEL_ACCESS_TOKEN",
429
- );
430
- }
431
-
432
- if (!this.settings.channelSecret) {
433
- throw new LineConfigurationError(
434
- "LINE_CHANNEL_SECRET is required",
435
- "LINE_CHANNEL_SECRET",
436
- );
437
- }
438
- }
439
-
440
- private async pushMessages(
441
- to: string,
442
- messages: Message[],
443
- ): Promise<LineSendResult> {
444
- if (!this.client) {
445
- return { success: false, error: "Service not connected" };
446
- }
447
-
448
- // Send in batches of 5
449
- for (let i = 0; i < messages.length; i += MAX_LINE_BATCH_SIZE) {
450
- const batch = messages.slice(i, i + MAX_LINE_BATCH_SIZE);
451
-
452
- await this.client.pushMessage({
453
- to,
454
- messages: batch as unknown as messagingApi.Message[],
455
- });
456
- }
457
-
458
- // Emit sent event
459
- if (this.runtime) {
460
- this.runtime.emitEvent(LineEventTypes.MESSAGE_SENT, {
461
- runtime: this.runtime,
462
- source: "line",
463
- to,
464
- messageCount: messages.length,
465
- } as unknown as EventPayload);
466
- }
467
-
468
- return {
469
- success: true,
470
- messageId: Date.now().toString(),
471
- chatId: to,
472
- };
473
- }
474
-
475
- private async handleWebhookEvent(event: WebhookEvent): Promise<void> {
476
- if (!this.runtime) {
477
- return;
478
- }
479
-
480
- switch (event.type) {
481
- case "message":
482
- await this.handleMessageEvent(event);
483
- break;
484
- case "follow":
485
- this.runtime.emitEvent([LineEventTypes.FOLLOW], {
486
- runtime: this.runtime,
487
- source: "line",
488
- userId: event.source.userId,
489
- timestamp: event.timestamp,
490
- } as unknown as EventPayload);
491
- break;
492
- case "unfollow":
493
- this.runtime.emitEvent([LineEventTypes.UNFOLLOW], {
494
- runtime: this.runtime,
495
- source: "line",
496
- userId: event.source.userId,
497
- timestamp: event.timestamp,
498
- } as unknown as EventPayload);
499
- break;
500
- case "join":
501
- this.runtime.emitEvent([LineEventTypes.JOIN_GROUP], {
502
- runtime: this.runtime,
503
- source: "line",
504
- groupId:
505
- event.source.type === "group"
506
- ? event.source.groupId
507
- : event.source.type === "room"
508
- ? event.source.roomId
509
- : undefined,
510
- type: event.source.type,
511
- timestamp: event.timestamp,
512
- } as unknown as EventPayload);
513
- break;
514
- case "leave":
515
- this.runtime.emitEvent([LineEventTypes.LEAVE_GROUP], {
516
- runtime: this.runtime,
517
- source: "line",
518
- groupId:
519
- event.source.type === "group"
520
- ? event.source.groupId
521
- : event.source.type === "room"
522
- ? event.source.roomId
523
- : undefined,
524
- type: event.source.type,
525
- timestamp: event.timestamp,
526
- } as unknown as EventPayload);
527
- break;
528
- case "postback":
529
- this.runtime.emitEvent([LineEventTypes.POSTBACK], {
530
- runtime: this.runtime,
531
- source: "line",
532
- userId: event.source.userId,
533
- data: event.postback.data,
534
- params: event.postback.params,
535
- timestamp: event.timestamp,
536
- } as unknown as EventPayload);
537
- break;
538
- }
539
- }
540
-
541
- private async handleMessageEvent(
542
- event: WebhookEvent & { type: "message" },
543
- ): Promise<void> {
544
- if (!this.runtime) {
545
- return;
546
- }
547
-
548
- const message: LineMessage = {
549
- id: event.message.id,
550
- type: event.message.type,
551
- userId: event.source.userId || "",
552
- timestamp: event.timestamp,
553
- replyToken: event.replyToken,
554
- };
555
-
556
- // Add text for text messages
557
- if (event.message.type === "text") {
558
- message.text = event.message.text;
559
- message.mention = event.message.mention;
560
- }
561
-
562
- // Add group/room ID if applicable
563
- if (event.source.type === "group") {
564
- message.groupId = event.source.groupId;
565
- } else if (event.source.type === "room") {
566
- message.roomId = event.source.roomId;
567
- }
568
-
569
- // Emit message received event
570
- this.runtime.emitEvent([LineEventTypes.MESSAGE_RECEIVED], {
571
- runtime: this.runtime,
572
- source: "line",
573
- message,
574
- lineSource: event.source,
575
- replyToken: event.replyToken,
576
- } as unknown as EventPayload);
577
- }
578
- }