openmates 0.14.8-alpha.14 → 0.14.8-alpha.16
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-FHPNKPNJ.js → chunk-6M52O6HO.js} +448 -234
- package/dist/cli.js +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -1
- package/package.json +1 -1
|
@@ -3594,7 +3594,8 @@ var CLOUD_API_URL = "https://api.openmates.org";
|
|
|
3594
3594
|
var DEFAULT_API_URL = process.env.OPENMATES_API_URL ?? CLOUD_API_URL;
|
|
3595
3595
|
var SETTINGS_GET_RATE_LIMIT_RETRY_MS = 61e3;
|
|
3596
3596
|
var SKILL_TASK_POLL_INTERVAL_MS = 2e3;
|
|
3597
|
-
var SKILL_TASK_POLL_TIMEOUT_MS =
|
|
3597
|
+
var SKILL_TASK_POLL_TIMEOUT_MS = 12e5;
|
|
3598
|
+
var SKILL_TASK_POLL_TRANSIENT_ERROR_STATUS = 500;
|
|
3598
3599
|
function normalizeOrigin(url) {
|
|
3599
3600
|
url.pathname = "";
|
|
3600
3601
|
url.search = "";
|
|
@@ -5167,10 +5168,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
5167
5168
|
2e4
|
|
5168
5169
|
);
|
|
5169
5170
|
await ws.sendAsync("chat_message_added", messagePayload);
|
|
5170
|
-
|
|
5171
|
-
if (typeof confirmedPayload.new_messages_v === "number" && Number.isSafeInteger(confirmedPayload.new_messages_v)) {
|
|
5172
|
-
terminalExpectedMessagesV = confirmedPayload.new_messages_v;
|
|
5173
|
-
}
|
|
5171
|
+
await confirmed;
|
|
5174
5172
|
let assistant = "";
|
|
5175
5173
|
let assistantMessageId = null;
|
|
5176
5174
|
let category = null;
|
|
@@ -5342,237 +5340,22 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
5342
5340
|
`The assistant requested memories (${event.requestedKeys.join(", ")}). Rerun with --auto-approve-memories to explicitly approve requested memory categories from the CLI, or continue this chat in the web app to approve or reject the request.`
|
|
5343
5341
|
);
|
|
5344
5342
|
};
|
|
5345
|
-
const persistEncryptedSystemMessage = async (systemMessage, targetChatId = chatId) => {
|
|
5346
|
-
await ws.sendAsync("chat_system_message_added", {
|
|
5347
|
-
chat_id: targetChatId,
|
|
5348
|
-
message: systemMessage
|
|
5349
|
-
});
|
|
5350
|
-
await ws.waitForMessage(
|
|
5351
|
-
"system_message_confirmed",
|
|
5352
|
-
(payload) => payload.message_id === systemMessage.message_id,
|
|
5353
|
-
2e4
|
|
5354
|
-
);
|
|
5355
|
-
};
|
|
5356
5343
|
const persistedTaskEventIds = /* @__PURE__ */ new Set();
|
|
5357
5344
|
const persistTaskEventSystemMessages = async (events) => {
|
|
5358
5345
|
if (!chatKeyBytes || events.length === 0) return;
|
|
5359
5346
|
for (const event of events) {
|
|
5360
5347
|
if (persistedTaskEventIds.has(event.event_id)) continue;
|
|
5361
|
-
await persistEncryptedSystemMessage(
|
|
5362
|
-
|
|
5363
|
-
|
|
5364
|
-
|
|
5365
|
-
|
|
5366
|
-
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
const persistPendingTaskUpdateJobs = async (jobs, events) => {
|
|
5370
|
-
const handledJobIds = /* @__PURE__ */ new Set();
|
|
5371
|
-
if (jobs.length === 0) return handledJobIds;
|
|
5372
|
-
const masterKey = this.getMasterKeyBytes();
|
|
5373
|
-
let decryptedTasksCache = null;
|
|
5374
|
-
const eventByJobId = new Map(events.map((event) => [event.task_update_job_id, event]));
|
|
5375
|
-
const buildTaskKeyWrappersForChat = async (task, targetChatId, createdAt2) => {
|
|
5376
|
-
const encryptedTaskKey = task.encrypted.encrypted_task_key;
|
|
5377
|
-
if (!encryptedTaskKey) throw new Error(`Task ${task.taskId} is missing encrypted task key.`);
|
|
5378
|
-
const taskKey = await decryptBytesWithAesGcm(encryptedTaskKey, masterKey);
|
|
5379
|
-
if (!taskKey) throw new Error(`Failed to decrypt task key for ${task.taskId}.`);
|
|
5380
|
-
const targetChatKey = await resolveChatKey(targetChatId);
|
|
5381
|
-
const existingProjectWrappers = await listProjectTaskKeyWrappers(task.taskId, createdAt2);
|
|
5382
|
-
const linkedProjectIds = task.linkedProjectIds ?? [];
|
|
5383
|
-
if (linkedProjectIds.length > existingProjectWrappers.length) {
|
|
5384
|
-
throw new Error(`Task ${task.taskId} is missing project key wrappers required for move persistence.`);
|
|
5385
|
-
}
|
|
5386
|
-
return [
|
|
5387
|
-
{
|
|
5388
|
-
key_type: "master",
|
|
5389
|
-
encrypted_task_key: await encryptBytesWithAesGcm(taskKey, masterKey),
|
|
5390
|
-
created_at: createdAt2
|
|
5391
|
-
},
|
|
5392
|
-
{
|
|
5393
|
-
key_type: "chat",
|
|
5394
|
-
hashed_chat_id: computeSHA256(targetChatId),
|
|
5395
|
-
encrypted_task_key: await encryptBytesWithAesGcm(taskKey, targetChatKey),
|
|
5396
|
-
created_at: createdAt2
|
|
5397
|
-
},
|
|
5398
|
-
...existingProjectWrappers
|
|
5399
|
-
];
|
|
5400
|
-
};
|
|
5401
|
-
const listProjectTaskKeyWrappers = async (taskId, createdAt2) => {
|
|
5402
|
-
const response = await this.http.get(
|
|
5403
|
-
`/v1/user-tasks/${encodeURIComponent(taskId)}/key-wrappers`,
|
|
5404
|
-
this.getCliRequestHeaders()
|
|
5348
|
+
await this.persistEncryptedSystemMessage(
|
|
5349
|
+
ws,
|
|
5350
|
+
await buildTaskEventSystemMessage({
|
|
5351
|
+
chatKey: chatKeyBytes,
|
|
5352
|
+
userMessageId: messageId,
|
|
5353
|
+
event
|
|
5354
|
+
}),
|
|
5355
|
+
chatId
|
|
5405
5356
|
);
|
|
5406
|
-
if (!response.ok) {
|
|
5407
|
-
throw new Error(`User task key wrapper list failed with HTTP ${response.status}`);
|
|
5408
|
-
}
|
|
5409
|
-
return (response.data.key_wrappers ?? []).filter((wrapper) => wrapper.key_type === "project").map((wrapper) => ({
|
|
5410
|
-
key_type: "project",
|
|
5411
|
-
hashed_project_id: wrapper.hashed_project_id,
|
|
5412
|
-
encrypted_task_key: wrapper.encrypted_task_key,
|
|
5413
|
-
created_at: typeof wrapper.created_at === "number" ? wrapper.created_at : createdAt2,
|
|
5414
|
-
expires_at: wrapper.expires_at ?? null
|
|
5415
|
-
}));
|
|
5416
|
-
};
|
|
5417
|
-
const resolveChatKey = async (targetChatId) => {
|
|
5418
|
-
if (targetChatId === chatId && chatKeyBytes) return chatKeyBytes;
|
|
5419
|
-
const cache = loadSyncCache() ?? await this.ensureSynced();
|
|
5420
|
-
const targetChat = cache.chats.find((chat) => String(chat.details.id ?? "") === targetChatId);
|
|
5421
|
-
const encryptedTargetChatKey = typeof targetChat?.details.encrypted_chat_key === "string" ? targetChat.details.encrypted_chat_key : null;
|
|
5422
|
-
if (!encryptedTargetChatKey) {
|
|
5423
|
-
throw new Error(`Encrypted chat key not found for task move target '${targetChatId}'. Sync and try again.`);
|
|
5424
|
-
}
|
|
5425
|
-
const targetChatKey = await decryptBytesWithAesGcm(encryptedTargetChatKey, masterKey);
|
|
5426
|
-
if (!targetChatKey) {
|
|
5427
|
-
throw new Error(`Failed to decrypt chat key for task move target '${targetChatId}'.`);
|
|
5428
|
-
}
|
|
5429
|
-
return targetChatKey;
|
|
5430
|
-
};
|
|
5431
|
-
const findTaskForUpdateJob = async (claim) => {
|
|
5432
|
-
const chatIds = [claim.source_task_chat_id, claim.chat_id, claim.safe_metadata?.primary_chat_id].filter((value) => typeof value === "string" && value.length > 0);
|
|
5433
|
-
const uniqueChatIds = [...new Set(chatIds)];
|
|
5434
|
-
for (const candidateChatId of uniqueChatIds) {
|
|
5435
|
-
const scopedTasks = await decryptUserTasks(await this.listUserTasks({ chatId: candidateChatId }), masterKey);
|
|
5436
|
-
try {
|
|
5437
|
-
return findTask(scopedTasks, claim.task_id);
|
|
5438
|
-
} catch (error) {
|
|
5439
|
-
if (!(error instanceof Error) || !error.message.includes("was not found")) throw error;
|
|
5440
|
-
}
|
|
5441
|
-
}
|
|
5442
|
-
if (!decryptedTasksCache) {
|
|
5443
|
-
decryptedTasksCache = await decryptUserTasks(await this.listUserTasks({ limit: 1e3 }), masterKey);
|
|
5444
|
-
}
|
|
5445
|
-
return findTask(decryptedTasksCache, claim.task_id);
|
|
5446
|
-
};
|
|
5447
|
-
const taskEventTypeForOperation = (operation) => {
|
|
5448
|
-
switch (operation) {
|
|
5449
|
-
case "create":
|
|
5450
|
-
return "created";
|
|
5451
|
-
case "move":
|
|
5452
|
-
return "moved";
|
|
5453
|
-
case "update":
|
|
5454
|
-
return "updated";
|
|
5455
|
-
default:
|
|
5456
|
-
return operation || "updated";
|
|
5457
|
-
}
|
|
5458
|
-
};
|
|
5459
|
-
for (const job of jobs) {
|
|
5460
|
-
if (!taskUpdateJobBelongsToActiveTurn(job, chatId, events)) {
|
|
5461
|
-
handledJobIds.add(job.job_id);
|
|
5462
|
-
continue;
|
|
5463
|
-
}
|
|
5464
|
-
const claimPromise = ws.waitForMessage(
|
|
5465
|
-
"task_update_job_claimed",
|
|
5466
|
-
(payload) => payload.job_id === job.job_id,
|
|
5467
|
-
2e4
|
|
5468
|
-
);
|
|
5469
|
-
await ws.sendAsync("task_update_job_claim", {
|
|
5470
|
-
protocol_version: 1,
|
|
5471
|
-
job_id: job.job_id
|
|
5472
|
-
});
|
|
5473
|
-
const claim = (await claimPromise).payload;
|
|
5474
|
-
const privatePatch = claim.private_patch ?? {};
|
|
5475
|
-
const safeMetadata = claim.safe_metadata ?? {};
|
|
5476
|
-
const sourceChatId = claim.chat_id ?? job.chat_id ?? chatId;
|
|
5477
|
-
const sourceChatKey = await resolveChatKey(sourceChatId);
|
|
5478
|
-
const event = eventByJobId.get(job.job_id) ?? {
|
|
5479
|
-
event_id: `task-event-${job.job_id}`,
|
|
5480
|
-
chat_id: sourceChatId,
|
|
5481
|
-
task_id: claim.task_id,
|
|
5482
|
-
event_type: taskEventTypeForOperation(claim.operation),
|
|
5483
|
-
title: typeof privatePatch.title === "string" ? privatePatch.title : null,
|
|
5484
|
-
status: typeof safeMetadata.status === "string" ? safeMetadata.status : null,
|
|
5485
|
-
created_at: typeof safeMetadata.updated_at === "number" ? safeMetadata.updated_at : Math.floor(Date.now() / 1e3),
|
|
5486
|
-
task_update_job_id: job.job_id
|
|
5487
|
-
};
|
|
5488
|
-
const eventMessage = await buildTaskEventSystemMessage({
|
|
5489
|
-
chatKey: sourceChatKey,
|
|
5490
|
-
userMessageId: claim.message_id ?? messageId,
|
|
5491
|
-
event
|
|
5492
|
-
});
|
|
5493
|
-
const confirmTaskEventPersisted = async () => {
|
|
5494
|
-
const confirmedPromise = ws.waitForMessage(
|
|
5495
|
-
"task_update_job_event_confirmed",
|
|
5496
|
-
(payload) => payload.job_id === job.job_id,
|
|
5497
|
-
2e4
|
|
5498
|
-
);
|
|
5499
|
-
await ws.sendAsync("task_update_job_event_confirmed", {
|
|
5500
|
-
protocol_version: 1,
|
|
5501
|
-
job_id: job.job_id,
|
|
5502
|
-
event_system_message_id: eventMessage.message_id
|
|
5503
|
-
});
|
|
5504
|
-
await confirmedPromise;
|
|
5505
|
-
};
|
|
5506
|
-
if (claim.state === "TASK_PERSISTED") {
|
|
5507
|
-
await persistEncryptedSystemMessage(eventMessage, sourceChatId);
|
|
5508
|
-
persistedTaskEventIds.add(event.event_id);
|
|
5509
|
-
await confirmTaskEventPersisted();
|
|
5510
|
-
handledJobIds.add(job.job_id);
|
|
5511
|
-
continue;
|
|
5512
|
-
}
|
|
5513
|
-
if (!claim.lease_token || !Number.isSafeInteger(claim.lease_generation)) {
|
|
5514
|
-
throw new Error("Task update job claim returned an invalid lease.");
|
|
5515
|
-
}
|
|
5516
|
-
let encryptedTaskPayload;
|
|
5517
|
-
if (claim.operation === "create") {
|
|
5518
|
-
const input = await buildCreateUserTaskInput(masterKey, {
|
|
5519
|
-
title: typeof privatePatch.title === "string" ? privatePatch.title : "Untitled task",
|
|
5520
|
-
description: typeof privatePatch.description === "string" ? privatePatch.description : "",
|
|
5521
|
-
status: typeof safeMetadata.status === "string" ? safeMetadata.status : "todo",
|
|
5522
|
-
assign: typeof safeMetadata.assignee_type === "string" ? safeMetadata.assignee_type : "user",
|
|
5523
|
-
chatId: typeof safeMetadata.primary_chat_id === "string" ? safeMetadata.primary_chat_id : claim.chat_id ?? chatId
|
|
5524
|
-
});
|
|
5525
|
-
encryptedTaskPayload = {
|
|
5526
|
-
...input,
|
|
5527
|
-
task_id: claim.task_id,
|
|
5528
|
-
position: typeof safeMetadata.position === "number" ? safeMetadata.position : input.position,
|
|
5529
|
-
created_at: typeof safeMetadata.created_at === "number" ? safeMetadata.created_at : input.created_at,
|
|
5530
|
-
updated_at: typeof safeMetadata.updated_at === "number" ? safeMetadata.updated_at : input.updated_at
|
|
5531
|
-
};
|
|
5532
|
-
} else {
|
|
5533
|
-
const task = await findTaskForUpdateJob(claim);
|
|
5534
|
-
const patch = await buildUpdateUserTaskInput(task, masterKey, {
|
|
5535
|
-
title: typeof privatePatch.title === "string" ? privatePatch.title : void 0,
|
|
5536
|
-
description: typeof privatePatch.description === "string" ? privatePatch.description : void 0,
|
|
5537
|
-
status: typeof safeMetadata.status === "string" ? safeMetadata.status : void 0,
|
|
5538
|
-
assign: typeof safeMetadata.assignee_type === "string" ? safeMetadata.assignee_type : void 0,
|
|
5539
|
-
chatId: typeof safeMetadata.primary_chat_id === "string" ? safeMetadata.primary_chat_id : void 0
|
|
5540
|
-
});
|
|
5541
|
-
encryptedTaskPayload = {
|
|
5542
|
-
...patch,
|
|
5543
|
-
version: claim.expected_task_version,
|
|
5544
|
-
updated_at: typeof safeMetadata.updated_at === "number" ? safeMetadata.updated_at : patch.updated_at
|
|
5545
|
-
};
|
|
5546
|
-
if (typeof safeMetadata.primary_chat_id === "string") {
|
|
5547
|
-
encryptedTaskPayload.key_wrappers = await buildTaskKeyWrappersForChat(
|
|
5548
|
-
task,
|
|
5549
|
-
safeMetadata.primary_chat_id,
|
|
5550
|
-
typeof safeMetadata.updated_at === "number" ? safeMetadata.updated_at : Math.floor(Date.now() / 1e3)
|
|
5551
|
-
);
|
|
5552
|
-
}
|
|
5553
|
-
}
|
|
5554
|
-
const encryptedEventMessage = eventMessage.encrypted_content;
|
|
5555
|
-
const persistedPromise = ws.waitForMessage(
|
|
5556
|
-
"task_update_job_persisted",
|
|
5557
|
-
(payload) => payload.job_id === job.job_id,
|
|
5558
|
-
2e4
|
|
5559
|
-
);
|
|
5560
|
-
await ws.sendAsync("task_update_job_persist", buildTaskUpdateJobPersistPayload({
|
|
5561
|
-
jobId: job.job_id,
|
|
5562
|
-
leaseToken: claim.lease_token,
|
|
5563
|
-
leaseGeneration: claim.lease_generation,
|
|
5564
|
-
expectedTaskVersion: claim.expected_task_version,
|
|
5565
|
-
encryptedTaskPayload,
|
|
5566
|
-
encryptedTaskEventMessage: encryptedEventMessage
|
|
5567
|
-
}));
|
|
5568
|
-
await persistedPromise;
|
|
5569
|
-
await persistEncryptedSystemMessage(eventMessage, sourceChatId);
|
|
5570
5357
|
persistedTaskEventIds.add(event.event_id);
|
|
5571
|
-
await confirmTaskEventPersisted();
|
|
5572
|
-
handledJobIds.add(job.job_id);
|
|
5573
5358
|
}
|
|
5574
|
-
clearSyncCache();
|
|
5575
|
-
return handledJobIds;
|
|
5576
5359
|
};
|
|
5577
5360
|
const streamOpts = {
|
|
5578
5361
|
onStream: params.onStream,
|
|
@@ -5764,7 +5547,15 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
5764
5547
|
newChatSuggestions: resp.newChatSuggestions,
|
|
5765
5548
|
encryptedChatKey
|
|
5766
5549
|
});
|
|
5767
|
-
const persistedTaskJobIds = await persistPendingTaskUpdateJobs(
|
|
5550
|
+
const persistedTaskJobIds = await this.persistPendingTaskUpdateJobs({
|
|
5551
|
+
ws,
|
|
5552
|
+
jobs: pendingTaskUpdateJobs,
|
|
5553
|
+
events: taskEvents,
|
|
5554
|
+
activeChatId: chatId,
|
|
5555
|
+
activeChatKeyBytes: chatKeyBytes,
|
|
5556
|
+
fallbackUserMessageId: messageId,
|
|
5557
|
+
requireActiveTurnEvent: true
|
|
5558
|
+
});
|
|
5768
5559
|
pendingTaskUpdateJobs = pendingTaskUpdateJobs.filter((job) => !persistedTaskJobIds.has(job.job_id));
|
|
5769
5560
|
await persistTaskEventSystemMessages(taskEvents);
|
|
5770
5561
|
clearSyncCache();
|
|
@@ -5791,6 +5582,224 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
5791
5582
|
appSettingsMemoryRequests
|
|
5792
5583
|
};
|
|
5793
5584
|
}
|
|
5585
|
+
async persistEncryptedSystemMessage(ws, systemMessage, targetChatId) {
|
|
5586
|
+
await ws.sendAsync("chat_system_message_added", {
|
|
5587
|
+
chat_id: targetChatId,
|
|
5588
|
+
message: systemMessage
|
|
5589
|
+
});
|
|
5590
|
+
await ws.waitForMessage(
|
|
5591
|
+
"system_message_confirmed",
|
|
5592
|
+
(payload) => payload.message_id === systemMessage.message_id,
|
|
5593
|
+
2e4
|
|
5594
|
+
);
|
|
5595
|
+
}
|
|
5596
|
+
async persistPendingTaskUpdateJobs(params) {
|
|
5597
|
+
const handledJobIds = /* @__PURE__ */ new Set();
|
|
5598
|
+
if (params.jobs.length === 0) return handledJobIds;
|
|
5599
|
+
const masterKey = this.getMasterKeyBytes();
|
|
5600
|
+
let decryptedTasksCache = null;
|
|
5601
|
+
const eventByJobId = new Map(params.events.map((event) => [event.task_update_job_id, event]));
|
|
5602
|
+
const resolveChatKey = async (targetChatId) => {
|
|
5603
|
+
if (targetChatId === params.activeChatId && params.activeChatKeyBytes) return params.activeChatKeyBytes;
|
|
5604
|
+
const findChat = (chats) => chats?.find((chat) => String(chat.details.id ?? "") === targetChatId);
|
|
5605
|
+
const targetChat = findChat(params.syncedChats) ?? findChat(loadSyncCache()?.chats);
|
|
5606
|
+
const encryptedTargetChatKey = typeof targetChat?.details.encrypted_chat_key === "string" ? targetChat.details.encrypted_chat_key : null;
|
|
5607
|
+
if (!encryptedTargetChatKey) {
|
|
5608
|
+
throw new Error(`Encrypted chat key not found for task update job target '${targetChatId}'. Sync and try again.`);
|
|
5609
|
+
}
|
|
5610
|
+
const targetChatKey = await decryptBytesWithAesGcm(encryptedTargetChatKey, masterKey);
|
|
5611
|
+
if (!targetChatKey) {
|
|
5612
|
+
throw new Error(`Failed to decrypt chat key for task update job target '${targetChatId}'.`);
|
|
5613
|
+
}
|
|
5614
|
+
return targetChatKey;
|
|
5615
|
+
};
|
|
5616
|
+
const listProjectTaskKeyWrappers = async (taskId, createdAt) => {
|
|
5617
|
+
const response = await this.http.get(
|
|
5618
|
+
`/v1/user-tasks/${encodeURIComponent(taskId)}/key-wrappers`,
|
|
5619
|
+
this.getCliRequestHeaders()
|
|
5620
|
+
);
|
|
5621
|
+
if (!response.ok) {
|
|
5622
|
+
throw new Error(`User task key wrapper list failed with HTTP ${response.status}`);
|
|
5623
|
+
}
|
|
5624
|
+
return (response.data.key_wrappers ?? []).filter((wrapper) => wrapper.key_type === "project").map((wrapper) => ({
|
|
5625
|
+
key_type: "project",
|
|
5626
|
+
hashed_project_id: wrapper.hashed_project_id,
|
|
5627
|
+
encrypted_task_key: wrapper.encrypted_task_key,
|
|
5628
|
+
created_at: typeof wrapper.created_at === "number" ? wrapper.created_at : createdAt,
|
|
5629
|
+
expires_at: wrapper.expires_at ?? null
|
|
5630
|
+
}));
|
|
5631
|
+
};
|
|
5632
|
+
const buildTaskKeyWrappersForChat = async (task, targetChatId, createdAt) => {
|
|
5633
|
+
const encryptedTaskKey = task.encrypted.encrypted_task_key;
|
|
5634
|
+
if (!encryptedTaskKey) throw new Error(`Task ${task.taskId} is missing encrypted task key.`);
|
|
5635
|
+
const taskKey = await decryptBytesWithAesGcm(encryptedTaskKey, masterKey);
|
|
5636
|
+
if (!taskKey) throw new Error(`Failed to decrypt task key for ${task.taskId}.`);
|
|
5637
|
+
const targetChatKey = await resolveChatKey(targetChatId);
|
|
5638
|
+
const existingProjectWrappers = await listProjectTaskKeyWrappers(task.taskId, createdAt);
|
|
5639
|
+
const linkedProjectIds = task.linkedProjectIds ?? [];
|
|
5640
|
+
if (linkedProjectIds.length > existingProjectWrappers.length) {
|
|
5641
|
+
throw new Error(`Task ${task.taskId} is missing project key wrappers required for move persistence.`);
|
|
5642
|
+
}
|
|
5643
|
+
return [
|
|
5644
|
+
{
|
|
5645
|
+
key_type: "master",
|
|
5646
|
+
encrypted_task_key: await encryptBytesWithAesGcm(taskKey, masterKey),
|
|
5647
|
+
created_at: createdAt
|
|
5648
|
+
},
|
|
5649
|
+
{
|
|
5650
|
+
key_type: "chat",
|
|
5651
|
+
hashed_chat_id: computeSHA256(targetChatId),
|
|
5652
|
+
encrypted_task_key: await encryptBytesWithAesGcm(taskKey, targetChatKey),
|
|
5653
|
+
created_at: createdAt
|
|
5654
|
+
},
|
|
5655
|
+
...existingProjectWrappers
|
|
5656
|
+
];
|
|
5657
|
+
};
|
|
5658
|
+
const findTaskForUpdateJob = async (claim) => {
|
|
5659
|
+
const chatIds = [claim.source_task_chat_id, claim.chat_id, claim.safe_metadata?.primary_chat_id].filter((value) => typeof value === "string" && value.length > 0);
|
|
5660
|
+
for (const candidateChatId of [...new Set(chatIds)]) {
|
|
5661
|
+
const scopedTasks = await decryptUserTasks(await this.listUserTasks({ chatId: candidateChatId }), masterKey);
|
|
5662
|
+
try {
|
|
5663
|
+
return findTask(scopedTasks, claim.task_id);
|
|
5664
|
+
} catch (error) {
|
|
5665
|
+
if (!(error instanceof Error) || !error.message.includes("was not found")) throw error;
|
|
5666
|
+
}
|
|
5667
|
+
}
|
|
5668
|
+
if (!decryptedTasksCache) {
|
|
5669
|
+
decryptedTasksCache = await decryptUserTasks(await this.listUserTasks({ limit: 1e3 }), masterKey);
|
|
5670
|
+
}
|
|
5671
|
+
return findTask(decryptedTasksCache, claim.task_id);
|
|
5672
|
+
};
|
|
5673
|
+
const taskEventTypeForOperation = (operation) => {
|
|
5674
|
+
switch (operation) {
|
|
5675
|
+
case "create":
|
|
5676
|
+
return "created";
|
|
5677
|
+
case "move":
|
|
5678
|
+
return "moved";
|
|
5679
|
+
case "update":
|
|
5680
|
+
return "updated";
|
|
5681
|
+
default:
|
|
5682
|
+
return operation || "updated";
|
|
5683
|
+
}
|
|
5684
|
+
};
|
|
5685
|
+
for (const job of params.jobs) {
|
|
5686
|
+
if (params.requireActiveTurnEvent && params.activeChatId && !taskUpdateJobBelongsToActiveTurn(job, params.activeChatId, params.events)) {
|
|
5687
|
+
handledJobIds.add(job.job_id);
|
|
5688
|
+
continue;
|
|
5689
|
+
}
|
|
5690
|
+
const claimPromise = params.ws.waitForMessage(
|
|
5691
|
+
"task_update_job_claimed",
|
|
5692
|
+
(payload) => payload.job_id === job.job_id,
|
|
5693
|
+
2e4
|
|
5694
|
+
);
|
|
5695
|
+
await params.ws.sendAsync("task_update_job_claim", {
|
|
5696
|
+
protocol_version: 1,
|
|
5697
|
+
job_id: job.job_id
|
|
5698
|
+
});
|
|
5699
|
+
const claim = (await claimPromise).payload;
|
|
5700
|
+
const privatePatch = claim.private_patch ?? {};
|
|
5701
|
+
const safeMetadata = claim.safe_metadata ?? {};
|
|
5702
|
+
const sourceChatId = claim.chat_id ?? job.chat_id ?? params.activeChatId;
|
|
5703
|
+
if (!sourceChatId) throw new Error(`Task update job ${job.job_id} is missing a source chat id.`);
|
|
5704
|
+
const sourceChatKey = await resolveChatKey(sourceChatId);
|
|
5705
|
+
const event = eventByJobId.get(job.job_id) ?? {
|
|
5706
|
+
event_id: `task-event-${job.job_id}`,
|
|
5707
|
+
chat_id: sourceChatId,
|
|
5708
|
+
task_id: claim.task_id,
|
|
5709
|
+
event_type: taskEventTypeForOperation(claim.operation),
|
|
5710
|
+
title: typeof privatePatch.title === "string" ? privatePatch.title : null,
|
|
5711
|
+
status: typeof safeMetadata.status === "string" ? safeMetadata.status : null,
|
|
5712
|
+
created_at: typeof safeMetadata.updated_at === "number" ? safeMetadata.updated_at : Math.floor(Date.now() / 1e3),
|
|
5713
|
+
task_update_job_id: job.job_id
|
|
5714
|
+
};
|
|
5715
|
+
const userMessageId = claim.message_id ?? params.fallbackUserMessageId;
|
|
5716
|
+
if (!userMessageId) throw new Error(`Task update job ${job.job_id} is missing a user message id.`);
|
|
5717
|
+
const eventMessage = await buildTaskEventSystemMessage({
|
|
5718
|
+
chatKey: sourceChatKey,
|
|
5719
|
+
userMessageId,
|
|
5720
|
+
event
|
|
5721
|
+
});
|
|
5722
|
+
const confirmTaskEventPersisted = async () => {
|
|
5723
|
+
const confirmedPromise = params.ws.waitForMessage(
|
|
5724
|
+
"task_update_job_event_confirmed",
|
|
5725
|
+
(payload) => payload.job_id === job.job_id,
|
|
5726
|
+
2e4
|
|
5727
|
+
);
|
|
5728
|
+
await params.ws.sendAsync("task_update_job_event_confirmed", {
|
|
5729
|
+
protocol_version: 1,
|
|
5730
|
+
job_id: job.job_id,
|
|
5731
|
+
event_system_message_id: eventMessage.message_id
|
|
5732
|
+
});
|
|
5733
|
+
await confirmedPromise;
|
|
5734
|
+
};
|
|
5735
|
+
if (claim.state === "TASK_PERSISTED") {
|
|
5736
|
+
await this.persistEncryptedSystemMessage(params.ws, eventMessage, sourceChatId);
|
|
5737
|
+
await confirmTaskEventPersisted();
|
|
5738
|
+
handledJobIds.add(job.job_id);
|
|
5739
|
+
continue;
|
|
5740
|
+
}
|
|
5741
|
+
if (!claim.lease_token || !Number.isSafeInteger(claim.lease_generation)) {
|
|
5742
|
+
throw new Error("Task update job claim returned an invalid lease.");
|
|
5743
|
+
}
|
|
5744
|
+
let encryptedTaskPayload;
|
|
5745
|
+
if (claim.operation === "create") {
|
|
5746
|
+
const input = await buildCreateUserTaskInput(masterKey, {
|
|
5747
|
+
title: typeof privatePatch.title === "string" ? privatePatch.title : "Untitled task",
|
|
5748
|
+
description: typeof privatePatch.description === "string" ? privatePatch.description : "",
|
|
5749
|
+
status: typeof safeMetadata.status === "string" ? safeMetadata.status : "todo",
|
|
5750
|
+
assign: typeof safeMetadata.assignee_type === "string" ? safeMetadata.assignee_type : "user",
|
|
5751
|
+
chatId: typeof safeMetadata.primary_chat_id === "string" ? safeMetadata.primary_chat_id : claim.chat_id ?? params.activeChatId
|
|
5752
|
+
});
|
|
5753
|
+
encryptedTaskPayload = {
|
|
5754
|
+
...input,
|
|
5755
|
+
task_id: claim.task_id,
|
|
5756
|
+
position: typeof safeMetadata.position === "number" ? safeMetadata.position : input.position,
|
|
5757
|
+
created_at: typeof safeMetadata.created_at === "number" ? safeMetadata.created_at : input.created_at,
|
|
5758
|
+
updated_at: typeof safeMetadata.updated_at === "number" ? safeMetadata.updated_at : input.updated_at
|
|
5759
|
+
};
|
|
5760
|
+
} else {
|
|
5761
|
+
const task = await findTaskForUpdateJob(claim);
|
|
5762
|
+
const patch = await buildUpdateUserTaskInput(task, masterKey, {
|
|
5763
|
+
title: typeof privatePatch.title === "string" ? privatePatch.title : void 0,
|
|
5764
|
+
description: typeof privatePatch.description === "string" ? privatePatch.description : void 0,
|
|
5765
|
+
status: typeof safeMetadata.status === "string" ? safeMetadata.status : void 0,
|
|
5766
|
+
assign: typeof safeMetadata.assignee_type === "string" ? safeMetadata.assignee_type : void 0,
|
|
5767
|
+
chatId: typeof safeMetadata.primary_chat_id === "string" ? safeMetadata.primary_chat_id : void 0
|
|
5768
|
+
});
|
|
5769
|
+
encryptedTaskPayload = {
|
|
5770
|
+
...patch,
|
|
5771
|
+
version: claim.expected_task_version,
|
|
5772
|
+
updated_at: typeof safeMetadata.updated_at === "number" ? safeMetadata.updated_at : patch.updated_at
|
|
5773
|
+
};
|
|
5774
|
+
if (typeof safeMetadata.primary_chat_id === "string") {
|
|
5775
|
+
encryptedTaskPayload.key_wrappers = await buildTaskKeyWrappersForChat(
|
|
5776
|
+
task,
|
|
5777
|
+
safeMetadata.primary_chat_id,
|
|
5778
|
+
typeof safeMetadata.updated_at === "number" ? safeMetadata.updated_at : Math.floor(Date.now() / 1e3)
|
|
5779
|
+
);
|
|
5780
|
+
}
|
|
5781
|
+
}
|
|
5782
|
+
const persistedPromise = params.ws.waitForMessage(
|
|
5783
|
+
"task_update_job_persisted",
|
|
5784
|
+
(payload) => payload.job_id === job.job_id,
|
|
5785
|
+
2e4
|
|
5786
|
+
);
|
|
5787
|
+
await params.ws.sendAsync("task_update_job_persist", buildTaskUpdateJobPersistPayload({
|
|
5788
|
+
jobId: job.job_id,
|
|
5789
|
+
leaseToken: claim.lease_token,
|
|
5790
|
+
leaseGeneration: claim.lease_generation,
|
|
5791
|
+
expectedTaskVersion: claim.expected_task_version,
|
|
5792
|
+
encryptedTaskPayload,
|
|
5793
|
+
encryptedTaskEventMessage: eventMessage.encrypted_content
|
|
5794
|
+
}));
|
|
5795
|
+
await persistedPromise;
|
|
5796
|
+
await this.persistEncryptedSystemMessage(params.ws, eventMessage, sourceChatId);
|
|
5797
|
+
await confirmTaskEventPersisted();
|
|
5798
|
+
handledJobIds.add(job.job_id);
|
|
5799
|
+
}
|
|
5800
|
+
clearSyncCache();
|
|
5801
|
+
return handledJobIds;
|
|
5802
|
+
}
|
|
5794
5803
|
async persistStreamedEmbeds(params) {
|
|
5795
5804
|
const finalized = new Map(
|
|
5796
5805
|
params.embeds.filter((embed) => {
|
|
@@ -6032,14 +6041,28 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
6032
6041
|
}
|
|
6033
6042
|
async pollTaskUntilComplete(taskId, headers) {
|
|
6034
6043
|
const started = Date.now();
|
|
6044
|
+
let lastTransientError = null;
|
|
6035
6045
|
while (Date.now() - started < SKILL_TASK_POLL_TIMEOUT_MS) {
|
|
6036
|
-
|
|
6037
|
-
|
|
6038
|
-
|
|
6039
|
-
|
|
6046
|
+
let response;
|
|
6047
|
+
try {
|
|
6048
|
+
response = await this.http.get(
|
|
6049
|
+
`/v1/tasks/${encodeURIComponent(taskId)}`,
|
|
6050
|
+
headers
|
|
6051
|
+
);
|
|
6052
|
+
} catch (error) {
|
|
6053
|
+
lastTransientError = error instanceof Error ? error.message : String(error);
|
|
6054
|
+
await new Promise((resolve7) => setTimeout(resolve7, SKILL_TASK_POLL_INTERVAL_MS));
|
|
6055
|
+
continue;
|
|
6056
|
+
}
|
|
6040
6057
|
if (!response.ok) {
|
|
6058
|
+
if (response.status >= SKILL_TASK_POLL_TRANSIENT_ERROR_STATUS) {
|
|
6059
|
+
lastTransientError = `HTTP ${response.status}`;
|
|
6060
|
+
await new Promise((resolve7) => setTimeout(resolve7, SKILL_TASK_POLL_INTERVAL_MS));
|
|
6061
|
+
continue;
|
|
6062
|
+
}
|
|
6041
6063
|
throw new Error(`Task polling failed with HTTP ${response.status}`);
|
|
6042
6064
|
}
|
|
6065
|
+
lastTransientError = null;
|
|
6043
6066
|
if (response.data.status === "completed") {
|
|
6044
6067
|
return response.data;
|
|
6045
6068
|
}
|
|
@@ -6048,6 +6071,11 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
6048
6071
|
}
|
|
6049
6072
|
await new Promise((resolve7) => setTimeout(resolve7, SKILL_TASK_POLL_INTERVAL_MS));
|
|
6050
6073
|
}
|
|
6074
|
+
if (lastTransientError) {
|
|
6075
|
+
throw new Error(
|
|
6076
|
+
`Task ${taskId} did not complete within ${SKILL_TASK_POLL_TIMEOUT_MS / 1e3}s; last polling error: ${lastTransientError}`
|
|
6077
|
+
);
|
|
6078
|
+
}
|
|
6051
6079
|
throw new Error(`Task ${taskId} did not complete within ${SKILL_TASK_POLL_TIMEOUT_MS / 1e3}s`);
|
|
6052
6080
|
}
|
|
6053
6081
|
wrapResolvedSkillResult(original, result) {
|
|
@@ -7611,7 +7639,13 @@ Required: ${schema.required.join(", ")}`
|
|
|
7611
7639
|
* Get the session for file upload authentication.
|
|
7612
7640
|
*/
|
|
7613
7641
|
getSession() {
|
|
7614
|
-
|
|
7642
|
+
const session = this.requireSession();
|
|
7643
|
+
const currentCookies = this.http.getCookieMap();
|
|
7644
|
+
if (JSON.stringify(session.cookies) !== JSON.stringify(currentCookies)) {
|
|
7645
|
+
session.cookies = currentCookies;
|
|
7646
|
+
saveSession(session);
|
|
7647
|
+
}
|
|
7648
|
+
return session;
|
|
7615
7649
|
}
|
|
7616
7650
|
// ── Share link creation ──────────────────────────────────────────────
|
|
7617
7651
|
/**
|
|
@@ -8115,6 +8149,7 @@ Required: ${schema.required.join(", ")}`
|
|
|
8115
8149
|
let totalChatCount = 0;
|
|
8116
8150
|
let reconciliation = { authoritative: false };
|
|
8117
8151
|
const pendingAIResponses = [];
|
|
8152
|
+
let pendingTaskUpdateJobs = [];
|
|
8118
8153
|
try {
|
|
8119
8154
|
ws.send("phased_sync_request", {
|
|
8120
8155
|
phase: "all",
|
|
@@ -8163,6 +8198,7 @@ Required: ${schema.required.join(", ")}`
|
|
|
8163
8198
|
pendingAIResponses.push(frame.payload);
|
|
8164
8199
|
}
|
|
8165
8200
|
}
|
|
8201
|
+
pendingTaskUpdateJobs = ws.drainPassiveTaskUpdateJobs();
|
|
8166
8202
|
for (const chat of chats) {
|
|
8167
8203
|
const id = typeof chat.details.id === "string" ? chat.details.id : "";
|
|
8168
8204
|
const msgs = messagesByChatId.get(id);
|
|
@@ -8239,11 +8275,26 @@ Required: ${schema.required.join(", ")}`
|
|
|
8239
8275
|
chats.sort(
|
|
8240
8276
|
(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)
|
|
8241
8277
|
);
|
|
8278
|
+
let persistedTaskJobIds = /* @__PURE__ */ new Set();
|
|
8242
8279
|
try {
|
|
8243
8280
|
await this.persistPendingAIResponsesFromSync(ws, chats, pendingAIResponses);
|
|
8281
|
+
persistedTaskJobIds = await this.persistPendingTaskUpdateJobs({
|
|
8282
|
+
ws,
|
|
8283
|
+
jobs: pendingTaskUpdateJobs,
|
|
8284
|
+
events: [],
|
|
8285
|
+
activeChatId: null,
|
|
8286
|
+
activeChatKeyBytes: null,
|
|
8287
|
+
fallbackUserMessageId: null,
|
|
8288
|
+
syncedChats: chats,
|
|
8289
|
+
requireActiveTurnEvent: false
|
|
8290
|
+
});
|
|
8244
8291
|
} finally {
|
|
8245
8292
|
ws.close();
|
|
8246
8293
|
}
|
|
8294
|
+
if (persistedTaskJobIds.size > 0) {
|
|
8295
|
+
clearSyncCache();
|
|
8296
|
+
return this.ensureSynced(true, refreshChatIds);
|
|
8297
|
+
}
|
|
8247
8298
|
const cache = {
|
|
8248
8299
|
syncedAt: Date.now(),
|
|
8249
8300
|
totalChatCount,
|
|
@@ -23630,6 +23681,76 @@ var privateWorkspaceDemoVideoChat = {
|
|
|
23630
23681
|
}
|
|
23631
23682
|
};
|
|
23632
23683
|
|
|
23684
|
+
// ../ui/src/demo_chats/data/example_chats/reference-image-3d-model.ts
|
|
23685
|
+
var MODEL3D_POSTER_DATA_URL = "data:image/webp;base64,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";
|
|
23686
|
+
var referenceImage3DModelChat = {
|
|
23687
|
+
chat_id: "example-reference-image-3d-model",
|
|
23688
|
+
slug: "reference-image-3d-model",
|
|
23689
|
+
title: "example_chats.reference_image_3d_model.title",
|
|
23690
|
+
summary: "example_chats.reference_image_3d_model.summary",
|
|
23691
|
+
icon: "3dmodels",
|
|
23692
|
+
category: "design",
|
|
23693
|
+
keywords: ["3D model generation", "image to 3D", "Hi3D", "GLB", "product design"],
|
|
23694
|
+
follow_up_suggestions: [],
|
|
23695
|
+
messages: [
|
|
23696
|
+
{
|
|
23697
|
+
id: "c79b9ff0-7d58-4ed7-b860-4c427cdab6bd",
|
|
23698
|
+
role: "user",
|
|
23699
|
+
content: "example_chats.reference_image_3d_model.message_1",
|
|
23700
|
+
created_at: 1784071246
|
|
23701
|
+
},
|
|
23702
|
+
{
|
|
23703
|
+
id: "fbf595b9-2f71-4a7a-b544-56529bf9a38d",
|
|
23704
|
+
role: "assistant",
|
|
23705
|
+
content: "example_chats.reference_image_3d_model.message_2",
|
|
23706
|
+
created_at: 1784071268,
|
|
23707
|
+
category: "design",
|
|
23708
|
+
model_name: "Gemini 3 Flash"
|
|
23709
|
+
}
|
|
23710
|
+
],
|
|
23711
|
+
embeds: [
|
|
23712
|
+
{
|
|
23713
|
+
embed_id: "85716124-48d5-4c4c-9919-3126b733b41e",
|
|
23714
|
+
type: "app_skill_use",
|
|
23715
|
+
content: `app_id: models3d
|
|
23716
|
+
skill_id: generate
|
|
23717
|
+
type: model3d
|
|
23718
|
+
status: finished
|
|
23719
|
+
input_mode: image
|
|
23720
|
+
prompt: "Create a textured 3D GLB model from the uploaded reference image."
|
|
23721
|
+
provider: Hi3D
|
|
23722
|
+
provider_model: Hi3D
|
|
23723
|
+
poster_url: "${MODEL3D_POSTER_DATA_URL}"
|
|
23724
|
+
files:
|
|
23725
|
+
master:
|
|
23726
|
+
size_bytes: 25847448
|
|
23727
|
+
format: glb
|
|
23728
|
+
mime_type: model/gltf-binary
|
|
23729
|
+
poster:
|
|
23730
|
+
size_bytes: 20690
|
|
23731
|
+
format: webp
|
|
23732
|
+
mime_type: image/webp
|
|
23733
|
+
preview:
|
|
23734
|
+
size_bytes: 25847448
|
|
23735
|
+
format: glb
|
|
23736
|
+
mime_type: model/gltf-binary
|
|
23737
|
+
optimized: false
|
|
23738
|
+
fallback_reason: preview_optimization_failed
|
|
23739
|
+
generated_at: "2026-07-14T23:20:46+00:00"
|
|
23740
|
+
provenance:
|
|
23741
|
+
ai_generated: true
|
|
23742
|
+
labeling: static_public_fixture`,
|
|
23743
|
+
parent_embed_id: null,
|
|
23744
|
+
embed_ids: null
|
|
23745
|
+
}
|
|
23746
|
+
],
|
|
23747
|
+
metadata: {
|
|
23748
|
+
featured: true,
|
|
23749
|
+
order: 38,
|
|
23750
|
+
app_skill_examples: ["models3d.generate"]
|
|
23751
|
+
}
|
|
23752
|
+
};
|
|
23753
|
+
|
|
23633
23754
|
// ../ui/src/demo_chats/data/example_chats/upcoming-reminders-list.ts
|
|
23634
23755
|
var upcomingRemindersListChat = {
|
|
23635
23756
|
chat_id: "example-upcoming-reminders-list",
|
|
@@ -28227,6 +28348,7 @@ var ALL_EXAMPLE_CHATS = [
|
|
|
28227
28348
|
berlinDermatologyAppointmentsChat,
|
|
28228
28349
|
productLaunchSynthLoopChat,
|
|
28229
28350
|
privateWorkspaceDemoVideoChat,
|
|
28351
|
+
referenceImage3DModelChat,
|
|
28230
28352
|
upcomingRemindersListChat,
|
|
28231
28353
|
cancelTestReminderChat,
|
|
28232
28354
|
fediverseActivitypubSocialSearchChat,
|
|
@@ -36866,6 +36988,20 @@ Like [Denis Villeneuve](wiki:Denis_Villeneuve)\u2019s work, *Contact* avoids the
|
|
|
36866
36988
|
text: '```json\n{"type": "app_skill_use", "embed_id": "11ff377e-a0a2-40ed-81c3-9556b68142f3", "app_id": "videos", "skill_id": "search", "query": "retrieval augmented generation explained for beginners", "provider": "Brave"}\n```\n\nI\'ve found some excellent beginner-friendly videos that explain Retrieval-Augmented Generation (RAG). Here is a curated selection to get you started:\n\n[!](embed:youtube.com-OCK)\n[!](embed:youtube.com-20R)\n[!](embed:youtube.com-8SW)\n[!](embed:youtube.com-Fn4)\n[!](embed:youtube.com-rgp)\n\n### Which one should you watch first?\n\nI highly recommend starting with **[What is Retrieval-Augmented Generation (RAG)?](embed:youtube.com-OCK)** by **IBM Technology**.\n\n**Why this one first?**\n* **Conciseness:** At just 6 and a half minutes, it provides the most efficient "conceptual hook" without getting bogged down in implementation details.\n* **High-Level Clarity:** IBM\u2019s explanations are famous for being professional and easy to follow. They focus on the *why* (fixing LLM hallucinations and outdated data) before diving into the *what*.\n* **Authoritative:** It establishes a solid foundation from a reputable industry leader, which helps you better understand the more technical or "hands-on" videos later.\n\n### What to watch next?\n\nOnce you have the concept down, here are two paths depending on your interest:\n\n1. **For a better intuitive understanding:** Watch **[RAG Explained in 12 Minutes](embed:youtube.com-20R)** by **Aishwarya Srinivasan**. She uses a brilliant "Open-Book Exam" analogy that makes the whole process click instantly for most beginners.\n2. **For a technical overview:** If you want to see the "moving parts" (like vector databases and embeddings), check out **[RAG Explained For Beginners](embed:youtube.com-8SW)** by **KodeKloud**. It breaks the process down into a simple 3-step framework: Retrieval, Augmentation, and Generation.\n\nIf you\'re interested in building a RAG system yourself, I can help you find documentation for popular tools like [LangChain](wiki:LangChain) or LlamaIndex. Would you like to see how a simple RAG implementation looks in code?\n\n**Further exploration:**\n* [Check out more AI tutorials](/#settings/apps/videos)\n* [Search for RAG documentation](/#settings/apps/code)'
|
|
36867
36989
|
}
|
|
36868
36990
|
},
|
|
36991
|
+
reference_image_3d_model: {
|
|
36992
|
+
title: {
|
|
36993
|
+
text: "Reference Image to 3D Model"
|
|
36994
|
+
},
|
|
36995
|
+
summary: {
|
|
36996
|
+
text: "A 3D generation example that turns a reference image into a textured GLB model preview."
|
|
36997
|
+
},
|
|
36998
|
+
message_1: {
|
|
36999
|
+
text: "@skill:models3d:generate Turn this reference image into a textured 3D GLB model suitable for a product mockup."
|
|
37000
|
+
},
|
|
37001
|
+
message_2: {
|
|
37002
|
+
text: '```json\n{"type":"app_skill_use","embed_id":"85716124-48d5-4c4c-9919-3126b733b41e","app_id":"models3d","skill_id":"generate"}\n```\n\nI generated a textured GLB model from the reference image and attached the 3D model preview above.'
|
|
37003
|
+
}
|
|
37004
|
+
},
|
|
36869
37005
|
right_to_repair_laws_eu_us: {
|
|
36870
37006
|
title: {
|
|
36871
37007
|
text: "Right-to-Repair Laws in the EU and US"
|
|
@@ -47255,6 +47391,84 @@ As of mid-2026, the severe supply shocks from the 2024\u20132025 avian flu have
|
|
|
47255
47391
|
first_invites: {
|
|
47256
47392
|
text: "First invites in Jan/Feb 2025"
|
|
47257
47393
|
}
|
|
47394
|
+
},
|
|
47395
|
+
workflows: {
|
|
47396
|
+
template_share: {
|
|
47397
|
+
title: {
|
|
47398
|
+
text: "Share as template"
|
|
47399
|
+
},
|
|
47400
|
+
create_link: {
|
|
47401
|
+
text: "Create template link"
|
|
47402
|
+
},
|
|
47403
|
+
import: {
|
|
47404
|
+
text: "Import template"
|
|
47405
|
+
},
|
|
47406
|
+
complete_bindings: {
|
|
47407
|
+
text: "Complete requirements and enable"
|
|
47408
|
+
},
|
|
47409
|
+
revoked: {
|
|
47410
|
+
text: "Template access revoked."
|
|
47411
|
+
}
|
|
47412
|
+
},
|
|
47413
|
+
version_history: {
|
|
47414
|
+
title: {
|
|
47415
|
+
text: "Definition history"
|
|
47416
|
+
},
|
|
47417
|
+
retention: {
|
|
47418
|
+
text: "Keeps up to {max} definitions"
|
|
47419
|
+
},
|
|
47420
|
+
retention_loading: {
|
|
47421
|
+
text: "Loading retention..."
|
|
47422
|
+
},
|
|
47423
|
+
loading: {
|
|
47424
|
+
text: "Loading definition history..."
|
|
47425
|
+
},
|
|
47426
|
+
empty: {
|
|
47427
|
+
text: "No definition history is available yet."
|
|
47428
|
+
},
|
|
47429
|
+
version: {
|
|
47430
|
+
text: "Version {version}"
|
|
47431
|
+
},
|
|
47432
|
+
current: {
|
|
47433
|
+
text: "Current"
|
|
47434
|
+
},
|
|
47435
|
+
restored: {
|
|
47436
|
+
text: "Restored"
|
|
47437
|
+
},
|
|
47438
|
+
inspecting: {
|
|
47439
|
+
text: "Loading definition..."
|
|
47440
|
+
},
|
|
47441
|
+
inspecting_version: {
|
|
47442
|
+
text: "Version {version} graph"
|
|
47443
|
+
},
|
|
47444
|
+
nodes: {
|
|
47445
|
+
text: "nodes"
|
|
47446
|
+
},
|
|
47447
|
+
restore_as_new: {
|
|
47448
|
+
text: "Restore version {version} as new current version"
|
|
47449
|
+
},
|
|
47450
|
+
restore_explanation: {
|
|
47451
|
+
text: "This creates a new current version. The selected and existing versions remain unchanged."
|
|
47452
|
+
},
|
|
47453
|
+
confirm_restore: {
|
|
47454
|
+
text: "Create new current version"
|
|
47455
|
+
},
|
|
47456
|
+
restoring: {
|
|
47457
|
+
text: "Restoring..."
|
|
47458
|
+
},
|
|
47459
|
+
restore_success: {
|
|
47460
|
+
text: "Restored version {version} as a new current version."
|
|
47461
|
+
},
|
|
47462
|
+
load_failed: {
|
|
47463
|
+
text: "Failed to load definition history."
|
|
47464
|
+
},
|
|
47465
|
+
inspect_failed: {
|
|
47466
|
+
text: "Failed to load the selected definition."
|
|
47467
|
+
},
|
|
47468
|
+
restore_failed: {
|
|
47469
|
+
text: "Failed to restore the selected definition."
|
|
47470
|
+
}
|
|
47471
|
+
}
|
|
47258
47472
|
}
|
|
47259
47473
|
};
|
|
47260
47474
|
|
package/dist/cli.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1235,6 +1235,8 @@ declare class OpenMatesClient {
|
|
|
1235
1235
|
entryCount: number;
|
|
1236
1236
|
}>;
|
|
1237
1237
|
}>;
|
|
1238
|
+
private persistEncryptedSystemMessage;
|
|
1239
|
+
private persistPendingTaskUpdateJobs;
|
|
1238
1240
|
private persistStreamedEmbeds;
|
|
1239
1241
|
private persistPostProcessingMetadata;
|
|
1240
1242
|
/**
|
package/dist/index.js
CHANGED