@cdklabs/cdk-appmod-catalog-blueprints 1.10.0 → 1.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/.jsii +1276 -211
  2. package/lib/document-processing/adapter/queued-s3-adapter.js +1 -1
  3. package/lib/document-processing/agentic-document-processing.js +2 -2
  4. package/lib/document-processing/base-document-processing.js +1 -1
  5. package/lib/document-processing/bedrock-document-processing.js +1 -1
  6. package/lib/document-processing/default-document-processing-config.js +1 -1
  7. package/lib/framework/agents/base-agent.d.ts +15 -2
  8. package/lib/framework/agents/base-agent.js +3 -3
  9. package/lib/framework/agents/batch-agent.d.ts +1 -1
  10. package/lib/framework/agents/batch-agent.js +2 -2
  11. package/lib/framework/agents/default-agent-config.js +1 -1
  12. package/lib/framework/agents/interactive-agent.d.ts +286 -3
  13. package/lib/framework/agents/interactive-agent.js +412 -123
  14. package/lib/framework/agents/knowledge-base/base-knowledge-base.js +1 -1
  15. package/lib/framework/agents/knowledge-base/bedrock-knowledge-base.js +1 -1
  16. package/lib/framework/agents/resources/agentcore-agent-handler/Dockerfile +20 -0
  17. package/lib/framework/agents/resources/agentcore-agent-handler/main.py +224 -0
  18. package/lib/framework/agents/resources/agentcore-agent-handler/requirements.txt +5 -0
  19. package/lib/framework/agents/resources/interactive-agent-handler/index.py +16 -93
  20. package/lib/framework/agents/resources/interactive-agent-handler/test_handler.py +214 -413
  21. package/lib/framework/bedrock/bedrock.js +1 -1
  22. package/lib/framework/custom-resource/default-runtimes.js +1 -1
  23. package/lib/framework/foundation/access-log.js +1 -1
  24. package/lib/framework/foundation/eventbridge-broker.js +1 -1
  25. package/lib/framework/foundation/network.js +1 -1
  26. package/lib/framework/tests/interactive-agent-nag.test.js +56 -1
  27. package/lib/framework/tests/interactive-agent.test.js +257 -11
  28. package/lib/tsconfig.tsbuildinfo +1 -1
  29. package/lib/utilities/data-loader.js +1 -1
  30. package/lib/utilities/lambda-iam-utils.js +1 -1
  31. package/lib/utilities/observability/cloudfront-distribution-observability-property-injector.js +1 -1
  32. package/lib/utilities/observability/cloudwatch-transaction-search.js +1 -1
  33. package/lib/utilities/observability/default-observability-config.js +1 -1
  34. package/lib/utilities/observability/lambda-observability-property-injector.js +1 -1
  35. package/lib/utilities/observability/log-group-data-protection-utils.js +1 -1
  36. package/lib/utilities/observability/powertools-config.js +1 -1
  37. package/lib/utilities/observability/state-machine-observability-property-injector.js +1 -1
  38. package/lib/webapp/frontend-construct.js +1 -1
  39. package/package.json +2 -2
@@ -103,5 +103,5 @@ class BaseKnowledgeBase extends constructs_1.Construct {
103
103
  }
104
104
  exports.BaseKnowledgeBase = BaseKnowledgeBase;
105
105
  _a = JSII_RTTI_SYMBOL_1;
106
- BaseKnowledgeBase[_a] = { fqn: "@cdklabs/cdk-appmod-catalog-blueprints.BaseKnowledgeBase", version: "1.10.0" };
106
+ BaseKnowledgeBase[_a] = { fqn: "@cdklabs/cdk-appmod-catalog-blueprints.BaseKnowledgeBase", version: "1.12.0" };
107
107
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZS1rbm93bGVkZ2UtYmFzZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3VzZS1jYXNlcy9mcmFtZXdvcmsvYWdlbnRzL2tub3dsZWRnZS1iYXNlL2Jhc2Uta25vd2xlZGdlLWJhc2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFNQSwyQ0FBdUM7QUFTdkM7Ozs7Ozs7Ozs7Ozs7Ozs7R0FnQkc7QUFDSCxNQUFzQixpQkFBa0IsU0FBUSxzQkFBUztJQWlDdkQ7Ozs7Ozs7O09BUUc7SUFDSCxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQTZCO1FBQ3JFLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFakIsSUFBSSxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUUxQixJQUFJLENBQUMsSUFBSSxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUM7UUFDdkIsSUFBSSxDQUFDLFdBQVcsR0FBRyxLQUFLLENBQUMsV0FBVyxDQUFDO1FBQ3JDLElBQUksQ0FBQyxlQUFlLEdBQUcsS0FBSyxDQUFDLFNBQVMsSUFBSSxFQUFFLGVBQWUsRUFBRSxDQUFDLEVBQUUsQ0FBQztRQUNqRSxJQUFJLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQyxHQUFHLENBQUM7SUFDN0IsQ0FBQztJQUVEOzs7Ozs7Ozs7O09BVUc7SUFDTyxhQUFhLENBQUMsS0FBNkI7UUFDbkQsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLElBQUksS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQztZQUM1QyxNQUFNLElBQUksS0FBSyxDQUFDLHNDQUFzQyxDQUFDLENBQUM7UUFDMUQsQ0FBQztRQUNELElBQUksQ0FBQyxLQUFLLENBQUMsV0FBVyxJQUFJLEtBQUssQ0FBQyxXQUFXLENBQUMsSUFBSSxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUM7WUFDMUQsTUFBTSxJQUFJLEtBQUssQ0FBQyw2Q0FBNkMsQ0FBQyxDQUFDO1FBQ2pFLENBQUM7SUFDSCxDQUFDO0lBWUQ7Ozs7Ozs7OztPQVNHO0lBQ0ksbUJBQW1CO1FBQ3hCLE9BQU87WUFDTCxJQUFJLEVBQUUsSUFBSSxDQUFDLElBQUk7WUFDZixXQUFXLEVBQUUsSUFBSSxDQUFDLFdBQVc7WUFDN0IsU0FBUyxFQUFFLElBQUksQ0FBQyxlQUFlO1lBQy9CLEdBQUcsRUFBRSxJQUFJLENBQUMsU0FBUztTQUNwQixDQUFDO0lBQ0osQ0FBQztJQUVEOzs7Ozs7OztPQVFHO0lBQ0ksa0JBQWtCO1FBQ3ZCLE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7SUFFRDs7Ozs7Ozs7T0FRRztJQUNJLG1CQUFtQjtRQUN4QixPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDOztBQTlISCw4Q0ErSEMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgQW1hem9uLmNvbSwgSW5jLiBvciBpdHMgYWZmaWxpYXRlcy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbmltcG9ydCB7IFBvbGljeVN0YXRlbWVudCB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1pYW0nO1xuaW1wb3J0IHsgTGF5ZXJWZXJzaW9uIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWxhbWJkYSc7XG5pbXBvcnQgeyBBc3NldCB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1zMy1hc3NldHMnO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBJS25vd2xlZGdlQmFzZSB9IGZyb20gJy4vaS1rbm93bGVkZ2UtYmFzZSc7XG5pbXBvcnQge1xuICBBY2xDb25maWd1cmF0aW9uLFxuICBCYXNlS25vd2xlZGdlQmFzZVByb3BzLFxuICBLbm93bGVkZ2VCYXNlUnVudGltZUNvbmZpZyxcbiAgUmV0cmlldmFsQ29uZmlndXJhdGlvbixcbn0gZnJvbSAnLi9rbm93bGVkZ2UtYmFzZS1wcm9wcyc7XG5cbi8qKlxuICogQWJzdHJhY3QgYmFzZSBjbGFzcyBmb3Iga25vd2xlZGdlIGJhc2UgaW1wbGVtZW50YXRpb25zLlxuICpcbiAqIFRoaXMgY2xhc3MgcHJvdmlkZXMgY29tbW9uIGZ1bmN0aW9uYWxpdHkgZm9yIGFsbCBrbm93bGVkZ2UgYmFzZSBpbXBsZW1lbnRhdGlvbnMsXG4gKiBpbmNsdWRpbmcgY29uZmlndXJhdGlvbiBtYW5hZ2VtZW50LCB2YWxpZGF0aW9uLCBhbmQgZGVmYXVsdCBiZWhhdmlvcnMuIENvbmNyZXRlXG4gKiBpbXBsZW1lbnRhdGlvbnMgKGxpa2UgQmVkcm9ja0tub3dsZWRnZUJhc2UpIGV4dGVuZCB0aGlzIGNsYXNzIGFuZCBpbXBsZW1lbnRcbiAqIHRoZSBhYnN0cmFjdCBtZXRob2RzLlxuICpcbiAqIFRoZSBiYXNlIGNsYXNzIGhhbmRsZXM6XG4gKiAtIFByb3BzIHZhbGlkYXRpb24gKG5hbWUgYW5kIGRlc2NyaXB0aW9uIGFyZSByZXF1aXJlZClcbiAqIC0gRGVmYXVsdCByZXRyaWV2YWwgY29uZmlndXJhdGlvbiAobnVtYmVyT2ZSZXN1bHRzIGRlZmF1bHRzIHRvIDUpXG4gKiAtIEFDTCBjb25maWd1cmF0aW9uIHN0b3JhZ2VcbiAqIC0gQmFzZSBydW50aW1lIGNvbmZpZ3VyYXRpb24gZXhwb3J0XG4gKlxuICogU3ViY2xhc3NlcyBtdXN0IGltcGxlbWVudDpcbiAqIC0gYGdlbmVyYXRlSWFtUGVybWlzc2lvbnMoKWA6IFJldHVybiBJQU0gcGVybWlzc2lvbnMgc3BlY2lmaWMgdG8gdGhlIEtCIHR5cGVcbiAqL1xuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEJhc2VLbm93bGVkZ2VCYXNlIGV4dGVuZHMgQ29uc3RydWN0IGltcGxlbWVudHMgSUtub3dsZWRnZUJhc2Uge1xuICAvKipcbiAgICogSHVtYW4tcmVhZGFibGUgbmFtZSBmb3IgdGhpcyBrbm93bGVkZ2UgYmFzZS5cbiAgICpcbiAgICogVGhpcyBuYW1lIGlzIHVzZWQgZm9yIGxvZ2dpbmcsIGRpc3BsYXkgcHVycG9zZXMsIGFuZCB0byBoZWxwIHRoZSBhZ2VudFxuICAgKiBpZGVudGlmeSB3aGljaCBrbm93bGVkZ2UgYmFzZSB0byBxdWVyeS5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBuYW1lOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEh1bWFuLXJlYWRhYmxlIGRlc2NyaXB0aW9uIG9mIHdoYXQgdGhpcyBrbm93bGVkZ2UgYmFzZSBjb250YWlucy5cbiAgICpcbiAgICogVGhpcyBkZXNjcmlwdGlvbiBpcyBpbmNsdWRlZCBpbiB0aGUgYWdlbnQncyBzeXN0ZW0gcHJvbXB0IHRvIGhlbHBcbiAgICogdGhlIGFnZW50IGRlY2lkZSB3aGVuIHRvIHF1ZXJ5IHRoaXMga25vd2xlZGdlIGJhc2UuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgZGVzY3JpcHRpb246IHN0cmluZztcblxuICAvKipcbiAgICogUmV0cmlldmFsIGNvbmZpZ3VyYXRpb24gZm9yIHRoaXMga25vd2xlZGdlIGJhc2UuXG4gICAqXG4gICAqIENvbnRhaW5zIHNldHRpbmdzIGxpa2UgbnVtYmVyT2ZSZXN1bHRzIGFuZCBvcHRpb25hbCBtZXRhZGF0YSBmaWx0ZXJzLlxuICAgKiBEZWZhdWx0cyB0byB7IG51bWJlck9mUmVzdWx0czogNSB9IGlmIG5vdCBwcm92aWRlZC5cbiAgICovXG4gIHByb3RlY3RlZCByZWFkb25seSByZXRyaWV2YWxDb25maWc6IFJldHJpZXZhbENvbmZpZ3VyYXRpb247XG5cbiAgLyoqXG4gICAqIEFDTCBjb25maWd1cmF0aW9uIGZvciBpZGVudGl0eS1hd2FyZSByZXRyaWV2YWwuXG4gICAqXG4gICAqIFdoZW4gZW5hYmxlZCwgcmV0cmlldmFsIHF1ZXJpZXMgd2lsbCBiZSBmaWx0ZXJlZCBiYXNlZCBvbiB1c2VyXG4gICAqIGlkZW50aXR5IGNvbnRleHQuXG4gICAqL1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgYWNsQ29uZmlnPzogQWNsQ29uZmlndXJhdGlvbjtcblxuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyBCYXNlS25vd2xlZGdlQmFzZSBpbnN0YW5jZS5cbiAgICpcbiAgICogQHBhcmFtIHNjb3BlIC0gVGhlIHNjb3BlIGluIHdoaWNoIHRvIGRlZmluZSB0aGlzIGNvbnN0cnVjdFxuICAgKiBAcGFyYW0gaWQgLSBUaGUgc2NvcGVkIGNvbnN0cnVjdCBJRFxuICAgKiBAcGFyYW0gcHJvcHMgLSBDb25maWd1cmF0aW9uIHByb3BlcnRpZXMgZm9yIHRoZSBrbm93bGVkZ2UgYmFzZVxuICAgKiBAdGhyb3dzIEVycm9yIGlmIG5hbWUgaXMgZW1wdHkgb3Igbm90IHByb3ZpZGVkXG4gICAqIEB0aHJvd3MgRXJyb3IgaWYgZGVzY3JpcHRpb24gaXMgZW1wdHkgb3Igbm90IHByb3ZpZGVkXG4gICAqL1xuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogQmFzZUtub3dsZWRnZUJhc2VQcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG5cbiAgICB0aGlzLnZhbGlkYXRlUHJvcHMocHJvcHMpO1xuXG4gICAgdGhpcy5uYW1lID0gcHJvcHMubmFtZTtcbiAgICB0aGlzLmRlc2NyaXB0aW9uID0gcHJvcHMuZGVzY3JpcHRpb247XG4gICAgdGhpcy5yZXRyaWV2YWxDb25maWcgPSBwcm9wcy5yZXRyaWV2YWwgPz8geyBudW1iZXJPZlJlc3VsdHM6IDUgfTtcbiAgICB0aGlzLmFjbENvbmZpZyA9IHByb3BzLmFjbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZXMgdGhlIHByb3ZpZGVkIHByb3BzIGF0IGNvbnN0cnVjdGlvbiB0aW1lLlxuICAgKlxuICAgKiBFbnN1cmVzIHRoYXQgcmVxdWlyZWQgZmllbGRzIChuYW1lIGFuZCBkZXNjcmlwdGlvbikgYXJlIHByb3ZpZGVkXG4gICAqIGFuZCBub3QgZW1wdHkuIFN1YmNsYXNzZXMgY2FuIG92ZXJyaWRlIHRoaXMgbWV0aG9kIHRvIGFkZCBhZGRpdGlvbmFsXG4gICAqIHZhbGlkYXRpb24sIGJ1dCBzaG91bGQgY2FsbCBzdXBlci52YWxpZGF0ZVByb3BzKCkgZmlyc3QuXG4gICAqXG4gICAqIEBwYXJhbSBwcm9wcyAtIFRoZSBwcm9wcyB0byB2YWxpZGF0ZVxuICAgKiBAdGhyb3dzIEVycm9yIGlmIG5hbWUgaXMgZW1wdHkgb3Igbm90IHByb3ZpZGVkXG4gICAqIEB0aHJvd3MgRXJyb3IgaWYgZGVzY3JpcHRpb24gaXMgZW1wdHkgb3Igbm90IHByb3ZpZGVkXG4gICAqL1xuICBwcm90ZWN0ZWQgdmFsaWRhdGVQcm9wcyhwcm9wczogQmFzZUtub3dsZWRnZUJhc2VQcm9wcyk6IHZvaWQge1xuICAgIGlmICghcHJvcHMubmFtZSB8fCBwcm9wcy5uYW1lLnRyaW0oKSA9PT0gJycpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignbmFtZSBpcyByZXF1aXJlZCBhbmQgY2Fubm90IGJlIGVtcHR5Jyk7XG4gICAgfVxuICAgIGlmICghcHJvcHMuZGVzY3JpcHRpb24gfHwgcHJvcHMuZGVzY3JpcHRpb24udHJpbSgpID09PSAnJykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdkZXNjcmlwdGlvbiBpcyByZXF1aXJlZCBhbmQgY2Fubm90IGJlIGVtcHR5Jyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEdlbmVyYXRlIElBTSBwb2xpY3kgc3RhdGVtZW50cyByZXF1aXJlZCBmb3IgYWNjZXNzaW5nIHRoaXMga25vd2xlZGdlIGJhc2UuXG4gICAqXG4gICAqIFRoaXMgYWJzdHJhY3QgbWV0aG9kIG11c3QgYmUgaW1wbGVtZW50ZWQgYnkgc3ViY2xhc3NlcyB0byByZXR1cm4gdGhlXG4gICAqIHNwZWNpZmljIElBTSBwZXJtaXNzaW9ucyBuZWVkZWQgZm9yIHRoZWlyIGtub3dsZWRnZSBiYXNlIHR5cGUuXG4gICAqXG4gICAqIEByZXR1cm5zIEFycmF5IG9mIElBTSBQb2xpY3lTdGF0ZW1lbnQgb2JqZWN0cyBncmFudGluZyBuZWNlc3NhcnkgcGVybWlzc2lvbnNcbiAgICovXG4gIHB1YmxpYyBhYnN0cmFjdCBnZW5lcmF0ZUlhbVBlcm1pc3Npb25zKCk6IFBvbGljeVN0YXRlbWVudFtdO1xuXG4gIC8qKlxuICAgKiBFeHBvcnQgY29uZmlndXJhdGlvbiBmb3IgcnVudGltZSB1c2UgYnkgdGhlIHJldHJpZXZhbCB0b29sLlxuICAgKlxuICAgKiBSZXR1cm5zIGEgY29uZmlndXJhdGlvbiBvYmplY3QgY29udGFpbmluZyB0aGUgYmFzZSBrbm93bGVkZ2UgYmFzZVxuICAgKiBzZXR0aW5ncy4gU3ViY2xhc3NlcyBzaG91bGQgb3ZlcnJpZGUgdGhpcyBtZXRob2QgdG8gYWRkIGltcGxlbWVudGF0aW9uLVxuICAgKiBzcGVjaWZpYyBjb25maWd1cmF0aW9uLCBjYWxsaW5nIHN1cGVyLmV4cG9ydENvbmZpZ3VyYXRpb24oKSB0byBpbmNsdWRlXG4gICAqIHRoZSBiYXNlIGNvbmZpZ3VyYXRpb24uXG4gICAqXG4gICAqIEByZXR1cm5zIFJ1bnRpbWUgY29uZmlndXJhdGlvbiBvYmplY3QgZm9yIHRoZSByZXRyaWV2YWwgdG9vbFxuICAgKi9cbiAgcHVibGljIGV4cG9ydENvbmZpZ3VyYXRpb24oKTogS25vd2xlZGdlQmFzZVJ1bnRpbWVDb25maWcge1xuICAgIHJldHVybiB7XG4gICAgICBuYW1lOiB0aGlzLm5hbWUsXG4gICAgICBkZXNjcmlwdGlvbjogdGhpcy5kZXNjcmlwdGlvbixcbiAgICAgIHJldHJpZXZhbDogdGhpcy5yZXRyaWV2YWxDb25maWcsXG4gICAgICBhY2w6IHRoaXMuYWNsQ29uZmlnLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogUHJvdmlkZSB0aGUgcmV0cmlldmFsIHRvb2wgYXNzZXQgZm9yIHRoaXMga25vd2xlZGdlIGJhc2UgdHlwZS5cbiAgICpcbiAgICogQnkgZGVmYXVsdCwgcmV0dXJucyB1bmRlZmluZWQgdG8gdXNlIHRoZSBmcmFtZXdvcmsncyBkZWZhdWx0IHJldHJpZXZhbFxuICAgKiB0b29sLiBTdWJjbGFzc2VzIGNhbiBvdmVycmlkZSB0aGlzIG1ldGhvZCB0byBwcm92aWRlIGEgY3VzdG9tIHJldHJpZXZhbFxuICAgKiB0b29sIGltcGxlbWVudGF0aW9uLlxuICAgKlxuICAgKiBAcmV0dXJucyB1bmRlZmluZWQgdG8gdXNlIHRoZSBkZWZhdWx0IHJldHJpZXZhbCB0b29sXG4gICAqL1xuICBwdWJsaWMgcmV0cmlldmFsVG9vbEFzc2V0KCk6IEFzc2V0IHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgLyoqXG4gICAqIFByb3ZpZGUgTGFtYmRhIGxheWVycyByZXF1aXJlZCBieSB0aGUgcmV0cmlldmFsIHRvb2wuXG4gICAqXG4gICAqIEJ5IGRlZmF1bHQsIHJldHVybnMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm8gYWRkaXRpb25hbCBsYXllcnMgYXJlIG5lZWRlZC5cbiAgICogU3ViY2xhc3NlcyBjYW4gb3ZlcnJpZGUgdGhpcyBtZXRob2QgdG8gcHJvdmlkZSBMYW1iZGEgbGF5ZXJzIGNvbnRhaW5pbmdcbiAgICogZGVwZW5kZW5jaWVzIHJlcXVpcmVkIGJ5IHRoZWlyIHJldHJpZXZhbCB0b29sLlxuICAgKlxuICAgKiBAcmV0dXJucyB1bmRlZmluZWQgaW5kaWNhdGluZyBubyBhZGRpdGlvbmFsIGxheWVycyBuZWVkZWRcbiAgICovXG4gIHB1YmxpYyByZXRyaWV2YWxUb29sTGF5ZXJzKCk6IExheWVyVmVyc2lvbltdIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG59XG4iXX0=
@@ -188,5 +188,5 @@ class BedrockKnowledgeBase extends base_knowledge_base_1.BaseKnowledgeBase {
188
188
  }
189
189
  exports.BedrockKnowledgeBase = BedrockKnowledgeBase;
190
190
  _a = JSII_RTTI_SYMBOL_1;
191
- BedrockKnowledgeBase[_a] = { fqn: "@cdklabs/cdk-appmod-catalog-blueprints.BedrockKnowledgeBase", version: "1.10.0" };
191
+ BedrockKnowledgeBase[_a] = { fqn: "@cdklabs/cdk-appmod-catalog-blueprints.BedrockKnowledgeBase", version: "1.12.0" };
192
192
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmVkcm9jay1rbm93bGVkZ2UtYmFzZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3VzZS1jYXNlcy9mcmFtZXdvcmsvYWdlbnRzL2tub3dsZWRnZS1iYXNlL2JlZHJvY2sta25vd2xlZGdlLWJhc2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSxxRUFBcUU7QUFDckUsc0NBQXNDO0FBRXRDLDZCQUE2QjtBQUM3Qiw2Q0FBb0M7QUFDcEMsaURBQThEO0FBQzlELDZEQUFrRDtBQUVsRCwrREFBMEQ7QUFTMUQ7Ozs7Ozs7Ozs7OztHQVlHO0FBQ0gsTUFBYSxvQkFBcUIsU0FBUSx1Q0FBaUI7SUFxRHpEOzs7Ozs7O09BT0c7SUFDSCxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQWdDO1FBQ3hFLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBRXhCLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUVqQyxNQUFNLEtBQUssR0FBRyxtQkFBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUM3QixJQUFJLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUM7UUFDM0IsSUFBSSxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDO1FBRTdCLElBQUksQ0FBQyxlQUFlLEdBQUcsS0FBSyxDQUFDLGVBQWUsQ0FBQztRQUM3QyxJQUFJLENBQUMsZ0JBQWdCO1lBQ25CLEtBQUssQ0FBQyxnQkFBZ0I7Z0JBQ3RCLG1CQUFtQixJQUFJLENBQUMsTUFBTSxJQUFJLElBQUksQ0FBQyxPQUFPLG1CQUFtQixLQUFLLENBQUMsZUFBZSxFQUFFLENBQUM7UUFDM0YsSUFBSSxDQUFDLGVBQWUsR0FBRyxLQUFLLENBQUMsU0FBUyxDQUFDO1FBQ3ZDLHlDQUF5QztRQUN6QyxJQUFJLENBQUMsaUJBQWlCLEdBQUcsS0FBSyxDQUFDLFdBQVcs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QUksZ0JBQWdCLEdBQUc7aUJBQzlFO2FBQ0YsQ0FBQyxDQUNILENBQUM7UUFDSixDQUFDO1FBRUQsT0FBTyxVQUFVLENBQUM7SUFDcEIsQ0FBQztJQUVEOzs7Ozs7Ozs7Ozs7T0FZRztJQUNJLG1CQUFtQjtRQUN4QixPQUFPO1lBQ0wsR0FBRyxLQUFLLENBQUMsbUJBQW1CLEVBQUU7WUFDOUIsSUFBSSxFQUFFLFNBQVM7WUFDZixlQUFlLEVBQUUsSUFBSSxDQUFDLGVBQWU7WUFDckMsZ0JBQWdCLEVBQUUsSUFBSSxDQUFDLGdCQUFnQjtZQUN2QyxXQUFXLEVBQUUsSUFBSSxDQUFDLGlCQUFpQjtZQUNuQyxTQUFTLEVBQUUsSUFBSSxDQUFDLGVBQWU7U0FDaEMsQ0FBQztJQUNKLENBQUM7SUFFRDs7Ozs7Ozs7O09BU0c7SUFDSSxrQkFBa0I7UUFDdkIsT0FBTyxJQUFJLHFCQUFLLENBQUMsSUFBSSxFQUFFLHNCQUFzQixFQUFFO1lBQzdDLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxrQ0FBa0MsQ0FBQztZQUM5RCxPQUFPLEVBQUUsQ0FBQyxRQUFRLEVBQUUsV0FBVyxDQUFDO1NBQ2pDLENBQUMsQ0FBQztJQUNMLENBQUM7O0FBeE9ILG9EQXlPQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCBBbWF6b24uY29tLCBJbmMuIG9yIGl0cyBhZmZpbGlhdGVzLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCB7IFN0YWNrIH0gZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0IHsgRWZmZWN0LCBQb2xpY3lTdGF0ZW1lbnQgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtaWFtJztcbmltcG9ydCB7IEFzc2V0IH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLXMzLWFzc2V0cyc7XG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCB7IEJhc2VLbm93bGVkZ2VCYXNlIH0gZnJvbSAnLi9iYXNlLWtub3dsZWRnZS1iYXNlJztcbmltcG9ydCB7XG4gIEJlZHJvY2tLbm93bGVkZ2VCYXNlUHJvcHMsXG4gIENyZWF0ZUtub3dsZWRnZUJhc2VDb25maWd1cmF0aW9uLFxuICBHdWFyZHJhaWxDb25maWd1cmF0aW9uLFxuICBLbm93bGVkZ2VCYXNlUnVudGltZUNvbmZpZyxcbiAgVmVjdG9yU3RvcmVDb25maWd1cmF0aW9uLFxufSBmcm9tICcuL2tub3dsZWRnZS1iYXNlLXByb3BzJztcblxuLyoqXG4gKiBBbWF6b24gQmVkcm9jayBLbm93bGVkZ2UgQmFzZSBpbXBsZW1lbnRhdGlvbi5cbiAqXG4gKiBUaGlzIGNsYXNzIHByb3ZpZGVzIGludGVncmF0aW9uIHdpdGggQW1hem9uIEJlZHJvY2sgS25vd2xlZGdlIEJhc2VzLFxuICogd2hpY2ggdXNlIHZlY3RvciBzdG9yZXMgKFMzIFZlY3RvcnMgYnkgZGVmYXVsdCkgZm9yIHNlbWFudGljIHNlYXJjaC5cbiAqIEl0IGlzIHRoZSBkZWZhdWx0IGtub3dsZWRnZSBiYXNlIGltcGxlbWVudGF0aW9uIHdoZW4gbm9uZSBpcyBzcGVjaWZpZWQuXG4gKlxuICogVGhlIGltcGxlbWVudGF0aW9uIGhhbmRsZXM6XG4gKiAtIEFSTiBjb25zdHJ1Y3Rpb24gZnJvbSBrbm93bGVkZ2UgYmFzZSBJRCAoaWYgQVJOIG5vdCBwcm92aWRlZClcbiAqIC0gSUFNIHBlcm1pc3Npb24gZ2VuZXJhdGlvbiBmb3IgQmVkcm9jayBSZXRyaWV2ZSBhbmQgUmV0cmlldmVBbmRHZW5lcmF0ZSBBUElzXG4gKiAtIE9wdGlvbmFsIGd1YXJkcmFpbCBjb25maWd1cmF0aW9uIGZvciBjb250ZW50IGZpbHRlcmluZ1xuICogLSBSdW50aW1lIGNvbmZpZ3VyYXRpb24gZXhwb3J0IGZvciB0aGUgcmV0cmlldmFsIHRvb2xcbiAqL1xuZXhwb3J0IGNsYXNzIEJlZHJvY2tLbm93bGVkZ2VCYXNlIGV4dGVuZHMgQmFzZUtub3dsZWRnZUJhc2Uge1xuICAvKipcbiAgICogVGhlIHVuaXF1ZSBpZGVudGlmaWVyIGZvciB0aGUgQmVkcm9jayBLbm93bGVkZ2UgQmFzZS5cbiAgICpcbiAgICogVGhpcyBpcyB0aGUgSUQgYXNzaWduZWQgYnkgQmVkcm9jayB3aGVuIHRoZSBrbm93bGVkZ2UgYmFzZSB3YXMgY3JlYXRlZC5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBrbm93bGVkZ2VCYXNlSWQ6IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIEFSTiBvZiB0aGUgQmVkcm9jayBLbm93bGVkZ2UgQmFzZS5cbiAgICpcbiAgICogSWYgbm90IHByb3ZpZGVkIGluIHByb3BzLCB0aGlzIGlzIGNvbnN0cnVjdGVkIGZyb20gdGhlIGtub3dsZWRnZUJhc2VJZFxuICAgKiB1c2luZyB0aGUgY3VycmVudCByZWdpb24gYW5kIGFjY291bnQuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkga25vd2xlZGdlQmFzZUFybjogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBHdWFyZHJhaWwgY29uZmlndXJhdGlvbiBmb3IgY29udGVudCBmaWx0ZXJpbmcuXG4gICAqXG4gICAqIFdoZW4gY29uZmlndXJlZCwgdGhlIGd1YXJkcmFpbCB3aWxsIGJlIGFwcGxpZWQgZHVyaW5nIHJldHJpZXZhbFxuICAgKiBvcGVyYXRpb25zIHRvIGZpbHRlciBpbmFwcHJvcHJpYXRlIG9yIHNlbnNpdGl2ZSBjb250ZW50LlxuICAgKi9cbiAgcHJpdmF0ZSByZWFkb25seSBndWFyZHJhaWxDb25maWc/OiBHdWFyZHJhaWxDb25maWd1cmF0aW9uO1xuXG4gIC8qKlxuICAgKiBWZWN0b3Igc3RvcmUgY29uZmlndXJhdGlvbi5cbiAgICpcbiAgICogRGVmaW5lcyB0aGUgdHlwZSBvZiB2ZWN0b3Igc3RvcmUgdXNlZCBieSB0aGlzIGtub3dsZWRnZSBiYXNlLlxuICAgKiBEZWZhdWx0cyB0byBTMyBWZWN0b3JzIGlmIG5vdCBzcGVjaWZpZWQuXG4gICAqL1xuICBwcml2YXRlIHJlYWRvbmx5IHZlY3RvclN0b3JlQ29uZmlnOiBWZWN0b3JTdG9yZUNvbmZpZ3VyYXRpb247XG5cbiAgLyoqXG4gICAqIENvbmZpZ3VyYXRpb24gZm9yIGNyZWF0aW5nIGEgbmV3IGtub3dsZWRnZSBiYXNlLlxuICAgKlxuICAgKiBXaGVuIHByb3ZpZGVkLCBpbmRpY2F0ZXMgdGhhdCB0aGlzIGNvbnN0cnVjdCBzaG91bGQgY3JlYXRlIGEgbmV3XG4gICAqIEJlZHJvY2sgS25vd2xlZGdlIEJhc2UgcmF0aGVyIHRoYW4gcmVmZXJlbmNlIGFuIGV4aXN0aW5nIG9uZS5cbiAgICpcbiAgICogTm90ZTogS0IgY3JlYXRpb24gaXMgYW4gYWR2YW5jZWQgZmVhdHVyZS4gQ3VycmVudGx5LCB0aGlzIHByb3BlcnR5XG4gICAqIHN0b3JlcyB0aGUgY29uZmlndXJhdGlvbiBmb3IgZnV0dXJlIGltcGxlbWVudGF0aW9uLlxuICAgKi9cbiAgcHJpdmF0ZSByZWFkb25seSBjcmVhdGVDb25maWc/OiBDcmVhdGVLbm93bGVkZ2VCYXNlQ29uZmlndXJhdGlvbjtcblxuICAvKipcbiAgICogVGhlIEFXUyByZWdpb24gd2hlcmUgdGhlIGtub3dsZWRnZSBiYXNlIGlzIGRlcGxveWVkLlxuICAgKi9cbiAgcHJpdmF0ZSByZWFkb25seSByZWdpb246IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIEFXUyBhY2NvdW50IElEIHdoZXJlIHRoZSBrbm93bGVkZ2UgYmFzZSBpcyBkZXBsb3llZC5cbiAgICovXG4gIHByaXZhdGUgcmVhZG9ubHkgYWNjb3VudDogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgbmV3IEJlZHJvY2tLbm93bGVkZ2VCYXNlIGluc3RhbmNlLlxuICAgKlxuICAgKiBAcGFyYW0gc2NvcGUgLSBUaGUgc2NvcGUgaW4gd2hpY2ggdG8gZGVmaW5lIHRoaXMgY29uc3RydWN0XG4gICAqIEBwYXJhbSBpZCAtIFRoZSBzY29wZWQgY29uc3RydWN0IElEXG4gICAqIEBwYXJhbSBwcm9wcyAtIENvbmZpZ3VyYXRpb24gcHJvcGVydGllcyBmb3IgdGhlIEJlZHJvY2sgS25vd2xlZGdlIEJhc2VcbiAgICogQHRocm93cyBFcnJvciBpZiBrbm93bGVkZ2VCYXNlSWQgaXMgZW1wdHkgb3Igbm90IHByb3ZpZGVkXG4gICAqL1xuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogQmVkcm9ja0tub3dsZWRnZUJhc2VQcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCwgcHJvcHMpO1xuXG4gICAgdGhpcy52YWxpZGF0ZUJlZHJvY2tQcm9wcyhwcm9wcyk7XG5cbiAgICBjb25zdCBzdGFjayA9IFN0YWNrLm9mKHRoaXMpO1xuICAgIHRoaXMucmVnaW9uID0gc3RhY2sucmVnaW9uO1xuICAgIHRoaXMuYWNjb3VudCA9IHN0YWNrLmFjY291bnQ7XG5cbiAgICB0aGlzLmtub3dsZWRnZUJhc2VJZCA9IHByb3BzLmtub3dsZWRnZUJhc2VJZDtcbiAgICB0aGlzLmtub3dsZWRnZUJhc2VBcm4gPVxuICAgICAgcHJvcHMua25vd2xlZGdlQmFzZUFybiA/P1xuICAgICAgYGFybjphd3M6YmVkcm9jazoke3RoaXMucmVnaW9ufToke3RoaXMuYWNjb3VudH06a25vd2xlZGdlLWJhc2UvJHtwcm9wcy5rbm93bGVkZ2VCYXNlSWR9YDtcbiAgICB0aGlzLmd1YXJkcmFpbENvbmZpZyA9IHByb3BzLmd1YXJkcmFpbDtcbiAgICAvLyBEZWZhdWx0IHRvIFMzIFZlY3RvcnMgaWYgbm90IHNwZWNpZmllZFxuICAgIHRoaXMudmVjdG9yU3RvcmVDb25maWcgPSBwcm9wcy52ZWN0b3JTdG9yZSA/PyB7IHR5cGU6ICdzMy12ZWN0b3JzJyB9O1xuICAgIHRoaXMuY3JlYXRlQ29uZmlnID0gcHJvcHMuY3JlYXRlO1xuXG4gICAgLy8gTm90ZTogS0IgY3JlYXRpb24gaXMgaGFuZGxlZCBzZXBhcmF0ZWx5IHdoZW4gY3JlYXRlIGNvbmZpZyBpcyBwcm92aWRlZFxuICAgIC8vIFRoaXMgaXMgYW4gYWR2YW5jZWQgZmVhdHVyZSB0aGF0IHdpbGwgY3JlYXRlIGFjdHVhbCBBV1MgcmVzb3VyY2VzXG4gICAgaWYgKHRoaXMuY3JlYXRlQ29uZmlnKSB7XG4gICAgICB0aGlzLnNldHVwS25vd2xlZGdlQmFzZUNyZWF0aW9uKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgdXAga25vd2xlZGdlIGJhc2UgY3JlYXRpb24gd2hlbiBjcmVhdGUgY29uZmlndXJhdGlvbiBpcyBwcm92aWRlZC5cbiAgICpcbiAgICogVGhpcyBtZXRob2QgaXMgY2FsbGVkIGR1cmluZyBjb25zdHJ1Y3Rpb24gd2hlbiB0aGUgYGNyZWF0ZWAgcHJvcGVydHlcbiAgICogaXMgc3BlY2lmaWVkLiBJdCBwcmVwYXJlcyB0aGUgbmVjZXNzYXJ5IHJlc291cmNlcyBmb3IgY3JlYXRpbmcgYSBuZXdcbiAgICogQmVkcm9jayBLbm93bGVkZ2UgQmFzZS5cbiAgICpcbiAgICogTm90ZTogRnVsbCBLQiBjcmVhdGlvbiBpbXBsZW1lbnRhdGlvbiByZXF1aXJlcyBDbG91ZEZvcm1hdGlvbiBjdXN0b21cbiAgICogcmVzb3VyY2VzIG9yIEwxIGNvbnN0cnVjdHMuIFRoaXMgaXMgYSBwbGFjZWhvbGRlciBmb3IgZnV0dXJlIGltcGxlbWVudGF0aW9uLlxuICAgKi9cbiAgcHJpdmF0ZSBzZXR1cEtub3dsZWRnZUJhc2VDcmVhdGlvbigpOiB2b2lkIHtcbiAgICAvLyBLQiBjcmVhdGlvbiBpcyBhbiBhZHZhbmNlZCBmZWF0dXJlXG4gICAgLy8gVGhlIGFjdHVhbCBpbXBsZW1lbnRhdGlvbiB3b3VsZCBpbnZvbHZlOlxuICAgIC8vIDEuIENyZWF0aW5nIGFuIElBTSByb2xlIGZvciBCZWRyb2NrIEtCXG4gICAgLy8gMi4gQ3JlYXRpbmcgdGhlIEJlZHJvY2sgS0IgdmlhIENmbktub3dsZWRnZUJhc2VcbiAgICAvLyAzLiBDcmVhdGluZyBhIGRhdGEgc291cmNlIHBvaW50aW5nIHRvIHRoZSBTMyBidWNrZXRcbiAgICAvLyA0LiBDb25maWd1cmluZyB0aGUgZW1iZWRkaW5nIG1vZGVsXG4gICAgLy8gNS4gU2V0dGluZyB1cCB0aGUgdmVjdG9yIHN0b3JlIChTMyBWZWN0b3JzIGJ5IGRlZmF1bHQpXG4gICAgLy9cbiAgICAvLyBGb3Igbm93LCB0aGlzIHN0b3JlcyB0aGUgY29uZmlndXJhdGlvbiBmb3IgcmVmZXJlbmNlLlxuICAgIC8vIFVzZXJzIHNob3VsZCBjcmVhdGUgS0JzIHZpYSB0aGUgQmVkcm9jayBjb25zb2xlIG9yIENMSVxuICAgIC8vIGFuZCByZWZlcmVuY2UgdGhlbSBieSBJRC5cbiAgfVxuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZXMgQmVkcm9jay1zcGVjaWZpYyBwcm9wcyBhdCBjb25zdHJ1Y3Rpb24gdGltZS5cbiAgICpcbiAgICogRW5zdXJlcyB0aGF0IHRoZSBrbm93bGVkZ2VCYXNlSWQgaXMgcHJvdmlkZWQgYW5kIG5vdCBlbXB0eS5cbiAgICpcbiAgICogQHBhcmFtIHByb3BzIC0gVGhlIHByb3BzIHRvIHZhbGlkYXRlXG4gICAqIEB0aHJvd3MgRXJyb3IgaWYga25vd2xlZGdlQmFzZUlkIGlzIGVtcHR5IG9yIG5vdCBwcm92aWRlZFxuICAgKi9cbiAgcHJpdmF0ZSB2YWxpZGF0ZUJlZHJvY2tQcm9wcyhwcm9wczogQmVkcm9ja0tub3dsZWRnZUJhc2VQcm9wcyk6IHZvaWQge1xuICAgIGlmICghcHJvcHMua25vd2xlZGdlQmFzZUlkIHx8IHByb3BzLmtub3dsZWRnZUJhc2VJZC50cmltKCkgPT09ICcnKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2tub3dsZWRnZUJhc2VJZCBpcyByZXF1aXJlZCBhbmQgY2Fubm90IGJlIGVtcHR5Jyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEdlbmVyYXRlIElBTSBwb2xpY3kgc3RhdGVtZW50cyByZXF1aXJlZCBmb3IgYWNjZXNzaW5nIHRoaXMgQmVkcm9jayBLbm93bGVkZ2UgQmFzZS5cbiAgICpcbiAgICogUmV0dXJucyBwZXJtaXNzaW9ucyBmb3I6XG4gICAqIC0gYmVkcm9jazpSZXRyaWV2ZSAtIFF1ZXJ5IHRoZSBrbm93bGVkZ2UgYmFzZVxuICAgKiAtIGJlZHJvY2s6UmV0cmlldmVBbmRHZW5lcmF0ZSAtIFF1ZXJ5IGFuZCBnZW5lcmF0ZSByZXNwb25zZXNcbiAgICogLSBiZWRyb2NrOkFwcGx5R3VhcmRyYWlsIC0gQXBwbHkgZ3VhcmRyYWlsIChpZiBjb25maWd1cmVkKVxuICAgKiAtIHMzOkdldE9iamVjdCAtIEFjY2VzcyBTMyB2ZWN0b3JzIChpZiB1c2luZyBTMyBWZWN0b3JzIHdpdGggY3VzdG9tIGJ1Y2tldClcbiAgICogLSBzMzpHZXRPYmplY3QgLSBBY2Nlc3MgZGF0YSBzb3VyY2UgYnVja2V0IChpZiBjcmVhdGUgY29uZmlnIHByb3ZpZGVkKVxuICAgKlxuICAgKiBBbGwgcGVybWlzc2lvbnMgYXJlIHNjb3BlZCB0byB0aGUgc3BlY2lmaWMga25vd2xlZGdlIGJhc2UgQVJOXG4gICAqIGZvbGxvd2luZyB0aGUgcHJpbmNpcGxlIG9mIGxlYXN0IHByaXZpbGVnZS5cbiAgICpcbiAgICogQHJldHVybnMgQXJyYXkgb2YgSUFNIFBvbGljeVN0YXRlbWVudCBvYmplY3RzIGdyYW50aW5nIG5lY2Vzc2FyeSBwZXJtaXNzaW9uc1xuICAgKi9cbiAgcHVibGljIGdlbmVyYXRlSWFtUGVybWlzc2lvbnMoKTogUG9saWN5U3RhdGVtZW50W10ge1xuICAgIGNvbnN0IHN0YXRlbWVudHM6IFBvbGljeVN0YXRlbWVudFtdID0gW1xuICAgICAgbmV3IFBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgIGVmZmVjdDogRWZmZWN0LkFMTE9XLFxuICAgICAgICBhY3Rpb25zOiBbJ2JlZHJvY2s6UmV0cmlldmUnLCAnYmVkcm9jazpSZXRyaWV2ZUFuZEdlbmVyYXRlJ10sXG4gICAgICAgIHJlc291cmNlczogW3RoaXMua25vd2xlZGdlQmFzZUFybl0sXG4gICAgICB9KSxcbiAgICBdO1xuXG4gICAgLy8gQWRkIGd1YXJkcmFpbCBwZXJtaXNzaW9ucyBpZiBjb25maWd1cmVkXG4gICAgaWYgKHRoaXMuZ3VhcmRyYWlsQ29uZmlnKSB7XG4gICAgICBzdGF0ZW1lbnRzLnB1c2goXG4gICAgICAgIG5ldyBQb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICAgIGVmZmVjdDogRWZmZWN0LkFMTE9XLFxuICAgICAgICAgIGFjdGlvbnM6IFsnYmVkcm9jazpBcHBseUd1YXJkcmFpbCddLFxuICAgICAgICAgIHJlc291cmNlczogW1xuICAgICAgICAgICAgYGFybjphd3M6YmVkcm9jazoke3RoaXMucmVnaW9ufToke3RoaXMuYWNjb3VudH06Z3VhcmRyYWlsLyR7dGhpcy5ndWFyZHJhaWxDb25maWcuZ3VhcmRyYWlsSWR9YCxcbiAgICAgICAgICBdLFxuICAgICAgICB9KSxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gQWRkIFMzIHBlcm1pc3Npb25zIGlmIHVzaW5nIFMzIFZlY3RvcnMgd2l0aCBhIGN1c3RvbSBidWNrZXRcbiAgICBpZiAodGhpcy52ZWN0b3JTdG9yZUNvbmZpZy50eXBlID09PSAnczMtdmVjdG9ycycgJiYgdGhpcy52ZWN0b3JTdG9yZUNvbmZpZy5idWNrZXROYW1lKSB7XG4gICAgICBjb25zdCBwcmVmaXggPSB0aGlzLnZlY3RvclN0b3JlQ29uZmlnLnByZWZpeCA/PyAndmVjdG9ycy8nO1xuICAgICAgc3RhdGVtZW50cy5wdXNoKFxuICAgICAgICBuZXcgUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgICBlZmZlY3Q6IEVmZmVjdC5BTExPVyxcbiAgICAgICAgICBhY3Rpb25zOiBbJ3MzOkdldE9iamVjdCddLFxuICAgICAgICAgIHJlc291cmNlczogW1xuICAgICAgICAgICAgYGFybjphd3M6czM6Ojoke3RoaXMudmVjdG9yU3RvcmVDb25maWcuYnVja2V0TmFtZX0vJHtwcmVmaXh9KmAsXG4gICAgICAgICAgXSxcbiAgICAgICAgfSksXG4gICAgICApO1xuICAgIH1cblxuICAgIC8vIEFkZCBkYXRhIHNvdXJjZSBidWNrZXQgcGVybWlzc2lvbnMgaWYgY3JlYXRlIGNvbmZpZyBpcyBwcm92aWRlZFxuICAgIGlmICh0aGlzLmNyZWF0ZUNvbmZpZykge1xuICAgICAgY29uc3QgZGF0YVNvdXJjZVByZWZpeCA9IHRoaXMuY3JlYXRlQ29uZmlnLmRhdGFTb3VyY2VQcmVmaXggPz8gJyc7XG4gICAgICBzdGF0ZW1lbnRzLnB1c2goXG4gICAgICAgIG5ldyBQb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICAgIGVmZmVjdDogRWZmZWN0LkFMTE9XLFxuICAgICAgICAgIGFjdGlvbnM6IFsnczM6R2V0T2JqZWN0JywgJ3MzOkxpc3RCdWNrZXQnXSxcbiAgICAgICAgICByZXNvdXJjZXM6IFtcbiAgICAgICAgICAgIGBhcm46YXdzOnMzOjo6JHt0aGlzLmNyZWF0ZUNvbmZpZy5kYXRhU291cmNlQnVja2V0TmFtZX1gLFxuICAgICAgICAgICAgYGFybjphd3M6czM6Ojoke3RoaXMuY3JlYXRlQ29uZmlnLmRhdGFTb3VyY2VCdWNrZXROYW1lfS8ke2RhdGFTb3VyY2VQcmVmaXh9KmAsXG4gICAgICAgICAgXSxcbiAgICAgICAgfSksXG4gICAgICApO1xuICAgIH1cblxuICAgIHJldHVybiBzdGF0ZW1lbnRzO1xuICB9XG5cbiAgLyoqXG4gICAqIEV4cG9ydCBjb25maWd1cmF0aW9uIGZvciBydW50aW1lIHVzZSBieSB0aGUgcmV0cmlldmFsIHRvb2wuXG4gICAqXG4gICAqIFJldHVybnMgYSBjb25maWd1cmF0aW9uIG9iamVjdCBjb250YWluaW5nIGFsbCBCZWRyb2NrLXNwZWNpZmljXG4gICAqIHNldHRpbmdzIG5lZWRlZCB0byBxdWVyeSB0aGUga25vd2xlZGdlIGJhc2UgYXQgcnVudGltZSwgaW5jbHVkaW5nOlxuICAgKiAtIEJhc2UgY29uZmlndXJhdGlvbiAobmFtZSwgZGVzY3JpcHRpb24sIHJldHJpZXZhbCwgYWNsKVxuICAgKiAtIEtub3dsZWRnZSBiYXNlIHR5cGUgKCdiZWRyb2NrJylcbiAgICogLSBLbm93bGVkZ2UgYmFzZSBJRCBhbmQgQVJOXG4gICAqIC0gVmVjdG9yIHN0b3JlIGNvbmZpZ3VyYXRpb25cbiAgICogLSBHdWFyZHJhaWwgY29uZmlndXJhdGlvbiAoaWYgcHJlc2VudClcbiAgICpcbiAgICogQHJldHVybnMgUnVudGltZSBjb25maWd1cmF0aW9uIG9iamVjdCBmb3IgdGhlIHJldHJpZXZhbCB0b29sXG4gICAqL1xuICBwdWJsaWMgZXhwb3J0Q29uZmlndXJhdGlvbigpOiBLbm93bGVkZ2VCYXNlUnVudGltZUNvbmZpZyB7XG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLnN1cGVyLmV4cG9ydENvbmZpZ3VyYXRpb24oKSxcbiAgICAgIHR5cGU6ICdiZWRyb2NrJyxcbiAgICAgIGtub3dsZWRnZUJhc2VJZDogdGhpcy5rbm93bGVkZ2VCYXNlSWQsXG4gICAgICBrbm93bGVkZ2VCYXNlQXJuOiB0aGlzLmtub3dsZWRnZUJhc2VBcm4sXG4gICAgICB2ZWN0b3JTdG9yZTogdGhpcy52ZWN0b3JTdG9yZUNvbmZpZyxcbiAgICAgIGd1YXJkcmFpbDogdGhpcy5ndWFyZHJhaWxDb25maWcsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQcm92aWRlIHRoZSBCZWRyb2NrLXNwZWNpZmljIHJldHJpZXZhbCB0b29sIGFzc2V0LlxuICAgKlxuICAgKiBSZXR1cm5zIGFuIEFzc2V0IGNvbnRhaW5pbmcgdGhlIFB5dGhvbiByZXRyaWV2YWwgdG9vbCB0aGF0IHVzZXNcbiAgICogdGhlIEFtYXpvbiBCZWRyb2NrIEFnZW50IFJ1bnRpbWUgQVBJIHRvIHF1ZXJ5IGtub3dsZWRnZSBiYXNlcy5cbiAgICogVGhpcyB0b29sIGlzIGF1dG9tYXRpY2FsbHkgYWRkZWQgdG8gYWdlbnRzIHRoYXQgdXNlIEJlZHJvY2tcbiAgICoga25vd2xlZGdlIGJhc2VzLlxuICAgKlxuICAgKiBAcmV0dXJucyBBc3NldCBjb250YWluaW5nIHRoZSBCZWRyb2NrIHJldHJpZXZhbCB0b29sXG4gICAqL1xuICBwdWJsaWMgcmV0cmlldmFsVG9vbEFzc2V0KCk6IEFzc2V0IHtcbiAgICByZXR1cm4gbmV3IEFzc2V0KHRoaXMsICdCZWRyb2NrUmV0cmlldmFsVG9vbCcsIHtcbiAgICAgIHBhdGg6IHBhdGguam9pbihfX2Rpcm5hbWUsICcuLi9yZXNvdXJjZXMva25vd2xlZGdlLWJhc2UtdG9vbCcpLFxuICAgICAgZXhjbHVkZTogWyd0ZXN0XyonLCAnKl90ZXN0LnB5J10sXG4gICAgfSk7XG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,20 @@
1
+ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ # SPDX-License-Identifier: Apache-2.0
3
+
4
+ FROM python:3.13-slim
5
+
6
+ WORKDIR /app
7
+
8
+ # Install dependencies
9
+ COPY requirements.txt .
10
+ RUN pip install --no-cache-dir -r requirements.txt
11
+
12
+ # Copy handler code
13
+ COPY main.py .
14
+
15
+ # AgentCore Runtime HTTP protocol: listen on port 8080
16
+ EXPOSE 8080
17
+
18
+ # Use opentelemetry-instrument wrapper so ADOT auto-instrumentation
19
+ # emits traces/spans to AgentCore Observability when enabled.
20
+ CMD ["opentelemetry-instrument", "python", "main.py"]
@@ -0,0 +1,224 @@
1
+ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ # SPDX-License-Identifier: Apache-2.0
3
+
4
+ """
5
+ AgentCore Runtime Handler for Strands Agent.
6
+
7
+ Uses the Bedrock AgentCore SDK to run as a managed container.
8
+ The SDK handles the HTTP server (port 8080), /invocations and /ping
9
+ endpoints, and SSE streaming.
10
+
11
+ Architecture:
12
+ AgentCore Runtime → Container (port 8080) → AgentCore SDK → Strands Agent → Bedrock
13
+ """
14
+
15
+ import os
16
+ import json
17
+ import uuid
18
+ import importlib
19
+ import sys
20
+ import tempfile
21
+ import zipfile
22
+ import base64
23
+ import logging
24
+ import traceback
25
+ import boto3
26
+ from opentelemetry import baggage
27
+ from opentelemetry import context as otel_context
28
+
29
+ from bedrock_agentcore.runtime import BedrockAgentCoreApp
30
+ from strands import Agent
31
+ from strands.models import BedrockModel
32
+ from strands.agent.conversation_manager import SlidingWindowConversationManager
33
+ from strands.session.s3_session_manager import S3SessionManager as StrandsS3SessionManager
34
+
35
+ logger = logging.getLogger(__name__)
36
+ logging.basicConfig(level=logging.INFO)
37
+
38
+ s3_client = boto3.client('s3')
39
+
40
+ # Configuration from environment variables
41
+ MODEL_ID = os.getenv('MODEL_ID', 'anthropic.claude-3-5-sonnet-20241022-v2:0')
42
+ SYSTEM_PROMPT_BUCKET = os.getenv('SYSTEM_PROMPT_S3_BUCKET_NAME')
43
+ SYSTEM_PROMPT_KEY = os.getenv('SYSTEM_PROMPT_S3_KEY')
44
+ TOOLS_CONFIG = os.getenv('TOOLS_CONFIG', '[]')
45
+ KNOWLEDGE_BASE_SYSTEM_PROMPT_ADDITION = os.getenv('KNOWLEDGE_BASE_SYSTEM_PROMPT_ADDITION', '')
46
+ SESSION_BUCKET = os.getenv('SESSION_BUCKET')
47
+
48
+
49
+ def load_system_prompt() -> str:
50
+ """Load system prompt from S3 at cold start."""
51
+ if not SYSTEM_PROMPT_BUCKET or not SYSTEM_PROMPT_KEY:
52
+ return 'You are a helpful AI assistant.'
53
+
54
+ try:
55
+ response = s3_client.get_object(
56
+ Bucket=SYSTEM_PROMPT_BUCKET,
57
+ Key=SYSTEM_PROMPT_KEY
58
+ )
59
+ return response['Body'].read().decode('utf-8')
60
+ except Exception as e:
61
+ logger.error(f'Failed to load system prompt: {e}')
62
+ return 'You are a helpful AI assistant.'
63
+
64
+
65
+ def load_tools_from_s3() -> list:
66
+ """Load tool modules from S3 based on TOOLS_CONFIG env var."""
67
+ tools = []
68
+ try:
69
+ tools_config = json.loads(TOOLS_CONFIG)
70
+ except (json.JSONDecodeError, TypeError):
71
+ logger.warning('Invalid TOOLS_CONFIG, no tools loaded')
72
+ return tools
73
+
74
+ for tool_def in tools_config:
75
+ try:
76
+ bucket_name = tool_def.get('bucketName')
77
+ key = tool_def.get('key')
78
+ is_zip = tool_def.get('isZipArchive', False)
79
+
80
+ if not bucket_name or not key:
81
+ continue
82
+
83
+ tmp_dir = tempfile.mkdtemp()
84
+
85
+ if is_zip:
86
+ zip_path = os.path.join(tmp_dir, 'tools.zip')
87
+ s3_client.download_file(bucket_name, key, zip_path)
88
+ with zipfile.ZipFile(zip_path, 'r') as zf:
89
+ zf.extractall(tmp_dir)
90
+ os.remove(zip_path)
91
+ sys.path.insert(0, tmp_dir)
92
+ for fname in os.listdir(tmp_dir):
93
+ if fname.endswith('.py') and not fname.startswith('_'):
94
+ mod_name = fname[:-3]
95
+ mod = importlib.import_module(mod_name)
96
+ for attr_name in dir(mod):
97
+ attr = getattr(mod, attr_name)
98
+ if callable(attr) and hasattr(attr, '__wrapped__'):
99
+ tools.append(attr)
100
+ else:
101
+ file_path = os.path.join(tmp_dir, os.path.basename(key))
102
+ s3_client.download_file(bucket_name, key, file_path)
103
+ sys.path.insert(0, tmp_dir)
104
+ mod_name = os.path.basename(key).replace('.py', '')
105
+ mod = importlib.import_module(mod_name)
106
+ for attr_name in dir(mod):
107
+ attr = getattr(mod, attr_name)
108
+ if callable(attr) and hasattr(attr, '__wrapped__'):
109
+ tools.append(attr)
110
+
111
+ except Exception as e:
112
+ logger.error(f'Failed to load tool from S3: {e}')
113
+ continue
114
+
115
+ logger.info(f'Loaded {len(tools)} tools from S3')
116
+ return tools
117
+
118
+
119
+ def extract_user_id_from_headers(headers: dict) -> str | None:
120
+ """Extract user sub from JWT Authorization header.
121
+
122
+ AgentCore validates the JWT before forwarding the request,
123
+ so we only need to decode the payload — no verification needed.
124
+ """
125
+ auth = headers.get('authorization', '')
126
+ if not auth.lower().startswith('bearer '):
127
+ return None
128
+ token = auth[7:]
129
+ try:
130
+ payload_b64 = token.split('.')[1]
131
+ padding = 4 - len(payload_b64) % 4
132
+ if padding != 4:
133
+ payload_b64 += '=' * padding
134
+ payload = json.loads(base64.urlsafe_b64decode(payload_b64))
135
+ return payload.get('sub')
136
+ except Exception:
137
+ return None
138
+
139
+
140
+ # Cold start: load system prompt and tools
141
+ SYSTEM_PROMPT = load_system_prompt()
142
+ if KNOWLEDGE_BASE_SYSTEM_PROMPT_ADDITION:
143
+ SYSTEM_PROMPT = SYSTEM_PROMPT + '\n\n' + KNOWLEDGE_BASE_SYSTEM_PROMPT_ADDITION
144
+ AGENT_TOOLS = load_tools_from_s3()
145
+
146
+ app = BedrockAgentCoreApp()
147
+
148
+
149
+ @app.entrypoint
150
+ async def handle_invocation(payload, context):
151
+ """Handle agent invocation with streaming response.
152
+
153
+ The SDK calls this for POST /invocations. Yielding dicts streams them
154
+ as SSE events. The SDK handles serialization and transport.
155
+ """
156
+ user_message = payload.get('prompt') or payload.get('message', '')
157
+
158
+ # Session ID from AgentCore header or generate new
159
+ session_id = context.session_id or str(uuid.uuid4())
160
+
161
+ # Propagate session ID in OTEL baggage so ADOT can correlate
162
+ # traces/spans with the correct session in downstream headers.
163
+ ctx = baggage.set_baggage('session.id', session_id)
164
+ otel_context.attach(ctx)
165
+
166
+ # Extract user identity from the raw Starlette request headers.
167
+ # The SDK's context.request_headers may not include Authorization
168
+ # (it extracts it into workload_access_token), so we read directly
169
+ # from the underlying request object — same as the old FastAPI path.
170
+ headers = dict(context.request.headers) if context.request else {}
171
+ user_id = (
172
+ headers.get('x-amzn-bedrock-agentcore-runtime-user-id')
173
+ or extract_user_id_from_headers(headers)
174
+ )
175
+
176
+ logger.info('Invocation: session=%s, user=%s, message=%s...', session_id, user_id, user_message[:80])
177
+
178
+ # Yield session metadata first so the frontend can track the session
179
+ yield {'session_id': session_id}
180
+
181
+ try:
182
+ system_prompt = SYSTEM_PROMPT
183
+ if user_id:
184
+ system_prompt += (
185
+ '\n\n## Authenticated User\n'
186
+ f'The current authenticated user ID is: {user_id}\n'
187
+ 'Use this ID when looking up their transactions or other '
188
+ 'user specific information. Do not ask the user for their customer ID.'
189
+ )
190
+
191
+ session_manager = None
192
+ if SESSION_BUCKET:
193
+ session_manager = StrandsS3SessionManager(
194
+ session_id=session_id,
195
+ bucket=SESSION_BUCKET,
196
+ )
197
+
198
+ conversation_manager = SlidingWindowConversationManager(window_size=20)
199
+ model = BedrockModel(model_id=MODEL_ID, streaming=True)
200
+
201
+ agent = Agent(
202
+ model=model,
203
+ system_prompt=system_prompt,
204
+ tools=AGENT_TOOLS if AGENT_TOOLS else None,
205
+ session_manager=session_manager,
206
+ conversation_manager=conversation_manager,
207
+ callback_handler=None,
208
+ )
209
+
210
+ async for event in agent.stream_async(user_message):
211
+ if 'data' in event:
212
+ yield {'text': event['data']}
213
+
214
+ yield {'done': True}
215
+
216
+ except Exception as e:
217
+ error_detail = f'{type(e).__name__}: {e}'
218
+ logger.error('Error processing invocation: %s', error_detail)
219
+ traceback.print_exc()
220
+ yield {'error': error_detail}
221
+
222
+
223
+ if __name__ == '__main__':
224
+ app.run()
@@ -0,0 +1,5 @@
1
+ bedrock-agentcore>=1.0.0
2
+ strands-agents>=1.0.0
3
+ boto3>=1.0.0
4
+ aws-lambda-powertools>=2.0.0
5
+ aws-opentelemetry-distro>=0.10.0
@@ -16,7 +16,6 @@ Architecture:
16
16
  import os
17
17
  import json
18
18
  import uuid
19
- import time
20
19
  import importlib
21
20
  import sys
22
21
  import tempfile
@@ -32,6 +31,8 @@ import uvicorn
32
31
 
33
32
  from strands import Agent
34
33
  from strands.models import BedrockModel
34
+ from strands.agent.conversation_manager import SlidingWindowConversationManager
35
+ from strands.session.s3_session_manager import S3SessionManager as StrandsS3SessionManager
35
36
  from aws_lambda_powertools import Logger, Tracer, Metrics
36
37
  from aws_lambda_powertools.metrics import MetricUnit
37
38
 
@@ -50,9 +51,6 @@ SYSTEM_PROMPT_KEY = os.getenv('SYSTEM_PROMPT_S3_KEY')
50
51
  TOOLS_CONFIG = os.getenv('TOOLS_CONFIG', '[]')
51
52
  KNOWLEDGE_BASE_SYSTEM_PROMPT_ADDITION = os.getenv('KNOWLEDGE_BASE_SYSTEM_PROMPT_ADDITION', '')
52
53
  SESSION_BUCKET = os.getenv('SESSION_BUCKET')
53
- CONTEXT_ENABLED = os.getenv('CONTEXT_ENABLED', 'true').lower() == 'true'
54
- CONTEXT_STRATEGY = os.getenv('CONTEXT_STRATEGY', 'SlidingWindow')
55
- CONTEXT_WINDOW_SIZE = int(os.getenv('CONTEXT_WINDOW_SIZE', '20'))
56
54
 
57
55
 
58
56
  def load_system_prompt() -> str:
@@ -135,74 +133,6 @@ if KNOWLEDGE_BASE_SYSTEM_PROMPT_ADDITION:
135
133
  AGENT_TOOLS = load_tools_from_s3()
136
134
 
137
135
 
138
- class SessionManager:
139
- """Manages conversation sessions in S3."""
140
-
141
- def __init__(self, bucket: Optional[str] = None):
142
- self.bucket = bucket
143
- self.enabled = bucket is not None
144
-
145
- def get_session(self, session_id: str) -> List[Dict[str, Any]]:
146
- """Retrieve message history from S3."""
147
- if not self.enabled:
148
- return []
149
-
150
- key = f'sessions/{session_id}.json'
151
- try:
152
- response = s3_client.get_object(Bucket=self.bucket, Key=key)
153
- data = json.loads(response['Body'].read().decode('utf-8'))
154
- return data.get('messages', [])
155
- except s3_client.exceptions.NoSuchKey:
156
- return []
157
- except Exception as e:
158
- logger.warning(f'Failed to load session {session_id}: {e}')
159
- return []
160
-
161
- def save_session(self, session_id: str, messages: List[Dict[str, Any]]) -> None:
162
- """Save message history to S3."""
163
- if not self.enabled:
164
- return
165
-
166
- key = f'sessions/{session_id}.json'
167
- data = {
168
- 'session_id': session_id,
169
- 'messages': messages,
170
- 'updated_at': time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime()),
171
- }
172
- try:
173
- s3_client.put_object(
174
- Bucket=self.bucket,
175
- Key=key,
176
- Body=json.dumps(data),
177
- ContentType='application/json'
178
- )
179
- except Exception as e:
180
- logger.error(f'Failed to save session {session_id}: {e}')
181
-
182
-
183
- class ContextManager:
184
- """Manages conversation context windowing."""
185
-
186
- def __init__(self, strategy: str = 'SlidingWindow', window_size: int = 20, enabled: bool = True):
187
- self.strategy = strategy
188
- self.window_size = window_size
189
- self.enabled = enabled
190
-
191
- def get_context(self, messages: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
192
- """Apply context windowing to message history."""
193
- if not self.enabled or self.strategy == 'Null':
194
- return []
195
-
196
- if self.strategy == 'SlidingWindow':
197
- return messages[-self.window_size:] if len(messages) > self.window_size else list(messages)
198
-
199
- return list(messages)
200
-
201
-
202
- # Initialize managers
203
- session_manager = SessionManager(SESSION_BUCKET)
204
- context_manager = ContextManager(CONTEXT_STRATEGY, CONTEXT_WINDOW_SIZE, CONTEXT_ENABLED)
205
-
206
136
  # FastAPI app
207
137
  app = FastAPI()
208
138
 
@@ -249,28 +179,34 @@ async def chat(request: ChatRequest):
249
179
 
250
180
  full_response = ''
251
181
  try:
252
- # Load session history
253
- messages = session_manager.get_session(session_id)
182
+ # Create Strands-native session manager (handles load/save automatically)
183
+ session_manager = None
184
+ if SESSION_BUCKET:
185
+ session_manager = StrandsS3SessionManager(
186
+ session_id=session_id,
187
+ bucket_name=SESSION_BUCKET,
188
+ )
254
189
 
255
- # Apply context windowing
256
- context = context_manager.get_context(messages)
190
+ # Create Strands-native conversation manager for context windowing
191
+ conversation_manager = SlidingWindowConversationManager(window_size=20)
257
192
 
258
193
  # Create Bedrock model
259
194
  model = BedrockModel(model_id=MODEL_ID, streaming=True)
260
195
 
261
- # Create agent with system prompt, tools, and conversation history.
196
+ # Create agent with Strands-native session and conversation management.
197
+ # Strands handles session persistence and context windowing automatically.
262
198
  # Disable the default callback handler so stream_async yields all events.
263
199
  agent = Agent(
264
200
  model=model,
265
201
  system_prompt=SYSTEM_PROMPT,
266
202
  tools=AGENT_TOOLS if AGENT_TOOLS else None,
267
- messages=list(context) if context else None,
203
+ session_manager=session_manager,
204
+ conversation_manager=conversation_manager,
268
205
  callback_handler=None,
269
206
  )
270
207
 
271
208
  # Use stream_async for true token-by-token streaming.
272
209
  # Each event with a "data" key contains a text chunk from the model.
273
- result = None
274
210
  async for event in agent.stream_async(user_message):
275
211
  # Text chunk from model — stream it to the client immediately
276
212
  if 'data' in event:
@@ -278,20 +214,7 @@ async def chat(request: ChatRequest):
278
214
  full_response += chunk
279
215
  yield format_sse(json.dumps({'text': chunk}))
280
216
 
281
- # Capture the final result for session saving
282
- if 'result' in event:
283
- result = event['result']
284
-
285
- # Save updated session with the agent's actual messages if available.
286
- # The agent maintains its own messages list during stream_async,
287
- # so we can use it directly for accurate conversation history.
288
- if hasattr(agent, 'messages') and agent.messages:
289
- session_manager.save_session(session_id, list(agent.messages))
290
- else:
291
- # Fallback: append manually
292
- messages.append({'role': 'user', 'content': [{'text': user_message}]})
293
- messages.append({'role': 'assistant', 'content': [{'text': full_response}]})
294
- session_manager.save_session(session_id, messages)
217
+ # Session is saved automatically by Strands S3SessionManager
295
218
 
296
219
  metrics.add_metric(name='ChatResponses', unit=MetricUnit.Count, value=1)
297
220