@openclaw/line 2026.5.2-beta.2 → 2026.5.3-beta.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.
- package/dist/accounts-UXAvdBo_.js +105 -0
- package/dist/api.js +11 -0
- package/dist/basic-cards-7DTG6E-A.js +307 -0
- package/dist/card-command-UlPc6Vuc.js +240 -0
- package/dist/channel-Rls9s60K.js +601 -0
- package/dist/channel-plugin-api.js +2 -0
- package/dist/channel.runtime-bXoj8_Sl.js +4 -0
- package/dist/contract-api.js +2 -0
- package/dist/index.js +45 -0
- package/dist/markdown-to-line-CCWK6PJh.js +789 -0
- package/dist/monitor-B4_RxHc0.js +1523 -0
- package/dist/monitor.runtime-DyxYlrM9.js +2 -0
- package/dist/outbound-media-BfhBmWq5.js +55 -0
- package/dist/outbound.runtime-B-luYwEB.js +2 -0
- package/dist/probe-D9BPzb2n.js +30 -0
- package/dist/probe.runtime-N91OWW1J.js +2 -0
- package/dist/quick-reply-fallback-HskUUWsn.js +55 -0
- package/dist/reply-payload-transform-CFGTs9ln.js +713 -0
- package/dist/runtime-api.js +277 -0
- package/dist/schedule-cards-BwQChTdM.js +359 -0
- package/dist/secret-contract-api.js +5 -0
- package/dist/setup-api.js +2 -0
- package/dist/setup-entry.js +11 -0
- package/dist/setup-surface-DCH7CE-y.js +281 -0
- package/package.json +14 -6
- package/api.ts +0 -11
- package/channel-plugin-api.ts +0 -1
- package/contract-api.ts +0 -5
- package/index.ts +0 -54
- package/runtime-api.ts +0 -187
- package/secret-contract-api.ts +0 -4
- package/setup-api.ts +0 -2
- package/setup-entry.ts +0 -9
- package/src/account-helpers.ts +0 -16
- package/src/accounts.test.ts +0 -290
- package/src/accounts.ts +0 -187
- package/src/actions.ts +0 -61
- package/src/auto-reply-delivery.test.ts +0 -248
- package/src/auto-reply-delivery.ts +0 -200
- package/src/bindings.ts +0 -65
- package/src/bot-access.ts +0 -48
- package/src/bot-handlers.test.ts +0 -1089
- package/src/bot-handlers.ts +0 -642
- package/src/bot-message-context.test.ts +0 -405
- package/src/bot-message-context.ts +0 -581
- package/src/bot.ts +0 -70
- package/src/card-command.ts +0 -347
- package/src/channel-access-token.ts +0 -14
- package/src/channel-api.ts +0 -17
- package/src/channel-setup-status.contract.test.ts +0 -70
- package/src/channel-shared.ts +0 -48
- package/src/channel.logout.test.ts +0 -145
- package/src/channel.runtime.ts +0 -3
- package/src/channel.sendPayload.test.ts +0 -514
- package/src/channel.setup.ts +0 -11
- package/src/channel.status.test.ts +0 -63
- package/src/channel.ts +0 -154
- package/src/config-adapter.ts +0 -29
- package/src/config-schema.ts +0 -57
- package/src/download.test.ts +0 -133
- package/src/download.ts +0 -87
- package/src/flex-templates/basic-cards.ts +0 -395
- package/src/flex-templates/common.ts +0 -20
- package/src/flex-templates/media-control-cards.ts +0 -555
- package/src/flex-templates/message.ts +0 -13
- package/src/flex-templates/schedule-cards.ts +0 -467
- package/src/flex-templates/types.ts +0 -22
- package/src/flex-templates.ts +0 -32
- package/src/gateway.ts +0 -129
- package/src/group-keys.test.ts +0 -123
- package/src/group-keys.ts +0 -65
- package/src/group-policy.ts +0 -22
- package/src/markdown-to-line.test.ts +0 -348
- package/src/markdown-to-line.ts +0 -416
- package/src/message-cards.test.ts +0 -204
- package/src/monitor.lifecycle.test.ts +0 -421
- package/src/monitor.runtime.ts +0 -1
- package/src/monitor.ts +0 -506
- package/src/outbound-media.test.ts +0 -189
- package/src/outbound-media.ts +0 -120
- package/src/outbound.runtime.ts +0 -12
- package/src/outbound.ts +0 -356
- package/src/probe.contract.test.ts +0 -9
- package/src/probe.runtime.ts +0 -1
- package/src/probe.ts +0 -34
- package/src/quick-reply-fallback.ts +0 -10
- package/src/reply-chunks.test.ts +0 -179
- package/src/reply-chunks.ts +0 -110
- package/src/reply-payload-transform.test.ts +0 -387
- package/src/reply-payload-transform.ts +0 -317
- package/src/rich-menu.test.ts +0 -310
- package/src/rich-menu.ts +0 -326
- package/src/runtime.ts +0 -32
- package/src/send.test.ts +0 -346
- package/src/send.ts +0 -489
- package/src/setup-core.ts +0 -149
- package/src/setup-runtime-api.ts +0 -9
- package/src/setup-surface.test.ts +0 -474
- package/src/setup-surface.ts +0 -227
- package/src/signature.test.ts +0 -34
- package/src/signature.ts +0 -24
- package/src/status.ts +0 -37
- package/src/template-messages.ts +0 -333
- package/src/types.ts +0 -128
- package/src/webhook-node.test.ts +0 -513
- package/src/webhook-node.ts +0 -131
- package/src/webhook-utils.ts +0 -10
- package/src/webhook.ts +0 -111
- package/tsconfig.json +0 -16
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
import { i as resolveLineAccount, n as normalizeAccountId, r as resolveDefaultLineAccountId, t as listLineAccountIds } from "./accounts-UXAvdBo_.js";
|
|
2
|
+
import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
|
|
3
|
+
import { DEFAULT_ACCOUNT_ID, createAllowFromSection, createSetupInputPresenceValidator, createStandardChannelSetupStatus, formatDocsLink, mergeAllowFromEntries, setSetupChannelEnabled, splitSetupEntries } from "openclaw/plugin-sdk/setup";
|
|
4
|
+
//#region extensions/line/src/account-helpers.ts
|
|
5
|
+
function hasLineCredentials(account) {
|
|
6
|
+
return Boolean(account.channelAccessToken?.trim() && account.channelSecret?.trim());
|
|
7
|
+
}
|
|
8
|
+
function parseLineAllowFromId(raw) {
|
|
9
|
+
const trimmed = raw.trim().replace(/^line:(?:user:)?/i, "");
|
|
10
|
+
if (!/^U[a-f0-9]{32}$/i.test(trimmed)) return null;
|
|
11
|
+
return trimmed;
|
|
12
|
+
}
|
|
13
|
+
//#endregion
|
|
14
|
+
//#region extensions/line/src/setup-core.ts
|
|
15
|
+
function patchLineAccountConfig(params) {
|
|
16
|
+
const accountId = normalizeAccountId(params.accountId);
|
|
17
|
+
const lineConfig = params.cfg.channels?.line ?? {};
|
|
18
|
+
const clearFields = params.clearFields ?? [];
|
|
19
|
+
if (accountId === DEFAULT_ACCOUNT_ID) {
|
|
20
|
+
const nextLine = { ...lineConfig };
|
|
21
|
+
for (const field of clearFields) delete nextLine[field];
|
|
22
|
+
return {
|
|
23
|
+
...params.cfg,
|
|
24
|
+
channels: {
|
|
25
|
+
...params.cfg.channels,
|
|
26
|
+
line: {
|
|
27
|
+
...nextLine,
|
|
28
|
+
...params.enabled ? { enabled: true } : {},
|
|
29
|
+
...params.patch
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
const nextAccount = { ...lineConfig.accounts?.[accountId] };
|
|
35
|
+
for (const field of clearFields) delete nextAccount[field];
|
|
36
|
+
return {
|
|
37
|
+
...params.cfg,
|
|
38
|
+
channels: {
|
|
39
|
+
...params.cfg.channels,
|
|
40
|
+
line: {
|
|
41
|
+
...lineConfig,
|
|
42
|
+
...params.enabled ? { enabled: true } : {},
|
|
43
|
+
accounts: {
|
|
44
|
+
...lineConfig.accounts,
|
|
45
|
+
[accountId]: {
|
|
46
|
+
...nextAccount,
|
|
47
|
+
...params.enabled ? { enabled: true } : {},
|
|
48
|
+
...params.patch
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function isLineConfigured(cfg, accountId) {
|
|
56
|
+
return hasLineCredentials(resolveLineAccount({
|
|
57
|
+
cfg,
|
|
58
|
+
accountId
|
|
59
|
+
}));
|
|
60
|
+
}
|
|
61
|
+
const lineSetupAdapter = {
|
|
62
|
+
resolveAccountId: ({ accountId }) => normalizeAccountId(accountId),
|
|
63
|
+
applyAccountName: ({ cfg, accountId, name }) => patchLineAccountConfig({
|
|
64
|
+
cfg,
|
|
65
|
+
accountId,
|
|
66
|
+
patch: name?.trim() ? { name: name.trim() } : {}
|
|
67
|
+
}),
|
|
68
|
+
validateInput: createSetupInputPresenceValidator({
|
|
69
|
+
defaultAccountOnlyEnvError: "LINE_CHANNEL_ACCESS_TOKEN can only be used for the default account.",
|
|
70
|
+
whenNotUseEnv: [{
|
|
71
|
+
someOf: ["channelAccessToken", "tokenFile"],
|
|
72
|
+
message: "LINE requires channelAccessToken or --token-file (or --use-env)."
|
|
73
|
+
}, {
|
|
74
|
+
someOf: ["channelSecret", "secretFile"],
|
|
75
|
+
message: "LINE requires channelSecret or --secret-file (or --use-env)."
|
|
76
|
+
}]
|
|
77
|
+
}),
|
|
78
|
+
applyAccountConfig: ({ cfg, accountId, input }) => {
|
|
79
|
+
const typedInput = input;
|
|
80
|
+
const normalizedAccountId = normalizeAccountId(accountId);
|
|
81
|
+
if (normalizedAccountId === DEFAULT_ACCOUNT_ID) return patchLineAccountConfig({
|
|
82
|
+
cfg,
|
|
83
|
+
accountId: normalizedAccountId,
|
|
84
|
+
enabled: true,
|
|
85
|
+
clearFields: typedInput.useEnv ? [
|
|
86
|
+
"channelAccessToken",
|
|
87
|
+
"channelSecret",
|
|
88
|
+
"tokenFile",
|
|
89
|
+
"secretFile"
|
|
90
|
+
] : void 0,
|
|
91
|
+
patch: typedInput.useEnv ? {} : {
|
|
92
|
+
...typedInput.tokenFile ? { tokenFile: typedInput.tokenFile } : typedInput.channelAccessToken ? { channelAccessToken: typedInput.channelAccessToken } : {},
|
|
93
|
+
...typedInput.secretFile ? { secretFile: typedInput.secretFile } : typedInput.channelSecret ? { channelSecret: typedInput.channelSecret } : {}
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
return patchLineAccountConfig({
|
|
97
|
+
cfg,
|
|
98
|
+
accountId: normalizedAccountId,
|
|
99
|
+
enabled: true,
|
|
100
|
+
patch: {
|
|
101
|
+
...typedInput.tokenFile ? { tokenFile: typedInput.tokenFile } : typedInput.channelAccessToken ? { channelAccessToken: typedInput.channelAccessToken } : {},
|
|
102
|
+
...typedInput.secretFile ? { secretFile: typedInput.secretFile } : typedInput.channelSecret ? { channelSecret: typedInput.channelSecret } : {}
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
//#endregion
|
|
108
|
+
//#region extensions/line/src/setup-surface.ts
|
|
109
|
+
const channel = "line";
|
|
110
|
+
const LINE_SETUP_HELP_LINES = [
|
|
111
|
+
"1) Open the LINE Developers Console and create or pick a Messaging API channel",
|
|
112
|
+
"2) Copy the channel access token and channel secret",
|
|
113
|
+
"3) Enable Use webhook in the Messaging API settings",
|
|
114
|
+
"4) Point the webhook at https://<gateway-host>/line/webhook",
|
|
115
|
+
`Docs: ${formatDocsLink("/channels/line", "channels/line")}`
|
|
116
|
+
];
|
|
117
|
+
const LINE_ALLOW_FROM_HELP_LINES = [
|
|
118
|
+
"Allowlist LINE DMs by user id.",
|
|
119
|
+
"LINE ids are case-sensitive.",
|
|
120
|
+
"Examples:",
|
|
121
|
+
"- U1234567890abcdef1234567890abcdef",
|
|
122
|
+
"- line:user:U1234567890abcdef1234567890abcdef",
|
|
123
|
+
"Multiple entries: comma-separated.",
|
|
124
|
+
`Docs: ${formatDocsLink("/channels/line", "channels/line")}`
|
|
125
|
+
];
|
|
126
|
+
const lineDmPolicy = {
|
|
127
|
+
label: "LINE",
|
|
128
|
+
channel,
|
|
129
|
+
policyKey: "channels.line.dmPolicy",
|
|
130
|
+
allowFromKey: "channels.line.allowFrom",
|
|
131
|
+
resolveConfigKeys: (cfg, accountId) => (accountId ?? resolveDefaultLineAccountId(cfg)) !== DEFAULT_ACCOUNT_ID ? {
|
|
132
|
+
policyKey: `channels.line.accounts.${accountId ?? resolveDefaultLineAccountId(cfg)}.dmPolicy`,
|
|
133
|
+
allowFromKey: `channels.line.accounts.${accountId ?? resolveDefaultLineAccountId(cfg)}.allowFrom`
|
|
134
|
+
} : {
|
|
135
|
+
policyKey: "channels.line.dmPolicy",
|
|
136
|
+
allowFromKey: "channels.line.allowFrom"
|
|
137
|
+
},
|
|
138
|
+
getCurrent: (cfg, accountId) => resolveLineAccount({
|
|
139
|
+
cfg,
|
|
140
|
+
accountId: accountId ?? resolveDefaultLineAccountId(cfg)
|
|
141
|
+
}).config.dmPolicy ?? "pairing",
|
|
142
|
+
setPolicy: (cfg, policy, accountId) => patchLineAccountConfig({
|
|
143
|
+
cfg,
|
|
144
|
+
accountId: accountId ?? resolveDefaultLineAccountId(cfg),
|
|
145
|
+
enabled: true,
|
|
146
|
+
patch: policy === "open" ? {
|
|
147
|
+
dmPolicy: "open",
|
|
148
|
+
allowFrom: mergeAllowFromEntries(resolveLineAccount({
|
|
149
|
+
cfg,
|
|
150
|
+
accountId: accountId ?? resolveDefaultLineAccountId(cfg)
|
|
151
|
+
}).config.allowFrom, ["*"])
|
|
152
|
+
} : { dmPolicy: policy },
|
|
153
|
+
clearFields: policy === "pairing" || policy === "disabled" ? ["allowFrom"] : void 0
|
|
154
|
+
})
|
|
155
|
+
};
|
|
156
|
+
const lineSetupWizard = {
|
|
157
|
+
channel,
|
|
158
|
+
status: createStandardChannelSetupStatus({
|
|
159
|
+
channelLabel: "LINE",
|
|
160
|
+
configuredLabel: "configured",
|
|
161
|
+
unconfiguredLabel: "needs token + secret",
|
|
162
|
+
configuredHint: "configured",
|
|
163
|
+
unconfiguredHint: "needs token + secret",
|
|
164
|
+
configuredScore: 1,
|
|
165
|
+
unconfiguredScore: 0,
|
|
166
|
+
includeStatusLine: true,
|
|
167
|
+
resolveConfigured: ({ cfg, accountId }) => isLineConfigured(cfg, accountId ?? resolveDefaultLineAccountId(cfg)),
|
|
168
|
+
resolveExtraStatusLines: ({ cfg }) => [`Accounts: ${listLineAccountIds(cfg).length || 0}`]
|
|
169
|
+
}),
|
|
170
|
+
introNote: {
|
|
171
|
+
title: "LINE Messaging API",
|
|
172
|
+
lines: LINE_SETUP_HELP_LINES,
|
|
173
|
+
shouldShow: ({ cfg, accountId }) => !isLineConfigured(cfg, accountId ?? resolveDefaultLineAccountId(cfg))
|
|
174
|
+
},
|
|
175
|
+
credentials: [{
|
|
176
|
+
inputKey: "token",
|
|
177
|
+
providerHint: channel,
|
|
178
|
+
credentialLabel: "channel access token",
|
|
179
|
+
preferredEnvVar: "LINE_CHANNEL_ACCESS_TOKEN",
|
|
180
|
+
helpTitle: "LINE Messaging API",
|
|
181
|
+
helpLines: LINE_SETUP_HELP_LINES,
|
|
182
|
+
envPrompt: "LINE_CHANNEL_ACCESS_TOKEN detected. Use env var?",
|
|
183
|
+
keepPrompt: "LINE channel access token already configured. Keep it?",
|
|
184
|
+
inputPrompt: "Enter LINE channel access token",
|
|
185
|
+
allowEnv: ({ accountId }) => accountId === DEFAULT_ACCOUNT_ID,
|
|
186
|
+
inspect: ({ cfg, accountId }) => {
|
|
187
|
+
const resolved = resolveLineAccount({
|
|
188
|
+
cfg,
|
|
189
|
+
accountId
|
|
190
|
+
});
|
|
191
|
+
return {
|
|
192
|
+
accountConfigured: Boolean(normalizeOptionalString(resolved.channelAccessToken) && normalizeOptionalString(resolved.channelSecret)),
|
|
193
|
+
hasConfiguredValue: Boolean(normalizeOptionalString(resolved.config.channelAccessToken) ?? normalizeOptionalString(resolved.config.tokenFile)),
|
|
194
|
+
resolvedValue: normalizeOptionalString(resolved.channelAccessToken),
|
|
195
|
+
envValue: accountId === DEFAULT_ACCOUNT_ID ? normalizeOptionalString(process.env.LINE_CHANNEL_ACCESS_TOKEN) : void 0
|
|
196
|
+
};
|
|
197
|
+
},
|
|
198
|
+
applyUseEnv: ({ cfg, accountId }) => patchLineAccountConfig({
|
|
199
|
+
cfg,
|
|
200
|
+
accountId,
|
|
201
|
+
enabled: true,
|
|
202
|
+
clearFields: ["channelAccessToken", "tokenFile"],
|
|
203
|
+
patch: {}
|
|
204
|
+
}),
|
|
205
|
+
applySet: ({ cfg, accountId, resolvedValue }) => patchLineAccountConfig({
|
|
206
|
+
cfg,
|
|
207
|
+
accountId,
|
|
208
|
+
enabled: true,
|
|
209
|
+
clearFields: ["tokenFile"],
|
|
210
|
+
patch: { channelAccessToken: resolvedValue }
|
|
211
|
+
})
|
|
212
|
+
}, {
|
|
213
|
+
inputKey: "password",
|
|
214
|
+
providerHint: "line-secret",
|
|
215
|
+
credentialLabel: "channel secret",
|
|
216
|
+
preferredEnvVar: "LINE_CHANNEL_SECRET",
|
|
217
|
+
helpTitle: "LINE Messaging API",
|
|
218
|
+
helpLines: LINE_SETUP_HELP_LINES,
|
|
219
|
+
envPrompt: "LINE_CHANNEL_SECRET detected. Use env var?",
|
|
220
|
+
keepPrompt: "LINE channel secret already configured. Keep it?",
|
|
221
|
+
inputPrompt: "Enter LINE channel secret",
|
|
222
|
+
allowEnv: ({ accountId }) => accountId === DEFAULT_ACCOUNT_ID,
|
|
223
|
+
inspect: ({ cfg, accountId }) => {
|
|
224
|
+
const resolved = resolveLineAccount({
|
|
225
|
+
cfg,
|
|
226
|
+
accountId
|
|
227
|
+
});
|
|
228
|
+
return {
|
|
229
|
+
accountConfigured: Boolean(normalizeOptionalString(resolved.channelAccessToken) && normalizeOptionalString(resolved.channelSecret)),
|
|
230
|
+
hasConfiguredValue: Boolean(normalizeOptionalString(resolved.config.channelSecret) ?? normalizeOptionalString(resolved.config.secretFile)),
|
|
231
|
+
resolvedValue: normalizeOptionalString(resolved.channelSecret),
|
|
232
|
+
envValue: accountId === DEFAULT_ACCOUNT_ID ? normalizeOptionalString(process.env.LINE_CHANNEL_SECRET) : void 0
|
|
233
|
+
};
|
|
234
|
+
},
|
|
235
|
+
applyUseEnv: ({ cfg, accountId }) => patchLineAccountConfig({
|
|
236
|
+
cfg,
|
|
237
|
+
accountId,
|
|
238
|
+
enabled: true,
|
|
239
|
+
clearFields: ["channelSecret", "secretFile"],
|
|
240
|
+
patch: {}
|
|
241
|
+
}),
|
|
242
|
+
applySet: ({ cfg, accountId, resolvedValue }) => patchLineAccountConfig({
|
|
243
|
+
cfg,
|
|
244
|
+
accountId,
|
|
245
|
+
enabled: true,
|
|
246
|
+
clearFields: ["secretFile"],
|
|
247
|
+
patch: { channelSecret: resolvedValue }
|
|
248
|
+
})
|
|
249
|
+
}],
|
|
250
|
+
allowFrom: createAllowFromSection({
|
|
251
|
+
helpTitle: "LINE allowlist",
|
|
252
|
+
helpLines: LINE_ALLOW_FROM_HELP_LINES,
|
|
253
|
+
message: "LINE allowFrom (user id)",
|
|
254
|
+
placeholder: "U1234567890abcdef1234567890abcdef",
|
|
255
|
+
invalidWithoutCredentialNote: "LINE allowFrom requires raw user ids like U1234567890abcdef1234567890abcdef.",
|
|
256
|
+
parseInputs: splitSetupEntries,
|
|
257
|
+
parseId: parseLineAllowFromId,
|
|
258
|
+
apply: ({ cfg, accountId, allowFrom }) => patchLineAccountConfig({
|
|
259
|
+
cfg,
|
|
260
|
+
accountId,
|
|
261
|
+
enabled: true,
|
|
262
|
+
patch: {
|
|
263
|
+
dmPolicy: "allowlist",
|
|
264
|
+
allowFrom
|
|
265
|
+
}
|
|
266
|
+
})
|
|
267
|
+
}),
|
|
268
|
+
dmPolicy: lineDmPolicy,
|
|
269
|
+
completionNote: {
|
|
270
|
+
title: "LINE webhook",
|
|
271
|
+
lines: [
|
|
272
|
+
"Enable Use webhook in the LINE console after saving credentials.",
|
|
273
|
+
"Default webhook URL: https://<gateway-host>/line/webhook",
|
|
274
|
+
"If you set channels.line.webhookPath, update the URL to match.",
|
|
275
|
+
`Docs: ${formatDocsLink("/channels/line", "channels/line")}`
|
|
276
|
+
]
|
|
277
|
+
},
|
|
278
|
+
disable: (cfg) => setSetupChannelEnabled(cfg, channel, false)
|
|
279
|
+
};
|
|
280
|
+
//#endregion
|
|
281
|
+
export { lineSetupAdapter as n, hasLineCredentials as r, lineSetupWizard as t };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/line",
|
|
3
|
-
"version": "2026.5.
|
|
3
|
+
"version": "2026.5.3-beta.1",
|
|
4
4
|
"description": "OpenClaw LINE channel plugin",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"openclaw": "workspace:*"
|
|
16
16
|
},
|
|
17
17
|
"peerDependencies": {
|
|
18
|
-
"openclaw": ">=2026.5.
|
|
18
|
+
"openclaw": ">=2026.5.3-beta.1"
|
|
19
19
|
},
|
|
20
20
|
"peerDependenciesMeta": {
|
|
21
21
|
"openclaw": {
|
|
@@ -45,14 +45,22 @@
|
|
|
45
45
|
"minHostVersion": ">=2026.4.10"
|
|
46
46
|
},
|
|
47
47
|
"compat": {
|
|
48
|
-
"pluginApi": ">=2026.5.
|
|
48
|
+
"pluginApi": ">=2026.5.3-beta.1"
|
|
49
49
|
},
|
|
50
50
|
"build": {
|
|
51
|
-
"openclawVersion": "2026.5.
|
|
51
|
+
"openclawVersion": "2026.5.3-beta.1"
|
|
52
52
|
},
|
|
53
53
|
"release": {
|
|
54
54
|
"publishToClawHub": true,
|
|
55
55
|
"publishToNpm": true
|
|
56
|
-
}
|
|
57
|
-
|
|
56
|
+
},
|
|
57
|
+
"runtimeExtensions": [
|
|
58
|
+
"./dist/index.js"
|
|
59
|
+
],
|
|
60
|
+
"runtimeSetupEntry": "./dist/setup-entry.js"
|
|
61
|
+
},
|
|
62
|
+
"files": [
|
|
63
|
+
"dist/**",
|
|
64
|
+
"openclaw.plugin.json"
|
|
65
|
+
]
|
|
58
66
|
}
|
package/api.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export type {
|
|
2
|
-
ChannelAccountSnapshot,
|
|
3
|
-
ChannelPlugin,
|
|
4
|
-
OpenClawConfig,
|
|
5
|
-
OpenClawPluginApi,
|
|
6
|
-
PluginRuntime,
|
|
7
|
-
} from "openclaw/plugin-sdk/core";
|
|
8
|
-
export type { ReplyPayload } from "openclaw/plugin-sdk/reply-runtime";
|
|
9
|
-
export type { ResolvedLineAccount } from "./runtime-api.js";
|
|
10
|
-
export { linePlugin } from "./src/channel.js";
|
|
11
|
-
export { lineSetupPlugin } from "./src/channel.setup.js";
|
package/channel-plugin-api.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { linePlugin } from "./src/channel.js";
|
package/contract-api.ts
DELETED
package/index.ts
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
defineBundledChannelEntry,
|
|
3
|
-
type OpenClawPluginCommandDefinition,
|
|
4
|
-
type OpenClawPluginApi,
|
|
5
|
-
} from "openclaw/plugin-sdk/channel-entry-contract";
|
|
6
|
-
|
|
7
|
-
type RegisteredLineCardCommand = OpenClawPluginCommandDefinition;
|
|
8
|
-
|
|
9
|
-
let lineCardCommandPromise: Promise<RegisteredLineCardCommand> | null = null;
|
|
10
|
-
|
|
11
|
-
async function loadLineCardCommand(api: OpenClawPluginApi): Promise<RegisteredLineCardCommand> {
|
|
12
|
-
lineCardCommandPromise ??= (async () => {
|
|
13
|
-
let registered: RegisteredLineCardCommand | null = null;
|
|
14
|
-
const { registerLineCardCommand } = await import("./src/card-command.js");
|
|
15
|
-
registerLineCardCommand({
|
|
16
|
-
...api,
|
|
17
|
-
registerCommand(command: RegisteredLineCardCommand) {
|
|
18
|
-
registered = command;
|
|
19
|
-
},
|
|
20
|
-
});
|
|
21
|
-
if (!registered) {
|
|
22
|
-
throw new Error("LINE card command registration unavailable");
|
|
23
|
-
}
|
|
24
|
-
return registered;
|
|
25
|
-
})();
|
|
26
|
-
return await lineCardCommandPromise;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export default defineBundledChannelEntry({
|
|
30
|
-
id: "line",
|
|
31
|
-
name: "LINE",
|
|
32
|
-
description: "LINE Messaging API channel plugin",
|
|
33
|
-
importMetaUrl: import.meta.url,
|
|
34
|
-
plugin: {
|
|
35
|
-
specifier: "./channel-plugin-api.js",
|
|
36
|
-
exportName: "linePlugin",
|
|
37
|
-
},
|
|
38
|
-
runtime: {
|
|
39
|
-
specifier: "./runtime-api.js",
|
|
40
|
-
exportName: "setLineRuntime",
|
|
41
|
-
},
|
|
42
|
-
registerFull(api) {
|
|
43
|
-
api.registerCommand({
|
|
44
|
-
name: "card",
|
|
45
|
-
description: "Send a rich card message (LINE).",
|
|
46
|
-
acceptsArgs: true,
|
|
47
|
-
requireAuth: false,
|
|
48
|
-
async handler(ctx) {
|
|
49
|
-
const command = await loadLineCardCommand(api);
|
|
50
|
-
return await command.handler(ctx);
|
|
51
|
-
},
|
|
52
|
-
});
|
|
53
|
-
},
|
|
54
|
-
});
|
package/runtime-api.ts
DELETED
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
// Private runtime barrel for the bundled LINE extension.
|
|
2
|
-
// Keep this barrel thin and aligned with the local extension surface.
|
|
3
|
-
|
|
4
|
-
export type {
|
|
5
|
-
ChannelAccountSnapshot,
|
|
6
|
-
ChannelPlugin,
|
|
7
|
-
OpenClawConfig,
|
|
8
|
-
OpenClawPluginApi,
|
|
9
|
-
PluginRuntime,
|
|
10
|
-
} from "openclaw/plugin-sdk/core";
|
|
11
|
-
export type {
|
|
12
|
-
ChannelGatewayContext,
|
|
13
|
-
ChannelStatusIssue,
|
|
14
|
-
} from "openclaw/plugin-sdk/channel-contract";
|
|
15
|
-
export { clearAccountEntryFields } from "openclaw/plugin-sdk/core";
|
|
16
|
-
export { buildChannelConfigSchema } from "openclaw/plugin-sdk/channel-config-schema";
|
|
17
|
-
export type { ReplyPayload } from "openclaw/plugin-sdk/reply-runtime";
|
|
18
|
-
export type { ChannelSetupDmPolicy, ChannelSetupWizard } from "openclaw/plugin-sdk/setup";
|
|
19
|
-
export {
|
|
20
|
-
buildComputedAccountStatusSnapshot,
|
|
21
|
-
buildTokenChannelStatusSummary,
|
|
22
|
-
} from "openclaw/plugin-sdk/status-helpers";
|
|
23
|
-
export {
|
|
24
|
-
DEFAULT_ACCOUNT_ID,
|
|
25
|
-
formatDocsLink,
|
|
26
|
-
setSetupChannelEnabled,
|
|
27
|
-
splitSetupEntries,
|
|
28
|
-
} from "openclaw/plugin-sdk/setup";
|
|
29
|
-
export { setLineRuntime } from "./src/runtime.js";
|
|
30
|
-
export {
|
|
31
|
-
firstDefined,
|
|
32
|
-
isSenderAllowed,
|
|
33
|
-
normalizeAllowFrom,
|
|
34
|
-
normalizeDmAllowFromWithStore,
|
|
35
|
-
} from "./src/bot-access.js";
|
|
36
|
-
export { downloadLineMedia } from "./src/download.js";
|
|
37
|
-
export { probeLineBot } from "./src/probe.js";
|
|
38
|
-
export { buildTemplateMessageFromPayload } from "./src/template-messages.js";
|
|
39
|
-
export {
|
|
40
|
-
createQuickReplyItems,
|
|
41
|
-
pushFlexMessage,
|
|
42
|
-
pushLocationMessage,
|
|
43
|
-
pushMessageLine,
|
|
44
|
-
pushMessagesLine,
|
|
45
|
-
pushTemplateMessage,
|
|
46
|
-
pushTextMessageWithQuickReplies,
|
|
47
|
-
sendMessageLine,
|
|
48
|
-
} from "./src/send.js";
|
|
49
|
-
export { monitorLineProvider } from "./src/monitor.js";
|
|
50
|
-
export { hasLineDirectives, parseLineDirectives } from "./src/reply-payload-transform.js";
|
|
51
|
-
export {
|
|
52
|
-
listLineAccountIds,
|
|
53
|
-
normalizeAccountId,
|
|
54
|
-
resolveDefaultLineAccountId,
|
|
55
|
-
resolveLineAccount,
|
|
56
|
-
} from "./src/accounts.js";
|
|
57
|
-
export { type NormalizedAllowFrom } from "./src/bot-access.js";
|
|
58
|
-
export { resolveLineChannelAccessToken } from "./src/channel-access-token.js";
|
|
59
|
-
export {
|
|
60
|
-
LineChannelConfigSchema,
|
|
61
|
-
LineConfigSchema,
|
|
62
|
-
type LineConfigSchemaType,
|
|
63
|
-
} from "./src/config-schema.js";
|
|
64
|
-
export {
|
|
65
|
-
resolveExactLineGroupConfigKey,
|
|
66
|
-
resolveLineGroupConfigEntry,
|
|
67
|
-
resolveLineGroupLookupIds,
|
|
68
|
-
resolveLineGroupsConfig,
|
|
69
|
-
} from "./src/group-keys.js";
|
|
70
|
-
export {
|
|
71
|
-
type CodeBlock,
|
|
72
|
-
convertCodeBlockToFlexBubble,
|
|
73
|
-
convertLinksToFlexBubble,
|
|
74
|
-
convertTableToFlexBubble,
|
|
75
|
-
extractCodeBlocks,
|
|
76
|
-
extractLinks,
|
|
77
|
-
extractMarkdownTables,
|
|
78
|
-
hasMarkdownToConvert,
|
|
79
|
-
type MarkdownLink,
|
|
80
|
-
type MarkdownTable,
|
|
81
|
-
type ProcessedLineMessage,
|
|
82
|
-
processLineMessage,
|
|
83
|
-
stripMarkdown,
|
|
84
|
-
} from "./src/markdown-to-line.js";
|
|
85
|
-
export {
|
|
86
|
-
createAudioMessage,
|
|
87
|
-
createFlexMessage,
|
|
88
|
-
createImageMessage,
|
|
89
|
-
createLocationMessage,
|
|
90
|
-
createTextMessageWithQuickReplies,
|
|
91
|
-
createVideoMessage,
|
|
92
|
-
getUserDisplayName,
|
|
93
|
-
getUserProfile,
|
|
94
|
-
pushImageMessage,
|
|
95
|
-
replyMessageLine,
|
|
96
|
-
showLoadingAnimation,
|
|
97
|
-
} from "./src/send.js";
|
|
98
|
-
export { validateLineSignature } from "./src/signature.js";
|
|
99
|
-
export {
|
|
100
|
-
type ButtonsTemplate,
|
|
101
|
-
type CarouselColumn,
|
|
102
|
-
type CarouselTemplate,
|
|
103
|
-
type ConfirmTemplate,
|
|
104
|
-
createButtonMenu,
|
|
105
|
-
createButtonTemplate,
|
|
106
|
-
createCarouselColumn,
|
|
107
|
-
createConfirmTemplate,
|
|
108
|
-
createImageCarousel,
|
|
109
|
-
createImageCarouselColumn,
|
|
110
|
-
createLinkMenu,
|
|
111
|
-
createProductCarousel,
|
|
112
|
-
createTemplateCarousel,
|
|
113
|
-
createYesNoConfirm,
|
|
114
|
-
type ImageCarouselColumn,
|
|
115
|
-
type ImageCarouselTemplate,
|
|
116
|
-
type TemplateMessage,
|
|
117
|
-
} from "./src/template-messages.js";
|
|
118
|
-
export type {
|
|
119
|
-
LineChannelData,
|
|
120
|
-
LineConfig,
|
|
121
|
-
LineProbeResult,
|
|
122
|
-
ResolvedLineAccount,
|
|
123
|
-
} from "./src/types.js";
|
|
124
|
-
export { createLineNodeWebhookHandler, readLineWebhookRequestBody } from "./src/webhook-node.js";
|
|
125
|
-
export {
|
|
126
|
-
createLineWebhookMiddleware,
|
|
127
|
-
type LineWebhookOptions,
|
|
128
|
-
startLineWebhook,
|
|
129
|
-
type StartLineWebhookOptions,
|
|
130
|
-
} from "./src/webhook.js";
|
|
131
|
-
export { parseLineWebhookBody } from "./src/webhook-utils.js";
|
|
132
|
-
export { datetimePickerAction, messageAction, postbackAction, uriAction } from "./src/actions.js";
|
|
133
|
-
export type { Action } from "./src/actions.js";
|
|
134
|
-
export {
|
|
135
|
-
createActionCard,
|
|
136
|
-
createAgendaCard,
|
|
137
|
-
createAppleTvRemoteCard,
|
|
138
|
-
createCarousel,
|
|
139
|
-
createDeviceControlCard,
|
|
140
|
-
createEventCard,
|
|
141
|
-
createImageCard,
|
|
142
|
-
createInfoCard,
|
|
143
|
-
createListCard,
|
|
144
|
-
createMediaPlayerCard,
|
|
145
|
-
createNotificationBubble,
|
|
146
|
-
createReceiptCard,
|
|
147
|
-
toFlexMessage,
|
|
148
|
-
} from "./src/flex-templates.js";
|
|
149
|
-
export type {
|
|
150
|
-
CardAction,
|
|
151
|
-
FlexBox,
|
|
152
|
-
FlexBubble,
|
|
153
|
-
FlexButton,
|
|
154
|
-
FlexCarousel,
|
|
155
|
-
FlexComponent,
|
|
156
|
-
FlexContainer,
|
|
157
|
-
FlexImage,
|
|
158
|
-
FlexText,
|
|
159
|
-
ListItem,
|
|
160
|
-
} from "./src/flex-templates.js";
|
|
161
|
-
export {
|
|
162
|
-
cancelDefaultRichMenu,
|
|
163
|
-
createDefaultMenuConfig,
|
|
164
|
-
createGridLayout,
|
|
165
|
-
createRichMenu,
|
|
166
|
-
createRichMenuAlias,
|
|
167
|
-
deleteRichMenu,
|
|
168
|
-
deleteRichMenuAlias,
|
|
169
|
-
getDefaultRichMenuId,
|
|
170
|
-
getRichMenu,
|
|
171
|
-
getRichMenuIdOfUser,
|
|
172
|
-
getRichMenuList,
|
|
173
|
-
linkRichMenuToUser,
|
|
174
|
-
linkRichMenuToUsers,
|
|
175
|
-
setDefaultRichMenu,
|
|
176
|
-
unlinkRichMenuFromUser,
|
|
177
|
-
unlinkRichMenuFromUsers,
|
|
178
|
-
uploadRichMenuImage,
|
|
179
|
-
} from "./src/rich-menu.js";
|
|
180
|
-
export type {
|
|
181
|
-
CreateRichMenuParams,
|
|
182
|
-
RichMenuArea,
|
|
183
|
-
RichMenuAreaRequest,
|
|
184
|
-
RichMenuRequest,
|
|
185
|
-
RichMenuResponse,
|
|
186
|
-
RichMenuSize,
|
|
187
|
-
} from "./src/rich-menu.js";
|
package/secret-contract-api.ts
DELETED
package/setup-api.ts
DELETED
package/setup-entry.ts
DELETED
package/src/account-helpers.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
type LineCredentialAccount = {
|
|
2
|
-
channelAccessToken?: string;
|
|
3
|
-
channelSecret?: string;
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
export function hasLineCredentials(account: LineCredentialAccount): boolean {
|
|
7
|
-
return Boolean(account.channelAccessToken?.trim() && account.channelSecret?.trim());
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export function parseLineAllowFromId(raw: string): string | null {
|
|
11
|
-
const trimmed = raw.trim().replace(/^line:(?:user:)?/i, "");
|
|
12
|
-
if (!/^U[a-f0-9]{32}$/i.test(trimmed)) {
|
|
13
|
-
return null;
|
|
14
|
-
}
|
|
15
|
-
return trimmed;
|
|
16
|
-
}
|