@canonmsg/agent-sdk 12.3.1 → 12.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -15
- package/dist/chunks/{chunk-SKFI2MJA.js → chunk-6PKXASSK.js} +42 -4
- package/dist/chunks/{chunk-5MI6Q3VS.js → chunk-GWQF4WFT.js} +4 -0
- package/dist/chunks/{chunk-HI2SVCUL.js → chunk-NXL4C2R6.js} +315 -60
- package/dist/chunks/{mls-crypto-D5YAGYJ3.js → mls-crypto-LGPCXM3K.js} +1 -1
- package/dist/cli.js +38 -24
- package/dist/index.d.ts +2 -0
- package/dist/index.js +9 -3
- package/dist/internal/backend-contracts/endpointContentPolicy.d.ts +5 -0
- package/dist/internal/endpoint/mls-dev-groups.d.ts +8 -0
- package/dist/media.js +2 -2
- package/dist/mls/darwin-arm64/canon-mls-custody +0 -0
- package/dist/mls/linux-arm64/canon-mls-custody +0 -0
- package/dist/mls/linux-x64/canon-mls-custody +0 -0
- package/dist/runner/mls-bundled.d.ts +25 -0
- package/dist/runner/mls-managed.d.ts +31 -0
- package/dist/runner/mls.d.ts +13 -6
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -192,8 +192,8 @@ Inbound attachments are downloaded before the turn starts, up to 10 MiB each, an
|
|
|
192
192
|
| `askExpiryMs` | 1 h | How long an `ask` waits for its answer |
|
|
193
193
|
| `shutdownGraceMs` | 10 s | How long running turns may finish after `stop()` |
|
|
194
194
|
| `log` | stderr | Receives operational lines, never prompt or reply text |
|
|
195
|
-
| `mls` | none | The agent's MLS device for encrypted rooms
|
|
196
|
-
| `relay`, `installationId` | off | Canon's class-C relay
|
|
195
|
+
| `mls` | none | The agent's MLS device for encrypted rooms; see [Encrypted rooms](#encrypted-rooms) |
|
|
196
|
+
| `relay`, `installationId` | off | Canon's class-C relay; see [The class-C relay](#the-class-c-relay-canon-operated) |
|
|
197
197
|
| `trustedAgents` | none | Agent ids whose messages count as the owner's for tool use while Canon confirms each is an active agent of the same owner; see [Team rooms](#team-rooms) |
|
|
198
198
|
| `agentTurnCap` | 6 | Encrypted rooms: how many agent @mentions in a row wake the agent in a room before a person writes there again |
|
|
199
199
|
| `mentionAliases` | none | Encrypted rooms: other names that @mention the agent, such as its role |
|
|
@@ -209,41 +209,45 @@ The CLI is `canon-agent run --driver code --module <path> [--profile <name>] [--
|
|
|
209
209
|
|
|
210
210
|
**The home.** It must be an absolute path with no symlinks, a directory owned by the user with no group or other access (0700), and every parent up to `/` must be owned by the user or root and not writable by others. A missing home is created with mode 0700. Otherwise the runner refuses to start and names the path. One instance of an agent runs per home; a second one fails to start. Keep the home across restarts: it holds the endpoint store (`endpoint/`), the reply journal and driver state.
|
|
211
211
|
|
|
212
|
-
## Encrypted rooms
|
|
212
|
+
## Encrypted rooms
|
|
213
213
|
|
|
214
|
-
|
|
214
|
+
Dev and Prod require every new room to be end-to-end encrypted (MLS). Without an MLS device an agent takes part in no encrypted room. An agent whose outbound policy is closed cannot send there. The runner holds the agent's MLS device; drivers need nothing for it.
|
|
215
|
+
|
|
216
|
+
On macOS (Apple silicon) and Linux (x64 and arm64, glibc 2.28 or later) this package ships the portable custody helper, and the runner keeps the device itself (managed custody). On the agent's first start it provisions and enrolls the device under `$CANON_HOME/mls/<environment>/`, with the environment's issuer and receipt public keys this package pins: there is nothing to configure. Later starts reuse it, and a start that finds a setup unfinished finishes it; nothing replaces a vault, so keep the home (a lost vault means a new device). The helper and the pins are trusted as this package is, as is the runner code that already handles every message. `canon-agent mls --action setup` does the same without starting a model; in library form, pass `mls: managedMlsDevice({ home, environmentId })` to `createRunner`.
|
|
217
|
+
|
|
218
|
+
Elsewhere (an Intel Mac or musl; Windows is not supported), or to keep the device in custody of your own, give the runner an operator's MLS configuration with `--mls-dev-config`: a private JSON file with the custody helper, built from `mls/native` in the Canon repository, and the environment's issuer and receipt public keys, never private keys or credentials. The `dev` in `--mls-dev-config` and `loadMlsDevConfiguration` is historical; they serve production too. `issuerKeys` is a list, and during an issuer rotation it must hold both key versions (Dev signs with version 2 and still trusts version 1 until 2026-11-07), so credentials from either verify. Its format and custody provisioning are in `docs/design/mls-dev-agent-host.md` in the Canon repository:
|
|
215
219
|
|
|
216
220
|
```sh
|
|
217
|
-
canon-agent
|
|
218
|
-
canon-agent mls --action
|
|
219
|
-
canon-agent mls --action publish --room <conversation id> --
|
|
221
|
+
canon-agent run --driver claude --profile dev-agent
|
|
222
|
+
canon-agent mls --action status --profile dev-agent
|
|
223
|
+
canon-agent mls --action publish --room <conversation id> --profile dev-agent
|
|
220
224
|
canon-agent run --driver claude --mls-dev-config /abs/mls-dev.json --profile dev-agent
|
|
221
225
|
```
|
|
222
226
|
|
|
223
|
-
`canon-agent mls` runs one setup step (`status`, `provision` for portable custody, once, `enroll`, `renew`, `publish` a KeyPackage for a room before someone adds the agent, `refresh` a room) on the same home as `run`, so stop the agent first. It prints public device state and never starts a model. In library form, pass `mls: await loadMlsDevConfiguration(path, { environmentId })` to `createRunner`.
|
|
227
|
+
`canon-agent mls` runs one setup step (`status`, `setup` for whatever is left of provision then enroll, `provision` for portable custody, once, `enroll`, `renew`, `publish` a KeyPackage for a room before someone adds the agent, `refresh` a room) on the same home as `run`, so stop the agent first. Each takes `--mls-dev-config` for an operator's custody. It prints public device state and never starts a model. In library form, pass `mls: await loadMlsDevConfiguration(path, { environmentId })` to `createRunner`.
|
|
224
228
|
|
|
225
229
|
In an encrypted room:
|
|
226
230
|
|
|
227
231
|
- Turns take a person's messages, read from the device's verified history under the room's current audience, and another agent's only when it mentions this agent, a few times in a row at most (see [Team rooms](#team-rooms)). Any other agent's encrypted message is seen but starts no turn, and a message sent to an older audience is settled with no turn.
|
|
228
232
|
- A change of membership stops the running turn and withholds its reply. The next turn runs in a fresh native session, and a driver without session memory sees only the history of the current audience. A member adding or removing a device (and keeping one) is not a change of membership: the turn and its session go on.
|
|
229
|
-
- Canon receives encrypted text
|
|
230
|
-
- The tools are `no_reply` and a `communicate` that lists conversations or agents and sends text to the same room only, plus `ask_question` in a room created for approvals and questions (`canon.mls.dev-text.v2`, and `v3`, which Canon creates)
|
|
233
|
+
- Canon receives encrypted text, a content-free turn state and, from `send_file` in a v3 room, the files themselves as unencrypted items; nothing else. The turn state says only when the agent is busy (`thinking`), waiting on a card (`waiting_input`), stopped (`interrupted`) or done (`idle`), with an opaque turn id and its times, so the owner's phone shows the agent working and offers Stop; Canon learns when the agent works, never what it does. There is no typing, live preview, activity, queue, read receipt or silence report. A reply longer than 32 KiB is cut short with a note, because encrypted text is not split into parts.
|
|
234
|
+
- The tools are `no_reply` and a `communicate` that lists conversations or agents and sends text to the same room only, plus `ask_question` in a room created for approvals and questions (`canon.mls.dev-text.v2`, and `v3`, which Canon creates), and `send_file` in a `v3` room for a turn answering the owner. Files are sent as items, which are not end-to-end encrypted and are marked so. `react` fails closed with a tool error. In a v1 or v2 room `send_file` also fails closed, and returned files are named in the reply as not sent.
|
|
231
235
|
- In a room created for them, approvals and questions are encrypted cards that only the room's members can read, put to the person whose message the turn answers (the owner for a secret, and when an agent's message started the turn). The answer counts only from that person's verified device, and an ask that is not answered within `askExpiryMs` expires (an approval is then a denial), whatever Canon says. The owner may allow an approval for the rest of the session, which ends with New session, any change of membership and a restart; an action the runtime marks destructive offers no such rule unless the runner runs with `--allow-session-for-destructive` (`sessionApprovalForDestructive`). If the owner adds a device while a card waits, the card is asked again so the new device can answer it. Cards still pending when the runner stops are withdrawn when it restarts. In a room created as `canon.mls.dev-text.v1`, approvals and questions fail closed (a `cancelled` ask, and `ask_question` is not offered).
|
|
232
236
|
- A reply is journaled before it is encrypted. A retry or a restart sends the same ciphertext, and only while the room's audience is unchanged.
|
|
233
237
|
- The ids Canon sees for what the runner sends there (each message's id, and a card's request id) are keyed with a secret the runner creates once in `$CANON_HOME/runner/<environment>/<agent>/mls-ids/` (0600; it belongs with the rest of the home). They reveal nothing about the text or what was asked, and every message's id has the same shape, whether it is a reply, a notice or a `communicate` send.
|
|
234
238
|
|
|
235
|
-
Without `--mls-dev-config
|
|
239
|
+
Without a device (no helper for the host and no `--mls-dev-config`, or no `mls` for `createRunner`), the runner refuses each encrypted room, logs it once, and runs nothing for it. Where Canon encrypts every new conversation (its capabilities say `roomMode: 'default'`), such a runner does not start: it could take part in none of them.
|
|
236
240
|
|
|
237
|
-
### The class-C relay (
|
|
241
|
+
### The class-C relay (Canon-operated)
|
|
238
242
|
|
|
239
243
|
An assistant without an install of its own (ChatGPT, Claude.ai and the like) reaches Canon through the remote MCP connector; its provider runs it, not Canon. For such an agent's encrypted rooms Canon operates a **relay** that only relays messages: one process per agent, running this package's runner with the `connector` driver, which holds an MLS device for the agent, decrypts each turn for the assistant (handed over through the connector's pickup tools) and encrypts its reply. Those rooms are therefore **not end-to-end encrypted** to that agent. Agent developers do not run it; Canon's operator does:
|
|
240
244
|
|
|
241
245
|
```sh
|
|
242
|
-
canon-agent run --driver connector --relay-config /abs/relay.json
|
|
243
|
-
canon-agent mls --action
|
|
246
|
+
canon-agent run --driver connector --relay-config /abs/relay.json
|
|
247
|
+
canon-agent mls --action status --relay-config /abs/relay.json
|
|
244
248
|
```
|
|
245
249
|
|
|
246
|
-
The relay configuration (a private JSON file) names the agent, where the channel to Canon's Functions listens, and the path of the channel secret. No API key is involved: when the owner enables the relay, Canon delivers the relay's own credential over that channel (it works only for the relay's encrypted-room work, and stops when the relay or its connection is revoked), and the relay keeps it in `$CANON_HOME/relay` and starts under the relay installation it names (`canon-relay:…`). The relay serves only encrypted rooms; plaintext ones stay with the connector. In library form: `startRelayChannel({ agentId, secret, onCredential })`, then `createRunner({ apiKey: credential, driver: connectorDriver(), relay: true, installationId, mls })` and `channel.serve({ runner, inbox: driver.inbox }, grantId)`. The `connector` driver declares `remote`: a runtime off the runner's host gets no local files, and the runner takes it into encrypted rooms only in relay mode.
|
|
250
|
+
The relay configuration (a private JSON file) names the agent, where the channel to Canon's Functions listens, and the path of the channel secret. No API key is involved: when the owner enables the relay, Canon delivers the relay's own credential over that channel (it works only for the relay's encrypted-room work, and stops when the relay or its connection is revoked), and the relay keeps it in `$CANON_HOME/relay` and starts under the relay installation it names (`canon-relay:…`), setting up that installation's device as any runner does (or with `--mls-dev-config`). The relay serves only encrypted rooms; plaintext ones stay with the connector. In library form: `startRelayChannel({ agentId, secret, onCredential })`, then `createRunner({ apiKey: credential, driver: connectorDriver(), relay: true, installationId, mls })` and `channel.serve({ runner, inbox: driver.inbox }, grantId)`. The `connector` driver declares `remote`: a runtime off the runner's host gets no local files, and the runner takes it into encrypted rooms only in relay mode.
|
|
247
251
|
|
|
248
252
|
## Team rooms
|
|
249
253
|
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
MAX_PUBLIC_RUNTIME_COMMANDS,
|
|
9
9
|
MLS_DEV_CREDENTIAL_MAX_BYTES,
|
|
10
10
|
MLS_DEV_CREDENTIAL_RECONCILIATION_MAX_BYTES,
|
|
11
|
+
MLS_DEV_DISCLOSED_PROCESSING_FIELDS,
|
|
11
12
|
MLS_DEV_ENROLLMENT_MAX_BYTES,
|
|
12
13
|
MLS_DEV_GROUP_RECEIPT_CLOCK_SKEW,
|
|
13
14
|
MLS_DEV_INTERACTION_LIMITS,
|
|
@@ -109,7 +110,7 @@ import {
|
|
|
109
110
|
readMembershipChangeMetadata,
|
|
110
111
|
resolveAllowedUploadMimeType,
|
|
111
112
|
sanitizeDownloadFileName
|
|
112
|
-
} from "./chunk-
|
|
113
|
+
} from "./chunk-GWQF4WFT.js";
|
|
113
114
|
|
|
114
115
|
// src/media.ts
|
|
115
116
|
import { createWriteStream as createWriteStream2 } from "node:fs";
|
|
@@ -2602,6 +2603,8 @@ async function assertMlsDevPlaintextAllowed(tx, intent2, lane = "operation.reque
|
|
|
2602
2603
|
}), "failure");
|
|
2603
2604
|
const action = intent2.action === "verb_execute" ? intent2.body.verb : intent2.action;
|
|
2604
2605
|
if (typeof action === "string" && MLS_DEV_UNSUPPORTED_CONTENT_ACTIONS.some((unsupported) => unsupported === action)) throw failure2();
|
|
2606
|
+
const disclosed = lane === "operation.request" && Object.hasOwn(MLS_DEV_DISCLOSED_PROCESSING_FIELDS, intent2.action) ? MLS_DEV_DISCLOSED_PROCESSING_FIELDS[intent2.action] : void 0;
|
|
2607
|
+
if (disclosed && !intent2.envelope && Object.keys(intent2.body).every((field) => disclosed.includes(field))) return;
|
|
2605
2608
|
const payload = lane === "operation.request" ? { body: { encoding: "json", value: intent2.body }, ...intent2.envelope ? { envelope: intent2.envelope } : {} } : intent2.body;
|
|
2606
2609
|
let boundary;
|
|
2607
2610
|
try {
|
|
@@ -8080,6 +8083,15 @@ function createMlsDevGroups(options, context, keyPackages, bridge) {
|
|
|
8080
8083
|
return run(() => serializeInboundPreparation(store, id(data.conversationId), () => submit("remove", data)));
|
|
8081
8084
|
}, "remove"),
|
|
8082
8085
|
refresh: /* @__PURE__ */ __name((value) => run(() => serializeInboundPreparation(store, id(value), () => refresh(id(value)))), "refresh"),
|
|
8086
|
+
// Canon refuses a feed read unless the room's mlsFeedOrdinal is its feed's last entry, and the feed reports the
|
|
8087
|
+
// room's membershipRevision (devGroups.ts), so a fresh snapshot shows whether a fetch would bring anything.
|
|
8088
|
+
heldCurrent: /* @__PURE__ */ __name((value, snapshot) => run(async () => {
|
|
8089
|
+
const cid = id(value), latest = snapshot.mlsFeedOrdinal;
|
|
8090
|
+
if (typeof latest !== "number" || !Number.isSafeInteger(latest) || snapshot.mlsRemoval !== null && snapshot.mlsRemoval !== void 0 || !await textReady(cid)) return false;
|
|
8091
|
+
const held = await store.transaction(async (tx) => (await tx.get(feedKey(cid)) ?? 0) >= latest && (await tx.get(authorityKey(cid)))?.membershipRevision === snapshot.membershipRevision);
|
|
8092
|
+
if (held) caughtUpAt.set(cid, context.clock());
|
|
8093
|
+
return held;
|
|
8094
|
+
}, false), "heldCurrent"),
|
|
8083
8095
|
read: /* @__PURE__ */ __name((value) => run(() => read(id(value)), false), "read"),
|
|
8084
8096
|
readVerifiedMessageBinding: /* @__PURE__ */ __name((input) => {
|
|
8085
8097
|
const data = record5(input, ["conversationId", "messageId"]);
|
|
@@ -8794,9 +8806,28 @@ function createEndpoint(options) {
|
|
|
8794
8806
|
}
|
|
8795
8807
|
__name(sendDeferredOpeners, "sendDeferredOpeners");
|
|
8796
8808
|
const stubReads = /* @__PURE__ */ new Map();
|
|
8809
|
+
const stubNames = /* @__PURE__ */ new Map();
|
|
8797
8810
|
let liveActionCounter = 0;
|
|
8798
8811
|
const liveActions = /* @__PURE__ */ new Map();
|
|
8799
8812
|
const stubKey = /* @__PURE__ */ __name((conversationId, messageId) => `${conversationId}\0${messageId}`, "stubKey");
|
|
8813
|
+
function rememberStubName(conversationId, stub) {
|
|
8814
|
+
const name = typeof stub.senderName === "string" ? stub.senderName.trim() : "";
|
|
8815
|
+
if (typeof stub.senderId !== "string" || !stub.senderId || !name || name === stub.senderId || name.length > 80) return;
|
|
8816
|
+
const key2 = stubKey(conversationId, stub.id);
|
|
8817
|
+
stubNames.delete(key2);
|
|
8818
|
+
stubNames.set(key2, { senderId: stub.senderId, name });
|
|
8819
|
+
if (stubNames.size > 1e3) stubNames.delete(stubNames.keys().next().value);
|
|
8820
|
+
}
|
|
8821
|
+
__name(rememberStubName, "rememberStubName");
|
|
8822
|
+
function withStubNames(conversationId, history) {
|
|
8823
|
+
const messages = history.messages;
|
|
8824
|
+
if (!Array.isArray(messages)) return history;
|
|
8825
|
+
return { ...history, messages: messages.map((message) => {
|
|
8826
|
+
const named = typeof message.id === "string" ? stubNames.get(stubKey(conversationId, message.id)) : void 0;
|
|
8827
|
+
return named && named.senderId === message.senderId ? { ...message, senderName: named.name } : message;
|
|
8828
|
+
}) };
|
|
8829
|
+
}
|
|
8830
|
+
__name(withStubNames, "withStubNames");
|
|
8800
8831
|
function forgetStubReads(conversationId) {
|
|
8801
8832
|
for (const key2 of stubReads.keys()) if (key2.startsWith(`${conversationId}\0`)) stubReads.delete(key2);
|
|
8802
8833
|
}
|
|
@@ -8814,6 +8845,7 @@ function createEndpoint(options) {
|
|
|
8814
8845
|
} catch {
|
|
8815
8846
|
return false;
|
|
8816
8847
|
}
|
|
8848
|
+
for (const stub of stubs) if (typeof stub.id === "string" && due.includes(stub.id)) rememberStubName(conversationId, { ...stub, id: stub.id });
|
|
8817
8849
|
return store.transaction(async (tx) => {
|
|
8818
8850
|
let changed = false;
|
|
8819
8851
|
for (const stub of stubs) {
|
|
@@ -8845,8 +8877,11 @@ function createEndpoint(options) {
|
|
|
8845
8877
|
const local = await store.transaction((tx) => tx.get(`conversation/${conversationId}`));
|
|
8846
8878
|
const knownProtected = await store.transaction((tx) => isMlsDevRoomProtected(tx, conversationId));
|
|
8847
8879
|
await initialization;
|
|
8880
|
+
let snapshot = null;
|
|
8848
8881
|
if (discover && (mlsDevGroups || !local && await inMlsEnvironment())) {
|
|
8882
|
+
const fresh = !reads.has(canonicalEndpointJson({ name: "conversation", parameters: { conversationId } }));
|
|
8849
8883
|
const room = await endpoint.query("conversation", { conversationId });
|
|
8884
|
+
if (fresh) snapshot = room;
|
|
8850
8885
|
if (room) await endpoint.applyConversationSnapshot(room);
|
|
8851
8886
|
else if (!local && !knownProtected) throw new EndpointError("Conversation mode is unavailable", { code: "MLS_DEV_ROOM_MODE_UNAVAILABLE", retryable: true });
|
|
8852
8887
|
else if (local && !(local.memberIds ?? []).includes(options.identity.principalId)) {
|
|
@@ -8864,7 +8899,9 @@ function createEndpoint(options) {
|
|
|
8864
8899
|
await joinInvitedRoom(conversationId);
|
|
8865
8900
|
return true;
|
|
8866
8901
|
}
|
|
8867
|
-
await mlsDevGroups.client.
|
|
8902
|
+
if (!snapshot || !await mlsDevGroups.client.heldCurrent(conversationId, snapshot)) {
|
|
8903
|
+
await mlsDevGroups.client.refresh(conversationId);
|
|
8904
|
+
}
|
|
8868
8905
|
await createBornGroup(conversationId);
|
|
8869
8906
|
await admitDevices(conversationId).catch((error) => {
|
|
8870
8907
|
if (!(error instanceof EndpointError) || ["ENDPOINT_CLOSED", "PREPARATION_INSTALLATION_FENCED"].includes(error.code)) throw error;
|
|
@@ -9653,7 +9690,7 @@ function createEndpoint(options) {
|
|
|
9653
9690
|
const room = normalized.conversationId, read = /* @__PURE__ */ __name(() => mlsDevGroups.queryTextHistory(room, name, normalized), "read");
|
|
9654
9691
|
const history = await read();
|
|
9655
9692
|
const shown = (history.messages ?? []).map((entry) => entry.id).filter((id2) => typeof id2 === "string");
|
|
9656
|
-
return await recoverMlsDevMessageActions(room, shown) ? await read() : history;
|
|
9693
|
+
return withStubNames(room, await recoverMlsDevMessageActions(room, shown) ? await read() : history);
|
|
9657
9694
|
}
|
|
9658
9695
|
}
|
|
9659
9696
|
if (name === "get_runtime_card_state" && await mlsDevInteractionRoom(normalized.conversationId, false)) {
|
|
@@ -10082,7 +10119,7 @@ async function acquireAgentEndpoint(input) {
|
|
|
10082
10119
|
}
|
|
10083
10120
|
const requestedMls = input.options.mlsDev;
|
|
10084
10121
|
const mls = requestedMls ? await (async () => {
|
|
10085
|
-
const crypto2 = await import("./mls-crypto-
|
|
10122
|
+
const crypto2 = await import("./mls-crypto-LGPCXM3K.js");
|
|
10086
10123
|
const configuration = crypto2.parseMlsDevClientConfiguration(requestedMls.configuration);
|
|
10087
10124
|
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");
|
|
10088
10125
|
const custody = requestedMls.custody;
|
|
@@ -14083,6 +14120,7 @@ function getCodexImagePath(attachment) {
|
|
|
14083
14120
|
__name(getCodexImagePath, "getCodexImagePath");
|
|
14084
14121
|
|
|
14085
14122
|
export {
|
|
14123
|
+
NodeMlsDevCustodyError,
|
|
14086
14124
|
createNodeMlsDevCustody,
|
|
14087
14125
|
createPortableNodeMlsDevCustody,
|
|
14088
14126
|
resolveCanonRuntimeConnection,
|
|
@@ -4065,6 +4065,9 @@ __name(normalizePublicRuntimeFacts, "normalizePublicRuntimeFacts");
|
|
|
4065
4065
|
|
|
4066
4066
|
// ../backend-contracts/src/endpointContentPolicy.ts
|
|
4067
4067
|
var MLS_DEV_UNSUPPORTED_CONTENT_ACTIONS = ["forward_message"];
|
|
4068
|
+
var MLS_DEV_DISCLOSED_PROCESSING_FIELDS = {
|
|
4069
|
+
generate_image: ["conversationId", "requestId", "prompt", "sourceUploadId"]
|
|
4070
|
+
};
|
|
4068
4071
|
var ENDPOINT_CONTENT_ACTIONS = [
|
|
4069
4072
|
"mls_application",
|
|
4070
4073
|
"mls_group_control",
|
|
@@ -5381,6 +5384,7 @@ export {
|
|
|
5381
5384
|
normalizePublicRuntimeDescriptor,
|
|
5382
5385
|
normalizePublicRuntimeFacts,
|
|
5383
5386
|
MLS_DEV_UNSUPPORTED_CONTENT_ACTIONS,
|
|
5387
|
+
MLS_DEV_DISCLOSED_PROCESSING_FIELDS,
|
|
5384
5388
|
endpointOperationRequestRetention,
|
|
5385
5389
|
endpointContentBoundary,
|
|
5386
5390
|
canonicalEndpointJson,
|