@basicmemory/openclaw-basic-memory 0.1.0-alpha.9 → 0.1.2
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/README.md +140 -504
- package/bm-client.ts +33 -51
- package/config.ts +0 -24
- package/hooks/recall.ts +9 -10
- package/index.ts +54 -41
- package/openclaw.plugin.json +0 -12
- package/package.json +2 -2
- package/schema/conversation-schema.ts +33 -0
- package/tools/memory-provider.ts +21 -36
- package/analytics.ts +0 -162
package/analytics.ts
DELETED
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Lightweight analytics via Umami event collector.
|
|
3
|
-
*
|
|
4
|
-
* Sends anonymous, non-blocking usage events to help understand plugin adoption
|
|
5
|
-
* and tool usage patterns. No PII, no fingerprinting, no cookies.
|
|
6
|
-
*
|
|
7
|
-
* Events are fire-and-forget — analytics never blocks or breaks the plugin.
|
|
8
|
-
*
|
|
9
|
-
* Defaults point to the Basic Memory Umami Cloud instance. Override via:
|
|
10
|
-
* BASIC_MEMORY_UMAMI_HOST — Custom Umami instance URL
|
|
11
|
-
* BASIC_MEMORY_UMAMI_SITE_ID — Custom Website ID
|
|
12
|
-
* Opt out entirely with OPENCLAW_BASIC_MEMORY_TELEMETRY=0 or BASIC_MEMORY_NO_PROMOS=1.
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
import { readFileSync } from "node:fs"
|
|
16
|
-
import { join } from "node:path"
|
|
17
|
-
|
|
18
|
-
// ---------------------------------------------------------------------------
|
|
19
|
-
// Configuration
|
|
20
|
-
// ---------------------------------------------------------------------------
|
|
21
|
-
|
|
22
|
-
const DEFAULT_UMAMI_HOST = "https://cloud.umami.is"
|
|
23
|
-
const DEFAULT_UMAMI_SITE_ID = "f6479898-ebaf-4e60-bce2-6dc60a3f6c5c"
|
|
24
|
-
const SEND_TIMEOUT_MS = 3000
|
|
25
|
-
|
|
26
|
-
function umamiHost(): string {
|
|
27
|
-
return process.env.BASIC_MEMORY_UMAMI_HOST?.trim() || DEFAULT_UMAMI_HOST
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function umamiSiteId(): string {
|
|
31
|
-
return process.env.BASIC_MEMORY_UMAMI_SITE_ID?.trim() || DEFAULT_UMAMI_SITE_ID
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export function analyticsDisabled(): boolean {
|
|
35
|
-
// Plugin-specific opt-out
|
|
36
|
-
const telemetry = (process.env.OPENCLAW_BASIC_MEMORY_TELEMETRY ?? "")
|
|
37
|
-
.trim()
|
|
38
|
-
.toLowerCase()
|
|
39
|
-
if (telemetry === "0" || telemetry === "false" || telemetry === "no") {
|
|
40
|
-
return true
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Shared Basic Memory opt-out (also disables BM CLI analytics)
|
|
44
|
-
const noPromos = (process.env.BASIC_MEMORY_NO_PROMOS ?? "")
|
|
45
|
-
.trim()
|
|
46
|
-
.toLowerCase()
|
|
47
|
-
return noPromos === "1" || noPromos === "true" || noPromos === "yes"
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// ---------------------------------------------------------------------------
|
|
51
|
-
// Version
|
|
52
|
-
// ---------------------------------------------------------------------------
|
|
53
|
-
|
|
54
|
-
let _cachedVersion: string | null = null
|
|
55
|
-
|
|
56
|
-
function getVersion(): string {
|
|
57
|
-
if (_cachedVersion) return _cachedVersion
|
|
58
|
-
try {
|
|
59
|
-
const pkg = JSON.parse(
|
|
60
|
-
readFileSync(
|
|
61
|
-
join(import.meta.dirname ?? __dirname, "package.json"),
|
|
62
|
-
"utf-8",
|
|
63
|
-
),
|
|
64
|
-
)
|
|
65
|
-
_cachedVersion = pkg.version ?? "unknown"
|
|
66
|
-
} catch {
|
|
67
|
-
_cachedVersion = "unknown"
|
|
68
|
-
}
|
|
69
|
-
return _cachedVersion ?? "unknown"
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// ---------------------------------------------------------------------------
|
|
73
|
-
// Session-scoped dedup for tool calls
|
|
74
|
-
// ---------------------------------------------------------------------------
|
|
75
|
-
|
|
76
|
-
const _trackedTools = new Set<string>()
|
|
77
|
-
|
|
78
|
-
export function resetTrackedTools(): void {
|
|
79
|
-
_trackedTools.clear()
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// ---------------------------------------------------------------------------
|
|
83
|
-
// Event constants
|
|
84
|
-
// ---------------------------------------------------------------------------
|
|
85
|
-
|
|
86
|
-
export const EVENT_PLUGIN_INSTALLED = "openclaw-plugin-installed"
|
|
87
|
-
export const EVENT_PLUGIN_STARTED = "openclaw-plugin-started"
|
|
88
|
-
export const EVENT_TOOL_CALL = "openclaw-tool-call"
|
|
89
|
-
|
|
90
|
-
// ---------------------------------------------------------------------------
|
|
91
|
-
// Public API
|
|
92
|
-
// ---------------------------------------------------------------------------
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Send an analytics event to Umami. Non-blocking, silent on failure.
|
|
96
|
-
*
|
|
97
|
-
* @param eventName - Short kebab-case name (e.g. "openclaw-plugin-started")
|
|
98
|
-
* @param data - Optional dict of event properties (string/number values)
|
|
99
|
-
*/
|
|
100
|
-
export function track(
|
|
101
|
-
eventName: string,
|
|
102
|
-
data?: Record<string, string | number>,
|
|
103
|
-
): void {
|
|
104
|
-
if (analyticsDisabled()) return
|
|
105
|
-
|
|
106
|
-
const host = umamiHost()
|
|
107
|
-
const siteId = umamiSiteId()
|
|
108
|
-
|
|
109
|
-
const payload = {
|
|
110
|
-
payload: {
|
|
111
|
-
hostname: "openclaw.basicmemory.com",
|
|
112
|
-
language: "en",
|
|
113
|
-
url: `/openclaw/${eventName}`,
|
|
114
|
-
website: siteId,
|
|
115
|
-
name: eventName,
|
|
116
|
-
data: {
|
|
117
|
-
version: getVersion(),
|
|
118
|
-
...(data ?? {}),
|
|
119
|
-
},
|
|
120
|
-
},
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// Fire-and-forget — never block the plugin
|
|
124
|
-
_sendPayload(host, payload).catch(() => {})
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Track a tool call, deduped per tool name per session.
|
|
129
|
-
* Only the first invocation of each tool sends an event.
|
|
130
|
-
*/
|
|
131
|
-
export function trackToolCall(toolName: string): void {
|
|
132
|
-
if (analyticsDisabled()) return
|
|
133
|
-
if (_trackedTools.has(toolName)) return
|
|
134
|
-
_trackedTools.add(toolName)
|
|
135
|
-
track(EVENT_TOOL_CALL, { tool: toolName })
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// ---------------------------------------------------------------------------
|
|
139
|
-
// Internal send (exported for testing)
|
|
140
|
-
// ---------------------------------------------------------------------------
|
|
141
|
-
|
|
142
|
-
export async function _sendPayload(
|
|
143
|
-
host: string,
|
|
144
|
-
payload: unknown,
|
|
145
|
-
): Promise<void> {
|
|
146
|
-
const controller = new AbortController()
|
|
147
|
-
const timer = setTimeout(() => controller.abort(), SEND_TIMEOUT_MS)
|
|
148
|
-
|
|
149
|
-
try {
|
|
150
|
-
await fetch(`${host}/api/send`, {
|
|
151
|
-
method: "POST",
|
|
152
|
-
headers: {
|
|
153
|
-
"Content-Type": "application/json",
|
|
154
|
-
"User-Agent": `openclaw-basic-memory/${getVersion()}`,
|
|
155
|
-
},
|
|
156
|
-
body: JSON.stringify(payload),
|
|
157
|
-
signal: controller.signal,
|
|
158
|
-
})
|
|
159
|
-
} finally {
|
|
160
|
-
clearTimeout(timer)
|
|
161
|
-
}
|
|
162
|
-
}
|