@canonmsg/agent-sdk 12.6.1 → 13.0.3
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/README.md +23 -21
- package/dist/chunks/{chunk-S7BV74DN.js → chunk-5WPAB5MB.js} +293 -8
- package/dist/chunks/{chunk-HH7KR22P.js → chunk-DTAWEQCM.js} +2 -2
- package/dist/chunks/{chunk-DAJ7L7TN.js → chunk-XKUG2BQR.js} +378 -663
- package/dist/chunks/{chunk-QK37HAHC.js → chunk-YHDDOADK.js} +1 -1
- package/dist/chunks/{chunk-FVYKLH6I.js → chunk-YJUPKU47.js} +20 -5
- package/dist/chunks/{chunk-5J4YPLNW.js → chunk-ZPBOGOAD.js} +267 -1217
- package/dist/chunks/{mls-crypto-4DZT2UFH.js → mls-crypto-NZVMSUFU.js} +2 -2
- package/dist/cli.js +32 -36
- package/dist/drivers/subprocess.d.ts +4 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +6 -6
- package/dist/internal/backend-contracts/mlsDevGroup.d.ts +17 -0
- package/dist/internal/core/completed-output-journal.d.ts +0 -5
- package/dist/internal/core/index.d.ts +3 -9
- package/dist/internal/core/retry.d.ts +2 -89
- package/dist/internal/core/silent-turn.d.ts +4 -33
- package/dist/internal/endpoint/engine.d.ts +3 -0
- package/dist/internal/endpoint/mls-dev-groups.d.ts +12 -0
- package/dist/internal/endpoint/mls-dev-text.d.ts +29 -0
- package/dist/internal/endpoint/transport.d.ts +1 -1
- package/dist/media.js +4 -4
- package/dist/mls-wasm-host.js +3 -3
- package/dist/runner/mls.d.ts +4 -7
- package/dist/runner/runner.d.ts +9 -12
- package/dist/runner/types.d.ts +31 -0
- package/package.json +1 -1
- package/dist/internal/core/approval-manager.d.ts +0 -43
- package/dist/internal/core/runtime-request-manager.d.ts +0 -283
- package/dist/internal/core/turn-verbosity.d.ts +0 -79
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
createHttpEndpointTransport,
|
|
6
6
|
createNodeEndpointStore,
|
|
7
7
|
validateEndpointContentBoundary
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-YJUPKU47.js";
|
|
9
9
|
import {
|
|
10
10
|
CANON_ENDPOINT_PROTOCOL,
|
|
11
11
|
CANON_VERB_WIRE_SCHEMA_VERSION,
|
|
@@ -42,6 +42,7 @@ import {
|
|
|
42
42
|
isMlsPrincipalAlias,
|
|
43
43
|
logicalMediaBlobId,
|
|
44
44
|
mergeDeliveryObservation,
|
|
45
|
+
mlsAdmissionWait,
|
|
45
46
|
mlsDevProtocolCarriesCards,
|
|
46
47
|
normalizePublicRuntimeDescriptor,
|
|
47
48
|
normalizePublicRuntimeFacts,
|
|
@@ -106,11 +107,11 @@ import {
|
|
|
106
107
|
readMembershipChangeMetadata,
|
|
107
108
|
resolveAllowedUploadMimeType,
|
|
108
109
|
sanitizeDownloadFileName
|
|
109
|
-
} from "./chunk-
|
|
110
|
+
} from "./chunk-5WPAB5MB.js";
|
|
110
111
|
|
|
111
112
|
// src/media.ts
|
|
112
113
|
import { createWriteStream as createWriteStream2 } from "node:fs";
|
|
113
|
-
import { randomUUID as
|
|
114
|
+
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
114
115
|
import { mkdir as mkdir2, open as open2, rename as rename2, stat as stat2, unlink as unlink2 } from "node:fs/promises";
|
|
115
116
|
import { basename, dirname as dirname2, extname, join as join5 } from "node:path";
|
|
116
117
|
import { Readable, Transform as Transform2 } from "node:stream";
|
|
@@ -4904,6 +4905,38 @@ async function isMlsDevOwnAnswerSending(tx, conversationId, agentId, requestId)
|
|
|
4904
4905
|
return !!authored && authored.feedOrdinal === null && (authored.status === "queued" || authored.status === "uncertain");
|
|
4905
4906
|
}
|
|
4906
4907
|
__name(isMlsDevOwnAnswerSending, "isMlsDevOwnAnswerSending");
|
|
4908
|
+
var mlsDevHeldTextPrefix = /* @__PURE__ */ __name((conversationId) => `mls-dev-group/held-text/${conversationId === void 0 ? "" : `${encoded2(conversationId)}/`}`, "mlsDevHeldTextPrefix");
|
|
4909
|
+
var mlsDevHeldTextKey = /* @__PURE__ */ __name((conversationId, messageId) => `${mlsDevHeldTextPrefix(conversationId)}${encoded2(messageId)}`, "mlsDevHeldTextKey");
|
|
4910
|
+
async function readMlsDevHeldTexts(tx, conversationId) {
|
|
4911
|
+
const rows = await tx.scan(mlsDevHeldTextPrefix(conversationId), { limit: MLS_DEV_HELD_TEXT_MAX });
|
|
4912
|
+
return rows.map((row) => row.value).sort((a, b) => a.sequence - b.sequence);
|
|
4913
|
+
}
|
|
4914
|
+
__name(readMlsDevHeldTexts, "readMlsDevHeldTexts");
|
|
4915
|
+
var MLS_DEV_HELD_TEXT_MAX = 100;
|
|
4916
|
+
async function projectMlsDevHeldText(tx, value, account) {
|
|
4917
|
+
const { body } = value;
|
|
4918
|
+
const quote = body.replyTo ? mlsDevReplyQuote(
|
|
4919
|
+
await tx.get(mlsDevTextMessageKey(body.conversationId, body.replyTo)),
|
|
4920
|
+
MLS_DEV_REPLY_QUOTE_MAX_CHARACTERS
|
|
4921
|
+
) : void 0;
|
|
4922
|
+
return {
|
|
4923
|
+
id: body.messageId,
|
|
4924
|
+
conversationId: body.conversationId,
|
|
4925
|
+
senderId: account({ type: value.senderType, id: value.senderId }),
|
|
4926
|
+
senderType: value.senderType,
|
|
4927
|
+
contentType: "text",
|
|
4928
|
+
text: body.text,
|
|
4929
|
+
mentions: body.mentions ?? [],
|
|
4930
|
+
attachments: [],
|
|
4931
|
+
replyTo: body.replyTo ?? null,
|
|
4932
|
+
...quote ? { replyQuote: quote } : {},
|
|
4933
|
+
status: value.failed ? "failed" : "sending",
|
|
4934
|
+
deleted: false,
|
|
4935
|
+
createdAt: new Date(value.createdAtMs).toISOString(),
|
|
4936
|
+
mlsFeedOrdinal: null
|
|
4937
|
+
};
|
|
4938
|
+
}
|
|
4939
|
+
__name(projectMlsDevHeldText, "projectMlsDevHeldText");
|
|
4907
4940
|
var mlsDevTextDeletedKey = /* @__PURE__ */ __name((conversationId, messageId) => `mls-dev-group/message-deleted/${encoded2(conversationId)}/${encoded2(messageId)}`, "mlsDevTextDeletedKey");
|
|
4908
4941
|
var mlsDevTextReactionsKey = /* @__PURE__ */ __name((conversationId, messageId) => `mls-dev-group/message-reactions/${encoded2(conversationId)}/${encoded2(messageId)}`, "mlsDevTextReactionsKey");
|
|
4909
4942
|
var erased = /* @__PURE__ */ __name((value) => {
|
|
@@ -5036,7 +5069,8 @@ async function queryMlsDevTextHistory(tx, conversationId, name, parameters, audi
|
|
|
5036
5069
|
const messages2 = [], missingMessageIds = [];
|
|
5037
5070
|
for (const id2 of parameters.messageIds) {
|
|
5038
5071
|
const value = await tx.get(mlsDevTextMessageKey(conversationId, id2));
|
|
5039
|
-
const
|
|
5072
|
+
const held = value ? void 0 : await tx.get(mlsDevHeldTextKey(conversationId, id2));
|
|
5073
|
+
const projected = value ? await projectLocal(tx, value, audience) : held && await projectMlsDevHeldText(tx, held, audience.account);
|
|
5040
5074
|
if (projected) messages2.push(projected);
|
|
5041
5075
|
else missingMessageIds.push(id2);
|
|
5042
5076
|
}
|
|
@@ -5060,10 +5094,15 @@ async function queryMlsDevTextHistory(tx, conversationId, name, parameters, audi
|
|
|
5060
5094
|
return { ...row.value, ordinal: position };
|
|
5061
5095
|
});
|
|
5062
5096
|
const messages = [];
|
|
5063
|
-
if (parameters.before === void 0)
|
|
5064
|
-
const
|
|
5065
|
-
|
|
5066
|
-
|
|
5097
|
+
if (parameters.before === void 0) {
|
|
5098
|
+
for (const held of (await readMlsDevHeldTexts(tx, conversationId)).reverse()) {
|
|
5099
|
+
if (await tx.get(mlsDevTextMessageKey(conversationId, held.body.messageId)) === void 0) messages.push(await projectMlsDevHeldText(tx, held, audience.account));
|
|
5100
|
+
}
|
|
5101
|
+
for (const row of await tx.scan(pendingPrefix(conversationId), { limit: 100 })) {
|
|
5102
|
+
const value = await tx.get(mlsDevTextMessageKey(conversationId, row.value.messageId));
|
|
5103
|
+
const projected = value && await projectLocal(tx, value, audience);
|
|
5104
|
+
if (projected) messages.push(projected);
|
|
5105
|
+
}
|
|
5067
5106
|
}
|
|
5068
5107
|
for (const item of selected) {
|
|
5069
5108
|
const value = await tx.get(mlsDevTextMessageKey(conversationId, item.messageId));
|
|
@@ -5166,6 +5205,7 @@ var recoveryFailureKey = /* @__PURE__ */ __name((id2) => `mls-dev-group/recovery
|
|
|
5166
5205
|
var authorityKey = /* @__PURE__ */ __name((id2) => `mls-dev-group/authority/${encodeURIComponent(id2)}`, "authorityKey");
|
|
5167
5206
|
var acceptedKey = /* @__PURE__ */ __name((id2, sequence) => `mls-dev-group/accepted/${encodeURIComponent(id2)}/${sequence}`, "acceptedKey");
|
|
5168
5207
|
var feedKey = /* @__PURE__ */ __name((id2) => `mls-dev-group/feed/${encodeURIComponent(id2)}`, "feedKey");
|
|
5208
|
+
var missedEarlierKey = /* @__PURE__ */ __name((id2) => `mls-dev-group/missed-earlier/${encodeURIComponent(id2)}`, "missedEarlierKey");
|
|
5169
5209
|
var feedEntryKey = /* @__PURE__ */ __name((id2, ordinal3) => `mls-dev-group/feed-entry/${encodeURIComponent(id2)}/${ordinal3}`, "feedEntryKey");
|
|
5170
5210
|
var appIntentKey = /* @__PURE__ */ __name((operationId) => `mls-dev-group/application/${encodeURIComponent(operationId)}`, "appIntentKey");
|
|
5171
5211
|
var appOperationKey = /* @__PURE__ */ __name((deviceId, operationId) => `mls-dev-group/application-operation/${encodeURIComponent(deviceId)}/${encodeURIComponent(operationId)}`, "appOperationKey");
|
|
@@ -5433,6 +5473,7 @@ function createMlsDevGroups(options, context, keyPackages, bridge) {
|
|
|
5433
5473
|
return { changed: false, operation: void 0 };
|
|
5434
5474
|
}
|
|
5435
5475
|
if (feed) await checkFeedEntry(tx, current, conversationId, feed);
|
|
5476
|
+
if (!current.envelope?.head && current.envelope?.pending?.control.kind === "create" && current.envelope.pending.operationId !== accepted.operationId) fail6("MLS_DEV_GROUP_PENDING_CONTROL", true);
|
|
5436
5477
|
const rejoining = !!current.envelope && accepted.control.kind === "add" && accepted.control.keyPackageClaim?.recipientDeviceId === current.device.registration.device.deviceId && accepted.head.sequence > (current.envelope.head?.sequence ?? 0);
|
|
5437
5478
|
if (current.envelope?.removed && !rejoining) fail6("MLS_DEV_GROUP_REMOVED");
|
|
5438
5479
|
if (current.envelope?.head && !rejoining && (!same6(accepted.control.expectedHead, current.envelope.head) || accepted.head.sequence !== current.envelope.head.sequence + 1)) fail6("MLS_DEV_GROUP_CONTROL_GAP", true);
|
|
@@ -5840,6 +5881,8 @@ function createMlsDevGroups(options, context, keyPackages, bridge) {
|
|
|
5840
5881
|
observedSequence: current.envelope?.head?.sequence ?? 0
|
|
5841
5882
|
});
|
|
5842
5883
|
await rememberMlsDevRoomMode(tx, cid, response.marker);
|
|
5884
|
+
if (initialWelcome && captured.feedOrdinal === 0 && first.kind === "control" && first.ordinal > first.accepted.head.sequence)
|
|
5885
|
+
await tx.put(missedEarlierKey(cid), true);
|
|
5843
5886
|
});
|
|
5844
5887
|
for (const entry of response.entries) {
|
|
5845
5888
|
if (entry.kind === "control") {
|
|
@@ -5897,17 +5940,35 @@ function createMlsDevGroups(options, context, keyPackages, bridge) {
|
|
|
5897
5940
|
}
|
|
5898
5941
|
}
|
|
5899
5942
|
__name(validItem, "validItem");
|
|
5943
|
+
function validText(text) {
|
|
5944
|
+
try {
|
|
5945
|
+
parseMlsDevTextPayload({
|
|
5946
|
+
version: 1,
|
|
5947
|
+
kind: "text",
|
|
5948
|
+
conversationId: "validation",
|
|
5949
|
+
groupId: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
|
|
5950
|
+
messageId: "validation",
|
|
5951
|
+
operationId: "validation",
|
|
5952
|
+
senderDeviceId: "00000000-0000-4000-8000-000000000000",
|
|
5953
|
+
text
|
|
5954
|
+
});
|
|
5955
|
+
} catch {
|
|
5956
|
+
fail6("MLS_DEV_TEXT_INVALID");
|
|
5957
|
+
}
|
|
5958
|
+
}
|
|
5959
|
+
__name(validText, "validText");
|
|
5900
5960
|
function textInput(value) {
|
|
5901
|
-
const data = record4(value, ["conversationId"], ["text", "messageId", "contentType", "mentions", "attachments", "replyTo", "replyToPosition", "metadata", "forwarded", "contactCardUserId"]);
|
|
5961
|
+
const data = record4(value, ["conversationId"], ["text", "messageId", "contentType", "mentions", "attachments", "replyTo", "replyToPosition", "metadata", "forwarded", "contactCardUserId", "replyAuthority"]);
|
|
5902
5962
|
const attachments = data.attachments ?? [];
|
|
5903
5963
|
if (!Array.isArray(attachments) || attachments.length > 1) fail6(Array.isArray(attachments) ? "MLS_DEV_ONE_ITEM_PER_MESSAGE" : "MLS_DEV_TEXT_ONLY");
|
|
5904
5964
|
const item = attachments.length ? itemInput(attachments[0], data.text) : void 0;
|
|
5905
|
-
if (data.contentType !== void 0 && data.contentType !== (item ? item.type : "text") || !item && typeof data.text !== "string" || item && data.text !== void 0 && data.text !== null && typeof data.text !== "string" || data.mentions !== void 0 && (!Array.isArray(data.mentions) || data.mentions.some((mention) => typeof mention !== "string")) || data.replyTo !== void 0 && data.replyTo !== null && typeof data.replyTo !== "string" || ["replyToPosition", "metadata", "forwarded", "contactCardUserId"].some((key) => data[key] !== void 0 && data[key] !== null)) fail6("MLS_DEV_TEXT_ONLY");
|
|
5965
|
+
if (data.contentType !== void 0 && data.contentType !== (item ? item.type : "text") || !item && typeof data.text !== "string" || item && data.text !== void 0 && data.text !== null && typeof data.text !== "string" || data.mentions !== void 0 && (!Array.isArray(data.mentions) || data.mentions.some((mention) => typeof mention !== "string")) || data.replyTo !== void 0 && data.replyTo !== null && typeof data.replyTo !== "string" || ["replyToPosition", "metadata", "forwarded", "contactCardUserId"].some((key) => data[key] !== void 0 && data[key] !== null) || data.replyAuthority !== void 0 && (!!item || !data.replyAuthority || typeof data.replyAuthority !== "object" || Array.isArray(data.replyAuthority))) fail6("MLS_DEV_TEXT_ONLY");
|
|
5906
5966
|
const mentions = [...new Set(data.mentions ?? [])].map(id);
|
|
5907
5967
|
return {
|
|
5908
5968
|
conversationId: id(data.conversationId),
|
|
5909
5969
|
...item ? { item } : { text: data.text },
|
|
5910
5970
|
...data.messageId === void 0 ? {} : { messageId: id(data.messageId) },
|
|
5971
|
+
...data.replyAuthority === void 0 ? {} : { replyAuthority: data.replyAuthority },
|
|
5911
5972
|
...typeof data.replyTo === "string" ? { replyTo: id(data.replyTo) } : {},
|
|
5912
5973
|
...mentions.length ? { mentions } : {}
|
|
5913
5974
|
};
|
|
@@ -5919,18 +5980,23 @@ function createMlsDevGroups(options, context, keyPackages, bridge) {
|
|
|
5919
5980
|
return store.transaction(async (tx) => {
|
|
5920
5981
|
const room = await tx.get(`conversation/${conversationId}`);
|
|
5921
5982
|
const group = envelope((await readPreparationSnapshot(tx, scope4(conversationId))).protocolState, init.binding, conversationId);
|
|
5983
|
+
const missed = await tx.get(missedEarlierKey(conversationId)) === true ? { missedEarlier: true } : {};
|
|
5922
5984
|
if (room?.mlsAdmissionHold !== true) {
|
|
5923
5985
|
const joining = !!room && !!room.mls && (!group || group.removed);
|
|
5924
|
-
return Object.freeze({ held: joining, waitingPrincipalIds: Object.freeze(joining ? [init.identity.principalId] : []) });
|
|
5986
|
+
return Object.freeze({ held: joining, waitingPrincipalIds: Object.freeze(joining ? [init.identity.principalId] : []), ...missed });
|
|
5925
5987
|
}
|
|
5926
5988
|
const accounts = mlsRoomAccounts(room, init.binding.environmentId);
|
|
5927
5989
|
const admitted = new Set((group && !group.removed ? group.roster : []).map((entry) => mlsAccountOf(accounts, entry.device.principal)));
|
|
5928
|
-
const
|
|
5929
|
-
|
|
5930
|
-
|
|
5931
|
-
|
|
5932
|
-
|
|
5933
|
-
|
|
5990
|
+
const ids = /* @__PURE__ */ __name((value) => Array.isArray(value) ? value.filter((entry) => typeof entry === "string") : [], "ids");
|
|
5991
|
+
const waiting = mlsAdmissionWait({
|
|
5992
|
+
senderId: init.identity.principalId,
|
|
5993
|
+
memberIds: ids(room.memberIds),
|
|
5994
|
+
admitted,
|
|
5995
|
+
unacceptedIds: [...ids([room.mlsInviteeId]), ...ids(room.mlsPendingFounderIds)],
|
|
5996
|
+
joinedAtMs: Number(room.mlsMemberJoinedAtMs),
|
|
5997
|
+
nowMs: context.clock()
|
|
5998
|
+
});
|
|
5999
|
+
return Object.freeze({ held: waiting.length > 0, waitingPrincipalIds: Object.freeze(waiting), ...missed });
|
|
5934
6000
|
});
|
|
5935
6001
|
}
|
|
5936
6002
|
__name(admissionHold, "admissionHold");
|
|
@@ -5965,6 +6031,10 @@ function createMlsDevGroups(options, context, keyPackages, bridge) {
|
|
|
5965
6031
|
const current = await capture(tx, state, init, cid), group = current.envelope;
|
|
5966
6032
|
if (!isMlsDevTextProtocol(current.protocol)) fail6("MLS_DEV_TEXT_PROTOCOL_UNSUPPORTED");
|
|
5967
6033
|
if ((input.replyTo || input.mentions || input.item) && current.protocol !== MLS_DEV_TEXT_PROTOCOL_V3) fail6("MLS_DEV_TEXT_ONLY");
|
|
6034
|
+
if (input.mentions) {
|
|
6035
|
+
const members = (await tx.get(`conversation/${cid}`))?.memberIds;
|
|
6036
|
+
if (!Array.isArray(members) || input.mentions.some((mention) => !members.includes(mention))) fail6("MLS_DEV_MENTION_NOT_MEMBER");
|
|
6037
|
+
}
|
|
5968
6038
|
if (input.item && !canonItemReference(input.item, cid, init.binding.environmentId)) fail6("MLS_DEV_ITEM_INVALID");
|
|
5969
6039
|
if (input.replyTo) {
|
|
5970
6040
|
const quote = mlsDevReplyQuote(await tx.get(mlsDevTextMessageKey(cid, input.replyTo)), MLS_DEV_REPLY_QUOTE_MAX_CHARACTERS);
|
|
@@ -6038,6 +6108,7 @@ function createMlsDevGroups(options, context, keyPackages, bridge) {
|
|
|
6038
6108
|
feedOrdinal: null
|
|
6039
6109
|
});
|
|
6040
6110
|
const media = prepared.text.kind === "item" ? { mediaUploadIds: [prepared.text.item.uploadId] } : {};
|
|
6111
|
+
const reply = input.replyAuthority ? { replyAuthority: input.replyAuthority } : {};
|
|
6041
6112
|
return bridge.queue(tx, {
|
|
6042
6113
|
operationId,
|
|
6043
6114
|
installationId: init.identity.installationId,
|
|
@@ -6058,7 +6129,7 @@ function createMlsDevGroups(options, context, keyPackages, bridge) {
|
|
|
6058
6129
|
operationId,
|
|
6059
6130
|
installationId: init.identity.installationId,
|
|
6060
6131
|
action: "mls_application",
|
|
6061
|
-
body: { encoding: "json", value: { ...prepared.wire, ...media } },
|
|
6132
|
+
body: { encoding: "json", value: { ...prepared.wire, ...media, ...reply } },
|
|
6062
6133
|
...init.identity.ownershipVersion === void 0 ? {} : { ownershipVersion: init.identity.ownershipVersion }
|
|
6063
6134
|
}
|
|
6064
6135
|
});
|
|
@@ -6068,6 +6139,76 @@ function createMlsDevGroups(options, context, keyPackages, bridge) {
|
|
|
6068
6139
|
return operation;
|
|
6069
6140
|
}
|
|
6070
6141
|
__name(sendText, "sendText");
|
|
6142
|
+
async function holdText(input, operationId) {
|
|
6143
|
+
const cid = input.conversationId;
|
|
6144
|
+
if (input.item || input.replyAuthority || typeof input.text !== "string") return sendText(input, operationId);
|
|
6145
|
+
const messageId = input.messageId ?? await bridge.hash(canonicalEndpointJson(["canon.held-text-message.v1", operationId]));
|
|
6146
|
+
const body = {
|
|
6147
|
+
conversationId: cid,
|
|
6148
|
+
messageId,
|
|
6149
|
+
text: input.text,
|
|
6150
|
+
...input.replyTo ? { replyTo: input.replyTo } : {},
|
|
6151
|
+
...input.mentions ? { mentions: input.mentions } : {}
|
|
6152
|
+
};
|
|
6153
|
+
const init = await initialized(), key = mlsDevHeldTextKey(cid, messageId);
|
|
6154
|
+
const kept = await store.transaction(async (tx) => {
|
|
6155
|
+
const existing = await tx.get(key);
|
|
6156
|
+
if (!existing) return await tx.get(`operation/${operationId}`) !== void 0 ? "made" : (await readMlsDevHeldTexts(tx, cid)).some((held) => !held.failed) ? "behind" : "none";
|
|
6157
|
+
if (existing.operationId !== operationId || canonicalEndpointJson(existing.body) !== canonicalEndpointJson(body)) fail6("OPERATION_ID_COLLISION");
|
|
6158
|
+
if (existing.failed) {
|
|
6159
|
+
const { failed: _failed, ...again } = existing;
|
|
6160
|
+
await tx.put(key, again);
|
|
6161
|
+
}
|
|
6162
|
+
return "kept";
|
|
6163
|
+
});
|
|
6164
|
+
if (kept === "kept") return void 0;
|
|
6165
|
+
if (kept !== "behind") {
|
|
6166
|
+
try {
|
|
6167
|
+
return await sendText({ ...input, messageId }, operationId);
|
|
6168
|
+
} catch (error) {
|
|
6169
|
+
if (kept === "made" || !(error instanceof EndpointError) || error.code !== "MLS_DEV_GROUP_ADMISSION_PENDING") throw error;
|
|
6170
|
+
}
|
|
6171
|
+
}
|
|
6172
|
+
validText(body.text);
|
|
6173
|
+
await store.transaction(async (tx) => {
|
|
6174
|
+
const held = await readMlsDevHeldTexts(tx, cid);
|
|
6175
|
+
if (held.length >= MLS_DEV_HELD_TEXT_MAX) fail6("MLS_DEV_HELD_TEXT_LIMIT");
|
|
6176
|
+
await tx.put(key, {
|
|
6177
|
+
version: 1,
|
|
6178
|
+
body,
|
|
6179
|
+
operationId,
|
|
6180
|
+
senderId: init.binding.principal.id,
|
|
6181
|
+
senderType: principal.type,
|
|
6182
|
+
createdAtMs: context.clock(),
|
|
6183
|
+
sequence: (held.at(-1)?.sequence ?? 0) + 1
|
|
6184
|
+
});
|
|
6185
|
+
});
|
|
6186
|
+
bridge.historyChanged?.(cid);
|
|
6187
|
+
return void 0;
|
|
6188
|
+
}
|
|
6189
|
+
__name(holdText, "holdText");
|
|
6190
|
+
async function sendHeldTexts(conversationId) {
|
|
6191
|
+
const sent = [], failed = [];
|
|
6192
|
+
const kept = (await store.transaction((tx) => readMlsDevHeldTexts(tx, conversationId))).filter((held) => !held.failed);
|
|
6193
|
+
for (const held of kept) {
|
|
6194
|
+
const key = mlsDevHeldTextKey(conversationId, held.body.messageId);
|
|
6195
|
+
try {
|
|
6196
|
+
sent.push(await sendText(textInput(held.body), held.operationId));
|
|
6197
|
+
} catch (error) {
|
|
6198
|
+
if (error instanceof EndpointError && ["ENDPOINT_CLOSED", "PREPARATION_INSTALLATION_FENCED"].includes(error.code)) throw error;
|
|
6199
|
+
if (!(error instanceof EndpointError) || error.retryable) return { sent, failed, waiting: true };
|
|
6200
|
+
await store.transaction(async (tx) => {
|
|
6201
|
+
if (await tx.get(key) !== void 0) await tx.put(key, { ...held, failed: error.code });
|
|
6202
|
+
});
|
|
6203
|
+
failed.push({ operationId: held.operationId, error });
|
|
6204
|
+
bridge.historyChanged?.(conversationId);
|
|
6205
|
+
continue;
|
|
6206
|
+
}
|
|
6207
|
+
await store.transaction((tx) => tx.delete(key));
|
|
6208
|
+
}
|
|
6209
|
+
return { sent, failed, waiting: false };
|
|
6210
|
+
}
|
|
6211
|
+
__name(sendHeldTexts, "sendHeldTexts");
|
|
6071
6212
|
async function roomAccounts(tx, conversationId, init) {
|
|
6072
6213
|
return mlsRoomAccounts(await tx.get(`conversation/${conversationId}`), init.binding.environmentId);
|
|
6073
6214
|
}
|
|
@@ -6844,6 +6985,15 @@ function createMlsDevGroups(options, context, keyPackages, bridge) {
|
|
|
6844
6985
|
const input = textInput(value), selectedId = id(operationId), selectedGuard = guardId === void 0 ? void 0 : id(guardId);
|
|
6845
6986
|
return run(() => serializeInboundPreparation(store, input.conversationId, () => sendText(input, selectedId, selectedGuard)));
|
|
6846
6987
|
},
|
|
6988
|
+
/** `sendText` for a person's composer: in a held room the text is kept, not refused (undefined), until `sendHeldTexts`. */
|
|
6989
|
+
holdText(value, operationId) {
|
|
6990
|
+
const input = textInput(value), selectedId = id(operationId);
|
|
6991
|
+
return run(() => serializeInboundPreparation(store, input.conversationId, () => holdText(input, selectedId)));
|
|
6992
|
+
},
|
|
6993
|
+
sendHeldTexts(conversationId) {
|
|
6994
|
+
const cid = id(conversationId);
|
|
6995
|
+
return run(() => serializeInboundPreparation(store, cid, () => sendHeldTexts(cid)));
|
|
6996
|
+
},
|
|
6847
6997
|
/** A room this device holds caught up is read as it holds it: what fetches the room's new entries says so
|
|
6848
6998
|
* (bridge.historyChanged). Otherwise a read fetches the feed first, which the polling fallback and the connected
|
|
6849
6999
|
* stream's minute-long safety poll rely on. */
|
|
@@ -7127,6 +7277,7 @@ function createEndpoint(options) {
|
|
|
7127
7277
|
clearTimeout(admissionTimers.get(conversationId));
|
|
7128
7278
|
admissionTimers.delete(conversationId);
|
|
7129
7279
|
scheduleAdmission(conversationId, 0);
|
|
7280
|
+
void releaseHeldTexts(conversationId);
|
|
7130
7281
|
}, "controlSettled"),
|
|
7131
7282
|
// Whatever fetched them (a hint, the reconnect sweep, a send, recovery), the room's local reads show them now.
|
|
7132
7283
|
historyChanged: /* @__PURE__ */ __name((conversationId) => queryObserver.invalidate((query, parameters) => options.localInboxPreviews && query === "list_conversations" || parameters.conversationId === conversationId && ["list_messages", "get_messages", "get_runtime_card_state"].includes(query)), "historyChanged"),
|
|
@@ -7497,6 +7648,86 @@ function createEndpoint(options) {
|
|
|
7497
7648
|
}
|
|
7498
7649
|
}
|
|
7499
7650
|
__name(sendDeferredOpeners, "sendDeferredOpeners");
|
|
7651
|
+
const heldWaiters = /* @__PURE__ */ new Map();
|
|
7652
|
+
const heldRooms = /* @__PURE__ */ new Set(), heldTimers = /* @__PURE__ */ new Map(), heldDelays = /* @__PURE__ */ new Map();
|
|
7653
|
+
const releasingHeld = /* @__PURE__ */ new Set(), releaseAgain = /* @__PURE__ */ new Set();
|
|
7654
|
+
function settleHeldWaiters(operationId, settle) {
|
|
7655
|
+
const waiters = heldWaiters.get(operationId) ?? [];
|
|
7656
|
+
heldWaiters.delete(operationId);
|
|
7657
|
+
for (const waiter of waiters) settle(waiter);
|
|
7658
|
+
}
|
|
7659
|
+
__name(settleHeldWaiters, "settleHeldWaiters");
|
|
7660
|
+
function scheduleHeldTexts(conversationId) {
|
|
7661
|
+
if (closed || heldTimers.has(conversationId)) return;
|
|
7662
|
+
const delay = heldDelays.get(conversationId) ?? 3e3;
|
|
7663
|
+
heldDelays.set(conversationId, Math.min(delay * 2, 3e4));
|
|
7664
|
+
const timer = setTimeout(() => {
|
|
7665
|
+
heldTimers.delete(conversationId);
|
|
7666
|
+
void releaseHeldTexts(conversationId);
|
|
7667
|
+
}, delay);
|
|
7668
|
+
timer.unref?.();
|
|
7669
|
+
heldTimers.set(conversationId, timer);
|
|
7670
|
+
}
|
|
7671
|
+
__name(scheduleHeldTexts, "scheduleHeldTexts");
|
|
7672
|
+
async function releaseHeldTexts(conversationId) {
|
|
7673
|
+
if (!mlsDevGroups || closed || !heldRooms.has(conversationId)) return;
|
|
7674
|
+
if (releasingHeld.has(conversationId)) {
|
|
7675
|
+
releaseAgain.add(conversationId);
|
|
7676
|
+
return;
|
|
7677
|
+
}
|
|
7678
|
+
releasingHeld.add(conversationId);
|
|
7679
|
+
try {
|
|
7680
|
+
let waiting;
|
|
7681
|
+
do {
|
|
7682
|
+
releaseAgain.delete(conversationId);
|
|
7683
|
+
const result = await mlsDevGroups.sendHeldTexts(conversationId);
|
|
7684
|
+
for (const operation of result.sent) settleHeldWaiters(operation.operationId, (waiter) => waiter.resolve(operation));
|
|
7685
|
+
for (const { operationId, error } of result.failed) settleHeldWaiters(operationId, (waiter) => waiter.reject(error));
|
|
7686
|
+
waiting = result.waiting;
|
|
7687
|
+
} while (releaseAgain.has(conversationId));
|
|
7688
|
+
if (waiting) scheduleHeldTexts(conversationId);
|
|
7689
|
+
else {
|
|
7690
|
+
heldRooms.delete(conversationId);
|
|
7691
|
+
heldDelays.delete(conversationId);
|
|
7692
|
+
clearTimeout(heldTimers.get(conversationId));
|
|
7693
|
+
heldTimers.delete(conversationId);
|
|
7694
|
+
}
|
|
7695
|
+
} catch (error) {
|
|
7696
|
+
if (!(error instanceof EndpointError) || !["ENDPOINT_CLOSED", "PREPARATION_INSTALLATION_FENCED"].includes(error.code)) scheduleHeldTexts(conversationId);
|
|
7697
|
+
} finally {
|
|
7698
|
+
releasingHeld.delete(conversationId);
|
|
7699
|
+
}
|
|
7700
|
+
}
|
|
7701
|
+
__name(releaseHeldTexts, "releaseHeldTexts");
|
|
7702
|
+
function closeHeldTexts() {
|
|
7703
|
+
for (const timer of heldTimers.values()) clearTimeout(timer);
|
|
7704
|
+
heldTimers.clear();
|
|
7705
|
+
const closedError = new EndpointError("Endpoint is closed", { code: "ENDPOINT_CLOSED", retryable: false });
|
|
7706
|
+
for (const operationId of [...heldWaiters.keys()]) settleHeldWaiters(operationId, (waiter) => waiter.reject(closedError));
|
|
7707
|
+
}
|
|
7708
|
+
__name(closeHeldTexts, "closeHeldTexts");
|
|
7709
|
+
async function sendTextWhenReady(body, operationId) {
|
|
7710
|
+
const queued = await mlsDevGroups.holdText(body, operationId);
|
|
7711
|
+
if (queued) return queued;
|
|
7712
|
+
const conversationId = body.conversationId;
|
|
7713
|
+
const sent = new Promise((resolve3, reject) => {
|
|
7714
|
+
heldWaiters.set(operationId, [...heldWaiters.get(operationId) ?? [], { resolve: resolve3, reject }]);
|
|
7715
|
+
});
|
|
7716
|
+
heldRooms.add(conversationId);
|
|
7717
|
+
void releaseHeldTexts(conversationId);
|
|
7718
|
+
return sent;
|
|
7719
|
+
}
|
|
7720
|
+
__name(sendTextWhenReady, "sendTextWhenReady");
|
|
7721
|
+
async function resumeHeldTexts() {
|
|
7722
|
+
for (let after; ; ) {
|
|
7723
|
+
const page = await store.transaction((tx) => tx.scan(mlsDevHeldTextPrefix(), { limit: 100, ...after ? { after } : {} }));
|
|
7724
|
+
for (const row of page) if (!row.value.failed) heldRooms.add(row.value.body.conversationId);
|
|
7725
|
+
if (page.length < 100) break;
|
|
7726
|
+
after = page[page.length - 1].key;
|
|
7727
|
+
}
|
|
7728
|
+
for (const conversationId of heldRooms) void releaseHeldTexts(conversationId);
|
|
7729
|
+
}
|
|
7730
|
+
__name(resumeHeldTexts, "resumeHeldTexts");
|
|
7500
7731
|
const stubReads = /* @__PURE__ */ new Map();
|
|
7501
7732
|
const stubNames = /* @__PURE__ */ new Map();
|
|
7502
7733
|
let liveActionCounter = 0;
|
|
@@ -7601,6 +7832,7 @@ function createEndpoint(options) {
|
|
|
7601
7832
|
await mlsDevGroups.commitHeldRemoval(conversationId).catch((error) => {
|
|
7602
7833
|
if (!(error instanceof EndpointError) || ["ENDPOINT_CLOSED", "PREPARATION_INSTALLATION_FENCED"].includes(error.code)) throw error;
|
|
7603
7834
|
});
|
|
7835
|
+
void releaseHeldTexts(conversationId);
|
|
7604
7836
|
}
|
|
7605
7837
|
return true;
|
|
7606
7838
|
}
|
|
@@ -8117,6 +8349,7 @@ function createEndpoint(options) {
|
|
|
8117
8349
|
if (mode.required) {
|
|
8118
8350
|
if (!isMlsDevTextProtocol(mode.protocol) || !mlsDevGroups) throw new EndpointError("Encrypted text is unavailable for this room", { code: "MLS_DEV_ENCRYPTED_CONTENT_REQUIRED", retryable: false });
|
|
8119
8351
|
if (executeOptions.sensitive || authored.envelope || authored.preconditions) throw new EndpointError("Unsupported encrypted text fields", { code: "INVALID_MLS_DEV_TEXT_INPUT", retryable: false });
|
|
8352
|
+
if (executeOptions.waitWhileHeld && !executeOptions.guardId) return sendTextWhenReady(authored.body, operationId);
|
|
8120
8353
|
return mlsDevGroups.sendText(authored.body, operationId, executeOptions.guardId);
|
|
8121
8354
|
}
|
|
8122
8355
|
}
|
|
@@ -8741,6 +8974,7 @@ function createEndpoint(options) {
|
|
|
8741
8974
|
admissionTimers.clear();
|
|
8742
8975
|
for (const timer of openerTimers.values()) clearTimeout(timer);
|
|
8743
8976
|
openerTimers.clear();
|
|
8977
|
+
closeHeldTexts();
|
|
8744
8978
|
queryObserver.close();
|
|
8745
8979
|
listeners.clear();
|
|
8746
8980
|
closing = (async () => {
|
|
@@ -8763,6 +8997,7 @@ function createEndpoint(options) {
|
|
|
8763
8997
|
admissionTimers.clear();
|
|
8764
8998
|
for (const timer of openerTimers.values()) clearTimeout(timer);
|
|
8765
8999
|
openerTimers.clear();
|
|
9000
|
+
closeHeldTexts();
|
|
8766
9001
|
queryObserver.close();
|
|
8767
9002
|
sensitiveRequests.clear();
|
|
8768
9003
|
sensitiveFingerprints.clear();
|
|
@@ -8774,6 +9009,7 @@ function createEndpoint(options) {
|
|
|
8774
9009
|
registerArtifactEndpoint(endpoint, { store, closed: /* @__PURE__ */ __name(() => closed, "closed"), assertCurrent: assertCurrentInstallation });
|
|
8775
9010
|
void initialization.then(() => scheduleRetry(0)).catch(() => void 0);
|
|
8776
9011
|
void initialization.then(() => sendDeferredOpeners()).catch(() => void 0);
|
|
9012
|
+
if (mlsDevGroups) void initialization.then(() => resumeHeldTexts()).catch(() => void 0);
|
|
8777
9013
|
return endpoint;
|
|
8778
9014
|
}
|
|
8779
9015
|
__name(createEndpoint, "createEndpoint");
|
|
@@ -8828,7 +9064,7 @@ async function acquireAgentEndpoint(input) {
|
|
|
8828
9064
|
}
|
|
8829
9065
|
const requestedMls = input.options.mlsDev;
|
|
8830
9066
|
const mls = requestedMls ? await (async () => {
|
|
8831
|
-
const crypto2 = await import("./mls-crypto-
|
|
9067
|
+
const crypto2 = await import("./mls-crypto-NZVMSUFU.js");
|
|
8832
9068
|
const configuration = crypto2.parseMlsDevClientConfiguration(requestedMls.configuration);
|
|
8833
9069
|
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");
|
|
8834
9070
|
const custody = requestedMls.custody;
|
|
@@ -9433,7 +9669,7 @@ var CanonClient = class {
|
|
|
9433
9669
|
return result.status === "unavailable" && result.reason === "opening-text-required" ? void 0 : result;
|
|
9434
9670
|
}
|
|
9435
9671
|
async blockUser(userId) {
|
|
9436
|
-
await this.endpointAction("set_block", { userId, blocked: true });
|
|
9672
|
+
await this.endpointAction("set_block", { targetUserId: userId, blocked: true });
|
|
9437
9673
|
}
|
|
9438
9674
|
async deleteMessage(conversationId, messageId) {
|
|
9439
9675
|
await this.endpointAction("delete_message", { conversationId, messageId });
|
|
@@ -10330,1028 +10566,14 @@ async function ensureAgentProfile(options) {
|
|
|
10330
10566
|
}
|
|
10331
10567
|
__name(ensureAgentProfile, "ensureAgentProfile");
|
|
10332
10568
|
|
|
10333
|
-
// ../core/src/runtime-cards.ts
|
|
10334
|
-
var FIELD_TYPE_SET = new Set(RUNTIME_CARD_FIELD_TYPES);
|
|
10335
|
-
var LINE_ITEM_COLUMN_TYPE_SET = new Set(RUNTIME_CARD_LINE_ITEM_COLUMN_TYPES);
|
|
10336
|
-
function buildRuntimeInputOutcome(inputId, status, details) {
|
|
10337
|
-
return {
|
|
10338
|
-
text: status === "timeout" ? "Input request expired" : status === "cancelled" ? "Input request cancelled" : "Input request resolved",
|
|
10339
|
-
metadata: {
|
|
10340
|
-
type: "runtime_input_outcome",
|
|
10341
|
-
inputId,
|
|
10342
|
-
...details?.kind ? { kind: details.kind } : {},
|
|
10343
|
-
status,
|
|
10344
|
-
...details?.reason ? { reason: details.reason } : {}
|
|
10345
|
-
}
|
|
10346
|
-
};
|
|
10347
|
-
}
|
|
10348
|
-
__name(buildRuntimeInputOutcome, "buildRuntimeInputOutcome");
|
|
10349
|
-
function buildRuntimeCardOutcome(cardId, status, details) {
|
|
10350
|
-
return {
|
|
10351
|
-
text: status === "timeout" ? "Card request expired" : status === "cancelled" ? "Card request cancelled" : "Card request resolved",
|
|
10352
|
-
metadata: {
|
|
10353
|
-
type: "runtime_card_outcome",
|
|
10354
|
-
cardId,
|
|
10355
|
-
status,
|
|
10356
|
-
...details?.reason ? { reason: details.reason } : {},
|
|
10357
|
-
turnSemantics: "control",
|
|
10358
|
-
replyBehavior: "suppress_auto_reply"
|
|
10359
|
-
}
|
|
10360
|
-
};
|
|
10361
|
-
}
|
|
10362
|
-
__name(buildRuntimeCardOutcome, "buildRuntimeCardOutcome");
|
|
10363
|
-
|
|
10364
|
-
// ../core/src/runtime-request-manager.ts
|
|
10365
|
-
var RuntimeRequestCancelledError = class extends Error {
|
|
10366
|
-
static {
|
|
10367
|
-
__name(this, "RuntimeRequestCancelledError");
|
|
10368
|
-
}
|
|
10369
|
-
constructor(message = "Runtime request cancelled") {
|
|
10370
|
-
super(message);
|
|
10371
|
-
this.name = "RuntimeRequestCancelledError";
|
|
10372
|
-
}
|
|
10373
|
-
};
|
|
10374
|
-
var DEFAULT_TIMEOUT_MS = 3e5;
|
|
10375
|
-
var DEFAULT_POLL_MS = 1e3;
|
|
10376
|
-
function pendingKey(kind, conversationId, requestId) {
|
|
10377
|
-
return `${kind}::${conversationId}::${requestId}`;
|
|
10378
|
-
}
|
|
10379
|
-
__name(pendingKey, "pendingKey");
|
|
10380
|
-
var RuntimeRequestManager = class {
|
|
10381
|
-
static {
|
|
10382
|
-
__name(this, "RuntimeRequestManager");
|
|
10383
|
-
}
|
|
10384
|
-
client;
|
|
10385
|
-
ctx;
|
|
10386
|
-
descriptors = /* @__PURE__ */ new Map();
|
|
10387
|
-
pending = /* @__PURE__ */ new Map();
|
|
10388
|
-
rules = [];
|
|
10389
|
-
constructor(client, ctx) {
|
|
10390
|
-
this.client = client;
|
|
10391
|
-
this.ctx = ctx;
|
|
10392
|
-
this.registerBuiltins();
|
|
10393
|
-
}
|
|
10394
|
-
/** Register (or override) the descriptor for a kind. */
|
|
10395
|
-
register(kind, descriptor) {
|
|
10396
|
-
this.descriptors.set(kind, descriptor);
|
|
10397
|
-
}
|
|
10398
|
-
/** Built-in input, card, and plan descriptors. Subclasses add approval policy. */
|
|
10399
|
-
registerBuiltins() {
|
|
10400
|
-
this.register("input", runtimeInputDescriptor);
|
|
10401
|
-
this.register("card", runtimeCardDescriptor);
|
|
10402
|
-
this.register("plan", runtimePlanDescriptor);
|
|
10403
|
-
}
|
|
10404
|
-
get pendingCount() {
|
|
10405
|
-
return this.pending.size;
|
|
10406
|
-
}
|
|
10407
|
-
/**
|
|
10408
|
-
* Run one interactive runtime request end to end:
|
|
10409
|
-
* preflight → create → onCreated → register pending → poll (racing push wakeup
|
|
10410
|
-
* and abort) → post-deadline consume → finalize → onOutcome → resolve.
|
|
10411
|
-
*/
|
|
10412
|
-
async request(kind, conversationId, payload, options = {}) {
|
|
10413
|
-
const descriptor = this.descriptors.get(kind);
|
|
10414
|
-
if (!descriptor) {
|
|
10415
|
-
throw new Error(`No runtime-request descriptor registered for kind '${kind}'`);
|
|
10416
|
-
}
|
|
10417
|
-
if (options.signal?.aborted) {
|
|
10418
|
-
throw new RuntimeRequestCancelledError();
|
|
10419
|
-
}
|
|
10420
|
-
const pre = descriptor.preflight?.({
|
|
10421
|
-
client: this.client,
|
|
10422
|
-
ctx: this.ctx,
|
|
10423
|
-
conversationId,
|
|
10424
|
-
payload,
|
|
10425
|
-
options
|
|
10426
|
-
});
|
|
10427
|
-
if (pre != null) return pre;
|
|
10428
|
-
const requestId = options.requestId ?? descriptor.generateId(payload);
|
|
10429
|
-
const expiresAt = descriptor.resolveExpiry?.({ payload, options }) ?? options.expiresAt ?? Date.now() + (options.timeoutMs ?? DEFAULT_TIMEOUT_MS);
|
|
10430
|
-
const pollMs = descriptor.pollMs?.(payload) ?? options.pollMs ?? DEFAULT_POLL_MS;
|
|
10431
|
-
const created = await descriptor.create({
|
|
10432
|
-
client: this.client,
|
|
10433
|
-
ctx: this.ctx,
|
|
10434
|
-
conversationId,
|
|
10435
|
-
requestId,
|
|
10436
|
-
payload,
|
|
10437
|
-
expiresAt,
|
|
10438
|
-
state: void 0,
|
|
10439
|
-
options
|
|
10440
|
-
});
|
|
10441
|
-
const effectiveId = created.requestId || requestId;
|
|
10442
|
-
const effectiveExpiry = created.expiresAt ?? expiresAt;
|
|
10443
|
-
const state = created.state;
|
|
10444
|
-
const base = {
|
|
10445
|
-
client: this.client,
|
|
10446
|
-
ctx: this.ctx,
|
|
10447
|
-
conversationId,
|
|
10448
|
-
requestId: effectiveId,
|
|
10449
|
-
payload,
|
|
10450
|
-
expiresAt: effectiveExpiry,
|
|
10451
|
-
state
|
|
10452
|
-
};
|
|
10453
|
-
if (options.signal?.aborted) {
|
|
10454
|
-
await descriptor.cancel?.(base).catch(() => {
|
|
10455
|
-
});
|
|
10456
|
-
throw signalReason(options.signal) ?? new RuntimeRequestCancelledError();
|
|
10457
|
-
}
|
|
10458
|
-
if (options.onCreated) {
|
|
10459
|
-
await options.onCreated({
|
|
10460
|
-
requestId: effectiveId,
|
|
10461
|
-
expiresAt: effectiveExpiry,
|
|
10462
|
-
...created.messageId !== void 0 ? { messageId: created.messageId } : {},
|
|
10463
|
-
...created.interactive !== void 0 ? { interactive: created.interactive } : {}
|
|
10464
|
-
});
|
|
10465
|
-
}
|
|
10466
|
-
if (options.signal?.aborted) {
|
|
10467
|
-
await descriptor.cancel?.(base).catch(() => {
|
|
10468
|
-
});
|
|
10469
|
-
throw signalReason(options.signal) ?? new RuntimeRequestCancelledError();
|
|
10470
|
-
}
|
|
10471
|
-
const key = pendingKey(kind, conversationId, effectiveId);
|
|
10472
|
-
const signal = options.signal;
|
|
10473
|
-
return await new Promise((resolve3, reject) => {
|
|
10474
|
-
let settled = false;
|
|
10475
|
-
const finishCommon = /* @__PURE__ */ __name(() => {
|
|
10476
|
-
settled = true;
|
|
10477
|
-
entry.wake();
|
|
10478
|
-
clearTimeout(entry.timer);
|
|
10479
|
-
this.pending.delete(key);
|
|
10480
|
-
if (signal) signal.removeEventListener("abort", onAbort);
|
|
10481
|
-
}, "finishCommon");
|
|
10482
|
-
const settle = /* @__PURE__ */ __name((result, reason) => {
|
|
10483
|
-
if (settled) return;
|
|
10484
|
-
finishCommon();
|
|
10485
|
-
void (async () => {
|
|
10486
|
-
let finalResult = result;
|
|
10487
|
-
try {
|
|
10488
|
-
const override = descriptor.finalize?.({ ...base, result, reason });
|
|
10489
|
-
if (override !== void 0) finalResult = override;
|
|
10490
|
-
} catch {
|
|
10491
|
-
}
|
|
10492
|
-
if (options.onOutcome && descriptor.buildOutcome) {
|
|
10493
|
-
try {
|
|
10494
|
-
const env = descriptor.buildOutcome({ ...base, result: finalResult, reason });
|
|
10495
|
-
if (env) await options.onOutcome(env);
|
|
10496
|
-
} catch {
|
|
10497
|
-
}
|
|
10498
|
-
}
|
|
10499
|
-
resolve3(finalResult);
|
|
10500
|
-
})();
|
|
10501
|
-
}, "settle");
|
|
10502
|
-
const abort = /* @__PURE__ */ __name((error) => {
|
|
10503
|
-
if (settled) return;
|
|
10504
|
-
finishCommon();
|
|
10505
|
-
void descriptor.cancel?.(base).catch(() => {
|
|
10506
|
-
});
|
|
10507
|
-
reject(error);
|
|
10508
|
-
}, "abort");
|
|
10509
|
-
const onAbort = /* @__PURE__ */ __name(() => abort(signalReason(signal) ?? new RuntimeRequestCancelledError()), "onAbort");
|
|
10510
|
-
const entry = {
|
|
10511
|
-
kind,
|
|
10512
|
-
conversationId,
|
|
10513
|
-
requestId: effectiveId,
|
|
10514
|
-
timer: setTimeout(
|
|
10515
|
-
() => settle(descriptor.timeoutResult(base), "timeout"),
|
|
10516
|
-
Math.max(0, effectiveExpiry - Date.now())
|
|
10517
|
-
),
|
|
10518
|
-
wake: /* @__PURE__ */ __name(() => {
|
|
10519
|
-
}, "wake"),
|
|
10520
|
-
wakeRequested: false,
|
|
10521
|
-
settle: /* @__PURE__ */ __name((result, reason) => settle(result, reason), "settle"),
|
|
10522
|
-
abort
|
|
10523
|
-
};
|
|
10524
|
-
this.pending.set(key, entry);
|
|
10525
|
-
if (signal) signal.addEventListener("abort", onAbort, { once: true });
|
|
10526
|
-
const pollOnce = /* @__PURE__ */ __name(async () => {
|
|
10527
|
-
try {
|
|
10528
|
-
const outcome = await descriptor.consume(base);
|
|
10529
|
-
if (settled) return true;
|
|
10530
|
-
if (outcome.state === "resolved") {
|
|
10531
|
-
settle(outcome.result, "replied");
|
|
10532
|
-
return true;
|
|
10533
|
-
}
|
|
10534
|
-
if (outcome.state === "timeout") {
|
|
10535
|
-
settle(descriptor.timeoutResult(base), "timeout");
|
|
10536
|
-
return true;
|
|
10537
|
-
}
|
|
10538
|
-
} catch {
|
|
10539
|
-
}
|
|
10540
|
-
return false;
|
|
10541
|
-
}, "pollOnce");
|
|
10542
|
-
const poll = /* @__PURE__ */ __name(async () => {
|
|
10543
|
-
while (!settled && Date.now() < effectiveExpiry) {
|
|
10544
|
-
if (await pollOnce()) return;
|
|
10545
|
-
if (settled) return;
|
|
10546
|
-
await this.sleep(key, Math.min(pollMs, Math.max(1, effectiveExpiry - Date.now())));
|
|
10547
|
-
}
|
|
10548
|
-
if (settled) return;
|
|
10549
|
-
if (await pollOnce()) return;
|
|
10550
|
-
if (!settled) settle(descriptor.timeoutResult(base), "timeout");
|
|
10551
|
-
}, "poll");
|
|
10552
|
-
void poll();
|
|
10553
|
-
});
|
|
10554
|
-
}
|
|
10555
|
-
/** Push short-circuit: wake the pending request's poll to consume immediately. */
|
|
10556
|
-
notify(kind, conversationId, requestId) {
|
|
10557
|
-
const entry = this.pending.get(pendingKey(kind, conversationId, requestId));
|
|
10558
|
-
if (!entry) return;
|
|
10559
|
-
entry.wakeRequested = true;
|
|
10560
|
-
entry.wake();
|
|
10561
|
-
}
|
|
10562
|
-
/**
|
|
10563
|
-
* Feed an inbound message to the manager. Returns true when a matching pending
|
|
10564
|
-
* request was woken to consume canonical state. Receipt metadata never settles
|
|
10565
|
-
* the request directly. Fails closed on unknown / mismatched ids.
|
|
10566
|
-
*/
|
|
10567
|
-
handleMessage(conversationId, message) {
|
|
10568
|
-
if (this.pending.size === 0) return false;
|
|
10569
|
-
for (const descriptor of this.descriptors.values()) {
|
|
10570
|
-
const match = descriptor.matchPush?.({ conversationId, message, ctx: this.ctx });
|
|
10571
|
-
if (!match) continue;
|
|
10572
|
-
const entry = this.pending.get(pendingKey(descriptor.kind, conversationId, match.requestId));
|
|
10573
|
-
if (!entry) return false;
|
|
10574
|
-
entry.wakeRequested = true;
|
|
10575
|
-
entry.wake();
|
|
10576
|
-
return true;
|
|
10577
|
-
}
|
|
10578
|
-
return false;
|
|
10579
|
-
}
|
|
10580
|
-
/** Cancel a specific pending request (rejects its promise, best-effort server cancel). */
|
|
10581
|
-
async cancel(kind, conversationId, requestId) {
|
|
10582
|
-
this.pending.get(pendingKey(kind, conversationId, requestId))?.abort(new RuntimeRequestCancelledError());
|
|
10583
|
-
}
|
|
10584
|
-
// ── Session rules (approval descriptor uses these) ─────────────────
|
|
10585
|
-
checkSessionRules(toolName, conversationId) {
|
|
10586
|
-
this.pruneExpiredRules();
|
|
10587
|
-
for (const stored of this.rules) {
|
|
10588
|
-
if (conversationId && stored.conversationId !== conversationId) continue;
|
|
10589
|
-
const { rule } = stored;
|
|
10590
|
-
if (rule.type === "approve-all") return rule;
|
|
10591
|
-
if ((rule.type === "approve-tool" || rule.type === "deny-tool") && rule.toolPattern) {
|
|
10592
|
-
try {
|
|
10593
|
-
const re = new RegExp(`^${rule.toolPattern}$`, "i");
|
|
10594
|
-
if (re.test(toolName)) return rule;
|
|
10595
|
-
} catch {
|
|
10596
|
-
continue;
|
|
10597
|
-
}
|
|
10598
|
-
}
|
|
10599
|
-
}
|
|
10600
|
-
return null;
|
|
10601
|
-
}
|
|
10602
|
-
addSessionRule(conversationId, rule) {
|
|
10603
|
-
this.rules.push({ conversationId, rule });
|
|
10604
|
-
}
|
|
10605
|
-
getSessionRules() {
|
|
10606
|
-
this.pruneExpiredRules();
|
|
10607
|
-
return this.rules.map((stored) => stored.rule);
|
|
10608
|
-
}
|
|
10609
|
-
clearSessionRules() {
|
|
10610
|
-
this.rules = [];
|
|
10611
|
-
}
|
|
10612
|
-
dispose() {
|
|
10613
|
-
for (const entry of this.pending.values()) {
|
|
10614
|
-
clearTimeout(entry.timer);
|
|
10615
|
-
}
|
|
10616
|
-
this.pending.clear();
|
|
10617
|
-
this.rules = [];
|
|
10618
|
-
}
|
|
10619
|
-
pruneExpiredRules() {
|
|
10620
|
-
const now = Date.now();
|
|
10621
|
-
this.rules = this.rules.filter(({ rule }) => {
|
|
10622
|
-
if (!rule.expiresAt) return true;
|
|
10623
|
-
return new Date(rule.expiresAt).getTime() > now;
|
|
10624
|
-
});
|
|
10625
|
-
}
|
|
10626
|
-
/** Sleep that resolves on timeout, on `notify()` wakeup, or when the request settles. */
|
|
10627
|
-
sleep(key, ms) {
|
|
10628
|
-
const pending = this.pending.get(key);
|
|
10629
|
-
if (pending?.wakeRequested) {
|
|
10630
|
-
pending.wakeRequested = false;
|
|
10631
|
-
return Promise.resolve();
|
|
10632
|
-
}
|
|
10633
|
-
return new Promise((resolve3) => {
|
|
10634
|
-
let done = false;
|
|
10635
|
-
const finish = /* @__PURE__ */ __name(() => {
|
|
10636
|
-
if (done) return;
|
|
10637
|
-
done = true;
|
|
10638
|
-
clearTimeout(timer);
|
|
10639
|
-
const current = this.pending.get(key);
|
|
10640
|
-
if (current) {
|
|
10641
|
-
current.wakeRequested = false;
|
|
10642
|
-
current.wake = () => {
|
|
10643
|
-
};
|
|
10644
|
-
}
|
|
10645
|
-
resolve3();
|
|
10646
|
-
}, "finish");
|
|
10647
|
-
const timer = setTimeout(finish, ms);
|
|
10648
|
-
const entry = this.pending.get(key);
|
|
10649
|
-
if (entry) entry.wake = finish;
|
|
10650
|
-
});
|
|
10651
|
-
}
|
|
10652
|
-
};
|
|
10653
|
-
function signalReason(signal) {
|
|
10654
|
-
const reason = signal?.reason;
|
|
10655
|
-
return reason instanceof Error ? reason : void 0;
|
|
10656
|
-
}
|
|
10657
|
-
__name(signalReason, "signalReason");
|
|
10658
|
-
function resolveResponder(explicit, ownerId, policy) {
|
|
10659
|
-
if (explicit) return explicit;
|
|
10660
|
-
return policy === "owner" ? ownerId || void 0 : void 0;
|
|
10661
|
-
}
|
|
10662
|
-
__name(resolveResponder, "resolveResponder");
|
|
10663
|
-
var inputSeq = 0;
|
|
10664
|
-
var cardSeq = 0;
|
|
10665
|
-
var planSeq = 0;
|
|
10666
|
-
var runtimeInputDescriptor = {
|
|
10667
|
-
kind: "input",
|
|
10668
|
-
generateId(payload) {
|
|
10669
|
-
return `${payload.kind}_${Date.now().toString(36)}${(++inputSeq).toString(36)}`;
|
|
10670
|
-
},
|
|
10671
|
-
async create({ client, ctx, conversationId, requestId, payload, expiresAt, options }) {
|
|
10672
|
-
const responder = resolveResponder(payload.responseUserId, ctx.ownerId, options.responderPolicy ?? "owner");
|
|
10673
|
-
const created = await client.createRuntimeInputRequest({
|
|
10674
|
-
conversationId,
|
|
10675
|
-
inputId: requestId,
|
|
10676
|
-
kind: payload.kind,
|
|
10677
|
-
expiresAt,
|
|
10678
|
-
...responder !== void 0 ? { responseUserId: responder } : {},
|
|
10679
|
-
...payload.title !== void 0 ? { title: payload.title } : {},
|
|
10680
|
-
...payload.prompt !== void 0 ? { prompt: payload.prompt } : {},
|
|
10681
|
-
...payload.choices ? { choices: payload.choices } : {},
|
|
10682
|
-
...payload.questions ? { questions: payload.questions } : {},
|
|
10683
|
-
...payload.secretName ? { secretName: payload.secretName } : {},
|
|
10684
|
-
...payload.native ? { native: payload.native } : {},
|
|
10685
|
-
...payload.sensitive !== void 0 ? { sensitive: payload.sensitive } : {},
|
|
10686
|
-
...payload.turnId ? { turnId: payload.turnId } : {}
|
|
10687
|
-
});
|
|
10688
|
-
return { requestId, ...created.messageId !== void 0 ? { messageId: created.messageId } : {} };
|
|
10689
|
-
},
|
|
10690
|
-
async consume({ client, conversationId, requestId }) {
|
|
10691
|
-
const response = await client.consumeRuntimeInputResponse({ conversationId, inputId: requestId });
|
|
10692
|
-
if (response.status === "submitted") {
|
|
10693
|
-
return {
|
|
10694
|
-
state: "resolved",
|
|
10695
|
-
result: {
|
|
10696
|
-
status: "submitted",
|
|
10697
|
-
inputId: requestId,
|
|
10698
|
-
value: response.value,
|
|
10699
|
-
...response.answers ? { answers: response.answers } : {}
|
|
10700
|
-
}
|
|
10701
|
-
};
|
|
10702
|
-
}
|
|
10703
|
-
if (response.status === "cancelled") {
|
|
10704
|
-
return { state: "resolved", result: { status: "cancelled", inputId: requestId } };
|
|
10705
|
-
}
|
|
10706
|
-
if (response.status === "timeout") return { state: "timeout" };
|
|
10707
|
-
return { state: "pending" };
|
|
10708
|
-
},
|
|
10709
|
-
async cancel({ client, conversationId, requestId }) {
|
|
10710
|
-
await client.consumeRuntimeInputResponse({ conversationId, inputId: requestId, cancel: true });
|
|
10711
|
-
},
|
|
10712
|
-
timeoutResult({ requestId }) {
|
|
10713
|
-
return { status: "timeout", inputId: requestId };
|
|
10714
|
-
},
|
|
10715
|
-
buildOutcome({ payload, result }) {
|
|
10716
|
-
const outcome = buildRuntimeInputOutcome(result.inputId, result.status, {
|
|
10717
|
-
kind: payload.kind,
|
|
10718
|
-
reason: result.status
|
|
10719
|
-
});
|
|
10720
|
-
return { text: outcome.text, metadata: outcome.metadata };
|
|
10721
|
-
}
|
|
10722
|
-
};
|
|
10723
|
-
var runtimeCardDescriptor = {
|
|
10724
|
-
kind: "card",
|
|
10725
|
-
generateId(payload) {
|
|
10726
|
-
return payload.card.cardId ?? `card_${Date.now().toString(36)}${(++cardSeq).toString(36)}`;
|
|
10727
|
-
},
|
|
10728
|
-
async create({ client, ctx, conversationId, requestId, payload, expiresAt, options }) {
|
|
10729
|
-
const responder = resolveResponder(payload.responseUserId, ctx.ownerId, options.responderPolicy ?? "infer");
|
|
10730
|
-
const created = await client.createRuntimeCardRequest({
|
|
10731
|
-
conversationId,
|
|
10732
|
-
// Embed cardId into the card body (as hosts do) so the wire shape is
|
|
10733
|
-
// byte-identical whether a host folds onto this built-in or not.
|
|
10734
|
-
card: { ...payload.card, cardId: requestId },
|
|
10735
|
-
cardId: requestId,
|
|
10736
|
-
expiresAt,
|
|
10737
|
-
...responder !== void 0 ? { responseUserId: responder } : {},
|
|
10738
|
-
...payload.runtimeId ? { runtimeId: payload.runtimeId } : {},
|
|
10739
|
-
...payload.turnId ? { turnId: payload.turnId } : {},
|
|
10740
|
-
...payload.native ? { native: payload.native } : {}
|
|
10741
|
-
});
|
|
10742
|
-
return {
|
|
10743
|
-
requestId: created.cardId ?? requestId,
|
|
10744
|
-
interactive: created.interactive,
|
|
10745
|
-
...created.expiresAt ? { expiresAt: created.expiresAt } : {},
|
|
10746
|
-
...created.messageId !== void 0 ? { messageId: created.messageId } : {}
|
|
10747
|
-
};
|
|
10748
|
-
},
|
|
10749
|
-
async consume({ client, conversationId, requestId }) {
|
|
10750
|
-
const response = await client.consumeRuntimeCardResponse({ conversationId, cardId: requestId });
|
|
10751
|
-
if (response.status === "submitted") {
|
|
10752
|
-
return {
|
|
10753
|
-
state: "resolved",
|
|
10754
|
-
result: {
|
|
10755
|
-
status: "submitted",
|
|
10756
|
-
cardId: requestId,
|
|
10757
|
-
...response.actionId ? { actionId: response.actionId } : {},
|
|
10758
|
-
...response.values ? { values: response.values } : {},
|
|
10759
|
-
...response.respondedBy ? { respondedBy: response.respondedBy } : {}
|
|
10760
|
-
}
|
|
10761
|
-
};
|
|
10762
|
-
}
|
|
10763
|
-
if (response.status === "cancelled") {
|
|
10764
|
-
return {
|
|
10765
|
-
state: "resolved",
|
|
10766
|
-
result: {
|
|
10767
|
-
status: "cancelled",
|
|
10768
|
-
cardId: requestId,
|
|
10769
|
-
...response.respondedBy ? { respondedBy: response.respondedBy } : {}
|
|
10770
|
-
}
|
|
10771
|
-
};
|
|
10772
|
-
}
|
|
10773
|
-
if (response.status === "timeout") return { state: "timeout" };
|
|
10774
|
-
return { state: "pending" };
|
|
10775
|
-
},
|
|
10776
|
-
async cancel({ client, conversationId, requestId }) {
|
|
10777
|
-
await client.consumeRuntimeCardResponse({ conversationId, cardId: requestId, cancel: true });
|
|
10778
|
-
},
|
|
10779
|
-
timeoutResult({ requestId }) {
|
|
10780
|
-
return { status: "timeout", cardId: requestId };
|
|
10781
|
-
},
|
|
10782
|
-
buildOutcome({ result }) {
|
|
10783
|
-
const status = result.status;
|
|
10784
|
-
const outcome = buildRuntimeCardOutcome(result.cardId, status, { reason: status });
|
|
10785
|
-
return { text: outcome.text, metadata: outcome.metadata };
|
|
10786
|
-
}
|
|
10787
|
-
};
|
|
10788
|
-
var runtimePlanDescriptor = {
|
|
10789
|
-
kind: "plan",
|
|
10790
|
-
generateId() {
|
|
10791
|
-
return `plan_${Date.now().toString(36)}${(++planSeq).toString(36)}`;
|
|
10792
|
-
},
|
|
10793
|
-
async create({ client, ctx, conversationId, requestId, payload, expiresAt, options }) {
|
|
10794
|
-
const responder = resolveResponder(payload.responseUserId, ctx.ownerId, options.responderPolicy ?? "infer");
|
|
10795
|
-
const created = await client.createRuntimePlanRequest({
|
|
10796
|
-
conversationId,
|
|
10797
|
-
planId: requestId,
|
|
10798
|
-
expiresAt,
|
|
10799
|
-
...responder !== void 0 ? { responseUserId: responder } : {},
|
|
10800
|
-
...payload.title !== void 0 ? { title: payload.title } : {},
|
|
10801
|
-
...payload.summary !== void 0 ? { summary: payload.summary } : {},
|
|
10802
|
-
...payload.body !== void 0 ? { body: payload.body } : {},
|
|
10803
|
-
...payload.allowedPrompts ? { allowedPrompts: payload.allowedPrompts } : {},
|
|
10804
|
-
...payload.turnId ? { turnId: payload.turnId } : {}
|
|
10805
|
-
});
|
|
10806
|
-
return {
|
|
10807
|
-
requestId: created.planId ?? requestId,
|
|
10808
|
-
expiresAt: created.expiresAt,
|
|
10809
|
-
...created.messageId !== void 0 ? { messageId: created.messageId } : {}
|
|
10810
|
-
};
|
|
10811
|
-
},
|
|
10812
|
-
async consume({ client, conversationId, requestId }) {
|
|
10813
|
-
const response = await client.consumeRuntimePlanResponse({ conversationId, planId: requestId });
|
|
10814
|
-
if (response.status === "approve" || response.status === "revise" || response.status === "reject") {
|
|
10815
|
-
return {
|
|
10816
|
-
state: "resolved",
|
|
10817
|
-
result: {
|
|
10818
|
-
status: response.status,
|
|
10819
|
-
planId: requestId,
|
|
10820
|
-
...response.feedback ? { feedback: response.feedback } : {},
|
|
10821
|
-
...response.grantedPrompts ? { grantedPrompts: response.grantedPrompts } : {},
|
|
10822
|
-
...response.receiptId ? { receiptId: response.receiptId } : {}
|
|
10823
|
-
}
|
|
10824
|
-
};
|
|
10825
|
-
}
|
|
10826
|
-
if (response.status === "cancelled") {
|
|
10827
|
-
return { state: "resolved", result: { status: "cancelled", planId: requestId } };
|
|
10828
|
-
}
|
|
10829
|
-
if (response.status === "timeout") return { state: "timeout" };
|
|
10830
|
-
return { state: "pending" };
|
|
10831
|
-
},
|
|
10832
|
-
async cancel({ client, conversationId, requestId }) {
|
|
10833
|
-
await client.consumeRuntimePlanResponse({ conversationId, planId: requestId, cancel: true });
|
|
10834
|
-
},
|
|
10835
|
-
timeoutResult({ requestId }) {
|
|
10836
|
-
return { status: "timeout", planId: requestId };
|
|
10837
|
-
},
|
|
10838
|
-
matchPush({ message }) {
|
|
10839
|
-
if (message.metadata?.type !== "plan_approval_reply") return null;
|
|
10840
|
-
const requestId = message.metadata.planId;
|
|
10841
|
-
return typeof requestId === "string" ? { requestId } : null;
|
|
10842
|
-
}
|
|
10843
|
-
};
|
|
10844
|
-
|
|
10845
|
-
// ../core/src/approval-types.ts
|
|
10846
|
-
var DEFAULT_APPROVAL_CONFIG = {
|
|
10847
|
-
enabled: true,
|
|
10848
|
-
timeoutSeconds: 300,
|
|
10849
|
-
defaultOnTimeout: "deny",
|
|
10850
|
-
// Applied to every host's approval previews via ApprovalManager. Covers both
|
|
10851
|
-
// key=value assignments and common bare-credential shapes (bearer headers,
|
|
10852
|
-
// provider keys, cloud keys, PEM blocks, credentialed URLs) so a redacted
|
|
10853
|
-
// command preview does not leak secrets that the narrow key=value rule misses.
|
|
10854
|
-
// Order matters: redactSecrets applies patterns sequentially, so specific
|
|
10855
|
-
// credential shapes run BEFORE the broad key=value rule — otherwise the kv
|
|
10856
|
-
// rule would consume "Authorization: Bearer" and leave the opaque token.
|
|
10857
|
-
// Bare-credential shapes carry a left boundary so ordinary tokens whose tail
|
|
10858
|
-
// happens to embed a prefix (risk-assessment…, disk-cleanup…) are not mangled
|
|
10859
|
-
// in the command preview the owner must read before approving.
|
|
10860
|
-
redactPatterns: [
|
|
10861
|
-
"(?<![A-Za-z0-9])bearer\\s+[A-Za-z0-9._~+/=-]{12,}",
|
|
10862
|
-
"(?<![A-Za-z0-9])sk-[A-Za-z0-9_-]{16,}",
|
|
10863
|
-
"(?<![A-Za-z0-9])AKIA[0-9A-Z]{16}",
|
|
10864
|
-
"(?<![A-Za-z0-9])gh[posru]_[A-Za-z0-9]{20,}",
|
|
10865
|
-
"(?<![A-Za-z0-9])xox[baprs]-[A-Za-z0-9-]{10,}",
|
|
10866
|
-
"(?<![A-Za-z0-9])eyJ[A-Za-z0-9_-]{8,}\\.[A-Za-z0-9_-]{8,}\\.[A-Za-z0-9_-]{8,}",
|
|
10867
|
-
"-----BEGIN [A-Z ]*PRIVATE KEY-----[\\s\\S]*?-----END [A-Z ]*PRIVATE KEY-----",
|
|
10868
|
-
"://[^\\s:@/]+:[^\\s:@/]+@",
|
|
10869
|
-
"(?:api[_-]?key|access[_-]?token|client[_-]?secret|secret|token|password|passwd|pwd|authorization|auth[_-]?token|private[_-]?key)\\s*[:=]\\s*\\S+"
|
|
10870
|
-
]
|
|
10871
|
-
};
|
|
10872
|
-
function isRecord2(value) {
|
|
10873
|
-
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
10874
|
-
}
|
|
10875
|
-
__name(isRecord2, "isRecord");
|
|
10876
|
-
function normalizeString(value, maxLength) {
|
|
10877
|
-
if (typeof value !== "string") return null;
|
|
10878
|
-
const trimmed = value.trim();
|
|
10879
|
-
if (!trimmed || trimmed.length > maxLength) return null;
|
|
10880
|
-
return trimmed;
|
|
10881
|
-
}
|
|
10882
|
-
__name(normalizeString, "normalizeString");
|
|
10883
|
-
function parseSessionRule(value) {
|
|
10884
|
-
if (!isRecord2(value)) return null;
|
|
10885
|
-
const type = value.type;
|
|
10886
|
-
if (type !== "approve-all" && type !== "approve-tool" && type !== "deny-tool") {
|
|
10887
|
-
return null;
|
|
10888
|
-
}
|
|
10889
|
-
let expiresAt;
|
|
10890
|
-
if (value.expiresAt !== void 0) {
|
|
10891
|
-
if (value.expiresAt === null) {
|
|
10892
|
-
expiresAt = null;
|
|
10893
|
-
} else {
|
|
10894
|
-
const normalizedExpiresAt = normalizeString(value.expiresAt, 128);
|
|
10895
|
-
if (!normalizedExpiresAt) return null;
|
|
10896
|
-
const expiresMs = Date.parse(normalizedExpiresAt);
|
|
10897
|
-
if (!Number.isFinite(expiresMs) || expiresMs <= Date.now()) return null;
|
|
10898
|
-
expiresAt = new Date(expiresMs).toISOString();
|
|
10899
|
-
}
|
|
10900
|
-
}
|
|
10901
|
-
if (type === "approve-all") {
|
|
10902
|
-
return {
|
|
10903
|
-
type,
|
|
10904
|
-
...expiresAt !== void 0 ? { expiresAt } : {}
|
|
10905
|
-
};
|
|
10906
|
-
}
|
|
10907
|
-
const toolPattern = normalizeString(value.toolPattern, 128);
|
|
10908
|
-
if (!toolPattern || !/^[\w.*:-]+$/.test(toolPattern)) {
|
|
10909
|
-
return null;
|
|
10910
|
-
}
|
|
10911
|
-
return {
|
|
10912
|
-
type,
|
|
10913
|
-
toolPattern,
|
|
10914
|
-
...expiresAt !== void 0 ? { expiresAt } : {}
|
|
10915
|
-
};
|
|
10916
|
-
}
|
|
10917
|
-
__name(parseSessionRule, "parseSessionRule");
|
|
10918
|
-
function parseApprovalReplyMetadata(value) {
|
|
10919
|
-
if (!isRecord2(value) || value.type !== "approval_reply") return null;
|
|
10920
|
-
const approvalId = normalizeString(value.approvalId, 128);
|
|
10921
|
-
if (!approvalId) return null;
|
|
10922
|
-
const decision = value.decision;
|
|
10923
|
-
if (decision !== "allow" && decision !== "deny") return null;
|
|
10924
|
-
let sessionRule;
|
|
10925
|
-
if (value.sessionRule !== void 0) {
|
|
10926
|
-
const parsed = parseSessionRule(value.sessionRule);
|
|
10927
|
-
if (!parsed) return null;
|
|
10928
|
-
sessionRule = parsed;
|
|
10929
|
-
}
|
|
10930
|
-
return {
|
|
10931
|
-
type: "approval_reply",
|
|
10932
|
-
approvalId,
|
|
10933
|
-
decision,
|
|
10934
|
-
...sessionRule ? { sessionRule } : {}
|
|
10935
|
-
};
|
|
10936
|
-
}
|
|
10937
|
-
__name(parseApprovalReplyMetadata, "parseApprovalReplyMetadata");
|
|
10938
|
-
|
|
10939
10569
|
// ../core/src/unified-diff.ts
|
|
10940
10570
|
var UNIFIED_DIFF_MAX_TOTAL_BYTES = 96 * 1024;
|
|
10941
10571
|
var UNIFIED_DIFF_MAX_FILE_BYTES = 24 * 1024;
|
|
10942
|
-
var UNIFIED_DIFF_MAX_FILES = 100;
|
|
10943
10572
|
var textEncoder = new TextEncoder();
|
|
10944
|
-
function byteLength(text) {
|
|
10945
|
-
return textEncoder.encode(text).length;
|
|
10946
|
-
}
|
|
10947
|
-
__name(byteLength, "byteLength");
|
|
10948
|
-
function clipDiffText(text, maxBytes) {
|
|
10949
|
-
if (maxBytes <= 0) return { text: "", clipped: true };
|
|
10950
|
-
if (byteLength(text) <= maxBytes) return { text, clipped: false };
|
|
10951
|
-
const lines = text.split("\n");
|
|
10952
|
-
const kept = [];
|
|
10953
|
-
let used = 0;
|
|
10954
|
-
for (const line of lines) {
|
|
10955
|
-
const cost = byteLength(line) + (kept.length > 0 ? 1 : 0);
|
|
10956
|
-
if (used + cost > maxBytes) break;
|
|
10957
|
-
kept.push(line);
|
|
10958
|
-
used += cost;
|
|
10959
|
-
}
|
|
10960
|
-
return { text: kept.join("\n"), clipped: true };
|
|
10961
|
-
}
|
|
10962
|
-
__name(clipDiffText, "clipDiffText");
|
|
10963
|
-
function truncateUnifiedDiff(diff, options) {
|
|
10964
|
-
const maxTotalBytes = options?.maxTotalBytes ?? UNIFIED_DIFF_MAX_TOTAL_BYTES;
|
|
10965
|
-
const maxFileBytes = options?.maxFileBytes ?? UNIFIED_DIFF_MAX_FILE_BYTES;
|
|
10966
|
-
const maxFiles = options?.maxFiles ?? UNIFIED_DIFF_MAX_FILES;
|
|
10967
|
-
let totalBytes = 0;
|
|
10968
|
-
let anyClipped = false;
|
|
10969
|
-
const files = diff.files.slice(0, maxFiles).map((file) => {
|
|
10970
|
-
if (typeof file.diff !== "string" || file.diff.length === 0) {
|
|
10971
|
-
const { diff: _omitted, ...rest } = file;
|
|
10972
|
-
return rest;
|
|
10973
|
-
}
|
|
10974
|
-
let truncated2 = file.truncated === true;
|
|
10975
|
-
let text = file.diff;
|
|
10976
|
-
const perFile = clipDiffText(text, maxFileBytes);
|
|
10977
|
-
if (perFile.clipped) {
|
|
10978
|
-
text = perFile.text;
|
|
10979
|
-
truncated2 = true;
|
|
10980
|
-
}
|
|
10981
|
-
const remaining = maxTotalBytes - totalBytes;
|
|
10982
|
-
const withinTotal = clipDiffText(text, remaining);
|
|
10983
|
-
if (withinTotal.clipped) {
|
|
10984
|
-
text = withinTotal.text;
|
|
10985
|
-
truncated2 = true;
|
|
10986
|
-
}
|
|
10987
|
-
if (truncated2) anyClipped = true;
|
|
10988
|
-
if (text.length === 0) {
|
|
10989
|
-
const { diff: _dropped, ...rest } = file;
|
|
10990
|
-
return { ...rest, truncated: true };
|
|
10991
|
-
}
|
|
10992
|
-
totalBytes += byteLength(text);
|
|
10993
|
-
return { ...file, diff: text, ...truncated2 ? { truncated: true } : {} };
|
|
10994
|
-
});
|
|
10995
|
-
const droppedFiles = diff.files.length > files.length;
|
|
10996
|
-
const truncated = diff.truncated === true || droppedFiles || anyClipped;
|
|
10997
|
-
return { files, ...truncated ? { truncated: true } : {} };
|
|
10998
|
-
}
|
|
10999
|
-
__name(truncateUnifiedDiff, "truncateUnifiedDiff");
|
|
11000
|
-
|
|
11001
|
-
// ../core/src/approval-format.ts
|
|
11002
|
-
var seq = 0;
|
|
11003
|
-
function generateApprovalId() {
|
|
11004
|
-
const ts = Date.now().toString(36);
|
|
11005
|
-
const r = Math.random().toString(36).slice(2, 6);
|
|
11006
|
-
return `apr_${ts}${r}${++seq}`;
|
|
11007
|
-
}
|
|
11008
|
-
__name(generateApprovalId, "generateApprovalId");
|
|
11009
|
-
function summarizeToolInput(toolName, toolInput) {
|
|
11010
|
-
if (toolName === "Bash" && typeof toolInput.command === "string") {
|
|
11011
|
-
return toolInput.command;
|
|
11012
|
-
}
|
|
11013
|
-
if ((toolName === "Edit" || toolName === "Write") && typeof toolInput.file_path === "string") {
|
|
11014
|
-
return toolInput.file_path;
|
|
11015
|
-
}
|
|
11016
|
-
const json = JSON.stringify(toolInput);
|
|
11017
|
-
return json.length > 200 ? json.slice(0, 200) + "..." : json;
|
|
11018
|
-
}
|
|
11019
|
-
__name(summarizeToolInput, "summarizeToolInput");
|
|
11020
|
-
function redactSecrets(text, patterns) {
|
|
11021
|
-
let result = text;
|
|
11022
|
-
for (const pat of patterns) {
|
|
11023
|
-
result = result.replace(new RegExp(pat, "gi"), "[REDACTED]");
|
|
11024
|
-
}
|
|
11025
|
-
return result;
|
|
11026
|
-
}
|
|
11027
|
-
__name(redactSecrets, "redactSecrets");
|
|
11028
|
-
function redactApprovalDetails(details, patterns) {
|
|
11029
|
-
if (!details?.length) return void 0;
|
|
11030
|
-
return details.slice(0, 8).map((detail) => ({
|
|
11031
|
-
...detail,
|
|
11032
|
-
label: detail.label.slice(0, 80),
|
|
11033
|
-
value: patterns?.length ? redactSecrets(detail.value.slice(0, 500), patterns) : detail.value.slice(0, 500)
|
|
11034
|
-
}));
|
|
11035
|
-
}
|
|
11036
|
-
__name(redactApprovalDetails, "redactApprovalDetails");
|
|
11037
|
-
function buildApprovalRequest(approvalId, toolName, toolInput, opts) {
|
|
11038
|
-
let summary = opts.toolSummary ?? summarizeToolInput(toolName, toolInput);
|
|
11039
|
-
if (opts.redactPatterns?.length) {
|
|
11040
|
-
summary = redactSecrets(summary, opts.redactPatterns);
|
|
11041
|
-
}
|
|
11042
|
-
summary = summary.slice(0, 1e3);
|
|
11043
|
-
const risk = opts.risk ?? opts.riskLevel ?? "normal";
|
|
11044
|
-
const riskLevel = risk === "destructive" ? "destructive" : opts.riskLevel ?? "normal";
|
|
11045
|
-
const details = redactApprovalDetails(opts.details, opts.redactPatterns);
|
|
11046
|
-
const diff = opts.diff ? truncateUnifiedDiff(opts.diff) : void 0;
|
|
11047
|
-
const timeoutMin = Math.round(
|
|
11048
|
-
(new Date(opts.expiresAt).getTime() - Date.now()) / 6e4
|
|
11049
|
-
);
|
|
11050
|
-
const lines = [
|
|
11051
|
-
`Action Approval Required [${approvalId}]`,
|
|
11052
|
-
"",
|
|
11053
|
-
`Tool: ${toolName}`,
|
|
11054
|
-
summary,
|
|
11055
|
-
""
|
|
11056
|
-
];
|
|
11057
|
-
if (risk === "high" || risk === "destructive") {
|
|
11058
|
-
lines.push(risk === "destructive" ? "This is a destructive operation" : "This is a high-risk operation");
|
|
11059
|
-
lines.push("");
|
|
11060
|
-
}
|
|
11061
|
-
lines.push(`Reply "approve" or "deny" (expires in ${timeoutMin}m)`);
|
|
11062
|
-
const metadata = {
|
|
11063
|
-
type: "approval_request",
|
|
11064
|
-
approvalId,
|
|
11065
|
-
...opts.responseUserId ? { responseUserId: opts.responseUserId.slice(0, 128) } : {},
|
|
11066
|
-
toolName,
|
|
11067
|
-
toolSummary: summary,
|
|
11068
|
-
...opts.category ? { category: opts.category } : {},
|
|
11069
|
-
risk,
|
|
11070
|
-
riskLevel,
|
|
11071
|
-
...opts.runtimeId ? { runtimeId: opts.runtimeId } : {},
|
|
11072
|
-
...opts.turnId ? { turnId: opts.turnId } : {},
|
|
11073
|
-
...opts.native ? { native: opts.native } : {},
|
|
11074
|
-
...details ? { details } : {},
|
|
11075
|
-
...diff ? { diff } : {},
|
|
11076
|
-
expiresAt: opts.expiresAt
|
|
11077
|
-
};
|
|
11078
|
-
return { text: lines.join("\n"), metadata };
|
|
11079
|
-
}
|
|
11080
|
-
__name(buildApprovalRequest, "buildApprovalRequest");
|
|
11081
|
-
function buildApprovalOutcome(approvalId, toolName, toolSummary, decision, reason) {
|
|
11082
|
-
const icon = decision === "allow" ? "Approved" : "Denied";
|
|
11083
|
-
const short = toolSummary.length > 60 ? toolSummary.slice(0, 60) + "..." : toolSummary;
|
|
11084
|
-
if (reason === "timeout") {
|
|
11085
|
-
return `Expired [${approvalId}] -- ${toolName}: ${short} (auto-denied)`;
|
|
11086
|
-
}
|
|
11087
|
-
if (reason === "session-rule") {
|
|
11088
|
-
const label = decision === "allow" ? "Auto-approved" : "Auto-denied";
|
|
11089
|
-
return `${label} (session rule) -- ${toolName}: ${short}`;
|
|
11090
|
-
}
|
|
11091
|
-
return `${icon} [${approvalId}] -- ${toolName}: ${short}`;
|
|
11092
|
-
}
|
|
11093
|
-
__name(buildApprovalOutcome, "buildApprovalOutcome");
|
|
11094
|
-
|
|
11095
|
-
// ../core/src/approval-manager.ts
|
|
11096
|
-
var ApprovalManager = class extends RuntimeRequestManager {
|
|
11097
|
-
static {
|
|
11098
|
-
__name(this, "ApprovalManager");
|
|
11099
|
-
}
|
|
11100
|
-
config;
|
|
11101
|
-
constructor(client, agentId, ownerId, config) {
|
|
11102
|
-
super(client, { agentId, ownerId });
|
|
11103
|
-
this.config = { ...DEFAULT_APPROVAL_CONFIG, ...config };
|
|
11104
|
-
this.register("approval", this.buildApprovalDescriptor());
|
|
11105
|
-
}
|
|
11106
|
-
/**
|
|
11107
|
-
* Request approval for a tool call.
|
|
11108
|
-
*
|
|
11109
|
-
* 1. Checks session rules — may resolve immediately.
|
|
11110
|
-
* 2. Sends a message with approval card metadata.
|
|
11111
|
-
* 3. Waits for the owner's reply (or timeout).
|
|
11112
|
-
*/
|
|
11113
|
-
requestApproval(conversationId, toolName, toolInput, opts, runtimeOptions) {
|
|
11114
|
-
return this.request(
|
|
11115
|
-
"approval",
|
|
11116
|
-
conversationId,
|
|
11117
|
-
{ toolName, toolInput, opts },
|
|
11118
|
-
runtimeOptions
|
|
11119
|
-
);
|
|
11120
|
-
}
|
|
11121
|
-
buildApprovalDescriptor() {
|
|
11122
|
-
return {
|
|
11123
|
-
kind: "approval",
|
|
11124
|
-
generateId: /* @__PURE__ */ __name(() => generateApprovalId(), "generateId"),
|
|
11125
|
-
resolveExpiry: /* @__PURE__ */ __name(({ options }) => options.expiresAt ?? Date.now() + this.config.timeoutSeconds * 1e3, "resolveExpiry"),
|
|
11126
|
-
pollMs: /* @__PURE__ */ __name(() => 1e3, "pollMs"),
|
|
11127
|
-
preflight: /* @__PURE__ */ __name(({ conversationId, payload }) => {
|
|
11128
|
-
const { toolName, toolInput, opts } = payload;
|
|
11129
|
-
const nonOwnerResponder = Boolean(
|
|
11130
|
-
opts?.responseUserId && opts.responseUserId !== this.ctx.ownerId
|
|
11131
|
-
);
|
|
11132
|
-
const matchingRule = opts?.ignoreSessionRules || nonOwnerResponder ? null : this.checkSessionRules(toolName, conversationId);
|
|
11133
|
-
if (!matchingRule) return null;
|
|
11134
|
-
const decision = matchingRule.type === "deny-tool" ? "deny" : "allow";
|
|
11135
|
-
const rawSummary = opts?.toolSummary ?? summarizeTool(toolName, toolInput);
|
|
11136
|
-
const summary = this.config.redactPatterns.length ? redactSecrets(rawSummary, this.config.redactPatterns) : rawSummary;
|
|
11137
|
-
const logMsg = buildApprovalOutcome("", toolName, summary, decision, "session-rule");
|
|
11138
|
-
this.client.sendMessage(conversationId, logMsg, {
|
|
11139
|
-
metadata: { type: "approval_outcome", decision, reason: "session-rule" }
|
|
11140
|
-
}).catch(() => {
|
|
11141
|
-
});
|
|
11142
|
-
return { decision };
|
|
11143
|
-
}, "preflight"),
|
|
11144
|
-
create: /* @__PURE__ */ __name(async ({ conversationId, requestId, payload, expiresAt }) => {
|
|
11145
|
-
const { toolName, toolInput, opts } = payload;
|
|
11146
|
-
const approvalId = requestId;
|
|
11147
|
-
const expiresAtIso = new Date(expiresAt).toISOString();
|
|
11148
|
-
const requestedResponseUserId = opts?.responseUserId || this.ctx.ownerId || void 0;
|
|
11149
|
-
const requestedAllowSessionRule = requestedResponseUserId === this.ctx.ownerId && opts?.allowSessionRule !== false;
|
|
11150
|
-
const { metadata } = buildApprovalRequest(approvalId, toolName, toolInput, {
|
|
11151
|
-
riskLevel: opts?.riskLevel,
|
|
11152
|
-
risk: opts?.risk,
|
|
11153
|
-
category: opts?.category,
|
|
11154
|
-
responseUserId: requestedResponseUserId,
|
|
11155
|
-
runtimeId: opts?.runtimeId,
|
|
11156
|
-
turnId: opts?.turnId,
|
|
11157
|
-
native: opts?.native,
|
|
11158
|
-
toolSummary: opts?.toolSummary,
|
|
11159
|
-
details: opts?.details,
|
|
11160
|
-
diff: opts?.diff,
|
|
11161
|
-
expiresAt: expiresAtIso,
|
|
11162
|
-
redactPatterns: this.config.redactPatterns
|
|
11163
|
-
});
|
|
11164
|
-
const created = await this.client.createRuntimeApprovalRequest({
|
|
11165
|
-
conversationId,
|
|
11166
|
-
approvalId,
|
|
11167
|
-
toolName,
|
|
11168
|
-
toolSummary: metadata.toolSummary,
|
|
11169
|
-
expiresAt: Date.parse(expiresAtIso),
|
|
11170
|
-
...requestedResponseUserId ? { responseUserId: requestedResponseUserId } : {},
|
|
11171
|
-
...opts?.riskLevel ? { riskLevel: opts.riskLevel } : {},
|
|
11172
|
-
...opts?.risk ? { risk: opts.risk } : {},
|
|
11173
|
-
...opts?.category ? { category: opts.category } : {},
|
|
11174
|
-
...opts?.runtimeId ? { runtimeId: opts.runtimeId } : {},
|
|
11175
|
-
...opts?.turnId ? { turnId: opts.turnId } : {},
|
|
11176
|
-
...metadata.native ? { native: metadata.native } : {},
|
|
11177
|
-
...metadata.details ? { details: metadata.details } : {},
|
|
11178
|
-
...metadata.diff ? { diff: metadata.diff } : {},
|
|
11179
|
-
...!requestedAllowSessionRule ? { allowSessionRule: false } : {}
|
|
11180
|
-
});
|
|
11181
|
-
return {
|
|
11182
|
-
requestId: approvalId,
|
|
11183
|
-
expiresAt,
|
|
11184
|
-
state: {
|
|
11185
|
-
toolName,
|
|
11186
|
-
toolSummary: metadata.toolSummary,
|
|
11187
|
-
allowSessionRule: created.allowSessionRule ?? requestedAllowSessionRule
|
|
11188
|
-
}
|
|
11189
|
-
};
|
|
11190
|
-
}, "create"),
|
|
11191
|
-
consume: /* @__PURE__ */ __name(async ({ conversationId, requestId }) => {
|
|
11192
|
-
const response = await this.client.consumeRuntimeApprovalResponse({
|
|
11193
|
-
conversationId,
|
|
11194
|
-
approvalId: requestId
|
|
11195
|
-
});
|
|
11196
|
-
if (response.status === "allow" || response.status === "deny") {
|
|
11197
|
-
return {
|
|
11198
|
-
state: "resolved",
|
|
11199
|
-
result: {
|
|
11200
|
-
decision: response.status,
|
|
11201
|
-
...response.sessionRule ? { sessionRule: response.sessionRule } : {},
|
|
11202
|
-
...response.respondedBy ? { respondedBy: response.respondedBy } : {}
|
|
11203
|
-
}
|
|
11204
|
-
};
|
|
11205
|
-
}
|
|
11206
|
-
if (response.status === "timeout") return { state: "timeout" };
|
|
11207
|
-
return { state: "pending" };
|
|
11208
|
-
}, "consume"),
|
|
11209
|
-
cancel: /* @__PURE__ */ __name(async ({ conversationId, requestId }) => {
|
|
11210
|
-
await this.client.consumeRuntimeApprovalResponse({
|
|
11211
|
-
conversationId,
|
|
11212
|
-
approvalId: requestId,
|
|
11213
|
-
cancel: true
|
|
11214
|
-
});
|
|
11215
|
-
}, "cancel"),
|
|
11216
|
-
timeoutResult: /* @__PURE__ */ __name(() => ({ decision: "deny" }), "timeoutResult"),
|
|
11217
|
-
finalize: /* @__PURE__ */ __name(({ conversationId, requestId, state, result, reason }) => {
|
|
11218
|
-
const toolName = state?.toolName ?? "";
|
|
11219
|
-
const toolSummary = state?.toolSummary ?? "";
|
|
11220
|
-
if (reason === "timeout") {
|
|
11221
|
-
const msg = buildApprovalOutcome(requestId, toolName, toolSummary, "deny", "timeout");
|
|
11222
|
-
this.client.sendMessage(conversationId, msg, {
|
|
11223
|
-
metadata: {
|
|
11224
|
-
type: "approval_outcome",
|
|
11225
|
-
approvalId: requestId,
|
|
11226
|
-
decision: "deny",
|
|
11227
|
-
reason: "timeout"
|
|
11228
|
-
}
|
|
11229
|
-
}).catch(() => {
|
|
11230
|
-
});
|
|
11231
|
-
return { decision: "deny" };
|
|
11232
|
-
}
|
|
11233
|
-
const acceptedSessionRule = state?.allowSessionRule ? result.sessionRule : void 0;
|
|
11234
|
-
if (acceptedSessionRule) {
|
|
11235
|
-
this.addSessionRule(conversationId, acceptedSessionRule);
|
|
11236
|
-
}
|
|
11237
|
-
const outcomeMsg = buildApprovalOutcome(
|
|
11238
|
-
requestId,
|
|
11239
|
-
toolName,
|
|
11240
|
-
toolSummary,
|
|
11241
|
-
result.decision,
|
|
11242
|
-
"replied"
|
|
11243
|
-
);
|
|
11244
|
-
this.client.sendMessage(conversationId, outcomeMsg, {
|
|
11245
|
-
metadata: {
|
|
11246
|
-
type: "approval_outcome",
|
|
11247
|
-
approvalId: requestId,
|
|
11248
|
-
decision: result.decision,
|
|
11249
|
-
reason: "replied"
|
|
11250
|
-
}
|
|
11251
|
-
}).catch(() => {
|
|
11252
|
-
});
|
|
11253
|
-
if (acceptedSessionRule) {
|
|
11254
|
-
const ruleDesc = describeRule(acceptedSessionRule);
|
|
11255
|
-
this.client.sendMessage(conversationId, `Session rule set: ${ruleDesc}`, {
|
|
11256
|
-
metadata: { type: "approval_outcome", decision: result.decision, reason: "session-rule" }
|
|
11257
|
-
}).catch(() => {
|
|
11258
|
-
});
|
|
11259
|
-
}
|
|
11260
|
-
return {
|
|
11261
|
-
decision: result.decision,
|
|
11262
|
-
...acceptedSessionRule ? { sessionRule: acceptedSessionRule } : {},
|
|
11263
|
-
...result.respondedBy ? { respondedBy: result.respondedBy } : {}
|
|
11264
|
-
};
|
|
11265
|
-
}, "finalize"),
|
|
11266
|
-
matchPush: /* @__PURE__ */ __name(({ conversationId, message }) => {
|
|
11267
|
-
void conversationId;
|
|
11268
|
-
if (message.metadata?.type !== "approval_reply") return null;
|
|
11269
|
-
const parsed = parseApprovalReplyMetadata(message.metadata);
|
|
11270
|
-
if (!parsed) return null;
|
|
11271
|
-
return { requestId: parsed.approvalId };
|
|
11272
|
-
}, "matchPush")
|
|
11273
|
-
};
|
|
11274
|
-
}
|
|
11275
|
-
};
|
|
11276
|
-
function summarizeTool(toolName, toolInput) {
|
|
11277
|
-
if (toolName === "Bash" && typeof toolInput.command === "string") {
|
|
11278
|
-
return toolInput.command;
|
|
11279
|
-
}
|
|
11280
|
-
if ((toolName === "Edit" || toolName === "Write") && typeof toolInput.file_path === "string") {
|
|
11281
|
-
return toolInput.file_path;
|
|
11282
|
-
}
|
|
11283
|
-
const json = JSON.stringify(toolInput);
|
|
11284
|
-
return json.length > 100 ? json.slice(0, 100) + "..." : json;
|
|
11285
|
-
}
|
|
11286
|
-
__name(summarizeTool, "summarizeTool");
|
|
11287
|
-
function describeRule(rule) {
|
|
11288
|
-
if (rule.type === "approve-all") {
|
|
11289
|
-
if (rule.expiresAt) {
|
|
11290
|
-
const min = Math.round((new Date(rule.expiresAt).getTime() - Date.now()) / 6e4);
|
|
11291
|
-
return `auto-approving all tools for ${min}m`;
|
|
11292
|
-
}
|
|
11293
|
-
return "auto-approving all tools for this session";
|
|
11294
|
-
}
|
|
11295
|
-
if (rule.type === "approve-tool") {
|
|
11296
|
-
return `auto-approving all ${rule.toolPattern} commands`;
|
|
11297
|
-
}
|
|
11298
|
-
if (rule.type === "deny-tool") {
|
|
11299
|
-
return `auto-denying all ${rule.toolPattern} commands`;
|
|
11300
|
-
}
|
|
11301
|
-
return "unknown rule";
|
|
11302
|
-
}
|
|
11303
|
-
__name(describeRule, "describeRule");
|
|
11304
|
-
|
|
11305
|
-
// ../core/src/silent-turn.ts
|
|
11306
|
-
var NO_REPLY_REASON_SENTINEL = "given";
|
|
11307
|
-
function reportNoReplyOutcome(client, params) {
|
|
11308
|
-
try {
|
|
11309
|
-
const hasReason = Boolean(params.reason?.trim());
|
|
11310
|
-
const wire = projectVerbIntentToWire(
|
|
11311
|
-
"no_reply",
|
|
11312
|
-
{
|
|
11313
|
-
conversationId: params.conversationId,
|
|
11314
|
-
...params.messageId ? { messageId: params.messageId } : {},
|
|
11315
|
-
...hasReason ? { reason: NO_REPLY_REASON_SENTINEL } : {}
|
|
11316
|
-
},
|
|
11317
|
-
{ now: params.now ?? Date.now() }
|
|
11318
|
-
);
|
|
11319
|
-
void client.executeVerbWire(wire).catch(() => {
|
|
11320
|
-
});
|
|
11321
|
-
} catch {
|
|
11322
|
-
}
|
|
11323
|
-
}
|
|
11324
|
-
__name(reportNoReplyOutcome, "reportNoReplyOutcome");
|
|
11325
10573
|
|
|
11326
|
-
// ../core/src/
|
|
11327
|
-
var
|
|
11328
|
-
|
|
11329
|
-
group: "quiet",
|
|
11330
|
-
// Fail OPEN to today's behavior: 'unknown' is reachable whenever the
|
|
11331
|
-
// conversation fetch fails, and silence-by-accident is worse than noise.
|
|
11332
|
-
unknown: "verbose"
|
|
11333
|
-
};
|
|
11334
|
-
function normalizeTurnVerbosityConversationType(value) {
|
|
11335
|
-
const normalized = typeof value === "string" ? value.trim().toLowerCase() : "";
|
|
11336
|
-
if (normalized === "direct") return "direct";
|
|
11337
|
-
if (normalized === "group") return "group";
|
|
11338
|
-
return "unknown";
|
|
11339
|
-
}
|
|
11340
|
-
__name(normalizeTurnVerbosityConversationType, "normalizeTurnVerbosityConversationType");
|
|
11341
|
-
function resolveTurnVerbosity(input) {
|
|
11342
|
-
const configured = parseTurnVerbosityConfig(input.configured);
|
|
11343
|
-
if (configured === "verbose" || configured === "quiet") return configured;
|
|
11344
|
-
return DEFAULT_TURN_VERBOSITY_BY_CONVERSATION_TYPE[normalizeTurnVerbosityConversationType(input.conversationType)];
|
|
11345
|
-
}
|
|
11346
|
-
__name(resolveTurnVerbosity, "resolveTurnVerbosity");
|
|
11347
|
-
function parseTurnVerbosityConfig(raw) {
|
|
11348
|
-
const normalized = typeof raw === "string" ? raw.trim().toLowerCase() : "";
|
|
11349
|
-
if (normalized === "verbose" || normalized === "quiet" || normalized === "auto") {
|
|
11350
|
-
return normalized;
|
|
11351
|
-
}
|
|
11352
|
-
return null;
|
|
11353
|
-
}
|
|
11354
|
-
__name(parseTurnVerbosityConfig, "parseTurnVerbosityConfig");
|
|
10574
|
+
// ../core/src/runtime-cards.ts
|
|
10575
|
+
var FIELD_TYPE_SET = new Set(RUNTIME_CARD_FIELD_TYPES);
|
|
10576
|
+
var LINE_ITEM_COLUMN_TYPE_SET = new Set(RUNTIME_CARD_LINE_ITEM_COLUMN_TYPES);
|
|
11355
10577
|
|
|
11356
10578
|
// ../core/src/rtdb-rest.ts
|
|
11357
10579
|
var CLEARED_LOCAL_RUNTIME_FIELDS = {
|
|
@@ -11792,62 +11014,12 @@ function createRuntimeStatePublisher(options) {
|
|
|
11792
11014
|
__name(createRuntimeStatePublisher, "createRuntimeStatePublisher");
|
|
11793
11015
|
|
|
11794
11016
|
// ../core/src/retry.ts
|
|
11795
|
-
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
11796
11017
|
var CANON_MESSAGE_TEXT_MAX_BYTES = 4 * 1024;
|
|
11797
|
-
var DEFAULT_CHUNKED_MESSAGE_TEXT_MAX_BYTES = 3800;
|
|
11798
11018
|
function isPendingCanonOperation(error) {
|
|
11799
|
-
if (isChunkedSendMessageError(error)) return isPendingCanonOperation(error.cause);
|
|
11800
11019
|
return !!error && typeof error === "object" && "code" in error && ["OPERATION_PENDING", "OPERATION_UNCERTAIN", "ENDPOINT_CLOSED"].includes(String(error.code));
|
|
11801
11020
|
}
|
|
11802
11021
|
__name(isPendingCanonOperation, "isPendingCanonOperation");
|
|
11803
|
-
var ChunkedSendMessageError = class extends Error {
|
|
11804
|
-
static {
|
|
11805
|
-
__name(this, "ChunkedSendMessageError");
|
|
11806
|
-
}
|
|
11807
|
-
/** Ids of the parts that are durable in Canon, in part order. */
|
|
11808
|
-
deliveredMessageIds;
|
|
11809
|
-
/** The part the send stopped on (1-based). */
|
|
11810
|
-
failedPart;
|
|
11811
|
-
/** How many parts the text splits into in total. */
|
|
11812
|
-
totalParts;
|
|
11813
|
-
/** The underlying send failure — what callers should classify. */
|
|
11814
|
-
cause;
|
|
11815
|
-
constructor(input) {
|
|
11816
|
-
const detail = input.cause instanceof Error ? input.cause.message : String(input.cause);
|
|
11817
|
-
super(`Chunked send failed at part ${input.failedPart} of ${input.totalParts}: ${detail}`);
|
|
11818
|
-
this.name = "ChunkedSendMessageError";
|
|
11819
|
-
this.deliveredMessageIds = [...input.deliveredMessageIds];
|
|
11820
|
-
this.failedPart = input.failedPart;
|
|
11821
|
-
this.totalParts = input.totalParts;
|
|
11822
|
-
this.cause = input.cause;
|
|
11823
|
-
}
|
|
11824
|
-
/** How many parts are durable — a resume starts at the next one. */
|
|
11825
|
-
get deliveredParts() {
|
|
11826
|
-
return this.deliveredMessageIds.length;
|
|
11827
|
-
}
|
|
11828
|
-
};
|
|
11829
|
-
function isChunkedSendMessageError(error) {
|
|
11830
|
-
if (error instanceof ChunkedSendMessageError) return true;
|
|
11831
|
-
return error instanceof Error && error.name === "ChunkedSendMessageError" && Array.isArray(error.deliveredMessageIds);
|
|
11832
|
-
}
|
|
11833
|
-
__name(isChunkedSendMessageError, "isChunkedSendMessageError");
|
|
11834
11022
|
var textEncoder2 = new TextEncoder();
|
|
11835
|
-
function isRetryableCanonDeliveryError(error) {
|
|
11836
|
-
if (error instanceof CanonApiError) {
|
|
11837
|
-
return error.status === 429 || error.status >= 500;
|
|
11838
|
-
}
|
|
11839
|
-
return error instanceof Error;
|
|
11840
|
-
}
|
|
11841
|
-
__name(isRetryableCanonDeliveryError, "isRetryableCanonDeliveryError");
|
|
11842
|
-
async function sendMessageWithRetry(client, conversationId, text, options, retryOptions = {}) {
|
|
11843
|
-
try {
|
|
11844
|
-
return await (retryOptions.operationId ? client.sendMessage(conversationId, text, options, { operationId: retryOptions.operationId }) : client.sendMessage(conversationId, text, options));
|
|
11845
|
-
} catch (error) {
|
|
11846
|
-
if (!(error instanceof CanonApiError) || !error.operationId) throw error;
|
|
11847
|
-
return client.waitForOperation(error.operationId, { signal: retryOptions.signal, timeoutMs: retryOptions.timeoutMs });
|
|
11848
|
-
}
|
|
11849
|
-
}
|
|
11850
|
-
__name(sendMessageWithRetry, "sendMessageWithRetry");
|
|
11851
11023
|
function utf8ByteLength(value) {
|
|
11852
11024
|
return textEncoder2.encode(value).byteLength;
|
|
11853
11025
|
}
|
|
@@ -11946,8 +11118,7 @@ ${renderedFence.marker}` : "";
|
|
|
11946
11118
|
};
|
|
11947
11119
|
}
|
|
11948
11120
|
__name(takeChunk, "takeChunk");
|
|
11949
|
-
function
|
|
11950
|
-
const byteLimit = Math.min(maxBytes, CANON_MESSAGE_TEXT_MAX_BYTES);
|
|
11121
|
+
function splitTextWithinBytes(text, byteLimit) {
|
|
11951
11122
|
if (!Number.isFinite(byteLimit) || byteLimit < 4) {
|
|
11952
11123
|
throw new Error("maxBytes must be at least 4");
|
|
11953
11124
|
}
|
|
@@ -11972,115 +11143,7 @@ function splitTextByUtf8Bytes(text, maxBytes = DEFAULT_CHUNKED_MESSAGE_TEXT_MAX_
|
|
|
11972
11143
|
}
|
|
11973
11144
|
return chunks;
|
|
11974
11145
|
}
|
|
11975
|
-
__name(
|
|
11976
|
-
function chunkMessageId(baseMessageId, index) {
|
|
11977
|
-
if (!baseMessageId) return void 0;
|
|
11978
|
-
const suffix = `-part-${index}`;
|
|
11979
|
-
const maxBaseLength = 160 - suffix.length;
|
|
11980
|
-
return `${baseMessageId.slice(0, Math.max(0, maxBaseLength))}${suffix}`;
|
|
11981
|
-
}
|
|
11982
|
-
__name(chunkMessageId, "chunkMessageId");
|
|
11983
|
-
function stripTrailTextBlocks(trail) {
|
|
11984
|
-
if (!Array.isArray(trail)) return null;
|
|
11985
|
-
return trail.filter((block) => {
|
|
11986
|
-
if (!block || typeof block !== "object") return true;
|
|
11987
|
-
return block.kind !== "text";
|
|
11988
|
-
});
|
|
11989
|
-
}
|
|
11990
|
-
__name(stripTrailTextBlocks, "stripTrailTextBlocks");
|
|
11991
|
-
function buildChunkedMessagePartMetadata(input) {
|
|
11992
|
-
if (input.count <= 1) return { ...input.metadata ?? {} };
|
|
11993
|
-
const chunk = {
|
|
11994
|
-
type: "text",
|
|
11995
|
-
index: input.index,
|
|
11996
|
-
count: input.count,
|
|
11997
|
-
...input.groupId ? { groupId: input.groupId } : {}
|
|
11998
|
-
};
|
|
11999
|
-
if (input.index >= input.count) {
|
|
12000
|
-
const metadata = { ...input.metadata ?? {} };
|
|
12001
|
-
const trail = stripTrailTextBlocks(metadata.turnTrail);
|
|
12002
|
-
if (trail) {
|
|
12003
|
-
if (trail.length > 0) metadata.turnTrail = trail;
|
|
12004
|
-
else delete metadata.turnTrail;
|
|
12005
|
-
}
|
|
12006
|
-
return {
|
|
12007
|
-
...metadata,
|
|
12008
|
-
messageChunk: chunk
|
|
12009
|
-
};
|
|
12010
|
-
}
|
|
12011
|
-
const {
|
|
12012
|
-
turnSemantics: _turnSemantics,
|
|
12013
|
-
turnTrail: _turnTrail,
|
|
12014
|
-
...rest
|
|
12015
|
-
} = input.metadata ?? {};
|
|
12016
|
-
return {
|
|
12017
|
-
...rest,
|
|
12018
|
-
turnSemantics: "progress",
|
|
12019
|
-
replyBehavior: "suppress_auto_reply",
|
|
12020
|
-
messageChunk: chunk
|
|
12021
|
-
};
|
|
12022
|
-
}
|
|
12023
|
-
__name(buildChunkedMessagePartMetadata, "buildChunkedMessagePartMetadata");
|
|
12024
|
-
async function sendMessageWithRetryChunked(client, conversationId, text, options, retryOptions = {}, chunkingOptions = {}) {
|
|
12025
|
-
const chunks = splitTextByUtf8Bytes(
|
|
12026
|
-
text,
|
|
12027
|
-
chunkingOptions.maxTextBytes ?? DEFAULT_CHUNKED_MESSAGE_TEXT_MAX_BYTES
|
|
12028
|
-
);
|
|
12029
|
-
const alreadyDelivered = chunkingOptions.deliveredMessageIds ?? [];
|
|
12030
|
-
const resumable = chunkingOptions.resumable === true || alreadyDelivered.length > 0;
|
|
12031
|
-
if (chunks.length === 1) {
|
|
12032
|
-
if (alreadyDelivered.length > 0) {
|
|
12033
|
-
throw new ChunkedSendMessageError({
|
|
12034
|
-
cause: new Error(
|
|
12035
|
-
`Resume cursor holds ${alreadyDelivered.length} part(s) but the text now fits in one message`
|
|
12036
|
-
),
|
|
12037
|
-
deliveredMessageIds: alreadyDelivered,
|
|
12038
|
-
failedPart: 1,
|
|
12039
|
-
totalParts: 1
|
|
12040
|
-
});
|
|
12041
|
-
}
|
|
12042
|
-
const result = await sendMessageWithRetry(client, conversationId, text, options, retryOptions);
|
|
12043
|
-
return { messageIds: [result.messageId] };
|
|
12044
|
-
}
|
|
12045
|
-
const rootMessageId = options?.messageId ?? randomUUID6();
|
|
12046
|
-
const parts = chunks.map((text2, index) => ({ text: text2, options: {
|
|
12047
|
-
...options ?? {},
|
|
12048
|
-
messageId: chunkMessageId(rootMessageId, index + 1),
|
|
12049
|
-
metadata: buildChunkedMessagePartMetadata({ groupId: rootMessageId, metadata: options?.metadata, index: index + 1, count: chunks.length })
|
|
12050
|
-
} }));
|
|
12051
|
-
const group = await client.prepareMessageGroup(conversationId, rootMessageId, parts, retryOptions);
|
|
12052
|
-
const groupId = group.id;
|
|
12053
|
-
const cancel = /* @__PURE__ */ __name(() => {
|
|
12054
|
-
void client.cancelMessageGroup(groupId).catch(() => {
|
|
12055
|
-
});
|
|
12056
|
-
}, "cancel");
|
|
12057
|
-
retryOptions.signal?.addEventListener("abort", cancel, { once: true });
|
|
12058
|
-
try {
|
|
12059
|
-
const startIndex = Math.min(alreadyDelivered.length, chunks.length);
|
|
12060
|
-
const messageIds = [...alreadyDelivered.slice(0, startIndex)];
|
|
12061
|
-
for (let index = startIndex; index < chunks.length; index += 1) {
|
|
12062
|
-
const part = index + 1;
|
|
12063
|
-
try {
|
|
12064
|
-
if (retryOptions.signal?.aborted) throw new CanonApiError(409, JSON.stringify({ code: "OPERATION_PENDING", message: "Reply delivery was interrupted" }));
|
|
12065
|
-
const result = await group.sendPart(index, retryOptions);
|
|
12066
|
-
messageIds.push(result.messageId);
|
|
12067
|
-
} catch (error) {
|
|
12068
|
-
if (!resumable) throw error;
|
|
12069
|
-
throw new ChunkedSendMessageError({
|
|
12070
|
-
cause: error,
|
|
12071
|
-
deliveredMessageIds: messageIds,
|
|
12072
|
-
failedPart: part,
|
|
12073
|
-
totalParts: chunks.length
|
|
12074
|
-
});
|
|
12075
|
-
}
|
|
12076
|
-
}
|
|
12077
|
-
return { messageIds };
|
|
12078
|
-
} finally {
|
|
12079
|
-
retryOptions.signal?.removeEventListener("abort", cancel);
|
|
12080
|
-
if (retryOptions.signal?.aborted) await client.cancelMessageGroup(groupId);
|
|
12081
|
-
}
|
|
12082
|
-
}
|
|
12083
|
-
__name(sendMessageWithRetryChunked, "sendMessageWithRetryChunked");
|
|
11146
|
+
__name(splitTextWithinBytes, "splitTextWithinBytes");
|
|
12084
11147
|
|
|
12085
11148
|
// ../core/src/cli-metadata.ts
|
|
12086
11149
|
import { readFileSync as readFileSync3, realpathSync } from "node:fs";
|
|
@@ -12144,7 +11207,7 @@ function runCli(moduleUrl, main, onError, metadata) {
|
|
|
12144
11207
|
__name(runCli, "runCli");
|
|
12145
11208
|
|
|
12146
11209
|
// ../core/src/completed-output-journal.ts
|
|
12147
|
-
import { createHash as createHash4, randomUUID as
|
|
11210
|
+
import { createHash as createHash4, randomUUID as randomUUID6 } from "node:crypto";
|
|
12148
11211
|
import {
|
|
12149
11212
|
closeSync as closeSync3,
|
|
12150
11213
|
existsSync as existsSync2,
|
|
@@ -12221,7 +11284,7 @@ function createCompletedOutputJournal(directory, scope5, options) {
|
|
|
12221
11284
|
if (readFileSync4(path, "utf8") !== serialized) throw new Error(`Completed ${label} output cannot be replaced`);
|
|
12222
11285
|
return;
|
|
12223
11286
|
}
|
|
12224
|
-
const temporary = `${path.slice(0, -5)}.${process.pid}.${
|
|
11287
|
+
const temporary = `${path.slice(0, -5)}.${process.pid}.${randomUUID6()}.tmp`;
|
|
12225
11288
|
try {
|
|
12226
11289
|
const fd = openSync3(temporary, "wx", 384);
|
|
12227
11290
|
try {
|
|
@@ -12261,12 +11324,6 @@ function createCompletedOutputJournal(directory, scope5, options) {
|
|
|
12261
11324
|
};
|
|
12262
11325
|
}
|
|
12263
11326
|
__name(createCompletedOutputJournal, "createCompletedOutputJournal");
|
|
12264
|
-
function assertCompletedOutputAudience(record6, current, label) {
|
|
12265
|
-
if (!record6.audience || !current || record6.audience.membershipRevision !== void 0 && record6.audience.membershipRevision !== current.membershipRevision || JSON.stringify([...record6.audience.memberIds].sort()) !== JSON.stringify([...current.memberIds].sort())) {
|
|
12266
|
-
throw new Error(`Completed ${label} output audience changed; operator reconciliation is required`);
|
|
12267
|
-
}
|
|
12268
|
-
}
|
|
12269
|
-
__name(assertCompletedOutputAudience, "assertCompletedOutputAudience");
|
|
12270
11327
|
|
|
12271
11328
|
// src/bounded-file-read.ts
|
|
12272
11329
|
var BoundedFileReadError = class extends Error {
|
|
@@ -12545,7 +11602,7 @@ async function materializeAttachment(attachment, options) {
|
|
|
12545
11602
|
if (!response.body) {
|
|
12546
11603
|
throw new Error("Canon media response had no body");
|
|
12547
11604
|
}
|
|
12548
|
-
const tempPath = `${path}.${process.pid}.${
|
|
11605
|
+
const tempPath = `${path}.${process.pid}.${randomUUID7()}.part`;
|
|
12549
11606
|
const limiter = byteLimitTransform(maxBytes);
|
|
12550
11607
|
try {
|
|
12551
11608
|
await pipeline2(
|
|
@@ -12641,7 +11698,7 @@ async function uploadMediaFile(client, conversationId, filePath, options) {
|
|
|
12641
11698
|
const media = await client.getFileMediaPipeline(options?.fetchImpl);
|
|
12642
11699
|
const [attachment] = await media.prepare({
|
|
12643
11700
|
conversationId,
|
|
12644
|
-
attachmentId: options?.attachmentId ??
|
|
11701
|
+
attachmentId: options?.attachmentId ?? randomUUID7(),
|
|
12645
11702
|
files: [{ source: filePath, descriptor: {
|
|
12646
11703
|
mimeType,
|
|
12647
11704
|
sizeBytes: fileStat.size,
|
|
@@ -12670,7 +11727,7 @@ async function sendMediaFileMessage(client, conversationId, filePath, text = "",
|
|
|
12670
11727
|
const current = await client.getConversation(conversationId);
|
|
12671
11728
|
return !!current && originalMembers.size > 0 && current.memberIds.every((id2) => originalMembers.has(id2)) && canPublish();
|
|
12672
11729
|
} : void 0;
|
|
12673
|
-
const messageId = sendOptions.messageId ??
|
|
11730
|
+
const messageId = sendOptions.messageId ?? randomUUID7();
|
|
12674
11731
|
const pipeline3 = await client.getFileMediaPipeline(fetchImpl);
|
|
12675
11732
|
const delivered = await pipeline3.send({
|
|
12676
11733
|
conversationId,
|
|
@@ -12845,21 +11902,14 @@ export {
|
|
|
12845
11902
|
acquireLock,
|
|
12846
11903
|
clearPendingRegistration,
|
|
12847
11904
|
ensureAgentProfile,
|
|
12848
|
-
ApprovalManager,
|
|
12849
|
-
reportNoReplyOutcome,
|
|
12850
|
-
resolveTurnVerbosity,
|
|
12851
11905
|
initRTDBAuth,
|
|
12852
11906
|
renderCanonHostInboundContent,
|
|
12853
11907
|
createRuntimeStatePublisher,
|
|
12854
11908
|
isPendingCanonOperation,
|
|
12855
|
-
|
|
12856
|
-
splitTextByUtf8Bytes,
|
|
12857
|
-
buildChunkedMessagePartMetadata,
|
|
12858
|
-
sendMessageWithRetryChunked,
|
|
11909
|
+
splitTextWithinBytes,
|
|
12859
11910
|
readCliPackageVersion,
|
|
12860
11911
|
runCli,
|
|
12861
11912
|
createCompletedOutputJournal,
|
|
12862
|
-
assertCompletedOutputAudience,
|
|
12863
11913
|
BoundedFileReadError,
|
|
12864
11914
|
readBoundedRegularFileHandle,
|
|
12865
11915
|
DEFAULT_MEDIA_CACHE_DIR,
|