@canonmsg/backend-contracts 6.4.0 → 8.0.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 +3 -3
- package/dist/canon-verb-wire.schema.json +0 -73
- package/dist/canon-verbs.limits.json +0 -5
- package/dist/canon-verbs.schema.json +7 -233
- package/dist/cjs/communication.js +31 -0
- package/dist/cjs/firestoreValues.js +1 -1
- package/dist/cjs/index.js +2 -2
- package/dist/cjs/replyAuthority.js +2 -0
- package/dist/cjs/verbContract.js +1 -17
- package/dist/cjs/verbSchemas.js +11 -149
- package/dist/cjs/verbWire.js +1 -36
- package/dist/communication.d.ts +109 -0
- package/dist/communication.js +27 -0
- package/dist/firestoreValues.d.ts +1 -1
- package/dist/firestoreValues.js +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/replyAuthority.d.ts +12 -0
- package/dist/replyAuthority.js +1 -0
- package/dist/verbContract.d.ts +5 -65
- package/dist/verbContract.js +0 -16
- package/dist/verbSchemas.d.ts +3 -210
- package/dist/verbSchemas.js +10 -148
- package/dist/verbWire.d.ts +4 -61
- package/dist/verbWire.js +2 -37
- package/package.json +2 -2
- package/dist/accessPolicy.d.ts +0 -9
- package/dist/accessPolicy.js +0 -12
- package/dist/cjs/accessPolicy.js +0 -15
- package/dist/cjs/contactRequest.js +0 -163
- package/dist/contactRequest.d.ts +0 -50
- package/dist/contactRequest.js +0 -157
package/dist/cjs/verbSchemas.js
CHANGED
|
@@ -29,23 +29,11 @@
|
|
|
29
29
|
* endpoints validate against these schemas directly).
|
|
30
30
|
*/
|
|
31
31
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
32
|
-
exports.CANON_VERB_SCHEMA_REFS = exports.CANON_VERBS_JSON_SCHEMA = exports.
|
|
32
|
+
exports.CANON_VERB_SCHEMA_REFS = exports.CANON_VERBS_JSON_SCHEMA = exports.VERB_NATIVE_METADATA_JSON_SCHEMA = void 0;
|
|
33
33
|
exports.getVerbInputSchema = getVerbInputSchema;
|
|
34
34
|
exports.getVerbResultSchema = getVerbResultSchema;
|
|
35
35
|
const verbContract_js_1 = require("./verbContract.js");
|
|
36
36
|
const REF = (def) => ({ $ref: `#/$defs/${def}` });
|
|
37
|
-
const groupInviteRequirementsDef = {
|
|
38
|
-
type: 'object',
|
|
39
|
-
description: 'Independent gates on a pending group invite. policyApproval is social '
|
|
40
|
-
+ 'consent; ownerSessionSetup means the agent owner must choose the '
|
|
41
|
-
+ 'runtime session configuration before membership is activated.',
|
|
42
|
-
required: ['policyApproval', 'ownerSessionSetup'],
|
|
43
|
-
additionalProperties: false,
|
|
44
|
-
properties: {
|
|
45
|
-
policyApproval: { type: 'boolean' },
|
|
46
|
-
ownerSessionSetup: { type: 'boolean' },
|
|
47
|
-
},
|
|
48
|
-
};
|
|
49
37
|
const selfContextDef = {
|
|
50
38
|
type: 'object',
|
|
51
39
|
description: 'Private note-to-self attached to a cross-conversation send. Visible only to the '
|
|
@@ -315,50 +303,6 @@ exports.VERB_NATIVE_METADATA_JSON_SCHEMA = {
|
|
|
315
303
|
},
|
|
316
304
|
},
|
|
317
305
|
};
|
|
318
|
-
const sessionConfigValueDef = {
|
|
319
|
-
type: 'string',
|
|
320
|
-
pattern: verbContract_js_1.VERB_ID_PATTERNS.runtimeOptionValue,
|
|
321
|
-
maxLength: verbContract_js_1.VERB_LIMITS.sessionConfigValueChars,
|
|
322
|
-
};
|
|
323
|
-
exports.VERB_SESSION_CONFIG_JSON_SCHEMA = {
|
|
324
|
-
type: 'object',
|
|
325
|
-
description: 'Typed setup policy for an agent target. Values are stable runtime-advertised '
|
|
326
|
-
+ 'option ids and are validated against the target descriptor before session creation; '
|
|
327
|
-
+ 'labels, prompts, workspace paths, and arbitrary fields are not permitted.',
|
|
328
|
-
additionalProperties: false,
|
|
329
|
-
properties: {
|
|
330
|
-
model: sessionConfigValueDef,
|
|
331
|
-
permissionMode: sessionConfigValueDef,
|
|
332
|
-
effort: sessionConfigValueDef,
|
|
333
|
-
workspaceId: {
|
|
334
|
-
type: 'string',
|
|
335
|
-
pattern: verbContract_js_1.VERB_ID_PATTERNS.workspaceOptionId,
|
|
336
|
-
maxLength: verbContract_js_1.VERB_LIMITS.sessionConfigValueChars,
|
|
337
|
-
},
|
|
338
|
-
executionMode: { enum: ['worktree', 'locked'] },
|
|
339
|
-
runtimeControlValues: {
|
|
340
|
-
type: 'object',
|
|
341
|
-
maxProperties: verbContract_js_1.VERB_LIMITS.sessionConfigValues,
|
|
342
|
-
propertyNames: {
|
|
343
|
-
pattern: verbContract_js_1.VERB_ID_PATTERNS.runtimeControlId,
|
|
344
|
-
not: {
|
|
345
|
-
enum: [
|
|
346
|
-
'model',
|
|
347
|
-
'workspace',
|
|
348
|
-
'executionMode',
|
|
349
|
-
'permissionMode',
|
|
350
|
-
'effort',
|
|
351
|
-
'interrupt',
|
|
352
|
-
'runtimeControlValues',
|
|
353
|
-
'updatedAt',
|
|
354
|
-
'updatedBy',
|
|
355
|
-
],
|
|
356
|
-
},
|
|
357
|
-
},
|
|
358
|
-
additionalProperties: sessionConfigValueDef,
|
|
359
|
-
},
|
|
360
|
-
},
|
|
361
|
-
};
|
|
362
306
|
const timeoutFields = (maxMs, ceilingNote) => ({
|
|
363
307
|
timeoutMs: {
|
|
364
308
|
type: 'integer',
|
|
@@ -388,7 +332,7 @@ const send_to_input = {
|
|
|
388
332
|
+ 'sends -> admission resolve + create + send (the core reachOut composite). User '
|
|
389
333
|
+ 'targets resolve admission first: open targets get the message, approval-required '
|
|
390
334
|
+ 'targets get a contact request (send deferred and auto-fulfilled on approval), '
|
|
391
|
-
+ "
|
|
335
|
+
+ "closed targets surface as status 'unavailable' with reason closed.",
|
|
392
336
|
additionalProperties: false,
|
|
393
337
|
properties: {
|
|
394
338
|
targetConversationId: { type: 'string', pattern: verbContract_js_1.VERB_ID_PATTERNS.runtimeId },
|
|
@@ -412,11 +356,6 @@ const send_to_input = {
|
|
|
412
356
|
+ `truncate to ${verbContract_js_1.VERB_LIMITS.contactRequestNoteChars} chars.`,
|
|
413
357
|
},
|
|
414
358
|
sessionSelection: REF('sessionSelection'),
|
|
415
|
-
sessionConfig: {
|
|
416
|
-
oneOf: [REF('sessionConfig'), { type: 'null' }],
|
|
417
|
-
description: 'Coding-agent session setup (model/permissionMode/effort/workspaceId/executionMode); '
|
|
418
|
-
+ 'only applied to agent targets, stripped for humans.',
|
|
419
|
-
},
|
|
420
359
|
messageOptions: REF('messageOptions'),
|
|
421
360
|
},
|
|
422
361
|
oneOf: [
|
|
@@ -843,11 +782,9 @@ const create_group_input = {
|
|
|
843
782
|
description: "Create a group conversation. Each target's groupJoinPolicy is enforced "
|
|
844
783
|
+ 'server-side with staged admission: directly-addable members join at '
|
|
845
784
|
+ 'creation, approval-required members become pending group_invite '
|
|
846
|
-
+ 'requests;
|
|
847
|
-
+ 'owner requests; hard-denied members are skipped (see the result). A '
|
|
785
|
+
+ 'requests; hard-denied members are skipped (see the result). A '
|
|
848
786
|
+ 'creator-only group is valid when at least one requested member has a '
|
|
849
|
-
+ 'pending invite.
|
|
850
|
-
+ 'groups (403 CREATE_GROUP_CREATOR_SETUP_REQUIRED). Under MLS, membership '
|
|
787
|
+
+ 'pending invite. Under MLS, membership '
|
|
851
788
|
+ 'changes are Add/Remove proposals + Commit — a group operation is a '
|
|
852
789
|
+ 'cryptographic state change, not a codec swap.',
|
|
853
790
|
required: ['name', 'memberIds'],
|
|
@@ -866,8 +803,8 @@ const create_group_input = {
|
|
|
866
803
|
const create_group_result = {
|
|
867
804
|
type: 'object',
|
|
868
805
|
description: 'Staged admission: the group exists with the directly-added members; '
|
|
869
|
-
+ '`pending` lists group_invite requests awaiting policy approval
|
|
870
|
-
+ '
|
|
806
|
+
+ '`pending` lists group_invite requests awaiting policy approval; '
|
|
807
|
+
+ '`skipped` lists hard-denied targets.',
|
|
871
808
|
required: ['status', 'conversationId', 'added', 'pending', 'skipped'],
|
|
872
809
|
additionalProperties: true,
|
|
873
810
|
properties: {
|
|
@@ -881,12 +818,11 @@ const create_group_result = {
|
|
|
881
818
|
type: 'array',
|
|
882
819
|
items: {
|
|
883
820
|
type: 'object',
|
|
884
|
-
required: ['userId', 'requestId'
|
|
821
|
+
required: ['userId', 'requestId'],
|
|
885
822
|
additionalProperties: true,
|
|
886
823
|
properties: {
|
|
887
824
|
userId: { type: 'string' },
|
|
888
825
|
requestId: { type: 'string' },
|
|
889
|
-
requirements: REF('groupInviteRequirements'),
|
|
890
826
|
},
|
|
891
827
|
},
|
|
892
828
|
},
|
|
@@ -906,8 +842,8 @@ const create_group_result = {
|
|
|
906
842
|
};
|
|
907
843
|
const add_member_input = {
|
|
908
844
|
type: 'object',
|
|
909
|
-
description: 'A target needing policy approval
|
|
910
|
-
+ '
|
|
845
|
+
description: 'A target needing policy approval yields one pending group_invite. '
|
|
846
|
+
+ 'Under MLS an add is an Add proposal '
|
|
911
847
|
+ '+ Commit (new epoch), not a server-side membership write — the verb '
|
|
912
848
|
+ 'semantics are stable, the mechanism is not.',
|
|
913
849
|
required: ['conversationId', 'userId'],
|
|
@@ -918,8 +854,7 @@ const add_member_input = {
|
|
|
918
854
|
},
|
|
919
855
|
};
|
|
920
856
|
const add_member_result = {
|
|
921
|
-
description: 'Targets needing policy approval
|
|
922
|
-
+ 'pending group_invite routed to the target or agent owner.',
|
|
857
|
+
description: 'Targets needing policy approval yield an exact pending group invite.',
|
|
923
858
|
oneOf: [
|
|
924
859
|
{
|
|
925
860
|
type: 'object',
|
|
@@ -929,12 +864,11 @@ const add_member_result = {
|
|
|
929
864
|
},
|
|
930
865
|
{
|
|
931
866
|
type: 'object',
|
|
932
|
-
required: ['status', 'requestId'
|
|
867
|
+
required: ['status', 'requestId'],
|
|
933
868
|
additionalProperties: true,
|
|
934
869
|
properties: {
|
|
935
870
|
status: { const: 'pending' },
|
|
936
871
|
requestId: { type: 'string' },
|
|
937
|
-
requirements: REF('groupInviteRequirements'),
|
|
938
872
|
},
|
|
939
873
|
},
|
|
940
874
|
],
|
|
@@ -1001,72 +935,6 @@ const list_contacts_result = {
|
|
|
1001
935
|
},
|
|
1002
936
|
},
|
|
1003
937
|
};
|
|
1004
|
-
const list_contact_requests_input = {
|
|
1005
|
-
type: 'object',
|
|
1006
|
-
additionalProperties: false,
|
|
1007
|
-
properties: {
|
|
1008
|
-
direction: { enum: ['inbound', 'outbound'] },
|
|
1009
|
-
includeResolved: { type: 'boolean' },
|
|
1010
|
-
limit: { type: 'integer', minimum: 1, maximum: 100 },
|
|
1011
|
-
},
|
|
1012
|
-
};
|
|
1013
|
-
const list_contact_requests_result = {
|
|
1014
|
-
type: 'object',
|
|
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).',
|
|
1018
|
-
required: ['requests'],
|
|
1019
|
-
additionalProperties: true,
|
|
1020
|
-
properties: {
|
|
1021
|
-
requests: {
|
|
1022
|
-
type: 'array',
|
|
1023
|
-
items: {
|
|
1024
|
-
type: 'object',
|
|
1025
|
-
required: ['id', 'requesterId', 'targetId', 'status', 'kind', 'phase'],
|
|
1026
|
-
additionalProperties: true,
|
|
1027
|
-
properties: {
|
|
1028
|
-
id: { type: 'string' },
|
|
1029
|
-
requesterId: { type: 'string' },
|
|
1030
|
-
requesterName: { type: 'string' },
|
|
1031
|
-
targetId: { type: 'string' },
|
|
1032
|
-
status: { enum: ['pending', 'approved', 'rejected', 'expired', 'cancelled'] },
|
|
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
|
-
},
|
|
1045
|
-
message: { type: ['string', 'null'] },
|
|
1046
|
-
createdAt: { type: ['string', 'null'] },
|
|
1047
|
-
expiresAt: { type: ['string', 'null'] },
|
|
1048
|
-
},
|
|
1049
|
-
},
|
|
1050
|
-
},
|
|
1051
|
-
},
|
|
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
|
-
};
|
|
1070
938
|
const list_conversations_input = {
|
|
1071
939
|
type: 'object',
|
|
1072
940
|
additionalProperties: false,
|
|
@@ -1160,7 +1028,6 @@ exports.CANON_VERBS_JSON_SCHEMA = {
|
|
|
1160
1028
|
+ 'deliberately NOT verbs — they stay host-mediated.',
|
|
1161
1029
|
$defs: {
|
|
1162
1030
|
messageId: messageIdDef,
|
|
1163
|
-
groupInviteRequirements: groupInviteRequirementsDef,
|
|
1164
1031
|
selfContext: selfContextDef,
|
|
1165
1032
|
sessionSelection: sessionSelectionDef,
|
|
1166
1033
|
mediaAttachment: mediaAttachmentDef,
|
|
@@ -1173,7 +1040,6 @@ exports.CANON_VERBS_JSON_SCHEMA = {
|
|
|
1173
1040
|
sessionRule: sessionRuleDef,
|
|
1174
1041
|
runtimeCard: runtimeCardDef,
|
|
1175
1042
|
native: exports.VERB_NATIVE_METADATA_JSON_SCHEMA,
|
|
1176
|
-
sessionConfig: exports.VERB_SESSION_CONFIG_JSON_SCHEMA,
|
|
1177
1043
|
send_to_input,
|
|
1178
1044
|
send_to_result,
|
|
1179
1045
|
request_input_input,
|
|
@@ -1202,12 +1068,8 @@ exports.CANON_VERBS_JSON_SCHEMA = {
|
|
|
1202
1068
|
leave_conversation_result,
|
|
1203
1069
|
list_contacts_input,
|
|
1204
1070
|
list_contacts_result,
|
|
1205
|
-
list_contact_requests_input,
|
|
1206
|
-
list_contact_requests_result,
|
|
1207
1071
|
list_conversations_input,
|
|
1208
1072
|
list_conversations_result,
|
|
1209
|
-
cancel_contact_request_input,
|
|
1210
|
-
cancel_contact_request_result,
|
|
1211
1073
|
no_reply_input,
|
|
1212
1074
|
no_reply_result,
|
|
1213
1075
|
},
|
package/dist/cjs/verbWire.js
CHANGED
|
@@ -47,7 +47,6 @@ exports.VERB_WIRE_ENVELOPE_FIELDS = {
|
|
|
47
47
|
'canonContactId',
|
|
48
48
|
'sourceConversationId',
|
|
49
49
|
'sessionSelection',
|
|
50
|
-
'sessionConfig',
|
|
51
50
|
'idempotencyKey',
|
|
52
51
|
'replyTo',
|
|
53
52
|
'replyToPosition',
|
|
@@ -116,9 +115,7 @@ exports.VERB_WIRE_ENVELOPE_FIELDS = {
|
|
|
116
115
|
optional: [],
|
|
117
116
|
},
|
|
118
117
|
list_contacts: { required: [], optional: [] },
|
|
119
|
-
list_contact_requests: { required: [], optional: [] },
|
|
120
118
|
list_conversations: { required: [], optional: ['limit'] },
|
|
121
|
-
cancel_contact_request: { required: ['requestId'], optional: [] },
|
|
122
119
|
no_reply: { required: [], optional: ['conversationId', 'messageId'] },
|
|
123
120
|
};
|
|
124
121
|
// ---------------------------------------------------------------------------
|
|
@@ -160,7 +157,6 @@ const wireTurnDef = {
|
|
|
160
157
|
additionalProperties: false,
|
|
161
158
|
properties: {
|
|
162
159
|
turnId: { type: ['string', 'null'] },
|
|
163
|
-
sourceMessageId: { type: 'string', minLength: 1 },
|
|
164
160
|
turnSemantics: { enum: ['progress', 'turn_complete', 'control'] },
|
|
165
161
|
deliveryIntent: { enum: ['queue', 'interrupt', 'interleave', 'stop'] },
|
|
166
162
|
replyBehavior: { enum: ['allow_auto_reply', 'suppress_auto_reply'] },
|
|
@@ -208,9 +204,6 @@ const wireEnvelopeDef = {
|
|
|
208
204
|
},
|
|
209
205
|
],
|
|
210
206
|
},
|
|
211
|
-
sessionConfig: {
|
|
212
|
-
oneOf: [verbSchemas_js_1.VERB_SESSION_CONFIG_JSON_SCHEMA, { type: 'null' }],
|
|
213
|
-
},
|
|
214
207
|
idempotencyKey: {
|
|
215
208
|
type: 'string',
|
|
216
209
|
pattern: verbContract_js_1.VERB_ID_PATTERNS.runtimeId,
|
|
@@ -286,13 +279,7 @@ exports.CANON_VERB_WIRE_JSON_SCHEMA = {
|
|
|
286
279
|
// ---------------------------------------------------------------------------
|
|
287
280
|
// Intent <-> wire projection (json codec)
|
|
288
281
|
// ---------------------------------------------------------------------------
|
|
289
|
-
const TURN_KEYS = [
|
|
290
|
-
'turnId',
|
|
291
|
-
'sourceMessageId',
|
|
292
|
-
'turnSemantics',
|
|
293
|
-
'deliveryIntent',
|
|
294
|
-
'replyBehavior',
|
|
295
|
-
];
|
|
282
|
+
const TURN_KEYS = ['turnId', 'turnSemantics', 'deliveryIntent', 'replyBehavior'];
|
|
296
283
|
function splitTurnMetadata(metadata) {
|
|
297
284
|
if (!metadata || typeof metadata !== 'object')
|
|
298
285
|
return { turn: undefined, rest: undefined };
|
|
@@ -350,7 +337,6 @@ function projectVerbIntentToWire(verb, intent, options) {
|
|
|
350
337
|
canonContactId: input.canonContactId,
|
|
351
338
|
sourceConversationId: input.sourceConversationId,
|
|
352
339
|
sessionSelection: input.sessionSelection,
|
|
353
|
-
sessionConfig: input.sessionConfig,
|
|
354
340
|
idempotencyKey: messageOptions.messageId,
|
|
355
341
|
replyTo: messageOptions.replyTo,
|
|
356
342
|
replyToPosition: messageOptions.replyToPosition,
|
|
@@ -480,22 +466,10 @@ function projectVerbIntentToWire(verb, intent, options) {
|
|
|
480
466
|
case 'list_contacts': {
|
|
481
467
|
break;
|
|
482
468
|
}
|
|
483
|
-
case 'list_contact_requests': {
|
|
484
|
-
value = compact({
|
|
485
|
-
direction: input.direction,
|
|
486
|
-
includeResolved: input.includeResolved,
|
|
487
|
-
limit: input.limit,
|
|
488
|
-
});
|
|
489
|
-
break;
|
|
490
|
-
}
|
|
491
469
|
case 'list_conversations': {
|
|
492
470
|
envelope = compact({ limit: input.limit });
|
|
493
471
|
break;
|
|
494
472
|
}
|
|
495
|
-
case 'cancel_contact_request': {
|
|
496
|
-
envelope = compact({ requestId: input.requestId });
|
|
497
|
-
break;
|
|
498
|
-
}
|
|
499
473
|
case 'no_reply': {
|
|
500
474
|
envelope = compact({ conversationId: input.conversationId, messageId: input.messageId });
|
|
501
475
|
value = compact({ reason: input.reason });
|
|
@@ -541,7 +515,6 @@ function mergeVerbWireToIntent(request) {
|
|
|
541
515
|
canonContactId: envelope.canonContactId,
|
|
542
516
|
sourceConversationId: envelope.sourceConversationId,
|
|
543
517
|
sessionSelection: envelope.sessionSelection,
|
|
544
|
-
sessionConfig: envelope.sessionConfig,
|
|
545
518
|
text: value.text,
|
|
546
519
|
selfContext: value.selfContext,
|
|
547
520
|
requestMessage: value.requestMessage,
|
|
@@ -635,16 +608,8 @@ function mergeVerbWireToIntent(request) {
|
|
|
635
608
|
return compact({ conversationId: envelope.conversationId });
|
|
636
609
|
case 'list_contacts':
|
|
637
610
|
return {};
|
|
638
|
-
case 'list_contact_requests':
|
|
639
|
-
return compact({
|
|
640
|
-
direction: value.direction,
|
|
641
|
-
includeResolved: value.includeResolved,
|
|
642
|
-
limit: value.limit,
|
|
643
|
-
});
|
|
644
611
|
case 'list_conversations':
|
|
645
612
|
return compact({ limit: envelope.limit });
|
|
646
|
-
case 'cancel_contact_request':
|
|
647
|
-
return compact({ requestId: envelope.requestId });
|
|
648
613
|
case 'no_reply':
|
|
649
614
|
return compact({ conversationId: envelope.conversationId, messageId: envelope.messageId, reason: value.reason });
|
|
650
615
|
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/** The deliberately small policy vocabulary for principal communication. */
|
|
2
|
+
export type CommunicationRule = 'open' | 'approval-required' | 'closed';
|
|
3
|
+
/** Missing or invalid policy never widens access. */
|
|
4
|
+
export declare function readCommunicationRule(value: unknown): CommunicationRule;
|
|
5
|
+
/** Canon conversation selection is principal-neutral; a conversation is a runtime session boundary. */
|
|
6
|
+
export type DirectConversationSelection = {
|
|
7
|
+
mode: 'latest_or_new';
|
|
8
|
+
} | {
|
|
9
|
+
mode: 'new';
|
|
10
|
+
} | {
|
|
11
|
+
mode: 'specific';
|
|
12
|
+
conversationId: string;
|
|
13
|
+
};
|
|
14
|
+
export type CommunicateInput = {
|
|
15
|
+
action: 'message_existing';
|
|
16
|
+
conversationId: string;
|
|
17
|
+
text: string;
|
|
18
|
+
messageId?: string;
|
|
19
|
+
} | {
|
|
20
|
+
action: 'start_direct';
|
|
21
|
+
principalId: string;
|
|
22
|
+
text: string;
|
|
23
|
+
selection?: DirectConversationSelection;
|
|
24
|
+
messageId?: string;
|
|
25
|
+
} | {
|
|
26
|
+
action: 'create_group';
|
|
27
|
+
name: string;
|
|
28
|
+
memberIds: string[];
|
|
29
|
+
} | {
|
|
30
|
+
action: 'forward_message';
|
|
31
|
+
sourceConversationId: string;
|
|
32
|
+
targetConversationId: string;
|
|
33
|
+
messageId: string;
|
|
34
|
+
text?: string;
|
|
35
|
+
} | {
|
|
36
|
+
action: 'share_contact';
|
|
37
|
+
conversationId: string;
|
|
38
|
+
contactUserId: string;
|
|
39
|
+
text?: string;
|
|
40
|
+
messageId?: string;
|
|
41
|
+
} | {
|
|
42
|
+
action: 'manage_group_members';
|
|
43
|
+
conversationId: string;
|
|
44
|
+
userId: string;
|
|
45
|
+
operation: 'add' | 'remove';
|
|
46
|
+
};
|
|
47
|
+
export type CommunicateResult = {
|
|
48
|
+
status: 'messaged';
|
|
49
|
+
conversationId: string;
|
|
50
|
+
messageId: string;
|
|
51
|
+
created?: boolean;
|
|
52
|
+
reused?: boolean;
|
|
53
|
+
} | {
|
|
54
|
+
status: 'requested' | 'pending';
|
|
55
|
+
requestId: string;
|
|
56
|
+
} | {
|
|
57
|
+
status: 'created';
|
|
58
|
+
conversationId: string;
|
|
59
|
+
added: string[];
|
|
60
|
+
pending: Array<{
|
|
61
|
+
userId: string;
|
|
62
|
+
requestId: string;
|
|
63
|
+
}>;
|
|
64
|
+
skipped: Array<{
|
|
65
|
+
userId: string;
|
|
66
|
+
reason: string;
|
|
67
|
+
}>;
|
|
68
|
+
} | {
|
|
69
|
+
status: 'forwarded';
|
|
70
|
+
messageId: string;
|
|
71
|
+
targetConversationId: string;
|
|
72
|
+
} | {
|
|
73
|
+
status: 'shared';
|
|
74
|
+
conversationId: string;
|
|
75
|
+
messageId: string;
|
|
76
|
+
} | {
|
|
77
|
+
status: 'added' | 'removed';
|
|
78
|
+
conversationId: string;
|
|
79
|
+
userId: string;
|
|
80
|
+
} | {
|
|
81
|
+
status: 'approval_required';
|
|
82
|
+
reason: string;
|
|
83
|
+
} | {
|
|
84
|
+
status: 'blocked' | 'unavailable';
|
|
85
|
+
reason: string;
|
|
86
|
+
};
|
|
87
|
+
/** Principal-neutral app/SDK command. Humans may open a composer before sending. */
|
|
88
|
+
export interface StartDirectInput {
|
|
89
|
+
targetUserId: string;
|
|
90
|
+
opener?: {
|
|
91
|
+
text: string;
|
|
92
|
+
messageId?: string;
|
|
93
|
+
} | null;
|
|
94
|
+
selection?: DirectConversationSelection;
|
|
95
|
+
}
|
|
96
|
+
export type StartDirectResult = {
|
|
97
|
+
status: 'opened' | 'messaged';
|
|
98
|
+
conversationId: string;
|
|
99
|
+
messageId?: string;
|
|
100
|
+
created?: boolean;
|
|
101
|
+
reused?: boolean;
|
|
102
|
+
} | {
|
|
103
|
+
status: 'requested' | 'pending';
|
|
104
|
+
requestId: string;
|
|
105
|
+
} | {
|
|
106
|
+
status: 'blocked' | 'unavailable';
|
|
107
|
+
reason: string;
|
|
108
|
+
};
|
|
109
|
+
export declare function parseDirectConversationSelection(value: unknown): DirectConversationSelection;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** Missing or invalid policy never widens access. */
|
|
2
|
+
export function readCommunicationRule(value) {
|
|
3
|
+
if (value === 'open' || value === 'approval-required' || value === 'closed') {
|
|
4
|
+
return value;
|
|
5
|
+
}
|
|
6
|
+
return 'approval-required';
|
|
7
|
+
}
|
|
8
|
+
export function parseDirectConversationSelection(value) {
|
|
9
|
+
if (value == null)
|
|
10
|
+
return { mode: 'latest_or_new' };
|
|
11
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
12
|
+
throw new Error('selection must be an object');
|
|
13
|
+
}
|
|
14
|
+
const record = value;
|
|
15
|
+
if (record.mode === 'latest_or_new' || record.mode === 'new') {
|
|
16
|
+
return { mode: record.mode };
|
|
17
|
+
}
|
|
18
|
+
if (record.mode === 'specific') {
|
|
19
|
+
const conversationId = typeof record.conversationId === 'string'
|
|
20
|
+
? record.conversationId.trim()
|
|
21
|
+
: '';
|
|
22
|
+
if (!conversationId)
|
|
23
|
+
throw new Error('selection.conversationId is required');
|
|
24
|
+
return { mode: 'specific', conversationId };
|
|
25
|
+
}
|
|
26
|
+
throw new Error('selection.mode is invalid');
|
|
27
|
+
}
|
|
@@ -3,7 +3,7 @@ export declare function normalizeStoredString(value: unknown): string | null;
|
|
|
3
3
|
/**
|
|
4
4
|
* Firestore Timestamp-like -> ISO 8601, or null. Accepts only objects exposing
|
|
5
5
|
* `toDate()`. A raw `Date` is deliberately NOT accepted: that matches both call
|
|
6
|
-
* sites this replaced. `message.ts`
|
|
6
|
+
* sites this replaced. `message.ts` keeps its own
|
|
7
7
|
* Date-tolerant normalizers — a different contract, not this one.
|
|
8
8
|
*/
|
|
9
9
|
export declare function firestoreTimestampToISOString(value: unknown): string | null;
|
package/dist/firestoreValues.js
CHANGED
|
@@ -10,7 +10,7 @@ export function normalizeStoredString(value) {
|
|
|
10
10
|
/**
|
|
11
11
|
* Firestore Timestamp-like -> ISO 8601, or null. Accepts only objects exposing
|
|
12
12
|
* `toDate()`. A raw `Date` is deliberately NOT accepted: that matches both call
|
|
13
|
-
* sites this replaced. `message.ts`
|
|
13
|
+
* sites this replaced. `message.ts` keeps its own
|
|
14
14
|
* Date-tolerant normalizers — a different contract, not this one.
|
|
15
15
|
*/
|
|
16
16
|
export function firestoreTimestampToISOString(value) {
|
package/dist/index.d.ts
CHANGED
|
@@ -8,12 +8,12 @@ export * from './runtimeCardStorage.js';
|
|
|
8
8
|
export * from './turnProtocol.js';
|
|
9
9
|
export * from './agentBehaviorPolicy.js';
|
|
10
10
|
export * from './agentSearch.js';
|
|
11
|
-
export * from './contactRequest.js';
|
|
12
11
|
export * from './verbContract.js';
|
|
13
12
|
export * from './verbSchemas.js';
|
|
14
13
|
export * from './verbWire.js';
|
|
15
|
-
export * from './
|
|
14
|
+
export * from './communication.js';
|
|
16
15
|
export * from './apiErrors.js';
|
|
17
16
|
export * from './firestoreValues.js';
|
|
18
17
|
export * from './moderation.js';
|
|
19
18
|
export * from './selfContext.js';
|
|
19
|
+
export * from './replyAuthority.js';
|
package/dist/index.js
CHANGED
|
@@ -8,12 +8,12 @@ export * from './runtimeCardStorage.js';
|
|
|
8
8
|
export * from './turnProtocol.js';
|
|
9
9
|
export * from './agentBehaviorPolicy.js';
|
|
10
10
|
export * from './agentSearch.js';
|
|
11
|
-
export * from './contactRequest.js';
|
|
12
11
|
export * from './verbContract.js';
|
|
13
12
|
export * from './verbSchemas.js';
|
|
14
13
|
export * from './verbWire.js';
|
|
15
|
-
export * from './
|
|
14
|
+
export * from './communication.js';
|
|
16
15
|
export * from './apiErrors.js';
|
|
17
16
|
export * from './firestoreValues.js';
|
|
18
17
|
export * from './moderation.js';
|
|
19
18
|
export * from './selfContext.js';
|
|
19
|
+
export * from './replyAuthority.js';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Opaque, server-issued authority for one agent reply to one inbound message.
|
|
3
|
+
*
|
|
4
|
+
* The stream delivers this beside the triggering message. Runtimes keep it out
|
|
5
|
+
* of model-visible schemas and return it only on the ordinary reply path.
|
|
6
|
+
*/
|
|
7
|
+
export interface AgentReplyAuthorityV1 {
|
|
8
|
+
schema: 'canon.agent-reply-authority.v1';
|
|
9
|
+
sourceMessageId: string;
|
|
10
|
+
token: string;
|
|
11
|
+
expiresAt: string;
|
|
12
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|