@better_openclaw/betterclaw 2.1.2 → 2.2.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@better_openclaw/betterclaw",
3
- "version": "2.1.2",
3
+ "version": "2.2.1",
4
4
  "description": "Intelligent event filtering, context tracking, and proactive triggers for BetterClaw",
5
5
  "license": "AGPL-3.0-only",
6
6
  "repository": {
package/src/index.ts CHANGED
@@ -87,6 +87,7 @@ export default {
87
87
 
88
88
  // Track whether async init has completed
89
89
  let initialized = false;
90
+ let learnerRunning = false;
90
91
  const initPromise = (async () => {
91
92
  try {
92
93
  await ctxManager.load();
@@ -231,6 +232,16 @@ export default {
231
232
  }
232
233
  : null;
233
234
 
235
+ const triggerIds = ["low-battery-away", "unusual-inactivity", "sleep-deficit", "routine-deviation", "health-weekly-digest"];
236
+ const cooldowns: Record<string, number> = {};
237
+ if (patterns?.triggerCooldowns) {
238
+ for (const id of triggerIds) {
239
+ const ts = patterns.triggerCooldowns[id];
240
+ if (ts != null) cooldowns[id] = ts;
241
+ }
242
+ }
243
+ const triggers = patterns ? { cooldowns } : null;
244
+
234
245
  respond(true, {
235
246
  tier: runtime.tier,
236
247
  smartMode: runtime.smartMode,
@@ -240,7 +251,8 @@ export default {
240
251
  meta,
241
252
  routines,
242
253
  timestamps,
243
- triageProfile: profile ? { summary: profile.summary, computedAt: profile.computedAt } : null,
254
+ triageProfile: profile ?? null,
255
+ triggers,
244
256
  });
245
257
  } catch (err) {
246
258
  api.logger.error(`betterclaw.context error: ${err instanceof Error ? err.message : String(err)}`);
@@ -248,6 +260,53 @@ export default {
248
260
  }
249
261
  });
250
262
 
263
+ // Learn RPC — trigger on-demand triage profile learning
264
+ api.registerGatewayMethod("betterclaw.learn", async ({ respond }) => {
265
+ try {
266
+ if (!initialized) await initPromise;
267
+
268
+ if (learnerRunning) {
269
+ respond(true, { ok: false, error: "already-running" });
270
+ return;
271
+ }
272
+
273
+ // Soft cooldown: 1 hour since last profile
274
+ const profile = await loadTriageProfile(stateDir);
275
+ if (profile?.computedAt) {
276
+ const elapsed = Date.now() / 1000 - profile.computedAt;
277
+ if (elapsed < 3600) {
278
+ const nextAvailableAt = profile.computedAt + 3600;
279
+ respond(true, { ok: false, error: "cooldown", nextAvailableAt });
280
+ return;
281
+ }
282
+ }
283
+
284
+ learnerRunning = true;
285
+ try {
286
+ await runLearner({
287
+ stateDir,
288
+ workspaceDir: path.join(os.homedir(), ".openclaw", "workspace"),
289
+ context: ctxManager,
290
+ events: eventLog,
291
+ reactions: reactionTracker,
292
+ api,
293
+ });
294
+ const updatedProfile = await loadTriageProfile(stateDir);
295
+ respond(true, {
296
+ ok: true,
297
+ summary: updatedProfile?.summary ?? null,
298
+ computedAt: updatedProfile?.computedAt ?? null,
299
+ });
300
+ } finally {
301
+ learnerRunning = false;
302
+ }
303
+ } catch (err) {
304
+ learnerRunning = false;
305
+ api.logger.error(`betterclaw.learn error: ${err instanceof Error ? err.message : String(err)}`);
306
+ respond(true, { ok: false, error: err instanceof Error ? err.message : String(err) });
307
+ }
308
+ });
309
+
251
310
  // Snapshot RPC — bulk-apply device state for Smart Mode catch-up
252
311
  api.registerGatewayMethod("betterclaw.snapshot", async ({ params, respond }) => {
253
312
  try {
package/src/learner.ts CHANGED
@@ -172,7 +172,7 @@ export async function runLearner(deps: RunLearnerDeps): Promise<void> {
172
172
  await api.runtime.subagent.waitForRun({ runId, timeoutMs: 60000 });
173
173
 
174
174
  // 10. Read response
175
- const messages = await api.runtime.subagent.getSessionMessages({
175
+ const { messages } = await api.runtime.subagent.getSessionMessages({
176
176
  sessionKey: "betterclaw-learn",
177
177
  limit: 5,
178
178
  });