bereach-openclaw 0.2.0

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.
@@ -0,0 +1,75 @@
1
+ import type { Bereach } from "bereach";
2
+
3
+ /**
4
+ * Registers auto-reply commands and CLI commands.
5
+ * Auto-reply commands execute without invoking the LLM.
6
+ */
7
+ export function registerCommands(api: any, client: Bereach) {
8
+ api.registerCommand({
9
+ name: "bereach-credits",
10
+ description: "Show current BeReach credit balance",
11
+ handler: async () => {
12
+ const res = await (client as any).profile.getCredits();
13
+ const c = res.credits;
14
+ return {
15
+ text: [
16
+ `BeReach Credits: ${c.current}/${c.limit} used (${c.percentage}%)`,
17
+ `Remaining: ${c.remaining}`,
18
+ ].join("\n"),
19
+ };
20
+ },
21
+ });
22
+
23
+ api.registerCommand({
24
+ name: "bereach-status",
25
+ description: "Show LinkedIn rate limit summary",
26
+ handler: async () => {
27
+ const res = await (client as any).profile.getLimits();
28
+ const lines = ["BeReach Rate Limits:"];
29
+ for (const [action, data] of Object.entries(res.limits) as [string, any][]) {
30
+ const d = data.daily;
31
+ lines.push(` ${action}: ${d.current}/${d.limit} daily (${d.remaining} remaining)`);
32
+ }
33
+ return { text: lines.join("\n") };
34
+ },
35
+ });
36
+
37
+ api.registerCommand({
38
+ name: "bereach-limits",
39
+ description: "Show detailed per-action LinkedIn rate limits",
40
+ handler: async () => {
41
+ const res = await (client as any).profile.getLimits();
42
+ const lines = [`BeReach Rate Limits (multiplier: ${res.multiplier}x):`];
43
+ for (const [action, data] of Object.entries(res.limits) as [string, any][]) {
44
+ const d = data.daily;
45
+ const w = data.weekly;
46
+ lines.push(`\n ${action}:`);
47
+ lines.push(` Daily: ${d.current}/${d.limit} (${d.remaining} remaining, resets ${data.nextResetDaily})`);
48
+ if (w) {
49
+ lines.push(` Weekly: ${w.current}/${w.limit} (${w.remaining} remaining, resets ${data.nextResetWeekly})`);
50
+ }
51
+ lines.push(` Min interval: ${data.minIntervalSeconds}s`);
52
+ }
53
+ return { text: lines.join("\n") };
54
+ },
55
+ });
56
+
57
+ api.registerCli(
58
+ ({ program }: { program: any }) => {
59
+ program
60
+ .command("bereach")
61
+ .description("BeReach status commands")
62
+ .command("status")
63
+ .description("Show LinkedIn rate limit summary")
64
+ .action(async () => {
65
+ const res = await (client as any).profile.getLimits();
66
+ console.log("BeReach Rate Limits:");
67
+ for (const [action, data] of Object.entries(res.limits) as [string, any][]) {
68
+ const d = data.daily;
69
+ console.log(` ${action}: ${d.current}/${d.limit} daily (${d.remaining} remaining)`);
70
+ }
71
+ });
72
+ },
73
+ { commands: ["bereach"] },
74
+ );
75
+ }
package/src/index.ts ADDED
@@ -0,0 +1,11 @@
1
+ import { createClient } from "./client";
2
+ import { registerAllTools } from "./tools";
3
+ import { registerCommands } from "./commands";
4
+ import { createCampaignMonitor } from "./services/campaign-monitor";
5
+
6
+ export default function register(api: any) {
7
+ const client = createClient(api.config.BEREACH_API_KEY);
8
+ registerAllTools(api, client);
9
+ registerCommands(api, client);
10
+ api.registerService(createCampaignMonitor(api, client));
11
+ }
@@ -0,0 +1,59 @@
1
+ import type { Bereach } from "bereach";
2
+
3
+ /**
4
+ * Background service that polls active campaigns every 5 minutes
5
+ * and logs activity deltas (new actions since last check).
6
+ */
7
+ export function createCampaignMonitor(api: any, client: Bereach) {
8
+ const seen = new Map<string, number>();
9
+ let interval: ReturnType<typeof setInterval> | null = null;
10
+
11
+ async function poll() {
12
+ try {
13
+ const campaigns = await (client as any).campaigns.getStatus({});
14
+ if (!campaigns?.campaigns) return;
15
+
16
+ for (const c of campaigns.campaigns) {
17
+ if (c.status !== "active") continue;
18
+
19
+ const stats = await (client as any).campaigns.getStats({
20
+ campaignSlug: c.slug,
21
+ });
22
+ const total = stats?.totalActions ?? 0;
23
+ const prev = seen.get(c.slug) ?? total;
24
+ const delta = total - prev;
25
+ seen.set(c.slug, total);
26
+
27
+ if (delta > 0) {
28
+ api.logger.info(
29
+ `[bereach] Campaign "${c.slug}": +${delta} actions (${total} total)`,
30
+ );
31
+ }
32
+ }
33
+ } catch (err: any) {
34
+ if (err?.statusCode === 401) {
35
+ api.logger.error("[bereach] Campaign monitor: auth failed, stopping");
36
+ stop();
37
+ return;
38
+ }
39
+ api.logger.warn(`[bereach] Campaign monitor poll error: ${err.message}`);
40
+ }
41
+ }
42
+
43
+ function stop() {
44
+ if (interval) {
45
+ clearInterval(interval);
46
+ interval = null;
47
+ }
48
+ }
49
+
50
+ return {
51
+ id: "bereach-campaign-monitor",
52
+ start: () => {
53
+ poll();
54
+ interval = setInterval(poll, 5 * 60 * 1000);
55
+ api.logger.info("[bereach] Campaign monitor started (every 5m)");
56
+ },
57
+ stop,
58
+ };
59
+ }