@rlynicrisis/link 0.1.2 → 0.1.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.
- package/package.json +1 -1
- package/src/onboarding.ts +76 -32
package/package.json
CHANGED
package/src/onboarding.ts
CHANGED
|
@@ -4,6 +4,7 @@ import type {
|
|
|
4
4
|
WizardPrompter,
|
|
5
5
|
} from "openclaw/plugin-sdk";
|
|
6
6
|
import type { LinkConfig } from "./types.js";
|
|
7
|
+
import { LINK_DEFAULTS } from "./types.js";
|
|
7
8
|
|
|
8
9
|
const channel = "link" as const;
|
|
9
10
|
|
|
@@ -15,15 +16,19 @@ export const linkOnboardingAdapter: ChannelOnboardingAdapter = {
|
|
|
15
16
|
channel,
|
|
16
17
|
getStatus: async ({ cfg }) => {
|
|
17
18
|
const linkCfg = getLinkConfig(cfg);
|
|
18
|
-
const configured = Boolean(
|
|
19
|
-
linkCfg?.host && linkCfg?.accessToken
|
|
20
|
-
);
|
|
19
|
+
const configured = Boolean(linkCfg?.accessToken);
|
|
21
20
|
|
|
22
21
|
const statusLines: string[] = [];
|
|
23
22
|
if (!configured) {
|
|
24
|
-
statusLines.push("Link: needs
|
|
23
|
+
statusLines.push("Link: needs accessToken");
|
|
24
|
+
} else if (linkCfg?.groupId) {
|
|
25
|
+
statusLines.push(
|
|
26
|
+
`Link: group mode (groupId: ${linkCfg.groupId}, host: ${linkCfg.host ?? LINK_DEFAULTS.host})`
|
|
27
|
+
);
|
|
25
28
|
} else {
|
|
26
|
-
statusLines.push(
|
|
29
|
+
statusLines.push(
|
|
30
|
+
`Link: FileHelper mode (host: ${linkCfg?.host ?? LINK_DEFAULTS.host})`
|
|
31
|
+
);
|
|
27
32
|
}
|
|
28
33
|
|
|
29
34
|
return {
|
|
@@ -37,44 +42,89 @@ export const linkOnboardingAdapter: ChannelOnboardingAdapter = {
|
|
|
37
42
|
|
|
38
43
|
configure: async ({ cfg, prompter }) => {
|
|
39
44
|
let next = cfg;
|
|
40
|
-
const linkCfg = getLinkConfig(next) || {} as LinkConfig;
|
|
41
|
-
|
|
42
|
-
const host = await prompter.text({
|
|
43
|
-
message: "Link Server Host (host:port)",
|
|
44
|
-
initialValue: linkCfg.host,
|
|
45
|
-
placeholder: "e.g. embtcpbeta.bingolink.biz:20081",
|
|
46
|
-
validate: (value) => (value?.trim() ? undefined : "Required"),
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
// Remove separate port prompt, as it is merged into host
|
|
50
|
-
// const portStr = ...
|
|
45
|
+
const linkCfg = getLinkConfig(next) || ({} as LinkConfig);
|
|
51
46
|
|
|
47
|
+
// ── 必填:Access Token ─────────────────────────────────────────
|
|
52
48
|
const accessToken = await prompter.text({
|
|
53
49
|
message: "User Access Token",
|
|
54
50
|
initialValue: linkCfg.accessToken,
|
|
55
51
|
validate: (value) => (value?.trim() ? undefined : "Required"),
|
|
56
52
|
});
|
|
57
53
|
|
|
54
|
+
// ── 可选:Refresh Token ────────────────────────────────────────
|
|
58
55
|
const refreshToken = await prompter.text({
|
|
59
|
-
|
|
60
|
-
|
|
56
|
+
message: "Refresh Token (Optional — used for auto token renewal)",
|
|
57
|
+
initialValue: linkCfg.refreshToken,
|
|
61
58
|
});
|
|
62
59
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
60
|
+
// ── 可选:消息服务地址(有默认值)────────────────────────────────
|
|
61
|
+
const host = await prompter.text({
|
|
62
|
+
message: "Link Server Host (Optional)",
|
|
63
|
+
initialValue: linkCfg.host,
|
|
64
|
+
placeholder: `default: ${LINK_DEFAULTS.host}`,
|
|
67
65
|
});
|
|
68
66
|
|
|
69
|
-
|
|
67
|
+
// ── 模式选择 ───────────────────────────────────────────────────
|
|
68
|
+
const currentMode = linkCfg.groupId ? "group" : "filehelper";
|
|
69
|
+
const mode = await prompter.select({
|
|
70
|
+
message: "Access mode",
|
|
71
|
+
options: [
|
|
72
|
+
{
|
|
73
|
+
value: "filehelper",
|
|
74
|
+
label: "FileHelper — receive self-sent messages only (default)",
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
value: "group",
|
|
78
|
+
label: "Group Bot — monitor a group and reply via Webhook",
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
initialValue: currentMode,
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
let newLinkConfig: LinkConfig = {
|
|
70
85
|
...linkCfg,
|
|
71
|
-
host: String(host).trim(),
|
|
72
|
-
// port is now part of host string or handled internally
|
|
73
86
|
accessToken: String(accessToken).trim(),
|
|
74
87
|
refreshToken: refreshToken ? String(refreshToken).trim() : undefined,
|
|
75
|
-
|
|
88
|
+
host: host ? String(host).trim() : undefined,
|
|
89
|
+
// Clear group fields; re-populate below if group mode
|
|
90
|
+
groupId: undefined,
|
|
91
|
+
botToken: undefined,
|
|
92
|
+
notificationApiUrl: undefined,
|
|
76
93
|
};
|
|
77
94
|
|
|
95
|
+
if (mode === "group") {
|
|
96
|
+
// ── 群组模式:群 ID(必填)───────────────────────────────────
|
|
97
|
+
const groupId = await prompter.text({
|
|
98
|
+
message: "Group ID (groupId)",
|
|
99
|
+
initialValue: linkCfg.groupId,
|
|
100
|
+
placeholder: "e.g. 3ab33646-3a55-46fd-97ba-868d4bf29915",
|
|
101
|
+
validate: (value) => (value?.trim() ? undefined : "Required"),
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// ── 群机器人 Webhook Token(必填)────────────────────────────
|
|
105
|
+
const botToken = await prompter.text({
|
|
106
|
+
message: "Group Bot Webhook Token (botToken)",
|
|
107
|
+
initialValue: linkCfg.botToken,
|
|
108
|
+
validate: (value) => (value?.trim() ? undefined : "Required"),
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
// ── Webhook 地址(有默认值)───────────────────────────────────
|
|
112
|
+
const notificationApiUrl = await prompter.text({
|
|
113
|
+
message: "Notification API URL (Optional)",
|
|
114
|
+
initialValue: linkCfg.notificationApiUrl,
|
|
115
|
+
placeholder: `default: ${LINK_DEFAULTS.notificationApiUrl}`,
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
newLinkConfig = {
|
|
119
|
+
...newLinkConfig,
|
|
120
|
+
groupId: String(groupId).trim(),
|
|
121
|
+
botToken: String(botToken).trim(),
|
|
122
|
+
notificationApiUrl: notificationApiUrl
|
|
123
|
+
? String(notificationApiUrl).trim()
|
|
124
|
+
: undefined,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
78
128
|
next = {
|
|
79
129
|
...next,
|
|
80
130
|
channels: {
|
|
@@ -87,12 +137,6 @@ export const linkOnboardingAdapter: ChannelOnboardingAdapter = {
|
|
|
87
137
|
},
|
|
88
138
|
|
|
89
139
|
disable: (cfg) => {
|
|
90
|
-
// To disable, we might just remove the config or set a disabled flag if supported.
|
|
91
|
-
// Since LinkConfig doesn't have an 'enabled' flag in the type definition yet,
|
|
92
|
-
// we can just return the config as is or remove the link section.
|
|
93
|
-
// However, usually 'enabled' is checked at the framework level or added to the config.
|
|
94
|
-
// For now, let's just return the config.
|
|
95
|
-
// Better yet, let's remove the link config to effectively disable it since we don't have an enabled flag.
|
|
96
140
|
const { link, ...otherChannels } = cfg.channels || {};
|
|
97
141
|
return {
|
|
98
142
|
...cfg,
|