openmates 0.18.0-alpha.19 → 0.18.0-alpha.20
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-M2SHXC5P.js → chunk-VJRT2LPY.js} +1013 -871
- package/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
|
@@ -11,6 +11,132 @@ import {
|
|
|
11
11
|
uploadFile
|
|
12
12
|
} from "./chunk-BBKJZ23O.js";
|
|
13
13
|
|
|
14
|
+
// src/generatedFiles.ts
|
|
15
|
+
import { createWriteStream } from "fs";
|
|
16
|
+
import { mkdir, link, rename, unlink, stat } from "fs/promises";
|
|
17
|
+
import { basename, dirname, extname, resolve } from "path";
|
|
18
|
+
import { randomUUID } from "crypto";
|
|
19
|
+
import { Readable } from "stream";
|
|
20
|
+
import { pipeline } from "stream/promises";
|
|
21
|
+
var DOWNLOAD_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
22
|
+
var ORIGINAL_VARIANTS = ["original", "master", "full"];
|
|
23
|
+
var RESULT_FIELDS = ["data", "result", "results", "items", "final"];
|
|
24
|
+
var MIME_EXTENSIONS = { "audio/mpeg": "mp3", "audio/wav": "wav", "image/png": "png", "image/jpeg": "jpg", "image/webp": "webp", "video/mp4": "mp4", "application/pdf": "pdf", "model/gltf-binary": "glb" };
|
|
25
|
+
var record = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
26
|
+
var text = (value) => typeof value === "string" && value.length > 0 ? value : void 0;
|
|
27
|
+
function generatedFileOptions(flags, input) {
|
|
28
|
+
const option = (name) => {
|
|
29
|
+
if (flags[name] === void 0) return void 0;
|
|
30
|
+
if (typeof flags[name] !== "string" || !flags[name].trim()) throw new Error(`--${name} requires a path or name`);
|
|
31
|
+
return flags[name];
|
|
32
|
+
};
|
|
33
|
+
const output = option("output");
|
|
34
|
+
const directory = option("output-dir");
|
|
35
|
+
const filename = option("filename");
|
|
36
|
+
if (output && (directory || filename)) throw new Error("--output cannot be combined with --output-dir or --filename");
|
|
37
|
+
if (filename && (filename !== basename(filename) || /[\\/]/.test(filename) || filename.includes("\0") || filename === "." || filename === "..")) throw new Error("--filename must be a filename without directories");
|
|
38
|
+
if (flags["no-download"] && (output || directory || filename)) throw new Error("--no-download cannot be combined with download destinations");
|
|
39
|
+
if ((output || filename) && Array.isArray(input?.requests) && input.requests.length > 1) throw new Error("One filename cannot name multiple generated files; use --output-dir");
|
|
40
|
+
return { enabled: !flags["no-download"] && (flags.json !== true || !!(output || directory || filename)), directory: resolve(directory ?? "."), filename, output: output ? resolve(output) : void 0 };
|
|
41
|
+
}
|
|
42
|
+
function safeName(value) {
|
|
43
|
+
return basename(value.replaceAll("\\", "/")).replace(/[^a-zA-Z0-9._-]/g, "_").replace(/^\.+/, "") || "generated-file";
|
|
44
|
+
}
|
|
45
|
+
function collectGeneratedFiles(value) {
|
|
46
|
+
const files = [];
|
|
47
|
+
const seen = /* @__PURE__ */ new Set();
|
|
48
|
+
const add = (meta, parent, variant) => {
|
|
49
|
+
const assetId = text(meta.asset_id) ?? text(parent.embed_id) ?? text(parent.asset_id);
|
|
50
|
+
const url = text(meta.download_url) ?? (assetId ? `/v1/embeds/${encodeURIComponent(assetId)}/file?format=${encodeURIComponent(variant)}` : void 0);
|
|
51
|
+
if (!url || seen.has(url)) return;
|
|
52
|
+
seen.add(url);
|
|
53
|
+
const extension = safeName(text(meta.format) ?? MIME_EXTENSIONS[String(meta.mime_type)] ?? variant);
|
|
54
|
+
const suppliedName = text(meta.filename) ?? text(meta.path) ?? text(parent.filename);
|
|
55
|
+
const filename = suppliedName ? safeName(suppliedName) : `openmates-${safeName(assetId ?? "generated")}.${extension}`;
|
|
56
|
+
files.push({ url, filename, assetId });
|
|
57
|
+
};
|
|
58
|
+
const visit = (node) => {
|
|
59
|
+
if (Array.isArray(node)) {
|
|
60
|
+
node.forEach(visit);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const data = record(node);
|
|
64
|
+
if (!data) return;
|
|
65
|
+
const variants = record(data.files);
|
|
66
|
+
if (variants) {
|
|
67
|
+
const entries = Object.entries(variants).filter((entry) => !!record(entry[1]));
|
|
68
|
+
const preferred = [...ORIGINAL_VARIANTS, String(data.output_filetype ?? "")];
|
|
69
|
+
const chosen = preferred.map((key) => entries.find(([name]) => name === key)).find(Boolean) ?? entries.find(([name]) => !/preview|thumbnail|poster/i.test(name));
|
|
70
|
+
if (chosen) add(chosen[1], data, chosen[0]);
|
|
71
|
+
}
|
|
72
|
+
for (const field of ["artifacts", "files"]) {
|
|
73
|
+
if (Array.isArray(data[field])) for (const item of data[field]) {
|
|
74
|
+
const meta = record(item);
|
|
75
|
+
if (meta && text(meta.download_url)) add(meta, data, text(meta.variant) ?? "original");
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
for (const field of RESULT_FIELDS) if (data[field] !== void 0) visit(data[field]);
|
|
79
|
+
};
|
|
80
|
+
visit(value);
|
|
81
|
+
return files;
|
|
82
|
+
}
|
|
83
|
+
function fetchGeneratedFile(url) {
|
|
84
|
+
return fetch(url, { redirect: "error", signal: AbortSignal.timeout(DOWNLOAD_TIMEOUT_MS) });
|
|
85
|
+
}
|
|
86
|
+
async function downloadGeneratedFiles(result, options, fetchFile = fetchGeneratedFile) {
|
|
87
|
+
if (!options.enabled) return [];
|
|
88
|
+
const files = collectGeneratedFiles(result);
|
|
89
|
+
const explicitName = options.output || options.filename;
|
|
90
|
+
if (explicitName && files.length !== 1) throw new Error(`Expected one generated file for the explicit filename; received ${files.length}. Use --output-dir for multiple files.`);
|
|
91
|
+
const saved = [];
|
|
92
|
+
for (const file of files) {
|
|
93
|
+
let target = options.output ?? resolve(options.directory, options.filename ?? file.filename);
|
|
94
|
+
await mkdir(dirname(target), { recursive: true });
|
|
95
|
+
const temporary = resolve(dirname(target), `.${randomUUID()}.partial`);
|
|
96
|
+
try {
|
|
97
|
+
const response = await fetchFile(file.url);
|
|
98
|
+
if (!response.ok || !response.body) throw new Error(`Download returned HTTP ${response.status}`);
|
|
99
|
+
await pipeline(Readable.fromWeb(response.body), createWriteStream(temporary, { flags: "wx", mode: 384 }));
|
|
100
|
+
if ((await stat(temporary)).size === 0) throw new Error("Download returned an empty file");
|
|
101
|
+
if (explicitName) await rename(temporary, target);
|
|
102
|
+
else {
|
|
103
|
+
const original = target;
|
|
104
|
+
for (let suffix = 0; ; suffix++) {
|
|
105
|
+
if (suffix) {
|
|
106
|
+
const extension = extname(original);
|
|
107
|
+
target = `${original.slice(0, original.length - extension.length)}-${suffix}${extension}`;
|
|
108
|
+
}
|
|
109
|
+
try {
|
|
110
|
+
await link(temporary, target);
|
|
111
|
+
break;
|
|
112
|
+
} catch (error) {
|
|
113
|
+
if (error.code !== "EEXIST") throw error;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
saved.push({ path: target, asset_id: file.assetId });
|
|
118
|
+
} catch (error) {
|
|
119
|
+
const detail = error instanceof Error && !/https?:/.test(error.message) ? error.message : "Transfer failed";
|
|
120
|
+
throw new Error(`Generated file download failed (${detail}). Asset: ${file.assetId ?? "see result"}. Already saved: ${saved.map((f) => f.path).join(", ") || "none"}. Generation was not retried.`);
|
|
121
|
+
} finally {
|
|
122
|
+
await unlink(temporary).catch((error) => {
|
|
123
|
+
if (error.code !== "ENOENT") throw error;
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return saved;
|
|
128
|
+
}
|
|
129
|
+
var GENERATED_FILE_HELP = [
|
|
130
|
+
"Generated files:",
|
|
131
|
+
" By default, save in the current directory with unique automatic names; existing files are preserved.",
|
|
132
|
+
" --json Return download URLs and expiry times without downloading, unless a destination is given.",
|
|
133
|
+
" --output-dir <dir> Save generated files in this directory (created if missing).",
|
|
134
|
+
" --filename <name> Name one output file; replace an existing file after a successful download.",
|
|
135
|
+
" --output <path> Full output file path; cannot combine with --output-dir or --filename.",
|
|
136
|
+
" --no-download Return results without saving files.",
|
|
137
|
+
" Examples: --output-dir ./media; --output-dir ./media --filename result.wav; --json --output ./media/result.wav"
|
|
138
|
+
].join("\n");
|
|
139
|
+
|
|
14
140
|
// src/codexConnection.ts
|
|
15
141
|
import { execFile, spawn } from "child_process";
|
|
16
142
|
import { promisify } from "util";
|
|
@@ -45,7 +171,7 @@ async function readCodexThread(threadId, socketPath) {
|
|
|
45
171
|
codexResumeArguments({ provider: "codex", id: threadId });
|
|
46
172
|
const socket = socketPath ?? await daemonSocket();
|
|
47
173
|
if (!isAbsolute(socket) || socket.includes(":")) throw new Error("Codex requires an absolute local socket path.");
|
|
48
|
-
return new Promise((
|
|
174
|
+
return new Promise((resolve12, reject) => {
|
|
49
175
|
const ws = new WebSocket(`ws+unix://${socket}:/`, {
|
|
50
176
|
perMessageDeflate: false,
|
|
51
177
|
handshakeTimeout: CONNECTION_TIMEOUT_MS,
|
|
@@ -59,7 +185,7 @@ async function readCodexThread(threadId, socketPath) {
|
|
|
59
185
|
if (ws.readyState === WebSocket.OPEN) ws.close();
|
|
60
186
|
else if (ws.readyState !== WebSocket.CLOSED) ws.terminate();
|
|
61
187
|
if (error) reject(error);
|
|
62
|
-
else
|
|
188
|
+
else resolve12(value);
|
|
63
189
|
};
|
|
64
190
|
const timer = setTimeout(() => finish(new Error("Codex connection timed out.")), CONNECTION_TIMEOUT_MS);
|
|
65
191
|
ws.on("error", () => finish(new Error("Could not connect to the local Codex daemon.")));
|
|
@@ -100,15 +226,15 @@ async function resumeCodexTask(context) {
|
|
|
100
226
|
const args = codexResumeArguments(context);
|
|
101
227
|
if (!process.stdin.isTTY || !process.stdout.isTTY) throw new Error("Task resume requires an interactive terminal; status and connect never launch work.");
|
|
102
228
|
await readCodexThread(context.id);
|
|
103
|
-
await new Promise((
|
|
229
|
+
await new Promise((resolve12, reject) => {
|
|
104
230
|
const child = spawn("codex", args, { stdio: "inherit" });
|
|
105
231
|
child.once("error", () => reject(new Error("Could not open the installed Codex CLI.")));
|
|
106
|
-
child.once("exit", (code) => code === 0 ?
|
|
232
|
+
child.once("exit", (code) => code === 0 ? resolve12() : reject(new Error(`Codex resume exited with status ${code ?? "interrupted"}.`)));
|
|
107
233
|
});
|
|
108
234
|
}
|
|
109
235
|
|
|
110
236
|
// src/client.ts
|
|
111
|
-
import { createHash as createHash10, randomBytes as randomBytes4, randomUUID as
|
|
237
|
+
import { createHash as createHash10, randomBytes as randomBytes4, randomUUID as randomUUID7 } from "crypto";
|
|
112
238
|
import { arch, platform as platform2, release } from "os";
|
|
113
239
|
import { createInterface as createInterface2 } from "readline/promises";
|
|
114
240
|
import { stdin as stdin2, stdout } from "process";
|
|
@@ -936,9 +1062,9 @@ async function parseOpenCodeImportBuffer(payload, sourceName = "opencode-session
|
|
|
936
1062
|
throw new Error(`OpenCode transcript export could not be parsed: ${error instanceof Error ? error.message : String(error)}`);
|
|
937
1063
|
}
|
|
938
1064
|
if (!transcript || typeof transcript !== "object" || Array.isArray(transcript)) throw new Error("OpenCode transcript export must be an object");
|
|
939
|
-
const
|
|
940
|
-
const info =
|
|
941
|
-
const rawMessages = Array.isArray(
|
|
1065
|
+
const record2 = transcript;
|
|
1066
|
+
const info = record2.info && typeof record2.info === "object" ? record2.info : null;
|
|
1067
|
+
const rawMessages = Array.isArray(record2.messages) ? record2.messages : null;
|
|
942
1068
|
const sourceChatId = String(info?.id ?? "");
|
|
943
1069
|
if (!info || !sourceChatId || !rawMessages) throw new Error("OpenCode transcript export is missing info.id or messages");
|
|
944
1070
|
const messages = [];
|
|
@@ -950,7 +1076,7 @@ async function parseOpenCodeImportBuffer(payload, sourceName = "opencode-session
|
|
|
950
1076
|
if (role !== "user" && role !== "assistant") continue;
|
|
951
1077
|
const parts = Array.isArray(message.parts) ? message.parts.filter((part) => Boolean(part && typeof part === "object")) : [];
|
|
952
1078
|
const textParts = parts.filter((part) => part.type === "text" && part.ignored !== true && typeof part.text === "string");
|
|
953
|
-
const content = textParts.map((part) => String(part.text)).filter((
|
|
1079
|
+
const content = textParts.map((part) => String(part.text)).filter((text2) => text2.trim()).join("\n");
|
|
954
1080
|
if (content.trim()) {
|
|
955
1081
|
const time2 = messageInfo.time && typeof messageInfo.time === "object" ? messageInfo.time : {};
|
|
956
1082
|
messages.push({
|
|
@@ -1300,7 +1426,7 @@ import {
|
|
|
1300
1426
|
import lockfile from "proper-lockfile";
|
|
1301
1427
|
import { createHash as createHash4 } from "crypto";
|
|
1302
1428
|
import { homedir as homedir2 } from "os";
|
|
1303
|
-
import { isAbsolute as isAbsolute2, join, resolve } from "path";
|
|
1429
|
+
import { isAbsolute as isAbsolute2, join, resolve as resolve2 } from "path";
|
|
1304
1430
|
|
|
1305
1431
|
// src/keychain.ts
|
|
1306
1432
|
import { execFileSync } from "child_process";
|
|
@@ -1529,7 +1655,7 @@ function resolveStateDir(options = {}) {
|
|
|
1529
1655
|
const stateDir2 = options.stateDir ?? process.env.OPENMATES_STATE_DIR?.trim();
|
|
1530
1656
|
if (stateDir2) {
|
|
1531
1657
|
if (!isAbsolute2(stateDir2)) throw new Error("OPENMATES_STATE_DIR must be an absolute path.");
|
|
1532
|
-
return
|
|
1658
|
+
return resolve2(stateDir2);
|
|
1533
1659
|
}
|
|
1534
1660
|
const profile = options.profile ?? process.env.OPENMATES_PROFILE?.trim();
|
|
1535
1661
|
if (!profile) return join(homeDir, ".openmates");
|
|
@@ -1901,10 +2027,10 @@ function assertTrustedAccountId(expectedAccountId, actualAccountId) {
|
|
|
1901
2027
|
// src/serverConfig.ts
|
|
1902
2028
|
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync3, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
1903
2029
|
import { homedir as homedir3 } from "os";
|
|
1904
|
-
import { join as join2, resolve as
|
|
2030
|
+
import { join as join2, resolve as resolve3 } from "path";
|
|
1905
2031
|
var CONFIG_FILE = "server.json";
|
|
1906
2032
|
function stateDir() {
|
|
1907
|
-
return process.env.OPENMATES_STATE_DIR ?
|
|
2033
|
+
return process.env.OPENMATES_STATE_DIR ? resolve3(process.env.OPENMATES_STATE_DIR) : join2(homedir3(), ".openmates");
|
|
1908
2034
|
}
|
|
1909
2035
|
function ensureStateDir2() {
|
|
1910
2036
|
const STATE_DIR = stateDir();
|
|
@@ -1948,7 +2074,7 @@ function isOpenMatesDir(dir) {
|
|
|
1948
2074
|
}
|
|
1949
2075
|
function resolveServerPath(flags) {
|
|
1950
2076
|
if (typeof flags.path === "string" && flags.path) {
|
|
1951
|
-
const explicit =
|
|
2077
|
+
const explicit = resolve3(flags.path);
|
|
1952
2078
|
if (!isOpenMatesDir(explicit)) {
|
|
1953
2079
|
throw new Error(
|
|
1954
2080
|
`${explicit} does not appear to be an OpenMates installation (missing ${SOURCE_COMPOSE_MARKER} or ${IMAGE_COMPOSE_MARKER}).`
|
|
@@ -2162,14 +2288,14 @@ var OpenMatesWsClient = class {
|
|
|
2162
2288
|
});
|
|
2163
2289
|
}
|
|
2164
2290
|
async open(timeoutMs = 1e4) {
|
|
2165
|
-
await new Promise((
|
|
2291
|
+
await new Promise((resolve12, reject) => {
|
|
2166
2292
|
const timeout = setTimeout(
|
|
2167
2293
|
() => reject(new Error("WebSocket open timeout")),
|
|
2168
2294
|
timeoutMs
|
|
2169
2295
|
);
|
|
2170
2296
|
this.socket.once("open", () => {
|
|
2171
2297
|
clearTimeout(timeout);
|
|
2172
|
-
|
|
2298
|
+
resolve12();
|
|
2173
2299
|
});
|
|
2174
2300
|
this.socket.once("error", (error) => {
|
|
2175
2301
|
clearTimeout(timeout);
|
|
@@ -2198,10 +2324,10 @@ var OpenMatesWsClient = class {
|
|
|
2198
2324
|
this.socket.send(JSON.stringify({ type, payload }));
|
|
2199
2325
|
}
|
|
2200
2326
|
sendAsync(type, payload) {
|
|
2201
|
-
return new Promise((
|
|
2327
|
+
return new Promise((resolve12, reject) => {
|
|
2202
2328
|
this.socket.send(JSON.stringify({ type, payload }), (error) => {
|
|
2203
2329
|
if (error) reject(error);
|
|
2204
|
-
else
|
|
2330
|
+
else resolve12();
|
|
2205
2331
|
});
|
|
2206
2332
|
});
|
|
2207
2333
|
}
|
|
@@ -2247,9 +2373,9 @@ var OpenMatesWsClient = class {
|
|
|
2247
2373
|
return () => this.socket.off("message", onMessage);
|
|
2248
2374
|
}
|
|
2249
2375
|
waitForClose() {
|
|
2250
|
-
return new Promise((
|
|
2376
|
+
return new Promise((resolve12) => {
|
|
2251
2377
|
this.socket.once("close", (code, reason) => {
|
|
2252
|
-
|
|
2378
|
+
resolve12({ code, reason: reason.toString("utf-8") });
|
|
2253
2379
|
});
|
|
2254
2380
|
});
|
|
2255
2381
|
}
|
|
@@ -2281,7 +2407,7 @@ var OpenMatesWsClient = class {
|
|
|
2281
2407
|
return jobs;
|
|
2282
2408
|
}
|
|
2283
2409
|
waitForMessage(expectedType, predicate, timeoutMs = 2e4) {
|
|
2284
|
-
return new Promise((
|
|
2410
|
+
return new Promise((resolve12, reject) => {
|
|
2285
2411
|
const seenTypes = /* @__PURE__ */ new Set();
|
|
2286
2412
|
let predicateMisses = 0;
|
|
2287
2413
|
const onMessage = (rawData) => {
|
|
@@ -2303,7 +2429,7 @@ var OpenMatesWsClient = class {
|
|
|
2303
2429
|
return;
|
|
2304
2430
|
}
|
|
2305
2431
|
cleanup();
|
|
2306
|
-
|
|
2432
|
+
resolve12(parsed);
|
|
2307
2433
|
} catch {
|
|
2308
2434
|
}
|
|
2309
2435
|
};
|
|
@@ -2341,7 +2467,7 @@ var OpenMatesWsClient = class {
|
|
|
2341
2467
|
* Used by ensureSynced to consume the full phased-sync event stream.
|
|
2342
2468
|
*/
|
|
2343
2469
|
collectMessages(terminatorType, timeoutMs = 9e4) {
|
|
2344
|
-
return new Promise((
|
|
2470
|
+
return new Promise((resolve12, reject) => {
|
|
2345
2471
|
const collected = [];
|
|
2346
2472
|
const onMessage = (rawData) => {
|
|
2347
2473
|
try {
|
|
@@ -2354,7 +2480,7 @@ var OpenMatesWsClient = class {
|
|
|
2354
2480
|
}
|
|
2355
2481
|
if (parsed.type === terminatorType) {
|
|
2356
2482
|
cleanup();
|
|
2357
|
-
|
|
2483
|
+
resolve12(collected);
|
|
2358
2484
|
return;
|
|
2359
2485
|
}
|
|
2360
2486
|
collected.push(parsed);
|
|
@@ -2367,7 +2493,7 @@ var OpenMatesWsClient = class {
|
|
|
2367
2493
|
};
|
|
2368
2494
|
const onClose = () => {
|
|
2369
2495
|
cleanup();
|
|
2370
|
-
|
|
2496
|
+
resolve12(collected);
|
|
2371
2497
|
};
|
|
2372
2498
|
const timeout = setTimeout(() => {
|
|
2373
2499
|
cleanup();
|
|
@@ -2405,7 +2531,7 @@ var OpenMatesWsClient = class {
|
|
|
2405
2531
|
const timeoutMs = options?.timeoutMs ?? 9e4;
|
|
2406
2532
|
const onStream = options?.onStream;
|
|
2407
2533
|
const asyncEmbedWaitMs = options?.asyncEmbedWaitMs ?? DEFAULT_ASYNC_EMBED_WAIT_MS;
|
|
2408
|
-
return new Promise((
|
|
2534
|
+
return new Promise((resolve12, reject) => {
|
|
2409
2535
|
let latestContent = "";
|
|
2410
2536
|
let messageId = null;
|
|
2411
2537
|
let taskId = null;
|
|
@@ -2486,8 +2612,8 @@ var OpenMatesWsClient = class {
|
|
|
2486
2612
|
if (!content || typeof content !== "object") return "";
|
|
2487
2613
|
try {
|
|
2488
2614
|
const root = content;
|
|
2489
|
-
const
|
|
2490
|
-
return typeof
|
|
2615
|
+
const text2 = root.content?.[0]?.content?.[0]?.text;
|
|
2616
|
+
return typeof text2 === "string" ? text2 : "";
|
|
2491
2617
|
} catch {
|
|
2492
2618
|
return "";
|
|
2493
2619
|
}
|
|
@@ -2500,7 +2626,7 @@ var OpenMatesWsClient = class {
|
|
|
2500
2626
|
if (waitingForUserPayload) {
|
|
2501
2627
|
if (pendingSubChatHandlers.size > 0) return;
|
|
2502
2628
|
cleanup();
|
|
2503
|
-
|
|
2629
|
+
resolve12({
|
|
2504
2630
|
status: "waiting_for_user",
|
|
2505
2631
|
messageId,
|
|
2506
2632
|
taskId,
|
|
@@ -2532,7 +2658,7 @@ var OpenMatesWsClient = class {
|
|
|
2532
2658
|
if (processingEmbedIds.size > 0 && !asyncEmbedTimer) {
|
|
2533
2659
|
asyncEmbedTimer = setTimeout(() => {
|
|
2534
2660
|
cleanup();
|
|
2535
|
-
|
|
2661
|
+
resolve12({
|
|
2536
2662
|
status: "completed",
|
|
2537
2663
|
messageId,
|
|
2538
2664
|
taskId,
|
|
@@ -2560,7 +2686,7 @@ var OpenMatesWsClient = class {
|
|
|
2560
2686
|
}
|
|
2561
2687
|
if (processingEmbedIds.size > 0) return;
|
|
2562
2688
|
cleanup();
|
|
2563
|
-
|
|
2689
|
+
resolve12({
|
|
2564
2690
|
status: "completed",
|
|
2565
2691
|
messageId,
|
|
2566
2692
|
taskId,
|
|
@@ -2878,7 +3004,7 @@ var OpenMatesWsClient = class {
|
|
|
2878
3004
|
const onClose = () => {
|
|
2879
3005
|
if (aiResponseDone) {
|
|
2880
3006
|
cleanup();
|
|
2881
|
-
|
|
3007
|
+
resolve12({
|
|
2882
3008
|
status: "completed",
|
|
2883
3009
|
messageId,
|
|
2884
3010
|
taskId,
|
|
@@ -3364,7 +3490,7 @@ function escapeRegExp(s) {
|
|
|
3364
3490
|
}
|
|
3365
3491
|
|
|
3366
3492
|
// src/embedCreator.ts
|
|
3367
|
-
import { randomUUID, createHash as createHash5, randomBytes, webcrypto as webcrypto3 } from "crypto";
|
|
3493
|
+
import { randomUUID as randomUUID2, createHash as createHash5, randomBytes, webcrypto as webcrypto3 } from "crypto";
|
|
3368
3494
|
import { encode as toonEncode } from "@toon-format/toon";
|
|
3369
3495
|
var cryptoApi3 = webcrypto3;
|
|
3370
3496
|
var AES_GCM_IV_LENGTH3 = 12;
|
|
@@ -3428,7 +3554,7 @@ function toonEncodeContent(data) {
|
|
|
3428
3554
|
}
|
|
3429
3555
|
}
|
|
3430
3556
|
function generateEmbedId() {
|
|
3431
|
-
return
|
|
3557
|
+
return randomUUID2();
|
|
3432
3558
|
}
|
|
3433
3559
|
function createEmbedRef(type, source) {
|
|
3434
3560
|
const prefix = source.toLowerCase().replace(/^https?:\/\//, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40) || type;
|
|
@@ -3501,7 +3627,7 @@ async function encryptEmbed(embed, masterKey, chatKey, chatId, messageId, userId
|
|
|
3501
3627
|
|
|
3502
3628
|
// src/fileEmbed.ts
|
|
3503
3629
|
import { readFileSync as readFileSync4, statSync, existsSync as existsSync4 } from "fs";
|
|
3504
|
-
import { basename, extname, resolve as
|
|
3630
|
+
import { basename as basename2, extname as extname2, resolve as resolve4 } from "path";
|
|
3505
3631
|
import { homedir as homedir4 } from "os";
|
|
3506
3632
|
import { createHash as createHash6 } from "crypto";
|
|
3507
3633
|
import JSZip2 from "jszip";
|
|
@@ -3613,7 +3739,7 @@ function isEnvFile(filename) {
|
|
|
3613
3739
|
return lower === ".env" || lower.startsWith(".env.") || lower === ".envrc";
|
|
3614
3740
|
}
|
|
3615
3741
|
function getExt(filename) {
|
|
3616
|
-
const ext =
|
|
3742
|
+
const ext = extname2(filename).toLowerCase();
|
|
3617
3743
|
return ext.startsWith(".") ? ext.slice(1) : ext;
|
|
3618
3744
|
}
|
|
3619
3745
|
function isCodeOrTextFile(filename) {
|
|
@@ -3718,8 +3844,8 @@ function parseDelimitedLine(line, delimiter) {
|
|
|
3718
3844
|
cells.push(current);
|
|
3719
3845
|
return cells;
|
|
3720
3846
|
}
|
|
3721
|
-
function delimitedTextToMarkdownTable(
|
|
3722
|
-
const rows =
|
|
3847
|
+
function delimitedTextToMarkdownTable(text2, delimiter) {
|
|
3848
|
+
const rows = text2.split(/\r?\n/).map((line) => line.trimEnd()).filter((line) => line.length > 0).map((line) => parseDelimitedLine(line, delimiter));
|
|
3723
3849
|
if (rows.length === 0) return "";
|
|
3724
3850
|
const maxCols = Math.max(...rows.map((row) => row.length));
|
|
3725
3851
|
const normalized = rows.map((row) => {
|
|
@@ -3766,7 +3892,7 @@ async function docxBufferToHtml(buffer) {
|
|
|
3766
3892
|
const zip = await JSZip2.loadAsync(buffer);
|
|
3767
3893
|
const documentXml = await zip.file("word/document.xml")?.async("string");
|
|
3768
3894
|
if (!documentXml) return "";
|
|
3769
|
-
const paragraphs = getXmlBlocks(documentXml, "p").map(getTextFromDocxParagraph).map((
|
|
3895
|
+
const paragraphs = getXmlBlocks(documentXml, "p").map(getTextFromDocxParagraph).map((text2) => text2.trim()).filter(Boolean);
|
|
3770
3896
|
return paragraphs.map((paragraph) => `<p>${escapeHtml(paragraph)}</p>`).join("\n");
|
|
3771
3897
|
}
|
|
3772
3898
|
function columnLettersToIndex(letters) {
|
|
@@ -3870,9 +3996,9 @@ function processEnvFileZeroKnowledge(content) {
|
|
|
3870
3996
|
}
|
|
3871
3997
|
function resolvePath(filePath) {
|
|
3872
3998
|
if (filePath.startsWith("~/")) {
|
|
3873
|
-
return
|
|
3999
|
+
return resolve4(homedir4(), filePath.slice(2));
|
|
3874
4000
|
}
|
|
3875
|
-
return
|
|
4001
|
+
return resolve4(filePath);
|
|
3876
4002
|
}
|
|
3877
4003
|
function processFiles(filePaths, redactor) {
|
|
3878
4004
|
const embeds = [];
|
|
@@ -3880,7 +4006,7 @@ function processFiles(filePaths, redactor) {
|
|
|
3880
4006
|
const blocked = [];
|
|
3881
4007
|
for (const rawPath of filePaths) {
|
|
3882
4008
|
const resolvedPath = resolvePath(rawPath);
|
|
3883
|
-
const filename =
|
|
4009
|
+
const filename = basename2(resolvedPath);
|
|
3884
4010
|
const ext = getExt(filename);
|
|
3885
4011
|
if (!existsSync4(resolvedPath)) {
|
|
3886
4012
|
errors.push({ path: rawPath, error: "File not found" });
|
|
@@ -3962,7 +4088,7 @@ async function processFilesAsync(filePaths, redactor) {
|
|
|
3962
4088
|
const blocked = [];
|
|
3963
4089
|
for (const rawPath of filePaths) {
|
|
3964
4090
|
const resolvedPath = resolvePath(rawPath);
|
|
3965
|
-
const filename =
|
|
4091
|
+
const filename = basename2(resolvedPath);
|
|
3966
4092
|
const ext = getExt(filename);
|
|
3967
4093
|
if (!isDocFile(filename) && !isSheetFile(filename)) {
|
|
3968
4094
|
syncPaths.push(rawPath);
|
|
@@ -4395,7 +4521,7 @@ function buildEmbedShareUrl(origin, embedId, blob) {
|
|
|
4395
4521
|
}
|
|
4396
4522
|
|
|
4397
4523
|
// src/connectedAccountImport.ts
|
|
4398
|
-
import { createHash as createHash7, randomUUID as
|
|
4524
|
+
import { createHash as createHash7, randomUUID as randomUUID3, webcrypto as webcrypto5 } from "crypto";
|
|
4399
4525
|
var TRANSFER_PREFIX = "OMCA1.";
|
|
4400
4526
|
var SUPPORTED_KDF_ITERATIONS = 1e5;
|
|
4401
4527
|
async function decryptConnectedAccountCliTransferPayload(encryptedPayload, passcode) {
|
|
@@ -4425,7 +4551,7 @@ async function decryptConnectedAccountCliTransferPayload(encryptedPayload, passc
|
|
|
4425
4551
|
}
|
|
4426
4552
|
}
|
|
4427
4553
|
async function buildEncryptedConnectedAccountImportRow(params) {
|
|
4428
|
-
const accountId =
|
|
4554
|
+
const accountId = randomUUID3();
|
|
4429
4555
|
const providerId = params.payload.provider_id;
|
|
4430
4556
|
const appId = normalizeAppId(params.payload.app_id || appIdForProvider(providerId));
|
|
4431
4557
|
const capabilities = normalizeCapabilities(params.payload.capabilities);
|
|
@@ -4629,7 +4755,7 @@ import { connect as connectTcp } from "net";
|
|
|
4629
4755
|
import { arch as nodeArch, platform as nodePlatform } from "os";
|
|
4630
4756
|
import { stdin, stderr } from "process";
|
|
4631
4757
|
import { createInterface } from "readline/promises";
|
|
4632
|
-
import { randomUUID as
|
|
4758
|
+
import { randomUUID as randomUUID4 } from "crypto";
|
|
4633
4759
|
import { setTimeout as sleep } from "timers/promises";
|
|
4634
4760
|
var PROTON_BRIDGE_PROVIDER_ID = "protonmail_bridge";
|
|
4635
4761
|
var PROTON_BRIDGE_APP_ID = "mail";
|
|
@@ -4650,8 +4776,8 @@ function rejectProtonCredentialFlags(argsOrFlags) {
|
|
|
4650
4776
|
throw new Error(`${rejected.split("=")[0]} is not allowed. Bridge credentials must be read privately from Proton Bridge or a hidden prompt.`);
|
|
4651
4777
|
}
|
|
4652
4778
|
}
|
|
4653
|
-
function redactProtonBridgeSecrets(
|
|
4654
|
-
return
|
|
4779
|
+
function redactProtonBridgeSecrets(text2) {
|
|
4780
|
+
return text2.replace(CREDENTIAL_VALUE_RE, "$1<redacted>");
|
|
4655
4781
|
}
|
|
4656
4782
|
function containsCredentialLikeField(value) {
|
|
4657
4783
|
return containsCredentialLikeKey(value);
|
|
@@ -4781,7 +4907,7 @@ function validateProtonBridgeCredentials(credentials) {
|
|
|
4781
4907
|
}
|
|
4782
4908
|
async function validateProtonBridgeImap(credentials, timeoutMs = DEFAULT_IMAP_TIMEOUT_MS) {
|
|
4783
4909
|
validateProtonBridgeCredentials(credentials);
|
|
4784
|
-
await new Promise((
|
|
4910
|
+
await new Promise((resolve12, reject) => {
|
|
4785
4911
|
const socket = connectTcp({ host: credentials.imapHost, port: credentials.imapPort });
|
|
4786
4912
|
const timer = setTimeout(() => {
|
|
4787
4913
|
socket.destroy();
|
|
@@ -4790,7 +4916,7 @@ async function validateProtonBridgeImap(credentials, timeoutMs = DEFAULT_IMAP_TI
|
|
|
4790
4916
|
socket.once("connect", () => {
|
|
4791
4917
|
clearTimeout(timer);
|
|
4792
4918
|
socket.end();
|
|
4793
|
-
|
|
4919
|
+
resolve12();
|
|
4794
4920
|
});
|
|
4795
4921
|
socket.once("error", (error) => {
|
|
4796
4922
|
clearTimeout(timer);
|
|
@@ -4838,7 +4964,7 @@ async function runProtonBridgeConnector(client, options = {}, deps = {}) {
|
|
|
4838
4964
|
validateProtonBridgeCredentials(credentials);
|
|
4839
4965
|
await (deps.validateImap ?? validateProtonBridgeImap)(credentials);
|
|
4840
4966
|
registration = await client.registerLocalConnectedAccountConnector(createProtonLocalConnectorRegistration({
|
|
4841
|
-
connectorInstanceId: deps.connectorInstanceId ??
|
|
4967
|
+
connectorInstanceId: deps.connectorInstanceId ?? randomUUID4(),
|
|
4842
4968
|
credentials,
|
|
4843
4969
|
write
|
|
4844
4970
|
}));
|
|
@@ -4908,7 +5034,7 @@ var ProtonDelayedSendQueue = class {
|
|
|
4908
5034
|
this.delayMs = delayMs;
|
|
4909
5035
|
}
|
|
4910
5036
|
queue(payload, deliver, now = Date.now()) {
|
|
4911
|
-
const id =
|
|
5037
|
+
const id = randomUUID4();
|
|
4912
5038
|
const job = {
|
|
4913
5039
|
id,
|
|
4914
5040
|
status: "queued",
|
|
@@ -4967,8 +5093,8 @@ async function localConnectorRequestLoop(client, params) {
|
|
|
4967
5093
|
const ws = await client.openLocalConnectorWebSocket();
|
|
4968
5094
|
const sendQueue = new ProtonDelayedSendQueue();
|
|
4969
5095
|
let resolveOnce = null;
|
|
4970
|
-
const onceHandled = new Promise((
|
|
4971
|
-
resolveOnce =
|
|
5096
|
+
const onceHandled = new Promise((resolve12) => {
|
|
5097
|
+
resolveOnce = resolve12;
|
|
4972
5098
|
});
|
|
4973
5099
|
const removeListener = ws.onLocalConnectorRequest((request) => {
|
|
4974
5100
|
void handleLocalConnectorRequest(client, request, params, sendQueue).finally(() => {
|
|
@@ -5036,8 +5162,8 @@ async function handleLocalConnectorRequest(client, request, params, sendQueue) {
|
|
|
5036
5162
|
}
|
|
5037
5163
|
async function waitForAbort(signal) {
|
|
5038
5164
|
if (signal.aborted) return;
|
|
5039
|
-
await new Promise((
|
|
5040
|
-
signal.addEventListener("abort", () =>
|
|
5165
|
+
await new Promise((resolve12) => {
|
|
5166
|
+
signal.addEventListener("abort", () => resolve12(), { once: true });
|
|
5041
5167
|
});
|
|
5042
5168
|
}
|
|
5043
5169
|
async function searchProtonBridgeImap(credentials, arguments_) {
|
|
@@ -5048,7 +5174,7 @@ async function searchProtonBridgeImap(credentials, arguments_) {
|
|
|
5048
5174
|
const limit = clampLimit(arguments_.limit);
|
|
5049
5175
|
const imap = await openTextSocket(credentials.imapHost, credentials.imapPort, IMAP_COMMAND_TIMEOUT_MS);
|
|
5050
5176
|
try {
|
|
5051
|
-
await imap.readUntil((
|
|
5177
|
+
await imap.readUntil((text2) => /^\* OK/im.test(text2));
|
|
5052
5178
|
await imap.command(`LOGIN ${quoteImap(credentials.imapUsername)} ${quoteImap(credentials.imapPassword)}`);
|
|
5053
5179
|
await imap.command(`SELECT ${quoteImap(mailbox)}`);
|
|
5054
5180
|
const searchResponse = await imap.command(buildImapSearchCommand({ query, startDate, endDate }));
|
|
@@ -5093,25 +5219,25 @@ async function sendProtonBridgeSmtp(credentials, payload) {
|
|
|
5093
5219
|
const subject = typeof payload.subject === "string" ? payload.subject.slice(0, 300) : "";
|
|
5094
5220
|
const bodyText = typeof payload.body_text === "string" ? payload.body_text : typeof payload.body === "string" ? payload.body : "";
|
|
5095
5221
|
const from = credentials.smtpUsername || credentials.imapUsername;
|
|
5096
|
-
const messageId = `<om-${
|
|
5222
|
+
const messageId = `<om-${randomUUID4()}@local.openmates>`;
|
|
5097
5223
|
const smtp = await openTextSocket(credentials.smtpHost, credentials.smtpPort, SMTP_COMMAND_TIMEOUT_MS);
|
|
5098
5224
|
try {
|
|
5099
|
-
await smtp.readUntil((
|
|
5100
|
-
await smtp.rawCommand("EHLO openmates.local", (
|
|
5225
|
+
await smtp.readUntil((text2) => /^220[ -]/m.test(text2));
|
|
5226
|
+
await smtp.rawCommand("EHLO openmates.local", (text2) => /^250\s/m.test(text2), /^250[ -]/m);
|
|
5101
5227
|
const auth = Buffer.from(`\0${credentials.smtpUsername || credentials.imapUsername}\0${credentials.smtpPassword || credentials.imapPassword}`).toString("base64");
|
|
5102
5228
|
try {
|
|
5103
|
-
await smtp.rawCommand(`AUTH PLAIN ${auth}`, (
|
|
5229
|
+
await smtp.rawCommand(`AUTH PLAIN ${auth}`, (text2) => /^235[ -]/m.test(text2), /^235[ -]/m);
|
|
5104
5230
|
} catch {
|
|
5105
5231
|
throw new Error("Local SMTP authentication failed.");
|
|
5106
5232
|
}
|
|
5107
|
-
await smtp.rawCommand(`MAIL FROM:<${from}>`, (
|
|
5233
|
+
await smtp.rawCommand(`MAIL FROM:<${from}>`, (text2) => /^250[ -]/m.test(text2), /^250[ -]/m);
|
|
5108
5234
|
for (const recipient of to) {
|
|
5109
|
-
await smtp.rawCommand(`RCPT TO:<${recipient}>`, (
|
|
5235
|
+
await smtp.rawCommand(`RCPT TO:<${recipient}>`, (text2) => /^250[ -]/m.test(text2), /^250[ -]/m);
|
|
5110
5236
|
}
|
|
5111
|
-
await smtp.rawCommand("DATA", (
|
|
5237
|
+
await smtp.rawCommand("DATA", (text2) => /^354[ -]/m.test(text2), /^354[ -]/m);
|
|
5112
5238
|
await smtp.rawCommand(`${buildSmtpMessage({ from, to, subject, bodyText, messageId })}\r
|
|
5113
|
-
.`, (
|
|
5114
|
-
await smtp.rawCommand("QUIT", (
|
|
5239
|
+
.`, (text2) => /^250[ -]/m.test(text2), /^250[ -]/m);
|
|
5240
|
+
await smtp.rawCommand("QUIT", (text2) => /^221[ -]/m.test(text2), /^221[ -]/m).catch(() => void 0);
|
|
5115
5241
|
return { provider: PROTON_BRIDGE_PROVIDER_ID, message_id: messageId, delivered: true };
|
|
5116
5242
|
} finally {
|
|
5117
5243
|
smtp.close();
|
|
@@ -5199,14 +5325,14 @@ async function openTextSocket(host, port, timeoutMs) {
|
|
|
5199
5325
|
socket.on("data", (chunk) => {
|
|
5200
5326
|
buffer += String(chunk);
|
|
5201
5327
|
});
|
|
5202
|
-
await new Promise((
|
|
5328
|
+
await new Promise((resolve12, reject) => {
|
|
5203
5329
|
const timer = setTimeout(() => {
|
|
5204
5330
|
socket.destroy();
|
|
5205
5331
|
reject(new Error(`Timed out connecting to ${host}:${port}.`));
|
|
5206
5332
|
}, timeoutMs);
|
|
5207
5333
|
socket.once("connect", () => {
|
|
5208
5334
|
clearTimeout(timer);
|
|
5209
|
-
|
|
5335
|
+
resolve12();
|
|
5210
5336
|
});
|
|
5211
5337
|
socket.once("error", (error) => {
|
|
5212
5338
|
clearTimeout(timer);
|
|
@@ -5223,7 +5349,7 @@ async function openTextSocket(host, port, timeoutMs) {
|
|
|
5223
5349
|
buffer = "";
|
|
5224
5350
|
socket.write(`${tag} ${command}\r
|
|
5225
5351
|
`);
|
|
5226
|
-
const response = await waitForSocketText(socket, () => buffer, (
|
|
5352
|
+
const response = await waitForSocketText(socket, () => buffer, (text2) => marker.test(text2), timeoutMs);
|
|
5227
5353
|
if (expected && !expected.test(response)) {
|
|
5228
5354
|
throw new Error(`Local mail command failed: ${redactProtonBridgeSecrets(response.split(/\r?\n/).slice(-2).join(" "))}`);
|
|
5229
5355
|
}
|
|
@@ -5246,11 +5372,11 @@ async function openTextSocket(host, port, timeoutMs) {
|
|
|
5246
5372
|
};
|
|
5247
5373
|
}
|
|
5248
5374
|
async function waitForSocketText(socket, getBuffer, done, timeoutMs) {
|
|
5249
|
-
return await new Promise((
|
|
5375
|
+
return await new Promise((resolve12, reject) => {
|
|
5250
5376
|
const timer = setTimeout(() => cleanup(() => reject(new Error("Timed out waiting for local mail server response."))), timeoutMs);
|
|
5251
5377
|
const check = () => {
|
|
5252
|
-
const
|
|
5253
|
-
if (done(
|
|
5378
|
+
const text2 = getBuffer();
|
|
5379
|
+
if (done(text2)) cleanup(() => resolve12(text2));
|
|
5254
5380
|
};
|
|
5255
5381
|
const onData = () => check();
|
|
5256
5382
|
const onError = (error) => cleanup(() => reject(error));
|
|
@@ -5275,7 +5401,7 @@ function startProtonBridgeProcess(command, args) {
|
|
|
5275
5401
|
if (child.exitCode !== null || child.killed) return;
|
|
5276
5402
|
child.kill("SIGTERM");
|
|
5277
5403
|
await Promise.race([
|
|
5278
|
-
new Promise((
|
|
5404
|
+
new Promise((resolve12) => child.once("exit", () => resolve12())),
|
|
5279
5405
|
sleep(2e3).then(() => {
|
|
5280
5406
|
if (child.exitCode === null && !child.killed) child.kill("SIGKILL");
|
|
5281
5407
|
})
|
|
@@ -5374,7 +5500,7 @@ async function captureOrPromptBridgeCredentials(command, args) {
|
|
|
5374
5500
|
}
|
|
5375
5501
|
}
|
|
5376
5502
|
async function captureProtonBridgeInfo(command, args) {
|
|
5377
|
-
return await new Promise((
|
|
5503
|
+
return await new Promise((resolve12, reject) => {
|
|
5378
5504
|
const child = spawn2(command, args, { stdio: "pipe" });
|
|
5379
5505
|
let output = "";
|
|
5380
5506
|
let errorOutput = "";
|
|
@@ -5394,7 +5520,7 @@ async function captureProtonBridgeInfo(command, args) {
|
|
|
5394
5520
|
});
|
|
5395
5521
|
child.once("exit", () => {
|
|
5396
5522
|
clearTimeout(timer);
|
|
5397
|
-
if (output.trim())
|
|
5523
|
+
if (output.trim()) resolve12(output);
|
|
5398
5524
|
else reject(new Error(redactProtonBridgeSecrets(errorOutput || "Proton Bridge info produced no output.")));
|
|
5399
5525
|
});
|
|
5400
5526
|
child.stdin.write("info\nquit\n");
|
|
@@ -5424,11 +5550,11 @@ async function promptHidden(prompt) {
|
|
|
5424
5550
|
const wasRaw = stdin.isRaw === true;
|
|
5425
5551
|
stdin.setRawMode(true);
|
|
5426
5552
|
stdin.resume();
|
|
5427
|
-
return await new Promise((
|
|
5553
|
+
return await new Promise((resolve12, reject) => {
|
|
5428
5554
|
let value = "";
|
|
5429
5555
|
const onData = (chunk) => {
|
|
5430
|
-
const
|
|
5431
|
-
for (const char of
|
|
5556
|
+
const text2 = chunk.toString("utf8");
|
|
5557
|
+
for (const char of text2) {
|
|
5432
5558
|
if (char === "") {
|
|
5433
5559
|
cleanup();
|
|
5434
5560
|
reject(new Error("Bridge credential prompt cancelled."));
|
|
@@ -5437,7 +5563,7 @@ async function promptHidden(prompt) {
|
|
|
5437
5563
|
if (char === "\r" || char === "\n") {
|
|
5438
5564
|
cleanup();
|
|
5439
5565
|
stderr.write("\n");
|
|
5440
|
-
|
|
5566
|
+
resolve12(value);
|
|
5441
5567
|
return;
|
|
5442
5568
|
}
|
|
5443
5569
|
if (char === "\x7F" || char === "\b") {
|
|
@@ -5460,7 +5586,7 @@ function stripTimer(job) {
|
|
|
5460
5586
|
}
|
|
5461
5587
|
|
|
5462
5588
|
// src/tasksCli.ts
|
|
5463
|
-
import { createHash as createHash8, createHmac as createHmac2, hkdfSync as hkdfSync2, randomBytes as randomBytes2, randomUUID as
|
|
5589
|
+
import { createHash as createHash8, createHmac as createHmac2, hkdfSync as hkdfSync2, randomBytes as randomBytes2, randomUUID as randomUUID5 } from "crypto";
|
|
5464
5590
|
|
|
5465
5591
|
// src/objectSlugs.ts
|
|
5466
5592
|
import { createHmac, hkdfSync } from "crypto";
|
|
@@ -5723,105 +5849,105 @@ async function buildCreateTaskActivityInput(task, masterKey, input) {
|
|
|
5723
5849
|
created_at: input.createdAt ?? nowSeconds()
|
|
5724
5850
|
};
|
|
5725
5851
|
}
|
|
5726
|
-
async function decryptTaskActivityEntry(task, masterKey,
|
|
5852
|
+
async function decryptTaskActivityEntry(task, masterKey, record2) {
|
|
5727
5853
|
const base = {
|
|
5728
|
-
entryId:
|
|
5729
|
-
taskId:
|
|
5730
|
-
kind:
|
|
5731
|
-
actorType:
|
|
5732
|
-
actorHash:
|
|
5733
|
-
actorIdentity:
|
|
5734
|
-
actorDisplayName:
|
|
5735
|
-
actorProfileImageUrl:
|
|
5736
|
-
authorHash:
|
|
5737
|
-
eventType:
|
|
5738
|
-
sourceSurface:
|
|
5739
|
-
previousStatus:
|
|
5740
|
-
nextStatus:
|
|
5741
|
-
createdAt:
|
|
5742
|
-
deletedAt:
|
|
5743
|
-
deletedByHash:
|
|
5744
|
-
deletedByDisplayName:
|
|
5745
|
-
embedRefs:
|
|
5854
|
+
entryId: record2.entry_id,
|
|
5855
|
+
taskId: record2.task_id,
|
|
5856
|
+
kind: record2.kind,
|
|
5857
|
+
actorType: record2.actor_type,
|
|
5858
|
+
actorHash: record2.actor_hash,
|
|
5859
|
+
actorIdentity: record2.actor_identity ?? null,
|
|
5860
|
+
actorDisplayName: record2.actor_display_name ?? null,
|
|
5861
|
+
actorProfileImageUrl: record2.actor_profile_image_url ?? null,
|
|
5862
|
+
authorHash: record2.author_hash ?? record2.actor_hash ?? null,
|
|
5863
|
+
eventType: record2.event_type,
|
|
5864
|
+
sourceSurface: record2.source_surface,
|
|
5865
|
+
previousStatus: record2.previous_status ?? null,
|
|
5866
|
+
nextStatus: record2.next_status ?? null,
|
|
5867
|
+
createdAt: record2.created_at,
|
|
5868
|
+
deletedAt: record2.deleted_at ?? null,
|
|
5869
|
+
deletedByHash: record2.deleted_by_hash ?? null,
|
|
5870
|
+
deletedByDisplayName: record2.deleted_by_display_name ?? null,
|
|
5871
|
+
embedRefs: record2.kind === "tombstone" ? [] : record2.embed_refs
|
|
5746
5872
|
};
|
|
5747
|
-
if (
|
|
5748
|
-
if (
|
|
5749
|
-
if (!
|
|
5750
|
-
throw new Error(`Task Activity entry ${
|
|
5873
|
+
if (record2.kind === "tombstone") return base;
|
|
5874
|
+
if (record2.kind !== "comment") return base;
|
|
5875
|
+
if (!record2.encrypted_message) {
|
|
5876
|
+
throw new Error(`Task Activity entry ${record2.entry_id} is missing encrypted content.`);
|
|
5751
5877
|
}
|
|
5752
5878
|
const taskKey = await taskKeyFromRecord(task.encrypted, masterKey);
|
|
5753
|
-
const message = await decryptWithAesGcmCombined(
|
|
5754
|
-
if (message === null) throw new Error(`Failed to decrypt Task Activity entry ${
|
|
5755
|
-
const embedKeyMaterial =
|
|
5756
|
-
if (
|
|
5757
|
-
throw new Error(`Failed to decrypt Task Activity embed key material ${
|
|
5879
|
+
const message = await decryptWithAesGcmCombined(record2.encrypted_message, taskKey, `task_activity_comment:${task.taskId}:${record2.entry_id}:v1`);
|
|
5880
|
+
if (message === null) throw new Error(`Failed to decrypt Task Activity entry ${record2.entry_id}.`);
|
|
5881
|
+
const embedKeyMaterial = record2.encrypted_embed_key_material ? await decryptWithAesGcmCombined(record2.encrypted_embed_key_material, taskKey, `task_activity_embed_keys:${task.taskId}:${record2.entry_id}:v1`) : null;
|
|
5882
|
+
if (record2.encrypted_embed_key_material && embedKeyMaterial === null) {
|
|
5883
|
+
throw new Error(`Failed to decrypt Task Activity embed key material ${record2.entry_id}.`);
|
|
5758
5884
|
}
|
|
5759
5885
|
return { ...base, message, ...embedKeyMaterial !== null ? { embedKeyMaterial } : {} };
|
|
5760
5886
|
}
|
|
5761
5887
|
async function decryptTaskActivityEntries(task, masterKey, records) {
|
|
5762
5888
|
const entries = [];
|
|
5763
|
-
for (const
|
|
5889
|
+
for (const record2 of records) entries.push(await decryptTaskActivityEntry(task, masterKey, record2));
|
|
5764
5890
|
return entries;
|
|
5765
5891
|
}
|
|
5766
|
-
async function decryptUserTask(
|
|
5767
|
-
if (
|
|
5768
|
-
if (typeof
|
|
5769
|
-
const taskKey = await taskKeyFromRecord(
|
|
5770
|
-
const labels = parseStringArray(await decryptOptional(
|
|
5771
|
-
const linkedProjectIds = parseStringArray(await decryptOptional(
|
|
5772
|
-
const externalChat =
|
|
5773
|
-
provider:
|
|
5774
|
-
id: await decryptOptional(
|
|
5775
|
-
title: await decryptOptional(
|
|
5892
|
+
async function decryptUserTask(record2, masterKey) {
|
|
5893
|
+
if (record2.source === "workflow_run") return workflowProjectionToTask(record2);
|
|
5894
|
+
if (typeof record2.version !== "number") throw new Error(`Task ${record2.task_id} is missing version.`);
|
|
5895
|
+
const taskKey = await taskKeyFromRecord(record2, masterKey);
|
|
5896
|
+
const labels = parseStringArray(await decryptOptional(record2.encrypted_labels || record2.encrypted_tags, taskKey));
|
|
5897
|
+
const linkedProjectIds = parseStringArray(await decryptOptional(record2.encrypted_linked_project_ids, taskKey));
|
|
5898
|
+
const externalChat = record2.external_chat_provider && record2.encrypted_external_chat_id ? {
|
|
5899
|
+
provider: record2.external_chat_provider,
|
|
5900
|
+
id: await decryptOptional(record2.encrypted_external_chat_id, taskKey),
|
|
5901
|
+
title: await decryptOptional(record2.encrypted_external_chat_title, taskKey)
|
|
5776
5902
|
} : null;
|
|
5777
5903
|
return {
|
|
5778
|
-
taskId:
|
|
5779
|
-
shortId:
|
|
5780
|
-
slug: await decryptObjectSlug(
|
|
5781
|
-
title: await decryptOptional(
|
|
5782
|
-
description: await decryptOptional(
|
|
5904
|
+
taskId: record2.task_id,
|
|
5905
|
+
shortId: record2.short_id || deriveShortId(record2),
|
|
5906
|
+
slug: await decryptObjectSlug(record2.encrypted_slug, taskKey),
|
|
5907
|
+
title: await decryptOptional(record2.encrypted_title, taskKey) || "(untitled task)",
|
|
5908
|
+
description: await decryptOptional(record2.encrypted_description, taskKey),
|
|
5783
5909
|
labels,
|
|
5784
5910
|
tags: labels,
|
|
5785
|
-
latestInstruction: await decryptOptional(
|
|
5786
|
-
status:
|
|
5787
|
-
assigneeType:
|
|
5788
|
-
assigneeIdentity:
|
|
5789
|
-
assigneeHash:
|
|
5790
|
-
primaryChatId:
|
|
5911
|
+
latestInstruction: await decryptOptional(record2.encrypted_latest_instruction, taskKey),
|
|
5912
|
+
status: record2.status,
|
|
5913
|
+
assigneeType: record2.assignee_type,
|
|
5914
|
+
assigneeIdentity: record2.assignee_identity ?? null,
|
|
5915
|
+
assigneeHash: record2.assignee_hash ?? null,
|
|
5916
|
+
primaryChatId: record2.primary_chat_id ?? null,
|
|
5791
5917
|
externalChat,
|
|
5792
|
-
linkedProjectIds: linkedProjectIds.length > 0 ? linkedProjectIds :
|
|
5793
|
-
planId:
|
|
5794
|
-
dueAt:
|
|
5795
|
-
priority:
|
|
5796
|
-
priorityLevel: taskPriorityLevel(
|
|
5797
|
-
position:
|
|
5798
|
-
queueState:
|
|
5799
|
-
blockedReasonCode:
|
|
5800
|
-
blockedReason: await decryptOptional(
|
|
5801
|
-
aiExecutionState:
|
|
5802
|
-
version:
|
|
5803
|
-
encrypted:
|
|
5918
|
+
linkedProjectIds: linkedProjectIds.length > 0 ? linkedProjectIds : record2.linked_project_ids ?? [],
|
|
5919
|
+
planId: record2.plan_id ?? null,
|
|
5920
|
+
dueAt: record2.due_at ?? null,
|
|
5921
|
+
priority: record2.priority ?? 0,
|
|
5922
|
+
priorityLevel: taskPriorityLevel(record2.priority),
|
|
5923
|
+
position: record2.position ?? 0,
|
|
5924
|
+
queueState: record2.queue_state ?? "none",
|
|
5925
|
+
blockedReasonCode: record2.blocked_reason_code ?? null,
|
|
5926
|
+
blockedReason: await decryptOptional(record2.encrypted_blocked_reason, taskKey),
|
|
5927
|
+
aiExecutionState: record2.ai_execution_state ?? null,
|
|
5928
|
+
version: record2.version,
|
|
5929
|
+
encrypted: record2
|
|
5804
5930
|
};
|
|
5805
5931
|
}
|
|
5806
|
-
function workflowProjectionToTask(
|
|
5807
|
-
const blockedReason =
|
|
5932
|
+
function workflowProjectionToTask(record2) {
|
|
5933
|
+
const blockedReason = record2.blocked_reason_code ?? record2.blocked_reason ?? null;
|
|
5808
5934
|
return {
|
|
5809
|
-
taskId:
|
|
5935
|
+
taskId: record2.task_id,
|
|
5810
5936
|
source: "workflow_run",
|
|
5811
|
-
projectionKind:
|
|
5812
|
-
workflowId:
|
|
5813
|
-
workflowRunId:
|
|
5814
|
-
triggerId:
|
|
5815
|
-
canCancel: Boolean(
|
|
5816
|
-
canDelete: Boolean(
|
|
5817
|
-
shortId:
|
|
5937
|
+
projectionKind: record2.projection_kind ?? null,
|
|
5938
|
+
workflowId: record2.workflow_id ?? null,
|
|
5939
|
+
workflowRunId: record2.workflow_run_id ?? null,
|
|
5940
|
+
triggerId: record2.trigger_id ?? null,
|
|
5941
|
+
canCancel: Boolean(record2.can_cancel),
|
|
5942
|
+
canDelete: Boolean(record2.can_delete),
|
|
5943
|
+
shortId: record2.short_id || workflowProjectionShortId(record2),
|
|
5818
5944
|
slug: "",
|
|
5819
|
-
title:
|
|
5820
|
-
description:
|
|
5945
|
+
title: record2.title || "Workflow run",
|
|
5946
|
+
description: record2.blocked_message ?? "",
|
|
5821
5947
|
labels: [],
|
|
5822
5948
|
tags: [],
|
|
5823
5949
|
latestInstruction: "",
|
|
5824
|
-
status:
|
|
5950
|
+
status: record2.status,
|
|
5825
5951
|
assigneeType: "user",
|
|
5826
5952
|
assigneeIdentity: null,
|
|
5827
5953
|
assigneeHash: null,
|
|
@@ -5829,17 +5955,17 @@ function workflowProjectionToTask(record) {
|
|
|
5829
5955
|
externalChat: null,
|
|
5830
5956
|
linkedProjectIds: [],
|
|
5831
5957
|
planId: null,
|
|
5832
|
-
dueAt:
|
|
5833
|
-
priority:
|
|
5834
|
-
priorityLevel: taskPriorityLevel(
|
|
5835
|
-
position:
|
|
5836
|
-
queueState: String(
|
|
5958
|
+
dueAt: record2.due_at ?? null,
|
|
5959
|
+
priority: record2.priority ?? 0,
|
|
5960
|
+
priorityLevel: taskPriorityLevel(record2.priority),
|
|
5961
|
+
position: record2.position ?? 0,
|
|
5962
|
+
queueState: String(record2.run_status ?? "workflow"),
|
|
5837
5963
|
blockedReasonCode: blockedReason,
|
|
5838
|
-
blockedReason:
|
|
5964
|
+
blockedReason: record2.blocked_message ?? "",
|
|
5839
5965
|
aiExecutionState: null,
|
|
5840
5966
|
readOnly: true,
|
|
5841
|
-
version: typeof
|
|
5842
|
-
encrypted:
|
|
5967
|
+
version: typeof record2.version === "number" ? record2.version : 1,
|
|
5968
|
+
encrypted: record2
|
|
5843
5969
|
};
|
|
5844
5970
|
}
|
|
5845
5971
|
async function buildBlockUserTaskInput(task, masterKey, input) {
|
|
@@ -5851,23 +5977,23 @@ async function buildBlockUserTaskInput(task, masterKey, input) {
|
|
|
5851
5977
|
...encryptedBlockedReason ? { encrypted_blocked_reason: encryptedBlockedReason } : {}
|
|
5852
5978
|
};
|
|
5853
5979
|
}
|
|
5854
|
-
function workflowProjectionShortId(
|
|
5855
|
-
const stableId =
|
|
5980
|
+
function workflowProjectionShortId(record2) {
|
|
5981
|
+
const stableId = record2.workflow_run_id || record2.task_id;
|
|
5856
5982
|
return `WF-${createHash8("sha256").update(stableId).digest("hex").slice(0, 6).toUpperCase()}`;
|
|
5857
5983
|
}
|
|
5858
5984
|
async function decryptUserTasks(records, masterKey) {
|
|
5859
5985
|
const output = [];
|
|
5860
|
-
for (const
|
|
5986
|
+
for (const record2 of records) output.push(await decryptUserTask(record2, masterKey));
|
|
5861
5987
|
return output;
|
|
5862
5988
|
}
|
|
5863
5989
|
async function decryptUserTasksForCli(records, masterKey, warn) {
|
|
5864
5990
|
const output = [];
|
|
5865
|
-
for (const
|
|
5991
|
+
for (const record2 of records) {
|
|
5866
5992
|
try {
|
|
5867
|
-
output.push(await decryptUserTask(
|
|
5993
|
+
output.push(await decryptUserTask(record2, masterKey));
|
|
5868
5994
|
} catch {
|
|
5869
|
-
const identifier =
|
|
5870
|
-
warn(`Warning: skipped undecryptable task ${identifier} (${
|
|
5995
|
+
const identifier = record2.short_id || record2.task_id || "unknown";
|
|
5996
|
+
warn(`Warning: skipped undecryptable task ${identifier} (${record2.task_id || "unknown"}).`);
|
|
5871
5997
|
}
|
|
5872
5998
|
}
|
|
5873
5999
|
return output;
|
|
@@ -5982,10 +6108,10 @@ function columnTitle(status) {
|
|
|
5982
6108
|
function assigneeLabel(task) {
|
|
5983
6109
|
return taskIdentityDisplayName(task.assigneeIdentity) ?? (task.assigneeType === "unassigned" ? "unassigned" : task.assigneeHash ?? "user");
|
|
5984
6110
|
}
|
|
5985
|
-
async function taskKeyFromRecord(
|
|
5986
|
-
if (!
|
|
5987
|
-
const taskKey = await decryptBytesWithAesGcm(
|
|
5988
|
-
if (!taskKey) throw new Error(`Failed to decrypt task key for ${
|
|
6111
|
+
async function taskKeyFromRecord(record2, masterKey) {
|
|
6112
|
+
if (!record2.encrypted_task_key) throw new Error(`Task ${record2.task_id} is missing encrypted task key.`);
|
|
6113
|
+
const taskKey = await decryptBytesWithAesGcm(record2.encrypted_task_key, masterKey);
|
|
6114
|
+
if (!taskKey) throw new Error(`Failed to decrypt task key for ${record2.task_id}.`);
|
|
5989
6115
|
return taskKey;
|
|
5990
6116
|
}
|
|
5991
6117
|
async function decryptOptional(value, key) {
|
|
@@ -6001,9 +6127,9 @@ function parseStringArray(value) {
|
|
|
6001
6127
|
return [];
|
|
6002
6128
|
}
|
|
6003
6129
|
}
|
|
6004
|
-
function deriveShortId(
|
|
6005
|
-
const prefix =
|
|
6006
|
-
const source =
|
|
6130
|
+
function deriveShortId(record2) {
|
|
6131
|
+
const prefix = record2.short_id_prefix || DEFAULT_STANDALONE_PREFIX;
|
|
6132
|
+
const source = record2.task_id || `${record2.created_at ?? ""}-${record2.position ?? ""}`;
|
|
6007
6133
|
const digest = createHash8("sha256").update(source).digest("hex").slice(0, 4).toUpperCase();
|
|
6008
6134
|
return `${prefix}-${parseInt(digest, 16) % 1e4}`;
|
|
6009
6135
|
}
|
|
@@ -6014,7 +6140,7 @@ function formatActivityTime(value) {
|
|
|
6014
6140
|
return new Date(value * 1e3).toISOString();
|
|
6015
6141
|
}
|
|
6016
6142
|
function randomUUIDCompat() {
|
|
6017
|
-
return
|
|
6143
|
+
return randomUUID5();
|
|
6018
6144
|
}
|
|
6019
6145
|
function pad(value, length) {
|
|
6020
6146
|
return truncate(value, length).padEnd(length);
|
|
@@ -6024,7 +6150,7 @@ function truncate(value, length) {
|
|
|
6024
6150
|
}
|
|
6025
6151
|
|
|
6026
6152
|
// src/plansCli.ts
|
|
6027
|
-
import { createHash as createHash9, randomBytes as randomBytes3, randomUUID as
|
|
6153
|
+
import { createHash as createHash9, randomBytes as randomBytes3, randomUUID as randomUUID6 } from "crypto";
|
|
6028
6154
|
var PLAN_STATUSES = ["draft", "checking_assumptions", "awaiting_confirmation", "active", "executing", "running_checks", "blocked", "completed", "archived"];
|
|
6029
6155
|
var LEARNING_TYPES = ["workflow_improvement", "agent_instruction_improvement"];
|
|
6030
6156
|
var LEARNING_TARGET_KINDS = ["workflow", "project_agent_instructions"];
|
|
@@ -6225,49 +6351,49 @@ async function buildUserPlanKeyWrappers(input) {
|
|
|
6225
6351
|
}
|
|
6226
6352
|
return wrappers;
|
|
6227
6353
|
}
|
|
6228
|
-
async function decryptUserPlan(
|
|
6229
|
-
if (typeof
|
|
6230
|
-
const planKey = await planKeyFromRecord(
|
|
6231
|
-
const linkedProjectIds = parseStringArray2(await decryptOptional2(
|
|
6354
|
+
async function decryptUserPlan(record2, masterKey) {
|
|
6355
|
+
if (typeof record2.version !== "number") throw new Error(`Plan ${record2.plan_id} is missing version.`);
|
|
6356
|
+
const planKey = await planKeyFromRecord(record2, masterKey);
|
|
6357
|
+
const linkedProjectIds = parseStringArray2(await decryptOptional2(record2.encrypted_linked_project_ids, planKey));
|
|
6232
6358
|
return {
|
|
6233
|
-
planId:
|
|
6234
|
-
shortId: deriveShortId2(
|
|
6235
|
-
slug: await decryptObjectSlug(
|
|
6236
|
-
title: await decryptOptional2(
|
|
6237
|
-
goal: await decryptOptional2(
|
|
6238
|
-
scopeIn: await decryptOptional2(
|
|
6239
|
-
scopeOut: await decryptOptional2(
|
|
6240
|
-
userFlows: parseUserFlows(await decryptOptional2(
|
|
6241
|
-
assumptions: await decryptOptional2(
|
|
6242
|
-
openQuestions: await decryptOptional2(
|
|
6243
|
-
constraints: await decryptOptional2(
|
|
6244
|
-
decisions: await decryptOptional2(
|
|
6245
|
-
risks: await decryptOptional2(
|
|
6246
|
-
referencePatterns: await decryptOptional2(
|
|
6247
|
-
context: await decryptOptional2(
|
|
6248
|
-
status:
|
|
6249
|
-
primaryChatId:
|
|
6250
|
-
linkedProjectIds: linkedProjectIds.length > 0 ? linkedProjectIds :
|
|
6251
|
-
plannerFocusId:
|
|
6252
|
-
version:
|
|
6253
|
-
createdAt:
|
|
6254
|
-
updatedAt:
|
|
6255
|
-
completedAt:
|
|
6256
|
-
encrypted:
|
|
6359
|
+
planId: record2.plan_id,
|
|
6360
|
+
shortId: deriveShortId2(record2),
|
|
6361
|
+
slug: await decryptObjectSlug(record2.encrypted_slug, planKey),
|
|
6362
|
+
title: await decryptOptional2(record2.encrypted_title, planKey) || "(untitled plan)",
|
|
6363
|
+
goal: await decryptOptional2(record2.encrypted_goal, planKey),
|
|
6364
|
+
scopeIn: await decryptOptional2(record2.encrypted_scope_in, planKey),
|
|
6365
|
+
scopeOut: await decryptOptional2(record2.encrypted_scope_out, planKey),
|
|
6366
|
+
userFlows: parseUserFlows(await decryptOptional2(record2.encrypted_user_flows, planKey)),
|
|
6367
|
+
assumptions: await decryptOptional2(record2.encrypted_assumptions, planKey),
|
|
6368
|
+
openQuestions: await decryptOptional2(record2.encrypted_open_questions, planKey),
|
|
6369
|
+
constraints: await decryptOptional2(record2.encrypted_constraints, planKey),
|
|
6370
|
+
decisions: await decryptOptional2(record2.encrypted_decisions, planKey),
|
|
6371
|
+
risks: await decryptOptional2(record2.encrypted_risks, planKey),
|
|
6372
|
+
referencePatterns: await decryptOptional2(record2.encrypted_reference_patterns, planKey),
|
|
6373
|
+
context: await decryptOptional2(record2.encrypted_context, planKey),
|
|
6374
|
+
status: record2.status,
|
|
6375
|
+
primaryChatId: record2.primary_chat_id ?? null,
|
|
6376
|
+
linkedProjectIds: linkedProjectIds.length > 0 ? linkedProjectIds : record2.linked_project_ids ?? [],
|
|
6377
|
+
plannerFocusId: record2.planner_focus_id ?? null,
|
|
6378
|
+
version: record2.version,
|
|
6379
|
+
createdAt: record2.created_at ?? 0,
|
|
6380
|
+
updatedAt: record2.updated_at ?? 0,
|
|
6381
|
+
completedAt: record2.completed_at ?? null,
|
|
6382
|
+
encrypted: record2
|
|
6257
6383
|
};
|
|
6258
6384
|
}
|
|
6259
6385
|
async function decryptUserPlans(records, masterKey) {
|
|
6260
6386
|
const output = [];
|
|
6261
|
-
for (const
|
|
6387
|
+
for (const record2 of records) output.push(await decryptUserPlan(record2, masterKey));
|
|
6262
6388
|
return output;
|
|
6263
6389
|
}
|
|
6264
6390
|
async function decryptUserPlansForCli(records, masterKey, warn) {
|
|
6265
6391
|
const output = [];
|
|
6266
|
-
for (const
|
|
6392
|
+
for (const record2 of records) {
|
|
6267
6393
|
try {
|
|
6268
|
-
output.push(await decryptUserPlan(
|
|
6394
|
+
output.push(await decryptUserPlan(record2, masterKey));
|
|
6269
6395
|
} catch {
|
|
6270
|
-
warn(`Warning: skipped undecryptable plan ${
|
|
6396
|
+
warn(`Warning: skipped undecryptable plan ${record2.plan_id || "unknown"}.`);
|
|
6271
6397
|
}
|
|
6272
6398
|
}
|
|
6273
6399
|
return output;
|
|
@@ -6317,34 +6443,34 @@ async function buildUpdatePlanLearningInput(plan, masterKey, input) {
|
|
|
6317
6443
|
if (input.rejectionReason !== void 0) patch.encrypted_rejection_reason = await encryptWithAesGcmCombined(input.rejectionReason, planKey);
|
|
6318
6444
|
return patch;
|
|
6319
6445
|
}
|
|
6320
|
-
async function decryptPlanLearning(plan,
|
|
6446
|
+
async function decryptPlanLearning(plan, record2, masterKey) {
|
|
6321
6447
|
const planKey = await planKeyFromRecord(plan.encrypted, masterKey);
|
|
6322
6448
|
return {
|
|
6323
|
-
learningId:
|
|
6324
|
-
type:
|
|
6325
|
-
targetKind:
|
|
6326
|
-
status:
|
|
6327
|
-
severity:
|
|
6328
|
-
confidence:
|
|
6329
|
-
linkedTaskIds:
|
|
6330
|
-
linkedCheckIds:
|
|
6331
|
-
appliedTaskId:
|
|
6332
|
-
title: await decryptOptional2(
|
|
6333
|
-
observation: await decryptOptional2(
|
|
6334
|
-
rootCause: await decryptOptional2(
|
|
6335
|
-
suggestedChange: await decryptOptional2(
|
|
6336
|
-
evidenceSummary: await decryptOptional2(
|
|
6337
|
-
taskDraft: await decryptOptional2(
|
|
6338
|
-
rejectionReason: await decryptOptional2(
|
|
6339
|
-
version:
|
|
6340
|
-
createdAt:
|
|
6341
|
-
updatedAt:
|
|
6342
|
-
encrypted:
|
|
6449
|
+
learningId: record2.learning_id,
|
|
6450
|
+
type: record2.type,
|
|
6451
|
+
targetKind: record2.target_kind,
|
|
6452
|
+
status: record2.status ?? "draft",
|
|
6453
|
+
severity: record2.severity ?? null,
|
|
6454
|
+
confidence: record2.confidence ?? null,
|
|
6455
|
+
linkedTaskIds: record2.linked_task_ids ?? [],
|
|
6456
|
+
linkedCheckIds: record2.linked_check_ids ?? [],
|
|
6457
|
+
appliedTaskId: record2.applied_task_id ?? null,
|
|
6458
|
+
title: await decryptOptional2(record2.encrypted_title, planKey) || "(untitled learning)",
|
|
6459
|
+
observation: await decryptOptional2(record2.encrypted_observation, planKey),
|
|
6460
|
+
rootCause: await decryptOptional2(record2.encrypted_root_cause, planKey),
|
|
6461
|
+
suggestedChange: await decryptOptional2(record2.encrypted_suggested_change, planKey),
|
|
6462
|
+
evidenceSummary: await decryptOptional2(record2.encrypted_evidence_summary, planKey),
|
|
6463
|
+
taskDraft: await decryptOptional2(record2.encrypted_task_draft, planKey),
|
|
6464
|
+
rejectionReason: await decryptOptional2(record2.encrypted_rejection_reason, planKey),
|
|
6465
|
+
version: record2.version ?? 1,
|
|
6466
|
+
createdAt: record2.created_at ?? 0,
|
|
6467
|
+
updatedAt: record2.updated_at ?? 0,
|
|
6468
|
+
encrypted: record2
|
|
6343
6469
|
};
|
|
6344
6470
|
}
|
|
6345
6471
|
async function decryptPlanLearnings(plan, records, masterKey) {
|
|
6346
6472
|
const output = [];
|
|
6347
|
-
for (const
|
|
6473
|
+
for (const record2 of records) output.push(await decryptPlanLearning(plan, record2, masterKey));
|
|
6348
6474
|
return output;
|
|
6349
6475
|
}
|
|
6350
6476
|
function findPlan(plans, id) {
|
|
@@ -6533,11 +6659,11 @@ function hasHiddenControlCharacter(value) {
|
|
|
6533
6659
|
function finalizedLearningNeedsTaskSafetyScan(learning) {
|
|
6534
6660
|
return FINALIZED_LEARNING_STATUSES.has(learning.status) && !learning.appliedTaskId && Boolean(learning.taskDraft.trim());
|
|
6535
6661
|
}
|
|
6536
|
-
async function planKeyFromRecord(
|
|
6537
|
-
const wrapper =
|
|
6538
|
-
if (!wrapper || typeof wrapper.encrypted_plan_key !== "string") throw new Error(`Plan ${
|
|
6662
|
+
async function planKeyFromRecord(record2, masterKey) {
|
|
6663
|
+
const wrapper = record2.key_wrappers?.find((candidate) => candidate.key_type === "master" && typeof candidate.encrypted_plan_key === "string");
|
|
6664
|
+
if (!wrapper || typeof wrapper.encrypted_plan_key !== "string") throw new Error(`Plan ${record2.plan_id} is missing a master key wrapper.`);
|
|
6539
6665
|
const planKey = await decryptBytesWithAesGcm(wrapper.encrypted_plan_key, masterKey);
|
|
6540
|
-
if (!planKey) throw new Error(`Failed to decrypt plan key for ${
|
|
6666
|
+
if (!planKey) throw new Error(`Failed to decrypt plan key for ${record2.plan_id}.`);
|
|
6541
6667
|
return planKey;
|
|
6542
6668
|
}
|
|
6543
6669
|
function sha256Hex3(value) {
|
|
@@ -6562,8 +6688,8 @@ function parseUserFlows(value) {
|
|
|
6562
6688
|
if (!Array.isArray(parsed)) throw new Error("Plan user flows must be an array.");
|
|
6563
6689
|
return validateUserFlows(parsed);
|
|
6564
6690
|
}
|
|
6565
|
-
function deriveShortId2(
|
|
6566
|
-
const source =
|
|
6691
|
+
function deriveShortId2(record2) {
|
|
6692
|
+
const source = record2.plan_id || `${record2.created_at ?? ""}-${record2.updated_at ?? ""}`;
|
|
6567
6693
|
const digest = createHash9("sha256").update(source).digest("hex").slice(0, 6).toUpperCase();
|
|
6568
6694
|
return `${DEFAULT_PLAN_PREFIX}-${digest}`;
|
|
6569
6695
|
}
|
|
@@ -6571,7 +6697,7 @@ function nowSeconds2() {
|
|
|
6571
6697
|
return Math.floor(Date.now() / 1e3);
|
|
6572
6698
|
}
|
|
6573
6699
|
function randomUUIDCompat2() {
|
|
6574
|
-
return
|
|
6700
|
+
return randomUUID6();
|
|
6575
6701
|
}
|
|
6576
6702
|
function pad2(value, length) {
|
|
6577
6703
|
return truncate2(value, length).padEnd(length);
|
|
@@ -7482,8 +7608,8 @@ var MATE_NAMES = {
|
|
|
7482
7608
|
general_knowledge: "George",
|
|
7483
7609
|
onboarding_support: "Suki"
|
|
7484
7610
|
};
|
|
7485
|
-
function stripLegacySuggestionPrefix(
|
|
7486
|
-
return
|
|
7611
|
+
function stripLegacySuggestionPrefix(text2) {
|
|
7612
|
+
return text2.replace(/^\s*\[[^\]]+\]\s*/, "").trim();
|
|
7487
7613
|
}
|
|
7488
7614
|
var CLOUD_API_URL = "https://api.openmates.org";
|
|
7489
7615
|
var DEFAULT_API_URL = process.env.OPENMATES_API_URL ?? CLOUD_API_URL;
|
|
@@ -7828,7 +7954,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
7828
7954
|
const wrappingKey = await this.getChatWrappingKey(null, masterKey);
|
|
7829
7955
|
const encryptedChats = [];
|
|
7830
7956
|
for (const chat of chats) {
|
|
7831
|
-
const chatId =
|
|
7957
|
+
const chatId = randomUUID7();
|
|
7832
7958
|
const chatKey = new Uint8Array(randomBytes4(32));
|
|
7833
7959
|
const encryptedChatKey = await encryptBytesWithAesGcm(chatKey, wrappingKey);
|
|
7834
7960
|
const createdAt = Math.floor((chat.created_at ? Date.parse(chat.created_at) : Date.now()) / 1e3);
|
|
@@ -7836,7 +7962,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
7836
7962
|
const messages = [];
|
|
7837
7963
|
let previousUserMessageId = null;
|
|
7838
7964
|
for (const message of chat.messages) {
|
|
7839
|
-
const messageId =
|
|
7965
|
+
const messageId = randomUUID7();
|
|
7840
7966
|
const identity = message.role === "assistant" ? message.imported_assistant_identity : null;
|
|
7841
7967
|
const isCompressionSummary = message.provider_metadata?.import_type === COMPRESSION_SUMMARY_CATEGORY;
|
|
7842
7968
|
messages.push({
|
|
@@ -7896,7 +8022,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
7896
8022
|
this.requireSession();
|
|
7897
8023
|
const now = Math.floor(Date.now() / 1e3);
|
|
7898
8024
|
const teamKeyBytes = randomBytes4(32);
|
|
7899
|
-
const teamId = input.teamId ??
|
|
8025
|
+
const teamId = input.teamId ?? randomUUID7();
|
|
7900
8026
|
const payload = {
|
|
7901
8027
|
team_id: teamId,
|
|
7902
8028
|
slug: input.slug ?? void 0,
|
|
@@ -8016,7 +8142,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
8016
8142
|
}
|
|
8017
8143
|
async createTeamInvite(teamId, input) {
|
|
8018
8144
|
this.requireSession();
|
|
8019
|
-
const inviteId = typeof input.invite_id === "string" ? input.invite_id :
|
|
8145
|
+
const inviteId = typeof input.invite_id === "string" ? input.invite_id : randomUUID7();
|
|
8020
8146
|
const payload = {
|
|
8021
8147
|
invite_id: inviteId,
|
|
8022
8148
|
created_at: input.created_at ?? Math.floor(Date.now() / 1e3),
|
|
@@ -8304,11 +8430,11 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
8304
8430
|
}
|
|
8305
8431
|
let anonymousId = loadAnonymousId();
|
|
8306
8432
|
if (!anonymousId) {
|
|
8307
|
-
anonymousId =
|
|
8433
|
+
anonymousId = randomUUID7();
|
|
8308
8434
|
saveAnonymousId(anonymousId);
|
|
8309
8435
|
}
|
|
8310
|
-
const chatId = `anonymous-${
|
|
8311
|
-
const messageId = `anonymous-message-${
|
|
8436
|
+
const chatId = `anonymous-${randomUUID7()}`;
|
|
8437
|
+
const messageId = `anonymous-message-${randomUUID7()}`;
|
|
8312
8438
|
const requestBody = {
|
|
8313
8439
|
anonymous_id: anonymousId,
|
|
8314
8440
|
client_chat_id: chatId,
|
|
@@ -8535,7 +8661,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
8535
8661
|
throw new Error("Could not resolve current user id for local connected-account connector.");
|
|
8536
8662
|
}
|
|
8537
8663
|
const { createHash: createHash16 } = await import("crypto");
|
|
8538
|
-
const accountId =
|
|
8664
|
+
const accountId = randomUUID7();
|
|
8539
8665
|
const masterKey = this.getMasterKeyBytes();
|
|
8540
8666
|
const encryptLocalConnectorValue = async (value) => {
|
|
8541
8667
|
const plaintext = typeof value === "string" ? value : JSON.stringify(value);
|
|
@@ -8698,7 +8824,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
8698
8824
|
pin: pin.trim().toUpperCase(),
|
|
8699
8825
|
token
|
|
8700
8826
|
});
|
|
8701
|
-
const sessionId =
|
|
8827
|
+
const sessionId = randomUUID7();
|
|
8702
8828
|
const login = await this.http.post(
|
|
8703
8829
|
"/v1/auth/login",
|
|
8704
8830
|
{
|
|
@@ -8885,7 +9011,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
8885
9011
|
}
|
|
8886
9012
|
const session = {
|
|
8887
9013
|
apiUrl: this.apiUrl,
|
|
8888
|
-
sessionId:
|
|
9014
|
+
sessionId: randomUUID7(),
|
|
8889
9015
|
wsToken: null,
|
|
8890
9016
|
cookies: this.http.getCookieMap(),
|
|
8891
9017
|
masterKeyExportedB64: material.masterKeyB64,
|
|
@@ -9080,7 +9206,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
9080
9206
|
if (!markdown) throw new Error("Draft markdown must not be empty.");
|
|
9081
9207
|
const masterKey = this.getMasterKeyBytes();
|
|
9082
9208
|
const encrypted = await this.saveEncryptedDraft({
|
|
9083
|
-
chatId: params.chatId ??
|
|
9209
|
+
chatId: params.chatId ?? randomUUID7(),
|
|
9084
9210
|
encryptedDraftMd: await encryptWithAesGcmCombined(markdown, masterKey),
|
|
9085
9211
|
encryptedDraftPreview: params.preview ? await encryptWithAesGcmCombined(params.preview, masterKey) : null
|
|
9086
9212
|
});
|
|
@@ -9182,7 +9308,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
9182
9308
|
}
|
|
9183
9309
|
async addIdeaBucketAudio(params) {
|
|
9184
9310
|
const now = Math.floor(Date.now() / 1e3);
|
|
9185
|
-
const chatId = params.chatId ??
|
|
9311
|
+
const chatId = params.chatId ?? randomUUID7();
|
|
9186
9312
|
const fileResult = processFiles([params.filePath], null);
|
|
9187
9313
|
if (fileResult.blocked.length > 0) {
|
|
9188
9314
|
throw new Error(fileResult.blocked.map((entry) => `${entry.path}: ${entry.error}`).join("; "));
|
|
@@ -9266,7 +9392,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
9266
9392
|
async addIdeaBucketPreparedIdeas(params) {
|
|
9267
9393
|
if (params.ideas.length === 0) throw new Error("IdeaBucket add requires at least one idea.");
|
|
9268
9394
|
const now = Math.floor(Date.now() / 1e3);
|
|
9269
|
-
const chatId = params.chatId ??
|
|
9395
|
+
const chatId = params.chatId ?? randomUUID7();
|
|
9270
9396
|
const bucketId = params.bucketId ?? defaultIdeaBucketProcessingWindowId();
|
|
9271
9397
|
const processingWindowId = bucketId;
|
|
9272
9398
|
const settings = params.prompt === void 0 || params.scheduledSendAt === void 0 ? await this.getIdeaBucketSettings() : null;
|
|
@@ -9333,7 +9459,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
9333
9459
|
try {
|
|
9334
9460
|
if (!ownerId) throw new Error("Authenticated user identity is required to store IdeaBucket embeds.");
|
|
9335
9461
|
const masterKey = this.getMasterKeyBytes();
|
|
9336
|
-
const messageId =
|
|
9462
|
+
const messageId = randomUUID7();
|
|
9337
9463
|
for (const embed of params.preparedEmbeds) {
|
|
9338
9464
|
const encrypted = await encryptEmbed(
|
|
9339
9465
|
embed,
|
|
@@ -9344,7 +9470,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
9344
9470
|
ownerId
|
|
9345
9471
|
);
|
|
9346
9472
|
if (!encrypted) continue;
|
|
9347
|
-
const storeRequestId =
|
|
9473
|
+
const storeRequestId = randomUUID7();
|
|
9348
9474
|
const stored = ws.waitForMessage(
|
|
9349
9475
|
"store_embed_confirmed",
|
|
9350
9476
|
(payload) => {
|
|
@@ -9371,7 +9497,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
9371
9497
|
updated_at: encrypted.updated_at
|
|
9372
9498
|
});
|
|
9373
9499
|
await stored;
|
|
9374
|
-
const keysRequestId =
|
|
9500
|
+
const keysRequestId = randomUUID7();
|
|
9375
9501
|
const keysStored = ws.waitForMessage(
|
|
9376
9502
|
"store_embed_keys_confirmed",
|
|
9377
9503
|
(payload) => payload.request_id === keysRequestId,
|
|
@@ -9793,7 +9919,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
9793
9919
|
}
|
|
9794
9920
|
async requestAssistantSpeechMessage(ws, chatId, messageId, segments) {
|
|
9795
9921
|
const timeoutMs = 10 * 60 * 1e3;
|
|
9796
|
-
return await new Promise((
|
|
9922
|
+
return await new Promise((resolve12, reject) => {
|
|
9797
9923
|
const expected = /* @__PURE__ */ new Set();
|
|
9798
9924
|
const queued = /* @__PURE__ */ new Set();
|
|
9799
9925
|
const terminal = /* @__PURE__ */ new Map();
|
|
@@ -9802,7 +9928,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
9802
9928
|
if (!accepted || expected.size === 0 || terminal.size !== expected.size) return;
|
|
9803
9929
|
cleanup();
|
|
9804
9930
|
const statuses = [...terminal.values()];
|
|
9805
|
-
|
|
9931
|
+
resolve12({
|
|
9806
9932
|
generated: statuses.filter((status) => status.status === "ready" && queued.has(String(status.segment_id))).length,
|
|
9807
9933
|
reused: statuses.filter((status) => status.status === "ready" && !queued.has(String(status.segment_id))).length,
|
|
9808
9934
|
failed: statuses.filter((status) => status.status === "error").length,
|
|
@@ -9906,12 +10032,12 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
9906
10032
|
const boundaryIndex = findCliMessageBoundaryIndex(state.messages, params.fromMessageId);
|
|
9907
10033
|
const sourceSlice = state.messages.slice(0, boundaryIndex + 1);
|
|
9908
10034
|
const masterKey = this.getMasterKeyBytes();
|
|
9909
|
-
const newChatId =
|
|
10035
|
+
const newChatId = randomUUID7();
|
|
9910
10036
|
const newChatKey = new Uint8Array(randomBytes4(32));
|
|
9911
10037
|
const now = Math.floor(Date.now() / 1e3);
|
|
9912
10038
|
const encryptedMessages = [];
|
|
9913
10039
|
for (const message of sourceSlice) {
|
|
9914
|
-
const newMessageId =
|
|
10040
|
+
const newMessageId = randomUUID7();
|
|
9915
10041
|
const encryptedMessage = {
|
|
9916
10042
|
client_message_id: newMessageId,
|
|
9917
10043
|
message_id: newMessageId,
|
|
@@ -10337,7 +10463,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
10337
10463
|
if (params.newChatId) {
|
|
10338
10464
|
chatId = params.newChatId;
|
|
10339
10465
|
} else if (!params.chatId) {
|
|
10340
|
-
chatId =
|
|
10466
|
+
chatId = randomUUID7();
|
|
10341
10467
|
} else if (!CANONICAL_UUID_PATTERN.test(params.chatId)) {
|
|
10342
10468
|
const resolved = await this.resolveFullChatId(params.chatId, { teamId });
|
|
10343
10469
|
if (!resolved) {
|
|
@@ -10385,7 +10511,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
10385
10511
|
ws.close();
|
|
10386
10512
|
throw new Error("Authenticated user identity is required for saved chat recovery.");
|
|
10387
10513
|
}
|
|
10388
|
-
const messageId =
|
|
10514
|
+
const messageId = randomUUID7();
|
|
10389
10515
|
const createdAt = Math.floor(Date.now() / 1e3);
|
|
10390
10516
|
const isNewChat = !params.chatId;
|
|
10391
10517
|
let messageHistoryForRequest = params.messageHistory;
|
|
@@ -10549,7 +10675,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
10549
10675
|
if (!params.incognito && chatKeyBytes && encryptedChatKey) {
|
|
10550
10676
|
const protocolVersion = 1;
|
|
10551
10677
|
const chatKeyVersion = 1;
|
|
10552
|
-
const turnId =
|
|
10678
|
+
const turnId = randomUUID7();
|
|
10553
10679
|
savedTurnId = turnId;
|
|
10554
10680
|
terminalExpectedMessagesV = baselineMessagesV + 1;
|
|
10555
10681
|
const recoveryKeypair = await deriveChatCompletionRecoveryKeypair(
|
|
@@ -11527,7 +11653,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
11527
11653
|
created_at: now
|
|
11528
11654
|
}
|
|
11529
11655
|
] : [];
|
|
11530
|
-
const storeRequestId =
|
|
11656
|
+
const storeRequestId = randomUUID7();
|
|
11531
11657
|
const storeConfirmed = params.ws.waitForMessage(
|
|
11532
11658
|
"store_embed_confirmed",
|
|
11533
11659
|
(payload) => {
|
|
@@ -11560,7 +11686,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
11560
11686
|
});
|
|
11561
11687
|
await storeConfirmed;
|
|
11562
11688
|
if (keys.length > 0) {
|
|
11563
|
-
const keysRequestId =
|
|
11689
|
+
const keysRequestId = randomUUID7();
|
|
11564
11690
|
const keysConfirmed = params.ws.waitForMessage(
|
|
11565
11691
|
"store_embed_keys_confirmed",
|
|
11566
11692
|
(payload) => {
|
|
@@ -11740,16 +11866,16 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
11740
11866
|
);
|
|
11741
11867
|
} catch (error) {
|
|
11742
11868
|
lastTransientError = error instanceof Error ? error.message : String(error);
|
|
11743
|
-
await new Promise((
|
|
11869
|
+
await new Promise((resolve12) => setTimeout(resolve12, SKILL_TASK_POLL_INTERVAL_MS));
|
|
11744
11870
|
continue;
|
|
11745
11871
|
}
|
|
11746
11872
|
if (!response.ok) {
|
|
11747
11873
|
if (response.status >= SKILL_TASK_POLL_TRANSIENT_ERROR_STATUS) {
|
|
11748
11874
|
lastTransientError = `HTTP ${response.status}`;
|
|
11749
|
-
await new Promise((
|
|
11875
|
+
await new Promise((resolve12) => setTimeout(resolve12, SKILL_TASK_POLL_INTERVAL_MS));
|
|
11750
11876
|
continue;
|
|
11751
11877
|
}
|
|
11752
|
-
throw new Error(`Task polling failed with HTTP ${response.status}
|
|
11878
|
+
throw new Error(`Task ${taskId} polling failed with HTTP ${response.status}. Generation was not retried; retain this task ID for recovery.`);
|
|
11753
11879
|
}
|
|
11754
11880
|
lastTransientError = null;
|
|
11755
11881
|
if (response.data.status === "completed") {
|
|
@@ -11758,7 +11884,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
11758
11884
|
if (response.data.status === "failed") {
|
|
11759
11885
|
throw new Error(response.data.error ?? "Task failed");
|
|
11760
11886
|
}
|
|
11761
|
-
await new Promise((
|
|
11887
|
+
await new Promise((resolve12) => setTimeout(resolve12, SKILL_TASK_POLL_INTERVAL_MS));
|
|
11762
11888
|
}
|
|
11763
11889
|
if (lastTransientError) {
|
|
11764
11890
|
throw new Error(
|
|
@@ -12493,11 +12619,11 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
12493
12619
|
}
|
|
12494
12620
|
return response.data.events ?? [];
|
|
12495
12621
|
}
|
|
12496
|
-
async followUpWorkflowInput(sessionId,
|
|
12622
|
+
async followUpWorkflowInput(sessionId, text2) {
|
|
12497
12623
|
this.requireSession();
|
|
12498
12624
|
const response = await this.http.post(
|
|
12499
12625
|
`/v1/workflows/input/${encodeURIComponent(sessionId)}/follow-up`,
|
|
12500
|
-
{ text },
|
|
12626
|
+
{ text: text2 },
|
|
12501
12627
|
this.getCliRequestHeaders()
|
|
12502
12628
|
);
|
|
12503
12629
|
if (!response.ok || !response.data.session) {
|
|
@@ -12690,16 +12816,16 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
12690
12816
|
if (!response.ok) throw this.projectRequestError("remote result", response);
|
|
12691
12817
|
return response.data;
|
|
12692
12818
|
}
|
|
12693
|
-
async decryptProjectKey(
|
|
12819
|
+
async decryptProjectKey(record2, options = {}) {
|
|
12694
12820
|
const teamId = this.resolveTeamContext(options);
|
|
12695
12821
|
if (!teamId) {
|
|
12696
|
-
if (typeof
|
|
12697
|
-
const projectKey2 = await decryptBytesWithAesGcm(
|
|
12822
|
+
if (typeof record2.encrypted_project_key !== "string") throw new Error("Project is missing its Personal key wrapper.");
|
|
12823
|
+
const projectKey2 = await decryptBytesWithAesGcm(record2.encrypted_project_key, this.getMasterKeyBytes());
|
|
12698
12824
|
if (!projectKey2) throw new Error("Unable to decrypt Project key.");
|
|
12699
12825
|
return projectKey2;
|
|
12700
12826
|
}
|
|
12701
12827
|
const teamKey = await this.loadTeamKeyBytes(teamId);
|
|
12702
|
-
const wrapper =
|
|
12828
|
+
const wrapper = record2.key_wrappers?.find(
|
|
12703
12829
|
(candidate) => candidate.key_type === "team" && candidate.team_key_epoch === 1
|
|
12704
12830
|
);
|
|
12705
12831
|
if (!teamKey || !wrapper) throw new Error("Team Project key wrapper is unavailable.");
|
|
@@ -13354,7 +13480,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
13354
13480
|
`Rate limited by settings API; retrying in ${Math.ceil(SETTINGS_GET_RATE_LIMIT_RETRY_MS / 1e3)}s...
|
|
13355
13481
|
`
|
|
13356
13482
|
);
|
|
13357
|
-
await new Promise((
|
|
13483
|
+
await new Promise((resolve12) => setTimeout(resolve12, SETTINGS_GET_RATE_LIMIT_RETRY_MS));
|
|
13358
13484
|
response = await this.http.get(normalizedPath, headers);
|
|
13359
13485
|
}
|
|
13360
13486
|
if (!response.ok) {
|
|
@@ -14075,7 +14201,7 @@ Required: ${schema.required.join(", ")}`
|
|
|
14075
14201
|
);
|
|
14076
14202
|
}
|
|
14077
14203
|
}
|
|
14078
|
-
const entryId = params.entryId ??
|
|
14204
|
+
const entryId = params.entryId ?? randomUUID7();
|
|
14079
14205
|
const now = Math.floor(Date.now() / 1e3);
|
|
14080
14206
|
const teamId = this.resolveTeamContext({ teamId: params.teamId, personal: params.personal });
|
|
14081
14207
|
const hashedKey = hashItemKey(params.appId, params.itemType);
|
|
@@ -14395,7 +14521,7 @@ Required: ${schema.required.join(", ")}`
|
|
|
14395
14521
|
const now = Math.floor(Date.now() / 1e3);
|
|
14396
14522
|
const { ws } = await this.openWsClient();
|
|
14397
14523
|
try {
|
|
14398
|
-
const storeRequestId =
|
|
14524
|
+
const storeRequestId = randomUUID7();
|
|
14399
14525
|
const storeConfirmed = ws.waitForMessage(
|
|
14400
14526
|
"store_embed_confirmed",
|
|
14401
14527
|
(payload) => {
|
|
@@ -14427,7 +14553,7 @@ Required: ${schema.required.join(", ")}`
|
|
|
14427
14553
|
updated_at: now
|
|
14428
14554
|
});
|
|
14429
14555
|
await storeConfirmed;
|
|
14430
|
-
const diffRequestId =
|
|
14556
|
+
const diffRequestId = randomUUID7();
|
|
14431
14557
|
const diffConfirmed = ws.waitForMessage(
|
|
14432
14558
|
"store_embed_diff_confirmed",
|
|
14433
14559
|
(payload) => {
|
|
@@ -14679,7 +14805,7 @@ Required: ${schema.required.join(", ")}`
|
|
|
14679
14805
|
makeWsClient(session, options = {}) {
|
|
14680
14806
|
return new OpenMatesWsClient({
|
|
14681
14807
|
apiUrl: session.apiUrl,
|
|
14682
|
-
sessionId:
|
|
14808
|
+
sessionId: randomUUID7(),
|
|
14683
14809
|
wsToken: session.wsToken,
|
|
14684
14810
|
refreshToken: session.cookies.auth_refresh_token ?? null,
|
|
14685
14811
|
// Same User-Agent as login so OS-based device fingerprint hash matches.
|
|
@@ -15201,7 +15327,7 @@ function filenameFromContentDisposition(header2) {
|
|
|
15201
15327
|
return plain?.trim() ?? null;
|
|
15202
15328
|
}
|
|
15203
15329
|
function sleep2(ms) {
|
|
15204
|
-
return new Promise((
|
|
15330
|
+
return new Promise((resolve12) => setTimeout(resolve12, ms));
|
|
15205
15331
|
}
|
|
15206
15332
|
function printLogo() {
|
|
15207
15333
|
const W = "\x1B[1;37m";
|
|
@@ -20159,14 +20285,14 @@ var GeneratedAppSkills = class {
|
|
|
20159
20285
|
|
|
20160
20286
|
// src/sdk.ts
|
|
20161
20287
|
import { decode as toonDecode } from "@toon-format/toon";
|
|
20162
|
-
import { createHash as createHash11, createHmac as createHmac3, randomBytes as randomBytes6, randomUUID as
|
|
20288
|
+
import { createHash as createHash11, createHmac as createHmac3, randomBytes as randomBytes6, randomUUID as randomUUID8 } from "crypto";
|
|
20163
20289
|
import { chmodSync as chmodSync2, existsSync as existsSync6, mkdirSync as mkdirSync3, readFileSync as readFileSync5, writeFileSync as writeFileSync3 } from "fs";
|
|
20164
20290
|
import { homedir as homedir5 } from "os";
|
|
20165
|
-
import { dirname as
|
|
20291
|
+
import { dirname as dirname3, join as join3 } from "path";
|
|
20166
20292
|
|
|
20167
20293
|
// src/designIcons.ts
|
|
20168
|
-
import { mkdir, writeFile } from "fs/promises";
|
|
20169
|
-
import { dirname, extname as
|
|
20294
|
+
import { mkdir as mkdir2, writeFile } from "fs/promises";
|
|
20295
|
+
import { dirname as dirname2, extname as extname3 } from "path";
|
|
20170
20296
|
import { Resvg } from "@resvg/resvg-js";
|
|
20171
20297
|
var ICON_SEGMENT_PATTERN = /^[a-z0-9][a-z0-9._-]*$/i;
|
|
20172
20298
|
var ICON_PATH_PATTERN = /^\/v1\/apps\/design\/icons\/iconify\/([a-z0-9][a-z0-9._-]*)\/([a-z0-9][a-z0-9._-]*)\.svg$/i;
|
|
@@ -20234,7 +20360,7 @@ function applyDesignIconColor(svg, color) {
|
|
|
20234
20360
|
}
|
|
20235
20361
|
function resolveDesignIconFormat(format, outputPath) {
|
|
20236
20362
|
if (format) return format;
|
|
20237
|
-
const extension = outputPath ?
|
|
20363
|
+
const extension = outputPath ? extname3(outputPath).toLowerCase() : ".svg";
|
|
20238
20364
|
return extension === ".png" ? "png" : "svg";
|
|
20239
20365
|
}
|
|
20240
20366
|
function decodeFetchedSvg(value) {
|
|
@@ -20256,9 +20382,9 @@ function normalizePngSize(value, label) {
|
|
|
20256
20382
|
return value;
|
|
20257
20383
|
}
|
|
20258
20384
|
async function writeExportFile(path2, data) {
|
|
20259
|
-
const directory =
|
|
20385
|
+
const directory = dirname2(path2);
|
|
20260
20386
|
if (directory && directory !== ".") {
|
|
20261
|
-
await
|
|
20387
|
+
await mkdir2(directory, { recursive: true });
|
|
20262
20388
|
}
|
|
20263
20389
|
await writeFile(path2, data);
|
|
20264
20390
|
}
|
|
@@ -20321,8 +20447,8 @@ var ACCOUNT_EXPORT_FORBIDDEN_VALUE_PATTERNS = [
|
|
|
20321
20447
|
/#key=[A-Za-z0-9_-]{8,}/
|
|
20322
20448
|
];
|
|
20323
20449
|
async function writeAccountExportArchive(bundle, flags = {}) {
|
|
20324
|
-
const { mkdir:
|
|
20325
|
-
const { join: join13, dirname:
|
|
20450
|
+
const { mkdir: mkdir3, writeFile: writeFile2 } = await import("fs/promises");
|
|
20451
|
+
const { join: join13, dirname: dirname12 } = await import("path");
|
|
20326
20452
|
const exportId = safeArchiveSegment(String(bundle.export.export_id ?? `export-${Date.now()}`));
|
|
20327
20453
|
const archiveFormat = flags.format === "directory" ? "directory" : "zip";
|
|
20328
20454
|
const password = typeof flags.password === "string" && flags.password.length > 0 ? flags.password : null;
|
|
@@ -20339,7 +20465,7 @@ async function writeAccountExportArchive(bundle, flags = {}) {
|
|
|
20339
20465
|
}
|
|
20340
20466
|
const stagingDir = outputPath;
|
|
20341
20467
|
const fullPath = join13(stagingDir, relativePath);
|
|
20342
|
-
await
|
|
20468
|
+
await mkdir3(dirname12(fullPath), { recursive: true });
|
|
20343
20469
|
await writeFile2(fullPath, content, "utf-8");
|
|
20344
20470
|
writtenFiles.push(relativePath);
|
|
20345
20471
|
}
|
|
@@ -20356,7 +20482,7 @@ async function writeAccountExportArchive(bundle, flags = {}) {
|
|
|
20356
20482
|
}
|
|
20357
20483
|
await writeAccountExportChatFiles(domainPayloads.chats ?? [], writeArchiveText);
|
|
20358
20484
|
if (archiveFormat === "directory") return { output: outputPath, format: "directory", files: writtenFiles.length };
|
|
20359
|
-
await
|
|
20485
|
+
await mkdir3(dirname12(outputPath), { recursive: true });
|
|
20360
20486
|
const zipBuffer = await zip.generateAsync({ type: "nodebuffer", compression: "DEFLATE" });
|
|
20361
20487
|
await writeFile2(outputPath, password ? encryptZipBuffer(zipBuffer, password) : zipBuffer);
|
|
20362
20488
|
return { output: outputPath, format: "zip", files: writtenFiles.length, ...password ? { encrypted: true } : {} };
|
|
@@ -20502,8 +20628,8 @@ function buildAccountExportChatMarkdown(chat) {
|
|
|
20502
20628
|
lines.push("## Messages", "");
|
|
20503
20629
|
for (const message of messages) {
|
|
20504
20630
|
if (!message || typeof message !== "object" || Array.isArray(message)) continue;
|
|
20505
|
-
const
|
|
20506
|
-
lines.push(`### ${String(
|
|
20631
|
+
const record2 = message;
|
|
20632
|
+
lines.push(`### ${String(record2.role ?? record2.sender ?? "message")}`, "", String(record2.content ?? record2.text ?? ""), "");
|
|
20507
20633
|
}
|
|
20508
20634
|
} else {
|
|
20509
20635
|
lines.push("No readable message records were included in this export chunk.", "");
|
|
@@ -20597,18 +20723,18 @@ var IDEABUCKET_DEFAULT_PROCESSING_TIMES2 = ["09:00"];
|
|
|
20597
20723
|
var IDEABUCKET_PROCESSING_TIME_PATTERN2 = /^([01]\d|2[0-3]):([0-5]\d)$/;
|
|
20598
20724
|
function appSkillChatContent(value) {
|
|
20599
20725
|
if (!value || typeof value !== "object") return "";
|
|
20600
|
-
const
|
|
20601
|
-
if (typeof
|
|
20602
|
-
if (typeof
|
|
20603
|
-
if (typeof
|
|
20604
|
-
const choices =
|
|
20726
|
+
const record2 = value;
|
|
20727
|
+
if (typeof record2.content === "string") return record2.content;
|
|
20728
|
+
if (typeof record2.response === "string") return record2.response;
|
|
20729
|
+
if (typeof record2.answer === "string") return record2.answer;
|
|
20730
|
+
const choices = record2.choices;
|
|
20605
20731
|
if (Array.isArray(choices)) {
|
|
20606
20732
|
const first = choices[0];
|
|
20607
20733
|
const message = first?.message;
|
|
20608
20734
|
if (typeof message?.content === "string") return message.content;
|
|
20609
20735
|
if (typeof first?.text === "string") return first.text;
|
|
20610
20736
|
}
|
|
20611
|
-
return appSkillChatContent(
|
|
20737
|
+
return appSkillChatContent(record2.data);
|
|
20612
20738
|
}
|
|
20613
20739
|
function sdkOrigin(apiUrl) {
|
|
20614
20740
|
if (process.env.OPENMATES_APP_URL) return process.env.OPENMATES_APP_URL.replace(/\/$/, "");
|
|
@@ -21007,13 +21133,13 @@ var OpenMates = class {
|
|
|
21007
21133
|
});
|
|
21008
21134
|
} catch (error) {
|
|
21009
21135
|
lastTransientError = error instanceof Error ? error.message : String(error);
|
|
21010
|
-
await new Promise((
|
|
21136
|
+
await new Promise((resolve12) => setTimeout(resolve12, CODE_RUN_POLL_INTERVAL_MS));
|
|
21011
21137
|
continue;
|
|
21012
21138
|
}
|
|
21013
21139
|
if (!response.ok) {
|
|
21014
21140
|
if (response.status >= SKILL_TASK_POLL_TRANSIENT_ERROR_STATUS2) {
|
|
21015
21141
|
lastTransientError = `HTTP ${response.status}`;
|
|
21016
|
-
await new Promise((
|
|
21142
|
+
await new Promise((resolve12) => setTimeout(resolve12, CODE_RUN_POLL_INTERVAL_MS));
|
|
21017
21143
|
continue;
|
|
21018
21144
|
}
|
|
21019
21145
|
throw new OpenMatesApiError(response.status, await this.safeJson(response));
|
|
@@ -21022,7 +21148,7 @@ var OpenMates = class {
|
|
|
21022
21148
|
const status = await this.parseResponse(response);
|
|
21023
21149
|
const value = typeof status.status === "string" ? status.status : "";
|
|
21024
21150
|
if (CODE_RUN_TERMINAL_STATUSES.has(value)) return status;
|
|
21025
|
-
await new Promise((
|
|
21151
|
+
await new Promise((resolve12) => setTimeout(resolve12, CODE_RUN_POLL_INTERVAL_MS));
|
|
21026
21152
|
}
|
|
21027
21153
|
if (lastTransientError) {
|
|
21028
21154
|
throw new Error(`Code Run did not complete within ${CODE_RUN_POLL_TIMEOUT_MS / 1e3}s; last polling error: ${lastTransientError}`);
|
|
@@ -21047,13 +21173,13 @@ var OpenMates = class {
|
|
|
21047
21173
|
});
|
|
21048
21174
|
} catch (error) {
|
|
21049
21175
|
lastTransientError = error instanceof Error ? error.message : String(error);
|
|
21050
|
-
await new Promise((
|
|
21176
|
+
await new Promise((resolve12) => setTimeout(resolve12, SKILL_TASK_POLL_INTERVAL_MS2));
|
|
21051
21177
|
continue;
|
|
21052
21178
|
}
|
|
21053
21179
|
if (!response.ok) {
|
|
21054
21180
|
if (response.status >= SKILL_TASK_POLL_TRANSIENT_ERROR_STATUS2) {
|
|
21055
21181
|
lastTransientError = `HTTP ${response.status}`;
|
|
21056
|
-
await new Promise((
|
|
21182
|
+
await new Promise((resolve12) => setTimeout(resolve12, SKILL_TASK_POLL_INTERVAL_MS2));
|
|
21057
21183
|
continue;
|
|
21058
21184
|
}
|
|
21059
21185
|
throw new OpenMatesApiError(response.status, await this.safeJson(response));
|
|
@@ -21062,7 +21188,7 @@ var OpenMates = class {
|
|
|
21062
21188
|
const task = await this.parseResponse(response);
|
|
21063
21189
|
if (task.status === "completed") return task;
|
|
21064
21190
|
if (task.status === "failed") throw new Error(task.error ?? "Task failed");
|
|
21065
|
-
await new Promise((
|
|
21191
|
+
await new Promise((resolve12) => setTimeout(resolve12, SKILL_TASK_POLL_INTERVAL_MS2));
|
|
21066
21192
|
}
|
|
21067
21193
|
if (lastTransientError) {
|
|
21068
21194
|
throw new Error(`Task ${taskId} did not complete within ${SKILL_TASK_POLL_TIMEOUT_MS2 / 1e3}s; last polling error: ${lastTransientError}`);
|
|
@@ -21101,8 +21227,8 @@ function loadOrCreateDeviceId(customPath) {
|
|
|
21101
21227
|
const stored = readFileSync5(path2, "utf8").trim();
|
|
21102
21228
|
if (stored) return stored;
|
|
21103
21229
|
}
|
|
21104
|
-
const deviceId =
|
|
21105
|
-
mkdirSync3(
|
|
21230
|
+
const deviceId = randomUUID8();
|
|
21231
|
+
mkdirSync3(dirname3(path2), { recursive: true, mode: 448 });
|
|
21106
21232
|
writeFileSync3(path2, `${deviceId}
|
|
21107
21233
|
`, { encoding: "utf8", mode: 384 });
|
|
21108
21234
|
chmodSync2(path2, 384);
|
|
@@ -21154,7 +21280,7 @@ async function buildTeamPlainCreatePayload(client, input) {
|
|
|
21154
21280
|
const now = Math.floor(Date.now() / 1e3);
|
|
21155
21281
|
const createdAt = input.createdAt ?? now;
|
|
21156
21282
|
const payload = {
|
|
21157
|
-
team_id: input.teamId ??
|
|
21283
|
+
team_id: input.teamId ?? randomUUID8(),
|
|
21158
21284
|
slug: input.slug ?? void 0,
|
|
21159
21285
|
encrypted_name: await encryptWithAesGcmCombined(name, teamKey),
|
|
21160
21286
|
encrypted_description: input.description ? await encryptWithAesGcmCombined(input.description, teamKey) : void 0,
|
|
@@ -21195,7 +21321,7 @@ async function buildProjectCreatePayload(wrappingKey, input, teamId = null) {
|
|
|
21195
21321
|
lookupKey: wrappingKey
|
|
21196
21322
|
});
|
|
21197
21323
|
const payload = {
|
|
21198
|
-
project_id:
|
|
21324
|
+
project_id: randomUUID8(),
|
|
21199
21325
|
encrypted_project_key: teamId ? null : await encryptBytesWithAesGcm(projectKey, wrappingKey),
|
|
21200
21326
|
encrypted_slug: slugMetadata.encrypted_slug,
|
|
21201
21327
|
slug_lookup_hash: slugMetadata.slug_lookup_hash,
|
|
@@ -21219,36 +21345,36 @@ async function buildProjectCreatePayload(wrappingKey, input, teamId = null) {
|
|
|
21219
21345
|
};
|
|
21220
21346
|
return { payload, projectKey };
|
|
21221
21347
|
}
|
|
21222
|
-
async function decryptSdkProject(
|
|
21223
|
-
const encryptedProjectKey = teamId ?
|
|
21224
|
-
if (typeof encryptedProjectKey !== "string") throw new OpenMatesConfigError(`Project ${
|
|
21348
|
+
async function decryptSdkProject(record2, wrappingKey, teamId = null) {
|
|
21349
|
+
const encryptedProjectKey = teamId ? record2.key_wrappers?.find((wrapper) => wrapper.key_type === "team" && wrapper.hashed_team_id === createHash11("sha256").update(teamId).digest("hex") && wrapper.team_key_epoch === 1)?.encrypted_project_key : record2.encrypted_project_key;
|
|
21350
|
+
if (typeof encryptedProjectKey !== "string") throw new OpenMatesConfigError(`Project ${record2.project_id} is missing encrypted project key`);
|
|
21225
21351
|
const projectKey = await decryptBytesWithAesGcm(encryptedProjectKey, wrappingKey);
|
|
21226
|
-
if (!projectKey) throw new OpenMatesConfigError(`Failed to decrypt Project key for ${
|
|
21227
|
-
return decryptSdkProjectWithKey(
|
|
21352
|
+
if (!projectKey) throw new OpenMatesConfigError(`Failed to decrypt Project key for ${record2.project_id}`);
|
|
21353
|
+
return decryptSdkProjectWithKey(record2, projectKey);
|
|
21228
21354
|
}
|
|
21229
|
-
async function decryptSdkProjectWithKey(
|
|
21355
|
+
async function decryptSdkProjectWithKey(record2, projectKey) {
|
|
21230
21356
|
return {
|
|
21231
|
-
projectId:
|
|
21232
|
-
slug: await decryptObjectSlug(
|
|
21233
|
-
name: await decryptOptionalProjectField(
|
|
21234
|
-
description: await decryptOptionalProjectField(
|
|
21235
|
-
icon: await decryptOptionalProjectField(
|
|
21236
|
-
color: await decryptOptionalProjectField(
|
|
21237
|
-
pinned:
|
|
21238
|
-
archived:
|
|
21239
|
-
version: typeof
|
|
21240
|
-
createdAt: typeof
|
|
21241
|
-
updatedAt: typeof
|
|
21242
|
-
lastOpenedAt: typeof
|
|
21357
|
+
projectId: record2.project_id,
|
|
21358
|
+
slug: await decryptObjectSlug(record2.encrypted_slug, projectKey),
|
|
21359
|
+
name: await decryptOptionalProjectField(record2.encrypted_name, projectKey) || "(untitled project)",
|
|
21360
|
+
description: await decryptOptionalProjectField(record2.encrypted_description, projectKey),
|
|
21361
|
+
icon: await decryptOptionalProjectField(record2.encrypted_icon, projectKey),
|
|
21362
|
+
color: await decryptOptionalProjectField(record2.encrypted_color, projectKey),
|
|
21363
|
+
pinned: record2.pinned === true,
|
|
21364
|
+
archived: record2.archived === true,
|
|
21365
|
+
version: typeof record2.version === "number" ? record2.version : null,
|
|
21366
|
+
createdAt: typeof record2.created_at === "number" ? record2.created_at : null,
|
|
21367
|
+
updatedAt: typeof record2.updated_at === "number" ? record2.updated_at : null,
|
|
21368
|
+
lastOpenedAt: typeof record2.last_opened_at === "number" ? record2.last_opened_at : null
|
|
21243
21369
|
};
|
|
21244
21370
|
}
|
|
21245
21371
|
async function decryptOptionalProjectField(value, projectKey) {
|
|
21246
21372
|
return value ? await decryptWithAesGcmCombined(value, projectKey) ?? "" : "";
|
|
21247
21373
|
}
|
|
21248
21374
|
async function buildProjectUpdatePayload(client, projectId, input, context = { personal: true }) {
|
|
21249
|
-
const { record, projectKey } = await resolveSdkProject(client, projectId, context);
|
|
21375
|
+
const { record: record2, projectKey } = await resolveSdkProject(client, projectId, context);
|
|
21250
21376
|
const patch = {
|
|
21251
|
-
...typeof
|
|
21377
|
+
...typeof record2.version === "number" ? { version: record2.version } : {},
|
|
21252
21378
|
updated_at: Math.floor(Date.now() / 1e3)
|
|
21253
21379
|
};
|
|
21254
21380
|
if (input.name !== void 0) patch.encrypted_name = await encryptWithAesGcmCombined(input.name, projectKey);
|
|
@@ -21267,7 +21393,7 @@ async function buildProjectUpdatePayload(client, projectId, input, context = { p
|
|
|
21267
21393
|
}
|
|
21268
21394
|
if (input.pinned !== void 0) patch.pinned = input.pinned;
|
|
21269
21395
|
if (input.archived !== void 0) patch.archived = input.archived;
|
|
21270
|
-
return { project_id:
|
|
21396
|
+
return { project_id: record2.project_id, patch, projectKey };
|
|
21271
21397
|
}
|
|
21272
21398
|
function toPublicPlan(plan) {
|
|
21273
21399
|
const { encrypted: _encrypted, ...publicPlan } = plan;
|
|
@@ -21286,14 +21412,14 @@ async function resolveSdkProject(client, projectId, context = { personal: true }
|
|
|
21286
21412
|
const resolvedProjectId = await resolveSdkProjectId(client, projectId, context);
|
|
21287
21413
|
const crypto2 = await projectWrappingKey(client, context);
|
|
21288
21414
|
const response = await client.get(withQuery(`/v1/projects/${encodeURIComponent(resolvedProjectId)}`, { team_id: crypto2.teamId }));
|
|
21289
|
-
const
|
|
21290
|
-
if (!
|
|
21415
|
+
const record2 = response.project;
|
|
21416
|
+
if (!record2) throw new OpenMatesApiError(404, { detail: "Project not found" });
|
|
21291
21417
|
const teamHash = crypto2.teamId ? createHash11("sha256").update(crypto2.teamId).digest("hex") : null;
|
|
21292
|
-
const encryptedProjectKey = crypto2.teamId ?
|
|
21418
|
+
const encryptedProjectKey = crypto2.teamId ? record2.key_wrappers?.find((wrapper) => wrapper.key_type === "team" && wrapper.hashed_team_id === teamHash && wrapper.team_key_epoch === 1)?.encrypted_project_key : record2.encrypted_project_key;
|
|
21293
21419
|
if (typeof encryptedProjectKey !== "string") throw new OpenMatesConfigError("Project response is missing encrypted Project key wrapper");
|
|
21294
21420
|
const projectKey = await decryptBytesWithAesGcm(encryptedProjectKey, crypto2.key);
|
|
21295
21421
|
if (!projectKey) throw new OpenMatesConfigError("Failed to decrypt Project key");
|
|
21296
|
-
return { record, projectKey };
|
|
21422
|
+
return { record: record2, projectKey };
|
|
21297
21423
|
}
|
|
21298
21424
|
async function resolveSdkProjectId(client, projectId, context = { personal: true }) {
|
|
21299
21425
|
if (CANONICAL_UUID_PATTERN2.test(projectId)) return projectId;
|
|
@@ -21369,8 +21495,8 @@ async function listSdkRawPlans(client, filters = {}) {
|
|
|
21369
21495
|
async function resolveSdkPlanProjectLinks(client, projectIds) {
|
|
21370
21496
|
if (projectIds === void 0) return {};
|
|
21371
21497
|
const entries = await Promise.all(projectIds.map(async (projectId) => {
|
|
21372
|
-
const { record, projectKey } = await resolveSdkProject(client, projectId);
|
|
21373
|
-
return { projectId:
|
|
21498
|
+
const { record: record2, projectKey } = await resolveSdkProject(client, projectId);
|
|
21499
|
+
return { projectId: record2.project_id, projectKey };
|
|
21374
21500
|
}));
|
|
21375
21501
|
return {
|
|
21376
21502
|
linkedProjectIds: entries.map((entry) => entry.projectId),
|
|
@@ -21423,95 +21549,95 @@ function withoutEncryptedLearning(learning) {
|
|
|
21423
21549
|
const { encrypted: _encrypted, ...publicLearning } = learning;
|
|
21424
21550
|
return publicLearning;
|
|
21425
21551
|
}
|
|
21426
|
-
async function toPublicPlanCriterion(
|
|
21552
|
+
async function toPublicPlanCriterion(record2, planKey) {
|
|
21427
21553
|
return {
|
|
21428
|
-
criterionId:
|
|
21429
|
-
text: await decryptOptionalPlanField(
|
|
21430
|
-
type:
|
|
21431
|
-
status:
|
|
21432
|
-
required:
|
|
21433
|
-
linkedTaskIds:
|
|
21434
|
-
verificationIds:
|
|
21435
|
-
createdAt: typeof
|
|
21436
|
-
updatedAt: typeof
|
|
21554
|
+
criterionId: record2.criterion_id,
|
|
21555
|
+
text: await decryptOptionalPlanField(record2.encrypted_text, planKey),
|
|
21556
|
+
type: record2.type,
|
|
21557
|
+
status: record2.status,
|
|
21558
|
+
required: record2.required,
|
|
21559
|
+
linkedTaskIds: record2.linked_task_ids ?? [],
|
|
21560
|
+
verificationIds: record2.verification_ids ?? [],
|
|
21561
|
+
createdAt: typeof record2.created_at === "number" ? record2.created_at : null,
|
|
21562
|
+
updatedAt: typeof record2.updated_at === "number" ? record2.updated_at : null
|
|
21437
21563
|
};
|
|
21438
21564
|
}
|
|
21439
|
-
async function toPublicPlanAssumption(
|
|
21565
|
+
async function toPublicPlanAssumption(record2, planKey) {
|
|
21440
21566
|
return {
|
|
21441
|
-
assumptionId:
|
|
21442
|
-
text: await decryptOptionalPlanField(
|
|
21443
|
-
category:
|
|
21444
|
-
status:
|
|
21445
|
-
requiredBefore:
|
|
21446
|
-
linkedSubChatId:
|
|
21447
|
-
linkedTaskId:
|
|
21448
|
-
linkedCriterionIds:
|
|
21449
|
-
sourceCount:
|
|
21450
|
-
correctedText: await decryptOptionalPlanField(
|
|
21451
|
-
evidenceSummary: await decryptOptionalPlanField(
|
|
21452
|
-
blockerReason: await decryptOptionalPlanField(
|
|
21453
|
-
waiverReason: await decryptOptionalPlanField(
|
|
21454
|
-
sources: await decryptOptionalPlanField(
|
|
21455
|
-
createdAt: typeof
|
|
21456
|
-
updatedAt: typeof
|
|
21567
|
+
assumptionId: record2.assumption_id,
|
|
21568
|
+
text: await decryptOptionalPlanField(record2.encrypted_text, planKey),
|
|
21569
|
+
category: record2.category,
|
|
21570
|
+
status: record2.status,
|
|
21571
|
+
requiredBefore: record2.required_before,
|
|
21572
|
+
linkedSubChatId: record2.linked_sub_chat_id ?? null,
|
|
21573
|
+
linkedTaskId: record2.linked_task_id ?? null,
|
|
21574
|
+
linkedCriterionIds: record2.linked_criterion_ids ?? [],
|
|
21575
|
+
sourceCount: record2.source_count,
|
|
21576
|
+
correctedText: await decryptOptionalPlanField(record2.encrypted_corrected_text, planKey),
|
|
21577
|
+
evidenceSummary: await decryptOptionalPlanField(record2.encrypted_evidence_summary, planKey),
|
|
21578
|
+
blockerReason: await decryptOptionalPlanField(record2.encrypted_blocker_reason, planKey),
|
|
21579
|
+
waiverReason: await decryptOptionalPlanField(record2.encrypted_waiver_reason, planKey),
|
|
21580
|
+
sources: await decryptOptionalPlanField(record2.encrypted_sources, planKey),
|
|
21581
|
+
createdAt: typeof record2.created_at === "number" ? record2.created_at : null,
|
|
21582
|
+
updatedAt: typeof record2.updated_at === "number" ? record2.updated_at : null
|
|
21457
21583
|
};
|
|
21458
21584
|
}
|
|
21459
|
-
async function toPublicPlanReferencePattern(
|
|
21585
|
+
async function toPublicPlanReferencePattern(record2, planKey) {
|
|
21460
21586
|
return {
|
|
21461
|
-
patternId:
|
|
21462
|
-
title: await decryptOptionalPlanField(
|
|
21463
|
-
description: await decryptOptionalPlanField(
|
|
21464
|
-
category:
|
|
21465
|
-
status:
|
|
21466
|
-
requiredBefore:
|
|
21467
|
-
sourceCount:
|
|
21468
|
-
linkedTaskIds:
|
|
21469
|
-
linkedCheckIds:
|
|
21470
|
-
sources: await decryptOptionalPlanField(
|
|
21471
|
-
matchRules: await decryptOptionalPlanField(
|
|
21472
|
-
antiPatterns: await decryptOptionalPlanField(
|
|
21473
|
-
evidenceSummary: await decryptOptionalPlanField(
|
|
21474
|
-
waiverReason: await decryptOptionalPlanField(
|
|
21475
|
-
createdAt: typeof
|
|
21476
|
-
updatedAt: typeof
|
|
21587
|
+
patternId: record2.pattern_id,
|
|
21588
|
+
title: await decryptOptionalPlanField(record2.encrypted_title, planKey) || "(untitled pattern)",
|
|
21589
|
+
description: await decryptOptionalPlanField(record2.encrypted_description, planKey),
|
|
21590
|
+
category: record2.category,
|
|
21591
|
+
status: record2.status,
|
|
21592
|
+
requiredBefore: record2.required_before,
|
|
21593
|
+
sourceCount: record2.source_count,
|
|
21594
|
+
linkedTaskIds: record2.linked_task_ids ?? [],
|
|
21595
|
+
linkedCheckIds: record2.linked_check_ids ?? [],
|
|
21596
|
+
sources: await decryptOptionalPlanField(record2.encrypted_sources, planKey),
|
|
21597
|
+
matchRules: await decryptOptionalPlanField(record2.encrypted_match_rules, planKey),
|
|
21598
|
+
antiPatterns: await decryptOptionalPlanField(record2.encrypted_anti_patterns, planKey),
|
|
21599
|
+
evidenceSummary: await decryptOptionalPlanField(record2.encrypted_evidence_summary, planKey),
|
|
21600
|
+
waiverReason: await decryptOptionalPlanField(record2.encrypted_waiver_reason, planKey),
|
|
21601
|
+
createdAt: typeof record2.created_at === "number" ? record2.created_at : null,
|
|
21602
|
+
updatedAt: typeof record2.updated_at === "number" ? record2.updated_at : null
|
|
21477
21603
|
};
|
|
21478
21604
|
}
|
|
21479
|
-
async function toPublicPlanVerification(
|
|
21605
|
+
async function toPublicPlanVerification(record2, planKey) {
|
|
21480
21606
|
return {
|
|
21481
|
-
verificationId:
|
|
21482
|
-
kind:
|
|
21483
|
-
phase:
|
|
21484
|
-
status:
|
|
21485
|
-
requiredForDone:
|
|
21486
|
-
covers:
|
|
21487
|
-
sourceHash:
|
|
21488
|
-
threshold:
|
|
21489
|
-
score:
|
|
21490
|
-
confidence:
|
|
21491
|
-
linkedTaskId:
|
|
21492
|
-
runId:
|
|
21493
|
-
lifecycleStatus:
|
|
21494
|
-
linkedSubChatId:
|
|
21495
|
-
sourceEmbedId:
|
|
21496
|
-
runnerKind:
|
|
21497
|
-
description: await decryptOptionalPlanField(
|
|
21498
|
-
command: await decryptOptionalPlanField(
|
|
21499
|
-
evaluationPrompt: await decryptOptionalPlanField(
|
|
21500
|
-
evaluatorInstructions: await decryptOptionalPlanField(
|
|
21501
|
-
expectedResult: await decryptOptionalPlanField(
|
|
21502
|
-
sourcePath: await decryptOptionalPlanField(
|
|
21503
|
-
redPhaseReason: await decryptOptionalPlanField(
|
|
21504
|
-
resultSummary: await decryptOptionalPlanField(
|
|
21505
|
-
requiredFixes: await decryptOptionalPlanField(
|
|
21506
|
-
createdAt: typeof
|
|
21507
|
-
updatedAt: typeof
|
|
21607
|
+
verificationId: record2.verification_id,
|
|
21608
|
+
kind: record2.kind,
|
|
21609
|
+
phase: record2.phase,
|
|
21610
|
+
status: record2.status,
|
|
21611
|
+
requiredForDone: record2.required_for_done,
|
|
21612
|
+
covers: record2.covers ?? [],
|
|
21613
|
+
sourceHash: record2.source_hash ?? null,
|
|
21614
|
+
threshold: record2.threshold ?? null,
|
|
21615
|
+
score: record2.score ?? null,
|
|
21616
|
+
confidence: record2.confidence ?? null,
|
|
21617
|
+
linkedTaskId: record2.linked_task_id ?? null,
|
|
21618
|
+
runId: record2.run_id ?? null,
|
|
21619
|
+
lifecycleStatus: record2.lifecycle_status ?? null,
|
|
21620
|
+
linkedSubChatId: record2.linked_sub_chat_id ?? null,
|
|
21621
|
+
sourceEmbedId: record2.source_embed_id ?? null,
|
|
21622
|
+
runnerKind: record2.runner_kind ?? null,
|
|
21623
|
+
description: await decryptOptionalPlanField(record2.encrypted_description, planKey),
|
|
21624
|
+
command: await decryptOptionalPlanField(record2.encrypted_command, planKey),
|
|
21625
|
+
evaluationPrompt: await decryptOptionalPlanField(record2.encrypted_evaluation_prompt, planKey),
|
|
21626
|
+
evaluatorInstructions: await decryptOptionalPlanField(record2.encrypted_evaluator_instructions, planKey),
|
|
21627
|
+
expectedResult: await decryptOptionalPlanField(record2.encrypted_expected_result, planKey),
|
|
21628
|
+
sourcePath: await decryptOptionalPlanField(record2.encrypted_source_path, planKey),
|
|
21629
|
+
redPhaseReason: await decryptOptionalPlanField(record2.encrypted_red_phase_reason, planKey),
|
|
21630
|
+
resultSummary: await decryptOptionalPlanField(record2.encrypted_result_summary, planKey),
|
|
21631
|
+
requiredFixes: await decryptOptionalPlanField(record2.encrypted_required_fixes, planKey),
|
|
21632
|
+
createdAt: typeof record2.created_at === "number" ? record2.created_at : null,
|
|
21633
|
+
updatedAt: typeof record2.updated_at === "number" ? record2.updated_at : null
|
|
21508
21634
|
};
|
|
21509
21635
|
}
|
|
21510
21636
|
async function buildPlanAssumptionCreateInput(plan, masterKey, input) {
|
|
21511
21637
|
const planKey = await planKeyFromRecord(plan.encrypted, masterKey);
|
|
21512
21638
|
const timestamp = Math.floor(Date.now() / 1e3);
|
|
21513
21639
|
return {
|
|
21514
|
-
assumption_id: input.assumptionId ??
|
|
21640
|
+
assumption_id: input.assumptionId ?? randomUUID8(),
|
|
21515
21641
|
encrypted_text: await encryptWithAesGcmCombined(input.text, planKey),
|
|
21516
21642
|
category: input.category,
|
|
21517
21643
|
status: input.status,
|
|
@@ -21550,7 +21676,7 @@ async function buildPlanReferencePatternCreateInput(plan, masterKey, input) {
|
|
|
21550
21676
|
const planKey = await planKeyFromRecord(plan.encrypted, masterKey);
|
|
21551
21677
|
const timestamp = Math.floor(Date.now() / 1e3);
|
|
21552
21678
|
return {
|
|
21553
|
-
pattern_id: input.patternId ??
|
|
21679
|
+
pattern_id: input.patternId ?? randomUUID8(),
|
|
21554
21680
|
encrypted_title: await encryptWithAesGcmCombined(input.title, planKey),
|
|
21555
21681
|
encrypted_description: input.description !== void 0 ? await encryptWithAesGcmCombined(input.description, planKey) : void 0,
|
|
21556
21682
|
category: input.category,
|
|
@@ -21588,7 +21714,7 @@ async function buildPlanReferencePatternUpdateInput(plan, masterKey, input) {
|
|
|
21588
21714
|
async function createSdkProjectItem(client, projectId, projectKey, input) {
|
|
21589
21715
|
const timestamp = Math.floor(Date.now() / 1e3);
|
|
21590
21716
|
const response = await client.request(`/v1/projects/${encodeURIComponent(projectId)}/items`, {
|
|
21591
|
-
project_item_id:
|
|
21717
|
+
project_item_id: randomUUID8(),
|
|
21592
21718
|
folder_id: input.folder ?? null,
|
|
21593
21719
|
item_type: input.itemType,
|
|
21594
21720
|
target_id: input.targetId,
|
|
@@ -21625,18 +21751,18 @@ function normalizeHistory(history) {
|
|
|
21625
21751
|
return Array.isArray(history.messages) ? history.messages : [];
|
|
21626
21752
|
}
|
|
21627
21753
|
function rememberableMessagesFromRecords(records) {
|
|
21628
|
-
return records.map((
|
|
21629
|
-
const id = stringField(
|
|
21630
|
-
const content = stringField(
|
|
21754
|
+
return records.map((record2) => {
|
|
21755
|
+
const id = stringField(record2.id) ?? stringField(record2.client_message_id) ?? stringField(record2.message_id);
|
|
21756
|
+
const content = stringField(record2.content);
|
|
21631
21757
|
if (!id || content === null) return null;
|
|
21632
21758
|
return {
|
|
21633
21759
|
id,
|
|
21634
|
-
role: stringField(
|
|
21760
|
+
role: stringField(record2.role) ?? "unknown",
|
|
21635
21761
|
content,
|
|
21636
|
-
senderName: stringField(
|
|
21637
|
-
category: stringField(
|
|
21638
|
-
modelName: stringField(
|
|
21639
|
-
createdAt: numericField(
|
|
21762
|
+
senderName: stringField(record2.senderName) ?? stringField(record2.sender_name),
|
|
21763
|
+
category: stringField(record2.category),
|
|
21764
|
+
modelName: stringField(record2.modelName) ?? stringField(record2.model_name),
|
|
21765
|
+
createdAt: numericField(record2.created_at) ?? 0,
|
|
21640
21766
|
preview: content.replace(/\s+/g, " ").trim().slice(0, 120)
|
|
21641
21767
|
};
|
|
21642
21768
|
}).filter((message) => message !== null);
|
|
@@ -21688,12 +21814,12 @@ var OpenMatesChats = class {
|
|
|
21688
21814
|
}
|
|
21689
21815
|
}
|
|
21690
21816
|
async addToProject(chatId, projectId, options = {}) {
|
|
21691
|
-
const { record, projectKey } = await resolveSdkProject(this.client, projectId);
|
|
21817
|
+
const { record: record2, projectKey } = await resolveSdkProject(this.client, projectId);
|
|
21692
21818
|
const loaded = await this.load(chatId);
|
|
21693
21819
|
const chat = loaded.chat;
|
|
21694
21820
|
const targetId = String(chat?.id ?? chatId);
|
|
21695
21821
|
const displayName = typeof chat?.title === "string" ? chat.title : targetId;
|
|
21696
|
-
return createSdkProjectItem(this.client,
|
|
21822
|
+
return createSdkProjectItem(this.client, record2.project_id, projectKey, {
|
|
21697
21823
|
itemType: "chat",
|
|
21698
21824
|
targetId,
|
|
21699
21825
|
displayName,
|
|
@@ -21788,13 +21914,13 @@ var OpenMatesChats = class {
|
|
|
21788
21914
|
const boundaryIndex = findMessageBoundaryIndex(messages, options.fromMessageId);
|
|
21789
21915
|
const sourceSlice = messages.slice(0, boundaryIndex + 1);
|
|
21790
21916
|
const masterKey = await this.client.masterKey();
|
|
21791
|
-
const newChatId =
|
|
21917
|
+
const newChatId = randomUUID8();
|
|
21792
21918
|
const newChatKey = new Uint8Array(randomBytes6(32));
|
|
21793
21919
|
const now = Math.floor(Date.now() / 1e3);
|
|
21794
21920
|
const idMap = /* @__PURE__ */ new Map();
|
|
21795
21921
|
const encryptedMessages = [];
|
|
21796
21922
|
for (const message of sourceSlice) {
|
|
21797
|
-
const newMessageId =
|
|
21923
|
+
const newMessageId = randomUUID8();
|
|
21798
21924
|
idMap.set(message.id, newMessageId);
|
|
21799
21925
|
const raw = message.raw;
|
|
21800
21926
|
const encryptedMessage = {
|
|
@@ -21927,9 +22053,9 @@ var OpenMatesChats = class {
|
|
|
21927
22053
|
}
|
|
21928
22054
|
const teamId = options.teamId?.trim() || null;
|
|
21929
22055
|
const wrappingKey = teamId ? await teamKeyForRecord(this.client, await this.client.teams.get(teamId)) : masterKey;
|
|
21930
|
-
const chatId = options.chatId ? await resolveSdkChatId(this.client, options.chatId) :
|
|
21931
|
-
const turnId =
|
|
21932
|
-
const messageId =
|
|
22056
|
+
const chatId = options.chatId ? await resolveSdkChatId(this.client, options.chatId) : randomUUID8();
|
|
22057
|
+
const turnId = randomUUID8();
|
|
22058
|
+
const messageId = randomUUID8();
|
|
21933
22059
|
const createdAt = Math.floor(Date.now() / 1e3);
|
|
21934
22060
|
let chatKey;
|
|
21935
22061
|
let encryptedChatKey;
|
|
@@ -22125,7 +22251,7 @@ var OpenMatesChats = class {
|
|
|
22125
22251
|
}
|
|
22126
22252
|
const remainingMs = deadline - Date.now();
|
|
22127
22253
|
if (remainingMs <= 0) break;
|
|
22128
|
-
await new Promise((
|
|
22254
|
+
await new Promise((resolve12) => setTimeout(resolve12, Math.min(pollIntervalMs, remainingMs)));
|
|
22129
22255
|
}
|
|
22130
22256
|
throw new OpenMatesConfigError("Timed out waiting for saved chat recovery");
|
|
22131
22257
|
}
|
|
@@ -22358,7 +22484,7 @@ var OpenMatesIdeaBucket = class {
|
|
|
22358
22484
|
const bucketId = input.bucketId ?? new Date(now * 1e3).toISOString().slice(0, 10);
|
|
22359
22485
|
const settings = input.prompt === void 0 || input.scheduledSendAt === void 0 ? await this.settings() : null;
|
|
22360
22486
|
const scheduledSendAt = input.scheduledSendAt ?? (settings?.source === "account" ? nextIdeaBucketScheduledSendAt2(now, settings.processingTimes) : defaultIdeaBucketScheduledSendAt2(now));
|
|
22361
|
-
const chatId = input.chatId ??
|
|
22487
|
+
const chatId = input.chatId ?? randomUUID8();
|
|
22362
22488
|
const prompt = input.prompt ?? settings?.processingPrompt ?? IDEABUCKET_DEFAULT_PROCESSING_PROMPT2;
|
|
22363
22489
|
const markdown = buildIdeaBucketMarkdown2(prompt, ideaText);
|
|
22364
22490
|
const preview = `IdeaBucket ${bucketId}: ${ideaText.slice(0, 120)}`;
|
|
@@ -22631,14 +22757,14 @@ var OpenMatesAccount = class {
|
|
|
22631
22757
|
const masterKey = await this.client.masterKey();
|
|
22632
22758
|
const encryptedChats = [];
|
|
22633
22759
|
for (const chat of chats) {
|
|
22634
|
-
const chatId =
|
|
22760
|
+
const chatId = randomUUID8();
|
|
22635
22761
|
const chatKey = new Uint8Array(randomBytes6(32));
|
|
22636
22762
|
const createdAt = Math.floor((chat.created_at ? Date.parse(chat.created_at) : Date.now()) / 1e3);
|
|
22637
22763
|
const updatedAt = Math.floor((chat.updated_at ? Date.parse(chat.updated_at) : Date.now()) / 1e3);
|
|
22638
22764
|
const messages = [];
|
|
22639
22765
|
let previousUserMessageId = null;
|
|
22640
22766
|
for (const message of chat.messages) {
|
|
22641
|
-
const messageId =
|
|
22767
|
+
const messageId = randomUUID8();
|
|
22642
22768
|
const identity = message.role === "assistant" ? message.imported_assistant_identity : null;
|
|
22643
22769
|
const isCompressionSummary = message.provider_metadata.import_type === COMPRESSION_SUMMARY_CATEGORY;
|
|
22644
22770
|
messages.push({
|
|
@@ -22686,7 +22812,7 @@ var OpenMatesAccount = class {
|
|
|
22686
22812
|
const maxBatchCount = typeof preview.max_batch_count === "number" ? preview.max_batch_count : defaultSelectionCount;
|
|
22687
22813
|
const selectedCount = options.select === "all" ? Math.min(parsed.chats.length, maxBatchCount) : Math.min(defaultSelectionCount, parsed.chats.length, maxBatchCount);
|
|
22688
22814
|
if (selectedCount <= 0) throw new OpenMatesConfigError("No chats are selected for import.");
|
|
22689
|
-
const importId = typeof preview.import_id === "string" ? preview.import_id :
|
|
22815
|
+
const importId = typeof preview.import_id === "string" ? preview.import_id : randomUUID8();
|
|
22690
22816
|
const selectedChats = parsed.chats.slice(0, selectedCount);
|
|
22691
22817
|
const selectedFingerprints = selectedChats.map((chat) => chat.source_fingerprint);
|
|
22692
22818
|
const confirmation = await this.confirmImport(importId, selectedFingerprints);
|
|
@@ -22826,24 +22952,24 @@ var OpenMatesApiKeys = class {
|
|
|
22826
22952
|
async revoke(id) {
|
|
22827
22953
|
return this.client.delete(`/v1/sdk/settings/api-keys/${encodeURIComponent(id)}`);
|
|
22828
22954
|
}
|
|
22829
|
-
async decryptRecord(
|
|
22830
|
-
const encryptedName = typeof
|
|
22831
|
-
const encryptedPrefix = typeof
|
|
22955
|
+
async decryptRecord(record2, masterKey) {
|
|
22956
|
+
const encryptedName = typeof record2.encrypted_name === "string" ? record2.encrypted_name : "";
|
|
22957
|
+
const encryptedPrefix = typeof record2.encrypted_key_prefix === "string" ? record2.encrypted_key_prefix : "";
|
|
22832
22958
|
const name = encryptedName ? await decryptWithAesGcmCombined(encryptedName, masterKey) : null;
|
|
22833
22959
|
const keyPrefix = encryptedPrefix ? await decryptWithAesGcmCombined(encryptedPrefix, masterKey) : null;
|
|
22834
|
-
const lastUsedAt = typeof
|
|
22960
|
+
const lastUsedAt = typeof record2.last_used_at === "string" ? record2.last_used_at : null;
|
|
22835
22961
|
return {
|
|
22836
|
-
id: String(
|
|
22962
|
+
id: String(record2.id ?? ""),
|
|
22837
22963
|
name: name || encryptedName || "Unnamed API key",
|
|
22838
22964
|
keyPrefix: keyPrefix || encryptedPrefix || "sk-api-...",
|
|
22839
|
-
createdAt: typeof
|
|
22840
|
-
expiresAt: typeof
|
|
22965
|
+
createdAt: typeof record2.created_at === "string" ? record2.created_at : null,
|
|
22966
|
+
expiresAt: typeof record2.expires_at === "string" ? record2.expires_at : null,
|
|
22841
22967
|
lastUsedAt,
|
|
22842
22968
|
lastUsedLabel: lastUsedAt ? new Date(lastUsedAt).toLocaleString() : "Never used",
|
|
22843
|
-
fullAccess: typeof
|
|
22844
|
-
scopes:
|
|
22845
|
-
creditLimit:
|
|
22846
|
-
pendingDeviceCount: typeof
|
|
22969
|
+
fullAccess: typeof record2.full_access === "boolean" ? record2.full_access : true,
|
|
22970
|
+
scopes: record2.scopes && typeof record2.scopes === "object" ? record2.scopes : {},
|
|
22971
|
+
creditLimit: record2.credit_limit && typeof record2.credit_limit === "object" ? record2.credit_limit : null,
|
|
22972
|
+
pendingDeviceCount: typeof record2.pending_device_count === "number" ? record2.pending_device_count : 0
|
|
22847
22973
|
};
|
|
22848
22974
|
}
|
|
22849
22975
|
};
|
|
@@ -22887,7 +23013,7 @@ var OpenMatesMemories = class {
|
|
|
22887
23013
|
}
|
|
22888
23014
|
const now = Math.floor(Date.now() / 1e3);
|
|
22889
23015
|
const entry = {
|
|
22890
|
-
id: String(input.id ??
|
|
23016
|
+
id: String(input.id ?? randomUUID8()),
|
|
22891
23017
|
app_id: appId,
|
|
22892
23018
|
item_key: hashItemKey(appId, itemType),
|
|
22893
23019
|
item_type: itemType,
|
|
@@ -23048,8 +23174,8 @@ var OpenMatesProjects = class {
|
|
|
23048
23174
|
return Promise.all((response.projects ?? []).map((project) => decryptSdkProject(project, crypto2.key, crypto2.teamId)));
|
|
23049
23175
|
}
|
|
23050
23176
|
async show(projectId, context) {
|
|
23051
|
-
const { record, projectKey } = await resolveSdkProject(this.client, projectId, context);
|
|
23052
|
-
return decryptSdkProjectWithKey(
|
|
23177
|
+
const { record: record2, projectKey } = await resolveSdkProject(this.client, projectId, context);
|
|
23178
|
+
return decryptSdkProjectWithKey(record2, projectKey);
|
|
23053
23179
|
}
|
|
23054
23180
|
async create(input, context) {
|
|
23055
23181
|
const crypto2 = await projectWrappingKey(this.client, context);
|
|
@@ -23416,7 +23542,7 @@ function isTaskVersionConflict(error) {
|
|
|
23416
23542
|
return error instanceof OpenMatesApiError && error.status === 409 && String(JSON.stringify(error.data)).includes("TASK_VERSION_CONFLICT");
|
|
23417
23543
|
}
|
|
23418
23544
|
function delay(ms) {
|
|
23419
|
-
return new Promise((
|
|
23545
|
+
return new Promise((resolve12) => setTimeout(resolve12, ms));
|
|
23420
23546
|
}
|
|
23421
23547
|
var OpenMatesPlans = class {
|
|
23422
23548
|
client;
|
|
@@ -23550,14 +23676,14 @@ var OpenMatesPlans = class {
|
|
|
23550
23676
|
async addToProject(planId, projectId) {
|
|
23551
23677
|
const masterKey = await this.client.masterKey();
|
|
23552
23678
|
const plan = await decryptUserPlan(await this.getRawPlan(planId), masterKey);
|
|
23553
|
-
const { record, projectKey } = await resolveSdkProject(this.client, projectId);
|
|
23554
|
-
const linkedProjectIds = appendUniqueProjectId(plan.linkedProjectIds,
|
|
23679
|
+
const { record: record2, projectKey } = await resolveSdkProject(this.client, projectId);
|
|
23680
|
+
const linkedProjectIds = appendUniqueProjectId(plan.linkedProjectIds, record2.project_id);
|
|
23555
23681
|
const projectLinks = await resolveSdkPlanProjectLinks(this.client, linkedProjectIds);
|
|
23556
23682
|
const response = await this.client.patch(`/v1/user-plans/${encodeURIComponent(plan.planId)}`, await buildUpdateUserPlanInput(plan, masterKey, {
|
|
23557
23683
|
primaryChatId: plan.primaryChatId,
|
|
23558
23684
|
primaryChatKey: plan.primaryChatId ? await resolveSdkChatKey(this.client, plan.primaryChatId) : null,
|
|
23559
23685
|
linkedProjectIds,
|
|
23560
|
-
linkedProjectKeys: projectLinks.linkedProjectKeys ?? [{ projectId:
|
|
23686
|
+
linkedProjectKeys: projectLinks.linkedProjectKeys ?? [{ projectId: record2.project_id, projectKey }]
|
|
23561
23687
|
}));
|
|
23562
23688
|
if (!response.plan) throw new OpenMatesApiError(500, { detail: "User plan response missing plan" });
|
|
23563
23689
|
return toPublicPlan(await decryptUserPlan(response.plan, masterKey));
|
|
@@ -23633,8 +23759,8 @@ var OpenMatesPlans = class {
|
|
|
23633
23759
|
}
|
|
23634
23760
|
const response = await this.client.request(`/v1/user-plans/${encodeURIComponent(existing.plan_id)}/activate`, payload);
|
|
23635
23761
|
if (!response.plan) throw new OpenMatesApiError(500, { detail: "User plan response missing plan" });
|
|
23636
|
-
const
|
|
23637
|
-
return toPublicPlan(await decryptUserPlan(
|
|
23762
|
+
const record2 = response.plan.primary_chat_id || typeof payload.chat_id !== "string" ? response.plan : { ...response.plan, primary_chat_id: payload.chat_id };
|
|
23763
|
+
return toPublicPlan(await decryptUserPlan(record2, await this.client.masterKey()));
|
|
23638
23764
|
}
|
|
23639
23765
|
async attach(planId, input = {}) {
|
|
23640
23766
|
return this.activate(planId, input);
|
|
@@ -23899,9 +24025,9 @@ var OpenMatesWorkflows = class {
|
|
|
23899
24025
|
throw new OpenMatesConfigError(`Workflow '${workflowId}' was not found.`);
|
|
23900
24026
|
}
|
|
23901
24027
|
async addToProject(workflowId, projectId, options = {}) {
|
|
23902
|
-
const { record, projectKey } = await resolveSdkProject(this.client, projectId);
|
|
24028
|
+
const { record: record2, projectKey } = await resolveSdkProject(this.client, projectId);
|
|
23903
24029
|
const workflow = await this.get(workflowId);
|
|
23904
|
-
return createSdkProjectItem(this.client,
|
|
24030
|
+
return createSdkProjectItem(this.client, record2.project_id, projectKey, {
|
|
23905
24031
|
itemType: "workflow",
|
|
23906
24032
|
targetId: workflow.id,
|
|
23907
24033
|
displayName: workflow.title,
|
|
@@ -23985,8 +24111,8 @@ var OpenMatesWorkflows = class {
|
|
|
23985
24111
|
const response = await this.client.get(`/v1/workflows/input/${encodeURIComponent(sessionId)}/events?after_event_id=${encodeURIComponent(String(afterEventId))}`);
|
|
23986
24112
|
return response.events ?? [];
|
|
23987
24113
|
}
|
|
23988
|
-
async followUpInput(sessionId,
|
|
23989
|
-
const response = await this.client.request(`/v1/workflows/input/${encodeURIComponent(sessionId)}/follow-up`, { text });
|
|
24114
|
+
async followUpInput(sessionId, text2) {
|
|
24115
|
+
const response = await this.client.request(`/v1/workflows/input/${encodeURIComponent(sessionId)}/follow-up`, { text: text2 });
|
|
23990
24116
|
if (!response.session) throw new OpenMatesApiError(500, { detail: "Workflow input response missing session" });
|
|
23991
24117
|
return response.session;
|
|
23992
24118
|
}
|
|
@@ -24230,8 +24356,8 @@ var OpenMatesEmbeds = class {
|
|
|
24230
24356
|
return this.client.get(`/v1/sdk/embeds/${encodeURIComponent(embedId)}`);
|
|
24231
24357
|
}
|
|
24232
24358
|
async addToProject(embedId, projectId, options = {}) {
|
|
24233
|
-
const { record, projectKey } = await resolveSdkProject(this.client, projectId);
|
|
24234
|
-
return createSdkProjectItem(this.client,
|
|
24359
|
+
const { record: record2, projectKey } = await resolveSdkProject(this.client, projectId);
|
|
24360
|
+
return createSdkProjectItem(this.client, record2.project_id, projectKey, {
|
|
24235
24361
|
itemType: "embed",
|
|
24236
24362
|
targetId: embedId,
|
|
24237
24363
|
displayName: embedId,
|
|
@@ -24294,7 +24420,7 @@ var OpenMatesEmbedPreview = class {
|
|
|
24294
24420
|
if (["running", "failed", "timeout", "cancelled", "stopped"].includes(status.status)) {
|
|
24295
24421
|
return status;
|
|
24296
24422
|
}
|
|
24297
|
-
await new Promise((
|
|
24423
|
+
await new Promise((resolve12) => setTimeout(resolve12, 1e3));
|
|
24298
24424
|
}
|
|
24299
24425
|
throw new OpenMatesApiError(408, { detail: "Application preview did not reach running state before timeout" });
|
|
24300
24426
|
}
|
|
@@ -24533,20 +24659,20 @@ function activityDeliveryStore(scope, stateDir2 = resolveStateDir()) {
|
|
|
24533
24659
|
const acknowledgedDirectory = join4(directory, "acknowledged");
|
|
24534
24660
|
mkdirSync4(pendingDirectory, { recursive: true, mode: 448 });
|
|
24535
24661
|
mkdirSync4(acknowledgedDirectory, { recursive: true, mode: 448 });
|
|
24536
|
-
const save = (path2,
|
|
24662
|
+
const save = (path2, record2) => {
|
|
24537
24663
|
const temporary = `${path2}.${process.pid}.tmp`;
|
|
24538
|
-
writeFileSync4(temporary, JSON.stringify(
|
|
24664
|
+
writeFileSync4(temporary, JSON.stringify(record2), { mode: 384 });
|
|
24539
24665
|
renameSync2(temporary, path2);
|
|
24540
24666
|
};
|
|
24541
|
-
const send = async (path2,
|
|
24542
|
-
if (!
|
|
24543
|
-
const acknowledged = await create(
|
|
24544
|
-
if (acknowledged.entry_id !==
|
|
24545
|
-
|
|
24546
|
-
save(join4(acknowledgedDirectory, `${
|
|
24667
|
+
const send = async (path2, record2, create) => {
|
|
24668
|
+
if (!record2.acknowledged) {
|
|
24669
|
+
const acknowledged = await create(record2.input);
|
|
24670
|
+
if (acknowledged.entry_id !== record2.input.entry_id) throw new Error("Activity acknowledgement identity mismatch");
|
|
24671
|
+
record2.acknowledged = acknowledged;
|
|
24672
|
+
save(join4(acknowledgedDirectory, `${record2.input.entry_id}.json`), record2);
|
|
24547
24673
|
rmSync3(path2, { force: true });
|
|
24548
24674
|
}
|
|
24549
|
-
return
|
|
24675
|
+
return record2.acknowledged;
|
|
24550
24676
|
};
|
|
24551
24677
|
return {
|
|
24552
24678
|
async deliver(id, build, create) {
|
|
@@ -24555,15 +24681,15 @@ function activityDeliveryStore(scope, stateDir2 = resolveStateDir()) {
|
|
|
24555
24681
|
try {
|
|
24556
24682
|
const acknowledgedPath = join4(acknowledgedDirectory, `${id}.json`);
|
|
24557
24683
|
const path2 = existsSync7(acknowledgedPath) ? acknowledgedPath : join4(pendingDirectory, `${id}.json`);
|
|
24558
|
-
let
|
|
24684
|
+
let record2;
|
|
24559
24685
|
try {
|
|
24560
|
-
|
|
24686
|
+
record2 = JSON.parse(readFileSync6(path2, "utf8"));
|
|
24561
24687
|
} catch (error) {
|
|
24562
24688
|
if (error.code !== "ENOENT") throw error;
|
|
24563
|
-
|
|
24564
|
-
save(path2,
|
|
24689
|
+
record2 = { input: await build() };
|
|
24690
|
+
save(path2, record2);
|
|
24565
24691
|
}
|
|
24566
|
-
return await send(path2,
|
|
24692
|
+
return await send(path2, record2, create);
|
|
24567
24693
|
} finally {
|
|
24568
24694
|
await release2();
|
|
24569
24695
|
}
|
|
@@ -24576,12 +24702,12 @@ function activityDeliveryStore(scope, stateDir2 = resolveStateDir()) {
|
|
|
24576
24702
|
let attempted = 0;
|
|
24577
24703
|
for (const name of names) {
|
|
24578
24704
|
const path2 = join4(pendingDirectory, name);
|
|
24579
|
-
const
|
|
24580
|
-
if (
|
|
24705
|
+
const record2 = JSON.parse(readFileSync6(path2, "utf8"));
|
|
24706
|
+
if (record2.acknowledged) continue;
|
|
24581
24707
|
if (attempted >= 3) break;
|
|
24582
24708
|
attempted++;
|
|
24583
24709
|
try {
|
|
24584
|
-
await send(path2,
|
|
24710
|
+
await send(path2, record2, create);
|
|
24585
24711
|
pending--;
|
|
24586
24712
|
} catch {
|
|
24587
24713
|
break;
|
|
@@ -24598,8 +24724,8 @@ function activityDeliveryStore(scope, stateDir2 = resolveStateDir()) {
|
|
|
24598
24724
|
// src/cli.ts
|
|
24599
24725
|
import { existsSync as existsSync14, readFileSync as readFileSync13, realpathSync as realpathSync2, writeFileSync as writeFileSync11 } from "fs";
|
|
24600
24726
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
24601
|
-
import { basename as
|
|
24602
|
-
import { createHash as createHash15, randomBytes as randomBytes9, randomUUID as
|
|
24727
|
+
import { basename as basename5, dirname as dirname11 } from "path";
|
|
24728
|
+
import { createHash as createHash15, randomBytes as randomBytes9, randomUUID as randomUUID16 } from "crypto";
|
|
24603
24729
|
import { arch as arch2, platform as platform3 } from "os";
|
|
24604
24730
|
import { parse as parseYaml } from "yaml";
|
|
24605
24731
|
import WebSocket3 from "ws";
|
|
@@ -24836,27 +24962,27 @@ var SecretRegistry = class {
|
|
|
24836
24962
|
textsToAdd.push(entry.textToHide);
|
|
24837
24963
|
}
|
|
24838
24964
|
if (entry.additionalTexts) {
|
|
24839
|
-
for (const
|
|
24840
|
-
if (
|
|
24841
|
-
textsToAdd.push(
|
|
24965
|
+
for (const text2 of entry.additionalTexts) {
|
|
24966
|
+
if (text2 && text2.trim().length > 0) {
|
|
24967
|
+
textsToAdd.push(text2);
|
|
24842
24968
|
}
|
|
24843
24969
|
}
|
|
24844
24970
|
}
|
|
24845
|
-
for (const
|
|
24971
|
+
for (const text2 of textsToAdd) {
|
|
24846
24972
|
const placeholder = entry.replaceWith.startsWith("[") ? entry.replaceWith : `[${entry.replaceWith}]`;
|
|
24847
24973
|
const regEntry = {
|
|
24848
|
-
value:
|
|
24974
|
+
value: text2,
|
|
24849
24975
|
token: placeholder,
|
|
24850
24976
|
source: "settings",
|
|
24851
24977
|
name: entry.id,
|
|
24852
24978
|
type: "PERSONAL_DATA",
|
|
24853
|
-
length:
|
|
24979
|
+
length: text2.length
|
|
24854
24980
|
};
|
|
24855
|
-
this.entries.set(
|
|
24856
|
-
this.usedPlaceholders.set(placeholder,
|
|
24857
|
-
const lower =
|
|
24858
|
-
if (lower !==
|
|
24859
|
-
this.variantToOriginal.set(lower,
|
|
24981
|
+
this.entries.set(text2, regEntry);
|
|
24982
|
+
this.usedPlaceholders.set(placeholder, text2);
|
|
24983
|
+
const lower = text2.toLowerCase();
|
|
24984
|
+
if (lower !== text2) {
|
|
24985
|
+
this.variantToOriginal.set(lower, text2);
|
|
24860
24986
|
}
|
|
24861
24987
|
}
|
|
24862
24988
|
this.automaton = null;
|
|
@@ -24910,12 +25036,12 @@ var SecretRegistry = class {
|
|
|
24910
25036
|
* @param text Text to scan
|
|
24911
25037
|
* @returns Array of secret mappings for all matches found
|
|
24912
25038
|
*/
|
|
24913
|
-
findAll(
|
|
25039
|
+
findAll(text2) {
|
|
24914
25040
|
if (this.entries.size === 0) return [];
|
|
24915
25041
|
if (!this.automaton) {
|
|
24916
25042
|
this.buildAutomaton();
|
|
24917
25043
|
}
|
|
24918
|
-
const results = this.automaton.search(
|
|
25044
|
+
const results = this.automaton.search(text2);
|
|
24919
25045
|
const mappings = [];
|
|
24920
25046
|
const coveredRanges = [];
|
|
24921
25047
|
const sortedResults = [];
|
|
@@ -25120,16 +25246,16 @@ var SecretScanner = class {
|
|
|
25120
25246
|
* @param text Text to scan and redact
|
|
25121
25247
|
* @returns Object with redacted text and mappings for restoration
|
|
25122
25248
|
*/
|
|
25123
|
-
redact(
|
|
25124
|
-
if (!
|
|
25249
|
+
redact(text2) {
|
|
25250
|
+
if (!text2) return { redacted: text2, mappings: [] };
|
|
25125
25251
|
const allMappings = [];
|
|
25126
25252
|
const coveredRanges = [];
|
|
25127
|
-
const urlExclusionZones = getUrlExclusionZones(
|
|
25253
|
+
const urlExclusionZones = getUrlExclusionZones(text2);
|
|
25128
25254
|
if (this.options.enableRegistryDetection && this.registry.size > 0) {
|
|
25129
|
-
const registryMappings = this.registry.findAll(
|
|
25255
|
+
const registryMappings = this.registry.findAll(text2);
|
|
25130
25256
|
for (const mapping of registryMappings) {
|
|
25131
25257
|
let searchFrom = 0;
|
|
25132
|
-
const searchText =
|
|
25258
|
+
const searchText = text2.toLowerCase();
|
|
25133
25259
|
const matchLower = mapping.original.toLowerCase();
|
|
25134
25260
|
while (searchFrom < searchText.length) {
|
|
25135
25261
|
const idx = searchText.indexOf(matchLower, searchFrom);
|
|
@@ -25145,7 +25271,7 @@ var SecretScanner = class {
|
|
|
25145
25271
|
for (const pattern of [...SECRET_PATTERNS, ...GENERAL_PII_PATTERNS]) {
|
|
25146
25272
|
pattern.regex.lastIndex = 0;
|
|
25147
25273
|
let match;
|
|
25148
|
-
while ((match = pattern.regex.exec(
|
|
25274
|
+
while ((match = pattern.regex.exec(text2)) !== null) {
|
|
25149
25275
|
const matchText = match[0];
|
|
25150
25276
|
const startIndex = match.index;
|
|
25151
25277
|
const endIndex = startIndex + matchText.length;
|
|
@@ -25175,7 +25301,7 @@ var SecretScanner = class {
|
|
|
25175
25301
|
}
|
|
25176
25302
|
}
|
|
25177
25303
|
}
|
|
25178
|
-
let redacted =
|
|
25304
|
+
let redacted = text2;
|
|
25179
25305
|
const sortedMappings = [...allMappings].sort(
|
|
25180
25306
|
(a, b) => b.original.length - a.original.length
|
|
25181
25307
|
);
|
|
@@ -25204,9 +25330,9 @@ var SecretScanner = class {
|
|
|
25204
25330
|
* @param mappings Mappings from a previous redact() call
|
|
25205
25331
|
* @returns Text with placeholders replaced by original values
|
|
25206
25332
|
*/
|
|
25207
|
-
restore(
|
|
25208
|
-
if (!
|
|
25209
|
-
let result =
|
|
25333
|
+
restore(text2, mappings) {
|
|
25334
|
+
if (!text2 || !mappings || mappings.length === 0) return text2;
|
|
25335
|
+
let result = text2;
|
|
25210
25336
|
for (const mapping of mappings) {
|
|
25211
25337
|
result = result.split(mapping.placeholder).join(mapping.original);
|
|
25212
25338
|
}
|
|
@@ -25225,11 +25351,11 @@ var SecretScanner = class {
|
|
|
25225
25351
|
function escapeRegExp2(string) {
|
|
25226
25352
|
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
25227
25353
|
}
|
|
25228
|
-
function getUrlExclusionZones(
|
|
25354
|
+
function getUrlExclusionZones(text2) {
|
|
25229
25355
|
const urlExclusionRegex = /https?:\/\/[^\s]+/g;
|
|
25230
25356
|
const zones = [];
|
|
25231
25357
|
let match;
|
|
25232
|
-
while ((match = urlExclusionRegex.exec(
|
|
25358
|
+
while ((match = urlExclusionRegex.exec(text2)) !== null) {
|
|
25233
25359
|
zones.push({ start: match.index, end: match.index + match[0].length });
|
|
25234
25360
|
}
|
|
25235
25361
|
return zones;
|
|
@@ -25301,9 +25427,9 @@ var OutputRedactor = class {
|
|
|
25301
25427
|
* @param text Text to scan
|
|
25302
25428
|
* @returns Redacted text with placeholders
|
|
25303
25429
|
*/
|
|
25304
|
-
redact(
|
|
25305
|
-
if (!
|
|
25306
|
-
const result = this.scanner.redact(
|
|
25430
|
+
redact(text2) {
|
|
25431
|
+
if (!text2 || !this.initialized) return text2;
|
|
25432
|
+
const result = this.scanner.redact(text2);
|
|
25307
25433
|
for (const mapping of result.mappings) {
|
|
25308
25434
|
this.sessionMappings.set(mapping.placeholder, mapping);
|
|
25309
25435
|
}
|
|
@@ -25313,11 +25439,11 @@ var OutputRedactor = class {
|
|
|
25313
25439
|
* Redact and return both redacted text and mappings.
|
|
25314
25440
|
* Used when we need to store mappings alongside message data.
|
|
25315
25441
|
*/
|
|
25316
|
-
redactWithMappings(
|
|
25317
|
-
if (!
|
|
25318
|
-
return { redacted:
|
|
25442
|
+
redactWithMappings(text2) {
|
|
25443
|
+
if (!text2 || !this.initialized) {
|
|
25444
|
+
return { redacted: text2, mappings: [] };
|
|
25319
25445
|
}
|
|
25320
|
-
const result = this.scanner.redact(
|
|
25446
|
+
const result = this.scanner.redact(text2);
|
|
25321
25447
|
for (const mapping of result.mappings) {
|
|
25322
25448
|
this.sessionMappings.set(mapping.placeholder, mapping);
|
|
25323
25449
|
}
|
|
@@ -25327,9 +25453,9 @@ var OutputRedactor = class {
|
|
|
25327
25453
|
* Restore placeholders back to original values.
|
|
25328
25454
|
* Only uses mappings from this session (never from external sources).
|
|
25329
25455
|
*/
|
|
25330
|
-
restore(
|
|
25331
|
-
if (!
|
|
25332
|
-
return this.scanner.restore(
|
|
25456
|
+
restore(text2) {
|
|
25457
|
+
if (!text2 || this.sessionMappings.size === 0) return text2;
|
|
25458
|
+
return this.scanner.restore(text2, Array.from(this.sessionMappings.values()));
|
|
25333
25459
|
}
|
|
25334
25460
|
/** Whether the redactor has been initialized with personal data */
|
|
25335
25461
|
get isInitialized() {
|
|
@@ -25384,8 +25510,8 @@ function createWebsiteEmbed(url) {
|
|
|
25384
25510
|
status: "finished"
|
|
25385
25511
|
};
|
|
25386
25512
|
}
|
|
25387
|
-
function replaceUrlsInText(
|
|
25388
|
-
return
|
|
25513
|
+
function replaceUrlsInText(text2, embeds) {
|
|
25514
|
+
return text2.replace(URL_PATTERN, (rawUrl) => {
|
|
25389
25515
|
const { url, suffix } = trimTrailingUrlPunctuation(rawUrl);
|
|
25390
25516
|
if (!url) return rawUrl;
|
|
25391
25517
|
try {
|
|
@@ -25920,8 +26046,8 @@ async function renderRemotionShareLink(embedId, client, ln) {
|
|
|
25920
26046
|
}
|
|
25921
26047
|
}
|
|
25922
26048
|
function generateQr(value) {
|
|
25923
|
-
return new Promise((
|
|
25924
|
-
qrcode2.generate(value, { small: true }, (qr) =>
|
|
26049
|
+
return new Promise((resolve12) => {
|
|
26050
|
+
qrcode2.generate(value, { small: true }, (qr) => resolve12(qr));
|
|
25925
26051
|
});
|
|
25926
26052
|
}
|
|
25927
26053
|
function remotionMeta(c) {
|
|
@@ -26330,12 +26456,12 @@ function renderAudioTranscribePreview(c, ln) {
|
|
|
26330
26456
|
const language = str(c.language) ?? "";
|
|
26331
26457
|
if (duration) ln(`\x1B[2mDuration: ${duration}\x1B[0m`);
|
|
26332
26458
|
if (language) ln(`\x1B[2mLanguage: ${language}\x1B[0m`);
|
|
26333
|
-
const
|
|
26334
|
-
if (
|
|
26459
|
+
const text2 = str(c.text) ?? str(c.transcript) ?? "";
|
|
26460
|
+
if (text2) ln(trunc(text2, 60));
|
|
26335
26461
|
}
|
|
26336
26462
|
function renderAudioTranscribeFullscreen(c) {
|
|
26337
|
-
const
|
|
26338
|
-
if (
|
|
26463
|
+
const text2 = str(c.text) ?? str(c.transcript) ?? "";
|
|
26464
|
+
if (text2) console.log(text2);
|
|
26339
26465
|
else console.log("No transcript available.");
|
|
26340
26466
|
}
|
|
26341
26467
|
function renderByDirectType(embed, c, ln) {
|
|
@@ -26568,8 +26694,8 @@ function renderDirectTypeFullscreen(embed, c) {
|
|
|
26568
26694
|
|
|
26569
26695
|
`);
|
|
26570
26696
|
if (html) {
|
|
26571
|
-
const
|
|
26572
|
-
console.log(
|
|
26697
|
+
const text2 = html.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
|
|
26698
|
+
console.log(text2);
|
|
26573
26699
|
}
|
|
26574
26700
|
break;
|
|
26575
26701
|
}
|
|
@@ -26580,8 +26706,8 @@ function renderDirectTypeFullscreen(embed, c) {
|
|
|
26580
26706
|
|
|
26581
26707
|
`);
|
|
26582
26708
|
if (html) {
|
|
26583
|
-
const
|
|
26584
|
-
console.log(
|
|
26709
|
+
const text2 = html.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
|
|
26710
|
+
console.log(text2);
|
|
26585
26711
|
}
|
|
26586
26712
|
break;
|
|
26587
26713
|
}
|
|
@@ -26778,12 +26904,12 @@ function formatTs(ts) {
|
|
|
26778
26904
|
|
|
26779
26905
|
// src/server.ts
|
|
26780
26906
|
import { execFileSync as execFileSync4, execSync, spawn as nodeSpawn, spawnSync } from "child_process";
|
|
26781
|
-
import { createHash as createHash13, randomBytes as randomBytes8, randomUUID as
|
|
26907
|
+
import { createHash as createHash13, randomBytes as randomBytes8, randomUUID as randomUUID12 } from "crypto";
|
|
26782
26908
|
import { appendFileSync, chmodSync as chmodSync5, closeSync as closeSync2, copyFileSync as copyFileSync2, cpSync, existsSync as existsSync10, mkdirSync as mkdirSync7, mkdtempSync, openSync as openSync2, readFileSync as readFileSync8, readSync, readdirSync as readdirSync5, rmSync as rmSync7, writeFileSync as writeFileSync6 } from "fs";
|
|
26783
26909
|
import { createInterface as createInterface3 } from "readline";
|
|
26784
26910
|
import { createInterface as createPromptInterface } from "readline/promises";
|
|
26785
26911
|
import { homedir as homedir6 } from "os";
|
|
26786
|
-
import { dirname as
|
|
26912
|
+
import { dirname as dirname7, join as join8, resolve as resolve7 } from "path";
|
|
26787
26913
|
|
|
26788
26914
|
// src/branding.ts
|
|
26789
26915
|
var OPENMATES_WORDMARK = "OPENMATES";
|
|
@@ -26826,7 +26952,7 @@ import {
|
|
|
26826
26952
|
symlinkSync
|
|
26827
26953
|
} from "fs";
|
|
26828
26954
|
import { createRequire as createRequire3 } from "module";
|
|
26829
|
-
import { dirname as
|
|
26955
|
+
import { dirname as dirname4, join as join5, resolve as resolve5 } from "path";
|
|
26830
26956
|
var UI_PACKAGE_RELATIVE_PATH = join5("frontend", "packages", "ui");
|
|
26831
26957
|
var GENERATED_LOCALES_RELATIVE_PATH = join5(UI_PACKAGE_RELATIVE_PATH, "src", "i18n", "locales");
|
|
26832
26958
|
var BUILD_TRANSLATIONS_SCRIPT_RELATIVE_PATH = join5(UI_PACKAGE_RELATIVE_PATH, "scripts", "build-translations.js");
|
|
@@ -26852,8 +26978,8 @@ function ensureSourceInstallTranslations(installPath, sourcePath) {
|
|
|
26852
26978
|
}
|
|
26853
26979
|
function copyGeneratedLocaleJson(sourcePath, installPath) {
|
|
26854
26980
|
if (!sourcePath) return 0;
|
|
26855
|
-
const sourceRoot =
|
|
26856
|
-
const targetRoot =
|
|
26981
|
+
const sourceRoot = resolve5(sourcePath);
|
|
26982
|
+
const targetRoot = resolve5(installPath);
|
|
26857
26983
|
if (sourceRoot === targetRoot) return 0;
|
|
26858
26984
|
const sourceLocaleDir = sourceInstallLocalesPath(sourceRoot);
|
|
26859
26985
|
if (!existsSync8(join5(sourceLocaleDir, REQUIRED_LOCALE_JSON))) return 0;
|
|
@@ -26874,7 +27000,7 @@ function runBuildTranslationsScript(installPath) {
|
|
|
26874
27000
|
throw new Error(`Translation build script not found at ${buildScript}.`);
|
|
26875
27001
|
}
|
|
26876
27002
|
const requireFromCli = createRequire3(import.meta.url);
|
|
26877
|
-
const yamlPackageDir =
|
|
27003
|
+
const yamlPackageDir = dirname4(requireFromCli.resolve("yaml/package.json"));
|
|
26878
27004
|
const nodeModulesDir = join5(uiPackageDir, "node_modules");
|
|
26879
27005
|
const yamlLink = join5(nodeModulesDir, "yaml");
|
|
26880
27006
|
const hadNodeModulesDir = existsSync8(nodeModulesDir);
|
|
@@ -26897,7 +27023,7 @@ function runBuildTranslationsScript(installPath) {
|
|
|
26897
27023
|
}
|
|
26898
27024
|
|
|
26899
27025
|
// src/serverPlanning.ts
|
|
26900
|
-
import { dirname as
|
|
27026
|
+
import { dirname as dirname5, join as join6, resolve as resolve6 } from "path";
|
|
26901
27027
|
var CORE_WORKER_SERVICES = [
|
|
26902
27028
|
"task-worker",
|
|
26903
27029
|
"user-init-worker",
|
|
@@ -27107,10 +27233,10 @@ function parseServerRole(value) {
|
|
|
27107
27233
|
throw new Error(`Unsupported server role '${value}'. Use core, upload, or preview.`);
|
|
27108
27234
|
}
|
|
27109
27235
|
function defaultOpenMatesCloudOverlayPath(openMatesPath) {
|
|
27110
|
-
return
|
|
27236
|
+
return resolve6(join6(dirname5(resolve6(openMatesPath)), OPENMATESCLOUD_OVERLAY_DIR));
|
|
27111
27237
|
}
|
|
27112
27238
|
function defaultOpenMatesCloudComposeFile(overlayPath) {
|
|
27113
|
-
return
|
|
27239
|
+
return resolve6(join6(overlayPath, OPENMATESCLOUD_COMPOSE_FILE));
|
|
27114
27240
|
}
|
|
27115
27241
|
function planOpenMatesCloudOverlay(input) {
|
|
27116
27242
|
const deploymentMode = input.deploymentMode ?? "self_host";
|
|
@@ -27124,12 +27250,12 @@ function planOpenMatesCloudOverlay(input) {
|
|
|
27124
27250
|
modeLabel: "self-host core"
|
|
27125
27251
|
};
|
|
27126
27252
|
}
|
|
27127
|
-
const openMatesPath =
|
|
27128
|
-
const overlayPath =
|
|
27253
|
+
const openMatesPath = resolve6(input.openMatesPath);
|
|
27254
|
+
const overlayPath = resolve6(input.overlayPath ?? defaultOpenMatesCloudOverlayPath(openMatesPath));
|
|
27129
27255
|
if (input.overlayExists !== true) {
|
|
27130
27256
|
throw new Error(`OpenMatesCloud overlay path is required for official-cloud mode: ${overlayPath}`);
|
|
27131
27257
|
}
|
|
27132
|
-
const overlayComposeFile =
|
|
27258
|
+
const overlayComposeFile = resolve6(input.overlayComposeFile ?? defaultOpenMatesCloudComposeFile(overlayPath));
|
|
27133
27259
|
return {
|
|
27134
27260
|
deploymentMode,
|
|
27135
27261
|
enabled: true,
|
|
@@ -27511,20 +27637,20 @@ function validateServerEnvironmentTarget(command, environment) {
|
|
|
27511
27637
|
// src/serverBackupArchive.ts
|
|
27512
27638
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
27513
27639
|
import { chmodSync as chmodSync3, lstatSync, readdirSync as readdirSync4, renameSync as renameSync3, rmSync as rmSync5 } from "fs";
|
|
27514
|
-
import { randomUUID as
|
|
27640
|
+
import { randomUUID as randomUUID9 } from "crypto";
|
|
27515
27641
|
function assertRegularBackupTree(path2) {
|
|
27516
|
-
const
|
|
27517
|
-
if (
|
|
27642
|
+
const stat3 = lstatSync(path2);
|
|
27643
|
+
if (stat3.isDirectory()) {
|
|
27518
27644
|
for (const entry of readdirSync4(path2)) assertRegularBackupTree(`${path2}/${entry}`);
|
|
27519
27645
|
return;
|
|
27520
27646
|
}
|
|
27521
|
-
if (!
|
|
27647
|
+
if (!stat3.isFile() || stat3.nlink !== 1) {
|
|
27522
27648
|
throw new Error(`Backup archive refused unsafe entry: ${path2}`);
|
|
27523
27649
|
}
|
|
27524
27650
|
}
|
|
27525
27651
|
function publishServerBackupArchive(sourceDir, archivePath, options = {}) {
|
|
27526
27652
|
assertRegularBackupTree(sourceDir);
|
|
27527
|
-
const temporaryArchivePath = `${archivePath}.tmp-${
|
|
27653
|
+
const temporaryArchivePath = `${archivePath}.tmp-${randomUUID9()}`;
|
|
27528
27654
|
const previousUmask = process.umask(63);
|
|
27529
27655
|
try {
|
|
27530
27656
|
execFileSync3(options.tarCommand ?? "tar", ["-czf", temporaryArchivePath, "-C", sourceDir, "."], { stdio: "pipe" });
|
|
@@ -27539,7 +27665,7 @@ function publishServerBackupArchive(sourceDir, archivePath, options = {}) {
|
|
|
27539
27665
|
|
|
27540
27666
|
// src/serverHealth.ts
|
|
27541
27667
|
import dnsModule, { promises as dns } from "dns";
|
|
27542
|
-
import { createHmac as createHmac4, randomUUID as
|
|
27668
|
+
import { createHmac as createHmac4, randomUUID as randomUUID10 } from "crypto";
|
|
27543
27669
|
import { promises as fs } from "fs";
|
|
27544
27670
|
import { isIP } from "net";
|
|
27545
27671
|
import { request as httpsRequest } from "https";
|
|
@@ -27766,7 +27892,7 @@ function isBrevoAcceptedResponse(pathName, method, status, responseBody) {
|
|
|
27766
27892
|
}
|
|
27767
27893
|
async function requestBrevo(pathName, method, apiKey, payload) {
|
|
27768
27894
|
const body = payload ? JSON.stringify(payload) : void 0;
|
|
27769
|
-
await new Promise((
|
|
27895
|
+
await new Promise((resolve12, reject) => {
|
|
27770
27896
|
const request = httpsRequest(buildBrevoRequestOptions(pathName, method, apiKey, body), (response) => {
|
|
27771
27897
|
let responseBytes = 0;
|
|
27772
27898
|
const chunks = [];
|
|
@@ -27778,8 +27904,8 @@ async function requestBrevo(pathName, method, apiKey, payload) {
|
|
|
27778
27904
|
response.on("end", () => {
|
|
27779
27905
|
const status = response.statusCode ?? 0;
|
|
27780
27906
|
const responseBody = Buffer.concat(chunks).toString("utf8");
|
|
27781
|
-
if (isBrevoAcceptedResponse(pathName, method, status, responseBody))
|
|
27782
|
-
else if (isBrevoIdempotencyDuplicate(status, responseBody, payload))
|
|
27907
|
+
if (isBrevoAcceptedResponse(pathName, method, status, responseBody)) resolve12();
|
|
27908
|
+
else if (isBrevoIdempotencyDuplicate(status, responseBody, payload)) resolve12();
|
|
27783
27909
|
else reject(new Error(`brevo_delivery_failed:${status}`));
|
|
27784
27910
|
});
|
|
27785
27911
|
});
|
|
@@ -27922,10 +28048,10 @@ async function resolveGenericWebhookTarget(rawUrl, allowLocalDevelopmentFixture
|
|
|
27922
28048
|
async function sendGenericWebhook(target, secret, payload, allowLocalDevelopmentFixture = false) {
|
|
27923
28049
|
const { url, addresses } = await resolveGenericWebhookTarget(target, allowLocalDevelopmentFixture);
|
|
27924
28050
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
27925
|
-
const eventId =
|
|
28051
|
+
const eventId = randomUUID10();
|
|
27926
28052
|
const signed = signRuntimeWebhookPayload(payload, secret, timestamp, eventId);
|
|
27927
28053
|
const selected = addresses[0];
|
|
27928
|
-
await new Promise((
|
|
28054
|
+
await new Promise((resolve12, reject) => {
|
|
27929
28055
|
const requestFunction = url.protocol === "https:" ? httpsRequest : httpRequest;
|
|
27930
28056
|
const request = requestFunction({
|
|
27931
28057
|
protocol: url.protocol,
|
|
@@ -27945,7 +28071,7 @@ async function sendGenericWebhook(target, secret, payload, allowLocalDevelopment
|
|
|
27945
28071
|
});
|
|
27946
28072
|
response.on("end", () => {
|
|
27947
28073
|
const status = response.statusCode ?? 0;
|
|
27948
|
-
if (status >= 200 && status < 300)
|
|
28074
|
+
if (status >= 200 && status < 300) resolve12();
|
|
27949
28075
|
else reject(new Error(`webhook_delivery_failed:${status}`));
|
|
27950
28076
|
});
|
|
27951
28077
|
});
|
|
@@ -28026,7 +28152,7 @@ async function deliverWithRetries(channel, send) {
|
|
|
28026
28152
|
await send();
|
|
28027
28153
|
return { channel, status: "delivered", attempts: attempt };
|
|
28028
28154
|
} catch {
|
|
28029
|
-
if (attempt < 3) await new Promise((
|
|
28155
|
+
if (attempt < 3) await new Promise((resolve12) => setTimeout(resolve12, 250 * 2 ** (attempt - 1)));
|
|
28030
28156
|
}
|
|
28031
28157
|
}
|
|
28032
28158
|
return { channel, status: "exhausted", attempts: 3, sanitizedReason: "delivery_failed" };
|
|
@@ -28039,7 +28165,7 @@ async function deliverUpdateCompletionEmail(config, payload, send = sendUpdateCo
|
|
|
28039
28165
|
await send(config, payload);
|
|
28040
28166
|
return { status: "accepted", attempts };
|
|
28041
28167
|
} catch {
|
|
28042
|
-
if (attempts < 3) await new Promise((
|
|
28168
|
+
if (attempts < 3) await new Promise((resolve12) => setTimeout(resolve12, 250 * 2 ** (attempts - 1)));
|
|
28043
28169
|
}
|
|
28044
28170
|
}
|
|
28045
28171
|
return { status: "failed", attempts: Math.max(previousAttempts, 3), sanitizedReason: "delivery_failed" };
|
|
@@ -28132,7 +28258,7 @@ function signRuntimeWebhookPayload(payload, secret, timestamp, eventId) {
|
|
|
28132
28258
|
// src/serverUpdateState.ts
|
|
28133
28259
|
import { randomBytes as randomBytes7 } from "crypto";
|
|
28134
28260
|
import { chmodSync as chmodSync4, closeSync, existsSync as existsSync9, mkdirSync as mkdirSync6, openSync, readFileSync as readFileSync7, renameSync as renameSync4, rmSync as rmSync6, writeFileSync as writeFileSync5 } from "fs";
|
|
28135
|
-
import { dirname as
|
|
28261
|
+
import { dirname as dirname6, join as join7 } from "path";
|
|
28136
28262
|
function serverUpdateStatusFile(installPath, role) {
|
|
28137
28263
|
return join7(installPath, ".openmates", `${role}-update-status.json`);
|
|
28138
28264
|
}
|
|
@@ -28151,7 +28277,7 @@ function readServerUpdateStatus(installPath, role) {
|
|
|
28151
28277
|
}
|
|
28152
28278
|
function writeServerUpdateStatus(installPath, role, status) {
|
|
28153
28279
|
const filePath = serverUpdateStatusFile(installPath, role);
|
|
28154
|
-
mkdirSync6(
|
|
28280
|
+
mkdirSync6(dirname6(filePath), { recursive: true, mode: 448 });
|
|
28155
28281
|
const temporaryPath = `${filePath}.${process.pid}.${randomBytes7(4).toString("hex")}.tmp`;
|
|
28156
28282
|
writeFileSync5(temporaryPath, `${JSON.stringify({ role, updated_at: (/* @__PURE__ */ new Date()).toISOString(), ...status }, null, 2)}
|
|
28157
28283
|
`, { mode: 384 });
|
|
@@ -28189,7 +28315,7 @@ function acquireServerUpdateLock(installPath) {
|
|
|
28189
28315
|
}
|
|
28190
28316
|
|
|
28191
28317
|
// src/serverQuickTest.ts
|
|
28192
|
-
import { randomUUID as
|
|
28318
|
+
import { randomUUID as randomUUID11 } from "crypto";
|
|
28193
28319
|
var QUICK_TEST_RESPONSE_TIMEOUT_MS = 12e4;
|
|
28194
28320
|
var QUICK_TEST_WEB_QUERY = "site:openmates.org OpenMates";
|
|
28195
28321
|
var QUICK_TEST_EXPECTED_RESPONSE = "server quick test passed";
|
|
@@ -28255,7 +28381,7 @@ function decideQuickServerTestAction(input) {
|
|
|
28255
28381
|
async function runQuickServerTest(client, options = {}) {
|
|
28256
28382
|
const now = options.now ?? Date.now;
|
|
28257
28383
|
const checks = [];
|
|
28258
|
-
const chatId =
|
|
28384
|
+
const chatId = randomUUID11();
|
|
28259
28385
|
let chatMayExist = false;
|
|
28260
28386
|
checks.push({ id: "account.session", status: "passed", duration_ms: 0 });
|
|
28261
28387
|
const createStarted = now();
|
|
@@ -28346,12 +28472,12 @@ function containsExpectedMathResult(value) {
|
|
|
28346
28472
|
function containsBoundedWebResult(value) {
|
|
28347
28473
|
if (Array.isArray(value)) return value.some(containsBoundedWebResult);
|
|
28348
28474
|
if (!value || typeof value !== "object") return false;
|
|
28349
|
-
const
|
|
28350
|
-
if (Array.isArray(
|
|
28351
|
-
const directResults =
|
|
28475
|
+
const record2 = value;
|
|
28476
|
+
if (Array.isArray(record2.results)) {
|
|
28477
|
+
const directResults = record2.results.filter((item) => Boolean(item && typeof item === "object"));
|
|
28352
28478
|
if (directResults.some((item) => typeof item.title === "string" && typeof item.url === "string")) return true;
|
|
28353
28479
|
}
|
|
28354
|
-
return Object.values(
|
|
28480
|
+
return Object.values(record2).some(containsBoundedWebResult);
|
|
28355
28481
|
}
|
|
28356
28482
|
|
|
28357
28483
|
// src/server.ts
|
|
@@ -28590,9 +28716,9 @@ function exec(cmd, cwd) {
|
|
|
28590
28716
|
return execSync(cmd, { cwd, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
28591
28717
|
}
|
|
28592
28718
|
function runInteractive(cmd, args, cwd) {
|
|
28593
|
-
return new Promise((
|
|
28719
|
+
return new Promise((resolve12, reject) => {
|
|
28594
28720
|
const child = nodeSpawn(cmd, args, { cwd, stdio: "inherit", shell: false });
|
|
28595
|
-
child.on("close", (code) =>
|
|
28721
|
+
child.on("close", (code) => resolve12(code ?? 1));
|
|
28596
28722
|
child.on("error", reject);
|
|
28597
28723
|
});
|
|
28598
28724
|
}
|
|
@@ -28685,7 +28811,7 @@ function getInstallDeploymentMode(installPath, config) {
|
|
|
28685
28811
|
function getOpenMatesCloudOverlayPath(flags, config) {
|
|
28686
28812
|
const explicit = flags["openmatescloud-path"] ?? flags["openmates-cloud-path"];
|
|
28687
28813
|
if (explicit === true) throw new Error("Provide an OpenMatesCloud path: --openmatescloud-path <dir>.");
|
|
28688
|
-
if (typeof explicit === "string") return
|
|
28814
|
+
if (typeof explicit === "string") return resolve7(explicit);
|
|
28689
28815
|
return config?.openMatesCloudOverlayPath;
|
|
28690
28816
|
}
|
|
28691
28817
|
function hasServiceFilter(flags) {
|
|
@@ -28917,16 +29043,16 @@ async function fetchText(url) {
|
|
|
28917
29043
|
return response.text();
|
|
28918
29044
|
}
|
|
28919
29045
|
function packagedTemplatePath(role) {
|
|
28920
|
-
return join8(
|
|
29046
|
+
return join8(dirname7(new URL(import.meta.url).pathname), "..", "templates", ROLE_TEMPLATE_FILES[role]);
|
|
28921
29047
|
}
|
|
28922
29048
|
function packagedNoWebappTemplatePath() {
|
|
28923
|
-
return join8(
|
|
29049
|
+
return join8(dirname7(new URL(import.meta.url).pathname), "..", "templates", CORE_NO_WEBAPP_TEMPLATE_FILE);
|
|
28924
29050
|
}
|
|
28925
29051
|
function packagedCaddyTemplatePath(role) {
|
|
28926
|
-
return join8(
|
|
29052
|
+
return join8(dirname7(new URL(import.meta.url).pathname), "..", "templates", "caddy", role, "Caddyfile");
|
|
28927
29053
|
}
|
|
28928
29054
|
function packagedCoreAlertmanagerTemplatePath() {
|
|
28929
|
-
return join8(
|
|
29055
|
+
return join8(dirname7(new URL(import.meta.url).pathname), "..", "templates", "core", "monitoring", "alertmanager", "alertmanager.yml");
|
|
28930
29056
|
}
|
|
28931
29057
|
function readOfficialCloudNoWebappComposeTemplate() {
|
|
28932
29058
|
const packaged = packagedNoWebappTemplatePath();
|
|
@@ -28947,7 +29073,7 @@ function ensureOfficialCloudNoWebappComposeFile(installPath, deploymentMode, rol
|
|
|
28947
29073
|
if (deploymentMode !== "official_cloud" || role !== "core") return;
|
|
28948
29074
|
const filePath = join8(installPath, OFFICIAL_CLOUD_NO_WEBAPP_COMPOSE_FILE);
|
|
28949
29075
|
if (existsSync10(filePath)) return;
|
|
28950
|
-
mkdirSync7(
|
|
29076
|
+
mkdirSync7(dirname7(filePath), { recursive: true });
|
|
28951
29077
|
writeFileSync6(filePath, readOfficialCloudNoWebappComposeTemplate());
|
|
28952
29078
|
}
|
|
28953
29079
|
function fileHash(path2) {
|
|
@@ -28957,7 +29083,7 @@ function fileHash(path2) {
|
|
|
28957
29083
|
async function loadSelfHostComposeTemplate(templateRef, role) {
|
|
28958
29084
|
const templateDir = process.env.OPENMATES_SELFHOST_TEMPLATE_DIR;
|
|
28959
29085
|
if (templateDir) {
|
|
28960
|
-
return readFileSync8(join8(
|
|
29086
|
+
return readFileSync8(join8(resolve7(templateDir), ROLE_TEMPLATE_FILES[role]), "utf-8");
|
|
28961
29087
|
}
|
|
28962
29088
|
const overrideUrl = process.env.OPENMATES_SELFHOST_COMPOSE_URL;
|
|
28963
29089
|
if (overrideUrl) {
|
|
@@ -28978,12 +29104,12 @@ async function writeImageModeRuntimeFiles(installPath, imageTag, role) {
|
|
|
28978
29104
|
}
|
|
28979
29105
|
if (role === "core") {
|
|
28980
29106
|
const promtailConfigPath = join8(installPath, CORE_PROMTAIL_CONFIG_FILE);
|
|
28981
|
-
mkdirSync7(
|
|
29107
|
+
mkdirSync7(dirname7(promtailConfigPath), { recursive: true });
|
|
28982
29108
|
writeFileSync6(promtailConfigPath, SELFHOST_PROMTAIL_CONFIG_TEMPLATE);
|
|
28983
29109
|
const alertmanagerTemplatePath = packagedCoreAlertmanagerTemplatePath();
|
|
28984
29110
|
if (!existsSync10(alertmanagerTemplatePath)) throw new Error(`Packaged Alertmanager config not found: ${alertmanagerTemplatePath}`);
|
|
28985
29111
|
const alertmanagerConfigPath = join8(installPath, CORE_ALERTMANAGER_CONFIG_FILE);
|
|
28986
|
-
mkdirSync7(
|
|
29112
|
+
mkdirSync7(dirname7(alertmanagerConfigPath), { recursive: true });
|
|
28987
29113
|
copyFileSync2(alertmanagerTemplatePath, alertmanagerConfigPath);
|
|
28988
29114
|
}
|
|
28989
29115
|
writeFileSync6(join8(vaultConfigDir, "vault.hcl"), VAULT_CONFIG_TEMPLATE);
|
|
@@ -29065,7 +29191,7 @@ function defaultCloneBranchForVersion(version) {
|
|
|
29065
29191
|
}
|
|
29066
29192
|
function hasLlmCredentials(envPath) {
|
|
29067
29193
|
if (!existsSync10(envPath)) return false;
|
|
29068
|
-
if (hasLocalAiModels(
|
|
29194
|
+
if (hasLocalAiModels(dirname7(envPath))) return true;
|
|
29069
29195
|
const content = readFileSync8(envPath, "utf-8");
|
|
29070
29196
|
for (const line of content.split("\n")) {
|
|
29071
29197
|
const trimmed = line.trim();
|
|
@@ -29096,10 +29222,10 @@ function warnIfMissingLlmCredentials(installPath) {
|
|
|
29096
29222
|
}
|
|
29097
29223
|
async function confirmDestructive(phrase) {
|
|
29098
29224
|
const rl = createInterface3({ input: process.stdin, output: process.stderr });
|
|
29099
|
-
return new Promise((
|
|
29225
|
+
return new Promise((resolve12) => {
|
|
29100
29226
|
rl.question(`Type "${phrase}" to confirm: `, (answer) => {
|
|
29101
29227
|
rl.close();
|
|
29102
|
-
|
|
29228
|
+
resolve12(answer.trim() === phrase);
|
|
29103
29229
|
});
|
|
29104
29230
|
});
|
|
29105
29231
|
}
|
|
@@ -29116,7 +29242,7 @@ function imageBackendConfigPath(installPath) {
|
|
|
29116
29242
|
function ensureImageRuntimeConfig(installPath) {
|
|
29117
29243
|
const configPath = imageBackendConfigPath(installPath);
|
|
29118
29244
|
if (existsSync10(configPath)) return;
|
|
29119
|
-
mkdirSync7(
|
|
29245
|
+
mkdirSync7(dirname7(configPath), { recursive: true });
|
|
29120
29246
|
writeFileSync6(configPath, renderFeatureOverrides({ enabled: [], disabled: [] }));
|
|
29121
29247
|
}
|
|
29122
29248
|
function readLocalModelOverlay(path2) {
|
|
@@ -29131,7 +29257,7 @@ function readLocalModelOverlay(path2) {
|
|
|
29131
29257
|
}
|
|
29132
29258
|
}
|
|
29133
29259
|
function writeLocalModelOverlay(path2, overlay) {
|
|
29134
|
-
mkdirSync7(
|
|
29260
|
+
mkdirSync7(dirname7(path2), { recursive: true });
|
|
29135
29261
|
writeFileSync6(path2, `${JSON.stringify(overlay, null, 2)}
|
|
29136
29262
|
`);
|
|
29137
29263
|
}
|
|
@@ -29333,7 +29459,7 @@ function sourceUpdateMetadata(installPath) {
|
|
|
29333
29459
|
}
|
|
29334
29460
|
function copyIfExists(source, destination) {
|
|
29335
29461
|
if (!existsSync10(source)) return;
|
|
29336
|
-
mkdirSync7(
|
|
29462
|
+
mkdirSync7(dirname7(destination), { recursive: true });
|
|
29337
29463
|
cpSync(source, destination, { recursive: true, force: true });
|
|
29338
29464
|
}
|
|
29339
29465
|
function readEnvMap(installPath) {
|
|
@@ -29373,7 +29499,7 @@ function backupEnvFile(installPath) {
|
|
|
29373
29499
|
}
|
|
29374
29500
|
function writeEnvContent(installPath, content) {
|
|
29375
29501
|
const envPath = envPathForInstall(installPath);
|
|
29376
|
-
mkdirSync7(
|
|
29502
|
+
mkdirSync7(dirname7(envPath), { recursive: true });
|
|
29377
29503
|
writeFileSync6(envPath, content, { mode: 384 });
|
|
29378
29504
|
chmodSync5(envPath, 384);
|
|
29379
29505
|
}
|
|
@@ -29387,7 +29513,7 @@ function writeDeploymentModeEnv(installPath, deploymentMode, overlayPath) {
|
|
|
29387
29513
|
writeEnvContent(installPath, content);
|
|
29388
29514
|
return { overlayPath: null };
|
|
29389
29515
|
}
|
|
29390
|
-
const resolvedOverlayPath =
|
|
29516
|
+
const resolvedOverlayPath = resolve7(overlayPath ?? defaultOpenMatesCloudOverlayPath(installPath));
|
|
29391
29517
|
const overlayComposeFile = defaultOpenMatesCloudComposeFile(resolvedOverlayPath);
|
|
29392
29518
|
if (!existsSync10(resolvedOverlayPath) || !existsSync10(overlayComposeFile)) {
|
|
29393
29519
|
throw new Error(
|
|
@@ -29498,7 +29624,7 @@ function printServerCommandStart(subcommand, rest, flags) {
|
|
|
29498
29624
|
console.log(renderOpenMatesAsciiLogo());
|
|
29499
29625
|
console.log("");
|
|
29500
29626
|
console.log(`Running OpenMates ${command}...`);
|
|
29501
|
-
if (typeof flags.path === "string") console.log(`Path: ${
|
|
29627
|
+
if (typeof flags.path === "string") console.log(`Path: ${resolve7(flags.path)}`);
|
|
29502
29628
|
if (typeof flags.role === "string") console.log(`Role: ${flags.role}`);
|
|
29503
29629
|
console.log("");
|
|
29504
29630
|
}
|
|
@@ -29640,8 +29766,8 @@ function createServerBackup(installPath, role, options = {}) {
|
|
|
29640
29766
|
const plan = planBackup({ role, includeObservability: options.includeObservability });
|
|
29641
29767
|
const backupDir = roleBackupDir(installPath, role);
|
|
29642
29768
|
mkdirSync7(backupDir, { recursive: true, mode: 448 });
|
|
29643
|
-
const archivePath = options.output ?
|
|
29644
|
-
mkdirSync7(
|
|
29769
|
+
const archivePath = options.output ? resolve7(options.output) : join8(backupDir, options.preUpdate ? `latest-pre-update-${role}.tar.gz` : `openmates-${role}-${nowStamp()}.tar.gz`);
|
|
29770
|
+
mkdirSync7(dirname7(archivePath), { recursive: true, mode: 448 });
|
|
29645
29771
|
const tempDir = mkdtempSync(join8(backupDir, ".tmp-"));
|
|
29646
29772
|
const env = readEnvMap(installPath);
|
|
29647
29773
|
const manifest = {
|
|
@@ -29685,7 +29811,7 @@ function createServerBackup(installPath, role, options = {}) {
|
|
|
29685
29811
|
}
|
|
29686
29812
|
}
|
|
29687
29813
|
function restoreServerBackup(installPath, role, file) {
|
|
29688
|
-
const archivePath =
|
|
29814
|
+
const archivePath = resolve7(file);
|
|
29689
29815
|
if (!existsSync10(archivePath)) throw new Error(`Backup file not found: ${archivePath}`);
|
|
29690
29816
|
mkdirSync7(roleBackupDir(installPath, role), { recursive: true, mode: 448 });
|
|
29691
29817
|
const tempDir = mkdtempSync(join8(roleBackupDir(installPath, role), ".restore-"));
|
|
@@ -29996,12 +30122,12 @@ async function serverRegister(flags) {
|
|
|
29996
30122
|
if (!existsSync10(envPath)) {
|
|
29997
30123
|
throw new Error(`Runtime env file not found: ${envPath}`);
|
|
29998
30124
|
}
|
|
29999
|
-
const gitRoot =
|
|
30125
|
+
const gitRoot = resolve7(exec("git rev-parse --show-toplevel", installPath));
|
|
30000
30126
|
if (gitRoot !== installPath) {
|
|
30001
30127
|
throw new Error(`--path must point to the OpenMates Git checkout root (${gitRoot}).`);
|
|
30002
30128
|
}
|
|
30003
30129
|
const existing = loadServerConfig();
|
|
30004
|
-
if (existing?.installPath &&
|
|
30130
|
+
if (existing?.installPath && resolve7(existing.installPath) !== installPath && flags.yes !== true) {
|
|
30005
30131
|
throw new Error(
|
|
30006
30132
|
`Another server is registered at ${existing.installPath}. Rerun with --yes to replace the local CLI registration; no server data will be changed.`
|
|
30007
30133
|
);
|
|
@@ -30051,8 +30177,8 @@ async function serverRegister(flags) {
|
|
|
30051
30177
|
}
|
|
30052
30178
|
}
|
|
30053
30179
|
async function serverInstall(flags) {
|
|
30054
|
-
const installPath = typeof flags.path === "string" ?
|
|
30055
|
-
const sourcePath = typeof flags["source-path"] === "string" ?
|
|
30180
|
+
const installPath = typeof flags.path === "string" ? resolve7(flags.path) : DEFAULT_INSTALL_PATH;
|
|
30181
|
+
const sourcePath = typeof flags["source-path"] === "string" ? resolve7(flags["source-path"]) : null;
|
|
30056
30182
|
const fromSource = flags["from-source"] === true || sourcePath !== null;
|
|
30057
30183
|
const role = getServerRole(flags, null);
|
|
30058
30184
|
const profile = getCoreProfile(flags, null);
|
|
@@ -30076,7 +30202,7 @@ async function serverInstall(flags) {
|
|
|
30076
30202
|
requireDocker();
|
|
30077
30203
|
mkdirSync7(installPath, { recursive: true });
|
|
30078
30204
|
if (typeof flags["env-path"] === "string") {
|
|
30079
|
-
const envSource =
|
|
30205
|
+
const envSource = resolve7(flags["env-path"]);
|
|
30080
30206
|
if (!existsSync10(envSource)) {
|
|
30081
30207
|
throw new Error(`Env file not found: ${envSource}`);
|
|
30082
30208
|
}
|
|
@@ -30151,7 +30277,7 @@ CLI default API: ${cliUrls2.apiUrl}`);
|
|
|
30151
30277
|
throw new Error("Failed to clone the OpenMates repository.");
|
|
30152
30278
|
}
|
|
30153
30279
|
if (typeof flags["env-path"] === "string") {
|
|
30154
|
-
const envSource =
|
|
30280
|
+
const envSource = resolve7(flags["env-path"]);
|
|
30155
30281
|
if (!existsSync10(envSource)) {
|
|
30156
30282
|
throw new Error(`Env file not found: ${envSource}`);
|
|
30157
30283
|
}
|
|
@@ -30343,7 +30469,7 @@ async function runUpdateCompletionEmailGate(input) {
|
|
|
30343
30469
|
deliveryId: deliveryPlan.deliveryId
|
|
30344
30470
|
};
|
|
30345
30471
|
}
|
|
30346
|
-
const deliveryId = deliveryPlan.deliveryId ??
|
|
30472
|
+
const deliveryId = deliveryPlan.deliveryId ?? randomUUID12();
|
|
30347
30473
|
const deliveryPendingAt = deliveryPlan.pendingAt ?? completedAt;
|
|
30348
30474
|
const previousAttempts = deliveryPlan.previousAttempts ?? 0;
|
|
30349
30475
|
const { role: _role, updated_at: _updatedAt, ...currentStatus } = readServerUpdateStatus(input.installPath, input.role);
|
|
@@ -30420,7 +30546,7 @@ async function persistRuntimeResult(installPath, role, output) {
|
|
|
30420
30546
|
return deliveries.flat();
|
|
30421
30547
|
}
|
|
30422
30548
|
async function installRuntimeMonitoringServices(installPath, role) {
|
|
30423
|
-
const executablePath =
|
|
30549
|
+
const executablePath = resolve7(process.argv[1] ?? "/usr/local/bin/openmates");
|
|
30424
30550
|
const plan = planRuntimeMonitoringServices({ role, installPath, executablePath });
|
|
30425
30551
|
const notificationConfig = runtimeNotificationConfig(installPath);
|
|
30426
30552
|
const emailServiceAvailable = notificationConfig.email ? await probeRuntimeEmailService(notificationConfig.email) : false;
|
|
@@ -30460,7 +30586,7 @@ async function installRuntimeMonitoringServices(installPath, role) {
|
|
|
30460
30586
|
operationalPlan.watchdogTimerName
|
|
30461
30587
|
];
|
|
30462
30588
|
if (operationalPlan.scheduleEnabled) {
|
|
30463
|
-
mkdirSync7(
|
|
30589
|
+
mkdirSync7(dirname7(reportStatePath), { recursive: true, mode: 448 });
|
|
30464
30590
|
mkdirSync7(reportMetricsDir, { recursive: true, mode: 448 });
|
|
30465
30591
|
if (!existsSync10(reportStatePath)) {
|
|
30466
30592
|
writeFileSync6(
|
|
@@ -30981,7 +31107,7 @@ async function serverMonitoring(rest, flags) {
|
|
|
30981
31107
|
const config = loadConfigForInstallPath(installPath);
|
|
30982
31108
|
const role = getServerRole(flags, config);
|
|
30983
31109
|
if (rest[0] === "install-service") {
|
|
30984
|
-
const plan = planRuntimeMonitoringServices({ role, installPath, executablePath:
|
|
31110
|
+
const plan = planRuntimeMonitoringServices({ role, installPath, executablePath: resolve7(process.argv[1] ?? "/usr/local/bin/openmates") });
|
|
30985
31111
|
const files = [
|
|
30986
31112
|
[plan.serviceName, plan.unit],
|
|
30987
31113
|
[plan.timerName, plan.timer],
|
|
@@ -31708,7 +31834,7 @@ WARNING: This will replace ${appliedPath} with the packaged ${role} Caddyfile.`)
|
|
|
31708
31834
|
const backupPath = `${appliedPath}.openmates-backup-${nowStamp()}`;
|
|
31709
31835
|
const hadExistingCaddyfile = existsSync10(appliedPath);
|
|
31710
31836
|
try {
|
|
31711
|
-
mkdirSync7(
|
|
31837
|
+
mkdirSync7(dirname7(appliedPath), { recursive: true });
|
|
31712
31838
|
if (hadExistingCaddyfile) copyFileSync2(appliedPath, backupPath);
|
|
31713
31839
|
copyFileSync2(templatePath, appliedPath);
|
|
31714
31840
|
execSync("systemctl reload caddy", { stdio: "inherit" });
|
|
@@ -32047,8 +32173,8 @@ async function handleServer(client, subcommand, rest, flags) {
|
|
|
32047
32173
|
}
|
|
32048
32174
|
|
|
32049
32175
|
// src/codeRunInput.ts
|
|
32050
|
-
import { readdir, readFile, stat } from "fs/promises";
|
|
32051
|
-
import { basename as
|
|
32176
|
+
import { readdir, readFile, stat as stat2 } from "fs/promises";
|
|
32177
|
+
import { basename as basename3, relative, resolve as resolve8 } from "path";
|
|
32052
32178
|
var CODE_RUN_MAX_FILES = 50;
|
|
32053
32179
|
var CODE_RUN_MAX_FILE_BYTES = 1e6;
|
|
32054
32180
|
var CODE_RUN_MAX_TOTAL_BYTES = 1e7;
|
|
@@ -32092,9 +32218,9 @@ async function buildCodeRunRequestsFromFlags(flags) {
|
|
|
32092
32218
|
}, buffer.byteLength);
|
|
32093
32219
|
}
|
|
32094
32220
|
for (const filePath of toList(flags.file)) {
|
|
32095
|
-
const absolute =
|
|
32221
|
+
const absolute = resolve8(filePath);
|
|
32096
32222
|
const buffer = await readFile(absolute);
|
|
32097
|
-
const sandboxPath = normalizeCodeRunPath(
|
|
32223
|
+
const sandboxPath = normalizeCodeRunPath(basename3(filePath));
|
|
32098
32224
|
addFile({
|
|
32099
32225
|
path: sandboxPath,
|
|
32100
32226
|
content_base64: buffer.toString("base64"),
|
|
@@ -32104,7 +32230,7 @@ async function buildCodeRunRequestsFromFlags(flags) {
|
|
|
32104
32230
|
}, buffer.byteLength);
|
|
32105
32231
|
}
|
|
32106
32232
|
for (const dirPath of toList(flags.dir)) {
|
|
32107
|
-
const root =
|
|
32233
|
+
const root = resolve8(dirPath);
|
|
32108
32234
|
const dirFiles = await collectDirectoryFiles(root, flags.include, flags.exclude);
|
|
32109
32235
|
for (const absolute of dirFiles) {
|
|
32110
32236
|
const sandboxPath = normalizeCodeRunPath(relative(root, absolute).replace(/\\/g, "/"));
|
|
@@ -32121,10 +32247,10 @@ async function buildCodeRunRequestsFromFlags(flags) {
|
|
|
32121
32247
|
for (const url of toList(flags.url)) {
|
|
32122
32248
|
const response = await fetch(url);
|
|
32123
32249
|
if (!response.ok) throw new Error(`Failed to download Code Run URL ${redactUrl(url)} (HTTP ${response.status})`);
|
|
32124
|
-
const
|
|
32250
|
+
const text2 = await response.text();
|
|
32125
32251
|
const urlPath = new URL(url).pathname;
|
|
32126
|
-
const sandboxPath = normalizeCodeRunPath(entry ||
|
|
32127
|
-
const buffer = Buffer.from(
|
|
32252
|
+
const sandboxPath = normalizeCodeRunPath(entry || basename3(urlPath) || "main.txt");
|
|
32253
|
+
const buffer = Buffer.from(text2, "utf8");
|
|
32128
32254
|
addFile({
|
|
32129
32255
|
path: sandboxPath,
|
|
32130
32256
|
content_base64: buffer.toString("base64"),
|
|
@@ -32134,9 +32260,9 @@ async function buildCodeRunRequestsFromFlags(flags) {
|
|
|
32134
32260
|
}, buffer.byteLength);
|
|
32135
32261
|
}
|
|
32136
32262
|
if (flags.repo) {
|
|
32137
|
-
await addGithubRepoFiles(flags.repo, toList(flags.include), async (path2,
|
|
32263
|
+
await addGithubRepoFiles(flags.repo, toList(flags.include), async (path2, text2) => {
|
|
32138
32264
|
const sandboxPath = normalizeCodeRunPath(path2);
|
|
32139
|
-
const buffer = Buffer.from(
|
|
32265
|
+
const buffer = Buffer.from(text2, "utf8");
|
|
32140
32266
|
addFile({
|
|
32141
32267
|
path: sandboxPath,
|
|
32142
32268
|
content_base64: buffer.toString("base64"),
|
|
@@ -32201,7 +32327,7 @@ async function collectDirectoryFiles(root, include, exclude) {
|
|
|
32201
32327
|
const files = [];
|
|
32202
32328
|
async function walk(directory) {
|
|
32203
32329
|
for (const entry of await readdir(directory, { withFileTypes: true })) {
|
|
32204
|
-
const absolute =
|
|
32330
|
+
const absolute = resolve8(directory, entry.name);
|
|
32205
32331
|
const rel = relative(root, absolute).replace(/\\/g, "/");
|
|
32206
32332
|
if (matchesAny(rel, excludes) || matchesAny(entry.name, excludes)) continue;
|
|
32207
32333
|
if (entry.isDirectory()) {
|
|
@@ -32211,7 +32337,7 @@ async function collectDirectoryFiles(root, include, exclude) {
|
|
|
32211
32337
|
}
|
|
32212
32338
|
}
|
|
32213
32339
|
}
|
|
32214
|
-
const rootStat = await
|
|
32340
|
+
const rootStat = await stat2(root);
|
|
32215
32341
|
if (!rootStat.isDirectory()) throw new Error(`Code Run --dir is not a directory: ${root}`);
|
|
32216
32342
|
await walk(root);
|
|
32217
32343
|
return files.sort();
|
|
@@ -49252,9 +49378,9 @@ function decodeEmbedContent(content) {
|
|
|
49252
49378
|
}
|
|
49253
49379
|
return parseFlatToonFields(content);
|
|
49254
49380
|
}
|
|
49255
|
-
function stringField2(
|
|
49381
|
+
function stringField2(record2, keys) {
|
|
49256
49382
|
for (const key of keys) {
|
|
49257
|
-
const value = cleanString(
|
|
49383
|
+
const value = cleanString(record2[key]);
|
|
49258
49384
|
if (value) return value;
|
|
49259
49385
|
}
|
|
49260
49386
|
return "";
|
|
@@ -49265,9 +49391,9 @@ function basenameFromUrl(url) {
|
|
|
49265
49391
|
return withoutQuery.split("/").pop()?.replace(/[^a-zA-Z0-9._-]/g, "_") ?? "";
|
|
49266
49392
|
}
|
|
49267
49393
|
function extensionFromUrl(url) {
|
|
49268
|
-
const
|
|
49269
|
-
const dotIndex =
|
|
49270
|
-
return dotIndex > 0 ?
|
|
49394
|
+
const basename6 = basenameFromUrl(url);
|
|
49395
|
+
const dotIndex = basename6.lastIndexOf(".");
|
|
49396
|
+
return dotIndex > 0 ? basename6.slice(dotIndex + 1).toLowerCase() : "";
|
|
49271
49397
|
}
|
|
49272
49398
|
function extensionFromLanguage(language) {
|
|
49273
49399
|
const normalized = language.toLowerCase();
|
|
@@ -49293,16 +49419,16 @@ function nestedFormatFromToon(content) {
|
|
|
49293
49419
|
const match = content.match(/\n\s+format:\s*([^\n]+)/);
|
|
49294
49420
|
return cleanString(match?.[1]);
|
|
49295
49421
|
}
|
|
49296
|
-
function urlForType(type,
|
|
49297
|
-
if (type.includes("video") || type === "remotion-video") return stringField2(
|
|
49298
|
-
if (type.includes("audio") || type === "music" || type === "recording") return stringField2(
|
|
49299
|
-
if (type.includes("image") || type === "svg") return stringField2(
|
|
49300
|
-
return stringField2(
|
|
49422
|
+
function urlForType(type, record2) {
|
|
49423
|
+
if (type.includes("video") || type === "remotion-video") return stringField2(record2, VIDEO_URL_FIELDS);
|
|
49424
|
+
if (type.includes("audio") || type === "music" || type === "recording") return stringField2(record2, AUDIO_URL_FIELDS);
|
|
49425
|
+
if (type.includes("image") || type === "svg") return stringField2(record2, IMAGE_URL_FIELDS);
|
|
49426
|
+
return stringField2(record2, URL_FIELDS);
|
|
49301
49427
|
}
|
|
49302
|
-
function inferFallbackExtension(type,
|
|
49303
|
-
const mimeType = stringField2(
|
|
49428
|
+
function inferFallbackExtension(type, record2, content) {
|
|
49429
|
+
const mimeType = stringField2(record2, ["mime_type", "file_type", "mimeType"]);
|
|
49304
49430
|
if (mimeType && MIME_EXTENSION[mimeType]) return MIME_EXTENSION[mimeType];
|
|
49305
|
-
const urlExtension = extensionFromUrl(urlForType(type,
|
|
49431
|
+
const urlExtension = extensionFromUrl(urlForType(type, record2));
|
|
49306
49432
|
if (urlExtension) return urlExtension;
|
|
49307
49433
|
const nestedFormat = nestedFormatFromToon(content);
|
|
49308
49434
|
if (nestedFormat) return nestedFormat;
|
|
@@ -49314,25 +49440,25 @@ function inferFallbackExtension(type, record, content) {
|
|
|
49314
49440
|
if (type.includes("sheet") || type === "spreadsheet") return "xlsx";
|
|
49315
49441
|
if (type === "model3d") return "glb";
|
|
49316
49442
|
if (type.includes("code") || type === "notebook" || type === "pcb_schematic") {
|
|
49317
|
-
return extensionFromLanguage(stringField2(
|
|
49443
|
+
return extensionFromLanguage(stringField2(record2, ["language"]));
|
|
49318
49444
|
}
|
|
49319
49445
|
return "txt";
|
|
49320
49446
|
}
|
|
49321
|
-
function inferTitle(embedId, type,
|
|
49322
|
-
const url = urlForType(type,
|
|
49447
|
+
function inferTitle(embedId, type, record2, content) {
|
|
49448
|
+
const url = urlForType(type, record2);
|
|
49323
49449
|
const urlBasename = basenameFromUrl(url);
|
|
49324
|
-
const filename = stringField2(
|
|
49450
|
+
const filename = stringField2(record2, FILENAME_FIELDS);
|
|
49325
49451
|
if ((type.includes("video") || type === "music" || type === "audio") && urlBasename) {
|
|
49326
49452
|
return urlBasename;
|
|
49327
49453
|
}
|
|
49328
49454
|
if (filename) return filename.replace(/[/\\]/g, "_");
|
|
49329
49455
|
if (urlBasename) return urlBasename;
|
|
49330
|
-
const title = stringField2(
|
|
49456
|
+
const title = stringField2(record2, ["title"]);
|
|
49331
49457
|
if (title) {
|
|
49332
|
-
const extension2 = inferFallbackExtension(type,
|
|
49458
|
+
const extension2 = inferFallbackExtension(type, record2, content);
|
|
49333
49459
|
return `${title.replace(/[^a-zA-Z0-9._ -]/g, "_").trim()}.${extension2}`;
|
|
49334
49460
|
}
|
|
49335
|
-
const extension = inferFallbackExtension(type,
|
|
49461
|
+
const extension = inferFallbackExtension(type, record2, content);
|
|
49336
49462
|
return `${type || "file"}-${embedId.slice(0, 8)}.${extension}`;
|
|
49337
49463
|
}
|
|
49338
49464
|
function inferNodeType(title, type) {
|
|
@@ -49378,13 +49504,13 @@ function formatBytes(bytes) {
|
|
|
49378
49504
|
function plural(value, singular, pluralLabel = `${singular}s`) {
|
|
49379
49505
|
return `${value} ${value === 1 ? singular : pluralLabel}`;
|
|
49380
49506
|
}
|
|
49381
|
-
function buildMetadata(nodeType, type,
|
|
49507
|
+
function buildMetadata(nodeType, type, record2) {
|
|
49382
49508
|
const parts = [labelForNodeType(nodeType, type)];
|
|
49383
|
-
const lineCount = numberValue3(
|
|
49384
|
-
const pageCount = numberValue3(
|
|
49385
|
-
const wordCount = numberValue3(
|
|
49386
|
-
const duration = numberValue3(
|
|
49387
|
-
const size = numberValue3(
|
|
49509
|
+
const lineCount = numberValue3(record2.line_count ?? record2.lineCount);
|
|
49510
|
+
const pageCount = numberValue3(record2.page_count ?? record2.pageCount);
|
|
49511
|
+
const wordCount = numberValue3(record2.word_count ?? record2.wordCount);
|
|
49512
|
+
const duration = numberValue3(record2.duration_seconds ?? record2.durationSeconds);
|
|
49513
|
+
const size = numberValue3(record2.byte_length ?? record2.size_bytes ?? record2.sizeBytes);
|
|
49388
49514
|
if (lineCount) parts.push(plural(lineCount, "line"));
|
|
49389
49515
|
if (pageCount) parts.push(plural(pageCount, "page"));
|
|
49390
49516
|
if (wordCount) parts.push(plural(wordCount, "word"));
|
|
@@ -70872,10 +70998,10 @@ function buildAssistantFeedbackDecision(rating) {
|
|
|
70872
70998
|
}
|
|
70873
70999
|
|
|
70874
71000
|
// src/benchmark.ts
|
|
70875
|
-
import { createHash as createHash14, randomUUID as
|
|
71001
|
+
import { createHash as createHash14, randomUUID as randomUUID13 } from "crypto";
|
|
70876
71002
|
import { existsSync as existsSync11, mkdtempSync as mkdtempSync2, readFileSync as readFileSync9, readdirSync as readdirSync6, writeFileSync as writeFileSync7 } from "fs";
|
|
70877
71003
|
import { tmpdir } from "os";
|
|
70878
|
-
import { dirname as
|
|
71004
|
+
import { dirname as dirname8, join as join9, resolve as resolve9 } from "path";
|
|
70879
71005
|
import { fileURLToPath } from "url";
|
|
70880
71006
|
var DEFAULT_JUDGE_MODEL = "google/gemini-3-flash-preview";
|
|
70881
71007
|
var DEFAULT_PROMPT_BUDGET_MODEL = "google/gemini-3.5-flash";
|
|
@@ -71288,8 +71414,8 @@ async function handleBenchmark(client, subcommand, rest, flags) {
|
|
|
71288
71414
|
const caseIds = parseCaseIds(flags.case);
|
|
71289
71415
|
const dryRun = flags["dry-run"] === true;
|
|
71290
71416
|
const output = typeof flags.output === "string" ? flags.output : void 0;
|
|
71291
|
-
const runId = typeof flags["run-id"] === "string" ? flags["run-id"] :
|
|
71292
|
-
const imagePath = typeof flags.image === "string" ?
|
|
71417
|
+
const runId = typeof flags["run-id"] === "string" ? flags["run-id"] : randomUUID13();
|
|
71418
|
+
const imagePath = typeof flags.image === "string" ? resolve9(flags.image) : defaultImageFixturePath();
|
|
71293
71419
|
if (!dryRun && flags["confirm-spend-credits"] !== true) {
|
|
71294
71420
|
throw new Error(
|
|
71295
71421
|
"Benchmark runs spend real credits from the logged-in account. Rerun with --confirm-spend-credits, or use --dry-run to preview the plan."
|
|
@@ -71390,7 +71516,7 @@ async function handlePromptBudgetBenchmark(client, rest, flags) {
|
|
|
71390
71516
|
if (resumeArtifact) {
|
|
71391
71517
|
validatePromptBudgetResumeArtifact(resumeArtifact, { phase, targetModel, judgeModel });
|
|
71392
71518
|
}
|
|
71393
|
-
const runId = stringFlag(flags["run-id"]) ?? resumeArtifact?.runId ??
|
|
71519
|
+
const runId = stringFlag(flags["run-id"]) ?? resumeArtifact?.runId ?? randomUUID13();
|
|
71394
71520
|
const result = makePromptBudgetBaseResult({
|
|
71395
71521
|
phase,
|
|
71396
71522
|
runId,
|
|
@@ -71951,7 +72077,7 @@ function buildLongContextHistory() {
|
|
|
71951
72077
|
}
|
|
71952
72078
|
function appendHistory(history, role, content) {
|
|
71953
72079
|
history.push({
|
|
71954
|
-
message_id:
|
|
72080
|
+
message_id: randomUUID13(),
|
|
71955
72081
|
role,
|
|
71956
72082
|
sender_name: role === "user" ? "User" : "Assistant",
|
|
71957
72083
|
content,
|
|
@@ -72009,13 +72135,13 @@ function parseJudgment(answer) {
|
|
|
72009
72135
|
return { score: null, reason: null };
|
|
72010
72136
|
}
|
|
72011
72137
|
}
|
|
72012
|
-
function extractJsonObject(
|
|
72013
|
-
const fenced =
|
|
72138
|
+
function extractJsonObject(text2) {
|
|
72139
|
+
const fenced = text2.match(/```(?:json)?\s*([\s\S]*?)\s*```/i);
|
|
72014
72140
|
if (fenced) return fenced[1];
|
|
72015
|
-
const start =
|
|
72016
|
-
const end =
|
|
72141
|
+
const start = text2.indexOf("{");
|
|
72142
|
+
const end = text2.lastIndexOf("}");
|
|
72017
72143
|
if (start === -1 || end === -1 || end <= start) return null;
|
|
72018
|
-
return
|
|
72144
|
+
return text2.slice(start, end + 1);
|
|
72019
72145
|
}
|
|
72020
72146
|
function loadPricingForModels(models) {
|
|
72021
72147
|
const availablePricing = loadProviderPricing();
|
|
@@ -72044,21 +72170,21 @@ function loadProviderPricing() {
|
|
|
72044
72170
|
for (const fileName of readdirSync6(providersDir)) {
|
|
72045
72171
|
if (!fileName.endsWith(".yml")) continue;
|
|
72046
72172
|
const filePath = join9(providersDir, fileName);
|
|
72047
|
-
const
|
|
72048
|
-
const provider = parseProviderId(
|
|
72049
|
-
for (const modelPricing of parseModelPricing(
|
|
72173
|
+
const text2 = readFileSync9(filePath, "utf-8");
|
|
72174
|
+
const provider = parseProviderId(text2) ?? fileName.replace(/\.yml$/, "");
|
|
72175
|
+
for (const modelPricing of parseModelPricing(text2, provider)) {
|
|
72050
72176
|
pricing.set(`${modelPricing.provider}/${modelPricing.modelId}`, modelPricing);
|
|
72051
72177
|
pricing.set(modelPricing.modelId, modelPricing);
|
|
72052
72178
|
}
|
|
72053
72179
|
}
|
|
72054
72180
|
return pricing;
|
|
72055
72181
|
}
|
|
72056
|
-
function parseProviderId(
|
|
72057
|
-
const match =
|
|
72182
|
+
function parseProviderId(text2) {
|
|
72183
|
+
const match = text2.match(/^provider_id:\s*["']?([^"'\n]+)["']?/m);
|
|
72058
72184
|
return match?.[1]?.trim() ?? null;
|
|
72059
72185
|
}
|
|
72060
|
-
function parseModelPricing(
|
|
72061
|
-
const lines =
|
|
72186
|
+
function parseModelPricing(text2, provider) {
|
|
72187
|
+
const lines = text2.split("\n");
|
|
72062
72188
|
const results = [];
|
|
72063
72189
|
let modelId = null;
|
|
72064
72190
|
let inModel = false;
|
|
@@ -72096,13 +72222,13 @@ function normalizeModelKey(model) {
|
|
|
72096
72222
|
}
|
|
72097
72223
|
function findProvidersDir() {
|
|
72098
72224
|
const currentFile = fileURLToPath(import.meta.url);
|
|
72099
|
-
let current =
|
|
72225
|
+
let current = dirname8(currentFile);
|
|
72100
72226
|
for (let index = 0; index < 8; index += 1) {
|
|
72101
72227
|
const candidate = join9(current, "backend", "providers");
|
|
72102
72228
|
if (existsSync11(candidate)) return candidate;
|
|
72103
72229
|
const parentCandidate = join9(current, "..", "..", "backend", "providers");
|
|
72104
|
-
if (existsSync11(parentCandidate)) return
|
|
72105
|
-
const next =
|
|
72230
|
+
if (existsSync11(parentCandidate)) return resolve9(parentCandidate);
|
|
72231
|
+
const next = dirname8(current);
|
|
72106
72232
|
if (next === current) break;
|
|
72107
72233
|
current = next;
|
|
72108
72234
|
}
|
|
@@ -72309,7 +72435,7 @@ function stableHash(value) {
|
|
|
72309
72435
|
return createHash14("sha256").update(JSON.stringify(value)).digest("hex");
|
|
72310
72436
|
}
|
|
72311
72437
|
function defaultImageFixturePath() {
|
|
72312
|
-
const fixtureDir = join9(
|
|
72438
|
+
const fixtureDir = join9(dirname8(fileURLToPath(import.meta.url)), "..", "fixtures");
|
|
72313
72439
|
const fixturePath = join9(fixtureDir, "brandenburger-tor.png");
|
|
72314
72440
|
if (existsSync11(fixturePath)) return fixturePath;
|
|
72315
72441
|
const tempDir = mkdtempSync2(join9(tmpdir(), "openmates-benchmark-"));
|
|
@@ -73130,8 +73256,8 @@ async function runTui(client, terminal = new TuiTerminal()) {
|
|
|
73130
73256
|
void handleKey({ chunk, key, state, client, terminal, render, finish });
|
|
73131
73257
|
});
|
|
73132
73258
|
render();
|
|
73133
|
-
return new Promise((
|
|
73134
|
-
resolveResult =
|
|
73259
|
+
return new Promise((resolve12) => {
|
|
73260
|
+
resolveResult = resolve12;
|
|
73135
73261
|
});
|
|
73136
73262
|
}
|
|
73137
73263
|
async function handleKey(params) {
|
|
@@ -73295,14 +73421,14 @@ async function handleEnter(params) {
|
|
|
73295
73421
|
render();
|
|
73296
73422
|
return;
|
|
73297
73423
|
}
|
|
73298
|
-
const
|
|
73299
|
-
if (!
|
|
73424
|
+
const text2 = state.input.trim();
|
|
73425
|
+
if (!text2) return;
|
|
73300
73426
|
state.input = "";
|
|
73301
|
-
if (
|
|
73302
|
-
await handleCommand({ command:
|
|
73427
|
+
if (text2.startsWith("/")) {
|
|
73428
|
+
await handleCommand({ command: text2, state, client, terminal, render, finish });
|
|
73303
73429
|
return;
|
|
73304
73430
|
}
|
|
73305
|
-
await sendTuiMessage({ message:
|
|
73431
|
+
await sendTuiMessage({ message: text2, state, client, render });
|
|
73306
73432
|
}
|
|
73307
73433
|
async function handleCommand(params) {
|
|
73308
73434
|
const { command, state, client, terminal, render, finish } = params;
|
|
@@ -73833,7 +73959,7 @@ import {
|
|
|
73833
73959
|
writeFileSync as writeFileSync8
|
|
73834
73960
|
} from "fs";
|
|
73835
73961
|
import { spawn as spawn3, spawnSync as spawnSync2 } from "child_process";
|
|
73836
|
-
import { join as join10, resolve as
|
|
73962
|
+
import { join as join10, resolve as resolve10, relative as relative2 } from "path";
|
|
73837
73963
|
|
|
73838
73964
|
// src/projectFileRisk.ts
|
|
73839
73965
|
var SECRET_OR_ENVIRONMENT_PATTERNS = [
|
|
@@ -73955,7 +74081,7 @@ function resolveRemoteAccessRoots(pathFlag, cwd = process.cwd()) {
|
|
|
73955
74081
|
}
|
|
73956
74082
|
const roots = [];
|
|
73957
74083
|
for (const value of requested) {
|
|
73958
|
-
const candidate =
|
|
74084
|
+
const candidate = resolve10(cwd, value);
|
|
73959
74085
|
if (!existsSync12(candidate) || !statSync2(candidate).isDirectory()) {
|
|
73960
74086
|
throw new Error(`Remote source path does not exist or is not a directory: ${candidate}`);
|
|
73961
74087
|
}
|
|
@@ -74273,7 +74399,7 @@ function resolveRemoteCachePath(sourceId, homeDirectory = homedir7()) {
|
|
|
74273
74399
|
function startRemoteAccessSource(input) {
|
|
74274
74400
|
assertSafeSourceId(input.sourceId);
|
|
74275
74401
|
const homeDirectory = input.homeDirectory ?? homedir7();
|
|
74276
|
-
const requestedRootPath =
|
|
74402
|
+
const requestedRootPath = resolve10(input.rootPath);
|
|
74277
74403
|
if (!existsSync12(requestedRootPath) || !statSync2(requestedRootPath).isDirectory()) {
|
|
74278
74404
|
throw new Error(`Remote source path does not exist or is not a directory: ${requestedRootPath}`);
|
|
74279
74405
|
}
|
|
@@ -74311,7 +74437,7 @@ function listRemoteAccessSources(homeDirectory = homedir7()) {
|
|
|
74311
74437
|
}
|
|
74312
74438
|
}
|
|
74313
74439
|
async function searchRemoteSource(options) {
|
|
74314
|
-
const sourceRoot =
|
|
74440
|
+
const sourceRoot = resolve10(options.sourceRoot);
|
|
74315
74441
|
const maxResults = normalizeMaxResults(options.maxResults);
|
|
74316
74442
|
let output;
|
|
74317
74443
|
try {
|
|
@@ -74489,9 +74615,9 @@ function shouldExcludePath(sourceRoot, relativePath, userProtectedPatterns) {
|
|
|
74489
74615
|
return classifyProjectFileRisk(relativePath, userProtectedPatterns).isHighRisk;
|
|
74490
74616
|
}
|
|
74491
74617
|
function isPathInsideRoot(sourceRoot, relativePath) {
|
|
74492
|
-
const resolvedPath =
|
|
74618
|
+
const resolvedPath = resolve10(sourceRoot, relativePath);
|
|
74493
74619
|
const relation = relative2(sourceRoot, resolvedPath);
|
|
74494
|
-
return relation === "" || !relation.startsWith("..") && !
|
|
74620
|
+
return relation === "" || !relation.startsWith("..") && !resolve10(relation).startsWith("/..");
|
|
74495
74621
|
}
|
|
74496
74622
|
function isBinaryPath(path2) {
|
|
74497
74623
|
const lowerPath = path2.toLowerCase();
|
|
@@ -74517,7 +74643,7 @@ function parseRgMatch(line) {
|
|
|
74517
74643
|
}
|
|
74518
74644
|
function resolveApprovedPath(sourceRoot, relativePath) {
|
|
74519
74645
|
if (!relativePath || relativePath.includes("\0")) throw new Error("Remote source path is invalid");
|
|
74520
|
-
const lexical =
|
|
74646
|
+
const lexical = resolve10(sourceRoot, relativePath);
|
|
74521
74647
|
assertInsideRoot(sourceRoot, lexical);
|
|
74522
74648
|
const canonical = realpathSync(lexical);
|
|
74523
74649
|
assertInsideRoot(sourceRoot, canonical);
|
|
@@ -74525,7 +74651,7 @@ function resolveApprovedPath(sourceRoot, relativePath) {
|
|
|
74525
74651
|
}
|
|
74526
74652
|
function assertInsideRoot(sourceRoot, path2) {
|
|
74527
74653
|
const relation = relative2(sourceRoot, path2);
|
|
74528
|
-
if (relation.startsWith("..") ||
|
|
74654
|
+
if (relation.startsWith("..") || resolve10(sourceRoot, relation) !== resolve10(path2)) {
|
|
74529
74655
|
throw new Error("Remote source path escapes the approved source root");
|
|
74530
74656
|
}
|
|
74531
74657
|
}
|
|
@@ -74590,7 +74716,7 @@ function assertRemoteAccessSourceRecord(value, index) {
|
|
|
74590
74716
|
}
|
|
74591
74717
|
|
|
74592
74718
|
// src/projectRequester.ts
|
|
74593
|
-
import { randomUUID as
|
|
74719
|
+
import { randomUUID as randomUUID14 } from "crypto";
|
|
74594
74720
|
var REMOTE_PROTOCOL_TIMEOUT_MS = 45e3;
|
|
74595
74721
|
var REMOTE_POLL_INTERVAL_MS = 250;
|
|
74596
74722
|
var MAX_REMOTE_RESULT_BYTES = 200 * 1024;
|
|
@@ -74616,8 +74742,8 @@ async function requestProjectRemoteOperation(options) {
|
|
|
74616
74742
|
keyEpoch = discovery.keyEpoch;
|
|
74617
74743
|
routingIdentity = discovery.routingIdentity;
|
|
74618
74744
|
}
|
|
74619
|
-
const requestingClientId =
|
|
74620
|
-
const requestId =
|
|
74745
|
+
const requestingClientId = randomUUID14();
|
|
74746
|
+
const requestId = randomUUID14();
|
|
74621
74747
|
const identity = await buildIdentity(
|
|
74622
74748
|
options.client,
|
|
74623
74749
|
options.projectId,
|
|
@@ -74678,9 +74804,9 @@ async function requestProjectRemoteOperation(options) {
|
|
|
74678
74804
|
return response.result;
|
|
74679
74805
|
}
|
|
74680
74806
|
async function discoverRouting(options, timeoutMs) {
|
|
74681
|
-
const requestId =
|
|
74682
|
-
const requestingClientId =
|
|
74683
|
-
const nonce =
|
|
74807
|
+
const requestId = randomUUID14();
|
|
74808
|
+
const requestingClientId = randomUUID14();
|
|
74809
|
+
const nonce = randomUUID14();
|
|
74684
74810
|
const encryptedEnvelope = await encryptWithAesGcmCombined(JSON.stringify({
|
|
74685
74811
|
type: "routing_discovery",
|
|
74686
74812
|
requesting_client_id: requestingClientId,
|
|
@@ -74780,7 +74906,7 @@ function remoteErrorMessage(code) {
|
|
|
74780
74906
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
74781
74907
|
import { readFileSync as readFileSync11, mkdirSync as mkdirSync9, writeFileSync as writeFileSync9, renameSync as renameSync5 } from "fs";
|
|
74782
74908
|
import { homedir as homedir8 } from "os";
|
|
74783
|
-
import { dirname as
|
|
74909
|
+
import { dirname as dirname9, basename as basename4, join as join11 } from "path";
|
|
74784
74910
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
74785
74911
|
var PACKAGE_NAME = "openmates";
|
|
74786
74912
|
function channelFile() {
|
|
@@ -74804,17 +74930,17 @@ function savedChannel() {
|
|
|
74804
74930
|
function persistSelfUpdateChannel(plan) {
|
|
74805
74931
|
if (plan.dryRun || !plan.persistChannel) return;
|
|
74806
74932
|
const path2 = channelFile();
|
|
74807
|
-
mkdirSync9(
|
|
74933
|
+
mkdirSync9(dirname9(path2), { recursive: true, mode: 448 });
|
|
74808
74934
|
const temporary = `${path2}.${process.pid}.tmp`;
|
|
74809
74935
|
writeFileSync9(temporary, JSON.stringify({ channel: plan.channel }) + "\n", { mode: 384 });
|
|
74810
74936
|
renameSync5(temporary, path2);
|
|
74811
74937
|
}
|
|
74812
74938
|
function installedNpmPrefix(moduleUrl = import.meta.url, platform4 = process.platform) {
|
|
74813
|
-
const packageRoot =
|
|
74814
|
-
const modules =
|
|
74815
|
-
if (
|
|
74816
|
-
if (platform4 === "win32") return
|
|
74817
|
-
return
|
|
74939
|
+
const packageRoot = dirname9(dirname9(fileURLToPath2(moduleUrl)));
|
|
74940
|
+
const modules = dirname9(packageRoot);
|
|
74941
|
+
if (basename4(packageRoot) !== PACKAGE_NAME || basename4(modules) !== "node_modules") return null;
|
|
74942
|
+
if (platform4 === "win32") return dirname9(modules);
|
|
74943
|
+
return basename4(dirname9(modules)) === "lib" ? dirname9(dirname9(modules)) : null;
|
|
74818
74944
|
}
|
|
74819
74945
|
function compareVersions(left, right) {
|
|
74820
74946
|
const parse = (value) => {
|
|
@@ -74964,7 +75090,7 @@ function commandName(name) {
|
|
|
74964
75090
|
|
|
74965
75091
|
// src/workRecovery.ts
|
|
74966
75092
|
import { mkdirSync as mkdirSync10, renameSync as renameSync6, writeFileSync as writeFileSync10 } from "fs";
|
|
74967
|
-
import { dirname as
|
|
75093
|
+
import { dirname as dirname10 } from "path";
|
|
74968
75094
|
import { stringify } from "yaml";
|
|
74969
75095
|
async function projectPlanAssumption(plan, masterKey, assumption) {
|
|
74970
75096
|
const key = await planKeyFromRecord(plan.encrypted, masterKey);
|
|
@@ -75143,7 +75269,7 @@ function collectMismatchPaths(left, right, path2, mismatches) {
|
|
|
75143
75269
|
}
|
|
75144
75270
|
function writeWorkRecoveryAtomically(path2, document) {
|
|
75145
75271
|
validateWorkRecoveryDocument(document);
|
|
75146
|
-
mkdirSync10(
|
|
75272
|
+
mkdirSync10(dirname10(path2), { recursive: true, mode: 448 });
|
|
75147
75273
|
const temporaryPath = `${path2}.tmp`;
|
|
75148
75274
|
writeFileSync10(temporaryPath, stringify(document, { sortMapEntries: true, lineWidth: 0 }), { encoding: "utf8", mode: 384 });
|
|
75149
75275
|
renameSync6(temporaryPath, path2);
|
|
@@ -75151,10 +75277,10 @@ function writeWorkRecoveryAtomically(path2, document) {
|
|
|
75151
75277
|
|
|
75152
75278
|
// src/revolutBusinessCertificate.ts
|
|
75153
75279
|
import { execFileSync as execFileSync5 } from "child_process";
|
|
75154
|
-
import { createSign, randomUUID as
|
|
75280
|
+
import { createSign, randomUUID as randomUUID15 } from "crypto";
|
|
75155
75281
|
import { chmodSync as chmodSync7, existsSync as existsSync13, mkdirSync as mkdirSync11, readFileSync as readFileSync12 } from "fs";
|
|
75156
75282
|
import { homedir as homedir9 } from "os";
|
|
75157
|
-
import { join as join12, resolve as
|
|
75283
|
+
import { join as join12, resolve as resolve11 } from "path";
|
|
75158
75284
|
var REVOLUT_BUSINESS_CERTIFICATE_DOCS_URL = "https://developer.revolut.com/docs/guides/manage-accounts/get-started/make-your-first-api-request#generate-a-private-and-a-public-certificate";
|
|
75159
75285
|
var REVOLUT_BUSINESS_DEFAULT_SANDBOX_REDIRECT_URI = "https://app.dev.openmates.org/oauth/revolut-business/callback";
|
|
75160
75286
|
var REVOLUT_BUSINESS_DEFAULT_PRODUCTION_REDIRECT_URI = "https://openmates.org/oauth/revolut-business/callback";
|
|
@@ -75225,7 +75351,7 @@ function generateRevolutBusinessClientAssertion(options) {
|
|
|
75225
75351
|
aud: REVOLUT_BUSINESS_AUDIENCE,
|
|
75226
75352
|
exp: now + 3600,
|
|
75227
75353
|
iat: now,
|
|
75228
|
-
jti:
|
|
75354
|
+
jti: randomUUID15()
|
|
75229
75355
|
});
|
|
75230
75356
|
const unsigned = `${header2}.${payload}`;
|
|
75231
75357
|
const signer = createSign("RSA-SHA256");
|
|
@@ -75235,7 +75361,7 @@ function generateRevolutBusinessClientAssertion(options) {
|
|
|
75235
75361
|
}
|
|
75236
75362
|
function generateRevolutBusinessCertificate(options = {}) {
|
|
75237
75363
|
const environment = options.environment ?? "sandbox";
|
|
75238
|
-
const outputDir =
|
|
75364
|
+
const outputDir = resolve11(options.outputDir ?? defaultRevolutBusinessCertificateDir(environment));
|
|
75239
75365
|
const title = (options.title ?? REVOLUT_BUSINESS_DEFAULT_CERTIFICATE_TITLE).trim();
|
|
75240
75366
|
const redirectUri = (options.redirectUri ?? defaultRevolutBusinessRedirectUri(environment)).trim();
|
|
75241
75367
|
if (!title) throw new Error("Revolut certificate title must not be empty.");
|
|
@@ -75887,8 +76013,8 @@ async function handleTasks(client, subcommand, rest, flags, redactor) {
|
|
|
75887
76013
|
if (!message.trim()) throw new Error("Missing comment. Usage: openmates tasks activity add <task-id> --message <text>");
|
|
75888
76014
|
const deliveryId = typeof flags["delivery-id"] === "string" ? flags["delivery-id"] : void 0;
|
|
75889
76015
|
const build = () => buildCreateTaskActivityInput(task, masterKey, { message, ...deliveryId ? { entryId: deliveryId } : {} });
|
|
75890
|
-
const
|
|
75891
|
-
const entry = await decryptTaskActivityEntry(task, masterKey,
|
|
76016
|
+
const record2 = deliveryId ? await delivery().deliver(deliveryId, build, createActivity) : await createActivity(await build());
|
|
76017
|
+
const entry = await decryptTaskActivityEntry(task, masterKey, record2);
|
|
75892
76018
|
if (entry.message !== message) throw new Error("Activity delivery id already belongs to a different milestone message");
|
|
75893
76019
|
if (flags.json === true) printJson2({ entry: taskActivityToJson(entry) });
|
|
75894
76020
|
else console.log(renderTaskActivityList([entry]));
|
|
@@ -76231,13 +76357,13 @@ function extractRecord(container, key) {
|
|
|
76231
76357
|
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error(`Workspace ask planning returned invalid ${key}.`);
|
|
76232
76358
|
return value;
|
|
76233
76359
|
}
|
|
76234
|
-
function requiredString(
|
|
76235
|
-
const value =
|
|
76360
|
+
function requiredString(record2, key, fallback) {
|
|
76361
|
+
const value = record2[key];
|
|
76236
76362
|
if (typeof value === "string" && value.trim()) return value.trim();
|
|
76237
76363
|
return fallback;
|
|
76238
76364
|
}
|
|
76239
|
-
function optionalString(
|
|
76240
|
-
const value =
|
|
76365
|
+
function optionalString(record2, key) {
|
|
76366
|
+
const value = record2[key];
|
|
76241
76367
|
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
76242
76368
|
}
|
|
76243
76369
|
async function proposeTasksForAsk(client, instruction, flags) {
|
|
@@ -76530,28 +76656,28 @@ function normalizeAskLookup(value) {
|
|
|
76530
76656
|
async function loadProjects(client, masterKey, flags, context = teamContextFromFlags(flags)) {
|
|
76531
76657
|
const records = await client.listProjects({ includeArchived: true, ...context });
|
|
76532
76658
|
const projects = [];
|
|
76533
|
-
for (const
|
|
76534
|
-
const decrypted = await decryptProject(client,
|
|
76659
|
+
for (const record2 of records) {
|
|
76660
|
+
const decrypted = await decryptProject(client, record2, masterKey, context);
|
|
76535
76661
|
if (decrypted) projects.push(decrypted);
|
|
76536
76662
|
}
|
|
76537
76663
|
return projects;
|
|
76538
76664
|
}
|
|
76539
|
-
async function decryptProject(client,
|
|
76665
|
+
async function decryptProject(client, record2, masterKey, context = {}) {
|
|
76540
76666
|
void masterKey;
|
|
76541
|
-
if (!
|
|
76542
|
-
const projectKey = await client.decryptProjectKey(
|
|
76667
|
+
if (!record2.project_id) return null;
|
|
76668
|
+
const projectKey = await client.decryptProjectKey(record2, context);
|
|
76543
76669
|
return {
|
|
76544
|
-
projectId:
|
|
76545
|
-
slug: await decryptOptionalProjectField2(
|
|
76546
|
-
name: await decryptOptionalProjectField2(
|
|
76547
|
-
description: await decryptOptionalProjectField2(
|
|
76548
|
-
icon: await decryptOptionalProjectField2(
|
|
76549
|
-
color: await decryptOptionalProjectField2(
|
|
76550
|
-
pinned:
|
|
76551
|
-
archived:
|
|
76552
|
-
version: typeof
|
|
76670
|
+
projectId: record2.project_id,
|
|
76671
|
+
slug: await decryptOptionalProjectField2(record2.encrypted_slug, projectKey),
|
|
76672
|
+
name: await decryptOptionalProjectField2(record2.encrypted_name, projectKey) || "(untitled project)",
|
|
76673
|
+
description: await decryptOptionalProjectField2(record2.encrypted_description, projectKey),
|
|
76674
|
+
icon: await decryptOptionalProjectField2(record2.encrypted_icon, projectKey),
|
|
76675
|
+
color: await decryptOptionalProjectField2(record2.encrypted_color, projectKey),
|
|
76676
|
+
pinned: record2.pinned === true,
|
|
76677
|
+
archived: record2.archived === true,
|
|
76678
|
+
version: typeof record2.version === "number" ? record2.version : null,
|
|
76553
76679
|
projectKey,
|
|
76554
|
-
encrypted:
|
|
76680
|
+
encrypted: record2
|
|
76555
76681
|
};
|
|
76556
76682
|
}
|
|
76557
76683
|
async function decryptOptionalProjectField2(value, projectKey) {
|
|
@@ -76614,7 +76740,7 @@ async function resolveAddToProjectStorageChoice(client, project, flags, objectTy
|
|
|
76614
76740
|
async function createEncryptedProjectItem(client, project, input) {
|
|
76615
76741
|
const timestamp = nowSeconds3();
|
|
76616
76742
|
return client.createProjectItem(project.projectId, {
|
|
76617
|
-
project_item_id:
|
|
76743
|
+
project_item_id: randomUUID16(),
|
|
76618
76744
|
folder_id: input.folderId ?? null,
|
|
76619
76745
|
item_type: input.itemType,
|
|
76620
76746
|
target_id: input.targetId,
|
|
@@ -76808,7 +76934,7 @@ async function handlePlans(client, subcommand, rest, flags, redactor) {
|
|
|
76808
76934
|
const encryptedSources = proof.length ? await encryptPlanAssumptionSources(plan, masterKey, proof) : void 0;
|
|
76809
76935
|
if (action === "create" || action === "add") {
|
|
76810
76936
|
const assumption = await client.createPlanAssumption(plan.planId, {
|
|
76811
|
-
assumption_id: typeof flags.id === "string" ? flags.id :
|
|
76937
|
+
assumption_id: typeof flags.id === "string" ? flags.id : randomUUID16(),
|
|
76812
76938
|
encrypted_text: await encryptPlanAssumptionSources(plan, masterKey, requiredStringFlag(flags.text ?? rest.slice(2).join(" "), "--text <assumption>")),
|
|
76813
76939
|
status: typeof flags.status === "string" ? flags.status : void 0,
|
|
76814
76940
|
linked_sub_chat_id: typeof flags["sub-chat"] === "string" ? flags["sub-chat"] : void 0,
|
|
@@ -77129,10 +77255,10 @@ async function handlePlans(client, subcommand, rest, flags, redactor) {
|
|
|
77129
77255
|
else console.log(`Plan success criterion updated: ${updated.criterion_id}`);
|
|
77130
77256
|
return;
|
|
77131
77257
|
}
|
|
77132
|
-
const
|
|
77258
|
+
const text2 = requiredStringFlag(flags.text ?? rest.slice(2).join(" "), "--text <criterion>");
|
|
77133
77259
|
const criterion = await buildCreatePlanCriterionInput(plan, masterKey, {
|
|
77134
77260
|
criterionId: typeof flags.id === "string" ? flags.id : void 0,
|
|
77135
|
-
text,
|
|
77261
|
+
text: text2,
|
|
77136
77262
|
type: typeof flags.type === "string" ? flags.type : void 0,
|
|
77137
77263
|
status: typeof flags.status === "string" ? flags.status : void 0,
|
|
77138
77264
|
required: flags.required === true ? true : flags.optional === true ? false : void 0,
|
|
@@ -77430,25 +77556,25 @@ async function handleWorkRecovery(client, subcommand, rest, flags) {
|
|
|
77430
77556
|
if (conflicts.length > 0) throw new Error(`Recovery restore found conflicts and made no changes: ${JSON.stringify(conflicts)}`);
|
|
77431
77557
|
const applied = [];
|
|
77432
77558
|
try {
|
|
77433
|
-
for (const
|
|
77434
|
-
const linkContext = await resolvePlanLinkKeyContext(client, masterKey2, flags, { primaryChatId: typeof
|
|
77435
|
-
const input = await buildCreateUserPlanInput(masterKey2, recoveryPlanCreateOptions(
|
|
77559
|
+
for (const record2 of document.plans) {
|
|
77560
|
+
const linkContext = await resolvePlanLinkKeyContext(client, masterKey2, flags, { primaryChatId: typeof record2.primary_chat_id === "string" ? record2.primary_chat_id : null, linkedProjectIds: [project2.projectId] });
|
|
77561
|
+
const input = await buildCreateUserPlanInput(masterKey2, recoveryPlanCreateOptions(record2, linkContext));
|
|
77436
77562
|
await client.createUserPlan(input);
|
|
77437
77563
|
applied.push(`plan:${input.plan_id}`);
|
|
77438
77564
|
}
|
|
77439
|
-
for (const
|
|
77440
|
-
const input = await buildCreateUserTaskInput(masterKey2, recoveryTaskCreateOptions(
|
|
77565
|
+
for (const record2 of document.tasks) {
|
|
77566
|
+
const input = await buildCreateUserTaskInput(masterKey2, recoveryTaskCreateOptions(record2, project2.projectId));
|
|
77441
77567
|
await client.createUserTask(input);
|
|
77442
77568
|
applied.push(`task:${input.task_id}`);
|
|
77443
77569
|
}
|
|
77444
77570
|
const restoredPlans = await loadPlans(client, masterKey2, { projectId: project2.projectId });
|
|
77445
77571
|
const planById = new Map(restoredPlans.map((plan) => [plan.planId, plan]));
|
|
77446
|
-
for (const
|
|
77447
|
-
const planId = recoveryString(
|
|
77572
|
+
for (const record2 of document.assumptions) {
|
|
77573
|
+
const planId = recoveryString(record2, "plan_id");
|
|
77448
77574
|
const plan = planById.get(planId);
|
|
77449
77575
|
if (!plan) throw new Error(`Restored plan ${planId} was not available for its assumption.`);
|
|
77450
|
-
await client.createPlanAssumption(planId, await recoveryAssumptionInput(plan, masterKey2,
|
|
77451
|
-
applied.push(`assumption:${recoveryString(
|
|
77576
|
+
await client.createPlanAssumption(planId, await recoveryAssumptionInput(plan, masterKey2, record2));
|
|
77577
|
+
applied.push(`assumption:${recoveryString(record2, "assumption_id")}`);
|
|
77452
77578
|
}
|
|
77453
77579
|
for (const dependency of document.dependencies) {
|
|
77454
77580
|
const [kind, id] = dependency.source_ref.split(":", 2);
|
|
@@ -77456,13 +77582,13 @@ async function handleWorkRecovery(client, subcommand, rest, flags) {
|
|
|
77456
77582
|
else await client.addTaskDependency(id, dependency.target_ref);
|
|
77457
77583
|
applied.push(`dependency:${dependency.source_ref}->${dependency.target_ref}`);
|
|
77458
77584
|
}
|
|
77459
|
-
for (const
|
|
77460
|
-
const planId = recoveryString(
|
|
77461
|
-
const snapshot = JSON.stringify(
|
|
77585
|
+
for (const record2 of document.revisions) {
|
|
77586
|
+
const planId = recoveryString(record2, "plan_id");
|
|
77587
|
+
const snapshot = JSON.stringify(record2.snapshot);
|
|
77462
77588
|
const plan = planById.get(planId);
|
|
77463
77589
|
if (!plan) throw new Error(`Restored plan ${planId} was not available for its revision.`);
|
|
77464
|
-
await client.submitPlanRevision(planId, { fingerprint: recoveryString(
|
|
77465
|
-
applied.push(`revision:${recoveryString(
|
|
77590
|
+
await client.submitPlanRevision(planId, { fingerprint: recoveryString(record2, "fingerprint"), encrypted_snapshot: await encryptPlanAssumptionSources(plan, masterKey2, snapshot), created_at: nowSeconds3() });
|
|
77591
|
+
applied.push(`revision:${recoveryString(record2, "revision_id")}`);
|
|
77466
77592
|
}
|
|
77467
77593
|
} catch (error) {
|
|
77468
77594
|
throw new Error(`Recovery restore partially applied (${applied.join(", ") || "nothing"}); it is not cross-object atomic. ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -77500,13 +77626,13 @@ async function buildProjectWorkRecoveryDocument(client, masterKey, projectId) {
|
|
|
77500
77626
|
}
|
|
77501
77627
|
return { schema_version: 1, project: { project_id: projectId }, plans: plans.map(planToJson), tasks: tasks.map(taskToJson), dependencies, assumptions, revisions };
|
|
77502
77628
|
}
|
|
77503
|
-
function recoveryString(
|
|
77504
|
-
const value =
|
|
77629
|
+
function recoveryString(record2, key) {
|
|
77630
|
+
const value = record2[key];
|
|
77505
77631
|
if (typeof value !== "string") throw new Error(`Recovery record requires ${key}.`);
|
|
77506
77632
|
return value;
|
|
77507
77633
|
}
|
|
77508
|
-
function recoveryStrings(
|
|
77509
|
-
const value =
|
|
77634
|
+
function recoveryStrings(record2, key) {
|
|
77635
|
+
const value = record2[key];
|
|
77510
77636
|
if (!Array.isArray(value) || !value.every((item) => typeof item === "string")) throw new Error(`Recovery record requires ${key} string array.`);
|
|
77511
77637
|
return value;
|
|
77512
77638
|
}
|
|
@@ -77517,8 +77643,8 @@ function parsePlanUserFlowsFlag(value) {
|
|
|
77517
77643
|
if (!Array.isArray(parsed)) throw new Error("--user-flows must be a JSON array.");
|
|
77518
77644
|
return parsed;
|
|
77519
77645
|
}
|
|
77520
|
-
function recoveryPlanUserFlows(
|
|
77521
|
-
const flows =
|
|
77646
|
+
function recoveryPlanUserFlows(record2) {
|
|
77647
|
+
const flows = record2.user_flows;
|
|
77522
77648
|
if (!Array.isArray(flows)) throw new Error("Recovery record requires user_flows array.");
|
|
77523
77649
|
return flows;
|
|
77524
77650
|
}
|
|
@@ -77526,62 +77652,62 @@ function requiredPlanGoal(flags) {
|
|
|
77526
77652
|
if (typeof flags.goal !== "string" || !flags.goal.trim()) throw new Error("Creating a plan requires --goal.");
|
|
77527
77653
|
return flags.goal;
|
|
77528
77654
|
}
|
|
77529
|
-
function recoveryPlanCreateOptions(
|
|
77655
|
+
function recoveryPlanCreateOptions(record2, linkContext) {
|
|
77530
77656
|
return {
|
|
77531
|
-
planId: recoveryString(
|
|
77532
|
-
title: recoveryString(
|
|
77533
|
-
goal: recoveryString(
|
|
77534
|
-
scopeIn: recoveryString(
|
|
77535
|
-
scopeOut: recoveryString(
|
|
77536
|
-
userFlows: recoveryPlanUserFlows(
|
|
77537
|
-
assumptions: recoveryString(
|
|
77538
|
-
openQuestions: recoveryString(
|
|
77539
|
-
constraints: recoveryString(
|
|
77540
|
-
decisions: recoveryString(
|
|
77541
|
-
risks: recoveryString(
|
|
77542
|
-
referencePatterns: recoveryString(
|
|
77543
|
-
context: recoveryString(
|
|
77544
|
-
status: recoveryString(
|
|
77545
|
-
slug: typeof
|
|
77657
|
+
planId: recoveryString(record2, "plan_id"),
|
|
77658
|
+
title: recoveryString(record2, "title"),
|
|
77659
|
+
goal: recoveryString(record2, "goal"),
|
|
77660
|
+
scopeIn: recoveryString(record2, "scope_in"),
|
|
77661
|
+
scopeOut: recoveryString(record2, "scope_out"),
|
|
77662
|
+
userFlows: recoveryPlanUserFlows(record2),
|
|
77663
|
+
assumptions: recoveryString(record2, "assumptions"),
|
|
77664
|
+
openQuestions: recoveryString(record2, "open_questions"),
|
|
77665
|
+
constraints: recoveryString(record2, "constraints"),
|
|
77666
|
+
decisions: recoveryString(record2, "decisions"),
|
|
77667
|
+
risks: recoveryString(record2, "risks"),
|
|
77668
|
+
referencePatterns: recoveryString(record2, "reference_patterns"),
|
|
77669
|
+
context: recoveryString(record2, "context"),
|
|
77670
|
+
status: recoveryString(record2, "status"),
|
|
77671
|
+
slug: typeof record2.slug === "string" ? record2.slug : void 0,
|
|
77546
77672
|
primaryChatId: linkContext.primaryChatId,
|
|
77547
77673
|
primaryChatKey: linkContext.primaryChatKey,
|
|
77548
77674
|
linkedProjectIds: linkContext.linkedProjectIds,
|
|
77549
77675
|
linkedProjectKeys: linkContext.linkedProjectKeys,
|
|
77550
|
-
plannerFocusId: typeof
|
|
77676
|
+
plannerFocusId: typeof record2.planner_focus_id === "string" ? record2.planner_focus_id : null
|
|
77551
77677
|
};
|
|
77552
77678
|
}
|
|
77553
|
-
function recoveryTaskCreateOptions(
|
|
77679
|
+
function recoveryTaskCreateOptions(record2, projectId) {
|
|
77554
77680
|
return {
|
|
77555
|
-
taskId: recoveryString(
|
|
77556
|
-
title: recoveryString(
|
|
77557
|
-
description: recoveryString(
|
|
77558
|
-
labels: recoveryStrings(
|
|
77559
|
-
status: recoveryString(
|
|
77560
|
-
assign: typeof
|
|
77561
|
-
chatId: typeof
|
|
77681
|
+
taskId: recoveryString(record2, "task_id"),
|
|
77682
|
+
title: recoveryString(record2, "title"),
|
|
77683
|
+
description: recoveryString(record2, "description"),
|
|
77684
|
+
labels: recoveryStrings(record2, "labels"),
|
|
77685
|
+
status: recoveryString(record2, "status"),
|
|
77686
|
+
assign: typeof record2.assignee_hash === "string" ? record2.assignee_hash : recoveryString(record2, "assignee_type"),
|
|
77687
|
+
chatId: typeof record2.primary_chat_id === "string" ? record2.primary_chat_id : null,
|
|
77562
77688
|
projectIds: [projectId],
|
|
77563
|
-
planId: typeof
|
|
77564
|
-
dueAt: typeof
|
|
77565
|
-
priority: typeof
|
|
77566
|
-
slug: typeof
|
|
77689
|
+
planId: typeof record2.plan_id === "string" ? record2.plan_id : null,
|
|
77690
|
+
dueAt: typeof record2.due_at === "number" ? record2.due_at : null,
|
|
77691
|
+
priority: typeof record2.priority === "number" ? record2.priority : null,
|
|
77692
|
+
slug: typeof record2.slug === "string" ? record2.slug : void 0
|
|
77567
77693
|
};
|
|
77568
77694
|
}
|
|
77569
|
-
async function recoveryAssumptionInput(plan, masterKey,
|
|
77570
|
-
const encrypt = (key) => encryptPlanAssumptionSources(plan, masterKey, typeof
|
|
77695
|
+
async function recoveryAssumptionInput(plan, masterKey, record2) {
|
|
77696
|
+
const encrypt = (key) => encryptPlanAssumptionSources(plan, masterKey, typeof record2[key] === "string" ? record2[key] : "");
|
|
77571
77697
|
return {
|
|
77572
|
-
assumption_id: recoveryString(
|
|
77698
|
+
assumption_id: recoveryString(record2, "assumption_id"),
|
|
77573
77699
|
encrypted_text: await encrypt("text"),
|
|
77574
|
-
category: typeof
|
|
77575
|
-
status: typeof
|
|
77576
|
-
required_before: typeof
|
|
77577
|
-
linked_sub_chat_id: typeof
|
|
77578
|
-
linked_task_id: typeof
|
|
77579
|
-
linked_criterion_ids: Array.isArray(
|
|
77700
|
+
category: typeof record2.category === "string" ? record2.category : void 0,
|
|
77701
|
+
status: typeof record2.status === "string" ? record2.status : void 0,
|
|
77702
|
+
required_before: typeof record2.required_before === "string" ? record2.required_before : void 0,
|
|
77703
|
+
linked_sub_chat_id: typeof record2.linked_sub_chat_id === "string" ? record2.linked_sub_chat_id : null,
|
|
77704
|
+
linked_task_id: typeof record2.linked_task_id === "string" ? record2.linked_task_id : null,
|
|
77705
|
+
linked_criterion_ids: Array.isArray(record2.linked_criterion_ids) ? record2.linked_criterion_ids : [],
|
|
77580
77706
|
encrypted_corrected_text: await encrypt("corrected_text"),
|
|
77581
77707
|
encrypted_evidence_summary: await encrypt("evidence_summary"),
|
|
77582
77708
|
encrypted_blocker_reason: await encrypt("blocker_reason"),
|
|
77583
77709
|
encrypted_waiver_reason: await encrypt("waiver_reason"),
|
|
77584
|
-
encrypted_sources: await encryptPlanAssumptionSources(plan, masterKey, JSON.stringify(
|
|
77710
|
+
encrypted_sources: await encryptPlanAssumptionSources(plan, masterKey, JSON.stringify(record2.sources)),
|
|
77585
77711
|
created_at: nowSeconds3(),
|
|
77586
77712
|
updated_at: nowSeconds3()
|
|
77587
77713
|
};
|
|
@@ -77733,7 +77859,7 @@ async function handleProjects(client, subcommand, rest, flags, redactor) {
|
|
|
77733
77859
|
const name = requiredStringFlag(rest[0] ?? flags.name, "project name");
|
|
77734
77860
|
const projectKey = randomBytes9(32);
|
|
77735
77861
|
const wrapping = await client.projectWrappingKey(context);
|
|
77736
|
-
const projectId =
|
|
77862
|
+
const projectId = randomUUID16();
|
|
77737
77863
|
const timestamp = nowSeconds3();
|
|
77738
77864
|
const slugMetadata = await buildEncryptedObjectSlugMetadata({
|
|
77739
77865
|
value: typeof flags.slug === "string" ? flags.slug : name,
|
|
@@ -77763,8 +77889,8 @@ async function handleProjects(client, subcommand, rest, flags, redactor) {
|
|
|
77763
77889
|
}] : []
|
|
77764
77890
|
};
|
|
77765
77891
|
const result = await client.createProject(payload, context);
|
|
77766
|
-
const
|
|
77767
|
-
printProjectOutput(await decryptProject(client,
|
|
77892
|
+
const record2 = { ...payload, ...result.project ?? {} };
|
|
77893
|
+
printProjectOutput(await decryptProject(client, record2, masterKey, context), flags);
|
|
77768
77894
|
return;
|
|
77769
77895
|
}
|
|
77770
77896
|
if (["update", "archive", "unarchive"].includes(subcommand)) {
|
|
@@ -77841,7 +77967,7 @@ async function handleProjects(client, subcommand, rest, flags, redactor) {
|
|
|
77841
77967
|
const proposal = isShortWorkspaceAsk(instruction) ? { name: instruction, description: "", icon: "folder", color: "default" } : extractRecord(await client.planProjectAsk({ instruction }), "proposed_project");
|
|
77842
77968
|
const projectKey = randomBytes9(32);
|
|
77843
77969
|
const timestamp = Math.floor(Date.now() / 1e3);
|
|
77844
|
-
const projectId =
|
|
77970
|
+
const projectId = randomUUID16();
|
|
77845
77971
|
const name = requiredString(proposal, "name", instruction);
|
|
77846
77972
|
const slugMetadata = await buildEncryptedObjectSlugMetadata({
|
|
77847
77973
|
value: typeof flags.slug === "string" ? flags.slug : name,
|
|
@@ -78740,7 +78866,7 @@ async function handleRemoteAccess(client, subcommand, rest, flags) {
|
|
|
78740
78866
|
const projects = await loadProjects(client, masterKey, hostingFlags, hostingContext);
|
|
78741
78867
|
const bindings = await resolveRemoteAccessBindings(client, masterKey, projects, candidateRoots, hostingFlags, hostingContext);
|
|
78742
78868
|
if (bindings.length === 0) throw new Error("No Project folders were approved for remote access.");
|
|
78743
|
-
const sourceSessionId =
|
|
78869
|
+
const sourceSessionId = randomUUID16();
|
|
78744
78870
|
const controller = new AbortController();
|
|
78745
78871
|
const stop = () => controller.abort();
|
|
78746
78872
|
process.once("SIGINT", stop);
|
|
@@ -78847,8 +78973,8 @@ async function resolveRemoteAccessBindings(client, masterKey, projects, candidat
|
|
|
78847
78973
|
const answer = (await promptLine2(`Create ${unresolved.length} missing Project${unresolved.length === 1 ? "" : "s"}? [y/N] `)).trim().toLowerCase();
|
|
78848
78974
|
if (answer !== "y" && answer !== "yes") throw new Error("Remote access Project creation cancelled.");
|
|
78849
78975
|
for (const rootPath of unresolved) {
|
|
78850
|
-
const project = await createEncryptedRemoteAccessProject(client, masterKey,
|
|
78851
|
-
resolved.push({ rootPath, project, sourceId:
|
|
78976
|
+
const project = await createEncryptedRemoteAccessProject(client, masterKey, basename5(rootPath), context);
|
|
78977
|
+
resolved.push({ rootPath, project, sourceId: randomUUID16() });
|
|
78852
78978
|
}
|
|
78853
78979
|
}
|
|
78854
78980
|
const bindings = [];
|
|
@@ -78859,7 +78985,7 @@ async function resolveRemoteAccessBindings(client, masterKey, projects, candidat
|
|
|
78859
78985
|
projectId: item.project.projectId,
|
|
78860
78986
|
rootPath: item.rootPath,
|
|
78861
78987
|
sourceType,
|
|
78862
|
-
displayName:
|
|
78988
|
+
displayName: basename5(item.rootPath)
|
|
78863
78989
|
});
|
|
78864
78990
|
const remoteSources = await client.listProjectSources(item.project.projectId, context);
|
|
78865
78991
|
const remoteSource = remoteSources.find((entry) => entry.source_id === source.sourceId);
|
|
@@ -78885,7 +79011,7 @@ async function resolveRemoteAccessBindings(client, masterKey, projects, candidat
|
|
|
78885
79011
|
}
|
|
78886
79012
|
async function createEncryptedRemoteAccessProject(client, masterKey, name, context) {
|
|
78887
79013
|
const projectKey = randomBytes9(32);
|
|
78888
|
-
const projectId =
|
|
79014
|
+
const projectId = randomUUID16();
|
|
78889
79015
|
const timestamp = Math.floor(Date.now() / 1e3);
|
|
78890
79016
|
const wrapping = await client.projectWrappingKey(context);
|
|
78891
79017
|
const payload = {
|
|
@@ -78983,11 +79109,11 @@ async function handleIdeaBucket(client, subcommand, rest, flags) {
|
|
|
78983
79109
|
return;
|
|
78984
79110
|
}
|
|
78985
79111
|
if (subcommand === "add") {
|
|
78986
|
-
const
|
|
78987
|
-
if (!
|
|
79112
|
+
const text2 = rest.join(" ").trim();
|
|
79113
|
+
if (!text2) throw new Error("Missing IdeaBucket text for add.");
|
|
78988
79114
|
const scheduledSendAt = typeof flags["scheduled-at"] === "string" ? parseUnixSecondsFlag(flags["scheduled-at"], "--scheduled-at") : void 0;
|
|
78989
79115
|
printJson2(await client.addIdeaBucketText({
|
|
78990
|
-
text,
|
|
79116
|
+
text: text2,
|
|
78991
79117
|
chatId: typeof flags.chat === "string" ? flags.chat : void 0,
|
|
78992
79118
|
bucketId: typeof flags.bucket === "string" ? flags.bucket : void 0,
|
|
78993
79119
|
scheduledSendAt,
|
|
@@ -79532,10 +79658,10 @@ Run 'openmates chats show ` + chatId + "' to check if suggestions have been save
|
|
|
79532
79658
|
input: process.stdin,
|
|
79533
79659
|
output: process.stdout
|
|
79534
79660
|
});
|
|
79535
|
-
const answer = await new Promise((
|
|
79661
|
+
const answer = await new Promise((resolve12) => {
|
|
79536
79662
|
iface.question(
|
|
79537
79663
|
`Delete ${resolved.length} chat(s)? This cannot be undone. [y/N] `,
|
|
79538
|
-
|
|
79664
|
+
resolve12
|
|
79539
79665
|
);
|
|
79540
79666
|
});
|
|
79541
79667
|
iface.close();
|
|
@@ -79663,19 +79789,19 @@ ${deleted}/${resolved.length} chat(s) deleted.`);
|
|
|
79663
79789
|
if (embed.type === "app_skill_use" && embed.appId === "videos" && (embed.skillId === "get_transcript" || embed.skillId === "get-transcript") && embed.content) {
|
|
79664
79790
|
const results = embed.content.results ?? embed.content.data ?? [];
|
|
79665
79791
|
if (Array.isArray(results) && results.length > 0) {
|
|
79666
|
-
let
|
|
79792
|
+
let text2 = "";
|
|
79667
79793
|
for (const r of results) {
|
|
79668
79794
|
const meta = r.metadata;
|
|
79669
|
-
if (meta?.title)
|
|
79795
|
+
if (meta?.title) text2 += `# ${meta.title}
|
|
79670
79796
|
|
|
79671
79797
|
`;
|
|
79672
|
-
if (r.url)
|
|
79798
|
+
if (r.url) text2 += `Source: ${r.url}
|
|
79673
79799
|
|
|
79674
79800
|
`;
|
|
79675
|
-
|
|
79801
|
+
text2 += String(
|
|
79676
79802
|
r.transcript ?? r.formatted_transcript ?? r.text ?? r.content ?? ""
|
|
79677
79803
|
);
|
|
79678
|
-
|
|
79804
|
+
text2 += "\n\n---\n\n";
|
|
79679
79805
|
}
|
|
79680
79806
|
let fname = `${eid.slice(0, 8)}_transcript.md`;
|
|
79681
79807
|
const firstMeta = results[0]?.metadata;
|
|
@@ -79685,7 +79811,7 @@ ${deleted}/${resolved.length} chat(s) deleted.`);
|
|
|
79685
79811
|
transcriptEmbeds.push({
|
|
79686
79812
|
embedId: eid,
|
|
79687
79813
|
filename: fname,
|
|
79688
|
-
content:
|
|
79814
|
+
content: text2
|
|
79689
79815
|
});
|
|
79690
79816
|
}
|
|
79691
79817
|
}
|
|
@@ -79701,18 +79827,18 @@ ${deleted}/${resolved.length} chat(s) deleted.`);
|
|
|
79701
79827
|
} catch {
|
|
79702
79828
|
}
|
|
79703
79829
|
}
|
|
79704
|
-
const { mkdir:
|
|
79830
|
+
const { mkdir: mkdir3, writeFile: writeFile2 } = await import("fs/promises");
|
|
79705
79831
|
const { join: join13 } = await import("path");
|
|
79706
79832
|
if (useZip) {
|
|
79707
79833
|
const tmpDir = join13(outputDir, `.${filenameBase}_tmp`);
|
|
79708
|
-
await
|
|
79834
|
+
await mkdir3(tmpDir, { recursive: true });
|
|
79709
79835
|
await writeFile2(join13(tmpDir, `${filenameBase}.yml`), yamlContent);
|
|
79710
79836
|
await writeFile2(join13(tmpDir, `${filenameBase}.md`), mdContent);
|
|
79711
79837
|
if (codeEmbeds.length > 0) {
|
|
79712
79838
|
for (const ce of codeEmbeds) {
|
|
79713
79839
|
const fpath = ce.filePath ?? ce.filename ?? `${ce.embedId.slice(0, 8)}.${getExtForLang(ce.language)}`;
|
|
79714
79840
|
const fullPath = join13(tmpDir, "code", fpath);
|
|
79715
|
-
await
|
|
79841
|
+
await mkdir3(fullPath.substring(0, fullPath.lastIndexOf("/")), {
|
|
79716
79842
|
recursive: true
|
|
79717
79843
|
});
|
|
79718
79844
|
await writeFile2(fullPath, ce.content);
|
|
@@ -79720,7 +79846,7 @@ ${deleted}/${resolved.length} chat(s) deleted.`);
|
|
|
79720
79846
|
}
|
|
79721
79847
|
if (transcriptEmbeds.length > 0) {
|
|
79722
79848
|
const tDir = join13(tmpDir, "transcripts");
|
|
79723
|
-
await
|
|
79849
|
+
await mkdir3(tDir, { recursive: true });
|
|
79724
79850
|
for (const te of transcriptEmbeds) {
|
|
79725
79851
|
await writeFile2(join13(tDir, te.filename), te.content);
|
|
79726
79852
|
}
|
|
@@ -79741,7 +79867,7 @@ ${deleted}/${resolved.length} chat(s) deleted.`);
|
|
|
79741
79867
|
}
|
|
79742
79868
|
} else {
|
|
79743
79869
|
const chatDir = join13(outputDir, filenameBase);
|
|
79744
|
-
await
|
|
79870
|
+
await mkdir3(chatDir, { recursive: true });
|
|
79745
79871
|
const written = [];
|
|
79746
79872
|
await writeFile2(join13(chatDir, `${filenameBase}.yml`), yamlContent);
|
|
79747
79873
|
written.push(`${filenameBase}.yml`);
|
|
@@ -79751,7 +79877,7 @@ ${deleted}/${resolved.length} chat(s) deleted.`);
|
|
|
79751
79877
|
for (const ce of codeEmbeds) {
|
|
79752
79878
|
const fpath = ce.filePath ?? ce.filename ?? `${ce.embedId.slice(0, 8)}.${getExtForLang(ce.language)}`;
|
|
79753
79879
|
const fullPath = join13(chatDir, "code", fpath);
|
|
79754
|
-
await
|
|
79880
|
+
await mkdir3(fullPath.substring(0, fullPath.lastIndexOf("/")), {
|
|
79755
79881
|
recursive: true
|
|
79756
79882
|
});
|
|
79757
79883
|
await writeFile2(fullPath, ce.content);
|
|
@@ -79760,7 +79886,7 @@ ${deleted}/${resolved.length} chat(s) deleted.`);
|
|
|
79760
79886
|
}
|
|
79761
79887
|
if (transcriptEmbeds.length > 0) {
|
|
79762
79888
|
const tDir = join13(chatDir, "transcripts");
|
|
79763
|
-
await
|
|
79889
|
+
await mkdir3(tDir, { recursive: true });
|
|
79764
79890
|
for (const te of transcriptEmbeds) {
|
|
79765
79891
|
await writeFile2(join13(tDir, te.filename), te.content);
|
|
79766
79892
|
written.push(`transcripts/${te.filename}`);
|
|
@@ -80044,29 +80170,29 @@ function getCliApiKeyDeviceIdentity() {
|
|
|
80044
80170
|
}
|
|
80045
80171
|
function extractAiAskContent(value) {
|
|
80046
80172
|
if (!value || typeof value !== "object") return "";
|
|
80047
|
-
const
|
|
80048
|
-
if (typeof
|
|
80049
|
-
if (typeof
|
|
80050
|
-
if (typeof
|
|
80051
|
-
const choices =
|
|
80173
|
+
const record2 = value;
|
|
80174
|
+
if (typeof record2.content === "string") return record2.content;
|
|
80175
|
+
if (typeof record2.response === "string") return record2.response;
|
|
80176
|
+
if (typeof record2.answer === "string") return record2.answer;
|
|
80177
|
+
const choices = record2.choices;
|
|
80052
80178
|
if (Array.isArray(choices)) {
|
|
80053
80179
|
const first = choices[0];
|
|
80054
80180
|
const message = first?.message;
|
|
80055
80181
|
if (typeof message?.content === "string") return message.content;
|
|
80056
80182
|
if (typeof first?.text === "string") return first.text;
|
|
80057
80183
|
}
|
|
80058
|
-
const data =
|
|
80184
|
+
const data = record2.data;
|
|
80059
80185
|
if (data && typeof data === "object") return extractAiAskContent(data);
|
|
80060
80186
|
return JSON.stringify(value);
|
|
80061
80187
|
}
|
|
80062
80188
|
function extractApiKeyChatModelName(value, depth = 0) {
|
|
80063
80189
|
if (!value || typeof value !== "object" || depth > 3) return null;
|
|
80064
|
-
const
|
|
80190
|
+
const record2 = value;
|
|
80065
80191
|
for (const key of ["model_name", "modelName", "model"]) {
|
|
80066
|
-
const field =
|
|
80192
|
+
const field = record2[key];
|
|
80067
80193
|
if (typeof field === "string" && field) return field;
|
|
80068
80194
|
}
|
|
80069
|
-
return extractApiKeyChatModelName(
|
|
80195
|
+
return extractApiKeyChatModelName(record2.data, depth + 1) ?? extractApiKeyChatModelName(record2.raw, depth + 1) ?? null;
|
|
80070
80196
|
}
|
|
80071
80197
|
function normalizeApiKeyChatResponse(response) {
|
|
80072
80198
|
const chatId = typeof response.chat_id === "string" ? response.chat_id : null;
|
|
@@ -80432,10 +80558,10 @@ async function handleWorkflows(client, subcommand, rest, flags, redactor) {
|
|
|
80432
80558
|
return;
|
|
80433
80559
|
}
|
|
80434
80560
|
if (subcommand === "input") {
|
|
80435
|
-
const
|
|
80436
|
-
if (!
|
|
80561
|
+
const text2 = typeof flags.text === "string" ? flags.text : rest.join(" ").trim();
|
|
80562
|
+
if (!text2) throw new Error('Missing workflow input text. Example: openmates workflows ask "alert me if it rains"');
|
|
80437
80563
|
const session = await client.startWorkflowInput({
|
|
80438
|
-
text,
|
|
80564
|
+
text: text2,
|
|
80439
80565
|
selectedWorkflowId: typeof flags["workflow-id"] === "string" ? flags["workflow-id"] : void 0,
|
|
80440
80566
|
selectedProjectId: typeof flags["project-id"] === "string" ? flags["project-id"] : void 0
|
|
80441
80567
|
});
|
|
@@ -80479,9 +80605,9 @@ async function handleWorkflows(client, subcommand, rest, flags, redactor) {
|
|
|
80479
80605
|
}
|
|
80480
80606
|
if (subcommand === "input-follow-up") {
|
|
80481
80607
|
const sessionId = rest[0];
|
|
80482
|
-
const
|
|
80483
|
-
if (!sessionId || !
|
|
80484
|
-
const session = await client.followUpWorkflowInput(sessionId,
|
|
80608
|
+
const text2 = typeof flags.text === "string" ? flags.text : rest.slice(1).join(" ").trim();
|
|
80609
|
+
if (!sessionId || !text2) throw new Error('Missing session ID or text. Example: openmates workflows input-follow-up <session-id> "make it weekdays only"');
|
|
80610
|
+
const session = await client.followUpWorkflowInput(sessionId, text2);
|
|
80485
80611
|
if (flags.json === true) {
|
|
80486
80612
|
printJson2(session);
|
|
80487
80613
|
} else {
|
|
@@ -80824,7 +80950,7 @@ function buildImagesAiDetectionSummary(uploadResult, filePath) {
|
|
|
80824
80950
|
const classification = classifyImagesAiDetection(score);
|
|
80825
80951
|
return {
|
|
80826
80952
|
file: filePath,
|
|
80827
|
-
filename: uploadResult.filename ||
|
|
80953
|
+
filename: uploadResult.filename || basename5(filePath),
|
|
80828
80954
|
content_type: uploadResult.content_type,
|
|
80829
80955
|
embed_id: uploadResult.embed_id,
|
|
80830
80956
|
deduplicated: uploadResult.deduplicated,
|
|
@@ -80862,6 +80988,7 @@ async function handleGeneratedAppSkillCommand(client, command, positionals, flag
|
|
|
80862
80988
|
return;
|
|
80863
80989
|
}
|
|
80864
80990
|
const inputData = buildGeneratedAppSkillInput(command, positionals, flags);
|
|
80991
|
+
const downloadOptions = generatedFileOptions(flags, inputData);
|
|
80865
80992
|
try {
|
|
80866
80993
|
const result = await client.runSkill({
|
|
80867
80994
|
app: command.app_id,
|
|
@@ -80870,10 +80997,19 @@ async function handleGeneratedAppSkillCommand(client, command, positionals, flag
|
|
|
80870
80997
|
apiKey,
|
|
80871
80998
|
promptInjectionProtection: flags["disable-prompt-injection-protection"] === true ? false : void 0
|
|
80872
80999
|
});
|
|
81000
|
+
const localFiles = await downloadGeneratedFiles(result, downloadOptions, async (url) => {
|
|
81001
|
+
if (url.startsWith("/")) {
|
|
81002
|
+
const raw = await client.getRaw(url, apiKey);
|
|
81003
|
+
return new Response(Buffer.from(raw.data));
|
|
81004
|
+
}
|
|
81005
|
+
return fetchGeneratedFile(url);
|
|
81006
|
+
});
|
|
80873
81007
|
if (flags.json === true) {
|
|
80874
|
-
printJson2(result);
|
|
81008
|
+
printJson2(localFiles.length ? { ...result, local_files: localFiles } : result);
|
|
80875
81009
|
} else {
|
|
80876
|
-
|
|
81010
|
+
if (localFiles.length) header(`${capitalise(command.app_id)} \u203A ${capitalise(command.skill_id)} \xB7 ${localFiles.length} file${localFiles.length === 1 ? "" : "s"} generated`);
|
|
81011
|
+
else printSkillResult(command.app_id, command.skill_id, result);
|
|
81012
|
+
for (const file of localFiles) console.log(`Saved ${file.path}`);
|
|
80877
81013
|
}
|
|
80878
81014
|
} catch (err) {
|
|
80879
81015
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -80911,7 +81047,7 @@ function buildGeneratedAppSkillValue(command, shape, positionals, flags) {
|
|
|
80911
81047
|
const value = {};
|
|
80912
81048
|
const consumedPositionals = applyPrimaryPositionals(command, shape, value, positionals);
|
|
80913
81049
|
for (const [name, schema] of Object.entries(shape.properties)) {
|
|
80914
|
-
if (value[name] !== void 0 ||
|
|
81050
|
+
if (value[name] !== void 0 || ["requests", "output", "output_dir", "filename", "no_download"].includes(name)) continue;
|
|
80915
81051
|
const raw = readFlag(flags, name);
|
|
80916
81052
|
if (raw === void 0) continue;
|
|
80917
81053
|
value[name] = coerceAppSkillFlagValue(name, raw, schema);
|
|
@@ -81102,6 +81238,9 @@ ${command.description}
|
|
|
81102
81238
|
const key = `${command.app_id}/${command.skill_id}`;
|
|
81103
81239
|
const examples = APP_SKILL_COMMAND_EXAMPLES[key] ?? [buildGeneratedAppSkillExample(command, shape)];
|
|
81104
81240
|
for (const example of examples) console.log(` ${example}`);
|
|
81241
|
+
console.log(`
|
|
81242
|
+
${GENERATED_FILE_HELP}`);
|
|
81243
|
+
if (command.app_id === "code" && command.skill_id === "run") console.log(" --source-filename <name> Name the inline source code file (default follows --language).");
|
|
81105
81244
|
console.log("\nInspect metadata:");
|
|
81106
81245
|
console.log(` openmates apps skill-info ${command.app_id} ${command.skill_id}`);
|
|
81107
81246
|
}
|
|
@@ -81551,7 +81690,7 @@ async function handleCodeRun(client, flags, apiKey) {
|
|
|
81551
81690
|
const requests = await buildCodeRunRequestsFromFlags({
|
|
81552
81691
|
code: typeof flags.code === "string" ? flags.code : void 0,
|
|
81553
81692
|
language: typeof flags.language === "string" ? flags.language : void 0,
|
|
81554
|
-
filename: typeof flags
|
|
81693
|
+
filename: typeof flags["source-filename"] === "string" ? flags["source-filename"] : void 0,
|
|
81555
81694
|
entry: typeof flags.entry === "string" ? flags.entry : void 0,
|
|
81556
81695
|
file: typeof flags.file === "string" ? flags.file : void 0,
|
|
81557
81696
|
dir: typeof flags.dir === "string" ? flags.dir : void 0,
|
|
@@ -81570,6 +81709,7 @@ async function handleCodeRun(client, flags, apiKey) {
|
|
|
81570
81709
|
`);
|
|
81571
81710
|
}
|
|
81572
81711
|
}
|
|
81712
|
+
const downloadOptions = generatedFileOptions(flags, { requests });
|
|
81573
81713
|
const response = await client.runSkill({
|
|
81574
81714
|
app: "code",
|
|
81575
81715
|
skill: "run",
|
|
@@ -81607,11 +81747,13 @@ async function handleCodeRun(client, flags, apiKey) {
|
|
|
81607
81747
|
} else {
|
|
81608
81748
|
finalStatus = await pollCodeRunStatus(client, result.status_path, apiKey, flags.json === true);
|
|
81609
81749
|
}
|
|
81750
|
+
const localFiles = finalStatus.status === "finished" && finalStatus.exit_code === 0 ? await downloadGeneratedFiles(finalStatus, downloadOptions) : [];
|
|
81610
81751
|
if (flags.json === true) {
|
|
81611
|
-
printJson2({ ...result, final: finalStatus });
|
|
81752
|
+
printJson2({ ...result, final: finalStatus, ...localFiles.length ? { local_files: localFiles } : {} });
|
|
81612
81753
|
} else {
|
|
81613
81754
|
const finalOutput = formatCodeRunFinalStatusOutput(finalStatus, { includeOutput: !usedStream });
|
|
81614
81755
|
if (finalOutput) process.stdout.write(finalOutput);
|
|
81756
|
+
for (const file of localFiles) console.log(`Saved ${file.path}`);
|
|
81615
81757
|
}
|
|
81616
81758
|
const finalExitCode = typeof finalStatus.exit_code === "number" ? finalStatus.exit_code : null;
|
|
81617
81759
|
const finalState = typeof finalStatus.status === "string" ? finalStatus.status : "unknown";
|
|
@@ -81620,7 +81762,7 @@ async function handleCodeRun(client, flags, apiKey) {
|
|
|
81620
81762
|
}
|
|
81621
81763
|
}
|
|
81622
81764
|
async function streamCodeRunToTerminal(url, jsonMode) {
|
|
81623
|
-
return await new Promise((
|
|
81765
|
+
return await new Promise((resolve12, reject) => {
|
|
81624
81766
|
const ws = new WebSocket3(url);
|
|
81625
81767
|
let lastStatus = {};
|
|
81626
81768
|
ws.on("message", (data) => {
|
|
@@ -81629,17 +81771,17 @@ async function streamCodeRunToTerminal(url, jsonMode) {
|
|
|
81629
81771
|
const payload = message.payload ?? {};
|
|
81630
81772
|
if (message.type === "code_run_event") {
|
|
81631
81773
|
const kind = String(payload.kind ?? "status");
|
|
81632
|
-
const
|
|
81774
|
+
const text2 = String(payload.text ?? "");
|
|
81633
81775
|
if (!jsonMode) {
|
|
81634
|
-
if (kind === "stdout") process.stdout.write(
|
|
81635
|
-
else process.stderr.write(
|
|
81776
|
+
if (kind === "stdout") process.stdout.write(text2);
|
|
81777
|
+
else process.stderr.write(text2);
|
|
81636
81778
|
}
|
|
81637
81779
|
} else if (message.type === "code_run_update") {
|
|
81638
81780
|
lastStatus = { ...lastStatus, ...payload };
|
|
81639
81781
|
const status = String(payload.status ?? "");
|
|
81640
81782
|
if (["finished", "failed", "timeout", "cancelled"].includes(status)) {
|
|
81641
81783
|
ws.close();
|
|
81642
|
-
|
|
81784
|
+
resolve12(lastStatus);
|
|
81643
81785
|
}
|
|
81644
81786
|
}
|
|
81645
81787
|
} catch (err) {
|
|
@@ -81649,7 +81791,7 @@ async function streamCodeRunToTerminal(url, jsonMode) {
|
|
|
81649
81791
|
});
|
|
81650
81792
|
ws.on("error", () => reject(new Error("Code Run stream failed.")));
|
|
81651
81793
|
ws.on("close", () => {
|
|
81652
|
-
if (Object.keys(lastStatus).length > 0)
|
|
81794
|
+
if (Object.keys(lastStatus).length > 0) resolve12(lastStatus);
|
|
81653
81795
|
});
|
|
81654
81796
|
});
|
|
81655
81797
|
}
|
|
@@ -81660,7 +81802,7 @@ async function pollCodeRunStatus(client, statusPath, apiKey, jsonMode) {
|
|
|
81660
81802
|
if (!jsonMode && value) process.stderr.write(`Code Run status: ${value}
|
|
81661
81803
|
`);
|
|
81662
81804
|
if (["finished", "failed", "timeout", "cancelled"].includes(value)) return status;
|
|
81663
|
-
await new Promise((
|
|
81805
|
+
await new Promise((resolve12) => setTimeout(resolve12, 1e3));
|
|
81664
81806
|
}
|
|
81665
81807
|
}
|
|
81666
81808
|
async function suggestAppOrSkill(client, app, skill, apiKey) {
|
|
@@ -81942,7 +82084,7 @@ async function waitForApplicationPreview(client, started, flags) {
|
|
|
81942
82084
|
while (Date.now() < deadline) {
|
|
81943
82085
|
const status = String(current.status ?? "");
|
|
81944
82086
|
if (["running", "failed", "timeout", "cancelled", "stopped"].includes(status)) return current;
|
|
81945
|
-
await new Promise((
|
|
82087
|
+
await new Promise((resolve12) => setTimeout(resolve12, 1e3));
|
|
81946
82088
|
current = await client.getApplicationPreviewStatus(started.session_id);
|
|
81947
82089
|
}
|
|
81948
82090
|
throw new Error(`Application preview did not reach a terminal or running state within ${timeoutSeconds}s`);
|
|
@@ -82139,12 +82281,12 @@ async function parseAccountImportFile(parserFormat, file, flags = {}) {
|
|
|
82139
82281
|
const selectedSource = requestedSource;
|
|
82140
82282
|
if (parserFormat === "generic") {
|
|
82141
82283
|
if (selectedSource !== "gemini" && selectedSource !== "other") throw new Error("Generic account import requires --source gemini or --source other.");
|
|
82142
|
-
return parseGenericImportBuffer(payload,
|
|
82284
|
+
return parseGenericImportBuffer(payload, basename5(file), selectedSource);
|
|
82143
82285
|
}
|
|
82144
|
-
if (parserFormat === "claude") return parseClaudeImportBuffer(payload,
|
|
82145
|
-
if (parserFormat === "chatgpt") return parseChatGPTImportBuffer(payload,
|
|
82146
|
-
if (parserFormat === "opencode") return parseOpenCodeImportBuffer(payload,
|
|
82147
|
-
return parseOpenMatesImportBuffer(payload,
|
|
82286
|
+
if (parserFormat === "claude") return parseClaudeImportBuffer(payload, basename5(file), selectedSource);
|
|
82287
|
+
if (parserFormat === "chatgpt") return parseChatGPTImportBuffer(payload, basename5(file), selectedSource);
|
|
82288
|
+
if (parserFormat === "opencode") return parseOpenCodeImportBuffer(payload, basename5(file), selectedSource);
|
|
82289
|
+
return parseOpenMatesImportBuffer(payload, basename5(file), typeof flags.password === "string" ? flags.password : void 0, selectedSource);
|
|
82148
82290
|
}
|
|
82149
82291
|
async function runAccountImport(client, parserFormat, file, flags) {
|
|
82150
82292
|
if (parserFormat === "generic" && typeof flags.source !== "string") throw new Error("Generic account import requires --source gemini or --source other.");
|
|
@@ -82183,7 +82325,7 @@ async function runAccountImport(client, parserFormat, file, flags) {
|
|
|
82183
82325
|
if (flags.yes !== true) {
|
|
82184
82326
|
await confirmOrExit(`Import ${selectedCount} chat(s) into new encrypted OpenMates chats? [y/N] `);
|
|
82185
82327
|
}
|
|
82186
|
-
const importId = typeof preview.import_id === "string" ? preview.import_id :
|
|
82328
|
+
const importId = typeof preview.import_id === "string" ? preview.import_id : randomUUID16();
|
|
82187
82329
|
const selectedChats = parsed.chats.slice(0, selectedCount);
|
|
82188
82330
|
const selectedFingerprints = selectedChats.map((chat) => chat.source_fingerprint);
|
|
82189
82331
|
const confirmation = await client.confirmAccountImport(importId, selectedFingerprints);
|
|
@@ -82513,12 +82655,12 @@ function parseYamlScalar(value) {
|
|
|
82513
82655
|
return trimmed;
|
|
82514
82656
|
}
|
|
82515
82657
|
async function saveDownloadedDocument(document, output) {
|
|
82516
|
-
const { mkdir:
|
|
82517
|
-
const { join: join13, basename:
|
|
82658
|
+
const { mkdir: mkdir3, writeFile: writeFile2 } = await import("fs/promises");
|
|
82659
|
+
const { join: join13, basename: basename6, dirname: dirname12 } = await import("path");
|
|
82518
82660
|
const target = typeof output === "string" ? output : ".";
|
|
82519
|
-
const filename =
|
|
82661
|
+
const filename = basename6(document.filename || "document.pdf");
|
|
82520
82662
|
const filePath = target.endsWith(".pdf") ? target : join13(target, filename);
|
|
82521
|
-
await
|
|
82663
|
+
await mkdir3(dirname12(filePath), { recursive: true });
|
|
82522
82664
|
await writeFile2(filePath, document.data);
|
|
82523
82665
|
return filePath;
|
|
82524
82666
|
}
|
|
@@ -82546,7 +82688,7 @@ function printMateInfo(mateId, json) {
|
|
|
82546
82688
|
async function confirmOrExit(question) {
|
|
82547
82689
|
const rl = await import("readline");
|
|
82548
82690
|
const iface = rl.createInterface({ input: process.stdin, output: process.stdout });
|
|
82549
|
-
const answer = await new Promise((
|
|
82691
|
+
const answer = await new Promise((resolve12) => iface.question(question, resolve12));
|
|
82550
82692
|
iface.close();
|
|
82551
82693
|
if (answer.trim().toLowerCase() !== "y") {
|
|
82552
82694
|
console.log("Aborted.");
|
|
@@ -82556,7 +82698,7 @@ async function confirmOrExit(question) {
|
|
|
82556
82698
|
async function promptLine2(question) {
|
|
82557
82699
|
const rl = await import("readline");
|
|
82558
82700
|
const iface = rl.createInterface({ input: process.stdin, output: process.stdout });
|
|
82559
|
-
const answer = await new Promise((
|
|
82701
|
+
const answer = await new Promise((resolve12) => iface.question(question, resolve12));
|
|
82560
82702
|
iface.close();
|
|
82561
82703
|
return answer.trim();
|
|
82562
82704
|
}
|
|
@@ -82564,7 +82706,7 @@ async function promptSecret(question) {
|
|
|
82564
82706
|
if (!process.stdin.isTTY) {
|
|
82565
82707
|
return promptLine2(question);
|
|
82566
82708
|
}
|
|
82567
|
-
return new Promise((
|
|
82709
|
+
return new Promise((resolve12) => {
|
|
82568
82710
|
const stdin4 = process.stdin;
|
|
82569
82711
|
const wasRaw = stdin4.isRaw;
|
|
82570
82712
|
let value = "";
|
|
@@ -82577,7 +82719,7 @@ async function promptSecret(question) {
|
|
|
82577
82719
|
stdin4.off("data", onData);
|
|
82578
82720
|
stdin4.setRawMode(wasRaw);
|
|
82579
82721
|
process.stdout.write("\n");
|
|
82580
|
-
|
|
82722
|
+
resolve12(value);
|
|
82581
82723
|
return;
|
|
82582
82724
|
}
|
|
82583
82725
|
if (char === "") {
|
|
@@ -82677,8 +82819,8 @@ async function handleFinance(client, subcommand, _rest, flags) {
|
|
|
82677
82819
|
refresh_token_envelope: connectedAccount.refreshTokenBundle
|
|
82678
82820
|
}
|
|
82679
82821
|
] : [],
|
|
82680
|
-
chatId: `cli-finance-${
|
|
82681
|
-
messageId: `cli-finance-message-${
|
|
82822
|
+
chatId: `cli-finance-${randomUUID16()}`,
|
|
82823
|
+
messageId: `cli-finance-message-${randomUUID16()}`,
|
|
82682
82824
|
apiKey: resolveApiKey(flags) ?? void 0,
|
|
82683
82825
|
promptInjectionProtection: false
|
|
82684
82826
|
});
|
|
@@ -82690,7 +82832,7 @@ async function handleFinance(client, subcommand, _rest, flags) {
|
|
|
82690
82832
|
}
|
|
82691
82833
|
function readFinanceCsvStatements(flags) {
|
|
82692
82834
|
const paths = parseCsvFlag(flags.csv) ?? [];
|
|
82693
|
-
return paths.map((filePath) => ({ filename:
|
|
82835
|
+
return paths.map((filePath) => ({ filename: basename5(filePath), content: readFileSync13(filePath, "utf8") }));
|
|
82694
82836
|
}
|
|
82695
82837
|
function buildFinanceCheckAccountsInput(flags, csvStatements, connectedAccount) {
|
|
82696
82838
|
const input = {
|
|
@@ -82984,10 +83126,10 @@ async function promptPlainText(question) {
|
|
|
82984
83126
|
}
|
|
82985
83127
|
}
|
|
82986
83128
|
async function writeSecretFile(filePath, content, force = false) {
|
|
82987
|
-
const { mkdir:
|
|
82988
|
-
const { dirname:
|
|
83129
|
+
const { mkdir: mkdir3, writeFile: writeFile2, stat: stat3 } = await import("fs/promises");
|
|
83130
|
+
const { dirname: dirname12 } = await import("path");
|
|
82989
83131
|
try {
|
|
82990
|
-
await
|
|
83132
|
+
await stat3(filePath);
|
|
82991
83133
|
if (!force) throw new Error(`${filePath} already exists. Use --force to overwrite.`);
|
|
82992
83134
|
} catch (error) {
|
|
82993
83135
|
if (error instanceof Error && "code" in error && error.code !== "ENOENT") {
|
|
@@ -82995,7 +83137,7 @@ async function writeSecretFile(filePath, content, force = false) {
|
|
|
82995
83137
|
}
|
|
82996
83138
|
if (error instanceof Error && !("code" in error)) throw error;
|
|
82997
83139
|
}
|
|
82998
|
-
await
|
|
83140
|
+
await mkdir3(dirname12(filePath), { recursive: true });
|
|
82999
83141
|
await writeFile2(filePath, content, { mode: 384 });
|
|
83000
83142
|
return filePath;
|
|
83001
83143
|
}
|
|
@@ -84083,8 +84225,8 @@ function resolveApiKey(flags) {
|
|
|
84083
84225
|
function printJson2(value) {
|
|
84084
84226
|
console.log(JSON.stringify(value, null, 2));
|
|
84085
84227
|
}
|
|
84086
|
-
function header(
|
|
84087
|
-
process.stdout.write(`\x1B[1m${
|
|
84228
|
+
function header(text2) {
|
|
84229
|
+
process.stdout.write(`\x1B[1m${text2}\x1B[0m
|
|
84088
84230
|
`);
|
|
84089
84231
|
}
|
|
84090
84232
|
function kv(key, value, keyWidth = 16) {
|
|
@@ -84755,15 +84897,15 @@ async function acceptChatTaskProposals(client, chatId, proposals, fallbackText)
|
|
|
84755
84897
|
}
|
|
84756
84898
|
return accepted;
|
|
84757
84899
|
}
|
|
84758
|
-
function buildTaskProposalFallbackText(
|
|
84900
|
+
function buildTaskProposalFallbackText(text2) {
|
|
84759
84901
|
const seen = /* @__PURE__ */ new Set();
|
|
84760
|
-
const bulletLines =
|
|
84902
|
+
const bulletLines = text2.split("\n").map((line) => line.trim()).filter((line) => /^[-*•]\s+/.test(line)).map((line) => line.replace(/^([-*•]\s*)\[[ xX]\]\s*/, "$1")).filter((line) => {
|
|
84761
84903
|
const key = line.replace(/^[-*•]\s+/, "").trim().toLowerCase();
|
|
84762
84904
|
if (seen.has(key)) return false;
|
|
84763
84905
|
seen.add(key);
|
|
84764
84906
|
return true;
|
|
84765
84907
|
});
|
|
84766
|
-
return bulletLines.length > 0 ? bulletLines.join("\n") :
|
|
84908
|
+
return bulletLines.length > 0 ? bulletLines.join("\n") : text2;
|
|
84767
84909
|
}
|
|
84768
84910
|
function printIncognitoNoHistoryNotice(json) {
|
|
84769
84911
|
const message = "Incognito chats are not stored. There is no incognito history to show or clear.";
|
|
@@ -84781,8 +84923,8 @@ function parseMessageSegments(content) {
|
|
|
84781
84923
|
let m;
|
|
84782
84924
|
while ((m = pattern.exec(content)) !== null) {
|
|
84783
84925
|
if (m.index > last) {
|
|
84784
|
-
const
|
|
84785
|
-
segments.push({ type: "text", value:
|
|
84926
|
+
const text2 = content.slice(last, m.index);
|
|
84927
|
+
segments.push({ type: "text", value: text2, rawLength: text2.length });
|
|
84786
84928
|
}
|
|
84787
84929
|
const blockRawLength = m[0].length;
|
|
84788
84930
|
try {
|
|
@@ -84801,8 +84943,8 @@ function parseMessageSegments(content) {
|
|
|
84801
84943
|
last = m.index + m[0].length;
|
|
84802
84944
|
}
|
|
84803
84945
|
if (last < content.length) {
|
|
84804
|
-
const
|
|
84805
|
-
segments.push({ type: "text", value:
|
|
84946
|
+
const text2 = content.slice(last);
|
|
84947
|
+
segments.push({ type: "text", value: text2, rawLength: text2.length });
|
|
84806
84948
|
}
|
|
84807
84949
|
return segments;
|
|
84808
84950
|
}
|
|
@@ -84829,8 +84971,8 @@ function renderEmbedFromMeta(embedId, meta) {
|
|
|
84829
84971
|
process.stdout.write(`\x1B[2m\u2514\u2500 openmates embeds show ${shortId}\x1B[0m
|
|
84830
84972
|
`);
|
|
84831
84973
|
}
|
|
84832
|
-
async function renderMessageText(
|
|
84833
|
-
const lines =
|
|
84974
|
+
async function renderMessageText(text2, embedRefIndex, client) {
|
|
84975
|
+
const lines = text2.split("\n");
|
|
84834
84976
|
const outputLines = [];
|
|
84835
84977
|
for (const line of lines) {
|
|
84836
84978
|
const blockMatch = line.match(/^\s*\[!?\]\(embed:([^)]+)\)\s*$/);
|
|
@@ -85254,8 +85396,8 @@ No example chats are linked to ${label} yet.`);
|
|
|
85254
85396
|
console.log(`All examples: openmates apps examples ${appId}${skillId ? ` ${skillId}` : ""}`);
|
|
85255
85397
|
}
|
|
85256
85398
|
}
|
|
85257
|
-
function wrapText(
|
|
85258
|
-
const words =
|
|
85399
|
+
function wrapText(text2, width) {
|
|
85400
|
+
const words = text2.split(" ");
|
|
85259
85401
|
const lines = [];
|
|
85260
85402
|
let current = "";
|
|
85261
85403
|
for (const w of words) {
|
|
@@ -85458,8 +85600,8 @@ function printSkillResultItem(item, num, total) {
|
|
|
85458
85600
|
if (amenities.length > 0) kv("amenities", amenities.join(", "), 14);
|
|
85459
85601
|
const reviews = item.reviews;
|
|
85460
85602
|
if (reviews !== void 0 && reviews !== null) kv("reviews", String(reviews), 14);
|
|
85461
|
-
const
|
|
85462
|
-
if (
|
|
85603
|
+
const link2 = str2(item.link) ?? str2(item.url);
|
|
85604
|
+
if (link2) kv("url", link2, 14);
|
|
85463
85605
|
console.log("");
|
|
85464
85606
|
return;
|
|
85465
85607
|
}
|
|
@@ -86751,7 +86893,7 @@ Examples:
|
|
|
86751
86893
|
openmates apps math calculate "sqrt(144)" --mode numeric --json
|
|
86752
86894
|
openmates apps code get_docs --library React --question "How do I use useState?" --json
|
|
86753
86895
|
openmates apps examples travel search_connections
|
|
86754
|
-
openmates apps code run --language python --filename hello.py --code 'print("Hello from CLI")'
|
|
86896
|
+
openmates apps code run --language python --source-filename hello.py --code 'print("Hello from CLI")'
|
|
86755
86897
|
openmates apps images detect-ai --file ./image.png --json
|
|
86756
86898
|
openmates apps models3d search --query benchy --count 2 --providers Printables --json
|
|
86757
86899
|
openmates apps design search_icons --query home --count 12 --json
|
|
@@ -86982,18 +87124,18 @@ async function handleDocs(client, subcommand, rest, flags) {
|
|
|
86982
87124
|
return;
|
|
86983
87125
|
}
|
|
86984
87126
|
if (subcommand === "download") {
|
|
86985
|
-
const { writeFile: writeFile2, mkdir:
|
|
86986
|
-
const { join: join13, dirname:
|
|
87127
|
+
const { writeFile: writeFile2, mkdir: mkdir3 } = await import("fs/promises");
|
|
87128
|
+
const { join: join13, dirname: dirname12 } = await import("path");
|
|
86987
87129
|
if (flags.all === true) {
|
|
86988
87130
|
const outputDir = typeof flags.output === "string" ? flags.output : "./openmates-docs";
|
|
86989
87131
|
const tree = await client.listDocs();
|
|
86990
87132
|
const slugs = collectSlugs(tree);
|
|
86991
|
-
await
|
|
87133
|
+
await mkdir3(outputDir, { recursive: true });
|
|
86992
87134
|
let count = 0;
|
|
86993
87135
|
for (const slug2 of slugs) {
|
|
86994
87136
|
const content2 = await client.getDoc(slug2);
|
|
86995
87137
|
const filePath = join13(outputDir, `${slug2}.md`);
|
|
86996
|
-
await
|
|
87138
|
+
await mkdir3(dirname12(filePath), { recursive: true });
|
|
86997
87139
|
await writeFile2(filePath, content2, "utf-8");
|
|
86998
87140
|
count++;
|
|
86999
87141
|
process.stderr.write(`\r Downloaded ${count}/${slugs.length}`);
|
|
@@ -87066,7 +87208,7 @@ function isCliEntrypoint() {
|
|
|
87066
87208
|
try {
|
|
87067
87209
|
const invokedPath = realpathSync2(entrypoint);
|
|
87068
87210
|
const modulePath = realpathSync2(fileURLToPath3(import.meta.url));
|
|
87069
|
-
return invokedPath === modulePath ||
|
|
87211
|
+
return invokedPath === modulePath || basename5(invokedPath) === "cli.js" && dirname11(invokedPath) === dirname11(modulePath);
|
|
87070
87212
|
} catch {
|
|
87071
87213
|
return false;
|
|
87072
87214
|
}
|