@memtensor/memos-local-openclaw-plugin 1.0.4-beta.9 → 1.0.5

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.
Files changed (100) hide show
  1. package/.env.example +7 -0
  2. package/README.md +94 -27
  3. package/dist/capture/index.js +3 -1
  4. package/dist/capture/index.js.map +1 -1
  5. package/dist/client/connector.d.ts +5 -0
  6. package/dist/client/connector.d.ts.map +1 -1
  7. package/dist/client/connector.js +89 -8
  8. package/dist/client/connector.js.map +1 -1
  9. package/dist/config.d.ts.map +1 -1
  10. package/dist/config.js +2 -1
  11. package/dist/config.js.map +1 -1
  12. package/dist/hub/server.d.ts +2 -0
  13. package/dist/hub/server.d.ts.map +1 -1
  14. package/dist/hub/server.js +240 -35
  15. package/dist/hub/server.js.map +1 -1
  16. package/dist/hub/user-manager.d.ts +9 -0
  17. package/dist/hub/user-manager.d.ts.map +1 -1
  18. package/dist/hub/user-manager.js +26 -2
  19. package/dist/hub/user-manager.js.map +1 -1
  20. package/dist/ingest/chunker.d.ts +2 -1
  21. package/dist/ingest/chunker.d.ts.map +1 -1
  22. package/dist/ingest/chunker.js +14 -10
  23. package/dist/ingest/chunker.js.map +1 -1
  24. package/dist/ingest/providers/index.js +2 -2
  25. package/dist/ingest/providers/index.js.map +1 -1
  26. package/dist/recall/engine.d.ts.map +1 -1
  27. package/dist/recall/engine.js +22 -4
  28. package/dist/recall/engine.js.map +1 -1
  29. package/dist/shared/llm-call.d.ts.map +1 -1
  30. package/dist/shared/llm-call.js +2 -1
  31. package/dist/shared/llm-call.js.map +1 -1
  32. package/dist/sharing/types.d.ts +1 -1
  33. package/dist/sharing/types.d.ts.map +1 -1
  34. package/dist/skill/evolver.d.ts +2 -0
  35. package/dist/skill/evolver.d.ts.map +1 -1
  36. package/dist/skill/evolver.js +56 -5
  37. package/dist/skill/evolver.js.map +1 -1
  38. package/dist/skill/generator.d.ts +2 -0
  39. package/dist/skill/generator.d.ts.map +1 -1
  40. package/dist/skill/generator.js +45 -3
  41. package/dist/skill/generator.js.map +1 -1
  42. package/dist/skill/installer.d.ts +26 -0
  43. package/dist/skill/installer.d.ts.map +1 -1
  44. package/dist/skill/installer.js +80 -4
  45. package/dist/skill/installer.js.map +1 -1
  46. package/dist/skill/upgrader.d.ts +2 -0
  47. package/dist/skill/upgrader.d.ts.map +1 -1
  48. package/dist/skill/upgrader.js +139 -1
  49. package/dist/skill/upgrader.js.map +1 -1
  50. package/dist/skill/validator.d.ts +3 -0
  51. package/dist/skill/validator.d.ts.map +1 -1
  52. package/dist/skill/validator.js +75 -0
  53. package/dist/skill/validator.js.map +1 -1
  54. package/dist/storage/sqlite.d.ts +57 -0
  55. package/dist/storage/sqlite.d.ts.map +1 -1
  56. package/dist/storage/sqlite.js +290 -35
  57. package/dist/storage/sqlite.js.map +1 -1
  58. package/dist/telemetry.d.ts +4 -1
  59. package/dist/telemetry.d.ts.map +1 -1
  60. package/dist/telemetry.js +39 -12
  61. package/dist/telemetry.js.map +1 -1
  62. package/dist/types.d.ts +10 -0
  63. package/dist/types.d.ts.map +1 -1
  64. package/dist/types.js +4 -0
  65. package/dist/types.js.map +1 -1
  66. package/dist/viewer/html.d.ts.map +1 -1
  67. package/dist/viewer/html.js +564 -225
  68. package/dist/viewer/html.js.map +1 -1
  69. package/dist/viewer/server.d.ts +9 -0
  70. package/dist/viewer/server.d.ts.map +1 -1
  71. package/dist/viewer/server.js +357 -108
  72. package/dist/viewer/server.js.map +1 -1
  73. package/index.ts +412 -53
  74. package/openclaw.plugin.json +1 -1
  75. package/package.json +2 -1
  76. package/prebuilds/darwin-arm64/better_sqlite3.node +0 -0
  77. package/prebuilds/darwin-x64/better_sqlite3.node +0 -0
  78. package/prebuilds/linux-x64/better_sqlite3.node +0 -0
  79. package/prebuilds/win32-x64/better_sqlite3.node +0 -0
  80. package/src/capture/index.ts +4 -1
  81. package/src/client/connector.ts +92 -8
  82. package/src/config.ts +2 -1
  83. package/src/hub/server.ts +235 -35
  84. package/src/hub/user-manager.ts +42 -6
  85. package/src/ingest/chunker.ts +19 -13
  86. package/src/ingest/providers/index.ts +2 -2
  87. package/src/recall/engine.ts +20 -4
  88. package/src/shared/llm-call.ts +2 -1
  89. package/src/sharing/types.ts +1 -1
  90. package/src/skill/evolver.ts +58 -6
  91. package/src/skill/generator.ts +44 -5
  92. package/src/skill/installer.ts +107 -4
  93. package/src/skill/upgrader.ts +139 -1
  94. package/src/skill/validator.ts +79 -0
  95. package/src/storage/sqlite.ts +318 -40
  96. package/src/telemetry.ts +39 -14
  97. package/src/types.ts +11 -0
  98. package/src/viewer/html.ts +564 -225
  99. package/src/viewer/server.ts +333 -105
  100. package/telemetry.credentials.json +5 -0
@@ -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 {
@@ -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
 
@@ -54,6 +56,8 @@ export async function connectToHub(store: SqliteStore, config: MemosLocalConfig,
54
56
  userToken: result.userToken,
55
57
  role: "member",
56
58
  connectedAt: Date.now(),
59
+ identityKey: persisted.identityKey || "",
60
+ lastKnownStatus: "active",
57
61
  });
58
62
  return store.getClientHubConnection()!;
59
63
  }
@@ -63,6 +67,12 @@ export async function connectToHub(store: SqliteStore, config: MemosLocalConfig,
63
67
  if (result.status === "rejected") {
64
68
  throw new Error("Join request was rejected by the Hub admin.");
65
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
+ }
66
76
  } catch (err) {
67
77
  if (err instanceof PendingApprovalError) throw err;
68
78
  log.warn(`registration-status check failed, falling back to autoJoinHub: ${err}`);
@@ -78,6 +88,7 @@ export async function connectToHub(store: SqliteStore, config: MemosLocalConfig,
78
88
 
79
89
  const hubUrl = normalizeHubUrl(hubAddress);
80
90
  const me = await hubRequestJson(hubUrl, userToken, "/api/v1/hub/me", { method: "GET" }) as any;
91
+ const persisted = store.getClientHubConnection();
81
92
  store.setClientHubConnection({
82
93
  hubUrl,
83
94
  userId: String(me.id),
@@ -85,6 +96,8 @@ export async function connectToHub(store: SqliteStore, config: MemosLocalConfig,
85
96
  userToken,
86
97
  role: String(me.role ?? "member") as UserRole,
87
98
  connectedAt: Date.now(),
99
+ identityKey: persisted?.identityKey || String(me.identityKey ?? ""),
100
+ lastKnownStatus: "active",
88
101
  });
89
102
  return store.getClientHubConnection()!;
90
103
  }
@@ -95,9 +108,13 @@ export async function getHubStatus(store: SqliteStore, config: MemosLocalConfig)
95
108
  const hubAddress = conn?.hubUrl || (configHubAddress ? normalizeHubUrl(configHubAddress) : "");
96
109
  const userToken = conn?.userToken || config.sharing?.client?.userToken || "";
97
110
 
98
- // If DB has a connection to a different Hub than config, the DB data is stale
99
111
  if (conn && configHubAddress && conn.hubUrl && normalizeHubUrl(configHubAddress) !== conn.hubUrl) {
100
- store.clearClientHubConnection();
112
+ store.setClientHubConnection({
113
+ ...conn,
114
+ hubUrl: normalizeHubUrl(configHubAddress),
115
+ userToken: "",
116
+ lastKnownStatus: "hub_changed",
117
+ });
101
118
  return { connected: false, user: null };
102
119
  }
103
120
 
@@ -129,6 +146,8 @@ export async function getHubStatus(store: SqliteStore, config: MemosLocalConfig)
129
146
  userToken: result.userToken,
130
147
  role: "member",
131
148
  connectedAt: Date.now(),
149
+ identityKey: conn.identityKey || "",
150
+ lastKnownStatus: "active",
132
151
  });
133
152
  const me = await hubRequestJson(normalizeHubUrl(hubAddress), result.userToken, "/api/v1/hub/me", { method: "GET" }) as any;
134
153
  return {
@@ -169,12 +188,10 @@ export async function getHubStatus(store: SqliteStore, config: MemosLocalConfig)
169
188
  const latestRole = String(me.role ?? "member") as UserRole;
170
189
  if (conn && (conn.username !== latestUsername || conn.role !== latestRole)) {
171
190
  store.setClientHubConnection({
172
- hubUrl: conn.hubUrl,
173
- userId: conn.userId,
191
+ ...conn,
174
192
  username: latestUsername,
175
- userToken: conn.userToken,
176
193
  role: latestRole,
177
- connectedAt: conn.connectedAt,
194
+ lastKnownStatus: "active",
178
195
  });
179
196
  }
180
197
  return {
@@ -185,9 +202,63 @@ export async function getHubStatus(store: SqliteStore, config: MemosLocalConfig)
185
202
  username: latestUsername,
186
203
  role: latestRole,
187
204
  status: String(me.status ?? "active"),
205
+ groups: Array.isArray(me.groups) ? me.groups : [],
188
206
  },
189
207
  };
190
- } 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
+ }
191
262
  return { connected: false, user: null };
192
263
  }
193
264
  }
@@ -218,12 +289,17 @@ export async function autoJoinHub(
218
289
  }
219
290
  }
220
291
 
292
+ const persisted = store.getClientHubConnection();
293
+ const existingIdentityKey = persisted?.identityKey || "";
294
+
221
295
  log.info(`Joining Hub at ${hubUrl} as "${username}"...`);
222
296
  const result = await hubRequestJson(hubUrl, "", "/api/v1/hub/join", {
223
297
  method: "POST",
224
- body: JSON.stringify({ teamToken, username, deviceName: hostname, clientIp }),
298
+ body: JSON.stringify({ teamToken, username, deviceName: hostname, clientIp, identityKey: existingIdentityKey }),
225
299
  }) as any;
226
300
 
301
+ const returnedIdentityKey = String(result.identityKey || existingIdentityKey || "");
302
+
227
303
  if (result.status === "pending") {
228
304
  log.info(`Join request submitted, awaiting admin approval. userId=${result.userId}`);
229
305
  store.setClientHubConnection({
@@ -233,6 +309,8 @@ export async function autoJoinHub(
233
309
  userToken: "",
234
310
  role: "member",
235
311
  connectedAt: Date.now(),
312
+ identityKey: returnedIdentityKey,
313
+ lastKnownStatus: "pending",
236
314
  });
237
315
  throw new PendingApprovalError(result.userId);
238
316
  }
@@ -241,6 +319,10 @@ export async function autoJoinHub(
241
319
  throw new Error(`Join request was rejected by the Hub admin.`);
242
320
  }
243
321
 
322
+ if (result.status === "blocked") {
323
+ throw new Error(`Your account has been blocked by the Hub admin.`);
324
+ }
325
+
244
326
  if (!result.userToken) {
245
327
  throw new Error(`Hub join failed: ${JSON.stringify(result)}`);
246
328
  }
@@ -253,6 +335,8 @@ export async function autoJoinHub(
253
335
  userToken: result.userToken,
254
336
  role: "member",
255
337
  connectedAt: Date.now(),
338
+ identityKey: returnedIdentityKey,
339
+ lastKnownStatus: "active",
256
340
  });
257
341
  return store.getClientHubConnection()!;
258
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
- } : { hubAddress: "", userToken: "", teamToken: "", pendingUserId: "" };
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
  };