@memtensor/memos-local-openclaw-plugin 0.1.9 → 0.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/.env.example +6 -0
- package/README.md +90 -25
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +8 -0
- package/dist/config.js.map +1 -1
- package/dist/embedding/local.d.ts.map +1 -1
- package/dist/embedding/local.js +3 -2
- package/dist/embedding/local.js.map +1 -1
- package/dist/skill/evaluator.js +1 -1
- package/dist/skill/evaluator.js.map +1 -1
- package/dist/skill/generator.js +1 -1
- package/dist/skill/generator.js.map +1 -1
- package/dist/skill/upgrader.js +1 -1
- package/dist/skill/upgrader.js.map +1 -1
- package/dist/skill/validator.js +1 -1
- package/dist/skill/validator.js.map +1 -1
- package/dist/storage/sqlite.d.ts +4 -0
- package/dist/storage/sqlite.d.ts.map +1 -1
- package/dist/storage/sqlite.js +19 -0
- package/dist/storage/sqlite.js.map +1 -1
- package/dist/telemetry.d.ts +37 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +179 -0
- package/dist/telemetry.js.map +1 -0
- package/dist/types.d.ts +6 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/viewer/html.d.ts +1 -1
- package/dist/viewer/html.d.ts.map +1 -1
- package/dist/viewer/html.js +828 -52
- package/dist/viewer/html.js.map +1 -1
- package/dist/viewer/server.d.ts +25 -1
- package/dist/viewer/server.d.ts.map +1 -1
- package/dist/viewer/server.js +807 -0
- package/dist/viewer/server.js.map +1 -1
- package/index.ts +31 -3
- package/openclaw.plugin.json +3 -3
- package/package.json +4 -3
- package/src/config.ts +11 -0
- package/src/embedding/local.ts +3 -2
- package/src/skill/evaluator.ts +1 -1
- package/src/skill/generator.ts +1 -1
- package/src/skill/upgrader.ts +1 -1
- package/src/skill/validator.ts +1 -1
- package/src/storage/sqlite.ts +29 -0
- package/src/telemetry.ts +160 -0
- package/src/types.ts +7 -1
- package/src/viewer/html.ts +828 -52
- package/src/viewer/server.ts +818 -1
package/src/telemetry.ts
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Telemetry module — anonymous usage analytics via PostHog.
|
|
3
|
+
*
|
|
4
|
+
* Privacy-first design:
|
|
5
|
+
* - Enabled by default with anonymous data only; opt-out via TELEMETRY_ENABLED=false
|
|
6
|
+
* - Uses a random anonymous ID persisted locally (no PII)
|
|
7
|
+
* - Never sends memory content, queries, or any user data
|
|
8
|
+
* - Only sends aggregate counts, tool names, latencies, and version info
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { PostHog } from "posthog-node";
|
|
12
|
+
import * as fs from "fs";
|
|
13
|
+
import * as path from "path";
|
|
14
|
+
import * as os from "os";
|
|
15
|
+
import { v4 as uuidv4 } from "uuid";
|
|
16
|
+
import type { Logger } from "./types";
|
|
17
|
+
|
|
18
|
+
export interface TelemetryConfig {
|
|
19
|
+
enabled?: boolean;
|
|
20
|
+
posthogApiKey?: string;
|
|
21
|
+
posthogHost?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const DEFAULT_POSTHOG_API_KEY = "phc_7lae6UC5jyImDefX6uub7zCxWyswCGNoBifCKqjvDrI";
|
|
25
|
+
const DEFAULT_POSTHOG_HOST = "https://eu.i.posthog.com";
|
|
26
|
+
|
|
27
|
+
export class Telemetry {
|
|
28
|
+
private client: PostHog | null = null;
|
|
29
|
+
private distinctId: string;
|
|
30
|
+
private enabled: boolean;
|
|
31
|
+
private pluginVersion: string;
|
|
32
|
+
private log: Logger;
|
|
33
|
+
private dailyPingSent = false;
|
|
34
|
+
private dailyPingDate = "";
|
|
35
|
+
|
|
36
|
+
constructor(config: TelemetryConfig, stateDir: string, pluginVersion: string, log: Logger) {
|
|
37
|
+
this.log = log;
|
|
38
|
+
this.pluginVersion = pluginVersion;
|
|
39
|
+
this.enabled = config.enabled !== false;
|
|
40
|
+
this.distinctId = this.loadOrCreateAnonymousId(stateDir);
|
|
41
|
+
|
|
42
|
+
if (!this.enabled) {
|
|
43
|
+
this.log.debug("Telemetry disabled (opt-out via TELEMETRY_ENABLED=false)");
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const apiKey = config.posthogApiKey || DEFAULT_POSTHOG_API_KEY;
|
|
48
|
+
try {
|
|
49
|
+
this.client = new PostHog(apiKey, {
|
|
50
|
+
host: config.posthogHost || DEFAULT_POSTHOG_HOST,
|
|
51
|
+
flushAt: 10,
|
|
52
|
+
flushInterval: 30_000,
|
|
53
|
+
});
|
|
54
|
+
this.log.debug("Telemetry initialized (PostHog)");
|
|
55
|
+
} catch (err) {
|
|
56
|
+
this.log.warn(`Telemetry init failed: ${err}`);
|
|
57
|
+
this.enabled = false;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
private loadOrCreateAnonymousId(stateDir: string): string {
|
|
62
|
+
const idFile = path.join(stateDir, "memos-local", ".anonymous-id");
|
|
63
|
+
try {
|
|
64
|
+
const existing = fs.readFileSync(idFile, "utf-8").trim();
|
|
65
|
+
if (existing.length > 10) return existing;
|
|
66
|
+
} catch {}
|
|
67
|
+
|
|
68
|
+
const newId = uuidv4();
|
|
69
|
+
try {
|
|
70
|
+
fs.mkdirSync(path.dirname(idFile), { recursive: true });
|
|
71
|
+
fs.writeFileSync(idFile, newId, "utf-8");
|
|
72
|
+
} catch {}
|
|
73
|
+
return newId;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
private capture(event: string, properties?: Record<string, unknown>): void {
|
|
77
|
+
if (!this.enabled || !this.client) return;
|
|
78
|
+
|
|
79
|
+
try {
|
|
80
|
+
this.client.capture({
|
|
81
|
+
distinctId: this.distinctId,
|
|
82
|
+
event,
|
|
83
|
+
properties: {
|
|
84
|
+
plugin_version: this.pluginVersion,
|
|
85
|
+
os: os.platform(),
|
|
86
|
+
os_version: os.release(),
|
|
87
|
+
node_version: process.version,
|
|
88
|
+
arch: os.arch(),
|
|
89
|
+
...properties,
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
} catch {
|
|
93
|
+
// best-effort, never throw
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// ─── Public event methods ───
|
|
98
|
+
|
|
99
|
+
trackPluginStarted(embeddingProvider: string, summarizerProvider: string): void {
|
|
100
|
+
this.capture("plugin_started", {
|
|
101
|
+
embedding_provider: embeddingProvider,
|
|
102
|
+
summarizer_provider: summarizerProvider,
|
|
103
|
+
});
|
|
104
|
+
this.maybeSendDailyPing();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
trackToolCalled(toolName: string, latencyMs: number, success: boolean): void {
|
|
108
|
+
this.capture("tool_called", {
|
|
109
|
+
tool_name: toolName,
|
|
110
|
+
latency_ms: Math.round(latencyMs),
|
|
111
|
+
success,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
trackMemoryIngested(chunkCount: number): void {
|
|
116
|
+
this.capture("memory_ingested", {
|
|
117
|
+
chunk_count: chunkCount,
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
trackSkillInstalled(skillName: string): void {
|
|
122
|
+
this.capture("skill_installed", {
|
|
123
|
+
skill_name: skillName,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
trackSkillEvolved(skillName: string, upgradeType: string): void {
|
|
128
|
+
this.capture("skill_evolved", {
|
|
129
|
+
skill_name: skillName,
|
|
130
|
+
upgrade_type: upgradeType,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
trackViewerOpened(): void {
|
|
135
|
+
this.capture("viewer_opened");
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
trackAutoRecall(hitCount: number, latencyMs: number): void {
|
|
139
|
+
this.capture("auto_recall", {
|
|
140
|
+
hit_count: hitCount,
|
|
141
|
+
latency_ms: Math.round(latencyMs),
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
private maybeSendDailyPing(): void {
|
|
146
|
+
const today = new Date().toISOString().slice(0, 10);
|
|
147
|
+
if (this.dailyPingSent && this.dailyPingDate === today) return;
|
|
148
|
+
this.dailyPingSent = true;
|
|
149
|
+
this.dailyPingDate = today;
|
|
150
|
+
this.capture("daily_active");
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
async shutdown(): Promise<void> {
|
|
154
|
+
if (this.client) {
|
|
155
|
+
try {
|
|
156
|
+
await this.client.shutdown();
|
|
157
|
+
} catch {}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -229,7 +229,12 @@ export interface SkillEvolutionConfig {
|
|
|
229
229
|
minConfidence?: number;
|
|
230
230
|
maxSkillLines?: number;
|
|
231
231
|
autoInstall?: boolean;
|
|
232
|
-
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
export interface TelemetryConfig {
|
|
235
|
+
enabled?: boolean;
|
|
236
|
+
posthogApiKey?: string;
|
|
237
|
+
posthogHost?: string;
|
|
233
238
|
}
|
|
234
239
|
|
|
235
240
|
export interface MemosLocalConfig {
|
|
@@ -254,6 +259,7 @@ export interface MemosLocalConfig {
|
|
|
254
259
|
evidenceWrapperTag?: string;
|
|
255
260
|
};
|
|
256
261
|
skillEvolution?: SkillEvolutionConfig;
|
|
262
|
+
telemetry?: TelemetryConfig;
|
|
257
263
|
}
|
|
258
264
|
|
|
259
265
|
// ─── Defaults ───
|