(value: unknown)
| 129 | } |
| 130 | |
| 131 | export function decodeInteractionSnapshot(value: unknown): InteractionSnapshot { |
| 132 | const record = requireRecord(value, 'Interaction snapshot'); |
| 133 | assertExactKeys(record, 'Interaction snapshot', [ |
| 134 | 'schemaVersion', |
| 135 | 'interactionId', |
| 136 | 'sessionId', |
| 137 | 'turnId', |
| 138 | 'runId', |
| 139 | 'revision', |
| 140 | 'request', |
| 141 | 'status', |
| 142 | 'outcome', |
| 143 | ]); |
| 144 | if (record.schemaVersion !== INTERACTION_SCHEMA_VERSION) { |
| 145 | throw invalidProtocolFrame('Unsupported Interaction snapshot schema'); |
| 146 | } |
| 147 | |
| 148 | const request = decodeInteractionRequest(record.request); |
| 149 | const revision = requireInteractionRevision(record.revision); |
| 150 | const base: InteractionSnapshotBase = { |
| 151 | schemaVersion: INTERACTION_SCHEMA_VERSION, |
| 152 | interactionId: requireEntityId(record.interactionId, 'interactionId'), |
| 153 | sessionId: requireEntityId(record.sessionId, 'sessionId'), |
| 154 | turnId: requireEntityId(record.turnId, 'turnId'), |
| 155 | runId: requireEntityId(record.runId, 'runId'), |
| 156 | request, |
| 157 | }; |
| 158 | |
| 159 | if (record.status === 'pending') { |
| 160 | if (revision !== INTERACTION_PENDING_REVISION || record.outcome !== null) { |
| 161 | throw invalidProtocolFrame('Invalid pending Interaction snapshot'); |
| 162 | } |
| 163 | return { ...base, revision, status: 'pending', outcome: null }; |
| 164 | } |
| 165 | if (record.status !== 'answered' && record.status !== 'closed') { |
| 166 | throw invalidProtocolFrame('Invalid Interaction status'); |
| 167 | } |
| 168 | if (revision !== INTERACTION_RESOLVED_REVISION) { |
| 169 | throw invalidProtocolFrame('Invalid resolved Interaction revision'); |
| 170 | } |
| 171 | |
| 172 | const outcome = decodeInteractionCanonicalOutcome(record.outcome); |
| 173 | if (!isInteractionCanonicalOutcomeValidForRequest(request, outcome)) { |
| 174 | throw invalidProtocolFrame('Interaction outcome does not match its request'); |
| 175 | } |
| 176 | if (record.status === 'answered') { |
| 177 | if (outcome.kind === 'closure') { |
| 178 | throw invalidProtocolFrame('Answered Interaction has a closure outcome'); |
| 179 | } |
| 180 | return { ...base, revision, status: 'answered', outcome }; |
| 181 | } |
| 182 | if (outcome.kind !== 'closure') { |
| 183 | throw invalidProtocolFrame('Closed Interaction has an answer outcome'); |
| 184 | } |
| 185 | return { ...base, revision, status: 'closed', outcome }; |
| 186 | } |
| 187 | |
| 188 | export function decodeInteractionAnsweredSnapshot(value: unknown): InteractionAnsweredSnapshot { |
no test coverage detected