Skip to content

[Bedrock Agent Runtime] React Native Expo unable to parse response from InvokeAgent command #7123

@jacksonalvarez12

Description

@jacksonalvarez12

Checkboxes for prior research

Describe the bug

Bedrock agent runtime invokeAgent() returns an unusable response, specifically when using react native expo (I'm not sure about vanilla react native).

Here is a response given by invokeAgent when called by the js sdk in expo

 {
  "$metadata": {
    "httpStatusCode": 200,
    "requestId": "[REDACTED]",
    "attempts": 1,
    "totalRetryDelay": 0
  },
  "contentType": "application/json",
  "sessionId": "[REDACTED]",
  "completion": {
    "options": {
      "messageStream": {
        "options": {
          "inputStream": {},
          "decoder": {
            "headerMarshaller": {},
            "messageBuffer": [],
            "isEndOfStream": false
          }
        }
      }
    }
  }
}

As far as I can tell, this is a correct response. However, when trying to parse this using the below method I get this error: [TypeError: source[Symbol.asyncIterator] is not a function (it is undefined)]

 let completion = '';
  if (!invokeAgentOutput.completion) {
    throw new Error('Completion is undefined');
  }
  for await (const chunkEvent of invokeAgentOutput.completion) {
    const chunk = chunkEvent.chunk;
    // console.log(chunk);
    const decodedResponse = new TextDecoder('utf-8').decode(chunk?.bytes);
    completion += decodedResponse;
  }

Weirdly enough, this issue does not occur on React web application. I recreated the application in React web, with the same auth methods and the same use of the libraries, and the same code correctly returns the agent's response

Regression Issue

  • Select this option if this issue appears to be a regression.

SDK version number

"@aws-sdk/client-bedrock-agent-runtime": "^3.826.0"

Which JavaScript Runtime is this issue in?

React Native

Details of the browser/Node.js/ReactNative version

"expo": "~53.0.11", "react-native": "0.79.3",

Reproduction Steps

Create a fresh react native expo project using: npx create-expo-app@latest

Install necessary dependencies for auth and bedrock agent client. I'm using Cognito

Instantiate the Bedrock Agent Runtime Client, and give it credentials

const client: BedrockAgentRuntimeClient = new BedrockAgentRuntimeClient({region: 'us-east-2'});

 client.config.credentials = fromCognitoIdentityPool({
            clientConfig: {region: 'us-east-2'},
            identityPoolId,
            logins: {
              [session.getIdToken().payload['iss'].split('https://')[1]]: idToken
            }
          }); // Credentials from cognito

Create a session using the client, and invoke the agent using the client

const createSessionCommand: CreateSessionCommand = new CreateSessionCommand({});
const createSessionOutput: CreateSessionCommandOutput =
        await bedrockClient.client.send(createSessionCommand);

const invokeAgentInput: InvokeAgentCommandInput = {
        agentId: {{Agent id}},
        agentAliasId: {{Alias id}},
        inputText: 'This is a test prompt',
        sessionId: createSessionOutput.sessionId
      };

const invokeAgentCommand: InvokeAgentCommand = new InvokeAgentCommand(invokeAgentInput);
const invokeAgentOutput: InvokeAgentCommandOutput =
        await bedrockClient.client.send(invokeAgentCommand);
console.log(`InvokeAgentCommandOutput: ${JSON.stringify(invokeAgentOutput, null, 2)}`);

I'm parsing the response using the only method I've found online

let completion = "";
if (!invokeAgentOutput.completion) {
  throw new Error("Completion is undefined");
}
for await (const chunkEvent of invokeAgentOutput.completion) {
  const chunk = chunkEvent.chunk;
  console.log(chunk);
  const decodedResponse = new TextDecoder("utf-8").decode(chunk?.bytes);
  completion += decodedResponse;
}
console.log(`Completion: ${completion}`);

Trying to build that will fail, because of an issue I found that can be fixed by babel. To fix:

npm install @babel/plugin-transform-class-static-block

Create a babel.config.json file in the root project directory with content of

{
  "plugins": ["@babel/plugin-transform-class-static-block"]
}

You will also need to npm install 'react-native-get-random-values' and import in it the topmost component. This is due to issue with uuid used in the sdk and react native.

Finally you can run the code, and see that this error ([TypeError: source[Symbol.asyncIterator] is not a function) is thrown during parsing. Even though the client is correctly authed, and just called a bedrock function in createSession that worked perfectly fine.

As I mentioned earlier, I recreated this in web React. The same code can parse the correctly formatted response that is returned on the web, and I get the model's response. That is why, to the best of my ability, I think this is an issue with the js-sdk mixing with React Native.

Here's the response I get from the React web page

{
  "$metadata": {
    "httpStatusCode": 200,
    "requestId": "[REDACTED]",
    "attempts": 1,
    "totalRetryDelay": 0
  },
  "contentType": "application/json",
  "sessionId": "[REDACTED]",
  "completion": {
    "options": {
      "messageStream": {
        "options": {
          "inputStream": {},
          "decoder": {
            "headerMarshaller": {},
            "messageBuffer": [],
            "isEndOfStream": false
          }
        }
      }
    }
  }
}

Observed Behavior

Error is thrown while trying to parse chunk information

[TypeError: source[Symbol.asyncIterator] is not a function

Expected Behavior

Chunk information should be parsed correctly

Possible Solution

No response

Additional Information/Context

I tested all of this code in an android emulator, as I have no ability to test on iOS (I'm using windows).

I tested as far back as this sdk version (2 months ago)
"@aws-sdk/client-bedrock-agent-runtime": "3.787.0",

Finally, I'll draw attention to the only other place on the internet I could find someone experiencing this issue
#6519

Of course, the issue was never resolved, but a fix was provided by @zshzbh . I tried to implement this fix to no avail.

The fix is:
npm install react-native-get-random-values (I did this earlier)
npm install react-native-url-polyfill
npm install web-streams-polyfill

Include these import statements in the topmost component:
import "react-native-get-random-values";
import "react-native-url-polyfill/auto";
import "web-streams-polyfill/dist/polyfill";

Create a metro config using: npx expo customize metro.config.js
And then add this line: config.resolver.unstable_enablePackageExports = true;

Now clear the metro cache, and rebuild

Unfortunately, this doesn't do anything, and the same issue occurs

Metadata

Metadata

Assignees

Labels

bugThis issue is a bug.closed-for-stalenessp3This is a minor priority issue

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions