openmates 0.27.0-alpha.24 → 0.27.0-alpha.25
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-U5L7EZHI.js → chunk-D476Y5AI.js} +581 -309
- package/dist/{cli-C2G3DpGo.d.ts → cli-CKbfUQGp.d.ts} +25 -3
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +1 -1
- package/dist/index.d.ts +8 -2
- package/dist/index.js +1 -1
- package/dist/ruleDocuments-6VMP2CV5.js +91 -0
- package/fixtures/privacy-runtime/linux-arm64/libggml-base.so +0 -0
- package/fixtures/privacy-runtime/linux-arm64/libggml-base.so.0 +0 -0
- package/fixtures/privacy-runtime/linux-arm64/libggml-base.so.0.15.1 +0 -0
- package/fixtures/privacy-runtime/linux-arm64/libggml-cpu.so +0 -0
- package/fixtures/privacy-runtime/linux-arm64/libggml-cpu.so.0 +0 -0
- package/fixtures/privacy-runtime/linux-arm64/libggml-cpu.so.0.15.1 +0 -0
- package/fixtures/privacy-runtime/linux-arm64/libggml.so +0 -0
- package/fixtures/privacy-runtime/linux-arm64/libggml.so.0 +0 -0
- package/fixtures/privacy-runtime/linux-arm64/libggml.so.0.15.1 +0 -0
- package/fixtures/privacy-runtime/linux-arm64/manifest.json +9 -9
- package/package.json +1 -1
|
@@ -194,8 +194,8 @@ import { chmodSync, closeSync, fsyncSync, mkdirSync, openSync, readFileSync, ren
|
|
|
194
194
|
import { join } from "path";
|
|
195
195
|
var digest = (value) => createHash("sha256").update(value).digest("hex");
|
|
196
196
|
var shortenTaskText = (value, length) => {
|
|
197
|
-
const
|
|
198
|
-
return
|
|
197
|
+
const text7 = value.replace(/\s+/g, " ").trim();
|
|
198
|
+
return text7.length <= length ? text7 : `${text7.slice(0, length - 1)}\u2026`;
|
|
199
199
|
};
|
|
200
200
|
function atomicPrivateFile(path2, content) {
|
|
201
201
|
const temporary = `${path2}.${randomUUID()}.tmp`;
|
|
@@ -403,7 +403,7 @@ async function lockTaskDeliveryRecord(directory, id) {
|
|
|
403
403
|
}
|
|
404
404
|
|
|
405
405
|
// src/taskMutationDelivery.ts
|
|
406
|
-
var digest2 = (
|
|
406
|
+
var digest2 = (text7) => createHash3("sha256").update(text7).digest("hex");
|
|
407
407
|
var stable = (value) => JSON.stringify(value, (_key, item) => item && !Array.isArray(item) && typeof item === "object" ? Object.fromEntries(Object.entries(item).sort(([a], [b]) => a.localeCompare(b))) : item);
|
|
408
408
|
function reconcileMutation(mutation, current) {
|
|
409
409
|
if (mutation.kind === "delete") {
|
|
@@ -766,10 +766,10 @@ function assertCodexClaimCaller(threadId, currentThread = process.env.CODEX_THRE
|
|
|
766
766
|
}
|
|
767
767
|
|
|
768
768
|
// ../secret-scanner/src/identifierRanges.ts
|
|
769
|
-
function codingIdentifierRanges(
|
|
769
|
+
function codingIdentifierRanges(text7) {
|
|
770
770
|
const ranges = [];
|
|
771
771
|
const identifiers2 = /\b[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}\b|\b[\da-f]{40,64}\b|\[[A-Z][A-Z\d_]*\]/gi;
|
|
772
|
-
for (const match of Array.from(
|
|
772
|
+
for (const match of Array.from(text7.matchAll(identifiers2))) {
|
|
773
773
|
ranges.push({ start: match.index, end: match.index + match[0].length });
|
|
774
774
|
}
|
|
775
775
|
return ranges;
|
|
@@ -1247,16 +1247,16 @@ var PII_TYPE_TO_CATEGORY = {
|
|
|
1247
1247
|
USER_AT_HOSTNAME: "user_at_hostname",
|
|
1248
1248
|
MAC_ADDRESS: "mac_addresses"
|
|
1249
1249
|
};
|
|
1250
|
-
function detectPII(
|
|
1250
|
+
function detectPII(text7, excludedIdsOrOptions = /* @__PURE__ */ new Set()) {
|
|
1251
1251
|
const options = excludedIdsOrOptions instanceof Set ? { excludedIds: excludedIdsOrOptions } : excludedIdsOrOptions;
|
|
1252
1252
|
const excludedIds = options.excludedIds ?? /* @__PURE__ */ new Set();
|
|
1253
1253
|
const disabledCategories = options.disabledCategories ?? /* @__PURE__ */ new Set();
|
|
1254
1254
|
const personalEntries = options.personalDataEntries ?? [];
|
|
1255
|
-
if (!
|
|
1255
|
+
if (!text7 || text7.length < MIN_PII_TEXT_LENGTH && personalEntries.length === 0)
|
|
1256
1256
|
return [];
|
|
1257
1257
|
const matches2 = [];
|
|
1258
1258
|
const coveredRanges = [];
|
|
1259
|
-
const identifierRanges = codingIdentifierRanges(
|
|
1259
|
+
const identifierRanges = codingIdentifierRanges(text7);
|
|
1260
1260
|
const typeCounts = {};
|
|
1261
1261
|
const hasExclusions = excludedIds.size > 0;
|
|
1262
1262
|
const hasDisabledCategories = disabledCategories.size > 0;
|
|
@@ -1264,14 +1264,14 @@ function detectPII(text6, excludedIdsOrOptions = /* @__PURE__ */ new Set()) {
|
|
|
1264
1264
|
const urlExclusionZones = [];
|
|
1265
1265
|
URL_EXCLUSION_REGEX.lastIndex = 0;
|
|
1266
1266
|
let urlMatch;
|
|
1267
|
-
while ((urlMatch = URL_EXCLUSION_REGEX.exec(
|
|
1267
|
+
while ((urlMatch = URL_EXCLUSION_REGEX.exec(text7)) !== null) {
|
|
1268
1268
|
urlExclusionZones.push({
|
|
1269
1269
|
start: urlMatch.index,
|
|
1270
1270
|
end: urlMatch.index + urlMatch[0].length
|
|
1271
1271
|
});
|
|
1272
1272
|
}
|
|
1273
1273
|
const hasUrlExclusions = urlExclusionZones.length > 0;
|
|
1274
|
-
if (
|
|
1274
|
+
if (text7.length >= MIN_PII_TEXT_LENGTH) {
|
|
1275
1275
|
for (const pattern of PII_PATTERNS) {
|
|
1276
1276
|
if (hasDisabledCategories) {
|
|
1277
1277
|
const category = PII_TYPE_TO_CATEGORY[pattern.type];
|
|
@@ -1279,7 +1279,7 @@ function detectPII(text6, excludedIdsOrOptions = /* @__PURE__ */ new Set()) {
|
|
|
1279
1279
|
}
|
|
1280
1280
|
pattern.regex.lastIndex = 0;
|
|
1281
1281
|
let regexMatch;
|
|
1282
|
-
while ((regexMatch = pattern.regex.exec(
|
|
1282
|
+
while ((regexMatch = pattern.regex.exec(text7)) !== null) {
|
|
1283
1283
|
const matchText = regexMatch[0];
|
|
1284
1284
|
const startIndex = regexMatch.index;
|
|
1285
1285
|
const endIndex = startIndex + matchText.length;
|
|
@@ -1325,7 +1325,7 @@ function detectPII(text6, excludedIdsOrOptions = /* @__PURE__ */ new Set()) {
|
|
|
1325
1325
|
}
|
|
1326
1326
|
}
|
|
1327
1327
|
for (const searchText of textsToSearch) {
|
|
1328
|
-
const lowerText =
|
|
1328
|
+
const lowerText = text7.toLowerCase();
|
|
1329
1329
|
const lowerSearch = searchText.toLowerCase();
|
|
1330
1330
|
let searchFrom = 0;
|
|
1331
1331
|
while (searchFrom < lowerText.length) {
|
|
@@ -1337,7 +1337,7 @@ function detectPII(text6, excludedIdsOrOptions = /* @__PURE__ */ new Set()) {
|
|
|
1337
1337
|
(range) => startIndex >= range.start && startIndex < range.end || endIndex > range.start && endIndex <= range.end || startIndex <= range.start && endIndex >= range.end
|
|
1338
1338
|
);
|
|
1339
1339
|
if (!overlaps) {
|
|
1340
|
-
const matchText =
|
|
1340
|
+
const matchText = text7.substring(startIndex, endIndex);
|
|
1341
1341
|
const matchId = `pii-PERSONAL_DATA-${entry.id}-${startIndex}`;
|
|
1342
1342
|
if (!hasExclusions || !excludedIds.has(matchId)) {
|
|
1343
1343
|
const placeholder = entry.replaceWith.startsWith("[") ? entry.replaceWith : `[${entry.replaceWith}]`;
|
|
@@ -1438,8 +1438,8 @@ var ProjectFilePrivacy = class {
|
|
|
1438
1438
|
}
|
|
1439
1439
|
if (this.values.size + this.conflicts.length > 1e4) fail("pii_mapping_limit");
|
|
1440
1440
|
}
|
|
1441
|
-
restoreText(
|
|
1442
|
-
return
|
|
1441
|
+
restoreText(text7) {
|
|
1442
|
+
return text7.replace(TOKEN, (token) => {
|
|
1443
1443
|
if (this.ambiguous.has(token)) fail("pii_mapping_ambiguous");
|
|
1444
1444
|
const mapping = this.values.get(token);
|
|
1445
1445
|
const customToken = this.options.detection?.personalDataEntries?.some((entry) => (entry.replaceWith.startsWith("[") ? entry.replaceWith : `[${entry.replaceWith}]`) === token);
|
|
@@ -1477,28 +1477,28 @@ var ProjectFilePrivacy = class {
|
|
|
1477
1477
|
this.addMappings([{ placeholder, original, type }]);
|
|
1478
1478
|
return placeholder;
|
|
1479
1479
|
}
|
|
1480
|
-
redactText(
|
|
1480
|
+
redactText(text7, enhanced = []) {
|
|
1481
1481
|
const ranges = [];
|
|
1482
|
-
const tokens = Array.from(
|
|
1482
|
+
const tokens = Array.from(text7.matchAll(TOKEN)).map((match) => ({ start: match.index, end: match.index + match[0].length }));
|
|
1483
1483
|
for (const range of tokens) {
|
|
1484
|
-
const literal =
|
|
1484
|
+
const literal = text7.slice(range.start, range.end);
|
|
1485
1485
|
if (!(this.options.preserveMappedTokens && this.values.has(literal)) && (this.values.has(literal) || GENERATED_TOKEN.test(literal) || legacyToken(literal))) ranges.push(range);
|
|
1486
1486
|
}
|
|
1487
1487
|
const overlaps = (start, end) => [...tokens, ...ranges].some((r) => start < r.end && end > r.start);
|
|
1488
1488
|
for (const mapping of Array.from(this.values.values()).sort((a, b) => b.original.length - a.original.length)) {
|
|
1489
|
-
let start =
|
|
1489
|
+
let start = text7.indexOf(mapping.original);
|
|
1490
1490
|
while (start !== -1) {
|
|
1491
1491
|
const end = start + mapping.original.length;
|
|
1492
1492
|
if (!overlaps(start, end)) ranges.push({ start, end, type: mapping.type });
|
|
1493
|
-
start =
|
|
1493
|
+
start = text7.indexOf(mapping.original, end);
|
|
1494
1494
|
}
|
|
1495
1495
|
}
|
|
1496
1496
|
if (this.options.enabled !== false) {
|
|
1497
|
-
for (const match of detectPII(
|
|
1497
|
+
for (const match of detectPII(text7, this.options.detection)) {
|
|
1498
1498
|
if (!overlaps(match.startIndex, match.endIndex)) ranges.push({ start: match.startIndex, end: match.endIndex, type: match.type });
|
|
1499
1499
|
}
|
|
1500
1500
|
for (const range of enhanced) {
|
|
1501
|
-
if (!Number.isInteger(range.start) || !Number.isInteger(range.end) || range.start < 0 || range.end <= range.start || range.end >
|
|
1501
|
+
if (!Number.isInteger(range.start) || !Number.isInteger(range.end) || range.start < 0 || range.end <= range.start || range.end > text7.length) fail("pii_invalid_semantic_range");
|
|
1502
1502
|
let fragments = [{ ...range }];
|
|
1503
1503
|
for (const shield of [...tokens, ...ranges]) fragments = fragments.flatMap((part) => {
|
|
1504
1504
|
if (part.start >= shield.end || part.end <= shield.start) return [part];
|
|
@@ -1513,11 +1513,11 @@ var ProjectFilePrivacy = class {
|
|
|
1513
1513
|
let cursor = 0;
|
|
1514
1514
|
let result = "";
|
|
1515
1515
|
for (const range of ranges.sort((a, b) => a.start - b.start)) {
|
|
1516
|
-
result +=
|
|
1517
|
-
result +=
|
|
1516
|
+
result += text7.slice(cursor, range.start);
|
|
1517
|
+
result += text7.slice(range.start, range.end).split(/(\r?\n)/).map((part) => !part || /^(?:\r?\n)$/.test(part) ? part : this.token(part, range.type)).join("");
|
|
1518
1518
|
cursor = range.end;
|
|
1519
1519
|
}
|
|
1520
|
-
return result +
|
|
1520
|
+
return result + text7.slice(cursor);
|
|
1521
1521
|
}
|
|
1522
1522
|
async redactResult(value) {
|
|
1523
1523
|
const visit2 = async (item) => {
|
|
@@ -1556,26 +1556,26 @@ var LABELS = {
|
|
|
1556
1556
|
private_date: { type: "OTHER", category: "birthdays" },
|
|
1557
1557
|
private_url: { type: "OTHER", category: "private_urls" }
|
|
1558
1558
|
};
|
|
1559
|
-
function convertNativePrivacyRanges(
|
|
1559
|
+
function convertNativePrivacyRanges(text7, spans, disabled = /* @__PURE__ */ new Set()) {
|
|
1560
1560
|
const offsets = /* @__PURE__ */ new Map([[0, 0]]);
|
|
1561
1561
|
let bytes2 = 0;
|
|
1562
1562
|
let units = 0;
|
|
1563
|
-
for (const character of
|
|
1563
|
+
for (const character of text7) {
|
|
1564
1564
|
if (character.length === 1 && /[\uD800-\uDFFF]/.test(character)) throw privacyError("privacy_invalid_unicode");
|
|
1565
1565
|
bytes2 += Buffer.byteLength(character);
|
|
1566
1566
|
units += character.length;
|
|
1567
1567
|
offsets.set(bytes2, units);
|
|
1568
1568
|
}
|
|
1569
|
-
const protectedRanges = codingIdentifierRanges(
|
|
1569
|
+
const protectedRanges = codingIdentifierRanges(text7);
|
|
1570
1570
|
const result = [];
|
|
1571
1571
|
for (const span of spans) {
|
|
1572
1572
|
const label3 = LABELS[span.label];
|
|
1573
1573
|
const start = offsets.get(span.start), end = offsets.get(span.end);
|
|
1574
1574
|
if (!label3 || !Number.isInteger(span.start) || !Number.isInteger(span.end) || start === void 0 || end === void 0 || end <= start) throw privacyError("privacy_invalid_semantic_range");
|
|
1575
1575
|
if (disabled.has(label3.category) || span.label === "secret" && disabled.has("api_keys")) continue;
|
|
1576
|
-
const context =
|
|
1576
|
+
const context = text7.slice(Math.max(0, start - 60), Math.min(text7.length, end + 60));
|
|
1577
1577
|
const explicitSecret = /\b(?:password|secret|credential|api[_ -]?key|token)\b/i.test(context);
|
|
1578
|
-
if (protectedRanges.some((r) => start < r.end && end > r.start) && !(span.label === "secret" && explicitSecret && !
|
|
1578
|
+
if (protectedRanges.some((r) => start < r.end && end > r.start) && !(span.label === "secret" && explicitSecret && !text7.slice(start, end).startsWith("["))) continue;
|
|
1579
1579
|
if ((span.label === "private_date" || span.label === "account_number") && /\b(?:commit|sha|hash|build|release|branch|timestamp|version)\b/i.test(context) && !/\b(?:birth|birthday|born|dob|account|iban)\b/i.test(context)) continue;
|
|
1580
1580
|
result.push({ start, end, type: label3.type });
|
|
1581
1581
|
}
|
|
@@ -1591,30 +1591,30 @@ function privacyDetectionOptions(memories) {
|
|
|
1591
1591
|
})
|
|
1592
1592
|
} };
|
|
1593
1593
|
}
|
|
1594
|
-
async function scanEnhancedText(
|
|
1594
|
+
async function scanEnhancedText(text7, scope2, disabled = /* @__PURE__ */ new Set(), progress) {
|
|
1595
1595
|
const preferences = await readPrivacyPreferences();
|
|
1596
|
-
if (!
|
|
1596
|
+
if (!text7 || !enhancedScopeEnabled(preferences, scope2)) return [];
|
|
1597
1597
|
try {
|
|
1598
1598
|
await ensurePrivacyDaemon();
|
|
1599
1599
|
const ranges = [];
|
|
1600
|
-
for (let start = 0; start <
|
|
1601
|
-
let from = Math.max(0, start - 1024), end = Math.min(
|
|
1602
|
-
if (from > 0 && /[\uDC00-\uDFFF]/.test(
|
|
1603
|
-
if (end <
|
|
1604
|
-
progress?.(start,
|
|
1605
|
-
const window =
|
|
1600
|
+
for (let start = 0; start < text7.length; start += 8192) {
|
|
1601
|
+
let from = Math.max(0, start - 1024), end = Math.min(text7.length, start + 9216);
|
|
1602
|
+
if (from > 0 && /[\uDC00-\uDFFF]/.test(text7[from])) from--;
|
|
1603
|
+
if (end < text7.length && /[\uDC00-\uDFFF]/.test(text7[end])) end++;
|
|
1604
|
+
progress?.(start, text7.length);
|
|
1605
|
+
const window = text7.slice(from, end);
|
|
1606
1606
|
const result = await privacyRpc({ op: "scan", text: window, scope: privacyProfile(), idleSeconds: preferences.idleSeconds });
|
|
1607
1607
|
if (!Array.isArray(result.spans)) throw privacyError("privacy_worker_protocol_failed");
|
|
1608
1608
|
ranges.push(...convertNativePrivacyRanges(window, result.spans, disabled).map((r) => ({ ...r, start: r.start + from, end: r.end + from })));
|
|
1609
1609
|
}
|
|
1610
|
-
progress?.(
|
|
1610
|
+
progress?.(text7.length, text7.length);
|
|
1611
1611
|
return ranges;
|
|
1612
1612
|
} catch (error) {
|
|
1613
1613
|
await stopPrivacyDaemon();
|
|
1614
1614
|
throw error;
|
|
1615
1615
|
}
|
|
1616
1616
|
}
|
|
1617
|
-
async function prepareCliMessagePrivacy(
|
|
1617
|
+
async function prepareCliMessagePrivacy(text7, memories, existing = [], scope2 = { kind: "message" }, progress) {
|
|
1618
1618
|
const options = privacyDetectionOptions(memories);
|
|
1619
1619
|
let mappings = existing;
|
|
1620
1620
|
const privacy = new ProjectFilePrivacy({
|
|
@@ -1626,7 +1626,7 @@ async function prepareCliMessagePrivacy(text6, memories, existing = [], scope2 =
|
|
|
1626
1626
|
},
|
|
1627
1627
|
detectEnhanced: (value) => scanEnhancedText(value, scope2, options.detection.disabledCategories, progress)
|
|
1628
1628
|
});
|
|
1629
|
-
const message = await privacy.redactResult(
|
|
1629
|
+
const message = await privacy.redactResult(text7);
|
|
1630
1630
|
return { message, mappings: mappings.map((mapping) => ({ ...mapping, type: mapping.type ?? "OTHER" })) };
|
|
1631
1631
|
}
|
|
1632
1632
|
|
|
@@ -2246,7 +2246,7 @@ async function parseOpenCodeImportBuffer(payload, sourceName = "opencode-session
|
|
|
2246
2246
|
if (role !== "user" && role !== "assistant") continue;
|
|
2247
2247
|
const parts = Array.isArray(message.parts) ? message.parts.filter((part) => Boolean(part && typeof part === "object")) : [];
|
|
2248
2248
|
const textParts = parts.filter((part) => part.type === "text" && part.ignored !== true && typeof part.text === "string");
|
|
2249
|
-
const content = textParts.map((part) => String(part.text)).filter((
|
|
2249
|
+
const content = textParts.map((part) => String(part.text)).filter((text7) => text7.trim()).join("\n");
|
|
2250
2250
|
if (content.trim()) {
|
|
2251
2251
|
const time2 = messageInfo.time && typeof messageInfo.time === "object" ? messageInfo.time : {};
|
|
2252
2252
|
messages.push({
|
|
@@ -2994,12 +2994,12 @@ function createProjectFileJobExecutor(options) {
|
|
|
2994
2994
|
mutation = validateProjectFileMutation({ ...job.arguments, operation: job.operation, operation_id: job.operation_id });
|
|
2995
2995
|
if (context.privacy) mutation = context.privacy.restoreMutation(mutation);
|
|
2996
2996
|
if (!context.writeMode) throw Object.assign(new Error(), { code: "write_policy_required" });
|
|
2997
|
-
const
|
|
2998
|
-
proposalCommitment =
|
|
2999
|
-
if (context.writeMode === "always_ask" && approved.get(job.operation_id) !==
|
|
2997
|
+
const digest4 = await projectFileMutationDigest(context.projectKey, job.project_id, job.chat_id, mutation);
|
|
2998
|
+
proposalCommitment = digest4;
|
|
2999
|
+
if (context.writeMode === "always_ask" && approved.get(job.operation_id) !== digest4) {
|
|
3000
3000
|
const approvalRequest = { projectId: job.project_id, chatId: job.chat_id, mutation };
|
|
3001
3001
|
const proposal = context.privacy ? await context.privacy.redactResult(mutation) : mutation;
|
|
3002
|
-
await result("awaiting_approval", { proposal_commitment:
|
|
3002
|
+
await result("awaiting_approval", { proposal_commitment: digest4, proposal });
|
|
3003
3003
|
leaseReleased = true;
|
|
3004
3004
|
options.onWaitingForUser?.(approvalRequest);
|
|
3005
3005
|
if (!options.requestApproval) return;
|
|
@@ -3009,8 +3009,8 @@ function createProjectFileJobExecutor(options) {
|
|
|
3009
3009
|
await options.send("project_file_operation_reject", scope(job));
|
|
3010
3010
|
return;
|
|
3011
3011
|
}
|
|
3012
|
-
await options.approve(approvalRequest,
|
|
3013
|
-
approved.set(job.operation_id,
|
|
3012
|
+
await options.approve(approvalRequest, digest4);
|
|
3013
|
+
approved.set(job.operation_id, digest4);
|
|
3014
3014
|
processing.delete(job.operation_id);
|
|
3015
3015
|
await options.send("project_file_operation_claim", scope(job));
|
|
3016
3016
|
return;
|
|
@@ -3401,10 +3401,10 @@ async function projectFileContentHash(content) {
|
|
|
3401
3401
|
async function hostedProjectFileIdentity(projectKey, path2, kind) {
|
|
3402
3402
|
const normalized = normalizeHostedProjectPath(path2);
|
|
3403
3403
|
const key = await crypto.subtle.importKey("raw", new Uint8Array(projectKey).buffer, { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
|
|
3404
|
-
const
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
const hex = Array.from(
|
|
3404
|
+
const digest4 = new Uint8Array(await crypto.subtle.sign("HMAC", key, bytes(JSON.stringify(["openmates-hosted-file-v1", kind, normalized])))).slice(0, 16);
|
|
3405
|
+
digest4[6] = digest4[6] & 15 | 80;
|
|
3406
|
+
digest4[8] = digest4[8] & 63 | 128;
|
|
3407
|
+
const hex = Array.from(digest4, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
3408
3408
|
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
3409
3409
|
}
|
|
3410
3410
|
function textContent(head) {
|
|
@@ -3623,8 +3623,8 @@ async function executeHostedProjectFileJob(adapter, job, mutation) {
|
|
|
3623
3623
|
if (!mutation) failure("invalid_file_mutation");
|
|
3624
3624
|
const creating = mutation.operation === "create_file";
|
|
3625
3625
|
const embedId = found[0]?.embedId ?? await hostedProjectFileIdentity(adapter.projectKey, path2, "embed");
|
|
3626
|
-
const
|
|
3627
|
-
const receipt = await adapter.receipt(embedId, job,
|
|
3626
|
+
const digest4 = await projectFileMutationDigest(adapter.projectKey, adapter.projectId, job.chat_id, mutation);
|
|
3627
|
+
const receipt = await adapter.receipt(embedId, job, digest4);
|
|
3628
3628
|
if (receipt?.status === "committed") return { path: path2, operation_id: job.operation_id, revision: receipt.current_revision, idempotent: true };
|
|
3629
3629
|
if (creating && found[0]) failure("file_exists");
|
|
3630
3630
|
if (!creating && !found[0]) failure("file_not_found");
|
|
@@ -3662,7 +3662,7 @@ async function executeHostedProjectFileJob(adapter, job, mutation) {
|
|
|
3662
3662
|
embed_id: embedId,
|
|
3663
3663
|
project_id: adapter.projectId,
|
|
3664
3664
|
chat_id: job.chat_id,
|
|
3665
|
-
proposal_digest:
|
|
3665
|
+
proposal_digest: digest4,
|
|
3666
3666
|
expected_revision: current?.revision ?? 0,
|
|
3667
3667
|
...adapter.teamId ? { team_id: adapter.teamId } : {},
|
|
3668
3668
|
head: { encrypted_content: await adapter.encrypt(await adapter.encodeContent(contentObject), embedKey), encrypted_text_preview: await adapter.encrypt(`${path2} (${content.split("\n").length} lines)`, embedKey), status: "finished", updated_at: now },
|
|
@@ -3913,8 +3913,8 @@ async function activateCliProjectFocus(client2, projectId, chatId, teamId, activ
|
|
|
3913
3913
|
const key = await client2.decryptProjectKey(detail.project, context);
|
|
3914
3914
|
if (!settings.encrypted_settings || settings.selection_required) throw new Error("Choose this Project's write policy in Project settings before starting work.");
|
|
3915
3915
|
if (isCurrent && !isCurrent()) return;
|
|
3916
|
-
const
|
|
3917
|
-
const focus =
|
|
3916
|
+
const text7 = await decryptWithAesGcmCombined(settings.encrypted_settings, key);
|
|
3917
|
+
const focus = text7 ? JSON.parse(text7).default_focus : void 0;
|
|
3918
3918
|
if (!focus?.focus_id || typeof focus.instructions !== "string") throw new Error("The Project's default focus is unavailable.");
|
|
3919
3919
|
if (isCurrent && !isCurrent()) return;
|
|
3920
3920
|
await client2.activateProjectFocus(projectId, {
|
|
@@ -3956,10 +3956,10 @@ function registerCliProjectFileExecutor(options) {
|
|
|
3956
3956
|
send: (event, payload) => options.ws.sendAsync(event, payload),
|
|
3957
3957
|
requestApproval: options.requestApproval,
|
|
3958
3958
|
requestReadApproval: options.requestReadApproval,
|
|
3959
|
-
approve: async (request,
|
|
3959
|
+
approve: async (request, digest4) => {
|
|
3960
3960
|
const focus = await options.client.getActiveProjectFocus(request.chatId);
|
|
3961
3961
|
if (focus?.project_id !== request.projectId) throw Object.assign(new Error(), { code: "project_focus_required" });
|
|
3962
|
-
await options.client.approveProjectWrite(request.projectId, { chat_id: request.chatId, operation_id: request.mutation.operation_id, proposal_digest:
|
|
3962
|
+
await options.client.approveProjectWrite(request.projectId, { chat_id: request.chatId, operation_id: request.mutation.operation_id, proposal_digest: digest4 }, { teamId: focus.team_id, personal: !focus.team_id });
|
|
3963
3963
|
},
|
|
3964
3964
|
resolve: async (job) => {
|
|
3965
3965
|
const focus = await options.client.getActiveProjectFocus(job.chat_id);
|
|
@@ -3979,7 +3979,7 @@ function registerCliProjectFileExecutor(options) {
|
|
|
3979
3979
|
key: options.chatKey,
|
|
3980
3980
|
mappings: [...history.messages.flatMap((message) => message.piiMappings ?? []), ...options.piiMappings ?? []],
|
|
3981
3981
|
...detection,
|
|
3982
|
-
detectEnhanced: (
|
|
3982
|
+
detectEnhanced: (text7) => scanEnhancedText(text7, { kind: "project", projectId: job.project_id }, detection.detection.disabledCategories),
|
|
3983
3983
|
read: async () => {
|
|
3984
3984
|
try {
|
|
3985
3985
|
return await readFile(path2, "utf8");
|
|
@@ -4062,7 +4062,7 @@ function registerCliProjectFileExecutor(options) {
|
|
|
4062
4062
|
return files;
|
|
4063
4063
|
},
|
|
4064
4064
|
readHead: (embedId) => options.client.readEncryptedProjectFile(job.project_id, embedId, projectKey, context),
|
|
4065
|
-
receipt: (embedId, receiptJob,
|
|
4065
|
+
receipt: (embedId, receiptJob, digest4) => options.client.getProjectFileRevisionReceipt(job.project_id, embedId, receiptJob.operation_id, receiptJob.chat_id, digest4, context),
|
|
4066
4066
|
commit: async (payload) => {
|
|
4067
4067
|
const requestId = randomUUID5();
|
|
4068
4068
|
const pending = options.ws.waitForMessage("commit_embed_revision_result", (value) => value.request_id === requestId, 3e4);
|
|
@@ -4174,11 +4174,11 @@ function matchEnabledRemoteCommandPreset(options) {
|
|
|
4174
4174
|
for (const preset of options.config.presets) {
|
|
4175
4175
|
if (options.presetId && preset.id !== options.presetId) continue;
|
|
4176
4176
|
if (!preset.commands.some((command) => stableJson(command) === stableJson(options.policy))) continue;
|
|
4177
|
-
const
|
|
4177
|
+
const digest4 = remoteCommandPresetDigest(options.config, preset.id);
|
|
4178
4178
|
const active = options.activeGrants.some(
|
|
4179
|
-
(grant) => grant.enabled === true && grant.project_id === options.projectId && grant.preset_id === preset.id && grant.definition_digest ===
|
|
4179
|
+
(grant) => grant.enabled === true && grant.project_id === options.projectId && grant.preset_id === preset.id && grant.definition_digest === digest4
|
|
4180
4180
|
);
|
|
4181
|
-
if (active) return { presetId: preset.id, definitionDigest:
|
|
4181
|
+
if (active) return { presetId: preset.id, definitionDigest: digest4 };
|
|
4182
4182
|
}
|
|
4183
4183
|
return null;
|
|
4184
4184
|
}
|
|
@@ -4432,13 +4432,13 @@ var RemoteCommandOutputAccumulator = class {
|
|
|
4432
4432
|
return { text: this.#text, coverage: "full", sequence_gap: false, upstream_truncated: false, omitted_chars: 0 };
|
|
4433
4433
|
}
|
|
4434
4434
|
const half = Math.max(0, Math.floor((MAX_COMPLETION_CHARS - OMISSION_MARKER.length) / 2));
|
|
4435
|
-
const
|
|
4435
|
+
const text7 = this.#text.length <= MAX_COMPLETION_CHARS ? this.#text : `${this.#text.slice(0, half)}${OMISSION_MARKER}${this.#text.slice(-half)}`;
|
|
4436
4436
|
return {
|
|
4437
|
-
text:
|
|
4437
|
+
text: text7,
|
|
4438
4438
|
coverage: "selected_excerpt",
|
|
4439
4439
|
sequence_gap: this.#sequenceGap,
|
|
4440
4440
|
upstream_truncated: true,
|
|
4441
|
-
omitted_chars: Math.max(0, this.#inputChars -
|
|
4441
|
+
omitted_chars: Math.max(0, this.#inputChars - text7.length + (text7.includes(OMISSION_MARKER) ? OMISSION_MARKER.length : 0))
|
|
4442
4442
|
};
|
|
4443
4443
|
}
|
|
4444
4444
|
};
|
|
@@ -4700,8 +4700,8 @@ async function remoteCommandPortableRequestDigest(projectKey, request) {
|
|
|
4700
4700
|
assertProjectKey(projectKey);
|
|
4701
4701
|
const identity2 = JSON.stringify(["openmates-remote-command-request-v1", canonicalPortableRemoteCommandRequest(request)]);
|
|
4702
4702
|
const key = await cryptoApi2.subtle.importKey("raw", new Uint8Array(projectKey).buffer, { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
|
|
4703
|
-
const
|
|
4704
|
-
return Buffer.from(
|
|
4703
|
+
const digest4 = await cryptoApi2.subtle.sign("HMAC", key, new TextEncoder().encode(identity2));
|
|
4704
|
+
return Buffer.from(digest4).toString("base64url");
|
|
4705
4705
|
}
|
|
4706
4706
|
function validateApproval(value) {
|
|
4707
4707
|
if (value.kind === "one_run") return;
|
|
@@ -5454,8 +5454,8 @@ var OpenMatesWsClient = class {
|
|
|
5454
5454
|
if (!content || typeof content !== "object") return "";
|
|
5455
5455
|
try {
|
|
5456
5456
|
const root = content;
|
|
5457
|
-
const
|
|
5458
|
-
return typeof
|
|
5457
|
+
const text7 = root.content?.[0]?.content?.[0]?.text;
|
|
5458
|
+
return typeof text7 === "string" ? text7 : "";
|
|
5459
5459
|
} catch {
|
|
5460
5460
|
return "";
|
|
5461
5461
|
}
|
|
@@ -6010,29 +6010,55 @@ var OpenMatesWsClient = class {
|
|
|
6010
6010
|
}
|
|
6011
6011
|
};
|
|
6012
6012
|
|
|
6013
|
+
// ../ui/src/utils/loadedMemoryReceipt.ts
|
|
6014
|
+
var digest3 = /^[a-f0-9]{64}$/;
|
|
6015
|
+
var text3 = (value, max) => typeof value === "string" && !!value.trim() && value.length <= max;
|
|
6016
|
+
function parseMemoriesLoadedEvent(value) {
|
|
6017
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
6018
|
+
const event = value;
|
|
6019
|
+
if (event.type !== "memories_loaded" || typeof event.set_key !== "string" || !digest3.test(event.set_key) || !Array.isArray(event.memories) || !event.memories.length || event.memories.length > 24 || event.count !== event.memories.length) return null;
|
|
6020
|
+
const ids = /* @__PURE__ */ new Set();
|
|
6021
|
+
let size = 0;
|
|
6022
|
+
for (const entry of event.memories) {
|
|
6023
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry)) return null;
|
|
6024
|
+
const m = entry;
|
|
6025
|
+
if (!text3(m.id, 240) || ids.has(m.id) || !text3(m.title, 180) || !text3(m.body, 2e4) || typeof m.revision !== "string" || !digest3.test(m.revision)) return null;
|
|
6026
|
+
if (m.source === "app") {
|
|
6027
|
+
if (!text3(m.app_id, 64) || !/^[a-z][a-z0-9_]*$/.test(m.app_id) || !m.id.startsWith(`app:${m.app_id}:`) || m.project_id != null) return null;
|
|
6028
|
+
} else if (m.source === "project") {
|
|
6029
|
+
if (!text3(m.project_id, 240) || m.app_id != null) return null;
|
|
6030
|
+
} else return null;
|
|
6031
|
+
ids.add(m.id);
|
|
6032
|
+
size += m.body.length;
|
|
6033
|
+
if (size > 32e3) return null;
|
|
6034
|
+
}
|
|
6035
|
+
return event;
|
|
6036
|
+
}
|
|
6037
|
+
|
|
6013
6038
|
// src/chatContextEvents.ts
|
|
6014
6039
|
var DIRECTION_CORRECTION_NOTICE = "Chat is drifting too far away from the goals. Correction instruction was sent.";
|
|
6015
|
-
function
|
|
6040
|
+
function text4(value, limit) {
|
|
6016
6041
|
return typeof value === "string" && value.length > 0 && value.length <= limit;
|
|
6017
6042
|
}
|
|
6018
6043
|
function parseChatContextEvent(value, chatId) {
|
|
6019
6044
|
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
6020
6045
|
const event = value;
|
|
6021
|
-
if (!
|
|
6046
|
+
if (!text4(event.event_id, 128) || !Number.isSafeInteger(event.created_at) || Number(event.created_at) < 0 || chatId && event.chat_id !== void 0 && event.chat_id !== chatId) return null;
|
|
6047
|
+
if (event.type === "memories_loaded") return parseMemoriesLoadedEvent(event);
|
|
6022
6048
|
if (event.type === "rules_loaded") {
|
|
6023
|
-
if (!
|
|
6049
|
+
if (!text4(event.set_key, 128) || !Array.isArray(event.rules) || !event.rules.length || event.rules.length > 24 || event.count !== event.rules.length) return null;
|
|
6024
6050
|
const ids = /* @__PURE__ */ new Set();
|
|
6025
6051
|
let bodyChars = 0;
|
|
6026
6052
|
for (const rule of event.rules) {
|
|
6027
|
-
if (!rule || typeof rule !== "object" || !
|
|
6053
|
+
if (!rule || typeof rule !== "object" || !text4(rule.id, 128) || ids.has(rule.id) || !text4(rule.title, 200) || !["app", "personal", "project"].includes(rule.source) || !text4(rule.revision, 128) || !text4(rule.body, 32e3)) return null;
|
|
6028
6054
|
ids.add(rule.id);
|
|
6029
6055
|
bodyChars += rule.body.length;
|
|
6030
6056
|
}
|
|
6031
6057
|
if (bodyChars > 32e3) return null;
|
|
6032
6058
|
} else if (event.type === "chat_direction_correction") {
|
|
6033
|
-
if (event.notice !== DIRECTION_CORRECTION_NOTICE || !
|
|
6059
|
+
if (event.notice !== DIRECTION_CORRECTION_NOTICE || !text4(event.instruction, 8500) || !text4(event.delivery_id, 128)) return null;
|
|
6034
6060
|
} else if (event.type === "project_authoring_recommendation") {
|
|
6035
|
-
if (!
|
|
6061
|
+
if (!text4(event.recommendation_id, 128) || !text4(event.project_id, 128) || !["focus", "workflow"].includes(String(event.kind)) || !["create", "update"].includes(String(event.action)) || event.action === "update" && (!text4(event.target_id, 128) || !text4(event.expected_revision, 128)) || event.action === "create" && event.kind !== "focus") return null;
|
|
6036
6062
|
} else return null;
|
|
6037
6063
|
return event;
|
|
6038
6064
|
}
|
|
@@ -6044,12 +6070,12 @@ function parseChatContextContent(content) {
|
|
|
6044
6070
|
}
|
|
6045
6071
|
}
|
|
6046
6072
|
function chatContextSummary(event) {
|
|
6047
|
-
if (event.type === "rules_loaded") return `Loaded ${event.count}
|
|
6073
|
+
if (event.type === "memories_loaded" || event.type === "rules_loaded") return `Loaded ${event.count} memories`;
|
|
6048
6074
|
if (event.type === "chat_direction_correction") return DIRECTION_CORRECTION_NOTICE;
|
|
6049
6075
|
return `${event.action === "create" ? "Create" : "Update"} Project ${event.kind === "focus" ? "Focus" : "Workflow"}${event.title ? `: ${event.title}` : ""}`;
|
|
6050
6076
|
}
|
|
6051
6077
|
function chatContextDetails(event) {
|
|
6052
|
-
if (event.type === "rules_loaded") return event.rules.flatMap((rule) => [
|
|
6078
|
+
if (event.type === "memories_loaded" || event.type === "rules_loaded") return (event.type === "memories_loaded" ? event.memories : event.rules).flatMap((rule) => [
|
|
6053
6079
|
rule.title,
|
|
6054
6080
|
`${rule.source}${rule.project_id ? ` \xB7 Project ${rule.project_id}` : rule.app_id ? ` \xB7 ${rule.app_id}` : ""} \xB7 revision ${rule.revision}`,
|
|
6055
6081
|
"",
|
|
@@ -6072,7 +6098,7 @@ function registerChatContextEvents(options) {
|
|
|
6072
6098
|
const persist = (event) => {
|
|
6073
6099
|
if (seen.has(event.event_id)) return;
|
|
6074
6100
|
seen.add(event.event_id);
|
|
6075
|
-
if (event.type === "rules_loaded") {
|
|
6101
|
+
if (event.type === "memories_loaded" || event.type === "rules_loaded") {
|
|
6076
6102
|
if (event.set_key === previousRulesSetKey) return;
|
|
6077
6103
|
previousRulesSetKey = event.set_key;
|
|
6078
6104
|
}
|
|
@@ -6120,12 +6146,12 @@ function object(value) {
|
|
|
6120
6146
|
function keys(value, allowed) {
|
|
6121
6147
|
if (Object.keys(value).some((key) => !allowed.includes(key))) invalid();
|
|
6122
6148
|
}
|
|
6123
|
-
function
|
|
6149
|
+
function text5(value, limit) {
|
|
6124
6150
|
if (typeof value !== "string" || !value.trim() || value.length > limit) return invalid();
|
|
6125
6151
|
return value;
|
|
6126
6152
|
}
|
|
6127
6153
|
function identifier3(value, canonical) {
|
|
6128
|
-
const result =
|
|
6154
|
+
const result = text5(value, canonical ? 64 : 80);
|
|
6129
6155
|
if (!(canonical ? /^[a-z][a-z0-9_-]{0,63}$/ : /^[a-zA-Z0-9_-]{1,80}$/).test(result)) invalid();
|
|
6130
6156
|
return result;
|
|
6131
6157
|
}
|
|
@@ -6139,10 +6165,10 @@ function projectFocusDocumentFromMetadata(metadata, body) {
|
|
|
6139
6165
|
const hints = [header2.when_to_use, header2.preprocessor_hint, header2["preprocessor-hint"]].filter((value) => value !== void 0);
|
|
6140
6166
|
if (names.length !== 1 || hints.length !== 1) invalid();
|
|
6141
6167
|
const common = {
|
|
6142
|
-
name:
|
|
6143
|
-
description:
|
|
6144
|
-
when_to_use:
|
|
6145
|
-
instructions:
|
|
6168
|
+
name: text5(names[0], 200),
|
|
6169
|
+
description: text5(header2.description, 2e3),
|
|
6170
|
+
when_to_use: text5(hints[0], 2e3),
|
|
6171
|
+
instructions: text5(body.trim(), 64e3)
|
|
6146
6172
|
};
|
|
6147
6173
|
const phases = header2.phases === void 0 ? [] : header2.phases;
|
|
6148
6174
|
if (!Array.isArray(phases) || phases.length > 16) invalid();
|
|
@@ -6159,15 +6185,15 @@ function projectFocusDocumentFromMetadata(metadata, body) {
|
|
|
6159
6185
|
if (requirement.type !== void 0 && (typeof requirement.type !== "string" || !["semantic", "user_confirmation"].includes(requirement.type))) invalid();
|
|
6160
6186
|
return {
|
|
6161
6187
|
id: identifier3(requirement.id, true),
|
|
6162
|
-
text:
|
|
6188
|
+
text: text5(requirement.text, 4e3),
|
|
6163
6189
|
...requirement.type === void 0 ? {} : { type: requirement.type }
|
|
6164
6190
|
};
|
|
6165
6191
|
});
|
|
6166
6192
|
unique(gates.map((gate) => gate.id));
|
|
6167
6193
|
return {
|
|
6168
6194
|
id: identifier3(phase.id, true),
|
|
6169
|
-
title:
|
|
6170
|
-
instructions:
|
|
6195
|
+
title: text5(phase.title, 200),
|
|
6196
|
+
instructions: text5(phase.instructions, 16e3),
|
|
6171
6197
|
requirements: gates
|
|
6172
6198
|
};
|
|
6173
6199
|
});
|
|
@@ -6177,7 +6203,7 @@ function projectFocusDocumentFromMetadata(metadata, body) {
|
|
|
6177
6203
|
const legacy = phases.map((raw) => {
|
|
6178
6204
|
const phase = object(raw);
|
|
6179
6205
|
keys(phase, ["id", "name", "instructions"]);
|
|
6180
|
-
return { id: identifier3(phase.id, false), name:
|
|
6206
|
+
return { id: identifier3(phase.id, false), name: text5(phase.name, 120), instructions: text5(phase.instructions, 16e3) };
|
|
6181
6207
|
});
|
|
6182
6208
|
unique(legacy.map((phase) => phase.id));
|
|
6183
6209
|
return { ...common, phases: legacy };
|
|
@@ -6216,7 +6242,7 @@ async function discoverCliProjectCandidates(client2, options) {
|
|
|
6216
6242
|
}));
|
|
6217
6243
|
return entries.filter((entry) => entry !== null);
|
|
6218
6244
|
}
|
|
6219
|
-
async function loadActiveCliProjectContext(client2, chatId,
|
|
6245
|
+
async function loadActiveCliProjectContext(client2, chatId, text7) {
|
|
6220
6246
|
const active = await client2.getActiveProjectFocus(chatId);
|
|
6221
6247
|
if (!active) return {};
|
|
6222
6248
|
const options = { teamId: active.team_id, personal: !active.team_id };
|
|
@@ -6238,9 +6264,9 @@ async function loadActiveCliProjectContext(client2, chatId, text6) {
|
|
|
6238
6264
|
const metadataText = await decryptWithAesGcmCombined(item.encrypted_metadata, key);
|
|
6239
6265
|
const metadata = metadataText ? JSON.parse(metadataText) : {};
|
|
6240
6266
|
const path2 = typeof (metadata.path ?? metadata.display_path) === "string" ? String(metadata.path ?? metadata.display_path) : "";
|
|
6241
|
-
const match = /^\.openmates\/(rules|focuses|specs|facts)\/[^\0]+(?:\.md|\/SKILL\.md)$/.exec(path2);
|
|
6267
|
+
const match = /^\.openmates\/(memories|rules|focuses|specs|facts)\/[^\0]+(?:\.md|\/SKILL\.md)$/.exec(path2);
|
|
6242
6268
|
if (!match || path2.split("/").some((part) => part === ".." || part === "." || !part)) continue;
|
|
6243
|
-
const kind = { rules: "rule", focuses: "focus", specs: "spec", facts: "
|
|
6269
|
+
const kind = { memories: "memory", rules: "rule", focuses: "focus", specs: "spec", facts: "memory" }[match[1]];
|
|
6244
6270
|
const title = metadata.focus_title ?? metadata.title ?? metadata.name;
|
|
6245
6271
|
const description = metadata.focus_description ?? metadata.summary ?? metadata.description;
|
|
6246
6272
|
const currentRevision = revision(item);
|
|
@@ -6272,9 +6298,9 @@ async function loadActiveCliProjectContext(client2, chatId, text6) {
|
|
|
6272
6298
|
if (title && description) candidates.push({ kind: "folder", id: folder.folder_id, title: title.slice(0, 200), description: description.slice(0, 640), when_to_use: "", revision: revision(folder) });
|
|
6273
6299
|
}
|
|
6274
6300
|
let selected = [];
|
|
6275
|
-
if (
|
|
6301
|
+
if (text7?.trim() && candidates.length) selected = await client2.selectProjectContext(
|
|
6276
6302
|
active.project_id,
|
|
6277
|
-
{ chat_id: chatId, text:
|
|
6303
|
+
{ chat_id: chatId, text: text7.slice(0, 8e3), candidates: candidates.slice(0, 24) },
|
|
6278
6304
|
options
|
|
6279
6305
|
);
|
|
6280
6306
|
const specialistId = active.specialist_focus_id?.startsWith(`project-focus:${active.project_id}:`) ? active.specialist_focus_id.split(":")[2] : active.specialist_focus_id;
|
|
@@ -6302,7 +6328,7 @@ async function loadActiveCliProjectContext(client2, chatId, text6) {
|
|
|
6302
6328
|
if (typeof document !== "string" || document.length > (candidate.kind === "focus" ? 6e4 : 24e3) || totalChars + document.length > 64e3) continue;
|
|
6303
6329
|
totalChars += document.length;
|
|
6304
6330
|
if (candidate.kind === "focus") result.project_focus_documents.push({ item_id: candidate.id, document, revision: candidate.revision });
|
|
6305
|
-
else if (candidate.kind === "rule") result.custom_rule_documents.push({ id: candidate.id, source: "project", project_id: active.project_id, document });
|
|
6331
|
+
else if (candidate.kind === "rule") result.custom_rule_documents.push({ id: candidate.id, source: "project", project_id: active.project_id, document, item_revision: candidate.revision });
|
|
6306
6332
|
else result.project_context_documents.push({ item_id: candidate.id, kind: candidate.kind, title: candidate.title, description: candidate.description, document, revision: candidate.revision });
|
|
6307
6333
|
}
|
|
6308
6334
|
const [fresh, latest] = await Promise.all([client2.getActiveProjectFocus(chatId), client2.getProject(active.project_id, options)]);
|
|
@@ -6419,25 +6445,20 @@ async function collectRelatedCliTaskContext(client2, chatId, options, records, n
|
|
|
6419
6445
|
}
|
|
6420
6446
|
return candidates;
|
|
6421
6447
|
}
|
|
6422
|
-
async function prepareCliJevContext(client2, chatId, options, supplied = {},
|
|
6448
|
+
async function prepareCliJevContext(client2, chatId, options, supplied = {}, text7) {
|
|
6423
6449
|
let candidates = [];
|
|
6424
6450
|
let active = {};
|
|
6425
6451
|
let tasks = [];
|
|
6426
6452
|
let ownedTaskRecords = [];
|
|
6427
|
-
let personalRules = [];
|
|
6428
6453
|
await Promise.all([
|
|
6429
6454
|
discoverCliProjectCandidates(client2, options).then((value) => {
|
|
6430
6455
|
candidates = value;
|
|
6431
6456
|
}).catch(() => {
|
|
6432
6457
|
}),
|
|
6433
|
-
loadActiveCliProjectContext(client2, chatId,
|
|
6458
|
+
loadActiveCliProjectContext(client2, chatId, text7).then((value) => {
|
|
6434
6459
|
active = value;
|
|
6435
6460
|
}).catch(() => {
|
|
6436
6461
|
}),
|
|
6437
|
-
client2.getCustomRuleDocuments().then((value) => {
|
|
6438
|
-
personalRules = value;
|
|
6439
|
-
}).catch(() => {
|
|
6440
|
-
}),
|
|
6441
6462
|
(async () => {
|
|
6442
6463
|
const records = await client2.listUserTasks({ ...options, limit: 500 });
|
|
6443
6464
|
ownedTaskRecords = records;
|
|
@@ -6457,9 +6478,9 @@ async function prepareCliJevContext(client2, chatId, options, supplied = {}, tex
|
|
|
6457
6478
|
const customDocuments = [];
|
|
6458
6479
|
let documentChars = 0;
|
|
6459
6480
|
const documentIds = /* @__PURE__ */ new Set();
|
|
6460
|
-
for (const rule of [...
|
|
6481
|
+
for (const rule of [...loaded.custom_rule_documents ?? [], ...supplied.custom_memory_documents ?? supplied.custom_rule_documents ?? []]) {
|
|
6461
6482
|
const identity2 = `${rule.source}:${rule.project_id ?? ""}:${rule.id}`;
|
|
6462
|
-
if (rule.source
|
|
6483
|
+
if (rule.source !== "project" || rule.project_id !== current?.project_id || typeof rule.document !== "string" || rule.document.length > 24e3 || documentChars + rule.document.length > 64e3 || documentIds.has(identity2) || customDocuments.length >= 24) continue;
|
|
6463
6484
|
documentChars += rule.document.length;
|
|
6464
6485
|
documentIds.add(identity2);
|
|
6465
6486
|
customDocuments.push(rule);
|
|
@@ -6468,7 +6489,7 @@ async function prepareCliJevContext(client2, chatId, options, supplied = {}, tex
|
|
|
6468
6489
|
accepted_plan_context: acceptedPlan,
|
|
6469
6490
|
project_focus_candidates: (supplied.project_focus_candidates ?? candidates).slice(0, 40),
|
|
6470
6491
|
related_task_candidates: (supplied.related_task_candidates ?? tasks).slice(0, 24),
|
|
6471
|
-
|
|
6492
|
+
custom_memory_documents: customDocuments,
|
|
6472
6493
|
project_focus_catalog: current ? (supplied.project_focus_catalog ?? loaded.project_focus_catalog ?? []).slice(0, 20) : [],
|
|
6473
6494
|
project_focus_documents: current ? (supplied.project_focus_documents ?? loaded.project_focus_documents ?? []).slice(0, 20) : [],
|
|
6474
6495
|
project_context_documents: current ? (supplied.project_context_documents ?? loaded.project_context_documents ?? []).slice(0, 20) : []
|
|
@@ -6635,8 +6656,8 @@ async function startCliProjectAuthoring(client2, recommendation, history) {
|
|
|
6635
6656
|
const key = await client2.decryptProjectKey(detail.project, options);
|
|
6636
6657
|
for (const item of detail.items.filter((item2) => item2.item_type === "workflow" && !item2.deleted_target_state)) {
|
|
6637
6658
|
if (await decryptWithAesGcmCombined(item.target_id_encrypted, key) !== recommendation.target_id) continue;
|
|
6638
|
-
const
|
|
6639
|
-
const metadata =
|
|
6659
|
+
const text7 = item.encrypted_metadata ? await decryptWithAesGcmCombined(item.encrypted_metadata, key) : null;
|
|
6660
|
+
const metadata = text7 ? JSON.parse(text7) : {};
|
|
6640
6661
|
if (metadata.remote_workflow_file && typeof metadata.remote_workflow_file === "object") remoteBinding = metadata.remote_workflow_file;
|
|
6641
6662
|
break;
|
|
6642
6663
|
}
|
|
@@ -7310,8 +7331,8 @@ function parseDelimitedLine(line, delimiter) {
|
|
|
7310
7331
|
cells2.push(current);
|
|
7311
7332
|
return cells2;
|
|
7312
7333
|
}
|
|
7313
|
-
function delimitedTextToMarkdownTable(
|
|
7314
|
-
const rows2 =
|
|
7334
|
+
function delimitedTextToMarkdownTable(text7, delimiter) {
|
|
7335
|
+
const rows2 = text7.split(/\r?\n/).map((line) => line.trimEnd()).filter((line) => line.length > 0).map((line) => parseDelimitedLine(line, delimiter));
|
|
7315
7336
|
if (rows2.length === 0) return "";
|
|
7316
7337
|
const maxCols = Math.max(...rows2.map((row) => row.length));
|
|
7317
7338
|
const normalized = rows2.map((row) => {
|
|
@@ -7358,7 +7379,7 @@ async function docxBufferToHtml(buffer) {
|
|
|
7358
7379
|
const zip = await JSZip2.loadAsync(buffer);
|
|
7359
7380
|
const documentXml = await zip.file("word/document.xml")?.async("string");
|
|
7360
7381
|
if (!documentXml) return "";
|
|
7361
|
-
const paragraphs = getXmlBlocks(documentXml, "p").map(getTextFromDocxParagraph).map((
|
|
7382
|
+
const paragraphs = getXmlBlocks(documentXml, "p").map(getTextFromDocxParagraph).map((text7) => text7.trim()).filter(Boolean);
|
|
7362
7383
|
return paragraphs.map((paragraph) => `<p>${escapeHtml(paragraph)}</p>`).join("\n");
|
|
7363
7384
|
}
|
|
7364
7385
|
function columnLettersToIndex(letters) {
|
|
@@ -8197,8 +8218,8 @@ function splitLongParagraph(paragraph) {
|
|
|
8197
8218
|
if (remainder) chunks.push(remainder);
|
|
8198
8219
|
return chunks;
|
|
8199
8220
|
}
|
|
8200
|
-
function fallback(
|
|
8201
|
-
if (!language.toLowerCase().startsWith("de")) return
|
|
8221
|
+
function fallback(text7, language) {
|
|
8222
|
+
if (!language.toLowerCase().startsWith("de")) return text7;
|
|
8202
8223
|
const german = {
|
|
8203
8224
|
"Search results are available.": "Suchergebnisse sind verf\xFCgbar.",
|
|
8204
8225
|
"I used the News Search skill.": "Ich habe die News-Suche verwendet.",
|
|
@@ -8207,7 +8228,7 @@ function fallback(text6, language) {
|
|
|
8207
8228
|
"A code example is available.": "Ein Codebeispiel ist verf\xFCgbar.",
|
|
8208
8229
|
"A table is available.": "Eine Tabelle ist verf\xFCgbar."
|
|
8209
8230
|
};
|
|
8210
|
-
return german[
|
|
8231
|
+
return german[text7] ?? text7;
|
|
8211
8232
|
}
|
|
8212
8233
|
function projectFence(markdown, language) {
|
|
8213
8234
|
const body = markdown.replace(/^```[^\n]*\n|\n?```$/g, "").trim();
|
|
@@ -8289,8 +8310,8 @@ function rejectProtonCredentialFlags(argsOrFlags) {
|
|
|
8289
8310
|
throw new Error(`${rejected.split("=")[0]} is not allowed. Bridge credentials must be read privately from Proton Bridge or a hidden prompt.`);
|
|
8290
8311
|
}
|
|
8291
8312
|
}
|
|
8292
|
-
function redactProtonBridgeSecrets(
|
|
8293
|
-
return
|
|
8313
|
+
function redactProtonBridgeSecrets(text7) {
|
|
8314
|
+
return text7.replace(CREDENTIAL_VALUE_RE, "$1<redacted>");
|
|
8294
8315
|
}
|
|
8295
8316
|
function containsCredentialLikeField(value) {
|
|
8296
8317
|
return containsCredentialLikeKey(value);
|
|
@@ -8687,7 +8708,7 @@ async function searchProtonBridgeImap(credentials, arguments_) {
|
|
|
8687
8708
|
const limit = clampLimit(arguments_.limit);
|
|
8688
8709
|
const imap = await openTextSocket(credentials.imapHost, credentials.imapPort, IMAP_COMMAND_TIMEOUT_MS);
|
|
8689
8710
|
try {
|
|
8690
|
-
await imap.readUntil((
|
|
8711
|
+
await imap.readUntil((text7) => /^\* OK/im.test(text7));
|
|
8691
8712
|
await imap.command(`LOGIN ${quoteImap(credentials.imapUsername)} ${quoteImap(credentials.imapPassword)}`);
|
|
8692
8713
|
await imap.command(`SELECT ${quoteImap(mailbox)}`);
|
|
8693
8714
|
const searchResponse = await imap.command(buildImapSearchCommand({ query, startDate, endDate }));
|
|
@@ -8735,22 +8756,22 @@ async function sendProtonBridgeSmtp(credentials, payload) {
|
|
|
8735
8756
|
const messageId = `<om-${randomUUID7()}@local.openmates>`;
|
|
8736
8757
|
const smtp = await openTextSocket(credentials.smtpHost, credentials.smtpPort, SMTP_COMMAND_TIMEOUT_MS);
|
|
8737
8758
|
try {
|
|
8738
|
-
await smtp.readUntil((
|
|
8739
|
-
await smtp.rawCommand("EHLO openmates.local", (
|
|
8759
|
+
await smtp.readUntil((text7) => /^220[ -]/m.test(text7));
|
|
8760
|
+
await smtp.rawCommand("EHLO openmates.local", (text7) => /^250\s/m.test(text7), /^250[ -]/m);
|
|
8740
8761
|
const auth = Buffer.from(`\0${credentials.smtpUsername || credentials.imapUsername}\0${credentials.smtpPassword || credentials.imapPassword}`).toString("base64");
|
|
8741
8762
|
try {
|
|
8742
|
-
await smtp.rawCommand(`AUTH PLAIN ${auth}`, (
|
|
8763
|
+
await smtp.rawCommand(`AUTH PLAIN ${auth}`, (text7) => /^235[ -]/m.test(text7), /^235[ -]/m);
|
|
8743
8764
|
} catch {
|
|
8744
8765
|
throw new Error("Local SMTP authentication failed.");
|
|
8745
8766
|
}
|
|
8746
|
-
await smtp.rawCommand(`MAIL FROM:<${from}>`, (
|
|
8767
|
+
await smtp.rawCommand(`MAIL FROM:<${from}>`, (text7) => /^250[ -]/m.test(text7), /^250[ -]/m);
|
|
8747
8768
|
for (const recipient of to) {
|
|
8748
|
-
await smtp.rawCommand(`RCPT TO:<${recipient}>`, (
|
|
8769
|
+
await smtp.rawCommand(`RCPT TO:<${recipient}>`, (text7) => /^250[ -]/m.test(text7), /^250[ -]/m);
|
|
8749
8770
|
}
|
|
8750
|
-
await smtp.rawCommand("DATA", (
|
|
8771
|
+
await smtp.rawCommand("DATA", (text7) => /^354[ -]/m.test(text7), /^354[ -]/m);
|
|
8751
8772
|
await smtp.rawCommand(`${buildSmtpMessage({ from, to, subject, bodyText, messageId })}\r
|
|
8752
|
-
.`, (
|
|
8753
|
-
await smtp.rawCommand("QUIT", (
|
|
8773
|
+
.`, (text7) => /^250[ -]/m.test(text7), /^250[ -]/m);
|
|
8774
|
+
await smtp.rawCommand("QUIT", (text7) => /^221[ -]/m.test(text7), /^221[ -]/m).catch(() => void 0);
|
|
8754
8775
|
return { provider: PROTON_BRIDGE_PROVIDER_ID, message_id: messageId, delivered: true };
|
|
8755
8776
|
} finally {
|
|
8756
8777
|
smtp.close();
|
|
@@ -8862,7 +8883,7 @@ async function openTextSocket(host, port, timeoutMs) {
|
|
|
8862
8883
|
buffer = "";
|
|
8863
8884
|
socket.write(`${tag} ${command}\r
|
|
8864
8885
|
`);
|
|
8865
|
-
const response = await waitForSocketText(socket, () => buffer, (
|
|
8886
|
+
const response = await waitForSocketText(socket, () => buffer, (text7) => marker.test(text7), timeoutMs);
|
|
8866
8887
|
if (expected && !expected.test(response)) {
|
|
8867
8888
|
throw new Error(`Local mail command failed: ${redactProtonBridgeSecrets(response.split(/\r?\n/).slice(-2).join(" "))}`);
|
|
8868
8889
|
}
|
|
@@ -8888,8 +8909,8 @@ async function waitForSocketText(socket, getBuffer, done, timeoutMs) {
|
|
|
8888
8909
|
return await new Promise((resolve18, reject) => {
|
|
8889
8910
|
const timer = setTimeout(() => cleanup(() => reject(new Error("Timed out waiting for local mail server response."))), timeoutMs);
|
|
8890
8911
|
const check = () => {
|
|
8891
|
-
const
|
|
8892
|
-
if (done(
|
|
8912
|
+
const text7 = getBuffer();
|
|
8913
|
+
if (done(text7)) cleanup(() => resolve18(text7));
|
|
8893
8914
|
};
|
|
8894
8915
|
const onData = () => check();
|
|
8895
8916
|
const onError = (error) => cleanup(() => reject(error));
|
|
@@ -9066,8 +9087,8 @@ async function promptHidden(prompt) {
|
|
|
9066
9087
|
return await new Promise((resolve18, reject) => {
|
|
9067
9088
|
let value = "";
|
|
9068
9089
|
const onData = (chunk) => {
|
|
9069
|
-
const
|
|
9070
|
-
for (const char of
|
|
9090
|
+
const text7 = chunk.toString("utf8");
|
|
9091
|
+
for (const char of text7) {
|
|
9071
9092
|
if (char === "") {
|
|
9072
9093
|
cleanup();
|
|
9073
9094
|
reject(new Error("Bridge credential prompt cancelled."));
|
|
@@ -9646,8 +9667,8 @@ function parseUserFlows(value) {
|
|
|
9646
9667
|
}
|
|
9647
9668
|
function deriveShortId(record8) {
|
|
9648
9669
|
const source = record8.plan_id || `${record8.created_at ?? ""}-${record8.updated_at ?? ""}`;
|
|
9649
|
-
const
|
|
9650
|
-
return `${DEFAULT_PLAN_PREFIX}-${
|
|
9670
|
+
const digest4 = createHash12("sha256").update(source).digest("hex").slice(0, 6).toUpperCase();
|
|
9671
|
+
return `${DEFAULT_PLAN_PREFIX}-${digest4}`;
|
|
9651
9672
|
}
|
|
9652
9673
|
function nowSeconds() {
|
|
9653
9674
|
return Math.floor(Date.now() / 1e3);
|
|
@@ -9781,8 +9802,8 @@ async function hashPairSecret(secret) {
|
|
|
9781
9802
|
const bytes2 = decodeBase64url(secret, 32);
|
|
9782
9803
|
if (bytes2.length !== 32) throw new Error("Invalid pairing secret");
|
|
9783
9804
|
try {
|
|
9784
|
-
const
|
|
9785
|
-
return [...
|
|
9805
|
+
const digest4 = new Uint8Array(await crypto.subtle.digest("SHA-256", ownedBuffer(bytes2)));
|
|
9806
|
+
return [...digest4].map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
9786
9807
|
} finally {
|
|
9787
9808
|
bytes2.fill(0);
|
|
9788
9809
|
}
|
|
@@ -10360,6 +10381,13 @@ async function buildSubChatEncryptedMetadataPayloads(params) {
|
|
|
10360
10381
|
return payloads;
|
|
10361
10382
|
}
|
|
10362
10383
|
var MEMORY_TYPE_REGISTRY = {
|
|
10384
|
+
"openmates/memories": {
|
|
10385
|
+
appId: "openmates",
|
|
10386
|
+
itemType: "memories",
|
|
10387
|
+
entryType: "list",
|
|
10388
|
+
required: ["title", "document"],
|
|
10389
|
+
properties: { title: { type: "string" }, document: { type: "string" } }
|
|
10390
|
+
},
|
|
10363
10391
|
"books/favorite_books": {
|
|
10364
10392
|
appId: "books",
|
|
10365
10393
|
itemType: "favorite_books",
|
|
@@ -10769,8 +10797,8 @@ var MATE_NAMES = {
|
|
|
10769
10797
|
general_knowledge: "George",
|
|
10770
10798
|
onboarding_support: "Suki"
|
|
10771
10799
|
};
|
|
10772
|
-
function stripLegacySuggestionPrefix(
|
|
10773
|
-
return
|
|
10800
|
+
function stripLegacySuggestionPrefix(text7) {
|
|
10801
|
+
return text7.replace(/^\s*\[[^\]]+\]\s*/, "").trim();
|
|
10774
10802
|
}
|
|
10775
10803
|
var CLOUD_API_URL = "https://api.openmates.org";
|
|
10776
10804
|
var DEFAULT_API_URL = process.env.OPENMATES_API_URL ?? CLOUD_API_URL;
|
|
@@ -17297,11 +17325,11 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
17297
17325
|
}
|
|
17298
17326
|
return response.data.events ?? [];
|
|
17299
17327
|
}
|
|
17300
|
-
async followUpWorkflowInput(sessionId,
|
|
17328
|
+
async followUpWorkflowInput(sessionId, text7) {
|
|
17301
17329
|
this.requireSession();
|
|
17302
17330
|
const response = await this.http.post(
|
|
17303
17331
|
`/v1/workflows/input/${encodeURIComponent(sessionId)}/follow-up`,
|
|
17304
|
-
{ text:
|
|
17332
|
+
{ text: text7 },
|
|
17305
17333
|
this.getCliRequestHeaders()
|
|
17306
17334
|
);
|
|
17307
17335
|
if (!response.ok || !response.data.session) {
|
|
@@ -17456,11 +17484,13 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
17456
17484
|
async getCustomRuleDocuments() {
|
|
17457
17485
|
const user = await this.whoAmI();
|
|
17458
17486
|
const settings = await this.decryptSettingsRecord(user.encrypted_settings);
|
|
17459
|
-
|
|
17487
|
+
const legacy = Array.isArray(settings.rule_documents) ? settings.rule_documents : [];
|
|
17488
|
+
const canonical = Array.isArray(settings.memory_documents) ? settings.memory_documents : [];
|
|
17489
|
+
const byId = new Map([...legacy, ...canonical].filter((value) => value && typeof value.id === "string").map((value) => [value.id, value]));
|
|
17460
17490
|
let chars = 0;
|
|
17461
17491
|
const documents = [];
|
|
17462
|
-
for (const value of
|
|
17463
|
-
if (!value || typeof value !== "object" || value.source !== void 0 && value.source !== "personal" || typeof value.id !== "string" || !value.id || value.id.length >
|
|
17492
|
+
for (const value of [...byId.values()].slice(0, 24)) {
|
|
17493
|
+
if (!value || typeof value !== "object" || value.source !== void 0 && value.source !== "personal" || typeof value.id !== "string" || !value.id || value.id.length > 240 || typeof value.document !== "string" || value.document.length > 24e3) continue;
|
|
17464
17494
|
if (chars + value.document.length > 64e3) continue;
|
|
17465
17495
|
chars += value.document.length;
|
|
17466
17496
|
documents.push({ id: value.id, source: "personal", document: value.document });
|
|
@@ -19283,6 +19313,26 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
19283
19313
|
data: parsed
|
|
19284
19314
|
});
|
|
19285
19315
|
}
|
|
19316
|
+
if (!teamId) {
|
|
19317
|
+
let accountDocuments = [];
|
|
19318
|
+
try {
|
|
19319
|
+
accountDocuments = await this.getCustomRuleDocuments();
|
|
19320
|
+
} catch {
|
|
19321
|
+
}
|
|
19322
|
+
for (const memory of accountDocuments) {
|
|
19323
|
+
const title = /^title:\s*(.+)$/m.exec(memory.document)?.[1]?.replace(/^['"]|['"]$/g, "") ?? "Memory";
|
|
19324
|
+
results.push({
|
|
19325
|
+
id: `account-memory-${memory.id.replace(/^personal:/, "")}`,
|
|
19326
|
+
app_id: "openmates",
|
|
19327
|
+
item_type: "memories",
|
|
19328
|
+
item_key_hash: "",
|
|
19329
|
+
data: { title, document: memory.document },
|
|
19330
|
+
created_at: 0,
|
|
19331
|
+
updated_at: 0,
|
|
19332
|
+
item_version: 1
|
|
19333
|
+
});
|
|
19334
|
+
}
|
|
19335
|
+
}
|
|
19286
19336
|
return results;
|
|
19287
19337
|
}
|
|
19288
19338
|
/**
|
|
@@ -19310,6 +19360,13 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
19310
19360
|
* @param currentVersion - The entry's current item_version from listMemories()
|
|
19311
19361
|
*/
|
|
19312
19362
|
async updateMemory(params) {
|
|
19363
|
+
if (params.entryId.startsWith("account-memory-")) {
|
|
19364
|
+
if (params.appId !== "openmates" || params.itemType !== "memories" || this.resolveTeamContext(params)) {
|
|
19365
|
+
throw new Error("Account Memories belong to the personal OpenMates category.");
|
|
19366
|
+
}
|
|
19367
|
+
await this.mutateAccountMemory(params.entryId, params.itemValue);
|
|
19368
|
+
return { success: true, id: params.entryId };
|
|
19369
|
+
}
|
|
19313
19370
|
return this.upsertMemory({
|
|
19314
19371
|
appId: params.appId,
|
|
19315
19372
|
itemType: params.itemType,
|
|
@@ -19325,6 +19382,11 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
19325
19382
|
* WebSocket. The server deletes from Directus and broadcasts to all devices.
|
|
19326
19383
|
*/
|
|
19327
19384
|
async deleteMemory(entryId, options = {}) {
|
|
19385
|
+
if (entryId.startsWith("account-memory-")) {
|
|
19386
|
+
if (this.resolveTeamContext(options)) throw new Error("Account Memories belong to the personal OpenMates category.");
|
|
19387
|
+
await this.mutateAccountMemory(entryId);
|
|
19388
|
+
return { success: true };
|
|
19389
|
+
}
|
|
19328
19390
|
const { ws } = await this.openWsClient();
|
|
19329
19391
|
try {
|
|
19330
19392
|
const teamId = this.resolveTeamContext(options);
|
|
@@ -19345,6 +19407,34 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
19345
19407
|
// -------------------------------------------------------------------------
|
|
19346
19408
|
// Private helpers
|
|
19347
19409
|
// -------------------------------------------------------------------------
|
|
19410
|
+
/** Edit legacy account guides in their encrypted owner store, never as public app data. */
|
|
19411
|
+
async mutateAccountMemory(entryId, value) {
|
|
19412
|
+
const sessionId = this.requireSession().sessionId;
|
|
19413
|
+
const user = await this.whoAmI();
|
|
19414
|
+
const settings = await this.decryptSettingsRecord(user.encrypted_settings);
|
|
19415
|
+
const legacy = Array.isArray(settings.rule_documents) ? settings.rule_documents : [];
|
|
19416
|
+
const canonical = Array.isArray(settings.memory_documents) ? settings.memory_documents : [];
|
|
19417
|
+
const documents = new Map([...legacy, ...canonical].filter((document) => document && typeof document.id === "string").map((document) => [document.id, document]));
|
|
19418
|
+
const original = [...documents.values()].find((document) => `account-memory-${document.id.replace(/^personal:/, "")}` === entryId);
|
|
19419
|
+
if (!original || typeof original.document !== "string") throw new Error("Account Memory is unavailable.");
|
|
19420
|
+
if (value) {
|
|
19421
|
+
if (typeof value.title !== "string" || typeof value.document !== "string") throw new Error("Memory title and document are required.");
|
|
19422
|
+
const { parseRuleDocument, serializeRuleDocument } = await import("./ruleDocuments-6VMP2CV5.js");
|
|
19423
|
+
const document = serializeRuleDocument({ ...parseRuleDocument(value.document), title: value.title });
|
|
19424
|
+
documents.set(original.id, { id: original.id, document });
|
|
19425
|
+
settings.memory_documents = [...documents.values()].map(({ id, document: document2 }) => ({ id, document: document2 }));
|
|
19426
|
+
} else {
|
|
19427
|
+
for (const name of ["rule_documents", "memory_documents"]) {
|
|
19428
|
+
if (Array.isArray(settings[name])) settings[name] = settings[name].filter((document) => document.id !== original.id);
|
|
19429
|
+
}
|
|
19430
|
+
}
|
|
19431
|
+
const ciphertext = await encryptWithAesGcmCombined(JSON.stringify(settings), this.getMasterKeyBytes());
|
|
19432
|
+
const current = await this.whoAmI();
|
|
19433
|
+
if (this.requireSession().sessionId !== sessionId || current.encrypted_settings !== user.encrypted_settings || (current.id ?? current.user_id) !== (user.id ?? user.user_id)) {
|
|
19434
|
+
throw new Error("Account settings changed. Reload before editing the Memory.");
|
|
19435
|
+
}
|
|
19436
|
+
await this.settingsPost("/v1/settings/encrypted-account", { encrypted_settings: ciphertext });
|
|
19437
|
+
}
|
|
19348
19438
|
/**
|
|
19349
19439
|
* Validate memory item_value against the registered schema and
|
|
19350
19440
|
* encrypt + send over WebSocket.
|
|
@@ -29770,6 +29860,19 @@ var OpenMatesMemories = class {
|
|
|
29770
29860
|
constructor(client2) {
|
|
29771
29861
|
this.client = client2;
|
|
29772
29862
|
}
|
|
29863
|
+
/** Reviewed, read-only app guidance; independent of private encrypted entries. */
|
|
29864
|
+
async published(options = {}) {
|
|
29865
|
+
if (options.appId) {
|
|
29866
|
+
const app = await this.client.getPublic(
|
|
29867
|
+
`/v1/apps/${encodeURIComponent(options.appId)}/metadata?include_unavailable=true`
|
|
29868
|
+
);
|
|
29869
|
+
return { memories: app.memories ?? [] };
|
|
29870
|
+
}
|
|
29871
|
+
const metadata = await this.client.getPublic(
|
|
29872
|
+
"/v1/apps/metadata?include_unavailable=true"
|
|
29873
|
+
);
|
|
29874
|
+
return { memories: Object.values(metadata.apps).flatMap((app) => app.memories ?? []) };
|
|
29875
|
+
}
|
|
29773
29876
|
async list(options = {}) {
|
|
29774
29877
|
const data = await this.client.get(withQuery("/v1/sdk/memories", options.query));
|
|
29775
29878
|
const memories = await Promise.all((data.memories ?? []).map(async (memory) => {
|
|
@@ -30929,8 +31032,8 @@ var OpenMatesWorkflows = class {
|
|
|
30929
31032
|
const response = await this.client.get(`/v1/workflows/input/${encodeURIComponent(sessionId)}/events?after_event_id=${encodeURIComponent(String(afterEventId))}`);
|
|
30930
31033
|
return response.events ?? [];
|
|
30931
31034
|
}
|
|
30932
|
-
async followUpInput(sessionId,
|
|
30933
|
-
const response = await this.client.request(`/v1/workflows/input/${encodeURIComponent(sessionId)}/follow-up`, { text:
|
|
31035
|
+
async followUpInput(sessionId, text7) {
|
|
31036
|
+
const response = await this.client.request(`/v1/workflows/input/${encodeURIComponent(sessionId)}/follow-up`, { text: text7 });
|
|
30934
31037
|
if (!response.session) throw new OpenMatesApiError(500, { detail: "Workflow input response missing session" });
|
|
30935
31038
|
return response.session;
|
|
30936
31039
|
}
|
|
@@ -32200,27 +32303,27 @@ var SecretRegistry = class {
|
|
|
32200
32303
|
textsToAdd.push(entry.textToHide);
|
|
32201
32304
|
}
|
|
32202
32305
|
if (entry.additionalTexts) {
|
|
32203
|
-
for (const
|
|
32204
|
-
if (
|
|
32205
|
-
textsToAdd.push(
|
|
32306
|
+
for (const text7 of entry.additionalTexts) {
|
|
32307
|
+
if (text7 && text7.trim().length > 0) {
|
|
32308
|
+
textsToAdd.push(text7);
|
|
32206
32309
|
}
|
|
32207
32310
|
}
|
|
32208
32311
|
}
|
|
32209
|
-
for (const
|
|
32312
|
+
for (const text7 of textsToAdd) {
|
|
32210
32313
|
const placeholder = entry.replaceWith.startsWith("[") ? entry.replaceWith : `[${entry.replaceWith}]`;
|
|
32211
32314
|
const regEntry = {
|
|
32212
|
-
value:
|
|
32315
|
+
value: text7,
|
|
32213
32316
|
token: placeholder,
|
|
32214
32317
|
source: "settings",
|
|
32215
32318
|
name: entry.id,
|
|
32216
32319
|
type: "PERSONAL_DATA",
|
|
32217
|
-
length:
|
|
32320
|
+
length: text7.length
|
|
32218
32321
|
};
|
|
32219
|
-
this.entries.set(
|
|
32220
|
-
this.usedPlaceholders.set(placeholder,
|
|
32221
|
-
const lower =
|
|
32222
|
-
if (lower !==
|
|
32223
|
-
this.variantToOriginal.set(lower,
|
|
32322
|
+
this.entries.set(text7, regEntry);
|
|
32323
|
+
this.usedPlaceholders.set(placeholder, text7);
|
|
32324
|
+
const lower = text7.toLowerCase();
|
|
32325
|
+
if (lower !== text7) {
|
|
32326
|
+
this.variantToOriginal.set(lower, text7);
|
|
32224
32327
|
}
|
|
32225
32328
|
}
|
|
32226
32329
|
this.automaton = null;
|
|
@@ -32274,12 +32377,12 @@ var SecretRegistry = class {
|
|
|
32274
32377
|
* @param text Text to scan
|
|
32275
32378
|
* @returns Array of secret mappings for all matches found
|
|
32276
32379
|
*/
|
|
32277
|
-
findAll(
|
|
32380
|
+
findAll(text7) {
|
|
32278
32381
|
if (this.entries.size === 0) return [];
|
|
32279
32382
|
if (!this.automaton) {
|
|
32280
32383
|
this.buildAutomaton();
|
|
32281
32384
|
}
|
|
32282
|
-
const results = this.automaton.search(
|
|
32385
|
+
const results = this.automaton.search(text7);
|
|
32283
32386
|
const mappings = [];
|
|
32284
32387
|
const coveredRanges = [];
|
|
32285
32388
|
const sortedResults = [];
|
|
@@ -32484,17 +32587,17 @@ var SecretScanner = class {
|
|
|
32484
32587
|
* @param text Text to scan and redact
|
|
32485
32588
|
* @returns Object with redacted text and mappings for restoration
|
|
32486
32589
|
*/
|
|
32487
|
-
redact(
|
|
32488
|
-
if (!
|
|
32590
|
+
redact(text7) {
|
|
32591
|
+
if (!text7) return { redacted: text7, mappings: [] };
|
|
32489
32592
|
const allMappings = [];
|
|
32490
32593
|
const coveredRanges = [];
|
|
32491
|
-
const urlExclusionZones = getUrlExclusionZones(
|
|
32492
|
-
const identifierRanges = codingIdentifierRanges(
|
|
32594
|
+
const urlExclusionZones = getUrlExclusionZones(text7);
|
|
32595
|
+
const identifierRanges = codingIdentifierRanges(text7);
|
|
32493
32596
|
if (this.options.enableRegistryDetection && this.registry.size > 0) {
|
|
32494
|
-
const registryMappings = this.registry.findAll(
|
|
32597
|
+
const registryMappings = this.registry.findAll(text7);
|
|
32495
32598
|
for (const mapping of registryMappings) {
|
|
32496
32599
|
let searchFrom = 0;
|
|
32497
|
-
const searchText =
|
|
32600
|
+
const searchText = text7.toLowerCase();
|
|
32498
32601
|
const matchLower = mapping.original.toLowerCase();
|
|
32499
32602
|
while (searchFrom < searchText.length) {
|
|
32500
32603
|
const idx = searchText.indexOf(matchLower, searchFrom);
|
|
@@ -32510,7 +32613,7 @@ var SecretScanner = class {
|
|
|
32510
32613
|
for (const pattern of [...SECRET_PATTERNS, ...GENERAL_PII_PATTERNS]) {
|
|
32511
32614
|
pattern.regex.lastIndex = 0;
|
|
32512
32615
|
let match;
|
|
32513
|
-
while ((match = pattern.regex.exec(
|
|
32616
|
+
while ((match = pattern.regex.exec(text7)) !== null) {
|
|
32514
32617
|
const matchText = match[0];
|
|
32515
32618
|
const startIndex = match.index;
|
|
32516
32619
|
const endIndex = startIndex + matchText.length;
|
|
@@ -32541,7 +32644,7 @@ var SecretScanner = class {
|
|
|
32541
32644
|
}
|
|
32542
32645
|
}
|
|
32543
32646
|
}
|
|
32544
|
-
let redacted =
|
|
32647
|
+
let redacted = text7;
|
|
32545
32648
|
const sortedMappings = [...allMappings].sort(
|
|
32546
32649
|
(a, b) => b.original.length - a.original.length
|
|
32547
32650
|
);
|
|
@@ -32570,9 +32673,9 @@ var SecretScanner = class {
|
|
|
32570
32673
|
* @param mappings Mappings from a previous redact() call
|
|
32571
32674
|
* @returns Text with placeholders replaced by original values
|
|
32572
32675
|
*/
|
|
32573
|
-
restore(
|
|
32574
|
-
if (!
|
|
32575
|
-
let result =
|
|
32676
|
+
restore(text7, mappings) {
|
|
32677
|
+
if (!text7 || !mappings || mappings.length === 0) return text7;
|
|
32678
|
+
let result = text7;
|
|
32576
32679
|
for (const mapping of mappings) {
|
|
32577
32680
|
result = result.split(mapping.placeholder).join(mapping.original);
|
|
32578
32681
|
}
|
|
@@ -32591,11 +32694,11 @@ var SecretScanner = class {
|
|
|
32591
32694
|
function escapeRegExp2(string3) {
|
|
32592
32695
|
return string3.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
32593
32696
|
}
|
|
32594
|
-
function getUrlExclusionZones(
|
|
32697
|
+
function getUrlExclusionZones(text7) {
|
|
32595
32698
|
const urlExclusionRegex = /https?:\/\/[^\s]+/g;
|
|
32596
32699
|
const zones = [];
|
|
32597
32700
|
let match;
|
|
32598
|
-
while ((match = urlExclusionRegex.exec(
|
|
32701
|
+
while ((match = urlExclusionRegex.exec(text7)) !== null) {
|
|
32599
32702
|
zones.push({ start: match.index, end: match.index + match[0].length });
|
|
32600
32703
|
}
|
|
32601
32704
|
return zones;
|
|
@@ -32672,18 +32775,18 @@ var OutputRedactor = class {
|
|
|
32672
32775
|
* @param text Text to scan
|
|
32673
32776
|
* @returns Redacted text with placeholders
|
|
32674
32777
|
*/
|
|
32675
|
-
redact(
|
|
32676
|
-
return this.redactWithMappings(
|
|
32778
|
+
redact(text7) {
|
|
32779
|
+
return this.redactWithMappings(text7).redacted;
|
|
32677
32780
|
}
|
|
32678
32781
|
/**
|
|
32679
32782
|
* Redact and return both redacted text and mappings.
|
|
32680
32783
|
* Used when we need to store mappings alongside message data.
|
|
32681
32784
|
*/
|
|
32682
|
-
redactWithMappings(
|
|
32683
|
-
if (!
|
|
32684
|
-
return { redacted:
|
|
32785
|
+
redactWithMappings(text7) {
|
|
32786
|
+
if (!text7 || !this.initialized || !this.privacyEnabled) {
|
|
32787
|
+
return { redacted: text7, mappings: [] };
|
|
32685
32788
|
}
|
|
32686
|
-
const result = this.scanner.redact(
|
|
32789
|
+
const result = this.scanner.redact(text7);
|
|
32687
32790
|
const excluded = result.mappings.filter((m) => this.disabledCategories.has(PII_TYPE_TO_CATEGORY[m.type] ?? ""));
|
|
32688
32791
|
if (excluded.length) {
|
|
32689
32792
|
result.redacted = this.scanner.restore(result.redacted, excluded);
|
|
@@ -32698,9 +32801,9 @@ var OutputRedactor = class {
|
|
|
32698
32801
|
* Restore placeholders back to original values.
|
|
32699
32802
|
* Only uses mappings from this session (never from external sources).
|
|
32700
32803
|
*/
|
|
32701
|
-
restore(
|
|
32702
|
-
if (!
|
|
32703
|
-
return this.scanner.restore(
|
|
32804
|
+
restore(text7) {
|
|
32805
|
+
if (!text7 || this.sessionMappings.size === 0) return text7;
|
|
32806
|
+
return this.scanner.restore(text7, Array.from(this.sessionMappings.values()));
|
|
32704
32807
|
}
|
|
32705
32808
|
/** Mappings accumulated while preparing attachments and this message. */
|
|
32706
32809
|
getMappings() {
|
|
@@ -32759,8 +32862,8 @@ function createWebsiteEmbed(url) {
|
|
|
32759
32862
|
status: "finished"
|
|
32760
32863
|
};
|
|
32761
32864
|
}
|
|
32762
|
-
function replaceUrlsInText(
|
|
32763
|
-
return
|
|
32865
|
+
function replaceUrlsInText(text7, embeds) {
|
|
32866
|
+
return text7.replace(URL_PATTERN, (rawUrl) => {
|
|
32764
32867
|
const { url, suffix } = trimTrailingUrlPunctuation(rawUrl);
|
|
32765
32868
|
if (!url) return rawUrl;
|
|
32766
32869
|
try {
|
|
@@ -33760,12 +33863,12 @@ function renderAudioTranscribePreview(c, ln) {
|
|
|
33760
33863
|
const language = str(c.language) ?? "";
|
|
33761
33864
|
if (duration) ln(`\x1B[2mDuration: ${duration}\x1B[0m`);
|
|
33762
33865
|
if (language) ln(`\x1B[2mLanguage: ${language}\x1B[0m`);
|
|
33763
|
-
const
|
|
33764
|
-
if (
|
|
33866
|
+
const text7 = str(c.text) ?? str(c.transcript) ?? "";
|
|
33867
|
+
if (text7) ln(trunc(text7, 60));
|
|
33765
33868
|
}
|
|
33766
33869
|
function renderAudioTranscribeFullscreen(c) {
|
|
33767
|
-
const
|
|
33768
|
-
if (
|
|
33870
|
+
const text7 = str(c.text) ?? str(c.transcript) ?? "";
|
|
33871
|
+
if (text7) console.log(text7);
|
|
33769
33872
|
else console.log("No transcript available.");
|
|
33770
33873
|
}
|
|
33771
33874
|
function renderByDirectType(embed, c, ln) {
|
|
@@ -33998,8 +34101,8 @@ function renderDirectTypeFullscreen(embed, c) {
|
|
|
33998
34101
|
|
|
33999
34102
|
`);
|
|
34000
34103
|
if (html) {
|
|
34001
|
-
const
|
|
34002
|
-
console.log(
|
|
34104
|
+
const text7 = html.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
|
|
34105
|
+
console.log(text7);
|
|
34003
34106
|
}
|
|
34004
34107
|
break;
|
|
34005
34108
|
}
|
|
@@ -34010,8 +34113,8 @@ function renderDirectTypeFullscreen(embed, c) {
|
|
|
34010
34113
|
|
|
34011
34114
|
`);
|
|
34012
34115
|
if (html) {
|
|
34013
|
-
const
|
|
34014
|
-
console.log(
|
|
34116
|
+
const text7 = html.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
|
|
34117
|
+
console.log(text7);
|
|
34015
34118
|
}
|
|
34016
34119
|
break;
|
|
34017
34120
|
}
|
|
@@ -35075,7 +35178,7 @@ import { createHash as createHash16 } from "crypto";
|
|
|
35075
35178
|
import { accessSync, constants as constants2, existsSync as existsSync9, mkdirSync as mkdirSync9, mkdtempSync, readFileSync as readFileSync10, renameSync as renameSync4, rmSync as rmSync5, writeFileSync as writeFileSync5 } from "fs";
|
|
35076
35179
|
import { tmpdir } from "os";
|
|
35077
35180
|
import { dirname as dirname7, join as join12, isAbsolute as isAbsolute3, resolve as resolve6 } from "path";
|
|
35078
|
-
var hash2 = (
|
|
35181
|
+
var hash2 = (text7) => createHash16("sha256").update(text7).digest("hex");
|
|
35079
35182
|
function caddyConfigFromArgs(args, cwd) {
|
|
35080
35183
|
const index = args.indexOf("--config");
|
|
35081
35184
|
const value = index >= 0 ? args[index + 1] : args.find((arg) => arg.startsWith("--config="))?.slice(9);
|
|
@@ -40820,10 +40923,10 @@ async function buildCodeRunRequestsFromFlags(flags) {
|
|
|
40820
40923
|
for (const url of toList(flags.url)) {
|
|
40821
40924
|
const response = await fetch(url);
|
|
40822
40925
|
if (!response.ok) throw new Error(`Failed to download Code Run URL ${redactUrl(url)} (HTTP ${response.status})`);
|
|
40823
|
-
const
|
|
40926
|
+
const text7 = await response.text();
|
|
40824
40927
|
const urlPath = new URL(url).pathname;
|
|
40825
40928
|
const sandboxPath = normalizeCodeRunPath(entry || basename3(urlPath) || "main.txt");
|
|
40826
|
-
const buffer = Buffer.from(
|
|
40929
|
+
const buffer = Buffer.from(text7, "utf8");
|
|
40827
40930
|
addFile({
|
|
40828
40931
|
path: sandboxPath,
|
|
40829
40932
|
content_base64: buffer.toString("base64"),
|
|
@@ -40833,9 +40936,9 @@ async function buildCodeRunRequestsFromFlags(flags) {
|
|
|
40833
40936
|
}, buffer.byteLength);
|
|
40834
40937
|
}
|
|
40835
40938
|
if (flags.repo) {
|
|
40836
|
-
await addGithubRepoFiles(flags.repo, toList(flags.include), async (path2,
|
|
40939
|
+
await addGithubRepoFiles(flags.repo, toList(flags.include), async (path2, text7) => {
|
|
40837
40940
|
const sandboxPath = normalizeCodeRunPath(path2);
|
|
40838
|
-
const buffer = Buffer.from(
|
|
40941
|
+
const buffer = Buffer.from(text7, "utf8");
|
|
40839
40942
|
addFile({
|
|
40840
40943
|
path: sandboxPath,
|
|
40841
40944
|
content_base64: buffer.toString("base64"),
|
|
@@ -59555,6 +59658,14 @@ Only output the final Markdown table. Do NOT include explanations, notes, or any
|
|
|
59555
59658
|
}
|
|
59556
59659
|
}
|
|
59557
59660
|
},
|
|
59661
|
+
openmates: {
|
|
59662
|
+
memories: {
|
|
59663
|
+
text: "Memories",
|
|
59664
|
+
description: {
|
|
59665
|
+
text: "Your facts, preferences and reusable guidance. Shared with a mate only after permission or an explicit mention."
|
|
59666
|
+
}
|
|
59667
|
+
}
|
|
59668
|
+
},
|
|
59558
59669
|
plants: {
|
|
59559
59670
|
my_plants: {
|
|
59560
59671
|
text: "My Plants",
|
|
@@ -73600,6 +73711,152 @@ As of mid-2026, the severe supply shocks from the 2024\u20132025 avian flu have
|
|
|
73600
73711
|
text: "Sophia"
|
|
73601
73712
|
}
|
|
73602
73713
|
},
|
|
73714
|
+
memories: {
|
|
73715
|
+
manage: {
|
|
73716
|
+
text: "Memories"
|
|
73717
|
+
},
|
|
73718
|
+
guide_description: {
|
|
73719
|
+
text: "Save facts, preferences or reusable guidance as a Memory. Focus modes guide your current work; Specifications define required outcomes."
|
|
73720
|
+
},
|
|
73721
|
+
scope: {
|
|
73722
|
+
text: "Memory source"
|
|
73723
|
+
},
|
|
73724
|
+
source_app: {
|
|
73725
|
+
text: "App-provided"
|
|
73726
|
+
},
|
|
73727
|
+
sources_help: {
|
|
73728
|
+
text: "Public memories are provided by apps and load automatically when relevant. Private memories are encrypted. Personal memories are shared with your approval or an explicit mention; Project memories load with active Project access."
|
|
73729
|
+
},
|
|
73730
|
+
visibility_public: {
|
|
73731
|
+
text: "Public"
|
|
73732
|
+
},
|
|
73733
|
+
visibility_private: {
|
|
73734
|
+
text: "Private"
|
|
73735
|
+
},
|
|
73736
|
+
source_personal: {
|
|
73737
|
+
text: "Personal"
|
|
73738
|
+
},
|
|
73739
|
+
source_project: {
|
|
73740
|
+
text: "Project"
|
|
73741
|
+
},
|
|
73742
|
+
loaded: {
|
|
73743
|
+
text: "Loaded {count} memories."
|
|
73744
|
+
},
|
|
73745
|
+
revision: {
|
|
73746
|
+
text: "Revision"
|
|
73747
|
+
},
|
|
73748
|
+
project_storage: {
|
|
73749
|
+
text: "Project Memories are encrypted Markdown files and load when relevant while this chat has active Project access."
|
|
73750
|
+
},
|
|
73751
|
+
activation_required: {
|
|
73752
|
+
text: "Activate this Project in a chat before creating or editing its Memories."
|
|
73753
|
+
},
|
|
73754
|
+
title: {
|
|
73755
|
+
text: "Title"
|
|
73756
|
+
},
|
|
73757
|
+
description: {
|
|
73758
|
+
text: "Description"
|
|
73759
|
+
},
|
|
73760
|
+
when_to_use: {
|
|
73761
|
+
text: "When to use"
|
|
73762
|
+
},
|
|
73763
|
+
practices: {
|
|
73764
|
+
text: "Memory (Markdown)"
|
|
73765
|
+
},
|
|
73766
|
+
empty: {
|
|
73767
|
+
text: "No Memories saved here yet."
|
|
73768
|
+
},
|
|
73769
|
+
new: {
|
|
73770
|
+
text: "New Memory"
|
|
73771
|
+
},
|
|
73772
|
+
saved: {
|
|
73773
|
+
text: "Memory saved."
|
|
73774
|
+
},
|
|
73775
|
+
invalid_document: {
|
|
73776
|
+
text: "Add a title, description, applicability and practices within the field limits."
|
|
73777
|
+
},
|
|
73778
|
+
save_failed: {
|
|
73779
|
+
text: "Could not load or save the Memories. Please try again."
|
|
73780
|
+
},
|
|
73781
|
+
authoring_suggestions: {
|
|
73782
|
+
text: "Suggested Project improvements"
|
|
73783
|
+
},
|
|
73784
|
+
create_focus: {
|
|
73785
|
+
text: "Create Focus"
|
|
73786
|
+
},
|
|
73787
|
+
update_focus: {
|
|
73788
|
+
text: "Update Focus"
|
|
73789
|
+
},
|
|
73790
|
+
create_workflow: {
|
|
73791
|
+
text: "Create Workflow"
|
|
73792
|
+
},
|
|
73793
|
+
update_workflow: {
|
|
73794
|
+
text: "Update Workflow"
|
|
73795
|
+
},
|
|
73796
|
+
authoring_started: {
|
|
73797
|
+
text: "Started"
|
|
73798
|
+
},
|
|
73799
|
+
authoring_failed: {
|
|
73800
|
+
text: "Could not start this update. Please try again."
|
|
73801
|
+
},
|
|
73802
|
+
expanded: {
|
|
73803
|
+
text: "Expanded"
|
|
73804
|
+
},
|
|
73805
|
+
collapsed: {
|
|
73806
|
+
text: "Collapsed"
|
|
73807
|
+
},
|
|
73808
|
+
authoring_save_failed: {
|
|
73809
|
+
text: "Could not save this draft. Please try again."
|
|
73810
|
+
},
|
|
73811
|
+
review_draft: {
|
|
73812
|
+
text: "Review draft"
|
|
73813
|
+
},
|
|
73814
|
+
save_draft: {
|
|
73815
|
+
text: "Save draft"
|
|
73816
|
+
},
|
|
73817
|
+
job_running: {
|
|
73818
|
+
text: "Working on this improvement\u2026"
|
|
73819
|
+
},
|
|
73820
|
+
job_queued: {
|
|
73821
|
+
text: "Waiting to start."
|
|
73822
|
+
},
|
|
73823
|
+
job_needs_input: {
|
|
73824
|
+
text: "More information is needed."
|
|
73825
|
+
},
|
|
73826
|
+
job_needs_save: {
|
|
73827
|
+
text: "Draft ready for review and saving."
|
|
73828
|
+
},
|
|
73829
|
+
job_needs_binding_save: {
|
|
73830
|
+
text: "Save the remaining Project file connection."
|
|
73831
|
+
},
|
|
73832
|
+
job_pending_file: {
|
|
73833
|
+
text: "Waiting for the connected file."
|
|
73834
|
+
},
|
|
73835
|
+
job_partial: {
|
|
73836
|
+
text: "Some changes completed. The remaining changes need attention."
|
|
73837
|
+
},
|
|
73838
|
+
job_conflict: {
|
|
73839
|
+
text: "The source changed. Review the conflict before continuing."
|
|
73840
|
+
},
|
|
73841
|
+
job_ready: {
|
|
73842
|
+
text: "Project improvement saved."
|
|
73843
|
+
},
|
|
73844
|
+
job_failed: {
|
|
73845
|
+
text: "This improvement could not be completed."
|
|
73846
|
+
},
|
|
73847
|
+
job_saved: {
|
|
73848
|
+
text: "Saved."
|
|
73849
|
+
},
|
|
73850
|
+
job_cancelled: {
|
|
73851
|
+
text: "Cancelled."
|
|
73852
|
+
},
|
|
73853
|
+
job_waiting: {
|
|
73854
|
+
text: "Waiting for a job update."
|
|
73855
|
+
},
|
|
73856
|
+
app_loading: {
|
|
73857
|
+
text: "Public \xB7 Provided by the app \xB7 Read-only \xB7 Loads automatically when relevant"
|
|
73858
|
+
}
|
|
73859
|
+
},
|
|
73603
73860
|
metadata: {
|
|
73604
73861
|
default: {
|
|
73605
73862
|
title: {
|
|
@@ -85426,13 +85683,13 @@ function parseJudgment(answer) {
|
|
|
85426
85683
|
return { score: null, reason: null };
|
|
85427
85684
|
}
|
|
85428
85685
|
}
|
|
85429
|
-
function extractJsonObject(
|
|
85430
|
-
const fenced =
|
|
85686
|
+
function extractJsonObject(text7) {
|
|
85687
|
+
const fenced = text7.match(/```(?:json)?\s*([\s\S]*?)\s*```/i);
|
|
85431
85688
|
if (fenced) return fenced[1];
|
|
85432
|
-
const start =
|
|
85433
|
-
const end =
|
|
85689
|
+
const start = text7.indexOf("{");
|
|
85690
|
+
const end = text7.lastIndexOf("}");
|
|
85434
85691
|
if (start === -1 || end === -1 || end <= start) return null;
|
|
85435
|
-
return
|
|
85692
|
+
return text7.slice(start, end + 1);
|
|
85436
85693
|
}
|
|
85437
85694
|
function loadPricingForModels(models) {
|
|
85438
85695
|
const availablePricing = loadProviderPricing();
|
|
@@ -85461,21 +85718,21 @@ function loadProviderPricing() {
|
|
|
85461
85718
|
for (const fileName of readdirSync6(providersDir)) {
|
|
85462
85719
|
if (!fileName.endsWith(".yml")) continue;
|
|
85463
85720
|
const filePath = join16(providersDir, fileName);
|
|
85464
|
-
const
|
|
85465
|
-
const provider = parseProviderId(
|
|
85466
|
-
for (const modelPricing of parseModelPricing(
|
|
85721
|
+
const text7 = readFileSync13(filePath, "utf-8");
|
|
85722
|
+
const provider = parseProviderId(text7) ?? fileName.replace(/\.yml$/, "");
|
|
85723
|
+
for (const modelPricing of parseModelPricing(text7, provider)) {
|
|
85467
85724
|
pricing.set(`${modelPricing.provider}/${modelPricing.modelId}`, modelPricing);
|
|
85468
85725
|
pricing.set(modelPricing.modelId, modelPricing);
|
|
85469
85726
|
}
|
|
85470
85727
|
}
|
|
85471
85728
|
return pricing;
|
|
85472
85729
|
}
|
|
85473
|
-
function parseProviderId(
|
|
85474
|
-
const match =
|
|
85730
|
+
function parseProviderId(text7) {
|
|
85731
|
+
const match = text7.match(/^provider_id:\s*["']?([^"'\n]+)["']?/m);
|
|
85475
85732
|
return match?.[1]?.trim() ?? null;
|
|
85476
85733
|
}
|
|
85477
|
-
function parseModelPricing(
|
|
85478
|
-
const lines =
|
|
85734
|
+
function parseModelPricing(text7, provider) {
|
|
85735
|
+
const lines = text7.split("\n");
|
|
85479
85736
|
const results = [];
|
|
85480
85737
|
let modelId = null;
|
|
85481
85738
|
let inModel = false;
|
|
@@ -86037,10 +86294,10 @@ var TuiTerminal = class {
|
|
|
86037
86294
|
const tail = rows2.length < this.height ? `\x1B[${rows2.length + 1};1H\x1B[J` : "";
|
|
86038
86295
|
this.output.write(`\x1B[?2026h${body}${tail}\x1B[?2026l`);
|
|
86039
86296
|
}
|
|
86040
|
-
receiveInput(
|
|
86297
|
+
receiveInput(text7) {
|
|
86041
86298
|
if (this.inputTimer) clearTimeout(this.inputTimer);
|
|
86042
86299
|
this.inputTimer = null;
|
|
86043
|
-
this.pendingInput +=
|
|
86300
|
+
this.pendingInput += text7;
|
|
86044
86301
|
const marker = this.paste ? "\x1B[201~" : "\x1B[200~";
|
|
86045
86302
|
const found = this.pendingInput.indexOf(marker);
|
|
86046
86303
|
if (found >= 0) {
|
|
@@ -86068,10 +86325,10 @@ var TuiTerminal = class {
|
|
|
86068
86325
|
}, 30);
|
|
86069
86326
|
}
|
|
86070
86327
|
/** Consume SGR mouse reports without letting clicks become composer text. */
|
|
86071
|
-
dispatchInput(
|
|
86328
|
+
dispatchInput(text7) {
|
|
86072
86329
|
if (this.mouseTimer) clearTimeout(this.mouseTimer);
|
|
86073
86330
|
this.mouseTimer = null;
|
|
86074
|
-
const input = this.pendingMouse +
|
|
86331
|
+
const input = this.pendingMouse + text7;
|
|
86075
86332
|
this.pendingMouse = "";
|
|
86076
86333
|
let offset = 0;
|
|
86077
86334
|
while (offset < input.length) {
|
|
@@ -86470,25 +86727,25 @@ function wrapCells(value, width) {
|
|
|
86470
86727
|
width = Math.max(1, width);
|
|
86471
86728
|
const result = [];
|
|
86472
86729
|
for (const line of terminalText(value).split("\n")) {
|
|
86473
|
-
let
|
|
86730
|
+
let text7 = "", used = 0;
|
|
86474
86731
|
for (const { segment } of segments.segment(line)) {
|
|
86475
86732
|
const size = graphemeWidth(segment);
|
|
86476
86733
|
if (size > width) {
|
|
86477
|
-
if (
|
|
86734
|
+
if (text7) result.push(text7);
|
|
86478
86735
|
result.push("?");
|
|
86479
|
-
|
|
86736
|
+
text7 = "";
|
|
86480
86737
|
used = 0;
|
|
86481
86738
|
continue;
|
|
86482
86739
|
}
|
|
86483
86740
|
if (used + size > width) {
|
|
86484
|
-
result.push(
|
|
86485
|
-
|
|
86741
|
+
result.push(text7);
|
|
86742
|
+
text7 = "";
|
|
86486
86743
|
used = 0;
|
|
86487
86744
|
}
|
|
86488
|
-
|
|
86745
|
+
text7 += segment;
|
|
86489
86746
|
used += size;
|
|
86490
86747
|
}
|
|
86491
|
-
result.push(
|
|
86748
|
+
result.push(text7);
|
|
86492
86749
|
}
|
|
86493
86750
|
return result;
|
|
86494
86751
|
}
|
|
@@ -87142,8 +87399,8 @@ var NODE_FIELDS = {
|
|
|
87142
87399
|
custom_code: ["code"]
|
|
87143
87400
|
};
|
|
87144
87401
|
function compact(value, max = 80) {
|
|
87145
|
-
const
|
|
87146
|
-
const oneLine3 =
|
|
87402
|
+
const text7 = typeof value === "string" ? value : Array.isArray(value) ? value.map((item) => compact(item, max)).join(", ") : value && typeof value === "object" ? Object.entries(value).map(([key, item]) => `${key.replaceAll("_", " ")}: ${compact(item, max)}`).join(" \xB7 ") : String(value);
|
|
87403
|
+
const oneLine3 = text7.replace(/\s+/g, " ");
|
|
87147
87404
|
return truncateCells(oneLine3, max);
|
|
87148
87405
|
}
|
|
87149
87406
|
function label2(node) {
|
|
@@ -87906,7 +88163,7 @@ function renderWorkspaceFrame(state, rawWidth, rawHeight, body, options = {}) {
|
|
|
87906
88163
|
const title = state.activeChat?.title && state.workspace === "chats" ? ` \xB7 ${state.activeChat.title}` : "";
|
|
87907
88164
|
const nav = contentWidth >= 90 ? `OpenMates ${labels}${title}` : `OpenMates [${titleCase(state.workspace)}] ${state.sidebarOpen ? "Sidebar open" : "Ctrl+B sidebar"}${title}`;
|
|
87908
88165
|
const inputWidth = Math.max(1, contentWidth - 6);
|
|
87909
|
-
const inputLines = state.input.split("\n").flatMap((
|
|
88166
|
+
const inputLines = state.input.split("\n").flatMap((text7) => wrapCells(text7, inputWidth));
|
|
87910
88167
|
const showComposer = state.workspace !== "apps" || state.focus === "composer" || Boolean(state.input);
|
|
87911
88168
|
const composerRows = showComposer ? Math.min(3, Math.max(1, inputLines.length)) : 0;
|
|
87912
88169
|
const bodyHeight = Math.max(1, height - 2 - (showComposer ? composerRows + 3 : 1));
|
|
@@ -87961,8 +88218,8 @@ function renderWorkspaceFrame(state, rawWidth, rawHeight, body, options = {}) {
|
|
|
87961
88218
|
let remaining = span;
|
|
87962
88219
|
rendered = "";
|
|
87963
88220
|
for (const part of style.spans) {
|
|
87964
|
-
const
|
|
87965
|
-
rendered += part.background ? backgroundLine(
|
|
88221
|
+
const text7 = truncateCells(terminalText(part.text).replace(/\n/g, " "), remaining), size = cells(text7);
|
|
88222
|
+
rendered += part.background ? backgroundLine(text7, size, part.background, mode, part.bold) : text7;
|
|
87966
88223
|
remaining -= size;
|
|
87967
88224
|
if (!remaining) break;
|
|
87968
88225
|
}
|
|
@@ -87979,12 +88236,12 @@ function renderWorkspaceFrame(state, rawWidth, rawHeight, body, options = {}) {
|
|
|
87979
88236
|
const hintColor = state.focus === "composer" ? "#a0a0a0" : "#ff553b";
|
|
87980
88237
|
const composer = [];
|
|
87981
88238
|
if (showComposer) {
|
|
87982
|
-
const inputRows = inputLines.slice(-composerRows).map((
|
|
87983
|
-
if (contentWidth < 6) composer.push(...inputRows.map((
|
|
88239
|
+
const inputRows = inputLines.slice(-composerRows).map((text7, i) => `${i ? " " : "> "}${text7 || (!state.input ? placeholder : "")}`);
|
|
88240
|
+
if (contentWidth < 6) composer.push(...inputRows.map((text7) => place(padCells(text7, contentWidth))), place(foreground(padCells(hint, contentWidth), hintColor, mode)), place(" ".repeat(contentWidth)), place(" ".repeat(contentWidth)));
|
|
87984
88241
|
else {
|
|
87985
88242
|
const edge = (left, right) => place(foreground(left + line.repeat(contentWidth - 2) + right, "#6b6b6b", mode));
|
|
87986
|
-
const inputRow = (
|
|
87987
|
-
composer.push(edge(ascii ? "+" : "\u256D", ascii ? "+" : "\u256E"), ...inputRows.map((
|
|
88243
|
+
const inputRow = (text7, color) => place(foreground(vertical, "#6b6b6b", mode) + " " + foreground(padCells(text7, contentWidth - 4), color ?? "#e6e6e6", mode) + " " + foreground(vertical, "#6b6b6b", mode));
|
|
88244
|
+
composer.push(edge(ascii ? "+" : "\u256D", ascii ? "+" : "\u256E"), ...inputRows.map((text7) => inputRow(text7)), inputRow(hint, hintColor), edge(ascii ? "+" : "\u2570", ascii ? "+" : "\u256F"));
|
|
87988
88245
|
}
|
|
87989
88246
|
}
|
|
87990
88247
|
const frame = [
|
|
@@ -88036,8 +88293,8 @@ function renderCardCarousel(cards, width, selectedIndex, focused) {
|
|
|
88036
88293
|
return { text: spans.map((span) => span.text).join(""), spans };
|
|
88037
88294
|
});
|
|
88038
88295
|
}
|
|
88039
|
-
function centeredCarouselText(
|
|
88040
|
-
const value = truncateCells(
|
|
88296
|
+
function centeredCarouselText(text7, width) {
|
|
88297
|
+
const value = truncateCells(text7, width);
|
|
88041
88298
|
return " ".repeat(Math.max(0, Math.floor((width - cells(value)) / 2))) + value;
|
|
88042
88299
|
}
|
|
88043
88300
|
|
|
@@ -88317,7 +88574,7 @@ function homeHeader(state, width, height) {
|
|
|
88317
88574
|
const title = inspiration?.feature?.title || inspiration?.title || "Daily inspiration";
|
|
88318
88575
|
const banner = [centered2(`DAILY INSPIRATION ${state.focus === "inspiration" ? "\u2039 Enter open \u203A" : "\u2039 Ctrl+O explore \u203A"}`, width), "", ...parts.map((line) => centered2(line, width)), centered2(title, width)];
|
|
88319
88576
|
while (banner.length < rows2) banner.push("");
|
|
88320
|
-
banner.forEach((
|
|
88577
|
+
banner.forEach((text7) => result.push({ text: text7, background: gradient.start }));
|
|
88321
88578
|
result.push("", { text: centered2(state.workspace === "apps" ? prompts.apps : state.username ? `Hey ${state.username}!` : "Hey there!", width), bold: true });
|
|
88322
88579
|
if (state.workspace !== "chats" || !homeChatItems(state).length) result.push({ text: centered2(state.workspace === "apps" ? "Use your apps directly and return to saved results." : prompts[state.workspace], width), color: "#cfcfcf" });
|
|
88323
88580
|
result.push("");
|
|
@@ -88539,7 +88796,15 @@ function parseApp(value, idHint = "") {
|
|
|
88539
88796
|
}];
|
|
88540
88797
|
}),
|
|
88541
88798
|
focusModes: rows(value.focus_modes).map((entry) => ({ id: string2(entry.id), name: string2(entry.name), description: string2(entry.description) })),
|
|
88542
|
-
settingsMemories:
|
|
88799
|
+
settingsMemories: [
|
|
88800
|
+
...rows(value.settings_and_memories).map((entry) => ({ id: string2(entry.id), name: string2(entry.name), description: string2(entry.description) })),
|
|
88801
|
+
...rows(value.memories).map((entry) => ({
|
|
88802
|
+
id: string2(entry.id),
|
|
88803
|
+
name: string2(entry.title),
|
|
88804
|
+
description: `App-provided \xB7 Read-only \xB7 Loads automatically when relevant. ${string2(entry.description)}`,
|
|
88805
|
+
body: string2(entry.body)
|
|
88806
|
+
}))
|
|
88807
|
+
]
|
|
88543
88808
|
};
|
|
88544
88809
|
}
|
|
88545
88810
|
async function loadTuiApps(client2) {
|
|
@@ -88624,7 +88889,7 @@ function renderTuiAppIdentity(app, width) {
|
|
|
88624
88889
|
}
|
|
88625
88890
|
function renderTuiAppTabs(tab, width) {
|
|
88626
88891
|
const tabs = ["skills", "focus_modes", "settings_memories", "embeds", "workflows"];
|
|
88627
|
-
const labels = { skills: "Skills", focus_modes: "Focus modes", settings_memories: "
|
|
88892
|
+
const labels = { skills: "Skills", focus_modes: "Focus modes", settings_memories: "Memories", embeds: "Embeds", workflows: "Workflows" };
|
|
88628
88893
|
return outlinedTabs(tabs, labels, tab, width);
|
|
88629
88894
|
}
|
|
88630
88895
|
function renderTuiApp(app, options) {
|
|
@@ -88646,9 +88911,10 @@ function renderTuiApp(app, options) {
|
|
|
88646
88911
|
if (!items.length) lines.push("Nothing in this section.");
|
|
88647
88912
|
for (const item of items) {
|
|
88648
88913
|
lines.push(truncateCells(`${item.id === options.selectedId ? ">" : " "} ${item.name}`, width));
|
|
88649
|
-
if (item.description) lines.push(
|
|
88914
|
+
if (item.description) lines.push(...textLines(` ${oneLine2(item.description)}`, width));
|
|
88915
|
+
if ("body" in item && item.body && item.id === options.selectedId) lines.push(...textLines(item.body, width));
|
|
88650
88916
|
}
|
|
88651
|
-
lines.push("", "Manage
|
|
88917
|
+
lines.push("", "Manage private Memories in the web app.");
|
|
88652
88918
|
} else if (options.tab === "embeds") lines.push("Saved results load from the encrypted Apps history. Use Enter to inspect a result.");
|
|
88653
88919
|
else lines.push("Saved workflows for this app load from Workflows. Open a workflow there to inspect it.");
|
|
88654
88920
|
return lines;
|
|
@@ -89006,8 +89272,8 @@ function readableFields(value, width) {
|
|
|
89006
89272
|
lines.push(`${indent}${label3}`);
|
|
89007
89273
|
for (const [key, entry] of Object.entries(item)) visit2(readableLabel(key), entry, `${indent} `);
|
|
89008
89274
|
} else {
|
|
89009
|
-
const
|
|
89010
|
-
const [first = "", ...rest] =
|
|
89275
|
+
const text7 = item === null ? "None" : typeof item === "boolean" ? item ? "Yes" : "No" : String(item);
|
|
89276
|
+
const [first = "", ...rest] = text7.split("\n");
|
|
89011
89277
|
lines.push(`${indent}${label3} ${first}`);
|
|
89012
89278
|
lines.push(...rest.map((line) => `${indent} ${line}`));
|
|
89013
89279
|
}
|
|
@@ -89207,7 +89473,7 @@ function renderTuiFrame(state, width, height, options = {}) {
|
|
|
89207
89473
|
return renderWorkspaceFrame(state, width, height, renderBody(state, bodyWidth, height), { ...options, stickyRows, headerRows: state.screen === "chat" || state.screen === "example" ? renderChatHeader(state, bodyWidth).length : void 0 });
|
|
89208
89474
|
}
|
|
89209
89475
|
function coloredHero(lines, rows2, gradient = PRIMARY_GRADIENT) {
|
|
89210
|
-
return lines.map((
|
|
89476
|
+
return lines.map((text7, index) => index < rows2 ? { text: text7, background: gradient.start } : text7);
|
|
89211
89477
|
}
|
|
89212
89478
|
var blueHero = (lines, rows2) => coloredHero(lines, rows2);
|
|
89213
89479
|
function homeCards(lines, width, gradients) {
|
|
@@ -89219,7 +89485,7 @@ function homeCards(lines, width, gradients) {
|
|
|
89219
89485
|
}
|
|
89220
89486
|
return groups.filter((group) => group.length).flatMap((group, index) => {
|
|
89221
89487
|
const cardWidth = Math.min(width, Math.max(...group.map(cells))), inset = Math.max(0, Math.floor((width - cardWidth) / 2));
|
|
89222
|
-
return [...group.map((
|
|
89488
|
+
return [...group.map((text7) => ({ text: text7, background: (gradients[index] ?? PRIMARY_GRADIENT).start, inset })), ""];
|
|
89223
89489
|
});
|
|
89224
89490
|
}
|
|
89225
89491
|
function renderBody(state, width, height) {
|
|
@@ -89554,9 +89820,9 @@ import { randomUUID as randomUUID19 } from "crypto";
|
|
|
89554
89820
|
var AuthoringSaveApprovalRequired = class extends Error {
|
|
89555
89821
|
digest;
|
|
89556
89822
|
mutation;
|
|
89557
|
-
constructor(
|
|
89823
|
+
constructor(digest4, mutation) {
|
|
89558
89824
|
super("Review the generated file, then choose Save to approve this exact write.");
|
|
89559
|
-
this.digest =
|
|
89825
|
+
this.digest = digest4;
|
|
89560
89826
|
this.mutation = mutation;
|
|
89561
89827
|
}
|
|
89562
89828
|
};
|
|
@@ -89573,9 +89839,9 @@ function required(value) {
|
|
|
89573
89839
|
return value;
|
|
89574
89840
|
}
|
|
89575
89841
|
function authoringReplacementPatch(path2, original, content) {
|
|
89576
|
-
const lines = (
|
|
89577
|
-
if (!
|
|
89578
|
-
const parts =
|
|
89842
|
+
const lines = (text7, prefix) => {
|
|
89843
|
+
if (!text7) return { count: 0, rows: [] };
|
|
89844
|
+
const parts = text7.split("\n");
|
|
89579
89845
|
const newline = parts.at(-1) === "";
|
|
89580
89846
|
if (newline) parts.pop();
|
|
89581
89847
|
const rows2 = parts.map((line) => prefix + line);
|
|
@@ -89653,18 +89919,18 @@ async function persistCliProjectAuthoringJob(client2, job, approvedDigest) {
|
|
|
89653
89919
|
expected_base: await projectFileContentHash(original),
|
|
89654
89920
|
patch: authoringReplacementPatch(path2, original, markdown)
|
|
89655
89921
|
} : { operation: "create_file", operation_id: operationId, path: path2, expected_base: null, content: markdown };
|
|
89656
|
-
const
|
|
89922
|
+
const digest4 = await projectFileMutationDigest(projectKey, projectId, chatId, mutation);
|
|
89657
89923
|
let receipt;
|
|
89658
89924
|
try {
|
|
89659
|
-
receipt = await client2.getProjectFileRevisionReceipt(projectId, embedId, operationId, chatId,
|
|
89925
|
+
receipt = await client2.getProjectFileRevisionReceipt(projectId, embedId, operationId, chatId, digest4, options);
|
|
89660
89926
|
} catch (error) {
|
|
89661
89927
|
if (settings.write_mode !== "always_ask" || !error || typeof error !== "object" || !("code" in error) || error.code !== "PROJECT_WRITE_APPROVAL_REQUIRED" || !("status" in error) || error.status !== 409) throw error;
|
|
89662
89928
|
receipt = null;
|
|
89663
89929
|
}
|
|
89664
89930
|
if (receipt?.status !== "committed" && settings.write_mode === "always_ask") {
|
|
89665
|
-
if (approvedDigest !==
|
|
89931
|
+
if (approvedDigest !== digest4) throw new AuthoringSaveApprovalRequired(digest4, mutation);
|
|
89666
89932
|
await fresh();
|
|
89667
|
-
await client2.approveProjectWrite(projectId, { chat_id: chatId, operation_id: operationId, proposal_digest:
|
|
89933
|
+
await client2.approveProjectWrite(projectId, { chat_id: chatId, operation_id: operationId, proposal_digest: digest4 }, options);
|
|
89668
89934
|
}
|
|
89669
89935
|
const focusMetadata = {
|
|
89670
89936
|
...metadata,
|
|
@@ -89680,8 +89946,8 @@ async function persistCliProjectAuthoringJob(client2, job, approvedDigest) {
|
|
|
89680
89946
|
for (const row of detail.items) {
|
|
89681
89947
|
if (!["embed", "upload"].includes(row.item_type) || row.deleted_target_state) continue;
|
|
89682
89948
|
const target = await decryptWithAesGcmCombined(row.target_id_encrypted, projectKey);
|
|
89683
|
-
const
|
|
89684
|
-
const meta =
|
|
89949
|
+
const text7 = row.encrypted_metadata ? await decryptWithAesGcmCombined(row.encrypted_metadata, projectKey) : null;
|
|
89950
|
+
const meta = text7 ? record6(JSON.parse(text7)) : {};
|
|
89685
89951
|
const filePath = meta.path ?? meta.file_path ?? meta.filename ?? meta.display_path;
|
|
89686
89952
|
if (target && typeof filePath === "string") files.push({ embedId: target, path: filePath });
|
|
89687
89953
|
}
|
|
@@ -90362,8 +90628,8 @@ async function handleWorkspaceCommand(context, command) {
|
|
|
90362
90628
|
if (request !== state.routeVersion) return true;
|
|
90363
90629
|
state.detailTitle = embed.textPreview || (embed.appId ? `${embed.appId}${embed.skillId ? `/${embed.skillId}` : ""}` : embed.type?.replaceAll("_", " ")) || "Embed";
|
|
90364
90630
|
const body = embed.content;
|
|
90365
|
-
const
|
|
90366
|
-
state.detailLines = typeof
|
|
90631
|
+
const text7 = ["code", "markdown", "content", "text", "transcript"].map((key) => body?.[key]).find((value) => typeof value === "string");
|
|
90632
|
+
state.detailLines = typeof text7 === "string" ? text7.split("\n") : formatEmbedPreviewLines(embed, 100);
|
|
90367
90633
|
}
|
|
90368
90634
|
render();
|
|
90369
90635
|
return true;
|
|
@@ -90862,10 +91128,10 @@ async function handleWorkspaceKey(context, chunk, key) {
|
|
|
90862
91128
|
state.filter = "";
|
|
90863
91129
|
}
|
|
90864
91130
|
} else if (file) {
|
|
90865
|
-
const
|
|
91131
|
+
const text7 = await readTuiProjectFile(context.client, project, file);
|
|
90866
91132
|
if (request === state.routeVersion && state.activeProject?.id === project.id) {
|
|
90867
91133
|
state.detailTitle = file.name;
|
|
90868
|
-
state.detailLines =
|
|
91134
|
+
state.detailLines = text7.split("\n");
|
|
90869
91135
|
state.screen = "embed";
|
|
90870
91136
|
state.scrollOffset = 0;
|
|
90871
91137
|
}
|
|
@@ -90950,9 +91216,9 @@ async function handleWorkspaceKey(context, chunk, key) {
|
|
|
90950
91216
|
return true;
|
|
90951
91217
|
}
|
|
90952
91218
|
if (key.name === "return" && state.screen === "chats" && state.input.trim()) {
|
|
90953
|
-
const
|
|
91219
|
+
const text7 = state.input.trim();
|
|
90954
91220
|
newChat(state);
|
|
90955
|
-
await context.send(
|
|
91221
|
+
await context.send(text7);
|
|
90956
91222
|
return true;
|
|
90957
91223
|
}
|
|
90958
91224
|
const cursor = state.inputCursor ?? state.input.length;
|
|
@@ -90994,9 +91260,9 @@ async function handleWorkspaceKey(context, chunk, key) {
|
|
|
90994
91260
|
return true;
|
|
90995
91261
|
}
|
|
90996
91262
|
if (key.name === "paste" || !key.ctrl && !key.meta && chunk && chunk >= " ") {
|
|
90997
|
-
const
|
|
90998
|
-
state.input = state.input.slice(0, cursor) +
|
|
90999
|
-
state.inputCursor = cursor +
|
|
91263
|
+
const text7 = terminalText(chunk);
|
|
91264
|
+
state.input = state.input.slice(0, cursor) + text7 + state.input.slice(cursor);
|
|
91265
|
+
state.inputCursor = cursor + text7.length;
|
|
91000
91266
|
rememberDraft(state);
|
|
91001
91267
|
render();
|
|
91002
91268
|
return true;
|
|
@@ -91377,13 +91643,13 @@ async function handleEnter(params) {
|
|
|
91377
91643
|
render();
|
|
91378
91644
|
return;
|
|
91379
91645
|
}
|
|
91380
|
-
const
|
|
91381
|
-
if (!
|
|
91382
|
-
if (
|
|
91383
|
-
await handleCommand({ command:
|
|
91646
|
+
const text7 = state.input.trim();
|
|
91647
|
+
if (!text7) return;
|
|
91648
|
+
if (text7.startsWith("/")) {
|
|
91649
|
+
await handleCommand({ command: text7, state, client: client2, terminal, render, finish });
|
|
91384
91650
|
return;
|
|
91385
91651
|
}
|
|
91386
|
-
await sendTuiMessage({ message:
|
|
91652
|
+
await sendTuiMessage({ message: text7, state, client: client2, render });
|
|
91387
91653
|
}
|
|
91388
91654
|
async function handleCommand(params) {
|
|
91389
91655
|
const { command, state, client: client2, terminal, render, finish } = params;
|
|
@@ -92329,13 +92595,13 @@ function loadProjectPathPolicy(sourceRoot, options = {}) {
|
|
|
92329
92595
|
builtin_private_paths: PROJECT_BUILTIN_PRIVATE_PATHS,
|
|
92330
92596
|
private_paths: stickyPrivatePaths
|
|
92331
92597
|
}));
|
|
92332
|
-
const
|
|
92598
|
+
const digest4 = sha2562(stableJson2({
|
|
92333
92599
|
private_digest: privateDigest,
|
|
92334
92600
|
ignore_files: ignoreFiles.map((file) => ({ path: file.path, digest: sha2562(file.content) }))
|
|
92335
92601
|
}));
|
|
92336
92602
|
const policy = {
|
|
92337
92603
|
sourceRoot: root,
|
|
92338
|
-
digest:
|
|
92604
|
+
digest: digest4,
|
|
92339
92605
|
privateDigest,
|
|
92340
92606
|
isIgnored(path2, isDirectory = false) {
|
|
92341
92607
|
const normalized = normalizeSourceRelativePath(path2);
|
|
@@ -95239,8 +95505,8 @@ var RemoteCommandSourceController = class {
|
|
|
95239
95505
|
if (!plaintext) throw new Error("Remote command request authentication failed");
|
|
95240
95506
|
const portable = parsePortableRequest(plaintext);
|
|
95241
95507
|
assertPortableBinding(portable, claimed);
|
|
95242
|
-
const
|
|
95243
|
-
if (
|
|
95508
|
+
const digest4 = await remoteCommandPortableRequestDigest(binding.projectKey, portable);
|
|
95509
|
+
if (digest4 !== claimed.request_digest) throw new Error("Remote command request HMAC mismatch");
|
|
95244
95510
|
state.portable = portable;
|
|
95245
95511
|
const request = await this.#buildRuntimeRequest(binding, portable.policy, portable.execution_id);
|
|
95246
95512
|
const preflight = createRemoteCommandPreflight(request);
|
|
@@ -95635,7 +95901,7 @@ function validateSummary(value) {
|
|
|
95635
95901
|
chat_id: identifier4(item.chat_id, "chat_id"),
|
|
95636
95902
|
project_id: identifier4(item.project_id, "project_id"),
|
|
95637
95903
|
source_id: identifier4(item.source_id, "source_id"),
|
|
95638
|
-
state:
|
|
95904
|
+
state: text6(item.state, "state"),
|
|
95639
95905
|
last_sequence: integer3(item.last_sequence ?? -1, "last_sequence", -1),
|
|
95640
95906
|
lease_expires_at: integer3(item.lease_expires_at ?? 0, "lease_expires_at", 0)
|
|
95641
95907
|
};
|
|
@@ -95651,12 +95917,12 @@ function validateClaimedRequest(value, summary, binding, sourceSessionId) {
|
|
|
95651
95917
|
chat_id: identifier4(item.chat_id, "chat_id"),
|
|
95652
95918
|
project_id: identifier4(item.project_id, "project_id"),
|
|
95653
95919
|
source_id: identifier4(item.source_id, "source_id"),
|
|
95654
|
-
state:
|
|
95655
|
-
encrypted_request:
|
|
95656
|
-
request_digest:
|
|
95920
|
+
state: text6(item.state, "state"),
|
|
95921
|
+
encrypted_request: text6(item.encrypted_request, "encrypted_request"),
|
|
95922
|
+
request_digest: text6(item.request_digest, "request_digest"),
|
|
95657
95923
|
approval,
|
|
95658
95924
|
key_epoch: integer3(item.key_epoch, "key_epoch", 1),
|
|
95659
|
-
lease_token:
|
|
95925
|
+
lease_token: text6(item.lease_token, "lease_token"),
|
|
95660
95926
|
lease_generation: integer3(item.lease_generation, "lease_generation", 1),
|
|
95661
95927
|
lease_expires_at: integer3(item.lease_expires_at, "lease_expires_at", 1),
|
|
95662
95928
|
last_sequence: integer3(item.last_sequence ?? -1, "last_sequence", -1),
|
|
@@ -95669,7 +95935,7 @@ function validateLeaseResponse(value, executionId) {
|
|
|
95669
95935
|
return {
|
|
95670
95936
|
...item,
|
|
95671
95937
|
execution_id: executionId,
|
|
95672
|
-
lease_token:
|
|
95938
|
+
lease_token: text6(item.lease_token, "lease_token"),
|
|
95673
95939
|
lease_generation: integer3(item.lease_generation, "lease_generation", 1),
|
|
95674
95940
|
lease_expires_at: integer3(item.lease_expires_at, "lease_expires_at", 1),
|
|
95675
95941
|
last_sequence: integer3(item.last_sequence ?? -1, "last_sequence", -1),
|
|
@@ -95713,12 +95979,12 @@ function parsePolicy(value) {
|
|
|
95713
95979
|
if (!Array.isArray(policy.credential_profiles) || policy.credential_profiles.some((item) => typeof item !== "string")) throw new Error("Invalid credential profiles");
|
|
95714
95980
|
return {
|
|
95715
95981
|
argv: [...policy.argv],
|
|
95716
|
-
cwd:
|
|
95982
|
+
cwd: text6(policy.cwd, "cwd"),
|
|
95717
95983
|
mode: oneOf3(policy.mode, ["foreground", "background"], "mode"),
|
|
95718
95984
|
source_access: oneOf3(policy.source_access, ["read_only", "read_write"], "source_access"),
|
|
95719
95985
|
deadline_ms: integer3(policy.deadline_ms, "deadline_ms", 100),
|
|
95720
95986
|
writable_profiles: [...policy.writable_profiles],
|
|
95721
|
-
network_profile: policy.network_profile === null ? null :
|
|
95987
|
+
network_profile: policy.network_profile === null ? null : text6(policy.network_profile, "network_profile"),
|
|
95722
95988
|
credential_profiles: [...policy.credential_profiles]
|
|
95723
95989
|
};
|
|
95724
95990
|
}
|
|
@@ -95748,7 +96014,7 @@ function validateTrustedGrants(value) {
|
|
|
95748
96014
|
const result = {
|
|
95749
96015
|
writable_targets: value.writable_targets.map((item) => ({
|
|
95750
96016
|
profile_id: identifier4(item.profile_id, "writable profile"),
|
|
95751
|
-
host_path:
|
|
96017
|
+
host_path: text6(item.host_path, "writable host path")
|
|
95752
96018
|
})),
|
|
95753
96019
|
network_profiles: value.network_profiles.map((item) => {
|
|
95754
96020
|
if (!Array.isArray(item.destinations) || item.destinations.some((destination) => typeof destination !== "string")) {
|
|
@@ -95756,7 +96022,7 @@ function validateTrustedGrants(value) {
|
|
|
95756
96022
|
}
|
|
95757
96023
|
return {
|
|
95758
96024
|
profile_id: identifier4(item.profile_id, "network profile"),
|
|
95759
|
-
destinations: item.destinations.map((destination) =>
|
|
96025
|
+
destinations: item.destinations.map((destination) => text6(destination, "network destination"))
|
|
95760
96026
|
};
|
|
95761
96027
|
}),
|
|
95762
96028
|
credential_profiles: value.credential_profiles.map((item) => {
|
|
@@ -95847,7 +96113,7 @@ function identifier4(value, context) {
|
|
|
95847
96113
|
if (typeof value !== "string" || !IDENTIFIER3.test(value)) throw new Error(`Invalid ${context}`);
|
|
95848
96114
|
return value;
|
|
95849
96115
|
}
|
|
95850
|
-
function
|
|
96116
|
+
function text6(value, context) {
|
|
95851
96117
|
if (typeof value !== "string" || !value || value.length > 1048576 || value.includes("\0")) throw new Error(`Invalid ${context}`);
|
|
95852
96118
|
return value;
|
|
95853
96119
|
}
|
|
@@ -99871,10 +100137,10 @@ async function handlePlans(client2, subcommand, rest, flags, redactor) {
|
|
|
99871
100137
|
else console.log(`Plan success criterion updated: ${updated.criterion_id}`);
|
|
99872
100138
|
return;
|
|
99873
100139
|
}
|
|
99874
|
-
const
|
|
100140
|
+
const text7 = requiredStringFlag(flags.text ?? rest.slice(2).join(" "), "--text <criterion>");
|
|
99875
100141
|
const criterion = await buildCreatePlanCriterionInput(plan, masterKey, {
|
|
99876
100142
|
criterionId: typeof flags.id === "string" ? flags.id : void 0,
|
|
99877
|
-
text:
|
|
100143
|
+
text: text7,
|
|
99878
100144
|
type: typeof flags.type === "string" ? flags.type : void 0,
|
|
99879
100145
|
status: typeof flags.status === "string" ? flags.status : void 0,
|
|
99880
100146
|
required: flags.required === true ? true : flags.optional === true ? false : void 0,
|
|
@@ -102047,11 +102313,11 @@ async function handleIdeaBucket(client2, subcommand, rest, flags) {
|
|
|
102047
102313
|
return;
|
|
102048
102314
|
}
|
|
102049
102315
|
if (subcommand === "add") {
|
|
102050
|
-
const
|
|
102051
|
-
if (!
|
|
102316
|
+
const text7 = rest.join(" ").trim();
|
|
102317
|
+
if (!text7) throw new Error("Missing IdeaBucket text for add.");
|
|
102052
102318
|
const scheduledSendAt = typeof flags["scheduled-at"] === "string" ? parseUnixSecondsFlag(flags["scheduled-at"], "--scheduled-at") : void 0;
|
|
102053
102319
|
printJson2(await client2.addIdeaBucketText({
|
|
102054
|
-
text:
|
|
102320
|
+
text: text7,
|
|
102055
102321
|
chatId: typeof flags.chat === "string" ? flags.chat : void 0,
|
|
102056
102322
|
bucketId: typeof flags.bucket === "string" ? flags.bucket : void 0,
|
|
102057
102323
|
scheduledSendAt,
|
|
@@ -102145,11 +102411,11 @@ function renderRemoteCommandEvent(event) {
|
|
|
102145
102411
|
if (event.event_kind === "output") {
|
|
102146
102412
|
const raw = typeof event.payload.text === "string" ? event.payload.text : "";
|
|
102147
102413
|
const limit = 24e3;
|
|
102148
|
-
const
|
|
102414
|
+
const text7 = escapeTerminalControls(raw.slice(0, limit));
|
|
102149
102415
|
const omitted = raw.length > limit ? `
|
|
102150
102416
|
[${raw.length - limit} characters omitted from this display]` : "";
|
|
102151
102417
|
return `Unreviewed command output (inert) ${identity2}:
|
|
102152
|
-
${
|
|
102418
|
+
${text7}${omitted}`;
|
|
102153
102419
|
}
|
|
102154
102420
|
if (event.event_kind === "output_truncated") {
|
|
102155
102421
|
return `Command output was truncated upstream (${identity2}); displayed output does not cover the full process transcript.`;
|
|
@@ -102828,19 +103094,19 @@ ${deleted}/${resolved.length} chat(s) deleted.`);
|
|
|
102828
103094
|
if (embed.type === "app_skill_use" && embed.appId === "videos" && (embed.skillId === "get_transcript" || embed.skillId === "get-transcript") && embed.content) {
|
|
102829
103095
|
const results = embed.content.results ?? embed.content.data ?? [];
|
|
102830
103096
|
if (Array.isArray(results) && results.length > 0) {
|
|
102831
|
-
let
|
|
103097
|
+
let text7 = "";
|
|
102832
103098
|
for (const r of results) {
|
|
102833
103099
|
const meta = r.metadata;
|
|
102834
|
-
if (meta?.title)
|
|
103100
|
+
if (meta?.title) text7 += `# ${meta.title}
|
|
102835
103101
|
|
|
102836
103102
|
`;
|
|
102837
|
-
if (r.url)
|
|
103103
|
+
if (r.url) text7 += `Source: ${r.url}
|
|
102838
103104
|
|
|
102839
103105
|
`;
|
|
102840
|
-
|
|
103106
|
+
text7 += String(
|
|
102841
103107
|
r.transcript ?? r.formatted_transcript ?? r.text ?? r.content ?? ""
|
|
102842
103108
|
);
|
|
102843
|
-
|
|
103109
|
+
text7 += "\n\n---\n\n";
|
|
102844
103110
|
}
|
|
102845
103111
|
let fname = `${eid.slice(0, 8)}_transcript.md`;
|
|
102846
103112
|
const firstMeta = results[0]?.metadata;
|
|
@@ -102850,7 +103116,7 @@ ${deleted}/${resolved.length} chat(s) deleted.`);
|
|
|
102850
103116
|
transcriptEmbeds.push({
|
|
102851
103117
|
embedId: eid,
|
|
102852
103118
|
filename: fname,
|
|
102853
|
-
content:
|
|
103119
|
+
content: text7
|
|
102854
103120
|
});
|
|
102855
103121
|
}
|
|
102856
103122
|
}
|
|
@@ -103533,8 +103799,8 @@ async function syncCliBoundWorkflowFiles(client2, workflow, flags) {
|
|
|
103533
103799
|
const contents = await client2.listProjectItems(project.projectId, context);
|
|
103534
103800
|
for (const item of contents.items.filter((item2) => item2.item_type === "workflow")) {
|
|
103535
103801
|
if (await decryptOptionalProjectField2(item.target_id_encrypted, project.projectKey) !== workflow.id) continue;
|
|
103536
|
-
const
|
|
103537
|
-
const metadata =
|
|
103802
|
+
const text7 = await decryptOptionalProjectField2(item.encrypted_metadata, project.projectKey);
|
|
103803
|
+
const metadata = text7 ? JSON.parse(text7) : {};
|
|
103538
103804
|
const binding = metadata.remote_workflow_file;
|
|
103539
103805
|
if (!binding) continue;
|
|
103540
103806
|
const source = (await client2.listProjectSources(project.projectId, context)).find((item2) => item2.source_id === binding.source_id);
|
|
@@ -103824,10 +104090,10 @@ async function handleWorkflows(client2, subcommand, rest, flags, redactor) {
|
|
|
103824
104090
|
return;
|
|
103825
104091
|
}
|
|
103826
104092
|
if (subcommand === "input") {
|
|
103827
|
-
const
|
|
103828
|
-
if (!
|
|
104093
|
+
const text7 = typeof flags.text === "string" ? flags.text : rest.join(" ").trim();
|
|
104094
|
+
if (!text7) throw new Error('Missing workflow input text. Example: openmates workflows ask "alert me if it rains"');
|
|
103829
104095
|
const session = await client2.startWorkflowInput({
|
|
103830
|
-
text:
|
|
104096
|
+
text: text7,
|
|
103831
104097
|
selectedWorkflowId: typeof flags["workflow-id"] === "string" ? flags["workflow-id"] : void 0,
|
|
103832
104098
|
selectedProjectId: typeof flags["project-id"] === "string" ? flags["project-id"] : void 0,
|
|
103833
104099
|
timezone: typeof flags.timezone === "string" ? flags.timezone : Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
@@ -103874,9 +104140,9 @@ async function handleWorkflows(client2, subcommand, rest, flags, redactor) {
|
|
|
103874
104140
|
}
|
|
103875
104141
|
if (subcommand === "input-follow-up") {
|
|
103876
104142
|
const sessionId = rest[0];
|
|
103877
|
-
const
|
|
103878
|
-
if (!sessionId || !
|
|
103879
|
-
const session = await client2.followUpWorkflowInput(sessionId,
|
|
104143
|
+
const text7 = typeof flags.text === "string" ? flags.text : rest.slice(1).join(" ").trim();
|
|
104144
|
+
if (!sessionId || !text7) throw new Error('Missing session ID or text. Example: openmates workflows input-follow-up <session-id> "make it weekdays only"');
|
|
104145
|
+
const session = await client2.followUpWorkflowInput(sessionId, text7);
|
|
103880
104146
|
if (flags.json === true) {
|
|
103881
104147
|
printJson2(session);
|
|
103882
104148
|
} else {
|
|
@@ -105069,10 +105335,10 @@ async function streamCodeRunToTerminal(url, jsonMode) {
|
|
|
105069
105335
|
const payload = message.payload ?? {};
|
|
105070
105336
|
if (message.type === "code_run_event") {
|
|
105071
105337
|
const kind = String(payload.kind ?? "status");
|
|
105072
|
-
const
|
|
105338
|
+
const text7 = String(payload.text ?? "");
|
|
105073
105339
|
if (!jsonMode) {
|
|
105074
|
-
if (kind === "stdout") process.stdout.write(
|
|
105075
|
-
else process.stderr.write(
|
|
105340
|
+
if (kind === "stdout") process.stdout.write(text7);
|
|
105341
|
+
else process.stderr.write(text7);
|
|
105076
105342
|
}
|
|
105077
105343
|
} else if (message.type === "code_run_update") {
|
|
105078
105344
|
lastStatus = { ...lastStatus, ...payload };
|
|
@@ -107545,8 +107811,8 @@ function resolveApiKey(flags) {
|
|
|
107545
107811
|
function printJson2(value) {
|
|
107546
107812
|
console.log(JSON.stringify(value, null, 2));
|
|
107547
107813
|
}
|
|
107548
|
-
function header(
|
|
107549
|
-
process.stdout.write(`\x1B[1m${
|
|
107814
|
+
function header(text7) {
|
|
107815
|
+
process.stdout.write(`\x1B[1m${text7}\x1B[0m
|
|
107550
107816
|
`);
|
|
107551
107817
|
}
|
|
107552
107818
|
function kv(key, value, keyWidth = 16) {
|
|
@@ -108312,15 +108578,15 @@ async function acceptChatTaskProposals(client2, chatId, proposals, fallbackText)
|
|
|
108312
108578
|
}
|
|
108313
108579
|
return accepted;
|
|
108314
108580
|
}
|
|
108315
|
-
function buildTaskProposalFallbackText(
|
|
108581
|
+
function buildTaskProposalFallbackText(text7) {
|
|
108316
108582
|
const seen = /* @__PURE__ */ new Set();
|
|
108317
|
-
const bulletLines =
|
|
108583
|
+
const bulletLines = text7.split("\n").map((line) => line.trim()).filter((line) => /^[-*•]\s+/.test(line)).map((line) => line.replace(/^([-*•]\s*)\[[ xX]\]\s*/, "$1")).filter((line) => {
|
|
108318
108584
|
const key = line.replace(/^[-*•]\s+/, "").trim().toLowerCase();
|
|
108319
108585
|
if (seen.has(key)) return false;
|
|
108320
108586
|
seen.add(key);
|
|
108321
108587
|
return true;
|
|
108322
108588
|
});
|
|
108323
|
-
return bulletLines.length > 0 ? bulletLines.join("\n") :
|
|
108589
|
+
return bulletLines.length > 0 ? bulletLines.join("\n") : text7;
|
|
108324
108590
|
}
|
|
108325
108591
|
function printIncognitoNoHistoryNotice(json) {
|
|
108326
108592
|
const message = "Incognito chats are not stored. There is no incognito history to show or clear.";
|
|
@@ -108354,8 +108620,8 @@ function renderEmbedFromMeta(embedId, meta) {
|
|
|
108354
108620
|
process.stdout.write(`\x1B[2m\u2514\u2500 openmates embeds show ${shortId}\x1B[0m
|
|
108355
108621
|
`);
|
|
108356
108622
|
}
|
|
108357
|
-
async function renderMessageText(
|
|
108358
|
-
const lines =
|
|
108623
|
+
async function renderMessageText(text7, embedRefIndex, client2) {
|
|
108624
|
+
const lines = text7.split("\n");
|
|
108359
108625
|
const outputLines = [];
|
|
108360
108626
|
for (const line of lines) {
|
|
108361
108627
|
const blockMatch = line.match(/^\s*\[!?\]\(embed:([^)]+)\)\s*$/);
|
|
@@ -108612,6 +108878,12 @@ ${data.description}
|
|
|
108612
108878
|
}
|
|
108613
108879
|
console.log();
|
|
108614
108880
|
}
|
|
108881
|
+
if (data.memories?.length) {
|
|
108882
|
+
console.log("Memories \xB7 App-provided \xB7 Read-only \xB7 Loaded automatically when relevant");
|
|
108883
|
+
for (const memory of data.memories) console.log(` ${memory.title} (${memory.id})
|
|
108884
|
+
${memory.description}`);
|
|
108885
|
+
console.log();
|
|
108886
|
+
}
|
|
108615
108887
|
const focuses = data.focus_modes ?? [];
|
|
108616
108888
|
if (focuses.length > 0) {
|
|
108617
108889
|
process.stdout.write(`\x1B[1mFocus modes\x1B[0m
|
|
@@ -108779,8 +109051,8 @@ No example chats are linked to ${label3} yet.`);
|
|
|
108779
109051
|
console.log(`All examples: openmates apps examples ${appId}${skillId ? ` ${skillId}` : ""}`);
|
|
108780
109052
|
}
|
|
108781
109053
|
}
|
|
108782
|
-
function wrapText(
|
|
108783
|
-
const words =
|
|
109054
|
+
function wrapText(text7, width) {
|
|
109055
|
+
const words = text7.split(" ");
|
|
108784
109056
|
const lines = [];
|
|
108785
109057
|
let current = "";
|
|
108786
109058
|
for (const w of words) {
|