Add Tool Calling to Java SDK (#1481)

* Use Java Bean for connection details and add more tests (#1317)

* Use Java Bean for connection details and add more tests

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Simplify mock setup

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Adding even more tests for test coverage

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

---------

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>
Co-authored-by: Artur Ciocanu <ciocanu@adobe.com>
Co-authored-by: Cassie Coyle <cassie@diagrid.io>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Update CONTRIBUTING.md

Signed-off-by: Siri Varma Vegiraju <siri.varma@outlook.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Bump codecov/codecov-action from 5.4.0 to 5.4.2 (#1318)

Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 5.4.0 to 5.4.2.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v5.4.0...v5.4.2)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-version: 5.4.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Cassie Coyle <cassie@diagrid.io>
Co-authored-by: Dapr Bot <56698301+dapr-bot@users.noreply.github.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Fix URL building logic (#1320)

* Fix URL building logic

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Add test for query params

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Fix the assertion in the test

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Adjust the tests

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Remove uneeded changes from IT test

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Revert some unintended changes

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Simplify the testing a little bit

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Adjust the test to use ServerRequest

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Test removing things from method invoke controller

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Add query param encoding test

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Revert some unintended changes

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Some tiny styles

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

---------

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>
Co-authored-by: Artur Ciocanu <ciocanu@adobe.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Generate updated javadocs for 1.14.1

Signed-off-by: Dapr Bot <daprweb@microsoft.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Add Conversation AI to Java SDK (#1235)

* Conversation first commit

Signed-off-by: Siri Varma Vegiraju <svegiraju@microsoft.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>
Signed-off-by: siri-varma <siri.varma@outlook.com>

* Add unit tests

Signed-off-by: sirivarma <siri.varma@outlook.com>
Signed-off-by: siri-varma <siri.varma@outlook.com>

* change ai to conv

Signed-off-by: sirivarma <siri.varma@outlook.com>
Signed-off-by: siri-varma <siri.varma@outlook.com>

* Move to single module

Signed-off-by: sirivarma <siri.varma@outlook.com>
Signed-off-by: siri-varma <siri.varma@outlook.com>

* Remove module

Signed-off-by: sirivarma <siri.varma@outlook.com>
Signed-off-by: siri-varma <siri.varma@outlook.com>

* Add Integration tests

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Update sdk-tests/src/test/java/io/dapr/it/testcontainers/DaprConversationIT.java

Co-authored-by: Cassie Coyle <cassie.i.coyle@gmail.com>
Signed-off-by: Siri Varma Vegiraju <siri.varma@outlook.com>
Signed-off-by: siri-varma <siri.varma@outlook.com>

* Fix things

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Address comments

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Import tag

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Address comments

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Make common config

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Address comments

Signed-off-by: siri-varma <siri.varma@outlook.com>

* fix constant

Signed-off-by: siri-varma <siri.varma@outlook.com>

* fix constant

Signed-off-by: siri-varma <siri.varma@outlook.com>

* fix constant

Signed-off-by: siri-varma <siri.varma@outlook.com>

* fix s

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Fix things

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Fix things

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Fix things

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Make common config

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Update README.md

Signed-off-by: Siri Varma Vegiraju <siri.varma@outlook.com>

* Update README.md

Signed-off-by: Siri Varma Vegiraju <siri.varma@outlook.com>

---------

Signed-off-by: Siri Varma Vegiraju <svegiraju@microsoft.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>
Signed-off-by: siri-varma <siri.varma@outlook.com>
Signed-off-by: Siri Varma Vegiraju <siri.varma@outlook.com>
Co-authored-by: Cassie Coyle <cassie.i.coyle@gmail.com>
Co-authored-by: Cassie Coyle <cassie@diagrid.io>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Add docs for usage of Jobs SDK (#1323)

* Add doc for jobs

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Add docs for Jobs

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Apply suggestions from code review

Co-authored-by: Cassie Coyle <cassie.i.coyle@gmail.com>
Signed-off-by: Siri Varma Vegiraju <siri.varma@outlook.com>

---------

Signed-off-by: siri-varma <siri.varma@outlook.com>
Signed-off-by: Siri Varma Vegiraju <siri.varma@outlook.com>
Co-authored-by: artur-ciocanu <artur.ciocanu@gmail.com>
Co-authored-by: Cassie Coyle <cassie.i.coyle@gmail.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Use dapr/durabletask-java (#1336)

* microsoft durabletask-java -> dapr durabletask-java

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* update another ref

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* 1.5.2 release

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* fix import order

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* Sdk new changes

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Refine workflows

Signed-off-by: siri-varma <siri.varma@outlook.com>

* add ;

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* rm try

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

---------

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>
Signed-off-by: siri-varma <siri.varma@outlook.com>
Co-authored-by: siri-varma <siri.varma@outlook.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Update master version to 1.16.0-SNAPSHOT

Signed-off-by: Dapr Bot <daprweb@microsoft.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Renaming and exposing connection details (#1341)

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>
Co-authored-by: Artur Ciocanu <ciocanu@adobe.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* [Master] Fix Vulnerabilities (#1354)

* update okio

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* rm unused dep

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

---------

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Feat Add TLS & mTLS support for gRPC with root CA and insecure mode (#1361)

* feat: Support for GRPC ssl

Signed-off-by: Javier Aliaga <javier@diagrid.io>

* add tests

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* fix CI

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* add back else if

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* channel cleanup

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* add root ca support

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* checkstyles

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* add insecure

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* fix checkstyles

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* use InsecureTrustManagerFactory

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* fix test

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

---------

Signed-off-by: Javier Aliaga <javier@diagrid.io>
Signed-off-by: Cassandra Coyle <cassie@diagrid.io>
Co-authored-by: Javier Aliaga <javier@diagrid.io>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Fix the issue with retries not happening correctly for Activities and Workflows (#1343)

* Add coverage for some properties (#1297)

Signed-off-by: sirivarma <siri.varma@outlook.com>

* Make the DAPR version being used consistent across all tests (#1299)

Signed-off-by: sirivarma <siri.varma@outlook.com>

* Separate Dapr constants from IT container constants (#1315)

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>
Co-authored-by: Artur Ciocanu <ciocanu@adobe.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Use Java Bean for connection details and add more tests (#1317)

* Use Java Bean for connection details and add more tests

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Simplify mock setup

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Adding even more tests for test coverage

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

---------

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>
Co-authored-by: Artur Ciocanu <ciocanu@adobe.com>
Co-authored-by: Cassie Coyle <cassie@diagrid.io>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Update CONTRIBUTING.md

Signed-off-by: Siri Varma Vegiraju <siri.varma@outlook.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Bump codecov/codecov-action from 5.4.0 to 5.4.2 (#1318)

Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 5.4.0 to 5.4.2.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v5.4.0...v5.4.2)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-version: 5.4.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Cassie Coyle <cassie@diagrid.io>
Co-authored-by: Dapr Bot <56698301+dapr-bot@users.noreply.github.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Fix URL building logic (#1320)

* Fix URL building logic

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Add test for query params

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Fix the assertion in the test

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Adjust the tests

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Remove uneeded changes from IT test

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Revert some unintended changes

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Simplify the testing a little bit

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Adjust the test to use ServerRequest

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Test removing things from method invoke controller

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Add query param encoding test

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Revert some unintended changes

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Some tiny styles

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

---------

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>
Co-authored-by: Artur Ciocanu <ciocanu@adobe.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Generate updated javadocs for 1.14.1

Signed-off-by: Dapr Bot <daprweb@microsoft.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Add Conversation AI to Java SDK (#1235)

* Conversation first commit

Signed-off-by: Siri Varma Vegiraju <svegiraju@microsoft.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>
Signed-off-by: siri-varma <siri.varma@outlook.com>

* Add unit tests

Signed-off-by: sirivarma <siri.varma@outlook.com>
Signed-off-by: siri-varma <siri.varma@outlook.com>

* change ai to conv

Signed-off-by: sirivarma <siri.varma@outlook.com>
Signed-off-by: siri-varma <siri.varma@outlook.com>

* Move to single module

Signed-off-by: sirivarma <siri.varma@outlook.com>
Signed-off-by: siri-varma <siri.varma@outlook.com>

* Remove module

Signed-off-by: sirivarma <siri.varma@outlook.com>
Signed-off-by: siri-varma <siri.varma@outlook.com>

* Add Integration tests

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Update sdk-tests/src/test/java/io/dapr/it/testcontainers/DaprConversationIT.java

Co-authored-by: Cassie Coyle <cassie.i.coyle@gmail.com>
Signed-off-by: Siri Varma Vegiraju <siri.varma@outlook.com>
Signed-off-by: siri-varma <siri.varma@outlook.com>

* Fix things

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Address comments

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Import tag

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Address comments

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Make common config

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Address comments

Signed-off-by: siri-varma <siri.varma@outlook.com>

* fix constant

Signed-off-by: siri-varma <siri.varma@outlook.com>

* fix constant

Signed-off-by: siri-varma <siri.varma@outlook.com>

* fix constant

Signed-off-by: siri-varma <siri.varma@outlook.com>

* fix s

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Fix things

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Fix things

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Fix things

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Make common config

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Update README.md

Signed-off-by: Siri Varma Vegiraju <siri.varma@outlook.com>

* Update README.md

Signed-off-by: Siri Varma Vegiraju <siri.varma@outlook.com>

---------

Signed-off-by: Siri Varma Vegiraju <svegiraju@microsoft.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>
Signed-off-by: siri-varma <siri.varma@outlook.com>
Signed-off-by: Siri Varma Vegiraju <siri.varma@outlook.com>
Co-authored-by: Cassie Coyle <cassie.i.coyle@gmail.com>
Co-authored-by: Cassie Coyle <cassie@diagrid.io>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Add docs for usage of Jobs SDK (#1323)

* Add doc for jobs

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Add docs for Jobs

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Apply suggestions from code review

Co-authored-by: Cassie Coyle <cassie.i.coyle@gmail.com>
Signed-off-by: Siri Varma Vegiraju <siri.varma@outlook.com>

---------

Signed-off-by: siri-varma <siri.varma@outlook.com>
Signed-off-by: Siri Varma Vegiraju <siri.varma@outlook.com>
Co-authored-by: artur-ciocanu <artur.ciocanu@gmail.com>
Co-authored-by: Cassie Coyle <cassie.i.coyle@gmail.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Use dapr/durabletask-java (#1336)

* microsoft durabletask-java -> dapr durabletask-java

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* update another ref

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* 1.5.2 release

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* fix import order

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* Sdk new changes

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Refine workflows

Signed-off-by: siri-varma <siri.varma@outlook.com>

* add ;

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* rm try

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

---------

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>
Signed-off-by: siri-varma <siri.varma@outlook.com>
Co-authored-by: siri-varma <siri.varma@outlook.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Update master version to 1.16.0-SNAPSHOT

Signed-off-by: Dapr Bot <daprweb@microsoft.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Fix NPE

Signed-off-by: siri-varma <siri.varma@outlook.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Fix NPE

Signed-off-by: siri-varma <siri.varma@outlook.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Fix NPE

Signed-off-by: siri-varma <siri.varma@outlook.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Fix NPE

Signed-off-by: siri-varma <siri.varma@outlook.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Fix NPE

Signed-off-by: siri-varma <siri.varma@outlook.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Fix NPE

Signed-off-by: siri-varma <siri.varma@outlook.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Fix things

Signed-off-by: siri-varma <siri.varma@outlook.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Renaming and exposing connection details (#1341)

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>
Co-authored-by: Artur Ciocanu <ciocanu@adobe.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* [Master] Fix Vulnerabilities (#1354)

* update okio

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* rm unused dep

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

---------

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Feat Add TLS & mTLS support for gRPC with root CA and insecure mode (#1361)

* feat: Support for GRPC ssl

Signed-off-by: Javier Aliaga <javier@diagrid.io>

* add tests

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* fix CI

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* add back else if

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* channel cleanup

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* add root ca support

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* checkstyles

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* add insecure

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* fix checkstyles

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* use InsecureTrustManagerFactory

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* fix test

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

---------

Signed-off-by: Javier Aliaga <javier@diagrid.io>
Signed-off-by: Cassandra Coyle <cassie@diagrid.io>
Co-authored-by: Javier Aliaga <javier@diagrid.io>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Address comments

Signed-off-by: siri-varma <siri.varma@outlook.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Fix things

Signed-off-by: siri-varma <siri.varma@outlook.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Fix things

Signed-off-by: siri-varma <siri.varma@outlook.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

---------

Signed-off-by: sirivarma <siri.varma@outlook.com>
Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>
Signed-off-by: Siri Varma Vegiraju <siri.varma@outlook.com>
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Dapr Bot <daprweb@microsoft.com>
Signed-off-by: Siri Varma Vegiraju <svegiraju@microsoft.com>
Signed-off-by: siri-varma <siri.varma@outlook.com>
Signed-off-by: Cassandra Coyle <cassie@diagrid.io>
Signed-off-by: Javier Aliaga <javier@diagrid.io>
Co-authored-by: Matheus Cruz <56329339+mcruzdev@users.noreply.github.com>
Co-authored-by: artur-ciocanu <artur.ciocanu@gmail.com>
Co-authored-by: Artur Ciocanu <ciocanu@adobe.com>
Co-authored-by: Cassie Coyle <cassie@diagrid.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Dapr Bot <56698301+dapr-bot@users.noreply.github.com>
Co-authored-by: Dapr Bot <daprweb@microsoft.com>
Co-authored-by: Cassie Coyle <cassie.i.coyle@gmail.com>
Co-authored-by: Javier Aliaga <javier@diagrid.io>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* 1.5.4 (#1375)

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Bump codecov/codecov-action from 5.4.2 to 5.4.3 (#1379)

Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 5.4.2 to 5.4.3.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v5.4.2...v5.4.3)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-version: 5.4.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Bump fossas/fossa-action from 1.6.0 to 1.7.0 (#1380)

Bumps [fossas/fossa-action](https://github.com/fossas/fossa-action) from 1.6.0 to 1.7.0.
- [Release notes](https://github.com/fossas/fossa-action/releases)
- [Commits](https://github.com/fossas/fossa-action/compare/v1.6.0...v1.7.0)

---
updated-dependencies:
- dependency-name: fossas/fossa-action
  dependency-version: 1.7.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Cassie Coyle <cassie.i.coyle@gmail.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Fix component spec parsing (#1370)

* Fix component spec parsing

Signed-off-by: Deepak <sdeepaksharma15@gmail.com>

* Fix component spec parsing

Signed-off-by: Deepak <sdeepaksharma15@gmail.com>

* Fix component spec metadata parsing

Signed-off-by: Deepak <sdeepaksharma15@gmail.com>

* fix checkstyle-error

Signed-off-by: Deepak <sdeepaksharma15@gmail.com>

---------

Signed-off-by: Deepak <sdeepaksharma15@gmail.com>
Co-authored-by: Cassie Coyle <cassie.i.coyle@gmail.com>
Co-authored-by: artur-ciocanu <artur.ciocanu@gmail.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* chore: Add grpc keepalives (#1382)

* chore: Add grpc keepalives

Signed-off-by: Javier Aliaga <javier@diagrid.io>

* chore: Make grpc keepalive configurable

Signed-off-by: Javier Aliaga <javier@diagrid.io>

* chore: Fix review comments

Signed-off-by: Javier Aliaga <javier@diagrid.io>

* chore: Missing keepalive config for GRPC TLS INSECURE

Signed-off-by: Javier Aliaga <javier@diagrid.io>

* chore: Add test

Signed-off-by: Javier Aliaga <javier@diagrid.io>

* fix: Comment typo

Signed-off-by: Javier Aliaga <javier@diagrid.io>

---------

Signed-off-by: Javier Aliaga <javier@diagrid.io>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Fix : Typo in code comments (#1381)

* Fix Typo in Comments

Signed-off-by: Deepak <sdeepaksharma15@gmail.com>

* Update review comments

Signed-off-by: Deepak <sdeepaksharma15@gmail.com>

---------

Signed-off-by: Deepak <sdeepaksharma15@gmail.com>
Co-authored-by: artur-ciocanu <artur.ciocanu@gmail.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Spring boot workflow patterns examples with mechanical markdown and tests (#1377)

* Feat Add TLS & mTLS support for gRPC with root CA and insecure mode (#1361)

* feat: Support for GRPC ssl

Signed-off-by: Javier Aliaga <javier@diagrid.io>

* add tests

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* fix CI

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* add back else if

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* channel cleanup

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* add root ca support

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* checkstyles

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* add insecure

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* fix checkstyles

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* use InsecureTrustManagerFactory

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* fix test

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

---------

Signed-off-by: Javier Aliaga <javier@diagrid.io>
Signed-off-by: Cassandra Coyle <cassie@diagrid.io>
Co-authored-by: Javier Aliaga <javier@diagrid.io>
Signed-off-by: salaboy <Salaboy@gmail.com>

* spring boot workflow patterns initial version

Signed-off-by: salaboy <Salaboy@gmail.com>

* adding README for workflows

Signed-off-by: salaboy <Salaboy@gmail.com>

* adding child example

Signed-off-by: salaboy <Salaboy@gmail.com>

* updating examples to work with markdown tests

Signed-off-by: salaboy <Salaboy@gmail.com>

* running mechanical markdown for workflow examples

Signed-off-by: salaboy <Salaboy@gmail.com>

* Fix the issue with retries not happening correctly for Activities and Workflows (#1343)

* Add coverage for some properties (#1297)

Signed-off-by: sirivarma <siri.varma@outlook.com>

* Make the DAPR version being used consistent across all tests (#1299)

Signed-off-by: sirivarma <siri.varma@outlook.com>

* Separate Dapr constants from IT container constants (#1315)

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>
Co-authored-by: Artur Ciocanu <ciocanu@adobe.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Use Java Bean for connection details and add more tests (#1317)

* Use Java Bean for connection details and add more tests

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Simplify mock setup

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Adding even more tests for test coverage

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

---------

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>
Co-authored-by: Artur Ciocanu <ciocanu@adobe.com>
Co-authored-by: Cassie Coyle <cassie@diagrid.io>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Update CONTRIBUTING.md

Signed-off-by: Siri Varma Vegiraju <siri.varma@outlook.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Bump codecov/codecov-action from 5.4.0 to 5.4.2 (#1318)

Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 5.4.0 to 5.4.2.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v5.4.0...v5.4.2)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-version: 5.4.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Cassie Coyle <cassie@diagrid.io>
Co-authored-by: Dapr Bot <56698301+dapr-bot@users.noreply.github.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Fix URL building logic (#1320)

* Fix URL building logic

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Add test for query params

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Fix the assertion in the test

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Adjust the tests

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Remove uneeded changes from IT test

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Revert some unintended changes

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Simplify the testing a little bit

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Adjust the test to use ServerRequest

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Test removing things from method invoke controller

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Add query param encoding test

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Revert some unintended changes

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Some tiny styles

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

---------

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>
Co-authored-by: Artur Ciocanu <ciocanu@adobe.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Generate updated javadocs for 1.14.1

Signed-off-by: Dapr Bot <daprweb@microsoft.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Add Conversation AI to Java SDK (#1235)

* Conversation first commit

Signed-off-by: Siri Varma Vegiraju <svegiraju@microsoft.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>
Signed-off-by: siri-varma <siri.varma@outlook.com>

* Add unit tests

Signed-off-by: sirivarma <siri.varma@outlook.com>
Signed-off-by: siri-varma <siri.varma@outlook.com>

* change ai to conv

Signed-off-by: sirivarma <siri.varma@outlook.com>
Signed-off-by: siri-varma <siri.varma@outlook.com>

* Move to single module

Signed-off-by: sirivarma <siri.varma@outlook.com>
Signed-off-by: siri-varma <siri.varma@outlook.com>

* Remove module

Signed-off-by: sirivarma <siri.varma@outlook.com>
Signed-off-by: siri-varma <siri.varma@outlook.com>

* Add Integration tests

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Update sdk-tests/src/test/java/io/dapr/it/testcontainers/DaprConversationIT.java

Co-authored-by: Cassie Coyle <cassie.i.coyle@gmail.com>
Signed-off-by: Siri Varma Vegiraju <siri.varma@outlook.com>
Signed-off-by: siri-varma <siri.varma@outlook.com>

* Fix things

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Address comments

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Import tag

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Address comments

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Make common config

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Address comments

Signed-off-by: siri-varma <siri.varma@outlook.com>

* fix constant

Signed-off-by: siri-varma <siri.varma@outlook.com>

* fix constant

Signed-off-by: siri-varma <siri.varma@outlook.com>

* fix constant

Signed-off-by: siri-varma <siri.varma@outlook.com>

* fix s

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Fix things

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Fix things

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Fix things

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Make common config

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Update README.md

Signed-off-by: Siri Varma Vegiraju <siri.varma@outlook.com>

* Update README.md

Signed-off-by: Siri Varma Vegiraju <siri.varma@outlook.com>

---------

Signed-off-by: Siri Varma Vegiraju <svegiraju@microsoft.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>
Signed-off-by: siri-varma <siri.varma@outlook.com>
Signed-off-by: Siri Varma Vegiraju <siri.varma@outlook.com>
Co-authored-by: Cassie Coyle <cassie.i.coyle@gmail.com>
Co-authored-by: Cassie Coyle <cassie@diagrid.io>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Add docs for usage of Jobs SDK (#1323)

* Add doc for jobs

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Add docs for Jobs

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Apply suggestions from code review

Co-authored-by: Cassie Coyle <cassie.i.coyle@gmail.com>
Signed-off-by: Siri Varma Vegiraju <siri.varma@outlook.com>

---------

Signed-off-by: siri-varma <siri.varma@outlook.com>
Signed-off-by: Siri Varma Vegiraju <siri.varma@outlook.com>
Co-authored-by: artur-ciocanu <artur.ciocanu@gmail.com>
Co-authored-by: Cassie Coyle <cassie.i.coyle@gmail.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Use dapr/durabletask-java (#1336)

* microsoft durabletask-java -> dapr durabletask-java

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* update another ref

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* 1.5.2 release

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* fix import order

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* Sdk new changes

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Refine workflows

Signed-off-by: siri-varma <siri.varma@outlook.com>

* add ;

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* rm try

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

---------

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>
Signed-off-by: siri-varma <siri.varma@outlook.com>
Co-authored-by: siri-varma <siri.varma@outlook.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Update master version to 1.16.0-SNAPSHOT

Signed-off-by: Dapr Bot <daprweb@microsoft.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Fix NPE

Signed-off-by: siri-varma <siri.varma@outlook.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Fix NPE

Signed-off-by: siri-varma <siri.varma@outlook.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Fix NPE

Signed-off-by: siri-varma <siri.varma@outlook.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Fix NPE

Signed-off-by: siri-varma <siri.varma@outlook.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Fix NPE

Signed-off-by: siri-varma <siri.varma@outlook.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Fix NPE

Signed-off-by: siri-varma <siri.varma@outlook.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Fix things

Signed-off-by: siri-varma <siri.varma@outlook.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Renaming and exposing connection details (#1341)

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>
Co-authored-by: Artur Ciocanu <ciocanu@adobe.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* [Master] Fix Vulnerabilities (#1354)

* update okio

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* rm unused dep

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

---------

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Feat Add TLS & mTLS support for gRPC with root CA and insecure mode (#1361)

* feat: Support for GRPC ssl

Signed-off-by: Javier Aliaga <javier@diagrid.io>

* add tests

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* fix CI

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* add back else if

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* channel cleanup

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* add root ca support

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* checkstyles

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* add insecure

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* fix checkstyles

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* use InsecureTrustManagerFactory

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* fix test

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

---------

Signed-off-by: Javier Aliaga <javier@diagrid.io>
Signed-off-by: Cassandra Coyle <cassie@diagrid.io>
Co-authored-by: Javier Aliaga <javier@diagrid.io>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Address comments

Signed-off-by: siri-varma <siri.varma@outlook.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Fix things

Signed-off-by: siri-varma <siri.varma@outlook.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Fix things

Signed-off-by: siri-varma <siri.varma@outlook.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

---------

Signed-off-by: sirivarma <siri.varma@outlook.com>
Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>
Signed-off-by: Siri Varma Vegiraju <siri.varma@outlook.com>
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Dapr Bot <daprweb@microsoft.com>
Signed-off-by: Siri Varma Vegiraju <svegiraju@microsoft.com>
Signed-off-by: siri-varma <siri.varma@outlook.com>
Signed-off-by: Cassandra Coyle <cassie@diagrid.io>
Signed-off-by: Javier Aliaga <javier@diagrid.io>
Co-authored-by: Matheus Cruz <56329339+mcruzdev@users.noreply.github.com>
Co-authored-by: artur-ciocanu <artur.ciocanu@gmail.com>
Co-authored-by: Artur Ciocanu <ciocanu@adobe.com>
Co-authored-by: Cassie Coyle <cassie@diagrid.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Dapr Bot <56698301+dapr-bot@users.noreply.github.com>
Co-authored-by: Dapr Bot <daprweb@microsoft.com>
Co-authored-by: Cassie Coyle <cassie.i.coyle@gmail.com>
Co-authored-by: Javier Aliaga <javier@diagrid.io>
Signed-off-by: salaboy <Salaboy@gmail.com>

* 1.5.4 (#1375)

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>
Signed-off-by: salaboy <Salaboy@gmail.com>

* fixing order Id correlation

Signed-off-by: salaboy <Salaboy@gmail.com>

* fixing waiting time for tests to run

Signed-off-by: salaboy <Salaboy@gmail.com>

* fixing app name

Signed-off-by: salaboy <Salaboy@gmail.com>

* adding app name and removing log lines

Signed-off-by: salaboy <Salaboy@gmail.com>

* Bump codecov/codecov-action from 5.4.2 to 5.4.3 (#1379)

Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 5.4.2 to 5.4.3.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v5.4.2...v5.4.3)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-version: 5.4.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Signed-off-by: salaboy <Salaboy@gmail.com>

* Bump fossas/fossa-action from 1.6.0 to 1.7.0 (#1380)

Bumps [fossas/fossa-action](https://github.com/fossas/fossa-action) from 1.6.0 to 1.7.0.
- [Release notes](https://github.com/fossas/fossa-action/releases)
- [Commits](https://github.com/fossas/fossa-action/compare/v1.6.0...v1.7.0)

---
updated-dependencies:
- dependency-name: fossas/fossa-action
  dependency-version: 1.7.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Cassie Coyle <cassie.i.coyle@gmail.com>
Signed-off-by: salaboy <Salaboy@gmail.com>

* Fix component spec parsing (#1370)

* Fix component spec parsing

Signed-off-by: Deepak <sdeepaksharma15@gmail.com>

* Fix component spec parsing

Signed-off-by: Deepak <sdeepaksharma15@gmail.com>

* Fix component spec metadata parsing

Signed-off-by: Deepak <sdeepaksharma15@gmail.com>

* fix checkstyle-error

Signed-off-by: Deepak <sdeepaksharma15@gmail.com>

---------

Signed-off-by: Deepak <sdeepaksharma15@gmail.com>
Co-authored-by: Cassie Coyle <cassie.i.coyle@gmail.com>
Co-authored-by: artur-ciocanu <artur.ciocanu@gmail.com>
Signed-off-by: salaboy <Salaboy@gmail.com>

* Update spring-boot-examples/workflows/README.md

Co-authored-by: Cassie Coyle <cassie.i.coyle@gmail.com>
Signed-off-by: salaboy <Salaboy@gmail.com>

* fixing comments

Signed-off-by: salaboy <Salaboy@gmail.com>

* Update body.json

Signed-off-by: artur-ciocanu <artur.ciocanu@gmail.com>
Signed-off-by: salaboy <Salaboy@gmail.com>

* Update FanOutInWorkflow.java

Signed-off-by: artur-ciocanu <artur.ciocanu@gmail.com>
Signed-off-by: salaboy <Salaboy@gmail.com>

* clean up logs for multiple executions, for standalone mode

Signed-off-by: salaboy <Salaboy@gmail.com>

* Update application.properties

Signed-off-by: artur-ciocanu <artur.ciocanu@gmail.com>

---------

Signed-off-by: Javier Aliaga <javier@diagrid.io>
Signed-off-by: Cassandra Coyle <cassie@diagrid.io>
Signed-off-by: salaboy <Salaboy@gmail.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>
Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>
Signed-off-by: Siri Varma Vegiraju <siri.varma@outlook.com>
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Dapr Bot <daprweb@microsoft.com>
Signed-off-by: Siri Varma Vegiraju <svegiraju@microsoft.com>
Signed-off-by: siri-varma <siri.varma@outlook.com>
Signed-off-by: Deepak <sdeepaksharma15@gmail.com>
Signed-off-by: artur-ciocanu <artur.ciocanu@gmail.com>
Co-authored-by: Cassie Coyle <cassie.i.coyle@gmail.com>
Co-authored-by: Javier Aliaga <javier@diagrid.io>
Co-authored-by: Siri Varma Vegiraju <siri.varma@outlook.com>
Co-authored-by: Matheus Cruz <56329339+mcruzdev@users.noreply.github.com>
Co-authored-by: artur-ciocanu <artur.ciocanu@gmail.com>
Co-authored-by: Artur Ciocanu <ciocanu@adobe.com>
Co-authored-by: Cassie Coyle <cassie@diagrid.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Dapr Bot <56698301+dapr-bot@users.noreply.github.com>
Co-authored-by: Dapr Bot <daprweb@microsoft.com>
Co-authored-by: iddeepak <87892182+iddeepak@users.noreply.github.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* System Properties + Env Var Docs (#1384)

* add properties file to docs and align system properties to env var name convention with . as _

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* reset env var to what it was

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

---------

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>
Co-authored-by: artur-ciocanu <artur.ciocanu@gmail.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Updating docs to have spring boot 3.x banner and not hardcoded deps (#1366)

* updating docs to have spring boot 3.x banner and not hardcoded deps

Signed-off-by: salaboy <Salaboy@gmail.com>

* Update _index.md

Signed-off-by: salaboy <Salaboy@gmail.com>

* Update _index.md

Adding links to discord and github issues

Signed-off-by: salaboy <Salaboy@gmail.com>

---------

Signed-off-by: salaboy <Salaboy@gmail.com>
Co-authored-by: artur-ciocanu <artur.ciocanu@gmail.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Cleaup Test Dependencies (#1332)

* Update CONTRIBUTING.md

Signed-off-by: Siri Varma Vegiraju <siri.varma@outlook.com>

* Fix things

Signed-off-by: sirivarma <siri.varma@outlook.com>

* Fix things?

Signed-off-by: sirivarma <siri.varma@outlook.com>

* Fix logback version

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Fix logback version

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Add pom

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Add pom

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Add properties

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Added test scope

Signed-off-by: siri-varma <siri.varma@outlook.com>

* MArk as test

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Update pom.xml

Signed-off-by: Siri Varma Vegiraju <siri.varma@outlook.com>

* Update pom.xml

Signed-off-by: Siri Varma Vegiraju <siri.varma@outlook.com>

---------

Signed-off-by: Siri Varma Vegiraju <siri.varma@outlook.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>
Signed-off-by: siri-varma <siri.varma@outlook.com>
Co-authored-by: artur-ciocanu <artur.ciocanu@gmail.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* chore: New task execution task id test (#1352)

* chore: New task execution task id test

test how taskExecutionTaskId can be used for idempotency

Signed-off-by: Javier Aliaga <javier@diagrid.io>

* chore: Clean up not used files

Signed-off-by: Javier Aliaga <javier@diagrid.io>

* docs: Task execution keys

Signed-off-by: Javier Aliaga <javier@diagrid.io>

* test: Modify unit tests

Signed-off-by: Javier Aliaga <javier@diagrid.io>

* Remove new lines

Signed-off-by: artur-ciocanu <artur.ciocanu@gmail.com>

---------

Signed-off-by: Javier Aliaga <javier@diagrid.io>
Signed-off-by: artur-ciocanu <artur.ciocanu@gmail.com>
Co-authored-by: Cassie Coyle <cassie.i.coyle@gmail.com>
Co-authored-by: artur-ciocanu <artur.ciocanu@gmail.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Revert "chore: New task execution task id test (#1352)" (#1389)

This reverts commit 949584f69f.

Signed-off-by: Javier Aliaga <javier@diagrid.io>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* 1.5.5 (#1390)

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Add Documentation for Conversation AI SDK (#1387)

Signed-off-by: sirivarma <siri.varma@outlook.com>

* Cleanup Spring Dependencies (#1334)

* Update CONTRIBUTING.md

Signed-off-by: Siri Varma Vegiraju <siri.varma@outlook.com>

* Fix spring

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Add context

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Phase 1

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Fix things

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Fix things

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Fix spring

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Add context

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Phase 1

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Fix things

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Fix things

Signed-off-by: siri-varma <siri.varma@outlook.com>

* move version

Signed-off-by: sirivarma <siri.varma@outlook.com>

* Fix pom

Signed-off-by: sirivarma <siri.varma@outlook.com>

* change version

Signed-off-by: sirivarma <siri.varma@outlook.com>

* remove unused

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Address comments

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Fix test

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Fix test

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Fix things

Signed-off-by: sirivarma <siri.varma@outlook.com>

---------

Signed-off-by: Siri Varma Vegiraju <siri.varma@outlook.com>
Signed-off-by: siri-varma <siri.varma@outlook.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>
Co-authored-by: artur-ciocanu <artur.ciocanu@gmail.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Bump org.springframework:spring-context in /dapr-spring (#1394)

Bumps [org.springframework:spring-context](https://github.com/spring-projects/spring-framework) from 6.1.8 to 6.1.14.
- [Release notes](https://github.com/spring-projects/spring-framework/releases)
- [Commits](https://github.com/spring-projects/spring-framework/compare/v6.1.8...v6.1.14)

---
updated-dependencies:
- dependency-name: org.springframework:spring-context
  dependency-version: 6.1.14
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Compensation example for Workflows (#1333)

* add basic compensation example for wf

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* update commands to run + wf id

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* update readme + add mechanical markdown

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* fix import

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* fix mechanical markdown + add how to test it locally

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* move compensation example readme to workflows readme

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* Update BookCarActivity.java

Signed-off-by: artur-ciocanu <artur.ciocanu@gmail.com>

* Update BookFlightActivity.java

Signed-off-by: artur-ciocanu <artur.ciocanu@gmail.com>

* Update BookHotelActivity.java

Signed-off-by: artur-ciocanu <artur.ciocanu@gmail.com>

* Update BookTripClient.java

Signed-off-by: artur-ciocanu <artur.ciocanu@gmail.com>

* Update BookTripWorker.java

Signed-off-by: artur-ciocanu <artur.ciocanu@gmail.com>

* Update BookTripWorkflow.java

Signed-off-by: artur-ciocanu <artur.ciocanu@gmail.com>

* Update CancelCarActivity.java

Signed-off-by: artur-ciocanu <artur.ciocanu@gmail.com>

* Update CancelFlightActivity.java

Signed-off-by: artur-ciocanu <artur.ciocanu@gmail.com>

* Update CancelHotelActivity.java

Signed-off-by: artur-ciocanu <artur.ciocanu@gmail.com>

* add retry IT tests and catch TaskFailedException

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* add test for no compensation if successful and assert attempts

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* update mechanical markdown

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* add back pubsub... but this should be removed long term

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* try adding waitforsidecar

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* rm tests from examples pr

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* reset unintended changes

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

---------

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>
Signed-off-by: artur-ciocanu <artur.ciocanu@gmail.com>
Co-authored-by: artur-ciocanu <artur.ciocanu@gmail.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Adding remote endpoint request from inside activity with retry (#1388)

* adding remote endpoint request from inside activity with retry

Signed-off-by: salaboy <Salaboy@gmail.com>

* adding retry with Microcks payloads

Signed-off-by: salaboy <Salaboy@gmail.com>

* fixing review comments

Signed-off-by: salaboy <Salaboy@gmail.com>

* chore: New task execution task id test (#1352)

* chore: New task execution task id test

test how taskExecutionTaskId can be used for idempotency

Signed-off-by: Javier Aliaga <javier@diagrid.io>

* chore: Clean up not used files

Signed-off-by: Javier Aliaga <javier@diagrid.io>

* docs: Task execution keys

Signed-off-by: Javier Aliaga <javier@diagrid.io>

* test: Modify unit tests

Signed-off-by: Javier Aliaga <javier@diagrid.io>

* Remove new lines

Signed-off-by: artur-ciocanu <artur.ciocanu@gmail.com>

---------

Signed-off-by: Javier Aliaga <javier@diagrid.io>
Signed-off-by: artur-ciocanu <artur.ciocanu@gmail.com>
Co-authored-by: Cassie Coyle <cassie.i.coyle@gmail.com>
Co-authored-by: artur-ciocanu <artur.ciocanu@gmail.com>
Signed-off-by: salaboy <Salaboy@gmail.com>

* Revert "chore: New task execution task id test (#1352)" (#1389)

This reverts commit 949584f69f.

Signed-off-by: Javier Aliaga <javier@diagrid.io>
Signed-off-by: salaboy <Salaboy@gmail.com>

* 1.5.5 (#1390)

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>
Signed-off-by: salaboy <Salaboy@gmail.com>

* Add Documentation for Conversation AI SDK (#1387)

Signed-off-by: salaboy <Salaboy@gmail.com>

* Cleanup Spring Dependencies (#1334)

* Update CONTRIBUTING.md

Signed-off-by: Siri Varma Vegiraju <siri.varma@outlook.com>

* Fix spring

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Add context

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Phase 1

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Fix things

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Fix things

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Fix spring

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Add context

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Phase 1

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Fix things

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Fix things

Signed-off-by: siri-varma <siri.varma@outlook.com>

* move version

Signed-off-by: sirivarma <siri.varma@outlook.com>

* Fix pom

Signed-off-by: sirivarma <siri.varma@outlook.com>

* change version

Signed-off-by: sirivarma <siri.varma@outlook.com>

* remove unused

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Address comments

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Fix test

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Fix test

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Fix things

Signed-off-by: sirivarma <siri.varma@outlook.com>

---------

Signed-off-by: Siri Varma Vegiraju <siri.varma@outlook.com>
Signed-off-by: siri-varma <siri.varma@outlook.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>
Co-authored-by: artur-ciocanu <artur.ciocanu@gmail.com>
Signed-off-by: salaboy <Salaboy@gmail.com>

* network is needed

Signed-off-by: salaboy <Salaboy@gmail.com>

---------

Signed-off-by: salaboy <Salaboy@gmail.com>
Signed-off-by: Javier Aliaga <javier@diagrid.io>
Signed-off-by: artur-ciocanu <artur.ciocanu@gmail.com>
Signed-off-by: Cassandra Coyle <cassie@diagrid.io>
Signed-off-by: Siri Varma Vegiraju <siri.varma@outlook.com>
Signed-off-by: siri-varma <siri.varma@outlook.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>
Co-authored-by: Javier Aliaga <javier@diagrid.io>
Co-authored-by: Cassie Coyle <cassie.i.coyle@gmail.com>
Co-authored-by: artur-ciocanu <artur.ciocanu@gmail.com>
Co-authored-by: Siri Varma Vegiraju <siri.varma@outlook.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Bump org.springframework:spring-context in /dapr-spring (#1398)

Bumps [org.springframework:spring-context](https://github.com/spring-projects/spring-framework) from 6.1.14 to 6.1.20.
- [Release notes](https://github.com/spring-projects/spring-framework/releases)
- [Commits](https://github.com/spring-projects/spring-framework/compare/v6.1.14...v6.1.20)

---
updated-dependencies:
- dependency-name: org.springframework:spring-context
  dependency-version: 6.1.20
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Grouping IT tests per API surface (#1401)

* Grouping IT tests per API surface

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Fix build

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

---------

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>
Co-authored-by: Artur Ciocanu <ciocanu@adobe.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Ensure OTEL version from examples aligns with SDK and ITs (#1403)

Signed-off-by: sirivarma <siri.varma@outlook.com>

* chore: Support configuration for max grpc inbound message (#1411)

Signed-off-by: Javier Aliaga <javier@diagrid.io>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Adding Support for Suspend / Resume Workflows (#1405)

* adding IT test

Signed-off-by: salaboy <Salaboy@gmail.com>

* adding initial version of suspend/resume example

Signed-off-by: salaboy <Salaboy@gmail.com>

* updating README

Signed-off-by: salaboy <Salaboy@gmail.com>

* Update README.md

Signed-off-by: salaboy <Salaboy@gmail.com>

* following Javi's suggestion

Signed-off-by: salaboy <Salaboy@gmail.com>

* fixing wrong year in headers

Signed-off-by: salaboy <Salaboy@gmail.com>

* fixing paths in one more README.md file

Signed-off-by: salaboy <Salaboy@gmail.com>

* adding output validation

Signed-off-by: salaboy <Salaboy@gmail.com>

* adding missing port

Signed-off-by: salaboy <Salaboy@gmail.com>

* fixing check conditions

Signed-off-by: salaboy <Salaboy@gmail.com>

---------

Signed-off-by: salaboy <Salaboy@gmail.com>
Co-authored-by: Cassie Coyle <cassie.i.coyle@gmail.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Add retry handler support (#1412)

* Add retry handler support

Signed-off-by: Mason <theforbiddenai@gmail.com>

* Wrap DurableTask objects

Signed-off-by: Mason <theforbiddenai@gmail.com>

* Rename method

Signed-off-by: Mason <theforbiddenai@gmail.com>

* Add isNonRetriable field to WorkflowTaskFailureDetails

Signed-off-by: Mason <theforbiddenai@gmail.com>

* Add unit test

Signed-off-by: Mason <theforbiddenai@gmail.com>

* Removed duplicate WorkflowFailureDetails class

Signed-off-by: Mason <theforbiddenai@gmail.com>

* Removed unneeded when statements in retry policy unit test

Signed-off-by: Mason <theforbiddenai@gmail.com>

* Add unit test to test both RetryPolicy and RetryHandler

Signed-off-by: Mason <theforbiddenai@gmail.com>

* Create toRetryPolicy method

Signed-off-by: Mason <theforbiddenai@gmail.com>

---------

Signed-off-by: Mason <theforbiddenai@gmail.com>
Co-authored-by: Siri Varma Vegiraju <siri.varma@outlook.com>
Co-authored-by: Cassie Coyle <cassie.i.coyle@gmail.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Pull out createTimer logic (#1419)

* pull out logical changes from @salaboy's PR to release it

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

* add missing import

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>

---------

Signed-off-by: Cassandra Coyle <cassie@diagrid.io>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Make sure there no multiple empty lines and every file ends with a new line (#1417)

Signed-off-by: sirivarma <siri.varma@outlook.com>

* Automated Header Checks (#1416)

Signed-off-by: sirivarma <siri.varma@outlook.com>

* Bump org.springframework:spring-web in /dapr-spring (#1424)

Bumps [org.springframework:spring-web](https://github.com/spring-projects/spring-framework) from 6.1.20 to 6.1.21.
- [Release notes](https://github.com/spring-projects/spring-framework/releases)
- [Commits](https://github.com/spring-projects/spring-framework/compare/v6.1.20...v6.1.21)

---
updated-dependencies:
- dependency-name: org.springframework:spring-web
  dependency-version: 6.1.21
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Aligning Spring Boot and SpringFramework versions (#1427)

* aligning versions

Signed-off-by: salaboy <Salaboy@gmail.com>

* letting SB to manage the logback version, so it is aligned

Signed-off-by: salaboy <Salaboy@gmail.com>

* removing dep from sdk-tests

Signed-off-by: salaboy <Salaboy@gmail.com>

* removing logback

Signed-off-by: salaboy <Salaboy@gmail.com>

---------

Signed-off-by: salaboy <Salaboy@gmail.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Update pom.xml to have testcontainers 1.21.3 (#1436)

Signed-off-by: salaboy <Salaboy@gmail.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Adding examples to Spring Boot (duration, zoneddatetime and suspend/resume) (#1413)

* implementing createtime with zoneddatetime

Signed-off-by: salaboy <Salaboy@gmail.com>

* adding duration and zoneddatetime examples

Signed-off-by: salaboy <Salaboy@gmail.com>

* using external event wf to test suspend resume

Signed-off-by: salaboy <Salaboy@gmail.com>

---------

Signed-off-by: salaboy <Salaboy@gmail.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Bump org.apache.commons:commons-lang3 from 3.9 to 3.18.0 (#1446)

Bumps org.apache.commons:commons-lang3 from 3.9 to 3.18.0.

---
updated-dependencies:
- dependency-name: org.apache.commons:commons-lang3
  dependency-version: 3.18.0
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: artur-ciocanu <artur.ciocanu@gmail.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Update dapr docs for Hugo upgrade (#1443)

Signed-off-by: Marc Duiker <marcduiker@users.noreply.github.com>
Co-authored-by: Cassie Coyle <cassie.i.coyle@gmail.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Adds note about workflow start time (#1444)

Signed-off-by: joshvanl <me@joshvanl.dev>
Co-authored-by: Dapr Bot <56698301+dapr-bot@users.noreply.github.com>
Co-authored-by: artur-ciocanu <artur.ciocanu@gmail.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Migrate PubSub removing flaky test (#1407)

* Migrate PubSub removing flaky test

Signed-off-by: Matheus Cruz <matheuscruz.dev@gmail.com>

* Adjust assertion

Signed-off-by: Matheus Cruz <matheuscruz.dev@gmail.com>

* Change assert

Signed-off-by: Matheus Cruz <matheuscruz.dev@gmail.com>

* Apply pull request suggestions

Signed-off-by: Matheus Cruz <matheuscruz.dev@gmail.com>

* Use custom ObjectSerializer

Signed-off-by: Matheus Cruz <matheuscruz.dev@gmail.com>

---------

Signed-off-by: Matheus Cruz <matheuscruz.dev@gmail.com>
Co-authored-by: artur-ciocanu <artur.ciocanu@gmail.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* supporting spring boot property for API TOKEN on workflow interceptor (#1452)

Signed-off-by: salaboy <Salaboy@gmail.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Supporting placement and scheduler custom images (#1450)

* supporting placement and scheduler custom images

Signed-off-by: salaboy <Salaboy@gmail.com>

* Bump org.apache.commons:commons-lang3 from 3.9 to 3.18.0 (#1446)

Bumps org.apache.commons:commons-lang3 from 3.9 to 3.18.0.

---
updated-dependencies:
- dependency-name: org.apache.commons:commons-lang3
  dependency-version: 3.18.0
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: artur-ciocanu <artur.ciocanu@gmail.com>
Signed-off-by: salaboy <Salaboy@gmail.com>

* Update dapr docs for Hugo upgrade (#1443)

Signed-off-by: Marc Duiker <marcduiker@users.noreply.github.com>
Co-authored-by: Cassie Coyle <cassie.i.coyle@gmail.com>
Signed-off-by: salaboy <Salaboy@gmail.com>

* Adds note about workflow start time (#1444)

Signed-off-by: joshvanl <me@joshvanl.dev>
Co-authored-by: Dapr Bot <56698301+dapr-bot@users.noreply.github.com>
Co-authored-by: artur-ciocanu <artur.ciocanu@gmail.com>
Signed-off-by: salaboy <Salaboy@gmail.com>

* adding test to validate canonical names with substitutes

Signed-off-by: salaboy <Salaboy@gmail.com>

* Migrate PubSub removing flaky test (#1407)

* Migrate PubSub removing flaky test

Signed-off-by: Matheus Cruz <matheuscruz.dev@gmail.com>

* Adjust assertion

Signed-off-by: Matheus Cruz <matheuscruz.dev@gmail.com>

* Change assert

Signed-off-by: Matheus Cruz <matheuscruz.dev@gmail.com>

* Apply pull request suggestions

Signed-off-by: Matheus Cruz <matheuscruz.dev@gmail.com>

* Use custom ObjectSerializer

Signed-off-by: Matheus Cruz <matheuscruz.dev@gmail.com>

---------

Signed-off-by: Matheus Cruz <matheuscruz.dev@gmail.com>
Co-authored-by: artur-ciocanu <artur.ciocanu@gmail.com>
Signed-off-by: salaboy <Salaboy@gmail.com>

* adding tests for coverage

Signed-off-by: salaboy <Salaboy@gmail.com>

---------

Signed-off-by: salaboy <Salaboy@gmail.com>
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Marc Duiker <marcduiker@users.noreply.github.com>
Signed-off-by: joshvanl <me@joshvanl.dev>
Signed-off-by: Matheus Cruz <matheuscruz.dev@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: artur-ciocanu <artur.ciocanu@gmail.com>
Co-authored-by: Marc Duiker <marcduiker@users.noreply.github.com>
Co-authored-by: Cassie Coyle <cassie.i.coyle@gmail.com>
Co-authored-by: Josh van Leeuwen <me@joshvanl.dev>
Co-authored-by: Dapr Bot <56698301+dapr-bot@users.noreply.github.com>
Co-authored-by: Matheus Cruz <56329339+mcruzdev@users.noreply.github.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* chore: Replace ossrh url (#1454)

Signed-off-by: Javier Aliaga <javier@diagrid.io>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Upgrading to 1.15.7 (#1458)

* upgrading to 1.15.7

Signed-off-by: salaboy <Salaboy@gmail.com>

* using DAPR VERSION

Signed-off-by: salaboy <Salaboy@gmail.com>

---------

Signed-off-by: salaboy <Salaboy@gmail.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* updating sched api on DaprContainer (#1462)

Signed-off-by: salaboy <Salaboy@gmail.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Adding app health check parameters (#1465)

* adding app health check parameters

Signed-off-by: salaboy <Salaboy@gmail.com>

* fixing style

Signed-off-by: salaboy <Salaboy@gmail.com>

* testing with configure for coverage

Signed-off-by: salaboy <Salaboy@gmail.com>

* updating sched api on DaprContainer (#1462)

Signed-off-by: salaboy <Salaboy@gmail.com>

* fix Artur comments

Signed-off-by: salaboy <Salaboy@gmail.com>

---------

Signed-off-by: salaboy <Salaboy@gmail.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Add note about the dapr.client.* properties (#1467)

Signed-off-by: Matheus Cruz <matheuscruz.dev@gmail.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* conversation ai

Signed-off-by: sirivarma <siri.varma@outlook.com>

* Fix pom

Signed-off-by: sirivarma <siri.varma@outlook.com>

* Fix pom

Signed-off-by: sirivarma <siri.varma@outlook.com>

* fix things

Signed-off-by: sirivarma <siri.varma@outlook.com>

* Fix things

Signed-off-by: sirivarma <siri.varma@outlook.com>

* docs: Add gRPC response settings to properties documentation (#1482)

* docs: Add gRPC response settings to properties documentation

Signed-off-by: MyMirelHub <15373565+MyMirelHub@users.noreply.github.com>

* Apply suggestion from @javier-aliaga

Co-authored-by: Javier Aliaga <javier@diagrid.io>
Signed-off-by: Mirel Isaj <15373565+MyMirelHub@users.noreply.github.com>

---------

Signed-off-by: MyMirelHub <15373565+MyMirelHub@users.noreply.github.com>
Signed-off-by: Mirel Isaj <15373565+MyMirelHub@users.noreply.github.com>
Co-authored-by: Javier Aliaga <javier@diagrid.io>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Generate updated javadocs for 1.14.2

Signed-off-by: Dapr Bot <daprweb@microsoft.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* chore: Use 1.16.0 rc 2 (#1463)

* chore: Use 1.16.0 rc

Signed-off-by: Javier Aliaga <javier@diagrid.io>

* chore: Use dapr:1.16-rc.2

Signed-off-by: Javier Aliaga <javier@diagrid.io>

* chore: Add overwrite flag to jobs

Signed-off-by: Javier Aliaga <javier@diagrid.io>

---------

Signed-off-by: Javier Aliaga <javier@diagrid.io>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Add Failure Policy for Jobs SDK (#1448)

* Update CONTRIBUTING.md

Signed-off-by: Siri Varma Vegiraju <siri.varma@outlook.com>

* Add failrue policy

Signed-off-by: sirivarma <siri.varma@outlook.com>

* Add tests

Signed-off-by: sirivarma <siri.varma@outlook.com>

* Add Tests

Signed-off-by: sirivarma <siri.varma@outlook.com>

* Upgrading to 1.15.7 (#1458)

* upgrading to 1.15.7

Signed-off-by: salaboy <Salaboy@gmail.com>

* using DAPR VERSION

Signed-off-by: salaboy <Salaboy@gmail.com>

---------

Signed-off-by: salaboy <Salaboy@gmail.com>
Signed-off-by: siri-varma <siri.varma@outlook.com>

* Rename classes

Signed-off-by: siri-varma <siri.varma@outlook.com>

* add rc

Signed-off-by: sirivarma <siri.varma@outlook.com>

* fix checkstyle

Signed-off-by: sirivarma <siri.varma@outlook.com>

* Fix things

Signed-off-by: sirivarma <siri.varma@outlook.com>

* Test latest

Signed-off-by: sirivarma <siri.varma@outlook.com>

* fix checkstyle

Signed-off-by: sirivarma <siri.varma@outlook.com>

* Address comments

Signed-off-by: sirivarma <siri.varma@outlook.com>

* Address comments

Signed-off-by: sirivarma <siri.varma@outlook.com>

---------

Signed-off-by: Siri Varma Vegiraju <siri.varma@outlook.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>
Signed-off-by: salaboy <Salaboy@gmail.com>
Signed-off-by: siri-varma <siri.varma@outlook.com>
Co-authored-by: artur-ciocanu <artur.ciocanu@gmail.com>
Co-authored-by: salaboy <Salaboy@gmail.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>

* Fix things

Signed-off-by: sirivarma <siri.varma@outlook.com>

* Fix things

Signed-off-by: sirivarma <siri.varma@outlook.com>

* Fix things

Signed-off-by: sirivarma <siri.varma@outlook.com>

* Fix things

Signed-off-by: sirivarma <siri.varma@outlook.com>

* Fix things

Signed-off-by: sirivarma <siri.varma@outlook.com>

* fxi things

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Add better tests

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Add examples

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Add examples

Signed-off-by: siri-varma <siri.varma@outlook.com>

* Update README.md

Signed-off-by: Siri Varma Vegiraju <siri.varma@outlook.com>

* Update UserMessageDemo.java

Signed-off-by: Siri Varma Vegiraju <siri.varma@outlook.com>

* Update UserMessageDemo.java

Signed-off-by: Siri Varma Vegiraju <siri.varma@outlook.com>

* Fix tool calling

Signed-off-by: sirivarma <siri.varma@outlook.com>

* Address comments

Signed-off-by: sirivarma <siri.varma@outlook.com>

---------

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>
Signed-off-by: sirivarma <siri.varma@outlook.com>
Signed-off-by: Siri Varma Vegiraju <siri.varma@outlook.com>
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Dapr Bot <daprweb@microsoft.com>
Signed-off-by: Siri Varma Vegiraju <svegiraju@microsoft.com>
Signed-off-by: siri-varma <siri.varma@outlook.com>
Signed-off-by: Cassandra Coyle <cassie@diagrid.io>
Signed-off-by: Javier Aliaga <javier@diagrid.io>
Signed-off-by: Deepak <sdeepaksharma15@gmail.com>
Signed-off-by: salaboy <Salaboy@gmail.com>
Signed-off-by: artur-ciocanu <artur.ciocanu@gmail.com>
Signed-off-by: Mason <theforbiddenai@gmail.com>
Signed-off-by: Marc Duiker <marcduiker@users.noreply.github.com>
Signed-off-by: joshvanl <me@joshvanl.dev>
Signed-off-by: Matheus Cruz <matheuscruz.dev@gmail.com>
Signed-off-by: MyMirelHub <15373565+MyMirelHub@users.noreply.github.com>
Signed-off-by: Mirel Isaj <15373565+MyMirelHub@users.noreply.github.com>
Co-authored-by: artur-ciocanu <artur.ciocanu@gmail.com>
Co-authored-by: Artur Ciocanu <ciocanu@adobe.com>
Co-authored-by: Cassie Coyle <cassie@diagrid.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Dapr Bot <56698301+dapr-bot@users.noreply.github.com>
Co-authored-by: Dapr Bot <daprweb@microsoft.com>
Co-authored-by: Cassie Coyle <cassie.i.coyle@gmail.com>
Co-authored-by: Javier Aliaga <javier@diagrid.io>
Co-authored-by: Matheus Cruz <56329339+mcruzdev@users.noreply.github.com>
Co-authored-by: iddeepak <87892182+iddeepak@users.noreply.github.com>
Co-authored-by: salaboy <Salaboy@gmail.com>
Co-authored-by: Mason <TheForbiddenAI@gmail.com>
Co-authored-by: Marc Duiker <marcduiker@users.noreply.github.com>
Co-authored-by: Josh van Leeuwen <me@joshvanl.dev>
Co-authored-by: Mirel Isaj <15373565+MyMirelHub@users.noreply.github.com>
This commit is contained in:
Siri Varma Vegiraju 2025-09-11 15:03:11 -07:00 committed by GitHub
parent 12a1185958
commit dffa92a15a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
30 changed files with 3212 additions and 59 deletions

View File

@ -0,0 +1,136 @@
/*
* Copyright 2021 The Dapr Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
limitations under the License.
*/
package io.dapr.examples.conversation;
import io.dapr.client.DaprClientBuilder;
import io.dapr.client.DaprPreviewClient;
import io.dapr.client.domain.AssistantMessage;
import io.dapr.client.domain.ConversationInputAlpha2;
import io.dapr.client.domain.ConversationMessage;
import io.dapr.client.domain.ConversationMessageContent;
import io.dapr.client.domain.ConversationRequestAlpha2;
import io.dapr.client.domain.ConversationResponseAlpha2;
import io.dapr.client.domain.ConversationResultAlpha2;
import io.dapr.client.domain.ConversationResultChoices;
import io.dapr.client.domain.ConversationToolCalls;
import io.dapr.client.domain.ConversationToolCallsOfFunction;
import io.dapr.client.domain.SystemMessage;
import io.dapr.client.domain.ToolMessage;
import io.dapr.client.domain.UserMessage;
import reactor.core.publisher.Mono;
import java.util.ArrayList;
import java.util.List;
public class AssistantMessageDemo {
/**
* The main method to demonstrate conversation AI with assistant messages and conversation history.
*
* @param args Input arguments (unused).
*/
public static void main(String[] args) {
try (DaprPreviewClient client = new DaprClientBuilder().buildPreviewClient()) {
System.out.println("Demonstrating Conversation AI with Assistant Messages and Conversation History");
// Create a conversation history with multiple message types
List<ConversationMessage> conversationHistory = new ArrayList<>();
// 1. System message to set context
SystemMessage systemMessage = new SystemMessage(List.of(
new ConversationMessageContent("You are a helpful assistant that can help with weather queries.")
));
systemMessage.setName("WeatherBot");
conversationHistory.add(systemMessage);
// 2. Initial user greeting
UserMessage greeting = new UserMessage(List.of(
new ConversationMessageContent("Hello! I need help with weather information.")
));
greeting.setName("User123");
conversationHistory.add(greeting);
// 3. Assistant response with tool call
AssistantMessage assistantResponse = new AssistantMessage(
List.of(new ConversationMessageContent("I'll help you with weather information. Let me check the weather for you.")),
List.of(new ConversationToolCalls(
new ConversationToolCallsOfFunction("get_weather", "{\"location\": \"San Francisco\", \"unit\": \"fahrenheit\"}")
))
);
assistantResponse.setName("WeatherBot");
conversationHistory.add(assistantResponse);
// 4. Tool response (simulating weather API response)
ToolMessage toolResponse = new ToolMessage(List.of(
new ConversationMessageContent("{\"temperature\": \"72F\", \"condition\": \"sunny\", \"humidity\": \"65%\"}")
));
toolResponse.setName("weather_api");
conversationHistory.add(toolResponse);
// 5. Current user question
UserMessage currentQuestion = new UserMessage(List.of(
new ConversationMessageContent("Based on that weather data, should I wear a jacket today?")
));
currentQuestion.setName("User123");
conversationHistory.add(currentQuestion);
// Create conversation input with the full history
ConversationInputAlpha2 conversationInput = new ConversationInputAlpha2(conversationHistory);
conversationInput.setScrubPii(false);
// Create the conversation request
ConversationRequestAlpha2 request = new ConversationRequestAlpha2("echo", List.of(conversationInput))
.setContextId("assistant-demo-context")
.setTemperature(0.8d);
// Send the request
System.out.println("Sending conversation with assistant messages and history...");
System.out.println("Conversation includes:");
System.out.println("- System message (context setting)");
System.out.println("- User greeting");
System.out.println("- Assistant response with tool call");
System.out.println("- Tool response with weather data");
System.out.println("- User follow-up question");
Mono<ConversationResponseAlpha2> responseMono = client.converseAlpha2(request);
ConversationResponseAlpha2 response = responseMono.block();
// Process and display the response
if (response != null && response.getOutputs() != null && !response.getOutputs().isEmpty()) {
ConversationResultAlpha2 result = response.getOutputs().get(0);
if (result.getChoices() != null && !result.getChoices().isEmpty()) {
ConversationResultChoices choice = result.getChoices().get(0);
if (choice.getMessage() != null && choice.getMessage().getContent() != null) {
System.out.printf("Assistant Response: %s%n", choice.getMessage().getContent());
}
// Check for additional tool calls in the response
if (choice.getMessage() != null && choice.getMessage().getToolCalls() != null) {
System.out.println("Assistant requested additional tool calls:");
choice.getMessage().getToolCalls().forEach(toolCall -> {
System.out.printf("Tool: %s, Arguments: %s%n",
toolCall.getFunction().getName(),
toolCall.getFunction().getArguments());
});
}
}
}
System.out.println("Assistant message demonstration completed.");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

View File

@ -1,49 +0,0 @@
/*
* Copyright 2021 The Dapr Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
limitations under the License.
*/
package io.dapr.examples.conversation;
import io.dapr.client.DaprClientBuilder;
import io.dapr.client.DaprPreviewClient;
import io.dapr.client.domain.ConversationInput;
import io.dapr.client.domain.ConversationRequest;
import io.dapr.client.domain.ConversationResponse;
import reactor.core.publisher.Mono;
import java.util.List;
public class DemoConversationAI {
/**
* The main method to start the client.
*
* @param args Input arguments (unused).
*/
public static void main(String[] args) {
try (DaprPreviewClient client = new DaprClientBuilder().buildPreviewClient()) {
System.out.println("Sending the following input to LLM: Hello How are you? This is the my number 672-123-4567");
ConversationInput daprConversationInput = new ConversationInput("Hello How are you? "
+ "This is the my number 672-123-4567");
// Component name is the name provided in the metadata block of the conversation.yaml file.
Mono<ConversationResponse> responseMono = client.converse(new ConversationRequest("echo",
List.of(daprConversationInput))
.setContextId("contextId")
.setScrubPii(true).setTemperature(1.1d));
ConversationResponse response = responseMono.block();
System.out.printf("Conversation output: %s", response.getConversationOutputs().get(0).getResult());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

View File

@ -45,30 +45,51 @@ Run `dapr init` to initialize Dapr in Self-Hosted Mode if it's not already initi
### Running the example
This example uses the Java SDK Dapr client in order to **Converse** with an LLM.
`DemoConversationAI.java` is the example class demonstrating these features.
`UserMessageDemo.java` is the example class demonstrating these features.
Kindly check [DaprPreviewClient.java](https://github.com/dapr/java-sdk/blob/master/sdk/src/main/java/io/dapr/client/DaprPreviewClient.java) for a detailed description of the supported APIs.
```java
public class DemoConversationAI {
public class UserMessageDemo {
/**
* The main method to start the client.
*
* @param args Input arguments (unused).
*/
public static void main(String[] args) {
try (DaprPreviewClient client = new DaprClientBuilder().buildPreviewClient()) {
Map<Property<?>, String> overrides = Map.of(
Properties.HTTP_PORT, "3500",
Properties.GRPC_PORT, "50001"
);
try (DaprPreviewClient client = new DaprClientBuilder().withPropertyOverrides(overrides).buildPreviewClient()) {
System.out.println("Sending the following input to LLM: Hello How are you? This is the my number 672-123-4567");
ConversationInput daprConversationInput = new ConversationInput("Hello How are you? "
+ "This is the my number 672-123-4567");
// Create user message with content
UserMessage userMessage = new UserMessage(List.of(new ConversationMessageContent("Hello How are you? "
+ "This is the my number 672-123-4567")));
// Create conversation input with the user message
ConversationInputAlpha2 daprConversationInput = new ConversationInputAlpha2(List.of(userMessage));
// Component name is the name provided in the metadata block of the conversation.yaml file.
Mono<ConversationResponse> responseMono = client.converse(new ConversationRequest("echo",
Mono<ConversationResponseAlpha2> responseMono = client.converseAlpha2(new ConversationRequestAlpha2("echo",
List.of(daprConversationInput))
.setContextId("contextId")
.setScrubPii(true).setTemperature(1.1d));
ConversationResponse response = responseMono.block();
System.out.printf("Conversation output: %s", response.getConversationOutpus().get(0).getResult());
.setScrubPii(true)
.setTemperature(1.1d));
ConversationResponseAlpha2 response = responseMono.block();
// Extract and print the conversation result
if (response != null && response.getOutputs() != null && !response.getOutputs().isEmpty()) {
ConversationResultAlpha2 result = response.getOutputs().get(0);
if (result.getChoices() != null && !result.getChoices().isEmpty()) {
ConversationResultChoices choice = result.getChoices().get(0);
if (choice.getMessage() != null && choice.getMessage().getContent() != null) {
System.out.printf("Conversation output: %s", choice.getMessage().getContent());
}
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
@ -88,7 +109,7 @@ sleep: 10
-->
```bash
dapr run --resources-path ./components/conversation --app-id myapp --app-port 8080 --dapr-http-port 3500 --dapr-grpc-port 51439 --log-level debug -- java -jar target/dapr-java-sdk-examples-exec.jar io.dapr.examples.conversation.DemoConversationAI
dapr run --resources-path ./components/conversation --app-id myapp --app-port 8080 --dapr-http-port 3500 --dapr-grpc-port 51439 --log-level debug -- java -jar target/dapr-java-sdk-examples-exec.jar io.dapr.examples.conversation.UserMessageDemo
```
<!-- END_STEP -->

View File

@ -0,0 +1,109 @@
/*
* Copyright 2021 The Dapr Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
limitations under the License.
*/
package io.dapr.examples.conversation;
import io.dapr.client.DaprClientBuilder;
import io.dapr.client.DaprPreviewClient;
import io.dapr.client.domain.ConversationInputAlpha2;
import io.dapr.client.domain.ConversationMessageContent;
import io.dapr.client.domain.ConversationRequestAlpha2;
import io.dapr.client.domain.ConversationResponseAlpha2;
import io.dapr.client.domain.ConversationResultAlpha2;
import io.dapr.client.domain.ConversationResultChoices;
import io.dapr.client.domain.ConversationTools;
import io.dapr.client.domain.ConversationToolsFunction;
import io.dapr.client.domain.SystemMessage;
import io.dapr.client.domain.UserMessage;
import reactor.core.publisher.Mono;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ToolsCallDemo {
/**
* The main method to demonstrate conversation AI with tools/function calling.
*
* @param args Input arguments (unused).
*/
public static void main(String[] args) {
try (DaprPreviewClient client = new DaprClientBuilder().buildPreviewClient()) {
System.out.println("Demonstrating Conversation AI with Tools/Function Calling");
// Create system message to set context
SystemMessage systemMessage = new SystemMessage(List.of(
new ConversationMessageContent("You are a helpful weather assistant. Use the provided tools to get weather information.")
));
// Create user message asking for weather
UserMessage userMessage = new UserMessage(List.of(
new ConversationMessageContent("What's the weather like in San Francisco?")
));
// Create conversation input with messages
ConversationInputAlpha2 conversationInput = new ConversationInputAlpha2(List.of(systemMessage, userMessage));
// Define function parameters for the weather tool
Map<String, Object> functionParams = new HashMap<>();
functionParams.put("location", "string");
functionParams.put("unit", "string");
// Create the weather function definition
ConversationToolsFunction weatherFunction = new ConversationToolsFunction("get_current_weather", functionParams);
weatherFunction.setDescription("Get the current weather for a specified location");
// Create the tool wrapper
ConversationTools weatherTool = new ConversationTools(weatherFunction);
// Create the conversation request with tools
ConversationRequestAlpha2 request = new ConversationRequestAlpha2("echo", List.of(conversationInput))
.setContextId("weather-demo-context")
.setTemperature(0.7d)
.setTools(List.of(weatherTool));
// Send the request
System.out.println("Sending request to AI with weather tool available...");
Mono<ConversationResponseAlpha2> responseMono = client.converseAlpha2(request);
ConversationResponseAlpha2 response = responseMono.block();
// Process and display the response
if (response != null && response.getOutputs() != null && !response.getOutputs().isEmpty()) {
ConversationResultAlpha2 result = response.getOutputs().get(0);
if (result.getChoices() != null && !result.getChoices().isEmpty()) {
ConversationResultChoices choice = result.getChoices().get(0);
// Check if the AI wants to call a tool
if (choice.getMessage() != null && choice.getMessage().getToolCalls() != null) {
System.out.println("AI requested to call tools:");
choice.getMessage().getToolCalls().forEach(toolCall -> {
System.out.printf("Tool: %s, Arguments: %s%n",
toolCall.getFunction().getName(),
toolCall.getFunction().getArguments());
});
}
// Display the message content if available
if (choice.getMessage() != null && choice.getMessage().getContent() != null) {
System.out.printf("AI Response: %s%n", choice.getMessage().getContent());
}
}
}
System.out.println("Tools call demonstration completed.");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

View File

@ -0,0 +1,72 @@
/*
* Copyright 2021 The Dapr Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
limitations under the License.
*/
package io.dapr.examples.conversation;
import io.dapr.client.DaprClientBuilder;
import io.dapr.client.DaprPreviewClient;
import io.dapr.client.domain.ConversationInputAlpha2;
import io.dapr.client.domain.ConversationMessageContent;
import io.dapr.client.domain.ConversationRequestAlpha2;
import io.dapr.client.domain.ConversationResponseAlpha2;
import io.dapr.client.domain.ConversationResultAlpha2;
import io.dapr.client.domain.ConversationResultChoices;
import io.dapr.client.domain.UserMessage;
import io.dapr.config.Properties;
import io.dapr.config.Property;
import reactor.core.publisher.Mono;
import java.util.List;
import java.util.Map;
public class UserMessageDemo {
/**
* The main method to start the client.
*
* @param args Input arguments (unused).
*/
public static void main(String[] args) {
try (DaprPreviewClient client = new DaprClientBuilder().buildPreviewClient()) {
System.out.println("Sending the following input to LLM: Hello How are you? This is the my number 672-123-4567");
// Create user message with content
UserMessage userMessage = new UserMessage(List.of(new ConversationMessageContent("Hello How are you? "
+ "This is the my number 672-123-4567")));
// Create conversation input with the user message
ConversationInputAlpha2 daprConversationInput = new ConversationInputAlpha2(List.of(userMessage));
// Component name is the name provided in the metadata block of the conversation.yaml file.
Mono<ConversationResponseAlpha2> responseMono = client.converseAlpha2(new ConversationRequestAlpha2("echo",
List.of(daprConversationInput))
.setContextId("contextId")
.setScrubPii(true)
.setTemperature(1.1d));
ConversationResponseAlpha2 response = responseMono.block();
// Extract and print the conversation result
if (response != null && response.getOutputs() != null && !response.getOutputs().isEmpty()) {
ConversationResultAlpha2 result = response.getOutputs().get(0);
if (result.getChoices() != null && !result.getChoices().isEmpty()) {
ConversationResultChoices choice = result.getChoices().get(0);
if (choice.getMessage() != null && choice.getMessage().getContent() != null) {
System.out.printf("Conversation output: %s", choice.getMessage().getContent());
}
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

View File

@ -0,0 +1,386 @@
/*
* Copyright 2025 The Dapr Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
limitations under the License.
*/
package io.dapr.it.testcontainers.conversations;
import io.dapr.client.DaprPreviewClient;
import io.dapr.client.domain.AssistantMessage;
import io.dapr.client.domain.ConversationInputAlpha2;
import io.dapr.client.domain.ConversationMessage;
import io.dapr.client.domain.ConversationMessageContent;
import io.dapr.client.domain.ConversationRequestAlpha2;
import io.dapr.client.domain.ConversationResponseAlpha2;
import io.dapr.client.domain.ConversationResultAlpha2;
import io.dapr.client.domain.ConversationResultChoices;
import io.dapr.client.domain.ConversationToolCalls;
import io.dapr.client.domain.ConversationToolCallsOfFunction;
import io.dapr.client.domain.ConversationTools;
import io.dapr.client.domain.ConversationToolsFunction;
import io.dapr.client.domain.DeveloperMessage;
import io.dapr.client.domain.SystemMessage;
import io.dapr.client.domain.ToolMessage;
import io.dapr.client.domain.UserMessage;
import io.dapr.it.testcontainers.DaprPreviewClientConfiguration;
import io.dapr.testcontainers.Component;
import io.dapr.testcontainers.DaprContainer;
import io.dapr.testcontainers.DaprLogLevel;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.testcontainers.containers.Network;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import static io.dapr.it.testcontainers.ContainerConstants.DAPR_RUNTIME_IMAGE_TAG;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
@SpringBootTest(
webEnvironment = WebEnvironment.RANDOM_PORT,
classes = {
DaprPreviewClientConfiguration.class,
TestConversationApplication.class
}
)
@Testcontainers
@Tag("testcontainers")
public class DaprConversationAlpha2IT {
private static final Network DAPR_NETWORK = Network.newNetwork();
private static final Random RANDOM = new Random();
private static final int PORT = RANDOM.nextInt(1000) + 8000;
@Container
private static final DaprContainer DAPR_CONTAINER = new DaprContainer(DAPR_RUNTIME_IMAGE_TAG)
.withAppName("conversation-alpha2-dapr-app")
.withComponent(new Component("echo", "conversation.echo", "v1", new HashMap<>()))
.withNetwork(DAPR_NETWORK)
.withDaprLogLevel(DaprLogLevel.DEBUG)
.withLogConsumer(outputFrame -> System.out.println(outputFrame.getUtf8String()))
.withAppChannelAddress("host.testcontainers.internal")
.withAppPort(PORT);
/**
* Expose the Dapr port to the host.
*
* @param registry the dynamic property registry
*/
@DynamicPropertySource
static void daprProperties(DynamicPropertyRegistry registry) {
registry.add("dapr.http.endpoint", DAPR_CONTAINER::getHttpEndpoint);
registry.add("dapr.grpc.endpoint", DAPR_CONTAINER::getGrpcEndpoint);
registry.add("server.port", () -> PORT);
}
@Autowired
private DaprPreviewClient daprPreviewClient;
@BeforeEach
public void setUp() {
org.testcontainers.Testcontainers.exposeHostPorts(PORT);
}
@Test
public void testConverseAlpha2WithUserMessage() {
// Create a user message
UserMessage userMessage = new UserMessage(List.of(new ConversationMessageContent("Hello, how are you?")));
userMessage.setName("TestUser");
// Create input with the message
ConversationInputAlpha2 input = new ConversationInputAlpha2(List.of(userMessage));
ConversationRequestAlpha2 request = new ConversationRequestAlpha2("echo", List.of(input));
ConversationResponseAlpha2 response = daprPreviewClient.converseAlpha2(request).block();
assertNotNull(response);
assertNotNull(response.getOutputs());
assertEquals(1, response.getOutputs().size());
ConversationResultAlpha2 result = response.getOutputs().get(0);
assertNotNull(result.getChoices());
assertTrue(result.getChoices().size() > 0);
ConversationResultChoices choice = result.getChoices().get(0);
assertNotNull(choice.getMessage());
assertNotNull(choice.getMessage().getContent());
}
@Test
public void testConverseAlpha2WithAllMessageTypes() {
List<ConversationMessage> messages = new ArrayList<>();
// System message
SystemMessage systemMsg = new SystemMessage(List.of(new ConversationMessageContent("You are a helpful assistant.")));
systemMsg.setName("system");
messages.add(systemMsg);
// User message
UserMessage userMsg = new UserMessage(List.of(new ConversationMessageContent("Hello!")));
userMsg.setName("user");
messages.add(userMsg);
// Assistant message
AssistantMessage assistantMsg = new AssistantMessage(List.of(new ConversationMessageContent("Hi there!")),
List.of(new ConversationToolCalls(
new ConversationToolCallsOfFunction("get_weather", "{\"location\": \"New York\"}"))));
assistantMsg.setName("assistant");
messages.add(assistantMsg);
// Tool message
ToolMessage toolMsg = new ToolMessage(List.of(new ConversationMessageContent("Weather data: 72F")));
toolMsg.setName("tool");
messages.add(toolMsg);
// Developer message
DeveloperMessage devMsg = new DeveloperMessage(List.of(new ConversationMessageContent("Debug info")));
devMsg.setName("developer");
messages.add(devMsg);
ConversationInputAlpha2 input = new ConversationInputAlpha2(messages);
ConversationRequestAlpha2 request = new ConversationRequestAlpha2("echo", List.of(input));
ConversationResponseAlpha2 response = daprPreviewClient.converseAlpha2(request).block();
assertNotNull(response);
assertNotNull(response.getOutputs());
assertTrue(response.getOutputs().size() > 0);
}
@Test
public void testConverseAlpha2WithScrubPII() {
// Create a user message with PII
UserMessage userMessage = new UserMessage(List.of(new ConversationMessageContent("My email is test@example.com and phone is +1234567890")));
ConversationInputAlpha2 input = new ConversationInputAlpha2(List.of(userMessage));
input.setScrubPii(true);
ConversationRequestAlpha2 request = new ConversationRequestAlpha2("echo", List.of(input));
request.setScrubPii(true);
ConversationResponseAlpha2 response = daprPreviewClient.converseAlpha2(request).block();
assertNotNull(response);
assertNotNull(response.getOutputs());
assertTrue(response.getOutputs().size() > 0);
// Verify response structure (actual PII scrubbing depends on echo component implementation)
ConversationResultChoices choice = response.getOutputs().get(0).getChoices().get(0);
assertNotNull(choice.getMessage());
assertNotNull(choice.getMessage().getContent());
}
@Test
public void testConverseAlpha2WithTools() {
// Create a tool function
Map<String, Object> parameters = new HashMap<>();
parameters.put("location", "string");
parameters.put("unit", "celsius");
ConversationToolsFunction function = new ConversationToolsFunction("get_weather", parameters);
function.setDescription("Get current weather information");
ConversationTools tool = new ConversationTools(function);
// Create user message
UserMessage userMessage = new UserMessage(List.of(new ConversationMessageContent("What's the weather like?")));
ConversationInputAlpha2 input = new ConversationInputAlpha2(List.of(userMessage));
ConversationRequestAlpha2 request = new ConversationRequestAlpha2("echo", List.of(input));
request.setTools(List.of(tool));
request.setToolChoice("auto");
ConversationResponseAlpha2 response = daprPreviewClient.converseAlpha2(request).block();
assertNotNull(response);
assertNotNull(response.getOutputs());
assertTrue(response.getOutputs().size() > 0);
}
@Test
public void testConverseAlpha2WithMetadataAndParameters() {
UserMessage userMessage = new UserMessage(List.of(new ConversationMessageContent("Hello world")));
ConversationInputAlpha2 input = new ConversationInputAlpha2(List.of(userMessage));
// Set metadata and parameters
Map<String, String> metadata = new HashMap<>();
metadata.put("request-id", "test-123");
metadata.put("source", "integration-test");
Map<String, Object> parameters = new HashMap<>();
parameters.put("max_tokens", "1000");
parameters.put("temperature", "0.7");
ConversationRequestAlpha2 request = new ConversationRequestAlpha2("echo", List.of(input));
request.setContextId("test-context-123");
request.setTemperature(0.8);
request.setMetadata(metadata);
request.setParameters(parameters);
ConversationResponseAlpha2 response = daprPreviewClient.converseAlpha2(request).block();
assertNotNull(response);
assertNotNull(response.getOutputs());
assertTrue(response.getOutputs().size() > 0);
// Verify context ID is handled properly
// Note: actual context ID behavior depends on echo component implementation
assertNotNull(response.getContextId());
}
@Test
public void testConverseAlpha2WithAssistantToolCalls() {
// Create a tool call
ConversationToolCallsOfFunction toolFunction =
new ConversationToolCallsOfFunction("get_weather", "{\"location\": \"New York\"}");
ConversationToolCalls toolCall = new ConversationToolCalls(toolFunction);
toolCall.setId("call_123");
// Create assistant message with tool calls
AssistantMessage assistantMsg = new AssistantMessage(List.of(new ConversationMessageContent("Hi there!")),
List.of(new ConversationToolCalls(
new ConversationToolCallsOfFunction("get_weather", "{\"location\": \"New York\"}")))); // Note: Current implementation doesn't support setting tool calls in constructor
// This tests the structure and ensures no errors occur
ConversationInputAlpha2 input = new ConversationInputAlpha2(List.of(assistantMsg));
ConversationRequestAlpha2 request = new ConversationRequestAlpha2("echo", List.of(input));
ConversationResponseAlpha2 response = daprPreviewClient.converseAlpha2(request).block();
assertNotNull(response);
assertNotNull(response.getOutputs());
assertTrue(response.getOutputs().size() > 0);
}
@Test
public void testConverseAlpha2WithComplexScenario() {
List<ConversationMessage> messages = new ArrayList<>();
// System message setting context
SystemMessage systemMsg = new SystemMessage(List.of(new ConversationMessageContent("You are a helpful weather assistant.")));
systemMsg.setName("WeatherBot");
messages.add(systemMsg);
// User asking for weather
UserMessage userMsg = new UserMessage(List.of(new ConversationMessageContent("What's the weather in San Francisco?")));
userMsg.setName("User123");
messages.add(userMsg);
// Assistant response
AssistantMessage assistantMsg = new AssistantMessage(List.of(new ConversationMessageContent("Hi there!")),
List.of(new ConversationToolCalls(
new ConversationToolCallsOfFunction("get_weather", "{\"location\": \"New York\"}"))));
assistantMsg.setName("WeatherBot");
messages.add(assistantMsg);
// Tool response
ToolMessage toolMsg = new ToolMessage(List.of(new ConversationMessageContent("{\"temperature\": \"68F\", \"condition\": \"sunny\"}")));
toolMsg.setName("weather_api");
messages.add(toolMsg);
ConversationInputAlpha2 input = new ConversationInputAlpha2(messages);
input.setScrubPii(false);
// Create tools
Map<String, Object> functionParams = new HashMap<>();
functionParams.put("location", "string");
functionParams.put("unit", "fahrenheit");
ConversationToolsFunction weatherFunction = new ConversationToolsFunction("get_current_weather",
functionParams);
weatherFunction.setDescription("Get current weather for a location");
ConversationTools weatherTool = new ConversationTools(weatherFunction);
// Set up complete request
Map<String, String> metadata = new HashMap<>();
metadata.put("conversation-type", "weather-query");
metadata.put("user-session", "session-456");
Map<String, Object> parameters = new HashMap<>();
parameters.put("max_tokens", "2000");
parameters.put("response_format", "json");
ConversationRequestAlpha2 request = new ConversationRequestAlpha2("echo", List.of(input));
request.setContextId("weather-conversation-789");
request.setTemperature(0.7);
request.setScrubPii(false);
request.setTools(List.of(weatherTool));
request.setToolChoice("auto");
request.setMetadata(metadata);
request.setParameters(parameters);
ConversationResponseAlpha2 response = daprPreviewClient.converseAlpha2(request).block();
assertNotNull(response);
assertNotNull(response.getOutputs());
assertTrue(response.getOutputs().size() > 0);
ConversationResultAlpha2 result = response.getOutputs().get(0);
assertNotNull(result.getChoices());
assertTrue(result.getChoices().size() > 0);
ConversationResultChoices choice = result.getChoices().get(0);
assertNotNull(choice.getFinishReason());
assertTrue(choice.getIndex() >= 0);
if (choice.getMessage() != null) {
assertNotNull(choice.getMessage().getContent());
}
}
@Test
public void testConverseAlpha2MultipleInputs() {
// Create multiple conversation inputs
List<ConversationInputAlpha2> inputs = new ArrayList<>();
// First input - greeting
UserMessage greeting = new UserMessage(List.of(new ConversationMessageContent("Hello!")));
ConversationInputAlpha2 input1 = new ConversationInputAlpha2(List.of(greeting));
inputs.add(input1);
// Second input - question
UserMessage question = new UserMessage(List.of(new ConversationMessageContent("How are you?")));
ConversationInputAlpha2 input2 = new ConversationInputAlpha2(List.of(question));
input2.setScrubPii(true);
inputs.add(input2);
ConversationRequestAlpha2 request = new ConversationRequestAlpha2("echo", inputs);
ConversationResponseAlpha2 response = daprPreviewClient.converseAlpha2(request).block();
assertNotNull(response);
assertNotNull(response.getOutputs());
assertTrue(response.getOutputs().size() > 0);
// Should handle multiple inputs appropriately
for (ConversationResultAlpha2 result : response.getOutputs()) {
assertNotNull(result.getChoices());
assertTrue(result.getChoices().size() > 0);
}
}
}

View File

@ -128,3 +128,4 @@ public class DaprConversationIT {
response.getConversationOutputs().get(0).getResult());
}
}

View File

@ -17,9 +17,12 @@ import com.google.common.base.Strings;
import com.google.protobuf.Any;
import com.google.protobuf.ByteString;
import com.google.protobuf.Empty;
import com.google.protobuf.Struct;
import com.google.protobuf.Value;
import io.dapr.client.domain.ActorMetadata;
import io.dapr.client.domain.AppConnectionPropertiesHealthMetadata;
import io.dapr.client.domain.AppConnectionPropertiesMetadata;
import io.dapr.client.domain.AssistantMessage;
import io.dapr.client.domain.BulkPublishEntry;
import io.dapr.client.domain.BulkPublishRequest;
import io.dapr.client.domain.BulkPublishResponse;
@ -29,9 +32,21 @@ import io.dapr.client.domain.ComponentMetadata;
import io.dapr.client.domain.ConfigurationItem;
import io.dapr.client.domain.ConstantFailurePolicy;
import io.dapr.client.domain.ConversationInput;
import io.dapr.client.domain.ConversationInputAlpha2;
import io.dapr.client.domain.ConversationMessage;
import io.dapr.client.domain.ConversationMessageContent;
import io.dapr.client.domain.ConversationOutput;
import io.dapr.client.domain.ConversationRequest;
import io.dapr.client.domain.ConversationRequestAlpha2;
import io.dapr.client.domain.ConversationResponse;
import io.dapr.client.domain.ConversationResponseAlpha2;
import io.dapr.client.domain.ConversationResultAlpha2;
import io.dapr.client.domain.ConversationResultChoices;
import io.dapr.client.domain.ConversationResultMessage;
import io.dapr.client.domain.ConversationToolCalls;
import io.dapr.client.domain.ConversationToolCallsOfFunction;
import io.dapr.client.domain.ConversationTools;
import io.dapr.client.domain.ConversationToolsFunction;
import io.dapr.client.domain.DaprMetadata;
import io.dapr.client.domain.DeleteJobRequest;
import io.dapr.client.domain.DeleteStateRequest;
@ -64,6 +79,7 @@ import io.dapr.client.domain.StateOptions;
import io.dapr.client.domain.SubscribeConfigurationRequest;
import io.dapr.client.domain.SubscribeConfigurationResponse;
import io.dapr.client.domain.SubscriptionMetadata;
import io.dapr.client.domain.ToolMessage;
import io.dapr.client.domain.TransactionalStateOperation;
import io.dapr.client.domain.UnlockRequest;
import io.dapr.client.domain.UnlockResponseStatus;
@ -1620,6 +1636,7 @@ public class DaprClientImpl extends AbstractDaprClient {
/**
* {@inheritDoc}
*/
@Deprecated(forRemoval = true)
@Override
public Mono<ConversationResponse> converse(ConversationRequest conversationRequest) {
@ -1690,6 +1707,278 @@ public class DaprClientImpl extends AbstractDaprClient {
}
}
/**
* {@inheritDoc}
*/
@Override
public Mono<ConversationResponseAlpha2> converseAlpha2(ConversationRequestAlpha2 conversationRequestAlpha2) {
try {
if ((conversationRequestAlpha2.getName() == null) || (conversationRequestAlpha2.getName().trim().isEmpty())) {
throw new IllegalArgumentException("LLM name cannot be null or empty.");
}
if (conversationRequestAlpha2.getInputs() == null || conversationRequestAlpha2.getInputs().isEmpty()) {
throw new IllegalArgumentException("Conversation Inputs cannot be null or empty.");
}
DaprProtos.ConversationRequestAlpha2 protoRequest = buildConversationRequestProto(conversationRequestAlpha2);
Mono<DaprProtos.ConversationResponseAlpha2> conversationResponseMono = Mono.deferContextual(
context -> this.createMono(
it -> intercept(context, asyncStub).converseAlpha2(protoRequest, it)
)
);
DaprProtos.ConversationResponseAlpha2 conversationResponse = conversationResponseMono.block();
assert conversationResponse != null;
List<ConversationResultAlpha2> results = buildConversationResults(conversationResponse.getOutputsList());
return Mono.just(new ConversationResponseAlpha2(conversationResponse.getContextId(), results));
} catch (Exception ex) {
return DaprException.wrapMono(ex);
}
}
private DaprProtos.ConversationRequestAlpha2 buildConversationRequestProto(ConversationRequestAlpha2 request) {
DaprProtos.ConversationRequestAlpha2.Builder builder = DaprProtos.ConversationRequestAlpha2
.newBuilder()
.setTemperature(request.getTemperature())
.setScrubPii(request.isScrubPii())
.setName(request.getName());
if (request.getContextId() != null) {
builder.setContextId(request.getContextId());
}
if (request.getToolChoice() != null) {
builder.setToolChoice(request.getToolChoice());
}
if (request.getTools() != null) {
for (ConversationTools tool : request.getTools()) {
builder.addTools(buildConversationTools(tool));
}
}
if (request.getMetadata() != null) {
builder.putAllMetadata(request.getMetadata());
}
if (request.getParameters() != null) {
Map<String, Any> parameters = request.getParameters()
.entrySet().stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
e -> {
try {
return Any.newBuilder().setValue(ByteString.copyFrom(objectSerializer.serialize(e.getValue())))
.build();
} catch (IOException ex) {
throw new RuntimeException(ex);
}
})
);
builder.putAllParameters(parameters);
}
for (ConversationInputAlpha2 input : request.getInputs()) {
DaprProtos.ConversationInputAlpha2.Builder inputBuilder = DaprProtos.ConversationInputAlpha2
.newBuilder()
.setScrubPii(input.isScrubPii());
if (input.getMessages() != null) {
for (ConversationMessage message : input.getMessages()) {
DaprProtos.ConversationMessage protoMessage = buildConversationMessage(message);
inputBuilder.addMessages(protoMessage);
}
}
builder.addInputs(inputBuilder.build());
}
return builder.build();
}
private DaprProtos.ConversationTools buildConversationTools(ConversationTools tool) {
ConversationToolsFunction function = tool.getFunction();
DaprProtos.ConversationToolsFunction.Builder protoFunction = DaprProtos.ConversationToolsFunction.newBuilder()
.setName(function.getName());
if (function.getDescription() != null) {
protoFunction.setDescription(function.getDescription());
}
if (function.getParameters() != null) {
Map<String, Value> functionParams = function.getParameters()
.entrySet().stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
e -> {
try {
return ProtobufValueHelper.toProtobufValue(e.getValue());
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
));
protoFunction.setParameters(Struct.newBuilder().putAllFields(functionParams).build());
}
return DaprProtos.ConversationTools.newBuilder().setFunction(protoFunction).build();
}
private DaprProtos.ConversationMessage buildConversationMessage(ConversationMessage message) {
DaprProtos.ConversationMessage.Builder messageBuilder = DaprProtos.ConversationMessage.newBuilder();
switch (message.getRole()) {
case TOOL:
DaprProtos.ConversationMessageOfTool.Builder toolMessage =
DaprProtos.ConversationMessageOfTool.newBuilder();
if (message.getName() != null) {
toolMessage.setName(message.getName());
}
if (message.getContent() != null) {
toolMessage.addAllContent(getConversationMessageContent(message));
}
if (((ToolMessage)message).getToolId() != null) {
toolMessage.setToolId(((ToolMessage)message).getToolId());
}
messageBuilder.setOfTool(toolMessage);
break;
case USER:
DaprProtos.ConversationMessageOfUser.Builder userMessage =
DaprProtos.ConversationMessageOfUser.newBuilder();
if (message.getName() != null) {
userMessage.setName(message.getName());
}
if (message.getContent() != null) {
userMessage.addAllContent(getConversationMessageContent(message));
}
messageBuilder.setOfUser(userMessage);
break;
case ASSISTANT:
DaprProtos.ConversationMessageOfAssistant.Builder assistantMessage =
DaprProtos.ConversationMessageOfAssistant.newBuilder();
if (message.getName() != null) {
assistantMessage.setName(message.getName());
}
if (message.getContent() != null) {
assistantMessage.addAllContent(getConversationMessageContent(message));
}
if (((AssistantMessage)message).getToolCalls() != null) {
assistantMessage.addAllToolCalls(getConversationToolCalls((AssistantMessage)message));
}
messageBuilder.setOfAssistant(assistantMessage);
break;
case DEVELOPER:
DaprProtos.ConversationMessageOfDeveloper.Builder developerMessage =
DaprProtos.ConversationMessageOfDeveloper.newBuilder();
if (message.getName() != null) {
developerMessage.setName(message.getName());
}
if (message.getContent() != null) {
developerMessage.addAllContent(getConversationMessageContent(message));
}
messageBuilder.setOfDeveloper(developerMessage);
break;
case SYSTEM:
DaprProtos.ConversationMessageOfSystem.Builder systemMessage =
DaprProtos.ConversationMessageOfSystem.newBuilder();
if (message.getName() != null) {
systemMessage.setName(message.getName());
}
if (message.getContent() != null) {
systemMessage.addAllContent(getConversationMessageContent(message));
}
messageBuilder.setOfSystem(systemMessage);
break;
default:
throw new IllegalArgumentException("No role of type " + message.getRole() + " found");
}
return messageBuilder.build();
}
private List<ConversationResultAlpha2> buildConversationResults(
List<DaprProtos.ConversationResultAlpha2> protoResults) {
List<ConversationResultAlpha2> results = new ArrayList<>();
for (DaprProtos.ConversationResultAlpha2 protoResult : protoResults) {
List<ConversationResultChoices> choices = new ArrayList<>();
for (DaprProtos.ConversationResultChoices protoChoice : protoResult.getChoicesList()) {
ConversationResultMessage message = buildConversationResultMessage(protoChoice);
choices.add(new ConversationResultChoices(protoChoice.getFinishReason(), protoChoice.getIndex(), message));
}
results.add(new ConversationResultAlpha2(choices));
}
return results;
}
private ConversationResultMessage buildConversationResultMessage(DaprProtos.ConversationResultChoices protoChoice) {
if (!protoChoice.hasMessage()) {
return null;
}
List<ConversationToolCalls> toolCalls = new ArrayList<>();
for (DaprProtos.ConversationToolCalls protoToolCall : protoChoice.getMessage().getToolCallsList()) {
ConversationToolCallsOfFunction function = null;
if (protoToolCall.hasFunction()) {
function = new ConversationToolCallsOfFunction(
protoToolCall.getFunction().getName(),
protoToolCall.getFunction().getArguments()
);
}
ConversationToolCalls conversationToolCalls = new ConversationToolCalls(function);
conversationToolCalls.setId(protoToolCall.getId());
toolCalls.add(conversationToolCalls);
}
return new ConversationResultMessage(protoChoice.getMessage().getContent(), toolCalls
);
}
private List<DaprProtos.ConversationMessageContent> getConversationMessageContent(
ConversationMessage conversationMessage) {
List<DaprProtos.ConversationMessageContent> conversationMessageContents = new ArrayList<>();
for (ConversationMessageContent conversationMessageContent: conversationMessage.getContent()) {
conversationMessageContents.add(DaprProtos.ConversationMessageContent.newBuilder()
.setText(conversationMessageContent.getText())
.build());
}
return conversationMessageContents;
}
private List<DaprProtos.ConversationToolCalls> getConversationToolCalls(
AssistantMessage assistantMessage) {
List<DaprProtos.ConversationToolCalls> conversationToolCalls = new ArrayList<>();
for (ConversationToolCalls conversationToolCall: assistantMessage.getToolCalls()) {
DaprProtos.ConversationToolCalls.Builder toolCallsBuilder = DaprProtos.ConversationToolCalls.newBuilder()
.setFunction(DaprProtos.ConversationToolCallsOfFunction.newBuilder()
.setName(conversationToolCall.getFunction().getName())
.setArguments(conversationToolCall.getFunction().getArguments())
.build());
if (conversationToolCall.getId() != null) {
toolCallsBuilder.setId(conversationToolCall.getId());
}
conversationToolCalls.add(toolCallsBuilder.build());
}
return conversationToolCalls;
}
private DaprMetadata buildDaprMetadata(DaprProtos.GetMetadataResponse response) throws IOException {
String id = response.getId();
String runtimeVersion = response.getRuntimeVersion();

View File

@ -18,7 +18,9 @@ import io.dapr.client.domain.BulkPublishRequest;
import io.dapr.client.domain.BulkPublishResponse;
import io.dapr.client.domain.BulkPublishResponseFailedEntry;
import io.dapr.client.domain.ConversationRequest;
import io.dapr.client.domain.ConversationRequestAlpha2;
import io.dapr.client.domain.ConversationResponse;
import io.dapr.client.domain.ConversationResponseAlpha2;
import io.dapr.client.domain.DeleteJobRequest;
import io.dapr.client.domain.GetJobRequest;
import io.dapr.client.domain.GetJobResponse;
@ -313,5 +315,14 @@ public interface DaprPreviewClient extends AutoCloseable {
* @param conversationRequest request to be passed to the LLM.
* @return {@link ConversationResponse}.
*/
@Deprecated
public Mono<ConversationResponse> converse(ConversationRequest conversationRequest);
/*
* Converse with an LLM using Alpha2 API.
*
* @param conversationRequestAlpha2 request to be passed to the LLM with Alpha2 features.
* @return {@link ConversationResponseAlpha2}.
*/
public Mono<ConversationResponseAlpha2> converseAlpha2(ConversationRequestAlpha2 conversationRequestAlpha2);
}

View File

@ -0,0 +1,76 @@
/*
* Copyright 2021 The Dapr Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
limitations under the License.
*/
package io.dapr.client;
import com.google.protobuf.ListValue;
import com.google.protobuf.NullValue;
import com.google.protobuf.Struct;
import com.google.protobuf.Value;
import io.dapr.serializer.DaprObjectSerializer;
import java.io.IOException;
import java.util.List;
import java.util.Map;
/**
* Helper class to convert Java objects to Google Protobuf Value types.
*/
public class ProtobufValueHelper {
/**
* Converts a Java object to a Google Protobuf Value.
*
* @param obj the Java object to convert
* @return the corresponding Protobuf Value
* @throws IOException if serialization fails
*/
public static Value toProtobufValue(Object obj) throws IOException {
if (obj == null) {
return Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build();
}
if (obj instanceof Boolean) {
return Value.newBuilder().setBoolValue((Boolean) obj).build();
}
if (obj instanceof String) {
return Value.newBuilder().setStringValue((String) obj).build();
}
if (obj instanceof Number) {
return Value.newBuilder().setNumberValue(((Number) obj).doubleValue()).build();
}
if (obj instanceof List) {
ListValue.Builder listBuilder = ListValue.newBuilder();
for (Object item : (List<?>) obj) {
listBuilder.addValues(toProtobufValue(item));
}
return Value.newBuilder().setListValue(listBuilder.build()).build();
}
if (obj instanceof Map) {
Struct.Builder structBuilder = Struct.newBuilder();
for (Map.Entry<?, ?> entry : ((Map<?, ?>) obj).entrySet()) {
String key = entry.getKey().toString();
Value value = toProtobufValue(entry.getValue());
structBuilder.putFields(key, value);
}
return Value.newBuilder().setStructValue(structBuilder.build()).build();
}
// Fallback: convert to string
return Value.newBuilder().setStringValue(obj.toString()).build();
}
}

View File

@ -0,0 +1,67 @@
/*
* Copyright 2025 The Dapr Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
limitations under the License.
*/
package io.dapr.client.domain;
import java.util.List;
/**
* Assistant message containing responses from the AI model.
* Can include regular content and/or tool calls that the model wants to make.
*/
public class AssistantMessage implements ConversationMessage {
private String name;
private final List<ConversationMessageContent> content;
private final List<ConversationToolCalls> toolCalls;
/**
* Creates an assistant message with content and optional tool calls.
* @param content the content of the assistant message.
* @param toolCalls the tool calls requested by the assistant.
*/
public AssistantMessage(List<ConversationMessageContent> content, List<ConversationToolCalls> toolCalls) {
this.content = List.copyOf(content);
this.toolCalls = List.copyOf(toolCalls);
}
@Override
public ConversationMessageRole getRole() {
return ConversationMessageRole.ASSISTANT;
}
@Override
public String getName() {
return name;
}
/**
* Sets the name of the assistant participant.
*
* @param name the name to set
* @return this instance for method chaining
*/
public AssistantMessage setName(String name) {
this.name = name;
return this;
}
@Override
public List<ConversationMessageContent> getContent() {
return content;
}
public List<ConversationToolCalls> getToolCalls() {
return toolCalls;
}
}

View File

@ -0,0 +1,63 @@
/*
* Copyright 2025 The Dapr Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
limitations under the License.
*/
package io.dapr.client.domain;
import java.util.List;
/**
* Represents an Alpha2 input for conversation with enhanced message support.
*/
public class ConversationInputAlpha2 {
private final List<ConversationMessage> messages;
private boolean scrubPii;
/**
* Constructor.
*
* @param messages the list of conversation messages
*/
public ConversationInputAlpha2(List<ConversationMessage> messages) {
this.messages = List.copyOf(messages);
}
/**
* Gets the list of conversation messages.
*
* @return the list of messages
*/
public List<ConversationMessage> getMessages() {
return messages;
}
/**
* Checks if Personally Identifiable Information (PII) should be scrubbed before sending to the LLM.
*
* @return {@code true} if PII should be scrubbed, {@code false} otherwise.
*/
public boolean isScrubPii() {
return scrubPii;
}
/**
* Enable obfuscation of sensitive information present in the content field. Optional
*
* @param scrubPii A boolean indicating whether to remove PII.
* @return this.
*/
public ConversationInputAlpha2 setScrubPii(boolean scrubPii) {
this.scrubPii = scrubPii;
return this;
}
}

View File

@ -0,0 +1,44 @@
/*
* Copyright 2025 The Dapr Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
limitations under the License.
*/
package io.dapr.client.domain;
import java.util.List;
/**
* Interface representing a conversation message with role-specific content.
* Supports different message types: system, user, assistant, developer, and tool.
*/
public interface ConversationMessage {
/**
* Gets the role of the message sender.
*
* @return the message role
*/
ConversationMessageRole getRole();
/**
* Gets the name of the participant in the message.
*
* @return the participant name, or null if not specified
*/
String getName();
/**
* Gets the content of the message.
*
* @return the message content
*/
List<ConversationMessageContent> getContent();
}

View File

@ -0,0 +1,40 @@
/*
* Copyright 2025 The Dapr Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
limitations under the License.
*/
package io.dapr.client.domain;
/**
* Represents the content of a conversation message.
*/
public class ConversationMessageContent {
private final String text;
/**
* Constructor.
*
* @param text the text content of the message
*/
public ConversationMessageContent(String text) {
this.text = text;
}
/**
* Gets the text content of the message.
*
* @return the text content
*/
public String getText() {
return text;
}
}

View File

@ -0,0 +1,44 @@
/*
* Copyright 2022 The Dapr Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
limitations under the License.
*/
package io.dapr.client.domain;
/**
* Enum representing the different roles a conversation message can have.
*/
public enum ConversationMessageRole {
/**
* System message that sets the behavior or context for the conversation.
*/
SYSTEM,
/**
* User message containing input from the human user.
*/
USER,
/**
* Assistant message containing responses from the AI model.
*/
ASSISTANT,
/**
* Tool message containing results from function/tool calls.
*/
TOOL,
/**
* Developer message for development and debugging purposes.
*/
DEVELOPER
}

View File

@ -0,0 +1,209 @@
/*
* Copyright 2025 The Dapr Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
limitations under the License.
*/
package io.dapr.client.domain;
import java.util.List;
import java.util.Map;
/**
* Represents the Alpha2 conversation configuration with enhanced features including
* tools, improved message handling, and better compatibility with OpenAI ChatCompletion API.
*/
public class ConversationRequestAlpha2 {
private final String name;
private final List<ConversationInputAlpha2> inputs;
private String contextId;
private boolean scrubPii;
private double temperature;
private List<ConversationTools> tools;
private String toolChoice;
private Map<String, Object> parameters;
private Map<String, String> metadata;
/**
* Constructs a ConversationRequestAlpha2 with a component name and conversation inputs.
*
* @param name The name of the Dapr conversation component. See a list of all available conversation components
* @see <a href="https://docs.dapr.io/reference/components-reference/supported-conversation/"></a>
* @param inputs the list of Dapr conversation inputs (Alpha2 format)
*/
public ConversationRequestAlpha2(String name, List<ConversationInputAlpha2> inputs) {
this.name = name;
this.inputs = inputs;
}
/**
* Gets the conversation component name.
*
* @return the conversation component name
*/
public String getName() {
return name;
}
/**
* Gets the list of Dapr conversation input (Alpha2 format).
*
* @return the list of conversation input
*/
public List<ConversationInputAlpha2> getInputs() {
return inputs;
}
/**
* Gets the context identifier.
*
* @return the context identifier
*/
public String getContextId() {
return contextId;
}
/**
* Sets the context identifier.
*
* @param contextId the context identifier to set
* @return the current instance of {@link ConversationRequestAlpha2}
*/
public ConversationRequestAlpha2 setContextId(String contextId) {
this.contextId = contextId;
return this;
}
/**
* Checks if PII scrubbing is enabled.
*
* @return true if PII scrubbing is enabled, false otherwise
*/
public boolean isScrubPii() {
return scrubPii;
}
/**
* Enable obfuscation of sensitive information returning from the LLM. Optional.
*
* @param scrubPii whether to enable PII scrubbing
* @return the current instance of {@link ConversationRequestAlpha2}
*/
public ConversationRequestAlpha2 setScrubPii(boolean scrubPii) {
this.scrubPii = scrubPii;
return this;
}
/**
* Gets the temperature of the model. Used to optimize for consistency and creativity. Optional
*
* @return the temperature value
*/
public double getTemperature() {
return temperature;
}
/**
* Sets the temperature of the model. Used to optimize for consistency and creativity. Optional
*
* @param temperature the temperature value to set
* @return the current instance of {@link ConversationRequestAlpha2}
*/
public ConversationRequestAlpha2 setTemperature(double temperature) {
this.temperature = temperature;
return this;
}
/**
* Gets the tools available to be used by the LLM during the conversation.
*
* @return the list of tools
*/
public List<ConversationTools> getTools() {
return tools;
}
/**
* Sets the tools available to be used by the LLM during the conversation.
* These are sent on a per request basis.
*
* @param tools the tools to set
* @return the current instance of {@link ConversationRequestAlpha2}
*/
public ConversationRequestAlpha2 setTools(List<ConversationTools> tools) {
this.tools = tools;
return this;
}
/**
* Gets the tool choice setting which controls which (if any) tool is called by the model.
*
* @return the tool choice setting
*/
public String getToolChoice() {
return toolChoice;
}
/**
* Sets the tool choice setting which controls which (if any) tool is called by the model.
* - "none" means the model will not call any tool and instead generates a message
* - "auto" means the model can pick between generating a message or calling one or more tools
* - "required" requires one or more functions to be called
* - Alternatively, a specific tool name may be used here
*
* @param toolChoice the tool choice setting to set
* @return the current instance of {@link ConversationRequestAlpha2}
*/
public ConversationRequestAlpha2 setToolChoice(String toolChoice) {
this.toolChoice = toolChoice;
return this;
}
/**
* Gets the parameters for all custom fields.
*
* @return the parameters map
*/
public Map<String, Object> getParameters() {
return parameters;
}
/**
* Sets the parameters for all custom fields.
*
* @param parameters the parameters to set
* @return the current instance of {@link ConversationRequestAlpha2}
*/
public ConversationRequestAlpha2 setParameters(Map<String, Object> parameters) {
this.parameters = parameters;
return this;
}
/**
* Gets the metadata passing to conversation components.
*
* @return the metadata map
*/
public Map<String, String> getMetadata() {
return metadata;
}
/**
* Sets the metadata passing to conversation components.
*
* @param metadata the metadata to set
* @return the current instance of {@link ConversationRequestAlpha2}
*/
public ConversationRequestAlpha2 setMetadata(Map<String, String> metadata) {
this.metadata = metadata;
return this;
}
}

View File

@ -0,0 +1,54 @@
/*
* Copyright 2025 The Dapr Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
limitations under the License.
*/
package io.dapr.client.domain;
import java.util.List;
/**
* Alpha2 response from the Dapr Conversation API with enhanced features.
*/
public class ConversationResponseAlpha2 {
private final String contextId;
private final List<ConversationResultAlpha2> outputs;
/**
* Constructor.
*
* @param contextId context id supplied to LLM.
* @param outputs outputs from the LLM (Alpha2 format).
*/
public ConversationResponseAlpha2(String contextId, List<ConversationResultAlpha2> outputs) {
this.contextId = contextId;
this.outputs = List.copyOf(outputs);
}
/**
* The ID of an existing chat (like in ChatGPT).
*
* @return String identifier.
*/
public String getContextId() {
return this.contextId;
}
/**
* Get list of conversation outputs (Alpha2 format).
*
* @return List{@link ConversationResultAlpha2}.
*/
public List<ConversationResultAlpha2> getOutputs() {
return this.outputs;
}
}

View File

@ -0,0 +1,42 @@
/*
* Copyright 2025 The Dapr Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
limitations under the License.
*/
package io.dapr.client.domain;
import java.util.List;
/**
* Alpha2 result for conversation output with enhanced choice-based structure.
*/
public class ConversationResultAlpha2 {
private final List<ConversationResultChoices> choices;
/**
* Constructor.
*
* @param choices the list of conversation result choices.
*/
public ConversationResultAlpha2(List<ConversationResultChoices> choices) {
this.choices = List.copyOf(choices);
}
/**
* Gets the list of conversation result choices.
*
* @return the list of conversation result choices
*/
public List<ConversationResultChoices> getChoices() {
return choices;
}
}

View File

@ -0,0 +1,68 @@
/*
* Copyright 2025 The Dapr Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
limitations under the License.
*/
package io.dapr.client.domain;
/**
* Represents a conversation result choice with finish reason, index, and message.
*/
public class ConversationResultChoices {
private final String finishReason;
private final long index;
private final ConversationResultMessage message;
/**
* Constructor.
*
* @param finishReason the reason the model stopped generating tokens
* @param index the index of the choice in the list of choices
* @param message the result message
*/
public ConversationResultChoices(String finishReason, long index, ConversationResultMessage message) {
this.finishReason = finishReason;
this.index = index;
this.message = message;
}
/**
* Gets the reason the model stopped generating tokens.
* This will be "stop" if the model hit a natural stop point or a provided stop sequence,
* "length" if the maximum number of tokens specified in the request was reached,
* "content_filter" if content was omitted due to a flag from content filters,
* "tool_calls" if the model called a tool.
*
* @return the finish reason
*/
public String getFinishReason() {
return finishReason;
}
/**
* Gets the index of the choice in the list of choices.
*
* @return the index
*/
public long getIndex() {
return index;
}
/**
* Gets the result message.
*
* @return the message
*/
public ConversationResultMessage getMessage() {
return message;
}
}

View File

@ -0,0 +1,72 @@
/*
* Copyright 2025 The Dapr Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
limitations under the License.
*/
package io.dapr.client.domain;
import java.util.List;
/**
* Represents a conversation result message with content and optional tool calls.
*/
public class ConversationResultMessage {
private final String content;
private final List<ConversationToolCalls> toolCalls;
/**
* Constructor.
*
* @param content the contents of the message
* @param toolCalls the tool calls generated by the model (optional)
*/
public ConversationResultMessage(String content, List<ConversationToolCalls> toolCalls) {
this.content = content;
this.toolCalls = toolCalls != null ? List.copyOf(toolCalls) : null;
}
/**
* Constructor for message without tool calls.
*
* @param content the contents of the message
*/
public ConversationResultMessage(String content) {
this(content, null);
}
/**
* Gets the contents of the message.
*
* @return the message content
*/
public String getContent() {
return content;
}
/**
* Gets the tool calls generated by the model.
*
* @return the tool calls, or null if none
*/
public List<ConversationToolCalls> getToolCalls() {
return toolCalls;
}
/**
* Checks if the message has tool calls.
*
* @return true if there are tool calls, false otherwise
*/
public boolean hasToolCalls() {
return toolCalls != null && !toolCalls.isEmpty();
}
}

View File

@ -0,0 +1,61 @@
/*
* Copyright 2025 The Dapr Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
limitations under the License.
*/
package io.dapr.client.domain;
/**
* Represents a tool call request sent from the LLM to the client to execute.
*/
public class ConversationToolCalls {
private String id;
private final ConversationToolCallsOfFunction function;
/**
* Constructor without ID.
*
* @param function the function to call
*/
public ConversationToolCalls(ConversationToolCallsOfFunction function) {
this.function = function;
}
/**
* Gets the unique identifier for the tool call.
*
* @return the tool call ID, or null if not provided
*/
public String getId() {
return id;
}
/**
* Set with ID.
*
* @param id the unique identifier for the tool call
* @return this instance for method chaining
*/
public ConversationToolCalls setId(String id) {
this.id = id;
return this;
}
/**
* Gets the function to call.
*
* @return the function details
*/
public ConversationToolCallsOfFunction getFunction() {
return function;
}
}

View File

@ -0,0 +1,54 @@
/*
* Copyright 2025 The Dapr Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
limitations under the License.
*/
package io.dapr.client.domain;
/**
* Represents a function call within a tool call.
*/
public class ConversationToolCallsOfFunction {
private final String name;
private final String arguments;
/**
* Constructor.
*
* @param name the name of the function to call
* @param arguments the arguments to call the function with, as generated by the model in JSON format
*/
public ConversationToolCallsOfFunction(String name, String arguments) {
this.name = name;
this.arguments = arguments;
}
/**
* Gets the name of the function to call.
*
* @return the function name
*/
public String getName() {
return name;
}
/**
* Gets the arguments to call the function with, as generated by the model in JSON format.
* Note that the model does not always generate valid JSON, and may hallucinate parameters
* not defined by your function schema. Validate the arguments in your code before calling your function.
*
* @return the function arguments in JSON format
*/
public String getArguments() {
return arguments;
}
}

View File

@ -0,0 +1,40 @@
/*
* Copyright 2025 The Dapr Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
limitations under the License.
*/
package io.dapr.client.domain;
/**
* Represents tool definitions that can be used during conversation.
*/
public class ConversationTools {
private final ConversationToolsFunction function;
/**
* Constructor.
*
* @param function the function definition
*/
public ConversationTools(ConversationToolsFunction function) {
this.function = function;
}
/**
* Gets the function definition.
*
* @return the function definition
*/
public ConversationToolsFunction getFunction() {
return function;
}
}

View File

@ -0,0 +1,75 @@
/*
* Copyright 2025 The Dapr Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
limitations under the License.
*/
package io.dapr.client.domain;
import java.util.Map;
/**
* Represents a function definition for conversation tools.
*/
public class ConversationToolsFunction {
private String description;
private final String name;
private final Map<String, Object> parameters;
/**
* Constructor.
*
* @param name the function name
* @param parameters the function parameters schema
*/
public ConversationToolsFunction(String name, Map<String, Object> parameters) {
this.name = name;
this.parameters = parameters;
}
/**
* Gets the function name.
*
* @return the function name
*/
public String getName() {
return name;
}
/**
* Gets the function description.
*
* @return the function description
*/
public String getDescription() {
return description;
}
/**
* Sets the function description.
*
* @param description the function description
* @return this instance for method chaining
*/
public ConversationToolsFunction setDescription(String description) {
this.description = description;
return this;
}
/**
* Gets the function parameters schema.
*
* @return the function parameters
*/
public Map<String, Object> getParameters() {
return parameters;
}
}

View File

@ -0,0 +1,61 @@
/*
* Copyright 2025 The Dapr Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
limitations under the License.
*/
package io.dapr.client.domain;
import java.util.List;
/**
* Developer message for development and debugging purposes.
* Used for providing additional context or instructions during development.
*/
public class DeveloperMessage implements ConversationMessage {
private String name;
private final List<ConversationMessageContent> content;
/**
* Creates a developer message with content.
*
* @param content the content of the developer message
*/
public DeveloperMessage(List<ConversationMessageContent> content) {
this.content = List.copyOf(content);
}
@Override
public ConversationMessageRole getRole() {
return ConversationMessageRole.DEVELOPER;
}
@Override
public String getName() {
return name;
}
/**
* Sets the name of the developer participant.
*
* @param name the name to set
* @return this instance for method chaining
*/
public DeveloperMessage setName(String name) {
this.name = name;
return this;
}
@Override
public List<ConversationMessageContent> getContent() {
return content;
}
}

View File

@ -0,0 +1,59 @@
/*
* Copyright 2025 The Dapr Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
limitations under the License.
*/
package io.dapr.client.domain;
import java.util.List;
/**
* System message that sets the behavior or context for the conversation.
* Used to provide instructions or context to the AI model.
*/
public class SystemMessage implements ConversationMessage {
private String name;
private final List<ConversationMessageContent> content;
/**
* Creates a system message with content.
*
* @param content the content of the system message
*/
public SystemMessage(List<ConversationMessageContent> content) {
this.content = List.copyOf(content);
}
@Override
public ConversationMessageRole getRole() {
return ConversationMessageRole.SYSTEM;
}
@Override
public String getName() {
return name;
}
/**
* Sets the name of the system participant.
*
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
@Override
public List<ConversationMessageContent> getContent() {
return content;
}
}

View File

@ -0,0 +1,77 @@
/*
* Copyright 2025 The Dapr Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
limitations under the License.
*/
package io.dapr.client.domain;
import java.util.List;
/**
* Tool message containing results from function/tool calls.
* Used to provide the response from a tool execution back to the AI model.
*/
public class ToolMessage implements ConversationMessage {
private String toolId;
private String name;
private final List<ConversationMessageContent> content;
/**
* Creates a tool message with content.
*
* @param content the content containing the tool execution result
*/
public ToolMessage(List<ConversationMessageContent> content) {
this.content = List.copyOf(content);
}
@Override
public ConversationMessageRole getRole() {
return ConversationMessageRole.TOOL;
}
@Override
public String getName() {
return name;
}
/**
* Sets the tool identifier.
*
* @param toolId the tool identifier to set
* @return this instance for method chaining
*/
public ToolMessage setToolId(String toolId) {
this.toolId = toolId;
return this;
}
/**
* Sets the name of the tool participant.
*
* @param name the name to set
* @return this instance for method chaining
*/
public ToolMessage setName(String name) {
this.name = name;
return this;
}
@Override
public List<ConversationMessageContent> getContent() {
return content;
}
public String getToolId() {
return toolId;
}
}

View File

@ -0,0 +1,61 @@
/*
* Copyright 2025 The Dapr Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
limitations under the License.
*/
package io.dapr.client.domain;
import java.util.List;
/**
* User message containing input from the human user.
* Represents questions, requests, or other input from the end user.
*/
public class UserMessage implements ConversationMessage {
private String name;
private final List<ConversationMessageContent> content;
/**
* Creates a user message with content.
*
* @param content the content of the user message
*/
public UserMessage(List<ConversationMessageContent> content) {
this.content = List.copyOf(content);
}
@Override
public ConversationMessageRole getRole() {
return ConversationMessageRole.USER;
}
@Override
public String getName() {
return name;
}
/**
* Sets the name of the user participant.
*
* @param name the name to set
* @return this instance for method chaining
*/
public UserMessage setName(String name) {
this.name = name;
return this;
}
@Override
public List<ConversationMessageContent> getContent() {
return content;
}
}

View File

@ -16,12 +16,29 @@ package io.dapr.client;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import com.google.protobuf.Any;
import com.google.protobuf.ByteString;
import io.dapr.client.domain.AssistantMessage;
import io.dapr.client.domain.BulkPublishEntry;
import io.dapr.client.domain.BulkPublishRequest;
import io.dapr.client.domain.BulkPublishResponse;
import io.dapr.client.domain.CloudEvent;
import io.dapr.client.domain.ConversationToolCallsOfFunction;
import io.dapr.client.domain.ConversationToolsFunction;
import io.dapr.client.domain.ConversationInputAlpha2;
import io.dapr.client.domain.ConversationMessage;
import io.dapr.client.domain.ConversationMessageContent;
import io.dapr.client.domain.ConversationRequestAlpha2;
import io.dapr.client.domain.ConversationResponseAlpha2;
import io.dapr.client.domain.ConversationResultAlpha2;
import io.dapr.client.domain.ConversationResultChoices;
import io.dapr.client.domain.ConversationToolCalls;
import io.dapr.client.domain.ConversationTools;
import io.dapr.client.domain.DeleteJobRequest;
import io.dapr.client.domain.DeveloperMessage;
import io.dapr.client.domain.GetJobRequest;
import io.dapr.client.domain.GetJobResponse;
import io.dapr.client.domain.ConstantFailurePolicy;
import io.dapr.client.domain.ConversationInput;
import io.dapr.client.domain.ConversationRequest;
@ -35,7 +52,10 @@ import io.dapr.client.domain.QueryStateItem;
import io.dapr.client.domain.QueryStateRequest;
import io.dapr.client.domain.QueryStateResponse;
import io.dapr.client.domain.ScheduleJobRequest;
import io.dapr.client.domain.SystemMessage;
import io.dapr.client.domain.ToolMessage;
import io.dapr.client.domain.UnlockResponseStatus;
import io.dapr.client.domain.UserMessage;
import io.dapr.client.domain.query.Query;
import io.dapr.serializer.DaprObjectSerializer;
import io.dapr.serializer.DefaultObjectSerializer;
@ -1329,6 +1349,473 @@ public class DaprPreviewClientGrpcTest {
assertEquals("Name in the request cannot be null or empty", exception.getMessage());
}
@Test
public void converseAlpha2ShouldThrowIllegalArgumentExceptionWhenNameIsNull() {
List<ConversationMessage> messages = new ArrayList<>();
SystemMessage systemMsg = new SystemMessage(List.of(new ConversationMessageContent("System info")));
systemMsg.setName("system");
messages.add(systemMsg);
ConversationInputAlpha2 input = new ConversationInputAlpha2(messages);
ConversationRequestAlpha2 request = new ConversationRequestAlpha2(null, List.of(input));
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () ->
previewClient.converseAlpha2(request).block());
assertEquals("LLM name cannot be null or empty.", exception.getMessage());
}
@Test
public void converseAlpha2ShouldThrowIllegalArgumentExceptionWhenNameIsEmpty() {
List<ConversationMessage> messages = new ArrayList<>();
SystemMessage systemMsg = new SystemMessage(List.of(new ConversationMessageContent("System info")));
systemMsg.setName("system");
messages.add(systemMsg);
ConversationInputAlpha2 input = new ConversationInputAlpha2(messages);
ConversationRequestAlpha2 request = new ConversationRequestAlpha2("", List.of(input));
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () ->
previewClient.converseAlpha2(request).block());
assertEquals("LLM name cannot be null or empty.", exception.getMessage());
}
@Test
public void converseAlpha2ShouldThrowIllegalArgumentExceptionWhenNameIsWhitespace() {
List<ConversationMessage> messages = new ArrayList<>();
SystemMessage systemMsg = new SystemMessage(List.of(new ConversationMessageContent("System info")));
systemMsg.setName("system");
messages.add(systemMsg);
ConversationInputAlpha2 input = new ConversationInputAlpha2(messages);
ConversationRequestAlpha2 request = new ConversationRequestAlpha2(" ", null);
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () ->
previewClient.converseAlpha2(request).block());
assertEquals("LLM name cannot be null or empty.", exception.getMessage());
}
@Test
public void converseAlpha2ShouldThrowIllegalArgumentExceptionWhenInputIsNull() {
ConversationRequestAlpha2 request = new ConversationRequestAlpha2("abc", null);
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () ->
previewClient.converseAlpha2(request).block());
assertEquals("Conversation Inputs cannot be null or empty.", exception.getMessage());
}
@Test
public void converseAlpha2ShouldThrowIllegalArgumentExceptionWhenInputIsEmpty() {
ConversationRequestAlpha2 request = new ConversationRequestAlpha2("abc", new ArrayList<>());
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () ->
previewClient.converseAlpha2(request).block());
assertEquals("Conversation Inputs cannot be null or empty.", exception.getMessage());
}
@Test
public void converseAlpha2ExceptionThrownTest() {
doAnswer((Answer<Void>) invocation -> {
throw newStatusRuntimeException("INVALID_ARGUMENT", "bad argument");
}).when(daprStub).converseAlpha2(any(DaprProtos.ConversationRequestAlpha2.class), any());
ConversationRequestAlpha2 request = new ConversationRequestAlpha2("openai", null);
assertThrows(IllegalArgumentException.class, () -> previewClient.converseAlpha2(request).block());
}
@Test
public void converseAlpha2CallbackExceptionThrownTest() {
doAnswer((Answer<Void>) invocation -> {
StreamObserver<DaprProtos.ConversationResponseAlpha2> observer =
(StreamObserver<DaprProtos.ConversationResponseAlpha2>) invocation.getArguments()[1];
observer.onError(newStatusRuntimeException("INVALID_ARGUMENT", "bad argument"));
return null;
}).when(daprStub).converseAlpha2(any(DaprProtos.ConversationRequestAlpha2.class), any());
List<ConversationMessage> messages = new ArrayList<>();
SystemMessage systemMsg = new SystemMessage(List.of(new ConversationMessageContent("System info")));
systemMsg.setName("system");
messages.add(systemMsg);
ConversationInputAlpha2 input = new ConversationInputAlpha2(messages);
ConversationRequestAlpha2 request = new ConversationRequestAlpha2("openai", List.of(input));
Mono<ConversationResponseAlpha2> result = previewClient.converseAlpha2(request);
assertThrowsDaprException(
ExecutionException.class,
"INVALID_ARGUMENT",
"INVALID_ARGUMENT: bad argument",
() -> result.block());
}
@Test
public void converseAlpha2MinimalRequestTest() {
DaprProtos.ConversationResponseAlpha2 grpcResponse = DaprProtos.ConversationResponseAlpha2.newBuilder()
.setContextId("test-context")
.addOutputs(DaprProtos.ConversationResultAlpha2.newBuilder()
.addChoices(DaprProtos.ConversationResultChoices.newBuilder()
.setFinishReason("stop")
.setIndex(0)
.setMessage(DaprProtos.ConversationResultMessage.newBuilder()
.setContent("Hello! How can I help you today?")
.build())
.build())
.build())
.build();
doAnswer((Answer<Void>) invocation -> {
StreamObserver<DaprProtos.ConversationResponseAlpha2> observer =
(StreamObserver<DaprProtos.ConversationResponseAlpha2>) invocation.getArguments()[1];
observer.onNext(grpcResponse);
observer.onCompleted();
return null;
}).when(daprStub).converseAlpha2(any(DaprProtos.ConversationRequestAlpha2.class), any());
List<ConversationMessage> messages = new ArrayList<>();
DeveloperMessage devMsg = new DeveloperMessage(List.of(new ConversationMessageContent("Debug info")));
devMsg.setName("developer");
messages.add(devMsg);
ConversationInputAlpha2 input = new ConversationInputAlpha2(messages);
ConversationRequestAlpha2 request = new ConversationRequestAlpha2("openai", List.of(input));
ConversationResponseAlpha2 response = previewClient.converseAlpha2(request).block();
assertNotNull(response);
assertEquals("test-context", response.getContextId());
assertEquals(1, response.getOutputs().size());
ConversationResultAlpha2 result = response.getOutputs().get(0);
assertEquals(1, result.getChoices().size());
ConversationResultChoices choice = result.getChoices().get(0);
assertEquals("stop", choice.getFinishReason());
assertEquals(0, choice.getIndex());
assertEquals("Hello! How can I help you today?", choice.getMessage().getContent());
}
@Test
public void converseAlpha2ComplexRequestTest() {
// Create messages
List<ConversationMessage> messages = new ArrayList<>();
UserMessage userMessage = new UserMessage(List.of(new ConversationMessageContent("Hello, how are you?")));
userMessage.setName("John");
messages.add(userMessage);
// Create input
ConversationInputAlpha2 input = new ConversationInputAlpha2(messages);
input.setScrubPii(true);
// Create tools
Map<String, Object> functionParams = new HashMap<>();
functionParams.put("location", "Required location parameter");
List<ConversationTools> tools = new ArrayList<>();
ConversationToolsFunction function = new ConversationToolsFunction("get_weather", functionParams);
function.setDescription("Get current weather");
ConversationTools tool = new ConversationTools(function);
tools.add(tool);
Map<String, String> metadata = new HashMap<>();
metadata.put("key1", "value1");
Map<String, Object> parameters = new HashMap<>();
parameters.put("max_tokens", "1000");
ConversationRequestAlpha2 request = new ConversationRequestAlpha2("openai", List.of(input));
request.setContextId("test-context");
request.setTemperature(0.7);
request.setScrubPii(true);
request.setTools(tools);
request.setToolChoice("auto");
request.setMetadata(metadata);
request.setParameters(parameters);
// Mock response with tool calls
DaprProtos.ConversationResponseAlpha2 grpcResponse = DaprProtos.ConversationResponseAlpha2.newBuilder()
.setContextId("test-context")
.addOutputs(DaprProtos.ConversationResultAlpha2.newBuilder()
.addChoices(DaprProtos.ConversationResultChoices.newBuilder()
.setFinishReason("tool_calls")
.setIndex(0)
.setMessage(DaprProtos.ConversationResultMessage.newBuilder()
.setContent("I'll help you get the weather information.")
.addToolCalls(DaprProtos.ConversationToolCalls.newBuilder()
.setId("call_123")
.setFunction(DaprProtos.ConversationToolCallsOfFunction.newBuilder()
.setName("get_weather")
.setArguments("{\"location\": \"New York\"}")
.build())
.build())
.build())
.build())
.build())
.build();
doAnswer((Answer<Void>) invocation -> {
StreamObserver<DaprProtos.ConversationResponseAlpha2> observer =
(StreamObserver<DaprProtos.ConversationResponseAlpha2>) invocation.getArguments()[1];
observer.onNext(grpcResponse);
observer.onCompleted();
return null;
}).when(daprStub).converseAlpha2(any(DaprProtos.ConversationRequestAlpha2.class), any());
ConversationResponseAlpha2 response = previewClient.converseAlpha2(request).block();
assertNotNull(response);
assertEquals("test-context", response.getContextId());
ConversationResultChoices choice = response.getOutputs().get(0).getChoices().get(0);
assertEquals("tool_calls", choice.getFinishReason());
assertEquals("I'll help you get the weather information.", choice.getMessage().getContent());
assertEquals(1, choice.getMessage().getToolCalls().size());
ConversationToolCalls toolCall = choice.getMessage().getToolCalls().get(0);
assertEquals("call_123", toolCall.getId());
assertEquals("get_weather", toolCall.getFunction().getName());
assertEquals("{\"location\": \"New York\"}", toolCall.getFunction().getArguments());
// Verify the request was built correctly
ArgumentCaptor<DaprProtos.ConversationRequestAlpha2> captor =
ArgumentCaptor.forClass(DaprProtos.ConversationRequestAlpha2.class);
verify(daprStub).converseAlpha2(captor.capture(), any());
DaprProtos.ConversationRequestAlpha2 capturedRequest = captor.getValue();
assertEquals("openai", capturedRequest.getName());
assertEquals("test-context", capturedRequest.getContextId());
assertEquals(0.7, capturedRequest.getTemperature(), 0.001);
assertTrue(capturedRequest.getScrubPii());
assertEquals("auto", capturedRequest.getToolChoice());
assertEquals("value1", capturedRequest.getMetadataMap().get("key1"));
assertEquals(1, capturedRequest.getToolsCount());
assertEquals("get_weather", capturedRequest.getTools(0).getFunction().getName());
}
@Test
public void converseAlpha2AllMessageTypesTest() {
List<ConversationMessage> messages = new ArrayList<>();
// System message
SystemMessage systemMsg = new SystemMessage(List.of(new ConversationMessageContent("You are a helpful assistant.")));
systemMsg.setName("system");
messages.add(systemMsg);
// User message
UserMessage userMsg = new UserMessage(List.of(new ConversationMessageContent("Hello!")));
userMsg.setName("user");
messages.add(userMsg);
// Assistant message
AssistantMessage assistantMsg = new AssistantMessage(List.of(new ConversationMessageContent("Hi there!")),
List.of(new ConversationToolCalls(new ConversationToolCallsOfFunction("abc", "parameters"))));
assistantMsg.setName("assistant");
messages.add(assistantMsg);
// Tool message
ToolMessage toolMsg = new ToolMessage(List.of(new ConversationMessageContent("Weather data: 72F")));
toolMsg.setName("tool");
messages.add(toolMsg);
// Developer message
DeveloperMessage devMsg = new DeveloperMessage(List.of(new ConversationMessageContent("Debug info")));
devMsg.setName("developer");
messages.add(devMsg);
ConversationInputAlpha2 input = new ConversationInputAlpha2(messages);
ConversationRequestAlpha2 request = new ConversationRequestAlpha2("openai", List.of(input));
DaprProtos.ConversationResponseAlpha2 grpcResponse = DaprProtos.ConversationResponseAlpha2.newBuilder()
.addOutputs(DaprProtos.ConversationResultAlpha2.newBuilder()
.addChoices(DaprProtos.ConversationResultChoices.newBuilder()
.setFinishReason("stop")
.setIndex(0)
.setMessage(DaprProtos.ConversationResultMessage.newBuilder()
.setContent("Processed all message types")
.build())
.build())
.build())
.build();
doAnswer((Answer<Void>) invocation -> {
StreamObserver<DaprProtos.ConversationResponseAlpha2> observer =
(StreamObserver<DaprProtos.ConversationResponseAlpha2>) invocation.getArguments()[1];
observer.onNext(grpcResponse);
observer.onCompleted();
return null;
}).when(daprStub).converseAlpha2(any(DaprProtos.ConversationRequestAlpha2.class), any());
ConversationResponseAlpha2 response = previewClient.converseAlpha2(request).block();
assertNotNull(response);
assertEquals("Processed all message types", response.getOutputs().get(0).getChoices().get(0).getMessage().getContent());
// Verify all message types were processed
ArgumentCaptor<DaprProtos.ConversationRequestAlpha2> captor =
ArgumentCaptor.forClass(DaprProtos.ConversationRequestAlpha2.class);
verify(daprStub).converseAlpha2(captor.capture(), any());
DaprProtos.ConversationRequestAlpha2 capturedRequest = captor.getValue();
assertEquals(1, capturedRequest.getInputsCount());
assertEquals(5, capturedRequest.getInputs(0).getMessagesCount());
// Verify each message type was converted correctly
List<DaprProtos.ConversationMessage> capturedMessages = capturedRequest.getInputs(0).getMessagesList();
assertTrue(capturedMessages.get(0).hasOfSystem());
assertTrue(capturedMessages.get(1).hasOfUser());
assertTrue(capturedMessages.get(2).hasOfAssistant());
assertTrue(capturedMessages.get(3).hasOfTool());
assertTrue(capturedMessages.get(4).hasOfDeveloper());
}
@Test
public void converseAlpha2ResponseWithoutMessageTest() {
List<ConversationMessage> messages = new ArrayList<>();
DeveloperMessage devMsg = new DeveloperMessage(List.of(new ConversationMessageContent("Debug info")));
devMsg.setName("developer");
messages.add(devMsg);
ConversationInputAlpha2 input = new ConversationInputAlpha2(messages);
ConversationRequestAlpha2 request = new ConversationRequestAlpha2("openai", List.of(input));
DaprProtos.ConversationResponseAlpha2 grpcResponse = DaprProtos.ConversationResponseAlpha2.newBuilder()
.addOutputs(DaprProtos.ConversationResultAlpha2.newBuilder()
.addChoices(DaprProtos.ConversationResultChoices.newBuilder()
.setFinishReason("stop")
.setIndex(0)
// No message set
.build())
.build())
.build();
doAnswer((Answer<Void>) invocation -> {
StreamObserver<DaprProtos.ConversationResponseAlpha2> observer =
(StreamObserver<DaprProtos.ConversationResponseAlpha2>) invocation.getArguments()[1];
observer.onNext(grpcResponse);
observer.onCompleted();
return null;
}).when(daprStub).converseAlpha2(any(DaprProtos.ConversationRequestAlpha2.class), any());
ConversationResponseAlpha2 response = previewClient.converseAlpha2(request).block();
assertNotNull(response);
ConversationResultChoices choice = response.getOutputs().get(0).getChoices().get(0);
assertEquals("stop", choice.getFinishReason());
assertEquals(0, choice.getIndex());
assertNull(choice.getMessage());
}
@Test
public void converseAlpha2MultipleResultsTest() {
List<ConversationMessage> messages = new ArrayList<>();
DeveloperMessage devMsg = new DeveloperMessage(List.of(new ConversationMessageContent("Debug info")));
devMsg.setName("developer");
messages.add(devMsg);
ConversationInputAlpha2 input = new ConversationInputAlpha2(messages);
ConversationRequestAlpha2 request = new ConversationRequestAlpha2("openai", List.of(input));
DaprProtos.ConversationResponseAlpha2 grpcResponse = DaprProtos.ConversationResponseAlpha2.newBuilder()
.addOutputs(DaprProtos.ConversationResultAlpha2.newBuilder()
.addChoices(DaprProtos.ConversationResultChoices.newBuilder()
.setFinishReason("stop")
.setIndex(0)
.setMessage(DaprProtos.ConversationResultMessage.newBuilder()
.setContent("First choice")
.build())
.build())
.addChoices(DaprProtos.ConversationResultChoices.newBuilder()
.setFinishReason("stop")
.setIndex(1)
.setMessage(DaprProtos.ConversationResultMessage.newBuilder()
.setContent("Second choice")
.build())
.build())
.build())
.addOutputs(DaprProtos.ConversationResultAlpha2.newBuilder()
.addChoices(DaprProtos.ConversationResultChoices.newBuilder()
.setFinishReason("length")
.setIndex(0)
.setMessage(DaprProtos.ConversationResultMessage.newBuilder()
.setContent("Third result")
.build())
.build())
.build())
.build();
doAnswer((Answer<Void>) invocation -> {
StreamObserver<DaprProtos.ConversationResponseAlpha2> observer =
(StreamObserver<DaprProtos.ConversationResponseAlpha2>) invocation.getArguments()[1];
observer.onNext(grpcResponse);
observer.onCompleted();
return null;
}).when(daprStub).converseAlpha2(any(DaprProtos.ConversationRequestAlpha2.class), any());
ConversationResponseAlpha2 response = previewClient.converseAlpha2(request).block();
assertNotNull(response);
assertEquals(2, response.getOutputs().size());
// First result with 2 choices
ConversationResultAlpha2 firstResult = response.getOutputs().get(0);
assertEquals(2, firstResult.getChoices().size());
assertEquals("First choice", firstResult.getChoices().get(0).getMessage().getContent());
assertEquals("Second choice", firstResult.getChoices().get(1).getMessage().getContent());
// Second result with 1 choice
ConversationResultAlpha2 secondResult = response.getOutputs().get(1);
assertEquals(1, secondResult.getChoices().size());
assertEquals("Third result", secondResult.getChoices().get(0).getMessage().getContent());
}
@Test
public void converseAlpha2ToolCallWithoutFunctionTest() {
List<ConversationMessage> messages = new ArrayList<>();
UserMessage userMsg = new UserMessage(List.of(new ConversationMessageContent("Debug info")));
userMsg.setName("developer");
messages.add(userMsg);
ConversationInputAlpha2 input = new ConversationInputAlpha2(messages);
ConversationRequestAlpha2 request = new ConversationRequestAlpha2("openai", List.of(input));
DaprProtos.ConversationResponseAlpha2 grpcResponse = DaprProtos.ConversationResponseAlpha2.newBuilder()
.addOutputs(DaprProtos.ConversationResultAlpha2.newBuilder()
.addChoices(DaprProtos.ConversationResultChoices.newBuilder()
.setFinishReason("tool_calls")
.setIndex(0)
.setMessage(DaprProtos.ConversationResultMessage.newBuilder()
.setContent("Test content")
.addToolCalls(DaprProtos.ConversationToolCalls.newBuilder()
.setId("call_123")
// No function set
.build())
.build())
.build())
.build())
.build();
doAnswer((Answer<Void>) invocation -> {
StreamObserver<DaprProtos.ConversationResponseAlpha2> observer =
(StreamObserver<DaprProtos.ConversationResponseAlpha2>) invocation.getArguments()[1];
observer.onNext(grpcResponse);
observer.onCompleted();
return null;
}).when(daprStub).converseAlpha2(any(DaprProtos.ConversationRequestAlpha2.class), any());
ConversationResponseAlpha2 response = previewClient.converseAlpha2(request).block();
assertNotNull(response);
ConversationToolCalls toolCall = response.getOutputs().get(0).getChoices().get(0)
.getMessage().getToolCalls().get(0);
assertEquals("call_123", toolCall.getId());
assertNull(toolCall.getFunction());
}
private DaprProtos.QueryStateResponse buildQueryStateResponse(List<QueryStateItem<?>> resp,String token)
throws JsonProcessingException {
List<DaprProtos.QueryStateItem> items = new ArrayList<>();

View File

@ -0,0 +1,423 @@
/*
* Copyright 2021 The Dapr Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
limitations under the License.
*/
package io.dapr.client;
import com.google.protobuf.ListValue;
import com.google.protobuf.NullValue;
import com.google.protobuf.Struct;
import com.google.protobuf.Value;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class ProtobufValueHelperTest {
@Test
public void testToProtobufValue_Null() throws IOException {
Value result = ProtobufValueHelper.toProtobufValue(null);
assertNotNull(result);
assertTrue(result.hasNullValue());
assertEquals(NullValue.NULL_VALUE, result.getNullValue());
}
@Test
public void testToProtobufValue_Boolean_True() throws IOException {
Value result = ProtobufValueHelper.toProtobufValue(true);
assertNotNull(result);
assertTrue(result.hasBoolValue());
assertEquals(true, result.getBoolValue());
}
@Test
public void testToProtobufValue_Boolean_False() throws IOException {
Value result = ProtobufValueHelper.toProtobufValue(false);
assertNotNull(result);
assertTrue(result.hasBoolValue());
assertEquals(false, result.getBoolValue());
}
@Test
public void testToProtobufValue_String() throws IOException {
String testString = "Hello, World!";
Value result = ProtobufValueHelper.toProtobufValue(testString);
assertNotNull(result);
assertTrue(result.hasStringValue());
assertEquals(testString, result.getStringValue());
}
@Test
public void testToProtobufValue_String_Empty() throws IOException {
String emptyString = "";
Value result = ProtobufValueHelper.toProtobufValue(emptyString);
assertNotNull(result);
assertTrue(result.hasStringValue());
assertEquals(emptyString, result.getStringValue());
}
@Test
public void testToProtobufValue_Integer() throws IOException {
Integer testInt = 42;
Value result = ProtobufValueHelper.toProtobufValue(testInt);
assertNotNull(result);
assertTrue(result.hasNumberValue());
assertEquals(42.0, result.getNumberValue(), 0.001);
}
@Test
public void testToProtobufValue_Long() throws IOException {
Long testLong = 9876543210L;
Value result = ProtobufValueHelper.toProtobufValue(testLong);
assertNotNull(result);
assertTrue(result.hasNumberValue());
assertEquals(9876543210.0, result.getNumberValue(), 0.001);
}
@Test
public void testToProtobufValue_Double() throws IOException {
Double testDouble = 3.14159;
Value result = ProtobufValueHelper.toProtobufValue(testDouble);
assertNotNull(result);
assertTrue(result.hasNumberValue());
assertEquals(testDouble, result.getNumberValue(), 0.00001);
}
@Test
public void testToProtobufValue_Float() throws IOException {
Float testFloat = 2.718f;
Value result = ProtobufValueHelper.toProtobufValue(testFloat);
assertNotNull(result);
assertTrue(result.hasNumberValue());
assertEquals(2.718, result.getNumberValue(), 0.001);
}
@Test
public void testToProtobufValue_BigInteger() throws IOException {
BigInteger testBigInt = new BigInteger("123456789012345678901234567890");
Value result = ProtobufValueHelper.toProtobufValue(testBigInt);
assertNotNull(result);
assertTrue(result.hasNumberValue());
assertEquals(1.2345678901234568E29, result.getNumberValue(), 1E20);
}
@Test
public void testToProtobufValue_BigDecimal() throws IOException {
BigDecimal testBigDecimal = new BigDecimal("123.456789");
Value result = ProtobufValueHelper.toProtobufValue(testBigDecimal);
assertNotNull(result);
assertTrue(result.hasNumberValue());
assertEquals(123.456789, result.getNumberValue(), 0.000001);
}
@Test
public void testToProtobufValue_EmptyList() throws IOException {
List<Object> emptyList = new ArrayList<>();
Value result = ProtobufValueHelper.toProtobufValue(emptyList);
assertNotNull(result);
assertTrue(result.hasListValue());
ListValue listValue = result.getListValue();
assertEquals(0, listValue.getValuesCount());
}
@Test
public void testToProtobufValue_SimpleList() throws IOException {
List<Object> testList = Arrays.asList("hello", 42, true, null);
Value result = ProtobufValueHelper.toProtobufValue(testList);
assertNotNull(result);
assertTrue(result.hasListValue());
ListValue listValue = result.getListValue();
assertEquals(4, listValue.getValuesCount());
// Verify each element
assertEquals("hello", listValue.getValues(0).getStringValue());
assertEquals(42.0, listValue.getValues(1).getNumberValue(), 0.001);
assertEquals(true, listValue.getValues(2).getBoolValue());
assertEquals(NullValue.NULL_VALUE, listValue.getValues(3).getNullValue());
}
@Test
public void testToProtobufValue_NestedList() throws IOException {
List<Object> innerList = Arrays.asList(1, 2, 3);
List<Object> outerList = Arrays.asList("outer", innerList, "end");
Value result = ProtobufValueHelper.toProtobufValue(outerList);
assertNotNull(result);
assertTrue(result.hasListValue());
ListValue listValue = result.getListValue();
assertEquals(3, listValue.getValuesCount());
// Verify nested list
assertEquals("outer", listValue.getValues(0).getStringValue());
assertTrue(listValue.getValues(1).hasListValue());
ListValue nestedList = listValue.getValues(1).getListValue();
assertEquals(3, nestedList.getValuesCount());
assertEquals(1.0, nestedList.getValues(0).getNumberValue(), 0.001);
assertEquals(2.0, nestedList.getValues(1).getNumberValue(), 0.001);
assertEquals(3.0, nestedList.getValues(2).getNumberValue(), 0.001);
assertEquals("end", listValue.getValues(2).getStringValue());
}
@Test
public void testToProtobufValue_EmptyMap() throws IOException {
Map<String, Object> emptyMap = new HashMap<>();
Value result = ProtobufValueHelper.toProtobufValue(emptyMap);
assertNotNull(result);
assertTrue(result.hasStructValue());
Struct struct = result.getStructValue();
assertEquals(0, struct.getFieldsCount());
}
@Test
public void testToProtobufValue_SimpleMap() throws IOException {
Map<String, Object> testMap = new LinkedHashMap<>();
testMap.put("name", "John Doe");
testMap.put("age", 30);
testMap.put("active", true);
testMap.put("description", null);
Value result = ProtobufValueHelper.toProtobufValue(testMap);
assertNotNull(result);
assertTrue(result.hasStructValue());
Struct struct = result.getStructValue();
assertEquals(4, struct.getFieldsCount());
// Verify each field
assertEquals("John Doe", struct.getFieldsMap().get("name").getStringValue());
assertEquals(30.0, struct.getFieldsMap().get("age").getNumberValue(), 0.001);
assertEquals(true, struct.getFieldsMap().get("active").getBoolValue());
assertEquals(NullValue.NULL_VALUE, struct.getFieldsMap().get("description").getNullValue());
}
@Test
public void testToProtobufValue_NestedMap() throws IOException {
Map<String, Object> innerMap = new HashMap<>();
innerMap.put("city", "New York");
innerMap.put("zipcode", 10001);
Map<String, Object> outerMap = new HashMap<>();
outerMap.put("name", "John");
outerMap.put("address", innerMap);
outerMap.put("hobbies", Arrays.asList("reading", "coding"));
Value result = ProtobufValueHelper.toProtobufValue(outerMap);
assertNotNull(result);
assertTrue(result.hasStructValue());
Struct struct = result.getStructValue();
assertEquals(3, struct.getFieldsCount());
// Verify nested structure
assertEquals("John", struct.getFieldsMap().get("name").getStringValue());
// Verify nested map
assertTrue(struct.getFieldsMap().get("address").hasStructValue());
Struct nestedStruct = struct.getFieldsMap().get("address").getStructValue();
assertEquals("New York", nestedStruct.getFieldsMap().get("city").getStringValue());
assertEquals(10001.0, nestedStruct.getFieldsMap().get("zipcode").getNumberValue(), 0.001);
// Verify nested list
assertTrue(struct.getFieldsMap().get("hobbies").hasListValue());
ListValue hobbiesList = struct.getFieldsMap().get("hobbies").getListValue();
assertEquals(2, hobbiesList.getValuesCount());
assertEquals("reading", hobbiesList.getValues(0).getStringValue());
assertEquals("coding", hobbiesList.getValues(1).getStringValue());
}
@Test
public void testToProtobufValue_MapWithNonStringKeys() throws IOException {
Map<Integer, String> intKeyMap = new HashMap<>();
intKeyMap.put(1, "one");
intKeyMap.put(2, "two");
Value result = ProtobufValueHelper.toProtobufValue(intKeyMap);
assertNotNull(result);
assertTrue(result.hasStructValue());
Struct struct = result.getStructValue();
assertEquals(2, struct.getFieldsCount());
// Keys should be converted to strings
assertTrue(struct.getFieldsMap().containsKey("1"));
assertTrue(struct.getFieldsMap().containsKey("2"));
assertEquals("one", struct.getFieldsMap().get("1").getStringValue());
assertEquals("two", struct.getFieldsMap().get("2").getStringValue());
}
@Test
public void testToProtobufValue_CustomObject() throws IOException {
// Test with a custom object that will fall back to toString()
TestCustomObject customObj = new TestCustomObject("test", 123);
Value result = ProtobufValueHelper.toProtobufValue(customObj);
assertNotNull(result);
assertTrue(result.hasStringValue());
assertEquals("TestCustomObject{name='test', value=123}", result.getStringValue());
}
@Test
public void testToProtobufValue_ComplexNestedStructure() throws IOException {
// Create a complex nested structure
Map<String, Object> config = new HashMap<>();
config.put("timeout", 30);
config.put("retries", 3);
Map<String, Object> server = new HashMap<>();
server.put("host", "localhost");
server.put("port", 8080);
server.put("ssl", true);
server.put("config", config);
List<String> tags = Arrays.asList("prod", "critical", "monitoring");
Map<String, Object> application = new HashMap<>();
application.put("name", "my-app");
application.put("version", "1.0.0");
application.put("server", server);
application.put("tags", tags);
application.put("metadata", null);
Value result = ProtobufValueHelper.toProtobufValue(application);
assertNotNull(result);
assertTrue(result.hasStructValue());
Struct appStruct = result.getStructValue();
// Verify top-level fields
assertEquals("my-app", appStruct.getFieldsMap().get("name").getStringValue());
assertEquals("1.0.0", appStruct.getFieldsMap().get("version").getStringValue());
assertEquals(NullValue.NULL_VALUE, appStruct.getFieldsMap().get("metadata").getNullValue());
// Verify server object
assertTrue(appStruct.getFieldsMap().get("server").hasStructValue());
Struct serverStruct = appStruct.getFieldsMap().get("server").getStructValue();
assertEquals("localhost", serverStruct.getFieldsMap().get("host").getStringValue());
assertEquals(8080.0, serverStruct.getFieldsMap().get("port").getNumberValue(), 0.001);
assertEquals(true, serverStruct.getFieldsMap().get("ssl").getBoolValue());
// Verify nested config
assertTrue(serverStruct.getFieldsMap().get("config").hasStructValue());
Struct configStruct = serverStruct.getFieldsMap().get("config").getStructValue();
assertEquals(30.0, configStruct.getFieldsMap().get("timeout").getNumberValue(), 0.001);
assertEquals(3.0, configStruct.getFieldsMap().get("retries").getNumberValue(), 0.001);
// Verify tags list
assertTrue(appStruct.getFieldsMap().get("tags").hasListValue());
ListValue tagsList = appStruct.getFieldsMap().get("tags").getListValue();
assertEquals(3, tagsList.getValuesCount());
assertEquals("prod", tagsList.getValues(0).getStringValue());
assertEquals("critical", tagsList.getValues(1).getStringValue());
assertEquals("monitoring", tagsList.getValues(2).getStringValue());
}
@Test
public void testToProtobufValue_OpenAPIFunctionSchema() throws IOException {
// Test with the exact schema structure provided by the user
Map<String, Object> functionSchema = new LinkedHashMap<>();
functionSchema.put("type", "function");
functionSchema.put("name", "get_horoscope");
functionSchema.put("description", "Get today's horoscope for an astrological sign.");
Map<String, Object> parameters = new LinkedHashMap<>();
parameters.put("type", "object");
Map<String, Object> properties = new LinkedHashMap<>();
Map<String, Object> signProperty = new LinkedHashMap<>();
signProperty.put("type", "string");
signProperty.put("description", "An astrological sign like Taurus or Aquarius");
properties.put("sign", signProperty);
parameters.put("properties", properties);
parameters.put("required", Arrays.asList("sign"));
functionSchema.put("parameters", parameters);
Value result = ProtobufValueHelper.toProtobufValue(functionSchema);
assertNotNull(result);
assertTrue(result.hasStructValue());
Struct rootStruct = result.getStructValue();
// Verify root level fields
assertEquals("function", rootStruct.getFieldsMap().get("type").getStringValue());
assertEquals("get_horoscope", rootStruct.getFieldsMap().get("name").getStringValue());
assertEquals("Get today's horoscope for an astrological sign.",
rootStruct.getFieldsMap().get("description").getStringValue());
// Verify parameters object
assertTrue(rootStruct.getFieldsMap().get("parameters").hasStructValue());
Struct parametersStruct = rootStruct.getFieldsMap().get("parameters").getStructValue();
assertEquals("object", parametersStruct.getFieldsMap().get("type").getStringValue());
// Verify properties object
assertTrue(parametersStruct.getFieldsMap().get("properties").hasStructValue());
Struct propertiesStruct = parametersStruct.getFieldsMap().get("properties").getStructValue();
// Verify sign property
assertTrue(propertiesStruct.getFieldsMap().get("sign").hasStructValue());
Struct signStruct = propertiesStruct.getFieldsMap().get("sign").getStructValue();
assertEquals("string", signStruct.getFieldsMap().get("type").getStringValue());
assertEquals("An astrological sign like Taurus or Aquarius",
signStruct.getFieldsMap().get("description").getStringValue());
// Verify required array
assertTrue(parametersStruct.getFieldsMap().get("required").hasListValue());
ListValue requiredList = parametersStruct.getFieldsMap().get("required").getListValue();
assertEquals(1, requiredList.getValuesCount());
assertEquals("sign", requiredList.getValues(0).getStringValue());
}
/**
* Helper class for testing custom object conversion
*/
private static class TestCustomObject {
private final String name;
private final int value;
public TestCustomObject(String name, int value) {
this.name = name;
this.value = value;
}
@Override
public String toString() {
return "TestCustomObject{name='" + name + "', value=" + value + "}";
}
}
}