@canonmsg/backend-contracts 2.1.0 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/canon-verb-wire.schema.json +367 -0
- package/dist/canon-verbs.limits.json +70 -0
- package/dist/canon-verbs.schema.json +1744 -0
- package/dist/cjs/contactRequest.js +4 -1
- package/dist/cjs/environment.js +29 -0
- package/dist/cjs/index.js +4 -0
- package/dist/cjs/verbContract.js +288 -0
- package/dist/cjs/verbSchemas.js +1144 -0
- package/dist/cjs/verbWire.js +634 -0
- package/dist/contactRequest.d.ts +1 -0
- package/dist/contactRequest.js +4 -1
- package/dist/environment.d.ts +25 -0
- package/dist/environment.js +25 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/verbContract.d.ts +760 -0
- package/dist/verbContract.js +283 -0
- package/dist/verbSchemas.d.ts +1460 -0
- package/dist/verbSchemas.js +1139 -0
- package/dist/verbWire.d.ts +405 -0
- package/dist/verbWire.js +628 -0
- package/package.json +8 -3
|
@@ -74,7 +74,10 @@ function serializeContactRequest(requestId, data) {
|
|
|
74
74
|
targetAvatarUrl: typeof data.targetAvatarUrl === 'string' ? data.targetAvatarUrl : null,
|
|
75
75
|
targetUserType: data.targetUserType,
|
|
76
76
|
approverId: data.approverId,
|
|
77
|
-
|
|
77
|
+
// Free-form request content is owner-review material. This shared DTO is
|
|
78
|
+
// delivered to the target agent over REST/SSE, so it must never cross the
|
|
79
|
+
// admission boundary before the human approver accepts the reach-out.
|
|
80
|
+
message: null,
|
|
78
81
|
status: normalizeStatus(data.status),
|
|
79
82
|
kind: kindValue,
|
|
80
83
|
createdAt: normalizeTimestamp(data.createdAt),
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CANON_ENVIRONMENT_CONTRACTS = void 0;
|
|
4
|
+
exports.getCanonEnvironmentContract = getCanonEnvironmentContract;
|
|
5
|
+
exports.CANON_ENVIRONMENT_CONTRACTS = Object.freeze({
|
|
6
|
+
'canon-dev-v1': Object.freeze({
|
|
7
|
+
name: 'dev',
|
|
8
|
+
projectId: 'canonmail-dev',
|
|
9
|
+
region: 'europe-west1',
|
|
10
|
+
}),
|
|
11
|
+
'canon-prod-v1': Object.freeze({
|
|
12
|
+
name: 'prod',
|
|
13
|
+
projectId: 'canonmail-prod',
|
|
14
|
+
region: 'europe-west1',
|
|
15
|
+
}),
|
|
16
|
+
'canon-legacy-v1': Object.freeze({
|
|
17
|
+
name: 'legacy',
|
|
18
|
+
projectId: 'project-007a8e71-ba01-49e6-8aa',
|
|
19
|
+
region: 'us-central1',
|
|
20
|
+
}),
|
|
21
|
+
});
|
|
22
|
+
function getCanonEnvironmentContract(value) {
|
|
23
|
+
const environmentId = value.trim();
|
|
24
|
+
const contract = exports.CANON_ENVIRONMENT_CONTRACTS[environmentId];
|
|
25
|
+
if (!contract) {
|
|
26
|
+
throw new Error(`Unsupported Canon environment ID: ${value}`);
|
|
27
|
+
}
|
|
28
|
+
return Object.freeze({ environmentId, ...contract });
|
|
29
|
+
}
|
package/dist/cjs/index.js
CHANGED
|
@@ -15,6 +15,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./diffRedaction.js"), exports);
|
|
18
|
+
__exportStar(require("./environment.js"), exports);
|
|
18
19
|
__exportStar(require("./media.js"), exports);
|
|
19
20
|
__exportStar(require("./message.js"), exports);
|
|
20
21
|
__exportStar(require("./runtimeCardFields.js"), exports);
|
|
@@ -22,3 +23,6 @@ __exportStar(require("./runtimeCardStorage.js"), exports);
|
|
|
22
23
|
__exportStar(require("./turnProtocol.js"), exports);
|
|
23
24
|
__exportStar(require("./agentBehaviorPolicy.js"), exports);
|
|
24
25
|
__exportStar(require("./contactRequest.js"), exports);
|
|
26
|
+
__exportStar(require("./verbContract.js"), exports);
|
|
27
|
+
__exportStar(require("./verbSchemas.js"), exports);
|
|
28
|
+
__exportStar(require("./verbWire.js"), exports);
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Canon agent verb contract — the canonical, runtime-agnostic vocabulary for
|
|
4
|
+
* the conversational/HITL actions an agent deliberately takes against Canon
|
|
5
|
+
* (v1 scope: messaging, HITL interactions, contact sharing, and the read
|
|
6
|
+
* verbs bindings need alongside them).
|
|
7
|
+
*
|
|
8
|
+
* One verb = one intent-level action. Each runtime binding (Hermes native
|
|
9
|
+
* tool, MCP server, codex dynamicTools, agent-sdk method, CLI) projects these
|
|
10
|
+
* verbs into its native tool surface; the names, argument shapes, limits, and
|
|
11
|
+
* result vocabularies defined here are the single source of truth. JSON
|
|
12
|
+
* Schemas for each verb live in `verbSchemas.ts` and are also emitted as a
|
|
13
|
+
* plain JSON artifact at build time (`dist/canon-verbs.schema.json`) so
|
|
14
|
+
* non-TypeScript consumers (the Python hermes plugin, external integrators)
|
|
15
|
+
* can consume the identical contract.
|
|
16
|
+
*
|
|
17
|
+
* Deliberately NOT verbs: replying in the active conversation, streaming
|
|
18
|
+
* partials, typing, and read receipts stay host-mediated — the model talks
|
|
19
|
+
* and the platform delivers. Still out of scope pending their own design
|
|
20
|
+
* pass: plan approval (the fourth runtime-interaction kind — coding-host
|
|
21
|
+
* concern today) and block/mute. Their REST surfaces remain directly
|
|
22
|
+
* callable.
|
|
23
|
+
*
|
|
24
|
+
* Scope note: this module DESCRIBES the contract (canonical shapes + the
|
|
25
|
+
* server-enforced limits, with enforcement sites cited). Enforcement itself
|
|
26
|
+
* stays where it runs today — functions/src. Server-side verb endpoints that
|
|
27
|
+
* validate against these schemas are a planned follow-up.
|
|
28
|
+
*
|
|
29
|
+
* Normativity: the JSON Schemas in `verbSchemas.ts` (and the emitted
|
|
30
|
+
* canon-verbs.schema.json) are the normative contract. The TypeScript types
|
|
31
|
+
* here are a convenience projection — corrections flow schema -> type, and
|
|
32
|
+
* the dual-witness fixtures in verbContract.test.ts (each fixture is both
|
|
33
|
+
* compile-checked against the type and validated against the schema) guard
|
|
34
|
+
* the two from drifting. Single-sourcing the types from the schemas is a
|
|
35
|
+
* planned follow-up.
|
|
36
|
+
*
|
|
37
|
+
* Byte-sensitive limits: JSON Schema `maxLength` counts UTF-16 code units,
|
|
38
|
+
* but several server limits count UTF-8 bytes or serialized-JSON length,
|
|
39
|
+
* which no standard keyword expresses. Bindings MUST run
|
|
40
|
+
* `findVerbByteLimitViolations()` (or equivalent checks from the emitted
|
|
41
|
+
* canon-verbs.limits.json) after schema validation.
|
|
42
|
+
*/
|
|
43
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
|
+
exports.CANON_VERB_LIMITS_ARTIFACT = exports.CREATE_GROUP_CREATOR_SETUP_REQUIRED_CODE = exports.CREATE_GROUP_NO_ADDABLE_MEMBERS_CODE = exports.CANON_VERB_NAMES = exports.SELF_CONTEXT_TYPE = exports.VERB_RATE_LIMITS = exports.VERB_LIMITS = exports.VERB_ID_PATTERNS = exports.CANON_CARD_SCHEMA_ID = exports.CANON_VERB_NAMESPACE = exports.CANON_VERBS_SCHEMA_ID = exports.CANON_VERBS_SCHEMA_VERSION = void 0;
|
|
45
|
+
exports.canonVerbToolName = canonVerbToolName;
|
|
46
|
+
exports.findVerbByteLimitViolations = findVerbByteLimitViolations;
|
|
47
|
+
/** Identifier for this contract document. */
|
|
48
|
+
exports.CANON_VERBS_SCHEMA_VERSION = 'canon.verbs.v1';
|
|
49
|
+
/** $id of the emitted JSON Schema bundle. */
|
|
50
|
+
exports.CANON_VERBS_SCHEMA_ID = 'https://canonmsg.com/schemas/canon.verbs.v1.json';
|
|
51
|
+
/** Namespace prefix bindings should use for flat tool names (e.g. `canon_send_to`). */
|
|
52
|
+
exports.CANON_VERB_NAMESPACE = 'canon';
|
|
53
|
+
/**
|
|
54
|
+
* $id of the canonical canon.card.v1 document schema
|
|
55
|
+
* (@canonmsg/rich-cards RUNTIME_CARD_JSON_SCHEMA_V1). The verbs bundle only
|
|
56
|
+
* validates the card ENVELOPE; compose the full document schema into card
|
|
57
|
+
* verbs via `getVerbInputSchema(verb, { cardSchema })`.
|
|
58
|
+
*/
|
|
59
|
+
exports.CANON_CARD_SCHEMA_ID = 'https://canonmsg.com/schemas/canon.card.v1.json';
|
|
60
|
+
/**
|
|
61
|
+
* Identifier patterns, mirrored from the enforcing sites:
|
|
62
|
+
* - RUNTIME_ID_PATTERN: conversation/input/approval ids —
|
|
63
|
+
* functions/src/utils/runtimeRequestHelpers.ts (`/^[A-Za-z0-9_.:-]{1,160}$/`)
|
|
64
|
+
* - CARD_ID_PATTERN / ACTION_ID_PATTERN: functions/src/api/interactionCard.ts
|
|
65
|
+
* and @canonmsg/rich-cards RUNTIME_CARD_ACTION_ID_PATTERN (80 chars)
|
|
66
|
+
* - QUESTION_ID_PATTERN: functions/src/api/interactionInput.ts (120 chars)
|
|
67
|
+
* - SESSION_RULE_TOOL_PATTERN: functions/src/callable/respondToInteraction.ts
|
|
68
|
+
*/
|
|
69
|
+
exports.VERB_ID_PATTERNS = {
|
|
70
|
+
runtimeId: '^[A-Za-z0-9_.:-]{1,160}$',
|
|
71
|
+
cardId: '^[A-Za-z0-9_.:-]{1,80}$',
|
|
72
|
+
actionId: '^[A-Za-z0-9_.:-]{1,80}$',
|
|
73
|
+
questionId: '^[A-Za-z0-9_.:-]{1,120}$',
|
|
74
|
+
sessionRuleToolPattern: '^[\\w.*:-]{1,128}$',
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* Server-enforced limits, single-sourced. Each value cites its enforcement
|
|
78
|
+
* site; keep the citation current when a limit moves.
|
|
79
|
+
*/
|
|
80
|
+
exports.VERB_LIMITS = {
|
|
81
|
+
/** Message text — UTF-8 bytes (functions/src/api/sendMessage.ts MAX_MESSAGE_TEXT_BYTES). */
|
|
82
|
+
messageTextBytes: 4096,
|
|
83
|
+
/**
|
|
84
|
+
* Serialized metadata JSON length in UTF-16 code units — the server checks
|
|
85
|
+
* JSON.stringify(metadata).length, not bytes (sendMessage.ts:716-724 inline;
|
|
86
|
+
* parseBody.ts maxJsonBytes despite the name).
|
|
87
|
+
*/
|
|
88
|
+
messageMetadataJsonChars: 4096,
|
|
89
|
+
/** Attachments per message (sendMessage.ts MAX_MESSAGE_ATTACHMENTS). */
|
|
90
|
+
messageAttachments: 10,
|
|
91
|
+
/** Client-supplied messageId — chars and UTF-8 bytes (sendMessage.ts). */
|
|
92
|
+
messageIdChars: 160,
|
|
93
|
+
messageIdBytes: 256,
|
|
94
|
+
/** Self-context note (functions/src/utils/selfContexts.ts SELF_CONTEXT_CONTEXT_LIMIT). */
|
|
95
|
+
selfContextChars: 1000,
|
|
96
|
+
/**
|
|
97
|
+
* Contact-request note. Values longer than this are truncated by senders
|
|
98
|
+
* (slice(0,497)+'...') — the truncation is currently triplicated in
|
|
99
|
+
* functions/src/api/sendContextualMessage.ts, packages/core/src/reach-out.ts
|
|
100
|
+
* and the hermes plugin; this constant is the canonical figure.
|
|
101
|
+
*/
|
|
102
|
+
contactRequestNoteChars: 500,
|
|
103
|
+
/** Group membership cap incl. creator (functions/src/utils/conversations.ts MAX_GROUP_MEMBERS). */
|
|
104
|
+
groupMembers: 50,
|
|
105
|
+
/** Runtime input (functions/src/api/interactionInput.ts). */
|
|
106
|
+
inputTitleChars: 160,
|
|
107
|
+
inputPromptChars: 4000,
|
|
108
|
+
inputChoices: 12,
|
|
109
|
+
inputChoiceLabelChars: 120,
|
|
110
|
+
inputChoiceValueChars: 200,
|
|
111
|
+
inputChoiceDescriptionChars: 300,
|
|
112
|
+
inputQuestions: 12,
|
|
113
|
+
inputQuestionChars: 1000,
|
|
114
|
+
inputQuestionHeaderChars: 120,
|
|
115
|
+
inputSecretNameChars: 160,
|
|
116
|
+
inputAnswerChars: 8192,
|
|
117
|
+
/** Approval (functions/src/api/interactionApproval.ts). */
|
|
118
|
+
toolNameChars: 128,
|
|
119
|
+
toolSummaryChars: 1000,
|
|
120
|
+
approvalDetails: 8,
|
|
121
|
+
approvalDetailLabelChars: 80,
|
|
122
|
+
approvalDetailValueChars: 500,
|
|
123
|
+
diffFiles: 100,
|
|
124
|
+
diffPathChars: 1024,
|
|
125
|
+
diffFileBytes: 24 * 1024,
|
|
126
|
+
diffTotalBytes: 96 * 1024,
|
|
127
|
+
/** Card envelope acceptance (functions/src/api/interactionCard.ts — server caps;
|
|
128
|
+
* authoring caps in @canonmsg/rich-cards are stricter: title 120, fallback 500, blocks 24). */
|
|
129
|
+
cardEnvelopeBytes: 32 * 1024,
|
|
130
|
+
cardServerTitleChars: 200,
|
|
131
|
+
cardServerFallbackTextChars: 2000,
|
|
132
|
+
cardServerBlocks: 64,
|
|
133
|
+
/** Response-values caps enforced on submit (callable respondToInteraction.ts
|
|
134
|
+
* MAX_VALUES_BYTES/MAX_VALUES_DEPTH; interactionCard.ts re-checks bytes on
|
|
135
|
+
* consume via MAX_REPLY_BYTES). */
|
|
136
|
+
cardValuesBytes: 8 * 1024,
|
|
137
|
+
cardValuesDepth: 8,
|
|
138
|
+
/** Native correlation metadata (functions/src/api/interactionKinds.ts normalizeNative). */
|
|
139
|
+
nativeKeys: 24,
|
|
140
|
+
nativeValueChars: 256,
|
|
141
|
+
nativeHandles: 16,
|
|
142
|
+
/** Deadlines (functions/src/utils/runtimeRequestHelpers.ts). */
|
|
143
|
+
minTimeoutMs: 1000,
|
|
144
|
+
/** input/card/plan ceiling (30 minutes). */
|
|
145
|
+
maxTimeoutMs: 30 * 60 * 1000,
|
|
146
|
+
/** approval-only ceiling (72 hours — owner ruling 2026-07-10). */
|
|
147
|
+
maxApprovalTimeoutMs: 72 * 60 * 60 * 1000,
|
|
148
|
+
/** turnId / runtimeId fields on interaction creators. */
|
|
149
|
+
turnIdChars: 128,
|
|
150
|
+
/** Reaction key (functions/src/api/reactToMessage.ts normalizeReactionKey). */
|
|
151
|
+
reactionEmojiChars: 64,
|
|
152
|
+
/**
|
|
153
|
+
* Group name authoring cap (enforced on rename via updateNameServer; group
|
|
154
|
+
* CREATE does not length-check today — treat as the authoring contract).
|
|
155
|
+
*/
|
|
156
|
+
groupNameChars: 100,
|
|
157
|
+
};
|
|
158
|
+
/**
|
|
159
|
+
* Sender-side rate limits enforced by POST /messages/send
|
|
160
|
+
* (functions/src/api/sendMessage.ts). Bindings should surface 429s with the
|
|
161
|
+
* retryAfter the server returns rather than re-deriving these.
|
|
162
|
+
*/
|
|
163
|
+
exports.VERB_RATE_LIMITS = {
|
|
164
|
+
senderMessagesPer5Min: 300,
|
|
165
|
+
conversationMessagesPer5Min: 120,
|
|
166
|
+
agentPeerMessagesPerHour: 30,
|
|
167
|
+
};
|
|
168
|
+
/** The one self-context type the platform accepts today. */
|
|
169
|
+
exports.SELF_CONTEXT_TYPE = 'cross_session';
|
|
170
|
+
/** Canonical verb names. */
|
|
171
|
+
exports.CANON_VERB_NAMES = [
|
|
172
|
+
'send_to',
|
|
173
|
+
'request_input',
|
|
174
|
+
'request_approval',
|
|
175
|
+
'check_approval',
|
|
176
|
+
'send_card',
|
|
177
|
+
'request_card',
|
|
178
|
+
'share_contact',
|
|
179
|
+
'react',
|
|
180
|
+
'forward',
|
|
181
|
+
'create_group',
|
|
182
|
+
'add_member',
|
|
183
|
+
'remove_member',
|
|
184
|
+
'leave_conversation',
|
|
185
|
+
'list_contacts',
|
|
186
|
+
'list_contact_requests',
|
|
187
|
+
'list_conversations',
|
|
188
|
+
];
|
|
189
|
+
/**
|
|
190
|
+
* Error code on the 400 a create_group receives when NO member is directly
|
|
191
|
+
* addable (approval-required members can only be invited to an existing
|
|
192
|
+
* group; a creator-only group is not created). The error detail carries the
|
|
193
|
+
* partition: pendingRequired[] and skipped[].
|
|
194
|
+
*/
|
|
195
|
+
exports.CREATE_GROUP_NO_ADDABLE_MEMBERS_CODE = 'CREATE_GROUP_NO_ADDABLE_MEMBERS';
|
|
196
|
+
/**
|
|
197
|
+
* Error code on the 403 a create_group receives when the CREATOR itself is
|
|
198
|
+
* a coding agent requiring explicit session setup: the group helper prepares
|
|
199
|
+
* session configs for every coding-agent member including the creator, and
|
|
200
|
+
* only the agent's human owner may provide them (v1 scoping — the owner
|
|
201
|
+
* creates the group from the app instead).
|
|
202
|
+
*/
|
|
203
|
+
exports.CREATE_GROUP_CREATOR_SETUP_REQUIRED_CODE = 'CREATE_GROUP_CREATOR_SETUP_REQUIRED';
|
|
204
|
+
/** Flat tool name for a verb on namespaced tool surfaces (e.g. `canon_send_to`). */
|
|
205
|
+
function canonVerbToolName(verb) {
|
|
206
|
+
return `${exports.CANON_VERB_NAMESPACE}_${verb}`;
|
|
207
|
+
}
|
|
208
|
+
const utf8Bytes = (value) => new TextEncoder().encode(value).length;
|
|
209
|
+
function checkTextBytes(path, value, into) {
|
|
210
|
+
if (typeof value === 'string' && utf8Bytes(value) > exports.VERB_LIMITS.messageTextBytes) {
|
|
211
|
+
into.push({
|
|
212
|
+
path,
|
|
213
|
+
message: `text exceeds ${exports.VERB_LIMITS.messageTextBytes} UTF-8 bytes (sendMessage.ts MAX_MESSAGE_TEXT_BYTES)`,
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
function checkMessageId(path, value, into) {
|
|
218
|
+
if (typeof value === 'string' && utf8Bytes(value) > exports.VERB_LIMITS.messageIdBytes) {
|
|
219
|
+
into.push({
|
|
220
|
+
path,
|
|
221
|
+
message: `messageId exceeds ${exports.VERB_LIMITS.messageIdBytes} UTF-8 bytes (sendMessage.ts MAX_MESSAGE_ID_BYTES)`,
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* The server limits JSON Schema cannot express: UTF-8 byte caps and
|
|
227
|
+
* serialized-JSON length caps. Bindings MUST run this after schema
|
|
228
|
+
* validation; the server enforces the same checks with 400s.
|
|
229
|
+
*/
|
|
230
|
+
function findVerbByteLimitViolations(verb, input) {
|
|
231
|
+
const violations = [];
|
|
232
|
+
if (verb === 'send_to' || verb === 'share_contact' || verb === 'forward') {
|
|
233
|
+
checkTextBytes('text', input.text, violations);
|
|
234
|
+
}
|
|
235
|
+
if (verb === 'share_contact') {
|
|
236
|
+
checkMessageId('messageId', input.messageId, violations);
|
|
237
|
+
}
|
|
238
|
+
if (verb === 'send_to') {
|
|
239
|
+
const options = input.messageOptions;
|
|
240
|
+
if (options && typeof options === 'object' && !Array.isArray(options)) {
|
|
241
|
+
const record = options;
|
|
242
|
+
checkMessageId('messageOptions.messageId', record.messageId, violations);
|
|
243
|
+
if (record.metadata !== undefined) {
|
|
244
|
+
const serialized = JSON.stringify(record.metadata);
|
|
245
|
+
if (typeof serialized === 'string' && serialized.length > exports.VERB_LIMITS.messageMetadataJsonChars) {
|
|
246
|
+
violations.push({
|
|
247
|
+
path: 'messageOptions.metadata',
|
|
248
|
+
message: `metadata serializes to more than ${exports.VERB_LIMITS.messageMetadataJsonChars} JSON characters `
|
|
249
|
+
+ '(sendMessage.ts checks JSON.stringify length)',
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
if (verb === 'send_card' || verb === 'request_card') {
|
|
256
|
+
if (input.card !== undefined) {
|
|
257
|
+
const serialized = JSON.stringify(input.card);
|
|
258
|
+
if (typeof serialized === 'string' && utf8Bytes(serialized) > exports.VERB_LIMITS.cardEnvelopeBytes) {
|
|
259
|
+
violations.push({
|
|
260
|
+
path: 'card',
|
|
261
|
+
message: `card serializes to more than ${exports.VERB_LIMITS.cardEnvelopeBytes} bytes (interactionCard.ts MAX_CARD_BYTES)`,
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
return violations;
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Machine-readable limits companion to the schema bundle, emitted as
|
|
270
|
+
* dist/canon-verbs.limits.json so non-TypeScript bindings can apply the
|
|
271
|
+
* byte-sensitive checks JSON Schema cannot express.
|
|
272
|
+
*/
|
|
273
|
+
exports.CANON_VERB_LIMITS_ARTIFACT = {
|
|
274
|
+
schemaVersion: exports.CANON_VERBS_SCHEMA_VERSION,
|
|
275
|
+
limits: exports.VERB_LIMITS,
|
|
276
|
+
rateLimits: exports.VERB_RATE_LIMITS,
|
|
277
|
+
idPatterns: exports.VERB_ID_PATTERNS,
|
|
278
|
+
byteSemantics: {
|
|
279
|
+
'send_to.text': 'utf8_bytes<=messageTextBytes',
|
|
280
|
+
'share_contact.text': 'utf8_bytes<=messageTextBytes',
|
|
281
|
+
'forward.text': 'utf8_bytes<=messageTextBytes',
|
|
282
|
+
'send_to.messageOptions.messageId': 'utf8_bytes<=messageIdBytes',
|
|
283
|
+
'share_contact.messageId': 'utf8_bytes<=messageIdBytes',
|
|
284
|
+
'send_to.messageOptions.metadata': 'json_stringify_chars<=messageMetadataJsonChars',
|
|
285
|
+
'send_card.card': 'json_utf8_bytes<=cardEnvelopeBytes',
|
|
286
|
+
'request_card.card': 'json_utf8_bytes<=cardEnvelopeBytes',
|
|
287
|
+
},
|
|
288
|
+
};
|