From 0427652ff8188da015842f9861dfb2775f777b21 Mon Sep 17 00:00:00 2001 From: Paul Jakob Kroker Date: Wed, 25 Mar 2026 14:05:21 +0100 Subject: [PATCH 1/4] feat(graphql-conversation-transformer): add usage and metrics fields to message model --- .../src/graphql-types/message-model.ts | 6 +++++- .../assistant-streaming-mutation-resolver-fn.template.js | 8 +++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/packages/amplify-graphql-conversation-transformer/src/graphql-types/message-model.ts b/packages/amplify-graphql-conversation-transformer/src/graphql-types/message-model.ts index 1cecbede95..026e86692a 100644 --- a/packages/amplify-graphql-conversation-transformer/src/graphql-types/message-model.ts +++ b/packages/amplify-graphql-conversation-transformer/src/graphql-types/message-model.ts @@ -141,6 +141,8 @@ export const createAssistantResponseStreamingMutationInput = (messageModelName: makeInputValueDefinition('accumulatedTurnContent', makeListType(makeNamedType('AmplifyAIContentBlockInput'))), makeInputValueDefinition('errors', makeListType(makeNamedType('AmplifyAIConversationTurnErrorInput'))), makeInputValueDefinition('p', makeNamedType('String')), + makeInputValueDefinition('metrics', makeNamedType('AWSJSON')), + makeInputValueDefinition('usage', makeNamedType('AWSJSON')), ], }; }; @@ -282,11 +284,13 @@ const constructConversationMessageModel = ( const context = makeField('aiContext', [], makeNamedType('AWSJSON')); const uiComponents = makeField('toolConfiguration', [], makeNamedType('AmplifyAIToolConfiguration')); const associatedUserMessageId = makeField('associatedUserMessageId', [], makeNamedType('ID')); + const metrics = makeField('metrics', [], makeNamedType('AmplifyAIMetrics')); + const usage = makeField('usage', [], makeNamedType('AmplifyAIUsage')); const object = { ...blankObject(modelName), interfaces: [conversationMessageInterface], - fields: [id, conversationId, conversationField, role, content, context, uiComponents, associatedUserMessageId], + fields: [id, conversationId, conversationField, role, content, context, uiComponents, associatedUserMessageId, metrics, usage], directives: typeDirectives, }; diff --git a/packages/amplify-graphql-conversation-transformer/src/resolvers/templates/assistant-streaming-mutation-resolver-fn.template.js b/packages/amplify-graphql-conversation-transformer/src/resolvers/templates/assistant-streaming-mutation-resolver-fn.template.js index c08825ba88..5dc6e56ca7 100644 --- a/packages/amplify-graphql-conversation-transformer/src/resolvers/templates/assistant-streaming-mutation-resolver-fn.template.js +++ b/packages/amplify-graphql-conversation-transformer/src/resolvers/templates/assistant-streaming-mutation-resolver-fn.template.js @@ -12,6 +12,8 @@ export function request(ctx) { associatedUserMessageId, accumulatedTurnContent, errors, + metrics, + usage, } = ctx.args.input; const { owner } = ctx.args; @@ -28,7 +30,7 @@ export function request(ctx) { const { createdAt, updatedAt } = ctx.stash.defaultValues; const assistantResponseId = `${associatedUserMessageId}#response`; - const expression = 'SET #typename = :typename, #conversationId = :conversationId, #associatedUserMessageId = :associatedUserMessageId, #role = :role, #content = :content, #owner = :owner, #createdAt = if_not_exists(#createdAt, :createdAt), #updatedAt = :updatedAt'; + const expression = 'SET #typename = :typename, #conversationId = :conversationId, #associatedUserMessageId = :associatedUserMessageId, #role = :role, #content = :content, #owner = :owner, #createdAt = if_not_exists(#createdAt, :createdAt), #updatedAt = :updatedAt, #metrics = :metrics, #usage = :usage'; const expressionValues = util.dynamodb.toMapValues({ ':typename': '[[CONVERSATION_MESSAGE_TYPE_NAME]]', @@ -39,6 +41,8 @@ export function request(ctx) { ':owner': owner, ':createdAt': createdAt, ':updatedAt': updatedAt, + ':metrics': metrics, + ':usage': usage, }); // https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ReservedWords.html @@ -51,6 +55,8 @@ export function request(ctx) { '#owner': 'owner', '#createdAt': 'createdAt', '#updatedAt': 'updatedAt', + '#metrics': 'metrics', + '#usage': 'usage', }; return { From 18ef668175330321d0a3812f54b34da8d60f17b1 Mon Sep 17 00:00:00 2001 From: Paul Jakob Kroker Date: Wed, 25 Mar 2026 14:06:00 +0100 Subject: [PATCH 2/4] feat(graphql-conversation-transformer): add usage and metrics to streaming resolver --- .../src/resolvers/send-message-pipeline-definition.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/amplify-graphql-conversation-transformer/src/resolvers/send-message-pipeline-definition.ts b/packages/amplify-graphql-conversation-transformer/src/resolvers/send-message-pipeline-definition.ts index d06d55d0bc..8df8fca683 100644 --- a/packages/amplify-graphql-conversation-transformer/src/resolvers/send-message-pipeline-definition.ts +++ b/packages/amplify-graphql-conversation-transformer/src/resolvers/send-message-pipeline-definition.ts @@ -134,4 +134,4 @@ function templateGenerator(slotName: string) { return createS3AssetMappingTemplateGenerator('Mutation', slotName, fieldName); } -const streamingSelectionSet = `associatedUserMessageId contentBlockDeltaIndex contentBlockDoneAtIndex contentBlockIndex contentBlockText contentBlockToolUse { toolUseId name input } conversationId id stopReason owner errors { errorType message } p`; +const streamingSelectionSet = `associatedUserMessageId contentBlockDeltaIndex contentBlockDoneAtIndex contentBlockIndex contentBlockText contentBlockToolUse { toolUseId name input } conversationId id stopReason owner errors { errorType message } p metrics { latencyMs } usage { inputTokens outputTokens totalTokens }`; From 0f09a2cb36ac3720187f76602323445f7ef11bb6 Mon Sep 17 00:00:00 2001 From: Paul Jakob Kroker Date: Thu, 26 Mar 2026 11:21:25 +0100 Subject: [PATCH 3/4] feat(graphql-conversation-transformer): add AmplifyAIMetrics and AmplifyAIUsage type definitions Register explicit GraphQL types for metrics and usage in prepare handler. Update test schema and snapshots. --- ...phql-conversation-transformer.test.ts.snap | 40 +++++++++++++++---- .../src/graphql-types/message-model.ts | 20 ++++++++++ .../conversation-prepare-handler.ts | 9 ++++- 3 files changed, 60 insertions(+), 9 deletions(-) diff --git a/packages/amplify-graphql-conversation-transformer/src/__tests__/__snapshots__/amplify-graphql-conversation-transformer.test.ts.snap b/packages/amplify-graphql-conversation-transformer/src/__tests__/__snapshots__/amplify-graphql-conversation-transformer.test.ts.snap index a6cf9e90c4..5560b6a7ea 100644 --- a/packages/amplify-graphql-conversation-transformer/src/__tests__/__snapshots__/amplify-graphql-conversation-transformer.test.ts.snap +++ b/packages/amplify-graphql-conversation-transformer/src/__tests__/__snapshots__/amplify-graphql-conversation-transformer.test.ts.snap @@ -214,6 +214,8 @@ export function request(ctx) { associatedUserMessageId, accumulatedTurnContent, errors, + metrics, + usage, } = ctx.args.input; const { owner } = ctx.args; @@ -230,7 +232,7 @@ export function request(ctx) { const { createdAt, updatedAt } = ctx.stash.defaultValues; const assistantResponseId = \`\${associatedUserMessageId}#response\`; - const expression = 'SET #typename = :typename, #conversationId = :conversationId, #associatedUserMessageId = :associatedUserMessageId, #role = :role, #content = :content, #owner = :owner, #createdAt = if_not_exists(#createdAt, :createdAt), #updatedAt = :updatedAt'; + const expression = 'SET #typename = :typename, #conversationId = :conversationId, #associatedUserMessageId = :associatedUserMessageId, #role = :role, #content = :content, #owner = :owner, #createdAt = if_not_exists(#createdAt, :createdAt), #updatedAt = :updatedAt, #metrics = :metrics, #usage = :usage'; const expressionValues = util.dynamodb.toMapValues({ ':typename': 'ConversationMessagePirateChat', @@ -241,6 +243,8 @@ export function request(ctx) { ':owner': owner, ':createdAt': createdAt, ':updatedAt': updatedAt, + ':metrics': metrics, + ':usage': usage, }); // https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ReservedWords.html @@ -253,6 +257,8 @@ export function request(ctx) { '#owner': 'owner', '#createdAt': 'createdAt', '#updatedAt': 'updatedAt', + '#metrics': 'metrics', + '#usage': 'usage', }; return { @@ -676,7 +682,7 @@ export function request(ctx) { const { graphqlApiEndpoint } = ctx.stash; const userAgent = createUserAgent(request); - const selectionSet = 'associatedUserMessageId contentBlockDeltaIndex contentBlockDoneAtIndex contentBlockIndex contentBlockText contentBlockToolUse { toolUseId name input } conversationId id stopReason owner errors { errorType message } p'; + const selectionSet = 'associatedUserMessageId contentBlockDeltaIndex contentBlockDoneAtIndex contentBlockIndex contentBlockText contentBlockToolUse { toolUseId name input } conversationId id stopReason owner errors { errorType message } p metrics { latencyMs } usage { inputTokens outputTokens totalTokens }'; const streamingResponseMutation = { name: 'createAssistantResponseStreamPirateChat', @@ -1078,6 +1084,8 @@ export function request(ctx) { associatedUserMessageId, accumulatedTurnContent, errors, + metrics, + usage, } = ctx.args.input; const { owner } = ctx.args; @@ -1094,7 +1102,7 @@ export function request(ctx) { const { createdAt, updatedAt } = ctx.stash.defaultValues; const assistantResponseId = \`\${associatedUserMessageId}#response\`; - const expression = 'SET #typename = :typename, #conversationId = :conversationId, #associatedUserMessageId = :associatedUserMessageId, #role = :role, #content = :content, #owner = :owner, #createdAt = if_not_exists(#createdAt, :createdAt), #updatedAt = :updatedAt'; + const expression = 'SET #typename = :typename, #conversationId = :conversationId, #associatedUserMessageId = :associatedUserMessageId, #role = :role, #content = :content, #owner = :owner, #createdAt = if_not_exists(#createdAt, :createdAt), #updatedAt = :updatedAt, #metrics = :metrics, #usage = :usage'; const expressionValues = util.dynamodb.toMapValues({ ':typename': 'ConversationMessagePirateChat', @@ -1105,6 +1113,8 @@ export function request(ctx) { ':owner': owner, ':createdAt': createdAt, ':updatedAt': updatedAt, + ':metrics': metrics, + ':usage': usage, }); // https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ReservedWords.html @@ -1117,6 +1127,8 @@ export function request(ctx) { '#owner': 'owner', '#createdAt': 'createdAt', '#updatedAt': 'updatedAt', + '#metrics': 'metrics', + '#usage': 'usage', }; return { @@ -1540,7 +1552,7 @@ export function request(ctx) { const { graphqlApiEndpoint } = ctx.stash; const userAgent = createUserAgent(request); - const selectionSet = 'associatedUserMessageId contentBlockDeltaIndex contentBlockDoneAtIndex contentBlockIndex contentBlockText contentBlockToolUse { toolUseId name input } conversationId id stopReason owner errors { errorType message } p'; + const selectionSet = 'associatedUserMessageId contentBlockDeltaIndex contentBlockDoneAtIndex contentBlockIndex contentBlockText contentBlockToolUse { toolUseId name input } conversationId id stopReason owner errors { errorType message } p metrics { latencyMs } usage { inputTokens outputTokens totalTokens }'; const streamingResponseMutation = { name: 'createAssistantResponseStreamPirateChat', @@ -1942,6 +1954,8 @@ export function request(ctx) { associatedUserMessageId, accumulatedTurnContent, errors, + metrics, + usage, } = ctx.args.input; const { owner } = ctx.args; @@ -1958,7 +1972,7 @@ export function request(ctx) { const { createdAt, updatedAt } = ctx.stash.defaultValues; const assistantResponseId = \`\${associatedUserMessageId}#response\`; - const expression = 'SET #typename = :typename, #conversationId = :conversationId, #associatedUserMessageId = :associatedUserMessageId, #role = :role, #content = :content, #owner = :owner, #createdAt = if_not_exists(#createdAt, :createdAt), #updatedAt = :updatedAt'; + const expression = 'SET #typename = :typename, #conversationId = :conversationId, #associatedUserMessageId = :associatedUserMessageId, #role = :role, #content = :content, #owner = :owner, #createdAt = if_not_exists(#createdAt, :createdAt), #updatedAt = :updatedAt, #metrics = :metrics, #usage = :usage'; const expressionValues = util.dynamodb.toMapValues({ ':typename': 'ConversationMessagePirateChat', @@ -1969,6 +1983,8 @@ export function request(ctx) { ':owner': owner, ':createdAt': createdAt, ':updatedAt': updatedAt, + ':metrics': metrics, + ':usage': usage, }); // https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ReservedWords.html @@ -1981,6 +1997,8 @@ export function request(ctx) { '#owner': 'owner', '#createdAt': 'createdAt', '#updatedAt': 'updatedAt', + '#metrics': 'metrics', + '#usage': 'usage', }; return { @@ -2404,7 +2422,7 @@ export function request(ctx) { const { graphqlApiEndpoint } = ctx.stash; const userAgent = createUserAgent(request); - const selectionSet = 'associatedUserMessageId contentBlockDeltaIndex contentBlockDoneAtIndex contentBlockIndex contentBlockText contentBlockToolUse { toolUseId name input } conversationId id stopReason owner errors { errorType message } p'; + const selectionSet = 'associatedUserMessageId contentBlockDeltaIndex contentBlockDoneAtIndex contentBlockIndex contentBlockText contentBlockToolUse { toolUseId name input } conversationId id stopReason owner errors { errorType message } p metrics { latencyMs } usage { inputTokens outputTokens totalTokens }'; const streamingResponseMutation = { name: 'createAssistantResponseStreamPirateChat', @@ -2806,6 +2824,8 @@ export function request(ctx) { associatedUserMessageId, accumulatedTurnContent, errors, + metrics, + usage, } = ctx.args.input; const { owner } = ctx.args; @@ -2822,7 +2842,7 @@ export function request(ctx) { const { createdAt, updatedAt } = ctx.stash.defaultValues; const assistantResponseId = \`\${associatedUserMessageId}#response\`; - const expression = 'SET #typename = :typename, #conversationId = :conversationId, #associatedUserMessageId = :associatedUserMessageId, #role = :role, #content = :content, #owner = :owner, #createdAt = if_not_exists(#createdAt, :createdAt), #updatedAt = :updatedAt'; + const expression = 'SET #typename = :typename, #conversationId = :conversationId, #associatedUserMessageId = :associatedUserMessageId, #role = :role, #content = :content, #owner = :owner, #createdAt = if_not_exists(#createdAt, :createdAt), #updatedAt = :updatedAt, #metrics = :metrics, #usage = :usage'; const expressionValues = util.dynamodb.toMapValues({ ':typename': 'ConversationMessagePirateChat', @@ -2833,6 +2853,8 @@ export function request(ctx) { ':owner': owner, ':createdAt': createdAt, ':updatedAt': updatedAt, + ':metrics': metrics, + ':usage': usage, }); // https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ReservedWords.html @@ -2845,6 +2867,8 @@ export function request(ctx) { '#owner': 'owner', '#createdAt': 'createdAt', '#updatedAt': 'updatedAt', + '#metrics': 'metrics', + '#usage': 'usage', }; return { @@ -3268,7 +3292,7 @@ export function request(ctx) { const { graphqlApiEndpoint } = ctx.stash; const userAgent = createUserAgent(request); - const selectionSet = 'associatedUserMessageId contentBlockDeltaIndex contentBlockDoneAtIndex contentBlockIndex contentBlockText contentBlockToolUse { toolUseId name input } conversationId id stopReason owner errors { errorType message } p'; + const selectionSet = 'associatedUserMessageId contentBlockDeltaIndex contentBlockDoneAtIndex contentBlockIndex contentBlockText contentBlockToolUse { toolUseId name input } conversationId id stopReason owner errors { errorType message } p metrics { latencyMs } usage { inputTokens outputTokens totalTokens }'; const streamingResponseMutation = { name: 'createAssistantResponseStreamPirateChat', diff --git a/packages/amplify-graphql-conversation-transformer/src/graphql-types/message-model.ts b/packages/amplify-graphql-conversation-transformer/src/graphql-types/message-model.ts index 026e86692a..3ebd0cc8f5 100644 --- a/packages/amplify-graphql-conversation-transformer/src/graphql-types/message-model.ts +++ b/packages/amplify-graphql-conversation-transformer/src/graphql-types/message-model.ts @@ -158,6 +158,24 @@ export const createConversationTurnErrorInput = (): InputObjectTypeDefinitionNod }; }; +export const constructMetricsType = (): ObjectTypeDefinitionNode => ({ + kind: 'ObjectTypeDefinition', + name: { kind: 'Name', value: 'AmplifyAIMetrics' }, + fields: [makeField('latencyMs', [], makeNamedType('Int'))], + directives: [], +}); + +export const constructUsageType = (): ObjectTypeDefinitionNode => ({ + kind: 'ObjectTypeDefinition', + name: { kind: 'Name', value: 'AmplifyAIUsage' }, + fields: [ + makeField('inputTokens', [], makeNamedType('Int')), + makeField('outputTokens', [], makeNamedType('Int')), + makeField('totalTokens', [], makeNamedType('Int')), + ], + directives: [], +}); + export const createAssistantStreamingMutationField = (fieldName: string, inputTypeName: string): FieldDefinitionNode => { const args = [makeInputValueDefinition('input', makeNonNullType(makeNamedType(inputTypeName)))]; const cognitoAuthDirective = makeDirective('aws_cognito_user_pools', []); @@ -319,6 +337,8 @@ export const constructStreamResponseType = (): ObjectTypeDefinitionNode => { makeField('contentBlockDoneAtIndex', [], makeNamedType('Int')), makeField('stopReason', [], makeNamedType('String')), + makeField('metrics', [], makeNamedType('AmplifyAIMetrics')), + makeField('usage', [], makeNamedType('AmplifyAIUsage')), ], }; }; diff --git a/packages/amplify-graphql-conversation-transformer/src/transformer-steps/conversation-prepare-handler.ts b/packages/amplify-graphql-conversation-transformer/src/transformer-steps/conversation-prepare-handler.ts index 217a1a7d21..09c0a086ac 100644 --- a/packages/amplify-graphql-conversation-transformer/src/transformer-steps/conversation-prepare-handler.ts +++ b/packages/amplify-graphql-conversation-transformer/src/transformer-steps/conversation-prepare-handler.ts @@ -2,7 +2,12 @@ import { ModelTransformer } from '@aws-amplify/graphql-model-transformer'; import { BelongsToTransformer, HasManyTransformer } from '@aws-amplify/graphql-relational-transformer'; import { DDB_AMPLIFY_MANAGED_DATASOURCE_STRATEGY, InvalidTransformerError } from '@aws-amplify/graphql-transformer-core'; import { ConversationDirectiveConfiguration } from '../conversation-directive-configuration'; -import { constructStreamResponseType, createConversationTurnErrorInput } from '../graphql-types/message-model'; +import { + constructStreamResponseType, + createConversationTurnErrorInput, + constructMetricsType, + constructUsageType, +} from '../graphql-types/message-model'; import { TransformerAuthProvider, TransformerPrepareStepContextProvider } from '@aws-amplify/graphql-transformer-interfaces'; /** @@ -50,6 +55,8 @@ export class ConversationPrepareHandler { // add once per schema const conversationTurnErrorInput = createConversationTurnErrorInput(); ctx.output.addInput(conversationTurnErrorInput); + ctx.output.addObject(constructMetricsType()); + ctx.output.addObject(constructUsageType()); for (const directive of directives) { this.prepareResourcesForDirective(directive, ctx); From 032bb227a3a3c51e4b762b6b82771d52dce5d5a2 Mon Sep 17 00:00:00 2001 From: Paul Jakob Kroker Date: Mon, 30 Mar 2026 14:49:02 +0200 Subject: [PATCH 4/4] fix(graphql-conversation-transformer): conditionally persist metrics and usage in streaming resolver Only set metrics and usage in DynamoDB when values are present to avoid overwriting with null on non-terminal streaming chunks. --- ...phql-conversation-transformer.test.ts.snap | 84 +++++++++++++------ ...streaming-mutation-resolver-fn.template.js | 20 +++-- 2 files changed, 74 insertions(+), 30 deletions(-) diff --git a/packages/amplify-graphql-conversation-transformer/src/__tests__/__snapshots__/amplify-graphql-conversation-transformer.test.ts.snap b/packages/amplify-graphql-conversation-transformer/src/__tests__/__snapshots__/amplify-graphql-conversation-transformer.test.ts.snap index 5560b6a7ea..0cb0d45528 100644 --- a/packages/amplify-graphql-conversation-transformer/src/__tests__/__snapshots__/amplify-graphql-conversation-transformer.test.ts.snap +++ b/packages/amplify-graphql-conversation-transformer/src/__tests__/__snapshots__/amplify-graphql-conversation-transformer.test.ts.snap @@ -232,7 +232,7 @@ export function request(ctx) { const { createdAt, updatedAt } = ctx.stash.defaultValues; const assistantResponseId = \`\${associatedUserMessageId}#response\`; - const expression = 'SET #typename = :typename, #conversationId = :conversationId, #associatedUserMessageId = :associatedUserMessageId, #role = :role, #content = :content, #owner = :owner, #createdAt = if_not_exists(#createdAt, :createdAt), #updatedAt = :updatedAt, #metrics = :metrics, #usage = :usage'; + let expression = 'SET #typename = :typename, #conversationId = :conversationId, #associatedUserMessageId = :associatedUserMessageId, #role = :role, #content = :content, #owner = :owner, #createdAt = if_not_exists(#createdAt, :createdAt), #updatedAt = :updatedAt'; const expressionValues = util.dynamodb.toMapValues({ ':typename': 'ConversationMessagePirateChat', @@ -243,8 +243,6 @@ export function request(ctx) { ':owner': owner, ':createdAt': createdAt, ':updatedAt': updatedAt, - ':metrics': metrics, - ':usage': usage, }); // https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ReservedWords.html @@ -257,10 +255,20 @@ export function request(ctx) { '#owner': 'owner', '#createdAt': 'createdAt', '#updatedAt': 'updatedAt', - '#metrics': 'metrics', - '#usage': 'usage', }; + if (metrics) { + expression += ', #metrics = :metrics'; + expressionValues[':metrics'] = metrics; + expressionNames['#metrics'] = 'metrics'; + } + + if (usage) { + expression += ', #usage = :usage'; + expressionValues[':usage'] = usage; + expressionNames['#usage'] = 'usage'; + } + return { operation: 'UpdateItem', key: util.dynamodb.toMapValues({ id: assistantResponseId }), @@ -306,7 +314,8 @@ function generateRandomPadding() { const base = 'abcdefghijklmnopqrstuvwxyz0123456789'; const rand = Math.floor(Math.random() * 36); return base.slice(0, rand); -}" +} +" `; exports[`ConversationTransformer valid schemas should transform conversation route with inference configuration: AssistantResponseStreamMutation init slot function code 1`] = ` @@ -1102,7 +1111,7 @@ export function request(ctx) { const { createdAt, updatedAt } = ctx.stash.defaultValues; const assistantResponseId = \`\${associatedUserMessageId}#response\`; - const expression = 'SET #typename = :typename, #conversationId = :conversationId, #associatedUserMessageId = :associatedUserMessageId, #role = :role, #content = :content, #owner = :owner, #createdAt = if_not_exists(#createdAt, :createdAt), #updatedAt = :updatedAt, #metrics = :metrics, #usage = :usage'; + let expression = 'SET #typename = :typename, #conversationId = :conversationId, #associatedUserMessageId = :associatedUserMessageId, #role = :role, #content = :content, #owner = :owner, #createdAt = if_not_exists(#createdAt, :createdAt), #updatedAt = :updatedAt'; const expressionValues = util.dynamodb.toMapValues({ ':typename': 'ConversationMessagePirateChat', @@ -1113,8 +1122,6 @@ export function request(ctx) { ':owner': owner, ':createdAt': createdAt, ':updatedAt': updatedAt, - ':metrics': metrics, - ':usage': usage, }); // https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ReservedWords.html @@ -1127,10 +1134,20 @@ export function request(ctx) { '#owner': 'owner', '#createdAt': 'createdAt', '#updatedAt': 'updatedAt', - '#metrics': 'metrics', - '#usage': 'usage', }; + if (metrics) { + expression += ', #metrics = :metrics'; + expressionValues[':metrics'] = metrics; + expressionNames['#metrics'] = 'metrics'; + } + + if (usage) { + expression += ', #usage = :usage'; + expressionValues[':usage'] = usage; + expressionNames['#usage'] = 'usage'; + } + return { operation: 'UpdateItem', key: util.dynamodb.toMapValues({ id: assistantResponseId }), @@ -1176,7 +1193,8 @@ function generateRandomPadding() { const base = 'abcdefghijklmnopqrstuvwxyz0123456789'; const rand = Math.floor(Math.random() * 36); return base.slice(0, rand); -}" +} +" `; exports[`ConversationTransformer valid schemas should transform conversation route with model query tool including relationships: AssistantResponseStreamMutation init slot function code 1`] = ` @@ -1972,7 +1990,7 @@ export function request(ctx) { const { createdAt, updatedAt } = ctx.stash.defaultValues; const assistantResponseId = \`\${associatedUserMessageId}#response\`; - const expression = 'SET #typename = :typename, #conversationId = :conversationId, #associatedUserMessageId = :associatedUserMessageId, #role = :role, #content = :content, #owner = :owner, #createdAt = if_not_exists(#createdAt, :createdAt), #updatedAt = :updatedAt, #metrics = :metrics, #usage = :usage'; + let expression = 'SET #typename = :typename, #conversationId = :conversationId, #associatedUserMessageId = :associatedUserMessageId, #role = :role, #content = :content, #owner = :owner, #createdAt = if_not_exists(#createdAt, :createdAt), #updatedAt = :updatedAt'; const expressionValues = util.dynamodb.toMapValues({ ':typename': 'ConversationMessagePirateChat', @@ -1983,8 +2001,6 @@ export function request(ctx) { ':owner': owner, ':createdAt': createdAt, ':updatedAt': updatedAt, - ':metrics': metrics, - ':usage': usage, }); // https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ReservedWords.html @@ -1997,10 +2013,20 @@ export function request(ctx) { '#owner': 'owner', '#createdAt': 'createdAt', '#updatedAt': 'updatedAt', - '#metrics': 'metrics', - '#usage': 'usage', }; + if (metrics) { + expression += ', #metrics = :metrics'; + expressionValues[':metrics'] = metrics; + expressionNames['#metrics'] = 'metrics'; + } + + if (usage) { + expression += ', #usage = :usage'; + expressionValues[':usage'] = usage; + expressionNames['#usage'] = 'usage'; + } + return { operation: 'UpdateItem', key: util.dynamodb.toMapValues({ id: assistantResponseId }), @@ -2046,7 +2072,8 @@ function generateRandomPadding() { const base = 'abcdefghijklmnopqrstuvwxyz0123456789'; const rand = Math.floor(Math.random() * 36); return base.slice(0, rand); -}" +} +" `; exports[`ConversationTransformer valid schemas should transform conversation route with model query tool: AssistantResponseStreamMutation init slot function code 1`] = ` @@ -2842,7 +2869,7 @@ export function request(ctx) { const { createdAt, updatedAt } = ctx.stash.defaultValues; const assistantResponseId = \`\${associatedUserMessageId}#response\`; - const expression = 'SET #typename = :typename, #conversationId = :conversationId, #associatedUserMessageId = :associatedUserMessageId, #role = :role, #content = :content, #owner = :owner, #createdAt = if_not_exists(#createdAt, :createdAt), #updatedAt = :updatedAt, #metrics = :metrics, #usage = :usage'; + let expression = 'SET #typename = :typename, #conversationId = :conversationId, #associatedUserMessageId = :associatedUserMessageId, #role = :role, #content = :content, #owner = :owner, #createdAt = if_not_exists(#createdAt, :createdAt), #updatedAt = :updatedAt'; const expressionValues = util.dynamodb.toMapValues({ ':typename': 'ConversationMessagePirateChat', @@ -2853,8 +2880,6 @@ export function request(ctx) { ':owner': owner, ':createdAt': createdAt, ':updatedAt': updatedAt, - ':metrics': metrics, - ':usage': usage, }); // https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ReservedWords.html @@ -2867,10 +2892,20 @@ export function request(ctx) { '#owner': 'owner', '#createdAt': 'createdAt', '#updatedAt': 'updatedAt', - '#metrics': 'metrics', - '#usage': 'usage', }; + if (metrics) { + expression += ', #metrics = :metrics'; + expressionValues[':metrics'] = metrics; + expressionNames['#metrics'] = 'metrics'; + } + + if (usage) { + expression += ', #usage = :usage'; + expressionValues[':usage'] = usage; + expressionNames['#usage'] = 'usage'; + } + return { operation: 'UpdateItem', key: util.dynamodb.toMapValues({ id: assistantResponseId }), @@ -2916,7 +2951,8 @@ function generateRandomPadding() { const base = 'abcdefghijklmnopqrstuvwxyz0123456789'; const rand = Math.floor(Math.random() * 36); return base.slice(0, rand); -}" +} +" `; exports[`ConversationTransformer valid schemas should transform conversation route with query tools: AssistantResponseStreamMutation init slot function code 1`] = ` diff --git a/packages/amplify-graphql-conversation-transformer/src/resolvers/templates/assistant-streaming-mutation-resolver-fn.template.js b/packages/amplify-graphql-conversation-transformer/src/resolvers/templates/assistant-streaming-mutation-resolver-fn.template.js index 5dc6e56ca7..5c0f924af4 100644 --- a/packages/amplify-graphql-conversation-transformer/src/resolvers/templates/assistant-streaming-mutation-resolver-fn.template.js +++ b/packages/amplify-graphql-conversation-transformer/src/resolvers/templates/assistant-streaming-mutation-resolver-fn.template.js @@ -30,7 +30,7 @@ export function request(ctx) { const { createdAt, updatedAt } = ctx.stash.defaultValues; const assistantResponseId = `${associatedUserMessageId}#response`; - const expression = 'SET #typename = :typename, #conversationId = :conversationId, #associatedUserMessageId = :associatedUserMessageId, #role = :role, #content = :content, #owner = :owner, #createdAt = if_not_exists(#createdAt, :createdAt), #updatedAt = :updatedAt, #metrics = :metrics, #usage = :usage'; + let expression = 'SET #typename = :typename, #conversationId = :conversationId, #associatedUserMessageId = :associatedUserMessageId, #role = :role, #content = :content, #owner = :owner, #createdAt = if_not_exists(#createdAt, :createdAt), #updatedAt = :updatedAt'; const expressionValues = util.dynamodb.toMapValues({ ':typename': '[[CONVERSATION_MESSAGE_TYPE_NAME]]', @@ -41,8 +41,6 @@ export function request(ctx) { ':owner': owner, ':createdAt': createdAt, ':updatedAt': updatedAt, - ':metrics': metrics, - ':usage': usage, }); // https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ReservedWords.html @@ -55,10 +53,20 @@ export function request(ctx) { '#owner': 'owner', '#createdAt': 'createdAt', '#updatedAt': 'updatedAt', - '#metrics': 'metrics', - '#usage': 'usage', }; + if (metrics) { + expression += ', #metrics = :metrics'; + expressionValues[':metrics'] = metrics; + expressionNames['#metrics'] = 'metrics'; + } + + if (usage) { + expression += ', #usage = :usage'; + expressionValues[':usage'] = usage; + expressionNames['#usage'] = 'usage'; + } + return { operation: 'UpdateItem', key: util.dynamodb.toMapValues({ id: assistantResponseId }), @@ -104,4 +112,4 @@ function generateRandomPadding() { const base = 'abcdefghijklmnopqrstuvwxyz0123456789'; const rand = Math.floor(Math.random() * 36); return base.slice(0, rand); -} \ No newline at end of file +}