openmates 0.15.0-alpha.22 → 0.15.0-alpha.24
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-47BFVCB4.js → chunk-F4JZMA6W.js} +159 -64
- package/dist/cli.js +1 -1
- package/dist/index.d.ts +37 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
} from "./chunk-AXNRPVLE.js";
|
|
5
5
|
|
|
6
6
|
// src/client.ts
|
|
7
|
-
import { randomUUID as randomUUID5 } from "crypto";
|
|
7
|
+
import { createHash as createHash6, randomUUID as randomUUID5 } from "crypto";
|
|
8
8
|
import { arch, platform as platform2, release } from "os";
|
|
9
9
|
import { createInterface as createInterface2 } from "readline/promises";
|
|
10
10
|
import { stdin as stdin2, stdout } from "process";
|
|
@@ -3540,9 +3540,11 @@ function stripTimer(job) {
|
|
|
3540
3540
|
}
|
|
3541
3541
|
|
|
3542
3542
|
// src/tasksCli.ts
|
|
3543
|
-
import { createHash as createHash5, randomBytes as randomBytes2, randomUUID as randomUUID4 } from "crypto";
|
|
3543
|
+
import { createHash as createHash5, createHmac, hkdfSync, randomBytes as randomBytes2, randomUUID as randomUUID4 } from "crypto";
|
|
3544
3544
|
var TASK_STATUSES2 = ["backlog", "todo", "in_progress", "blocked", "done"];
|
|
3545
3545
|
var DEFAULT_STANDALONE_PREFIX = "TASK";
|
|
3546
|
+
var PRIORITY_LEVELS = ["none", "low", "medium", "high", "urgent"];
|
|
3547
|
+
var LABEL_INDEX_INFO = "openmates-task-label-index-v1";
|
|
3546
3548
|
function normalizeTaskStatus(value) {
|
|
3547
3549
|
if (value === void 0) return void 0;
|
|
3548
3550
|
if (TASK_STATUSES2.includes(value)) return value;
|
|
@@ -3566,12 +3568,43 @@ function parseDueAt(value) {
|
|
|
3566
3568
|
if (Number.isNaN(parsed)) throw new Error(`Invalid --due value '${value}'.`);
|
|
3567
3569
|
return Math.floor(parsed / 1e3);
|
|
3568
3570
|
}
|
|
3571
|
+
function normalizeLabels(labels) {
|
|
3572
|
+
const output = [];
|
|
3573
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3574
|
+
for (const label of labels ?? []) {
|
|
3575
|
+
const normalized = label.trim().toLowerCase().replace(/\s+/g, " ");
|
|
3576
|
+
if (!normalized || seen.has(normalized)) continue;
|
|
3577
|
+
seen.add(normalized);
|
|
3578
|
+
output.push(normalized);
|
|
3579
|
+
}
|
|
3580
|
+
return output;
|
|
3581
|
+
}
|
|
3582
|
+
function labelHashes(masterKey, labels) {
|
|
3583
|
+
const indexKey = Buffer.from(hkdfSync("sha256", Buffer.from(masterKey), Buffer.alloc(0), LABEL_INDEX_INFO, 32));
|
|
3584
|
+
return normalizeLabels(labels).map((label) => createHmac("sha256", indexKey).update(label).digest("hex"));
|
|
3585
|
+
}
|
|
3586
|
+
function normalizeTaskPriority(value) {
|
|
3587
|
+
if (value === void 0) return void 0;
|
|
3588
|
+
if (value === null) return 0;
|
|
3589
|
+
if (typeof value === "number") {
|
|
3590
|
+
if (!Number.isInteger(value) || value < 0 || value > 4) throw new Error(`Invalid task priority '${value}'.`);
|
|
3591
|
+
return value;
|
|
3592
|
+
}
|
|
3593
|
+
const normalized = value.trim().toLowerCase();
|
|
3594
|
+
const index = PRIORITY_LEVELS.indexOf(normalized);
|
|
3595
|
+
if (index < 0) throw new Error(`Unknown task priority '${value}'. Expected one of: ${PRIORITY_LEVELS.join(", ")}`);
|
|
3596
|
+
return index;
|
|
3597
|
+
}
|
|
3598
|
+
function taskPriorityLevel(priority) {
|
|
3599
|
+
return PRIORITY_LEVELS[Math.max(0, Math.min(4, Math.trunc(priority ?? 0)))] ?? "none";
|
|
3600
|
+
}
|
|
3569
3601
|
async function buildCreateUserTaskInput(masterKey, input) {
|
|
3570
3602
|
const taskKey = randomBytes2(32);
|
|
3571
3603
|
const encryptedTaskKey = await encryptBytesWithAesGcm(taskKey, masterKey);
|
|
3572
3604
|
const timestamp = nowSeconds();
|
|
3573
3605
|
const assignee = parseAssignee(input.assign);
|
|
3574
3606
|
const linkedProjectIds = input.projectIds ?? [];
|
|
3607
|
+
const labels = normalizeLabels(input.labels ?? input.tags ?? []);
|
|
3575
3608
|
const status = input.status ?? (assignee.assigneeType === "ai" && !input.dueAt ? "in_progress" : "todo");
|
|
3576
3609
|
return {
|
|
3577
3610
|
task_id: randomUUIDCompat(),
|
|
@@ -3580,7 +3613,9 @@ async function buildCreateUserTaskInput(masterKey, input) {
|
|
|
3580
3613
|
encrypted_task_key: encryptedTaskKey,
|
|
3581
3614
|
encrypted_title: await encryptWithAesGcmCombined(input.title, taskKey),
|
|
3582
3615
|
encrypted_description: await encryptWithAesGcmCombined(input.description ?? "", taskKey),
|
|
3583
|
-
|
|
3616
|
+
encrypted_labels: await encryptWithAesGcmCombined(JSON.stringify(labels), taskKey),
|
|
3617
|
+
encrypted_tags: await encryptWithAesGcmCombined(JSON.stringify(labels), taskKey),
|
|
3618
|
+
label_hashes: labelHashes(masterKey, labels),
|
|
3584
3619
|
encrypted_linked_project_ids: await encryptWithAesGcmCombined(JSON.stringify(linkedProjectIds), taskKey),
|
|
3585
3620
|
status,
|
|
3586
3621
|
assignee_type: assignee.assigneeType,
|
|
@@ -3589,7 +3624,7 @@ async function buildCreateUserTaskInput(masterKey, input) {
|
|
|
3589
3624
|
linked_project_ids: linkedProjectIds,
|
|
3590
3625
|
plan_id: input.planId ?? null,
|
|
3591
3626
|
due_at: input.dueAt ?? null,
|
|
3592
|
-
priority: 0,
|
|
3627
|
+
priority: normalizeTaskPriority(input.priority) ?? 0,
|
|
3593
3628
|
position: timestamp,
|
|
3594
3629
|
created_at: timestamp,
|
|
3595
3630
|
updated_at: timestamp
|
|
@@ -3612,20 +3647,32 @@ async function buildUpdateUserTaskInput(task, masterKey, input) {
|
|
|
3612
3647
|
patch.encrypted_linked_project_ids = await encryptWithAesGcmCombined(JSON.stringify(input.projectIds), taskKey);
|
|
3613
3648
|
}
|
|
3614
3649
|
if (input.planId !== void 0) patch.plan_id = input.planId;
|
|
3650
|
+
const priority = normalizeTaskPriority(input.priority);
|
|
3651
|
+
if (priority !== void 0) patch.priority = priority;
|
|
3652
|
+
const replaceLabels = input.labels ?? input.tags;
|
|
3653
|
+
if (replaceLabels !== void 0 || input.addLabels !== void 0 || input.addTags !== void 0 || input.removeLabels !== void 0 || input.removeTags !== void 0) {
|
|
3654
|
+
const remove = new Set(normalizeLabels([...input.removeLabels ?? [], ...input.removeTags ?? []]));
|
|
3655
|
+
const base = replaceLabels !== void 0 ? normalizeLabels(replaceLabels) : task.labels;
|
|
3656
|
+
const labels = normalizeLabels([...base.filter((label) => !remove.has(label)), ...input.addLabels ?? [], ...input.addTags ?? []]);
|
|
3657
|
+
patch.encrypted_labels = await encryptWithAesGcmCombined(JSON.stringify(labels), taskKey);
|
|
3658
|
+
patch.encrypted_tags = await encryptWithAesGcmCombined(JSON.stringify(labels), taskKey);
|
|
3659
|
+
patch.label_hashes = labelHashes(masterKey, labels);
|
|
3660
|
+
}
|
|
3615
3661
|
return patch;
|
|
3616
3662
|
}
|
|
3617
3663
|
async function decryptUserTask(record, masterKey) {
|
|
3618
3664
|
if (record.source === "workflow_run") return workflowProjectionToTask(record);
|
|
3619
3665
|
if (typeof record.version !== "number") throw new Error(`Task ${record.task_id} is missing version.`);
|
|
3620
3666
|
const taskKey = await taskKeyFromRecord(record, masterKey);
|
|
3621
|
-
const
|
|
3667
|
+
const labels = parseStringArray(await decryptOptional(record.encrypted_labels || record.encrypted_tags, taskKey));
|
|
3622
3668
|
const linkedProjectIds = parseStringArray(await decryptOptional(record.encrypted_linked_project_ids, taskKey));
|
|
3623
3669
|
return {
|
|
3624
3670
|
taskId: record.task_id,
|
|
3625
3671
|
shortId: record.short_id || deriveShortId(record),
|
|
3626
3672
|
title: await decryptOptional(record.encrypted_title, taskKey) || "(untitled task)",
|
|
3627
3673
|
description: await decryptOptional(record.encrypted_description, taskKey),
|
|
3628
|
-
|
|
3674
|
+
labels,
|
|
3675
|
+
tags: labels,
|
|
3629
3676
|
latestInstruction: await decryptOptional(record.encrypted_latest_instruction, taskKey),
|
|
3630
3677
|
status: record.status,
|
|
3631
3678
|
assigneeType: record.assignee_type,
|
|
@@ -3635,6 +3682,7 @@ async function decryptUserTask(record, masterKey) {
|
|
|
3635
3682
|
planId: record.plan_id ?? null,
|
|
3636
3683
|
dueAt: record.due_at ?? null,
|
|
3637
3684
|
priority: record.priority ?? 0,
|
|
3685
|
+
priorityLevel: taskPriorityLevel(record.priority),
|
|
3638
3686
|
position: record.position ?? 0,
|
|
3639
3687
|
queueState: record.queue_state ?? "none",
|
|
3640
3688
|
blockedReasonCode: record.blocked_reason_code ?? null,
|
|
@@ -3651,6 +3699,7 @@ function workflowProjectionToTask(record) {
|
|
|
3651
3699
|
shortId: record.short_id || workflowProjectionShortId(record),
|
|
3652
3700
|
title: record.title || "Workflow run",
|
|
3653
3701
|
description: record.blocked_message ?? "",
|
|
3702
|
+
labels: [],
|
|
3654
3703
|
tags: [],
|
|
3655
3704
|
latestInstruction: "",
|
|
3656
3705
|
status: record.status,
|
|
@@ -3661,6 +3710,7 @@ function workflowProjectionToTask(record) {
|
|
|
3661
3710
|
planId: null,
|
|
3662
3711
|
dueAt: record.due_at ?? null,
|
|
3663
3712
|
priority: record.priority ?? 0,
|
|
3713
|
+
priorityLevel: taskPriorityLevel(record.priority),
|
|
3664
3714
|
position: record.position ?? 0,
|
|
3665
3715
|
queueState: String(record.run_status ?? "workflow"),
|
|
3666
3716
|
blockedReasonCode: blockedReason,
|
|
@@ -3690,9 +3740,9 @@ function findTask(tasks, id) {
|
|
|
3690
3740
|
}
|
|
3691
3741
|
function renderTaskList(tasks) {
|
|
3692
3742
|
if (tasks.length === 0) return "No tasks found.";
|
|
3693
|
-
const lines = ["Tasks", "ID Status
|
|
3743
|
+
const lines = ["Tasks", "ID Status Priority Labels Title"];
|
|
3694
3744
|
for (const task of tasks) {
|
|
3695
|
-
lines.push(`${pad(task.shortId, 9)} ${pad(task.status, 12)} ${pad(
|
|
3745
|
+
lines.push(`${pad(task.shortId, 9)} ${pad(task.status, 12)} ${pad(task.priorityLevel, 9)} ${pad(task.labels.join(","), 19)} ${task.title}`);
|
|
3696
3746
|
}
|
|
3697
3747
|
return lines.join("\n");
|
|
3698
3748
|
}
|
|
@@ -3701,11 +3751,13 @@ function renderTaskDetail(task) {
|
|
|
3701
3751
|
`Task ${task.shortId}`,
|
|
3702
3752
|
`Title: ${task.title}`,
|
|
3703
3753
|
`Status: ${task.status}`,
|
|
3754
|
+
`Priority: ${task.priorityLevel}`,
|
|
3704
3755
|
`Assignee: ${assigneeLabel(task)}`,
|
|
3705
3756
|
`Queue: ${task.queueState}`,
|
|
3706
3757
|
`Task ID: ${task.taskId}`
|
|
3707
3758
|
];
|
|
3708
3759
|
if (task.description) lines.push(`Description: ${task.description}`);
|
|
3760
|
+
if (task.labels.length > 0) lines.push(`Labels: ${task.labels.join(", ")}`);
|
|
3709
3761
|
if (task.primaryChatId) lines.push(`Chat: ${task.primaryChatId}`);
|
|
3710
3762
|
if (task.linkedProjectIds.length > 0) lines.push(`Projects: ${task.linkedProjectIds.join(", ")}`);
|
|
3711
3763
|
if (task.planId) lines.push(`Plan: ${task.planId}`);
|
|
@@ -3801,7 +3853,8 @@ function normalizeUnixSeconds(value, fallback) {
|
|
|
3801
3853
|
}
|
|
3802
3854
|
function getClientMessagesVersionForSync(cached) {
|
|
3803
3855
|
if (cached.messages.length === 0) return 0;
|
|
3804
|
-
|
|
3856
|
+
const messagesVersion = typeof cached.details.messages_v === "number" ? cached.details.messages_v : 0;
|
|
3857
|
+
return Math.min(messagesVersion, cached.messages.length);
|
|
3805
3858
|
}
|
|
3806
3859
|
var INTEREST_TAG_IDS = [
|
|
3807
3860
|
"software_development",
|
|
@@ -4035,7 +4088,10 @@ function assertTaskPersistPayloadEncrypted(payload) {
|
|
|
4035
4088
|
"blocked_reason_code",
|
|
4036
4089
|
"created_at",
|
|
4037
4090
|
"key_wrappers",
|
|
4091
|
+
"label_hashes",
|
|
4038
4092
|
"linked_project_ids",
|
|
4093
|
+
"plan_id",
|
|
4094
|
+
"plan_step_id",
|
|
4039
4095
|
"position",
|
|
4040
4096
|
"primary_chat_id",
|
|
4041
4097
|
"priority",
|
|
@@ -4854,7 +4910,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
4854
4910
|
if (!userId) {
|
|
4855
4911
|
throw new Error("Could not resolve current user id for local connected-account connector.");
|
|
4856
4912
|
}
|
|
4857
|
-
const { createHash:
|
|
4913
|
+
const { createHash: createHash10 } = await import("crypto");
|
|
4858
4914
|
const accountId = randomUUID5();
|
|
4859
4915
|
const masterKey = this.getMasterKeyBytes();
|
|
4860
4916
|
const encryptLocalConnectorValue = async (value) => {
|
|
@@ -4863,9 +4919,9 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
4863
4919
|
};
|
|
4864
4920
|
const payload = {
|
|
4865
4921
|
id: accountId,
|
|
4866
|
-
hashed_user_id:
|
|
4922
|
+
hashed_user_id: createHash10("sha256").update(userId).digest("hex"),
|
|
4867
4923
|
encrypted_provider_type: await encryptLocalConnectorValue(input.provider_id),
|
|
4868
|
-
provider_type_hash:
|
|
4924
|
+
provider_type_hash: createHash10("sha256").update(input.provider_id).digest("hex"),
|
|
4869
4925
|
encrypted_account_label: await encryptLocalConnectorValue(input.label),
|
|
4870
4926
|
encrypted_capabilities: await encryptLocalConnectorValue(input.capabilities),
|
|
4871
4927
|
encrypted_app_permissions: await encryptLocalConnectorValue({
|
|
@@ -5306,14 +5362,26 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
5306
5362
|
async decryptChatKey(encryptedChatKey, masterKey) {
|
|
5307
5363
|
return decryptBytesWithAesGcm(encryptedChatKey, masterKey);
|
|
5308
5364
|
}
|
|
5365
|
+
getMasterWrapperEncryptedChatKey(cache, chatId) {
|
|
5366
|
+
const hashedChatId = createHash6("sha256").update(chatId).digest("hex");
|
|
5367
|
+
const wrapper = (cache?.chatKeyWrappers ?? []).find(
|
|
5368
|
+
(entry) => entry.key_type === "master" && entry.hashed_chat_id === hashedChatId && typeof entry.encrypted_chat_key === "string"
|
|
5369
|
+
);
|
|
5370
|
+
return typeof wrapper?.encrypted_chat_key === "string" ? wrapper.encrypted_chat_key : null;
|
|
5371
|
+
}
|
|
5372
|
+
async resolveChatKey(cache, cached, masterKey) {
|
|
5373
|
+
const chatId = String(cached.details.id ?? "");
|
|
5374
|
+
const wrapperKey = chatId ? this.getMasterWrapperEncryptedChatKey(cache, chatId) : null;
|
|
5375
|
+
const encryptedChatKey = wrapperKey ?? (typeof cached.details.encrypted_chat_key === "string" ? cached.details.encrypted_chat_key : null);
|
|
5376
|
+
return encryptedChatKey ? this.decryptChatKey(encryptedChatKey, masterKey) : null;
|
|
5377
|
+
}
|
|
5309
5378
|
/**
|
|
5310
5379
|
* Decrypt a single chat record from the sync cache into a ChatListItem.
|
|
5311
5380
|
*/
|
|
5312
|
-
async decryptChatListItem(cached, masterKey) {
|
|
5381
|
+
async decryptChatListItem(cached, masterKey, cache = loadSyncCache()) {
|
|
5313
5382
|
const d = cached.details;
|
|
5314
5383
|
const id = String(d.id ?? "");
|
|
5315
|
-
const
|
|
5316
|
-
const chatKeyBytes = encKey ? await this.decryptChatKey(encKey, masterKey) : null;
|
|
5384
|
+
const chatKeyBytes = await this.resolveChatKey(cache, cached, masterKey);
|
|
5317
5385
|
const title = typeof d.encrypted_title === "string" && chatKeyBytes ? await decryptWithAesGcmCombined(d.encrypted_title, chatKeyBytes) : null;
|
|
5318
5386
|
const summary = typeof d.encrypted_chat_summary === "string" && chatKeyBytes ? await decryptWithAesGcmCombined(
|
|
5319
5387
|
d.encrypted_chat_summary,
|
|
@@ -5338,7 +5406,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
5338
5406
|
const slice = cache.chats.slice(offset, offset + limit);
|
|
5339
5407
|
const output = [];
|
|
5340
5408
|
for (const chat of slice) {
|
|
5341
|
-
output.push(await this.decryptChatListItem(chat, masterKey));
|
|
5409
|
+
output.push(await this.decryptChatListItem(chat, masterKey, cache));
|
|
5342
5410
|
}
|
|
5343
5411
|
return {
|
|
5344
5412
|
chats: output,
|
|
@@ -5528,7 +5596,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
5528
5596
|
* @param query Full UUID, 8-char short ID, or chat title.
|
|
5529
5597
|
*/
|
|
5530
5598
|
async getChatMessages(query) {
|
|
5531
|
-
const cache = await this.ensureSynced();
|
|
5599
|
+
const cache = await this.ensureSynced(true);
|
|
5532
5600
|
const masterKey = this.getMasterKeyBytes();
|
|
5533
5601
|
const normalized = query.trim().toLowerCase();
|
|
5534
5602
|
let found;
|
|
@@ -5547,7 +5615,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
5547
5615
|
}
|
|
5548
5616
|
if (!found) {
|
|
5549
5617
|
for (const cached of cache.chats) {
|
|
5550
|
-
const item = await this.decryptChatListItem(cached, masterKey);
|
|
5618
|
+
const item = await this.decryptChatListItem(cached, masterKey, cache);
|
|
5551
5619
|
const title = (item.title ?? "").toLowerCase();
|
|
5552
5620
|
if (title === normalized) {
|
|
5553
5621
|
found = cached;
|
|
@@ -5570,9 +5638,8 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
5570
5638
|
`Chat '${query}' not found. Try 'openmates chats search "${query}"' to browse matches.`
|
|
5571
5639
|
);
|
|
5572
5640
|
}
|
|
5573
|
-
const chatItem = await this.decryptChatListItem(found, masterKey);
|
|
5574
|
-
const
|
|
5575
|
-
const chatKeyBytes = encKey ? await this.decryptChatKey(encKey, masterKey) : null;
|
|
5641
|
+
const chatItem = await this.decryptChatListItem(found, masterKey, cache);
|
|
5642
|
+
const chatKeyBytes = await this.resolveChatKey(cache, found, masterKey);
|
|
5576
5643
|
const messages = [];
|
|
5577
5644
|
for (const raw of found.messages) {
|
|
5578
5645
|
const m = typeof raw === "string" ? JSON.parse(raw) : raw;
|
|
@@ -5591,8 +5658,8 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
5591
5658
|
);
|
|
5592
5659
|
let msgEmbedIds = [];
|
|
5593
5660
|
if (clientMsgId && cache.embeds.length > 0) {
|
|
5594
|
-
const { createHash:
|
|
5595
|
-
const hashed =
|
|
5661
|
+
const { createHash: createHash10 } = await import("crypto");
|
|
5662
|
+
const hashed = createHash10("sha256").update(clientMsgId).digest("hex");
|
|
5596
5663
|
msgEmbedIds = cache.embeds.filter(
|
|
5597
5664
|
(e) => e.hashed_message_id === hashed && // Only include parent embeds (no parent_embed_id).
|
|
5598
5665
|
// Child embeds inherit the parent's key and are loaded
|
|
@@ -5639,8 +5706,8 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
5639
5706
|
);
|
|
5640
5707
|
}
|
|
5641
5708
|
const embedId = String(embed.embed_id ?? embed.id ?? "");
|
|
5642
|
-
const { createHash:
|
|
5643
|
-
const hashedEmbedId =
|
|
5709
|
+
const { createHash: createHash10 } = await import("crypto");
|
|
5710
|
+
const hashedEmbedId = createHash10("sha256").update(embedId).digest("hex");
|
|
5644
5711
|
const embedKeyBytes = await this.resolveEmbedKey(
|
|
5645
5712
|
cache,
|
|
5646
5713
|
masterKey,
|
|
@@ -5748,7 +5815,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
5748
5815
|
async resolveEmbedKey(cache, masterKey, embed, embedId, hashedEmbedId, visited = /* @__PURE__ */ new Set()) {
|
|
5749
5816
|
if (visited.has(embedId)) return null;
|
|
5750
5817
|
visited.add(embedId);
|
|
5751
|
-
const { createHash:
|
|
5818
|
+
const { createHash: createHash10 } = await import("crypto");
|
|
5752
5819
|
const masterKeyEntry = cache.embedKeys.find(
|
|
5753
5820
|
(ek) => ek.hashed_embed_id === hashedEmbedId && String(ek.key_type) === "master"
|
|
5754
5821
|
);
|
|
@@ -5765,7 +5832,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
5765
5832
|
if (chatKeyEntry && typeof chatKeyEntry.encrypted_embed_key === "string") {
|
|
5766
5833
|
const hashedChatId = String(chatKeyEntry.hashed_chat_id ?? "");
|
|
5767
5834
|
const owningChat = cache.chats.find((c) => {
|
|
5768
|
-
const chatHash =
|
|
5835
|
+
const chatHash = createHash10("sha256").update(String(c.details.id ?? "")).digest("hex");
|
|
5769
5836
|
return chatHash === hashedChatId;
|
|
5770
5837
|
});
|
|
5771
5838
|
if (owningChat) {
|
|
@@ -5794,7 +5861,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
5794
5861
|
const parentFullId = String(
|
|
5795
5862
|
parentEmbed2.embed_id ?? parentEmbed2.id ?? ""
|
|
5796
5863
|
);
|
|
5797
|
-
const parentHashedId =
|
|
5864
|
+
const parentHashedId = createHash10("sha256").update(parentFullId).digest("hex");
|
|
5798
5865
|
const parentKey = await this.resolveEmbedKey(
|
|
5799
5866
|
cache,
|
|
5800
5867
|
masterKey,
|
|
@@ -5886,9 +5953,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
5886
5953
|
(c) => String(c.details.id ?? "") === chatId || String(c.details.id ?? "").startsWith(chatId)
|
|
5887
5954
|
);
|
|
5888
5955
|
if (!found) return [];
|
|
5889
|
-
const
|
|
5890
|
-
if (!encKey) return [];
|
|
5891
|
-
const chatKeyBytes = await this.decryptChatKey(encKey, masterKey);
|
|
5956
|
+
const chatKeyBytes = await this.resolveChatKey(cache, found, masterKey);
|
|
5892
5957
|
if (!chatKeyBytes) return [];
|
|
5893
5958
|
const encSuggestions = typeof found.details.encrypted_follow_up_request_suggestions === "string" ? found.details.encrypted_follow_up_request_suggestions : null;
|
|
5894
5959
|
if (!encSuggestions) return [];
|
|
@@ -7783,6 +7848,8 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
7783
7848
|
if (filters.status) params.set("status", filters.status);
|
|
7784
7849
|
if (filters.chatId) params.set("chat_id", filters.chatId);
|
|
7785
7850
|
if (filters.projectId) params.set("project_id", filters.projectId);
|
|
7851
|
+
for (const labelHash of filters.labelHashes ?? []) params.append("label_hash", labelHash);
|
|
7852
|
+
if (filters.priority !== void 0) params.set("priority", String(filters.priority));
|
|
7786
7853
|
const limit = filters.limit;
|
|
7787
7854
|
if (Number.isSafeInteger(limit) && limit !== void 0 && limit > 0) params.set("limit", String(limit));
|
|
7788
7855
|
const query = params.toString();
|
|
@@ -8837,7 +8904,7 @@ Required: ${schema.required.join(", ")}`
|
|
|
8837
8904
|
const session = this.requireSession();
|
|
8838
8905
|
const masterKey = base64ToBytes(session.masterKeyExportedB64);
|
|
8839
8906
|
const cache = await this.ensureSynced();
|
|
8840
|
-
const { createHash:
|
|
8907
|
+
const { createHash: createHash10 } = await import("crypto");
|
|
8841
8908
|
const embed = cache.embeds.find(
|
|
8842
8909
|
(e) => String(e.embed_id ?? "").startsWith(embedIdOrShort) || String(e.id ?? "").startsWith(embedIdOrShort)
|
|
8843
8910
|
);
|
|
@@ -8845,7 +8912,7 @@ Required: ${schema.required.join(", ")}`
|
|
|
8845
8912
|
throw new Error(`Embed '${embedIdOrShort}' not found in local cache.`);
|
|
8846
8913
|
}
|
|
8847
8914
|
const embedId = String(embed.embed_id ?? embed.id ?? "");
|
|
8848
|
-
const hashedEmbedId =
|
|
8915
|
+
const hashedEmbedId = createHash10("sha256").update(embedId).digest("hex");
|
|
8849
8916
|
const embedKeyBytes = await this.resolveEmbedKey(
|
|
8850
8917
|
cache,
|
|
8851
8918
|
masterKey,
|
|
@@ -8953,8 +9020,8 @@ Required: ${schema.required.join(", ")}`
|
|
|
8953
9020
|
if (!embed) {
|
|
8954
9021
|
throw new Error(`Embed '${embedId}' not found in local cache. Run 'openmates chats list' to sync first.`);
|
|
8955
9022
|
}
|
|
8956
|
-
const { createHash:
|
|
8957
|
-
const hashedEmbedId =
|
|
9023
|
+
const { createHash: createHash10 } = await import("crypto");
|
|
9024
|
+
const hashedEmbedId = createHash10("sha256").update(embedId).digest("hex");
|
|
8958
9025
|
const embedKey = await this.resolveEmbedKey(
|
|
8959
9026
|
cache,
|
|
8960
9027
|
masterKey,
|
|
@@ -9048,8 +9115,8 @@ Required: ${schema.required.join(", ")}`
|
|
|
9048
9115
|
if (!embed) {
|
|
9049
9116
|
throw new Error(`Embed '${embedId}' not found in local cache. Run 'openmates chats list' to sync first.`);
|
|
9050
9117
|
}
|
|
9051
|
-
const { createHash:
|
|
9052
|
-
const hashedEmbedId =
|
|
9118
|
+
const { createHash: createHash10 } = await import("crypto");
|
|
9119
|
+
const hashedEmbedId = createHash10("sha256").update(embedId).digest("hex");
|
|
9053
9120
|
const embedKey = await this.resolveEmbedKey(
|
|
9054
9121
|
cache,
|
|
9055
9122
|
masterKey,
|
|
@@ -9321,6 +9388,7 @@ Required: ${schema.required.join(", ")}`
|
|
|
9321
9388
|
const chats = [];
|
|
9322
9389
|
const embeds = [];
|
|
9323
9390
|
const embedKeys = [];
|
|
9391
|
+
const chatKeyWrappers = [];
|
|
9324
9392
|
let newChatSuggestions = [];
|
|
9325
9393
|
let totalChatCount = 0;
|
|
9326
9394
|
let reconciliation = { authoritative: false };
|
|
@@ -9348,6 +9416,7 @@ Required: ${schema.required.join(", ")}`
|
|
|
9348
9416
|
}
|
|
9349
9417
|
if (p.embeds) embeds.push(...p.embeds);
|
|
9350
9418
|
if (p.embed_keys) embedKeys.push(...p.embed_keys);
|
|
9419
|
+
if (p.chat_key_wrappers) chatKeyWrappers.push(...p.chat_key_wrappers);
|
|
9351
9420
|
} else if (frame.type === "phase_2_last_20_chats_ready") {
|
|
9352
9421
|
const p = frame.payload;
|
|
9353
9422
|
totalChatCount = p.total_chat_count ?? 0;
|
|
@@ -9361,6 +9430,7 @@ Required: ${schema.required.join(", ")}`
|
|
|
9361
9430
|
if (!details || typeof details.id !== "string") continue;
|
|
9362
9431
|
chats.push({ details, messages: [] });
|
|
9363
9432
|
}
|
|
9433
|
+
if (p.chat_key_wrappers) chatKeyWrappers.push(...p.chat_key_wrappers);
|
|
9364
9434
|
} else if (frame.type === "background_message_sync") {
|
|
9365
9435
|
const p = frame.payload;
|
|
9366
9436
|
for (const c of p.chats ?? []) {
|
|
@@ -9370,6 +9440,7 @@ Required: ${schema.required.join(", ")}`
|
|
|
9370
9440
|
}
|
|
9371
9441
|
if (p.embeds) embeds.push(...p.embeds);
|
|
9372
9442
|
if (p.embed_keys) embedKeys.push(...p.embed_keys);
|
|
9443
|
+
if (p.chat_key_wrappers) chatKeyWrappers.push(...p.chat_key_wrappers);
|
|
9373
9444
|
} else if (frame.type === "pending_ai_response") {
|
|
9374
9445
|
pendingAIResponses.push(frame.payload);
|
|
9375
9446
|
}
|
|
@@ -9435,18 +9506,29 @@ Required: ${schema.required.join(", ")}`
|
|
|
9435
9506
|
embedKeys.push(cached);
|
|
9436
9507
|
}
|
|
9437
9508
|
}
|
|
9509
|
+
const serverChatKeyWrapperIds = new Set(
|
|
9510
|
+
chatKeyWrappers.map((entry) => String(entry.id ?? ""))
|
|
9511
|
+
);
|
|
9512
|
+
for (const cached of existingCache.chatKeyWrappers ?? []) {
|
|
9513
|
+
const cachedId = String(cached.id ?? "");
|
|
9514
|
+
if (cachedId && !serverChatKeyWrapperIds.has(cachedId)) {
|
|
9515
|
+
chatKeyWrappers.push(cached);
|
|
9516
|
+
}
|
|
9517
|
+
}
|
|
9438
9518
|
}
|
|
9439
9519
|
const reconciledChats = reconcileAuthoritativeChats(chats, reconciliation);
|
|
9440
9520
|
chats.splice(0, chats.length, ...reconciledChats);
|
|
9441
9521
|
if (reconciliation.deleted_chat_ids?.length) {
|
|
9442
|
-
const { createHash:
|
|
9522
|
+
const { createHash: createHash10 } = await import("crypto");
|
|
9443
9523
|
const deletedHashes = new Set(
|
|
9444
|
-
reconciliation.deleted_chat_ids.map((id) =>
|
|
9524
|
+
reconciliation.deleted_chat_ids.map((id) => createHash10("sha256").update(id).digest("hex"))
|
|
9445
9525
|
);
|
|
9446
9526
|
const keptEmbeds = embeds.filter((embed) => !deletedHashes.has(String(embed.hashed_chat_id ?? "")));
|
|
9447
9527
|
const keptKeys = embedKeys.filter((key) => !deletedHashes.has(String(key.hashed_chat_id ?? "")));
|
|
9528
|
+
const keptChatKeyWrappers = chatKeyWrappers.filter((key) => !deletedHashes.has(String(key.hashed_chat_id ?? "")));
|
|
9448
9529
|
embeds.splice(0, embeds.length, ...keptEmbeds);
|
|
9449
9530
|
embedKeys.splice(0, embedKeys.length, ...keptKeys);
|
|
9531
|
+
chatKeyWrappers.splice(0, chatKeyWrappers.length, ...keptChatKeyWrappers);
|
|
9450
9532
|
}
|
|
9451
9533
|
chats.sort(
|
|
9452
9534
|
(a, b) => (typeof b.details.last_edited_overall_timestamp === "number" ? b.details.last_edited_overall_timestamp : 0) - (typeof a.details.last_edited_overall_timestamp === "number" ? a.details.last_edited_overall_timestamp : 0)
|
|
@@ -9478,6 +9560,7 @@ Required: ${schema.required.join(", ")}`
|
|
|
9478
9560
|
chats,
|
|
9479
9561
|
embeds,
|
|
9480
9562
|
embedKeys,
|
|
9563
|
+
chatKeyWrappers,
|
|
9481
9564
|
newChatSuggestions
|
|
9482
9565
|
};
|
|
9483
9566
|
saveSyncCache(cache);
|
|
@@ -9509,9 +9592,7 @@ Required: ${schema.required.join(", ")}`
|
|
|
9509
9592
|
} catch {
|
|
9510
9593
|
}
|
|
9511
9594
|
}
|
|
9512
|
-
const
|
|
9513
|
-
if (!encryptedChatKey) continue;
|
|
9514
|
-
const chatKeyBytes = await this.decryptChatKey(encryptedChatKey, masterKey);
|
|
9595
|
+
const chatKeyBytes = await this.resolveChatKey(loadSyncCache(), chat, masterKey);
|
|
9515
9596
|
if (!chatKeyBytes) continue;
|
|
9516
9597
|
const completedAt = normalizeUnixSeconds(
|
|
9517
9598
|
pending.fired_at,
|
|
@@ -13625,7 +13706,7 @@ var GeneratedAppSkills = class {
|
|
|
13625
13706
|
|
|
13626
13707
|
// src/sdk.ts
|
|
13627
13708
|
import { decode as toonDecode } from "@toon-format/toon";
|
|
13628
|
-
import { createHash as
|
|
13709
|
+
import { createHash as createHash7, randomBytes as randomBytes3, randomUUID as randomUUID6 } from "crypto";
|
|
13629
13710
|
import { chmodSync as chmodSync2, existsSync as existsSync5, mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "fs";
|
|
13630
13711
|
import { homedir as homedir4 } from "os";
|
|
13631
13712
|
import { dirname, join as join3 } from "path";
|
|
@@ -13763,15 +13844,11 @@ var OpenMates = class {
|
|
|
13763
13844
|
}
|
|
13764
13845
|
async resolveEmbedKeyForShare(embedKeys, embedId) {
|
|
13765
13846
|
const masterKey = await this.getMasterKey();
|
|
13766
|
-
const hashedEmbedId =
|
|
13847
|
+
const hashedEmbedId = createHash7("sha256").update(embedId).digest("hex");
|
|
13767
13848
|
return this.resolveLoadedEmbedKey(embedKeys, hashedEmbedId, masterKey, masterKey);
|
|
13768
13849
|
}
|
|
13769
|
-
async decryptChatMetadata(chat) {
|
|
13770
|
-
|
|
13771
|
-
return chat;
|
|
13772
|
-
}
|
|
13773
|
-
const masterKey = await this.getMasterKey();
|
|
13774
|
-
const chatKey = await decryptBytesWithAesGcm(chat.encrypted_chat_key, masterKey);
|
|
13850
|
+
async decryptChatMetadata(chat, chatKeyWrappers) {
|
|
13851
|
+
const chatKey = await this.resolveLoadedChatKey(chat, chatKeyWrappers);
|
|
13775
13852
|
if (!chatKey) {
|
|
13776
13853
|
return chat;
|
|
13777
13854
|
}
|
|
@@ -13793,8 +13870,9 @@ var OpenMates = class {
|
|
|
13793
13870
|
return payload;
|
|
13794
13871
|
}
|
|
13795
13872
|
const chatMetadata = chat;
|
|
13796
|
-
const
|
|
13797
|
-
const
|
|
13873
|
+
const chatKeyWrappers = Array.isArray(payload.chat_key_wrappers) ? payload.chat_key_wrappers : Array.isArray(chatMetadata.chat_key_wrappers) ? chatMetadata.chat_key_wrappers : [];
|
|
13874
|
+
const decryptedChat = await this.decryptChatMetadata(chatMetadata, chatKeyWrappers);
|
|
13875
|
+
const chatKey = await this.resolveLoadedChatKey(chatMetadata, chatKeyWrappers);
|
|
13798
13876
|
if (!chatKey || !Array.isArray(payload.messages)) {
|
|
13799
13877
|
return { ...payload, chat: decryptedChat };
|
|
13800
13878
|
}
|
|
@@ -13821,6 +13899,15 @@ var OpenMates = class {
|
|
|
13821
13899
|
) : payload.embeds;
|
|
13822
13900
|
return { ...payload, chat: decryptedChat, messages, embeds };
|
|
13823
13901
|
}
|
|
13902
|
+
async resolveLoadedChatKey(chat, chatKeyWrappers) {
|
|
13903
|
+
const masterKey = await this.getMasterKey();
|
|
13904
|
+
const hashedChatId = createHash7("sha256").update(chat.id).digest("hex");
|
|
13905
|
+
const wrapper = (chatKeyWrappers ?? []).find(
|
|
13906
|
+
(entry) => entry.key_type === "master" && entry.hashed_chat_id === hashedChatId && typeof entry.encrypted_chat_key === "string"
|
|
13907
|
+
);
|
|
13908
|
+
const encryptedChatKey = typeof wrapper?.encrypted_chat_key === "string" ? wrapper.encrypted_chat_key : typeof chat.encrypted_chat_key === "string" ? chat.encrypted_chat_key : null;
|
|
13909
|
+
return encryptedChatKey ? decryptBytesWithAesGcm(encryptedChatKey, masterKey) : null;
|
|
13910
|
+
}
|
|
13824
13911
|
async decryptLoadedChatEmbeds(embeds, embedKeys, chatKey) {
|
|
13825
13912
|
const masterKey = await this.getMasterKey();
|
|
13826
13913
|
return Promise.all(embeds.map(async (embed) => {
|
|
@@ -13828,7 +13915,7 @@ var OpenMates = class {
|
|
|
13828
13915
|
if (!embedId) {
|
|
13829
13916
|
return { ...embed };
|
|
13830
13917
|
}
|
|
13831
|
-
const hashedEmbedId =
|
|
13918
|
+
const hashedEmbedId = createHash7("sha256").update(embedId).digest("hex");
|
|
13832
13919
|
const embedKey = await this.resolveLoadedEmbedKey(embedKeys, hashedEmbedId, masterKey, chatKey);
|
|
13833
13920
|
if (!embedKey) {
|
|
13834
13921
|
return { ...embed };
|
|
@@ -13951,7 +14038,12 @@ function loadOrCreateDeviceId(customPath) {
|
|
|
13951
14038
|
function withQuery(path, query = {}) {
|
|
13952
14039
|
const params = new URLSearchParams();
|
|
13953
14040
|
for (const [key, value] of Object.entries(query)) {
|
|
13954
|
-
if (value
|
|
14041
|
+
if (value === void 0 || value === null) continue;
|
|
14042
|
+
if (Array.isArray(value)) {
|
|
14043
|
+
for (const item of value) params.append(key, String(item));
|
|
14044
|
+
} else {
|
|
14045
|
+
params.set(key, String(value));
|
|
14046
|
+
}
|
|
13955
14047
|
}
|
|
13956
14048
|
const serialized = params.toString();
|
|
13957
14049
|
return serialized ? `${path}?${serialized}` : path;
|
|
@@ -14705,10 +14797,13 @@ var OpenMatesTasks = class {
|
|
|
14705
14797
|
return this.reorder(id, move, filters);
|
|
14706
14798
|
}
|
|
14707
14799
|
async listRaw(filters = {}) {
|
|
14800
|
+
const masterKey = filters.labels || filters.tags ? await this.client.masterKey() : void 0;
|
|
14708
14801
|
const response = await this.client.get(withQuery("/v1/user-tasks", {
|
|
14709
14802
|
status: filters.status,
|
|
14710
14803
|
chat_id: filters.chatId,
|
|
14711
|
-
project_id: filters.projectId
|
|
14804
|
+
project_id: filters.projectId,
|
|
14805
|
+
label_hash: masterKey ? labelHashes(masterKey, normalizeLabels(filters.labels ?? filters.tags ?? [])) : void 0,
|
|
14806
|
+
priority: normalizeTaskPriority(filters.priority)
|
|
14712
14807
|
}));
|
|
14713
14808
|
return response.tasks ?? [];
|
|
14714
14809
|
}
|
|
@@ -15906,7 +16001,7 @@ var OutputRedactor = class {
|
|
|
15906
16001
|
import { readFileSync as readFileSync5, statSync, existsSync as existsSync6 } from "fs";
|
|
15907
16002
|
import { basename, extname, resolve as resolve2 } from "path";
|
|
15908
16003
|
import { homedir as homedir5 } from "os";
|
|
15909
|
-
import { createHash as
|
|
16004
|
+
import { createHash as createHash8 } from "crypto";
|
|
15910
16005
|
var MAX_PER_FILE_SIZE = 100 * 1024 * 1024;
|
|
15911
16006
|
var BLOCKED_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
15912
16007
|
".pem",
|
|
@@ -16216,7 +16311,7 @@ function processCodeFile(filePath, filename, redactor) {
|
|
|
16216
16311
|
line_count: lineCount
|
|
16217
16312
|
});
|
|
16218
16313
|
const textPreview = `${filename} (${language}, ${lineCount} lines)`;
|
|
16219
|
-
const contentHash =
|
|
16314
|
+
const contentHash = createHash8("sha256").update(content).digest("hex");
|
|
16220
16315
|
const embed = {
|
|
16221
16316
|
embedId,
|
|
16222
16317
|
embedRef,
|
|
@@ -17771,7 +17866,7 @@ function formatTs(ts) {
|
|
|
17771
17866
|
|
|
17772
17867
|
// src/server.ts
|
|
17773
17868
|
import { execFileSync as execFileSync2, execSync, spawn as nodeSpawn, spawnSync } from "child_process";
|
|
17774
|
-
import { createHash as
|
|
17869
|
+
import { createHash as createHash9, randomBytes as randomBytes4 } from "crypto";
|
|
17775
17870
|
import { chmodSync as chmodSync3, closeSync, copyFileSync, cpSync, existsSync as existsSync7, mkdirSync as mkdirSync4, mkdtempSync, openSync, readFileSync as readFileSync6, readSync, readdirSync, rmSync as rmSync3, writeFileSync as writeFileSync4 } from "fs";
|
|
17776
17871
|
import { createInterface as createInterface3 } from "readline";
|
|
17777
17872
|
import { createInterface as createPromptInterface } from "readline/promises";
|
|
@@ -18436,7 +18531,7 @@ function packagedCaddyTemplatePath(role) {
|
|
|
18436
18531
|
}
|
|
18437
18532
|
function fileHash(path) {
|
|
18438
18533
|
if (!existsSync7(path)) return null;
|
|
18439
|
-
return
|
|
18534
|
+
return createHash9("sha256").update(readFileSync6(path)).digest("hex");
|
|
18440
18535
|
}
|
|
18441
18536
|
async function loadSelfHostComposeTemplate(templateRef, role) {
|
|
18442
18537
|
const templateDir = process.env.OPENMATES_SELFHOST_TEMPLATE_DIR;
|
|
@@ -18822,7 +18917,7 @@ function formatSecretPreflight(preflight) {
|
|
|
18822
18917
|
return parts.join("; ");
|
|
18823
18918
|
}
|
|
18824
18919
|
function hashFile(path) {
|
|
18825
|
-
const hash =
|
|
18920
|
+
const hash = createHash9("sha256");
|
|
18826
18921
|
const fd = openSync(path, "r");
|
|
18827
18922
|
const buffer = Buffer.allocUnsafe(CHECKSUM_BUFFER_BYTES);
|
|
18828
18923
|
try {
|
|
@@ -43031,7 +43126,7 @@ Only output the final Markdown table. Do NOT include explanations, notes, or any
|
|
|
43031
43126
|
text: "@skill:tasks:create Do not ask follow-up questions. Create exactly these three tasks for a public OpenMates demo release checklist. Task 1 title: Review transcript for private data. Description: Confirm the source chat does not contain secrets, personal data, or private account details before publishing. Assign to me. Task 2 title: Verify Tasks and Workflows embeds. Description: Open the public example pages and confirm both parent embeds and child previews render and open fullscreen. Assign to me. Task 3 title: Write public release note. Description: Draft a short release note for developers explaining that the examples come from real CLI-created app-skill chats. Assign to OpenMates."
|
|
43032
43127
|
},
|
|
43033
43128
|
message_2: {
|
|
43034
|
-
text: '```json\n{"type": "app_skill_use", "embed_id": "7996e3b5-8d25-46bd-b527-8da6f9c65ecf", "app_id": "tasks", "skill_id": "create"}\n```\n\
|
|
43129
|
+
text: '```json\n{"type": "app_skill_use", "embed_id": "7996e3b5-8d25-46bd-b527-8da6f9c65ecf", "app_id": "tasks", "skill_id": "create"}\n```\n\nIch habe die drei Aufgaben f\xFCr die OpenMates-Demo-Release-Checkliste erstellt:\n\n1. **Transkript auf private Daten pr\xFCfen** (dir zugewiesen)\n2. **Tasks- und Workflows-Embeds pr\xFCfen** (dir zugewiesen)\n3. **\xD6ffentliche Release-Notiz schreiben** (OpenMates zugewiesen)'
|
|
43035
43130
|
}
|
|
43036
43131
|
},
|
|
43037
43132
|
family_stays_kyoto: {
|
|
@@ -43415,7 +43510,7 @@ How are you leaning personally on this issue heading into the dinner? Are you ho
|
|
|
43415
43510
|
text: "@skill:workflows:create-or-modify Do not ask follow-up questions. Create a simple manual workflow titled Library Book Return Checklist. It should have a manual trigger and three manual steps: gather borrowed books from the shelf, check due dates in the library account, and pack books in a tote bag before leaving home. Keep it concise and suitable for a public demo."
|
|
43416
43511
|
},
|
|
43417
43512
|
message_2: {
|
|
43418
|
-
text: '```json\n{"type": "app_skill_use", "embed_id": "cda4695f-7f68-42d7-9cfe-d719aa08dc3e", "app_id": "workflows", "skill_id": "create-or-modify"}\n```\n\
|
|
43513
|
+
text: '```json\n{"type": "app_skill_use", "embed_id": "cda4695f-7f68-42d7-9cfe-d719aa08dc3e", "app_id": "workflows", "skill_id": "create-or-modify"}\n```\n\nIch habe den Workflow **Bibliotheksb\xFCcher-R\xFCckgabe-Checkliste** erstellt. Diese manuelle Automatisierung enth\xE4lt die folgenden Schritte:\n\n1. **B\xFCcher zusammensuchen**: Ausgeliehene B\xFCcher aus dem Regal nehmen.\n2. **F\xE4lligkeitsdaten pr\xFCfen**: F\xE4lligkeitsdaten im Bibliothekskonto pr\xFCfen.\n3. **Stofftasche packen**: B\xFCcher vor dem Verlassen des Hauses in eine Stofftasche packen.\n\nDu kannst diese Checkliste in der [Workflows-App](/#settings/apps/workflows) ansehen und verwalten.'
|
|
43419
43514
|
}
|
|
43420
43515
|
},
|
|
43421
43516
|
mastodon_account_recent_posts: {
|
|
@@ -61220,11 +61315,11 @@ function decodeBase32(input) {
|
|
|
61220
61315
|
return Buffer.from(bytes);
|
|
61221
61316
|
}
|
|
61222
61317
|
async function generateTotpCode(secret) {
|
|
61223
|
-
const { createHmac } = await import("crypto");
|
|
61318
|
+
const { createHmac: createHmac2 } = await import("crypto");
|
|
61224
61319
|
const counter = Math.floor(Date.now() / 1e3 / 30);
|
|
61225
61320
|
const counterBuffer = Buffer.alloc(8);
|
|
61226
61321
|
counterBuffer.writeBigUInt64BE(BigInt(counter));
|
|
61227
|
-
const hmac =
|
|
61322
|
+
const hmac = createHmac2("sha1", decodeBase32(secret)).update(counterBuffer).digest();
|
|
61228
61323
|
const offset = hmac[hmac.length - 1] & 15;
|
|
61229
61324
|
const code = (hmac.readUInt32BE(offset) & 2147483647) % 1e6;
|
|
61230
61325
|
return String(code).padStart(6, "0");
|
package/dist/cli.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -31,6 +31,9 @@ interface CachedEmbed {
|
|
|
31
31
|
interface CachedEmbedKey {
|
|
32
32
|
[key: string]: unknown;
|
|
33
33
|
}
|
|
34
|
+
interface CachedChatKeyWrapper {
|
|
35
|
+
[key: string]: unknown;
|
|
36
|
+
}
|
|
34
37
|
interface CachedNewChatSuggestion {
|
|
35
38
|
[key: string]: unknown;
|
|
36
39
|
}
|
|
@@ -47,6 +50,8 @@ interface SyncCache {
|
|
|
47
50
|
embeds: CachedEmbed[];
|
|
48
51
|
/** Embed keys for embed decryption */
|
|
49
52
|
embedKeys: CachedEmbedKey[];
|
|
53
|
+
/** Chat key wrappers for wrapper-first chat decryption */
|
|
54
|
+
chatKeyWrappers?: CachedChatKeyWrapper[];
|
|
50
55
|
/**
|
|
51
56
|
* New chat suggestions from the last sync.
|
|
52
57
|
* Each entry has id, chat_id, encrypted_suggestion, created_at.
|
|
@@ -559,7 +564,9 @@ interface UserTaskRecord {
|
|
|
559
564
|
encrypted_task_key?: string | null;
|
|
560
565
|
encrypted_title: string;
|
|
561
566
|
encrypted_description?: string | null;
|
|
567
|
+
encrypted_labels?: string | null;
|
|
562
568
|
encrypted_tags?: string | null;
|
|
569
|
+
label_hashes?: string[] | null;
|
|
563
570
|
encrypted_linked_project_ids?: string | null;
|
|
564
571
|
encrypted_activity_summary?: string | null;
|
|
565
572
|
encrypted_latest_instruction?: string | null;
|
|
@@ -1283,6 +1290,8 @@ declare class OpenMatesClient {
|
|
|
1283
1290
|
* encrypt/decrypt the chat's title, category, messages, etc.
|
|
1284
1291
|
*/
|
|
1285
1292
|
private decryptChatKey;
|
|
1293
|
+
private getMasterWrapperEncryptedChatKey;
|
|
1294
|
+
private resolveChatKey;
|
|
1286
1295
|
/**
|
|
1287
1296
|
* Decrypt a single chat record from the sync cache into a ChatListItem.
|
|
1288
1297
|
*/
|
|
@@ -1582,6 +1591,8 @@ declare class OpenMatesClient {
|
|
|
1582
1591
|
status?: UserTaskStatus;
|
|
1583
1592
|
chatId?: string;
|
|
1584
1593
|
projectId?: string;
|
|
1594
|
+
labelHashes?: string[];
|
|
1595
|
+
priority?: number;
|
|
1585
1596
|
limit?: number;
|
|
1586
1597
|
}): Promise<UserTaskRecord[]>;
|
|
1587
1598
|
createUserTask(input: UserTaskCreateInput): Promise<UserTaskRecord>;
|
|
@@ -4800,12 +4811,15 @@ declare class GeneratedAppSkills {
|
|
|
4800
4811
|
readonly workflows: WorkflowsAppSkills;
|
|
4801
4812
|
}
|
|
4802
4813
|
|
|
4814
|
+
declare const PRIORITY_LEVELS: readonly ["none", "low", "medium", "high", "urgent"];
|
|
4815
|
+
type TaskPriorityLevel = typeof PRIORITY_LEVELS[number];
|
|
4803
4816
|
interface DecryptedUserTask {
|
|
4804
4817
|
taskId: string;
|
|
4805
4818
|
source?: string;
|
|
4806
4819
|
shortId: string;
|
|
4807
4820
|
title: string;
|
|
4808
4821
|
description: string;
|
|
4822
|
+
labels: string[];
|
|
4809
4823
|
tags: string[];
|
|
4810
4824
|
latestInstruction: string;
|
|
4811
4825
|
status: UserTaskStatus;
|
|
@@ -4816,6 +4830,7 @@ interface DecryptedUserTask {
|
|
|
4816
4830
|
planId: string | null;
|
|
4817
4831
|
dueAt: number | null;
|
|
4818
4832
|
priority: number;
|
|
4833
|
+
priorityLevel: TaskPriorityLevel;
|
|
4819
4834
|
position: number;
|
|
4820
4835
|
queueState: string;
|
|
4821
4836
|
blockedReasonCode: string | null;
|
|
@@ -4827,21 +4842,31 @@ interface DecryptedUserTask {
|
|
|
4827
4842
|
interface TaskCreateOptions {
|
|
4828
4843
|
title: string;
|
|
4829
4844
|
description?: string;
|
|
4845
|
+
labels?: string[];
|
|
4846
|
+
tags?: string[];
|
|
4830
4847
|
status?: UserTaskStatus;
|
|
4831
4848
|
assign?: string;
|
|
4832
4849
|
chatId?: string | null;
|
|
4833
4850
|
projectIds?: string[];
|
|
4834
4851
|
planId?: string | null;
|
|
4835
4852
|
dueAt?: number | null;
|
|
4853
|
+
priority?: TaskPriorityLevel | number | null;
|
|
4836
4854
|
}
|
|
4837
4855
|
interface TaskUpdateOptions {
|
|
4838
4856
|
title?: string;
|
|
4839
4857
|
description?: string;
|
|
4858
|
+
labels?: string[];
|
|
4859
|
+
tags?: string[];
|
|
4860
|
+
addLabels?: string[];
|
|
4861
|
+
addTags?: string[];
|
|
4862
|
+
removeLabels?: string[];
|
|
4863
|
+
removeTags?: string[];
|
|
4840
4864
|
status?: UserTaskStatus;
|
|
4841
4865
|
assign?: string;
|
|
4842
4866
|
chatId?: string | null;
|
|
4843
4867
|
projectIds?: string[];
|
|
4844
4868
|
planId?: string | null;
|
|
4869
|
+
priority?: TaskPriorityLevel | number | null;
|
|
4845
4870
|
}
|
|
4846
4871
|
|
|
4847
4872
|
interface OpenMatesOptions {
|
|
@@ -4938,6 +4963,7 @@ interface EncryptedChatMetadata {
|
|
|
4938
4963
|
id: string;
|
|
4939
4964
|
encrypted_title?: string;
|
|
4940
4965
|
encrypted_chat_key?: string;
|
|
4966
|
+
chat_key_wrappers?: ChatKeyWrapperRecord[];
|
|
4941
4967
|
encrypted_chat_summary?: string;
|
|
4942
4968
|
encrypted_category?: string;
|
|
4943
4969
|
title?: string;
|
|
@@ -4961,6 +4987,9 @@ type TaskListFilters = {
|
|
|
4961
4987
|
status?: UserTaskStatus;
|
|
4962
4988
|
chatId?: string;
|
|
4963
4989
|
projectId?: string;
|
|
4990
|
+
labels?: string[];
|
|
4991
|
+
tags?: string[];
|
|
4992
|
+
priority?: TaskPriorityLevel | number | null;
|
|
4964
4993
|
};
|
|
4965
4994
|
type TaskPlainCreateOptions = TaskCreateOptions;
|
|
4966
4995
|
type TaskPlainUpdateOptions = TaskUpdateOptions;
|
|
@@ -4986,6 +5015,12 @@ interface EmbedKeyRecord {
|
|
|
4986
5015
|
encrypted_embed_key?: string;
|
|
4987
5016
|
[key: string]: unknown;
|
|
4988
5017
|
}
|
|
5018
|
+
interface ChatKeyWrapperRecord {
|
|
5019
|
+
hashed_chat_id?: string;
|
|
5020
|
+
key_type?: string;
|
|
5021
|
+
encrypted_chat_key?: string;
|
|
5022
|
+
[key: string]: unknown;
|
|
5023
|
+
}
|
|
4989
5024
|
interface FocusModeSelection {
|
|
4990
5025
|
appId: string;
|
|
4991
5026
|
focusModeId: string;
|
|
@@ -5043,8 +5078,9 @@ declare class OpenMates {
|
|
|
5043
5078
|
masterKey(): Promise<Uint8Array>;
|
|
5044
5079
|
sdkSession(): Promise<SdkSessionResponse>;
|
|
5045
5080
|
resolveEmbedKeyForShare(embedKeys: EmbedKeyRecord[], embedId: string): Promise<Uint8Array | null>;
|
|
5046
|
-
decryptChatMetadata<T extends EncryptedChatMetadata>(chat: T): Promise<T>;
|
|
5081
|
+
decryptChatMetadata<T extends EncryptedChatMetadata>(chat: T, chatKeyWrappers?: ChatKeyWrapperRecord[]): Promise<T>;
|
|
5047
5082
|
decryptLoadedChatPayload<T extends Record<string, unknown>>(payload: T): Promise<T>;
|
|
5083
|
+
private resolveLoadedChatKey;
|
|
5048
5084
|
private decryptLoadedChatEmbeds;
|
|
5049
5085
|
private resolveLoadedEmbedKey;
|
|
5050
5086
|
private requestWithMethod;
|
package/dist/index.js
CHANGED