@rlynicrisis/link 0.1.2 → 0.1.3

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 (2) hide show
  1. package/package.json +1 -1
  2. package/src/onboarding.ts +76 -32
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rlynicrisis/link",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "type": "module",
5
5
  "description": "OpenClaw Link channel plugin",
6
6
  "files": [
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 host and accessToken");
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(`Link: configured (host: ${linkCfg?.host})`);
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
- message: "Refresh Token (Optional)",
60
- initialValue: linkCfg.refreshToken,
56
+ message: "Refresh Token (Optional — used for auto token renewal)",
57
+ initialValue: linkCfg.refreshToken,
61
58
  });
62
59
 
63
- const ssoUrl = await prompter.text({
64
- message: "SSO URL (Optional, for refresh)",
65
- initialValue: linkCfg.ssoUrl,
66
- placeholder: "e.g. https://sso.example.com",
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
- const newLinkConfig: LinkConfig = {
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
- ssoUrl: ssoUrl ? String(ssoUrl).trim() : undefined,
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,