@memtensor/memos-local-openclaw-plugin 1.0.4-beta.8 → 1.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/.env.example +7 -0
- package/README.md +94 -27
- package/dist/capture/index.js +3 -1
- package/dist/capture/index.js.map +1 -1
- package/dist/client/connector.d.ts +5 -0
- package/dist/client/connector.d.ts.map +1 -1
- package/dist/client/connector.js +132 -10
- package/dist/client/connector.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +2 -1
- package/dist/config.js.map +1 -1
- package/dist/hub/server.d.ts +2 -0
- package/dist/hub/server.d.ts.map +1 -1
- package/dist/hub/server.js +251 -38
- package/dist/hub/server.js.map +1 -1
- package/dist/hub/user-manager.d.ts +9 -0
- package/dist/hub/user-manager.d.ts.map +1 -1
- package/dist/hub/user-manager.js +26 -2
- package/dist/hub/user-manager.js.map +1 -1
- package/dist/ingest/chunker.d.ts +2 -1
- package/dist/ingest/chunker.d.ts.map +1 -1
- package/dist/ingest/chunker.js +14 -10
- package/dist/ingest/chunker.js.map +1 -1
- package/dist/ingest/providers/index.js +2 -2
- package/dist/ingest/providers/index.js.map +1 -1
- package/dist/recall/engine.d.ts.map +1 -1
- package/dist/recall/engine.js +96 -1
- package/dist/recall/engine.js.map +1 -1
- package/dist/shared/llm-call.d.ts.map +1 -1
- package/dist/shared/llm-call.js +2 -1
- package/dist/shared/llm-call.js.map +1 -1
- package/dist/sharing/types.d.ts +1 -1
- package/dist/sharing/types.d.ts.map +1 -1
- package/dist/skill/evolver.d.ts +2 -0
- package/dist/skill/evolver.d.ts.map +1 -1
- package/dist/skill/evolver.js +56 -5
- package/dist/skill/evolver.js.map +1 -1
- package/dist/skill/generator.d.ts +2 -0
- package/dist/skill/generator.d.ts.map +1 -1
- package/dist/skill/generator.js +45 -3
- package/dist/skill/generator.js.map +1 -1
- package/dist/skill/installer.d.ts +26 -0
- package/dist/skill/installer.d.ts.map +1 -1
- package/dist/skill/installer.js +80 -4
- package/dist/skill/installer.js.map +1 -1
- package/dist/skill/upgrader.d.ts +2 -0
- package/dist/skill/upgrader.d.ts.map +1 -1
- package/dist/skill/upgrader.js +139 -1
- package/dist/skill/upgrader.js.map +1 -1
- package/dist/skill/validator.d.ts +3 -0
- package/dist/skill/validator.d.ts.map +1 -1
- package/dist/skill/validator.js +75 -0
- package/dist/skill/validator.js.map +1 -1
- package/dist/storage/sqlite.d.ts +58 -0
- package/dist/storage/sqlite.d.ts.map +1 -1
- package/dist/storage/sqlite.js +295 -35
- package/dist/storage/sqlite.js.map +1 -1
- package/dist/telemetry.d.ts.map +1 -1
- package/dist/telemetry.js +27 -8
- package/dist/telemetry.js.map +1 -1
- package/dist/types.d.ts +10 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +4 -0
- package/dist/types.js.map +1 -1
- package/dist/viewer/html.d.ts.map +1 -1
- package/dist/viewer/html.js +796 -289
- package/dist/viewer/html.js.map +1 -1
- package/dist/viewer/server.d.ts +11 -0
- package/dist/viewer/server.d.ts.map +1 -1
- package/dist/viewer/server.js +456 -92
- package/dist/viewer/server.js.map +1 -1
- package/index.ts +411 -52
- package/openclaw.plugin.json +1 -1
- package/package.json +2 -1
- package/prebuilds/darwin-arm64/better_sqlite3.node +0 -0
- package/prebuilds/darwin-x64/better_sqlite3.node +0 -0
- package/prebuilds/linux-x64/better_sqlite3.node +0 -0
- package/prebuilds/win32-x64/better_sqlite3.node +0 -0
- package/src/capture/index.ts +4 -1
- package/src/client/connector.ts +136 -10
- package/src/config.ts +2 -1
- package/src/hub/server.ts +246 -38
- package/src/hub/user-manager.ts +42 -6
- package/src/ingest/chunker.ts +19 -13
- package/src/ingest/providers/index.ts +2 -2
- package/src/recall/engine.ts +89 -1
- package/src/shared/llm-call.ts +2 -1
- package/src/sharing/types.ts +1 -1
- package/src/skill/evolver.ts +58 -6
- package/src/skill/generator.ts +44 -5
- package/src/skill/installer.ts +107 -4
- package/src/skill/upgrader.ts +139 -1
- package/src/skill/validator.ts +79 -0
- package/src/storage/sqlite.ts +326 -40
- package/src/telemetry.ts +27 -9
- package/src/types.ts +11 -0
- package/src/viewer/html.ts +796 -289
- package/src/viewer/server.ts +430 -89
- package/telemetry.credentials.json +5 -0
|
Binary file
|
package/src/capture/index.ts
CHANGED
|
@@ -167,8 +167,11 @@ export function stripInboundMetadata(text: string): string {
|
|
|
167
167
|
/** Strip <think…>…</think> blocks emitted by DeepSeek-style reasoning models. */
|
|
168
168
|
const THINKING_TAG_RE = /<think[\s>][\s\S]*?<\/think>\s*/gi;
|
|
169
169
|
|
|
170
|
+
/** Unwrap <final>…</final> tags from MiniMax-style models (keep content, strip tags). */
|
|
171
|
+
const FINAL_TAG_RE = /<\/?final\s*>/gi;
|
|
172
|
+
|
|
170
173
|
function stripThinkingTags(text: string): string {
|
|
171
|
-
return text.replace(THINKING_TAG_RE, "");
|
|
174
|
+
return text.replace(THINKING_TAG_RE, "").replace(FINAL_TAG_RE, "").trim();
|
|
172
175
|
}
|
|
173
176
|
|
|
174
177
|
function extractEnvelopeTimestamp(text: string): number | null {
|
package/src/client/connector.ts
CHANGED
|
@@ -10,6 +10,7 @@ export interface HubSessionInfo {
|
|
|
10
10
|
userToken: string;
|
|
11
11
|
role: UserRole;
|
|
12
12
|
connectedAt: number;
|
|
13
|
+
identityKey?: string;
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
export interface HubStatusInfo {
|
|
@@ -20,6 +21,7 @@ export interface HubStatusInfo {
|
|
|
20
21
|
username: string;
|
|
21
22
|
role: UserRole;
|
|
22
23
|
status: UserStatus | string;
|
|
24
|
+
groups?: Array<{ id: string; name: string }>;
|
|
23
25
|
};
|
|
24
26
|
}
|
|
25
27
|
|
|
@@ -34,6 +36,49 @@ export async function connectToHub(store: SqliteStore, config: MemosLocalConfig,
|
|
|
34
36
|
|
|
35
37
|
if (!userToken && config.sharing?.client?.teamToken) {
|
|
36
38
|
if (!log) throw new Error("hub client connection is not configured (no userToken, has teamToken but no logger for auto-join)");
|
|
39
|
+
|
|
40
|
+
// If DB has a pending connection (userId exists, no token), check registration-status first
|
|
41
|
+
const persisted = store.getClientHubConnection();
|
|
42
|
+
if (persisted?.userId && !persisted.userToken && hubAddress) {
|
|
43
|
+
const hubUrl = normalizeHubUrl(hubAddress);
|
|
44
|
+
const teamToken = config.sharing.client!.teamToken!;
|
|
45
|
+
try {
|
|
46
|
+
const result = await hubRequestJson(hubUrl, "", "/api/v1/hub/registration-status", {
|
|
47
|
+
method: "POST",
|
|
48
|
+
body: JSON.stringify({ teamToken, userId: persisted.userId }),
|
|
49
|
+
}) as any;
|
|
50
|
+
if (result.status === "active" && result.userToken) {
|
|
51
|
+
log.info(`Pending user approved! Connecting with token. userId=${persisted.userId}`);
|
|
52
|
+
store.setClientHubConnection({
|
|
53
|
+
hubUrl,
|
|
54
|
+
userId: persisted.userId,
|
|
55
|
+
username: persisted.username || "",
|
|
56
|
+
userToken: result.userToken,
|
|
57
|
+
role: "member",
|
|
58
|
+
connectedAt: Date.now(),
|
|
59
|
+
identityKey: persisted.identityKey || "",
|
|
60
|
+
lastKnownStatus: "active",
|
|
61
|
+
});
|
|
62
|
+
return store.getClientHubConnection()!;
|
|
63
|
+
}
|
|
64
|
+
if (result.status === "pending") {
|
|
65
|
+
throw new PendingApprovalError(persisted.userId);
|
|
66
|
+
}
|
|
67
|
+
if (result.status === "rejected") {
|
|
68
|
+
throw new Error("Join request was rejected by the Hub admin.");
|
|
69
|
+
}
|
|
70
|
+
if (result.status === "blocked") {
|
|
71
|
+
throw new Error("Your account has been blocked by the Hub admin.");
|
|
72
|
+
}
|
|
73
|
+
if (result.status === "left" || result.status === "removed") {
|
|
74
|
+
log.info(`User status is "${result.status}", will try to rejoin.`);
|
|
75
|
+
}
|
|
76
|
+
} catch (err) {
|
|
77
|
+
if (err instanceof PendingApprovalError) throw err;
|
|
78
|
+
log.warn(`registration-status check failed, falling back to autoJoinHub: ${err}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
37
82
|
return autoJoinHub(store, config, log);
|
|
38
83
|
}
|
|
39
84
|
|
|
@@ -43,6 +88,7 @@ export async function connectToHub(store: SqliteStore, config: MemosLocalConfig,
|
|
|
43
88
|
|
|
44
89
|
const hubUrl = normalizeHubUrl(hubAddress);
|
|
45
90
|
const me = await hubRequestJson(hubUrl, userToken, "/api/v1/hub/me", { method: "GET" }) as any;
|
|
91
|
+
const persisted = store.getClientHubConnection();
|
|
46
92
|
store.setClientHubConnection({
|
|
47
93
|
hubUrl,
|
|
48
94
|
userId: String(me.id),
|
|
@@ -50,22 +96,35 @@ export async function connectToHub(store: SqliteStore, config: MemosLocalConfig,
|
|
|
50
96
|
userToken,
|
|
51
97
|
role: String(me.role ?? "member") as UserRole,
|
|
52
98
|
connectedAt: Date.now(),
|
|
99
|
+
identityKey: persisted?.identityKey || String(me.identityKey ?? ""),
|
|
100
|
+
lastKnownStatus: "active",
|
|
53
101
|
});
|
|
54
102
|
return store.getClientHubConnection()!;
|
|
55
103
|
}
|
|
56
104
|
|
|
57
105
|
export async function getHubStatus(store: SqliteStore, config: MemosLocalConfig): Promise<HubStatusInfo> {
|
|
58
106
|
const conn = store.getClientHubConnection();
|
|
59
|
-
const
|
|
107
|
+
const configHubAddress = config.sharing?.client?.hubAddress || "";
|
|
108
|
+
const hubAddress = conn?.hubUrl || (configHubAddress ? normalizeHubUrl(configHubAddress) : "");
|
|
60
109
|
const userToken = conn?.userToken || config.sharing?.client?.userToken || "";
|
|
61
110
|
|
|
111
|
+
if (conn && configHubAddress && conn.hubUrl && normalizeHubUrl(configHubAddress) !== conn.hubUrl) {
|
|
112
|
+
store.setClientHubConnection({
|
|
113
|
+
...conn,
|
|
114
|
+
hubUrl: normalizeHubUrl(configHubAddress),
|
|
115
|
+
userToken: "",
|
|
116
|
+
lastKnownStatus: "hub_changed",
|
|
117
|
+
});
|
|
118
|
+
return { connected: false, user: null };
|
|
119
|
+
}
|
|
120
|
+
|
|
62
121
|
if (conn && conn.userId && (!userToken || userToken === "")) {
|
|
63
122
|
const teamToken = config.sharing?.client?.teamToken ?? "";
|
|
64
123
|
if (hubAddress && teamToken) {
|
|
65
124
|
try {
|
|
66
|
-
const result = await hubRequestJson(normalizeHubUrl(hubAddress), "", "/api/v1/hub/
|
|
125
|
+
const result = await hubRequestJson(normalizeHubUrl(hubAddress), "", "/api/v1/hub/registration-status", {
|
|
67
126
|
method: "POST",
|
|
68
|
-
body: JSON.stringify({ teamToken,
|
|
127
|
+
body: JSON.stringify({ teamToken, userId: conn.userId }),
|
|
69
128
|
}) as any;
|
|
70
129
|
if (result.status === "pending") {
|
|
71
130
|
return {
|
|
@@ -82,11 +141,13 @@ export async function getHubStatus(store: SqliteStore, config: MemosLocalConfig)
|
|
|
82
141
|
if (result.status === "active" && result.userToken) {
|
|
83
142
|
store.setClientHubConnection({
|
|
84
143
|
hubUrl: normalizeHubUrl(hubAddress),
|
|
85
|
-
userId:
|
|
144
|
+
userId: conn.userId,
|
|
86
145
|
username: conn.username || "",
|
|
87
146
|
userToken: result.userToken,
|
|
88
147
|
role: "member",
|
|
89
148
|
connectedAt: Date.now(),
|
|
149
|
+
identityKey: conn.identityKey || "",
|
|
150
|
+
lastKnownStatus: "active",
|
|
90
151
|
});
|
|
91
152
|
const me = await hubRequestJson(normalizeHubUrl(hubAddress), result.userToken, "/api/v1/hub/me", { method: "GET" }) as any;
|
|
92
153
|
return {
|
|
@@ -127,12 +188,10 @@ export async function getHubStatus(store: SqliteStore, config: MemosLocalConfig)
|
|
|
127
188
|
const latestRole = String(me.role ?? "member") as UserRole;
|
|
128
189
|
if (conn && (conn.username !== latestUsername || conn.role !== latestRole)) {
|
|
129
190
|
store.setClientHubConnection({
|
|
130
|
-
|
|
131
|
-
userId: conn.userId,
|
|
191
|
+
...conn,
|
|
132
192
|
username: latestUsername,
|
|
133
|
-
userToken: conn.userToken,
|
|
134
193
|
role: latestRole,
|
|
135
|
-
|
|
194
|
+
lastKnownStatus: "active",
|
|
136
195
|
});
|
|
137
196
|
}
|
|
138
197
|
return {
|
|
@@ -143,9 +202,63 @@ export async function getHubStatus(store: SqliteStore, config: MemosLocalConfig)
|
|
|
143
202
|
username: latestUsername,
|
|
144
203
|
role: latestRole,
|
|
145
204
|
status: String(me.status ?? "active"),
|
|
205
|
+
groups: Array.isArray(me.groups) ? me.groups : [],
|
|
146
206
|
},
|
|
147
207
|
};
|
|
148
|
-
} catch {
|
|
208
|
+
} catch (err: any) {
|
|
209
|
+
const is401 = typeof err?.message === "string" && err.message.includes("(401)");
|
|
210
|
+
if (is401 && conn) {
|
|
211
|
+
const teamToken = config.sharing?.client?.teamToken ?? "";
|
|
212
|
+
if (hubAddress && teamToken) {
|
|
213
|
+
try {
|
|
214
|
+
const regResult = await hubRequestJson(normalizeHubUrl(hubAddress), "", "/api/v1/hub/registration-status", {
|
|
215
|
+
method: "POST",
|
|
216
|
+
body: JSON.stringify({ teamToken, userId: conn.userId }),
|
|
217
|
+
}) as any;
|
|
218
|
+
if (regResult.status === "active" && regResult.userToken) {
|
|
219
|
+
store.setClientHubConnection({
|
|
220
|
+
...conn,
|
|
221
|
+
hubUrl: normalizeHubUrl(hubAddress),
|
|
222
|
+
userToken: regResult.userToken,
|
|
223
|
+
connectedAt: Date.now(),
|
|
224
|
+
lastKnownStatus: "active",
|
|
225
|
+
});
|
|
226
|
+
try {
|
|
227
|
+
const me = await hubRequestJson(normalizeHubUrl(hubAddress), regResult.userToken, "/api/v1/hub/me", { method: "GET" }) as any;
|
|
228
|
+
return {
|
|
229
|
+
connected: true,
|
|
230
|
+
hubUrl: normalizeHubUrl(hubAddress),
|
|
231
|
+
user: {
|
|
232
|
+
id: String(me.id),
|
|
233
|
+
username: String(me.username ?? ""),
|
|
234
|
+
role: String(me.role ?? "member") as UserRole,
|
|
235
|
+
status: String(me.status ?? "active"),
|
|
236
|
+
groups: Array.isArray(me.groups) ? me.groups : [],
|
|
237
|
+
},
|
|
238
|
+
};
|
|
239
|
+
} catch { /* fall through to token-only return */ }
|
|
240
|
+
return {
|
|
241
|
+
connected: true,
|
|
242
|
+
hubUrl: normalizeHubUrl(hubAddress),
|
|
243
|
+
user: { id: conn.userId, username: conn.username || "", role: conn.role as UserRole || "member", status: "active" },
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
const realStatus = regResult.status as string;
|
|
247
|
+
store.setClientHubConnection({ ...conn, userToken: "", lastKnownStatus: realStatus });
|
|
248
|
+
return {
|
|
249
|
+
connected: false,
|
|
250
|
+
hubUrl: normalizeHubUrl(hubAddress),
|
|
251
|
+
user: { id: conn.userId, username: conn.username || "", role: "member", status: realStatus },
|
|
252
|
+
};
|
|
253
|
+
} catch { /* registration-status also failed, fall through */ }
|
|
254
|
+
}
|
|
255
|
+
store.setClientHubConnection({ ...conn, userToken: "", lastKnownStatus: "token_expired" });
|
|
256
|
+
return {
|
|
257
|
+
connected: false,
|
|
258
|
+
hubUrl: normalizeHubUrl(hubAddress),
|
|
259
|
+
user: { id: conn.userId, username: conn.username || "", role: "member", status: "token_expired" },
|
|
260
|
+
};
|
|
261
|
+
}
|
|
149
262
|
return { connected: false, user: null };
|
|
150
263
|
}
|
|
151
264
|
}
|
|
@@ -176,12 +289,17 @@ export async function autoJoinHub(
|
|
|
176
289
|
}
|
|
177
290
|
}
|
|
178
291
|
|
|
292
|
+
const persisted = store.getClientHubConnection();
|
|
293
|
+
const existingIdentityKey = persisted?.identityKey || "";
|
|
294
|
+
|
|
179
295
|
log.info(`Joining Hub at ${hubUrl} as "${username}"...`);
|
|
180
296
|
const result = await hubRequestJson(hubUrl, "", "/api/v1/hub/join", {
|
|
181
297
|
method: "POST",
|
|
182
|
-
body: JSON.stringify({ teamToken, username, deviceName: hostname, clientIp }),
|
|
298
|
+
body: JSON.stringify({ teamToken, username, deviceName: hostname, clientIp, identityKey: existingIdentityKey }),
|
|
183
299
|
}) as any;
|
|
184
300
|
|
|
301
|
+
const returnedIdentityKey = String(result.identityKey || existingIdentityKey || "");
|
|
302
|
+
|
|
185
303
|
if (result.status === "pending") {
|
|
186
304
|
log.info(`Join request submitted, awaiting admin approval. userId=${result.userId}`);
|
|
187
305
|
store.setClientHubConnection({
|
|
@@ -191,6 +309,8 @@ export async function autoJoinHub(
|
|
|
191
309
|
userToken: "",
|
|
192
310
|
role: "member",
|
|
193
311
|
connectedAt: Date.now(),
|
|
312
|
+
identityKey: returnedIdentityKey,
|
|
313
|
+
lastKnownStatus: "pending",
|
|
194
314
|
});
|
|
195
315
|
throw new PendingApprovalError(result.userId);
|
|
196
316
|
}
|
|
@@ -199,6 +319,10 @@ export async function autoJoinHub(
|
|
|
199
319
|
throw new Error(`Join request was rejected by the Hub admin.`);
|
|
200
320
|
}
|
|
201
321
|
|
|
322
|
+
if (result.status === "blocked") {
|
|
323
|
+
throw new Error(`Your account has been blocked by the Hub admin.`);
|
|
324
|
+
}
|
|
325
|
+
|
|
202
326
|
if (!result.userToken) {
|
|
203
327
|
throw new Error(`Hub join failed: ${JSON.stringify(result)}`);
|
|
204
328
|
}
|
|
@@ -211,6 +335,8 @@ export async function autoJoinHub(
|
|
|
211
335
|
userToken: result.userToken,
|
|
212
336
|
role: "member",
|
|
213
337
|
connectedAt: Date.now(),
|
|
338
|
+
identityKey: returnedIdentityKey,
|
|
339
|
+
lastKnownStatus: "active",
|
|
214
340
|
});
|
|
215
341
|
return store.getClientHubConnection()!;
|
|
216
342
|
}
|
package/src/config.ts
CHANGED
|
@@ -128,7 +128,8 @@ export function resolveConfig(raw: Partial<MemosLocalConfig> | undefined, stateD
|
|
|
128
128
|
userToken: cfg.sharing?.client?.userToken ?? "",
|
|
129
129
|
teamToken: cfg.sharing?.client?.teamToken ?? "",
|
|
130
130
|
pendingUserId: cfg.sharing?.client?.pendingUserId ?? "",
|
|
131
|
-
|
|
131
|
+
nickname: cfg.sharing?.client?.nickname ?? "",
|
|
132
|
+
} : { hubAddress: "", userToken: "", teamToken: "", pendingUserId: "", nickname: "" };
|
|
132
133
|
return { enabled, role, hub, client, capabilities: sharingCapabilities };
|
|
133
134
|
})(),
|
|
134
135
|
};
|