clawpet-plugins 1.0.1 → 1.1.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/index.ts +35 -30
- package/openclaw.plugin.json +3 -4
- package/package.json +2 -2
package/index.ts
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* ClawPet OpenClaw Plugin
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Automatically reports agent tool calls to the ClawPet backend,
|
|
5
|
+
* driving real-time lobster pet animations.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
* - after_tool_call:
|
|
9
|
-
* - agent_end:
|
|
7
|
+
* Hooks:
|
|
8
|
+
* - after_tool_call: reports action + summary after each tool execution
|
|
9
|
+
* - agent_end: reports when an agent turn completes
|
|
10
10
|
*
|
|
11
|
-
*
|
|
11
|
+
* Configuration (in OpenClaw config plugins.entries):
|
|
12
12
|
* {
|
|
13
13
|
* "clawpet-plugins": {
|
|
14
14
|
* "enabled": true,
|
|
15
15
|
* "config": {
|
|
16
|
-
* "
|
|
17
|
-
* "
|
|
16
|
+
* "apiBase": "https://api.myclawpet.cn",
|
|
17
|
+
* "apiKey": "cpk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
|
18
18
|
* }
|
|
19
19
|
* }
|
|
20
20
|
* }
|
|
21
21
|
*/
|
|
22
22
|
|
|
23
23
|
// ---------------------------------------------------------------------------
|
|
24
|
-
//
|
|
24
|
+
// Type definitions (aligned with OpenClaw Plugin API, no source imports)
|
|
25
25
|
// ---------------------------------------------------------------------------
|
|
26
26
|
|
|
27
27
|
type PluginLogger = {
|
|
@@ -44,20 +44,17 @@ type PluginApi = {
|
|
|
44
44
|
};
|
|
45
45
|
|
|
46
46
|
// ---------------------------------------------------------------------------
|
|
47
|
-
//
|
|
47
|
+
// Constants
|
|
48
48
|
// ---------------------------------------------------------------------------
|
|
49
49
|
|
|
50
|
-
/**
|
|
51
|
-
const DEFAULT_API_BASE = "https://api.venusx.top";
|
|
52
|
-
|
|
53
|
-
/** 去重窗口(ms)—— 同一工具 2 秒内不重复上报 */
|
|
50
|
+
/** Dedup window (ms) — skip duplicate reports for the same tool within 2s */
|
|
54
51
|
const DEDUP_WINDOW = 2000;
|
|
55
52
|
|
|
56
|
-
/**
|
|
53
|
+
/** Report timeout (ms) */
|
|
57
54
|
const REPORT_TIMEOUT = 5000;
|
|
58
55
|
|
|
59
56
|
// ---------------------------------------------------------------------------
|
|
60
|
-
//
|
|
57
|
+
// Plugin entry
|
|
61
58
|
// ---------------------------------------------------------------------------
|
|
62
59
|
|
|
63
60
|
export default {
|
|
@@ -66,7 +63,15 @@ export default {
|
|
|
66
63
|
| { apiKey?: string; apiBase?: string }
|
|
67
64
|
| undefined;
|
|
68
65
|
const apiKey = config?.apiKey;
|
|
69
|
-
let apiBase = config?.apiBase
|
|
66
|
+
let apiBase = config?.apiBase;
|
|
67
|
+
|
|
68
|
+
if (!apiBase) {
|
|
69
|
+
api.logger.warn(
|
|
70
|
+
"[ClawPet] No apiBase configured — plugin disabled. " +
|
|
71
|
+
"Set plugins.entries.clawpet-plugins.config.apiBase in your OpenClaw config.",
|
|
72
|
+
);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
70
75
|
|
|
71
76
|
if (!apiKey) {
|
|
72
77
|
api.logger.warn(
|
|
@@ -85,28 +90,28 @@ export default {
|
|
|
85
90
|
|
|
86
91
|
api.logger.info(`[ClawPet] Plugin active, reporting to ${apiBase}`);
|
|
87
92
|
|
|
88
|
-
//
|
|
93
|
+
// Dedup: track recently reported toolName → timestamp
|
|
89
94
|
const lastReported = new Map<string, number>();
|
|
90
95
|
|
|
91
96
|
/**
|
|
92
|
-
*
|
|
93
|
-
*
|
|
97
|
+
* Async report to ClawPet backend.
|
|
98
|
+
* Fire-and-forget — never blocks the agent.
|
|
94
99
|
*/
|
|
95
100
|
function reportActivity(action: string, summary: string): void {
|
|
96
|
-
//
|
|
101
|
+
// Dedup check
|
|
97
102
|
const now = Date.now();
|
|
98
103
|
const lastTime = lastReported.get(action);
|
|
99
104
|
if (lastTime && now - lastTime < DEDUP_WINDOW) return;
|
|
100
105
|
lastReported.set(action, now);
|
|
101
106
|
|
|
102
|
-
//
|
|
107
|
+
// Evict stale dedup entries (prevent memory leaks)
|
|
103
108
|
if (lastReported.size > 100) {
|
|
104
109
|
for (const [key, ts] of lastReported) {
|
|
105
110
|
if (now - ts > DEDUP_WINDOW * 5) lastReported.delete(key);
|
|
106
111
|
}
|
|
107
112
|
}
|
|
108
113
|
|
|
109
|
-
//
|
|
114
|
+
// Async POST, fire-and-forget
|
|
110
115
|
const controller = new AbortController();
|
|
111
116
|
const timeout = setTimeout(() => controller.abort(), REPORT_TIMEOUT);
|
|
112
117
|
|
|
@@ -124,7 +129,7 @@ export default {
|
|
|
124
129
|
if (res.ok) {
|
|
125
130
|
try {
|
|
126
131
|
const data = await res.json();
|
|
127
|
-
//
|
|
132
|
+
// Piggyback apiBase update from webhook response
|
|
128
133
|
if (data?.config?.apiBase && data.config.apiBase !== apiBase) {
|
|
129
134
|
api.logger.info(
|
|
130
135
|
`[ClawPet] API base updated: ${apiBase} → ${data.config.apiBase}`,
|
|
@@ -132,19 +137,19 @@ export default {
|
|
|
132
137
|
apiBase = data.config.apiBase;
|
|
133
138
|
}
|
|
134
139
|
} catch {
|
|
135
|
-
// JSON
|
|
140
|
+
// JSON parse failure — ignore
|
|
136
141
|
}
|
|
137
142
|
}
|
|
138
143
|
})
|
|
139
144
|
.catch(() => {
|
|
140
145
|
clearTimeout(timeout);
|
|
141
|
-
//
|
|
146
|
+
// Report failure silently — never affect agent work
|
|
142
147
|
});
|
|
143
148
|
}
|
|
144
149
|
|
|
145
150
|
// ========================================
|
|
146
151
|
// Hook: after_tool_call
|
|
147
|
-
//
|
|
152
|
+
// Reports after each tool execution
|
|
148
153
|
// ========================================
|
|
149
154
|
|
|
150
155
|
api.on("after_tool_call", (event: any) => {
|
|
@@ -159,13 +164,13 @@ export default {
|
|
|
159
164
|
|
|
160
165
|
reportActivity(toolName, summary);
|
|
161
166
|
} catch {
|
|
162
|
-
// Hook
|
|
167
|
+
// Hook errors are silent — never affect agent
|
|
163
168
|
}
|
|
164
169
|
});
|
|
165
170
|
|
|
166
171
|
// ========================================
|
|
167
172
|
// Hook: agent_end
|
|
168
|
-
//
|
|
173
|
+
// Reports when an agent turn completes
|
|
169
174
|
// ========================================
|
|
170
175
|
|
|
171
176
|
api.on("agent_end", (event: any) => {
|
|
@@ -177,7 +182,7 @@ export default {
|
|
|
177
182
|
reportActivity("error", `Turn failed: ${event.error ?? "unknown"}`);
|
|
178
183
|
}
|
|
179
184
|
} catch {
|
|
180
|
-
// Hook
|
|
185
|
+
// Hook errors are silent — never affect agent
|
|
181
186
|
}
|
|
182
187
|
});
|
|
183
188
|
},
|
package/openclaw.plugin.json
CHANGED
|
@@ -8,14 +8,13 @@
|
|
|
8
8
|
"properties": {
|
|
9
9
|
"apiBase": {
|
|
10
10
|
"type": "string",
|
|
11
|
-
"description": "ClawPet API base URL"
|
|
12
|
-
"default": "https://api.venusx.top"
|
|
11
|
+
"description": "ClawPet API base URL (required)"
|
|
13
12
|
},
|
|
14
13
|
"apiKey": {
|
|
15
14
|
"type": "string",
|
|
16
|
-
"description": "ClawPet API key (cpk_xxx)"
|
|
15
|
+
"description": "ClawPet API key (cpk_xxx, required)"
|
|
17
16
|
}
|
|
18
17
|
},
|
|
19
|
-
"required": []
|
|
18
|
+
"required": ["apiBase", "apiKey"]
|
|
20
19
|
}
|
|
21
20
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "clawpet-plugins",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "OpenClaw plugin for ClawPet — auto-report tool calls for real-time pet visualization",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"openclaw.plugin.json",
|
|
12
12
|
"README.md"
|
|
13
13
|
],
|
|
14
|
-
"homepage": "https://myclawpet.
|
|
14
|
+
"homepage": "https://myclawpet.cn",
|
|
15
15
|
"publishConfig": {
|
|
16
16
|
"access": "public"
|
|
17
17
|
},
|