@openclaw/line 2026.7.2-beta.2 → 2026.7.2-beta.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 (109) hide show
  1. package/dist/{accounts-DJVOv1JI.js → accounts-BUBOoW5Q.js} +95 -33
  2. package/dist/api.js +4 -3
  3. package/dist/basic-cards-Rb-Ow7LN.js +307 -0
  4. package/dist/{card-command-DQ-epsgt.js → card-command-Ch0TwcDW.js} +2 -1
  5. package/dist/{channel-BHR-GoJ0.js → channel-CNcv74n2.js} +22 -10
  6. package/dist/channel-plugin-api.js +1 -1
  7. package/dist/channel.runtime-BBCZvRa_.js +4 -0
  8. package/dist/contract-api.js +1 -1
  9. package/dist/{flex-templates-K1lS9i8L.js → flex-templates-KiKaVYgi.js} +1 -318
  10. package/dist/index.js +1 -1
  11. package/dist/{markdown-to-line-XceqeKRP.js → markdown-to-line-DWIdzBfy.js} +224 -220
  12. package/dist/{monitor-Db2rZsSX.js → monitor-BinAXvIY.js} +454 -288
  13. package/dist/monitor.runtime-DKj4FHkA.js +2 -0
  14. package/dist/outbound.runtime-DRyoVa81.js +2 -0
  15. package/dist/quick-reply-fallback-D86FwAfr.js +56 -0
  16. package/dist/{reply-payload-transform-r9sa-TYT.js → reply-payload-transform-d57WYHFm.js} +3 -164
  17. package/dist/runtime-api.js +10 -24
  18. package/dist/send-receipt-CY2ey8XH.js +107 -0
  19. package/dist/setup-api.js +1 -1
  20. package/dist/{setup-surface-B7W6pwn3.js → setup-surface-Bili5gWy.js} +64 -5
  21. package/node_modules/@line/bot-sdk/dist/cjs/manage-audience/model/audienceGroupCreateRoute.d.ts.map +1 -1
  22. package/node_modules/@line/bot-sdk/dist/cjs/manage-audience/model/audienceGroupFailedType.d.ts.map +1 -1
  23. package/node_modules/@line/bot-sdk/dist/cjs/manage-audience/model/audienceGroupJobFailedType.d.ts.map +1 -1
  24. package/node_modules/@line/bot-sdk/dist/cjs/manage-audience/model/audienceGroupJobStatus.d.ts.map +1 -1
  25. package/node_modules/@line/bot-sdk/dist/cjs/manage-audience/model/audienceGroupStatus.d.ts.map +1 -1
  26. package/node_modules/@line/bot-sdk/dist/cjs/messaging-api/model/flexBoxBorderWidth.d.ts.map +1 -1
  27. package/node_modules/@line/bot-sdk/dist/cjs/messaging-api/model/flexBoxCornerRadius.d.ts.map +1 -1
  28. package/node_modules/@line/bot-sdk/dist/cjs/messaging-api/model/flexBubble.d.ts.map +1 -1
  29. package/node_modules/@line/bot-sdk/dist/cjs/messaging-api/model/flexIconSize.d.ts.map +1 -1
  30. package/node_modules/@line/bot-sdk/dist/cjs/messaging-api/model/flexSpanSize.d.ts.map +1 -1
  31. package/node_modules/@line/bot-sdk/dist/cjs/messaging-api/model/flexTextFontSize.d.ts.map +1 -1
  32. package/node_modules/@line/bot-sdk/dist/cjs/messaging-api/model/numberOfMessagesResponse.d.ts.map +1 -1
  33. package/node_modules/@line/bot-sdk/dist/cjs/messaging-api/model/postbackAction.d.ts.map +1 -1
  34. package/node_modules/@line/bot-sdk/dist/cjs/messaging-api/model/subscriptionPeriodDemographic.d.ts.map +1 -1
  35. package/node_modules/@line/bot-sdk/dist/cjs/version.d.ts +1 -1
  36. package/node_modules/@line/bot-sdk/dist/cjs/version.js +1 -1
  37. package/node_modules/@line/bot-sdk/dist/cjs/webhook/model/event.d.ts +2 -1
  38. package/node_modules/@line/bot-sdk/dist/cjs/webhook/model/event.d.ts.map +1 -1
  39. package/node_modules/@line/bot-sdk/dist/cjs/webhook/model/messageEditedEvent.d.ts +24 -0
  40. package/node_modules/@line/bot-sdk/dist/cjs/webhook/model/messageEditedEvent.d.ts.map +1 -0
  41. package/node_modules/@line/bot-sdk/dist/cjs/webhook/model/messageEditedEvent.js +14 -0
  42. package/node_modules/@line/bot-sdk/dist/cjs/webhook/model/messageEditedEvent.js.map +1 -0
  43. package/node_modules/@line/bot-sdk/dist/cjs/webhook/model/models.d.ts +1 -0
  44. package/node_modules/@line/bot-sdk/dist/cjs/webhook/model/models.d.ts.map +1 -1
  45. package/node_modules/@line/bot-sdk/dist/cjs/webhook/model/models.js +1 -0
  46. package/node_modules/@line/bot-sdk/dist/cjs/webhook/model/models.js.map +1 -1
  47. package/node_modules/@line/bot-sdk/dist/manage-audience/model/audienceGroupCreateRoute.d.ts.map +1 -1
  48. package/node_modules/@line/bot-sdk/dist/manage-audience/model/audienceGroupFailedType.d.ts.map +1 -1
  49. package/node_modules/@line/bot-sdk/dist/manage-audience/model/audienceGroupJobFailedType.d.ts.map +1 -1
  50. package/node_modules/@line/bot-sdk/dist/manage-audience/model/audienceGroupJobStatus.d.ts.map +1 -1
  51. package/node_modules/@line/bot-sdk/dist/manage-audience/model/audienceGroupStatus.d.ts.map +1 -1
  52. package/node_modules/@line/bot-sdk/dist/messaging-api/model/flexBoxBorderWidth.d.ts.map +1 -1
  53. package/node_modules/@line/bot-sdk/dist/messaging-api/model/flexBoxCornerRadius.d.ts.map +1 -1
  54. package/node_modules/@line/bot-sdk/dist/messaging-api/model/flexBubble.d.ts.map +1 -1
  55. package/node_modules/@line/bot-sdk/dist/messaging-api/model/flexIconSize.d.ts.map +1 -1
  56. package/node_modules/@line/bot-sdk/dist/messaging-api/model/flexSpanSize.d.ts.map +1 -1
  57. package/node_modules/@line/bot-sdk/dist/messaging-api/model/flexTextFontSize.d.ts.map +1 -1
  58. package/node_modules/@line/bot-sdk/dist/messaging-api/model/numberOfMessagesResponse.d.ts.map +1 -1
  59. package/node_modules/@line/bot-sdk/dist/messaging-api/model/postbackAction.d.ts.map +1 -1
  60. package/node_modules/@line/bot-sdk/dist/messaging-api/model/subscriptionPeriodDemographic.d.ts.map +1 -1
  61. package/node_modules/@line/bot-sdk/dist/version.d.ts +1 -1
  62. package/node_modules/@line/bot-sdk/dist/version.js +1 -1
  63. package/node_modules/@line/bot-sdk/dist/webhook/model/event.d.ts +2 -1
  64. package/node_modules/@line/bot-sdk/dist/webhook/model/event.d.ts.map +1 -1
  65. package/node_modules/@line/bot-sdk/dist/webhook/model/messageEditedEvent.d.ts +24 -0
  66. package/node_modules/@line/bot-sdk/dist/webhook/model/messageEditedEvent.d.ts.map +1 -0
  67. package/node_modules/@line/bot-sdk/dist/webhook/model/messageEditedEvent.js +13 -0
  68. package/node_modules/@line/bot-sdk/dist/webhook/model/messageEditedEvent.js.map +1 -0
  69. package/node_modules/@line/bot-sdk/dist/webhook/model/models.d.ts +1 -0
  70. package/node_modules/@line/bot-sdk/dist/webhook/model/models.d.ts.map +1 -1
  71. package/node_modules/@line/bot-sdk/dist/webhook/model/models.js +1 -0
  72. package/node_modules/@line/bot-sdk/dist/webhook/model/models.js.map +1 -1
  73. package/node_modules/@line/bot-sdk/lib/insight/model/getNumberOfFollowersResponse.ts +1 -1
  74. package/node_modules/@line/bot-sdk/lib/liff/model/liffScope.ts +1 -1
  75. package/node_modules/@line/bot-sdk/lib/manage-audience/model/audienceGroupCreateRoute.ts +1 -4
  76. package/node_modules/@line/bot-sdk/lib/manage-audience/model/audienceGroupFailedType.ts +1 -2
  77. package/node_modules/@line/bot-sdk/lib/manage-audience/model/audienceGroupJobFailedType.ts +1 -2
  78. package/node_modules/@line/bot-sdk/lib/manage-audience/model/audienceGroupJobStatus.ts +1 -4
  79. package/node_modules/@line/bot-sdk/lib/manage-audience/model/audienceGroupStatus.ts +1 -6
  80. package/node_modules/@line/bot-sdk/lib/messaging-api/model/botInfoResponse.ts +1 -1
  81. package/node_modules/@line/bot-sdk/lib/messaging-api/model/flexBoxBorderWidth.ts +1 -6
  82. package/node_modules/@line/bot-sdk/lib/messaging-api/model/flexBoxCornerRadius.ts +1 -7
  83. package/node_modules/@line/bot-sdk/lib/messaging-api/model/flexBubble.ts +1 -7
  84. package/node_modules/@line/bot-sdk/lib/messaging-api/model/flexIconSize.ts +1 -10
  85. package/node_modules/@line/bot-sdk/lib/messaging-api/model/flexSpanSize.ts +1 -10
  86. package/node_modules/@line/bot-sdk/lib/messaging-api/model/flexTextFontSize.ts +1 -10
  87. package/node_modules/@line/bot-sdk/lib/messaging-api/model/getAggregationUnitNameListResponse.ts +1 -1
  88. package/node_modules/@line/bot-sdk/lib/messaging-api/model/getFollowersResponse.ts +1 -1
  89. package/node_modules/@line/bot-sdk/lib/messaging-api/model/getJoinedMembershipUsersResponse.ts +1 -1
  90. package/node_modules/@line/bot-sdk/lib/messaging-api/model/issueLinkTokenResponse.ts +1 -1
  91. package/node_modules/@line/bot-sdk/lib/messaging-api/model/numberOfMessagesResponse.ts +2 -5
  92. package/node_modules/@line/bot-sdk/lib/messaging-api/model/postbackAction.ts +1 -4
  93. package/node_modules/@line/bot-sdk/lib/messaging-api/model/subscriptionPeriodDemographic.ts +1 -5
  94. package/node_modules/@line/bot-sdk/lib/version.ts +1 -1
  95. package/node_modules/@line/bot-sdk/lib/webhook/.openapi-generator/FILES +1 -0
  96. package/node_modules/@line/bot-sdk/lib/webhook/model/event.ts +2 -0
  97. package/node_modules/@line/bot-sdk/lib/webhook/model/messageEditedEvent.ts +32 -0
  98. package/node_modules/@line/bot-sdk/lib/webhook/model/models.ts +1 -0
  99. package/node_modules/@line/bot-sdk/lib/webhook/model/stickerMessageContent.ts +1 -1
  100. package/node_modules/@line/bot-sdk/package.json +3 -3
  101. package/node_modules/@types/node/README.md +1 -1
  102. package/node_modules/@types/node/fs/promises.d.ts +16 -5
  103. package/node_modules/@types/node/package.json +3 -3
  104. package/npm-shrinkwrap.json +10 -10
  105. package/openclaw.plugin.json +0 -18
  106. package/package.json +71 -6
  107. package/dist/channel.runtime-DFgZ_Xwn.js +0 -4
  108. package/dist/monitor.runtime-CZuQgsEE.js +0 -2
  109. package/dist/outbound.runtime-DnpU0Cms.js +0 -2
@@ -1,55 +1,113 @@
1
1
  import { DEFAULT_ACCOUNT_ID, normalizeAccountId, normalizeOptionalAccountId } from "openclaw/plugin-sdk/account-id";
2
2
  import { resolveAccountEntry } from "openclaw/plugin-sdk/account-resolution";
3
- import { tryReadSecretFileSync } from "openclaw/plugin-sdk/core";
3
+ import { tryReadSecretFileSync } from "openclaw/plugin-sdk/secret-file-runtime";
4
4
  //#region extensions/line/src/accounts.ts
5
- function readFileIfExists(filePath) {
6
- return tryReadSecretFileSync(filePath, "LINE credential file", { rejectSymlink: true });
5
+ function readCredentialFile(filePath, configPath) {
6
+ return tryReadSecretFileSync(filePath, "LINE credential file", { rejectSymlink: true }, { configPath });
7
7
  }
8
8
  function resolveToken(params) {
9
9
  const { accountId, baseConfig, accountConfig } = params;
10
10
  if (accountConfig?.channelAccessToken?.trim()) return {
11
- token: accountConfig.channelAccessToken.trim(),
12
- tokenSource: "config"
13
- };
14
- const accountFileToken = readFileIfExists(accountConfig?.tokenFile);
15
- if (accountFileToken) return {
16
- token: accountFileToken,
17
- tokenSource: "file"
11
+ value: accountConfig.channelAccessToken.trim(),
12
+ source: "config",
13
+ status: "available"
18
14
  };
15
+ if (accountConfig?.tokenFile?.trim()) {
16
+ const result = readCredentialFile(accountConfig.tokenFile, `channels.line.accounts.${accountId}.tokenFile`);
17
+ return result.status === "available" ? {
18
+ value: result.value,
19
+ source: "file",
20
+ status: "available"
21
+ } : {
22
+ value: "",
23
+ source: "file",
24
+ status: "configured_unavailable",
25
+ diagnostic: result.diagnostic
26
+ };
27
+ }
19
28
  if (accountId === DEFAULT_ACCOUNT_ID) {
20
29
  if (baseConfig?.channelAccessToken?.trim()) return {
21
- token: baseConfig.channelAccessToken.trim(),
22
- tokenSource: "config"
23
- };
24
- const baseFileToken = readFileIfExists(baseConfig?.tokenFile);
25
- if (baseFileToken) return {
26
- token: baseFileToken,
27
- tokenSource: "file"
30
+ value: baseConfig.channelAccessToken.trim(),
31
+ source: "config",
32
+ status: "available"
28
33
  };
34
+ if (baseConfig?.tokenFile?.trim()) {
35
+ const result = readCredentialFile(baseConfig.tokenFile, "channels.line.tokenFile");
36
+ return result.status === "available" ? {
37
+ value: result.value,
38
+ source: "file",
39
+ status: "available"
40
+ } : {
41
+ value: "",
42
+ source: "file",
43
+ status: "configured_unavailable",
44
+ diagnostic: result.diagnostic
45
+ };
46
+ }
29
47
  const envToken = process.env.LINE_CHANNEL_ACCESS_TOKEN?.trim();
30
48
  if (envToken) return {
31
- token: envToken,
32
- tokenSource: "env"
49
+ value: envToken,
50
+ source: "env",
51
+ status: "available"
33
52
  };
34
53
  }
35
54
  return {
36
- token: "",
37
- tokenSource: "none"
55
+ value: "",
56
+ source: "none",
57
+ status: "missing"
38
58
  };
39
59
  }
40
60
  function resolveSecret(params) {
41
61
  const { accountId, baseConfig, accountConfig } = params;
42
- if (accountConfig?.channelSecret?.trim()) return accountConfig.channelSecret.trim();
43
- const accountFileSecret = readFileIfExists(accountConfig?.secretFile);
44
- if (accountFileSecret) return accountFileSecret;
62
+ if (accountConfig?.channelSecret?.trim()) return {
63
+ value: accountConfig.channelSecret.trim(),
64
+ source: "config",
65
+ status: "available"
66
+ };
67
+ if (accountConfig?.secretFile?.trim()) {
68
+ const result = readCredentialFile(accountConfig.secretFile, `channels.line.accounts.${accountId}.secretFile`);
69
+ return result.status === "available" ? {
70
+ value: result.value,
71
+ source: "file",
72
+ status: "available"
73
+ } : {
74
+ value: "",
75
+ source: "file",
76
+ status: "configured_unavailable",
77
+ diagnostic: result.diagnostic
78
+ };
79
+ }
45
80
  if (accountId === DEFAULT_ACCOUNT_ID) {
46
- if (baseConfig?.channelSecret?.trim()) return baseConfig.channelSecret.trim();
47
- const baseFileSecret = readFileIfExists(baseConfig?.secretFile);
48
- if (baseFileSecret) return baseFileSecret;
81
+ if (baseConfig?.channelSecret?.trim()) return {
82
+ value: baseConfig.channelSecret.trim(),
83
+ source: "config",
84
+ status: "available"
85
+ };
86
+ if (baseConfig?.secretFile?.trim()) {
87
+ const result = readCredentialFile(baseConfig.secretFile, "channels.line.secretFile");
88
+ return result.status === "available" ? {
89
+ value: result.value,
90
+ source: "file",
91
+ status: "available"
92
+ } : {
93
+ value: "",
94
+ source: "file",
95
+ status: "configured_unavailable",
96
+ diagnostic: result.diagnostic
97
+ };
98
+ }
49
99
  const envSecret = process.env.LINE_CHANNEL_SECRET?.trim();
50
- if (envSecret) return envSecret;
100
+ if (envSecret) return {
101
+ value: envSecret,
102
+ source: "env",
103
+ status: "available"
104
+ };
51
105
  }
52
- return "";
106
+ return {
107
+ value: "",
108
+ source: "none",
109
+ status: "missing"
110
+ };
53
111
  }
54
112
  function resolveLineAccount(params) {
55
113
  const cfg = params.cfg;
@@ -57,7 +115,7 @@ function resolveLineAccount(params) {
57
115
  const lineConfig = cfg.channels?.line;
58
116
  const accounts = lineConfig?.accounts;
59
117
  const accountConfig = resolveAccountEntry(accounts, accountId);
60
- const { token, tokenSource } = resolveToken({
118
+ const token = resolveToken({
61
119
  accountId,
62
120
  baseConfig: lineConfig,
63
121
  accountConfig
@@ -79,9 +137,13 @@ function resolveLineAccount(params) {
79
137
  accountId,
80
138
  name: accountConfig?.name ?? (accountId === DEFAULT_ACCOUNT_ID ? lineConfig?.name : void 0),
81
139
  enabled,
82
- channelAccessToken: token,
83
- channelSecret: secret,
84
- tokenSource,
140
+ channelAccessToken: token.value,
141
+ channelSecret: secret.value,
142
+ tokenSource: token.source,
143
+ signingSecretSource: secret.source,
144
+ tokenStatus: token.status,
145
+ signingSecretStatus: secret.status,
146
+ ...[token.diagnostic, secret.diagnostic].some(Boolean) ? { credentialDiagnostics: [token.diagnostic, secret.diagnostic].filter((diagnostic) => Boolean(diagnostic)) } : {},
85
147
  config: mergedConfig
86
148
  };
87
149
  }
package/dist/api.js CHANGED
@@ -1,11 +1,12 @@
1
- import { n as lineChannelPluginCommon, t as linePlugin } from "./channel-BHR-GoJ0.js";
2
- import { n as lineSetupAdapter, t as lineSetupWizard } from "./setup-surface-B7W6pwn3.js";
1
+ import { n as lineChannelPluginCommon, t as linePlugin } from "./channel-CNcv74n2.js";
2
+ import { n as lineSetupAdapter, r as lineSetupContract, t as lineSetupWizard } from "./setup-surface-Bili5gWy.js";
3
3
  //#region extensions/line/src/channel.setup.ts
4
4
  const lineSetupPlugin = {
5
5
  id: "line",
6
6
  ...lineChannelPluginCommon,
7
7
  setupWizard: lineSetupWizard,
8
- setup: lineSetupAdapter
8
+ setup: lineSetupAdapter,
9
+ setupContract: lineSetupContract
9
10
  };
10
11
  //#endregion
11
12
  export { linePlugin, lineSetupPlugin };
@@ -0,0 +1,307 @@
1
+ import { d as attachFooterText } from "./flex-templates-KiKaVYgi.js";
2
+ //#region extensions/line/src/flex-templates/basic-cards.ts
3
+ /**
4
+ * Create an info card with title, body, and optional footer
5
+ *
6
+ * Editorial design: Clean hierarchy with accent bar, generous spacing,
7
+ * and subtle background zones for visual separation.
8
+ */
9
+ function createInfoCard(title, body, footer) {
10
+ const bubble = {
11
+ type: "bubble",
12
+ size: "mega",
13
+ body: {
14
+ type: "box",
15
+ layout: "vertical",
16
+ contents: [{
17
+ type: "box",
18
+ layout: "horizontal",
19
+ contents: [{
20
+ type: "box",
21
+ layout: "vertical",
22
+ contents: [],
23
+ width: "4px",
24
+ backgroundColor: "#06C755",
25
+ cornerRadius: "2px"
26
+ }, {
27
+ type: "text",
28
+ text: title,
29
+ weight: "bold",
30
+ size: "xl",
31
+ color: "#111111",
32
+ wrap: true,
33
+ flex: 1,
34
+ margin: "lg"
35
+ }]
36
+ }, {
37
+ type: "box",
38
+ layout: "vertical",
39
+ contents: [{
40
+ type: "text",
41
+ text: body,
42
+ size: "md",
43
+ color: "#444444",
44
+ wrap: true,
45
+ lineSpacing: "6px"
46
+ }],
47
+ margin: "xl",
48
+ paddingAll: "lg",
49
+ backgroundColor: "#F8F9FA",
50
+ cornerRadius: "lg"
51
+ }],
52
+ paddingAll: "xl",
53
+ backgroundColor: "#FFFFFF"
54
+ }
55
+ };
56
+ if (footer) attachFooterText(bubble, footer);
57
+ return bubble;
58
+ }
59
+ /**
60
+ * Create a list card with title and multiple items
61
+ *
62
+ * Editorial design: Numbered/bulleted list with clear visual hierarchy,
63
+ * accent dots for each item, and generous spacing.
64
+ */
65
+ function createListCard(title, items) {
66
+ const itemContents = items.slice(0, 8).map((item, index) => {
67
+ const itemContentsLocal = [{
68
+ type: "text",
69
+ text: item.title,
70
+ size: "md",
71
+ weight: "bold",
72
+ color: "#1a1a1a",
73
+ wrap: true
74
+ }];
75
+ if (item.subtitle) itemContentsLocal.push({
76
+ type: "text",
77
+ text: item.subtitle,
78
+ size: "sm",
79
+ color: "#888888",
80
+ wrap: true,
81
+ margin: "xs"
82
+ });
83
+ const itemBox = {
84
+ type: "box",
85
+ layout: "horizontal",
86
+ contents: [{
87
+ type: "box",
88
+ layout: "vertical",
89
+ contents: [{
90
+ type: "box",
91
+ layout: "vertical",
92
+ contents: [],
93
+ width: "8px",
94
+ height: "8px",
95
+ backgroundColor: index === 0 ? "#06C755" : "#DDDDDD",
96
+ cornerRadius: "4px"
97
+ }],
98
+ width: "20px",
99
+ alignItems: "center",
100
+ paddingTop: "sm"
101
+ }, {
102
+ type: "box",
103
+ layout: "vertical",
104
+ contents: itemContentsLocal,
105
+ flex: 1
106
+ }],
107
+ margin: index > 0 ? "lg" : void 0
108
+ };
109
+ if (item.action) itemBox.action = item.action;
110
+ return itemBox;
111
+ });
112
+ return {
113
+ type: "bubble",
114
+ size: "mega",
115
+ body: {
116
+ type: "box",
117
+ layout: "vertical",
118
+ contents: [
119
+ {
120
+ type: "text",
121
+ text: title,
122
+ weight: "bold",
123
+ size: "xl",
124
+ color: "#111111",
125
+ wrap: true
126
+ },
127
+ {
128
+ type: "separator",
129
+ margin: "lg",
130
+ color: "#EEEEEE"
131
+ },
132
+ {
133
+ type: "box",
134
+ layout: "vertical",
135
+ contents: itemContents,
136
+ margin: "lg"
137
+ }
138
+ ],
139
+ paddingAll: "xl",
140
+ backgroundColor: "#FFFFFF"
141
+ }
142
+ };
143
+ }
144
+ /**
145
+ * Create an image card with image, title, and optional body text
146
+ */
147
+ function createImageCard(imageUrl, title, body, options) {
148
+ const bubble = {
149
+ type: "bubble",
150
+ hero: {
151
+ type: "image",
152
+ url: imageUrl,
153
+ size: "full",
154
+ aspectRatio: options?.aspectRatio ?? "20:13",
155
+ aspectMode: options?.aspectMode ?? "cover",
156
+ action: options?.action
157
+ },
158
+ body: {
159
+ type: "box",
160
+ layout: "vertical",
161
+ contents: [{
162
+ type: "text",
163
+ text: title,
164
+ weight: "bold",
165
+ size: "xl",
166
+ wrap: true
167
+ }],
168
+ paddingAll: "lg"
169
+ }
170
+ };
171
+ if (body && bubble.body) bubble.body.contents.push({
172
+ type: "text",
173
+ text: body,
174
+ size: "md",
175
+ wrap: true,
176
+ margin: "md",
177
+ color: "#666666"
178
+ });
179
+ return bubble;
180
+ }
181
+ /**
182
+ * Create an action card with title, body, and action buttons
183
+ */
184
+ function createActionCard(title, body, actions, options) {
185
+ const bubble = {
186
+ type: "bubble",
187
+ body: {
188
+ type: "box",
189
+ layout: "vertical",
190
+ contents: [{
191
+ type: "text",
192
+ text: title,
193
+ weight: "bold",
194
+ size: "xl",
195
+ wrap: true
196
+ }, {
197
+ type: "text",
198
+ text: body,
199
+ size: "md",
200
+ wrap: true,
201
+ margin: "md",
202
+ color: "#666666"
203
+ }],
204
+ paddingAll: "lg"
205
+ },
206
+ footer: {
207
+ type: "box",
208
+ layout: "vertical",
209
+ contents: actions.slice(0, 4).map((action, index) => ({
210
+ type: "button",
211
+ action: action.action,
212
+ style: index === 0 ? "primary" : "secondary",
213
+ margin: index > 0 ? "sm" : void 0
214
+ })),
215
+ paddingAll: "md"
216
+ }
217
+ };
218
+ if (options?.imageUrl) bubble.hero = {
219
+ type: "image",
220
+ url: options.imageUrl,
221
+ size: "full",
222
+ aspectRatio: options.aspectRatio ?? "20:13",
223
+ aspectMode: "cover"
224
+ };
225
+ return bubble;
226
+ }
227
+ /**
228
+ * Create a carousel container from multiple bubbles
229
+ * LINE allows max 12 bubbles in a carousel
230
+ */
231
+ function createCarousel(bubbles) {
232
+ return {
233
+ type: "carousel",
234
+ contents: bubbles.slice(0, 12)
235
+ };
236
+ }
237
+ /**
238
+ * Create a notification bubble (for alerts, status updates)
239
+ *
240
+ * Editorial design: Bold status indicator with accent color,
241
+ * clear typography, optional icon for context.
242
+ */
243
+ function createNotificationBubble(text, options) {
244
+ const typeColors = {
245
+ info: {
246
+ accent: "#3B82F6",
247
+ bg: "#EFF6FF"
248
+ },
249
+ success: {
250
+ accent: "#06C755",
251
+ bg: "#F0FDF4"
252
+ },
253
+ warning: {
254
+ accent: "#F59E0B",
255
+ bg: "#FFFBEB"
256
+ },
257
+ error: {
258
+ accent: "#EF4444",
259
+ bg: "#FEF2F2"
260
+ }
261
+ }[options?.type ?? "info"];
262
+ const contents = [];
263
+ contents.push({
264
+ type: "box",
265
+ layout: "vertical",
266
+ contents: [],
267
+ width: "4px",
268
+ backgroundColor: typeColors.accent,
269
+ cornerRadius: "2px"
270
+ });
271
+ const textContents = [];
272
+ if (options?.title) textContents.push({
273
+ type: "text",
274
+ text: options.title,
275
+ size: "md",
276
+ weight: "bold",
277
+ color: "#111111",
278
+ wrap: true
279
+ });
280
+ textContents.push({
281
+ type: "text",
282
+ text,
283
+ size: options?.title ? "sm" : "md",
284
+ color: options?.title ? "#666666" : "#333333",
285
+ wrap: true,
286
+ margin: options?.title ? "sm" : void 0
287
+ });
288
+ contents.push({
289
+ type: "box",
290
+ layout: "vertical",
291
+ contents: textContents,
292
+ flex: 1,
293
+ paddingStart: "lg"
294
+ });
295
+ return {
296
+ type: "bubble",
297
+ body: {
298
+ type: "box",
299
+ layout: "horizontal",
300
+ contents,
301
+ paddingAll: "xl",
302
+ backgroundColor: typeColors.bg
303
+ }
304
+ };
305
+ }
306
+ //#endregion
307
+ export { createListCard as a, createInfoCard as i, createCarousel as n, createNotificationBubble as o, createImageCard as r, createActionCard as t };
@@ -1,4 +1,5 @@
1
- import { c as uriAction, d as createReceiptCard, f as createActionCard, g as createListCard, h as createInfoCard, m as createImageCard, o as messageAction, s as postbackAction } from "./flex-templates-K1lS9i8L.js";
1
+ import { a as messageAction, o as postbackAction, s as uriAction, u as createReceiptCard } from "./flex-templates-KiKaVYgi.js";
2
+ import { a as createListCard, i as createInfoCard, r as createImageCard, t as createActionCard } from "./basic-cards-Rb-Ow7LN.js";
2
3
  import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
3
4
  import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
4
5
  import { expectDefined } from "openclaw/plugin-sdk/expect-runtime";
@@ -1,6 +1,8 @@
1
- import { i as resolveLineAccount, r as resolveDefaultLineAccountId, t as listLineAccountIds } from "./accounts-DJVOv1JI.js";
2
- import { n as lineSetupAdapter, r as hasLineCredentials, t as lineSetupWizard } from "./setup-surface-B7W6pwn3.js";
3
- import { a as buildLineMediaMessage, d as LineChannelConfigSchema, i as buildLineQuickReplyFallbackText, l as getLineRuntime, n as parseLineDirectives, o as hasLineSpecificMediaOptions, p as resolveExactLineGroupConfigKey, r as createLineSendReceipt, s as resolveLineOutboundMedia, t as hasLineDirectives } from "./reply-payload-transform-r9sa-TYT.js";
1
+ import { i as resolveLineAccount, r as resolveDefaultLineAccountId, t as listLineAccountIds } from "./accounts-BUBOoW5Q.js";
2
+ import { i as hasLineCredentials, n as lineSetupAdapter, r as lineSetupContract, t as lineSetupWizard } from "./setup-surface-Bili5gWy.js";
3
+ import { i as resolveExactLineGroupConfigKey, n as getLineRuntime, t as buildLineQuickReplyFallbackText } from "./quick-reply-fallback-D86FwAfr.js";
4
+ import { n as parseLineDirectives, r as LineChannelConfigSchema, t as hasLineDirectives } from "./reply-payload-transform-d57WYHFm.js";
5
+ import { i as resolveLineOutboundMedia, n as buildLineMediaMessage, r as hasLineSpecificMediaOptions, t as createLineSendReceipt } from "./send-receipt-CY2ey8XH.js";
4
6
  import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
5
7
  import { buildDmGroupAccountAllowlistAdapter, createFlatAllowlistOverrideResolver } from "openclaw/plugin-sdk/allowlist-config-edit";
6
8
  import { buildChannelOutboundSessionRoute, createChatChannelPlugin } from "openclaw/plugin-sdk/channel-core";
@@ -8,10 +10,10 @@ import { createPairingPrefixStripper } from "openclaw/plugin-sdk/channel-pairing
8
10
  import { buildChannelGroupsScopeTree, createRestrictSendersChannelSecurity, resolveScopeRequireMention } from "openclaw/plugin-sdk/channel-policy";
9
11
  import { createEmptyChannelDirectoryAdapter } from "openclaw/plugin-sdk/directory-runtime";
10
12
  import { DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$1 } from "openclaw/plugin-sdk/account-id";
11
- import { clearAccountEntryFields } from "openclaw/plugin-sdk/core";
12
13
  import { describeWebhookAccountSnapshot } from "openclaw/plugin-sdk/account-helpers";
13
14
  import { createScopedChannelConfigAdapter } from "openclaw/plugin-sdk/channel-config-helpers";
14
15
  import { normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
16
+ import { clearAccountEntryFields } from "openclaw/plugin-sdk/core";
15
17
  import { defineChannelMessageAdapter } from "openclaw/plugin-sdk/channel-outbound";
16
18
  import { createAttachedChannelResultAdapter, createEmptyChannelResult } from "openclaw/plugin-sdk/channel-send-result";
17
19
  import { resolveOutboundMediaUrls } from "openclaw/plugin-sdk/reply-payload";
@@ -104,14 +106,19 @@ const lineChannelPluginCommon = {
104
106
  describeAccount: (account) => describeWebhookAccountSnapshot({
105
107
  account,
106
108
  configured: hasLineCredentials(account),
107
- extra: { tokenSource: account.tokenSource ?? void 0 }
109
+ extra: {
110
+ tokenSource: account.tokenSource ?? void 0,
111
+ signingSecretSource: account.signingSecretSource ?? void 0,
112
+ tokenStatus: account.tokenStatus,
113
+ signingSecretStatus: account.signingSecretStatus
114
+ }
108
115
  })
109
116
  }
110
117
  };
111
118
  //#endregion
112
119
  //#region extensions/line/src/gateway.ts
113
120
  const loadLineProbeRuntime$1 = createLazyRuntimeModule(() => import("./probe.runtime-CRhVGqwl.js"));
114
- const loadLineMonitorRuntime = createLazyRuntimeModule(() => import("./monitor.runtime-CZuQgsEE.js"));
121
+ const loadLineMonitorRuntime = createLazyRuntimeModule(() => import("./monitor.runtime-DKj4FHkA.js"));
115
122
  const lineGatewayAdapter = {
116
123
  startAccount: async (ctx) => {
117
124
  const account = ctx.account;
@@ -226,7 +233,8 @@ function inferLineTargetChatType(target) {
226
233
  }
227
234
  //#endregion
228
235
  //#region extensions/line/src/outbound.ts
229
- const loadLineOutboundRuntime = createLazyRuntimeModule(() => import("./outbound.runtime-DnpU0Cms.js"));
236
+ const loadLineOutboundRuntime = createLazyRuntimeModule(() => import("./outbound.runtime-DRyoVa81.js"));
237
+ const LINE_FLEX_ALT_TEXT_LIMIT = 1500;
230
238
  const lineOutboundAdapter = {
231
239
  deliveryMode: "direct",
232
240
  chunker: (text, limit) => getLineRuntime().channel.text.chunkMarkdownText(text, limit),
@@ -353,7 +361,7 @@ const lineOutboundAdapter = {
353
361
  const quickReplyMessages = [];
354
362
  if (lineData.flexMessage) quickReplyMessages.push({
355
363
  type: "flex",
356
- altText: truncateUtf16Safe(lineData.flexMessage.altText, 400),
364
+ altText: truncateUtf16Safe(lineData.flexMessage.altText, LINE_FLEX_ALT_TEXT_LIMIT),
357
365
  contents: lineData.flexMessage.contents
358
366
  });
359
367
  if (lineData.templateMessage) {
@@ -369,7 +377,7 @@ const lineOutboundAdapter = {
369
377
  });
370
378
  for (const flexMsg of processed.flexMessages) quickReplyMessages.push({
371
379
  type: "flex",
372
- altText: truncateUtf16Safe(flexMsg.altText, 400),
380
+ altText: truncateUtf16Safe(flexMsg.altText, LINE_FLEX_ALT_TEXT_LIMIT),
373
381
  contents: flexMsg.contents
374
382
  });
375
383
  for (const url of mediaUrls) {
@@ -514,13 +522,16 @@ const lineStatusAdapter = createComputedAccountStatusAdapter({
514
522
  configured: hasLineCredentials(account),
515
523
  extra: {
516
524
  tokenSource: account.tokenSource,
525
+ signingSecretSource: account.signingSecretSource,
526
+ tokenStatus: account.tokenStatus,
527
+ signingSecretStatus: account.signingSecretStatus,
517
528
  mode: "webhook"
518
529
  }
519
530
  })
520
531
  });
521
532
  //#endregion
522
533
  //#region extensions/line/src/channel.ts
523
- const loadLineChannelRuntime = createLazyRuntimeModule(() => import("./channel.runtime-DFgZ_Xwn.js"));
534
+ const loadLineChannelRuntime = createLazyRuntimeModule(() => import("./channel.runtime-BBCZvRa_.js"));
524
535
  const lineSecurityAdapter = createRestrictSendersChannelSecurity({
525
536
  channelKey: "line",
526
537
  resolveDmPolicy: (account) => account.config.dmPolicy,
@@ -602,6 +613,7 @@ const linePlugin = createChatChannelPlugin({
602
613
  },
603
614
  directory: createEmptyChannelDirectoryAdapter(),
604
615
  setup: lineSetupAdapter,
616
+ setupContract: lineSetupContract,
605
617
  status: lineStatusAdapter,
606
618
  gateway: lineGatewayAdapter,
607
619
  message: lineMessageAdapter,
@@ -1,2 +1,2 @@
1
- import { t as linePlugin } from "./channel-BHR-GoJ0.js";
1
+ import { t as linePlugin } from "./channel-CNcv74n2.js";
2
2
  export { linePlugin };
@@ -0,0 +1,4 @@
1
+ import { v as pushMessageLine } from "./markdown-to-line-DWIdzBfy.js";
2
+ import { t as monitorLineProvider } from "./monitor-BinAXvIY.js";
3
+ import { t as probeLineBot } from "./probe-BslD77tJ.js";
4
+ export { monitorLineProvider, probeLineBot, pushMessageLine };
@@ -1,2 +1,2 @@
1
- import { i as resolveLineAccount, r as resolveDefaultLineAccountId, t as listLineAccountIds } from "./accounts-DJVOv1JI.js";
1
+ import { i as resolveLineAccount, r as resolveDefaultLineAccountId, t as listLineAccountIds } from "./accounts-BUBOoW5Q.js";
2
2
  export { listLineAccountIds, resolveDefaultLineAccountId, resolveLineAccount };