openmates 0.11.0-alpha.13 → 0.11.0-alpha.15
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/{chunk-NS4C7FTB.js → chunk-A5UXPRLU.js} +444 -162
- package/dist/cli.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -1
- package/package.json +3 -2
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
} from "./chunk-SFTCIVE2.js";
|
|
4
4
|
|
|
5
5
|
// src/client.ts
|
|
6
|
-
import { randomUUID } from "crypto";
|
|
6
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
7
7
|
import { platform as platform2, release } from "os";
|
|
8
8
|
import { createInterface } from "readline/promises";
|
|
9
9
|
import { stdin, stdout } from "process";
|
|
@@ -726,6 +726,12 @@ function loadSyncCache() {
|
|
|
726
726
|
const filePath = join(ensureStateDir(), SYNC_CACHE_FILE);
|
|
727
727
|
return readJsonFile(filePath);
|
|
728
728
|
}
|
|
729
|
+
function clearSyncCache() {
|
|
730
|
+
const filePath = join(ensureStateDir(), SYNC_CACHE_FILE);
|
|
731
|
+
if (existsSync2(filePath)) {
|
|
732
|
+
rmSync(filePath);
|
|
733
|
+
}
|
|
734
|
+
}
|
|
729
735
|
function isSyncCacheFresh(maxAgeMs = 3e5) {
|
|
730
736
|
const cache = loadSyncCache();
|
|
731
737
|
if (!cache) return false;
|
|
@@ -733,7 +739,9 @@ function isSyncCacheFresh(maxAgeMs = 3e5) {
|
|
|
733
739
|
}
|
|
734
740
|
|
|
735
741
|
// src/ws.ts
|
|
736
|
-
import
|
|
742
|
+
import { createRequire } from "module";
|
|
743
|
+
var require2 = createRequire(import.meta.url);
|
|
744
|
+
var WebSocket = require2("ws");
|
|
737
745
|
var OpenMatesWsClient = class {
|
|
738
746
|
socket;
|
|
739
747
|
constructor(options) {
|
|
@@ -793,6 +801,14 @@ var OpenMatesWsClient = class {
|
|
|
793
801
|
send(type, payload) {
|
|
794
802
|
this.socket.send(JSON.stringify({ type, payload }));
|
|
795
803
|
}
|
|
804
|
+
sendAsync(type, payload) {
|
|
805
|
+
return new Promise((resolve4, reject) => {
|
|
806
|
+
this.socket.send(JSON.stringify({ type, payload }), (error) => {
|
|
807
|
+
if (error) reject(error);
|
|
808
|
+
else resolve4();
|
|
809
|
+
});
|
|
810
|
+
});
|
|
811
|
+
}
|
|
796
812
|
waitForMessage(expectedType, predicate, timeoutMs = 2e4) {
|
|
797
813
|
return new Promise((resolve4, reject) => {
|
|
798
814
|
const onMessage = (rawData) => {
|
|
@@ -895,35 +911,83 @@ var OpenMatesWsClient = class {
|
|
|
895
911
|
collectAiResponse(userMessageId, chatId, options) {
|
|
896
912
|
const timeoutMs = options?.timeoutMs ?? 9e4;
|
|
897
913
|
const onStream = options?.onStream;
|
|
914
|
+
const asyncEmbedWaitMs = options?.asyncEmbedWaitMs ?? 12e4;
|
|
898
915
|
return new Promise((resolve4, reject) => {
|
|
899
916
|
let latestContent = "";
|
|
917
|
+
let messageId = null;
|
|
918
|
+
let taskId = null;
|
|
900
919
|
let category = null;
|
|
901
920
|
let modelName = null;
|
|
902
921
|
let followUpSuggestions = [];
|
|
922
|
+
const embeds = /* @__PURE__ */ new Map();
|
|
923
|
+
const processingEmbedIds = /* @__PURE__ */ new Set();
|
|
903
924
|
let aiResponseDone = false;
|
|
925
|
+
let postProcessingDone = false;
|
|
904
926
|
const POST_PROCESSING_WINDOW_MS = 12e3;
|
|
905
927
|
let postProcessingTimer = null;
|
|
928
|
+
let asyncEmbedTimer = null;
|
|
906
929
|
const timeout = setTimeout(() => {
|
|
907
930
|
cleanup();
|
|
908
931
|
reject(new Error("Timed out waiting for AI response"));
|
|
909
932
|
}, timeoutMs);
|
|
910
933
|
const capture = (p) => {
|
|
934
|
+
if (typeof p.message_id === "string" && p.message_id)
|
|
935
|
+
messageId = p.message_id;
|
|
936
|
+
if (typeof p.task_id === "string" && p.task_id) taskId = p.task_id;
|
|
911
937
|
if (typeof p.category === "string" && p.category) category = p.category;
|
|
912
938
|
if (typeof p.model_name === "string" && p.model_name)
|
|
913
939
|
modelName = p.model_name;
|
|
914
940
|
};
|
|
941
|
+
const extractMessageContent = (message) => {
|
|
942
|
+
if (typeof message.content === "string") return message.content;
|
|
943
|
+
const content = message.content;
|
|
944
|
+
if (!content || typeof content !== "object") return "";
|
|
945
|
+
try {
|
|
946
|
+
const root = content;
|
|
947
|
+
const text = root.content?.[0]?.content?.[0]?.text;
|
|
948
|
+
return typeof text === "string" ? text : "";
|
|
949
|
+
} catch {
|
|
950
|
+
return "";
|
|
951
|
+
}
|
|
952
|
+
};
|
|
953
|
+
const finishPostProcessingWait = () => {
|
|
954
|
+
postProcessingDone = true;
|
|
955
|
+
maybeResolve();
|
|
956
|
+
};
|
|
957
|
+
const maybeResolve = () => {
|
|
958
|
+
if (!aiResponseDone || !postProcessingDone) return;
|
|
959
|
+
if (processingEmbedIds.size > 0 && !asyncEmbedTimer) {
|
|
960
|
+
asyncEmbedTimer = setTimeout(() => {
|
|
961
|
+
cleanup();
|
|
962
|
+
resolve4({
|
|
963
|
+
messageId,
|
|
964
|
+
taskId,
|
|
965
|
+
content: latestContent,
|
|
966
|
+
category,
|
|
967
|
+
modelName,
|
|
968
|
+
followUpSuggestions,
|
|
969
|
+
embeds: [...embeds.values()]
|
|
970
|
+
});
|
|
971
|
+
}, asyncEmbedWaitMs);
|
|
972
|
+
return;
|
|
973
|
+
}
|
|
974
|
+
if (processingEmbedIds.size > 0) return;
|
|
975
|
+
cleanup();
|
|
976
|
+
resolve4({
|
|
977
|
+
messageId,
|
|
978
|
+
taskId,
|
|
979
|
+
content: latestContent,
|
|
980
|
+
category,
|
|
981
|
+
modelName,
|
|
982
|
+
followUpSuggestions,
|
|
983
|
+
embeds: [...embeds.values()]
|
|
984
|
+
});
|
|
985
|
+
};
|
|
915
986
|
const scheduleResolve = (content) => {
|
|
916
987
|
aiResponseDone = true;
|
|
917
988
|
latestContent = content;
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
resolve4({
|
|
921
|
-
content: latestContent,
|
|
922
|
-
category,
|
|
923
|
-
modelName,
|
|
924
|
-
followUpSuggestions
|
|
925
|
-
});
|
|
926
|
-
}, POST_PROCESSING_WINDOW_MS);
|
|
989
|
+
clearTimeout(timeout);
|
|
990
|
+
postProcessingTimer = setTimeout(finishPostProcessingWait, POST_PROCESSING_WINDOW_MS);
|
|
927
991
|
};
|
|
928
992
|
const onMessage = (rawData) => {
|
|
929
993
|
try {
|
|
@@ -939,9 +1003,27 @@ var OpenMatesWsClient = class {
|
|
|
939
1003
|
);
|
|
940
1004
|
return;
|
|
941
1005
|
}
|
|
1006
|
+
if (type === "send_embed_data") {
|
|
1007
|
+
const embedPayload = p.payload && typeof p.payload === "object" ? p.payload : p;
|
|
1008
|
+
if (typeof embedPayload.chat_id === "string" && embedPayload.chat_id !== chatId) {
|
|
1009
|
+
return;
|
|
1010
|
+
}
|
|
1011
|
+
const embedId = embedPayload.embed_id;
|
|
1012
|
+
if (typeof embedId === "string" && embedId) {
|
|
1013
|
+
const status = typeof embedPayload.status === "string" ? embedPayload.status : "finished";
|
|
1014
|
+
embeds.set(embedId, embedPayload);
|
|
1015
|
+
if (status === "processing") {
|
|
1016
|
+
processingEmbedIds.add(embedId);
|
|
1017
|
+
} else {
|
|
1018
|
+
processingEmbedIds.delete(embedId);
|
|
1019
|
+
}
|
|
1020
|
+
maybeResolve();
|
|
1021
|
+
}
|
|
1022
|
+
return;
|
|
1023
|
+
}
|
|
942
1024
|
if (type === "ai_message_update") {
|
|
943
1025
|
const msgId = p.user_message_id ?? p.userMessageId;
|
|
944
|
-
if (msgId !== userMessageId) return;
|
|
1026
|
+
if (msgId !== userMessageId && p.chat_id !== chatId) return;
|
|
945
1027
|
capture(p);
|
|
946
1028
|
if (typeof p.full_content_so_far === "string") {
|
|
947
1029
|
latestContent = p.full_content_so_far;
|
|
@@ -966,7 +1048,7 @@ var OpenMatesWsClient = class {
|
|
|
966
1048
|
}
|
|
967
1049
|
if (type === "ai_background_response_completed") {
|
|
968
1050
|
const msgId = p.user_message_id ?? p.userMessageId;
|
|
969
|
-
if (msgId && msgId !== userMessageId) return;
|
|
1051
|
+
if (msgId && msgId !== userMessageId && p.chat_id !== chatId) return;
|
|
970
1052
|
if (!msgId && p.chat_id !== chatId) return;
|
|
971
1053
|
capture(p);
|
|
972
1054
|
const content = typeof p.full_content === "string" ? p.full_content : latestContent;
|
|
@@ -974,6 +1056,25 @@ var OpenMatesWsClient = class {
|
|
|
974
1056
|
scheduleResolve(content);
|
|
975
1057
|
return;
|
|
976
1058
|
}
|
|
1059
|
+
if (type === "chat_message_added") {
|
|
1060
|
+
if (p.chat_id !== chatId) return;
|
|
1061
|
+
const rawMessage = p.message;
|
|
1062
|
+
if (!rawMessage || typeof rawMessage !== "object") return;
|
|
1063
|
+
const message = rawMessage;
|
|
1064
|
+
if (message.role !== "assistant") return;
|
|
1065
|
+
const content = extractMessageContent(message);
|
|
1066
|
+
if (!content) return;
|
|
1067
|
+
capture(message);
|
|
1068
|
+
if (typeof message.category === "string" && message.category) {
|
|
1069
|
+
category = message.category;
|
|
1070
|
+
}
|
|
1071
|
+
if (typeof message.model_name === "string" && message.model_name) {
|
|
1072
|
+
modelName = message.model_name;
|
|
1073
|
+
}
|
|
1074
|
+
onStream?.({ kind: "done", content, category, modelName });
|
|
1075
|
+
scheduleResolve(content);
|
|
1076
|
+
return;
|
|
1077
|
+
}
|
|
977
1078
|
if (type === "ai_typing_started") {
|
|
978
1079
|
capture(p);
|
|
979
1080
|
onStream?.({
|
|
@@ -997,13 +1098,7 @@ var OpenMatesWsClient = class {
|
|
|
997
1098
|
clearTimeout(postProcessingTimer);
|
|
998
1099
|
postProcessingTimer = null;
|
|
999
1100
|
}
|
|
1000
|
-
|
|
1001
|
-
resolve4({
|
|
1002
|
-
content: latestContent,
|
|
1003
|
-
category,
|
|
1004
|
-
modelName,
|
|
1005
|
-
followUpSuggestions
|
|
1006
|
-
});
|
|
1101
|
+
finishPostProcessingWait();
|
|
1007
1102
|
}
|
|
1008
1103
|
return;
|
|
1009
1104
|
}
|
|
@@ -1018,10 +1113,13 @@ var OpenMatesWsClient = class {
|
|
|
1018
1113
|
if (aiResponseDone) {
|
|
1019
1114
|
cleanup();
|
|
1020
1115
|
resolve4({
|
|
1116
|
+
messageId,
|
|
1117
|
+
taskId,
|
|
1021
1118
|
content: latestContent,
|
|
1022
1119
|
category,
|
|
1023
1120
|
modelName,
|
|
1024
|
-
followUpSuggestions
|
|
1121
|
+
followUpSuggestions,
|
|
1122
|
+
embeds: [...embeds.values()]
|
|
1025
1123
|
});
|
|
1026
1124
|
return;
|
|
1027
1125
|
}
|
|
@@ -1034,6 +1132,10 @@ var OpenMatesWsClient = class {
|
|
|
1034
1132
|
clearTimeout(postProcessingTimer);
|
|
1035
1133
|
postProcessingTimer = null;
|
|
1036
1134
|
}
|
|
1135
|
+
if (asyncEmbedTimer) {
|
|
1136
|
+
clearTimeout(asyncEmbedTimer);
|
|
1137
|
+
asyncEmbedTimer = null;
|
|
1138
|
+
}
|
|
1037
1139
|
this.socket.off("message", onMessage);
|
|
1038
1140
|
this.socket.off("error", onError);
|
|
1039
1141
|
this.socket.off("close", onClose);
|
|
@@ -1345,9 +1447,137 @@ function escapeRegExp(s) {
|
|
|
1345
1447
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1346
1448
|
}
|
|
1347
1449
|
|
|
1450
|
+
// src/embedCreator.ts
|
|
1451
|
+
import { randomUUID, createHash as createHash3, randomBytes, webcrypto as webcrypto3 } from "crypto";
|
|
1452
|
+
import { encode as toonEncode } from "@toon-format/toon";
|
|
1453
|
+
var cryptoApi3 = webcrypto3;
|
|
1454
|
+
var AES_GCM_IV_LENGTH3 = 12;
|
|
1455
|
+
function bytesToBase642(input) {
|
|
1456
|
+
return Buffer.from(input).toString("base64");
|
|
1457
|
+
}
|
|
1458
|
+
function toArrayBuffer2(input) {
|
|
1459
|
+
return input.buffer.slice(input.byteOffset, input.byteOffset + input.byteLength);
|
|
1460
|
+
}
|
|
1461
|
+
async function encryptAesGcm(plaintext, rawKeyBytes) {
|
|
1462
|
+
const iv = cryptoApi3.getRandomValues(new Uint8Array(AES_GCM_IV_LENGTH3));
|
|
1463
|
+
const key = await cryptoApi3.subtle.importKey(
|
|
1464
|
+
"raw",
|
|
1465
|
+
toArrayBuffer2(rawKeyBytes),
|
|
1466
|
+
{ name: "AES-GCM" },
|
|
1467
|
+
false,
|
|
1468
|
+
["encrypt"]
|
|
1469
|
+
);
|
|
1470
|
+
const encrypted = await cryptoApi3.subtle.encrypt(
|
|
1471
|
+
{ name: "AES-GCM", iv: toArrayBuffer2(iv) },
|
|
1472
|
+
key,
|
|
1473
|
+
new TextEncoder().encode(plaintext)
|
|
1474
|
+
);
|
|
1475
|
+
const cipherBytes = new Uint8Array(encrypted);
|
|
1476
|
+
const combined = new Uint8Array(iv.length + cipherBytes.length);
|
|
1477
|
+
combined.set(iv);
|
|
1478
|
+
combined.set(cipherBytes, iv.length);
|
|
1479
|
+
return bytesToBase642(combined);
|
|
1480
|
+
}
|
|
1481
|
+
async function wrapKey(embedKey, wrappingKey) {
|
|
1482
|
+
const cryptoKey = await cryptoApi3.subtle.importKey(
|
|
1483
|
+
"raw",
|
|
1484
|
+
toArrayBuffer2(wrappingKey),
|
|
1485
|
+
{ name: "AES-GCM" },
|
|
1486
|
+
false,
|
|
1487
|
+
["encrypt"]
|
|
1488
|
+
);
|
|
1489
|
+
const iv = cryptoApi3.getRandomValues(new Uint8Array(AES_GCM_IV_LENGTH3));
|
|
1490
|
+
const encrypted = await cryptoApi3.subtle.encrypt(
|
|
1491
|
+
{ name: "AES-GCM", iv: toArrayBuffer2(iv) },
|
|
1492
|
+
cryptoKey,
|
|
1493
|
+
toArrayBuffer2(embedKey)
|
|
1494
|
+
);
|
|
1495
|
+
const cipherBytes = new Uint8Array(encrypted);
|
|
1496
|
+
const combined = new Uint8Array(iv.length + cipherBytes.length);
|
|
1497
|
+
combined.set(iv);
|
|
1498
|
+
combined.set(cipherBytes, iv.length);
|
|
1499
|
+
return bytesToBase642(combined);
|
|
1500
|
+
}
|
|
1501
|
+
function generateEmbedKey() {
|
|
1502
|
+
return new Uint8Array(randomBytes(32));
|
|
1503
|
+
}
|
|
1504
|
+
function computeSHA256(content) {
|
|
1505
|
+
return createHash3("sha256").update(content).digest("hex");
|
|
1506
|
+
}
|
|
1507
|
+
function toonEncodeContent(data) {
|
|
1508
|
+
try {
|
|
1509
|
+
return toonEncode(data);
|
|
1510
|
+
} catch {
|
|
1511
|
+
return JSON.stringify(data);
|
|
1512
|
+
}
|
|
1513
|
+
}
|
|
1514
|
+
function generateEmbedId() {
|
|
1515
|
+
return randomUUID();
|
|
1516
|
+
}
|
|
1517
|
+
function createEmbedReferenceBlock(type, embedId) {
|
|
1518
|
+
const ref = JSON.stringify({ type, embed_id: embedId }, null, 2);
|
|
1519
|
+
return "```json\n" + ref + "\n```";
|
|
1520
|
+
}
|
|
1521
|
+
async function encryptEmbed(embed, masterKey, chatKey, chatId, messageId, userId) {
|
|
1522
|
+
try {
|
|
1523
|
+
const embedKey = generateEmbedKey();
|
|
1524
|
+
const encryptedContent = await encryptAesGcm(embed.content, embedKey);
|
|
1525
|
+
const encryptedType = await encryptAesGcm(embed.type, embedKey);
|
|
1526
|
+
const encryptedTextPreview = await encryptAesGcm(embed.textPreview, embedKey);
|
|
1527
|
+
const hashedEmbedId = computeSHA256(embed.embedId);
|
|
1528
|
+
const hashedChatId = computeSHA256(chatId);
|
|
1529
|
+
const hashedMessageId = computeSHA256(messageId);
|
|
1530
|
+
const hashedUserId = computeSHA256(userId);
|
|
1531
|
+
const wrappedWithMaster = await wrapKey(embedKey, masterKey);
|
|
1532
|
+
const nowSeconds = Math.floor(Date.now() / 1e3);
|
|
1533
|
+
const embedKeys = [
|
|
1534
|
+
{
|
|
1535
|
+
hashed_embed_id: hashedEmbedId,
|
|
1536
|
+
key_type: "master",
|
|
1537
|
+
hashed_chat_id: null,
|
|
1538
|
+
encrypted_embed_key: wrappedWithMaster,
|
|
1539
|
+
hashed_user_id: hashedUserId,
|
|
1540
|
+
created_at: nowSeconds
|
|
1541
|
+
}
|
|
1542
|
+
];
|
|
1543
|
+
if (chatKey) {
|
|
1544
|
+
const wrappedWithChat = await wrapKey(embedKey, chatKey);
|
|
1545
|
+
embedKeys.push({
|
|
1546
|
+
hashed_embed_id: hashedEmbedId,
|
|
1547
|
+
key_type: "chat",
|
|
1548
|
+
hashed_chat_id: hashedChatId,
|
|
1549
|
+
encrypted_embed_key: wrappedWithChat,
|
|
1550
|
+
hashed_user_id: hashedUserId,
|
|
1551
|
+
created_at: nowSeconds
|
|
1552
|
+
});
|
|
1553
|
+
}
|
|
1554
|
+
return {
|
|
1555
|
+
embed_id: embed.embedId,
|
|
1556
|
+
encrypted_type: encryptedType,
|
|
1557
|
+
encrypted_content: encryptedContent,
|
|
1558
|
+
encrypted_text_preview: encryptedTextPreview,
|
|
1559
|
+
status: embed.status,
|
|
1560
|
+
hashed_chat_id: hashedChatId,
|
|
1561
|
+
hashed_message_id: hashedMessageId,
|
|
1562
|
+
hashed_user_id: hashedUserId,
|
|
1563
|
+
file_path: embed.filePath,
|
|
1564
|
+
content_hash: embed.contentHash,
|
|
1565
|
+
text_length_chars: embed.textLengthChars,
|
|
1566
|
+
created_at: nowSeconds,
|
|
1567
|
+
updated_at: nowSeconds,
|
|
1568
|
+
embed_keys: embedKeys
|
|
1569
|
+
};
|
|
1570
|
+
} catch (error) {
|
|
1571
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
1572
|
+
process.stderr.write(`\x1B[31mError:\x1B[0m Failed to encrypt embed: ${msg}
|
|
1573
|
+
`);
|
|
1574
|
+
return null;
|
|
1575
|
+
}
|
|
1576
|
+
}
|
|
1577
|
+
|
|
1348
1578
|
// src/shareEncryption.ts
|
|
1349
|
-
import { webcrypto as
|
|
1350
|
-
var crypto =
|
|
1579
|
+
import { webcrypto as webcrypto4 } from "crypto";
|
|
1580
|
+
var crypto = webcrypto4;
|
|
1351
1581
|
function base64UrlEncode(data) {
|
|
1352
1582
|
return Buffer.from(data).toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
1353
1583
|
}
|
|
@@ -1459,6 +1689,12 @@ function buildEmbedShareUrl(origin, embedId, blob) {
|
|
|
1459
1689
|
}
|
|
1460
1690
|
|
|
1461
1691
|
// src/client.ts
|
|
1692
|
+
function normalizeUnixSeconds(value, fallback) {
|
|
1693
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
|
|
1694
|
+
return fallback;
|
|
1695
|
+
}
|
|
1696
|
+
return value > 1e10 ? Math.floor(value / 1e3) : Math.floor(value);
|
|
1697
|
+
}
|
|
1462
1698
|
var MEMORY_TYPE_REGISTRY = {
|
|
1463
1699
|
"ai/communication_style": {
|
|
1464
1700
|
appId: "ai",
|
|
@@ -1892,7 +2128,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
1892
2128
|
pin: pin.trim().toUpperCase(),
|
|
1893
2129
|
token
|
|
1894
2130
|
});
|
|
1895
|
-
const sessionId =
|
|
2131
|
+
const sessionId = randomUUID2();
|
|
1896
2132
|
const login = await this.http.post(
|
|
1897
2133
|
"/v1/auth/login",
|
|
1898
2134
|
{
|
|
@@ -2387,7 +2623,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
2387
2623
|
async sendMessage(params) {
|
|
2388
2624
|
let chatId;
|
|
2389
2625
|
if (!params.chatId) {
|
|
2390
|
-
chatId =
|
|
2626
|
+
chatId = randomUUID2();
|
|
2391
2627
|
} else if (params.chatId.length < 36) {
|
|
2392
2628
|
const resolved = await this.resolveFullChatId(params.chatId);
|
|
2393
2629
|
if (!resolved) {
|
|
@@ -2400,7 +2636,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
2400
2636
|
chatId = params.chatId;
|
|
2401
2637
|
}
|
|
2402
2638
|
const { ws, session } = await this.openWsClient();
|
|
2403
|
-
const messageId =
|
|
2639
|
+
const messageId = randomUUID2();
|
|
2404
2640
|
const createdAt = Math.floor(Date.now() / 1e3);
|
|
2405
2641
|
const isNewChat = !params.chatId;
|
|
2406
2642
|
ws.send("set_active_chat", { chat_id: chatId });
|
|
@@ -2420,6 +2656,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
2420
2656
|
};
|
|
2421
2657
|
let chatKeyBytes = null;
|
|
2422
2658
|
let encryptedChatKey = null;
|
|
2659
|
+
let baselineMessagesV = 0;
|
|
2423
2660
|
if (!params.incognito) {
|
|
2424
2661
|
const masterKey = this.getMasterKeyBytes();
|
|
2425
2662
|
if (isNewChat) {
|
|
@@ -2439,6 +2676,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
2439
2676
|
(c) => String(c.details.id ?? "") === chatId || String(c.details.id ?? "").startsWith(chatId)
|
|
2440
2677
|
);
|
|
2441
2678
|
if (chat) {
|
|
2679
|
+
baselineMessagesV = typeof chat.details.messages_v === "number" ? chat.details.messages_v : 0;
|
|
2442
2680
|
const encKey = typeof chat.details.encrypted_chat_key === "string" ? chat.details.encrypted_chat_key : null;
|
|
2443
2681
|
if (encKey) {
|
|
2444
2682
|
chatKeyBytes = await decryptBytesWithAesGcm(encKey, masterKey);
|
|
@@ -2476,6 +2714,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
2476
2714
|
ws.send("encrypted_chat_metadata", metadataPayload);
|
|
2477
2715
|
}
|
|
2478
2716
|
let assistant = "";
|
|
2717
|
+
let assistantMessageId = null;
|
|
2479
2718
|
let category = null;
|
|
2480
2719
|
let modelName = null;
|
|
2481
2720
|
let followUpSuggestions = [];
|
|
@@ -2483,6 +2722,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
2483
2722
|
if (params.incognito) {
|
|
2484
2723
|
try {
|
|
2485
2724
|
const resp = await ws.collectAiResponse(messageId, chatId, streamOpts);
|
|
2725
|
+
assistantMessageId = resp.messageId;
|
|
2486
2726
|
assistant = resp.content;
|
|
2487
2727
|
category = resp.category;
|
|
2488
2728
|
modelName = resp.modelName;
|
|
@@ -2492,10 +2732,55 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
2492
2732
|
} else {
|
|
2493
2733
|
try {
|
|
2494
2734
|
const resp = await ws.collectAiResponse(messageId, chatId, streamOpts);
|
|
2735
|
+
assistantMessageId = resp.messageId;
|
|
2495
2736
|
assistant = resp.content;
|
|
2496
2737
|
category = resp.category;
|
|
2497
2738
|
modelName = resp.modelName;
|
|
2498
2739
|
followUpSuggestions = resp.followUpSuggestions;
|
|
2740
|
+
if (chatKeyBytes && assistant) {
|
|
2741
|
+
const completedAt = Math.floor(Date.now() / 1e3);
|
|
2742
|
+
const encryptedAssistantContent = await encryptWithAesGcmCombined(
|
|
2743
|
+
assistant,
|
|
2744
|
+
chatKeyBytes
|
|
2745
|
+
);
|
|
2746
|
+
const encryptedCategory = category ? await encryptWithAesGcmCombined(category, chatKeyBytes) : void 0;
|
|
2747
|
+
const encryptedModelName = modelName ? await encryptWithAesGcmCombined(modelName, chatKeyBytes) : void 0;
|
|
2748
|
+
const persistedAssistantMessageId = assistantMessageId ?? randomUUID2();
|
|
2749
|
+
ws.send("ai_response_completed", {
|
|
2750
|
+
chat_id: chatId,
|
|
2751
|
+
message: {
|
|
2752
|
+
message_id: persistedAssistantMessageId,
|
|
2753
|
+
chat_id: chatId,
|
|
2754
|
+
role: "assistant",
|
|
2755
|
+
created_at: completedAt,
|
|
2756
|
+
status: "synced",
|
|
2757
|
+
user_message_id: messageId,
|
|
2758
|
+
encrypted_content: encryptedAssistantContent,
|
|
2759
|
+
encrypted_category: encryptedCategory,
|
|
2760
|
+
encrypted_model_name: encryptedModelName
|
|
2761
|
+
},
|
|
2762
|
+
versions: {
|
|
2763
|
+
messages_v: baselineMessagesV + 2,
|
|
2764
|
+
last_edited_overall_timestamp: completedAt
|
|
2765
|
+
}
|
|
2766
|
+
});
|
|
2767
|
+
await ws.waitForMessage(
|
|
2768
|
+
"ai_response_storage_confirmed",
|
|
2769
|
+
(payload) => {
|
|
2770
|
+
const p = payload;
|
|
2771
|
+
return p.message_id === persistedAssistantMessageId;
|
|
2772
|
+
},
|
|
2773
|
+
2e4
|
|
2774
|
+
);
|
|
2775
|
+
await this.persistStreamedEmbeds({
|
|
2776
|
+
ws,
|
|
2777
|
+
embeds: resp.embeds,
|
|
2778
|
+
chatId,
|
|
2779
|
+
chatKeyBytes,
|
|
2780
|
+
fallbackMessageId: persistedAssistantMessageId
|
|
2781
|
+
});
|
|
2782
|
+
clearSyncCache();
|
|
2783
|
+
}
|
|
2499
2784
|
} finally {
|
|
2500
2785
|
ws.close();
|
|
2501
2786
|
}
|
|
@@ -2510,6 +2795,110 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
2510
2795
|
followUpSuggestions
|
|
2511
2796
|
};
|
|
2512
2797
|
}
|
|
2798
|
+
async persistStreamedEmbeds(params) {
|
|
2799
|
+
const finalized = new Map(
|
|
2800
|
+
params.embeds.filter((embed) => {
|
|
2801
|
+
const status = embed.status ?? "finished";
|
|
2802
|
+
return embed.embed_id && embed.content && status !== "processing" && status !== "error" && status !== "cancelled";
|
|
2803
|
+
}).map((embed) => [embed.embed_id, embed])
|
|
2804
|
+
);
|
|
2805
|
+
if (finalized.size === 0) return;
|
|
2806
|
+
const session = this.requireSession();
|
|
2807
|
+
const masterKey = this.getMasterKeyBytes();
|
|
2808
|
+
const parentKeys = /* @__PURE__ */ new Map();
|
|
2809
|
+
const processed = /* @__PURE__ */ new Set();
|
|
2810
|
+
const makeKey = () => {
|
|
2811
|
+
const key = new Uint8Array(32);
|
|
2812
|
+
globalThis.crypto.getRandomValues(key);
|
|
2813
|
+
return key;
|
|
2814
|
+
};
|
|
2815
|
+
const persistOne = async (embed, embedKey, isChild) => {
|
|
2816
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
2817
|
+
const createdAt = normalizeUnixSeconds(embed.createdAt, now);
|
|
2818
|
+
const updatedAt = normalizeUnixSeconds(embed.updatedAt, now);
|
|
2819
|
+
const messageId = embed.message_id || params.fallbackMessageId;
|
|
2820
|
+
const userId = embed.user_id || session.hashedEmail;
|
|
2821
|
+
const hashedChatId = computeSHA256(params.chatId);
|
|
2822
|
+
const hashedMessageId = computeSHA256(messageId);
|
|
2823
|
+
const hashedUserId = computeSHA256(userId);
|
|
2824
|
+
const hashedEmbedId = computeSHA256(embed.embed_id);
|
|
2825
|
+
const encryptedContent = await encryptWithAesGcmCombined(
|
|
2826
|
+
embed.content ?? "",
|
|
2827
|
+
embedKey
|
|
2828
|
+
);
|
|
2829
|
+
const encryptedType = await encryptWithAesGcmCombined(
|
|
2830
|
+
embed.type || "app_skill_use",
|
|
2831
|
+
embedKey
|
|
2832
|
+
);
|
|
2833
|
+
const encryptedTextPreview = embed.text_preview ? await encryptWithAesGcmCombined(embed.text_preview, embedKey) : void 0;
|
|
2834
|
+
await params.ws.sendAsync("store_embed", {
|
|
2835
|
+
embed_id: embed.embed_id,
|
|
2836
|
+
encrypted_type: encryptedType,
|
|
2837
|
+
encrypted_content: encryptedContent,
|
|
2838
|
+
encrypted_text_preview: encryptedTextPreview,
|
|
2839
|
+
status: embed.status || "finished",
|
|
2840
|
+
hashed_chat_id: hashedChatId,
|
|
2841
|
+
hashed_message_id: hashedMessageId,
|
|
2842
|
+
hashed_task_id: embed.task_id ? computeSHA256(embed.task_id) : void 0,
|
|
2843
|
+
hashed_user_id: hashedUserId,
|
|
2844
|
+
embed_ids: embed.embed_ids,
|
|
2845
|
+
parent_embed_id: embed.parent_embed_id || void 0,
|
|
2846
|
+
version_number: embed.version_number,
|
|
2847
|
+
file_path: embed.file_path,
|
|
2848
|
+
content_hash: embed.content_hash,
|
|
2849
|
+
text_length_chars: embed.text_length_chars,
|
|
2850
|
+
is_private: embed.is_private ?? false,
|
|
2851
|
+
is_shared: embed.is_shared ?? false,
|
|
2852
|
+
created_at: createdAt,
|
|
2853
|
+
updated_at: updatedAt
|
|
2854
|
+
});
|
|
2855
|
+
if (!isChild) {
|
|
2856
|
+
const keys = [
|
|
2857
|
+
{
|
|
2858
|
+
hashed_embed_id: hashedEmbedId,
|
|
2859
|
+
key_type: "master",
|
|
2860
|
+
hashed_chat_id: null,
|
|
2861
|
+
encrypted_embed_key: await encryptBytesWithAesGcm(embedKey, masterKey),
|
|
2862
|
+
hashed_user_id: hashedUserId,
|
|
2863
|
+
created_at: now
|
|
2864
|
+
},
|
|
2865
|
+
{
|
|
2866
|
+
hashed_embed_id: hashedEmbedId,
|
|
2867
|
+
key_type: "chat",
|
|
2868
|
+
hashed_chat_id: hashedChatId,
|
|
2869
|
+
encrypted_embed_key: await encryptBytesWithAesGcm(
|
|
2870
|
+
embedKey,
|
|
2871
|
+
params.chatKeyBytes
|
|
2872
|
+
),
|
|
2873
|
+
hashed_user_id: hashedUserId,
|
|
2874
|
+
created_at: now
|
|
2875
|
+
}
|
|
2876
|
+
];
|
|
2877
|
+
await params.ws.sendAsync("store_embed_keys", { keys });
|
|
2878
|
+
parentKeys.set(embed.embed_id, embedKey);
|
|
2879
|
+
}
|
|
2880
|
+
};
|
|
2881
|
+
let madeProgress = true;
|
|
2882
|
+
while (processed.size < finalized.size && madeProgress) {
|
|
2883
|
+
madeProgress = false;
|
|
2884
|
+
for (const embed of finalized.values()) {
|
|
2885
|
+
if (processed.has(embed.embed_id)) continue;
|
|
2886
|
+
const parentId = embed.parent_embed_id || null;
|
|
2887
|
+
if (parentId && finalized.has(parentId) && !parentKeys.has(parentId)) {
|
|
2888
|
+
continue;
|
|
2889
|
+
}
|
|
2890
|
+
const parentKey = parentId ? parentKeys.get(parentId) : void 0;
|
|
2891
|
+
await persistOne(embed, parentKey ?? makeKey(), Boolean(parentKey));
|
|
2892
|
+
processed.add(embed.embed_id);
|
|
2893
|
+
madeProgress = true;
|
|
2894
|
+
}
|
|
2895
|
+
}
|
|
2896
|
+
for (const embed of finalized.values()) {
|
|
2897
|
+
if (processed.has(embed.embed_id)) continue;
|
|
2898
|
+
await persistOne(embed, makeKey(), false);
|
|
2899
|
+
processed.add(embed.embed_id);
|
|
2900
|
+
}
|
|
2901
|
+
}
|
|
2513
2902
|
/**
|
|
2514
2903
|
* Delete a chat by ID.
|
|
2515
2904
|
*
|
|
@@ -3284,7 +3673,7 @@ Required: ${schema.required.join(", ")}`
|
|
|
3284
3673
|
);
|
|
3285
3674
|
}
|
|
3286
3675
|
}
|
|
3287
|
-
const entryId = params.entryId ??
|
|
3676
|
+
const entryId = params.entryId ?? randomUUID2();
|
|
3288
3677
|
const now = Math.floor(Date.now() / 1e3);
|
|
3289
3678
|
const hashedKey = hashItemKey(params.appId, params.itemType);
|
|
3290
3679
|
const plaintextPayload = {
|
|
@@ -3556,7 +3945,7 @@ Required: ${schema.required.join(", ")}`
|
|
|
3556
3945
|
makeWsClient(session) {
|
|
3557
3946
|
return new OpenMatesWsClient({
|
|
3558
3947
|
apiUrl: session.apiUrl,
|
|
3559
|
-
sessionId:
|
|
3948
|
+
sessionId: randomUUID2(),
|
|
3560
3949
|
wsToken: session.wsToken,
|
|
3561
3950
|
refreshToken: session.cookies.auth_refresh_token ?? null,
|
|
3562
3951
|
// Same User-Agent as login so OS-based device fingerprint hash matches.
|
|
@@ -3928,7 +4317,7 @@ function printLogo() {
|
|
|
3928
4317
|
}
|
|
3929
4318
|
|
|
3930
4319
|
// ../secret-scanner/src/registry.ts
|
|
3931
|
-
import { createRequire } from "module";
|
|
4320
|
+
import { createRequire as createRequire2 } from "module";
|
|
3932
4321
|
|
|
3933
4322
|
// ../secret-scanner/src/types.ts
|
|
3934
4323
|
var SECRET_ENV_PATTERNS = [
|
|
@@ -4062,8 +4451,8 @@ var SECRET_PATTERNS = [
|
|
|
4062
4451
|
];
|
|
4063
4452
|
|
|
4064
4453
|
// ../secret-scanner/src/registry.ts
|
|
4065
|
-
var
|
|
4066
|
-
var AhoCorasick =
|
|
4454
|
+
var require3 = createRequire2(import.meta.url);
|
|
4455
|
+
var AhoCorasick = require3("ahocorasick");
|
|
4067
4456
|
var MIN_SECRET_LENGTH = 8;
|
|
4068
4457
|
var SecretRegistry = class {
|
|
4069
4458
|
/** Map from plaintext value → registry entry */
|
|
@@ -4605,136 +4994,6 @@ import { readFileSync as readFileSync3, statSync, existsSync as existsSync3 } fr
|
|
|
4605
4994
|
import { basename, extname, resolve } from "path";
|
|
4606
4995
|
import { homedir as homedir3 } from "os";
|
|
4607
4996
|
import { createHash as createHash4 } from "crypto";
|
|
4608
|
-
|
|
4609
|
-
// src/embedCreator.ts
|
|
4610
|
-
import { randomUUID as randomUUID2, createHash as createHash3, randomBytes, webcrypto as webcrypto4 } from "crypto";
|
|
4611
|
-
import { encode as toonEncode } from "@toon-format/toon";
|
|
4612
|
-
var cryptoApi3 = webcrypto4;
|
|
4613
|
-
var AES_GCM_IV_LENGTH3 = 12;
|
|
4614
|
-
function bytesToBase643(input) {
|
|
4615
|
-
return Buffer.from(input).toString("base64");
|
|
4616
|
-
}
|
|
4617
|
-
function toArrayBuffer2(input) {
|
|
4618
|
-
return input.buffer.slice(input.byteOffset, input.byteOffset + input.byteLength);
|
|
4619
|
-
}
|
|
4620
|
-
async function encryptAesGcm(plaintext, rawKeyBytes) {
|
|
4621
|
-
const iv = cryptoApi3.getRandomValues(new Uint8Array(AES_GCM_IV_LENGTH3));
|
|
4622
|
-
const key = await cryptoApi3.subtle.importKey(
|
|
4623
|
-
"raw",
|
|
4624
|
-
toArrayBuffer2(rawKeyBytes),
|
|
4625
|
-
{ name: "AES-GCM" },
|
|
4626
|
-
false,
|
|
4627
|
-
["encrypt"]
|
|
4628
|
-
);
|
|
4629
|
-
const encrypted = await cryptoApi3.subtle.encrypt(
|
|
4630
|
-
{ name: "AES-GCM", iv: toArrayBuffer2(iv) },
|
|
4631
|
-
key,
|
|
4632
|
-
new TextEncoder().encode(plaintext)
|
|
4633
|
-
);
|
|
4634
|
-
const cipherBytes = new Uint8Array(encrypted);
|
|
4635
|
-
const combined = new Uint8Array(iv.length + cipherBytes.length);
|
|
4636
|
-
combined.set(iv);
|
|
4637
|
-
combined.set(cipherBytes, iv.length);
|
|
4638
|
-
return bytesToBase643(combined);
|
|
4639
|
-
}
|
|
4640
|
-
async function wrapKey(embedKey, wrappingKey) {
|
|
4641
|
-
const cryptoKey = await cryptoApi3.subtle.importKey(
|
|
4642
|
-
"raw",
|
|
4643
|
-
toArrayBuffer2(wrappingKey),
|
|
4644
|
-
{ name: "AES-GCM" },
|
|
4645
|
-
false,
|
|
4646
|
-
["encrypt"]
|
|
4647
|
-
);
|
|
4648
|
-
const iv = cryptoApi3.getRandomValues(new Uint8Array(AES_GCM_IV_LENGTH3));
|
|
4649
|
-
const encrypted = await cryptoApi3.subtle.encrypt(
|
|
4650
|
-
{ name: "AES-GCM", iv: toArrayBuffer2(iv) },
|
|
4651
|
-
cryptoKey,
|
|
4652
|
-
toArrayBuffer2(embedKey)
|
|
4653
|
-
);
|
|
4654
|
-
const cipherBytes = new Uint8Array(encrypted);
|
|
4655
|
-
const combined = new Uint8Array(iv.length + cipherBytes.length);
|
|
4656
|
-
combined.set(iv);
|
|
4657
|
-
combined.set(cipherBytes, iv.length);
|
|
4658
|
-
return bytesToBase643(combined);
|
|
4659
|
-
}
|
|
4660
|
-
function generateEmbedKey() {
|
|
4661
|
-
return new Uint8Array(randomBytes(32));
|
|
4662
|
-
}
|
|
4663
|
-
function computeSHA256(content) {
|
|
4664
|
-
return createHash3("sha256").update(content).digest("hex");
|
|
4665
|
-
}
|
|
4666
|
-
function toonEncodeContent(data) {
|
|
4667
|
-
try {
|
|
4668
|
-
return toonEncode(data);
|
|
4669
|
-
} catch {
|
|
4670
|
-
return JSON.stringify(data);
|
|
4671
|
-
}
|
|
4672
|
-
}
|
|
4673
|
-
function generateEmbedId() {
|
|
4674
|
-
return randomUUID2();
|
|
4675
|
-
}
|
|
4676
|
-
function createEmbedReferenceBlock(type, embedId) {
|
|
4677
|
-
const ref = JSON.stringify({ type, embed_id: embedId }, null, 2);
|
|
4678
|
-
return "```json\n" + ref + "\n```";
|
|
4679
|
-
}
|
|
4680
|
-
async function encryptEmbed(embed, masterKey, chatKey, chatId, messageId, userId) {
|
|
4681
|
-
try {
|
|
4682
|
-
const embedKey = generateEmbedKey();
|
|
4683
|
-
const encryptedContent = await encryptAesGcm(embed.content, embedKey);
|
|
4684
|
-
const encryptedType = await encryptAesGcm(embed.type, embedKey);
|
|
4685
|
-
const encryptedTextPreview = await encryptAesGcm(embed.textPreview, embedKey);
|
|
4686
|
-
const hashedEmbedId = computeSHA256(embed.embedId);
|
|
4687
|
-
const hashedChatId = computeSHA256(chatId);
|
|
4688
|
-
const hashedMessageId = computeSHA256(messageId);
|
|
4689
|
-
const hashedUserId = computeSHA256(userId);
|
|
4690
|
-
const wrappedWithMaster = await wrapKey(embedKey, masterKey);
|
|
4691
|
-
const nowSeconds = Math.floor(Date.now() / 1e3);
|
|
4692
|
-
const embedKeys = [
|
|
4693
|
-
{
|
|
4694
|
-
hashed_embed_id: hashedEmbedId,
|
|
4695
|
-
key_type: "master",
|
|
4696
|
-
hashed_chat_id: null,
|
|
4697
|
-
encrypted_embed_key: wrappedWithMaster,
|
|
4698
|
-
hashed_user_id: hashedUserId,
|
|
4699
|
-
created_at: nowSeconds
|
|
4700
|
-
}
|
|
4701
|
-
];
|
|
4702
|
-
if (chatKey) {
|
|
4703
|
-
const wrappedWithChat = await wrapKey(embedKey, chatKey);
|
|
4704
|
-
embedKeys.push({
|
|
4705
|
-
hashed_embed_id: hashedEmbedId,
|
|
4706
|
-
key_type: "chat",
|
|
4707
|
-
hashed_chat_id: hashedChatId,
|
|
4708
|
-
encrypted_embed_key: wrappedWithChat,
|
|
4709
|
-
hashed_user_id: hashedUserId,
|
|
4710
|
-
created_at: nowSeconds
|
|
4711
|
-
});
|
|
4712
|
-
}
|
|
4713
|
-
return {
|
|
4714
|
-
embed_id: embed.embedId,
|
|
4715
|
-
encrypted_type: encryptedType,
|
|
4716
|
-
encrypted_content: encryptedContent,
|
|
4717
|
-
encrypted_text_preview: encryptedTextPreview,
|
|
4718
|
-
status: embed.status,
|
|
4719
|
-
hashed_chat_id: hashedChatId,
|
|
4720
|
-
hashed_message_id: hashedMessageId,
|
|
4721
|
-
hashed_user_id: hashedUserId,
|
|
4722
|
-
file_path: embed.filePath,
|
|
4723
|
-
content_hash: embed.contentHash,
|
|
4724
|
-
text_length_chars: embed.textLengthChars,
|
|
4725
|
-
created_at: nowSeconds,
|
|
4726
|
-
updated_at: nowSeconds,
|
|
4727
|
-
embed_keys: embedKeys
|
|
4728
|
-
};
|
|
4729
|
-
} catch (error) {
|
|
4730
|
-
const msg = error instanceof Error ? error.message : String(error);
|
|
4731
|
-
process.stderr.write(`\x1B[31mError:\x1B[0m Failed to encrypt embed: ${msg}
|
|
4732
|
-
`);
|
|
4733
|
-
return null;
|
|
4734
|
-
}
|
|
4735
|
-
}
|
|
4736
|
-
|
|
4737
|
-
// src/fileEmbed.ts
|
|
4738
4997
|
var MAX_PER_FILE_SIZE = 100 * 1024 * 1024;
|
|
4739
4998
|
var BLOCKED_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
4740
4999
|
".pem",
|
|
@@ -6174,7 +6433,7 @@ function formatTs(ts) {
|
|
|
6174
6433
|
|
|
6175
6434
|
// src/server.ts
|
|
6176
6435
|
import { execSync, spawn as nodeSpawn } from "child_process";
|
|
6177
|
-
import { copyFileSync, existsSync as existsSync5, readFileSync as readFileSync5, rmSync as rmSync3 } from "fs";
|
|
6436
|
+
import { copyFileSync, existsSync as existsSync5, readFileSync as readFileSync5, rmSync as rmSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
6178
6437
|
import { createInterface as createInterface2 } from "readline";
|
|
6179
6438
|
import { homedir as homedir5 } from "os";
|
|
6180
6439
|
import { join as join3, resolve as resolve3 } from "path";
|
|
@@ -6272,6 +6531,21 @@ function composeArgs(installPath, withOverrides) {
|
|
|
6272
6531
|
}
|
|
6273
6532
|
return args;
|
|
6274
6533
|
}
|
|
6534
|
+
function ensureGitWorkDirEnv(installPath) {
|
|
6535
|
+
const envPath = join3(installPath, ".env");
|
|
6536
|
+
if (!existsSync5(envPath)) return;
|
|
6537
|
+
const content = readFileSync5(envPath, "utf-8");
|
|
6538
|
+
const lineRegex = /^GIT_WORK_DIR=.*$/m;
|
|
6539
|
+
const value = `GIT_WORK_DIR=${installPath}`;
|
|
6540
|
+
if (lineRegex.test(content)) {
|
|
6541
|
+
const next = content.replace(lineRegex, value);
|
|
6542
|
+
if (next !== content) writeFileSync3(envPath, next);
|
|
6543
|
+
return;
|
|
6544
|
+
}
|
|
6545
|
+
const separator = content.endsWith("\n") ? "" : "\n";
|
|
6546
|
+
writeFileSync3(envPath, `${content}${separator}${value}
|
|
6547
|
+
`);
|
|
6548
|
+
}
|
|
6275
6549
|
function requireDocker() {
|
|
6276
6550
|
try {
|
|
6277
6551
|
execSync("docker version", { stdio: "pipe" });
|
|
@@ -6344,6 +6618,7 @@ function printJson(data) {
|
|
|
6344
6618
|
async function serverStatus(flags) {
|
|
6345
6619
|
requireDocker();
|
|
6346
6620
|
const installPath = resolveServerPath(flags);
|
|
6621
|
+
ensureGitWorkDirEnv(installPath);
|
|
6347
6622
|
const config = loadServerConfig();
|
|
6348
6623
|
const withOverrides = config?.composeProfile === "full";
|
|
6349
6624
|
const args = [...composeArgs(installPath, withOverrides), "ps"];
|
|
@@ -6356,6 +6631,7 @@ async function serverStatus(flags) {
|
|
|
6356
6631
|
async function serverStart(flags) {
|
|
6357
6632
|
requireDocker();
|
|
6358
6633
|
const installPath = resolveServerPath(flags);
|
|
6634
|
+
ensureGitWorkDirEnv(installPath);
|
|
6359
6635
|
warnIfMissingLlmCredentials(installPath);
|
|
6360
6636
|
const withOverrides = flags["with-overrides"] === true;
|
|
6361
6637
|
const args = [...composeArgs(installPath, withOverrides), "up", "-d"];
|
|
@@ -6381,6 +6657,7 @@ async function serverStart(flags) {
|
|
|
6381
6657
|
async function serverStop(flags) {
|
|
6382
6658
|
requireDocker();
|
|
6383
6659
|
const installPath = resolveServerPath(flags);
|
|
6660
|
+
ensureGitWorkDirEnv(installPath);
|
|
6384
6661
|
const config = loadServerConfig();
|
|
6385
6662
|
const withOverrides = config?.composeProfile === "full";
|
|
6386
6663
|
const args = [...composeArgs(installPath, withOverrides), "down"];
|
|
@@ -6396,6 +6673,7 @@ async function serverStop(flags) {
|
|
|
6396
6673
|
async function serverRestart(flags) {
|
|
6397
6674
|
requireDocker();
|
|
6398
6675
|
const installPath = resolveServerPath(flags);
|
|
6676
|
+
ensureGitWorkDirEnv(installPath);
|
|
6399
6677
|
const config = loadServerConfig();
|
|
6400
6678
|
const withOverrides = config?.composeProfile === "full";
|
|
6401
6679
|
if (flags.rebuild === true) {
|
|
@@ -6428,6 +6706,7 @@ async function serverRestart(flags) {
|
|
|
6428
6706
|
async function serverLogs(flags) {
|
|
6429
6707
|
requireDocker();
|
|
6430
6708
|
const installPath = resolveServerPath(flags);
|
|
6709
|
+
ensureGitWorkDirEnv(installPath);
|
|
6431
6710
|
const config = loadServerConfig();
|
|
6432
6711
|
const withOverrides = config?.composeProfile === "full";
|
|
6433
6712
|
const args = [...composeArgs(installPath, withOverrides), "logs"];
|
|
@@ -6514,6 +6793,7 @@ async function serverUpdate(flags) {
|
|
|
6514
6793
|
requireGit();
|
|
6515
6794
|
requireDocker();
|
|
6516
6795
|
const installPath = resolveServerPath(flags);
|
|
6796
|
+
ensureGitWorkDirEnv(installPath);
|
|
6517
6797
|
console.error("Updating OpenMates...");
|
|
6518
6798
|
if (flags.force === true) {
|
|
6519
6799
|
console.error("Stashing local changes...");
|
|
@@ -6560,6 +6840,7 @@ async function serverUpdate(flags) {
|
|
|
6560
6840
|
async function serverReset(flags) {
|
|
6561
6841
|
requireDocker();
|
|
6562
6842
|
const installPath = resolveServerPath(flags);
|
|
6843
|
+
ensureGitWorkDirEnv(installPath);
|
|
6563
6844
|
const config = loadServerConfig();
|
|
6564
6845
|
const withOverrides = config?.composeProfile === "full";
|
|
6565
6846
|
const userDataOnly = flags["delete-user-data-only"] === true;
|
|
@@ -6640,6 +6921,7 @@ async function serverMakeAdmin(rest, flags) {
|
|
|
6640
6921
|
async function serverUninstall(flags) {
|
|
6641
6922
|
requireDocker();
|
|
6642
6923
|
const installPath = resolveServerPath(flags);
|
|
6924
|
+
ensureGitWorkDirEnv(installPath);
|
|
6643
6925
|
const config = loadServerConfig();
|
|
6644
6926
|
const withOverrides = config?.composeProfile === "full";
|
|
6645
6927
|
const keepData = flags["keep-data"] === true;
|
package/dist/cli.js
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openmates",
|
|
3
|
-
"version": "0.11.0-alpha.
|
|
3
|
+
"version": "0.11.0-alpha.15",
|
|
4
4
|
"description": "OpenMates CLI and SDK",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -18,9 +18,10 @@
|
|
|
18
18
|
"test:unit:crypto": "node --test --experimental-strip-types tests/crypto.test.ts",
|
|
19
19
|
"test:unit:storage": "node --test --experimental-strip-types --loader ./tests/loader.mjs tests/storage.test.ts",
|
|
20
20
|
"test:unit:keychain": "node --test --experimental-strip-types tests/keychain.test.ts",
|
|
21
|
+
"test:unit:ws": "node --test --experimental-strip-types tests/ws.test.ts",
|
|
21
22
|
"test:unit:server": "node --test --experimental-strip-types tests/server.test.ts",
|
|
22
23
|
"test:unit:cli": "node --test tests/cli.test.ts",
|
|
23
|
-
"test": "node --test --experimental-strip-types --loader ./tests/loader.mjs tests/crypto.test.ts tests/storage.test.ts tests/keychain.test.ts tests/mentions.test.ts tests/outputRedactor.test.ts tests/fileEmbed.test.ts tests/embedCreator.test.ts tests/shareEncryption.test.ts tests/server.test.ts && node --test tests/cli.test.ts"
|
|
24
|
+
"test": "node --test --experimental-strip-types --loader ./tests/loader.mjs tests/crypto.test.ts tests/storage.test.ts tests/keychain.test.ts tests/mentions.test.ts tests/outputRedactor.test.ts tests/fileEmbed.test.ts tests/embedCreator.test.ts tests/shareEncryption.test.ts tests/server.test.ts tests/ws.test.ts && node --test tests/cli.test.ts"
|
|
24
25
|
},
|
|
25
26
|
"keywords": [
|
|
26
27
|
"openmates",
|