@better_openclaw/betterclaw 2.1.1 → 2.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.
- package/package.json +1 -1
- package/src/cli.ts +1 -0
- package/src/index.ts +60 -1
package/package.json
CHANGED
package/src/cli.ts
CHANGED
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
|
|
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 {
|