@memtensor/memos-local-openclaw-plugin 1.0.4-beta.0 → 1.0.4-beta.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/dist/client/connector.d.ts +4 -0
- package/dist/client/connector.d.ts.map +1 -1
- package/dist/client/connector.js +92 -0
- package/dist/client/connector.js.map +1 -1
- package/dist/config.js +9 -9
- package/dist/config.js.map +1 -1
- package/dist/hub/server.d.ts.map +1 -1
- package/dist/hub/server.js +27 -22
- package/dist/hub/server.js.map +1 -1
- package/dist/hub/user-manager.d.ts +1 -0
- package/dist/hub/user-manager.d.ts.map +1 -1
- package/dist/hub/user-manager.js +13 -0
- package/dist/hub/user-manager.js.map +1 -1
- package/dist/storage/sqlite.d.ts.map +1 -1
- package/dist/storage/sqlite.js +20 -94
- package/dist/storage/sqlite.js.map +1 -1
- package/dist/viewer/html.d.ts.map +1 -1
- package/dist/viewer/html.js +393 -211
- package/dist/viewer/html.js.map +1 -1
- package/dist/viewer/server.d.ts +2 -0
- package/dist/viewer/server.d.ts.map +1 -1
- package/dist/viewer/server.js +104 -15
- package/dist/viewer/server.js.map +1 -1
- package/package.json +1 -1
- package/src/client/connector.ts +94 -0
- package/src/config.ts +9 -9
- package/src/hub/server.ts +28 -22
- package/src/hub/user-manager.ts +13 -0
- package/src/storage/sqlite.ts +20 -94
- package/src/viewer/html.ts +393 -211
- package/src/viewer/server.ts +98 -15
package/src/viewer/server.ts
CHANGED
|
@@ -251,6 +251,7 @@ export class ViewerServer {
|
|
|
251
251
|
else if (p === "/api/sharing/pending-users" && req.method === "GET") this.serveSharingPendingUsers(res);
|
|
252
252
|
else if (p === "/api/sharing/approve-user" && req.method === "POST") this.handleSharingApproveUser(req, res);
|
|
253
253
|
else if (p === "/api/sharing/reject-user" && req.method === "POST") this.handleSharingRejectUser(req, res);
|
|
254
|
+
else if (p === "/api/sharing/retry-join" && req.method === "POST") this.handleRetryJoin(req, res);
|
|
254
255
|
else if (p === "/api/sharing/search/memories" && req.method === "POST") this.handleSharingMemorySearch(req, res);
|
|
255
256
|
else if (p === "/api/sharing/memories/list" && req.method === "GET") this.serveSharingMemoryList(res, url);
|
|
256
257
|
else if (p === "/api/sharing/tasks/list" && req.method === "GET") this.serveSharingTaskList(res, url);
|
|
@@ -1185,7 +1186,8 @@ export class ViewerServer {
|
|
|
1185
1186
|
return;
|
|
1186
1187
|
}
|
|
1187
1188
|
|
|
1188
|
-
|
|
1189
|
+
const hasPendingConnection = Boolean(persisted?.hubUrl && persisted?.userId && !persisted?.userToken);
|
|
1190
|
+
if (!hasClientConfig && !hasPendingConnection) {
|
|
1189
1191
|
this.jsonResponse(res, base);
|
|
1190
1192
|
return;
|
|
1191
1193
|
}
|
|
@@ -1193,12 +1195,23 @@ export class ViewerServer {
|
|
|
1193
1195
|
try {
|
|
1194
1196
|
const status = await getHubStatus(this.store, this.ctx.config);
|
|
1195
1197
|
const output = { ...base, connection: { ...base.connection, ...status } } as any;
|
|
1198
|
+
if (status.user?.status === "pending") {
|
|
1199
|
+
output.connection.pendingApproval = true;
|
|
1200
|
+
}
|
|
1201
|
+
if (status.user?.status === "rejected") {
|
|
1202
|
+
output.connection.rejected = true;
|
|
1203
|
+
}
|
|
1196
1204
|
if (status.connected && status.hubUrl) {
|
|
1197
1205
|
try {
|
|
1198
1206
|
const info = await fetch(`${status.hubUrl}/api/v1/hub/info`).then((r) => (r.ok ? r.json() : null)).catch(() => null) as any;
|
|
1199
1207
|
output.connection.teamName = info?.teamName ?? null;
|
|
1200
1208
|
output.connection.apiVersion = info?.apiVersion ?? null;
|
|
1201
1209
|
} catch {}
|
|
1210
|
+
} else if (status.hubUrl) {
|
|
1211
|
+
try {
|
|
1212
|
+
const info = await fetch(`${status.hubUrl}/api/v1/hub/info`).then((r) => (r.ok ? r.json() : null)).catch(() => null) as any;
|
|
1213
|
+
output.connection.teamName = info?.teamName ?? null;
|
|
1214
|
+
} catch {}
|
|
1202
1215
|
}
|
|
1203
1216
|
output.admin.canManageUsers = status.connected && status.user?.role === "admin";
|
|
1204
1217
|
output.admin.rejectSupported = output.admin.canManageUsers;
|
|
@@ -1256,6 +1269,42 @@ export class ViewerServer {
|
|
|
1256
1269
|
});
|
|
1257
1270
|
}
|
|
1258
1271
|
|
|
1272
|
+
private handleRetryJoin(req: http.IncomingMessage, res: http.ServerResponse): void {
|
|
1273
|
+
this.readBody(req, async (_body) => {
|
|
1274
|
+
if (!this.ctx) return this.jsonResponse(res, { ok: false, error: "sharing_unavailable" });
|
|
1275
|
+
const sharing = this.ctx.config.sharing;
|
|
1276
|
+
if (!sharing?.enabled || sharing.role !== "client") {
|
|
1277
|
+
return this.jsonResponse(res, { ok: false, error: "not_in_client_mode" });
|
|
1278
|
+
}
|
|
1279
|
+
const hubAddress = sharing.client?.hubAddress ?? "";
|
|
1280
|
+
const teamToken = sharing.client?.teamToken ?? "";
|
|
1281
|
+
if (!hubAddress || !teamToken) {
|
|
1282
|
+
return this.jsonResponse(res, { ok: false, error: "missing_hub_address_or_team_token" });
|
|
1283
|
+
}
|
|
1284
|
+
try {
|
|
1285
|
+
const hubUrl = normalizeHubUrl(hubAddress);
|
|
1286
|
+
const os = await import("os");
|
|
1287
|
+
const username = os.userInfo().username || "user";
|
|
1288
|
+
const hostname = os.hostname() || "unknown";
|
|
1289
|
+
const result = await hubRequestJson(hubUrl, "", "/api/v1/hub/join", {
|
|
1290
|
+
method: "POST",
|
|
1291
|
+
body: JSON.stringify({ teamToken, username, deviceName: hostname }),
|
|
1292
|
+
}) as any;
|
|
1293
|
+
this.store.setClientHubConnection({
|
|
1294
|
+
hubUrl,
|
|
1295
|
+
userId: String(result.userId || ""),
|
|
1296
|
+
username,
|
|
1297
|
+
userToken: result.userToken || "",
|
|
1298
|
+
role: "member",
|
|
1299
|
+
connectedAt: Date.now(),
|
|
1300
|
+
});
|
|
1301
|
+
this.jsonResponse(res, { ok: true, status: result.status || "pending" });
|
|
1302
|
+
} catch (err) {
|
|
1303
|
+
this.jsonResponse(res, { ok: false, error: String(err) });
|
|
1304
|
+
}
|
|
1305
|
+
});
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1259
1308
|
private async serveSharingMemoryList(res: http.ServerResponse, url: URL): Promise<void> {
|
|
1260
1309
|
if (!this.ctx) return this.jsonResponse(res, { memories: [], error: "sharing_unavailable" });
|
|
1261
1310
|
try {
|
|
@@ -1395,8 +1444,8 @@ export class ViewerServer {
|
|
|
1395
1444
|
try {
|
|
1396
1445
|
const parsed = JSON.parse(body || "{}");
|
|
1397
1446
|
const taskId = String(parsed.taskId || "");
|
|
1398
|
-
const visibility =
|
|
1399
|
-
const groupId
|
|
1447
|
+
const visibility = "public";
|
|
1448
|
+
const groupId: string | undefined = undefined;
|
|
1400
1449
|
const task = this.store.getTask(taskId);
|
|
1401
1450
|
if (!task) return this.jsonResponse(res, { ok: false, error: "task_not_found" });
|
|
1402
1451
|
const chunks = this.store.getChunksByTask(taskId);
|
|
@@ -1410,7 +1459,7 @@ export class ViewerServer {
|
|
|
1410
1459
|
sourceTaskId: task.id,
|
|
1411
1460
|
title: task.title,
|
|
1412
1461
|
summary: task.summary,
|
|
1413
|
-
groupId:
|
|
1462
|
+
groupId: null,
|
|
1414
1463
|
visibility,
|
|
1415
1464
|
createdAt: task.startedAt ?? Date.now(),
|
|
1416
1465
|
updatedAt: task.updatedAt ?? Date.now(),
|
|
@@ -1436,7 +1485,7 @@ export class ViewerServer {
|
|
|
1436
1485
|
sourceUserId: hubUserId,
|
|
1437
1486
|
title: task.title,
|
|
1438
1487
|
summary: task.summary,
|
|
1439
|
-
groupId:
|
|
1488
|
+
groupId: null,
|
|
1440
1489
|
visibility,
|
|
1441
1490
|
createdAt: task.startedAt ?? Date.now(),
|
|
1442
1491
|
updatedAt: task.updatedAt ?? Date.now(),
|
|
@@ -1477,8 +1526,8 @@ export class ViewerServer {
|
|
|
1477
1526
|
try {
|
|
1478
1527
|
const parsed = JSON.parse(body || "{}");
|
|
1479
1528
|
const chunkId = String(parsed.chunkId || "");
|
|
1480
|
-
const visibility =
|
|
1481
|
-
const groupId
|
|
1529
|
+
const visibility = "public";
|
|
1530
|
+
const groupId: string | undefined = undefined;
|
|
1482
1531
|
const db = (this.store as any).db;
|
|
1483
1532
|
const chunk = db.prepare("SELECT * FROM chunks WHERE id = ?").get(chunkId) as any;
|
|
1484
1533
|
if (!chunk) return this.jsonResponse(res, { ok: false, error: "memory_not_found" });
|
|
@@ -1492,7 +1541,7 @@ export class ViewerServer {
|
|
|
1492
1541
|
content: chunk.content,
|
|
1493
1542
|
summary: chunk.summary,
|
|
1494
1543
|
kind: chunk.kind,
|
|
1495
|
-
groupId:
|
|
1544
|
+
groupId: null,
|
|
1496
1545
|
visibility,
|
|
1497
1546
|
},
|
|
1498
1547
|
}),
|
|
@@ -1509,7 +1558,7 @@ export class ViewerServer {
|
|
|
1509
1558
|
content: chunk.content,
|
|
1510
1559
|
summary: chunk.summary ?? "",
|
|
1511
1560
|
kind: chunk.kind,
|
|
1512
|
-
groupId:
|
|
1561
|
+
groupId: null,
|
|
1513
1562
|
visibility,
|
|
1514
1563
|
createdAt: existing?.createdAt ?? now,
|
|
1515
1564
|
updatedAt: now,
|
|
@@ -1563,8 +1612,8 @@ export class ViewerServer {
|
|
|
1563
1612
|
try {
|
|
1564
1613
|
const parsed = JSON.parse(body || "{}");
|
|
1565
1614
|
const skillId = String(parsed.skillId || "");
|
|
1566
|
-
const visibility =
|
|
1567
|
-
const groupId
|
|
1615
|
+
const visibility = "public";
|
|
1616
|
+
const groupId: string | null = null;
|
|
1568
1617
|
const skill = this.store.getSkill(skillId);
|
|
1569
1618
|
if (!skill) return this.jsonResponse(res, { ok: false, error: "skill_not_found" });
|
|
1570
1619
|
const bundle = buildSkillBundleForHub(this.store, skillId);
|
|
@@ -1573,7 +1622,7 @@ export class ViewerServer {
|
|
|
1573
1622
|
method: "POST",
|
|
1574
1623
|
body: JSON.stringify({
|
|
1575
1624
|
visibility,
|
|
1576
|
-
groupId:
|
|
1625
|
+
groupId: null,
|
|
1577
1626
|
metadata: bundle.metadata,
|
|
1578
1627
|
bundle: bundle.bundle,
|
|
1579
1628
|
}),
|
|
@@ -1588,7 +1637,7 @@ export class ViewerServer {
|
|
|
1588
1637
|
name: skill.name,
|
|
1589
1638
|
description: skill.description,
|
|
1590
1639
|
version: skill.version,
|
|
1591
|
-
groupId:
|
|
1640
|
+
groupId: null,
|
|
1592
1641
|
visibility,
|
|
1593
1642
|
bundle: JSON.stringify(bundle.bundle),
|
|
1594
1643
|
qualityScore: skill.qualityScore,
|
|
@@ -1864,7 +1913,7 @@ export class ViewerServer {
|
|
|
1864
1913
|
}
|
|
1865
1914
|
}
|
|
1866
1915
|
|
|
1867
|
-
private
|
|
1916
|
+
private getLocalIPs(): string[] {
|
|
1868
1917
|
const nets = os.networkInterfaces();
|
|
1869
1918
|
const ips: string[] = [];
|
|
1870
1919
|
for (const name of Object.keys(nets)) {
|
|
@@ -1874,6 +1923,11 @@ export class ViewerServer {
|
|
|
1874
1923
|
}
|
|
1875
1924
|
}
|
|
1876
1925
|
}
|
|
1926
|
+
return ips;
|
|
1927
|
+
}
|
|
1928
|
+
|
|
1929
|
+
private serveLocalIPs(res: http.ServerResponse): void {
|
|
1930
|
+
const ips = this.getLocalIPs();
|
|
1877
1931
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
1878
1932
|
res.end(JSON.stringify({ ips }));
|
|
1879
1933
|
}
|
|
@@ -1942,10 +1996,30 @@ export class ViewerServer {
|
|
|
1942
1996
|
if (newCfg.sharing !== undefined) {
|
|
1943
1997
|
const existing = (config.sharing as Record<string, unknown>) || {};
|
|
1944
1998
|
const merged = { ...existing, ...newCfg.sharing };
|
|
1945
|
-
// Deep-merge capabilities so new keys don't wipe existing ones
|
|
1946
1999
|
if (newCfg.sharing.capabilities && existing.capabilities) {
|
|
1947
2000
|
merged.capabilities = { ...(existing.capabilities as Record<string, unknown>), ...newCfg.sharing.capabilities };
|
|
1948
2001
|
}
|
|
2002
|
+
if (merged.role === "client" && merged.client) {
|
|
2003
|
+
const clientCfg = merged.client as Record<string, unknown>;
|
|
2004
|
+
const addr = String(clientCfg.hubAddress || "");
|
|
2005
|
+
if (addr) {
|
|
2006
|
+
const localIPs = this.getLocalIPs();
|
|
2007
|
+
localIPs.push("127.0.0.1", "localhost", "0.0.0.0");
|
|
2008
|
+
try {
|
|
2009
|
+
const u = new URL(addr.startsWith("http") ? addr : `http://${addr}`);
|
|
2010
|
+
if (localIPs.includes(u.hostname)) {
|
|
2011
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
2012
|
+
res.end(JSON.stringify({ error: "cannot_join_self" }));
|
|
2013
|
+
return;
|
|
2014
|
+
}
|
|
2015
|
+
} catch {}
|
|
2016
|
+
}
|
|
2017
|
+
}
|
|
2018
|
+
if (merged.role === "hub") {
|
|
2019
|
+
merged.client = { hubAddress: "", userToken: "", teamToken: "" };
|
|
2020
|
+
} else if (merged.role === "client") {
|
|
2021
|
+
merged.hub = { port: 18800, teamName: "", teamToken: "" };
|
|
2022
|
+
}
|
|
1949
2023
|
config.sharing = merged;
|
|
1950
2024
|
}
|
|
1951
2025
|
|
|
@@ -2014,6 +2088,15 @@ export class ViewerServer {
|
|
|
2014
2088
|
try {
|
|
2015
2089
|
const { hubUrl } = JSON.parse(body);
|
|
2016
2090
|
if (!hubUrl) { this.jsonResponse(res, { ok: false, error: "hubUrl is required" }); return; }
|
|
2091
|
+
try {
|
|
2092
|
+
const localIPs = this.getLocalIPs();
|
|
2093
|
+
localIPs.push("127.0.0.1", "localhost", "0.0.0.0");
|
|
2094
|
+
const parsed = new URL(hubUrl.startsWith("http") ? hubUrl : `http://${hubUrl}`);
|
|
2095
|
+
if (localIPs.includes(parsed.hostname)) {
|
|
2096
|
+
this.jsonResponse(res, { ok: false, error: "cannot_join_self" });
|
|
2097
|
+
return;
|
|
2098
|
+
}
|
|
2099
|
+
} catch {}
|
|
2017
2100
|
const url = hubUrl.replace(/\/+$/, "") + "/api/v1/hub/info";
|
|
2018
2101
|
const ctrl = new AbortController();
|
|
2019
2102
|
const timeout = setTimeout(() => ctrl.abort(), 8000);
|