@better_openclaw/betterclaw 3.0.3 → 3.0.4
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/tools/get-context.ts +48 -12
package/package.json
CHANGED
package/src/tools/get-context.ts
CHANGED
|
@@ -1,12 +1,39 @@
|
|
|
1
1
|
import type { ContextManager } from "../context.js";
|
|
2
2
|
import { loadTriageProfile } from "../learner.js";
|
|
3
3
|
|
|
4
|
+
const STALE_THRESHOLD_S = 600; // 10 minutes
|
|
5
|
+
|
|
6
|
+
/** Format seconds into human-readable age string */
|
|
7
|
+
function formatAge(seconds: number): string {
|
|
8
|
+
if (seconds < 60) return `${Math.round(seconds)}s ago`;
|
|
9
|
+
if (seconds < 3600) return `${Math.round(seconds / 60)}m ago`;
|
|
10
|
+
if (seconds < 86400) return `${Math.round(seconds / 3600)}h ago`;
|
|
11
|
+
return `${Math.round(seconds / 86400)}d ago`;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* On premium, stale device data (>10 min) is replaced with a pointer
|
|
16
|
+
* to the fresh node command. The agent can't shortcut to stale values.
|
|
17
|
+
*/
|
|
18
|
+
function deviceFieldOrPointer(
|
|
19
|
+
data: Record<string, unknown> | null,
|
|
20
|
+
ageSeconds: number | null,
|
|
21
|
+
freshCommand: string,
|
|
22
|
+
isPremium: boolean,
|
|
23
|
+
): Record<string, unknown> | null {
|
|
24
|
+
if (!data) return null;
|
|
25
|
+
if (isPremium && ageSeconds != null && ageSeconds > STALE_THRESHOLD_S) {
|
|
26
|
+
return { stale: true, ageHuman: formatAge(ageSeconds), freshCommand };
|
|
27
|
+
}
|
|
28
|
+
return { ...data, dataAgeSeconds: ageSeconds };
|
|
29
|
+
}
|
|
30
|
+
|
|
4
31
|
export function createGetContextTool(ctx: ContextManager, stateDir?: string) {
|
|
5
32
|
return {
|
|
6
33
|
name: "get_context",
|
|
7
34
|
label: "Get Device Context",
|
|
8
35
|
description:
|
|
9
|
-
"Get BetterClaw context — patterns, trends, activity zone, event history,
|
|
36
|
+
"Get BetterClaw context — patterns, trends, activity zone, and event history. On premium, stale device readings (>10 min) are hidden — use node commands (location.get, device.battery, health.*) for current data. On free, this includes the full device snapshot.",
|
|
10
37
|
parameters: {},
|
|
11
38
|
async execute(_id: string, _params: Record<string, unknown>) {
|
|
12
39
|
const state = ctx.get();
|
|
@@ -14,28 +41,37 @@ export function createGetContextTool(ctx: ContextManager, stateDir?: string) {
|
|
|
14
41
|
const patterns = await ctx.readPatterns();
|
|
15
42
|
const dataAge = ctx.getDataAge();
|
|
16
43
|
|
|
17
|
-
const isPremium = runtime.tier === "premium";
|
|
44
|
+
const isPremium = runtime.tier === "premium" || runtime.tier === "premium+";
|
|
18
45
|
|
|
19
46
|
const result: Record<string, unknown> = {
|
|
20
47
|
tierHint: {
|
|
21
48
|
tier: runtime.tier,
|
|
22
49
|
note: isPremium
|
|
23
|
-
? "Node commands available for fresh readings (location.get, device.battery, health.*)"
|
|
50
|
+
? "Node commands available for fresh readings (location.get, device.battery, health.*). Stale device data is hidden — call the node command instead."
|
|
24
51
|
: "This is the only data source on free tier — check dataAgeSeconds for freshness",
|
|
25
52
|
},
|
|
26
53
|
smartMode: runtime.smartMode,
|
|
27
54
|
};
|
|
28
55
|
|
|
29
56
|
result.device = {
|
|
30
|
-
battery:
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
57
|
+
battery: deviceFieldOrPointer(
|
|
58
|
+
state.device.battery as unknown as Record<string, unknown>,
|
|
59
|
+
dataAge.battery,
|
|
60
|
+
"device.battery",
|
|
61
|
+
isPremium,
|
|
62
|
+
),
|
|
63
|
+
location: deviceFieldOrPointer(
|
|
64
|
+
state.device.location as unknown as Record<string, unknown>,
|
|
65
|
+
dataAge.location,
|
|
66
|
+
"location.get",
|
|
67
|
+
isPremium,
|
|
68
|
+
),
|
|
69
|
+
health: deviceFieldOrPointer(
|
|
70
|
+
state.device.health as unknown as Record<string, unknown>,
|
|
71
|
+
dataAge.health,
|
|
72
|
+
"health.summary",
|
|
73
|
+
isPremium,
|
|
74
|
+
),
|
|
39
75
|
};
|
|
40
76
|
|
|
41
77
|
result.activity = { ...state.activity, updatedAt: ctx.getTimestamp("activity") };
|