openmates 0.15.0-alpha.8 → 0.15.0-alpha.9
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-4JMZEG73.js → chunk-LGY6IN75.js} +1715 -258
- package/dist/cli.js +1 -1
- package/dist/index.js +5 -1377
- package/package.json +1 -1
|
@@ -198,9 +198,9 @@ function generateSecureRecoveryKey(length = 24) {
|
|
|
198
198
|
const chars = requiredSets[index];
|
|
199
199
|
result[index] = chars.charAt(randomByte % chars.length);
|
|
200
200
|
}
|
|
201
|
-
const
|
|
201
|
+
const randomBytes5 = cryptoApi.getRandomValues(new Uint8Array(length));
|
|
202
202
|
for (let index = requiredSets.length; index < length; index += 1) {
|
|
203
|
-
result[index] = allChars.charAt(
|
|
203
|
+
result[index] = allChars.charAt(randomBytes5[index] % allChars.length);
|
|
204
204
|
}
|
|
205
205
|
for (let index = result.length - 1; index > 0; index -= 1) {
|
|
206
206
|
const randomByte = cryptoApi.getRandomValues(new Uint8Array(1))[0];
|
|
@@ -4844,7 +4844,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
4844
4844
|
if (!userId) {
|
|
4845
4845
|
throw new Error("Could not resolve current user id for local connected-account connector.");
|
|
4846
4846
|
}
|
|
4847
|
-
const { createHash:
|
|
4847
|
+
const { createHash: createHash9 } = await import("crypto");
|
|
4848
4848
|
const accountId = randomUUID5();
|
|
4849
4849
|
const masterKey = this.getMasterKeyBytes();
|
|
4850
4850
|
const encryptLocalConnectorValue = async (value) => {
|
|
@@ -4853,9 +4853,9 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
4853
4853
|
};
|
|
4854
4854
|
const payload = {
|
|
4855
4855
|
id: accountId,
|
|
4856
|
-
hashed_user_id:
|
|
4856
|
+
hashed_user_id: createHash9("sha256").update(userId).digest("hex"),
|
|
4857
4857
|
encrypted_provider_type: await encryptLocalConnectorValue(input.provider_id),
|
|
4858
|
-
provider_type_hash:
|
|
4858
|
+
provider_type_hash: createHash9("sha256").update(input.provider_id).digest("hex"),
|
|
4859
4859
|
encrypted_account_label: await encryptLocalConnectorValue(input.label),
|
|
4860
4860
|
encrypted_capabilities: await encryptLocalConnectorValue(input.capabilities),
|
|
4861
4861
|
encrypted_app_permissions: await encryptLocalConnectorValue({
|
|
@@ -5581,8 +5581,8 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
5581
5581
|
);
|
|
5582
5582
|
let msgEmbedIds = [];
|
|
5583
5583
|
if (clientMsgId && cache.embeds.length > 0) {
|
|
5584
|
-
const { createHash:
|
|
5585
|
-
const hashed =
|
|
5584
|
+
const { createHash: createHash9 } = await import("crypto");
|
|
5585
|
+
const hashed = createHash9("sha256").update(clientMsgId).digest("hex");
|
|
5586
5586
|
msgEmbedIds = cache.embeds.filter(
|
|
5587
5587
|
(e) => e.hashed_message_id === hashed && // Only include parent embeds (no parent_embed_id).
|
|
5588
5588
|
// Child embeds inherit the parent's key and are loaded
|
|
@@ -5629,8 +5629,8 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
5629
5629
|
);
|
|
5630
5630
|
}
|
|
5631
5631
|
const embedId = String(embed.embed_id ?? embed.id ?? "");
|
|
5632
|
-
const { createHash:
|
|
5633
|
-
const hashedEmbedId =
|
|
5632
|
+
const { createHash: createHash9 } = await import("crypto");
|
|
5633
|
+
const hashedEmbedId = createHash9("sha256").update(embedId).digest("hex");
|
|
5634
5634
|
const embedKeyBytes = await this.resolveEmbedKey(
|
|
5635
5635
|
cache,
|
|
5636
5636
|
masterKey,
|
|
@@ -5738,7 +5738,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
5738
5738
|
async resolveEmbedKey(cache, masterKey, embed, embedId, hashedEmbedId, visited = /* @__PURE__ */ new Set()) {
|
|
5739
5739
|
if (visited.has(embedId)) return null;
|
|
5740
5740
|
visited.add(embedId);
|
|
5741
|
-
const { createHash:
|
|
5741
|
+
const { createHash: createHash9 } = await import("crypto");
|
|
5742
5742
|
const masterKeyEntry = cache.embedKeys.find(
|
|
5743
5743
|
(ek) => ek.hashed_embed_id === hashedEmbedId && String(ek.key_type) === "master"
|
|
5744
5744
|
);
|
|
@@ -5755,7 +5755,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
5755
5755
|
if (chatKeyEntry && typeof chatKeyEntry.encrypted_embed_key === "string") {
|
|
5756
5756
|
const hashedChatId = String(chatKeyEntry.hashed_chat_id ?? "");
|
|
5757
5757
|
const owningChat = cache.chats.find((c) => {
|
|
5758
|
-
const chatHash =
|
|
5758
|
+
const chatHash = createHash9("sha256").update(String(c.details.id ?? "")).digest("hex");
|
|
5759
5759
|
return chatHash === hashedChatId;
|
|
5760
5760
|
});
|
|
5761
5761
|
if (owningChat) {
|
|
@@ -5784,7 +5784,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
5784
5784
|
const parentFullId = String(
|
|
5785
5785
|
parentEmbed2.embed_id ?? parentEmbed2.id ?? ""
|
|
5786
5786
|
);
|
|
5787
|
-
const parentHashedId =
|
|
5787
|
+
const parentHashedId = createHash9("sha256").update(parentFullId).digest("hex");
|
|
5788
5788
|
const parentKey = await this.resolveEmbedKey(
|
|
5789
5789
|
cache,
|
|
5790
5790
|
masterKey,
|
|
@@ -8796,7 +8796,7 @@ Required: ${schema.required.join(", ")}`
|
|
|
8796
8796
|
const session = this.requireSession();
|
|
8797
8797
|
const masterKey = base64ToBytes(session.masterKeyExportedB64);
|
|
8798
8798
|
const cache = await this.ensureSynced();
|
|
8799
|
-
const { createHash:
|
|
8799
|
+
const { createHash: createHash9 } = await import("crypto");
|
|
8800
8800
|
const embed = cache.embeds.find(
|
|
8801
8801
|
(e) => String(e.embed_id ?? "").startsWith(embedIdOrShort) || String(e.id ?? "").startsWith(embedIdOrShort)
|
|
8802
8802
|
);
|
|
@@ -8804,7 +8804,7 @@ Required: ${schema.required.join(", ")}`
|
|
|
8804
8804
|
throw new Error(`Embed '${embedIdOrShort}' not found in local cache.`);
|
|
8805
8805
|
}
|
|
8806
8806
|
const embedId = String(embed.embed_id ?? embed.id ?? "");
|
|
8807
|
-
const hashedEmbedId =
|
|
8807
|
+
const hashedEmbedId = createHash9("sha256").update(embedId).digest("hex");
|
|
8808
8808
|
const embedKeyBytes = await this.resolveEmbedKey(
|
|
8809
8809
|
cache,
|
|
8810
8810
|
masterKey,
|
|
@@ -8912,8 +8912,8 @@ Required: ${schema.required.join(", ")}`
|
|
|
8912
8912
|
if (!embed) {
|
|
8913
8913
|
throw new Error(`Embed '${embedId}' not found in local cache. Run 'openmates chats list' to sync first.`);
|
|
8914
8914
|
}
|
|
8915
|
-
const { createHash:
|
|
8916
|
-
const hashedEmbedId =
|
|
8915
|
+
const { createHash: createHash9 } = await import("crypto");
|
|
8916
|
+
const hashedEmbedId = createHash9("sha256").update(embedId).digest("hex");
|
|
8917
8917
|
const embedKey = await this.resolveEmbedKey(
|
|
8918
8918
|
cache,
|
|
8919
8919
|
masterKey,
|
|
@@ -9007,8 +9007,8 @@ Required: ${schema.required.join(", ")}`
|
|
|
9007
9007
|
if (!embed) {
|
|
9008
9008
|
throw new Error(`Embed '${embedId}' not found in local cache. Run 'openmates chats list' to sync first.`);
|
|
9009
9009
|
}
|
|
9010
|
-
const { createHash:
|
|
9011
|
-
const hashedEmbedId =
|
|
9010
|
+
const { createHash: createHash9 } = await import("crypto");
|
|
9011
|
+
const hashedEmbedId = createHash9("sha256").update(embedId).digest("hex");
|
|
9012
9012
|
const embedKey = await this.resolveEmbedKey(
|
|
9013
9013
|
cache,
|
|
9014
9014
|
masterKey,
|
|
@@ -9397,9 +9397,9 @@ Required: ${schema.required.join(", ")}`
|
|
|
9397
9397
|
const reconciledChats = reconcileAuthoritativeChats(chats, reconciliation);
|
|
9398
9398
|
chats.splice(0, chats.length, ...reconciledChats);
|
|
9399
9399
|
if (reconciliation.deleted_chat_ids?.length) {
|
|
9400
|
-
const { createHash:
|
|
9400
|
+
const { createHash: createHash9 } = await import("crypto");
|
|
9401
9401
|
const deletedHashes = new Set(
|
|
9402
|
-
reconciliation.deleted_chat_ids.map((id) =>
|
|
9402
|
+
reconciliation.deleted_chat_ids.map((id) => createHash9("sha256").update(id).digest("hex"))
|
|
9403
9403
|
);
|
|
9404
9404
|
const keptEmbeds = embeds.filter((embed) => !deletedHashes.has(String(embed.hashed_chat_id ?? "")));
|
|
9405
9405
|
const keptKeys = embedKeys.filter((key) => !deletedHashes.has(String(key.hashed_chat_id ?? "")));
|
|
@@ -9674,15 +9674,6 @@ function printLogo() {
|
|
|
9674
9674
|
stdout.write(lines.join("\n") + "\n");
|
|
9675
9675
|
}
|
|
9676
9676
|
|
|
9677
|
-
// src/cli.ts
|
|
9678
|
-
import { createInterface as createInterface5 } from "readline/promises";
|
|
9679
|
-
import { stdin as stdin3, stdout as stdout2 } from "process";
|
|
9680
|
-
import { readFileSync as readFileSync9, realpathSync, writeFileSync as writeFileSync6 } from "fs";
|
|
9681
|
-
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
9682
|
-
import { basename as basename3, dirname as dirname3 } from "path";
|
|
9683
|
-
import { randomUUID as randomUUID7 } from "crypto";
|
|
9684
|
-
import WebSocket2 from "ws";
|
|
9685
|
-
|
|
9686
9677
|
// src/generated/appSkills.ts
|
|
9687
9678
|
var APP_SKILL_METADATA = [
|
|
9688
9679
|
{
|
|
@@ -13590,6 +13581,1374 @@ var GeneratedAppSkills = class {
|
|
|
13590
13581
|
workflows;
|
|
13591
13582
|
};
|
|
13592
13583
|
|
|
13584
|
+
// src/sdk.ts
|
|
13585
|
+
import { decode as toonDecode } from "@toon-format/toon";
|
|
13586
|
+
import { createHash as createHash6, randomBytes as randomBytes3, randomUUID as randomUUID6 } from "crypto";
|
|
13587
|
+
import { chmodSync as chmodSync2, existsSync as existsSync5, mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "fs";
|
|
13588
|
+
import { homedir as homedir4 } from "os";
|
|
13589
|
+
import { dirname, join as join3 } from "path";
|
|
13590
|
+
var DEFAULT_API_URL2 = "https://api.openmates.org";
|
|
13591
|
+
var DEFAULT_RECOVERY_POLL_INTERVAL_MS = 500;
|
|
13592
|
+
var DEFAULT_RECOVERY_TIMEOUT_MS = 6e4;
|
|
13593
|
+
var OpenMatesConfigError = class extends Error {
|
|
13594
|
+
constructor(message) {
|
|
13595
|
+
super(message);
|
|
13596
|
+
this.name = "OpenMatesConfigError";
|
|
13597
|
+
}
|
|
13598
|
+
};
|
|
13599
|
+
var OpenMatesApiError = class extends Error {
|
|
13600
|
+
status;
|
|
13601
|
+
data;
|
|
13602
|
+
constructor(status, data) {
|
|
13603
|
+
super(`OpenMates API request failed with HTTP ${status}`);
|
|
13604
|
+
this.name = "OpenMatesApiError";
|
|
13605
|
+
this.status = status;
|
|
13606
|
+
this.data = data;
|
|
13607
|
+
}
|
|
13608
|
+
};
|
|
13609
|
+
var OpenMates = class {
|
|
13610
|
+
apps;
|
|
13611
|
+
account;
|
|
13612
|
+
benchmark;
|
|
13613
|
+
billing;
|
|
13614
|
+
chats;
|
|
13615
|
+
connectedAccounts;
|
|
13616
|
+
docs;
|
|
13617
|
+
drafts;
|
|
13618
|
+
embeds;
|
|
13619
|
+
feedback;
|
|
13620
|
+
inspirations;
|
|
13621
|
+
learningMode;
|
|
13622
|
+
memories;
|
|
13623
|
+
newChatSuggestions;
|
|
13624
|
+
notifications;
|
|
13625
|
+
reminders;
|
|
13626
|
+
projects;
|
|
13627
|
+
settings;
|
|
13628
|
+
plans;
|
|
13629
|
+
tasks;
|
|
13630
|
+
workflows;
|
|
13631
|
+
apiKey;
|
|
13632
|
+
apiUrl;
|
|
13633
|
+
deviceId;
|
|
13634
|
+
sdkSessionPromise;
|
|
13635
|
+
masterKeyPromise;
|
|
13636
|
+
constructor(options = {}) {
|
|
13637
|
+
this.apiKey = options.apiKey ?? process.env.OPENMATES_API_KEY;
|
|
13638
|
+
this.apiUrl = (options.apiUrl ?? DEFAULT_API_URL2).replace(/\/$/, "");
|
|
13639
|
+
this.deviceId = options.deviceId ?? loadOrCreateDeviceId(options.deviceIdPath);
|
|
13640
|
+
this.apps = new GeneratedAppSkills(this.runAppSkill.bind(this));
|
|
13641
|
+
this.account = new OpenMatesAccount(this);
|
|
13642
|
+
this.benchmark = new OpenMatesBenchmark(this);
|
|
13643
|
+
this.billing = new OpenMatesBilling(this);
|
|
13644
|
+
this.chats = new OpenMatesChats(this);
|
|
13645
|
+
this.connectedAccounts = new OpenMatesConnectedAccounts(this);
|
|
13646
|
+
this.docs = new OpenMatesDocs(this);
|
|
13647
|
+
this.drafts = new OpenMatesDrafts(this);
|
|
13648
|
+
this.embeds = new OpenMatesEmbeds(this);
|
|
13649
|
+
this.feedback = new OpenMatesFeedback(this);
|
|
13650
|
+
this.inspirations = new OpenMatesInspirations(this);
|
|
13651
|
+
this.learningMode = new OpenMatesLearningMode(this);
|
|
13652
|
+
this.memories = new OpenMatesMemories(this);
|
|
13653
|
+
this.newChatSuggestions = new OpenMatesNewChatSuggestions(this);
|
|
13654
|
+
this.notifications = new OpenMatesNotifications(this);
|
|
13655
|
+
this.reminders = new OpenMatesReminders(this);
|
|
13656
|
+
this.projects = new OpenMatesProjects(this);
|
|
13657
|
+
this.settings = new OpenMatesSettings(this);
|
|
13658
|
+
this.plans = new OpenMatesPlans(this);
|
|
13659
|
+
this.tasks = new OpenMatesTasks(this);
|
|
13660
|
+
this.workflows = new OpenMatesWorkflows(this);
|
|
13661
|
+
}
|
|
13662
|
+
async runAppSkill(appId, skillId, input) {
|
|
13663
|
+
return this.request(`/v1/apps/${appId}/skills/${skillId}`, input);
|
|
13664
|
+
}
|
|
13665
|
+
async request(path, body, timeoutMs, extraHeaders) {
|
|
13666
|
+
return this.requestWithMethod("POST", path, body, timeoutMs, extraHeaders);
|
|
13667
|
+
}
|
|
13668
|
+
async patch(path, body) {
|
|
13669
|
+
return this.requestWithMethod("PATCH", path, body);
|
|
13670
|
+
}
|
|
13671
|
+
async put(path, body) {
|
|
13672
|
+
return this.requestWithMethod("PUT", path, body);
|
|
13673
|
+
}
|
|
13674
|
+
async delete(path, body) {
|
|
13675
|
+
return this.requestWithMethod("DELETE", path, body);
|
|
13676
|
+
}
|
|
13677
|
+
async get(path) {
|
|
13678
|
+
if (!this.apiKey) {
|
|
13679
|
+
throw new OpenMatesConfigError("OpenMates API key is required");
|
|
13680
|
+
}
|
|
13681
|
+
const response = await fetch(`${this.apiUrl}${path}`, {
|
|
13682
|
+
method: "GET",
|
|
13683
|
+
headers: this.headers(false)
|
|
13684
|
+
});
|
|
13685
|
+
return this.parseResponse(response);
|
|
13686
|
+
}
|
|
13687
|
+
async getPublic(path) {
|
|
13688
|
+
const response = await fetch(`${this.apiUrl}${path}`, {
|
|
13689
|
+
method: "GET",
|
|
13690
|
+
headers: this.publicHeaders()
|
|
13691
|
+
});
|
|
13692
|
+
return this.parseResponse(response);
|
|
13693
|
+
}
|
|
13694
|
+
async getRaw(path) {
|
|
13695
|
+
if (!this.apiKey) {
|
|
13696
|
+
throw new OpenMatesConfigError("OpenMates API key is required");
|
|
13697
|
+
}
|
|
13698
|
+
const response = await fetch(`${this.apiUrl}${path}`, {
|
|
13699
|
+
method: "GET",
|
|
13700
|
+
headers: this.headers(false)
|
|
13701
|
+
});
|
|
13702
|
+
if (!response.ok) {
|
|
13703
|
+
await this.parseResponse(response);
|
|
13704
|
+
}
|
|
13705
|
+
return {
|
|
13706
|
+
contentType: response.headers.get("content-type") ?? "application/octet-stream",
|
|
13707
|
+
filename: extractFilename(response.headers.get("content-disposition")),
|
|
13708
|
+
data: await response.arrayBuffer()
|
|
13709
|
+
};
|
|
13710
|
+
}
|
|
13711
|
+
webOrigin() {
|
|
13712
|
+
return deriveWebOrigin(this.apiUrl);
|
|
13713
|
+
}
|
|
13714
|
+
masterKey() {
|
|
13715
|
+
return this.getMasterKey();
|
|
13716
|
+
}
|
|
13717
|
+
sdkSession() {
|
|
13718
|
+
return this.getSdkSession();
|
|
13719
|
+
}
|
|
13720
|
+
async resolveEmbedKeyForShare(embedKeys, embedId) {
|
|
13721
|
+
const masterKey = await this.getMasterKey();
|
|
13722
|
+
const hashedEmbedId = createHash6("sha256").update(embedId).digest("hex");
|
|
13723
|
+
return this.resolveLoadedEmbedKey(embedKeys, hashedEmbedId, masterKey, masterKey);
|
|
13724
|
+
}
|
|
13725
|
+
async decryptChatMetadata(chat) {
|
|
13726
|
+
if (typeof chat.encrypted_chat_key !== "string") {
|
|
13727
|
+
return chat;
|
|
13728
|
+
}
|
|
13729
|
+
const masterKey = await this.getMasterKey();
|
|
13730
|
+
const chatKey = await decryptBytesWithAesGcm(chat.encrypted_chat_key, masterKey);
|
|
13731
|
+
if (!chatKey) {
|
|
13732
|
+
return chat;
|
|
13733
|
+
}
|
|
13734
|
+
const decrypted = { ...chat };
|
|
13735
|
+
if (typeof chat.encrypted_title === "string") {
|
|
13736
|
+
decrypted.title = await decryptWithAesGcmCombined(chat.encrypted_title, chatKey);
|
|
13737
|
+
}
|
|
13738
|
+
if (typeof chat.encrypted_chat_summary === "string") {
|
|
13739
|
+
decrypted.chat_summary = await decryptWithAesGcmCombined(chat.encrypted_chat_summary, chatKey);
|
|
13740
|
+
}
|
|
13741
|
+
if (typeof chat.encrypted_category === "string") {
|
|
13742
|
+
decrypted.category = await decryptWithAesGcmCombined(chat.encrypted_category, chatKey);
|
|
13743
|
+
}
|
|
13744
|
+
return decrypted;
|
|
13745
|
+
}
|
|
13746
|
+
async decryptLoadedChatPayload(payload) {
|
|
13747
|
+
const chat = payload.chat;
|
|
13748
|
+
if (!chat || typeof chat !== "object") {
|
|
13749
|
+
return payload;
|
|
13750
|
+
}
|
|
13751
|
+
const chatMetadata = chat;
|
|
13752
|
+
const decryptedChat = await this.decryptChatMetadata(chatMetadata);
|
|
13753
|
+
const chatKey = typeof chatMetadata.encrypted_chat_key === "string" ? await decryptBytesWithAesGcm(chatMetadata.encrypted_chat_key, await this.getMasterKey()) : null;
|
|
13754
|
+
if (!chatKey || !Array.isArray(payload.messages)) {
|
|
13755
|
+
return { ...payload, chat: decryptedChat };
|
|
13756
|
+
}
|
|
13757
|
+
const messages = await Promise.all(payload.messages.map(async (rawMessage) => {
|
|
13758
|
+
const message = typeof rawMessage === "string" ? JSON.parse(rawMessage) : { ...rawMessage };
|
|
13759
|
+
if (typeof message.encrypted_content === "string") {
|
|
13760
|
+
message.content = await decryptWithAesGcmCombined(message.encrypted_content, chatKey);
|
|
13761
|
+
}
|
|
13762
|
+
if (typeof message.encrypted_sender_name === "string") {
|
|
13763
|
+
message.senderName = await decryptWithAesGcmCombined(message.encrypted_sender_name, chatKey);
|
|
13764
|
+
}
|
|
13765
|
+
if (typeof message.encrypted_category === "string") {
|
|
13766
|
+
message.category = await decryptWithAesGcmCombined(message.encrypted_category, chatKey);
|
|
13767
|
+
}
|
|
13768
|
+
if (typeof message.encrypted_model_name === "string") {
|
|
13769
|
+
message.modelName = await decryptWithAesGcmCombined(message.encrypted_model_name, chatKey);
|
|
13770
|
+
}
|
|
13771
|
+
return message;
|
|
13772
|
+
}));
|
|
13773
|
+
const embeds = Array.isArray(payload.embeds) ? await this.decryptLoadedChatEmbeds(
|
|
13774
|
+
payload.embeds,
|
|
13775
|
+
Array.isArray(payload.embed_keys) ? payload.embed_keys : [],
|
|
13776
|
+
chatKey
|
|
13777
|
+
) : payload.embeds;
|
|
13778
|
+
return { ...payload, chat: decryptedChat, messages, embeds };
|
|
13779
|
+
}
|
|
13780
|
+
async decryptLoadedChatEmbeds(embeds, embedKeys, chatKey) {
|
|
13781
|
+
const masterKey = await this.getMasterKey();
|
|
13782
|
+
return Promise.all(embeds.map(async (embed) => {
|
|
13783
|
+
const embedId = String(embed.embed_id ?? embed.id ?? "");
|
|
13784
|
+
if (!embedId) {
|
|
13785
|
+
return { ...embed };
|
|
13786
|
+
}
|
|
13787
|
+
const hashedEmbedId = createHash6("sha256").update(embedId).digest("hex");
|
|
13788
|
+
const embedKey = await this.resolveLoadedEmbedKey(embedKeys, hashedEmbedId, masterKey, chatKey);
|
|
13789
|
+
if (!embedKey) {
|
|
13790
|
+
return { ...embed };
|
|
13791
|
+
}
|
|
13792
|
+
const decrypted = { ...embed };
|
|
13793
|
+
if (typeof embed.encrypted_type === "string") {
|
|
13794
|
+
decrypted.type = await decryptWithAesGcmCombined(embed.encrypted_type, embedKey);
|
|
13795
|
+
}
|
|
13796
|
+
if (typeof embed.encrypted_text_preview === "string") {
|
|
13797
|
+
decrypted.textPreview = await decryptWithAesGcmCombined(embed.encrypted_text_preview, embedKey);
|
|
13798
|
+
}
|
|
13799
|
+
if (typeof embed.encrypted_content === "string") {
|
|
13800
|
+
const content = await decryptWithAesGcmCombined(embed.encrypted_content, embedKey);
|
|
13801
|
+
decrypted.content = parseMaybeJson(content);
|
|
13802
|
+
}
|
|
13803
|
+
return decrypted;
|
|
13804
|
+
}));
|
|
13805
|
+
}
|
|
13806
|
+
async resolveLoadedEmbedKey(embedKeys, hashedEmbedId, masterKey, chatKey) {
|
|
13807
|
+
const matchingKeys = embedKeys.filter((key) => key.hashed_embed_id === hashedEmbedId);
|
|
13808
|
+
const masterKeyEntry = matchingKeys.find((key) => key.key_type === "master");
|
|
13809
|
+
if (typeof masterKeyEntry?.encrypted_embed_key === "string") {
|
|
13810
|
+
const embedKey = await decryptBytesWithAesGcm(masterKeyEntry.encrypted_embed_key, masterKey);
|
|
13811
|
+
if (embedKey) return embedKey;
|
|
13812
|
+
}
|
|
13813
|
+
const chatKeyEntry = matchingKeys.find((key) => key.key_type === "chat");
|
|
13814
|
+
if (typeof chatKeyEntry?.encrypted_embed_key === "string") {
|
|
13815
|
+
return decryptBytesWithAesGcm(chatKeyEntry.encrypted_embed_key, chatKey);
|
|
13816
|
+
}
|
|
13817
|
+
return null;
|
|
13818
|
+
}
|
|
13819
|
+
async requestWithMethod(method, path, body, timeoutMs, extraHeaders) {
|
|
13820
|
+
if (!this.apiKey) {
|
|
13821
|
+
throw new OpenMatesConfigError("OpenMates API key is required");
|
|
13822
|
+
}
|
|
13823
|
+
const response = await fetch(`${this.apiUrl}${path}`, {
|
|
13824
|
+
method,
|
|
13825
|
+
headers: { ...this.headers(body !== void 0), ...extraHeaders },
|
|
13826
|
+
body: body === void 0 ? void 0 : JSON.stringify(body),
|
|
13827
|
+
signal: timeoutMs === void 0 ? void 0 : AbortSignal.timeout(timeoutMs)
|
|
13828
|
+
});
|
|
13829
|
+
return this.parseResponse(response);
|
|
13830
|
+
}
|
|
13831
|
+
getMasterKey() {
|
|
13832
|
+
this.masterKeyPromise ??= this.loadMasterKey();
|
|
13833
|
+
return this.masterKeyPromise;
|
|
13834
|
+
}
|
|
13835
|
+
async loadMasterKey() {
|
|
13836
|
+
if (!this.apiKey) {
|
|
13837
|
+
throw new OpenMatesConfigError("OpenMates API key is required");
|
|
13838
|
+
}
|
|
13839
|
+
const session = await this.getSdkSession();
|
|
13840
|
+
const wrapper = session.key_wrapper;
|
|
13841
|
+
if (!wrapper?.encrypted_key || !wrapper.salt || !wrapper.key_iv) {
|
|
13842
|
+
throw new OpenMatesConfigError("SDK session did not include API-key-wrapped master key material");
|
|
13843
|
+
}
|
|
13844
|
+
const masterKey = await unwrapApiKeyMasterKey({
|
|
13845
|
+
apiKey: this.apiKey,
|
|
13846
|
+
encryptedMasterKeyB64: wrapper.encrypted_key,
|
|
13847
|
+
saltB64: wrapper.salt,
|
|
13848
|
+
keyIvB64: wrapper.key_iv
|
|
13849
|
+
});
|
|
13850
|
+
if (!masterKey) {
|
|
13851
|
+
throw new OpenMatesConfigError("Unable to decrypt SDK session master key with API key");
|
|
13852
|
+
}
|
|
13853
|
+
return masterKey;
|
|
13854
|
+
}
|
|
13855
|
+
getSdkSession() {
|
|
13856
|
+
this.sdkSessionPromise ??= this.request("/v1/sdk/session", {
|
|
13857
|
+
sdk_name: "npm",
|
|
13858
|
+
device_identity: this.deviceId
|
|
13859
|
+
});
|
|
13860
|
+
return this.sdkSessionPromise;
|
|
13861
|
+
}
|
|
13862
|
+
headers(hasBody = true) {
|
|
13863
|
+
const headers = {
|
|
13864
|
+
Accept: "application/json",
|
|
13865
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
13866
|
+
"X-OpenMates-SDK": "npm",
|
|
13867
|
+
"X-OpenMates-Device-Identity": this.deviceId
|
|
13868
|
+
};
|
|
13869
|
+
if (hasBody) {
|
|
13870
|
+
headers["Content-Type"] = "application/json";
|
|
13871
|
+
}
|
|
13872
|
+
return headers;
|
|
13873
|
+
}
|
|
13874
|
+
publicHeaders() {
|
|
13875
|
+
return {
|
|
13876
|
+
Accept: "application/json",
|
|
13877
|
+
"X-OpenMates-SDK": "npm",
|
|
13878
|
+
"X-OpenMates-Device-Identity": this.deviceId
|
|
13879
|
+
};
|
|
13880
|
+
}
|
|
13881
|
+
async parseResponse(response) {
|
|
13882
|
+
let data = {};
|
|
13883
|
+
try {
|
|
13884
|
+
data = await response.json();
|
|
13885
|
+
} catch {
|
|
13886
|
+
data = {};
|
|
13887
|
+
}
|
|
13888
|
+
if (!response.ok) {
|
|
13889
|
+
throw new OpenMatesApiError(response.status, data);
|
|
13890
|
+
}
|
|
13891
|
+
return data;
|
|
13892
|
+
}
|
|
13893
|
+
};
|
|
13894
|
+
function loadOrCreateDeviceId(customPath) {
|
|
13895
|
+
const path = customPath ?? join3(homedir4(), ".openmates", "sdk-device-id");
|
|
13896
|
+
if (existsSync5(path)) {
|
|
13897
|
+
const stored = readFileSync4(path, "utf8").trim();
|
|
13898
|
+
if (stored) return stored;
|
|
13899
|
+
}
|
|
13900
|
+
const deviceId = randomUUID6();
|
|
13901
|
+
mkdirSync3(dirname(path), { recursive: true, mode: 448 });
|
|
13902
|
+
writeFileSync3(path, `${deviceId}
|
|
13903
|
+
`, { encoding: "utf8", mode: 384 });
|
|
13904
|
+
chmodSync2(path, 384);
|
|
13905
|
+
return deviceId;
|
|
13906
|
+
}
|
|
13907
|
+
function withQuery(path, query = {}) {
|
|
13908
|
+
const params = new URLSearchParams();
|
|
13909
|
+
for (const [key, value] of Object.entries(query)) {
|
|
13910
|
+
if (value !== void 0 && value !== null) params.set(key, String(value));
|
|
13911
|
+
}
|
|
13912
|
+
const serialized = params.toString();
|
|
13913
|
+
return serialized ? `${path}?${serialized}` : path;
|
|
13914
|
+
}
|
|
13915
|
+
function requireConfirmed(options, action) {
|
|
13916
|
+
if (options?.confirmed !== true) {
|
|
13917
|
+
throw new OpenMatesConfigError(`${action} requires confirmed: true`);
|
|
13918
|
+
}
|
|
13919
|
+
}
|
|
13920
|
+
function unsupportedSdkFeature(feature) {
|
|
13921
|
+
throw new OpenMatesConfigError(`${feature} is not available through the API-key SDK yet`);
|
|
13922
|
+
}
|
|
13923
|
+
function extractFilename(contentDisposition) {
|
|
13924
|
+
if (!contentDisposition) return void 0;
|
|
13925
|
+
const encoded = contentDisposition.match(/filename\*=UTF-8''([^;]+)/)?.[1];
|
|
13926
|
+
if (encoded) return decodeURIComponent(encoded);
|
|
13927
|
+
return contentDisposition.match(/filename="?([^";]+)"?/)?.[1];
|
|
13928
|
+
}
|
|
13929
|
+
function normalizeHistory(history) {
|
|
13930
|
+
if (!history) return [];
|
|
13931
|
+
if (Array.isArray(history)) return history;
|
|
13932
|
+
return Array.isArray(history.messages) ? history.messages : [];
|
|
13933
|
+
}
|
|
13934
|
+
function parseMaybeJson(value) {
|
|
13935
|
+
if (value === null) return null;
|
|
13936
|
+
try {
|
|
13937
|
+
return JSON.parse(value);
|
|
13938
|
+
} catch {
|
|
13939
|
+
try {
|
|
13940
|
+
return toonDecode(value, { strict: false });
|
|
13941
|
+
} catch {
|
|
13942
|
+
return value;
|
|
13943
|
+
}
|
|
13944
|
+
}
|
|
13945
|
+
}
|
|
13946
|
+
var OpenMatesChats = class {
|
|
13947
|
+
client;
|
|
13948
|
+
constructor(client) {
|
|
13949
|
+
this.client = client;
|
|
13950
|
+
}
|
|
13951
|
+
async list(options = {}) {
|
|
13952
|
+
const result = await this.client.get(
|
|
13953
|
+
withQuery("/v1/sdk/chats", { limit: options.limit ?? 10, offset: options.offset })
|
|
13954
|
+
);
|
|
13955
|
+
const chats = Array.isArray(result.chats) ? result.chats : [];
|
|
13956
|
+
return Promise.all(chats.map((chat) => this.client.decryptChatMetadata(chat)));
|
|
13957
|
+
}
|
|
13958
|
+
async search(query, options = {}) {
|
|
13959
|
+
const normalized = query.trim().toLowerCase();
|
|
13960
|
+
const chats = await this.list({ limit: 0 });
|
|
13961
|
+
const offset = options.offset ?? 0;
|
|
13962
|
+
const limit = options.limit ?? 10;
|
|
13963
|
+
const matches2 = chats.filter((chat) => {
|
|
13964
|
+
const haystack = [chat.title, chat.chat_summary, chat.category, chat.id].filter((value) => typeof value === "string").join("\n").toLowerCase();
|
|
13965
|
+
return haystack.includes(normalized);
|
|
13966
|
+
});
|
|
13967
|
+
return matches2.slice(offset, limit === 0 ? void 0 : offset + limit);
|
|
13968
|
+
}
|
|
13969
|
+
async load(chatId) {
|
|
13970
|
+
const payload = await this.client.get(`/v1/sdk/chats/${encodeURIComponent(chatId)}`);
|
|
13971
|
+
return this.client.decryptLoadedChatPayload(payload);
|
|
13972
|
+
}
|
|
13973
|
+
async send(message, options = {}) {
|
|
13974
|
+
if (options.saveToAccount === true) {
|
|
13975
|
+
return this.sendSaved(message, options);
|
|
13976
|
+
}
|
|
13977
|
+
const result = await this.client.request("/v1/sdk/chats", {
|
|
13978
|
+
message,
|
|
13979
|
+
history: normalizeHistory(options.history),
|
|
13980
|
+
save_to_account: false,
|
|
13981
|
+
memory_ids: options.memoryIds ?? [],
|
|
13982
|
+
model: options.model,
|
|
13983
|
+
focus_mode: options.focusMode ? { app_id: options.focusMode.appId, focus_mode_id: options.focusMode.focusModeId } : void 0
|
|
13984
|
+
});
|
|
13985
|
+
return result.response ?? result;
|
|
13986
|
+
}
|
|
13987
|
+
async sendSaved(message, options) {
|
|
13988
|
+
const masterKey = await this.client.masterKey();
|
|
13989
|
+
const session = await this.client.sdkSession();
|
|
13990
|
+
if (!session.user?.id) {
|
|
13991
|
+
throw new OpenMatesConfigError("SDK session did not include the authenticated user identity");
|
|
13992
|
+
}
|
|
13993
|
+
const chatId = options.chatId ?? randomUUID6();
|
|
13994
|
+
const turnId = randomUUID6();
|
|
13995
|
+
const messageId = randomUUID6();
|
|
13996
|
+
const createdAt = Math.floor(Date.now() / 1e3);
|
|
13997
|
+
let chatKey;
|
|
13998
|
+
let encryptedChatKey;
|
|
13999
|
+
let expectedMessagesV = 0;
|
|
14000
|
+
let encryptedChatMetadata;
|
|
14001
|
+
if (options.chatId) {
|
|
14002
|
+
const loaded = await this.load(chatId);
|
|
14003
|
+
const chat = loaded.chat;
|
|
14004
|
+
if (!chat?.encrypted_chat_key) {
|
|
14005
|
+
throw new OpenMatesConfigError("Saved chat does not include encrypted chat key material");
|
|
14006
|
+
}
|
|
14007
|
+
const decrypted = await decryptBytesWithAesGcm(chat.encrypted_chat_key, masterKey);
|
|
14008
|
+
if (!decrypted) {
|
|
14009
|
+
throw new OpenMatesConfigError("Unable to decrypt saved chat key material");
|
|
14010
|
+
}
|
|
14011
|
+
chatKey = decrypted;
|
|
14012
|
+
encryptedChatKey = chat.encrypted_chat_key;
|
|
14013
|
+
expectedMessagesV = Number(chat.messages_v ?? 0);
|
|
14014
|
+
} else {
|
|
14015
|
+
chatKey = new Uint8Array(randomBytes3(32));
|
|
14016
|
+
encryptedChatKey = await encryptBytesWithAesGcm(chatKey, masterKey);
|
|
14017
|
+
encryptedChatMetadata = {
|
|
14018
|
+
encrypted_title: await encryptWithAesGcmCombined(options.title ?? message.slice(0, 80), chatKey),
|
|
14019
|
+
encrypted_chat_key: encryptedChatKey,
|
|
14020
|
+
created_at: createdAt,
|
|
14021
|
+
updated_at: createdAt
|
|
14022
|
+
};
|
|
14023
|
+
}
|
|
14024
|
+
const recovery = await deriveChatCompletionRecoveryKeypair(
|
|
14025
|
+
Buffer.from(chatKey).toString("base64url"),
|
|
14026
|
+
chatId,
|
|
14027
|
+
1
|
|
14028
|
+
);
|
|
14029
|
+
const history = normalizeHistory(options.history);
|
|
14030
|
+
const inferenceRequest = {
|
|
14031
|
+
messages: [...history, { role: "user", content: message }],
|
|
14032
|
+
model: options.model,
|
|
14033
|
+
focus_mode: options.focusMode ? { app_id: options.focusMode.appId, focus_mode_id: options.focusMode.focusModeId } : void 0,
|
|
14034
|
+
memory_ids: options.memoryIds ?? []
|
|
14035
|
+
};
|
|
14036
|
+
const result = await this.client.request("/v1/sdk/chats", {
|
|
14037
|
+
message,
|
|
14038
|
+
history,
|
|
14039
|
+
save_to_account: true,
|
|
14040
|
+
title: options.title,
|
|
14041
|
+
memory_ids: options.memoryIds ?? [],
|
|
14042
|
+
model: options.model,
|
|
14043
|
+
focus_mode: inferenceRequest.focus_mode,
|
|
14044
|
+
protocol_version: 1,
|
|
14045
|
+
chat_id: chatId,
|
|
14046
|
+
turn_id: turnId,
|
|
14047
|
+
message_id: messageId,
|
|
14048
|
+
chat_key_version: 1,
|
|
14049
|
+
encrypted_chat_key: encryptedChatKey,
|
|
14050
|
+
recovery_public_key: recovery.publicKey,
|
|
14051
|
+
expected_messages_v: expectedMessagesV,
|
|
14052
|
+
encrypted_user_message: {
|
|
14053
|
+
client_message_id: messageId,
|
|
14054
|
+
chat_id: chatId,
|
|
14055
|
+
encrypted_content: await encryptWithAesGcmCombined(message, chatKey),
|
|
14056
|
+
encrypted_sender_name: await encryptWithAesGcmCombined("User", chatKey),
|
|
14057
|
+
role: "user",
|
|
14058
|
+
created_at: createdAt,
|
|
14059
|
+
updated_at: createdAt
|
|
14060
|
+
},
|
|
14061
|
+
encrypted_chat_metadata: encryptedChatMetadata,
|
|
14062
|
+
inference_request: inferenceRequest
|
|
14063
|
+
});
|
|
14064
|
+
if (!result.task_id) {
|
|
14065
|
+
throw new OpenMatesConfigError("Saved chat dispatch did not return a stable inference task id");
|
|
14066
|
+
}
|
|
14067
|
+
const claim = await this.pollRecoveryClaim(
|
|
14068
|
+
result.task_id,
|
|
14069
|
+
options.recoveryTimeoutMs ?? DEFAULT_RECOVERY_TIMEOUT_MS,
|
|
14070
|
+
options.recoveryPollIntervalMs ?? DEFAULT_RECOVERY_POLL_INTERVAL_MS
|
|
14071
|
+
);
|
|
14072
|
+
const recovered = await this.openRecoveryClaim(
|
|
14073
|
+
claim,
|
|
14074
|
+
recovery.privateKey,
|
|
14075
|
+
session.user.id,
|
|
14076
|
+
chatId,
|
|
14077
|
+
turnId
|
|
14078
|
+
);
|
|
14079
|
+
const completedAt = Math.floor(Date.now() / 1e3);
|
|
14080
|
+
const encryptedAssistantMessage = {
|
|
14081
|
+
client_message_id: recovered.assistantMessageId,
|
|
14082
|
+
chat_id: chatId,
|
|
14083
|
+
encrypted_content: await encryptWithAesGcmCombined(recovered.content, chatKey),
|
|
14084
|
+
encrypted_sender_name: await encryptWithAesGcmCombined("Assistant", chatKey),
|
|
14085
|
+
role: "assistant",
|
|
14086
|
+
user_message_id: messageId,
|
|
14087
|
+
created_at: completedAt,
|
|
14088
|
+
updated_at: completedAt
|
|
14089
|
+
};
|
|
14090
|
+
if (recovered.category !== null) {
|
|
14091
|
+
encryptedAssistantMessage.encrypted_category = await encryptWithAesGcmCombined(recovered.category, chatKey);
|
|
14092
|
+
}
|
|
14093
|
+
if (recovered.modelName !== null) {
|
|
14094
|
+
encryptedAssistantMessage.encrypted_model_name = await encryptWithAesGcmCombined(recovered.modelName, chatKey);
|
|
14095
|
+
}
|
|
14096
|
+
const terminal = await this.client.request(
|
|
14097
|
+
`/v1/sdk/chats/recovery/${encodeURIComponent(result.task_id)}/persist`,
|
|
14098
|
+
{
|
|
14099
|
+
protocol_version: 1,
|
|
14100
|
+
lease_generation: claim.lease_generation,
|
|
14101
|
+
lease_token: claim.lease_token,
|
|
14102
|
+
expected_messages_v: expectedMessagesV + 1,
|
|
14103
|
+
encrypted_assistant_message: encryptedAssistantMessage
|
|
14104
|
+
}
|
|
14105
|
+
);
|
|
14106
|
+
if (terminal.state !== "TERMINAL") {
|
|
14107
|
+
throw new OpenMatesConfigError("Saved chat recovery did not reach terminal persistence");
|
|
14108
|
+
}
|
|
14109
|
+
return {
|
|
14110
|
+
content: recovered.content,
|
|
14111
|
+
category: recovered.category,
|
|
14112
|
+
model_name: recovered.modelName,
|
|
14113
|
+
chat_id: result.chat_id ?? chatId,
|
|
14114
|
+
task_id: result.task_id,
|
|
14115
|
+
preflight: result.preflight,
|
|
14116
|
+
terminal
|
|
14117
|
+
};
|
|
14118
|
+
}
|
|
14119
|
+
async pollRecoveryClaim(taskId, timeoutMs, pollIntervalMs) {
|
|
14120
|
+
if (!Number.isFinite(timeoutMs) || !Number.isFinite(pollIntervalMs) || timeoutMs <= 0 || pollIntervalMs <= 0) {
|
|
14121
|
+
throw new OpenMatesConfigError("Recovery timeout and poll interval must be finite and positive");
|
|
14122
|
+
}
|
|
14123
|
+
const deadline = Date.now() + timeoutMs;
|
|
14124
|
+
while (Date.now() < deadline) {
|
|
14125
|
+
try {
|
|
14126
|
+
const remainingMs2 = deadline - Date.now();
|
|
14127
|
+
if (remainingMs2 <= 0) break;
|
|
14128
|
+
return await this.client.request(
|
|
14129
|
+
`/v1/sdk/chats/recovery/${encodeURIComponent(taskId)}/claim`,
|
|
14130
|
+
{ protocol_version: 1 },
|
|
14131
|
+
remainingMs2
|
|
14132
|
+
);
|
|
14133
|
+
} catch (error) {
|
|
14134
|
+
if (!(error instanceof OpenMatesApiError) || error.status !== 404) throw error;
|
|
14135
|
+
}
|
|
14136
|
+
const remainingMs = deadline - Date.now();
|
|
14137
|
+
if (remainingMs <= 0) break;
|
|
14138
|
+
await new Promise((resolve7) => setTimeout(resolve7, Math.min(pollIntervalMs, remainingMs)));
|
|
14139
|
+
}
|
|
14140
|
+
throw new OpenMatesConfigError("Timed out waiting for saved chat recovery");
|
|
14141
|
+
}
|
|
14142
|
+
async openRecoveryClaim(claim, recoveryPrivateKey, ownerId, chatId, turnId) {
|
|
14143
|
+
const jobId = typeof claim.job_id === "string" ? claim.job_id : null;
|
|
14144
|
+
const assistantMessageId = typeof claim.assistant_message_id === "string" ? claim.assistant_message_id : null;
|
|
14145
|
+
const keyVersion = Number.isSafeInteger(claim.chat_key_version) ? Number(claim.chat_key_version) : null;
|
|
14146
|
+
if (claim.state !== "LEASED" || typeof claim.lease_token !== "string" || !Number.isSafeInteger(claim.lease_generation) || !jobId || !assistantMessageId || keyVersion !== 1 || claim.chat_id !== chatId || claim.turn_id !== turnId || typeof claim.sealed_payload !== "string") {
|
|
14147
|
+
throw new OpenMatesConfigError("Recovery job claim returned invalid lease or identity data");
|
|
14148
|
+
}
|
|
14149
|
+
let envelope;
|
|
14150
|
+
try {
|
|
14151
|
+
envelope = JSON.parse(claim.sealed_payload);
|
|
14152
|
+
} catch {
|
|
14153
|
+
throw new OpenMatesConfigError("Recovery job contained an invalid sealed envelope");
|
|
14154
|
+
}
|
|
14155
|
+
const plaintext = await openChatCompletionRecoveryEnvelope(envelope, {
|
|
14156
|
+
recoveryPrivateKey,
|
|
14157
|
+
ownerId,
|
|
14158
|
+
chatId,
|
|
14159
|
+
turnId,
|
|
14160
|
+
jobId,
|
|
14161
|
+
assistantMessageId,
|
|
14162
|
+
keyVersion
|
|
14163
|
+
});
|
|
14164
|
+
let payload;
|
|
14165
|
+
try {
|
|
14166
|
+
payload = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(plaintext));
|
|
14167
|
+
} catch {
|
|
14168
|
+
throw new OpenMatesConfigError("Recovery job plaintext was not valid UTF-8 JSON");
|
|
14169
|
+
}
|
|
14170
|
+
const fields = ["assistant_message_id", "category", "chat_id", "content", "job_id", "key_version", "model_name", "turn_id"];
|
|
14171
|
+
if (Object.keys(payload).sort().join(",") !== fields.join(",") || payload.assistant_message_id !== assistantMessageId || payload.chat_id !== chatId || payload.turn_id !== turnId || payload.job_id !== jobId || payload.key_version !== keyVersion || typeof payload.content !== "string" || payload.category !== null && typeof payload.category !== "string" || payload.model_name !== null && typeof payload.model_name !== "string") {
|
|
14172
|
+
throw new OpenMatesConfigError("Recovery job plaintext did not match the terminal completion identity");
|
|
14173
|
+
}
|
|
14174
|
+
return {
|
|
14175
|
+
assistantMessageId,
|
|
14176
|
+
content: payload.content,
|
|
14177
|
+
category: payload.category,
|
|
14178
|
+
modelName: payload.model_name
|
|
14179
|
+
};
|
|
14180
|
+
}
|
|
14181
|
+
async export(chatId, options = {}) {
|
|
14182
|
+
const payload = await this.load(chatId);
|
|
14183
|
+
return this.client.request(`/v1/sdk/chats/${encodeURIComponent(chatId)}/export`, {
|
|
14184
|
+
format: options.format ?? "json",
|
|
14185
|
+
payload
|
|
14186
|
+
});
|
|
14187
|
+
}
|
|
14188
|
+
async delete(chatId, options) {
|
|
14189
|
+
requireConfirmed(options, "Deleting a chat");
|
|
14190
|
+
return this.client.delete(`/v1/sdk/chats/${encodeURIComponent(chatId)}`);
|
|
14191
|
+
}
|
|
14192
|
+
async share(chatId, options = {}) {
|
|
14193
|
+
const loaded = await this.load(chatId);
|
|
14194
|
+
const chat = loaded.chat;
|
|
14195
|
+
if (!chat?.encrypted_chat_key) {
|
|
14196
|
+
throw new OpenMatesConfigError("Chat does not include an encrypted chat key");
|
|
14197
|
+
}
|
|
14198
|
+
const chatKey = await decryptBytesWithAesGcm(chat.encrypted_chat_key, await this.client.masterKey());
|
|
14199
|
+
if (!chatKey) {
|
|
14200
|
+
throw new OpenMatesConfigError("Unable to decrypt chat key for share link");
|
|
14201
|
+
}
|
|
14202
|
+
const blob = await generateChatShareBlob(chatId, chatKey, options.expires ?? 0, options.password);
|
|
14203
|
+
return { url: buildChatShareUrl(this.client.webOrigin(), chatId, blob) };
|
|
14204
|
+
}
|
|
14205
|
+
async followUps(chatId) {
|
|
14206
|
+
const payload = await this.load(chatId);
|
|
14207
|
+
const chat = payload.chat;
|
|
14208
|
+
const encrypted = chat?.encrypted_follow_up_request_suggestions;
|
|
14209
|
+
if (typeof encrypted !== "string") return [];
|
|
14210
|
+
const raw = await decryptWithAesGcmCombined(encrypted, await this.client.masterKey());
|
|
14211
|
+
const parsed = raw ? parseMaybeJson(raw) : [];
|
|
14212
|
+
return Array.isArray(parsed) ? parsed.filter((item) => typeof item === "string") : [];
|
|
14213
|
+
}
|
|
14214
|
+
async incognito(message) {
|
|
14215
|
+
return this.send(message, { saveToAccount: false });
|
|
14216
|
+
}
|
|
14217
|
+
};
|
|
14218
|
+
var OpenMatesDrafts = class {
|
|
14219
|
+
client;
|
|
14220
|
+
constructor(client) {
|
|
14221
|
+
this.client = client;
|
|
14222
|
+
}
|
|
14223
|
+
async listEncrypted() {
|
|
14224
|
+
const response = await this.client.get("/v1/sdk/drafts");
|
|
14225
|
+
return (response.drafts ?? []).map(normalizeEncryptedDraft);
|
|
14226
|
+
}
|
|
14227
|
+
async list() {
|
|
14228
|
+
return Promise.all((await this.listEncrypted()).map((draft) => this.decrypt(draft)));
|
|
14229
|
+
}
|
|
14230
|
+
async getEncrypted(chatId) {
|
|
14231
|
+
const response = await this.client.get(
|
|
14232
|
+
`/v1/sdk/drafts/${encodeURIComponent(chatId)}`
|
|
14233
|
+
);
|
|
14234
|
+
return response.draft ? normalizeEncryptedDraft(response.draft) : null;
|
|
14235
|
+
}
|
|
14236
|
+
async get(chatId) {
|
|
14237
|
+
const encrypted = await this.getEncrypted(chatId);
|
|
14238
|
+
return encrypted ? this.decrypt(encrypted) : null;
|
|
14239
|
+
}
|
|
14240
|
+
async decrypt(draft) {
|
|
14241
|
+
const masterKey = await this.client.masterKey();
|
|
14242
|
+
const markdown = await decryptWithAesGcmCombined(draft.encryptedDraftMd, masterKey);
|
|
14243
|
+
if (markdown === null) throw new OpenMatesConfigError("Unable to decrypt draft markdown");
|
|
14244
|
+
const preview = draft.encryptedDraftPreview ? await decryptWithAesGcmCombined(draft.encryptedDraftPreview, masterKey) : markdown.slice(0, 160);
|
|
14245
|
+
return { ...draft, markdown, preview };
|
|
14246
|
+
}
|
|
14247
|
+
};
|
|
14248
|
+
function normalizeEncryptedDraft(raw) {
|
|
14249
|
+
return {
|
|
14250
|
+
chatId: String(raw.chat_id ?? ""),
|
|
14251
|
+
encryptedDraftMd: String(raw.encrypted_draft_md ?? ""),
|
|
14252
|
+
encryptedDraftPreview: typeof raw.encrypted_draft_preview === "string" ? raw.encrypted_draft_preview : null,
|
|
14253
|
+
draftV: Number(raw.draft_v ?? 0)
|
|
14254
|
+
};
|
|
14255
|
+
}
|
|
14256
|
+
var OpenMatesAccount = class {
|
|
14257
|
+
client;
|
|
14258
|
+
constructor(client) {
|
|
14259
|
+
this.client = client;
|
|
14260
|
+
}
|
|
14261
|
+
async info() {
|
|
14262
|
+
return this.client.get("/v1/sdk/account");
|
|
14263
|
+
}
|
|
14264
|
+
async setTimezone(timezone) {
|
|
14265
|
+
return this.client.request("/v1/sdk/account/timezone", { timezone });
|
|
14266
|
+
}
|
|
14267
|
+
async listInterests() {
|
|
14268
|
+
const data = await this.client.get("/v1/sdk/account/topic-preferences");
|
|
14269
|
+
const encrypted = data.encrypted_settings;
|
|
14270
|
+
if (typeof encrypted !== "string") return { selectedTagIds: [] };
|
|
14271
|
+
const raw = await decryptWithAesGcmCombined(encrypted, await this.client.masterKey());
|
|
14272
|
+
const parsed = raw ? parseMaybeJson(raw) : {};
|
|
14273
|
+
return {
|
|
14274
|
+
selectedTagIds: typeof parsed === "object" && parsed !== null && Array.isArray(parsed.selected_tag_ids) ? parsed.selected_tag_ids : []
|
|
14275
|
+
};
|
|
14276
|
+
}
|
|
14277
|
+
async setInterests(selectedTagIds) {
|
|
14278
|
+
const encrypted_settings = await encryptWithAesGcmCombined(
|
|
14279
|
+
JSON.stringify({ selected_tag_ids: selectedTagIds }),
|
|
14280
|
+
await this.client.masterKey()
|
|
14281
|
+
);
|
|
14282
|
+
return this.client.request("/v1/sdk/account/topic-preferences", { encrypted_settings });
|
|
14283
|
+
}
|
|
14284
|
+
async clearInterests() {
|
|
14285
|
+
return this.setInterests([]);
|
|
14286
|
+
}
|
|
14287
|
+
async exportManifest() {
|
|
14288
|
+
return this.client.get("/v1/sdk/account/export/manifest");
|
|
14289
|
+
}
|
|
14290
|
+
async exportData() {
|
|
14291
|
+
return this.client.get("/v1/sdk/account/export/data");
|
|
14292
|
+
}
|
|
14293
|
+
async setUsername(username) {
|
|
14294
|
+
return this.client.request("/v1/sdk/account/username", { username });
|
|
14295
|
+
}
|
|
14296
|
+
async storageOverview() {
|
|
14297
|
+
return this.client.get("/v1/sdk/account/storage");
|
|
14298
|
+
}
|
|
14299
|
+
async storageFiles(options = {}) {
|
|
14300
|
+
return this.client.get(withQuery("/v1/sdk/account/storage/files", options.query));
|
|
14301
|
+
}
|
|
14302
|
+
async deleteStorage(options) {
|
|
14303
|
+
requireConfirmed(options, "Deleting stored account files");
|
|
14304
|
+
return this.client.delete("/v1/sdk/account/storage/files", {
|
|
14305
|
+
file_id: options.fileId,
|
|
14306
|
+
category: options.category,
|
|
14307
|
+
all: options.all === true
|
|
14308
|
+
});
|
|
14309
|
+
}
|
|
14310
|
+
};
|
|
14311
|
+
var OpenMatesSettings = class {
|
|
14312
|
+
client;
|
|
14313
|
+
constructor(client) {
|
|
14314
|
+
this.client = client;
|
|
14315
|
+
}
|
|
14316
|
+
async setLanguage(language) {
|
|
14317
|
+
return this.client.request("/v1/sdk/settings/language", { language });
|
|
14318
|
+
}
|
|
14319
|
+
async setDarkMode(enabled) {
|
|
14320
|
+
return this.client.request("/v1/sdk/settings/dark-mode", { enabled });
|
|
14321
|
+
}
|
|
14322
|
+
async setFont(font) {
|
|
14323
|
+
return this.client.request("/v1/sdk/settings/font", { font });
|
|
14324
|
+
}
|
|
14325
|
+
async setModelDefaults(defaults) {
|
|
14326
|
+
return this.client.request("/v1/sdk/settings/ai-model-defaults", defaults);
|
|
14327
|
+
}
|
|
14328
|
+
async setChatAutoDelete(period) {
|
|
14329
|
+
return this.client.request("/v1/sdk/settings/auto-delete/chats", { period });
|
|
14330
|
+
}
|
|
14331
|
+
async shareDebugLogs(options) {
|
|
14332
|
+
requireConfirmed(options, "Sharing debug logs");
|
|
14333
|
+
return unsupportedSdkFeature("Debug-log sharing");
|
|
14334
|
+
}
|
|
14335
|
+
};
|
|
14336
|
+
var OpenMatesMemories = class {
|
|
14337
|
+
client;
|
|
14338
|
+
constructor(client) {
|
|
14339
|
+
this.client = client;
|
|
14340
|
+
}
|
|
14341
|
+
async list(options = {}) {
|
|
14342
|
+
const data = await this.client.get(withQuery("/v1/sdk/memories", options.query));
|
|
14343
|
+
const memories = await Promise.all((data.memories ?? []).map(async (memory) => {
|
|
14344
|
+
const decrypted = { ...memory };
|
|
14345
|
+
if (typeof memory.encrypted_item_json === "string") {
|
|
14346
|
+
const raw = await decryptWithAesGcmCombined(memory.encrypted_item_json, await this.client.masterKey());
|
|
14347
|
+
decrypted.data = raw ? parseMaybeJson(raw) : null;
|
|
14348
|
+
}
|
|
14349
|
+
return decrypted;
|
|
14350
|
+
}));
|
|
14351
|
+
return { memories };
|
|
14352
|
+
}
|
|
14353
|
+
async types(options = {}) {
|
|
14354
|
+
return this.client.get(withQuery("/v1/sdk/memories/types", options.query));
|
|
14355
|
+
}
|
|
14356
|
+
async create(input) {
|
|
14357
|
+
return this.storeMemory(input);
|
|
14358
|
+
}
|
|
14359
|
+
async update(id, input) {
|
|
14360
|
+
return this.storeMemory({ ...input, id });
|
|
14361
|
+
}
|
|
14362
|
+
async delete(id, options) {
|
|
14363
|
+
requireConfirmed(options, "Deleting a memory");
|
|
14364
|
+
return this.client.delete(`/v1/sdk/memories/${encodeURIComponent(id)}`);
|
|
14365
|
+
}
|
|
14366
|
+
async storeMemory(input) {
|
|
14367
|
+
const appId = String(input.appId ?? input.app_id ?? "");
|
|
14368
|
+
const itemType = String(input.itemType ?? input.item_type ?? "");
|
|
14369
|
+
const rawItemValue = input.itemValue ?? input.item_value ?? input.data ?? {};
|
|
14370
|
+
const itemValue = rawItemValue && typeof rawItemValue === "object" && !Array.isArray(rawItemValue) ? rawItemValue : { value: rawItemValue };
|
|
14371
|
+
if (!appId || !itemType) {
|
|
14372
|
+
throw new OpenMatesConfigError("Memory create/update requires appId and itemType");
|
|
14373
|
+
}
|
|
14374
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
14375
|
+
const entry = {
|
|
14376
|
+
id: String(input.id ?? randomUUID6()),
|
|
14377
|
+
app_id: appId,
|
|
14378
|
+
item_key: hashItemKey(appId, itemType),
|
|
14379
|
+
item_type: itemType,
|
|
14380
|
+
encrypted_item_json: await encryptWithAesGcmCombined(
|
|
14381
|
+
JSON.stringify({ ...itemValue, settings_group: appId, _original_item_key: itemType, added_date: now }),
|
|
14382
|
+
await this.client.masterKey()
|
|
14383
|
+
),
|
|
14384
|
+
encrypted_app_key: "",
|
|
14385
|
+
created_at: Number(input.created_at ?? now),
|
|
14386
|
+
updated_at: now,
|
|
14387
|
+
item_version: Number(input.itemVersion ?? input.item_version ?? 1)
|
|
14388
|
+
};
|
|
14389
|
+
return this.client.request("/v1/sdk/memories", { entry });
|
|
14390
|
+
}
|
|
14391
|
+
};
|
|
14392
|
+
var OpenMatesBilling = class {
|
|
14393
|
+
client;
|
|
14394
|
+
constructor(client) {
|
|
14395
|
+
this.client = client;
|
|
14396
|
+
}
|
|
14397
|
+
async overview() {
|
|
14398
|
+
return this.client.get("/v1/sdk/billing");
|
|
14399
|
+
}
|
|
14400
|
+
async usage(options = {}) {
|
|
14401
|
+
return this.client.get(withQuery("/v1/sdk/billing/usage", options.query));
|
|
14402
|
+
}
|
|
14403
|
+
async usageSummaries() {
|
|
14404
|
+
return this.client.get("/v1/sdk/billing/usage/summaries");
|
|
14405
|
+
}
|
|
14406
|
+
async usageDaily() {
|
|
14407
|
+
return this.client.get("/v1/sdk/billing/usage/daily");
|
|
14408
|
+
}
|
|
14409
|
+
async usageExport(options = {}) {
|
|
14410
|
+
return this.client.getRaw(withQuery("/v1/sdk/billing/usage/export", { months: options.months }));
|
|
14411
|
+
}
|
|
14412
|
+
async createBankTransferOrder(credits) {
|
|
14413
|
+
return this.client.request("/v1/sdk/billing/bank-transfer-orders", { credits_amount: credits, currency: "eur" });
|
|
14414
|
+
}
|
|
14415
|
+
async bankTransferStatus(orderId) {
|
|
14416
|
+
return this.client.get(`/v1/sdk/billing/bank-transfer-orders/${encodeURIComponent(orderId)}`);
|
|
14417
|
+
}
|
|
14418
|
+
async listBankTransferOrders() {
|
|
14419
|
+
return this.client.get("/v1/sdk/billing/bank-transfer-orders");
|
|
14420
|
+
}
|
|
14421
|
+
async listInvoices() {
|
|
14422
|
+
return this.client.get("/v1/sdk/billing/invoices");
|
|
14423
|
+
}
|
|
14424
|
+
async downloadInvoice(invoiceId) {
|
|
14425
|
+
return this.client.getRaw(`/v1/sdk/billing/invoices/${encodeURIComponent(invoiceId)}/download`);
|
|
14426
|
+
}
|
|
14427
|
+
async downloadCreditNote(invoiceId) {
|
|
14428
|
+
return this.client.getRaw(`/v1/sdk/billing/invoices/${encodeURIComponent(invoiceId)}/credit-note/download`);
|
|
14429
|
+
}
|
|
14430
|
+
async requestRefund(invoiceId, options) {
|
|
14431
|
+
requireConfirmed(options, "Requesting an invoice refund");
|
|
14432
|
+
return this.client.request("/v1/sdk/billing/refund", { invoice_id: invoiceId, email_encryption_key: options.emailEncryptionKey });
|
|
14433
|
+
}
|
|
14434
|
+
async redeemGiftCard(code) {
|
|
14435
|
+
return this.client.request("/v1/sdk/billing/gift-cards/redeem", { code });
|
|
14436
|
+
}
|
|
14437
|
+
async listRedeemedGiftCards() {
|
|
14438
|
+
return this.client.get("/v1/sdk/billing/gift-cards/redeemed");
|
|
14439
|
+
}
|
|
14440
|
+
async createGiftCardBankTransferOrder(credits) {
|
|
14441
|
+
return this.client.request("/v1/sdk/billing/gift-cards/bank-transfer-orders", { credits_amount: credits, currency: "eur" });
|
|
14442
|
+
}
|
|
14443
|
+
async giftCardPurchaseStatus(orderId) {
|
|
14444
|
+
return this.client.get(`/v1/sdk/billing/gift-cards/purchases/${encodeURIComponent(orderId)}`);
|
|
14445
|
+
}
|
|
14446
|
+
async listPurchasedGiftCards() {
|
|
14447
|
+
return this.client.get("/v1/sdk/billing/gift-cards/purchased");
|
|
14448
|
+
}
|
|
14449
|
+
async setLowBalanceAutoTopup(input) {
|
|
14450
|
+
return this.client.request("/v1/sdk/billing/auto-topup/low-balance", input);
|
|
14451
|
+
}
|
|
14452
|
+
};
|
|
14453
|
+
var OpenMatesNotifications = class {
|
|
14454
|
+
client;
|
|
14455
|
+
constructor(client) {
|
|
14456
|
+
this.client = client;
|
|
14457
|
+
}
|
|
14458
|
+
async status() {
|
|
14459
|
+
return this.client.get("/v1/sdk/notifications/status");
|
|
14460
|
+
}
|
|
14461
|
+
async list(options = {}) {
|
|
14462
|
+
return this.client.get(withQuery("/v1/sdk/notifications", { limit: options.limit }));
|
|
14463
|
+
}
|
|
14464
|
+
};
|
|
14465
|
+
var OpenMatesReminders = class {
|
|
14466
|
+
client;
|
|
14467
|
+
constructor(client) {
|
|
14468
|
+
this.client = client;
|
|
14469
|
+
}
|
|
14470
|
+
async list() {
|
|
14471
|
+
return this.client.get("/v1/sdk/reminders");
|
|
14472
|
+
}
|
|
14473
|
+
async update(id, input) {
|
|
14474
|
+
return this.client.patch(`/v1/sdk/reminders/${encodeURIComponent(id)}`, input);
|
|
14475
|
+
}
|
|
14476
|
+
async delete(id, options) {
|
|
14477
|
+
requireConfirmed(options, "Deleting a reminder");
|
|
14478
|
+
return this.client.delete(`/v1/sdk/reminders/${encodeURIComponent(id)}`);
|
|
14479
|
+
}
|
|
14480
|
+
};
|
|
14481
|
+
var OpenMatesProjects = class {
|
|
14482
|
+
client;
|
|
14483
|
+
constructor(client) {
|
|
14484
|
+
this.client = client;
|
|
14485
|
+
}
|
|
14486
|
+
async listSources(projectId) {
|
|
14487
|
+
const response = await this.client.get(`/v1/projects/${encodeURIComponent(projectId)}/sources`);
|
|
14488
|
+
return response.sources ?? [];
|
|
14489
|
+
}
|
|
14490
|
+
async createSource(projectId, input) {
|
|
14491
|
+
const response = await this.client.request(`/v1/projects/${encodeURIComponent(projectId)}/sources`, input);
|
|
14492
|
+
if (!response.source) throw new OpenMatesApiError(500, { detail: "Project source response missing source" });
|
|
14493
|
+
return response.source;
|
|
14494
|
+
}
|
|
14495
|
+
};
|
|
14496
|
+
var OpenMatesTasks = class {
|
|
14497
|
+
client;
|
|
14498
|
+
constructor(client) {
|
|
14499
|
+
this.client = client;
|
|
14500
|
+
}
|
|
14501
|
+
async list(filters = {}) {
|
|
14502
|
+
const response = await this.client.get(withQuery("/v1/user-tasks", {
|
|
14503
|
+
status: filters.status,
|
|
14504
|
+
chat_id: filters.chatId,
|
|
14505
|
+
project_id: filters.projectId
|
|
14506
|
+
}));
|
|
14507
|
+
return response.tasks ?? [];
|
|
14508
|
+
}
|
|
14509
|
+
async create(input) {
|
|
14510
|
+
const response = await this.client.request("/v1/user-tasks", input);
|
|
14511
|
+
if (!response.task) throw new OpenMatesApiError(500, { detail: "User task response missing task" });
|
|
14512
|
+
return response.task;
|
|
14513
|
+
}
|
|
14514
|
+
async update(taskId, input) {
|
|
14515
|
+
const response = await this.client.patch(`/v1/user-tasks/${encodeURIComponent(taskId)}`, input);
|
|
14516
|
+
if (!response.task) throw new OpenMatesApiError(500, { detail: "User task response missing task" });
|
|
14517
|
+
return response.task;
|
|
14518
|
+
}
|
|
14519
|
+
async startAI(taskId, input) {
|
|
14520
|
+
const response = await this.client.request(`/v1/user-tasks/${encodeURIComponent(taskId)}/start-ai`, input);
|
|
14521
|
+
if (!response.task) throw new OpenMatesApiError(500, { detail: "User task response missing task" });
|
|
14522
|
+
return response.task;
|
|
14523
|
+
}
|
|
14524
|
+
};
|
|
14525
|
+
var OpenMatesPlans = class {
|
|
14526
|
+
client;
|
|
14527
|
+
constructor(client) {
|
|
14528
|
+
this.client = client;
|
|
14529
|
+
}
|
|
14530
|
+
async list(filters = {}) {
|
|
14531
|
+
const response = await this.client.get(withQuery("/v1/user-plans", {
|
|
14532
|
+
status: filters.status,
|
|
14533
|
+
chat_id: filters.chatId,
|
|
14534
|
+
project_id: filters.projectId,
|
|
14535
|
+
active_only: filters.activeOnly
|
|
14536
|
+
}));
|
|
14537
|
+
return response.plans ?? [];
|
|
14538
|
+
}
|
|
14539
|
+
async create(input) {
|
|
14540
|
+
const response = await this.client.request("/v1/user-plans", input);
|
|
14541
|
+
if (!response.plan) throw new OpenMatesApiError(500, { detail: "User plan response missing plan" });
|
|
14542
|
+
return response.plan;
|
|
14543
|
+
}
|
|
14544
|
+
async update(planId, input) {
|
|
14545
|
+
const response = await this.client.patch(`/v1/user-plans/${encodeURIComponent(planId)}`, input);
|
|
14546
|
+
if (!response.plan) throw new OpenMatesApiError(500, { detail: "User plan response missing plan" });
|
|
14547
|
+
return response.plan;
|
|
14548
|
+
}
|
|
14549
|
+
async activate(planId, input = {}) {
|
|
14550
|
+
const response = await this.client.request(`/v1/user-plans/${encodeURIComponent(planId)}/activate`, input);
|
|
14551
|
+
if (!response.plan) throw new OpenMatesApiError(500, { detail: "User plan response missing plan" });
|
|
14552
|
+
return response.plan.primary_chat_id || typeof input.chat_id !== "string" ? response.plan : { ...response.plan, primary_chat_id: input.chat_id };
|
|
14553
|
+
}
|
|
14554
|
+
async complete(planId, input = {}) {
|
|
14555
|
+
const response = await this.client.request(`/v1/user-plans/${encodeURIComponent(planId)}/complete`, input);
|
|
14556
|
+
if (!response.plan) throw new OpenMatesApiError(500, { detail: "User plan response missing plan" });
|
|
14557
|
+
return response.plan;
|
|
14558
|
+
}
|
|
14559
|
+
async createCriterion(planId, input) {
|
|
14560
|
+
const response = await this.client.request(`/v1/user-plans/${encodeURIComponent(planId)}/criteria`, input);
|
|
14561
|
+
if (!response.criterion) throw new OpenMatesApiError(500, { detail: "User plan criterion response missing criterion" });
|
|
14562
|
+
return response.criterion;
|
|
14563
|
+
}
|
|
14564
|
+
async createVerification(planId, input) {
|
|
14565
|
+
const response = await this.client.request(`/v1/user-plans/${encodeURIComponent(planId)}/verification`, input);
|
|
14566
|
+
if (!response.verification) throw new OpenMatesApiError(500, { detail: "User plan verification response missing verification" });
|
|
14567
|
+
return response.verification;
|
|
14568
|
+
}
|
|
14569
|
+
async addVerificationEvidence(planId, verificationId, input) {
|
|
14570
|
+
const response = await this.client.request(`/v1/user-plans/${encodeURIComponent(planId)}/verification/${encodeURIComponent(verificationId)}/evidence`, input);
|
|
14571
|
+
if (!response.verification) throw new OpenMatesApiError(500, { detail: "User plan verification response missing verification" });
|
|
14572
|
+
return response.verification;
|
|
14573
|
+
}
|
|
14574
|
+
};
|
|
14575
|
+
var OpenMatesWorkflows = class {
|
|
14576
|
+
client;
|
|
14577
|
+
constructor(client) {
|
|
14578
|
+
this.client = client;
|
|
14579
|
+
}
|
|
14580
|
+
async list() {
|
|
14581
|
+
const response = await this.client.get("/v1/workflows");
|
|
14582
|
+
return response.workflows ?? [];
|
|
14583
|
+
}
|
|
14584
|
+
async temporary() {
|
|
14585
|
+
const response = await this.client.get("/v1/workflows/temporary");
|
|
14586
|
+
return response.workflows ?? [];
|
|
14587
|
+
}
|
|
14588
|
+
async capabilities() {
|
|
14589
|
+
const response = await this.client.get("/v1/workflows/capabilities");
|
|
14590
|
+
return response.capabilities ?? [];
|
|
14591
|
+
}
|
|
14592
|
+
async validateYaml(source) {
|
|
14593
|
+
const response = await this.client.request("/v1/workflows/validate", { source });
|
|
14594
|
+
if (!response.validation) throw new OpenMatesApiError(500, { detail: "Workflow validation response missing validation" });
|
|
14595
|
+
return response.validation;
|
|
14596
|
+
}
|
|
14597
|
+
async createFromYaml(source) {
|
|
14598
|
+
const response = await this.client.request("/v1/workflows/yaml", { source });
|
|
14599
|
+
if (!response.workflow) throw new OpenMatesApiError(500, { detail: "Workflow YAML response missing workflow" });
|
|
14600
|
+
if (!response.validation) throw new OpenMatesApiError(500, { detail: "Workflow YAML response missing validation" });
|
|
14601
|
+
return { workflow: response.workflow, validation: response.validation };
|
|
14602
|
+
}
|
|
14603
|
+
async updateFromYaml(workflowId, source) {
|
|
14604
|
+
const response = await this.client.request(`/v1/workflows/${encodeURIComponent(workflowId)}/yaml`, { source });
|
|
14605
|
+
if (!response.workflow) throw new OpenMatesApiError(500, { detail: "Workflow YAML response missing workflow" });
|
|
14606
|
+
if (!response.validation) throw new OpenMatesApiError(500, { detail: "Workflow YAML response missing validation" });
|
|
14607
|
+
return { workflow: response.workflow, validation: response.validation };
|
|
14608
|
+
}
|
|
14609
|
+
async startInput(params) {
|
|
14610
|
+
const response = await this.client.request("/v1/workflows/input", {
|
|
14611
|
+
...params.text !== void 0 ? { text: params.text } : {},
|
|
14612
|
+
input_type: params.inputType ?? "text",
|
|
14613
|
+
...params.audioRef !== void 0 ? { audio_ref: params.audioRef } : {},
|
|
14614
|
+
...params.selectedWorkflowId !== void 0 ? { selected_workflow_id: params.selectedWorkflowId } : {},
|
|
14615
|
+
...params.selectedProjectId !== void 0 ? { selected_project_id: params.selectedProjectId } : {}
|
|
14616
|
+
});
|
|
14617
|
+
if (!response.session) throw new OpenMatesApiError(500, { detail: "Workflow input response missing session" });
|
|
14618
|
+
return response.session;
|
|
14619
|
+
}
|
|
14620
|
+
async inputSession(sessionId) {
|
|
14621
|
+
const response = await this.client.get(`/v1/workflows/input/${encodeURIComponent(sessionId)}`);
|
|
14622
|
+
if (!response.session) throw new OpenMatesApiError(500, { detail: "Workflow input response missing session" });
|
|
14623
|
+
return response.session;
|
|
14624
|
+
}
|
|
14625
|
+
async inputEvents(sessionId, afterEventId = 0) {
|
|
14626
|
+
const response = await this.client.get(`/v1/workflows/input/${encodeURIComponent(sessionId)}/events?after_event_id=${encodeURIComponent(String(afterEventId))}`);
|
|
14627
|
+
return response.events ?? [];
|
|
14628
|
+
}
|
|
14629
|
+
async followUpInput(sessionId, text) {
|
|
14630
|
+
const response = await this.client.request(`/v1/workflows/input/${encodeURIComponent(sessionId)}/follow-up`, { text });
|
|
14631
|
+
if (!response.session) throw new OpenMatesApiError(500, { detail: "Workflow input response missing session" });
|
|
14632
|
+
return response.session;
|
|
14633
|
+
}
|
|
14634
|
+
async stopInput(sessionId) {
|
|
14635
|
+
const response = await this.client.request(`/v1/workflows/input/${encodeURIComponent(sessionId)}/stop`, {});
|
|
14636
|
+
if (!response.session) throw new OpenMatesApiError(500, { detail: "Workflow input response missing session" });
|
|
14637
|
+
return response.session;
|
|
14638
|
+
}
|
|
14639
|
+
async undoInput(sessionId) {
|
|
14640
|
+
const response = await this.client.request(`/v1/workflows/input/${encodeURIComponent(sessionId)}/undo`, {});
|
|
14641
|
+
if (!response.session) throw new OpenMatesApiError(500, { detail: "Workflow input response missing session" });
|
|
14642
|
+
return response.session;
|
|
14643
|
+
}
|
|
14644
|
+
async get(workflowId) {
|
|
14645
|
+
const response = await this.client.get(`/v1/workflows/${encodeURIComponent(workflowId)}`);
|
|
14646
|
+
if (!response.workflow) throw new OpenMatesApiError(500, { detail: "Workflow response missing workflow" });
|
|
14647
|
+
return response.workflow;
|
|
14648
|
+
}
|
|
14649
|
+
async create(params) {
|
|
14650
|
+
const response = await this.client.request("/v1/workflows", {
|
|
14651
|
+
title: params.title,
|
|
14652
|
+
...params.description !== void 0 ? { description: params.description } : {},
|
|
14653
|
+
graph: params.graph,
|
|
14654
|
+
enabled: params.enabled ?? false,
|
|
14655
|
+
run_content_retention: params.runContentRetention ?? "last_5",
|
|
14656
|
+
...params.lifecycle ? { lifecycle: params.lifecycle } : {},
|
|
14657
|
+
...params.source ? { source: params.source } : {},
|
|
14658
|
+
...params.sourceChatId !== void 0 ? { source_chat_id: params.sourceChatId } : {},
|
|
14659
|
+
...params.createdByAssistant !== void 0 ? { created_by_assistant: params.createdByAssistant } : {},
|
|
14660
|
+
...params.autoDeleteAt !== void 0 ? { auto_delete_at: params.autoDeleteAt } : {}
|
|
14661
|
+
});
|
|
14662
|
+
if (!response.workflow) throw new OpenMatesApiError(500, { detail: "Workflow response missing workflow" });
|
|
14663
|
+
return response.workflow;
|
|
14664
|
+
}
|
|
14665
|
+
async update(workflowId, params) {
|
|
14666
|
+
const payload = {};
|
|
14667
|
+
if (params.title !== void 0) payload.title = params.title;
|
|
14668
|
+
if (params.description !== void 0) payload.description = params.description;
|
|
14669
|
+
if (params.graph !== void 0) payload.graph = params.graph;
|
|
14670
|
+
if (params.enabled !== void 0) payload.enabled = params.enabled;
|
|
14671
|
+
if (params.runContentRetention !== void 0) payload.run_content_retention = params.runContentRetention;
|
|
14672
|
+
const response = await this.client.patch(`/v1/workflows/${encodeURIComponent(workflowId)}`, payload);
|
|
14673
|
+
if (!response.workflow) throw new OpenMatesApiError(500, { detail: "Workflow response missing workflow" });
|
|
14674
|
+
return response.workflow;
|
|
14675
|
+
}
|
|
14676
|
+
async enable(workflowId) {
|
|
14677
|
+
const response = await this.client.request(`/v1/workflows/${encodeURIComponent(workflowId)}/enable`, {});
|
|
14678
|
+
if (!response.workflow) throw new OpenMatesApiError(500, { detail: "Workflow response missing workflow" });
|
|
14679
|
+
return response.workflow;
|
|
14680
|
+
}
|
|
14681
|
+
async disable(workflowId) {
|
|
14682
|
+
const response = await this.client.request(`/v1/workflows/${encodeURIComponent(workflowId)}/disable`, {});
|
|
14683
|
+
if (!response.workflow) throw new OpenMatesApiError(500, { detail: "Workflow response missing workflow" });
|
|
14684
|
+
return response.workflow;
|
|
14685
|
+
}
|
|
14686
|
+
async delete(workflowId, options = {}) {
|
|
14687
|
+
requireConfirmed(options, "Deleting a workflow");
|
|
14688
|
+
return this.client.delete(`/v1/workflows/${encodeURIComponent(workflowId)}`);
|
|
14689
|
+
}
|
|
14690
|
+
async keep(workflowId) {
|
|
14691
|
+
const response = await this.client.request(`/v1/workflows/${encodeURIComponent(workflowId)}/keep`, {});
|
|
14692
|
+
if (!response.workflow) throw new OpenMatesApiError(500, { detail: "Workflow response missing workflow" });
|
|
14693
|
+
return response.workflow;
|
|
14694
|
+
}
|
|
14695
|
+
async run(workflowId, params) {
|
|
14696
|
+
if (!params.idempotencyKey.trim()) throw new OpenMatesConfigError("Workflow run requires a stable idempotencyKey");
|
|
14697
|
+
const response = await this.client.request(`/v1/workflows/${encodeURIComponent(workflowId)}/run`, {
|
|
14698
|
+
mode: params.mode ?? "manual",
|
|
14699
|
+
input: params.input ?? {}
|
|
14700
|
+
}, void 0, { "Idempotency-Key": params.idempotencyKey });
|
|
14701
|
+
if (!response.run) throw new OpenMatesApiError(500, { detail: "Workflow response missing run" });
|
|
14702
|
+
return response.run;
|
|
14703
|
+
}
|
|
14704
|
+
async runs(workflowId) {
|
|
14705
|
+
const response = await this.client.get(`/v1/workflows/${encodeURIComponent(workflowId)}/runs`);
|
|
14706
|
+
return response.runs ?? [];
|
|
14707
|
+
}
|
|
14708
|
+
async runDetail(workflowId, runId) {
|
|
14709
|
+
const response = await this.client.get(`/v1/workflows/${encodeURIComponent(workflowId)}/runs/${encodeURIComponent(runId)}`);
|
|
14710
|
+
if (!response.run) throw new OpenMatesApiError(500, { detail: "Workflow response missing run" });
|
|
14711
|
+
return response.run;
|
|
14712
|
+
}
|
|
14713
|
+
async cancelRun(workflowId, runId) {
|
|
14714
|
+
const result = await this.client.request(
|
|
14715
|
+
`/v1/workflows/${encodeURIComponent(workflowId)}/runs/${encodeURIComponent(runId)}/cancel`,
|
|
14716
|
+
{}
|
|
14717
|
+
);
|
|
14718
|
+
if (result.status !== "cancellation_requested" && result.status !== "cancelled") {
|
|
14719
|
+
throw new OpenMatesApiError(500, { detail: "Workflow response has invalid cancellation status" });
|
|
14720
|
+
}
|
|
14721
|
+
return result;
|
|
14722
|
+
}
|
|
14723
|
+
async respond(workflowId, runId, stepId, input) {
|
|
14724
|
+
const response = await this.client.request(
|
|
14725
|
+
`/v1/workflows/${encodeURIComponent(workflowId)}/runs/${encodeURIComponent(runId)}/respond`,
|
|
14726
|
+
{ step_id: stepId, input }
|
|
14727
|
+
);
|
|
14728
|
+
if (!response.run) throw new OpenMatesApiError(500, { detail: "Workflow response missing run" });
|
|
14729
|
+
return response.run;
|
|
14730
|
+
}
|
|
14731
|
+
async upsertTemplateProjection(workflowId, params) {
|
|
14732
|
+
return this.client.put(`/v1/workflows/${encodeURIComponent(workflowId)}/template-projection`, {
|
|
14733
|
+
template_id: params.templateId,
|
|
14734
|
+
source_version: params.sourceVersion,
|
|
14735
|
+
ciphertext: params.ciphertext,
|
|
14736
|
+
ciphertext_checksum: params.ciphertextChecksum,
|
|
14737
|
+
owner_wrapped_key: params.ownerWrappedKey,
|
|
14738
|
+
projection_schema_version: params.projectionSchemaVersion
|
|
14739
|
+
});
|
|
14740
|
+
}
|
|
14741
|
+
async getPublicTemplateProjection(templateId) {
|
|
14742
|
+
return this.client.getPublic(
|
|
14743
|
+
`/v1/workflows/template-projections/${encodeURIComponent(templateId)}`
|
|
14744
|
+
);
|
|
14745
|
+
}
|
|
14746
|
+
async revokeTemplateProjection(workflowId) {
|
|
14747
|
+
return this.client.request(
|
|
14748
|
+
`/v1/workflows/${encodeURIComponent(workflowId)}/template-projection/revoke`,
|
|
14749
|
+
{}
|
|
14750
|
+
);
|
|
14751
|
+
}
|
|
14752
|
+
async unrevokeTemplateProjection(workflowId) {
|
|
14753
|
+
return this.client.request(
|
|
14754
|
+
`/v1/workflows/${encodeURIComponent(workflowId)}/template-projection/unrevoke`,
|
|
14755
|
+
{}
|
|
14756
|
+
);
|
|
14757
|
+
}
|
|
14758
|
+
async completeImportedBinding(workflowId, params) {
|
|
14759
|
+
return this.client.request(
|
|
14760
|
+
`/v1/workflows/${encodeURIComponent(workflowId)}/binding-requirements/complete`,
|
|
14761
|
+
{ type: params.type, node_id: params.nodeId }
|
|
14762
|
+
);
|
|
14763
|
+
}
|
|
14764
|
+
async createTemplateShortUrl(params) {
|
|
14765
|
+
return this.client.request("/v1/share/short-url", {
|
|
14766
|
+
token: params.token,
|
|
14767
|
+
encrypted_url: params.encryptedUrl,
|
|
14768
|
+
content_type: "workflow_template",
|
|
14769
|
+
content_id: params.templateId,
|
|
14770
|
+
password_protected: params.passwordProtected ?? false,
|
|
14771
|
+
...params.ttlSeconds !== void 0 ? { ttl_seconds: params.ttlSeconds } : {}
|
|
14772
|
+
});
|
|
14773
|
+
}
|
|
14774
|
+
async revokeShortUrl(token) {
|
|
14775
|
+
return this.client.delete(`/v1/share/short-url/${encodeURIComponent(token)}`);
|
|
14776
|
+
}
|
|
14777
|
+
async importTemplate(payload) {
|
|
14778
|
+
const response = await this.client.request("/v1/workflows/template-import", payload);
|
|
14779
|
+
if (!response.workflow) throw new OpenMatesApiError(500, { detail: "Workflow template import response missing workflow" });
|
|
14780
|
+
return response.workflow;
|
|
14781
|
+
}
|
|
14782
|
+
};
|
|
14783
|
+
var OpenMatesDocs = class {
|
|
14784
|
+
client;
|
|
14785
|
+
constructor(client) {
|
|
14786
|
+
this.client = client;
|
|
14787
|
+
}
|
|
14788
|
+
async list() {
|
|
14789
|
+
return this.client.get("/v1/sdk/docs");
|
|
14790
|
+
}
|
|
14791
|
+
async search(query) {
|
|
14792
|
+
return this.client.get(withQuery("/v1/sdk/docs/search", { q: query }));
|
|
14793
|
+
}
|
|
14794
|
+
async show(slug) {
|
|
14795
|
+
return this.client.get(`/v1/sdk/docs/${encodeURIComponent(slug)}`);
|
|
14796
|
+
}
|
|
14797
|
+
async download(slug) {
|
|
14798
|
+
return this.client.get(`/v1/sdk/docs/${encodeURIComponent(slug)}/download`);
|
|
14799
|
+
}
|
|
14800
|
+
};
|
|
14801
|
+
var OpenMatesEmbeds = class {
|
|
14802
|
+
preview;
|
|
14803
|
+
client;
|
|
14804
|
+
constructor(client) {
|
|
14805
|
+
this.client = client;
|
|
14806
|
+
this.preview = new OpenMatesEmbedPreview(client);
|
|
14807
|
+
}
|
|
14808
|
+
async show(embedId) {
|
|
14809
|
+
return this.client.get(`/v1/sdk/embeds/${encodeURIComponent(embedId)}`);
|
|
14810
|
+
}
|
|
14811
|
+
async share(embedId, options = {}) {
|
|
14812
|
+
const shown = await this.show(embedId);
|
|
14813
|
+
const keys = Array.isArray(shown.embed_keys) ? shown.embed_keys : [];
|
|
14814
|
+
const embedKey = await this.client.resolveEmbedKeyForShare(keys, embedId);
|
|
14815
|
+
if (!embedKey) throw new OpenMatesConfigError("Unable to resolve embed key for share link");
|
|
14816
|
+
const blob = await generateEmbedShareBlob(embedId, embedKey, options.expires ?? 0, options.password);
|
|
14817
|
+
return { url: buildEmbedShareUrl(this.client.webOrigin(), embedId, blob) };
|
|
14818
|
+
}
|
|
14819
|
+
async versions(embedId) {
|
|
14820
|
+
return this.client.get(`/v1/sdk/embeds/${encodeURIComponent(embedId)}/versions`);
|
|
14821
|
+
}
|
|
14822
|
+
async version(embedId, version) {
|
|
14823
|
+
return this.client.get(`/v1/sdk/embeds/${encodeURIComponent(embedId)}/versions/${version}`);
|
|
14824
|
+
}
|
|
14825
|
+
async restoreVersion(embedId, version, options) {
|
|
14826
|
+
requireConfirmed(options, "Restoring an embed version");
|
|
14827
|
+
return this.client.request(`/v1/sdk/embeds/${encodeURIComponent(embedId)}/versions/${version}/restore`);
|
|
14828
|
+
}
|
|
14829
|
+
};
|
|
14830
|
+
var OpenMatesEmbedPreview = class {
|
|
14831
|
+
client;
|
|
14832
|
+
constructor(client) {
|
|
14833
|
+
this.client = client;
|
|
14834
|
+
}
|
|
14835
|
+
async start(embedId, options) {
|
|
14836
|
+
const response = await this.client.request(
|
|
14837
|
+
`/v1/applications/${encodeURIComponent(embedId)}/preview/start`,
|
|
14838
|
+
{
|
|
14839
|
+
chat_id: options.chatId,
|
|
14840
|
+
...options.sharedContext ? { shared_context: options.sharedContext } : {},
|
|
14841
|
+
...options.requestedRuntime ? { requested_runtime: options.requestedRuntime } : {},
|
|
14842
|
+
...options.sourceMessageId ? { source_message_id: options.sourceMessageId } : {}
|
|
14843
|
+
}
|
|
14844
|
+
);
|
|
14845
|
+
return options.wait === true ? this.waitForRunning(response.session_id, options.timeoutMs ?? 12e4) : response;
|
|
14846
|
+
}
|
|
14847
|
+
async status(sessionId) {
|
|
14848
|
+
return this.client.get(`/v1/applications/preview/${encodeURIComponent(sessionId)}`);
|
|
14849
|
+
}
|
|
14850
|
+
async open(sessionId) {
|
|
14851
|
+
return this.client.request(`/v1/applications/preview/${encodeURIComponent(sessionId)}/open`, {});
|
|
14852
|
+
}
|
|
14853
|
+
async stop(sessionId) {
|
|
14854
|
+
return this.client.request(`/v1/applications/preview/${encodeURIComponent(sessionId)}/stop`, {});
|
|
14855
|
+
}
|
|
14856
|
+
async waitForRunning(sessionId, timeoutMs) {
|
|
14857
|
+
const deadline = Date.now() + timeoutMs;
|
|
14858
|
+
while (Date.now() < deadline) {
|
|
14859
|
+
const status = await this.status(sessionId);
|
|
14860
|
+
if (["running", "failed", "timeout", "cancelled", "stopped"].includes(status.status)) {
|
|
14861
|
+
return status;
|
|
14862
|
+
}
|
|
14863
|
+
await new Promise((resolve7) => setTimeout(resolve7, 1e3));
|
|
14864
|
+
}
|
|
14865
|
+
throw new OpenMatesApiError(408, { detail: "Application preview did not reach running state before timeout" });
|
|
14866
|
+
}
|
|
14867
|
+
};
|
|
14868
|
+
var OpenMatesConnectedAccounts = class {
|
|
14869
|
+
client;
|
|
14870
|
+
constructor(client) {
|
|
14871
|
+
this.client = client;
|
|
14872
|
+
}
|
|
14873
|
+
async import(input) {
|
|
14874
|
+
const payload = await decryptConnectedAccountCliTransferPayload(input.payload, input.passcode);
|
|
14875
|
+
const account = await this.client.get("/v1/sdk/account");
|
|
14876
|
+
const userId = typeof account.id === "string" ? account.id : "";
|
|
14877
|
+
if (!userId) {
|
|
14878
|
+
throw new OpenMatesConfigError("Could not resolve current user id for connected account import");
|
|
14879
|
+
}
|
|
14880
|
+
const row = await buildEncryptedConnectedAccountImportRow({
|
|
14881
|
+
payload,
|
|
14882
|
+
userId,
|
|
14883
|
+
masterKey: await this.client.masterKey()
|
|
14884
|
+
});
|
|
14885
|
+
return this.client.request("/v1/sdk/connected-accounts/import", { row });
|
|
14886
|
+
}
|
|
14887
|
+
};
|
|
14888
|
+
var OpenMatesLearningMode = class {
|
|
14889
|
+
client;
|
|
14890
|
+
constructor(client) {
|
|
14891
|
+
this.client = client;
|
|
14892
|
+
}
|
|
14893
|
+
async status() {
|
|
14894
|
+
return this.client.get("/v1/sdk/learning-mode");
|
|
14895
|
+
}
|
|
14896
|
+
async enable(input) {
|
|
14897
|
+
return this.client.request("/v1/sdk/learning-mode/enable", { age_group: input.ageGroup, passcode: input.passcode });
|
|
14898
|
+
}
|
|
14899
|
+
async disable(passcode) {
|
|
14900
|
+
return this.client.request("/v1/sdk/learning-mode/disable", { passcode });
|
|
14901
|
+
}
|
|
14902
|
+
};
|
|
14903
|
+
var OpenMatesInspirations = class {
|
|
14904
|
+
client;
|
|
14905
|
+
constructor(client) {
|
|
14906
|
+
this.client = client;
|
|
14907
|
+
}
|
|
14908
|
+
async list(options = {}) {
|
|
14909
|
+
return this.client.get(withQuery("/v1/sdk/inspirations", { lang: options.language }));
|
|
14910
|
+
}
|
|
14911
|
+
};
|
|
14912
|
+
var OpenMatesNewChatSuggestions = class {
|
|
14913
|
+
client;
|
|
14914
|
+
constructor(client) {
|
|
14915
|
+
this.client = client;
|
|
14916
|
+
}
|
|
14917
|
+
async list(options = {}) {
|
|
14918
|
+
return this.client.get(withQuery("/v1/sdk/new-chat-suggestions", { limit: options.limit ?? 10 }));
|
|
14919
|
+
}
|
|
14920
|
+
};
|
|
14921
|
+
var OpenMatesFeedback = class {
|
|
14922
|
+
client;
|
|
14923
|
+
constructor(client) {
|
|
14924
|
+
this.client = client;
|
|
14925
|
+
}
|
|
14926
|
+
async assistantResponse(input) {
|
|
14927
|
+
return this.client.request("/v1/sdk/feedback/assistant-response", input);
|
|
14928
|
+
}
|
|
14929
|
+
};
|
|
14930
|
+
var OpenMatesBenchmark = class {
|
|
14931
|
+
client;
|
|
14932
|
+
constructor(client) {
|
|
14933
|
+
this.client = client;
|
|
14934
|
+
}
|
|
14935
|
+
async run(input) {
|
|
14936
|
+
return this.client.request("/v1/sdk/benchmark/run", input);
|
|
14937
|
+
}
|
|
14938
|
+
async estimate(input) {
|
|
14939
|
+
return this.client.request("/v1/sdk/benchmark/estimate", input);
|
|
14940
|
+
}
|
|
14941
|
+
};
|
|
14942
|
+
|
|
14943
|
+
// src/cli.ts
|
|
14944
|
+
import { createInterface as createInterface5 } from "readline/promises";
|
|
14945
|
+
import { stdin as stdin3, stdout as stdout2 } from "process";
|
|
14946
|
+
import { readFileSync as readFileSync10, realpathSync, writeFileSync as writeFileSync7 } from "fs";
|
|
14947
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
14948
|
+
import { basename as basename3, dirname as dirname4 } from "path";
|
|
14949
|
+
import { randomUUID as randomUUID8 } from "crypto";
|
|
14950
|
+
import WebSocket2 from "ws";
|
|
14951
|
+
|
|
13593
14952
|
// ../secret-scanner/src/registry.ts
|
|
13594
14953
|
import { createRequire as createRequire2 } from "module";
|
|
13595
14954
|
|
|
@@ -14303,10 +15662,10 @@ var OutputRedactor = class {
|
|
|
14303
15662
|
};
|
|
14304
15663
|
|
|
14305
15664
|
// src/fileEmbed.ts
|
|
14306
|
-
import { readFileSync as
|
|
15665
|
+
import { readFileSync as readFileSync5, statSync, existsSync as existsSync6 } from "fs";
|
|
14307
15666
|
import { basename, extname, resolve as resolve2 } from "path";
|
|
14308
|
-
import { homedir as
|
|
14309
|
-
import { createHash as
|
|
15667
|
+
import { homedir as homedir5 } from "os";
|
|
15668
|
+
import { createHash as createHash7 } from "crypto";
|
|
14310
15669
|
var MAX_PER_FILE_SIZE = 100 * 1024 * 1024;
|
|
14311
15670
|
var BLOCKED_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
14312
15671
|
".pem",
|
|
@@ -14510,7 +15869,7 @@ function processEnvFileZeroKnowledge(content) {
|
|
|
14510
15869
|
}
|
|
14511
15870
|
function resolvePath(filePath) {
|
|
14512
15871
|
if (filePath.startsWith("~/")) {
|
|
14513
|
-
return resolve2(
|
|
15872
|
+
return resolve2(homedir5(), filePath.slice(2));
|
|
14514
15873
|
}
|
|
14515
15874
|
return resolve2(filePath);
|
|
14516
15875
|
}
|
|
@@ -14522,7 +15881,7 @@ function processFiles(filePaths, redactor) {
|
|
|
14522
15881
|
const resolvedPath = resolvePath(rawPath);
|
|
14523
15882
|
const filename = basename(resolvedPath);
|
|
14524
15883
|
const ext = getExt(filename);
|
|
14525
|
-
if (!
|
|
15884
|
+
if (!existsSync6(resolvedPath)) {
|
|
14526
15885
|
errors.push({ path: rawPath, error: "File not found" });
|
|
14527
15886
|
continue;
|
|
14528
15887
|
}
|
|
@@ -14588,7 +15947,7 @@ function processFiles(filePaths, redactor) {
|
|
|
14588
15947
|
}
|
|
14589
15948
|
function processCodeFile(filePath, filename, redactor) {
|
|
14590
15949
|
try {
|
|
14591
|
-
let content =
|
|
15950
|
+
let content = readFileSync5(filePath, "utf-8");
|
|
14592
15951
|
let secretsRedacted = false;
|
|
14593
15952
|
let zeroKnowledge = false;
|
|
14594
15953
|
if (isEnvFile(filename)) {
|
|
@@ -14616,7 +15975,7 @@ function processCodeFile(filePath, filename, redactor) {
|
|
|
14616
15975
|
line_count: lineCount
|
|
14617
15976
|
});
|
|
14618
15977
|
const textPreview = `${filename} (${language}, ${lineCount} lines)`;
|
|
14619
|
-
const contentHash =
|
|
15978
|
+
const contentHash = createHash7("sha256").update(content).digest("hex");
|
|
14620
15979
|
const embed = {
|
|
14621
15980
|
embedId,
|
|
14622
15981
|
embedRef,
|
|
@@ -16171,12 +17530,12 @@ function formatTs(ts) {
|
|
|
16171
17530
|
|
|
16172
17531
|
// src/server.ts
|
|
16173
17532
|
import { execFileSync as execFileSync2, execSync, spawn as nodeSpawn, spawnSync } from "child_process";
|
|
16174
|
-
import { createHash as
|
|
16175
|
-
import { chmodSync as
|
|
17533
|
+
import { createHash as createHash8, randomBytes as randomBytes4 } from "crypto";
|
|
17534
|
+
import { chmodSync as chmodSync3, closeSync, copyFileSync, cpSync, existsSync as existsSync7, mkdirSync as mkdirSync4, mkdtempSync, openSync, readFileSync as readFileSync6, readSync, readdirSync, rmSync as rmSync3, writeFileSync as writeFileSync4 } from "fs";
|
|
16176
17535
|
import { createInterface as createInterface3 } from "readline";
|
|
16177
17536
|
import { createInterface as createPromptInterface } from "readline/promises";
|
|
16178
|
-
import { homedir as
|
|
16179
|
-
import { dirname, join as
|
|
17537
|
+
import { homedir as homedir6 } from "os";
|
|
17538
|
+
import { dirname as dirname2, join as join4, resolve as resolve3 } from "path";
|
|
16180
17539
|
|
|
16181
17540
|
// src/branding.ts
|
|
16182
17541
|
var OPENMATES_WORDMARK = "OPENMATES";
|
|
@@ -16446,19 +17805,19 @@ function planContinuousUpdateService(input) {
|
|
|
16446
17805
|
}
|
|
16447
17806
|
|
|
16448
17807
|
// src/server.ts
|
|
16449
|
-
var SOURCE_COMPOSE_FILE =
|
|
17808
|
+
var SOURCE_COMPOSE_FILE = join4("backend", "core", "docker-compose.yml");
|
|
16450
17809
|
var ROLE_IMAGE_COMPOSE_FILES = {
|
|
16451
|
-
core:
|
|
16452
|
-
upload:
|
|
16453
|
-
preview:
|
|
17810
|
+
core: join4("backend", "core", "docker-compose.selfhost.yml"),
|
|
17811
|
+
upload: join4("backend", "upload", "docker-compose.yml"),
|
|
17812
|
+
preview: join4("backend", "preview", "docker-compose.preview.yml")
|
|
16454
17813
|
};
|
|
16455
17814
|
var ROLE_TEMPLATE_FILES = {
|
|
16456
|
-
core:
|
|
16457
|
-
upload:
|
|
16458
|
-
preview:
|
|
17815
|
+
core: join4("core", "docker-compose.selfhost.yml"),
|
|
17816
|
+
upload: join4("upload", "docker-compose.yml"),
|
|
17817
|
+
preview: join4("preview", "docker-compose.preview.yml")
|
|
16459
17818
|
};
|
|
16460
|
-
var COMPOSE_OVERRIDE =
|
|
16461
|
-
var DEFAULT_INSTALL_PATH =
|
|
17819
|
+
var COMPOSE_OVERRIDE = join4("backend", "core", "docker-compose.override.yml");
|
|
17820
|
+
var DEFAULT_INSTALL_PATH = join4(homedir6(), "openmates");
|
|
16462
17821
|
var REPO_URL = "https://github.com/glowingkitty/OpenMates.git";
|
|
16463
17822
|
var DEV_BRANCH = "dev";
|
|
16464
17823
|
var MAIN_BRANCH = "main";
|
|
@@ -16472,8 +17831,8 @@ var IMAGE_CHANNEL_TAGS = {
|
|
|
16472
17831
|
main: MAIN_BRANCH,
|
|
16473
17832
|
dev: DEV_BRANCH
|
|
16474
17833
|
};
|
|
16475
|
-
var BACKEND_CONFIG_FILE =
|
|
16476
|
-
var IMAGE_RUNTIME_CONFIG_FILE =
|
|
17834
|
+
var BACKEND_CONFIG_FILE = join4("backend", "config", "backend_config.yml");
|
|
17835
|
+
var IMAGE_RUNTIME_CONFIG_FILE = join4("config", "backend_config.yml");
|
|
16477
17836
|
var LOCAL_AI_MODELS_FILE = "local-ai-models.yml";
|
|
16478
17837
|
var OFF_BY_DEFAULT_FEATURES = /* @__PURE__ */ new Map([
|
|
16479
17838
|
["embed:code:application", "Application previews are still unstable"],
|
|
@@ -16613,7 +17972,7 @@ function loadConfigForInstallPath(installPath) {
|
|
|
16613
17972
|
}
|
|
16614
17973
|
function getInstallMode(installPath, config = loadConfigForInstallPath(installPath)) {
|
|
16615
17974
|
if (config?.installMode) return config.installMode;
|
|
16616
|
-
if (Object.values(ROLE_IMAGE_COMPOSE_FILES).some((composeFile) =>
|
|
17975
|
+
if (Object.values(ROLE_IMAGE_COMPOSE_FILES).some((composeFile) => existsSync7(join4(installPath, composeFile)))) return "image";
|
|
16617
17976
|
return "source";
|
|
16618
17977
|
}
|
|
16619
17978
|
function getServerRole(flags, config) {
|
|
@@ -16698,24 +18057,24 @@ function featureKind(featureId) {
|
|
|
16698
18057
|
function composeArgs(installPath, withOverrides, installMode = getInstallMode(installPath), role = "core") {
|
|
16699
18058
|
const composeFile = installMode === "image" ? ROLE_IMAGE_COMPOSE_FILES[role] : SOURCE_COMPOSE_FILE;
|
|
16700
18059
|
const args = ["compose", "--env-file", ".env", "-f", composeFile];
|
|
16701
|
-
if (withOverrides &&
|
|
18060
|
+
if (withOverrides && existsSync7(join4(installPath, COMPOSE_OVERRIDE))) {
|
|
16702
18061
|
args.push("-f", COMPOSE_OVERRIDE);
|
|
16703
18062
|
}
|
|
16704
18063
|
return args;
|
|
16705
18064
|
}
|
|
16706
18065
|
function ensureGitWorkDirEnv(installPath) {
|
|
16707
|
-
const envPath =
|
|
16708
|
-
if (!
|
|
16709
|
-
const content =
|
|
18066
|
+
const envPath = join4(installPath, ".env");
|
|
18067
|
+
if (!existsSync7(envPath)) return;
|
|
18068
|
+
const content = readFileSync6(envPath, "utf-8");
|
|
16710
18069
|
const lineRegex = /^GIT_WORK_DIR=.*$/m;
|
|
16711
18070
|
const value = `GIT_WORK_DIR=${installPath}`;
|
|
16712
18071
|
if (lineRegex.test(content)) {
|
|
16713
18072
|
const next = content.replace(lineRegex, value);
|
|
16714
|
-
if (next !== content)
|
|
18073
|
+
if (next !== content) writeFileSync4(envPath, next);
|
|
16715
18074
|
return;
|
|
16716
18075
|
}
|
|
16717
18076
|
const separator2 = content.endsWith("\n") ? "" : "\n";
|
|
16718
|
-
|
|
18077
|
+
writeFileSync4(envPath, `${content}${separator2}${value}
|
|
16719
18078
|
`);
|
|
16720
18079
|
}
|
|
16721
18080
|
function requireDocker() {
|
|
@@ -16736,7 +18095,7 @@ function requireGit() {
|
|
|
16736
18095
|
}
|
|
16737
18096
|
function getPackageVersion() {
|
|
16738
18097
|
try {
|
|
16739
|
-
const packageJson = JSON.parse(
|
|
18098
|
+
const packageJson = JSON.parse(readFileSync6(new URL("../package.json", import.meta.url), "utf-8"));
|
|
16740
18099
|
return packageJson.version ?? "";
|
|
16741
18100
|
} catch {
|
|
16742
18101
|
return "";
|
|
@@ -16789,10 +18148,10 @@ function resolveTargetImageTag(flags, currentTag, packageVersion) {
|
|
|
16789
18148
|
return { tag: getDefaultImageTagForVersion(packageVersion) };
|
|
16790
18149
|
}
|
|
16791
18150
|
function randomHex(bytes) {
|
|
16792
|
-
return
|
|
18151
|
+
return randomBytes4(bytes).toString("hex");
|
|
16793
18152
|
}
|
|
16794
18153
|
function generateInviteCode() {
|
|
16795
|
-
const digits = Array.from(
|
|
18154
|
+
const digits = Array.from(randomBytes4(12), (byte) => String(byte % 10)).join("");
|
|
16796
18155
|
return `${digits.slice(0, 4)}-${digits.slice(4, 8)}-${digits.slice(8, 12)}`;
|
|
16797
18156
|
}
|
|
16798
18157
|
function getEnvVar(content, name) {
|
|
@@ -16829,38 +18188,38 @@ async function fetchText(url) {
|
|
|
16829
18188
|
return response.text();
|
|
16830
18189
|
}
|
|
16831
18190
|
function packagedTemplatePath(role) {
|
|
16832
|
-
return
|
|
18191
|
+
return join4(dirname2(new URL(import.meta.url).pathname), "..", "templates", ROLE_TEMPLATE_FILES[role]);
|
|
16833
18192
|
}
|
|
16834
18193
|
function packagedCaddyTemplatePath(role) {
|
|
16835
|
-
return
|
|
18194
|
+
return join4(dirname2(new URL(import.meta.url).pathname), "..", "templates", "caddy", role, "Caddyfile");
|
|
16836
18195
|
}
|
|
16837
18196
|
function fileHash(path) {
|
|
16838
|
-
if (!
|
|
16839
|
-
return
|
|
18197
|
+
if (!existsSync7(path)) return null;
|
|
18198
|
+
return createHash8("sha256").update(readFileSync6(path)).digest("hex");
|
|
16840
18199
|
}
|
|
16841
18200
|
async function loadSelfHostComposeTemplate(templateRef, role) {
|
|
16842
18201
|
const templateDir = process.env.OPENMATES_SELFHOST_TEMPLATE_DIR;
|
|
16843
18202
|
if (templateDir) {
|
|
16844
|
-
return
|
|
18203
|
+
return readFileSync6(join4(resolve3(templateDir), ROLE_TEMPLATE_FILES[role]), "utf-8");
|
|
16845
18204
|
}
|
|
16846
18205
|
const overrideUrl = process.env.OPENMATES_SELFHOST_COMPOSE_URL;
|
|
16847
18206
|
if (overrideUrl) {
|
|
16848
18207
|
return fetchText(overrideUrl);
|
|
16849
18208
|
}
|
|
16850
18209
|
const packaged = packagedTemplatePath(role);
|
|
16851
|
-
if (
|
|
18210
|
+
if (existsSync7(packaged)) return readFileSync6(packaged, "utf-8");
|
|
16852
18211
|
return fetchText(`https://raw.githubusercontent.com/glowingkitty/OpenMates/${templateRef}/${ROLE_IMAGE_COMPOSE_FILES[role]}`);
|
|
16853
18212
|
}
|
|
16854
18213
|
async function writeImageModeRuntimeFiles(installPath, imageTag, role) {
|
|
16855
|
-
const roleDir =
|
|
16856
|
-
const vaultConfigDir =
|
|
16857
|
-
|
|
16858
|
-
|
|
16859
|
-
|
|
16860
|
-
|
|
18214
|
+
const roleDir = join4(installPath, "backend", role === "core" ? "core" : role);
|
|
18215
|
+
const vaultConfigDir = join4(roleDir, "vault", "config");
|
|
18216
|
+
mkdirSync4(vaultConfigDir, { recursive: true });
|
|
18217
|
+
mkdirSync4(join4(installPath, "config", "providers"), { recursive: true });
|
|
18218
|
+
writeFileSync4(join4(installPath, ROLE_IMAGE_COMPOSE_FILES[role]), await loadSelfHostComposeTemplate(templateRefForImageTag(imageTag, getPackageVersion()), role));
|
|
18219
|
+
writeFileSync4(join4(vaultConfigDir, "vault.hcl"), VAULT_CONFIG_TEMPLATE);
|
|
16861
18220
|
ensureImageRuntimeConfig(installPath);
|
|
16862
|
-
const envPath =
|
|
16863
|
-
let envContent =
|
|
18221
|
+
const envPath = join4(installPath, ".env");
|
|
18222
|
+
let envContent = existsSync7(envPath) ? readFileSync6(envPath, "utf-8") : MINIMAL_ENV_TEMPLATE;
|
|
16864
18223
|
envContent = setEnvIfEmpty(envContent, "DATABASE_ADMIN_PASSWORD", randomHex(12));
|
|
16865
18224
|
envContent = setEnvIfEmpty(envContent, "DATABASE_PASSWORD", randomHex(12));
|
|
16866
18225
|
envContent = setEnvIfEmpty(envContent, "DIRECTUS_TOKEN", randomHex(32));
|
|
@@ -16872,13 +18231,13 @@ async function writeImageModeRuntimeFiles(installPath, imageTag, role) {
|
|
|
16872
18231
|
envContent = setEnvVar(envContent, "OPENMATES_IMAGE_TAG", imageTag);
|
|
16873
18232
|
envContent = setEnvVar(envContent, "OPENMATES_IMAGE_REGISTRY", DEFAULT_IMAGE_REGISTRY);
|
|
16874
18233
|
envContent = setEnvVar(envContent, "GIT_WORK_DIR", installPath);
|
|
16875
|
-
|
|
18234
|
+
writeFileSync4(envPath, envContent.endsWith("\n") ? envContent : `${envContent}
|
|
16876
18235
|
`);
|
|
16877
18236
|
}
|
|
16878
18237
|
function getImageTagFromEnv(installPath, config) {
|
|
16879
|
-
const envPath =
|
|
16880
|
-
if (
|
|
16881
|
-
const envTag = getEnvVar(
|
|
18238
|
+
const envPath = join4(installPath, ".env");
|
|
18239
|
+
if (existsSync7(envPath)) {
|
|
18240
|
+
const envTag = getEnvVar(readFileSync6(envPath, "utf-8"), "OPENMATES_IMAGE_TAG");
|
|
16882
18241
|
if (envTag) return envTag;
|
|
16883
18242
|
}
|
|
16884
18243
|
return config?.imageTag ?? "";
|
|
@@ -16911,8 +18270,8 @@ async function waitForServerHealth(installPath, role = "core", options = {}) {
|
|
|
16911
18270
|
}
|
|
16912
18271
|
throw new Error(`Updated ${role} server did not pass health checks in time. Tried ${healthUrl}.`);
|
|
16913
18272
|
}
|
|
16914
|
-
const envPath =
|
|
16915
|
-
const envContent =
|
|
18273
|
+
const envPath = join4(installPath, ".env");
|
|
18274
|
+
const envContent = existsSync7(envPath) ? readFileSync6(envPath, "utf-8") : "";
|
|
16916
18275
|
const urls = deriveSelfHostCliUrls(envContent);
|
|
16917
18276
|
const apiHealthUrl = `${trailingSlashTrimmed(urls.apiUrl)}/health`;
|
|
16918
18277
|
const appUrl = trailingSlashTrimmed(urls.appUrl);
|
|
@@ -16935,9 +18294,9 @@ function defaultCloneBranchForVersion(version) {
|
|
|
16935
18294
|
return /-(alpha|beta|rc)(\.|\d|$)/.test(version) ? DEV_BRANCH : null;
|
|
16936
18295
|
}
|
|
16937
18296
|
function hasLlmCredentials(envPath) {
|
|
16938
|
-
if (!
|
|
16939
|
-
if (hasLocalAiModels(
|
|
16940
|
-
const content =
|
|
18297
|
+
if (!existsSync7(envPath)) return false;
|
|
18298
|
+
if (hasLocalAiModels(dirname2(envPath))) return true;
|
|
18299
|
+
const content = readFileSync6(envPath, "utf-8");
|
|
16941
18300
|
for (const line of content.split("\n")) {
|
|
16942
18301
|
const trimmed = line.trim();
|
|
16943
18302
|
if (trimmed.startsWith("#") || !trimmed) continue;
|
|
@@ -16952,8 +18311,8 @@ function hasLlmCredentials(envPath) {
|
|
|
16952
18311
|
return false;
|
|
16953
18312
|
}
|
|
16954
18313
|
function warnIfMissingLlmCredentials(installPath) {
|
|
16955
|
-
const envPath =
|
|
16956
|
-
if (!
|
|
18314
|
+
const envPath = join4(installPath, ".env");
|
|
18315
|
+
if (!existsSync7(envPath)) {
|
|
16957
18316
|
console.error(
|
|
16958
18317
|
"No .env file found. Run 'openmates server install' first, or create .env from .env.example."
|
|
16959
18318
|
);
|
|
@@ -16978,22 +18337,22 @@ function printJson(data) {
|
|
|
16978
18337
|
console.log(JSON.stringify(data, null, 2));
|
|
16979
18338
|
}
|
|
16980
18339
|
function localModelsOverlayPath(installPath, installMode = getInstallMode(installPath)) {
|
|
16981
|
-
if (installMode === "source") return
|
|
16982
|
-
return
|
|
18340
|
+
if (installMode === "source") return join4(installPath, "backend", "providers", LOCAL_AI_MODELS_FILE);
|
|
18341
|
+
return join4(installPath, "config", "providers", LOCAL_AI_MODELS_FILE);
|
|
16983
18342
|
}
|
|
16984
18343
|
function imageBackendConfigPath(installPath) {
|
|
16985
|
-
return
|
|
18344
|
+
return join4(installPath, IMAGE_RUNTIME_CONFIG_FILE);
|
|
16986
18345
|
}
|
|
16987
18346
|
function ensureImageRuntimeConfig(installPath) {
|
|
16988
18347
|
const configPath = imageBackendConfigPath(installPath);
|
|
16989
|
-
if (
|
|
16990
|
-
|
|
16991
|
-
|
|
18348
|
+
if (existsSync7(configPath)) return;
|
|
18349
|
+
mkdirSync4(dirname2(configPath), { recursive: true });
|
|
18350
|
+
writeFileSync4(configPath, renderFeatureOverrides({ enabled: [], disabled: [] }));
|
|
16992
18351
|
}
|
|
16993
18352
|
function readLocalModelOverlay(path) {
|
|
16994
|
-
if (!
|
|
18353
|
+
if (!existsSync7(path)) return { providers: [] };
|
|
16995
18354
|
try {
|
|
16996
|
-
const parsed = JSON.parse(
|
|
18355
|
+
const parsed = JSON.parse(readFileSync6(path, "utf-8"));
|
|
16997
18356
|
return { providers: Array.isArray(parsed.providers) ? parsed.providers : [] };
|
|
16998
18357
|
} catch (error) {
|
|
16999
18358
|
throw new Error(
|
|
@@ -17002,15 +18361,15 @@ function readLocalModelOverlay(path) {
|
|
|
17002
18361
|
}
|
|
17003
18362
|
}
|
|
17004
18363
|
function writeLocalModelOverlay(path, overlay) {
|
|
17005
|
-
|
|
17006
|
-
|
|
18364
|
+
mkdirSync4(dirname2(path), { recursive: true });
|
|
18365
|
+
writeFileSync4(path, `${JSON.stringify(overlay, null, 2)}
|
|
17007
18366
|
`);
|
|
17008
18367
|
}
|
|
17009
18368
|
function hasLocalAiModels(installPath) {
|
|
17010
|
-
const imagePath =
|
|
17011
|
-
const sourcePath =
|
|
18369
|
+
const imagePath = join4(installPath, "config", "providers", LOCAL_AI_MODELS_FILE);
|
|
18370
|
+
const sourcePath = join4(installPath, "backend", "providers", LOCAL_AI_MODELS_FILE);
|
|
17012
18371
|
return [imagePath, sourcePath].some((path) => {
|
|
17013
|
-
if (!
|
|
18372
|
+
if (!existsSync7(path)) return false;
|
|
17014
18373
|
try {
|
|
17015
18374
|
return readLocalModelOverlay(path).providers.some((provider) => provider.models.length > 0);
|
|
17016
18375
|
} catch {
|
|
@@ -17051,30 +18410,30 @@ function nowStamp() {
|
|
|
17051
18410
|
return (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
17052
18411
|
}
|
|
17053
18412
|
function backupRoot(installPath) {
|
|
17054
|
-
return
|
|
18413
|
+
return join4(installPath, "backups");
|
|
17055
18414
|
}
|
|
17056
18415
|
function roleBackupDir(installPath, role) {
|
|
17057
|
-
return
|
|
18416
|
+
return join4(backupRoot(installPath), role);
|
|
17058
18417
|
}
|
|
17059
18418
|
function updateStatusFile(installPath, role) {
|
|
17060
|
-
return
|
|
18419
|
+
return join4(installPath, ".openmates", `${role}-update-status.json`);
|
|
17061
18420
|
}
|
|
17062
18421
|
function writeUpdateStatus(installPath, role, status) {
|
|
17063
18422
|
const filePath = updateStatusFile(installPath, role);
|
|
17064
|
-
|
|
17065
|
-
|
|
18423
|
+
mkdirSync4(dirname2(filePath), { recursive: true, mode: 448 });
|
|
18424
|
+
writeFileSync4(filePath, `${JSON.stringify({ role, updated_at: (/* @__PURE__ */ new Date()).toISOString(), ...status }, null, 2)}
|
|
17066
18425
|
`, { mode: 384 });
|
|
17067
18426
|
}
|
|
17068
18427
|
function copyIfExists(source, destination) {
|
|
17069
|
-
if (!
|
|
17070
|
-
|
|
18428
|
+
if (!existsSync7(source)) return;
|
|
18429
|
+
mkdirSync4(dirname2(destination), { recursive: true });
|
|
17071
18430
|
cpSync(source, destination, { recursive: true, force: true });
|
|
17072
18431
|
}
|
|
17073
18432
|
function readEnvMap(installPath) {
|
|
17074
|
-
const envPath =
|
|
17075
|
-
if (!
|
|
18433
|
+
const envPath = join4(installPath, ".env");
|
|
18434
|
+
if (!existsSync7(envPath)) return {};
|
|
17076
18435
|
const values = {};
|
|
17077
|
-
for (const line of
|
|
18436
|
+
for (const line of readFileSync6(envPath, "utf-8").split("\n")) {
|
|
17078
18437
|
const trimmed = line.trim();
|
|
17079
18438
|
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
17080
18439
|
const eqIdx = trimmed.indexOf("=");
|
|
@@ -17222,7 +18581,7 @@ function formatSecretPreflight(preflight) {
|
|
|
17222
18581
|
return parts.join("; ");
|
|
17223
18582
|
}
|
|
17224
18583
|
function hashFile(path) {
|
|
17225
|
-
const hash =
|
|
18584
|
+
const hash = createHash8("sha256");
|
|
17226
18585
|
const fd = openSync(path, "r");
|
|
17227
18586
|
const buffer = Buffer.allocUnsafe(CHECKSUM_BUFFER_BYTES);
|
|
17228
18587
|
try {
|
|
@@ -17240,7 +18599,7 @@ function writeChecksums(rootDir) {
|
|
|
17240
18599
|
const lines = [];
|
|
17241
18600
|
const walk = (dir) => {
|
|
17242
18601
|
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
17243
|
-
const path =
|
|
18602
|
+
const path = join4(dir, entry.name);
|
|
17244
18603
|
if (entry.isDirectory()) {
|
|
17245
18604
|
walk(path);
|
|
17246
18605
|
continue;
|
|
@@ -17251,13 +18610,13 @@ function writeChecksums(rootDir) {
|
|
|
17251
18610
|
}
|
|
17252
18611
|
};
|
|
17253
18612
|
walk(rootDir);
|
|
17254
|
-
|
|
18613
|
+
writeFileSync4(join4(rootDir, "checksums.sha256"), `${lines.sort().join("\n")}
|
|
17255
18614
|
`);
|
|
17256
18615
|
}
|
|
17257
18616
|
function verifyChecksums(rootDir) {
|
|
17258
|
-
const checksumsPath =
|
|
17259
|
-
if (!
|
|
17260
|
-
for (const line of
|
|
18617
|
+
const checksumsPath = join4(rootDir, "checksums.sha256");
|
|
18618
|
+
if (!existsSync7(checksumsPath)) throw new Error("Backup archive is missing checksums.sha256.");
|
|
18619
|
+
for (const line of readFileSync6(checksumsPath, "utf-8").split("\n")) {
|
|
17261
18620
|
const trimmed = line.trim();
|
|
17262
18621
|
if (!trimmed) continue;
|
|
17263
18622
|
const match = trimmed.match(/^([a-f0-9]{64}) {2}(.+)$/);
|
|
@@ -17266,8 +18625,8 @@ function verifyChecksums(rootDir) {
|
|
|
17266
18625
|
if (relative3.startsWith("/") || relative3.split(/[\\/]/).includes("..")) {
|
|
17267
18626
|
throw new Error(`Unsafe checksum path in backup archive: ${relative3}`);
|
|
17268
18627
|
}
|
|
17269
|
-
const filePath =
|
|
17270
|
-
if (!
|
|
18628
|
+
const filePath = join4(rootDir, relative3);
|
|
18629
|
+
if (!existsSync7(filePath)) throw new Error(`Backup archive is missing checksummed file: ${relative3}`);
|
|
17271
18630
|
const actual = hashFile(filePath);
|
|
17272
18631
|
if (actual !== match[1]) throw new Error(`Backup checksum mismatch for ${relative3}.`);
|
|
17273
18632
|
}
|
|
@@ -17275,27 +18634,27 @@ function verifyChecksums(rootDir) {
|
|
|
17275
18634
|
function createServerBackup(installPath, role, options = {}) {
|
|
17276
18635
|
const plan = planBackup({ role, includeObservability: options.includeObservability });
|
|
17277
18636
|
const backupDir = roleBackupDir(installPath, role);
|
|
17278
|
-
|
|
17279
|
-
const archivePath = options.output ? resolve3(options.output) :
|
|
17280
|
-
const tempDir = mkdtempSync(
|
|
18637
|
+
mkdirSync4(backupDir, { recursive: true, mode: 448 });
|
|
18638
|
+
const archivePath = options.output ? resolve3(options.output) : join4(backupDir, options.preUpdate ? `latest-pre-update-${role}.tar.gz` : `openmates-${role}-${nowStamp()}.tar.gz`);
|
|
18639
|
+
const tempDir = mkdtempSync(join4(backupDir, ".tmp-"));
|
|
17281
18640
|
const env = readEnvMap(installPath);
|
|
17282
18641
|
const manifest = {
|
|
17283
18642
|
role,
|
|
17284
18643
|
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
17285
18644
|
cli_version: getPackageVersion(),
|
|
17286
|
-
image_tag: getEnvVar(
|
|
18645
|
+
image_tag: getEnvVar(existsSync7(join4(installPath, ".env")) ? readFileSync6(join4(installPath, ".env"), "utf-8") : "", "OPENMATES_IMAGE_TAG"),
|
|
17287
18646
|
include_observability: options.includeObservability === true,
|
|
17288
18647
|
contents: plan.contents
|
|
17289
18648
|
};
|
|
17290
18649
|
try {
|
|
17291
|
-
|
|
18650
|
+
writeFileSync4(join4(tempDir, "manifest.json"), `${JSON.stringify(manifest, null, 2)}
|
|
17292
18651
|
`);
|
|
17293
|
-
copyIfExists(
|
|
17294
|
-
copyIfExists(
|
|
18652
|
+
copyIfExists(join4(installPath, ".env"), join4(tempDir, "runtime", ".env"));
|
|
18653
|
+
copyIfExists(join4(installPath, "config"), join4(tempDir, "runtime", "config"));
|
|
17295
18654
|
if (role === "core") {
|
|
17296
18655
|
const databaseUser = env.DATABASE_USERNAME || "directus";
|
|
17297
18656
|
const databaseName = env.DATABASE_NAME || "directus";
|
|
17298
|
-
const dumpFile = openSync(
|
|
18657
|
+
const dumpFile = openSync(join4(tempDir, "postgres.sql"), "w");
|
|
17299
18658
|
try {
|
|
17300
18659
|
const result = spawnSync(
|
|
17301
18660
|
"docker",
|
|
@@ -17311,15 +18670,15 @@ function createServerBackup(installPath, role, options = {}) {
|
|
|
17311
18670
|
}
|
|
17312
18671
|
}
|
|
17313
18672
|
for (const item of [
|
|
17314
|
-
[
|
|
17315
|
-
[
|
|
17316
|
-
[
|
|
18673
|
+
[join4(installPath, "backend", "core", "uploads"), join4(tempDir, "directus-uploads")],
|
|
18674
|
+
[join4(installPath, "backend", "core", "extensions"), join4(tempDir, "directus-extensions")],
|
|
18675
|
+
[join4(installPath, "backend", role, "vault"), join4(tempDir, `${role}-vault-config`)]
|
|
17317
18676
|
]) {
|
|
17318
18677
|
copyIfExists(item[0], item[1]);
|
|
17319
18678
|
}
|
|
17320
18679
|
writeChecksums(tempDir);
|
|
17321
18680
|
execSync(`tar -czf ${shellQuote(archivePath)} -C ${shellQuote(tempDir)} .`, { stdio: "pipe" });
|
|
17322
|
-
|
|
18681
|
+
chmodSync3(archivePath, plan.fileMode);
|
|
17323
18682
|
return archivePath;
|
|
17324
18683
|
} finally {
|
|
17325
18684
|
rmSync3(tempDir, { recursive: true, force: true });
|
|
@@ -17327,25 +18686,25 @@ function createServerBackup(installPath, role, options = {}) {
|
|
|
17327
18686
|
}
|
|
17328
18687
|
function restoreServerBackup(installPath, role, file) {
|
|
17329
18688
|
const archivePath = resolve3(file);
|
|
17330
|
-
if (!
|
|
17331
|
-
|
|
17332
|
-
const tempDir = mkdtempSync(
|
|
18689
|
+
if (!existsSync7(archivePath)) throw new Error(`Backup file not found: ${archivePath}`);
|
|
18690
|
+
mkdirSync4(roleBackupDir(installPath, role), { recursive: true, mode: 448 });
|
|
18691
|
+
const tempDir = mkdtempSync(join4(roleBackupDir(installPath, role), ".restore-"));
|
|
17333
18692
|
const env = readEnvMap(installPath);
|
|
17334
18693
|
try {
|
|
17335
18694
|
execSync(`tar -xzf ${shellQuote(archivePath)} -C ${shellQuote(tempDir)}`, { stdio: "pipe" });
|
|
17336
18695
|
verifyChecksums(tempDir);
|
|
17337
|
-
const manifestPath =
|
|
17338
|
-
if (!
|
|
17339
|
-
const manifest = JSON.parse(
|
|
18696
|
+
const manifestPath = join4(tempDir, "manifest.json");
|
|
18697
|
+
if (!existsSync7(manifestPath)) throw new Error("Backup archive is missing manifest.json.");
|
|
18698
|
+
const manifest = JSON.parse(readFileSync6(manifestPath, "utf-8"));
|
|
17340
18699
|
if (manifest.role !== role) throw new Error(`Backup role '${manifest.role}' does not match requested role '${role}'.`);
|
|
17341
|
-
copyIfExists(
|
|
17342
|
-
copyIfExists(
|
|
17343
|
-
const postgresDump =
|
|
17344
|
-
if (role === "core" &&
|
|
18700
|
+
copyIfExists(join4(tempDir, "runtime", ".env"), join4(installPath, ".env"));
|
|
18701
|
+
copyIfExists(join4(tempDir, "runtime", "config"), join4(installPath, "config"));
|
|
18702
|
+
const postgresDump = join4(tempDir, "postgres.sql");
|
|
18703
|
+
if (role === "core" && existsSync7(postgresDump)) {
|
|
17345
18704
|
const databaseUser = env.DATABASE_USERNAME || "directus";
|
|
17346
18705
|
const databaseName = env.DATABASE_NAME || "directus";
|
|
17347
18706
|
execSync(`docker exec -i cms-database psql -v ON_ERROR_STOP=1 -U ${shellQuote(databaseUser)} ${shellQuote(databaseName)}`, {
|
|
17348
|
-
input:
|
|
18707
|
+
input: readFileSync6(postgresDump),
|
|
17349
18708
|
stdio: ["pipe", "pipe", "pipe"]
|
|
17350
18709
|
});
|
|
17351
18710
|
}
|
|
@@ -17600,26 +18959,26 @@ async function serverInstall(flags) {
|
|
|
17600
18959
|
const role = getServerRole(flags, null);
|
|
17601
18960
|
const profile = getCoreProfile(flags, null);
|
|
17602
18961
|
const runtimePlan = planServerRuntime({ role, profile, withAlerts: flags["with-alerts"] === true });
|
|
17603
|
-
if (
|
|
18962
|
+
if (existsSync7(join4(installPath, SOURCE_COMPOSE_FILE)) || Object.values(ROLE_IMAGE_COMPOSE_FILES).some((composeFile) => existsSync7(join4(installPath, composeFile)))) {
|
|
17604
18963
|
console.error(`OpenMates already exists at ${installPath}.`);
|
|
17605
18964
|
console.error("Use 'openmates server update' to update, or choose a different --path.");
|
|
17606
18965
|
process.exit(1);
|
|
17607
18966
|
}
|
|
17608
18967
|
if (!fromSource) {
|
|
17609
18968
|
requireDocker();
|
|
17610
|
-
|
|
18969
|
+
mkdirSync4(installPath, { recursive: true });
|
|
17611
18970
|
if (typeof flags["env-path"] === "string") {
|
|
17612
18971
|
const envSource = resolve3(flags["env-path"]);
|
|
17613
|
-
if (!
|
|
18972
|
+
if (!existsSync7(envSource)) {
|
|
17614
18973
|
throw new Error(`Env file not found: ${envSource}`);
|
|
17615
18974
|
}
|
|
17616
|
-
copyFileSync(envSource,
|
|
18975
|
+
copyFileSync(envSource, join4(installPath, ".env"));
|
|
17617
18976
|
console.error(`Copied ${envSource} to ${installPath}/.env`);
|
|
17618
18977
|
}
|
|
17619
18978
|
const imageTag = typeof flags["image-tag"] === "string" ? flags["image-tag"] : getDefaultImageTag();
|
|
17620
18979
|
console.error(`Preparing OpenMates image-mode install at ${installPath}...`);
|
|
17621
18980
|
await writeImageModeRuntimeFiles(installPath, imageTag, role);
|
|
17622
|
-
const cliUrls2 = deriveSelfHostCliUrls(
|
|
18981
|
+
const cliUrls2 = deriveSelfHostCliUrls(readFileSync6(join4(installPath, ".env"), "utf-8"));
|
|
17623
18982
|
try {
|
|
17624
18983
|
exec("docker network create openmates", installPath);
|
|
17625
18984
|
} catch {
|
|
@@ -17639,7 +18998,7 @@ async function serverInstall(flags) {
|
|
|
17639
18998
|
if (flags.json === true) {
|
|
17640
18999
|
printJson({ command: "install", status: "success", path: installPath, mode: "image", imageTag });
|
|
17641
19000
|
} else {
|
|
17642
|
-
const firstInvite = getEnvVar(
|
|
19001
|
+
const firstInvite = getEnvVar(readFileSync6(join4(installPath, ".env"), "utf-8"), "SELF_HOST_FIRST_INVITE_CODE");
|
|
17643
19002
|
console.log(`
|
|
17644
19003
|
OpenMates installed at ${installPath}`);
|
|
17645
19004
|
console.log(`Mode: image (${DEFAULT_IMAGE_REGISTRY}, tag ${imageTag})`);
|
|
@@ -17676,10 +19035,10 @@ CLI default API: ${cliUrls2.apiUrl}`);
|
|
|
17676
19035
|
}
|
|
17677
19036
|
if (typeof flags["env-path"] === "string") {
|
|
17678
19037
|
const envSource = resolve3(flags["env-path"]);
|
|
17679
|
-
if (!
|
|
19038
|
+
if (!existsSync7(envSource)) {
|
|
17680
19039
|
throw new Error(`Env file not found: ${envSource}`);
|
|
17681
19040
|
}
|
|
17682
|
-
copyFileSync(envSource,
|
|
19041
|
+
copyFileSync(envSource, join4(installPath, ".env"));
|
|
17683
19042
|
console.error(`Copied ${envSource} to ${installPath}/.env`);
|
|
17684
19043
|
}
|
|
17685
19044
|
console.error("\nRunning setup script...");
|
|
@@ -17692,8 +19051,8 @@ CLI default API: ${cliUrls2.apiUrl}`);
|
|
|
17692
19051
|
console.error("Setup script failed. Check the output above for details.");
|
|
17693
19052
|
process.exit(setupCode);
|
|
17694
19053
|
}
|
|
17695
|
-
const envPath =
|
|
17696
|
-
const cliUrls = deriveSelfHostCliUrls(
|
|
19054
|
+
const envPath = join4(installPath, ".env");
|
|
19055
|
+
const cliUrls = deriveSelfHostCliUrls(existsSync7(envPath) ? readFileSync6(envPath, "utf-8") : "");
|
|
17697
19056
|
saveServerConfig({
|
|
17698
19057
|
installPath,
|
|
17699
19058
|
installedAt: Date.now(),
|
|
@@ -17725,15 +19084,15 @@ async function installContinuousUpdateService(flags) {
|
|
|
17725
19084
|
const channel = typeof flags.channel === "string" ? flags.channel : config?.imageChannel ?? "main";
|
|
17726
19085
|
const window = typeof flags.window === "string" ? flags.window : "02:00-04:00 UTC";
|
|
17727
19086
|
const plan = planContinuousUpdateService({ role, channel, window });
|
|
17728
|
-
const servicePath =
|
|
17729
|
-
const timerPath =
|
|
19087
|
+
const servicePath = join4("/etc", "systemd", "system", plan.serviceName);
|
|
19088
|
+
const timerPath = join4("/etc", "systemd", "system", plan.timerName);
|
|
17730
19089
|
if (flags["dry-run"] === true || flags.json === true) {
|
|
17731
19090
|
printJson({ command: "update install-service", status: "planned", role, servicePath, timerPath, unit: plan.unit, timer: plan.timer });
|
|
17732
19091
|
return;
|
|
17733
19092
|
}
|
|
17734
19093
|
try {
|
|
17735
|
-
|
|
17736
|
-
|
|
19094
|
+
writeFileSync4(servicePath, plan.unit, { mode: 420 });
|
|
19095
|
+
writeFileSync4(timerPath, plan.timer, { mode: 420 });
|
|
17737
19096
|
execSync("systemctl daemon-reload", { stdio: "pipe" });
|
|
17738
19097
|
execSync(`systemctl enable --now ${shellQuote(plan.timerName)}`, { stdio: "pipe" });
|
|
17739
19098
|
} catch (error) {
|
|
@@ -17750,14 +19109,14 @@ async function serverUpdate(rest, flags) {
|
|
|
17750
19109
|
const role2 = getServerRole(flags, config2);
|
|
17751
19110
|
const filePath = updateStatusFile(installPath2, role2);
|
|
17752
19111
|
if (flags.json === true) {
|
|
17753
|
-
printJson(
|
|
19112
|
+
printJson(existsSync7(filePath) ? JSON.parse(readFileSync6(filePath, "utf-8")) : { role: role2, status: "unknown" });
|
|
17754
19113
|
return;
|
|
17755
19114
|
}
|
|
17756
|
-
if (!
|
|
19115
|
+
if (!existsSync7(filePath)) {
|
|
17757
19116
|
console.log(`No update status recorded for ${role2}.`);
|
|
17758
19117
|
return;
|
|
17759
19118
|
}
|
|
17760
|
-
console.log(
|
|
19119
|
+
console.log(readFileSync6(filePath, "utf-8").trim());
|
|
17761
19120
|
return;
|
|
17762
19121
|
}
|
|
17763
19122
|
if (rest[0] === "install-service") {
|
|
@@ -18066,14 +19425,14 @@ async function serverFeatures(rest, flags) {
|
|
|
18066
19425
|
const installPath = resolveServerPath(flags);
|
|
18067
19426
|
const installMode = getInstallMode(installPath);
|
|
18068
19427
|
if (installMode === "image") ensureImageRuntimeConfig(installPath);
|
|
18069
|
-
const configPath = installMode === "image" ? imageBackendConfigPath(installPath) :
|
|
18070
|
-
if (!
|
|
19428
|
+
const configPath = installMode === "image" ? imageBackendConfigPath(installPath) : join4(installPath, BACKEND_CONFIG_FILE);
|
|
19429
|
+
if (!existsSync7(configPath)) {
|
|
18071
19430
|
throw new Error(`Backend config not found at ${configPath}. Run 'openmates server install' first or pass --path <dir>.`);
|
|
18072
19431
|
}
|
|
18073
|
-
const content =
|
|
19432
|
+
const content = readFileSync6(configPath, "utf-8");
|
|
18074
19433
|
const overrides = parseFeatureOverrides(content);
|
|
18075
19434
|
const writeOverrides = (nextOverrides) => {
|
|
18076
|
-
|
|
19435
|
+
writeFileSync4(configPath, updateFeatureOverridesContent(content, nextOverrides));
|
|
18077
19436
|
console.log(`Updated ${configPath}`);
|
|
18078
19437
|
console.log("Restart the server for feature changes to take effect: openmates server restart");
|
|
18079
19438
|
};
|
|
@@ -18306,7 +19665,7 @@ async function serverBackup(rest, flags) {
|
|
|
18306
19665
|
const role = getServerRole(flags, config);
|
|
18307
19666
|
if (action === "list") {
|
|
18308
19667
|
const dir = roleBackupDir(installPath, role);
|
|
18309
|
-
const files =
|
|
19668
|
+
const files = existsSync7(dir) ? readdirSync(dir).filter((item) => item.endsWith(".tar.gz")).sort() : [];
|
|
18310
19669
|
if (flags.json === true) {
|
|
18311
19670
|
printJson({ role, backupDir: dir, files });
|
|
18312
19671
|
return;
|
|
@@ -18316,7 +19675,7 @@ async function serverBackup(rest, flags) {
|
|
|
18316
19675
|
console.log(" none");
|
|
18317
19676
|
return;
|
|
18318
19677
|
}
|
|
18319
|
-
for (const file of files) console.log(` ${
|
|
19678
|
+
for (const file of files) console.log(` ${join4(dir, file)}`);
|
|
18320
19679
|
return;
|
|
18321
19680
|
}
|
|
18322
19681
|
requireDocker();
|
|
@@ -18476,7 +19835,7 @@ async function serverCaddy(rest, flags) {
|
|
|
18476
19835
|
const role = getServerRole(flags, config);
|
|
18477
19836
|
const appliedPath = typeof flags.config === "string" ? flags.config : "/etc/caddy/Caddyfile";
|
|
18478
19837
|
const templatePath = packagedCaddyTemplatePath(role);
|
|
18479
|
-
if (!
|
|
19838
|
+
if (!existsSync7(templatePath)) throw new Error(`Packaged Caddy template not found: ${templatePath}`);
|
|
18480
19839
|
const plan = planCaddyCommand({ role, action, appliedPath });
|
|
18481
19840
|
const payload = {
|
|
18482
19841
|
...plan,
|
|
@@ -18495,7 +19854,7 @@ async function serverCaddy(rest, flags) {
|
|
|
18495
19854
|
return;
|
|
18496
19855
|
}
|
|
18497
19856
|
if (action === "diff") {
|
|
18498
|
-
if (!
|
|
19857
|
+
if (!existsSync7(appliedPath)) throw new Error(`Applied Caddyfile not found: ${appliedPath}`);
|
|
18499
19858
|
try {
|
|
18500
19859
|
execSync(`diff -u ${shellQuote(appliedPath)} ${shellQuote(templatePath)}`, { stdio: "inherit" });
|
|
18501
19860
|
} catch (error) {
|
|
@@ -18516,9 +19875,9 @@ WARNING: This will replace ${appliedPath} with the packaged ${role} Caddyfile.`)
|
|
|
18516
19875
|
}
|
|
18517
19876
|
}
|
|
18518
19877
|
const backupPath = `${appliedPath}.openmates-backup-${nowStamp()}`;
|
|
18519
|
-
const hadExistingCaddyfile =
|
|
19878
|
+
const hadExistingCaddyfile = existsSync7(appliedPath);
|
|
18520
19879
|
try {
|
|
18521
|
-
|
|
19880
|
+
mkdirSync4(dirname2(appliedPath), { recursive: true });
|
|
18522
19881
|
if (hadExistingCaddyfile) copyFileSync(appliedPath, backupPath);
|
|
18523
19882
|
copyFileSync(templatePath, appliedPath);
|
|
18524
19883
|
execSync("systemctl reload caddy", { stdio: "inherit" });
|
|
@@ -53151,10 +54510,10 @@ function buildAssistantFeedbackDecision(rating) {
|
|
|
53151
54510
|
}
|
|
53152
54511
|
|
|
53153
54512
|
// src/benchmark.ts
|
|
53154
|
-
import { randomUUID as
|
|
53155
|
-
import { existsSync as
|
|
54513
|
+
import { randomUUID as randomUUID7 } from "crypto";
|
|
54514
|
+
import { existsSync as existsSync8, mkdtempSync as mkdtempSync2, readFileSync as readFileSync7, readdirSync as readdirSync2, writeFileSync as writeFileSync5 } from "fs";
|
|
53156
54515
|
import { tmpdir } from "os";
|
|
53157
|
-
import { dirname as
|
|
54516
|
+
import { dirname as dirname3, join as join5, resolve as resolve5 } from "path";
|
|
53158
54517
|
import { fileURLToPath } from "url";
|
|
53159
54518
|
var DEFAULT_JUDGE_MODEL = "google/gemini-3-flash-preview";
|
|
53160
54519
|
var DEFAULT_EXTENSIVE_SIZE = 10;
|
|
@@ -53451,7 +54810,7 @@ async function handleBenchmark(client, subcommand, rest, flags) {
|
|
|
53451
54810
|
const caseIds = parseCaseIds(flags.case);
|
|
53452
54811
|
const dryRun = flags["dry-run"] === true;
|
|
53453
54812
|
const output = typeof flags.output === "string" ? flags.output : void 0;
|
|
53454
|
-
const runId = typeof flags["run-id"] === "string" ? flags["run-id"] :
|
|
54813
|
+
const runId = typeof flags["run-id"] === "string" ? flags["run-id"] : randomUUID7();
|
|
53455
54814
|
const imagePath = typeof flags.image === "string" ? resolve5(flags.image) : defaultImageFixturePath();
|
|
53456
54815
|
if (!dryRun && flags["confirm-spend-credits"] !== true) {
|
|
53457
54816
|
throw new Error(
|
|
@@ -53747,7 +55106,7 @@ async function buildPromptWithAttachments(client, benchmarkCase, model, imagePat
|
|
|
53747
55106
|
${attachment.messageSuffix}`, embeds: attachment.embeds };
|
|
53748
55107
|
}
|
|
53749
55108
|
async function prepareImageAttachment(client, imagePath) {
|
|
53750
|
-
if (!
|
|
55109
|
+
if (!existsSync8(imagePath)) throw new Error(`Benchmark image not found: ${imagePath}`);
|
|
53751
55110
|
const processed = processFiles([imagePath], null);
|
|
53752
55111
|
if (processed.blocked.length > 0 || processed.errors.length > 0 || processed.embeds.length === 0) {
|
|
53753
55112
|
const reason = [...processed.blocked, ...processed.errors].map((entry) => entry.error).join("; ") || "no image embed produced";
|
|
@@ -53861,7 +55220,7 @@ function buildLongContextHistory() {
|
|
|
53861
55220
|
}
|
|
53862
55221
|
function appendHistory(history, role, content) {
|
|
53863
55222
|
history.push({
|
|
53864
|
-
message_id:
|
|
55223
|
+
message_id: randomUUID7(),
|
|
53865
55224
|
role,
|
|
53866
55225
|
sender_name: role === "user" ? "User" : "Assistant",
|
|
53867
55226
|
content,
|
|
@@ -53953,8 +55312,8 @@ function loadProviderPricing() {
|
|
|
53953
55312
|
if (!providersDir) return pricing;
|
|
53954
55313
|
for (const fileName of readdirSync2(providersDir)) {
|
|
53955
55314
|
if (!fileName.endsWith(".yml")) continue;
|
|
53956
|
-
const filePath =
|
|
53957
|
-
const text =
|
|
55315
|
+
const filePath = join5(providersDir, fileName);
|
|
55316
|
+
const text = readFileSync7(filePath, "utf-8");
|
|
53958
55317
|
const provider = parseProviderId(text) ?? fileName.replace(/\.yml$/, "");
|
|
53959
55318
|
for (const modelPricing of parseModelPricing(text, provider)) {
|
|
53960
55319
|
pricing.set(`${modelPricing.provider}/${modelPricing.modelId}`, modelPricing);
|
|
@@ -54006,13 +55365,13 @@ function normalizeModelKey(model) {
|
|
|
54006
55365
|
}
|
|
54007
55366
|
function findProvidersDir() {
|
|
54008
55367
|
const currentFile = fileURLToPath(import.meta.url);
|
|
54009
|
-
let current =
|
|
55368
|
+
let current = dirname3(currentFile);
|
|
54010
55369
|
for (let index = 0; index < 8; index += 1) {
|
|
54011
|
-
const candidate =
|
|
54012
|
-
if (
|
|
54013
|
-
const parentCandidate =
|
|
54014
|
-
if (
|
|
54015
|
-
const next =
|
|
55370
|
+
const candidate = join5(current, "backend", "providers");
|
|
55371
|
+
if (existsSync8(candidate)) return candidate;
|
|
55372
|
+
const parentCandidate = join5(current, "..", "..", "backend", "providers");
|
|
55373
|
+
if (existsSync8(parentCandidate)) return resolve5(parentCandidate);
|
|
55374
|
+
const next = dirname3(current);
|
|
54016
55375
|
if (next === current) break;
|
|
54017
55376
|
current = next;
|
|
54018
55377
|
}
|
|
@@ -54133,18 +55492,18 @@ function round2(value) {
|
|
|
54133
55492
|
return Math.round(value * 100) / 100;
|
|
54134
55493
|
}
|
|
54135
55494
|
function defaultImageFixturePath() {
|
|
54136
|
-
const fixtureDir =
|
|
54137
|
-
const fixturePath =
|
|
54138
|
-
if (
|
|
54139
|
-
const tempDir = mkdtempSync2(
|
|
54140
|
-
const tempPath =
|
|
54141
|
-
|
|
55495
|
+
const fixtureDir = join5(dirname3(fileURLToPath(import.meta.url)), "..", "fixtures");
|
|
55496
|
+
const fixturePath = join5(fixtureDir, "brandenburger-tor.png");
|
|
55497
|
+
if (existsSync8(fixturePath)) return fixturePath;
|
|
55498
|
+
const tempDir = mkdtempSync2(join5(tmpdir(), "openmates-benchmark-"));
|
|
55499
|
+
const tempPath = join5(tempDir, "brandenburger-tor.svg");
|
|
55500
|
+
writeFileSync5(tempPath, FIXTURE_IMAGE_SVG, "utf-8");
|
|
54142
55501
|
return tempPath;
|
|
54143
55502
|
}
|
|
54144
55503
|
function writeBenchmarkResult(result, flags, output) {
|
|
54145
55504
|
const json = `${JSON.stringify(result, null, 2)}
|
|
54146
55505
|
`;
|
|
54147
|
-
if (output)
|
|
55506
|
+
if (output) writeFileSync5(output, json, "utf-8");
|
|
54148
55507
|
if (flags.json === true || output) {
|
|
54149
55508
|
process.stdout.write(json);
|
|
54150
55509
|
return;
|
|
@@ -55503,10 +56862,10 @@ function clamp(value, min, max) {
|
|
|
55503
56862
|
}
|
|
55504
56863
|
|
|
55505
56864
|
// src/remoteAccess.ts
|
|
55506
|
-
import { homedir as
|
|
55507
|
-
import { chmodSync as
|
|
56865
|
+
import { homedir as homedir7 } from "os";
|
|
56866
|
+
import { chmodSync as chmodSync4, existsSync as existsSync9, mkdirSync as mkdirSync5, readFileSync as readFileSync8, statSync as statSync2, writeFileSync as writeFileSync6 } from "fs";
|
|
55508
56867
|
import { spawn as spawn2 } from "child_process";
|
|
55509
|
-
import { join as
|
|
56868
|
+
import { join as join6, resolve as resolve6, relative as relative2 } from "path";
|
|
55510
56869
|
|
|
55511
56870
|
// src/projectFileRisk.ts
|
|
55512
56871
|
var SECRET_OR_ENVIRONMENT_PATTERNS = [
|
|
@@ -55612,15 +56971,15 @@ var BINARY_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
55612
56971
|
".mp4",
|
|
55613
56972
|
".mov"
|
|
55614
56973
|
]);
|
|
55615
|
-
function resolveRemoteCachePath(sourceId, homeDirectory =
|
|
56974
|
+
function resolveRemoteCachePath(sourceId, homeDirectory = homedir7()) {
|
|
55616
56975
|
assertSafeSourceId(sourceId);
|
|
55617
|
-
return
|
|
56976
|
+
return join6(homeDirectory, ".openmates", "remote-cache", sourceId);
|
|
55618
56977
|
}
|
|
55619
56978
|
function startRemoteAccessSource(input) {
|
|
55620
56979
|
assertSafeSourceId(input.sourceId);
|
|
55621
|
-
const homeDirectory = input.homeDirectory ??
|
|
56980
|
+
const homeDirectory = input.homeDirectory ?? homedir7();
|
|
55622
56981
|
const rootPath = resolve6(input.rootPath);
|
|
55623
|
-
if (!
|
|
56982
|
+
if (!existsSync9(rootPath) || !statSync2(rootPath).isDirectory()) {
|
|
55624
56983
|
throw new Error(`Remote source path does not exist or is not a directory: ${rootPath}`);
|
|
55625
56984
|
}
|
|
55626
56985
|
const now = Math.floor(Date.now() / 1e3);
|
|
@@ -55637,14 +56996,14 @@ function startRemoteAccessSource(input) {
|
|
|
55637
56996
|
};
|
|
55638
56997
|
const sources = listRemoteAccessSources(homeDirectory).filter((entry) => entry.sourceId !== input.sourceId);
|
|
55639
56998
|
saveRemoteAccessSources([...sources, source], homeDirectory);
|
|
55640
|
-
|
|
56999
|
+
mkdirSync5(source.cachePath, { recursive: true, mode: 448 });
|
|
55641
57000
|
return source;
|
|
55642
57001
|
}
|
|
55643
|
-
function listRemoteAccessSources(homeDirectory =
|
|
57002
|
+
function listRemoteAccessSources(homeDirectory = homedir7()) {
|
|
55644
57003
|
const filePath = remoteAccessStorePath(homeDirectory);
|
|
55645
|
-
if (!
|
|
57004
|
+
if (!existsSync9(filePath)) return [];
|
|
55646
57005
|
try {
|
|
55647
|
-
const parsed = JSON.parse(
|
|
57006
|
+
const parsed = JSON.parse(readFileSync8(filePath, "utf-8"));
|
|
55648
57007
|
if (!Array.isArray(parsed.sources)) {
|
|
55649
57008
|
throw new Error("Remote source store is missing the sources array");
|
|
55650
57009
|
}
|
|
@@ -55793,16 +57152,16 @@ function parseRgMatch(line) {
|
|
|
55793
57152
|
}
|
|
55794
57153
|
}
|
|
55795
57154
|
function remoteAccessStorePath(homeDirectory) {
|
|
55796
|
-
return
|
|
57155
|
+
return join6(homeDirectory, ".openmates", "remote-sources.json");
|
|
55797
57156
|
}
|
|
55798
57157
|
function saveRemoteAccessSources(sources, homeDirectory) {
|
|
55799
57158
|
const filePath = remoteAccessStorePath(homeDirectory);
|
|
55800
|
-
const stateDir =
|
|
55801
|
-
|
|
55802
|
-
|
|
55803
|
-
|
|
57159
|
+
const stateDir = join6(homeDirectory, ".openmates");
|
|
57160
|
+
mkdirSync5(stateDir, { recursive: true, mode: 448 });
|
|
57161
|
+
chmodSync4(stateDir, 448);
|
|
57162
|
+
writeFileSync6(filePath, `${JSON.stringify({ sources }, null, 2)}
|
|
55804
57163
|
`, { mode: 384 });
|
|
55805
|
-
|
|
57164
|
+
chmodSync4(filePath, 384);
|
|
55806
57165
|
}
|
|
55807
57166
|
function assertRemoteAccessSourceRecord(value, index) {
|
|
55808
57167
|
if (typeof value !== "object" || value === null) {
|
|
@@ -55821,13 +57180,13 @@ function assertRemoteAccessSourceRecord(value, index) {
|
|
|
55821
57180
|
|
|
55822
57181
|
// src/selfUpdate.ts
|
|
55823
57182
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
55824
|
-
import { readFileSync as
|
|
57183
|
+
import { readFileSync as readFileSync9 } from "fs";
|
|
55825
57184
|
var PACKAGE_NAME = "openmates";
|
|
55826
57185
|
var DEFAULT_TARGET = "latest";
|
|
55827
57186
|
var SAFE_TARGET_RE = /^[a-zA-Z0-9._@+~:-]+$/;
|
|
55828
57187
|
function getCliPackageVersion() {
|
|
55829
57188
|
try {
|
|
55830
|
-
const packageJson = JSON.parse(
|
|
57189
|
+
const packageJson = JSON.parse(readFileSync9(new URL("../package.json", import.meta.url), "utf-8"));
|
|
55831
57190
|
return packageJson.version ?? "unknown";
|
|
55832
57191
|
} catch {
|
|
55833
57192
|
return "unknown";
|
|
@@ -56449,7 +57808,7 @@ async function handleRemoteAccess(client, subcommand, rest, flags) {
|
|
|
56449
57808
|
if (!rootPath) {
|
|
56450
57809
|
throw new Error("Missing source path. Usage: openmates remote-access start --path <folder>");
|
|
56451
57810
|
}
|
|
56452
|
-
const sourceId = typeof flags["source-id"] === "string" ? flags["source-id"] :
|
|
57811
|
+
const sourceId = typeof flags["source-id"] === "string" ? flags["source-id"] : randomUUID8();
|
|
56453
57812
|
const projectId = typeof flags.project === "string" ? flags.project : void 0;
|
|
56454
57813
|
validateRemoteSourceRegistrationFlags(projectId, flags);
|
|
56455
57814
|
const sourceType = parseRemoteAccessSourceType(flags.type);
|
|
@@ -56606,6 +57965,7 @@ async function handleChats(client, subcommand, rest, flags, redactor) {
|
|
|
56606
57965
|
printChatsHelp();
|
|
56607
57966
|
return;
|
|
56608
57967
|
}
|
|
57968
|
+
const apiKey = resolveApiKey(flags) ?? void 0;
|
|
56609
57969
|
if (rest[0] === "tasks") {
|
|
56610
57970
|
await handleTasks(client, rest[1], rest.slice(2), { ...flags, chat: subcommand });
|
|
56611
57971
|
return;
|
|
@@ -56613,7 +57973,7 @@ async function handleChats(client, subcommand, rest, flags, redactor) {
|
|
|
56613
57973
|
if (subcommand === "list") {
|
|
56614
57974
|
const limit = typeof flags.limit === "string" ? parseInt(flags.limit, 10) : 10;
|
|
56615
57975
|
const page = typeof flags.page === "string" ? parseInt(flags.page, 10) : 1;
|
|
56616
|
-
const result = client.hasSession() ? await client.listChats(limit, page) : listExampleChats(limit, page);
|
|
57976
|
+
const result = apiKey ? await listApiKeyChats(client, apiKey, limit, page) : client.hasSession() ? await client.listChats(limit, page) : listExampleChats(limit, page);
|
|
56617
57977
|
if (flags.json === true) {
|
|
56618
57978
|
printJson2(result);
|
|
56619
57979
|
} else {
|
|
@@ -56627,7 +57987,7 @@ async function handleChats(client, subcommand, rest, flags, redactor) {
|
|
|
56627
57987
|
throw new Error(
|
|
56628
57988
|
"Missing search query. Usage: openmates chats search <query>"
|
|
56629
57989
|
);
|
|
56630
|
-
const result = client.hasSession() ? await client.searchChats(query) : searchExampleChats(query);
|
|
57990
|
+
const result = apiKey ? await searchApiKeyChats(client, apiKey, query) : client.hasSession() ? await client.searchChats(query) : searchExampleChats(query);
|
|
56631
57991
|
if (flags.json === true) {
|
|
56632
57992
|
printJson2(result);
|
|
56633
57993
|
} else {
|
|
@@ -56647,7 +58007,7 @@ async function handleChats(client, subcommand, rest, flags, redactor) {
|
|
|
56647
58007
|
throw new Error(
|
|
56648
58008
|
"Missing message text. Usage: openmates chats new <message>"
|
|
56649
58009
|
);
|
|
56650
|
-
const result = await sendMessageStreaming(
|
|
58010
|
+
const result = apiKey ? await sendApiKeyChatNew(client, apiKey, message, flags) : await sendMessageStreaming(
|
|
56651
58011
|
client,
|
|
56652
58012
|
{
|
|
56653
58013
|
message,
|
|
@@ -56887,7 +58247,14 @@ Run 'openmates chats show ` + chatId + "' to check if suggestions have been save
|
|
|
56887
58247
|
let deleted = 0;
|
|
56888
58248
|
for (const r of resolved) {
|
|
56889
58249
|
try {
|
|
56890
|
-
|
|
58250
|
+
if (apiKey) {
|
|
58251
|
+
await new OpenMates({ apiKey, apiUrl: client.apiUrl }).chats.delete(
|
|
58252
|
+
r.input,
|
|
58253
|
+
{ confirmed: true }
|
|
58254
|
+
);
|
|
58255
|
+
} else {
|
|
58256
|
+
await client.deleteChat(r.input);
|
|
58257
|
+
}
|
|
56891
58258
|
const label = r.title ? `"${r.title}"` : r.input;
|
|
56892
58259
|
process.stdout.write(` \x1B[32m\u2713\x1B[0m Deleted ${label}
|
|
56893
58260
|
`);
|
|
@@ -57035,16 +58402,16 @@ ${deleted}/${resolved.length} chat(s) deleted.`);
|
|
|
57035
58402
|
}
|
|
57036
58403
|
}
|
|
57037
58404
|
const { mkdir, writeFile } = await import("fs/promises");
|
|
57038
|
-
const { join:
|
|
58405
|
+
const { join: join7 } = await import("path");
|
|
57039
58406
|
if (useZip) {
|
|
57040
|
-
const tmpDir =
|
|
58407
|
+
const tmpDir = join7(outputDir, `.${filenameBase}_tmp`);
|
|
57041
58408
|
await mkdir(tmpDir, { recursive: true });
|
|
57042
|
-
await writeFile(
|
|
57043
|
-
await writeFile(
|
|
58409
|
+
await writeFile(join7(tmpDir, `${filenameBase}.yml`), yamlContent);
|
|
58410
|
+
await writeFile(join7(tmpDir, `${filenameBase}.md`), mdContent);
|
|
57044
58411
|
if (codeEmbeds.length > 0) {
|
|
57045
58412
|
for (const ce of codeEmbeds) {
|
|
57046
58413
|
const fpath = ce.filePath ?? ce.filename ?? `${ce.embedId.slice(0, 8)}.${getExtForLang(ce.language)}`;
|
|
57047
|
-
const fullPath =
|
|
58414
|
+
const fullPath = join7(tmpDir, "code", fpath);
|
|
57048
58415
|
await mkdir(fullPath.substring(0, fullPath.lastIndexOf("/")), {
|
|
57049
58416
|
recursive: true
|
|
57050
58417
|
});
|
|
@@ -57052,13 +58419,13 @@ ${deleted}/${resolved.length} chat(s) deleted.`);
|
|
|
57052
58419
|
}
|
|
57053
58420
|
}
|
|
57054
58421
|
if (transcriptEmbeds.length > 0) {
|
|
57055
|
-
const tDir =
|
|
58422
|
+
const tDir = join7(tmpDir, "transcripts");
|
|
57056
58423
|
await mkdir(tDir, { recursive: true });
|
|
57057
58424
|
for (const te of transcriptEmbeds) {
|
|
57058
|
-
await writeFile(
|
|
58425
|
+
await writeFile(join7(tDir, te.filename), te.content);
|
|
57059
58426
|
}
|
|
57060
58427
|
}
|
|
57061
|
-
const zipPath =
|
|
58428
|
+
const zipPath = join7(outputDir, `${filenameBase}.zip`);
|
|
57062
58429
|
const { execSync: execSync2 } = await import("child_process");
|
|
57063
58430
|
try {
|
|
57064
58431
|
execSync2(`cd "${tmpDir}" && zip -r "${zipPath}" .`, { stdio: "pipe" });
|
|
@@ -57073,17 +58440,17 @@ ${deleted}/${resolved.length} chat(s) deleted.`);
|
|
|
57073
58440
|
);
|
|
57074
58441
|
}
|
|
57075
58442
|
} else {
|
|
57076
|
-
const chatDir =
|
|
58443
|
+
const chatDir = join7(outputDir, filenameBase);
|
|
57077
58444
|
await mkdir(chatDir, { recursive: true });
|
|
57078
58445
|
const written = [];
|
|
57079
|
-
await writeFile(
|
|
58446
|
+
await writeFile(join7(chatDir, `${filenameBase}.yml`), yamlContent);
|
|
57080
58447
|
written.push(`${filenameBase}.yml`);
|
|
57081
|
-
await writeFile(
|
|
58448
|
+
await writeFile(join7(chatDir, `${filenameBase}.md`), mdContent);
|
|
57082
58449
|
written.push(`${filenameBase}.md`);
|
|
57083
58450
|
if (codeEmbeds.length > 0) {
|
|
57084
58451
|
for (const ce of codeEmbeds) {
|
|
57085
58452
|
const fpath = ce.filePath ?? ce.filename ?? `${ce.embedId.slice(0, 8)}.${getExtForLang(ce.language)}`;
|
|
57086
|
-
const fullPath =
|
|
58453
|
+
const fullPath = join7(chatDir, "code", fpath);
|
|
57087
58454
|
await mkdir(fullPath.substring(0, fullPath.lastIndexOf("/")), {
|
|
57088
58455
|
recursive: true
|
|
57089
58456
|
});
|
|
@@ -57092,10 +58459,10 @@ ${deleted}/${resolved.length} chat(s) deleted.`);
|
|
|
57092
58459
|
}
|
|
57093
58460
|
}
|
|
57094
58461
|
if (transcriptEmbeds.length > 0) {
|
|
57095
|
-
const tDir =
|
|
58462
|
+
const tDir = join7(chatDir, "transcripts");
|
|
57096
58463
|
await mkdir(tDir, { recursive: true });
|
|
57097
58464
|
for (const te of transcriptEmbeds) {
|
|
57098
|
-
await writeFile(
|
|
58465
|
+
await writeFile(join7(tDir, te.filename), te.content);
|
|
57099
58466
|
written.push(`transcripts/${te.filename}`);
|
|
57100
58467
|
}
|
|
57101
58468
|
}
|
|
@@ -57131,7 +58498,7 @@ ${deleted}/${resolved.length} chat(s) deleted.`);
|
|
|
57131
58498
|
printJson2({
|
|
57132
58499
|
chat_id: chat.id,
|
|
57133
58500
|
title: chat.title,
|
|
57134
|
-
output_dir: useZip ?
|
|
58501
|
+
output_dir: useZip ? join7(outputDir, `${filenameBase}.zip`) : join7(outputDir, filenameBase),
|
|
57135
58502
|
files,
|
|
57136
58503
|
code_embeds: codeEmbeds.length,
|
|
57137
58504
|
transcript_embeds: transcriptEmbeds.length
|
|
@@ -57256,6 +58623,109 @@ ${deleted}/${resolved.length} chat(s) deleted.`);
|
|
|
57256
58623
|
printChatsHelp();
|
|
57257
58624
|
process.exit(1);
|
|
57258
58625
|
}
|
|
58626
|
+
async function listApiKeyChats(client, apiKey, limit, page) {
|
|
58627
|
+
const safeLimit = Number.isFinite(limit) && limit > 0 ? limit : 10;
|
|
58628
|
+
const safePage = Number.isFinite(page) && page > 0 ? page : 1;
|
|
58629
|
+
const sdk = new OpenMates({ apiKey, apiUrl: client.apiUrl });
|
|
58630
|
+
const chats = await sdk.chats.list({ limit: safeLimit, offset: (safePage - 1) * safeLimit });
|
|
58631
|
+
return sdkChatsToChatListPage(chats, safeLimit, safePage);
|
|
58632
|
+
}
|
|
58633
|
+
async function searchApiKeyChats(client, apiKey, query) {
|
|
58634
|
+
const sdk = new OpenMates({ apiKey, apiUrl: client.apiUrl });
|
|
58635
|
+
const chats = await sdk.chats.search(query, { limit: 0 });
|
|
58636
|
+
return sdkChatsToChatListPage(chats, chats.length || 1, 1).chats;
|
|
58637
|
+
}
|
|
58638
|
+
function sdkChatsToChatListPage(chats, limit, page) {
|
|
58639
|
+
return {
|
|
58640
|
+
chats: chats.map((chat) => {
|
|
58641
|
+
const category = typeof chat.category === "string" ? chat.category : null;
|
|
58642
|
+
return {
|
|
58643
|
+
id: chat.id,
|
|
58644
|
+
shortId: chat.id.slice(0, 8),
|
|
58645
|
+
title: typeof chat.title === "string" ? chat.title : null,
|
|
58646
|
+
summary: typeof chat.chat_summary === "string" ? chat.chat_summary : null,
|
|
58647
|
+
updatedAt: normalizeSdkTimestamp(chat.updated_at),
|
|
58648
|
+
category,
|
|
58649
|
+
mateName: category ? MATE_NAMES[category] ?? null : null
|
|
58650
|
+
};
|
|
58651
|
+
}),
|
|
58652
|
+
total: chats.length,
|
|
58653
|
+
page,
|
|
58654
|
+
limit,
|
|
58655
|
+
hasMore: chats.length >= limit
|
|
58656
|
+
};
|
|
58657
|
+
}
|
|
58658
|
+
function normalizeSdkTimestamp(value) {
|
|
58659
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
58660
|
+
if (typeof value === "string" && value.trim()) {
|
|
58661
|
+
const parsed = Date.parse(value);
|
|
58662
|
+
return Number.isFinite(parsed) ? Math.floor(parsed / 1e3) : null;
|
|
58663
|
+
}
|
|
58664
|
+
return null;
|
|
58665
|
+
}
|
|
58666
|
+
async function sendApiKeyChatNew(client, apiKey, message, flags) {
|
|
58667
|
+
const sdk = new OpenMates({ apiKey, apiUrl: client.apiUrl });
|
|
58668
|
+
const response = await sdk.chats.send(message, {
|
|
58669
|
+
saveToAccount: false
|
|
58670
|
+
});
|
|
58671
|
+
const result = normalizeApiKeyChatResponse(response);
|
|
58672
|
+
if (flags.json !== true) {
|
|
58673
|
+
const category = typeof result.category === "string" ? result.category : null;
|
|
58674
|
+
const modelName = typeof result.modelName === "string" ? result.modelName : null;
|
|
58675
|
+
const mateBlock = ansiMateBlock(category, category ? MATE_NAMES[category] ?? null : null);
|
|
58676
|
+
const modelSuffix = modelName ? ` \x1B[2m${modelName}\x1B[0m` : "";
|
|
58677
|
+
process.stdout.write(`${SEP}
|
|
58678
|
+
`);
|
|
58679
|
+
process.stdout.write(`${mateBlock}${modelSuffix}
|
|
58680
|
+
`);
|
|
58681
|
+
process.stdout.write(`${SEP}
|
|
58682
|
+
`);
|
|
58683
|
+
process.stdout.write(`${String(result.assistant ?? "")}
|
|
58684
|
+
`);
|
|
58685
|
+
const chatId = typeof result.chatId === "string" ? result.chatId : null;
|
|
58686
|
+
if (chatId) {
|
|
58687
|
+
const shortId = chatId.slice(0, 8);
|
|
58688
|
+
process.stdout.write(`${SEP}
|
|
58689
|
+
`);
|
|
58690
|
+
process.stdout.write(
|
|
58691
|
+
`\x1B[2mContinue: openmates chats send --chat ${shortId} "your message"\x1B[0m
|
|
58692
|
+
\x1B[2mHistory: openmates chats show ${shortId}\x1B[0m
|
|
58693
|
+
`
|
|
58694
|
+
);
|
|
58695
|
+
}
|
|
58696
|
+
}
|
|
58697
|
+
return result;
|
|
58698
|
+
}
|
|
58699
|
+
function normalizeApiKeyChatResponse(response) {
|
|
58700
|
+
const chatId = typeof response.chat_id === "string" ? response.chat_id : null;
|
|
58701
|
+
const category = typeof response.category === "string" ? response.category : null;
|
|
58702
|
+
const modelName = typeof response.model_name === "string" ? response.model_name : null;
|
|
58703
|
+
return {
|
|
58704
|
+
status: "completed",
|
|
58705
|
+
chatId,
|
|
58706
|
+
chat_id: chatId,
|
|
58707
|
+
messageId: null,
|
|
58708
|
+
message_id: null,
|
|
58709
|
+
assistant: typeof response.content === "string" ? response.content : "",
|
|
58710
|
+
category,
|
|
58711
|
+
modelName,
|
|
58712
|
+
model_name: modelName,
|
|
58713
|
+
mateName: category ? MATE_NAMES[category] ?? null : null,
|
|
58714
|
+
followUpSuggestions: [],
|
|
58715
|
+
follow_up_suggestions: [],
|
|
58716
|
+
taskEvents: [],
|
|
58717
|
+
task_events: [],
|
|
58718
|
+
pendingTaskUpdateJobs: [],
|
|
58719
|
+
pending_task_update_jobs: [],
|
|
58720
|
+
subChatEvents: [],
|
|
58721
|
+
sub_chat_events: [],
|
|
58722
|
+
appSettingsMemoryRequests: [],
|
|
58723
|
+
app_settings_memory_requests: [],
|
|
58724
|
+
acceptedTaskProposals: [],
|
|
58725
|
+
accepted_task_proposals: [],
|
|
58726
|
+
raw: response
|
|
58727
|
+
};
|
|
58728
|
+
}
|
|
57259
58729
|
function resolveExampleChatForOpen(target) {
|
|
57260
58730
|
const numericTarget = parseInt(target, 10);
|
|
57261
58731
|
if (!Number.isNaN(numericTarget) && String(numericTarget) === target.trim()) {
|
|
@@ -57302,7 +58772,7 @@ async function handleWorkflows(client, subcommand, rest, flags) {
|
|
|
57302
58772
|
if (subcommand === "validate") {
|
|
57303
58773
|
const file = typeof flags.file === "string" ? flags.file : "";
|
|
57304
58774
|
if (!file) throw new Error("Missing --file. Example: openmates workflows validate --file workflow.yml");
|
|
57305
|
-
const validation = await client.validateWorkflowYaml(
|
|
58775
|
+
const validation = await client.validateWorkflowYaml(readFileSync10(file, "utf8"));
|
|
57306
58776
|
if (flags.json === true) {
|
|
57307
58777
|
printJson2(validation);
|
|
57308
58778
|
} else {
|
|
@@ -57318,7 +58788,7 @@ async function handleWorkflows(client, subcommand, rest, flags) {
|
|
|
57318
58788
|
if (subcommand === "create") {
|
|
57319
58789
|
const yamlFile = typeof flags.file === "string" ? flags.file : "";
|
|
57320
58790
|
if (yamlFile) {
|
|
57321
|
-
const result = await client.createWorkflowYaml(
|
|
58791
|
+
const result = await client.createWorkflowYaml(readFileSync10(yamlFile, "utf8"));
|
|
57322
58792
|
if (flags.json === true) {
|
|
57323
58793
|
printJson2(result);
|
|
57324
58794
|
} else {
|
|
@@ -57351,7 +58821,7 @@ async function handleWorkflows(client, subcommand, rest, flags) {
|
|
|
57351
58821
|
const workflowId = rest[0];
|
|
57352
58822
|
const yamlFile = typeof flags.file === "string" ? flags.file : "";
|
|
57353
58823
|
if (!workflowId || !yamlFile) throw new Error("Missing workflow ID or --file. Example: openmates workflows update <id> --file workflow.yml");
|
|
57354
|
-
const result = await client.updateWorkflowYaml(workflowId,
|
|
58824
|
+
const result = await client.updateWorkflowYaml(workflowId, readFileSync10(yamlFile, "utf8"));
|
|
57355
58825
|
if (flags.json === true) {
|
|
57356
58826
|
printJson2(result);
|
|
57357
58827
|
} else {
|
|
@@ -58470,7 +59940,7 @@ async function handleEmbeds(client, subcommand, rest, flags) {
|
|
|
58470
59940
|
throw new Error("Embed version content was not available after local reconstruction.");
|
|
58471
59941
|
}
|
|
58472
59942
|
if (typeof flags.output === "string") {
|
|
58473
|
-
|
|
59943
|
+
writeFileSync7(flags.output, result.content, "utf-8");
|
|
58474
59944
|
if (flags.json === true) {
|
|
58475
59945
|
printJson2({ ...result, output: flags.output });
|
|
58476
59946
|
} else {
|
|
@@ -58912,11 +60382,11 @@ function parseYamlScalar(value) {
|
|
|
58912
60382
|
}
|
|
58913
60383
|
async function saveDownloadedDocument(document, output) {
|
|
58914
60384
|
const { mkdir, writeFile } = await import("fs/promises");
|
|
58915
|
-
const { join:
|
|
60385
|
+
const { join: join7, basename: basename4, dirname: dirname5 } = await import("path");
|
|
58916
60386
|
const target = typeof output === "string" ? output : ".";
|
|
58917
60387
|
const filename = basename4(document.filename || "document.pdf");
|
|
58918
|
-
const filePath = target.endsWith(".pdf") ? target :
|
|
58919
|
-
await mkdir(
|
|
60388
|
+
const filePath = target.endsWith(".pdf") ? target : join7(target, filename);
|
|
60389
|
+
await mkdir(dirname5(filePath), { recursive: true });
|
|
58920
60390
|
await writeFile(filePath, document.data);
|
|
58921
60391
|
return filePath;
|
|
58922
60392
|
}
|
|
@@ -59073,7 +60543,7 @@ async function promptPlainText(question) {
|
|
|
59073
60543
|
}
|
|
59074
60544
|
async function writeSecretFile(filePath, content, force = false) {
|
|
59075
60545
|
const { mkdir, writeFile, stat: stat2 } = await import("fs/promises");
|
|
59076
|
-
const { dirname:
|
|
60546
|
+
const { dirname: dirname5 } = await import("path");
|
|
59077
60547
|
try {
|
|
59078
60548
|
await stat2(filePath);
|
|
59079
60549
|
if (!force) throw new Error(`${filePath} already exists. Use --force to overwrite.`);
|
|
@@ -59083,13 +60553,13 @@ async function writeSecretFile(filePath, content, force = false) {
|
|
|
59083
60553
|
}
|
|
59084
60554
|
if (error instanceof Error && !("code" in error)) throw error;
|
|
59085
60555
|
}
|
|
59086
|
-
await mkdir(
|
|
60556
|
+
await mkdir(dirname5(filePath), { recursive: true });
|
|
59087
60557
|
await writeFile(filePath, content, { mode: 384 });
|
|
59088
60558
|
return filePath;
|
|
59089
60559
|
}
|
|
59090
60560
|
async function generateProvisioningPassword() {
|
|
59091
|
-
const { randomBytes:
|
|
59092
|
-
return `OM-${
|
|
60561
|
+
const { randomBytes: randomBytes5 } = await import("crypto");
|
|
60562
|
+
return `OM-${randomBytes5(18).toString("base64url")}-aA2#`;
|
|
59093
60563
|
}
|
|
59094
60564
|
function decodeBase32(input) {
|
|
59095
60565
|
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
|
@@ -62574,7 +64044,7 @@ async function handleDocs(client, subcommand, rest, flags) {
|
|
|
62574
64044
|
}
|
|
62575
64045
|
if (subcommand === "download") {
|
|
62576
64046
|
const { writeFile, mkdir } = await import("fs/promises");
|
|
62577
|
-
const { join:
|
|
64047
|
+
const { join: join7, dirname: dirname5 } = await import("path");
|
|
62578
64048
|
if (flags.all === true) {
|
|
62579
64049
|
const outputDir = typeof flags.output === "string" ? flags.output : "./openmates-docs";
|
|
62580
64050
|
const tree = await client.listDocs();
|
|
@@ -62583,8 +64053,8 @@ async function handleDocs(client, subcommand, rest, flags) {
|
|
|
62583
64053
|
let count = 0;
|
|
62584
64054
|
for (const slug2 of slugs) {
|
|
62585
64055
|
const content2 = await client.getDoc(slug2);
|
|
62586
|
-
const filePath =
|
|
62587
|
-
await mkdir(
|
|
64056
|
+
const filePath = join7(outputDir, `${slug2}.md`);
|
|
64057
|
+
await mkdir(dirname5(filePath), { recursive: true });
|
|
62588
64058
|
await writeFile(filePath, content2, "utf-8");
|
|
62589
64059
|
count++;
|
|
62590
64060
|
process.stderr.write(`\r Downloaded ${count}/${slugs.length}`);
|
|
@@ -62657,7 +64127,7 @@ function isCliEntrypoint() {
|
|
|
62657
64127
|
try {
|
|
62658
64128
|
const invokedPath = realpathSync(entrypoint);
|
|
62659
64129
|
const modulePath = realpathSync(fileURLToPath2(import.meta.url));
|
|
62660
|
-
return invokedPath === modulePath || basename3(invokedPath) === "cli.js" &&
|
|
64130
|
+
return invokedPath === modulePath || basename3(invokedPath) === "cli.js" && dirname4(invokedPath) === dirname4(modulePath);
|
|
62661
64131
|
} catch {
|
|
62662
64132
|
return false;
|
|
62663
64133
|
}
|
|
@@ -62671,21 +64141,6 @@ if (isCliEntrypoint()) {
|
|
|
62671
64141
|
}
|
|
62672
64142
|
|
|
62673
64143
|
export {
|
|
62674
|
-
deriveChatCompletionRecoveryKeypair,
|
|
62675
|
-
openChatCompletionRecoveryEnvelope,
|
|
62676
|
-
unwrapApiKeyMasterKey,
|
|
62677
|
-
decryptWithAesGcmCombined,
|
|
62678
|
-
decryptBytesWithAesGcm,
|
|
62679
|
-
encryptBytesWithAesGcm,
|
|
62680
|
-
encryptWithAesGcmCombined,
|
|
62681
|
-
hashItemKey,
|
|
62682
|
-
generateChatShareBlob,
|
|
62683
|
-
generateEmbedShareBlob,
|
|
62684
|
-
deriveWebOrigin,
|
|
62685
|
-
buildChatShareUrl,
|
|
62686
|
-
buildEmbedShareUrl,
|
|
62687
|
-
decryptConnectedAccountCliTransferPayload,
|
|
62688
|
-
buildEncryptedConnectedAccountImportRow,
|
|
62689
64144
|
INTEREST_TAG_IDS,
|
|
62690
64145
|
normalizeInterestTagIds,
|
|
62691
64146
|
MEMORY_TYPE_REGISTRY,
|
|
@@ -62694,7 +64149,9 @@ export {
|
|
|
62694
64149
|
deriveAppUrl,
|
|
62695
64150
|
OpenMatesClient,
|
|
62696
64151
|
APP_SKILL_METADATA,
|
|
62697
|
-
|
|
64152
|
+
OpenMatesConfigError,
|
|
64153
|
+
OpenMatesApiError,
|
|
64154
|
+
OpenMates,
|
|
62698
64155
|
SUPPORT_URL,
|
|
62699
64156
|
renderSupportInfo,
|
|
62700
64157
|
defaultCloneBranchForVersion,
|