@openclaw/line 2026.6.11 → 2026.7.1-beta.2

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.
@@ -1,4 +1,4 @@
1
- import { n as createEventCard, t as createAgendaCard } from "./schedule-cards-Bq74H30B.js";
1
+ import { i as createMediaPlayerCard, l as createAgendaCard, n as createAppleTvRemoteCard, r as createDeviceControlCard, u as createEventCard } from "./flex-templates-DPBtqQ8R.js";
2
2
  import { normalizeAccountId } from "openclaw/plugin-sdk/account-id";
3
3
  import { resolveAccountEntry } from "openclaw/plugin-sdk/account-resolution";
4
4
  import { normalizeLowercaseStringOrEmpty, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
@@ -197,405 +197,6 @@ function createLineSendReceipt(params) {
197
197
  });
198
198
  }
199
199
  //#endregion
200
- //#region extensions/line/src/flex-templates/media-control-cards.ts
201
- /**
202
- * Create a media player card for Sonos, Spotify, Apple Music, etc.
203
- *
204
- * Editorial design: Album art hero with gradient overlay for text,
205
- * prominent now-playing indicator, refined playback controls.
206
- */
207
- function createMediaPlayerCard(params) {
208
- const { title, subtitle, source, imageUrl, isPlaying, progress, controls, extraActions } = params;
209
- const trackInfo = [{
210
- type: "text",
211
- text: title,
212
- weight: "bold",
213
- size: "xl",
214
- color: "#111111",
215
- wrap: true
216
- }];
217
- if (subtitle) trackInfo.push({
218
- type: "text",
219
- text: subtitle,
220
- size: "md",
221
- color: "#666666",
222
- wrap: true,
223
- margin: "sm"
224
- });
225
- const statusItems = [];
226
- if (isPlaying !== void 0) statusItems.push({
227
- type: "box",
228
- layout: "horizontal",
229
- contents: [{
230
- type: "box",
231
- layout: "vertical",
232
- contents: [],
233
- width: "8px",
234
- height: "8px",
235
- backgroundColor: isPlaying ? "#06C755" : "#CCCCCC",
236
- cornerRadius: "4px"
237
- }, {
238
- type: "text",
239
- text: isPlaying ? "Now Playing" : "Paused",
240
- size: "xs",
241
- color: isPlaying ? "#06C755" : "#888888",
242
- weight: "bold",
243
- margin: "sm"
244
- }],
245
- alignItems: "center"
246
- });
247
- if (source) statusItems.push({
248
- type: "text",
249
- text: source,
250
- size: "xs",
251
- color: "#AAAAAA",
252
- margin: statusItems.length > 0 ? "lg" : void 0
253
- });
254
- if (progress) statusItems.push({
255
- type: "text",
256
- text: progress,
257
- size: "xs",
258
- color: "#888888",
259
- align: "end",
260
- flex: 1
261
- });
262
- const bodyContents = [{
263
- type: "box",
264
- layout: "vertical",
265
- contents: trackInfo
266
- }];
267
- if (statusItems.length > 0) bodyContents.push({
268
- type: "box",
269
- layout: "horizontal",
270
- contents: statusItems,
271
- margin: "lg",
272
- alignItems: "center"
273
- });
274
- const bubble = {
275
- type: "bubble",
276
- size: "mega",
277
- body: {
278
- type: "box",
279
- layout: "vertical",
280
- contents: bodyContents,
281
- paddingAll: "xl",
282
- backgroundColor: "#FFFFFF"
283
- }
284
- };
285
- if (imageUrl) bubble.hero = {
286
- type: "image",
287
- url: imageUrl,
288
- size: "full",
289
- aspectRatio: "1:1",
290
- aspectMode: "cover"
291
- };
292
- if (controls || extraActions?.length) {
293
- const footerContents = [];
294
- if (controls) {
295
- const controlButtons = [];
296
- if (controls.previous) controlButtons.push({
297
- type: "button",
298
- action: {
299
- type: "postback",
300
- label: "⏮",
301
- data: controls.previous.data
302
- },
303
- style: "secondary",
304
- flex: 1,
305
- height: "sm"
306
- });
307
- if (controls.play) controlButtons.push({
308
- type: "button",
309
- action: {
310
- type: "postback",
311
- label: "▶",
312
- data: controls.play.data
313
- },
314
- style: isPlaying ? "secondary" : "primary",
315
- flex: 1,
316
- height: "sm",
317
- margin: controls.previous ? "md" : void 0
318
- });
319
- if (controls.pause) controlButtons.push({
320
- type: "button",
321
- action: {
322
- type: "postback",
323
- label: "⏸",
324
- data: controls.pause.data
325
- },
326
- style: isPlaying ? "primary" : "secondary",
327
- flex: 1,
328
- height: "sm",
329
- margin: controlButtons.length > 0 ? "md" : void 0
330
- });
331
- if (controls.next) controlButtons.push({
332
- type: "button",
333
- action: {
334
- type: "postback",
335
- label: "⏭",
336
- data: controls.next.data
337
- },
338
- style: "secondary",
339
- flex: 1,
340
- height: "sm",
341
- margin: controlButtons.length > 0 ? "md" : void 0
342
- });
343
- if (controlButtons.length > 0) footerContents.push({
344
- type: "box",
345
- layout: "horizontal",
346
- contents: controlButtons
347
- });
348
- }
349
- if (extraActions?.length) footerContents.push({
350
- type: "box",
351
- layout: "horizontal",
352
- contents: extraActions.slice(0, 2).map((action, index) => ({
353
- type: "button",
354
- action: {
355
- type: "postback",
356
- label: action.label.slice(0, 15),
357
- data: action.data
358
- },
359
- style: "secondary",
360
- flex: 1,
361
- height: "sm",
362
- margin: index > 0 ? "md" : void 0
363
- })),
364
- margin: "md"
365
- });
366
- if (footerContents.length > 0) bubble.footer = {
367
- type: "box",
368
- layout: "vertical",
369
- contents: footerContents,
370
- paddingAll: "lg",
371
- backgroundColor: "#FAFAFA"
372
- };
373
- }
374
- return bubble;
375
- }
376
- /**
377
- * Create an Apple TV remote card with a D-pad and control rows.
378
- */
379
- function createAppleTvRemoteCard(params) {
380
- const { deviceName, status, actionData } = params;
381
- const headerContents = [{
382
- type: "text",
383
- text: deviceName,
384
- weight: "bold",
385
- size: "xl",
386
- color: "#111111",
387
- wrap: true
388
- }];
389
- if (status) headerContents.push({
390
- type: "text",
391
- text: status,
392
- size: "sm",
393
- color: "#666666",
394
- wrap: true,
395
- margin: "sm"
396
- });
397
- const makeButton = (label, data, style = "secondary") => ({
398
- type: "button",
399
- action: {
400
- type: "postback",
401
- label,
402
- data
403
- },
404
- style,
405
- height: "sm",
406
- flex: 1
407
- });
408
- const dpadRows = [
409
- {
410
- type: "box",
411
- layout: "horizontal",
412
- contents: [
413
- { type: "filler" },
414
- makeButton("↑", actionData.up),
415
- { type: "filler" }
416
- ]
417
- },
418
- {
419
- type: "box",
420
- layout: "horizontal",
421
- contents: [
422
- makeButton("←", actionData.left),
423
- makeButton("OK", actionData.select, "primary"),
424
- makeButton("→", actionData.right)
425
- ],
426
- margin: "md"
427
- },
428
- {
429
- type: "box",
430
- layout: "horizontal",
431
- contents: [
432
- { type: "filler" },
433
- makeButton("↓", actionData.down),
434
- { type: "filler" }
435
- ],
436
- margin: "md"
437
- }
438
- ];
439
- const menuRow = {
440
- type: "box",
441
- layout: "horizontal",
442
- contents: [makeButton("Menu", actionData.menu), makeButton("Home", actionData.home)],
443
- margin: "lg"
444
- };
445
- const playbackRow = {
446
- type: "box",
447
- layout: "horizontal",
448
- contents: [makeButton("Play", actionData.play), makeButton("Pause", actionData.pause)],
449
- margin: "md"
450
- };
451
- const volumeRow = {
452
- type: "box",
453
- layout: "horizontal",
454
- contents: [
455
- makeButton("Vol +", actionData.volumeUp),
456
- makeButton("Mute", actionData.mute),
457
- makeButton("Vol -", actionData.volumeDown)
458
- ],
459
- margin: "md"
460
- };
461
- return {
462
- type: "bubble",
463
- size: "mega",
464
- body: {
465
- type: "box",
466
- layout: "vertical",
467
- contents: [
468
- {
469
- type: "box",
470
- layout: "vertical",
471
- contents: headerContents
472
- },
473
- {
474
- type: "separator",
475
- margin: "lg",
476
- color: "#EEEEEE"
477
- },
478
- ...dpadRows,
479
- menuRow,
480
- playbackRow,
481
- volumeRow
482
- ],
483
- paddingAll: "xl",
484
- backgroundColor: "#FFFFFF"
485
- }
486
- };
487
- }
488
- /**
489
- * Create a device control card for Apple TV, smart home devices, etc.
490
- *
491
- * Editorial design: Device-focused header with status indicator,
492
- * clean control grid with clear visual hierarchy.
493
- */
494
- function createDeviceControlCard(params) {
495
- const { deviceName, deviceType, status, isOnline, imageUrl, controls } = params;
496
- const headerContents = [{
497
- type: "box",
498
- layout: "horizontal",
499
- contents: [{
500
- type: "box",
501
- layout: "vertical",
502
- contents: [],
503
- width: "10px",
504
- height: "10px",
505
- backgroundColor: isOnline !== false ? "#06C755" : "#FF5555",
506
- cornerRadius: "5px"
507
- }, {
508
- type: "text",
509
- text: deviceName,
510
- weight: "bold",
511
- size: "xl",
512
- color: "#111111",
513
- wrap: true,
514
- flex: 1,
515
- margin: "md"
516
- }],
517
- alignItems: "center"
518
- }];
519
- if (deviceType) headerContents.push({
520
- type: "text",
521
- text: deviceType,
522
- size: "sm",
523
- color: "#888888",
524
- margin: "sm"
525
- });
526
- if (status) headerContents.push({
527
- type: "box",
528
- layout: "vertical",
529
- contents: [{
530
- type: "text",
531
- text: status,
532
- size: "sm",
533
- color: "#444444",
534
- wrap: true
535
- }],
536
- margin: "lg",
537
- paddingAll: "md",
538
- backgroundColor: "#F8F9FA",
539
- cornerRadius: "md"
540
- });
541
- const bubble = {
542
- type: "bubble",
543
- size: "mega",
544
- body: {
545
- type: "box",
546
- layout: "vertical",
547
- contents: headerContents,
548
- paddingAll: "xl",
549
- backgroundColor: "#FFFFFF"
550
- }
551
- };
552
- if (imageUrl) bubble.hero = {
553
- type: "image",
554
- url: imageUrl,
555
- size: "full",
556
- aspectRatio: "16:9",
557
- aspectMode: "cover"
558
- };
559
- if (controls.length > 0) {
560
- const rows = [];
561
- const limitedControls = controls.slice(0, 6);
562
- for (let i = 0; i < limitedControls.length; i += 2) {
563
- const rowButtons = [];
564
- for (let j = i; j < Math.min(i + 2, limitedControls.length); j++) {
565
- const ctrl = limitedControls[j];
566
- const buttonLabel = ctrl.icon ? `${ctrl.icon} ${ctrl.label}` : ctrl.label;
567
- rowButtons.push({
568
- type: "button",
569
- action: {
570
- type: "postback",
571
- label: buttonLabel.slice(0, 18),
572
- data: ctrl.data
573
- },
574
- style: ctrl.style ?? "secondary",
575
- flex: 1,
576
- height: "sm",
577
- margin: j > i ? "md" : void 0
578
- });
579
- }
580
- if (rowButtons.length === 1) rowButtons.push({ type: "filler" });
581
- rows.push({
582
- type: "box",
583
- layout: "horizontal",
584
- contents: rowButtons,
585
- margin: i > 0 ? "md" : void 0
586
- });
587
- }
588
- bubble.footer = {
589
- type: "box",
590
- layout: "vertical",
591
- contents: rows,
592
- paddingAll: "lg",
593
- backgroundColor: "#FAFAFA"
594
- };
595
- }
596
- return bubble;
597
- }
598
- //#endregion
599
200
  //#region extensions/line/src/reply-payload-transform.ts
600
201
  /**
601
202
  * Parse LINE-specific directives from text and extract them into ReplyPayload fields.
@@ -853,4 +454,4 @@ function hasLineDirectives(text) {
853
454
  return /\[\[(quick_replies|location|confirm|buttons|media_player|event|agenda|device|appletv_remote):/i.test(text);
854
455
  }
855
456
  //#endregion
856
- export { resolveLineGroupsConfig as _, createMediaPlayerCard as a, resolveLineOutboundMedia as c, setLineRuntime as d, LineChannelConfigSchema as f, resolveLineGroupLookupIds as g, resolveLineGroupConfigEntry as h, createDeviceControlCard as i, validateLineMediaUrl as l, resolveExactLineGroupConfigKey as m, parseLineDirectives as n, createLineSendReceipt as o, LineConfigSchema as p, createAppleTvRemoteCard as r, buildLineQuickReplyFallbackText as s, hasLineDirectives as t, getLineRuntime as u };
457
+ export { resolveLineOutboundMedia as a, setLineRuntime as c, resolveExactLineGroupConfigKey as d, resolveLineGroupConfigEntry as f, buildLineQuickReplyFallbackText as i, LineChannelConfigSchema as l, resolveLineGroupsConfig as m, parseLineDirectives as n, validateLineMediaUrl as o, resolveLineGroupLookupIds as p, createLineSendReceipt as r, getLineRuntime as s, hasLineDirectives as t, LineConfigSchema as u };
@@ -1,10 +1,9 @@
1
- import { i as resolveLineAccount, n as normalizeAccountId, r as resolveDefaultLineAccountId, t as listLineAccountIds } from "./accounts-B-K3yrdP.js";
2
- import { _ as resolveLineGroupsConfig, a as createMediaPlayerCard, d as setLineRuntime, f as LineChannelConfigSchema, g as resolveLineGroupLookupIds, h as resolveLineGroupConfigEntry, i as createDeviceControlCard, m as resolveExactLineGroupConfigKey, n as parseLineDirectives, p as LineConfigSchema, r as createAppleTvRemoteCard, t as hasLineDirectives } from "./reply-payload-transform-DZ8-37Ot.js";
3
- import { n as createEventCard, r as createReceiptCard, t as createAgendaCard } from "./schedule-cards-Bq74H30B.js";
4
- import { a as createListCard, i as createInfoCard, n as createCarousel, o as createNotificationBubble, r as createImageCard, t as createActionCard } from "./basic-cards-B1eTkw-f.js";
5
- import { A as buildTemplateMessageFromPayload, B as createYesNoConfirm, C as pushMessagesLine, D as sendMessageLine, E as replyMessageLine, F as createImageCarousel, G as toFlexMessage, H as messageAction, I as createImageCarouselColumn, L as createLinkMenu, M as createButtonTemplate, N as createCarouselColumn, O as showLoadingAnimation, P as createConfirmTemplate, R as createProductCarousel, S as pushMessageLine, T as pushTextMessageWithQuickReplies, U as postbackAction, V as datetimePickerAction, W as uriAction, _ as getUserDisplayName, a as extractLinks, b as pushImageMessage, c as processLineMessage, d as createFlexMessage, f as createImageMessage, g as createVideoMessage, h as createTextMessageWithQuickReplies, i as extractCodeBlocks, j as createButtonMenu, k as resolveLineChannelAccessToken, l as stripMarkdown, m as createQuickReplyItems, n as convertLinksToFlexBubble, o as extractMarkdownTables, p as createLocationMessage, r as convertTableToFlexBubble, s as hasMarkdownToConvert, t as convertCodeBlockToFlexBubble, u as createAudioMessage, v as getUserProfile, w as pushTemplateMessage, x as pushLocationMessage, y as pushFlexMessage, z as createTemplateCarousel } from "./markdown-to-line-juqp-iiY.js";
6
- import { a as validateLineSignature, c as normalizeAllowFrom, i as parseLineWebhookBody, n as createLineNodeWebhookHandler, o as downloadLineMedia, r as readLineWebhookRequestBody, s as firstDefined, t as monitorLineProvider } from "./monitor-CULIHcvR.js";
7
- import { t as probeLineBot } from "./probe-CqTNoMdZ.js";
1
+ import { i as resolveLineAccount, n as normalizeAccountId, r as resolveDefaultLineAccountId, t as listLineAccountIds } from "./accounts-DJVOv1JI.js";
2
+ import { c as setLineRuntime, d as resolveExactLineGroupConfigKey, f as resolveLineGroupConfigEntry, l as LineChannelConfigSchema, m as resolveLineGroupsConfig, n as parseLineDirectives, p as resolveLineGroupLookupIds, t as hasLineDirectives, u as LineConfigSchema } from "./reply-payload-transform-BwF-zq0G.js";
3
+ import { _ as createNotificationBubble, a as datetimePickerAction, c as uriAction, d as createReceiptCard, f as createActionCard, g as createListCard, h as createInfoCard, i as createMediaPlayerCard, l as createAgendaCard, m as createImageCard, n as createAppleTvRemoteCard, o as messageAction, p as createCarousel, r as createDeviceControlCard, s as postbackAction, t as toFlexMessage, u as createEventCard } from "./flex-templates-DPBtqQ8R.js";
4
+ import { a as validateLineSignature, c as normalizeAllowFrom, i as parseLineWebhookBody, n as createLineNodeWebhookHandler, o as downloadLineMedia, r as readLineWebhookRequestBody, s as firstDefined, t as monitorLineProvider } from "./monitor-DzkYuWhv.js";
5
+ import { t as probeLineBot } from "./probe-BslD77tJ.js";
6
+ import { A as buildTemplateMessageFromPayload, B as createYesNoConfirm, C as pushMessagesLine, D as sendMessageLine, E as replyMessageLine, F as createImageCarousel, I as createImageCarouselColumn, L as createLinkMenu, M as createButtonTemplate, N as createCarouselColumn, O as showLoadingAnimation, P as createConfirmTemplate, R as createProductCarousel, S as pushMessageLine, T as pushTextMessageWithQuickReplies, _ as getUserDisplayName, a as extractLinks, b as pushImageMessage, c as processLineMessage, d as createFlexMessage, f as createImageMessage, g as createVideoMessage, h as createTextMessageWithQuickReplies, i as extractCodeBlocks, j as createButtonMenu, k as resolveLineChannelAccessToken, l as stripMarkdown, m as createQuickReplyItems, n as convertLinksToFlexBubble, o as extractMarkdownTables, p as createLocationMessage, r as convertTableToFlexBubble, s as hasMarkdownToConvert, t as convertCodeBlockToFlexBubble, u as createAudioMessage, v as getUserProfile, w as pushTemplateMessage, x as pushLocationMessage, y as pushFlexMessage, z as createTemplateCarousel } from "./markdown-to-line-CFx7ME4o.js";
8
7
  import { clearAccountEntryFields } from "openclaw/plugin-sdk/core";
9
8
  import { buildChannelConfigSchema } from "openclaw/plugin-sdk/channel-config-schema";
10
9
  import { createMessageReceiveContext } from "openclaw/plugin-sdk/channel-outbound";
@@ -94,6 +93,7 @@ function startLineWebhook(options) {
94
93
  //#endregion
95
94
  //#region extensions/line/src/rich-menu.ts
96
95
  const USER_BATCH_SIZE = 500;
96
+ const graphemeSegmenter = new Intl.Segmenter(void 0, { granularity: "grapheme" });
97
97
  function getClient(opts) {
98
98
  const account = resolveLineAccount({
99
99
  cfg: opts.cfg,
@@ -115,13 +115,23 @@ function chunkUserIds(userIds) {
115
115
  for (let i = 0; i < userIds.length; i += USER_BATCH_SIZE) batches.push(userIds.slice(i, i + USER_BATCH_SIZE));
116
116
  return batches;
117
117
  }
118
+ function truncateGraphemes(input, maxLength) {
119
+ let result = "";
120
+ let count = 0;
121
+ for (const { segment } of graphemeSegmenter.segment(input)) {
122
+ if (count >= maxLength) break;
123
+ result += segment;
124
+ count += 1;
125
+ }
126
+ return result;
127
+ }
118
128
  async function createRichMenu(menu, opts) {
119
129
  const client = getClient(opts);
120
130
  const richMenuRequest = {
121
131
  size: menu.size,
122
132
  selected: menu.selected ?? false,
123
- name: menu.name.slice(0, 300),
124
- chatBarText: menu.chatBarText.slice(0, 14),
133
+ name: truncateGraphemes(menu.name, 300),
134
+ chatBarText: truncateGraphemes(menu.chatBarText, 14),
125
135
  areas: menu.areas
126
136
  };
127
137
  const response = await client.createRichMenu(richMenuRequest);
package/dist/setup-api.js CHANGED
@@ -1,2 +1,2 @@
1
- import { n as lineSetupAdapter, t as lineSetupWizard } from "./setup-surface-CvTRDCEq.js";
1
+ import { n as lineSetupAdapter, t as lineSetupWizard } from "./setup-surface-Bc36YSS3.js";
2
2
  export { lineSetupAdapter, lineSetupWizard };
@@ -1,4 +1,4 @@
1
- import { i as resolveLineAccount, n as normalizeAccountId, r as resolveDefaultLineAccountId, t as listLineAccountIds } from "./accounts-B-K3yrdP.js";
1
+ import { i as resolveLineAccount, n as normalizeAccountId, r as resolveDefaultLineAccountId, t as listLineAccountIds } from "./accounts-DJVOv1JI.js";
2
2
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
3
3
  import { DEFAULT_ACCOUNT_ID, createAllowFromSection, createSetupInputPresenceValidator, createSetupTranslator, createStandardChannelSetupStatus, formatDocsLink, mergeAllowFromEntries, setSetupChannelEnabled, splitSetupEntries } from "openclaw/plugin-sdk/setup";
4
4
  //#region extensions/line/src/account-helpers.ts
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "name": "@openclaw/line",
3
- "version": "2026.6.11",
3
+ "version": "2026.7.1-beta.2",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@openclaw/line",
9
- "version": "2026.6.11",
9
+ "version": "2026.7.1-beta.2",
10
10
  "dependencies": {
11
11
  "@line/bot-sdk": "11.0.1",
12
12
  "zod": "4.4.3"
13
13
  },
14
14
  "peerDependencies": {
15
- "openclaw": ">=2026.6.11"
15
+ "openclaw": ">=2026.7.1-beta.2"
16
16
  },
17
17
  "peerDependenciesMeta": {
18
18
  "openclaw": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/line",
3
- "version": "2026.6.11",
3
+ "version": "2026.7.1-beta.2",
4
4
  "description": "OpenClaw LINE channel plugin for LINE Bot API chats.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -12,7 +12,7 @@
12
12
  "zod": "4.4.3"
13
13
  },
14
14
  "peerDependencies": {
15
- "openclaw": ">=2026.6.11"
15
+ "openclaw": ">=2026.7.1-beta.2"
16
16
  },
17
17
  "peerDependenciesMeta": {
18
18
  "openclaw": {
@@ -42,10 +42,10 @@
42
42
  "minHostVersion": ">=2026.4.10"
43
43
  },
44
44
  "compat": {
45
- "pluginApi": ">=2026.6.11"
45
+ "pluginApi": ">=2026.7.1-beta.2"
46
46
  },
47
47
  "build": {
48
- "openclawVersion": "2026.6.11"
48
+ "openclawVersion": "2026.7.1-beta.2"
49
49
  },
50
50
  "release": {
51
51
  "publishToClawHub": true,