diff --git a/.changelog/f0080c1f15ae43c5a697801297110714.json b/.changelog/f0080c1f15ae43c5a697801297110714.json index ce58ca2f8aa..45f08d4b80c 100644 --- a/.changelog/f0080c1f15ae43c5a697801297110714.json +++ b/.changelog/f0080c1f15ae43c5a697801297110714.json @@ -2,7 +2,7 @@ "id": "f0080c1f-15ae-43c5-a697-801297110714", "type": "bugfix", "collapse": true, - "description": "Fixes a bug that prevented aws.EndpointResolverWithOptions from being used by the service client.", + "description": "Fixes a bug that prevented aws.EndpointResolverWithOptions from being used by the service client. ([#1514](https://github.com/aws/aws-sdk-go-v2/pull/1514))", "modules": [ "internal/protocoltest/awsrestjson", "internal/protocoltest/ec2query", @@ -306,4 +306,4 @@ "service/workspaces", "service/xray" ] -} \ No newline at end of file +} diff --git a/.changelog/f0b246281bad4ac285fe7d8e7a342a7d.json b/.changelog/f0b246281bad4ac285fe7d8e7a342a7d.json new file mode 100644 index 00000000000..e9949233db2 --- /dev/null +++ b/.changelog/f0b246281bad4ac285fe7d8e7a342a7d.json @@ -0,0 +1,8 @@ +{ + "id": "f0b24628-1bad-4ac2-85fe-7d8e7a342a7d", + "type": "feature", + "description": "Support has been added for the `StartConversation` API.", + "modules": [ + "service/lexruntimev2" + ] +} \ No newline at end of file diff --git a/codegen/smithy-aws-go-codegen/src/main/java/software/amazon/smithy/aws/go/codegen/FilterShapes.java b/codegen/smithy-aws-go-codegen/src/main/java/software/amazon/smithy/aws/go/codegen/FilterShapes.java index 290dda555bf..1cc8ee4dfbd 100644 --- a/codegen/smithy-aws-go-codegen/src/main/java/software/amazon/smithy/aws/go/codegen/FilterShapes.java +++ b/codegen/smithy-aws-go-codegen/src/main/java/software/amazon/smithy/aws/go/codegen/FilterShapes.java @@ -32,9 +32,7 @@ public final class FilterShapes implements GoIntegration { private static final Logger LOGGER = Logger.getLogger(FilterShapes.class.getName()); - private static final Set SHAPE_IDS = SetUtils.of( - ShapeId.from("com.amazonaws.lexruntimev2#StartConversation") - ); + private static final Set SHAPE_IDS = SetUtils.of(); public FilterShapes() { } diff --git a/service/lexruntimev2/api_client.go b/service/lexruntimev2/api_client.go index 9a60a9eeabf..7151f4c188b 100644 --- a/service/lexruntimev2/api_client.go +++ b/service/lexruntimev2/api_client.go @@ -126,6 +126,8 @@ func (c *Client) invokeOperation(ctx context.Context, opID string, params interf fn(&options) } + setSafeEventStreamClientLogMode(&options, opID) + finalizeClientEndpointResolverOptions(&options) for _, fn := range stackFns { diff --git a/service/lexruntimev2/api_op_StartConversation.go b/service/lexruntimev2/api_op_StartConversation.go new file mode 100644 index 00000000000..1952972bd22 --- /dev/null +++ b/service/lexruntimev2/api_op_StartConversation.go @@ -0,0 +1,337 @@ +// Code generated by smithy-go-codegen DO NOT EDIT. + +package lexruntimev2 + +import ( + "context" + awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" + "github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/eventstreamapi" + "github.com/aws/aws-sdk-go-v2/aws/signer/v4" + "github.com/aws/aws-sdk-go-v2/service/lexruntimev2/types" + "github.com/aws/smithy-go/middleware" + smithysync "github.com/aws/smithy-go/sync" + smithyhttp "github.com/aws/smithy-go/transport/http" + "sync" + "time" +) + +// Starts an HTTP/2 bidirectional event stream that enables you to send audio, +// text, or DTMF input in real time. After your application starts a conversation, +// users send input to Amazon Lex V2 as a stream of events. Amazon Lex V2 processes +// the incoming events and responds with streaming text or audio events. Audio +// input must be in the following format: audio/lpcm sample-rate=8000 +// sample-size-bits=16 channel-count=1; is-big-endian=false. If the optional +// post-fulfillment response is specified, the messages are returned as follows. +// For more information, see PostFulfillmentStatusSpecification +// (https://docs.aws.amazon.com/lexv2/latest/dg/API_PostFulfillmentStatusSpecification.html). +// +// * +// Success message - Returned if the Lambda function completes successfully and the +// intent state is fulfilled or ready fulfillment if the message is present. +// +// * +// Failed message - The failed message is returned if the Lambda function throws an +// exception or if the Lambda function returns a failed intent state without a +// message. +// +// * Timeout message - If you don't configure a timeout message and a +// timeout, and the Lambda function doesn't return within 30 seconds, the timeout +// message is returned. If you configure a timeout, the timeout message is returned +// when the period times out. +// +// For more information, see Completion message +// (https://docs.aws.amazon.com/lexv2/latest/dg/streaming-progress.html#progress-complete.html). +// If the optional update message is configured, it is played at the specified +// frequency while the Lambda function is running and the update message state is +// active. If the fulfillment update message is not active, the Lambda function +// runs with a 30 second timeout. For more information, see Update message +// (https://docs.aws.amazon.com/lexv2/latest/dg/streaming-progress.html#progress-update.html) +// The StartConversation operation is supported only in the following SDKs: +// +// * AWS +// SDK for C++ +// (https://docs.aws.amazon.com/goto/SdkForCpp/runtime.lex.v2-2020-08-07/StartConversation) +// +// * +// AWS SDK for Java V2 +// (https://docs.aws.amazon.com/goto/SdkForJavaV2/runtime.lex.v2-2020-08-07/StartConversation) +// +// * +// AWS SDK for Ruby V3 +// (https://docs.aws.amazon.com/goto/SdkForRubyV3/runtime.lex.v2-2020-08-07/StartConversation) +func (c *Client) StartConversation(ctx context.Context, params *StartConversationInput, optFns ...func(*Options)) (*StartConversationOutput, error) { + if params == nil { + params = &StartConversationInput{} + } + + result, metadata, err := c.invokeOperation(ctx, "StartConversation", params, optFns, c.addOperationStartConversationMiddlewares) + if err != nil { + return nil, err + } + + out := result.(*StartConversationOutput) + out.ResultMetadata = metadata + return out, nil +} + +type StartConversationInput struct { + + // The alias identifier in use for the bot that processes the request. + // + // This member is required. + BotAliasId *string + + // The identifier of the bot to process the request. + // + // This member is required. + BotId *string + + // The locale where the session is in use. + // + // This member is required. + LocaleId *string + + // The identifier of the user session that is having the conversation. + // + // This member is required. + SessionId *string + + // The conversation type that you are using the Amazon Lex V2. If the conversation + // mode is AUDIO you can send both audio and DTMF information. If the mode is TEXT + // you can only send text. + ConversationMode types.ConversationMode + + noSmithyDocumentSerde +} + +type StartConversationOutput struct { + eventStream *StartConversationEventStream + + // Metadata pertaining to the operation's result. + ResultMetadata middleware.Metadata + + noSmithyDocumentSerde +} + +// GetStream returns the type to interact with the event stream. +func (o *StartConversationOutput) GetStream() *StartConversationEventStream { + return o.eventStream +} + +func (c *Client) addOperationStartConversationMiddlewares(stack *middleware.Stack, options Options) (err error) { + err = stack.Serialize.Add(&awsRestjson1_serializeOpStartConversation{}, middleware.After) + if err != nil { + return err + } + err = stack.Deserialize.Add(&awsRestjson1_deserializeOpStartConversation{}, middleware.After) + if err != nil { + return err + } + if err = addEventStreamStartConversationMiddleware(stack, options); err != nil { + return err + } + if err = smithyhttp.AddRequireMinimumProtocol(stack, 2, 0); err != nil { + return err + } + if err = addSetLoggerMiddleware(stack, options); err != nil { + return err + } + if err = awsmiddleware.AddClientRequestIDMiddleware(stack); err != nil { + return err + } + if err = addResolveEndpointMiddleware(stack, options); err != nil { + return err + } + if err = v4.AddStreamingEventsPayload(stack); err != nil { + return err + } + if err = v4.AddContentSHA256HeaderMiddleware(stack); err != nil { + return err + } + if err = addRetryMiddlewares(stack, options); err != nil { + return err + } + if err = addHTTPSignerV4Middleware(stack, options); err != nil { + return err + } + if err = awsmiddleware.AddRawResponseToMetadata(stack); err != nil { + return err + } + if err = awsmiddleware.AddRecordResponseTiming(stack); err != nil { + return err + } + if err = addClientUserAgent(stack); err != nil { + return err + } + if err = eventstreamapi.AddInitializeStreamWriter(stack); err != nil { + return err + } + if err = addOpStartConversationValidationMiddleware(stack); err != nil { + return err + } + if err = stack.Initialize.Add(newServiceMetadataMiddleware_opStartConversation(options.Region), middleware.Before); err != nil { + return err + } + if err = addRequestIDRetrieverMiddleware(stack); err != nil { + return err + } + if err = addResponseErrorMiddleware(stack); err != nil { + return err + } + if err = addRequestResponseLogging(stack, options); err != nil { + return err + } + return nil +} + +func newServiceMetadataMiddleware_opStartConversation(region string) *awsmiddleware.RegisterServiceMetadata { + return &awsmiddleware.RegisterServiceMetadata{ + Region: region, + ServiceID: ServiceID, + SigningName: "lex", + OperationName: "StartConversation", + } +} + +// StartConversationEventStream provides the event stream handling for the StartConversation operation. +// +// For testing and mocking the event stream this type should be initialized via +// the NewStartConversationEventStream constructor function. Using the functional options +// to pass in nested mock behavior. +type StartConversationEventStream struct { + // StartConversationRequestEventStreamWriter is the EventStream writer for the + // StartConversationRequestEventStream events. This value is automatically set by + // the SDK when the API call is made Use this member when unit testing your code + // with the SDK to mock out the EventStream Writer. + // + // Must not be nil. + Writer StartConversationRequestEventStreamWriter + + // StartConversationResponseEventStreamReader is the EventStream reader for the + // StartConversationResponseEventStream events. This value is automatically set by + // the SDK when the API call is made Use this member when unit testing your code + // with the SDK to mock out the EventStream Reader. + // + // Must not be nil. + Reader StartConversationResponseEventStreamReader + + done chan struct{} + closeOnce sync.Once + err *smithysync.OnceErr +} + +// NewStartConversationEventStream initializes an StartConversationEventStream. +// This function should only be used for testing and mocking the StartConversationEventStream +// stream within your application. +// +// The Writer member must be set before writing events to the stream. +// +// The Reader member must be set before reading events from the stream. +func NewStartConversationEventStream(optFns ...func(*StartConversationEventStream)) *StartConversationEventStream { + es := &StartConversationEventStream{ + done: make(chan struct{}), + err: smithysync.NewOnceErr(), + } + for _, fn := range optFns { + fn(es) + } + return es +} + +// Send writes the event to the stream blocking until the event is written. +// Returns an error if the event was not written. +func (es *StartConversationEventStream) Send(ctx context.Context, event types.StartConversationRequestEventStream) error { + return es.Writer.Send(ctx, event) +} + +// Events returns a channel to read events from. +func (es *StartConversationEventStream) Events() <-chan types.StartConversationResponseEventStream { + return es.Reader.Events() +} + +// Close closes the stream. This will also cause the stream to be closed. +// Close must be called when done using the stream API. Not calling Close +// may result in resource leaks. +// +// Will close the underlying EventStream writer and reader, and no more events can be +// sent or received. +func (es *StartConversationEventStream) Close() error { + es.closeOnce.Do(es.safeClose) + return es.Err() +} + +func (es *StartConversationEventStream) safeClose() { + close(es.done) + + t := time.NewTicker(time.Second) + defer t.Stop() + writeCloseDone := make(chan error) + go func() { + if err := es.Writer.Close(); err != nil { + es.err.SetError(err) + } + close(writeCloseDone) + }() + select { + case <-t.C: + case <-writeCloseDone: + } + + es.Reader.Close() +} + +// Err returns any error that occurred while reading or writing EventStream Events +// from the service API's response. Returns nil if there were no errors. +func (es *StartConversationEventStream) Err() error { + if err := es.err.Err(); err != nil { + return err + } + + if err := es.Writer.Err(); err != nil { + return err + } + + if err := es.Reader.Err(); err != nil { + return err + } + + return nil +} + +func (es *StartConversationEventStream) waitStreamClose() { + type errorSet interface { + ErrorSet() <-chan struct{} + } + + var inputErrCh <-chan struct{} + if v, ok := es.Writer.(errorSet); ok { + inputErrCh = v.ErrorSet() + } + + var outputErrCh <-chan struct{} + if v, ok := es.Reader.(errorSet); ok { + outputErrCh = v.ErrorSet() + } + var outputClosedCh <-chan struct{} + if v, ok := es.Reader.(interface{ Closed() <-chan struct{} }); ok { + outputClosedCh = v.Closed() + } + + select { + case <-es.done: + case <-inputErrCh: + es.err.SetError(es.Writer.Err()) + es.Close() + + case <-outputErrCh: + es.err.SetError(es.Reader.Err()) + es.Close() + + case <-outputClosedCh: + if err := es.Reader.Err(); err != nil { + es.err.SetError(es.Reader.Err()) + } + es.Close() + + } +} diff --git a/service/lexruntimev2/deserializers.go b/service/lexruntimev2/deserializers.go index 1df02653621..a39a404e11d 100644 --- a/service/lexruntimev2/deserializers.go +++ b/service/lexruntimev2/deserializers.go @@ -5,8 +5,11 @@ package lexruntimev2 import ( "bytes" "context" + "encoding/base64" "encoding/json" "fmt" + "github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream" + "github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/eventstreamapi" "github.com/aws/aws-sdk-go-v2/aws/protocol/restjson" "github.com/aws/aws-sdk-go-v2/service/lexruntimev2/types" smithy "github.com/aws/smithy-go" @@ -907,16 +910,58 @@ func awsRestjson1_deserializeOpDocumentRecognizeUtteranceOutput(v *RecognizeUtte return nil } -func awsRestjson1_deserializeErrorAccessDeniedException(response *smithyhttp.Response, errorBody *bytes.Reader) error { - output := &types.AccessDeniedException{} +type awsRestjson1_deserializeOpStartConversation struct { +} + +func (*awsRestjson1_deserializeOpStartConversation) ID() string { + return "OperationDeserializer" +} + +func (m *awsRestjson1_deserializeOpStartConversation) HandleDeserialize(ctx context.Context, in middleware.DeserializeInput, next middleware.DeserializeHandler) ( + out middleware.DeserializeOutput, metadata middleware.Metadata, err error, +) { + out, metadata, err = next.HandleDeserialize(ctx, in) + if err != nil { + return out, metadata, err + } + + response, ok := out.RawResponse.(*smithyhttp.Response) + if !ok { + return out, metadata, &smithy.DeserializationError{Err: fmt.Errorf("unknown transport type %T", out.RawResponse)} + } + + if response.StatusCode < 200 || response.StatusCode >= 300 { + return out, metadata, awsRestjson1_deserializeOpErrorStartConversation(response, &metadata) + } + output := &StartConversationOutput{} + out.Result = output + + return out, metadata, err +} + +func awsRestjson1_deserializeOpErrorStartConversation(response *smithyhttp.Response, metadata *middleware.Metadata) error { + var errorBuffer bytes.Buffer + if _, err := io.Copy(&errorBuffer, response.Body); err != nil { + return &smithy.DeserializationError{Err: fmt.Errorf("failed to copy error response body, %w", err)} + } + errorBody := bytes.NewReader(errorBuffer.Bytes()) + + errorCode := "UnknownError" + errorMessage := errorCode + + code := response.Header.Get("X-Amzn-ErrorType") + if len(code) != 0 { + errorCode = restjson.SanitizeErrorCode(code) + } + var buff [1024]byte ringBuffer := smithyio.NewRingBuffer(buff[:]) body := io.TeeReader(errorBody, ringBuffer) decoder := json.NewDecoder(body) decoder.UseNumber() - var shape interface{} - if err := decoder.Decode(&shape); err != nil && err != io.EOF { + code, message, err := restjson.GetErrorInfo(decoder) + if err != nil { var snapshot bytes.Buffer io.Copy(&snapshot, ringBuffer) err = &smithy.DeserializationError{ @@ -926,29 +971,179 @@ func awsRestjson1_deserializeErrorAccessDeniedException(response *smithyhttp.Res return err } - err := awsRestjson1_deserializeDocumentAccessDeniedException(&output, shape) + errorBody.Seek(0, io.SeekStart) + if len(code) != 0 { + errorCode = restjson.SanitizeErrorCode(code) + } + if len(message) != 0 { + errorMessage = message + } - if err != nil { - var snapshot bytes.Buffer - io.Copy(&snapshot, ringBuffer) - err = &smithy.DeserializationError{ - Err: fmt.Errorf("failed to decode response body, %w", err), - Snapshot: snapshot.Bytes(), + switch { + case strings.EqualFold("AccessDeniedException", errorCode): + return awsRestjson1_deserializeErrorAccessDeniedException(response, errorBody) + + case strings.EqualFold("InternalServerException", errorCode): + return awsRestjson1_deserializeErrorInternalServerException(response, errorBody) + + case strings.EqualFold("ThrottlingException", errorCode): + return awsRestjson1_deserializeErrorThrottlingException(response, errorBody) + + case strings.EqualFold("ValidationException", errorCode): + return awsRestjson1_deserializeErrorValidationException(response, errorBody) + + default: + genericError := &smithy.GenericAPIError{ + Code: errorCode, + Message: errorMessage, } - return err + return genericError + } +} - errorBody.Seek(0, io.SeekStart) +func awsRestjson1_deserializeEventStreamStartConversationResponseEventStream(v *types.StartConversationResponseEventStream, msg *eventstream.Message) error { + if v == nil { + return fmt.Errorf("unexpected serialization of nil %T", v) + } - return output + eventType := msg.Headers.Get(eventstreamapi.EventTypeHeader) + if eventType == nil { + return fmt.Errorf("%s event header not present", eventstreamapi.EventTypeHeader) + } + + switch { + case strings.EqualFold("AudioResponseEvent", eventType.String()): + vv := &types.StartConversationResponseEventStreamMemberAudioResponseEvent{} + if err := awsRestjson1_deserializeEventMessageAudioResponseEvent(&vv.Value, msg); err != nil { + return err + } + *v = vv + return nil + + case strings.EqualFold("HeartbeatEvent", eventType.String()): + vv := &types.StartConversationResponseEventStreamMemberHeartbeatEvent{} + if err := awsRestjson1_deserializeEventMessageHeartbeatEvent(&vv.Value, msg); err != nil { + return err + } + *v = vv + return nil + + case strings.EqualFold("IntentResultEvent", eventType.String()): + vv := &types.StartConversationResponseEventStreamMemberIntentResultEvent{} + if err := awsRestjson1_deserializeEventMessageIntentResultEvent(&vv.Value, msg); err != nil { + return err + } + *v = vv + return nil + + case strings.EqualFold("PlaybackInterruptionEvent", eventType.String()): + vv := &types.StartConversationResponseEventStreamMemberPlaybackInterruptionEvent{} + if err := awsRestjson1_deserializeEventMessagePlaybackInterruptionEvent(&vv.Value, msg); err != nil { + return err + } + *v = vv + return nil + + case strings.EqualFold("TextResponseEvent", eventType.String()): + vv := &types.StartConversationResponseEventStreamMemberTextResponseEvent{} + if err := awsRestjson1_deserializeEventMessageTextResponseEvent(&vv.Value, msg); err != nil { + return err + } + *v = vv + return nil + + case strings.EqualFold("TranscriptEvent", eventType.String()): + vv := &types.StartConversationResponseEventStreamMemberTranscriptEvent{} + if err := awsRestjson1_deserializeEventMessageTranscriptEvent(&vv.Value, msg); err != nil { + return err + } + *v = vv + return nil + + default: + buffer := bytes.NewBuffer(nil) + eventstream.NewEncoder().Encode(buffer, *msg) + *v = &types.UnknownUnionMember{ + Tag: eventType.String(), + Value: buffer.Bytes(), + } + return nil + + } } -func awsRestjson1_deserializeErrorBadGatewayException(response *smithyhttp.Response, errorBody *bytes.Reader) error { - output := &types.BadGatewayException{} +func awsRestjson1_deserializeEventStreamExceptionStartConversationResponseEventStream(msg *eventstream.Message) error { + exceptionType := msg.Headers.Get(eventstreamapi.ExceptionTypeHeader) + if exceptionType == nil { + return fmt.Errorf("%s event header not present", eventstreamapi.ExceptionTypeHeader) + } + + switch { + case strings.EqualFold("AccessDeniedException", exceptionType.String()): + return awsRestjson1_deserializeEventMessageExceptionAccessDeniedException(msg) + + case strings.EqualFold("BadGatewayException", exceptionType.String()): + return awsRestjson1_deserializeEventMessageExceptionBadGatewayException(msg) + + case strings.EqualFold("ConflictException", exceptionType.String()): + return awsRestjson1_deserializeEventMessageExceptionConflictException(msg) + + case strings.EqualFold("DependencyFailedException", exceptionType.String()): + return awsRestjson1_deserializeEventMessageExceptionDependencyFailedException(msg) + + case strings.EqualFold("InternalServerException", exceptionType.String()): + return awsRestjson1_deserializeEventMessageExceptionInternalServerException(msg) + + case strings.EqualFold("ResourceNotFoundException", exceptionType.String()): + return awsRestjson1_deserializeEventMessageExceptionResourceNotFoundException(msg) + + case strings.EqualFold("ThrottlingException", exceptionType.String()): + return awsRestjson1_deserializeEventMessageExceptionThrottlingException(msg) + + case strings.EqualFold("ValidationException", exceptionType.String()): + return awsRestjson1_deserializeEventMessageExceptionValidationException(msg) + + default: + br := bytes.NewReader(msg.Payload) + var buff [1024]byte + ringBuffer := smithyio.NewRingBuffer(buff[:]) + + body := io.TeeReader(br, ringBuffer) + decoder := json.NewDecoder(body) + decoder.UseNumber() + code, message, err := restjson.GetErrorInfo(decoder) + if err != nil { + return err + } + errorCode := "UnknownError" + errorMessage := errorCode + if ev := exceptionType.String(); len(ev) > 0 { + errorCode = ev + } else if ev := code; len(ev) > 0 { + errorCode = ev + } + if ev := message; len(ev) > 0 { + errorMessage = ev + } + return &smithy.GenericAPIError{ + Code: errorCode, + Message: errorMessage, + } + + } +} + +func awsRestjson1_deserializeEventMessagePlaybackInterruptionEvent(v *types.PlaybackInterruptionEvent, msg *eventstream.Message) error { + if v == nil { + return fmt.Errorf("unexpected serialization of nil %T", v) + } + + br := bytes.NewReader(msg.Payload) var buff [1024]byte ringBuffer := smithyio.NewRingBuffer(buff[:]) - body := io.TeeReader(errorBody, ringBuffer) + body := io.TeeReader(br, ringBuffer) decoder := json.NewDecoder(body) decoder.UseNumber() var shape interface{} @@ -962,29 +1157,31 @@ func awsRestjson1_deserializeErrorBadGatewayException(response *smithyhttp.Respo return err } - err := awsRestjson1_deserializeDocumentBadGatewayException(&output, shape) - - if err != nil { - var snapshot bytes.Buffer - io.Copy(&snapshot, ringBuffer) - err = &smithy.DeserializationError{ - Err: fmt.Errorf("failed to decode response body, %w", err), - Snapshot: snapshot.Bytes(), + if err := awsRestjson1_deserializeDocumentPlaybackInterruptionEvent(&v, shape); err != nil { + if err != nil { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return err } - return err - } - errorBody.Seek(0, io.SeekStart) - - return output + } + return nil } -func awsRestjson1_deserializeErrorConflictException(response *smithyhttp.Response, errorBody *bytes.Reader) error { - output := &types.ConflictException{} +func awsRestjson1_deserializeEventMessageTranscriptEvent(v *types.TranscriptEvent, msg *eventstream.Message) error { + if v == nil { + return fmt.Errorf("unexpected serialization of nil %T", v) + } + + br := bytes.NewReader(msg.Payload) var buff [1024]byte ringBuffer := smithyio.NewRingBuffer(buff[:]) - body := io.TeeReader(errorBody, ringBuffer) + body := io.TeeReader(br, ringBuffer) decoder := json.NewDecoder(body) decoder.UseNumber() var shape interface{} @@ -998,9 +1195,35 @@ func awsRestjson1_deserializeErrorConflictException(response *smithyhttp.Respons return err } - err := awsRestjson1_deserializeDocumentConflictException(&output, shape) + if err := awsRestjson1_deserializeDocumentTranscriptEvent(&v, shape); err != nil { + if err != nil { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return err + } - if err != nil { + } + return nil +} + +func awsRestjson1_deserializeEventMessageIntentResultEvent(v *types.IntentResultEvent, msg *eventstream.Message) error { + if v == nil { + return fmt.Errorf("unexpected serialization of nil %T", v) + } + + br := bytes.NewReader(msg.Payload) + var buff [1024]byte + ringBuffer := smithyio.NewRingBuffer(buff[:]) + + body := io.TeeReader(br, ringBuffer) + decoder := json.NewDecoder(body) + decoder.UseNumber() + var shape interface{} + if err := decoder.Decode(&shape); err != nil && err != io.EOF { var snapshot bytes.Buffer io.Copy(&snapshot, ringBuffer) err = &smithy.DeserializationError{ @@ -1010,17 +1233,31 @@ func awsRestjson1_deserializeErrorConflictException(response *smithyhttp.Respons return err } - errorBody.Seek(0, io.SeekStart) + if err := awsRestjson1_deserializeDocumentIntentResultEvent(&v, shape); err != nil { + if err != nil { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return err + } - return output + } + return nil } -func awsRestjson1_deserializeErrorDependencyFailedException(response *smithyhttp.Response, errorBody *bytes.Reader) error { - output := &types.DependencyFailedException{} +func awsRestjson1_deserializeEventMessageTextResponseEvent(v *types.TextResponseEvent, msg *eventstream.Message) error { + if v == nil { + return fmt.Errorf("unexpected serialization of nil %T", v) + } + + br := bytes.NewReader(msg.Payload) var buff [1024]byte ringBuffer := smithyio.NewRingBuffer(buff[:]) - body := io.TeeReader(errorBody, ringBuffer) + body := io.TeeReader(br, ringBuffer) decoder := json.NewDecoder(body) decoder.UseNumber() var shape interface{} @@ -1034,9 +1271,35 @@ func awsRestjson1_deserializeErrorDependencyFailedException(response *smithyhttp return err } - err := awsRestjson1_deserializeDocumentDependencyFailedException(&output, shape) + if err := awsRestjson1_deserializeDocumentTextResponseEvent(&v, shape); err != nil { + if err != nil { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return err + } - if err != nil { + } + return nil +} + +func awsRestjson1_deserializeEventMessageAudioResponseEvent(v *types.AudioResponseEvent, msg *eventstream.Message) error { + if v == nil { + return fmt.Errorf("unexpected serialization of nil %T", v) + } + + br := bytes.NewReader(msg.Payload) + var buff [1024]byte + ringBuffer := smithyio.NewRingBuffer(buff[:]) + + body := io.TeeReader(br, ringBuffer) + decoder := json.NewDecoder(body) + decoder.UseNumber() + var shape interface{} + if err := decoder.Decode(&shape); err != nil && err != io.EOF { var snapshot bytes.Buffer io.Copy(&snapshot, ringBuffer) err = &smithy.DeserializationError{ @@ -1046,17 +1309,31 @@ func awsRestjson1_deserializeErrorDependencyFailedException(response *smithyhttp return err } - errorBody.Seek(0, io.SeekStart) + if err := awsRestjson1_deserializeDocumentAudioResponseEvent(&v, shape); err != nil { + if err != nil { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return err + } - return output + } + return nil } -func awsRestjson1_deserializeErrorInternalServerException(response *smithyhttp.Response, errorBody *bytes.Reader) error { - output := &types.InternalServerException{} +func awsRestjson1_deserializeEventMessageHeartbeatEvent(v *types.HeartbeatEvent, msg *eventstream.Message) error { + if v == nil { + return fmt.Errorf("unexpected serialization of nil %T", v) + } + + br := bytes.NewReader(msg.Payload) var buff [1024]byte ringBuffer := smithyio.NewRingBuffer(buff[:]) - body := io.TeeReader(errorBody, ringBuffer) + body := io.TeeReader(br, ringBuffer) decoder := json.NewDecoder(body) decoder.UseNumber() var shape interface{} @@ -1070,9 +1347,31 @@ func awsRestjson1_deserializeErrorInternalServerException(response *smithyhttp.R return err } - err := awsRestjson1_deserializeDocumentInternalServerException(&output, shape) + if err := awsRestjson1_deserializeDocumentHeartbeatEvent(&v, shape); err != nil { + if err != nil { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return err + } - if err != nil { + } + return nil +} + +func awsRestjson1_deserializeEventMessageExceptionAccessDeniedException(msg *eventstream.Message) error { + br := bytes.NewReader(msg.Payload) + var buff [1024]byte + ringBuffer := smithyio.NewRingBuffer(buff[:]) + + body := io.TeeReader(br, ringBuffer) + decoder := json.NewDecoder(body) + decoder.UseNumber() + var shape interface{} + if err := decoder.Decode(&shape); err != nil && err != io.EOF { var snapshot bytes.Buffer io.Copy(&snapshot, ringBuffer) err = &smithy.DeserializationError{ @@ -1082,17 +1381,28 @@ func awsRestjson1_deserializeErrorInternalServerException(response *smithyhttp.R return err } - errorBody.Seek(0, io.SeekStart) + v := &types.AccessDeniedException{} + if err := awsRestjson1_deserializeDocumentAccessDeniedException(&v, shape); err != nil { + if err != nil { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return err + } - return output + } + return v } -func awsRestjson1_deserializeErrorResourceNotFoundException(response *smithyhttp.Response, errorBody *bytes.Reader) error { - output := &types.ResourceNotFoundException{} +func awsRestjson1_deserializeEventMessageExceptionResourceNotFoundException(msg *eventstream.Message) error { + br := bytes.NewReader(msg.Payload) var buff [1024]byte ringBuffer := smithyio.NewRingBuffer(buff[:]) - body := io.TeeReader(errorBody, ringBuffer) + body := io.TeeReader(br, ringBuffer) decoder := json.NewDecoder(body) decoder.UseNumber() var shape interface{} @@ -1106,9 +1416,32 @@ func awsRestjson1_deserializeErrorResourceNotFoundException(response *smithyhttp return err } - err := awsRestjson1_deserializeDocumentResourceNotFoundException(&output, shape) + v := &types.ResourceNotFoundException{} + if err := awsRestjson1_deserializeDocumentResourceNotFoundException(&v, shape); err != nil { + if err != nil { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return err + } - if err != nil { + } + return v +} + +func awsRestjson1_deserializeEventMessageExceptionValidationException(msg *eventstream.Message) error { + br := bytes.NewReader(msg.Payload) + var buff [1024]byte + ringBuffer := smithyio.NewRingBuffer(buff[:]) + + body := io.TeeReader(br, ringBuffer) + decoder := json.NewDecoder(body) + decoder.UseNumber() + var shape interface{} + if err := decoder.Decode(&shape); err != nil && err != io.EOF { var snapshot bytes.Buffer io.Copy(&snapshot, ringBuffer) err = &smithy.DeserializationError{ @@ -1118,17 +1451,28 @@ func awsRestjson1_deserializeErrorResourceNotFoundException(response *smithyhttp return err } - errorBody.Seek(0, io.SeekStart) + v := &types.ValidationException{} + if err := awsRestjson1_deserializeDocumentValidationException(&v, shape); err != nil { + if err != nil { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return err + } - return output + } + return v } -func awsRestjson1_deserializeErrorThrottlingException(response *smithyhttp.Response, errorBody *bytes.Reader) error { - output := &types.ThrottlingException{} +func awsRestjson1_deserializeEventMessageExceptionThrottlingException(msg *eventstream.Message) error { + br := bytes.NewReader(msg.Payload) var buff [1024]byte ringBuffer := smithyio.NewRingBuffer(buff[:]) - body := io.TeeReader(errorBody, ringBuffer) + body := io.TeeReader(br, ringBuffer) decoder := json.NewDecoder(body) decoder.UseNumber() var shape interface{} @@ -1142,9 +1486,32 @@ func awsRestjson1_deserializeErrorThrottlingException(response *smithyhttp.Respo return err } - err := awsRestjson1_deserializeDocumentThrottlingException(&output, shape) + v := &types.ThrottlingException{} + if err := awsRestjson1_deserializeDocumentThrottlingException(&v, shape); err != nil { + if err != nil { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return err + } - if err != nil { + } + return v +} + +func awsRestjson1_deserializeEventMessageExceptionInternalServerException(msg *eventstream.Message) error { + br := bytes.NewReader(msg.Payload) + var buff [1024]byte + ringBuffer := smithyio.NewRingBuffer(buff[:]) + + body := io.TeeReader(br, ringBuffer) + decoder := json.NewDecoder(body) + decoder.UseNumber() + var shape interface{} + if err := decoder.Decode(&shape); err != nil && err != io.EOF { var snapshot bytes.Buffer io.Copy(&snapshot, ringBuffer) err = &smithy.DeserializationError{ @@ -1154,17 +1521,28 @@ func awsRestjson1_deserializeErrorThrottlingException(response *smithyhttp.Respo return err } - errorBody.Seek(0, io.SeekStart) + v := &types.InternalServerException{} + if err := awsRestjson1_deserializeDocumentInternalServerException(&v, shape); err != nil { + if err != nil { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return err + } - return output + } + return v } -func awsRestjson1_deserializeErrorValidationException(response *smithyhttp.Response, errorBody *bytes.Reader) error { - output := &types.ValidationException{} +func awsRestjson1_deserializeEventMessageExceptionConflictException(msg *eventstream.Message) error { + br := bytes.NewReader(msg.Payload) var buff [1024]byte ringBuffer := smithyio.NewRingBuffer(buff[:]) - body := io.TeeReader(errorBody, ringBuffer) + body := io.TeeReader(br, ringBuffer) decoder := json.NewDecoder(body) decoder.UseNumber() var shape interface{} @@ -1178,9 +1556,32 @@ func awsRestjson1_deserializeErrorValidationException(response *smithyhttp.Respo return err } - err := awsRestjson1_deserializeDocumentValidationException(&output, shape) + v := &types.ConflictException{} + if err := awsRestjson1_deserializeDocumentConflictException(&v, shape); err != nil { + if err != nil { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return err + } - if err != nil { + } + return v +} + +func awsRestjson1_deserializeEventMessageExceptionDependencyFailedException(msg *eventstream.Message) error { + br := bytes.NewReader(msg.Payload) + var buff [1024]byte + ringBuffer := smithyio.NewRingBuffer(buff[:]) + + body := io.TeeReader(br, ringBuffer) + decoder := json.NewDecoder(body) + decoder.UseNumber() + var shape interface{} + if err := decoder.Decode(&shape); err != nil && err != io.EOF { var snapshot bytes.Buffer io.Copy(&snapshot, ringBuffer) err = &smithy.DeserializationError{ @@ -1190,9 +1591,55 @@ func awsRestjson1_deserializeErrorValidationException(response *smithyhttp.Respo return err } - errorBody.Seek(0, io.SeekStart) + v := &types.DependencyFailedException{} + if err := awsRestjson1_deserializeDocumentDependencyFailedException(&v, shape); err != nil { + if err != nil { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return err + } - return output + } + return v +} + +func awsRestjson1_deserializeEventMessageExceptionBadGatewayException(msg *eventstream.Message) error { + br := bytes.NewReader(msg.Payload) + var buff [1024]byte + ringBuffer := smithyio.NewRingBuffer(buff[:]) + + body := io.TeeReader(br, ringBuffer) + decoder := json.NewDecoder(body) + decoder.UseNumber() + var shape interface{} + if err := decoder.Decode(&shape); err != nil && err != io.EOF { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return err + } + + v := &types.BadGatewayException{} + if err := awsRestjson1_deserializeDocumentBadGatewayException(&v, shape); err != nil { + if err != nil { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return err + } + + } + return v } func awsRestjson1_deserializeDocumentAccessDeniedException(v **types.AccessDeniedException, value interface{}) error { @@ -1412,6 +1859,68 @@ func awsRestjson1_deserializeDocumentActiveContextTimeToLive(v **types.ActiveCon return nil } +func awsRestjson1_deserializeDocumentAudioResponseEvent(v **types.AudioResponseEvent, value interface{}) error { + if v == nil { + return fmt.Errorf("unexpected nil of type %T", v) + } + if value == nil { + return nil + } + + shape, ok := value.(map[string]interface{}) + if !ok { + return fmt.Errorf("unexpected JSON type %v", value) + } + + var sv *types.AudioResponseEvent + if *v == nil { + sv = &types.AudioResponseEvent{} + } else { + sv = *v + } + + for key, value := range shape { + switch key { + case "audioChunk": + if value != nil { + jtv, ok := value.(string) + if !ok { + return fmt.Errorf("expected AudioChunk to be []byte, got %T instead", value) + } + dv, err := base64.StdEncoding.DecodeString(jtv) + if err != nil { + return fmt.Errorf("failed to base64 decode AudioChunk, %w", err) + } + sv.AudioChunk = dv + } + + case "contentType": + if value != nil { + jtv, ok := value.(string) + if !ok { + return fmt.Errorf("expected NonEmptyString to be of type string, got %T instead", value) + } + sv.ContentType = ptr.String(jtv) + } + + case "eventId": + if value != nil { + jtv, ok := value.(string) + if !ok { + return fmt.Errorf("expected EventId to be of type string, got %T instead", value) + } + sv.EventId = ptr.String(jtv) + } + + default: + _, _ = key, value + + } + } + *v = sv + return nil +} + func awsRestjson1_deserializeDocumentBadGatewayException(v **types.BadGatewayException, value interface{}) error { if v == nil { return fmt.Errorf("unexpected nil of type %T", v) @@ -1738,6 +2247,46 @@ func awsRestjson1_deserializeDocumentDialogAction(v **types.DialogAction, value return nil } +func awsRestjson1_deserializeDocumentHeartbeatEvent(v **types.HeartbeatEvent, value interface{}) error { + if v == nil { + return fmt.Errorf("unexpected nil of type %T", v) + } + if value == nil { + return nil + } + + shape, ok := value.(map[string]interface{}) + if !ok { + return fmt.Errorf("unexpected JSON type %v", value) + } + + var sv *types.HeartbeatEvent + if *v == nil { + sv = &types.HeartbeatEvent{} + } else { + sv = *v + } + + for key, value := range shape { + switch key { + case "eventId": + if value != nil { + jtv, ok := value.(string) + if !ok { + return fmt.Errorf("expected EventId to be of type string, got %T instead", value) + } + sv.EventId = ptr.String(jtv) + } + + default: + _, _ = key, value + + } + } + *v = sv + return nil +} + func awsRestjson1_deserializeDocumentImageResponseCard(v **types.ImageResponseCard, value interface{}) error { if v == nil { return fmt.Errorf("unexpected nil of type %T", v) @@ -1864,6 +2413,79 @@ func awsRestjson1_deserializeDocumentIntent(v **types.Intent, value interface{}) return nil } +func awsRestjson1_deserializeDocumentIntentResultEvent(v **types.IntentResultEvent, value interface{}) error { + if v == nil { + return fmt.Errorf("unexpected nil of type %T", v) + } + if value == nil { + return nil + } + + shape, ok := value.(map[string]interface{}) + if !ok { + return fmt.Errorf("unexpected JSON type %v", value) + } + + var sv *types.IntentResultEvent + if *v == nil { + sv = &types.IntentResultEvent{} + } else { + sv = *v + } + + for key, value := range shape { + switch key { + case "eventId": + if value != nil { + jtv, ok := value.(string) + if !ok { + return fmt.Errorf("expected EventId to be of type string, got %T instead", value) + } + sv.EventId = ptr.String(jtv) + } + + case "inputMode": + if value != nil { + jtv, ok := value.(string) + if !ok { + return fmt.Errorf("expected InputMode to be of type string, got %T instead", value) + } + sv.InputMode = types.InputMode(jtv) + } + + case "interpretations": + if err := awsRestjson1_deserializeDocumentInterpretations(&sv.Interpretations, value); err != nil { + return err + } + + case "requestAttributes": + if err := awsRestjson1_deserializeDocumentStringMap(&sv.RequestAttributes, value); err != nil { + return err + } + + case "sessionId": + if value != nil { + jtv, ok := value.(string) + if !ok { + return fmt.Errorf("expected SessionId to be of type string, got %T instead", value) + } + sv.SessionId = ptr.String(jtv) + } + + case "sessionState": + if err := awsRestjson1_deserializeDocumentSessionState(&sv.SessionState, value); err != nil { + return err + } + + default: + _, _ = key, value + + } + } + *v = sv + return nil +} + func awsRestjson1_deserializeDocumentInternalServerException(v **types.InternalServerException, value interface{}) error { if v == nil { return fmt.Errorf("unexpected nil of type %T", v) @@ -2072,7 +2694,7 @@ func awsRestjson1_deserializeDocumentMessages(v *[]types.Message, value interfac return nil } -func awsRestjson1_deserializeDocumentResourceNotFoundException(v **types.ResourceNotFoundException, value interface{}) error { +func awsRestjson1_deserializeDocumentPlaybackInterruptionEvent(v **types.PlaybackInterruptionEvent, value interface{}) error { if v == nil { return fmt.Errorf("unexpected nil of type %T", v) } @@ -2085,30 +2707,88 @@ func awsRestjson1_deserializeDocumentResourceNotFoundException(v **types.Resourc return fmt.Errorf("unexpected JSON type %v", value) } - var sv *types.ResourceNotFoundException + var sv *types.PlaybackInterruptionEvent if *v == nil { - sv = &types.ResourceNotFoundException{} + sv = &types.PlaybackInterruptionEvent{} } else { sv = *v } for key, value := range shape { switch key { - case "message": + case "causedByEventId": if value != nil { jtv, ok := value.(string) if !ok { - return fmt.Errorf("expected String to be of type string, got %T instead", value) + return fmt.Errorf("expected EventId to be of type string, got %T instead", value) } - sv.Message = ptr.String(jtv) + sv.CausedByEventId = ptr.String(jtv) } - default: - _, _ = key, value + case "eventId": + if value != nil { + jtv, ok := value.(string) + if !ok { + return fmt.Errorf("expected EventId to be of type string, got %T instead", value) + } + sv.EventId = ptr.String(jtv) + } - } - } - *v = sv + case "eventReason": + if value != nil { + jtv, ok := value.(string) + if !ok { + return fmt.Errorf("expected PlaybackInterruptionReason to be of type string, got %T instead", value) + } + sv.EventReason = types.PlaybackInterruptionReason(jtv) + } + + default: + _, _ = key, value + + } + } + *v = sv + return nil +} + +func awsRestjson1_deserializeDocumentResourceNotFoundException(v **types.ResourceNotFoundException, value interface{}) error { + if v == nil { + return fmt.Errorf("unexpected nil of type %T", v) + } + if value == nil { + return nil + } + + shape, ok := value.(map[string]interface{}) + if !ok { + return fmt.Errorf("unexpected JSON type %v", value) + } + + var sv *types.ResourceNotFoundException + if *v == nil { + sv = &types.ResourceNotFoundException{} + } else { + sv = *v + } + + for key, value := range shape { + switch key { + case "message": + if value != nil { + jtv, ok := value.(string) + if !ok { + return fmt.Errorf("expected String to be of type string, got %T instead", value) + } + sv.Message = ptr.String(jtv) + } + + default: + _, _ = key, value + + } + } + *v = sv return nil } @@ -2541,6 +3221,51 @@ func awsRestjson1_deserializeDocumentStringMap(v *map[string]string, value inter return nil } +func awsRestjson1_deserializeDocumentTextResponseEvent(v **types.TextResponseEvent, value interface{}) error { + if v == nil { + return fmt.Errorf("unexpected nil of type %T", v) + } + if value == nil { + return nil + } + + shape, ok := value.(map[string]interface{}) + if !ok { + return fmt.Errorf("unexpected JSON type %v", value) + } + + var sv *types.TextResponseEvent + if *v == nil { + sv = &types.TextResponseEvent{} + } else { + sv = *v + } + + for key, value := range shape { + switch key { + case "eventId": + if value != nil { + jtv, ok := value.(string) + if !ok { + return fmt.Errorf("expected EventId to be of type string, got %T instead", value) + } + sv.EventId = ptr.String(jtv) + } + + case "messages": + if err := awsRestjson1_deserializeDocumentMessages(&sv.Messages, value); err != nil { + return err + } + + default: + _, _ = key, value + + } + } + *v = sv + return nil +} + func awsRestjson1_deserializeDocumentThrottlingException(v **types.ThrottlingException, value interface{}) error { if v == nil { return fmt.Errorf("unexpected nil of type %T", v) @@ -2581,6 +3306,55 @@ func awsRestjson1_deserializeDocumentThrottlingException(v **types.ThrottlingExc return nil } +func awsRestjson1_deserializeDocumentTranscriptEvent(v **types.TranscriptEvent, value interface{}) error { + if v == nil { + return fmt.Errorf("unexpected nil of type %T", v) + } + if value == nil { + return nil + } + + shape, ok := value.(map[string]interface{}) + if !ok { + return fmt.Errorf("unexpected JSON type %v", value) + } + + var sv *types.TranscriptEvent + if *v == nil { + sv = &types.TranscriptEvent{} + } else { + sv = *v + } + + for key, value := range shape { + switch key { + case "eventId": + if value != nil { + jtv, ok := value.(string) + if !ok { + return fmt.Errorf("expected EventId to be of type string, got %T instead", value) + } + sv.EventId = ptr.String(jtv) + } + + case "transcript": + if value != nil { + jtv, ok := value.(string) + if !ok { + return fmt.Errorf("expected String to be of type string, got %T instead", value) + } + sv.Transcript = ptr.String(jtv) + } + + default: + _, _ = key, value + + } + } + *v = sv + return nil +} + func awsRestjson1_deserializeDocumentValidationException(v **types.ValidationException, value interface{}) error { if v == nil { return fmt.Errorf("unexpected nil of type %T", v) @@ -2708,3 +3482,291 @@ func awsRestjson1_deserializeDocumentValues(v *[]types.Slot, value interface{}) *v = cv return nil } + +func awsRestjson1_deserializeErrorAccessDeniedException(response *smithyhttp.Response, errorBody *bytes.Reader) error { + output := &types.AccessDeniedException{} + var buff [1024]byte + ringBuffer := smithyio.NewRingBuffer(buff[:]) + + body := io.TeeReader(errorBody, ringBuffer) + decoder := json.NewDecoder(body) + decoder.UseNumber() + var shape interface{} + if err := decoder.Decode(&shape); err != nil && err != io.EOF { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return err + } + + err := awsRestjson1_deserializeDocumentAccessDeniedException(&output, shape) + + if err != nil { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return err + } + + errorBody.Seek(0, io.SeekStart) + + return output +} + +func awsRestjson1_deserializeErrorBadGatewayException(response *smithyhttp.Response, errorBody *bytes.Reader) error { + output := &types.BadGatewayException{} + var buff [1024]byte + ringBuffer := smithyio.NewRingBuffer(buff[:]) + + body := io.TeeReader(errorBody, ringBuffer) + decoder := json.NewDecoder(body) + decoder.UseNumber() + var shape interface{} + if err := decoder.Decode(&shape); err != nil && err != io.EOF { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return err + } + + err := awsRestjson1_deserializeDocumentBadGatewayException(&output, shape) + + if err != nil { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return err + } + + errorBody.Seek(0, io.SeekStart) + + return output +} + +func awsRestjson1_deserializeErrorConflictException(response *smithyhttp.Response, errorBody *bytes.Reader) error { + output := &types.ConflictException{} + var buff [1024]byte + ringBuffer := smithyio.NewRingBuffer(buff[:]) + + body := io.TeeReader(errorBody, ringBuffer) + decoder := json.NewDecoder(body) + decoder.UseNumber() + var shape interface{} + if err := decoder.Decode(&shape); err != nil && err != io.EOF { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return err + } + + err := awsRestjson1_deserializeDocumentConflictException(&output, shape) + + if err != nil { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return err + } + + errorBody.Seek(0, io.SeekStart) + + return output +} + +func awsRestjson1_deserializeErrorDependencyFailedException(response *smithyhttp.Response, errorBody *bytes.Reader) error { + output := &types.DependencyFailedException{} + var buff [1024]byte + ringBuffer := smithyio.NewRingBuffer(buff[:]) + + body := io.TeeReader(errorBody, ringBuffer) + decoder := json.NewDecoder(body) + decoder.UseNumber() + var shape interface{} + if err := decoder.Decode(&shape); err != nil && err != io.EOF { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return err + } + + err := awsRestjson1_deserializeDocumentDependencyFailedException(&output, shape) + + if err != nil { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return err + } + + errorBody.Seek(0, io.SeekStart) + + return output +} + +func awsRestjson1_deserializeErrorInternalServerException(response *smithyhttp.Response, errorBody *bytes.Reader) error { + output := &types.InternalServerException{} + var buff [1024]byte + ringBuffer := smithyio.NewRingBuffer(buff[:]) + + body := io.TeeReader(errorBody, ringBuffer) + decoder := json.NewDecoder(body) + decoder.UseNumber() + var shape interface{} + if err := decoder.Decode(&shape); err != nil && err != io.EOF { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return err + } + + err := awsRestjson1_deserializeDocumentInternalServerException(&output, shape) + + if err != nil { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return err + } + + errorBody.Seek(0, io.SeekStart) + + return output +} + +func awsRestjson1_deserializeErrorResourceNotFoundException(response *smithyhttp.Response, errorBody *bytes.Reader) error { + output := &types.ResourceNotFoundException{} + var buff [1024]byte + ringBuffer := smithyio.NewRingBuffer(buff[:]) + + body := io.TeeReader(errorBody, ringBuffer) + decoder := json.NewDecoder(body) + decoder.UseNumber() + var shape interface{} + if err := decoder.Decode(&shape); err != nil && err != io.EOF { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return err + } + + err := awsRestjson1_deserializeDocumentResourceNotFoundException(&output, shape) + + if err != nil { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return err + } + + errorBody.Seek(0, io.SeekStart) + + return output +} + +func awsRestjson1_deserializeErrorThrottlingException(response *smithyhttp.Response, errorBody *bytes.Reader) error { + output := &types.ThrottlingException{} + var buff [1024]byte + ringBuffer := smithyio.NewRingBuffer(buff[:]) + + body := io.TeeReader(errorBody, ringBuffer) + decoder := json.NewDecoder(body) + decoder.UseNumber() + var shape interface{} + if err := decoder.Decode(&shape); err != nil && err != io.EOF { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return err + } + + err := awsRestjson1_deserializeDocumentThrottlingException(&output, shape) + + if err != nil { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return err + } + + errorBody.Seek(0, io.SeekStart) + + return output +} + +func awsRestjson1_deserializeErrorValidationException(response *smithyhttp.Response, errorBody *bytes.Reader) error { + output := &types.ValidationException{} + var buff [1024]byte + ringBuffer := smithyio.NewRingBuffer(buff[:]) + + body := io.TeeReader(errorBody, ringBuffer) + decoder := json.NewDecoder(body) + decoder.UseNumber() + var shape interface{} + if err := decoder.Decode(&shape); err != nil && err != io.EOF { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return err + } + + err := awsRestjson1_deserializeDocumentValidationException(&output, shape) + + if err != nil { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return err + } + + errorBody.Seek(0, io.SeekStart) + + return output +} diff --git a/service/lexruntimev2/eventstream.go b/service/lexruntimev2/eventstream.go new file mode 100644 index 00000000000..6d9509501bb --- /dev/null +++ b/service/lexruntimev2/eventstream.go @@ -0,0 +1,539 @@ +// Code generated by smithy-go-codegen DO NOT EDIT. + +package lexruntimev2 + +import ( + "bytes" + "context" + "fmt" + "github.com/aws/aws-sdk-go-v2/aws" + awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" + "github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream" + "github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/eventstreamapi" + "github.com/aws/aws-sdk-go-v2/aws/signer/v4" + "github.com/aws/aws-sdk-go-v2/service/lexruntimev2/types" + smithy "github.com/aws/smithy-go" + "github.com/aws/smithy-go/middleware" + smithysync "github.com/aws/smithy-go/sync" + smithyhttp "github.com/aws/smithy-go/transport/http" + "io" + "io/ioutil" + "sync" + "time" +) + +// StartConversationRequestEventStreamWriter provides the interface for writing +// events to a stream. +// +// The writer's Close method must allow multiple concurrent calls. +type StartConversationRequestEventStreamWriter interface { + Send(context.Context, types.StartConversationRequestEventStream) error + Close() error + Err() error +} + +// StartConversationResponseEventStreamReader provides the interface for reading +// events from a stream. +// +// The writer's Close method must allow multiple concurrent calls. +type StartConversationResponseEventStreamReader interface { + Events() <-chan types.StartConversationResponseEventStream + Close() error + Err() error +} + +type eventStreamSigner interface { + GetSignature(ctx context.Context, headers, payload []byte, signingTime time.Time, optFns ...func(*v4.StreamSignerOptions)) ([]byte, error) +} + +type asyncStartConversationRequestEventStream struct { + Event types.StartConversationRequestEventStream + Result chan<- error +} + +func (e asyncStartConversationRequestEventStream) ReportResult(cancel <-chan struct{}, err error) bool { + select { + case e.Result <- err: + return true + + case <-cancel: + return false + + } +} + +type startConversationRequestEventStream struct { + encoder *eventstream.Encoder + signer eventStreamSigner + stream chan asyncStartConversationRequestEventStream + serializationBuffer *bytes.Buffer + signingBuffer *bytes.Buffer + eventStream io.WriteCloser + done chan struct{} + closeOnce sync.Once + err *smithysync.OnceErr +} + +func newStartConversationRequestEventStream(stream io.WriteCloser, encoder *eventstream.Encoder, signer eventStreamSigner) *startConversationRequestEventStream { + w := &startConversationRequestEventStream{ + encoder: encoder, + signer: signer, + stream: make(chan asyncStartConversationRequestEventStream), + eventStream: stream, + done: make(chan struct{}), + err: smithysync.NewOnceErr(), + serializationBuffer: bytes.NewBuffer(nil), + signingBuffer: bytes.NewBuffer(nil), + } + + go w.writeStream() + + return w + +} + +func (w *startConversationRequestEventStream) Send(ctx context.Context, event types.StartConversationRequestEventStream) error { + return w.send(ctx, event) +} + +func (w *startConversationRequestEventStream) send(ctx context.Context, event types.StartConversationRequestEventStream) error { + if err := w.err.Err(); err != nil { + return err + } + + resultCh := make(chan error) + + wrapped := asyncStartConversationRequestEventStream{ + Event: event, + Result: resultCh, + } + + select { + case w.stream <- wrapped: + case <-ctx.Done(): + return ctx.Err() + case <-w.done: + return fmt.Errorf("stream closed, unable to send event") + + } + + select { + case err := <-resultCh: + return err + case <-ctx.Done(): + return ctx.Err() + case <-w.done: + return fmt.Errorf("stream closed, unable to send event") + + } + +} + +func (w *startConversationRequestEventStream) writeStream() { + defer w.Close() + + for { + select { + case wrapper := <-w.stream: + err := w.writeEvent(wrapper.Event) + wrapper.ReportResult(w.done, err) + if err != nil { + w.err.SetError(err) + return + } + + case <-w.done: + if err := w.closeStream(); err != nil { + w.err.SetError(err) + } + return + + } + } +} + +func (w *startConversationRequestEventStream) writeEvent(event types.StartConversationRequestEventStream) error { + // serializedEvent returned bytes refers to an underlying byte buffer and must not + // escape this writeEvent scope without first copying. Any previous bytes stored in + // the buffer are cleared by this call. + serializedEvent, err := w.serializeEvent(event) + if err != nil { + return err + } + + // signedEvent returned bytes refers to an underlying byte buffer and must not + // escape this writeEvent scope without first copying. Any previous bytes stored in + // the buffer are cleared by this call. + signedEvent, err := w.signEvent(serializedEvent) + if err != nil { + return err + } + + // bytes are now copied to the underlying stream writer + _, err = io.Copy(w.eventStream, bytes.NewReader(signedEvent)) + return err +} + +func (w *startConversationRequestEventStream) serializeEvent(event types.StartConversationRequestEventStream) ([]byte, error) { + w.serializationBuffer.Reset() + + eventMessage := eventstream.Message{} + + if err := awsRestjson1_serializeEventStreamStartConversationRequestEventStream(event, &eventMessage); err != nil { + return nil, err + } + + if err := w.encoder.Encode(w.serializationBuffer, eventMessage); err != nil { + return nil, err + } + + return w.serializationBuffer.Bytes(), nil +} + +func (w *startConversationRequestEventStream) signEvent(payload []byte) ([]byte, error) { + w.signingBuffer.Reset() + + date := time.Now().UTC() + + var msg eventstream.Message + msg.Headers.Set(eventstreamapi.DateHeader, eventstream.TimestampValue(date)) + msg.Payload = payload + + var headers bytes.Buffer + if err := eventstream.EncodeHeaders(&headers, msg.Headers); err != nil { + return nil, err + } + + sig, err := w.signer.GetSignature(context.Background(), headers.Bytes(), msg.Payload, date) + if err != nil { + return nil, err + } + + msg.Headers.Set(eventstreamapi.ChunkSignatureHeader, eventstream.BytesValue(sig)) + + if err := w.encoder.Encode(w.signingBuffer, msg); err != nil { + return nil, err + } + + return w.signingBuffer.Bytes(), nil +} + +func (w *startConversationRequestEventStream) closeStream() (err error) { + defer func() { + if cErr := w.eventStream.Close(); cErr != nil && err == nil { + err = cErr + } + }() + + // Per the protocol, a signed empty message is used to indicate the end of the stream, + // and that no subsequent events will be sent. + signedEvent, err := w.signEvent([]byte{}) + if err != nil { + return err + } + + _, err = io.Copy(w.eventStream, bytes.NewReader(signedEvent)) + return err +} + +func (w *startConversationRequestEventStream) ErrorSet() <-chan struct{} { + return w.err.ErrorSet() +} + +func (w *startConversationRequestEventStream) Close() error { + w.closeOnce.Do(w.safeClose) + return w.Err() +} + +func (w *startConversationRequestEventStream) safeClose() { + close(w.done) +} + +func (w *startConversationRequestEventStream) Err() error { + return w.err.Err() +} + +type startConversationResponseEventStream struct { + stream chan types.StartConversationResponseEventStream + decoder *eventstream.Decoder + eventStream io.ReadCloser + err *smithysync.OnceErr + payloadBuf []byte + done chan struct{} + closeOnce sync.Once +} + +func newStartConversationResponseEventStream(readCloser io.ReadCloser, decoder *eventstream.Decoder) *startConversationResponseEventStream { + w := &startConversationResponseEventStream{ + stream: make(chan types.StartConversationResponseEventStream), + decoder: decoder, + eventStream: readCloser, + err: smithysync.NewOnceErr(), + done: make(chan struct{}), + payloadBuf: make([]byte, 10*1024), + } + + go w.readEventStream() + + return w +} + +func (r *startConversationResponseEventStream) Events() <-chan types.StartConversationResponseEventStream { + return r.stream +} + +func (r *startConversationResponseEventStream) readEventStream() { + defer r.Close() + defer close(r.stream) + + for { + r.payloadBuf = r.payloadBuf[0:0] + decodedMessage, err := r.decoder.Decode(r.eventStream, r.payloadBuf) + if err != nil { + if err == io.EOF { + return + } + select { + case <-r.done: + return + default: + r.err.SetError(err) + return + } + } + + event, err := r.deserializeEventMessage(&decodedMessage) + if err != nil { + r.err.SetError(err) + return + } + + select { + case r.stream <- event: + case <-r.done: + return + } + + } +} + +func (r *startConversationResponseEventStream) deserializeEventMessage(msg *eventstream.Message) (types.StartConversationResponseEventStream, error) { + messageType := msg.Headers.Get(eventstreamapi.MessageTypeHeader) + if messageType == nil { + return nil, fmt.Errorf("%s event header not present", eventstreamapi.MessageTypeHeader) + } + + switch messageType.String() { + case eventstreamapi.EventMessageType: + var v types.StartConversationResponseEventStream + if err := awsRestjson1_deserializeEventStreamStartConversationResponseEventStream(&v, msg); err != nil { + return nil, err + } + return v, nil + + case eventstreamapi.ExceptionMessageType: + return nil, awsRestjson1_deserializeEventStreamExceptionStartConversationResponseEventStream(msg) + + case eventstreamapi.ErrorMessageType: + errorCode := "UnknownError" + errorMessage := errorCode + if header := msg.Headers.Get(eventstreamapi.ErrorCodeHeader); header != nil { + errorCode = header.String() + } + if header := msg.Headers.Get(eventstreamapi.ErrorMessageHeader); header != nil { + errorMessage = header.String() + } + return nil, &smithy.GenericAPIError{ + Code: errorCode, + Message: errorMessage, + } + + default: + mc := msg.Clone() + return nil, &UnknownEventMessageError{ + Type: messageType.String(), + Message: &mc, + } + + } +} + +func (r *startConversationResponseEventStream) ErrorSet() <-chan struct{} { + return r.err.ErrorSet() +} + +func (r *startConversationResponseEventStream) Close() error { + r.closeOnce.Do(r.safeClose) + return r.Err() +} + +func (r *startConversationResponseEventStream) safeClose() { + close(r.done) + r.eventStream.Close() + +} + +func (r *startConversationResponseEventStream) Err() error { + return r.err.Err() +} + +func (r *startConversationResponseEventStream) Closed() <-chan struct{} { + return r.done +} + +type awsRestjson1_deserializeOpEventStreamStartConversation struct { + LogEventStreamWrites bool + LogEventStreamReads bool +} + +func (*awsRestjson1_deserializeOpEventStreamStartConversation) ID() string { + return "OperationEventStreamDeserializer" +} + +func (m *awsRestjson1_deserializeOpEventStreamStartConversation) HandleDeserialize(ctx context.Context, in middleware.DeserializeInput, next middleware.DeserializeHandler) ( + out middleware.DeserializeOutput, metadata middleware.Metadata, err error, +) { + defer func() { + if err == nil { + return + } + m.closeResponseBody(out) + }() + + logger := middleware.GetLogger(ctx) + + request, ok := in.Request.(*smithyhttp.Request) + if !ok { + return out, metadata, fmt.Errorf("unknown transport type: %T", in.Request) + } + _ = request + + if err := eventstreamapi.ApplyHTTPTransportFixes(request); err != nil { + return out, metadata, err + } + + requestSignature, err := v4.GetSignedRequestSignature(request.Request) + if err != nil { + return out, metadata, fmt.Errorf("failed to get event stream seed signature: %v", err) + } + + signer := v4.NewStreamSigner( + awsmiddleware.GetSigningCredentials(ctx), + awsmiddleware.GetSigningName(ctx), + awsmiddleware.GetSigningRegion(ctx), + requestSignature, + ) + + eventWriter := newStartConversationRequestEventStream( + eventstreamapi.GetInputStreamWriter(ctx), + eventstream.NewEncoder(func(options *eventstream.EncoderOptions) { + options.Logger = logger + options.LogMessages = m.LogEventStreamWrites + + }), + signer, + ) + defer func() { + if err == nil { + return + } + _ = eventWriter.Close() + }() + + out, metadata, err = next.HandleDeserialize(ctx, in) + if err != nil { + return out, metadata, err + } + + deserializeOutput, ok := out.RawResponse.(*smithyhttp.Response) + if !ok { + return out, metadata, fmt.Errorf("unknown transport type: %T", out.RawResponse) + } + _ = deserializeOutput + + output, ok := out.Result.(*StartConversationOutput) + if out.Result != nil && !ok { + return out, metadata, fmt.Errorf("unexpected output result type: %T", out.Result) + } else if out.Result == nil { + output = &StartConversationOutput{} + out.Result = output + } + + eventReader := newStartConversationResponseEventStream( + deserializeOutput.Body, + eventstream.NewDecoder(func(options *eventstream.DecoderOptions) { + options.Logger = logger + options.LogMessages = m.LogEventStreamReads + + }), + ) + defer func() { + if err == nil { + return + } + _ = eventReader.Close() + }() + + output.eventStream = NewStartConversationEventStream(func(stream *StartConversationEventStream) { + stream.Writer = eventWriter + stream.Reader = eventReader + }) + + go output.eventStream.waitStreamClose() + + return out, metadata, nil +} + +func (*awsRestjson1_deserializeOpEventStreamStartConversation) closeResponseBody(out middleware.DeserializeOutput) { + if resp, ok := out.RawResponse.(*smithyhttp.Response); ok && resp != nil && resp.Body != nil { + _, _ = io.Copy(ioutil.Discard, resp.Body) + _ = resp.Body.Close() + } +} + +func addEventStreamStartConversationMiddleware(stack *middleware.Stack, options Options) error { + return stack.Deserialize.Insert(&awsRestjson1_deserializeOpEventStreamStartConversation{ + LogEventStreamWrites: options.ClientLogMode.IsRequestEventMessage(), + LogEventStreamReads: options.ClientLogMode.IsResponseEventMessage(), + }, "OperationDeserializer", middleware.Before) +} + +// UnknownEventMessageError provides an error when a message is received from the stream, +// but the reader is unable to determine what kind of message it is. +type UnknownEventMessageError struct { + Type string + Message *eventstream.Message +} + +// Error retruns the error message string. +func (e *UnknownEventMessageError) Error() string { + return "unknown event stream message type, " + e.Type +} + +func setSafeEventStreamClientLogMode(o *Options, operation string) { + switch operation { + case "StartConversation": + toggleEventStreamClientLogMode(o, true, true) + return + + default: + return + + } +} +func toggleEventStreamClientLogMode(o *Options, request, response bool) { + mode := o.ClientLogMode + + if request && mode.IsRequestWithBody() { + mode.ClearRequestWithBody() + mode |= aws.LogRequest + } + + if response && mode.IsResponseWithBody() { + mode.ClearResponseWithBody() + mode |= aws.LogResponse + } + + o.ClientLogMode = mode + +} diff --git a/service/lexruntimev2/generated.json b/service/lexruntimev2/generated.json index 87e494640ae..bacf73e409e 100644 --- a/service/lexruntimev2/generated.json +++ b/service/lexruntimev2/generated.json @@ -1,6 +1,7 @@ { "dependencies": { "github.com/aws/aws-sdk-go-v2": "v1.4.0", + "github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream": "v0.0.0-00010101000000-000000000000", "github.com/aws/aws-sdk-go-v2/internal/configsources": "v0.0.0-00010101000000-000000000000", "github.com/aws/aws-sdk-go-v2/internal/endpoints/v2": "v2.0.0-00010101000000-000000000000", "github.com/aws/smithy-go": "v1.4.0" @@ -12,9 +13,11 @@ "api_op_PutSession.go", "api_op_RecognizeText.go", "api_op_RecognizeUtterance.go", + "api_op_StartConversation.go", "deserializers.go", "doc.go", "endpoints.go", + "eventstream.go", "generated.json", "internal/endpoints/endpoints.go", "internal/endpoints/endpoints_test.go", @@ -23,6 +26,7 @@ "types/enums.go", "types/errors.go", "types/types.go", + "types/types_exported_test.go", "validators.go" ], "go": "1.15", diff --git a/service/lexruntimev2/go.mod b/service/lexruntimev2/go.mod index aee60d0ed81..319e75c4893 100644 --- a/service/lexruntimev2/go.mod +++ b/service/lexruntimev2/go.mod @@ -4,6 +4,7 @@ go 1.15 require ( github.com/aws/aws-sdk-go-v2 v1.11.1 + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.0.0 github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.1 github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.0.1 github.com/aws/smithy-go v1.9.0 @@ -11,6 +12,8 @@ require ( replace github.com/aws/aws-sdk-go-v2 => ../../ +replace github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream => ../../aws/protocol/eventstream/ + replace github.com/aws/aws-sdk-go-v2/internal/configsources => ../../internal/configsources/ replace github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 => ../../internal/endpoints/v2/ diff --git a/service/lexruntimev2/serializers.go b/service/lexruntimev2/serializers.go index b50fca2fa3a..8b4bdb0bb77 100644 --- a/service/lexruntimev2/serializers.go +++ b/service/lexruntimev2/serializers.go @@ -6,6 +6,8 @@ import ( "bytes" "context" "fmt" + "github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream" + "github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/eventstreamapi" "github.com/aws/aws-sdk-go-v2/service/lexruntimev2/types" smithy "github.com/aws/smithy-go" "github.com/aws/smithy-go/encoding/httpbinding" @@ -551,6 +553,223 @@ func awsRestjson1_serializeOpHttpBindingsRecognizeUtteranceInput(v *RecognizeUtt return nil } +type awsRestjson1_serializeOpStartConversation struct { +} + +func (*awsRestjson1_serializeOpStartConversation) ID() string { + return "OperationSerializer" +} + +func (m *awsRestjson1_serializeOpStartConversation) HandleSerialize(ctx context.Context, in middleware.SerializeInput, next middleware.SerializeHandler) ( + out middleware.SerializeOutput, metadata middleware.Metadata, err error, +) { + request, ok := in.Request.(*smithyhttp.Request) + if !ok { + return out, metadata, &smithy.SerializationError{Err: fmt.Errorf("unknown transport type %T", in.Request)} + } + + input, ok := in.Parameters.(*StartConversationInput) + _ = input + if !ok { + return out, metadata, &smithy.SerializationError{Err: fmt.Errorf("unknown input parameters type %T", in.Parameters)} + } + + opPath, opQuery := httpbinding.SplitURI("/bots/{botId}/botAliases/{botAliasId}/botLocales/{localeId}/sessions/{sessionId}/conversation") + request.URL.Path = smithyhttp.JoinPath(request.URL.Path, opPath) + request.URL.RawQuery = smithyhttp.JoinRawQuery(request.URL.RawQuery, opQuery) + request.Method = "POST" + restEncoder, err := httpbinding.NewEncoder(request.URL.Path, request.URL.RawQuery, request.Header) + if err != nil { + return out, metadata, &smithy.SerializationError{Err: err} + } + + if err := awsRestjson1_serializeOpHttpBindingsStartConversationInput(input, restEncoder); err != nil { + return out, metadata, &smithy.SerializationError{Err: err} + } + + restEncoder.SetHeader("Content-Type").String("application/vnd.amazon.eventstream") + + if request.Request, err = restEncoder.Encode(request.Request); err != nil { + return out, metadata, &smithy.SerializationError{Err: err} + } + in.Request = request + + return next.HandleSerialize(ctx, in) +} +func awsRestjson1_serializeOpHttpBindingsStartConversationInput(v *StartConversationInput, encoder *httpbinding.Encoder) error { + if v == nil { + return fmt.Errorf("unsupported serialization of nil %T", v) + } + + if v.BotAliasId == nil || len(*v.BotAliasId) == 0 { + return &smithy.SerializationError{Err: fmt.Errorf("input member botAliasId must not be empty")} + } + if v.BotAliasId != nil { + if err := encoder.SetURI("botAliasId").String(*v.BotAliasId); err != nil { + return err + } + } + + if v.BotId == nil || len(*v.BotId) == 0 { + return &smithy.SerializationError{Err: fmt.Errorf("input member botId must not be empty")} + } + if v.BotId != nil { + if err := encoder.SetURI("botId").String(*v.BotId); err != nil { + return err + } + } + + if len(v.ConversationMode) > 0 { + locationName := "X-Amz-Lex-Conversation-Mode" + encoder.SetHeader(locationName).String(string(v.ConversationMode)) + } + + if v.LocaleId == nil || len(*v.LocaleId) == 0 { + return &smithy.SerializationError{Err: fmt.Errorf("input member localeId must not be empty")} + } + if v.LocaleId != nil { + if err := encoder.SetURI("localeId").String(*v.LocaleId); err != nil { + return err + } + } + + if v.SessionId == nil || len(*v.SessionId) == 0 { + return &smithy.SerializationError{Err: fmt.Errorf("input member sessionId must not be empty")} + } + if v.SessionId != nil { + if err := encoder.SetURI("sessionId").String(*v.SessionId); err != nil { + return err + } + } + + return nil +} + +func awsRestjson1_serializeEventStreamStartConversationRequestEventStream(v types.StartConversationRequestEventStream, msg *eventstream.Message) error { + if v == nil { + return fmt.Errorf("unexpected serialization of nil %T", v) + } + + switch vv := v.(type) { + case *types.StartConversationRequestEventStreamMemberConfigurationEvent: + msg.Headers.Set(eventstreamapi.EventTypeHeader, eventstream.StringValue("ConfigurationEvent")) + return awsRestjson1_serializeEventMessageConfigurationEvent(&vv.Value, msg) + + case *types.StartConversationRequestEventStreamMemberAudioInputEvent: + msg.Headers.Set(eventstreamapi.EventTypeHeader, eventstream.StringValue("AudioInputEvent")) + return awsRestjson1_serializeEventMessageAudioInputEvent(&vv.Value, msg) + + case *types.StartConversationRequestEventStreamMemberDTMFInputEvent: + msg.Headers.Set(eventstreamapi.EventTypeHeader, eventstream.StringValue("DTMFInputEvent")) + return awsRestjson1_serializeEventMessageDTMFInputEvent(&vv.Value, msg) + + case *types.StartConversationRequestEventStreamMemberTextInputEvent: + msg.Headers.Set(eventstreamapi.EventTypeHeader, eventstream.StringValue("TextInputEvent")) + return awsRestjson1_serializeEventMessageTextInputEvent(&vv.Value, msg) + + case *types.StartConversationRequestEventStreamMemberPlaybackCompletionEvent: + msg.Headers.Set(eventstreamapi.EventTypeHeader, eventstream.StringValue("PlaybackCompletionEvent")) + return awsRestjson1_serializeEventMessagePlaybackCompletionEvent(&vv.Value, msg) + + case *types.StartConversationRequestEventStreamMemberDisconnectionEvent: + msg.Headers.Set(eventstreamapi.EventTypeHeader, eventstream.StringValue("DisconnectionEvent")) + return awsRestjson1_serializeEventMessageDisconnectionEvent(&vv.Value, msg) + + default: + return fmt.Errorf("unexpected event message type: %v", v) + + } +} +func awsRestjson1_serializeEventMessageAudioInputEvent(v *types.AudioInputEvent, msg *eventstream.Message) error { + if v == nil { + return fmt.Errorf("unexpected serialization of nil %T", v) + } + + msg.Headers.Set(eventstreamapi.MessageTypeHeader, eventstream.StringValue(eventstreamapi.EventMessageType)) + msg.Headers.Set(eventstreamapi.ContentTypeHeader, eventstream.StringValue("application/json")) + jsonEncoder := smithyjson.NewEncoder() + if err := awsRestjson1_serializeDocumentAudioInputEvent(v, jsonEncoder.Value); err != nil { + return err + } + msg.Payload = jsonEncoder.Bytes() + return nil +} + +func awsRestjson1_serializeEventMessageConfigurationEvent(v *types.ConfigurationEvent, msg *eventstream.Message) error { + if v == nil { + return fmt.Errorf("unexpected serialization of nil %T", v) + } + + msg.Headers.Set(eventstreamapi.MessageTypeHeader, eventstream.StringValue(eventstreamapi.EventMessageType)) + msg.Headers.Set(eventstreamapi.ContentTypeHeader, eventstream.StringValue("application/json")) + jsonEncoder := smithyjson.NewEncoder() + if err := awsRestjson1_serializeDocumentConfigurationEvent(v, jsonEncoder.Value); err != nil { + return err + } + msg.Payload = jsonEncoder.Bytes() + return nil +} + +func awsRestjson1_serializeEventMessageDisconnectionEvent(v *types.DisconnectionEvent, msg *eventstream.Message) error { + if v == nil { + return fmt.Errorf("unexpected serialization of nil %T", v) + } + + msg.Headers.Set(eventstreamapi.MessageTypeHeader, eventstream.StringValue(eventstreamapi.EventMessageType)) + msg.Headers.Set(eventstreamapi.ContentTypeHeader, eventstream.StringValue("application/json")) + jsonEncoder := smithyjson.NewEncoder() + if err := awsRestjson1_serializeDocumentDisconnectionEvent(v, jsonEncoder.Value); err != nil { + return err + } + msg.Payload = jsonEncoder.Bytes() + return nil +} + +func awsRestjson1_serializeEventMessageDTMFInputEvent(v *types.DTMFInputEvent, msg *eventstream.Message) error { + if v == nil { + return fmt.Errorf("unexpected serialization of nil %T", v) + } + + msg.Headers.Set(eventstreamapi.MessageTypeHeader, eventstream.StringValue(eventstreamapi.EventMessageType)) + msg.Headers.Set(eventstreamapi.ContentTypeHeader, eventstream.StringValue("application/json")) + jsonEncoder := smithyjson.NewEncoder() + if err := awsRestjson1_serializeDocumentDTMFInputEvent(v, jsonEncoder.Value); err != nil { + return err + } + msg.Payload = jsonEncoder.Bytes() + return nil +} + +func awsRestjson1_serializeEventMessagePlaybackCompletionEvent(v *types.PlaybackCompletionEvent, msg *eventstream.Message) error { + if v == nil { + return fmt.Errorf("unexpected serialization of nil %T", v) + } + + msg.Headers.Set(eventstreamapi.MessageTypeHeader, eventstream.StringValue(eventstreamapi.EventMessageType)) + msg.Headers.Set(eventstreamapi.ContentTypeHeader, eventstream.StringValue("application/json")) + jsonEncoder := smithyjson.NewEncoder() + if err := awsRestjson1_serializeDocumentPlaybackCompletionEvent(v, jsonEncoder.Value); err != nil { + return err + } + msg.Payload = jsonEncoder.Bytes() + return nil +} + +func awsRestjson1_serializeEventMessageTextInputEvent(v *types.TextInputEvent, msg *eventstream.Message) error { + if v == nil { + return fmt.Errorf("unexpected serialization of nil %T", v) + } + + msg.Headers.Set(eventstreamapi.MessageTypeHeader, eventstream.StringValue(eventstreamapi.EventMessageType)) + msg.Headers.Set(eventstreamapi.ContentTypeHeader, eventstream.StringValue("application/json")) + jsonEncoder := smithyjson.NewEncoder() + if err := awsRestjson1_serializeDocumentTextInputEvent(v, jsonEncoder.Value); err != nil { + return err + } + msg.Payload = jsonEncoder.Bytes() + return nil +} + func awsRestjson1_serializeDocumentActiveContext(v *types.ActiveContext, value smithyjson.Value) error { object := value.Object() defer object.Close() @@ -618,6 +837,33 @@ func awsRestjson1_serializeDocumentActiveContextTimeToLive(v *types.ActiveContex return nil } +func awsRestjson1_serializeDocumentAudioInputEvent(v *types.AudioInputEvent, value smithyjson.Value) error { + object := value.Object() + defer object.Close() + + if v.AudioChunk != nil { + ok := object.Key("audioChunk") + ok.Base64EncodeBytes(v.AudioChunk) + } + + if v.ClientTimestampMillis != 0 { + ok := object.Key("clientTimestampMillis") + ok.Long(v.ClientTimestampMillis) + } + + if v.ContentType != nil { + ok := object.Key("contentType") + ok.String(*v.ContentType) + } + + if v.EventId != nil { + ok := object.Key("eventId") + ok.String(*v.EventId) + } + + return nil +} + func awsRestjson1_serializeDocumentButton(v *types.Button, value smithyjson.Value) error { object := value.Object() defer object.Close() @@ -648,6 +894,54 @@ func awsRestjson1_serializeDocumentButtonsList(v []types.Button, value smithyjso return nil } +func awsRestjson1_serializeDocumentConfigurationEvent(v *types.ConfigurationEvent, value smithyjson.Value) error { + object := value.Object() + defer object.Close() + + if v.ClientTimestampMillis != 0 { + ok := object.Key("clientTimestampMillis") + ok.Long(v.ClientTimestampMillis) + } + + if v.DisablePlayback { + ok := object.Key("disablePlayback") + ok.Boolean(v.DisablePlayback) + } + + if v.EventId != nil { + ok := object.Key("eventId") + ok.String(*v.EventId) + } + + if v.RequestAttributes != nil { + ok := object.Key("requestAttributes") + if err := awsRestjson1_serializeDocumentStringMap(v.RequestAttributes, ok); err != nil { + return err + } + } + + if v.ResponseContentType != nil { + ok := object.Key("responseContentType") + ok.String(*v.ResponseContentType) + } + + if v.SessionState != nil { + ok := object.Key("sessionState") + if err := awsRestjson1_serializeDocumentSessionState(v.SessionState, ok); err != nil { + return err + } + } + + if v.WelcomeMessages != nil { + ok := object.Key("welcomeMessages") + if err := awsRestjson1_serializeDocumentMessages(v.WelcomeMessages, ok); err != nil { + return err + } + } + + return nil +} + func awsRestjson1_serializeDocumentDialogAction(v *types.DialogAction, value smithyjson.Value) error { object := value.Object() defer object.Close() @@ -670,6 +964,45 @@ func awsRestjson1_serializeDocumentDialogAction(v *types.DialogAction, value smi return nil } +func awsRestjson1_serializeDocumentDisconnectionEvent(v *types.DisconnectionEvent, value smithyjson.Value) error { + object := value.Object() + defer object.Close() + + if v.ClientTimestampMillis != 0 { + ok := object.Key("clientTimestampMillis") + ok.Long(v.ClientTimestampMillis) + } + + if v.EventId != nil { + ok := object.Key("eventId") + ok.String(*v.EventId) + } + + return nil +} + +func awsRestjson1_serializeDocumentDTMFInputEvent(v *types.DTMFInputEvent, value smithyjson.Value) error { + object := value.Object() + defer object.Close() + + if v.ClientTimestampMillis != 0 { + ok := object.Key("clientTimestampMillis") + ok.Long(v.ClientTimestampMillis) + } + + if v.EventId != nil { + ok := object.Key("eventId") + ok.String(*v.EventId) + } + + if v.InputCharacter != nil { + ok := object.Key("inputCharacter") + ok.String(*v.InputCharacter) + } + + return nil +} + func awsRestjson1_serializeDocumentImageResponseCard(v *types.ImageResponseCard, value smithyjson.Value) error { object := value.Object() defer object.Close() @@ -765,6 +1098,23 @@ func awsRestjson1_serializeDocumentMessages(v []types.Message, value smithyjson. return nil } +func awsRestjson1_serializeDocumentPlaybackCompletionEvent(v *types.PlaybackCompletionEvent, value smithyjson.Value) error { + object := value.Object() + defer object.Close() + + if v.ClientTimestampMillis != 0 { + ok := object.Key("clientTimestampMillis") + ok.Long(v.ClientTimestampMillis) + } + + if v.EventId != nil { + ok := object.Key("eventId") + ok.String(*v.EventId) + } + + return nil +} + func awsRestjson1_serializeDocumentSessionState(v *types.SessionState, value smithyjson.Value) error { object := value.Object() defer object.Close() @@ -867,6 +1217,28 @@ func awsRestjson1_serializeDocumentStringMap(v map[string]string, value smithyjs return nil } +func awsRestjson1_serializeDocumentTextInputEvent(v *types.TextInputEvent, value smithyjson.Value) error { + object := value.Object() + defer object.Close() + + if v.ClientTimestampMillis != 0 { + ok := object.Key("clientTimestampMillis") + ok.Long(v.ClientTimestampMillis) + } + + if v.EventId != nil { + ok := object.Key("eventId") + ok.String(*v.EventId) + } + + if v.Text != nil { + ok := object.Key("text") + ok.String(*v.Text) + } + + return nil +} + func awsRestjson1_serializeDocumentValue(v *types.Value, value smithyjson.Value) error { object := value.Object() defer object.Close() diff --git a/service/lexruntimev2/types/enums.go b/service/lexruntimev2/types/enums.go index b085130bc35..ad24a2d9e58 100644 --- a/service/lexruntimev2/types/enums.go +++ b/service/lexruntimev2/types/enums.go @@ -22,6 +22,24 @@ func (ConfirmationState) Values() []ConfirmationState { } } +type ConversationMode string + +// Enum values for ConversationMode +const ( + ConversationModeAudio ConversationMode = "AUDIO" + ConversationModeText ConversationMode = "TEXT" +) + +// Values returns all known values for ConversationMode. Note that this can be +// expanded in the future, and so it is only as up to date as the client. The +// ordering of this slice is not guaranteed to be stable across updates. +func (ConversationMode) Values() []ConversationMode { + return []ConversationMode{ + "AUDIO", + "TEXT", + } +} + type DialogActionType string // Enum values for DialogActionType @@ -48,6 +66,26 @@ func (DialogActionType) Values() []DialogActionType { } } +type InputMode string + +// Enum values for InputMode +const ( + InputModeText InputMode = "Text" + InputModeSpeech InputMode = "Speech" + InputModeDtmf InputMode = "DTMF" +) + +// Values returns all known values for InputMode. Note that this can be expanded in +// the future, and so it is only as up to date as the client. The ordering of this +// slice is not guaranteed to be stable across updates. +func (InputMode) Values() []InputMode { + return []InputMode{ + "Text", + "Speech", + "DTMF", + } +} + type IntentState string // Enum values for IntentState @@ -96,6 +134,26 @@ func (MessageContentType) Values() []MessageContentType { } } +type PlaybackInterruptionReason string + +// Enum values for PlaybackInterruptionReason +const ( + PlaybackInterruptionReasonDtmfStartDetected PlaybackInterruptionReason = "DTMF_START_DETECTED" + PlaybackInterruptionReasonTextDetected PlaybackInterruptionReason = "TEXT_DETECTED" + PlaybackInterruptionReasonVoiceStartDetected PlaybackInterruptionReason = "VOICE_START_DETECTED" +) + +// Values returns all known values for PlaybackInterruptionReason. Note that this +// can be expanded in the future, and so it is only as up to date as the client. +// The ordering of this slice is not guaranteed to be stable across updates. +func (PlaybackInterruptionReason) Values() []PlaybackInterruptionReason { + return []PlaybackInterruptionReason{ + "DTMF_START_DETECTED", + "TEXT_DETECTED", + "VOICE_START_DETECTED", + } +} + type SentimentType string // Enum values for SentimentType diff --git a/service/lexruntimev2/types/types.go b/service/lexruntimev2/types/types.go index b9dc021cca9..cb6581c9184 100644 --- a/service/lexruntimev2/types/types.go +++ b/service/lexruntimev2/types/types.go @@ -56,6 +56,52 @@ type ActiveContextTimeToLive struct { noSmithyDocumentSerde } +// Represents a chunk of audio sent from the client application to Amazon Lex V2. +// The audio is all or part of an utterance from the user. Amazon Lex V2 +// accumulates audio chunks until it recognizes a natural pause in speech before +// processing the input. +type AudioInputEvent struct { + + // The encoding used for the audio chunk. You must use 8 KHz PCM 16-bit + // mono-channel little-endian format. The value of the field should be: audio/lpcm; + // sample-rate=8000; sample-size-bits=16; channel-count=1; is-big-endian=false + // + // This member is required. + ContentType *string + + // An encoded stream of audio. + AudioChunk []byte + + // A timestamp set by the client of the date and time that the event was sent to + // Amazon Lex V2. + ClientTimestampMillis int64 + + // A unique identifier that your application assigns to the event. You can use this + // to identify events in logs. + EventId *string + + noSmithyDocumentSerde +} + +// An event sent from Amazon Lex V2 to your client application containing audio to +// play to the user. +type AudioResponseEvent struct { + + // A chunk of the audio to play. + AudioChunk []byte + + // The encoding of the audio chunk. This is the same as the encoding configure in + // the contentType field of the ConfigurationEvent. + ContentType *string + + // A unique identifier of the event sent by Amazon Lex V2. The identifier is in the + // form RESPONSE-N, where N is a number starting with one and incremented for each + // event sent by Amazon Lex V2 in the current session. + EventId *string + + noSmithyDocumentSerde +} + // A button that appears on a response card show to the user. type Button struct { @@ -84,6 +130,73 @@ type ConfidenceScore struct { noSmithyDocumentSerde } +// The initial event sent from the application to Amazon Lex V2 to configure the +// conversation, including session and request attributes and the response content +// type. +type ConfigurationEvent struct { + + // The message that Amazon Lex V2 returns in the response can be either text or + // speech based on the responseContentType value. + // + // * If the value is + // text/plain;charset=utf-8, Amazon Lex V2 returns text in the response. + // + // * If the + // value begins with audio/, Amazon Lex V2 returns speech in the response. Amazon + // Lex V2 uses Amazon Polly to generate the speech using the configuration that you + // specified in the requestContentType parameter. For example, if you specify + // audio/mpeg as the value, Amazon Lex V2 returns speech in the MPEG format. + // + // * If + // the value is audio/pcm, the speech returned is audio/pcm in 16-bit, + // little-endian format. + // + // * The following are the accepted values: + // + // * audio/mpeg + // + // * + // audio/ogg + // + // * audio/pcm + // + // * audio/* (defaults to mpeg) + // + // * text/plain; + // charset=utf-8 + // + // This member is required. + ResponseContentType *string + + // A timestamp set by the client of the date and time that the event was sent to + // Amazon Lex V2. + ClientTimestampMillis int64 + + // Determines whether Amazon Lex V2 should send audio responses to the client + // application. Set this field to false when the client is operating in a playback + // mode where audio responses are played to the user. If the client isn't operating + // in playback mode, such as a text chat application, set this to true so that + // Amazon Lex V2 doesn't wait for the prompt to finish playing on the client. + DisablePlayback bool + + // A unique identifier that your application assigns to the event. You can use this + // to identify events in logs. + EventId *string + + // Request-specific information passed between the client application and Amazon + // Lex V2. The namespace x-amz-lex: is reserved for special attributes. Don't + // create any request attributes for prefix x-amz-lex:. + RequestAttributes map[string]string + + // The state of the user's session with Amazon Lex V2. + SessionState *SessionState + + // A list of messages to send to the user. + WelcomeMessages []Message + + noSmithyDocumentSerde +} + // The next action that Amazon Lex V2 should take. type DialogAction struct { @@ -125,6 +238,56 @@ type DialogAction struct { noSmithyDocumentSerde } +// A notification from the client that it is disconnecting from Amazon Lex V2. +// Sending a DisconnectionEvent event is optional, but can help identify a +// conversation in logs. +type DisconnectionEvent struct { + + // A timestamp set by the client of the date and time that the event was sent to + // Amazon Lex V2. + ClientTimestampMillis int64 + + // A unique identifier that your application assigns to the event. You can use this + // to identify events in logs. + EventId *string + + noSmithyDocumentSerde +} + +// A DTMF character sent from the client application. DTMF characters are typically +// sent from a phone keypad to represent numbers. For example, you can have Amazon +// Lex V2 process a credit card number input from a phone. +type DTMFInputEvent struct { + + // The DTMF character that the user pressed. The allowed characters are A - D, 0 - + // 9, # and *. + // + // This member is required. + InputCharacter *string + + // A timestamp set by the client of the date and time that the event was sent to + // Amazon Lex V2. + ClientTimestampMillis int64 + + // A unique identifier that your application assigns to the event. You can use this + // to identify events in logs. + EventId *string + + noSmithyDocumentSerde +} + +// Event that Amazon Lex V2 sends to indicate that the stream is still open between +// the client application and Amazon Lex V2 +type HeartbeatEvent struct { + + // A unique identifier of the event sent by Amazon Lex V2. The identifier is in the + // form RESPONSE-N, where N is a number starting with one and incremented for each + // event sent by Amazon Lex V2 in the current session. + EventId *string + + noSmithyDocumentSerde +} + // A card that is shown to the user by a messaging platform. You define the // contents of the card, the card is displayed by the platform. When you use a // response card, the response from the user is constrained to the text associated @@ -174,6 +337,37 @@ type Intent struct { noSmithyDocumentSerde } +// Contains the current state of the conversation between the client application +// and Amazon Lex V2. +type IntentResultEvent struct { + + // A unique identifier of the event sent by Amazon Lex V2. The identifier is in the + // form RESPONSE-N, where N is a number starting with one and incremented for each + // event sent by Amazon Lex V2 in the current session. + EventId *string + + // Indicates whether the input to the operation was text or speech. + InputMode InputMode + + // A list of intents that Amazon Lex V2 determined might satisfy the user's + // utterance. Each interpretation includes the intent, a score that indicates how + // confident Amazon Lex V2 is that the interpretation is the correct one, and an + // optional sentiment response that indicates the sentiment expressed in the + // utterance. + Interpretations []Interpretation + + // The attributes sent in the request. + RequestAttributes map[string]string + + // The identifier of the session in use. + SessionId *string + + // The state of the user's session with Amazon Lex V2. + SessionState *SessionState + + noSmithyDocumentSerde +} + // An intent that Amazon Lex V2 determined might satisfy the user's utterance. The // intents are ordered by the confidence score. type Interpretation struct { @@ -216,6 +410,45 @@ type Message struct { noSmithyDocumentSerde } +// Event sent from the client application to Amazon Lex V2 to indicate that +// playback of audio is complete and that Amazon Lex V2 should start processing the +// user's input. +type PlaybackCompletionEvent struct { + + // A timestamp set by the client of the date and time that the event was sent to + // Amazon Lex V2. + ClientTimestampMillis int64 + + // A unique identifier that your application assigns to the event. You can use this + // to identify events in logs. + EventId *string + + noSmithyDocumentSerde +} + +// Event sent from Amazon Lex V2 to indicate to the client application should stop +// playback of audio. For example, if the client is playing a prompt that asks for +// the user's telephone number, the user might start to say the phone number before +// the prompt is complete. Amazon Lex V2 sends this event to the client application +// to indicate that the user is responding and that Amazon Lex V2 is processing +// their input. +type PlaybackInterruptionEvent struct { + + // The identifier of the event that contained the audio, DTMF, or text that caused + // the interruption. + CausedByEventId *string + + // A unique identifier of the event sent by Amazon Lex V2. The identifier is in the + // form RESPONSE-N, where N is a number starting with one and incremented for each + // event sent by Amazon Lex V2 in the current session. + EventId *string + + // Indicates the type of user input that Amazon Lex V2 detected. + EventReason PlaybackInterruptionReason + + noSmithyDocumentSerde +} + // Provides information about the sentiment expressed in a user's response in a // conversation. Sentiments are determined using Amazon Comprehend. Sentiments are // only returned if they are enabled for the bot. For more information, see @@ -300,6 +533,231 @@ type Slot struct { noSmithyDocumentSerde } +// Represents a stream of events between your application and Amazon Lex V2. +// +// The following types satisfy this interface: +// StartConversationRequestEventStreamMemberAudioInputEvent +// StartConversationRequestEventStreamMemberConfigurationEvent +// StartConversationRequestEventStreamMemberDisconnectionEvent +// StartConversationRequestEventStreamMemberDTMFInputEvent +// StartConversationRequestEventStreamMemberPlaybackCompletionEvent +// StartConversationRequestEventStreamMemberTextInputEvent +type StartConversationRequestEventStream interface { + isStartConversationRequestEventStream() +} + +// Speech audio sent from your client application to Amazon Lex V2. Audio starts +// accumulating when Amazon Lex V2 identifies a voice and continues until a natural +// pause in the speech is found before processing. +type StartConversationRequestEventStreamMemberAudioInputEvent struct { + Value AudioInputEvent + + noSmithyDocumentSerde +} + +func (*StartConversationRequestEventStreamMemberAudioInputEvent) isStartConversationRequestEventStream() { +} + +// Configuration information sent from your client application to Amazon Lex V2 +type StartConversationRequestEventStreamMemberConfigurationEvent struct { + Value ConfigurationEvent + + noSmithyDocumentSerde +} + +func (*StartConversationRequestEventStreamMemberConfigurationEvent) isStartConversationRequestEventStream() { +} + +// Event sent from the client application to indicate to Amazon Lex V2 that the +// conversation is over. +type StartConversationRequestEventStreamMemberDisconnectionEvent struct { + Value DisconnectionEvent + + noSmithyDocumentSerde +} + +func (*StartConversationRequestEventStreamMemberDisconnectionEvent) isStartConversationRequestEventStream() { +} + +// DTMF information sent to Amazon Lex V2 by your application. Amazon Lex V2 +// accumulates the DMTF information from when the user sends the first character +// and ends +// +// * when there's a pause longer that the value configured for the end +// timeout. +// +// * when there's a digit that is the configured end character. +// +// * when +// Amazon Lex V2 accumulates characters equal to the maximum DTMF character +// configuration. +type StartConversationRequestEventStreamMemberDTMFInputEvent struct { + Value DTMFInputEvent + + noSmithyDocumentSerde +} + +func (*StartConversationRequestEventStreamMemberDTMFInputEvent) isStartConversationRequestEventStream() { +} + +// Event sent from the client application to Amazon Lex V2 to indicate that it has +// finished playing audio and that Amazon Lex V2 should start listening for user +// input. +type StartConversationRequestEventStreamMemberPlaybackCompletionEvent struct { + Value PlaybackCompletionEvent + + noSmithyDocumentSerde +} + +func (*StartConversationRequestEventStreamMemberPlaybackCompletionEvent) isStartConversationRequestEventStream() { +} + +// Text sent from your client application to Amazon Lex V2. Each TextInputEvent is +// processed individually. +type StartConversationRequestEventStreamMemberTextInputEvent struct { + Value TextInputEvent + + noSmithyDocumentSerde +} + +func (*StartConversationRequestEventStreamMemberTextInputEvent) isStartConversationRequestEventStream() { +} + +// Represents a stream of events between Amazon Lex V2 and your application. +// +// The following types satisfy this interface: +// StartConversationResponseEventStreamMemberAudioResponseEvent +// StartConversationResponseEventStreamMemberHeartbeatEvent +// StartConversationResponseEventStreamMemberIntentResultEvent +// StartConversationResponseEventStreamMemberPlaybackInterruptionEvent +// StartConversationResponseEventStreamMemberTextResponseEvent +// StartConversationResponseEventStreamMemberTranscriptEvent +type StartConversationResponseEventStream interface { + isStartConversationResponseEventStream() +} + +// An event sent from Amazon Lex V2 to your client application containing audio to +// play to the user. +type StartConversationResponseEventStreamMemberAudioResponseEvent struct { + Value AudioResponseEvent + + noSmithyDocumentSerde +} + +func (*StartConversationResponseEventStreamMemberAudioResponseEvent) isStartConversationResponseEventStream() { +} + +// Event that Amazon Lex V2 sends to indicate that the stream is still open between +// the client application and Amazon Lex V2 +type StartConversationResponseEventStreamMemberHeartbeatEvent struct { + Value HeartbeatEvent + + noSmithyDocumentSerde +} + +func (*StartConversationResponseEventStreamMemberHeartbeatEvent) isStartConversationResponseEventStream() { +} + +// Event sent from Amazon Lex V2 to the client application containing the current +// state of the conversation between the user and Amazon Lex V2. +type StartConversationResponseEventStreamMemberIntentResultEvent struct { + Value IntentResultEvent + + noSmithyDocumentSerde +} + +func (*StartConversationResponseEventStreamMemberIntentResultEvent) isStartConversationResponseEventStream() { +} + +// Event sent from Amazon Lex V2 to indicate to the client application should stop +// playback of audio. For example, if the client is playing a prompt that asks for +// the user's telephone number, the user might start to say the phone number before +// the prompt is complete. Amazon Lex V2 sends this event to the client application +// to indicate that the user is responding and that Amazon Lex V2 is processing +// their input. +type StartConversationResponseEventStreamMemberPlaybackInterruptionEvent struct { + Value PlaybackInterruptionEvent + + noSmithyDocumentSerde +} + +func (*StartConversationResponseEventStreamMemberPlaybackInterruptionEvent) isStartConversationResponseEventStream() { +} + +// The event sent from Amazon Lex V2 to your application with text to present to +// the user. +type StartConversationResponseEventStreamMemberTextResponseEvent struct { + Value TextResponseEvent + + noSmithyDocumentSerde +} + +func (*StartConversationResponseEventStreamMemberTextResponseEvent) isStartConversationResponseEventStream() { +} + +// Event sent from Amazon Lex V2 to your client application that contains a +// transcript of voice audio. +type StartConversationResponseEventStreamMemberTranscriptEvent struct { + Value TranscriptEvent + + noSmithyDocumentSerde +} + +func (*StartConversationResponseEventStreamMemberTranscriptEvent) isStartConversationResponseEventStream() { +} + +// The event sent from your client application to Amazon Lex V2 with text input +// from the user. +type TextInputEvent struct { + + // The text from the user. Amazon Lex V2 processes this as a complete statement. + // + // This member is required. + Text *string + + // A timestamp set by the client of the date and time that the event was sent to + // Amazon Lex V2. + ClientTimestampMillis int64 + + // A unique identifier that your application assigns to the event. You can use this + // to identify events in logs. + EventId *string + + noSmithyDocumentSerde +} + +// The event sent from Amazon Lex V2 to your application with text to present to +// the user. +type TextResponseEvent struct { + + // A unique identifier of the event sent by Amazon Lex V2. The identifier is in the + // form RESPONSE-N, where N is a number starting with one and incremented for each + // event sent by Amazon Lex V2 in the current session. + EventId *string + + // A list of messages to send to the user. Messages are ordered based on the order + // that you returned the messages from your Lambda function or the order that the + // messages are defined in the bot. + Messages []Message + + noSmithyDocumentSerde +} + +// Event sent from Amazon Lex V2 to your client application that contains a +// transcript of voice audio. +type TranscriptEvent struct { + + // A unique identifier of the event sent by Amazon Lex V2. The identifier is in the + // form RESPONSE-N, where N is a number starting with one and incremented for each + // event sent by Amazon Lex V2 in the current session. + EventId *string + + // The transcript of the voice audio from the user. + Transcript *string + + noSmithyDocumentSerde +} + // The value of a slot. type Value struct { @@ -321,3 +779,15 @@ type Value struct { } type noSmithyDocumentSerde = smithydocument.NoSerde + +// UnknownUnionMember is returned when a union member is returned over the wire, +// but has an unknown tag. +type UnknownUnionMember struct { + Tag string + Value []byte + + noSmithyDocumentSerde +} + +func (*UnknownUnionMember) isStartConversationRequestEventStream() {} +func (*UnknownUnionMember) isStartConversationResponseEventStream() {} diff --git a/service/lexruntimev2/types/types_exported_test.go b/service/lexruntimev2/types/types_exported_test.go new file mode 100644 index 00000000000..ed19dff1526 --- /dev/null +++ b/service/lexruntimev2/types/types_exported_test.go @@ -0,0 +1,84 @@ +// Code generated by smithy-go-codegen DO NOT EDIT. + +package types_test + +import ( + "fmt" + "github.com/aws/aws-sdk-go-v2/service/lexruntimev2/types" +) + +func ExampleStartConversationRequestEventStream_outputUsage() { + var union types.StartConversationRequestEventStream + // type switches can be used to check the union value + switch v := union.(type) { + case *types.StartConversationRequestEventStreamMemberAudioInputEvent: + _ = v.Value // Value is types.AudioInputEvent + + case *types.StartConversationRequestEventStreamMemberConfigurationEvent: + _ = v.Value // Value is types.ConfigurationEvent + + case *types.StartConversationRequestEventStreamMemberDisconnectionEvent: + _ = v.Value // Value is types.DisconnectionEvent + + case *types.StartConversationRequestEventStreamMemberDTMFInputEvent: + _ = v.Value // Value is types.DTMFInputEvent + + case *types.StartConversationRequestEventStreamMemberPlaybackCompletionEvent: + _ = v.Value // Value is types.PlaybackCompletionEvent + + case *types.StartConversationRequestEventStreamMemberTextInputEvent: + _ = v.Value // Value is types.TextInputEvent + + case *types.UnknownUnionMember: + fmt.Println("unknown tag:", v.Tag) + + default: + fmt.Println("union is nil or unknown type") + + } +} + +var _ *types.AudioInputEvent +var _ *types.TextInputEvent +var _ *types.ConfigurationEvent +var _ *types.DisconnectionEvent +var _ *types.DTMFInputEvent +var _ *types.PlaybackCompletionEvent + +func ExampleStartConversationResponseEventStream_outputUsage() { + var union types.StartConversationResponseEventStream + // type switches can be used to check the union value + switch v := union.(type) { + case *types.StartConversationResponseEventStreamMemberAudioResponseEvent: + _ = v.Value // Value is types.AudioResponseEvent + + case *types.StartConversationResponseEventStreamMemberHeartbeatEvent: + _ = v.Value // Value is types.HeartbeatEvent + + case *types.StartConversationResponseEventStreamMemberIntentResultEvent: + _ = v.Value // Value is types.IntentResultEvent + + case *types.StartConversationResponseEventStreamMemberPlaybackInterruptionEvent: + _ = v.Value // Value is types.PlaybackInterruptionEvent + + case *types.StartConversationResponseEventStreamMemberTextResponseEvent: + _ = v.Value // Value is types.TextResponseEvent + + case *types.StartConversationResponseEventStreamMemberTranscriptEvent: + _ = v.Value // Value is types.TranscriptEvent + + case *types.UnknownUnionMember: + fmt.Println("unknown tag:", v.Tag) + + default: + fmt.Println("union is nil or unknown type") + + } +} + +var _ *types.IntentResultEvent +var _ *types.HeartbeatEvent +var _ *types.AudioResponseEvent +var _ *types.PlaybackInterruptionEvent +var _ *types.TranscriptEvent +var _ *types.TextResponseEvent diff --git a/service/lexruntimev2/validators.go b/service/lexruntimev2/validators.go index e3a0381dfab..f8cab94205b 100644 --- a/service/lexruntimev2/validators.go +++ b/service/lexruntimev2/validators.go @@ -110,6 +110,26 @@ func (m *validateOpRecognizeUtterance) HandleInitialize(ctx context.Context, in return next.HandleInitialize(ctx, in) } +type validateOpStartConversation struct { +} + +func (*validateOpStartConversation) ID() string { + return "OperationInputValidation" +} + +func (m *validateOpStartConversation) HandleInitialize(ctx context.Context, in middleware.InitializeInput, next middleware.InitializeHandler) ( + out middleware.InitializeOutput, metadata middleware.Metadata, err error, +) { + input, ok := in.Parameters.(*StartConversationInput) + if !ok { + return out, metadata, fmt.Errorf("unknown input parameters type %T", in.Parameters) + } + if err := validateOpStartConversationInput(input); err != nil { + return out, metadata, err + } + return next.HandleInitialize(ctx, in) +} + func addOpDeleteSessionValidationMiddleware(stack *middleware.Stack) error { return stack.Initialize.Add(&validateOpDeleteSession{}, middleware.After) } @@ -130,6 +150,10 @@ func addOpRecognizeUtteranceValidationMiddleware(stack *middleware.Stack) error return stack.Initialize.Add(&validateOpRecognizeUtterance{}, middleware.After) } +func addOpStartConversationValidationMiddleware(stack *middleware.Stack) error { + return stack.Initialize.Add(&validateOpStartConversation{}, middleware.After) +} + func validateActiveContext(v *types.ActiveContext) error { if v == nil { return nil @@ -190,6 +214,21 @@ func validateActiveContextTimeToLive(v *types.ActiveContextTimeToLive) error { } } +func validateAudioInputEvent(v *types.AudioInputEvent) error { + if v == nil { + return nil + } + invalidParams := smithy.InvalidParamsError{Context: "AudioInputEvent"} + if v.ContentType == nil { + invalidParams.Add(smithy.NewErrParamRequired("ContentType")) + } + if invalidParams.Len() > 0 { + return invalidParams + } else { + return nil + } +} + func validateButton(v *types.Button) error { if v == nil { return nil @@ -225,6 +264,31 @@ func validateButtonsList(v []types.Button) error { } } +func validateConfigurationEvent(v *types.ConfigurationEvent) error { + if v == nil { + return nil + } + invalidParams := smithy.InvalidParamsError{Context: "ConfigurationEvent"} + if v.ResponseContentType == nil { + invalidParams.Add(smithy.NewErrParamRequired("ResponseContentType")) + } + if v.SessionState != nil { + if err := validateSessionState(v.SessionState); err != nil { + invalidParams.AddNested("SessionState", err.(smithy.InvalidParamsError)) + } + } + if v.WelcomeMessages != nil { + if err := validateMessages(v.WelcomeMessages); err != nil { + invalidParams.AddNested("WelcomeMessages", err.(smithy.InvalidParamsError)) + } + } + if invalidParams.Len() > 0 { + return invalidParams + } else { + return nil + } +} + func validateDialogAction(v *types.DialogAction) error { if v == nil { return nil @@ -240,6 +304,21 @@ func validateDialogAction(v *types.DialogAction) error { } } +func validateDTMFInputEvent(v *types.DTMFInputEvent) error { + if v == nil { + return nil + } + invalidParams := smithy.InvalidParamsError{Context: "DTMFInputEvent"} + if v.InputCharacter == nil { + invalidParams.Add(smithy.NewErrParamRequired("InputCharacter")) + } + if invalidParams.Len() > 0 { + return invalidParams + } else { + return nil + } +} + func validateImageResponseCard(v *types.ImageResponseCard) error { if v == nil { return nil @@ -384,6 +463,55 @@ func validateSlots(v map[string]types.Slot) error { } } +func validateStartConversationRequestEventStream(v types.StartConversationRequestEventStream) error { + if v == nil { + return nil + } + invalidParams := smithy.InvalidParamsError{Context: "StartConversationRequestEventStream"} + switch uv := v.(type) { + case *types.StartConversationRequestEventStreamMemberAudioInputEvent: + if err := validateAudioInputEvent(&uv.Value); err != nil { + invalidParams.AddNested("[AudioInputEvent]", err.(smithy.InvalidParamsError)) + } + + case *types.StartConversationRequestEventStreamMemberConfigurationEvent: + if err := validateConfigurationEvent(&uv.Value); err != nil { + invalidParams.AddNested("[ConfigurationEvent]", err.(smithy.InvalidParamsError)) + } + + case *types.StartConversationRequestEventStreamMemberDTMFInputEvent: + if err := validateDTMFInputEvent(&uv.Value); err != nil { + invalidParams.AddNested("[DTMFInputEvent]", err.(smithy.InvalidParamsError)) + } + + case *types.StartConversationRequestEventStreamMemberTextInputEvent: + if err := validateTextInputEvent(&uv.Value); err != nil { + invalidParams.AddNested("[TextInputEvent]", err.(smithy.InvalidParamsError)) + } + + } + if invalidParams.Len() > 0 { + return invalidParams + } else { + return nil + } +} + +func validateTextInputEvent(v *types.TextInputEvent) error { + if v == nil { + return nil + } + invalidParams := smithy.InvalidParamsError{Context: "TextInputEvent"} + if v.Text == nil { + invalidParams.Add(smithy.NewErrParamRequired("Text")) + } + if invalidParams.Len() > 0 { + return invalidParams + } else { + return nil + } +} + func validateValue(v *types.Value) error { if v == nil { return nil @@ -558,3 +686,27 @@ func validateOpRecognizeUtteranceInput(v *RecognizeUtteranceInput) error { return nil } } + +func validateOpStartConversationInput(v *StartConversationInput) error { + if v == nil { + return nil + } + invalidParams := smithy.InvalidParamsError{Context: "StartConversationInput"} + if v.BotId == nil { + invalidParams.Add(smithy.NewErrParamRequired("BotId")) + } + if v.BotAliasId == nil { + invalidParams.Add(smithy.NewErrParamRequired("BotAliasId")) + } + if v.LocaleId == nil { + invalidParams.Add(smithy.NewErrParamRequired("LocaleId")) + } + if v.SessionId == nil { + invalidParams.Add(smithy.NewErrParamRequired("SessionId")) + } + if invalidParams.Len() > 0 { + return invalidParams + } else { + return nil + } +}