openmates 0.15.0-alpha.36 → 0.15.0-alpha.38
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.
|
@@ -1739,13 +1739,6 @@ var OpenMatesWsClient = class {
|
|
|
1739
1739
|
});
|
|
1740
1740
|
return;
|
|
1741
1741
|
}
|
|
1742
|
-
if (options?.recoveryTurnId && recoveryJobId && aiResponseDone && !postProcessingDone) {
|
|
1743
|
-
if (postProcessingTimer) {
|
|
1744
|
-
clearTimeout(postProcessingTimer);
|
|
1745
|
-
postProcessingTimer = null;
|
|
1746
|
-
}
|
|
1747
|
-
postProcessingDone = true;
|
|
1748
|
-
}
|
|
1749
1742
|
if (!aiResponseDone || !postProcessingDone) return;
|
|
1750
1743
|
if (options?.recoveryTurnId && !recoveryJobId) return;
|
|
1751
1744
|
if (pendingSubChatHandlers.size > 0) return;
|
|
@@ -21795,6 +21788,243 @@ function redactUrl(rawUrl) {
|
|
|
21795
21788
|
return url.toString();
|
|
21796
21789
|
}
|
|
21797
21790
|
|
|
21791
|
+
// src/accountExportArchive.ts
|
|
21792
|
+
var ACCOUNT_EXPORT_FORBIDDEN_FIELD_NAMES = /* @__PURE__ */ new Set([
|
|
21793
|
+
"access_token",
|
|
21794
|
+
"api_key",
|
|
21795
|
+
"backup_code_hash",
|
|
21796
|
+
"encrypted_master_key",
|
|
21797
|
+
"lookup_hash",
|
|
21798
|
+
"password_hash",
|
|
21799
|
+
"private_key",
|
|
21800
|
+
"raw_key",
|
|
21801
|
+
"refresh_token",
|
|
21802
|
+
"share_key",
|
|
21803
|
+
"signing_secret",
|
|
21804
|
+
"token_hash",
|
|
21805
|
+
"totp_seed",
|
|
21806
|
+
"webhook_secret"
|
|
21807
|
+
]);
|
|
21808
|
+
var ACCOUNT_EXPORT_REDACTION_CATEGORIES = [
|
|
21809
|
+
"api_credentials",
|
|
21810
|
+
"authentication_tokens",
|
|
21811
|
+
"key_material",
|
|
21812
|
+
"password_and_recovery_hashes",
|
|
21813
|
+
"webhook_secrets"
|
|
21814
|
+
];
|
|
21815
|
+
var ACCOUNT_EXPORT_FORBIDDEN_VALUE_PATTERNS = [
|
|
21816
|
+
/-----BEGIN [A-Z ]*PRIVATE KEY-----/,
|
|
21817
|
+
/(?:^|[^a-z0-9])sk-(?:api|proj|live|test)[-_a-z0-9]{6,}/i,
|
|
21818
|
+
/#key=[A-Za-z0-9_-]{8,}/
|
|
21819
|
+
];
|
|
21820
|
+
async function writeAccountExportArchive(bundle, flags = {}) {
|
|
21821
|
+
const { mkdir: mkdir2, mkdtemp, rm, writeFile: writeFile2 } = await import("fs/promises");
|
|
21822
|
+
const { tmpdir: tmpdir2 } = await import("os");
|
|
21823
|
+
const { execFileSync: execFileSync3 } = await import("child_process");
|
|
21824
|
+
const { join: join7, dirname: dirname6 } = await import("path");
|
|
21825
|
+
const exportId = safeArchiveSegment(String(bundle.export.export_id ?? `export-${Date.now()}`));
|
|
21826
|
+
const archiveFormat = flags.format === "directory" ? "directory" : "zip";
|
|
21827
|
+
const outputPath = typeof flags.output === "string" ? flags.output : join7(process.cwd(), archiveFormat === "zip" ? `openmates-account-export-${exportId}.zip` : `openmates-account-export-${exportId}`);
|
|
21828
|
+
const stagingDir = archiveFormat === "directory" ? outputPath : await mkdtemp(join7(tmpdir2(), `openmates-account-export-${exportId}-`));
|
|
21829
|
+
const writtenFiles = [];
|
|
21830
|
+
async function writeArchiveText(relativePath, content) {
|
|
21831
|
+
assertAccountExportTextSafe(content, relativePath);
|
|
21832
|
+
const fullPath = join7(stagingDir, relativePath);
|
|
21833
|
+
await mkdir2(dirname6(fullPath), { recursive: true });
|
|
21834
|
+
await writeFile2(fullPath, content, "utf-8");
|
|
21835
|
+
writtenFiles.push(relativePath);
|
|
21836
|
+
}
|
|
21837
|
+
await writeArchiveText("README.md", buildAccountExportReadme(bundle));
|
|
21838
|
+
await writeArchiveText("manifest.yml", serializeArchiveYaml(bundle.manifest));
|
|
21839
|
+
await writeArchiveText("manifest.json", `${JSON.stringify(bundle.manifest, null, 2)}
|
|
21840
|
+
`);
|
|
21841
|
+
await writeArchiveText("export-report.yml", serializeArchiveYaml(buildAccountExportReport(bundle)));
|
|
21842
|
+
const domainPayloads = collectAccountExportDomainPayloads(bundle.chunks);
|
|
21843
|
+
for (const [domain, payloads] of Object.entries(domainPayloads)) {
|
|
21844
|
+
const domainFile = payloads.length === 1 ? payloads[0] : { chunks: payloads };
|
|
21845
|
+
await writeArchiveText(`domains/${safeArchiveSegment(domain)}.json`, `${JSON.stringify(domainFile, null, 2)}
|
|
21846
|
+
`);
|
|
21847
|
+
}
|
|
21848
|
+
await writeAccountExportChatFiles(domainPayloads.chats ?? [], writeArchiveText);
|
|
21849
|
+
if (archiveFormat === "directory") return { output: outputPath, format: "directory", files: writtenFiles.length };
|
|
21850
|
+
await mkdir2(dirname6(outputPath), { recursive: true });
|
|
21851
|
+
try {
|
|
21852
|
+
execFileSync3("zip", ["-r", outputPath, "."], { cwd: stagingDir, stdio: "pipe" });
|
|
21853
|
+
return { output: outputPath, format: "zip", files: writtenFiles.length };
|
|
21854
|
+
} finally {
|
|
21855
|
+
await rm(stagingDir, { recursive: true, force: true });
|
|
21856
|
+
}
|
|
21857
|
+
}
|
|
21858
|
+
function assertAccountExportPayloadSafe(value, path = "$export") {
|
|
21859
|
+
if (value === null || value === void 0) return;
|
|
21860
|
+
if (typeof value === "string") {
|
|
21861
|
+
for (const pattern of ACCOUNT_EXPORT_FORBIDDEN_VALUE_PATTERNS) {
|
|
21862
|
+
if (pattern.test(value)) throw new Error(`Account export contains forbidden secret-like value at ${path}`);
|
|
21863
|
+
}
|
|
21864
|
+
return;
|
|
21865
|
+
}
|
|
21866
|
+
if (typeof value !== "object") return;
|
|
21867
|
+
if (Array.isArray(value)) {
|
|
21868
|
+
value.forEach((item, index) => assertAccountExportPayloadSafe(item, `${path}[${index}]`));
|
|
21869
|
+
return;
|
|
21870
|
+
}
|
|
21871
|
+
for (const [key, child] of Object.entries(value)) {
|
|
21872
|
+
const normalizedKey = key.toLowerCase();
|
|
21873
|
+
if (ACCOUNT_EXPORT_FORBIDDEN_FIELD_NAMES.has(normalizedKey)) {
|
|
21874
|
+
throw new Error(`Account export contains forbidden secret field '${key}' at ${path}`);
|
|
21875
|
+
}
|
|
21876
|
+
assertAccountExportPayloadSafe(child, `${path}.${key}`);
|
|
21877
|
+
}
|
|
21878
|
+
}
|
|
21879
|
+
function sanitizeAccountExportManifest(manifest) {
|
|
21880
|
+
const copy = JSON.parse(JSON.stringify(manifest));
|
|
21881
|
+
const report = copy.report;
|
|
21882
|
+
if (report && typeof report === "object" && !Array.isArray(report)) {
|
|
21883
|
+
const reportObject = report;
|
|
21884
|
+
if (Array.isArray(reportObject.redactions)) {
|
|
21885
|
+
reportObject.redactions = ACCOUNT_EXPORT_REDACTION_CATEGORIES;
|
|
21886
|
+
}
|
|
21887
|
+
}
|
|
21888
|
+
assertAccountExportPayloadSafe(copy, "$manifest");
|
|
21889
|
+
return copy;
|
|
21890
|
+
}
|
|
21891
|
+
function assertAccountExportTextSafe(content, relativePath) {
|
|
21892
|
+
for (const pattern of ACCOUNT_EXPORT_FORBIDDEN_VALUE_PATTERNS) {
|
|
21893
|
+
if (pattern.test(content)) throw new Error(`Account export file ${relativePath} contains forbidden secret-like content`);
|
|
21894
|
+
}
|
|
21895
|
+
for (const field of ACCOUNT_EXPORT_FORBIDDEN_FIELD_NAMES) {
|
|
21896
|
+
if (new RegExp(`"?${field}"?\\s*:`, "i").test(content)) {
|
|
21897
|
+
throw new Error(`Account export file ${relativePath} contains forbidden secret field '${field}'`);
|
|
21898
|
+
}
|
|
21899
|
+
}
|
|
21900
|
+
}
|
|
21901
|
+
function buildAccountExportReadme(bundle) {
|
|
21902
|
+
const selectedDomains = Array.isArray(bundle.manifest.selected_domains) ? bundle.manifest.selected_domains.map(String) : [];
|
|
21903
|
+
return [
|
|
21904
|
+
"# OpenMates Account Export",
|
|
21905
|
+
"",
|
|
21906
|
+
`Export ID: ${String(bundle.export.export_id ?? "unknown")}`,
|
|
21907
|
+
`Status: ${String(bundle.export.status ?? "unknown")}`,
|
|
21908
|
+
`Schema: ${String(bundle.manifest.schema_version ?? "account-export-v1")}`,
|
|
21909
|
+
`Exported at: ${(/* @__PURE__ */ new Date()).toISOString()}`,
|
|
21910
|
+
"",
|
|
21911
|
+
"## Contents",
|
|
21912
|
+
"",
|
|
21913
|
+
"- `manifest.yml` records selected domains, filters, and domain status.",
|
|
21914
|
+
"- `export-report.yml` summarizes completion, failures, and redacted categories.",
|
|
21915
|
+
"- `domains/` contains one JSON file per exported domain.",
|
|
21916
|
+
"- `chats/` contains one Markdown and one YAML file per chat when chat rows include readable content.",
|
|
21917
|
+
"",
|
|
21918
|
+
"## Selected Domains",
|
|
21919
|
+
"",
|
|
21920
|
+
...selectedDomains.length > 0 ? selectedDomains.map((domain) => `- ${domain}`) : ["- none"],
|
|
21921
|
+
"",
|
|
21922
|
+
"Reusable credentials, token hashes, private keys, and raw secrets are intentionally excluded.",
|
|
21923
|
+
""
|
|
21924
|
+
].join("\n");
|
|
21925
|
+
}
|
|
21926
|
+
function buildAccountExportReport(bundle) {
|
|
21927
|
+
const report = bundle.manifest.report && typeof bundle.manifest.report === "object" && !Array.isArray(bundle.manifest.report) ? bundle.manifest.report : {};
|
|
21928
|
+
return {
|
|
21929
|
+
export_id: bundle.export.export_id ?? null,
|
|
21930
|
+
status: bundle.export.status ?? report.status ?? "unknown",
|
|
21931
|
+
selected_domains: Array.isArray(bundle.manifest.selected_domains) ? bundle.manifest.selected_domains : [],
|
|
21932
|
+
failures: Array.isArray(report.failures) ? report.failures : [],
|
|
21933
|
+
redacted_secret_categories: ACCOUNT_EXPORT_REDACTION_CATEGORIES,
|
|
21934
|
+
partial_requires_acceptance: Boolean(report.partial_requires_acceptance)
|
|
21935
|
+
};
|
|
21936
|
+
}
|
|
21937
|
+
function collectAccountExportDomainPayloads(chunks) {
|
|
21938
|
+
const grouped = {};
|
|
21939
|
+
for (const chunk of chunks) {
|
|
21940
|
+
const domain = safeArchiveSegment(String(chunk.domain ?? "unknown"));
|
|
21941
|
+
const payload = chunk.payload && typeof chunk.payload === "object" && !Array.isArray(chunk.payload) ? chunk.payload : { value: chunk.payload ?? null };
|
|
21942
|
+
grouped[domain] = grouped[domain] ?? [];
|
|
21943
|
+
grouped[domain].push({
|
|
21944
|
+
chunk_id: chunk.chunk_id ?? null,
|
|
21945
|
+
sequence: chunk.sequence ?? null,
|
|
21946
|
+
status: chunk.status ?? null,
|
|
21947
|
+
...payload
|
|
21948
|
+
});
|
|
21949
|
+
}
|
|
21950
|
+
return grouped;
|
|
21951
|
+
}
|
|
21952
|
+
async function writeAccountExportChatFiles(chatPayloads, writeArchiveText) {
|
|
21953
|
+
const chats = [];
|
|
21954
|
+
for (const payload of chatPayloads) {
|
|
21955
|
+
if (Array.isArray(payload.items)) {
|
|
21956
|
+
chats.push(...payload.items.filter((item) => item !== null && typeof item === "object" && !Array.isArray(item)));
|
|
21957
|
+
}
|
|
21958
|
+
}
|
|
21959
|
+
for (const [index, chat] of chats.entries()) {
|
|
21960
|
+
const chatId = safeArchiveSegment(String(chat.id ?? chat.chat_id ?? `chat-${index + 1}`));
|
|
21961
|
+
await writeArchiveText(`chats/${chatId}.yml`, serializeArchiveYaml({ chat, messages: Array.isArray(chat.messages) ? chat.messages : [] }));
|
|
21962
|
+
await writeArchiveText(`chats/${chatId}.md`, buildAccountExportChatMarkdown(chat));
|
|
21963
|
+
}
|
|
21964
|
+
}
|
|
21965
|
+
function buildAccountExportChatMarkdown(chat) {
|
|
21966
|
+
const title = String(chat.title ?? chat.name ?? chat.id ?? chat.chat_id ?? "Untitled Chat");
|
|
21967
|
+
const lines = [`# ${title}`, ""];
|
|
21968
|
+
if (typeof chat.summary === "string" && chat.summary.trim()) {
|
|
21969
|
+
lines.push("## Summary", "", chat.summary.trim(), "");
|
|
21970
|
+
}
|
|
21971
|
+
const messages = Array.isArray(chat.messages) ? chat.messages : [];
|
|
21972
|
+
if (messages.length > 0) {
|
|
21973
|
+
lines.push("## Messages", "");
|
|
21974
|
+
for (const message of messages) {
|
|
21975
|
+
if (!message || typeof message !== "object" || Array.isArray(message)) continue;
|
|
21976
|
+
const record = message;
|
|
21977
|
+
lines.push(`### ${String(record.role ?? record.sender ?? "message")}`, "", String(record.content ?? record.text ?? ""), "");
|
|
21978
|
+
}
|
|
21979
|
+
} else {
|
|
21980
|
+
lines.push("No readable message records were included in this export chunk.", "");
|
|
21981
|
+
}
|
|
21982
|
+
return `${lines.join("\n")}
|
|
21983
|
+
`;
|
|
21984
|
+
}
|
|
21985
|
+
function serializeArchiveYaml(data, indent = 0) {
|
|
21986
|
+
const pad2 = " ".repeat(indent);
|
|
21987
|
+
let out = "";
|
|
21988
|
+
for (const [key, val] of Object.entries(data)) {
|
|
21989
|
+
if (val === null || val === void 0) {
|
|
21990
|
+
out += `${pad2}${key}: null
|
|
21991
|
+
`;
|
|
21992
|
+
} else if (typeof val === "boolean" || typeof val === "number") {
|
|
21993
|
+
out += `${pad2}${key}: ${val}
|
|
21994
|
+
`;
|
|
21995
|
+
} else if (typeof val === "string") {
|
|
21996
|
+
out += val.includes("\n") ? `${pad2}${key}: |
|
|
21997
|
+
${val.split("\n").map((line) => `${pad2} ${line}`).join("\n")}
|
|
21998
|
+
` : `${pad2}${key}: ${quoteYamlString(val)}
|
|
21999
|
+
`;
|
|
22000
|
+
} else if (Array.isArray(val)) {
|
|
22001
|
+
out += `${pad2}${key}:
|
|
22002
|
+
`;
|
|
22003
|
+
for (const item of val) {
|
|
22004
|
+
if (item && typeof item === "object" && !Array.isArray(item)) {
|
|
22005
|
+
out += `${pad2}-
|
|
22006
|
+
${serializeArchiveYaml(item, indent + 2)}`;
|
|
22007
|
+
} else {
|
|
22008
|
+
out += `${pad2}- ${typeof item === "string" ? quoteYamlString(item) : String(item)}
|
|
22009
|
+
`;
|
|
22010
|
+
}
|
|
22011
|
+
}
|
|
22012
|
+
} else if (typeof val === "object") {
|
|
22013
|
+
out += `${pad2}${key}:
|
|
22014
|
+
${serializeArchiveYaml(val, indent + 1)}`;
|
|
22015
|
+
}
|
|
22016
|
+
}
|
|
22017
|
+
return out;
|
|
22018
|
+
}
|
|
22019
|
+
function quoteYamlString(value) {
|
|
22020
|
+
const needsQuote = value.includes(":") || value.includes("#") || value.startsWith("{") || value.startsWith("[") || value === "" || ["true", "false", "null"].includes(value);
|
|
22021
|
+
return needsQuote ? `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"` : value;
|
|
22022
|
+
}
|
|
22023
|
+
function safeArchiveSegment(value) {
|
|
22024
|
+
const cleaned = value.trim().replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
22025
|
+
return cleaned || "unknown";
|
|
22026
|
+
}
|
|
22027
|
+
|
|
21798
22028
|
// ../ui/src/demo_chats/data/example_chats/gigantic-airplanes.ts
|
|
21799
22029
|
var giganticAirplanesChat = {
|
|
21800
22030
|
chat_id: "example-gigantic-airplanes",
|
|
@@ -40092,6 +40322,15 @@ Only output the final Markdown table. Do NOT include explanations, notes, or any
|
|
|
40092
40322
|
new_chat: {
|
|
40093
40323
|
text: "New chat"
|
|
40094
40324
|
},
|
|
40325
|
+
ideabucket_badge: {
|
|
40326
|
+
text: "IdeaBucket"
|
|
40327
|
+
},
|
|
40328
|
+
ideabucket_draft: {
|
|
40329
|
+
text: "IdeaBucket draft"
|
|
40330
|
+
},
|
|
40331
|
+
ideabucket_input_pill: {
|
|
40332
|
+
text: "IdeaBucket for today"
|
|
40333
|
+
},
|
|
40095
40334
|
request_feature: {
|
|
40096
40335
|
text: "Request feature"
|
|
40097
40336
|
},
|
|
@@ -62969,26 +63208,44 @@ async function runAccountExport(client, flags) {
|
|
|
62969
63208
|
client.getAccountExportManifest(exportId),
|
|
62970
63209
|
client.listAccountExportChunks(exportId)
|
|
62971
63210
|
]);
|
|
62972
|
-
const
|
|
62973
|
-
|
|
63211
|
+
const downloadedChunks = [];
|
|
63212
|
+
try {
|
|
63213
|
+
for (const chunk of chunks.chunks) {
|
|
63214
|
+
const chunkId = String(chunk.chunk_id ?? "");
|
|
63215
|
+
const downloaded = chunkId ? await client.getAccountExportChunk(exportId, chunkId) : chunk;
|
|
63216
|
+
assertAccountExportPayloadSafe(downloaded);
|
|
63217
|
+
downloadedChunks.push(downloaded);
|
|
63218
|
+
}
|
|
63219
|
+
} catch (error) {
|
|
63220
|
+
await client.cancelAccountExport(exportId).catch(() => void 0);
|
|
63221
|
+
throw error;
|
|
63222
|
+
}
|
|
63223
|
+
let completed = await client.completeAccountExport(exportId);
|
|
63224
|
+
const completedStatus = String(completed.export.status ?? "");
|
|
63225
|
+
if (completedStatus === "partial") {
|
|
63226
|
+
if (flags["accept-partial"] !== true) {
|
|
63227
|
+
throw new Error(`Account export ${exportId} is partial. Re-run with --accept-partial to accept it, or inspect/cancel the job first.`);
|
|
63228
|
+
}
|
|
63229
|
+
completed = await client.acceptPartialAccountExport(exportId);
|
|
63230
|
+
}
|
|
63231
|
+
const bundle = {
|
|
62974
63232
|
export: completed.export,
|
|
62975
|
-
manifest: manifest.manifest,
|
|
62976
|
-
chunks:
|
|
63233
|
+
manifest: sanitizeAccountExportManifest(manifest.manifest),
|
|
63234
|
+
chunks: downloadedChunks
|
|
62977
63235
|
};
|
|
63236
|
+
const archive = await writeAccountExportArchive(bundle, flags);
|
|
63237
|
+
return { ...bundle, archive };
|
|
62978
63238
|
}
|
|
62979
63239
|
function printAccountExportBundle(bundle, flags) {
|
|
62980
|
-
if (typeof flags.output === "string") {
|
|
62981
|
-
writeFileSync7(flags.output, `${JSON.stringify(bundle, null, 2)}
|
|
62982
|
-
`, "utf-8");
|
|
62983
|
-
}
|
|
62984
63240
|
if (flags.json === true) {
|
|
62985
|
-
printJson2(
|
|
63241
|
+
printJson2(bundle);
|
|
62986
63242
|
return;
|
|
62987
63243
|
}
|
|
62988
63244
|
const exportRecord = bundle.export && typeof bundle.export === "object" ? bundle.export : {};
|
|
63245
|
+
const archive = bundle.archive && typeof bundle.archive === "object" ? bundle.archive : {};
|
|
62989
63246
|
process.stdout.write(`Account export ${String(exportRecord.export_id ?? "")} ${String(exportRecord.status ?? "unknown")}
|
|
62990
63247
|
`);
|
|
62991
|
-
if (typeof
|
|
63248
|
+
if (typeof archive.output === "string") process.stdout.write(`Wrote ${archive.output}
|
|
62992
63249
|
`);
|
|
62993
63250
|
}
|
|
62994
63251
|
function printApiKeyList(result, flags) {
|
package/dist/cli.js
CHANGED
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openmates",
|
|
3
|
-
"version": "0.15.0-alpha.
|
|
3
|
+
"version": "0.15.0-alpha.38",
|
|
4
4
|
"description": "OpenMates CLI and SDK",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -30,11 +30,13 @@
|
|
|
30
30
|
"test:unit:workflows": "node --test --experimental-strip-types --loader ./tests/loader.mjs tests/workflows.test.ts",
|
|
31
31
|
"test:unit:sdk-workflows": "node --test --experimental-strip-types --loader ./tests/loader.mjs tests/sdk-workflows.test.ts",
|
|
32
32
|
"test:unit:remote-access": "node --test --experimental-strip-types --loader ./tests/loader.mjs tests/remoteSources.test.ts tests/remoteAccess.test.ts",
|
|
33
|
+
"test:unit:teams": "node --test --experimental-strip-types --loader ./tests/loader.mjs tests/teams-permissions.test.ts",
|
|
33
34
|
"test:unit:proton-bridge-connector": "node --test --experimental-strip-types --loader ./tests/loader.mjs tests/protonBridgeConnector.test.ts",
|
|
34
35
|
"test:unit:proton-bridge-connector-integration": "node --test --experimental-strip-types --loader ./tests/loader.mjs tests/protonBridgeConnector.integration.test.ts",
|
|
35
36
|
"test:unit:sdk-projects": "node --test --experimental-strip-types --loader ./tests/loader.mjs tests/sdk-projects.test.ts",
|
|
36
37
|
"test:unit:billing": "node --test tests/billing.test.ts",
|
|
37
38
|
"test:unit:account-delete": "node --test tests/account-delete.test.ts",
|
|
39
|
+
"test:unit:ideabucket": "node --test --experimental-strip-types --loader ./tests/loader.mjs tests/ideabucket.test.ts",
|
|
38
40
|
"test:unit:cli": "node --test tests/cli.test.ts",
|
|
39
41
|
"test:t-cli-recovery": "node --test --experimental-strip-types --loader ./tests/loader.mjs --test-name-pattern recovery tests/client.test.ts",
|
|
40
42
|
"test:t-cli-update-required": "npm run build && node --test --test-name-pattern update-required tests/cli.test.ts",
|
|
@@ -43,7 +45,7 @@
|
|
|
43
45
|
"test:unit:tui": "node --test --experimental-strip-types --loader ./tests/loader.mjs tests/tui.test.ts tests/tuiExampleContinuation.test.ts tests/tuiWorkflowInteraction.test.ts",
|
|
44
46
|
"test:unit:connected-account-import": "node --test --experimental-strip-types --loader ./tests/loader.mjs tests/connectedAccountImport.test.ts",
|
|
45
47
|
"test:unit:benchmark": "node --test --experimental-strip-types --loader ./tests/loader.mjs src/__tests__/benchmark.test.ts",
|
|
46
|
-
"test": "node --test --experimental-strip-types --loader ./tests/loader.mjs tests/crypto.test.ts tests/storage.test.ts tests/keychain.test.ts tests/mentions.test.ts tests/outputRedactor.test.ts tests/fileEmbed.test.ts tests/embedCreator.test.ts tests/shareEncryption.test.ts tests/server.test.ts tests/ws.test.ts tests/urlEmbed.test.ts tests/tui.test.ts tests/tuiExampleContinuation.test.ts tests/tuiWorkflowInteraction.test.ts tests/workflows.test.ts tests/sdk-workflows.test.ts tests/draft-sync.test.ts tests/sdk-draft-sync.test.ts src/__tests__/benchmark.test.ts && node --test --experimental-strip-types --loader ./tests/loader.mjs tests/embedRenderers.test.ts tests/connectedAccountImport.test.ts && node --test tests/cli.test.ts tests/billing.test.ts tests/account-delete.test.ts tests/signup.test.ts tests/security-setup.test.ts tests/e2e-provisioning.test.ts"
|
|
48
|
+
"test": "node --test --experimental-strip-types --loader ./tests/loader.mjs tests/crypto.test.ts tests/storage.test.ts tests/keychain.test.ts tests/mentions.test.ts tests/outputRedactor.test.ts tests/fileEmbed.test.ts tests/embedCreator.test.ts tests/shareEncryption.test.ts tests/server.test.ts tests/ws.test.ts tests/urlEmbed.test.ts tests/tui.test.ts tests/tuiExampleContinuation.test.ts tests/tuiWorkflowInteraction.test.ts tests/workflows.test.ts tests/sdk-workflows.test.ts tests/draft-sync.test.ts tests/sdk-draft-sync.test.ts tests/ideabucket.test.ts tests/teams-permissions.test.ts src/__tests__/benchmark.test.ts && node --test --experimental-strip-types --loader ./tests/loader.mjs tests/embedRenderers.test.ts tests/connectedAccountImport.test.ts && node --test tests/cli.test.ts tests/billing.test.ts tests/account-delete.test.ts tests/signup.test.ts tests/security-setup.test.ts tests/e2e-provisioning.test.ts"
|
|
47
49
|
},
|
|
48
50
|
"keywords": [
|
|
49
51
|
"openmates",
|
|
@@ -185,25 +185,27 @@ services:
|
|
|
185
185
|
restart: on-failure
|
|
186
186
|
|
|
187
187
|
task-worker:
|
|
188
|
-
|
|
188
|
+
<<: *openmates-worker-base
|
|
189
189
|
container_name: task-worker
|
|
190
|
-
restart: unless-stopped
|
|
191
190
|
mem_limit: ${TASK_WORKER_MEMORY_LIMIT:-3g}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
191
|
+
environment:
|
|
192
|
+
<<: *openmates-worker-env
|
|
193
|
+
CELERY_QUEUES: email,user_init,persistence,health_check,server_stats,demo,reminder,push
|
|
194
|
+
CELERY_AUTOSCALE_MAX: ${TASK_WORKER_CONCURRENCY:-${CELERY_AUTOSCALE_MAX:-3}}
|
|
195
|
+
CELERY_AUTOSCALE_MIN: ${CELERY_AUTOSCALE_MIN:-1}
|
|
196
|
+
CELERY_METRICS_PORT: "9101"
|
|
197
|
+
command: >
|
|
198
|
+
sh -c "chown -R celeryuser:celeryuser /vault-data && gosu celeryuser python -m celery -A backend.core.api.app.tasks.celery_config worker --loglevel=info --queues=email,user_init,persistence,health_check,server_stats,demo,reminder,push --concurrency=$${CELERY_AUTOSCALE_MAX} --max-tasks-per-child=50 --max-memory-per-child=600000 --prefetch-multiplier=1"
|
|
196
199
|
|
|
197
200
|
task-scheduler:
|
|
198
|
-
|
|
201
|
+
<<: *openmates-worker-base
|
|
199
202
|
container_name: task-scheduler
|
|
200
|
-
restart: unless-stopped
|
|
201
|
-
env_file: ../../.env
|
|
202
203
|
command: python -m celery -A backend.core.api.app.tasks.celery_config beat --loglevel=info --schedule=/celerybeat-data/celerybeat-schedule
|
|
203
204
|
volumes:
|
|
205
|
+
- ../../config:/app_config
|
|
206
|
+
- vault-setup-data:/vault-data
|
|
207
|
+
- api-logs:/app/logs
|
|
204
208
|
- celerybeat-schedule-data:/celerybeat-data
|
|
205
|
-
networks: [openmates]
|
|
206
|
-
depends_on: [api]
|
|
207
209
|
|
|
208
210
|
app-ai-worker:
|
|
209
211
|
<<: *openmates-worker-base
|