@feihan-im/openclaw-plugin 0.1.15 → 0.1.17

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/src/channel.ts CHANGED
@@ -5,12 +5,15 @@ import {
5
5
  createChatChannelPlugin,
6
6
  createChannelPluginBase,
7
7
  } from "openclaw/plugin-sdk/core";
8
+ import { createHybridChannelConfigBase } from "openclaw/plugin-sdk/channel-config-helpers";
8
9
  import type { OpenClawConfig } from "openclaw/plugin-sdk/core";
9
10
  import { listAccountIds, resolveAccountConfig } from "./config.js";
10
11
  import { sendText } from "./messaging/outbound.js";
11
12
  import { parseTarget } from "./targets.js";
12
13
  import type { FeihanAccountConfig } from "./types.js";
13
14
 
15
+ const BASE_FIELDS = ["appId", "appSecret", "backendUrl", "enabled", "enableEncryption", "requestTimeout"];
16
+
14
17
  export const base = createChannelPluginBase<FeihanAccountConfig>({
15
18
  id: "feihan",
16
19
 
@@ -28,37 +31,42 @@ export const base = createChannelPluginBase<FeihanAccountConfig>({
28
31
  },
29
32
 
30
33
  config: {
31
- listAccountIds: (cfg: OpenClawConfig) => listAccountIds(cfg),
32
- resolveAccount: (cfg: OpenClawConfig, accountId?: string | null) =>
33
- resolveAccountConfig(cfg, accountId ?? undefined),
34
- inspectAccount(cfg: OpenClawConfig, accountId?: string | null) {
35
- const resolved = resolveAccountConfig(cfg, accountId ?? undefined);
36
- const hasConfig = Boolean(
37
- resolved.appId && resolved.appSecret && resolved.backendUrl,
38
- );
39
- return {
40
- enabled: resolved.enabled,
41
- configured: hasConfig,
42
- tokenStatus: hasConfig ? "available" : "missing",
43
- };
44
- },
34
+ ...createHybridChannelConfigBase<FeihanAccountConfig>({
35
+ sectionKey: "feihan",
36
+ listAccountIds: (cfg) => listAccountIds(cfg),
37
+ resolveAccount: (cfg, accountId) =>
38
+ resolveAccountConfig(cfg, accountId ?? undefined),
39
+ defaultAccountId: () => "default",
40
+ inspectAccount(cfg, accountId) {
41
+ const resolved = resolveAccountConfig(cfg, accountId ?? undefined);
42
+ const hasConfig = Boolean(
43
+ resolved.appId && resolved.appSecret && resolved.backendUrl,
44
+ );
45
+ return {
46
+ enabled: resolved.enabled,
47
+ configured: hasConfig,
48
+ tokenStatus: hasConfig ? "available" : "missing",
49
+ };
50
+ },
51
+ clearBaseFields: BASE_FIELDS,
52
+ }),
45
53
  },
46
54
 
47
55
  setup: {
48
56
  validateInput: ({ input }) => {
49
57
  const missing: string[] = [];
50
- if (!input.appToken) missing.push("--app-token (App ID)");
51
- if (!input.token) missing.push("--token (App Secret)");
52
- if (!input.url) missing.push("--url (Backend URL)");
58
+ if (!input.appToken) missing.push("--app-token (App ID from Admin Console)");
59
+ if (!input.token) missing.push("--token (App Secret from Admin Console)");
60
+ if (!input.url) missing.push("--url (your Feihan server address)");
53
61
  if (missing.length > 0) {
54
62
  return [
55
63
  `Missing required flags: ${missing.join(", ")}`,
56
64
  "",
57
- "Either provide all flags:",
65
+ "Usage:",
58
66
  ` openclaw channels add --channel feihan --app-token <APP_ID> --token <APP_SECRET> --url <BACKEND_URL>`,
59
67
  "",
60
- "Or use the interactive wizard:",
61
- " openclaw channels add",
68
+ "You can find App ID and App Secret in:",
69
+ " Feihan Admin Console → Workplace → App Management → App Details",
62
70
  ].join("\n");
63
71
  }
64
72
  return null;
@@ -76,21 +84,15 @@ export const base = createChannelPluginBase<FeihanAccountConfig>({
76
84
  const appSecret = input.token;
77
85
  const backendUrl = input.url;
78
86
 
79
- if (accountId && accountId !== "default") {
80
- // Multi-account: write under accounts.<accountId>
81
- if (!section.accounts) section.accounts = {};
82
- const accounts = section.accounts as Record<string, Record<string, unknown>>;
83
- if (!accounts[accountId]) accounts[accountId] = {};
84
- const account = accounts[accountId];
85
- if (appId) account.appId = appId;
86
- if (appSecret) account.appSecret = appSecret;
87
- if (backendUrl) account.backendUrl = backendUrl;
88
- } else {
89
- // Single-account: write at top level
90
- if (appId) section.appId = appId;
91
- if (appSecret) section.appSecret = appSecret;
92
- if (backendUrl) section.backendUrl = backendUrl;
93
- }
87
+ const id = accountId || "default";
88
+
89
+ if (!section.accounts) section.accounts = {};
90
+ const accounts = section.accounts as Record<string, Record<string, unknown>>;
91
+ if (!accounts[id]) accounts[id] = {};
92
+ const account = accounts[id];
93
+ if (appId) account.appId = appId;
94
+ if (appSecret) account.appSecret = appSecret;
95
+ if (backendUrl) account.backendUrl = backendUrl;
94
96
 
95
97
  return updated as OpenClawConfig;
96
98
  },
@@ -117,7 +119,8 @@ export const base = createChannelPluginBase<FeihanAccountConfig>({
117
119
  preferredEnvVar: "FEIHAN_APP_ID",
118
120
  envPrompt: "Use FEIHAN_APP_ID from environment?",
119
121
  keepPrompt: "Keep current App ID?",
120
- inputPrompt: "Enter your Feihan App ID:",
122
+ inputPrompt:
123
+ "Enter App ID (from Feihan Admin Console → Workplace → App Management → App Details):",
121
124
  inspect: ({ cfg, accountId }) => {
122
125
  const resolved = resolveAccountConfig(cfg, accountId ?? undefined);
123
126
  return {
@@ -133,7 +136,8 @@ export const base = createChannelPluginBase<FeihanAccountConfig>({
133
136
  preferredEnvVar: "FEIHAN_APP_SECRET",
134
137
  envPrompt: "Use FEIHAN_APP_SECRET from environment?",
135
138
  keepPrompt: "Keep current App Secret?",
136
- inputPrompt: "Enter your Feihan App Secret:",
139
+ inputPrompt:
140
+ "Enter App Secret (from the same App Details page, keep this value confidential):",
137
141
  inspect: ({ cfg, accountId }) => {
138
142
  const resolved = resolveAccountConfig(cfg, accountId ?? undefined);
139
143
  return {
@@ -145,11 +149,12 @@ export const base = createChannelPluginBase<FeihanAccountConfig>({
145
149
  {
146
150
  inputKey: "url",
147
151
  providerHint: "feihan",
148
- credentialLabel: "Backend URL",
152
+ credentialLabel: "Feihan Server URL",
149
153
  preferredEnvVar: "FEIHAN_BACKEND_URL",
150
154
  envPrompt: "Use FEIHAN_BACKEND_URL from environment?",
151
- keepPrompt: "Keep current Backend URL?",
152
- inputPrompt: "Enter your Feihan backend server URL:",
155
+ keepPrompt: "Keep current Feihan Server URL?",
156
+ inputPrompt:
157
+ "Enter your Feihan server address (e.g. http://192.168.10.10:21000):",
153
158
  inspect: ({ cfg, accountId }) => {
154
159
  const resolved = resolveAccountConfig(cfg, accountId ?? undefined);
155
160
  return {
@@ -16,8 +16,8 @@ describe("listAccountIds", () => {
16
16
  expect(listAccountIds(undefined)).toEqual([]);
17
17
  });
18
18
 
19
- it("returns ['default'] for flat single-account config", () => {
20
- const cfg = { channels: { feihan: { appId: "app_1" } } };
19
+ it("returns ['default'] for single-account config", () => {
20
+ const cfg = { channels: { feihan: { accounts: { default: { appId: "app_1" } } } } };
21
21
  expect(listAccountIds(cfg)).toEqual(["default"]);
22
22
  });
23
23
 
@@ -48,13 +48,17 @@ describe("listAccountIds", () => {
48
48
  });
49
49
 
50
50
  describe("resolveAccountConfig", () => {
51
- it("resolves flat config with defaults applied", () => {
51
+ it("resolves default account with defaults applied", () => {
52
52
  const cfg = {
53
53
  channels: {
54
54
  feihan: {
55
- appId: "app_1",
56
- appSecret: "secret_1",
57
- backendUrl: "https://your-backend-url.com",
55
+ accounts: {
56
+ default: {
57
+ appId: "app_1",
58
+ appSecret: "secret_1",
59
+ backendUrl: "https://your-backend-url.com",
60
+ },
61
+ },
58
62
  },
59
63
  },
60
64
  };
@@ -118,7 +122,7 @@ describe("resolveAccountConfig", () => {
118
122
  it("config values take precedence over env vars", () => {
119
123
  process.env.FEIHAN_APP_ID = "env_app";
120
124
  const cfg = {
121
- channels: { feihan: { appId: "config_app", appSecret: "s", backendUrl: "http://x" } },
125
+ channels: { feihan: { accounts: { default: { appId: "config_app", appSecret: "s", backendUrl: "http://x" } } } },
122
126
  };
123
127
  try {
124
128
  const account = resolveAccountConfig(cfg);
@@ -205,9 +209,13 @@ describe("resolveAndValidateAccountConfig", () => {
205
209
  const cfg = {
206
210
  channels: {
207
211
  feihan: {
208
- appId: "app_1",
209
- appSecret: "secret_1",
210
- backendUrl: "https://your-backend-url.com",
212
+ accounts: {
213
+ default: {
214
+ appId: "app_1",
215
+ appSecret: "secret_1",
216
+ backendUrl: "https://your-backend-url.com",
217
+ },
218
+ },
211
219
  },
212
220
  },
213
221
  };
package/src/config.ts CHANGED
@@ -45,7 +45,6 @@ export function listAccountIds(cfg: unknown): string[] {
45
45
  return [];
46
46
  }
47
47
  if (ch.accounts) return Object.keys(ch.accounts);
48
- if (ch.appId) return ["default"];
49
48
  // env var fallback
50
49
  if (process.env[`${ENV_PREFIX}APP_ID`]) return ["default"];
51
50
  return [];
@@ -59,7 +58,7 @@ export function resolveAccountConfig(
59
58
  const id = accountId ?? "default";
60
59
  const envConfig = readEnvConfig();
61
60
 
62
- const raw = ch?.accounts?.[id] ?? ch;
61
+ const raw = ch?.accounts?.[id];
63
62
 
64
63
  return {
65
64
  accountId: id,
package/src/index.test.ts CHANGED
@@ -151,7 +151,7 @@ describe("service start — config validation", () => {
151
151
  it("connects valid accounts normally", async () => {
152
152
  const api = createMockApi({
153
153
  channels: {
154
- feihan: { appId: "a", appSecret: "s", backendUrl: "https://ok.io" },
154
+ feihan: { accounts: { default: { appId: "a", appSecret: "s", backendUrl: "https://ok.io" } } },
155
155
  },
156
156
  });
157
157
  entry.default.registerFull(api);
package/src/types.ts CHANGED
@@ -23,12 +23,6 @@ export interface FeihanRawAccountConfig {
23
23
  }
24
24
 
25
25
  export interface FeihanChannelConfig {
26
- appId?: string;
27
- appSecret?: string;
28
- backendUrl?: string;
29
- enabled?: boolean;
30
- enableEncryption?: boolean;
31
- requestTimeout?: number;
32
26
  accounts?: Record<string, FeihanRawAccountConfig>;
33
27
  }
34
28