@canonmsg/agent-sdk 13.2.0 → 13.2.1
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/chunks/{chunk-YHDDOADK.js → chunk-2NVLVPSG.js} +1 -1
- package/dist/chunks/{chunk-YJUPKU47.js → chunk-BPSFHEAA.js} +2 -2
- package/dist/chunks/{chunk-5YKGDUJX.js → chunk-HTLKCUQG.js} +82 -361
- package/dist/chunks/{chunk-DTAWEQCM.js → chunk-POBMFS2K.js} +2 -2
- package/dist/chunks/{chunk-6FD6KFQN.js → chunk-TJBG6NKF.js} +5 -5
- package/dist/chunks/{chunk-5WPAB5MB.js → chunk-VIS5WXNH.js} +0 -24
- package/dist/chunks/{mls-crypto-NZVMSUFU.js → mls-crypto-ZBEC26B5.js} +2 -2
- package/dist/cli.js +6 -6
- package/dist/index.js +6 -6
- package/dist/internal/endpoint/engine.d.ts +2 -6
- package/dist/internal/endpoint/events.d.ts +1 -2
- package/dist/internal/endpoint/index.d.ts +0 -5
- package/dist/internal/endpoint/media.d.ts +2 -61
- package/dist/internal/endpoint/queue.d.ts +1 -3
- package/dist/media.js +4 -4
- package/dist/mls-wasm-host.js +3 -3
- package/package.json +2 -3
- package/dist/internal/endpoint/artifact-images.d.ts +0 -60
- package/dist/internal/endpoint/artifact-reducer.d.ts +0 -35
- package/dist/internal/endpoint/artifact-views.d.ts +0 -113
- package/dist/internal/endpoint/artifacts.d.ts +0 -75
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
createHttpEndpointTransport,
|
|
6
6
|
createNodeEndpointStore,
|
|
7
7
|
validateEndpointContentBoundary
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-BPSFHEAA.js";
|
|
9
9
|
import {
|
|
10
10
|
CANON_ENDPOINT_PROTOCOL,
|
|
11
11
|
CANON_VERB_WIRE_SCHEMA_VERSION,
|
|
@@ -40,8 +40,6 @@ import {
|
|
|
40
40
|
isMlsDevTextProtocol,
|
|
41
41
|
isMlsEnvironmentId,
|
|
42
42
|
isMlsPrincipalAlias,
|
|
43
|
-
logicalMediaBlobId,
|
|
44
|
-
mergeDeliveryObservation,
|
|
45
43
|
mlsAdmissionWait,
|
|
46
44
|
mlsDevProtocolCarriesCards,
|
|
47
45
|
normalizePublicRuntimeDescriptor,
|
|
@@ -102,12 +100,11 @@ import {
|
|
|
102
100
|
parseMlsPrincipalOpening,
|
|
103
101
|
parseMlsRoomIdentities,
|
|
104
102
|
prepareJsonContent,
|
|
105
|
-
projectDeliveryStatus,
|
|
106
103
|
projectVerbIntentToWire,
|
|
107
104
|
readMembershipChangeMetadata,
|
|
108
105
|
resolveAllowedUploadMimeType,
|
|
109
106
|
sanitizeDownloadFileName
|
|
110
|
-
} from "./chunk-
|
|
107
|
+
} from "./chunk-VIS5WXNH.js";
|
|
111
108
|
|
|
112
109
|
// src/media.ts
|
|
113
110
|
import { createWriteStream as createWriteStream2 } from "node:fs";
|
|
@@ -587,7 +584,6 @@ function endpointIntentOrdering(intent2) {
|
|
|
587
584
|
const body = { ...intent2.body, ...intent2.envelope };
|
|
588
585
|
if (intent2.action === "consume_runtime_signal") return "independent";
|
|
589
586
|
if (intent2.action === "generate_image") return "provider";
|
|
590
|
-
if (["append_artifact_command", "retain_artifact_asset"].includes(intent2.action) && typeof body.artifactId === "string") return "artifact";
|
|
591
587
|
if (intent2.action === "session_control" && !body.primitive && typeof body.agentId === "string") {
|
|
592
588
|
const type = body.signal?.type;
|
|
593
589
|
if (type === "interrupt" || type === "stop_and_drop") return "signal";
|
|
@@ -609,12 +605,10 @@ async function orderOperation(tx, operation) {
|
|
|
609
605
|
}
|
|
610
606
|
__name(orderOperation, "orderOperation");
|
|
611
607
|
var outboxKey = /* @__PURE__ */ __name((operation) => operation.queueOrder === void 0 ? `outbox/${operation.operationId}` : `outbox/${ordinal(operation.queueOrder)}/${operation.operationId}`, "outboxKey");
|
|
612
|
-
var artifactOrderingPrefix = /* @__PURE__ */ __name((conversationId, artifactId) => `outbound-artifact-order/${scope(conversationId)}/${scope(artifactId)}/`, "artifactOrderingPrefix");
|
|
613
608
|
var controlOrderingKey = /* @__PURE__ */ __name((operation) => operation.action === "session_control" && operation.conversationId && operation.agentId ? `outbound-control-order/${scope(operation.conversationId)}/${scope(operation.agentId)}/` : void 0, "controlOrderingKey");
|
|
614
609
|
var operationOrderingKey = /* @__PURE__ */ __name((operation) => {
|
|
615
610
|
if (!operation.conversationId || operation.ordering === "independent" || operation.ordering === "provider") return void 0;
|
|
616
611
|
if (operation.ordering === "signal") return controlOrderingKey(operation);
|
|
617
|
-
if (operation.ordering === "artifact") return artifactOrderingPrefix(operation.conversationId, operation.artifactId ?? "~");
|
|
618
612
|
return operation.ordering === "message" ? `outbound-ack-order/${scope(operation.conversationId)}/${scope(operation.messageId)}/` : `outbound-order/${scope(operation.conversationId)}/`;
|
|
619
613
|
}, "operationOrderingKey");
|
|
620
614
|
var outboundPrefix = /* @__PURE__ */ __name((operation) => operationOrderingKey(operation), "outboundPrefix");
|
|
@@ -1106,42 +1100,18 @@ var ROOM_QUERIES = /* @__PURE__ */ new Set([
|
|
|
1106
1100
|
"list_voice_sessions",
|
|
1107
1101
|
"get_voice_session"
|
|
1108
1102
|
]);
|
|
1109
|
-
var ARTIFACT_QUERIES = /* @__PURE__ */ new Set(["list_artifacts", "get_artifact_log", "get_artifact_asset"]);
|
|
1110
1103
|
var INBOX_QUERIES = /* @__PURE__ */ new Set(["list_conversations", "get_unread_summary"]);
|
|
1111
1104
|
var CONTACT_QUERIES = /* @__PURE__ */ new Set(["list_contacts", "get_contact", "list_contact_requests"]);
|
|
1112
1105
|
var ROOM_OPERATIONS = /* @__PURE__ */ new Set(["send_message", "mls_application", "mls_group_control", "react", "delete_message", "mark_read"]);
|
|
1113
|
-
var ARTIFACT_OPERATIONS = /* @__PURE__ */ new Set(["append_artifact_command", "retain_artifact_asset"]);
|
|
1114
1106
|
function queryAffectedByOperation(operation, query, parameters) {
|
|
1115
|
-
if (ARTIFACT_OPERATIONS.has(operation.action)) {
|
|
1116
|
-
if (operation.status !== "succeeded" || !ARTIFACT_QUERIES.has(query)) return false;
|
|
1117
|
-
return typeof parameters.conversationId !== "string" || !operation.conversationId || parameters.conversationId === operation.conversationId;
|
|
1118
|
-
}
|
|
1119
|
-
if (ARTIFACT_QUERIES.has(query)) return false;
|
|
1120
1107
|
if (!ROOM_OPERATIONS.has(operation.action)) return true;
|
|
1121
1108
|
if (operation.status !== "succeeded" && !(operation.action === "mls_application" && ["rejected", "uncertain"].includes(operation.status))) return false;
|
|
1122
1109
|
return queryAffectedByEvent({ kind: "conversation.changed", data: { conversationId: operation.conversationId } }, query, parameters);
|
|
1123
1110
|
}
|
|
1124
1111
|
__name(queryAffectedByOperation, "queryAffectedByOperation");
|
|
1125
|
-
function artifactQueryAffected(event, query, parameters) {
|
|
1126
|
-
const conversationId = parameters.conversationId;
|
|
1127
|
-
const sameRoom = typeof conversationId !== "string" || typeof event.data.conversationId !== "string" || event.data.conversationId === conversationId;
|
|
1128
|
-
if (event.kind === "artifact.changed") {
|
|
1129
|
-
if (!sameRoom) return false;
|
|
1130
|
-
return query === "list_artifacts" || typeof parameters.artifactId !== "string" || typeof event.data.artifactId !== "string" || parameters.artifactId === event.data.artifactId;
|
|
1131
|
-
}
|
|
1132
|
-
if (event.kind === "conversation.removed") return sameRoom;
|
|
1133
|
-
if (event.kind === "conversations.changed") {
|
|
1134
|
-
const removed = event.data.removedConversationIds;
|
|
1135
|
-
return Array.isArray(removed) && (typeof conversationId !== "string" || removed.includes(conversationId));
|
|
1136
|
-
}
|
|
1137
|
-
return false;
|
|
1138
|
-
}
|
|
1139
|
-
__name(artifactQueryAffected, "artifactQueryAffected");
|
|
1140
1112
|
function queryAffectedByEvent(event, query, parameters) {
|
|
1141
|
-
if (!ROOM_QUERIES.has(query) && !
|
|
1113
|
+
if (!ROOM_QUERIES.has(query) && !INBOX_QUERIES.has(query) && !CONTACT_QUERIES.has(query)) return true;
|
|
1142
1114
|
if (event.kind === "agent.context" || event.kind.startsWith("replay.")) return true;
|
|
1143
|
-
if (ARTIFACT_QUERIES.has(query)) return artifactQueryAffected(event, query, parameters);
|
|
1144
|
-
if (event.kind === "artifact.changed") return false;
|
|
1145
1115
|
if (/^contacts?\./.test(event.kind)) return CONTACT_QUERIES.has(query);
|
|
1146
1116
|
if (!/^(message\.|conversations?\.|voice\.session\.)/.test(event.kind)) return true;
|
|
1147
1117
|
if (CONTACT_QUERIES.has(query)) return false;
|
|
@@ -1172,10 +1142,10 @@ async function prepareEndpointIntent(input) {
|
|
|
1172
1142
|
const { intent: intent2 } = input;
|
|
1173
1143
|
const nested = intent2.action === "verb_execute";
|
|
1174
1144
|
const action = nested ? intent2.body.verb : intent2.action;
|
|
1175
|
-
if (!["remove_member", "update_member_role", "leave_conversation"
|
|
1145
|
+
if (!["remove_member", "update_member_role", "leave_conversation"].includes(String(action))) return intent2;
|
|
1176
1146
|
const body = intentBody(intent2);
|
|
1177
1147
|
const conversationId = body.conversationId ?? body.targetConversationId;
|
|
1178
|
-
const ownAdmission =
|
|
1148
|
+
const ownAdmission = action === "leave_conversation";
|
|
1179
1149
|
const targetUserId = body.targetUserId ?? body.userId ?? body.agentId;
|
|
1180
1150
|
if (typeof conversationId !== "string" || !ownAdmission && typeof targetUserId !== "string") {
|
|
1181
1151
|
throw new EndpointError("Membership control requires a conversation and target", { status: 400, code: "INVALID_MEMBERSHIP_CONTROL", retryable: false });
|
|
@@ -2035,7 +2005,7 @@ __name(createEndpointMigration, "createEndpointMigration");
|
|
|
2035
2005
|
|
|
2036
2006
|
// ../endpoint/src/media.ts
|
|
2037
2007
|
function createEndpointMediaPipeline(options) {
|
|
2038
|
-
const { endpoint, store, bytes
|
|
2008
|
+
const { endpoint, store, bytes } = options;
|
|
2039
2009
|
const clock = options.clock ?? Date.now;
|
|
2040
2010
|
const ids = options.ids ?? (() => crypto.randomUUID());
|
|
2041
2011
|
const leaseMs = Math.max(1e3, options.leaseMs ?? 3e4);
|
|
@@ -2090,14 +2060,6 @@ function createEndpointMediaPipeline(options) {
|
|
|
2090
2060
|
const listeners = /* @__PURE__ */ new Set();
|
|
2091
2061
|
let closed = false;
|
|
2092
2062
|
let foreground = true;
|
|
2093
|
-
let restoredNativeObservations = false;
|
|
2094
|
-
const reconciliation = /* @__PURE__ */ new Map();
|
|
2095
|
-
const observations = /* @__PURE__ */ new Map();
|
|
2096
|
-
let backgroundCapability;
|
|
2097
|
-
let lastServerBackgroundCapability;
|
|
2098
|
-
let serverPreparedContentVersion;
|
|
2099
|
-
const preparationGeneration = background ? endpoint.ready().then(() => readPreparationGeneration(store)) : Promise.resolve(0);
|
|
2100
|
-
void preparationGeneration.catch(() => void 0);
|
|
2101
2063
|
let timer;
|
|
2102
2064
|
const prefix3 = "media-flow/";
|
|
2103
2065
|
const attachmentFor = /* @__PURE__ */ __name((file, value, resultUploadId) => {
|
|
@@ -2117,7 +2079,6 @@ function createEndpointMediaPipeline(options) {
|
|
|
2117
2079
|
for (const file of previous?.files ?? []) if (file.uploadId && !currentIds.has(file.uploadId)) await tx.delete(`media-prepared-upload/${file.uploadId}`);
|
|
2118
2080
|
for (const uploadId of currentIds) await tx.put(`media-prepared-upload/${uploadId}`, { id: flow.id });
|
|
2119
2081
|
}
|
|
2120
|
-
if (flow.status === "succeeded" || flow.status === "cancelled") delete flow.preparedContent;
|
|
2121
2082
|
await tx.put(`${prefix3}${flow.id}`, flow);
|
|
2122
2083
|
if (flow.status === "pending" || flow.status === "sending") await tx.put(`media-pending/${flow.id}`, { id: flow.id });
|
|
2123
2084
|
else await tx.delete(`media-pending/${flow.id}`);
|
|
@@ -2158,10 +2119,6 @@ function createEndpointMediaPipeline(options) {
|
|
|
2158
2119
|
timer.unref?.();
|
|
2159
2120
|
}
|
|
2160
2121
|
__name(schedule, "schedule");
|
|
2161
|
-
const stopConnections = background ? endpoint.observeEvents?.(() => void 0, { families: ["messages"], onConnected: /* @__PURE__ */ __name(() => {
|
|
2162
|
-
for (const state of reconciliation.values()) state.nextAt = Math.min(state.nextAt, clock() + 5e3);
|
|
2163
|
-
schedule();
|
|
2164
|
-
}, "onConnected") }) : void 0;
|
|
2165
2122
|
const unsubscribe = endpoint.subscribe((operation) => {
|
|
2166
2123
|
if (operation.status === "succeeded" && operation.action.endsWith("_upload")) schedule();
|
|
2167
2124
|
});
|
|
@@ -2170,265 +2127,21 @@ function createEndpointMediaPipeline(options) {
|
|
|
2170
2127
|
await Promise.allSettled(flow.files.filter((file) => file.reference).map((file) => bytes.release(file.reference)));
|
|
2171
2128
|
}
|
|
2172
2129
|
__name(release, "release");
|
|
2173
|
-
function probeBackgroundCapability() {
|
|
2174
|
-
if (!background) return Promise.resolve(false);
|
|
2175
|
-
if (!backgroundCapability) {
|
|
2176
|
-
const check = Promise.resolve().then(() => Promise.all([background.available(), endpoint.capabilities()])).then(([nativeAvailable, capabilities]) => {
|
|
2177
|
-
if (capabilities) serverPreparedContentVersion = capabilities.preparedMediaContentVersion;
|
|
2178
|
-
if (capabilities) lastServerBackgroundCapability = capabilities.actions.includes("stage_media_message") && (background.observationVersion !== 2 || capabilities.mediaDeliveryObservationVersion === 2);
|
|
2179
|
-
return nativeAvailable && lastServerBackgroundCapability === true;
|
|
2180
|
-
}).catch(() => false).then((enabled) => {
|
|
2181
|
-
if (!enabled && backgroundCapability === check) backgroundCapability = void 0;
|
|
2182
|
-
return enabled;
|
|
2183
|
-
});
|
|
2184
|
-
backgroundCapability = check;
|
|
2185
|
-
}
|
|
2186
|
-
return backgroundCapability;
|
|
2187
|
-
}
|
|
2188
|
-
__name(probeBackgroundCapability, "probeBackgroundCapability");
|
|
2189
2130
|
const encryptedRoom = /* @__PURE__ */ __name(async (conversationId) => await endpoint.getConversationContentMode(conversationId) !== "plaintext", "encryptedRoom");
|
|
2190
|
-
async function
|
|
2191
|
-
if (!background) return false;
|
|
2192
|
-
if (options2?.conversationId !== void 0 && await encryptedRoom(options2.conversationId).catch(() => true)) return false;
|
|
2193
|
-
if (options2?.maxProbeWaitMs === void 0) return probeBackgroundCapability();
|
|
2194
|
-
const nativeAvailable = await Promise.resolve().then(() => background.available()).catch(() => false);
|
|
2195
|
-
if (!nativeAvailable) return false;
|
|
2196
|
-
if (lastServerBackgroundCapability === false) {
|
|
2197
|
-
void probeBackgroundCapability();
|
|
2198
|
-
return false;
|
|
2199
|
-
}
|
|
2200
|
-
const check = probeBackgroundCapability();
|
|
2201
|
-
const waitMs = Math.max(0, options2.maxProbeWaitMs);
|
|
2202
|
-
if (waitMs === 0) return false;
|
|
2203
|
-
return new Promise((resolve3) => {
|
|
2204
|
-
const timer2 = setTimeout(() => resolve3(false), waitMs);
|
|
2205
|
-
void check.then((enabled) => {
|
|
2206
|
-
clearTimeout(timer2);
|
|
2207
|
-
resolve3(enabled);
|
|
2208
|
-
});
|
|
2209
|
-
});
|
|
2210
|
-
}
|
|
2211
|
-
__name(canSendInBackground, "canSendInBackground");
|
|
2212
|
-
async function applyBackgroundSnapshot(snapshot) {
|
|
2213
|
-
if (closed || !background) return;
|
|
2214
|
-
const flow = await read(snapshot.deliveryId);
|
|
2215
|
-
if (!flow || flow.deliveryMode !== "background") return;
|
|
2216
|
-
if (snapshot.schemaVersion === 2) {
|
|
2217
|
-
const identity = await endpoint.ready();
|
|
2218
|
-
if (!snapshot.identity || snapshot.identity.installationId !== identity.installationId || snapshot.identity.environmentId !== identity.environmentId || snapshot.identity.conversationId !== flow.conversationId || snapshot.identity.messageId !== flow.messageId) {
|
|
2219
|
-
schedule();
|
|
2220
|
-
return;
|
|
2221
|
-
}
|
|
2222
|
-
}
|
|
2223
|
-
const owner = await acquire(flow.id).catch(() => null);
|
|
2224
|
-
if (!owner) {
|
|
2225
|
-
schedule();
|
|
2226
|
-
return;
|
|
2227
|
-
}
|
|
2228
|
-
try {
|
|
2229
|
-
const current = await read(flow.id);
|
|
2230
|
-
if (!current || current.deliveryMode !== "background" || current.status === "succeeded" || current.status === "cancelled") return;
|
|
2231
|
-
if (snapshot.schemaVersion === 2) {
|
|
2232
|
-
const identity = await endpoint.ready();
|
|
2233
|
-
if (snapshot.observation) current.observation = mergeDeliveryObservation(current.observation, snapshot.observation, {
|
|
2234
|
-
deliveryId: flow.id,
|
|
2235
|
-
conversationId: flow.conversationId,
|
|
2236
|
-
messageId: flow.messageId,
|
|
2237
|
-
installationId: identity.installationId,
|
|
2238
|
-
environmentId: identity.environmentId
|
|
2239
|
-
});
|
|
2240
|
-
current.attention = snapshot.attention;
|
|
2241
|
-
const phase = ["published", "cancelled", "expired", "rejected"].includes(snapshot.status) ? "idle" : snapshot.status;
|
|
2242
|
-
current.status = projectDeliveryStatus(current.observation?.outcome ?? "unknown", phase);
|
|
2243
|
-
current.background = { phase: snapshot.status, uploadedBytes: Math.max(0, snapshot.uploadedBytes), totalBytes: Math.max(0, snapshot.totalBytes) };
|
|
2244
|
-
if (current.attention) current.error = { code: current.attention.code, message: snapshot.errorMessage ?? "Delivery needs attention. Its server outcome is being checked." };
|
|
2245
|
-
else delete current.error;
|
|
2246
|
-
} else {
|
|
2247
|
-
current.background = {
|
|
2248
|
-
phase: snapshot.status,
|
|
2249
|
-
uploadedBytes: Math.max(0, snapshot.uploadedBytes),
|
|
2250
|
-
totalBytes: Math.max(0, snapshot.totalBytes)
|
|
2251
|
-
};
|
|
2252
|
-
if (snapshot.status === "published") {
|
|
2253
|
-
current.status = "succeeded";
|
|
2254
|
-
delete current.error;
|
|
2255
|
-
} else if (snapshot.status === "cancelled") {
|
|
2256
|
-
current.status = "cancelled";
|
|
2257
|
-
delete current.error;
|
|
2258
|
-
} else if (snapshot.status === "expired" || snapshot.status === "rejected") {
|
|
2259
|
-
current.status = "rejected";
|
|
2260
|
-
current.error = { code: snapshot.errorCode ?? (snapshot.status === "expired" ? "MEDIA_BACKGROUND_EXPIRED" : "MEDIA_BACKGROUND_REJECTED"), message: snapshot.errorMessage ?? "Attachment delivery needs attention" };
|
|
2261
|
-
} else {
|
|
2262
|
-
current.status = snapshot.status === "sending" ? "sending" : "pending";
|
|
2263
|
-
delete current.error;
|
|
2264
|
-
}
|
|
2265
|
-
}
|
|
2266
|
-
await write(current, owner);
|
|
2267
|
-
if (current.status === "succeeded" || current.status === "cancelled") {
|
|
2268
|
-
delete current.attention;
|
|
2269
|
-
delete current.error;
|
|
2270
|
-
await Promise.allSettled(current.files.filter((file) => file.descriptor.cleanupAfterSend).map((file) => background.cleanupSource?.(file.reference)));
|
|
2271
|
-
await write({ ...current, message: {}, files: [] }, owner);
|
|
2272
|
-
}
|
|
2273
|
-
if (current.status === "pending" || current.status === "sending") schedule();
|
|
2274
|
-
} finally {
|
|
2275
|
-
await unlock(flow.id, owner);
|
|
2276
|
-
}
|
|
2277
|
-
}
|
|
2278
|
-
__name(applyBackgroundSnapshot, "applyBackgroundSnapshot");
|
|
2279
|
-
async function authoritativeSnapshot(id2) {
|
|
2280
|
-
if (!background?.reconcile || !foreground) return void 0;
|
|
2281
|
-
const state = reconciliation.get(id2) ?? { nextAt: 0, failures: 0 };
|
|
2282
|
-
if (state.pending) return state.pending;
|
|
2283
|
-
if (clock() < state.nextAt) {
|
|
2284
|
-
schedule();
|
|
2285
|
-
return void 0;
|
|
2286
|
-
}
|
|
2287
|
-
state.nextAt = clock() + 5e3;
|
|
2288
|
-
const pending = background.reconcile(id2).then((snapshot) => {
|
|
2289
|
-
state.failures = 0;
|
|
2290
|
-
state.nextAt = clock() + 5e3;
|
|
2291
|
-
return snapshot;
|
|
2292
|
-
}, (error) => {
|
|
2293
|
-
state.failures += 1;
|
|
2294
|
-
state.nextAt = clock() + Math.min(3e5, 5e3 * 2 ** Math.min(6, state.failures));
|
|
2295
|
-
schedule();
|
|
2296
|
-
throw error;
|
|
2297
|
-
}).finally(() => {
|
|
2298
|
-
delete state.pending;
|
|
2299
|
-
});
|
|
2300
|
-
state.pending = pending;
|
|
2301
|
-
reconciliation.set(id2, state);
|
|
2302
|
-
return pending;
|
|
2303
|
-
}
|
|
2304
|
-
__name(authoritativeSnapshot, "authoritativeSnapshot");
|
|
2305
|
-
async function resumeBackground(flow, onProgress) {
|
|
2306
|
-
if (!background) throw new EndpointError("This delivery needs a Canon version with background transfer support", { code: "MEDIA_BACKGROUND_MODULE_UNAVAILABLE", retryable: false });
|
|
2131
|
+
async function retireBackground(flow) {
|
|
2307
2132
|
if (flow.status === "succeeded") return flow.messageId;
|
|
2308
|
-
if (flow.status
|
|
2309
|
-
|
|
2310
|
-
let snapshot = snapshots.find((item) => item.deliveryId === flow.id);
|
|
2311
|
-
if (!snapshot && flow.background?.phase === "cancelling") {
|
|
2312
|
-
throw new EndpointError("Cancellation is being reconciled", { code: "MEDIA_CANCELLING", retryable: true });
|
|
2313
|
-
}
|
|
2314
|
-
if (!snapshot) {
|
|
2315
|
-
const identity = await endpoint.ready();
|
|
2316
|
-
snapshot = await background.enqueue({
|
|
2317
|
-
deliveryId: flow.id,
|
|
2318
|
-
installationId: identity.installationId,
|
|
2319
|
-
conversationId: flow.conversationId,
|
|
2320
|
-
messageId: flow.messageId,
|
|
2321
|
-
message: copyJson(flow.message),
|
|
2322
|
-
...flow.preparedContent ? { preparedContent: copyJson(flow.preparedContent) } : {},
|
|
2323
|
-
files: flow.files.map((file) => ({ source: file.reference, descriptor: copyJson(file.descriptor) }))
|
|
2324
|
-
});
|
|
2325
|
-
}
|
|
2326
|
-
await applyBackgroundSnapshot(snapshot);
|
|
2327
|
-
if (background.reconcile) {
|
|
2328
|
-
const authoritative = await authoritativeSnapshot(flow.id).catch(() => void 0);
|
|
2329
|
-
if (authoritative) {
|
|
2330
|
-
snapshot = authoritative;
|
|
2331
|
-
await applyBackgroundSnapshot(snapshot);
|
|
2332
|
-
}
|
|
2333
|
-
schedule();
|
|
2334
|
-
}
|
|
2335
|
-
if (snapshot.schemaVersion !== 2 && (snapshot.status === "expired" || snapshot.status === "rejected")) {
|
|
2336
|
-
throw new EndpointError(snapshot.errorMessage ?? "Attach this file again to send it", {
|
|
2337
|
-
code: snapshot.errorCode ?? (snapshot.status === "expired" ? "MEDIA_BACKGROUND_EXPIRED" : "MEDIA_BACKGROUND_REJECTED"),
|
|
2338
|
-
retryable: false
|
|
2339
|
-
});
|
|
2340
|
-
}
|
|
2341
|
-
const phase = snapshot.status === "waiting_for_connection" ? "waiting_for_connection" : snapshot.status === "cancelling" ? "cancelling" : snapshot.status === "sending" || snapshot.status === "published" ? "sending" : snapshot.status === "uploading" ? "uploading" : "preparing";
|
|
2342
|
-
onProgress?.({ phase, uploadedBytes: snapshot.uploadedBytes, totalBytes: snapshot.totalBytes });
|
|
2343
|
-
return flow.messageId;
|
|
2344
|
-
}
|
|
2345
|
-
__name(resumeBackground, "resumeBackground");
|
|
2346
|
-
async function stageBackground(input, sendOptions) {
|
|
2347
|
-
if (!background) throw new Error("Background media adapter is missing");
|
|
2348
|
-
const id2 = flowId(input.conversationId, input.messageId);
|
|
2349
|
-
const existing = staging.get(id2);
|
|
2350
|
-
if (existing) {
|
|
2351
|
-
await existing;
|
|
2352
|
-
return stageBackground(input, sendOptions);
|
|
2353
|
-
}
|
|
2354
|
-
const staged = (async () => {
|
|
2355
|
-
if (closed || sendOptions?.signal?.aborted) throw new DOMException("Attachment cancelled", "AbortError");
|
|
2356
|
-
const fingerprint = await hash(canonicalEndpointJson({ message: input.message, files: input.files.map((file) => ({ descriptor: file.descriptor, source: background.sourceIdentity(file.source) })) }));
|
|
2357
|
-
if (closed || sendOptions?.signal?.aborted) throw new DOMException("Attachment cancelled", "AbortError");
|
|
2358
|
-
const owner = await acquire(id2);
|
|
2359
|
-
try {
|
|
2360
|
-
if (closed || sendOptions?.signal?.aborted) throw new DOMException("Attachment cancelled", "AbortError");
|
|
2361
|
-
const prior = await read(id2);
|
|
2362
|
-
if (prior) {
|
|
2363
|
-
if (prior.deliveryMode !== "background" || prior.fingerprint !== fingerprint) throw new EndpointError("Message identity already belongs to another attachment", { status: 409, code: "MEDIA_FLOW_CONFLICT", retryable: false });
|
|
2364
|
-
} else {
|
|
2365
|
-
const flow = {
|
|
2366
|
-
id: id2,
|
|
2367
|
-
conversationId: input.conversationId,
|
|
2368
|
-
messageId: input.messageId,
|
|
2369
|
-
message: copyJson(input.message),
|
|
2370
|
-
fingerprint,
|
|
2371
|
-
createdAt: new Date(clock()).toISOString(),
|
|
2372
|
-
files: input.files.map((file) => ({ descriptor: copyJson(file.descriptor), reference: background.sourceIdentity(file.source) })),
|
|
2373
|
-
deliveryMode: "background",
|
|
2374
|
-
status: "pending",
|
|
2375
|
-
background: { phase: "preparing", uploadedBytes: 0, totalBytes: input.files.reduce((sum, file) => sum + file.descriptor.sizeBytes, 0) }
|
|
2376
|
-
};
|
|
2377
|
-
if (background.preparedContentVersion === 1 && serverPreparedContentVersion === 1) {
|
|
2378
|
-
const generation2 = await preparationGeneration;
|
|
2379
|
-
const operationId = `media:${id2}`;
|
|
2380
|
-
await reservePreparedIdentity(store, { operationId, action: "send_message", fingerprint, installationGeneration: generation2 });
|
|
2381
|
-
const committed = await prepareAndCommitContent({
|
|
2382
|
-
store,
|
|
2383
|
-
scope: input.conversationId,
|
|
2384
|
-
installationGeneration: generation2,
|
|
2385
|
-
existing: /* @__PURE__ */ __name((tx) => tx.get(`${prefix3}${id2}`), "existing"),
|
|
2386
|
-
prepare: /* @__PURE__ */ __name(async (snapshot) => ({ nextProtocolState: snapshot.protocolState, payload: prepareJsonContent({
|
|
2387
|
-
context: { action: "send_message", conversationId: input.conversationId, messageId: input.messageId },
|
|
2388
|
-
body: { ...input.message, conversationId: input.conversationId, messageId: input.messageId },
|
|
2389
|
-
blobs: input.files.map((_, index) => ({ id: logicalMediaBlobId(input.conversationId, input.messageId, index), index })),
|
|
2390
|
-
expected: { installationGeneration: generation2, protocolRevision: snapshot.protocolRevision, ...snapshot.admission ? { admission: snapshot.admission } : {} }
|
|
2391
|
-
}) }), "prepare"),
|
|
2392
|
-
commit: /* @__PURE__ */ __name(async (tx, preparedContent) => {
|
|
2393
|
-
if (closed || sendOptions?.signal?.aborted) throw new DOMException("Attachment cancelled", "AbortError");
|
|
2394
|
-
const sealed = { ...flow, preparedContent };
|
|
2395
|
-
await writeInTransaction(tx, sealed, owner);
|
|
2396
|
-
await tx.delete(`preparation/${operationId}`);
|
|
2397
|
-
return sealed;
|
|
2398
|
-
}, "commit")
|
|
2399
|
-
});
|
|
2400
|
-
notifyFlow(committed);
|
|
2401
|
-
} else await write(flow, owner);
|
|
2402
|
-
}
|
|
2403
|
-
} finally {
|
|
2404
|
-
await unlock(id2, owner);
|
|
2405
|
-
}
|
|
2406
|
-
const onAbort = /* @__PURE__ */ __name(() => {
|
|
2407
|
-
void pipeline3.cancel(id2).catch(() => void 0);
|
|
2408
|
-
}, "onAbort");
|
|
2409
|
-
sendOptions?.signal?.addEventListener("abort", onAbort, { once: true });
|
|
2133
|
+
if (flow.status !== "cancelled") {
|
|
2134
|
+
const owner = await acquire(flow.id);
|
|
2410
2135
|
try {
|
|
2411
|
-
|
|
2412
|
-
|
|
2136
|
+
const { id: id2, conversationId, messageId, createdAt, deliveryMode } = flow;
|
|
2137
|
+
await write({ id: id2, conversationId, messageId, createdAt, deliveryMode, message: {}, files: [], status: "cancelled" }, owner);
|
|
2413
2138
|
} finally {
|
|
2414
|
-
|
|
2139
|
+
await unlock(flow.id, owner);
|
|
2415
2140
|
}
|
|
2416
|
-
})();
|
|
2417
|
-
staging.set(id2, staged);
|
|
2418
|
-
try {
|
|
2419
|
-
return await staged;
|
|
2420
|
-
} finally {
|
|
2421
|
-
if (staging.get(id2) === staged) staging.delete(id2);
|
|
2422
2141
|
}
|
|
2142
|
+
throw new EndpointError("Attachment was cancelled", { code: "MEDIA_FLOW_CANCELLED", retryable: false });
|
|
2423
2143
|
}
|
|
2424
|
-
__name(
|
|
2425
|
-
const stopBackground = background?.subscribe((snapshot) => {
|
|
2426
|
-
const next = (observations.get(snapshot.deliveryId) ?? Promise.resolve()).then(() => applyBackgroundSnapshot(snapshot)).catch(() => schedule());
|
|
2427
|
-
observations.set(snapshot.deliveryId, next);
|
|
2428
|
-
void next.finally(() => {
|
|
2429
|
-
if (observations.get(snapshot.deliveryId) === next) observations.delete(snapshot.deliveryId);
|
|
2430
|
-
});
|
|
2431
|
-
});
|
|
2144
|
+
__name(retireBackground, "retireBackground");
|
|
2432
2145
|
async function stage(input, sendOptions, prepareOnly = false) {
|
|
2433
2146
|
if (closed) throw new Error("Endpoint media pipeline is closed");
|
|
2434
2147
|
const id2 = flowId(input.conversationId, input.messageId);
|
|
@@ -2470,7 +2183,7 @@ function createEndpointMediaPipeline(options) {
|
|
|
2470
2183
|
files.push({ descriptor: copyJson(file.descriptor), reference: await bytes.retain(`${id2}:${fingerprint}:${index}`, file.source) });
|
|
2471
2184
|
}
|
|
2472
2185
|
checkOpen();
|
|
2473
|
-
await write({ id: id2, ...prepareOnly ? { purpose: "prepare" } : {}, conversationId: input.conversationId, messageId: input.messageId, fingerprint, createdAt: new Date(clock()).toISOString(), ...sendOptions?.beforePublish ? { requiresPublicationApproval: true } : {}, message: copyJson(input.message), files,
|
|
2186
|
+
await write({ id: id2, ...prepareOnly ? { purpose: "prepare" } : {}, conversationId: input.conversationId, messageId: input.messageId, fingerprint, createdAt: new Date(clock()).toISOString(), ...sendOptions?.beforePublish ? { requiresPublicationApproval: true } : {}, message: copyJson(input.message), files, status: "pending" }, owner);
|
|
2474
2187
|
}
|
|
2475
2188
|
} catch (error) {
|
|
2476
2189
|
await Promise.allSettled(files.map((file) => bytes.release(file.reference)));
|
|
@@ -2492,18 +2205,9 @@ function createEndpointMediaPipeline(options) {
|
|
|
2492
2205
|
}
|
|
2493
2206
|
__name(stage, "stage");
|
|
2494
2207
|
const pipeline3 = {
|
|
2495
|
-
canSendInBackground,
|
|
2496
2208
|
async send(input, sendOptions) {
|
|
2497
|
-
const
|
|
2498
|
-
|
|
2499
|
-
if (prior?.deliveryMode === "background") return stageBackground(input, sendOptions);
|
|
2500
|
-
if (!prior && !sendOptions?.beforePublish && sendOptions?.handoffMode !== "legacy") {
|
|
2501
|
-
const encrypted = await encryptedRoom(input.conversationId);
|
|
2502
|
-
if (encrypted && sendOptions?.handoffMode === "background") {
|
|
2503
|
-
throw new EndpointError("An encrypted room's attachments are prepared on this device", { code: "MEDIA_BACKGROUND_UNAVAILABLE", retryable: false });
|
|
2504
|
-
}
|
|
2505
|
-
if (!encrypted && (sendOptions?.handoffMode === "background" || await canSendInBackground())) return stageBackground(input, sendOptions);
|
|
2506
|
-
}
|
|
2209
|
+
const prior = await read(flowId(input.conversationId, input.messageId));
|
|
2210
|
+
if (prior?.deliveryMode === "background") return retireBackground(prior);
|
|
2507
2211
|
return stage(input, sendOptions);
|
|
2508
2212
|
},
|
|
2509
2213
|
async prepare(input, prepareOptions) {
|
|
@@ -2515,7 +2219,7 @@ function createEndpointMediaPipeline(options) {
|
|
|
2515
2219
|
},
|
|
2516
2220
|
async resume(id2, resumeOptions) {
|
|
2517
2221
|
const persisted = await read(id2);
|
|
2518
|
-
if (persisted?.deliveryMode === "background") return
|
|
2222
|
+
if (persisted?.deliveryMode === "background") return retireBackground(persisted);
|
|
2519
2223
|
installGuard(id2, resumeOptions?.beforePublish);
|
|
2520
2224
|
const existing = running.get(id2);
|
|
2521
2225
|
if (existing) return existing;
|
|
@@ -2771,15 +2475,6 @@ function createEndpointMediaPipeline(options) {
|
|
|
2771
2475
|
},
|
|
2772
2476
|
async resumePending() {
|
|
2773
2477
|
if (closed) return;
|
|
2774
|
-
if (background?.reconcile && !restoredNativeObservations) {
|
|
2775
|
-
restoredNativeObservations = true;
|
|
2776
|
-
try {
|
|
2777
|
-
for (const snapshot of await background.inspect()) await applyBackgroundSnapshot(snapshot);
|
|
2778
|
-
} catch {
|
|
2779
|
-
restoredNativeObservations = false;
|
|
2780
|
-
schedule();
|
|
2781
|
-
}
|
|
2782
|
-
}
|
|
2783
2478
|
let after;
|
|
2784
2479
|
do {
|
|
2785
2480
|
const records = await store.transaction((tx) => tx.scan("media-pending/", { after, limit: 100 }));
|
|
@@ -2793,20 +2488,9 @@ function createEndpointMediaPipeline(options) {
|
|
|
2793
2488
|
if (saved) await pipeline3.cancel(saved.id);
|
|
2794
2489
|
},
|
|
2795
2490
|
async cancel(id2) {
|
|
2796
|
-
const
|
|
2797
|
-
if (
|
|
2798
|
-
|
|
2799
|
-
const owner2 = await acquire(id2);
|
|
2800
|
-
try {
|
|
2801
|
-
const current = await read(id2);
|
|
2802
|
-
if (!current || current.status === "succeeded" || current.status === "cancelled") return;
|
|
2803
|
-
current.background = { phase: "cancelling", uploadedBytes: current.background?.uploadedBytes ?? 0, totalBytes: current.background?.totalBytes ?? 0 };
|
|
2804
|
-
await write(current, owner2);
|
|
2805
|
-
} finally {
|
|
2806
|
-
await unlock(id2, owner2);
|
|
2807
|
-
}
|
|
2808
|
-
await background.cancel(id2);
|
|
2809
|
-
schedule();
|
|
2491
|
+
const retired = await read(id2);
|
|
2492
|
+
if (retired?.deliveryMode === "background") {
|
|
2493
|
+
await retireBackground(retired).catch(() => void 0);
|
|
2810
2494
|
return;
|
|
2811
2495
|
}
|
|
2812
2496
|
if (staging.has(id2)) cancelledStages.add(id2);
|
|
@@ -2829,15 +2513,12 @@ function createEndpointMediaPipeline(options) {
|
|
|
2829
2513
|
async close(closeOptions) {
|
|
2830
2514
|
closed = true;
|
|
2831
2515
|
unsubscribe();
|
|
2832
|
-
stopConnections?.();
|
|
2833
|
-
stopBackground?.();
|
|
2834
2516
|
listeners.clear();
|
|
2835
2517
|
for (const guard of publicationGuards.values()) guard.unregister();
|
|
2836
2518
|
publicationGuards.clear();
|
|
2837
2519
|
if (timer) clearTimeout(timer);
|
|
2838
2520
|
for (const controller of controllers.values()) controller.abort();
|
|
2839
2521
|
await Promise.allSettled([...staging.values(), ...running.values()]);
|
|
2840
|
-
if (closeOptions?.discard) await background?.cleanup();
|
|
2841
2522
|
if (closeOptions?.discard) {
|
|
2842
2523
|
let after;
|
|
2843
2524
|
do {
|
|
@@ -3412,13 +3093,6 @@ function createExternalInboundClaims(input) {
|
|
|
3412
3093
|
}
|
|
3413
3094
|
__name(createExternalInboundClaims, "createExternalInboundClaims");
|
|
3414
3095
|
|
|
3415
|
-
// ../endpoint/src/artifact-context.ts
|
|
3416
|
-
var contexts = /* @__PURE__ */ new WeakMap();
|
|
3417
|
-
function registerArtifactEndpoint(endpoint, context) {
|
|
3418
|
-
contexts.set(endpoint, context);
|
|
3419
|
-
}
|
|
3420
|
-
__name(registerArtifactEndpoint, "registerArtifactEndpoint");
|
|
3421
|
-
|
|
3422
3096
|
// ../endpoint/src/receipts.ts
|
|
3423
3097
|
function endpointReceiptResult(receipt) {
|
|
3424
3098
|
if (receipt.resultError) throw new EndpointError(receipt.resultError.message, { status: receipt.resultError.status, code: receipt.resultError.code, retryable: receipt.resultError.retryable, operationId: receipt.operationId });
|
|
@@ -7931,6 +7605,51 @@ function createEndpoint(options) {
|
|
|
7931
7605
|
}
|
|
7932
7606
|
}
|
|
7933
7607
|
__name(refreshMlsRoomFromHint, "refreshMlsRoomFromHint");
|
|
7608
|
+
const roomHints = /* @__PURE__ */ new Map();
|
|
7609
|
+
let roomHintWorker;
|
|
7610
|
+
function queueRoomHint(key3, run, last = false) {
|
|
7611
|
+
if (closed) return Promise.resolve();
|
|
7612
|
+
let hint = roomHints.get(key3);
|
|
7613
|
+
if (hint && last) roomHints.delete(key3);
|
|
7614
|
+
if (!hint) {
|
|
7615
|
+
let settle;
|
|
7616
|
+
const done = new Promise((resolve3, reject) => {
|
|
7617
|
+
settle = /* @__PURE__ */ __name((error) => error === void 0 ? resolve3() : reject(error), "settle");
|
|
7618
|
+
});
|
|
7619
|
+
done.catch(() => void 0);
|
|
7620
|
+
hint = { run, done, settle };
|
|
7621
|
+
}
|
|
7622
|
+
roomHints.set(key3, hint);
|
|
7623
|
+
drainRoomHints();
|
|
7624
|
+
return hint.done;
|
|
7625
|
+
}
|
|
7626
|
+
__name(queueRoomHint, "queueRoomHint");
|
|
7627
|
+
function drainRoomHints() {
|
|
7628
|
+
if (roomHintWorker) return;
|
|
7629
|
+
roomHintWorker = (async () => {
|
|
7630
|
+
for (const [key3, hint] of roomHints) {
|
|
7631
|
+
roomHints.delete(key3);
|
|
7632
|
+
if (closed) {
|
|
7633
|
+
hint.settle();
|
|
7634
|
+
continue;
|
|
7635
|
+
}
|
|
7636
|
+
try {
|
|
7637
|
+
await hint.run();
|
|
7638
|
+
hint.settle();
|
|
7639
|
+
} catch (error) {
|
|
7640
|
+
hint.settle(error);
|
|
7641
|
+
}
|
|
7642
|
+
}
|
|
7643
|
+
})().finally(() => {
|
|
7644
|
+
roomHintWorker = void 0;
|
|
7645
|
+
if (roomHints.size) drainRoomHints();
|
|
7646
|
+
});
|
|
7647
|
+
}
|
|
7648
|
+
__name(drainRoomHints, "drainRoomHints");
|
|
7649
|
+
const hintRoom = /* @__PURE__ */ __name((conversationId) => queueRoomHint(`room/${conversationId}`, async () => {
|
|
7650
|
+
await refreshMlsRoomFromHint(conversationId);
|
|
7651
|
+
await sendDeferredOpeners(conversationId);
|
|
7652
|
+
}), "hintRoom");
|
|
7934
7653
|
const queryObserver = createEndpointQueryObserver({ query: /* @__PURE__ */ __name((name, parameters) => endpoint.query(name, parameters), "query"), getPollInterval: /* @__PURE__ */ __name(() => events.isConnected() ? Math.max(options.queryIntervalMs ?? 0, 6e4) : options.queryIntervalMs ?? 3e3, "getPollInterval") });
|
|
7935
7654
|
const invalidateEvent = /* @__PURE__ */ __name((event) => queryObserver.invalidate(event ? (query, parameters) => queryAffectedByEvent(event, query, parameters) : void 0), "invalidateEvent");
|
|
7936
7655
|
const syncConversation = createConversationSynchronizer({ store, query: /* @__PURE__ */ __name((name, parameters) => endpoint.query(name, parameters), "query"), ready: /* @__PURE__ */ __name(() => initialization, "ready"), clock, invalidate: /* @__PURE__ */ __name((conversationId) => invalidateEvent({ kind: "conversation.changed", data: { conversationId } }), "invalidate"), admitRecoveredMessages: options.admitRecoveredMessages, preparationGeneration: /* @__PURE__ */ __name(() => installationGeneration, "preparationGeneration"), prepareProtocol: /* @__PURE__ */ __name((id2) => refreshMlsRoom(id2, true), "prepareProtocol"), syncProtocol: /* @__PURE__ */ __name(async (id2, opts) => {
|
|
@@ -7939,19 +7658,20 @@ function createEndpoint(options) {
|
|
|
7939
7658
|
return mlsDevGroups.syncText(id2, opts);
|
|
7940
7659
|
}, "syncProtocol") });
|
|
7941
7660
|
const events = createEndpointEventHub({ transport, invalidate: invalidateEvent, onDisconnected: /* @__PURE__ */ __name(() => queryObserver.reschedule(), "onDisconnected"), onEvent: /* @__PURE__ */ __name(async (event) => {
|
|
7661
|
+
const hinted = [];
|
|
7942
7662
|
if (mlsDevGroups && ["conversation.changed", "conversation.updated", "conversation.removed"].includes(event.kind)) {
|
|
7943
7663
|
const id2 = event.data.conversationId ?? event.data.id;
|
|
7944
7664
|
if (typeof id2 === "string" && ENDPOINT_ID_PATTERN.test(id2)) {
|
|
7945
7665
|
if (event.kind === "conversation.changed" && event.data.projection === void 0) forgetStubReads(id2);
|
|
7946
7666
|
const unseenRemoval = event.kind === "conversation.removed" && await store.transaction(async (tx) => await tx.get(`conversation/${id2}`) === void 0 && !await isMlsDevRoomProtected(tx, id2));
|
|
7947
|
-
if (!unseenRemoval)
|
|
7948
|
-
await sendDeferredOpeners(id2);
|
|
7667
|
+
if (!unseenRemoval) hinted.push(hintRoom(id2));
|
|
7668
|
+
else await sendDeferredOpeners(id2);
|
|
7949
7669
|
}
|
|
7950
7670
|
}
|
|
7951
7671
|
if (mlsDevGroups && event.kind === "conversations.changed" && Array.isArray(event.data.conversationIds)) {
|
|
7952
7672
|
for (const id2 of event.data.conversationIds) {
|
|
7953
7673
|
if (typeof id2 === "string" && ENDPOINT_ID_PATTERN.test(id2) && await store.transaction((tx) => isMlsDevRoomProtected(tx, id2))) {
|
|
7954
|
-
|
|
7674
|
+
hinted.push(hintRoom(id2));
|
|
7955
7675
|
}
|
|
7956
7676
|
}
|
|
7957
7677
|
}
|
|
@@ -7963,13 +7683,16 @@ function createEndpoint(options) {
|
|
|
7963
7683
|
if (event.kind === "connected") serverRoomMode = void 0;
|
|
7964
7684
|
for (let after; ; ) {
|
|
7965
7685
|
const page = await store.transaction((tx) => tx.scan("mls-dev-group/mode/", { after, limit: 100 }));
|
|
7966
|
-
for (const item of page)
|
|
7686
|
+
for (const item of page) hinted.push(hintRoom(decodeURIComponent(item.key.slice("mls-dev-group/mode/".length))));
|
|
7967
7687
|
if (page.length < 100) break;
|
|
7968
7688
|
after = page[page.length - 1].key;
|
|
7969
7689
|
}
|
|
7970
|
-
|
|
7971
|
-
|
|
7690
|
+
hinted.push(queueRoomHint("after/reconnect", async () => {
|
|
7691
|
+
await sendDeferredOpeners();
|
|
7692
|
+
await discoverInviteeRooms().catch(() => void 0);
|
|
7693
|
+
}, true));
|
|
7972
7694
|
}
|
|
7695
|
+
if (event.id) await Promise.all(hinted);
|
|
7973
7696
|
if ((event.kind === "message.updated" || event.kind === "message.deleted") && typeof event.data.conversationId === "string" && typeof event.data.messageId === "string" && ENDPOINT_ID_PATTERN.test(event.data.conversationId)) {
|
|
7974
7697
|
const room = event.data.conversationId, message = event.data.messageId;
|
|
7975
7698
|
const applied = await store.transaction(async (tx) => {
|
|
@@ -8540,7 +8263,6 @@ function createEndpoint(options) {
|
|
|
8540
8263
|
...endpointIntentConversationId(normalized) ? { conversationId: endpointIntentConversationId(normalized) } : {},
|
|
8541
8264
|
...typeof routedBody.messageId === "string" ? { messageId: routedBody.messageId } : {},
|
|
8542
8265
|
...normalized.action === "session_control" && typeof routedBody.agentId === "string" ? { agentId: routedBody.agentId } : {},
|
|
8543
|
-
...endpointIntentOrdering(normalized) === "artifact" && typeof routedBody.artifactId === "string" ? { artifactId: routedBody.artifactId } : {},
|
|
8544
8266
|
sensitive,
|
|
8545
8267
|
status: "queued",
|
|
8546
8268
|
attempts: 0,
|
|
@@ -8606,7 +8328,7 @@ function createEndpoint(options) {
|
|
|
8606
8328
|
let dispatched = 0;
|
|
8607
8329
|
let hasDeferred = false;
|
|
8608
8330
|
const blockedKeys = /* @__PURE__ */ new Set();
|
|
8609
|
-
for (const ordering of ["independent", "signal", "message", "provider", "
|
|
8331
|
+
for (const ordering of ["independent", "signal", "message", "provider", "conversation"]) {
|
|
8610
8332
|
let after;
|
|
8611
8333
|
do {
|
|
8612
8334
|
const batch = await store.transaction(async (tx) => {
|
|
@@ -8782,9 +8504,9 @@ function createEndpoint(options) {
|
|
|
8782
8504
|
},
|
|
8783
8505
|
refreshQueries: /* @__PURE__ */ __name(() => queryObserver.invalidate(), "refreshQueries"),
|
|
8784
8506
|
observeEvents: events.observe,
|
|
8785
|
-
createMediaPipeline(bytes
|
|
8507
|
+
createMediaPipeline(bytes) {
|
|
8786
8508
|
assertOpen();
|
|
8787
|
-
const pipeline3 = createEndpointMediaPipeline({ endpoint, store, bytes, hash, ids, clock
|
|
8509
|
+
const pipeline3 = createEndpointMediaPipeline({ endpoint, store, bytes, hash, ids, clock });
|
|
8788
8510
|
mediaPipelines2.add(pipeline3);
|
|
8789
8511
|
return pipeline3;
|
|
8790
8512
|
},
|
|
@@ -9088,7 +8810,7 @@ function createEndpoint(options) {
|
|
|
9088
8810
|
listeners.clear();
|
|
9089
8811
|
closing = (async () => {
|
|
9090
8812
|
await Promise.allSettled([handoffs.close(), recovery.close(), syncConversation.close(), events.close(), ...[...consumers].map((consumer) => consumer.close()), ...[...mediaPipelines2].map((pipeline3) => pipeline3.close({ discard: true }))]);
|
|
9091
|
-
await Promise.allSettled([...running.values(), ...reads.values(), ...deviceRuns, initialization]);
|
|
8813
|
+
await Promise.allSettled([...running.values(), ...reads.values(), ...deviceRuns, initialization, roomHintWorker]);
|
|
9092
8814
|
await endpoint.discardPending();
|
|
9093
8815
|
await eraseEndpointPlaintext(store);
|
|
9094
8816
|
await store.close();
|
|
@@ -9111,11 +8833,10 @@ function createEndpoint(options) {
|
|
|
9111
8833
|
sensitiveRequests.clear();
|
|
9112
8834
|
sensitiveFingerprints.clear();
|
|
9113
8835
|
listeners.clear();
|
|
9114
|
-
closing = Promise.allSettled([handoffs.close(), recovery.close(), syncConversation.close(), events.close(), ...[...consumers].map((consumer) => consumer.close()), ...[...mediaPipelines2].map((pipeline3) => pipeline3.close())]).then(() => Promise.allSettled([...running.values(), ...reads.values(), ...deviceRuns, initialization])).then(() => store.close());
|
|
8836
|
+
closing = Promise.allSettled([handoffs.close(), recovery.close(), syncConversation.close(), events.close(), ...[...consumers].map((consumer) => consumer.close()), ...[...mediaPipelines2].map((pipeline3) => pipeline3.close())]).then(() => Promise.allSettled([...running.values(), ...reads.values(), ...deviceRuns, initialization, roomHintWorker])).then(() => store.close());
|
|
9115
8837
|
return closing;
|
|
9116
8838
|
}
|
|
9117
8839
|
};
|
|
9118
|
-
registerArtifactEndpoint(endpoint, { store, closed: /* @__PURE__ */ __name(() => closed, "closed"), assertCurrent: assertCurrentInstallation });
|
|
9119
8840
|
void initialization.then(() => scheduleRetry(0)).catch(() => void 0);
|
|
9120
8841
|
void initialization.then(() => sendDeferredOpeners()).catch(() => void 0);
|
|
9121
8842
|
if (mlsDevGroups) void initialization.then(() => resumeHeldTexts()).catch(() => void 0);
|
|
@@ -9173,7 +8894,7 @@ async function acquireAgentEndpoint(input) {
|
|
|
9173
8894
|
}
|
|
9174
8895
|
const requestedMls = input.options.mlsDev;
|
|
9175
8896
|
const mls = requestedMls ? await (async () => {
|
|
9176
|
-
const crypto2 = await import("./mls-crypto-
|
|
8897
|
+
const crypto2 = await import("./mls-crypto-ZBEC26B5.js");
|
|
9177
8898
|
const configuration = crypto2.parseMlsDevClientConfiguration(requestedMls.configuration);
|
|
9178
8899
|
if (configuration.environmentId !== environmentId || baseUrl !== CANON_RUNTIME_ENDPOINT_DEFAULTS[configuration.environmentId]?.apiBaseUrl || configuration.principalIds && !configuration.principalIds.includes(input.principalId) || !Number.isSafeInteger(input.ownershipVersion) || input.ownershipVersion < 0) throw new Error("MLS_DEV_AGENT_CONFIGURATION_BINDING_MISMATCH");
|
|
9179
8900
|
const custody = requestedMls.custody;
|