@canonmsg/backend-contracts 1.7.0 → 1.8.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/agentBehaviorPolicy.d.ts +86 -45
- package/dist/agentBehaviorPolicy.js +53 -0
- package/dist/bridgeLocal.d.ts +1729 -0
- package/dist/bridgeLocal.js +673 -0
- package/dist/cjs/agentBehaviorPolicy.js +54 -1
- package/dist/cjs/bridgeLocal.js +676 -0
- package/dist/cjs/contactRequest.js +30 -0
- package/dist/cjs/controlSignals.js +44 -0
- package/dist/cjs/endpointRegistry.js +264 -0
- package/dist/cjs/hitl.js +171 -0
- package/dist/cjs/inboundFrame.js +92 -0
- package/dist/cjs/index.js +8 -0
- package/dist/cjs/media.js +13 -0
- package/dist/cjs/message.js +64 -0
- package/dist/cjs/restEndpoints.js +220 -0
- package/dist/cjs/runtimeCardFields.js +58 -1
- package/dist/cjs/sendContextual.js +92 -0
- package/dist/cjs/sseEvents.js +298 -0
- package/dist/cjs/turnProtocol.js +41 -2
- package/dist/contactRequest.d.ts +42 -23
- package/dist/contactRequest.js +29 -0
- package/dist/controlSignals.d.ts +55 -0
- package/dist/controlSignals.js +41 -0
- package/dist/endpointRegistry.d.ts +13 -0
- package/dist/endpointRegistry.js +261 -0
- package/dist/hitl.d.ts +303 -0
- package/dist/hitl.js +168 -0
- package/dist/inboundFrame.d.ts +229 -0
- package/dist/inboundFrame.js +89 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +8 -0
- package/dist/media.d.ts +24 -11
- package/dist/media.js +12 -0
- package/dist/message.d.ts +133 -50
- package/dist/message.js +64 -1
- package/dist/restEndpoints.d.ts +496 -0
- package/dist/restEndpoints.js +217 -0
- package/dist/runtimeCardFields.d.ts +112 -39
- package/dist/runtimeCardFields.js +57 -0
- package/dist/schemas/agent-behavior-settings-record.schema.json +48 -0
- package/dist/schemas/bridge-connection-state-notification.schema.json +19 -0
- package/dist/schemas/bridge-get-attachment-params.schema.json +24 -0
- package/dist/schemas/bridge-get-attachment-result.schema.json +20 -0
- package/dist/schemas/bridge-hello-params.schema.json +42 -0
- package/dist/schemas/bridge-hello-result.schema.json +105 -0
- package/dist/schemas/bridge-hitl-state.schema.json +38 -0
- package/dist/schemas/bridge-ok-result.schema.json +15 -0
- package/dist/schemas/bridge-ready-notification.schema.json +79 -0
- package/dist/schemas/bridge-resync-reason.schema.json +9 -0
- package/dist/schemas/bridge-resync.schema.json +18 -0
- package/dist/schemas/bridge-rpc-error.schema.json +19 -0
- package/dist/schemas/bridge-rpc-id.schema.json +12 -0
- package/dist/schemas/bridge-rpc-notification.schema.json +20 -0
- package/dist/schemas/bridge-rpc-request.schema.json +31 -0
- package/dist/schemas/bridge-rpc-response.schema.json +81 -0
- package/dist/schemas/bridge-status-result.schema.json +76 -0
- package/dist/schemas/bridge-upload-media-params.schema.json +28 -0
- package/dist/schemas/bridge-upstream-state.schema.json +10 -0
- package/dist/schemas/contacts-response.schema.json +52 -0
- package/dist/schemas/control-channel-key.schema.json +10 -0
- package/dist/schemas/control-primitive-event.schema.json +30 -0
- package/dist/schemas/control-primitive-map.schema.json +15 -0
- package/dist/schemas/control-session-event.schema.json +26 -0
- package/dist/schemas/control-session-node.schema.json +11 -0
- package/dist/schemas/control-signal-event.schema.json +35 -0
- package/dist/schemas/control-signal-node.schema.json +22 -0
- package/dist/schemas/control-signal-type.schema.json +10 -0
- package/dist/schemas/conversations-response.schema.json +127 -0
- package/dist/schemas/create-contact-request-request.schema.json +17 -0
- package/dist/schemas/create-contact-request-response.schema.json +51 -0
- package/dist/schemas/create-conversation-request.schema.json +82 -0
- package/dist/schemas/create-conversation-response.schema.json +29 -0
- package/dist/schemas/delete-message-response.schema.json +11 -0
- package/dist/schemas/delivery-intent.schema.json +11 -0
- package/dist/schemas/forward-message-request.schema.json +25 -0
- package/dist/schemas/forward-message-response.schema.json +35 -0
- package/dist/schemas/forwarded-from.schema.json +18 -0
- package/dist/schemas/get-messages-query.schema.json +17 -0
- package/dist/schemas/hitl-approval-category.schema.json +15 -0
- package/dist/schemas/hitl-approval-detail.schema.json +21 -0
- package/dist/schemas/hitl-approval-outcome-record.schema.json +33 -0
- package/dist/schemas/hitl-approval-reply-record.schema.json +57 -0
- package/dist/schemas/hitl-approval-request-record.schema.json +105 -0
- package/dist/schemas/hitl-approval-risk.schema.json +11 -0
- package/dist/schemas/hitl-card-outcome-record.schema.json +48 -0
- package/dist/schemas/hitl-card-reply-record.schema.json +46 -0
- package/dist/schemas/hitl-card-request-record.schema.json +73 -0
- package/dist/schemas/hitl-input-answers.schema.json +23 -0
- package/dist/schemas/hitl-input-kind.schema.json +10 -0
- package/dist/schemas/hitl-input-outcome-record.schema.json +46 -0
- package/dist/schemas/hitl-input-question.schema.json +54 -0
- package/dist/schemas/hitl-input-reply-record.schema.json +44 -0
- package/dist/schemas/hitl-input-request-record.schema.json +134 -0
- package/dist/schemas/hitl-pending.schema.json +31 -0
- package/dist/schemas/hitl-request-accepted.schema.json +18 -0
- package/dist/schemas/hitl-request-kind.schema.json +10 -0
- package/dist/schemas/hitl-resolution-status.schema.json +10 -0
- package/dist/schemas/hitl-resolution.schema.json +38 -0
- package/dist/schemas/hitl-session-rule.schema.json +32 -0
- package/dist/schemas/inbound-disposition.schema.json +13 -0
- package/dist/schemas/inbound-frame-attachment-v1.schema.json +94 -0
- package/dist/schemas/inbound-frame-contact-card-v1.schema.json +59 -0
- package/dist/schemas/inbound-frame-group-context-v1.schema.json +96 -0
- package/dist/schemas/inbound-frame-reply-context-v1.schema.json +261 -0
- package/dist/schemas/inbound-frame-shape-v1.schema.json +12 -0
- package/dist/schemas/inbound-frame-v1.schema.json +506 -0
- package/dist/schemas/mark-read-response.schema.json +11 -0
- package/dist/schemas/media-attachment-kind.schema.json +11 -0
- package/dist/schemas/media-attachment.schema.json +42 -0
- package/dist/schemas/messages-page-response.schema.json +290 -0
- package/dist/schemas/participation-decision-input.schema.json +44 -0
- package/dist/schemas/participation-history-message.schema.json +23 -0
- package/dist/schemas/participation-history-snapshot.schema.json +37 -0
- package/dist/schemas/participation-style.schema.json +13 -0
- package/dist/schemas/react-request.schema.json +22 -0
- package/dist/schemas/react-response.schema.json +35 -0
- package/dist/schemas/resolve-admission-request.schema.json +30 -0
- package/dist/schemas/resolve-admission-response.schema.json +129 -0
- package/dist/schemas/resolved-agent-behavior-policy-record.schema.json +81 -0
- package/dist/schemas/rest-contact.schema.json +40 -0
- package/dist/schemas/rest-conversation.schema.json +115 -0
- package/dist/schemas/rest-message.schema.json +252 -0
- package/dist/schemas/rest-ok-response.schema.json +11 -0
- package/dist/schemas/rest-session-selection.schema.json +40 -0
- package/dist/schemas/runtime-card-field-choice.schema.json +23 -0
- package/dist/schemas/runtime-card-field-type.schema.json +17 -0
- package/dist/schemas/runtime-card-field.schema.json +180 -0
- package/dist/schemas/runtime-card-line-item-column-type.schema.json +12 -0
- package/dist/schemas/runtime-card-line-item-column.schema.json +74 -0
- package/dist/schemas/send-contextual-deferred-response.schema.json +39 -0
- package/dist/schemas/send-contextual-messaged-response.schema.json +42 -0
- package/dist/schemas/send-contextual-request.schema.json +103 -0
- package/dist/schemas/send-contextual-response.schema.json +105 -0
- package/dist/schemas/send-contextual-self-context.schema.json +19 -0
- package/dist/schemas/send-contextual-state-response.schema.json +24 -0
- package/dist/schemas/send-message-request.schema.json +106 -0
- package/dist/schemas/send-message-response.schema.json +14 -0
- package/dist/schemas/sender-type.schema.json +9 -0
- package/dist/schemas/serialize-message-input.schema.json +29 -0
- package/dist/schemas/serialized-agent-client-type.schema.json +12 -0
- package/dist/schemas/serialized-contact-card.schema.json +65 -0
- package/dist/schemas/serialized-contact-request-status.schema.json +11 -0
- package/dist/schemas/serialized-contact-request.schema.json +157 -0
- package/dist/schemas/serialized-content-type.schema.json +13 -0
- package/dist/schemas/serialized-message.schema.json +249 -0
- package/dist/schemas/serialized-reactions.schema.json +14 -0
- package/dist/schemas/serialized-sender-type.schema.json +9 -0
- package/dist/schemas/set-streaming-request.schema.json +67 -0
- package/dist/schemas/set-typing-request.schema.json +25 -0
- package/dist/schemas/sse-access-policy.schema.json +10 -0
- package/dist/schemas/sse-agent-context-payload.schema.json +57 -0
- package/dist/schemas/sse-connected-payload.schema.json +18 -0
- package/dist/schemas/sse-contact-payload.schema.json +40 -0
- package/dist/schemas/sse-contact-removed-payload.schema.json +14 -0
- package/dist/schemas/sse-contact-request-payload.schema.json +157 -0
- package/dist/schemas/sse-conversation-updated-payload.schema.json +48 -0
- package/dist/schemas/sse-error-payload.schema.json +23 -0
- package/dist/schemas/sse-event-envelope.schema.json +42 -0
- package/dist/schemas/sse-event-family.schema.json +12 -0
- package/dist/schemas/sse-event-type.schema.json +28 -0
- package/dist/schemas/sse-heartbeat-payload.schema.json +14 -0
- package/dist/schemas/sse-membership-change.schema.json +28 -0
- package/dist/schemas/sse-message-created-payload.schema.json +414 -0
- package/dist/schemas/sse-message-deleted-payload.schema.json +18 -0
- package/dist/schemas/sse-message-updated-payload.schema.json +46 -0
- package/dist/schemas/sse-presence-payload.schema.json +21 -0
- package/dist/schemas/sse-provenance.schema.json +64 -0
- package/dist/schemas/sse-replay-expired-payload.schema.json +21 -0
- package/dist/schemas/sse-runtime-control-kind.schema.json +13 -0
- package/dist/schemas/sse-runtime-control-payload.schema.json +44 -0
- package/dist/schemas/sse-runtime-updated-payload.schema.json +78 -0
- package/dist/schemas/sse-self-context.schema.json +45 -0
- package/dist/schemas/sse-turn-dispatch.schema.json +29 -0
- package/dist/schemas/sse-turn-updated-payload.schema.json +33 -0
- package/dist/schemas/sse-typing-payload.schema.json +32 -0
- package/dist/schemas/sse-voice-session-event-payload.schema.json +170 -0
- package/dist/schemas/sse-voice-session.schema.json +157 -0
- package/dist/schemas/trigger-decision.schema.json +27 -0
- package/dist/schemas/turn-lifecycle-state.schema.json +14 -0
- package/dist/schemas/turn-message-semantics.schema.json +10 -0
- package/dist/schemas/turn-metadata.schema.json +56 -0
- package/dist/schemas/turn-state-like.schema.json +39 -0
- package/dist/schemas/update-disposition-request.schema.json +22 -0
- package/dist/schemas/upload-media-request.schema.json +25 -0
- package/dist/schemas/upload-media-response.schema.json +55 -0
- package/dist/sendContextual.d.ts +114 -0
- package/dist/sendContextual.js +89 -0
- package/dist/sseEvents.d.ts +494 -0
- package/dist/sseEvents.js +295 -0
- package/dist/turnProtocol.d.ts +91 -24
- package/dist/turnProtocol.js +40 -1
- package/package.json +8 -5
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
// Wire contract v1 — SSE event envelope + per-family payload schemas.
|
|
2
|
+
//
|
|
3
|
+
// Grounded in what stream-service ACTUALLY emits (stream-service/src/stream.ts
|
|
4
|
+
// + listeners.ts) and what @canonmsg/core's CanonStream consumes — not in
|
|
5
|
+
// design-doc prose. Payload slots that stream-service passes through opaquely
|
|
6
|
+
// (behavior policies, runtime snapshots, raw RTDB values) stay loose objects;
|
|
7
|
+
// slots stream-service constructs field-by-field are closed.
|
|
8
|
+
//
|
|
9
|
+
// The golden fixtures in @canonmsg/test-fixtures parse under these schemas;
|
|
10
|
+
// the future Python framework must pass the same fixtures.
|
|
11
|
+
import { z } from 'zod';
|
|
12
|
+
import { SerializedContactRequestSchema } from './contactRequest.js';
|
|
13
|
+
import { SerializedMessageSchema, SerializedReactionsSchema } from './message.js';
|
|
14
|
+
export const SseAccessPolicySchema = z.enum(['open', 'approval-required', 'owner-only']);
|
|
15
|
+
// ── Lifecycle events ───────────────────────────────────────────────────
|
|
16
|
+
export const SseConnectedPayloadSchema = z.object({
|
|
17
|
+
connectionId: z.string(),
|
|
18
|
+
agentId: z.string(),
|
|
19
|
+
});
|
|
20
|
+
/** Trusted, server-injected identity & access info (stream.ts `agent.context`). */
|
|
21
|
+
export const SseAgentContextPayloadSchema = z.looseObject({
|
|
22
|
+
agentId: z.string(),
|
|
23
|
+
canonContactId: z.string().optional(),
|
|
24
|
+
clientType: z.string().optional(),
|
|
25
|
+
ownerId: z.string(),
|
|
26
|
+
ownerName: z.string(),
|
|
27
|
+
/** Resolved agent behavior policy — passed through opaquely. */
|
|
28
|
+
defaultBehavior: z.record(z.string(), z.unknown()).optional(),
|
|
29
|
+
inboundPolicy: SseAccessPolicySchema,
|
|
30
|
+
groupJoinPolicy: SseAccessPolicySchema,
|
|
31
|
+
discoverable: z.boolean(),
|
|
32
|
+
});
|
|
33
|
+
export const SseHeartbeatPayloadSchema = z.object({
|
|
34
|
+
timestamp: z.string(),
|
|
35
|
+
});
|
|
36
|
+
export const SseReplayExpiredPayloadSchema = z.looseObject({
|
|
37
|
+
lastAvailableId: z.string().nullable().optional(),
|
|
38
|
+
message: z.string().optional(),
|
|
39
|
+
});
|
|
40
|
+
export const SseErrorPayloadSchema = z.looseObject({
|
|
41
|
+
code: z.string().optional(),
|
|
42
|
+
message: z.string().optional(),
|
|
43
|
+
retryAfterMs: z.number().optional(),
|
|
44
|
+
activeConnections: z.number().optional(),
|
|
45
|
+
maxConnections: z.number().optional(),
|
|
46
|
+
});
|
|
47
|
+
// ── Messages family ────────────────────────────────────────────────────
|
|
48
|
+
export const SseSelfContextSchema = z.object({
|
|
49
|
+
id: z.string(),
|
|
50
|
+
type: z.literal('cross_session'),
|
|
51
|
+
context: z.string(),
|
|
52
|
+
createdAt: z.string().nullable(),
|
|
53
|
+
updatedAt: z.string().nullable(),
|
|
54
|
+
});
|
|
55
|
+
export const SseTurnDispatchSchema = z.looseObject({
|
|
56
|
+
kind: z.enum(['run_turn', 'observe_only']),
|
|
57
|
+
reason: z.string(),
|
|
58
|
+
addressed: z.boolean(),
|
|
59
|
+
policyVersion: z.string().optional(),
|
|
60
|
+
});
|
|
61
|
+
export const SseProvenanceSchema = z.looseObject({
|
|
62
|
+
conversation: z.looseObject({
|
|
63
|
+
id: z.string(),
|
|
64
|
+
type: z.enum(['direct', 'group', 'unknown']),
|
|
65
|
+
}),
|
|
66
|
+
sender: z.looseObject({
|
|
67
|
+
id: z.string(),
|
|
68
|
+
name: z.string().optional(),
|
|
69
|
+
type: z.enum(['human', 'ai_agent']),
|
|
70
|
+
isOwner: z.boolean(),
|
|
71
|
+
}),
|
|
72
|
+
mentionedAgent: z.boolean(),
|
|
73
|
+
});
|
|
74
|
+
/**
|
|
75
|
+
* `message.created` — the inbound message envelope. `message` is exactly the
|
|
76
|
+
* SerializedMessage the shared serializer emits (the E2EE S1 slot).
|
|
77
|
+
*/
|
|
78
|
+
export const SseMessageCreatedPayloadSchema = z.looseObject({
|
|
79
|
+
conversationId: z.string(),
|
|
80
|
+
/** Resolved agent behavior policy — passed through opaquely. */
|
|
81
|
+
behavior: z.record(z.string(), z.unknown()).optional(),
|
|
82
|
+
activeSelfContextId: z.string().nullable().optional(),
|
|
83
|
+
selfContexts: z.array(SseSelfContextSchema).optional(),
|
|
84
|
+
provenance: SseProvenanceSchema.optional(),
|
|
85
|
+
turnDispatch: SseTurnDispatchSchema.optional(),
|
|
86
|
+
message: SerializedMessageSchema,
|
|
87
|
+
});
|
|
88
|
+
export const SseMessageUpdatedPayloadSchema = z.object({
|
|
89
|
+
conversationId: z.string(),
|
|
90
|
+
messageId: z.string(),
|
|
91
|
+
actorId: z.string().optional(),
|
|
92
|
+
updatedAt: z.string().optional(),
|
|
93
|
+
changes: z.looseObject({
|
|
94
|
+
reactions: SerializedReactionsSchema,
|
|
95
|
+
}),
|
|
96
|
+
});
|
|
97
|
+
export const SseMessageDeletedPayloadSchema = z.object({
|
|
98
|
+
conversationId: z.string(),
|
|
99
|
+
messageId: z.string(),
|
|
100
|
+
});
|
|
101
|
+
export const SseMembershipChangeSchema = z.object({
|
|
102
|
+
addedMemberIds: z.array(z.string()),
|
|
103
|
+
removedMemberIds: z.array(z.string()),
|
|
104
|
+
memberCount: z.number(),
|
|
105
|
+
});
|
|
106
|
+
export const SseConversationUpdatedPayloadSchema = z.object({
|
|
107
|
+
conversationId: z.string(),
|
|
108
|
+
changes: z.record(z.string(), z.unknown()),
|
|
109
|
+
membershipChange: SseMembershipChangeSchema.optional(),
|
|
110
|
+
});
|
|
111
|
+
// ── Contacts family ────────────────────────────────────────────────────
|
|
112
|
+
/** `contact.request` / `contact.approved` carry the serialized contact request. */
|
|
113
|
+
export const SseContactRequestPayloadSchema = SerializedContactRequestSchema;
|
|
114
|
+
/**
|
|
115
|
+
* `contact.added` / `contact.updated`. `source` is a pass-through string —
|
|
116
|
+
* canonical values today: direct_add, phone_book, contact_request, link, qr,
|
|
117
|
+
* group, open_inbound_message, unknown.
|
|
118
|
+
*/
|
|
119
|
+
export const SseContactPayloadSchema = z.object({
|
|
120
|
+
id: z.string(),
|
|
121
|
+
source: z.string(),
|
|
122
|
+
addedAt: z.string().nullable(),
|
|
123
|
+
displayNameOverride: z.string().nullable(),
|
|
124
|
+
});
|
|
125
|
+
export const SseContactRemovedPayloadSchema = z.object({
|
|
126
|
+
id: z.string(),
|
|
127
|
+
});
|
|
128
|
+
// ── Typing / presence family ───────────────────────────────────────────
|
|
129
|
+
export const SseTypingPayloadSchema = z.object({
|
|
130
|
+
conversationId: z.string(),
|
|
131
|
+
userId: z.string(),
|
|
132
|
+
isTyping: z.boolean(),
|
|
133
|
+
status: z.enum(['thinking', 'typing']).optional(),
|
|
134
|
+
timestamp: z.number().optional(),
|
|
135
|
+
});
|
|
136
|
+
export const SsePresencePayloadSchema = z.object({
|
|
137
|
+
userId: z.string(),
|
|
138
|
+
online: z.boolean(),
|
|
139
|
+
lastSeen: z.string().optional(),
|
|
140
|
+
});
|
|
141
|
+
// ── Runtime / turn family ──────────────────────────────────────────────
|
|
142
|
+
/** Aggregated RTDB runtime snapshot — nodes are passed through opaquely. */
|
|
143
|
+
export const SseRuntimeUpdatedPayloadSchema = z.object({
|
|
144
|
+
conversationId: z.string(),
|
|
145
|
+
agentId: z.string(),
|
|
146
|
+
runtime: z.record(z.string(), z.unknown()).nullable(),
|
|
147
|
+
runtimeInfo: z.record(z.string(), z.unknown()).nullable(),
|
|
148
|
+
sessionState: z.record(z.string(), z.unknown()).nullable(),
|
|
149
|
+
sessionConfig: z.record(z.string(), z.unknown()).nullable(),
|
|
150
|
+
});
|
|
151
|
+
export const SseTurnUpdatedPayloadSchema = z.object({
|
|
152
|
+
conversationId: z.string(),
|
|
153
|
+
agentId: z.string(),
|
|
154
|
+
turn: z.record(z.string(), z.unknown()).nullable(),
|
|
155
|
+
});
|
|
156
|
+
export const SseRuntimeControlKindSchema = z.enum([
|
|
157
|
+
'session',
|
|
158
|
+
'signal',
|
|
159
|
+
'primitive',
|
|
160
|
+
'runtimeInput',
|
|
161
|
+
'runtimeCard',
|
|
162
|
+
'runtimeApproval',
|
|
163
|
+
]);
|
|
164
|
+
export const SseRuntimeControlPayloadSchema = z.object({
|
|
165
|
+
conversationId: z.string(),
|
|
166
|
+
agentId: z.string(),
|
|
167
|
+
kind: SseRuntimeControlKindSchema,
|
|
168
|
+
requestId: z.string().optional(),
|
|
169
|
+
updatedAt: z.number().optional(),
|
|
170
|
+
value: z.record(z.string(), z.unknown()),
|
|
171
|
+
});
|
|
172
|
+
// ── Voice family ───────────────────────────────────────────────────────
|
|
173
|
+
export const SseVoiceSessionSchema = z.looseObject({
|
|
174
|
+
id: z.string(),
|
|
175
|
+
conversationId: z.string(),
|
|
176
|
+
roomName: z.string(),
|
|
177
|
+
mode: z.enum(['human', 'runtime_voice']),
|
|
178
|
+
status: z.enum(['active', 'ended', 'error']),
|
|
179
|
+
createdBy: z.string(),
|
|
180
|
+
participantIds: z.array(z.string()),
|
|
181
|
+
participants: z.array(z.looseObject({
|
|
182
|
+
userId: z.string(),
|
|
183
|
+
userType: z.enum(['human', 'ai_agent', 'system']),
|
|
184
|
+
displayName: z.string().nullable(),
|
|
185
|
+
joinedAt: z.string().nullable(),
|
|
186
|
+
leftAt: z.string().nullable(),
|
|
187
|
+
})).optional(),
|
|
188
|
+
targetAgentId: z.string().nullable().optional(),
|
|
189
|
+
createdAt: z.string().nullable().optional(),
|
|
190
|
+
updatedAt: z.string().nullable().optional(),
|
|
191
|
+
endedAt: z.string().nullable().optional(),
|
|
192
|
+
error: z.string().nullable().optional(),
|
|
193
|
+
});
|
|
194
|
+
export const SseVoiceSessionEventPayloadSchema = z.object({
|
|
195
|
+
conversationId: z.string(),
|
|
196
|
+
session: SseVoiceSessionSchema,
|
|
197
|
+
});
|
|
198
|
+
// ── Envelope + registry ────────────────────────────────────────────────
|
|
199
|
+
/**
|
|
200
|
+
* Every SSE `event:` name stream-service emits today (stream.ts + listeners.ts;
|
|
201
|
+
* mirrored by CanonStream's dispatch switch in core). NOTE: `contact.updated`
|
|
202
|
+
* is emitted by stream-service but not yet consumed by CanonStream.
|
|
203
|
+
*/
|
|
204
|
+
export const SSE_EVENT_TYPES = [
|
|
205
|
+
'connected',
|
|
206
|
+
'agent.context',
|
|
207
|
+
'heartbeat',
|
|
208
|
+
'message.created',
|
|
209
|
+
'message.updated',
|
|
210
|
+
'message.deleted',
|
|
211
|
+
'conversation.updated',
|
|
212
|
+
'contact.request',
|
|
213
|
+
'contact.approved',
|
|
214
|
+
'contact.added',
|
|
215
|
+
'contact.updated',
|
|
216
|
+
'contact.removed',
|
|
217
|
+
'typing',
|
|
218
|
+
'presence',
|
|
219
|
+
'runtime.updated',
|
|
220
|
+
'turn.updated',
|
|
221
|
+
'runtime.control',
|
|
222
|
+
'voice.session.started',
|
|
223
|
+
'voice.session.ended',
|
|
224
|
+
'replay.expired',
|
|
225
|
+
'error',
|
|
226
|
+
];
|
|
227
|
+
export const SseEventTypeSchema = z.enum(SSE_EVENT_TYPES);
|
|
228
|
+
/** Payload schema for every event type — the machine-readable event registry. */
|
|
229
|
+
export const SSE_EVENT_PAYLOAD_SCHEMAS = {
|
|
230
|
+
'connected': SseConnectedPayloadSchema,
|
|
231
|
+
'agent.context': SseAgentContextPayloadSchema,
|
|
232
|
+
'heartbeat': SseHeartbeatPayloadSchema,
|
|
233
|
+
'message.created': SseMessageCreatedPayloadSchema,
|
|
234
|
+
'message.updated': SseMessageUpdatedPayloadSchema,
|
|
235
|
+
'message.deleted': SseMessageDeletedPayloadSchema,
|
|
236
|
+
'conversation.updated': SseConversationUpdatedPayloadSchema,
|
|
237
|
+
'contact.request': SseContactRequestPayloadSchema,
|
|
238
|
+
'contact.approved': SseContactRequestPayloadSchema,
|
|
239
|
+
'contact.added': SseContactPayloadSchema,
|
|
240
|
+
'contact.updated': SseContactPayloadSchema,
|
|
241
|
+
'contact.removed': SseContactRemovedPayloadSchema,
|
|
242
|
+
'typing': SseTypingPayloadSchema,
|
|
243
|
+
'presence': SsePresencePayloadSchema,
|
|
244
|
+
'runtime.updated': SseRuntimeUpdatedPayloadSchema,
|
|
245
|
+
'turn.updated': SseTurnUpdatedPayloadSchema,
|
|
246
|
+
'runtime.control': SseRuntimeControlPayloadSchema,
|
|
247
|
+
'voice.session.started': SseVoiceSessionEventPayloadSchema,
|
|
248
|
+
'voice.session.ended': SseVoiceSessionEventPayloadSchema,
|
|
249
|
+
'replay.expired': SseReplayExpiredPayloadSchema,
|
|
250
|
+
'error': SseErrorPayloadSchema,
|
|
251
|
+
};
|
|
252
|
+
/**
|
|
253
|
+
* Subscription families (`?events=` filter). Lifecycle events (`connected`,
|
|
254
|
+
* `agent.context`, `heartbeat`, `replay.expired`, `error`) are always sent.
|
|
255
|
+
*/
|
|
256
|
+
export const SSE_EVENT_FAMILIES = [
|
|
257
|
+
'messages',
|
|
258
|
+
'contacts',
|
|
259
|
+
'typing_presence',
|
|
260
|
+
'runtime_turn',
|
|
261
|
+
'voice',
|
|
262
|
+
];
|
|
263
|
+
export const SseEventFamilySchema = z.enum(SSE_EVENT_FAMILIES);
|
|
264
|
+
export const SSE_EVENT_FAMILY_BY_TYPE = {
|
|
265
|
+
'connected': 'lifecycle',
|
|
266
|
+
'agent.context': 'lifecycle',
|
|
267
|
+
'heartbeat': 'lifecycle',
|
|
268
|
+
'message.created': 'messages',
|
|
269
|
+
'message.updated': 'messages',
|
|
270
|
+
'message.deleted': 'messages',
|
|
271
|
+
'conversation.updated': 'messages',
|
|
272
|
+
'contact.request': 'contacts',
|
|
273
|
+
'contact.approved': 'contacts',
|
|
274
|
+
'contact.added': 'contacts',
|
|
275
|
+
'contact.updated': 'contacts',
|
|
276
|
+
'contact.removed': 'contacts',
|
|
277
|
+
'typing': 'typing_presence',
|
|
278
|
+
'presence': 'typing_presence',
|
|
279
|
+
'runtime.updated': 'runtime_turn',
|
|
280
|
+
'turn.updated': 'runtime_turn',
|
|
281
|
+
'runtime.control': 'runtime_turn',
|
|
282
|
+
'voice.session.started': 'voice',
|
|
283
|
+
'voice.session.ended': 'voice',
|
|
284
|
+
'replay.expired': 'lifecycle',
|
|
285
|
+
'error': 'lifecycle',
|
|
286
|
+
};
|
|
287
|
+
/**
|
|
288
|
+
* A parsed SSE frame: `id:` (replay cursor), `event:`, and the JSON-decoded
|
|
289
|
+
* `data:` payload. Validate `data` with SSE_EVENT_PAYLOAD_SCHEMAS[event].
|
|
290
|
+
*/
|
|
291
|
+
export const SseEventEnvelopeSchema = z.object({
|
|
292
|
+
id: z.string().optional(),
|
|
293
|
+
event: SseEventTypeSchema,
|
|
294
|
+
data: z.unknown(),
|
|
295
|
+
});
|
package/dist/turnProtocol.d.ts
CHANGED
|
@@ -1,27 +1,94 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const SenderTypeSchema: z.ZodEnum<{
|
|
3
|
+
human: "human";
|
|
4
|
+
ai_agent: "ai_agent";
|
|
5
|
+
}>;
|
|
6
|
+
export type SenderType = z.infer<typeof SenderTypeSchema>;
|
|
7
|
+
export declare const TurnLifecycleStateSchema: z.ZodEnum<{
|
|
8
|
+
idle: "idle";
|
|
9
|
+
thinking: "thinking";
|
|
10
|
+
streaming: "streaming";
|
|
11
|
+
tool: "tool";
|
|
12
|
+
waiting_input: "waiting_input";
|
|
13
|
+
completed: "completed";
|
|
14
|
+
interrupted: "interrupted";
|
|
15
|
+
}>;
|
|
16
|
+
export type TurnLifecycleState = z.infer<typeof TurnLifecycleStateSchema>;
|
|
17
|
+
export declare const TurnMessageSemanticsSchema: z.ZodEnum<{
|
|
18
|
+
progress: "progress";
|
|
19
|
+
turn_complete: "turn_complete";
|
|
20
|
+
control: "control";
|
|
21
|
+
}>;
|
|
22
|
+
export type TurnMessageSemantics = z.infer<typeof TurnMessageSemanticsSchema>;
|
|
23
|
+
export declare const DeliveryIntentSchema: z.ZodEnum<{
|
|
24
|
+
queue: "queue";
|
|
25
|
+
interrupt: "interrupt";
|
|
26
|
+
interleave: "interleave";
|
|
27
|
+
stop: "stop";
|
|
28
|
+
}>;
|
|
29
|
+
export type DeliveryIntent = z.infer<typeof DeliveryIntentSchema>;
|
|
30
|
+
export declare const InboundDispositionSchema: z.ZodEnum<{
|
|
31
|
+
queued: "queued";
|
|
32
|
+
accepted_now: "accepted_now";
|
|
33
|
+
interleaved: "interleaved";
|
|
34
|
+
trigger_suppressed: "trigger_suppressed";
|
|
35
|
+
rejected: "rejected";
|
|
36
|
+
cancelled: "cancelled";
|
|
37
|
+
}>;
|
|
38
|
+
export type InboundDisposition = z.infer<typeof InboundDispositionSchema>;
|
|
39
|
+
export declare const TurnMetadataSchema: z.ZodObject<{
|
|
40
|
+
turnId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
41
|
+
turnSemantics: z.ZodOptional<z.ZodEnum<{
|
|
42
|
+
progress: "progress";
|
|
43
|
+
turn_complete: "turn_complete";
|
|
44
|
+
control: "control";
|
|
45
|
+
}>>;
|
|
46
|
+
deliveryIntent: z.ZodOptional<z.ZodEnum<{
|
|
47
|
+
queue: "queue";
|
|
48
|
+
interrupt: "interrupt";
|
|
49
|
+
interleave: "interleave";
|
|
50
|
+
stop: "stop";
|
|
51
|
+
}>>;
|
|
52
|
+
replyBehavior: z.ZodOptional<z.ZodEnum<{
|
|
53
|
+
allow_auto_reply: "allow_auto_reply";
|
|
54
|
+
suppress_auto_reply: "suppress_auto_reply";
|
|
55
|
+
}>>;
|
|
56
|
+
inboundDisposition: z.ZodOptional<z.ZodEnum<{
|
|
57
|
+
queued: "queued";
|
|
58
|
+
accepted_now: "accepted_now";
|
|
59
|
+
interleaved: "interleaved";
|
|
60
|
+
trigger_suppressed: "trigger_suppressed";
|
|
61
|
+
rejected: "rejected";
|
|
62
|
+
cancelled: "cancelled";
|
|
63
|
+
}>>;
|
|
64
|
+
requestedTurnMode: z.ZodOptional<z.ZodString>;
|
|
65
|
+
}, z.core.$strip>;
|
|
66
|
+
export type TurnMetadata = z.infer<typeof TurnMetadataSchema>;
|
|
67
|
+
export declare const TriggerDecisionSchema: z.ZodObject<{
|
|
68
|
+
allow: z.ZodBoolean;
|
|
69
|
+
semantics: z.ZodEnum<{
|
|
70
|
+
progress: "progress";
|
|
71
|
+
turn_complete: "turn_complete";
|
|
72
|
+
control: "control";
|
|
73
|
+
}>;
|
|
74
|
+
reason: z.ZodString;
|
|
75
|
+
}, z.core.$strip>;
|
|
76
|
+
export type TriggerDecision = z.infer<typeof TriggerDecisionSchema>;
|
|
77
|
+
export declare const TurnStateLikeSchema: z.ZodObject<{
|
|
78
|
+
state: z.ZodEnum<{
|
|
79
|
+
idle: "idle";
|
|
80
|
+
thinking: "thinking";
|
|
81
|
+
streaming: "streaming";
|
|
82
|
+
tool: "tool";
|
|
83
|
+
waiting_input: "waiting_input";
|
|
84
|
+
completed: "completed";
|
|
85
|
+
interrupted: "interrupted";
|
|
86
|
+
}>;
|
|
87
|
+
openedAt: z.ZodOptional<z.ZodNumber>;
|
|
88
|
+
updatedAt: z.ZodOptional<z.ZodNumber>;
|
|
89
|
+
turnUpdatedAt: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
90
|
+
}, z.core.$strip>;
|
|
91
|
+
export type TurnStateLike = z.infer<typeof TurnStateLikeSchema>;
|
|
25
92
|
export declare const ACTIVE_TURN_STALE_THRESHOLD_MS: number;
|
|
26
93
|
export declare const WAITING_INPUT_STALE_THRESHOLD_MS: number;
|
|
27
94
|
export declare function normalizeTurnMetadata(metadata: unknown): TurnMetadata | null;
|
package/dist/turnProtocol.js
CHANGED
|
@@ -1,3 +1,43 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export const SenderTypeSchema = z.enum(['human', 'ai_agent']);
|
|
3
|
+
export const TurnLifecycleStateSchema = z.enum([
|
|
4
|
+
'idle',
|
|
5
|
+
'thinking',
|
|
6
|
+
'streaming',
|
|
7
|
+
'tool',
|
|
8
|
+
'waiting_input',
|
|
9
|
+
'completed',
|
|
10
|
+
'interrupted',
|
|
11
|
+
]);
|
|
12
|
+
export const TurnMessageSemanticsSchema = z.enum(['progress', 'turn_complete', 'control']);
|
|
13
|
+
export const DeliveryIntentSchema = z.enum(['queue', 'interrupt', 'interleave', 'stop']);
|
|
14
|
+
export const InboundDispositionSchema = z.enum([
|
|
15
|
+
'queued',
|
|
16
|
+
'accepted_now',
|
|
17
|
+
'interleaved',
|
|
18
|
+
'trigger_suppressed',
|
|
19
|
+
'rejected',
|
|
20
|
+
'cancelled',
|
|
21
|
+
]);
|
|
22
|
+
export const TurnMetadataSchema = z.object({
|
|
23
|
+
turnId: z.string().nullable().optional(),
|
|
24
|
+
turnSemantics: TurnMessageSemanticsSchema.optional(),
|
|
25
|
+
deliveryIntent: DeliveryIntentSchema.optional(),
|
|
26
|
+
replyBehavior: z.enum(['allow_auto_reply', 'suppress_auto_reply']).optional(),
|
|
27
|
+
inboundDisposition: InboundDispositionSchema.optional(),
|
|
28
|
+
requestedTurnMode: z.string().optional(),
|
|
29
|
+
});
|
|
30
|
+
export const TriggerDecisionSchema = z.object({
|
|
31
|
+
allow: z.boolean(),
|
|
32
|
+
semantics: TurnMessageSemanticsSchema,
|
|
33
|
+
reason: z.string(),
|
|
34
|
+
});
|
|
35
|
+
export const TurnStateLikeSchema = z.object({
|
|
36
|
+
state: TurnLifecycleStateSchema,
|
|
37
|
+
openedAt: z.number().optional(),
|
|
38
|
+
updatedAt: z.number().optional(),
|
|
39
|
+
turnUpdatedAt: z.number().nullable().optional(),
|
|
40
|
+
});
|
|
1
41
|
export const ACTIVE_TURN_STALE_THRESHOLD_MS = 30 * 60 * 1000;
|
|
2
42
|
export const WAITING_INPUT_STALE_THRESHOLD_MS = 12 * 60 * 60 * 1000;
|
|
3
43
|
const TURN_SEMANTICS = [
|
|
@@ -19,7 +59,6 @@ function isHiddenRuntimeCardMetadata(metadata) {
|
|
|
19
59
|
return false;
|
|
20
60
|
return metadata.type === 'approval_reply'
|
|
21
61
|
|| metadata.type === 'approval_outcome'
|
|
22
|
-
|| metadata.type === 'question_reply'
|
|
23
62
|
|| metadata.type === 'plan_approval_reply'
|
|
24
63
|
|| metadata.type === 'runtime_input_reply'
|
|
25
64
|
|| metadata.type === 'runtime_input_outcome'
|
package/package.json
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@canonmsg/backend-contracts",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"description": "Canon backend contract helpers shared by Functions and stream-service",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/cjs/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
8
|
"exports": {
|
|
9
9
|
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
10
11
|
"import": "./dist/index.js",
|
|
11
|
-
"require": "./dist/cjs/index.js"
|
|
12
|
-
"types": "./dist/index.d.ts"
|
|
12
|
+
"require": "./dist/cjs/index.js"
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
15
|
"files": [
|
|
16
16
|
"dist"
|
|
17
17
|
],
|
|
18
18
|
"scripts": {
|
|
19
|
-
"build": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.json && tsc -p tsconfig.cjs.json && node -e \"require('fs').mkdirSync('dist/cjs',{recursive:true}); require('fs').writeFileSync('dist/cjs/package.json', JSON.stringify({type:'commonjs'}))\"",
|
|
19
|
+
"build": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.json && tsc -p tsconfig.cjs.json && node -e \"require('fs').mkdirSync('dist/cjs',{recursive:true}); require('fs').writeFileSync('dist/cjs/package.json', JSON.stringify({type:'commonjs'}))\" && node scripts/emit-json-schema.mjs",
|
|
20
20
|
"dev": "tsc -p tsconfig.json --watch",
|
|
21
21
|
"test": "vitest run",
|
|
22
22
|
"prepack": "npm run build"
|
|
@@ -44,5 +44,8 @@
|
|
|
44
44
|
"typescript": "~5.7.0",
|
|
45
45
|
"vitest": "^4.1.8"
|
|
46
46
|
},
|
|
47
|
-
"license": "MIT"
|
|
47
|
+
"license": "MIT",
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"zod": "^4.4.3"
|
|
50
|
+
}
|
|
48
51
|
}
|