@canonmsg/backend-contracts 6.3.0 → 6.4.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/README.md +1 -1
- package/dist/canon-verb-wire.schema.json +6 -0
- package/dist/canon-verbs.schema.json +61 -4
- package/dist/cjs/contactRequest.js +56 -7
- package/dist/cjs/verbContract.js +1 -0
- package/dist/cjs/verbSchemas.js +40 -6
- package/dist/cjs/verbWire.js +29 -3
- package/dist/contactRequest.d.ts +21 -7
- package/dist/contactRequest.js +54 -7
- package/dist/verbContract.d.ts +23 -7
- package/dist/verbContract.js +1 -0
- package/dist/verbSchemas.d.ts +42 -3
- package/dist/verbSchemas.js +40 -6
- package/dist/verbWire.d.ts +8 -2
- package/dist/verbWire.js +29 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ Node.js 18+. Ships both ESM and CommonJS builds — Cloud Functions consume the
|
|
|
16
16
|
|
|
17
17
|
## What is in it
|
|
18
18
|
|
|
19
|
-
**The verb contract.** `canon.verbs.v1` (`verbContract.ts`) is the plaintext *intent* schema —
|
|
19
|
+
**The verb contract.** `canon.verbs.v1` (`verbContract.ts`) is the plaintext *intent* schema — eighteen verbs, their input and result schemas, byte limits, and rate limits. `canon.verb-wire.v1` (`verbWire.ts`) is what actually crosses the network: a server-readable envelope plus a body that is either `{ encoding: 'json', value }` or `{ encoding: 'mls', … }`. `projectVerbIntentToWire` and `mergeVerbWireToIntent` are the two halves of that split, so bindings and the server never disagree about which fields are envelope and which are content.
|
|
20
20
|
|
|
21
21
|
```ts
|
|
22
22
|
import {
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
"list_contacts",
|
|
34
34
|
"list_contact_requests",
|
|
35
35
|
"list_conversations",
|
|
36
|
+
"cancel_contact_request",
|
|
36
37
|
"no_reply"
|
|
37
38
|
]
|
|
38
39
|
},
|
|
@@ -427,6 +428,10 @@
|
|
|
427
428
|
"null"
|
|
428
429
|
]
|
|
429
430
|
},
|
|
431
|
+
"sourceMessageId": {
|
|
432
|
+
"type": "string",
|
|
433
|
+
"minLength": 1
|
|
434
|
+
},
|
|
430
435
|
"turnSemantics": {
|
|
431
436
|
"enum": [
|
|
432
437
|
"progress",
|
|
@@ -508,6 +513,7 @@
|
|
|
508
513
|
"list_contacts",
|
|
509
514
|
"list_contact_requests",
|
|
510
515
|
"list_conversations",
|
|
516
|
+
"cancel_contact_request",
|
|
511
517
|
"no_reply"
|
|
512
518
|
]
|
|
513
519
|
},
|
|
@@ -1767,11 +1767,26 @@
|
|
|
1767
1767
|
"list_contact_requests_input": {
|
|
1768
1768
|
"type": "object",
|
|
1769
1769
|
"additionalProperties": false,
|
|
1770
|
-
"properties": {
|
|
1770
|
+
"properties": {
|
|
1771
|
+
"direction": {
|
|
1772
|
+
"enum": [
|
|
1773
|
+
"inbound",
|
|
1774
|
+
"outbound"
|
|
1775
|
+
]
|
|
1776
|
+
},
|
|
1777
|
+
"includeResolved": {
|
|
1778
|
+
"type": "boolean"
|
|
1779
|
+
},
|
|
1780
|
+
"limit": {
|
|
1781
|
+
"type": "integer",
|
|
1782
|
+
"minimum": 1,
|
|
1783
|
+
"maximum": 100
|
|
1784
|
+
}
|
|
1785
|
+
}
|
|
1771
1786
|
},
|
|
1772
1787
|
"list_contact_requests_result": {
|
|
1773
1788
|
"type": "object",
|
|
1774
|
-
"description": "
|
|
1789
|
+
"description": "Contact requests, newest first, capped at 100. Defaults to pending inbound; requesters use direction=outbound with includeResolved=true to recover lifecycle state. Items are SerializedContactRequest (backend-contracts contactRequest.ts).",
|
|
1775
1790
|
"required": [
|
|
1776
1791
|
"requests"
|
|
1777
1792
|
],
|
|
@@ -1786,7 +1801,8 @@
|
|
|
1786
1801
|
"requesterId",
|
|
1787
1802
|
"targetId",
|
|
1788
1803
|
"status",
|
|
1789
|
-
"kind"
|
|
1804
|
+
"kind",
|
|
1805
|
+
"phase"
|
|
1790
1806
|
],
|
|
1791
1807
|
"additionalProperties": true,
|
|
1792
1808
|
"properties": {
|
|
@@ -1807,7 +1823,8 @@
|
|
|
1807
1823
|
"pending",
|
|
1808
1824
|
"approved",
|
|
1809
1825
|
"rejected",
|
|
1810
|
-
"expired"
|
|
1826
|
+
"expired",
|
|
1827
|
+
"cancelled"
|
|
1811
1828
|
]
|
|
1812
1829
|
},
|
|
1813
1830
|
"kind": {
|
|
@@ -1816,6 +1833,17 @@
|
|
|
1816
1833
|
"group_invite"
|
|
1817
1834
|
]
|
|
1818
1835
|
},
|
|
1836
|
+
"phase": {
|
|
1837
|
+
"enum": [
|
|
1838
|
+
"awaiting_owner",
|
|
1839
|
+
"starting",
|
|
1840
|
+
"connected",
|
|
1841
|
+
"rejected",
|
|
1842
|
+
"expired",
|
|
1843
|
+
"cancelled",
|
|
1844
|
+
"failed"
|
|
1845
|
+
]
|
|
1846
|
+
},
|
|
1819
1847
|
"message": {
|
|
1820
1848
|
"type": [
|
|
1821
1849
|
"string",
|
|
@@ -1949,6 +1977,35 @@
|
|
|
1949
1977
|
}
|
|
1950
1978
|
}
|
|
1951
1979
|
},
|
|
1980
|
+
"cancel_contact_request_input": {
|
|
1981
|
+
"type": "object",
|
|
1982
|
+
"required": [
|
|
1983
|
+
"requestId"
|
|
1984
|
+
],
|
|
1985
|
+
"additionalProperties": false,
|
|
1986
|
+
"properties": {
|
|
1987
|
+
"requestId": {
|
|
1988
|
+
"type": "string",
|
|
1989
|
+
"pattern": "^[A-Za-z0-9_.:-]{1,160}$"
|
|
1990
|
+
}
|
|
1991
|
+
}
|
|
1992
|
+
},
|
|
1993
|
+
"cancel_contact_request_result": {
|
|
1994
|
+
"type": "object",
|
|
1995
|
+
"required": [
|
|
1996
|
+
"status",
|
|
1997
|
+
"requestId"
|
|
1998
|
+
],
|
|
1999
|
+
"additionalProperties": true,
|
|
2000
|
+
"properties": {
|
|
2001
|
+
"status": {
|
|
2002
|
+
"const": "cancelled"
|
|
2003
|
+
},
|
|
2004
|
+
"requestId": {
|
|
2005
|
+
"type": "string"
|
|
2006
|
+
}
|
|
2007
|
+
}
|
|
2008
|
+
},
|
|
1952
2009
|
"no_reply_input": {
|
|
1953
2010
|
"type": "object",
|
|
1954
2011
|
"description": "End this turn without posting anything to the conversation. Nothing is rendered and no other member or agent is triggered.",
|
|
@@ -1,18 +1,29 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.readContactRequestRequirements = readContactRequestRequirements;
|
|
3
4
|
exports.readGroupInviteRequirements = readGroupInviteRequirements;
|
|
5
|
+
exports.deriveContactRequestPhase = deriveContactRequestPhase;
|
|
4
6
|
exports.serializeContactRequest = serializeContactRequest;
|
|
5
|
-
function
|
|
7
|
+
function readContactRequestRequirements(value) {
|
|
6
8
|
const record = isRecord(value) ? value : null;
|
|
7
9
|
if (typeof record?.policyApproval !== 'boolean'
|
|
8
10
|
|| typeof record.ownerSessionSetup !== 'boolean') {
|
|
9
|
-
throw new TypeError('Invalid
|
|
11
|
+
throw new TypeError('Invalid contact request requirements');
|
|
10
12
|
}
|
|
11
13
|
return {
|
|
12
14
|
policyApproval: record.policyApproval,
|
|
13
15
|
ownerSessionSetup: record.ownerSessionSetup,
|
|
14
16
|
};
|
|
15
17
|
}
|
|
18
|
+
/** Backward-compatible parser retained for existing group invite clients. */
|
|
19
|
+
function readGroupInviteRequirements(value) {
|
|
20
|
+
try {
|
|
21
|
+
return readContactRequestRequirements(value);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
throw new TypeError('Invalid group invite requirements');
|
|
25
|
+
}
|
|
26
|
+
}
|
|
16
27
|
function isRecord(value) {
|
|
17
28
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
18
29
|
}
|
|
@@ -30,12 +41,36 @@ function normalizeStatus(value) {
|
|
|
30
41
|
if (value === 'pending'
|
|
31
42
|
|| value === 'approved'
|
|
32
43
|
|| value === 'rejected'
|
|
33
|
-
|| value === 'expired'
|
|
44
|
+
|| value === 'expired'
|
|
45
|
+
|| value === 'cancelled') {
|
|
34
46
|
return value;
|
|
35
47
|
}
|
|
36
48
|
return 'pending';
|
|
37
49
|
}
|
|
38
|
-
function
|
|
50
|
+
function deriveContactRequestPhase(data) {
|
|
51
|
+
const status = data.status;
|
|
52
|
+
const openingStatus = data.openingMessageStatus;
|
|
53
|
+
let phase;
|
|
54
|
+
if (status === 'cancelled')
|
|
55
|
+
phase = 'cancelled';
|
|
56
|
+
else if (status === 'rejected')
|
|
57
|
+
phase = 'rejected';
|
|
58
|
+
else if (status === 'expired')
|
|
59
|
+
phase = 'expired';
|
|
60
|
+
else if (status === 'delivery_failed' || openingStatus === 'failed')
|
|
61
|
+
phase = 'failed';
|
|
62
|
+
else if (status === 'approved')
|
|
63
|
+
phase = 'connected';
|
|
64
|
+
else if (status === 'delivery_pending'
|
|
65
|
+
|| openingStatus === 'ready'
|
|
66
|
+
|| openingStatus === 'delivering'
|
|
67
|
+
|| openingStatus === 'retryable')
|
|
68
|
+
phase = 'starting';
|
|
69
|
+
else
|
|
70
|
+
phase = 'awaiting_owner';
|
|
71
|
+
return phase;
|
|
72
|
+
}
|
|
73
|
+
function serializeContactRequest(requestId, data, options = {}) {
|
|
39
74
|
if (typeof data.approverId !== 'string' || data.approverId.length === 0) {
|
|
40
75
|
return null;
|
|
41
76
|
}
|
|
@@ -92,21 +127,35 @@ function serializeContactRequest(requestId, data) {
|
|
|
92
127
|
message: null,
|
|
93
128
|
status: normalizeStatus(data.status),
|
|
94
129
|
kind: kindValue,
|
|
130
|
+
phase: deriveContactRequestPhase(data),
|
|
95
131
|
createdAt: normalizeTimestamp(data.createdAt),
|
|
96
132
|
resolvedAt: normalizeTimestamp(data.resolvedAt),
|
|
97
133
|
expiresAt: normalizeTimestamp(data.expiresAt),
|
|
98
134
|
};
|
|
99
|
-
if (groupContext) {
|
|
135
|
+
if (groupContext || kindValue === 'dm') {
|
|
100
136
|
let requirements;
|
|
101
137
|
try {
|
|
102
|
-
requirements =
|
|
138
|
+
requirements = data.requirements === undefined && kindValue === 'dm'
|
|
139
|
+
? { policyApproval: true, ownerSessionSetup: false }
|
|
140
|
+
: readContactRequestRequirements(data.requirements);
|
|
103
141
|
}
|
|
104
142
|
catch {
|
|
105
143
|
return null;
|
|
106
144
|
}
|
|
107
|
-
payload.groupContext = groupContext;
|
|
108
145
|
payload.requirements = requirements;
|
|
109
146
|
}
|
|
147
|
+
if (groupContext)
|
|
148
|
+
payload.groupContext = groupContext;
|
|
149
|
+
if (options.audience === 'requester') {
|
|
150
|
+
if (typeof data.sourceConversationId === 'string' && data.sourceConversationId.length > 0) {
|
|
151
|
+
payload.sourceConversationId = data.sourceConversationId;
|
|
152
|
+
}
|
|
153
|
+
if (payload.phase === 'connected'
|
|
154
|
+
&& typeof data.openingMessageConversationId === 'string'
|
|
155
|
+
&& data.openingMessageConversationId.length > 0) {
|
|
156
|
+
payload.conversationId = data.openingMessageConversationId;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
110
159
|
if (data.targetUserType === 'ai_agent') {
|
|
111
160
|
payload.targetOwnerId = data.targetOwnerId;
|
|
112
161
|
}
|
package/dist/cjs/verbContract.js
CHANGED
package/dist/cjs/verbSchemas.js
CHANGED
|
@@ -1004,13 +1004,17 @@ const list_contacts_result = {
|
|
|
1004
1004
|
const list_contact_requests_input = {
|
|
1005
1005
|
type: 'object',
|
|
1006
1006
|
additionalProperties: false,
|
|
1007
|
-
properties: {
|
|
1007
|
+
properties: {
|
|
1008
|
+
direction: { enum: ['inbound', 'outbound'] },
|
|
1009
|
+
includeResolved: { type: 'boolean' },
|
|
1010
|
+
limit: { type: 'integer', minimum: 1, maximum: 100 },
|
|
1011
|
+
},
|
|
1008
1012
|
};
|
|
1009
1013
|
const list_contact_requests_result = {
|
|
1010
1014
|
type: 'object',
|
|
1011
|
-
description: '
|
|
1012
|
-
+ '
|
|
1013
|
-
+
|
|
1015
|
+
description: 'Contact requests, newest first, capped at 100. Defaults to pending inbound; '
|
|
1016
|
+
+ 'requesters use direction=outbound with includeResolved=true to recover lifecycle state. '
|
|
1017
|
+
+ 'Items are SerializedContactRequest (backend-contracts contactRequest.ts).',
|
|
1014
1018
|
required: ['requests'],
|
|
1015
1019
|
additionalProperties: true,
|
|
1016
1020
|
properties: {
|
|
@@ -1018,15 +1022,26 @@ const list_contact_requests_result = {
|
|
|
1018
1022
|
type: 'array',
|
|
1019
1023
|
items: {
|
|
1020
1024
|
type: 'object',
|
|
1021
|
-
required: ['id', 'requesterId', 'targetId', 'status', 'kind'],
|
|
1025
|
+
required: ['id', 'requesterId', 'targetId', 'status', 'kind', 'phase'],
|
|
1022
1026
|
additionalProperties: true,
|
|
1023
1027
|
properties: {
|
|
1024
1028
|
id: { type: 'string' },
|
|
1025
1029
|
requesterId: { type: 'string' },
|
|
1026
1030
|
requesterName: { type: 'string' },
|
|
1027
1031
|
targetId: { type: 'string' },
|
|
1028
|
-
status: { enum: ['pending', 'approved', 'rejected', 'expired'] },
|
|
1032
|
+
status: { enum: ['pending', 'approved', 'rejected', 'expired', 'cancelled'] },
|
|
1029
1033
|
kind: { enum: ['dm', 'group_invite'] },
|
|
1034
|
+
phase: {
|
|
1035
|
+
enum: [
|
|
1036
|
+
'awaiting_owner',
|
|
1037
|
+
'starting',
|
|
1038
|
+
'connected',
|
|
1039
|
+
'rejected',
|
|
1040
|
+
'expired',
|
|
1041
|
+
'cancelled',
|
|
1042
|
+
'failed',
|
|
1043
|
+
],
|
|
1044
|
+
},
|
|
1030
1045
|
message: { type: ['string', 'null'] },
|
|
1031
1046
|
createdAt: { type: ['string', 'null'] },
|
|
1032
1047
|
expiresAt: { type: ['string', 'null'] },
|
|
@@ -1035,6 +1050,23 @@ const list_contact_requests_result = {
|
|
|
1035
1050
|
},
|
|
1036
1051
|
},
|
|
1037
1052
|
};
|
|
1053
|
+
const cancel_contact_request_input = {
|
|
1054
|
+
type: 'object',
|
|
1055
|
+
required: ['requestId'],
|
|
1056
|
+
additionalProperties: false,
|
|
1057
|
+
properties: {
|
|
1058
|
+
requestId: { type: 'string', pattern: verbContract_js_1.VERB_ID_PATTERNS.runtimeId },
|
|
1059
|
+
},
|
|
1060
|
+
};
|
|
1061
|
+
const cancel_contact_request_result = {
|
|
1062
|
+
type: 'object',
|
|
1063
|
+
required: ['status', 'requestId'],
|
|
1064
|
+
additionalProperties: true,
|
|
1065
|
+
properties: {
|
|
1066
|
+
status: { const: 'cancelled' },
|
|
1067
|
+
requestId: { type: 'string' },
|
|
1068
|
+
},
|
|
1069
|
+
};
|
|
1038
1070
|
const list_conversations_input = {
|
|
1039
1071
|
type: 'object',
|
|
1040
1072
|
additionalProperties: false,
|
|
@@ -1174,6 +1206,8 @@ exports.CANON_VERBS_JSON_SCHEMA = {
|
|
|
1174
1206
|
list_contact_requests_result,
|
|
1175
1207
|
list_conversations_input,
|
|
1176
1208
|
list_conversations_result,
|
|
1209
|
+
cancel_contact_request_input,
|
|
1210
|
+
cancel_contact_request_result,
|
|
1177
1211
|
no_reply_input,
|
|
1178
1212
|
no_reply_result,
|
|
1179
1213
|
},
|
package/dist/cjs/verbWire.js
CHANGED
|
@@ -118,6 +118,7 @@ exports.VERB_WIRE_ENVELOPE_FIELDS = {
|
|
|
118
118
|
list_contacts: { required: [], optional: [] },
|
|
119
119
|
list_contact_requests: { required: [], optional: [] },
|
|
120
120
|
list_conversations: { required: [], optional: ['limit'] },
|
|
121
|
+
cancel_contact_request: { required: ['requestId'], optional: [] },
|
|
121
122
|
no_reply: { required: [], optional: ['conversationId', 'messageId'] },
|
|
122
123
|
};
|
|
123
124
|
// ---------------------------------------------------------------------------
|
|
@@ -159,6 +160,7 @@ const wireTurnDef = {
|
|
|
159
160
|
additionalProperties: false,
|
|
160
161
|
properties: {
|
|
161
162
|
turnId: { type: ['string', 'null'] },
|
|
163
|
+
sourceMessageId: { type: 'string', minLength: 1 },
|
|
162
164
|
turnSemantics: { enum: ['progress', 'turn_complete', 'control'] },
|
|
163
165
|
deliveryIntent: { enum: ['queue', 'interrupt', 'interleave', 'stop'] },
|
|
164
166
|
replyBehavior: { enum: ['allow_auto_reply', 'suppress_auto_reply'] },
|
|
@@ -284,7 +286,13 @@ exports.CANON_VERB_WIRE_JSON_SCHEMA = {
|
|
|
284
286
|
// ---------------------------------------------------------------------------
|
|
285
287
|
// Intent <-> wire projection (json codec)
|
|
286
288
|
// ---------------------------------------------------------------------------
|
|
287
|
-
const TURN_KEYS = [
|
|
289
|
+
const TURN_KEYS = [
|
|
290
|
+
'turnId',
|
|
291
|
+
'sourceMessageId',
|
|
292
|
+
'turnSemantics',
|
|
293
|
+
'deliveryIntent',
|
|
294
|
+
'replyBehavior',
|
|
295
|
+
];
|
|
288
296
|
function splitTurnMetadata(metadata) {
|
|
289
297
|
if (!metadata || typeof metadata !== 'object')
|
|
290
298
|
return { turn: undefined, rest: undefined };
|
|
@@ -469,14 +477,25 @@ function projectVerbIntentToWire(verb, intent, options) {
|
|
|
469
477
|
envelope = compact({ conversationId: input.conversationId });
|
|
470
478
|
break;
|
|
471
479
|
}
|
|
472
|
-
case 'list_contacts':
|
|
480
|
+
case 'list_contacts': {
|
|
481
|
+
break;
|
|
482
|
+
}
|
|
473
483
|
case 'list_contact_requests': {
|
|
484
|
+
value = compact({
|
|
485
|
+
direction: input.direction,
|
|
486
|
+
includeResolved: input.includeResolved,
|
|
487
|
+
limit: input.limit,
|
|
488
|
+
});
|
|
474
489
|
break;
|
|
475
490
|
}
|
|
476
491
|
case 'list_conversations': {
|
|
477
492
|
envelope = compact({ limit: input.limit });
|
|
478
493
|
break;
|
|
479
494
|
}
|
|
495
|
+
case 'cancel_contact_request': {
|
|
496
|
+
envelope = compact({ requestId: input.requestId });
|
|
497
|
+
break;
|
|
498
|
+
}
|
|
480
499
|
case 'no_reply': {
|
|
481
500
|
envelope = compact({ conversationId: input.conversationId, messageId: input.messageId });
|
|
482
501
|
value = compact({ reason: input.reason });
|
|
@@ -615,10 +634,17 @@ function mergeVerbWireToIntent(request) {
|
|
|
615
634
|
case 'leave_conversation':
|
|
616
635
|
return compact({ conversationId: envelope.conversationId });
|
|
617
636
|
case 'list_contacts':
|
|
618
|
-
case 'list_contact_requests':
|
|
619
637
|
return {};
|
|
638
|
+
case 'list_contact_requests':
|
|
639
|
+
return compact({
|
|
640
|
+
direction: value.direction,
|
|
641
|
+
includeResolved: value.includeResolved,
|
|
642
|
+
limit: value.limit,
|
|
643
|
+
});
|
|
620
644
|
case 'list_conversations':
|
|
621
645
|
return compact({ limit: envelope.limit });
|
|
646
|
+
case 'cancel_contact_request':
|
|
647
|
+
return compact({ requestId: envelope.requestId });
|
|
622
648
|
case 'no_reply':
|
|
623
649
|
return compact({ conversationId: envelope.conversationId, messageId: envelope.messageId, reason: value.reason });
|
|
624
650
|
}
|
package/dist/contactRequest.d.ts
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
|
-
export type SerializedContactRequestStatus = 'pending' | 'approved' | 'rejected' | 'expired';
|
|
1
|
+
export type SerializedContactRequestStatus = 'pending' | 'approved' | 'rejected' | 'expired' | 'cancelled';
|
|
2
|
+
export type ContactRequestLifecyclePhase = 'awaiting_owner' | 'starting' | 'connected' | 'rejected' | 'expired' | 'cancelled' | 'failed';
|
|
2
3
|
/**
|
|
3
|
-
* Independent gates that must be satisfied before a pending
|
|
4
|
-
*
|
|
4
|
+
* Independent gates that must be satisfied before a pending contact request
|
|
5
|
+
* can activate. DM introductions and group invites share this owner-review
|
|
6
|
+
* vocabulary even though their activation pipelines remain separate.
|
|
5
7
|
*/
|
|
6
|
-
export interface
|
|
8
|
+
export interface ContactRequestRequirements {
|
|
7
9
|
policyApproval: boolean;
|
|
8
10
|
ownerSessionSetup: boolean;
|
|
9
11
|
}
|
|
12
|
+
/** Backward-compatible name retained for existing group invite clients. */
|
|
13
|
+
export type GroupInviteRequirements = ContactRequestRequirements;
|
|
14
|
+
export declare function readContactRequestRequirements(value: unknown): ContactRequestRequirements;
|
|
15
|
+
/** Backward-compatible parser retained for existing group invite clients. */
|
|
10
16
|
export declare function readGroupInviteRequirements(value: unknown): GroupInviteRequirements;
|
|
11
17
|
export interface SerializedContactRequest {
|
|
12
18
|
id: string;
|
|
@@ -27,10 +33,18 @@ export interface SerializedContactRequest {
|
|
|
27
33
|
conversationId: string;
|
|
28
34
|
groupName: string | null;
|
|
29
35
|
};
|
|
30
|
-
/** Present for
|
|
31
|
-
requirements?:
|
|
36
|
+
/** Present for group invites and setup/policy-aware DM introductions. */
|
|
37
|
+
requirements?: ContactRequestRequirements;
|
|
38
|
+
phase: ContactRequestLifecyclePhase;
|
|
39
|
+
/** Requester-only source lane for an opener-backed introduction. */
|
|
40
|
+
sourceConversationId?: string;
|
|
41
|
+
/** Requester-only destination, present after an opener-backed DM connects. */
|
|
42
|
+
conversationId?: string;
|
|
32
43
|
createdAt: string | null;
|
|
33
44
|
resolvedAt?: string | null;
|
|
34
45
|
expiresAt?: string | null;
|
|
35
46
|
}
|
|
36
|
-
export declare function
|
|
47
|
+
export declare function deriveContactRequestPhase(data: Record<string, unknown>): ContactRequestLifecyclePhase;
|
|
48
|
+
export declare function serializeContactRequest(requestId: string, data: Record<string, unknown>, options?: {
|
|
49
|
+
audience?: 'inbound' | 'requester';
|
|
50
|
+
}): SerializedContactRequest | null;
|
package/dist/contactRequest.js
CHANGED
|
@@ -1,14 +1,23 @@
|
|
|
1
|
-
export function
|
|
1
|
+
export function readContactRequestRequirements(value) {
|
|
2
2
|
const record = isRecord(value) ? value : null;
|
|
3
3
|
if (typeof record?.policyApproval !== 'boolean'
|
|
4
4
|
|| typeof record.ownerSessionSetup !== 'boolean') {
|
|
5
|
-
throw new TypeError('Invalid
|
|
5
|
+
throw new TypeError('Invalid contact request requirements');
|
|
6
6
|
}
|
|
7
7
|
return {
|
|
8
8
|
policyApproval: record.policyApproval,
|
|
9
9
|
ownerSessionSetup: record.ownerSessionSetup,
|
|
10
10
|
};
|
|
11
11
|
}
|
|
12
|
+
/** Backward-compatible parser retained for existing group invite clients. */
|
|
13
|
+
export function readGroupInviteRequirements(value) {
|
|
14
|
+
try {
|
|
15
|
+
return readContactRequestRequirements(value);
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
throw new TypeError('Invalid group invite requirements');
|
|
19
|
+
}
|
|
20
|
+
}
|
|
12
21
|
function isRecord(value) {
|
|
13
22
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
14
23
|
}
|
|
@@ -26,12 +35,36 @@ function normalizeStatus(value) {
|
|
|
26
35
|
if (value === 'pending'
|
|
27
36
|
|| value === 'approved'
|
|
28
37
|
|| value === 'rejected'
|
|
29
|
-
|| value === 'expired'
|
|
38
|
+
|| value === 'expired'
|
|
39
|
+
|| value === 'cancelled') {
|
|
30
40
|
return value;
|
|
31
41
|
}
|
|
32
42
|
return 'pending';
|
|
33
43
|
}
|
|
34
|
-
export function
|
|
44
|
+
export function deriveContactRequestPhase(data) {
|
|
45
|
+
const status = data.status;
|
|
46
|
+
const openingStatus = data.openingMessageStatus;
|
|
47
|
+
let phase;
|
|
48
|
+
if (status === 'cancelled')
|
|
49
|
+
phase = 'cancelled';
|
|
50
|
+
else if (status === 'rejected')
|
|
51
|
+
phase = 'rejected';
|
|
52
|
+
else if (status === 'expired')
|
|
53
|
+
phase = 'expired';
|
|
54
|
+
else if (status === 'delivery_failed' || openingStatus === 'failed')
|
|
55
|
+
phase = 'failed';
|
|
56
|
+
else if (status === 'approved')
|
|
57
|
+
phase = 'connected';
|
|
58
|
+
else if (status === 'delivery_pending'
|
|
59
|
+
|| openingStatus === 'ready'
|
|
60
|
+
|| openingStatus === 'delivering'
|
|
61
|
+
|| openingStatus === 'retryable')
|
|
62
|
+
phase = 'starting';
|
|
63
|
+
else
|
|
64
|
+
phase = 'awaiting_owner';
|
|
65
|
+
return phase;
|
|
66
|
+
}
|
|
67
|
+
export function serializeContactRequest(requestId, data, options = {}) {
|
|
35
68
|
if (typeof data.approverId !== 'string' || data.approverId.length === 0) {
|
|
36
69
|
return null;
|
|
37
70
|
}
|
|
@@ -88,21 +121,35 @@ export function serializeContactRequest(requestId, data) {
|
|
|
88
121
|
message: null,
|
|
89
122
|
status: normalizeStatus(data.status),
|
|
90
123
|
kind: kindValue,
|
|
124
|
+
phase: deriveContactRequestPhase(data),
|
|
91
125
|
createdAt: normalizeTimestamp(data.createdAt),
|
|
92
126
|
resolvedAt: normalizeTimestamp(data.resolvedAt),
|
|
93
127
|
expiresAt: normalizeTimestamp(data.expiresAt),
|
|
94
128
|
};
|
|
95
|
-
if (groupContext) {
|
|
129
|
+
if (groupContext || kindValue === 'dm') {
|
|
96
130
|
let requirements;
|
|
97
131
|
try {
|
|
98
|
-
requirements =
|
|
132
|
+
requirements = data.requirements === undefined && kindValue === 'dm'
|
|
133
|
+
? { policyApproval: true, ownerSessionSetup: false }
|
|
134
|
+
: readContactRequestRequirements(data.requirements);
|
|
99
135
|
}
|
|
100
136
|
catch {
|
|
101
137
|
return null;
|
|
102
138
|
}
|
|
103
|
-
payload.groupContext = groupContext;
|
|
104
139
|
payload.requirements = requirements;
|
|
105
140
|
}
|
|
141
|
+
if (groupContext)
|
|
142
|
+
payload.groupContext = groupContext;
|
|
143
|
+
if (options.audience === 'requester') {
|
|
144
|
+
if (typeof data.sourceConversationId === 'string' && data.sourceConversationId.length > 0) {
|
|
145
|
+
payload.sourceConversationId = data.sourceConversationId;
|
|
146
|
+
}
|
|
147
|
+
if (payload.phase === 'connected'
|
|
148
|
+
&& typeof data.openingMessageConversationId === 'string'
|
|
149
|
+
&& data.openingMessageConversationId.length > 0) {
|
|
150
|
+
payload.conversationId = data.openingMessageConversationId;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
106
153
|
if (data.targetUserType === 'ai_agent') {
|
|
107
154
|
payload.targetOwnerId = data.targetOwnerId;
|
|
108
155
|
}
|
package/dist/verbContract.d.ts
CHANGED
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
* `findVerbByteLimitViolations()` (or equivalent checks from the emitted
|
|
43
43
|
* canon-verbs.limits.json) after schema validation.
|
|
44
44
|
*/
|
|
45
|
-
import type {
|
|
45
|
+
import type { ContactRequestRequirements } from './contactRequest.js';
|
|
46
46
|
/** Identifier for this contract document. */
|
|
47
47
|
export declare const CANON_VERBS_SCHEMA_VERSION = "canon.verbs.v1";
|
|
48
48
|
/** $id of the emitted JSON Schema bundle. */
|
|
@@ -184,7 +184,7 @@ export declare const VERB_RATE_LIMITS: {
|
|
|
184
184
|
/** The one self-context type the platform accepts today. */
|
|
185
185
|
export declare const SELF_CONTEXT_TYPE = "cross_session";
|
|
186
186
|
/** Canonical verb names. */
|
|
187
|
-
export declare const CANON_VERB_NAMES: readonly ["send_to", "request_input", "request_approval", "check_approval", "send_card", "request_card", "share_contact", "react", "forward", "create_group", "add_member", "remove_member", "leave_conversation", "list_contacts", "list_contact_requests", "list_conversations", "no_reply"];
|
|
187
|
+
export declare const CANON_VERB_NAMES: readonly ["send_to", "request_input", "request_approval", "check_approval", "send_card", "request_card", "share_contact", "react", "forward", "create_group", "add_member", "remove_member", "leave_conversation", "list_contacts", "list_contact_requests", "list_conversations", "cancel_contact_request", "no_reply"];
|
|
188
188
|
export type CanonVerbName = (typeof CANON_VERB_NAMES)[number];
|
|
189
189
|
/** Private note-to-self attached to a cross-conversation send. */
|
|
190
190
|
export interface VerbSelfContext {
|
|
@@ -268,6 +268,7 @@ export interface VerbMediaAttachment {
|
|
|
268
268
|
*/
|
|
269
269
|
export interface VerbTurnMetadata {
|
|
270
270
|
turnId?: string | null;
|
|
271
|
+
sourceMessageId?: string;
|
|
271
272
|
turnSemantics?: 'progress' | 'turn_complete' | 'control';
|
|
272
273
|
deliveryIntent?: 'queue' | 'interrupt' | 'interleave' | 'stop';
|
|
273
274
|
replyBehavior?: 'allow_auto_reply' | 'suppress_auto_reply';
|
|
@@ -322,7 +323,7 @@ export type SendToResult = {
|
|
|
322
323
|
selfContextId?: string;
|
|
323
324
|
created?: boolean;
|
|
324
325
|
reused?: boolean;
|
|
325
|
-
sessionSelection?:
|
|
326
|
+
sessionSelection?: VerbSessionSelection['mode'];
|
|
326
327
|
} | {
|
|
327
328
|
status: 'requested';
|
|
328
329
|
requestId: string | null;
|
|
@@ -613,7 +614,7 @@ export interface CreateGroupInput {
|
|
|
613
614
|
export interface PendingGroupInviteResult {
|
|
614
615
|
userId: string;
|
|
615
616
|
requestId: string;
|
|
616
|
-
requirements:
|
|
617
|
+
requirements: ContactRequestRequirements;
|
|
617
618
|
}
|
|
618
619
|
export interface CreateGroupResult {
|
|
619
620
|
status: 'created';
|
|
@@ -653,7 +654,7 @@ export type AddMemberResult = {
|
|
|
653
654
|
} | {
|
|
654
655
|
status: 'pending';
|
|
655
656
|
requestId: string;
|
|
656
|
-
requirements:
|
|
657
|
+
requirements: ContactRequestRequirements;
|
|
657
658
|
};
|
|
658
659
|
export interface RemoveMemberInput {
|
|
659
660
|
conversationId: string;
|
|
@@ -680,11 +681,26 @@ export interface VerbContact {
|
|
|
680
681
|
export interface ListContactsResult {
|
|
681
682
|
contacts: VerbContact[];
|
|
682
683
|
}
|
|
683
|
-
export type
|
|
684
|
-
|
|
684
|
+
export type ContactRequestListDirection = 'inbound' | 'outbound';
|
|
685
|
+
export interface ListContactRequestsInput {
|
|
686
|
+
/** Defaults to inbound. Outbound is the reconnect/recovery surface. */
|
|
687
|
+
direction?: ContactRequestListDirection;
|
|
688
|
+
/** Include terminal and starting lifecycle states; default false. */
|
|
689
|
+
includeResolved?: boolean;
|
|
690
|
+
/** Newest-first result cap; default and maximum 100. */
|
|
691
|
+
limit?: number;
|
|
692
|
+
}
|
|
693
|
+
/** Items are SerializedContactRequest (contactRequest.ts), newest first, capped at 100. */
|
|
685
694
|
export interface ListContactRequestsResult {
|
|
686
695
|
requests: unknown[];
|
|
687
696
|
}
|
|
697
|
+
export interface CancelContactRequestInput {
|
|
698
|
+
requestId: string;
|
|
699
|
+
}
|
|
700
|
+
export interface CancelContactRequestResult {
|
|
701
|
+
status: 'cancelled';
|
|
702
|
+
requestId: string;
|
|
703
|
+
}
|
|
688
704
|
export interface ListConversationsInput {
|
|
689
705
|
/** Optional client-side cap; the REST endpoint returns all memberships. */
|
|
690
706
|
limit?: number;
|
package/dist/verbContract.js
CHANGED
package/dist/verbSchemas.d.ts
CHANGED
|
@@ -1615,7 +1615,19 @@ export declare const CANON_VERBS_JSON_SCHEMA: {
|
|
|
1615
1615
|
readonly list_contact_requests_input: {
|
|
1616
1616
|
readonly type: "object";
|
|
1617
1617
|
readonly additionalProperties: false;
|
|
1618
|
-
readonly properties: {
|
|
1618
|
+
readonly properties: {
|
|
1619
|
+
readonly direction: {
|
|
1620
|
+
readonly enum: readonly ["inbound", "outbound"];
|
|
1621
|
+
};
|
|
1622
|
+
readonly includeResolved: {
|
|
1623
|
+
readonly type: "boolean";
|
|
1624
|
+
};
|
|
1625
|
+
readonly limit: {
|
|
1626
|
+
readonly type: "integer";
|
|
1627
|
+
readonly minimum: 1;
|
|
1628
|
+
readonly maximum: 100;
|
|
1629
|
+
};
|
|
1630
|
+
};
|
|
1619
1631
|
};
|
|
1620
1632
|
readonly list_contact_requests_result: {
|
|
1621
1633
|
readonly type: "object";
|
|
@@ -1627,7 +1639,7 @@ export declare const CANON_VERBS_JSON_SCHEMA: {
|
|
|
1627
1639
|
readonly type: "array";
|
|
1628
1640
|
readonly items: {
|
|
1629
1641
|
readonly type: "object";
|
|
1630
|
-
readonly required: readonly ["id", "requesterId", "targetId", "status", "kind"];
|
|
1642
|
+
readonly required: readonly ["id", "requesterId", "targetId", "status", "kind", "phase"];
|
|
1631
1643
|
readonly additionalProperties: true;
|
|
1632
1644
|
readonly properties: {
|
|
1633
1645
|
readonly id: {
|
|
@@ -1643,11 +1655,14 @@ export declare const CANON_VERBS_JSON_SCHEMA: {
|
|
|
1643
1655
|
readonly type: "string";
|
|
1644
1656
|
};
|
|
1645
1657
|
readonly status: {
|
|
1646
|
-
readonly enum: readonly ["pending", "approved", "rejected", "expired"];
|
|
1658
|
+
readonly enum: readonly ["pending", "approved", "rejected", "expired", "cancelled"];
|
|
1647
1659
|
};
|
|
1648
1660
|
readonly kind: {
|
|
1649
1661
|
readonly enum: readonly ["dm", "group_invite"];
|
|
1650
1662
|
};
|
|
1663
|
+
readonly phase: {
|
|
1664
|
+
readonly enum: readonly ["awaiting_owner", "starting", "connected", "rejected", "expired", "cancelled", "failed"];
|
|
1665
|
+
};
|
|
1651
1666
|
readonly message: {
|
|
1652
1667
|
readonly type: readonly ["string", "null"];
|
|
1653
1668
|
};
|
|
@@ -1741,6 +1756,30 @@ export declare const CANON_VERBS_JSON_SCHEMA: {
|
|
|
1741
1756
|
};
|
|
1742
1757
|
};
|
|
1743
1758
|
};
|
|
1759
|
+
readonly cancel_contact_request_input: {
|
|
1760
|
+
readonly type: "object";
|
|
1761
|
+
readonly required: readonly ["requestId"];
|
|
1762
|
+
readonly additionalProperties: false;
|
|
1763
|
+
readonly properties: {
|
|
1764
|
+
readonly requestId: {
|
|
1765
|
+
readonly type: "string";
|
|
1766
|
+
readonly pattern: "^[A-Za-z0-9_.:-]{1,160}$";
|
|
1767
|
+
};
|
|
1768
|
+
};
|
|
1769
|
+
};
|
|
1770
|
+
readonly cancel_contact_request_result: {
|
|
1771
|
+
readonly type: "object";
|
|
1772
|
+
readonly required: readonly ["status", "requestId"];
|
|
1773
|
+
readonly additionalProperties: true;
|
|
1774
|
+
readonly properties: {
|
|
1775
|
+
readonly status: {
|
|
1776
|
+
readonly const: "cancelled";
|
|
1777
|
+
};
|
|
1778
|
+
readonly requestId: {
|
|
1779
|
+
readonly type: "string";
|
|
1780
|
+
};
|
|
1781
|
+
};
|
|
1782
|
+
};
|
|
1744
1783
|
readonly no_reply_input: {
|
|
1745
1784
|
readonly type: "object";
|
|
1746
1785
|
readonly description: string;
|
package/dist/verbSchemas.js
CHANGED
|
@@ -999,13 +999,17 @@ const list_contacts_result = {
|
|
|
999
999
|
const list_contact_requests_input = {
|
|
1000
1000
|
type: 'object',
|
|
1001
1001
|
additionalProperties: false,
|
|
1002
|
-
properties: {
|
|
1002
|
+
properties: {
|
|
1003
|
+
direction: { enum: ['inbound', 'outbound'] },
|
|
1004
|
+
includeResolved: { type: 'boolean' },
|
|
1005
|
+
limit: { type: 'integer', minimum: 1, maximum: 100 },
|
|
1006
|
+
},
|
|
1003
1007
|
};
|
|
1004
1008
|
const list_contact_requests_result = {
|
|
1005
1009
|
type: 'object',
|
|
1006
|
-
description: '
|
|
1007
|
-
+ '
|
|
1008
|
-
+
|
|
1010
|
+
description: 'Contact requests, newest first, capped at 100. Defaults to pending inbound; '
|
|
1011
|
+
+ 'requesters use direction=outbound with includeResolved=true to recover lifecycle state. '
|
|
1012
|
+
+ 'Items are SerializedContactRequest (backend-contracts contactRequest.ts).',
|
|
1009
1013
|
required: ['requests'],
|
|
1010
1014
|
additionalProperties: true,
|
|
1011
1015
|
properties: {
|
|
@@ -1013,15 +1017,26 @@ const list_contact_requests_result = {
|
|
|
1013
1017
|
type: 'array',
|
|
1014
1018
|
items: {
|
|
1015
1019
|
type: 'object',
|
|
1016
|
-
required: ['id', 'requesterId', 'targetId', 'status', 'kind'],
|
|
1020
|
+
required: ['id', 'requesterId', 'targetId', 'status', 'kind', 'phase'],
|
|
1017
1021
|
additionalProperties: true,
|
|
1018
1022
|
properties: {
|
|
1019
1023
|
id: { type: 'string' },
|
|
1020
1024
|
requesterId: { type: 'string' },
|
|
1021
1025
|
requesterName: { type: 'string' },
|
|
1022
1026
|
targetId: { type: 'string' },
|
|
1023
|
-
status: { enum: ['pending', 'approved', 'rejected', 'expired'] },
|
|
1027
|
+
status: { enum: ['pending', 'approved', 'rejected', 'expired', 'cancelled'] },
|
|
1024
1028
|
kind: { enum: ['dm', 'group_invite'] },
|
|
1029
|
+
phase: {
|
|
1030
|
+
enum: [
|
|
1031
|
+
'awaiting_owner',
|
|
1032
|
+
'starting',
|
|
1033
|
+
'connected',
|
|
1034
|
+
'rejected',
|
|
1035
|
+
'expired',
|
|
1036
|
+
'cancelled',
|
|
1037
|
+
'failed',
|
|
1038
|
+
],
|
|
1039
|
+
},
|
|
1025
1040
|
message: { type: ['string', 'null'] },
|
|
1026
1041
|
createdAt: { type: ['string', 'null'] },
|
|
1027
1042
|
expiresAt: { type: ['string', 'null'] },
|
|
@@ -1030,6 +1045,23 @@ const list_contact_requests_result = {
|
|
|
1030
1045
|
},
|
|
1031
1046
|
},
|
|
1032
1047
|
};
|
|
1048
|
+
const cancel_contact_request_input = {
|
|
1049
|
+
type: 'object',
|
|
1050
|
+
required: ['requestId'],
|
|
1051
|
+
additionalProperties: false,
|
|
1052
|
+
properties: {
|
|
1053
|
+
requestId: { type: 'string', pattern: VERB_ID_PATTERNS.runtimeId },
|
|
1054
|
+
},
|
|
1055
|
+
};
|
|
1056
|
+
const cancel_contact_request_result = {
|
|
1057
|
+
type: 'object',
|
|
1058
|
+
required: ['status', 'requestId'],
|
|
1059
|
+
additionalProperties: true,
|
|
1060
|
+
properties: {
|
|
1061
|
+
status: { const: 'cancelled' },
|
|
1062
|
+
requestId: { type: 'string' },
|
|
1063
|
+
},
|
|
1064
|
+
};
|
|
1033
1065
|
const list_conversations_input = {
|
|
1034
1066
|
type: 'object',
|
|
1035
1067
|
additionalProperties: false,
|
|
@@ -1169,6 +1201,8 @@ export const CANON_VERBS_JSON_SCHEMA = {
|
|
|
1169
1201
|
list_contact_requests_result,
|
|
1170
1202
|
list_conversations_input,
|
|
1171
1203
|
list_conversations_result,
|
|
1204
|
+
cancel_contact_request_input,
|
|
1205
|
+
cancel_contact_request_result,
|
|
1172
1206
|
no_reply_input,
|
|
1173
1207
|
no_reply_result,
|
|
1174
1208
|
},
|
package/dist/verbWire.d.ts
CHANGED
|
@@ -40,6 +40,8 @@ export type VerbWireBody = {
|
|
|
40
40
|
/** Turn-protocol keys the server enforces on (subset of TurnMetadata). */
|
|
41
41
|
export interface VerbWireTurn {
|
|
42
42
|
turnId?: string | null;
|
|
43
|
+
/** Trusted message that initiated a host-bound owner turn. */
|
|
44
|
+
sourceMessageId?: string;
|
|
43
45
|
turnSemantics?: 'progress' | 'turn_complete' | 'control';
|
|
44
46
|
deliveryIntent?: 'queue' | 'interrupt' | 'interleave' | 'stop';
|
|
45
47
|
replyBehavior?: 'allow_auto_reply' | 'suppress_auto_reply';
|
|
@@ -137,7 +139,7 @@ export declare const CANON_VERB_WIRE_JSON_SCHEMA: {
|
|
|
137
139
|
readonly const: "canon.verb-wire.v1";
|
|
138
140
|
};
|
|
139
141
|
readonly verb: {
|
|
140
|
-
readonly enum: readonly ["send_to", "request_input", "request_approval", "check_approval", "send_card", "request_card", "share_contact", "react", "forward", "create_group", "add_member", "remove_member", "leave_conversation", "list_contacts", "list_contact_requests", "list_conversations", "no_reply"];
|
|
142
|
+
readonly enum: readonly ["send_to", "request_input", "request_approval", "check_approval", "send_card", "request_card", "share_contact", "react", "forward", "create_group", "add_member", "remove_member", "leave_conversation", "list_contacts", "list_contact_requests", "list_conversations", "cancel_contact_request", "no_reply"];
|
|
141
143
|
};
|
|
142
144
|
readonly envelope: {
|
|
143
145
|
readonly $ref: "#/$defs/envelope";
|
|
@@ -464,6 +466,10 @@ export declare const CANON_VERB_WIRE_JSON_SCHEMA: {
|
|
|
464
466
|
readonly turnId: {
|
|
465
467
|
readonly type: readonly ["string", "null"];
|
|
466
468
|
};
|
|
469
|
+
readonly sourceMessageId: {
|
|
470
|
+
readonly type: "string";
|
|
471
|
+
readonly minLength: 1;
|
|
472
|
+
};
|
|
467
473
|
readonly turnSemantics: {
|
|
468
474
|
readonly enum: readonly ["progress", "turn_complete", "control"];
|
|
469
475
|
};
|
|
@@ -509,7 +515,7 @@ export declare const CANON_VERB_WIRE_JSON_SCHEMA: {
|
|
|
509
515
|
readonly const: "canon.verb-wire.v1";
|
|
510
516
|
};
|
|
511
517
|
readonly verb: {
|
|
512
|
-
readonly enum: readonly ["send_to", "request_input", "request_approval", "check_approval", "send_card", "request_card", "share_contact", "react", "forward", "create_group", "add_member", "remove_member", "leave_conversation", "list_contacts", "list_contact_requests", "list_conversations", "no_reply"];
|
|
518
|
+
readonly enum: readonly ["send_to", "request_input", "request_approval", "check_approval", "send_card", "request_card", "share_contact", "react", "forward", "create_group", "add_member", "remove_member", "leave_conversation", "list_contacts", "list_contact_requests", "list_conversations", "cancel_contact_request", "no_reply"];
|
|
513
519
|
};
|
|
514
520
|
readonly result: {
|
|
515
521
|
readonly $ref: "#/$defs/body";
|
package/dist/verbWire.js
CHANGED
|
@@ -112,6 +112,7 @@ export const VERB_WIRE_ENVELOPE_FIELDS = {
|
|
|
112
112
|
list_contacts: { required: [], optional: [] },
|
|
113
113
|
list_contact_requests: { required: [], optional: [] },
|
|
114
114
|
list_conversations: { required: [], optional: ['limit'] },
|
|
115
|
+
cancel_contact_request: { required: ['requestId'], optional: [] },
|
|
115
116
|
no_reply: { required: [], optional: ['conversationId', 'messageId'] },
|
|
116
117
|
};
|
|
117
118
|
// ---------------------------------------------------------------------------
|
|
@@ -153,6 +154,7 @@ const wireTurnDef = {
|
|
|
153
154
|
additionalProperties: false,
|
|
154
155
|
properties: {
|
|
155
156
|
turnId: { type: ['string', 'null'] },
|
|
157
|
+
sourceMessageId: { type: 'string', minLength: 1 },
|
|
156
158
|
turnSemantics: { enum: ['progress', 'turn_complete', 'control'] },
|
|
157
159
|
deliveryIntent: { enum: ['queue', 'interrupt', 'interleave', 'stop'] },
|
|
158
160
|
replyBehavior: { enum: ['allow_auto_reply', 'suppress_auto_reply'] },
|
|
@@ -278,7 +280,13 @@ export const CANON_VERB_WIRE_JSON_SCHEMA = {
|
|
|
278
280
|
// ---------------------------------------------------------------------------
|
|
279
281
|
// Intent <-> wire projection (json codec)
|
|
280
282
|
// ---------------------------------------------------------------------------
|
|
281
|
-
const TURN_KEYS = [
|
|
283
|
+
const TURN_KEYS = [
|
|
284
|
+
'turnId',
|
|
285
|
+
'sourceMessageId',
|
|
286
|
+
'turnSemantics',
|
|
287
|
+
'deliveryIntent',
|
|
288
|
+
'replyBehavior',
|
|
289
|
+
];
|
|
282
290
|
function splitTurnMetadata(metadata) {
|
|
283
291
|
if (!metadata || typeof metadata !== 'object')
|
|
284
292
|
return { turn: undefined, rest: undefined };
|
|
@@ -463,14 +471,25 @@ export function projectVerbIntentToWire(verb, intent, options) {
|
|
|
463
471
|
envelope = compact({ conversationId: input.conversationId });
|
|
464
472
|
break;
|
|
465
473
|
}
|
|
466
|
-
case 'list_contacts':
|
|
474
|
+
case 'list_contacts': {
|
|
475
|
+
break;
|
|
476
|
+
}
|
|
467
477
|
case 'list_contact_requests': {
|
|
478
|
+
value = compact({
|
|
479
|
+
direction: input.direction,
|
|
480
|
+
includeResolved: input.includeResolved,
|
|
481
|
+
limit: input.limit,
|
|
482
|
+
});
|
|
468
483
|
break;
|
|
469
484
|
}
|
|
470
485
|
case 'list_conversations': {
|
|
471
486
|
envelope = compact({ limit: input.limit });
|
|
472
487
|
break;
|
|
473
488
|
}
|
|
489
|
+
case 'cancel_contact_request': {
|
|
490
|
+
envelope = compact({ requestId: input.requestId });
|
|
491
|
+
break;
|
|
492
|
+
}
|
|
474
493
|
case 'no_reply': {
|
|
475
494
|
envelope = compact({ conversationId: input.conversationId, messageId: input.messageId });
|
|
476
495
|
value = compact({ reason: input.reason });
|
|
@@ -609,10 +628,17 @@ export function mergeVerbWireToIntent(request) {
|
|
|
609
628
|
case 'leave_conversation':
|
|
610
629
|
return compact({ conversationId: envelope.conversationId });
|
|
611
630
|
case 'list_contacts':
|
|
612
|
-
case 'list_contact_requests':
|
|
613
631
|
return {};
|
|
632
|
+
case 'list_contact_requests':
|
|
633
|
+
return compact({
|
|
634
|
+
direction: value.direction,
|
|
635
|
+
includeResolved: value.includeResolved,
|
|
636
|
+
limit: value.limit,
|
|
637
|
+
});
|
|
614
638
|
case 'list_conversations':
|
|
615
639
|
return compact({ limit: envelope.limit });
|
|
640
|
+
case 'cancel_contact_request':
|
|
641
|
+
return compact({ requestId: envelope.requestId });
|
|
616
642
|
case 'no_reply':
|
|
617
643
|
return compact({ conversationId: envelope.conversationId, messageId: envelope.messageId, reason: value.reason });
|
|
618
644
|
}
|