pygeai 0.1.6__py3-none-any.whl → 0.6.0b15__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pygeai/__init__.py +11 -2
- pygeai/_docs/Makefile +20 -0
- pygeai/_docs/make.bat +35 -0
- pygeai/_docs/source/conf.py +117 -0
- pygeai/_docs/source/content/ai_lab/cli.rst +747 -0
- pygeai/_docs/source/content/ai_lab/models.rst +1734 -0
- pygeai/_docs/source/content/ai_lab/runner.rst +253 -0
- pygeai/_docs/source/content/ai_lab/spec.rst +431 -0
- pygeai/_docs/source/content/ai_lab/usage.rst +1011 -0
- pygeai/_docs/source/content/ai_lab.rst +102 -0
- pygeai/_docs/source/content/analytics.rst +598 -0
- pygeai/_docs/source/content/api_reference/admin.rst +161 -0
- pygeai/_docs/source/content/api_reference/assistant.rst +326 -0
- pygeai/_docs/source/content/api_reference/auth.rst +379 -0
- pygeai/_docs/source/content/api_reference/chat.rst +754 -0
- pygeai/_docs/source/content/api_reference/embeddings.rst +154 -0
- pygeai/_docs/source/content/api_reference/evaluation.rst +590 -0
- pygeai/_docs/source/content/api_reference/feedback.rst +237 -0
- pygeai/_docs/source/content/api_reference/files.rst +592 -0
- pygeai/_docs/source/content/api_reference/gam.rst +401 -0
- pygeai/_docs/source/content/api_reference/health.rst +58 -0
- pygeai/_docs/source/content/api_reference/project.rst +738 -0
- pygeai/_docs/source/content/api_reference/proxy.rst +318 -0
- pygeai/_docs/source/content/api_reference/rag.rst +710 -0
- pygeai/_docs/source/content/api_reference/rerank.rst +94 -0
- pygeai/_docs/source/content/api_reference/secrets.rst +495 -0
- pygeai/_docs/source/content/api_reference/usage_limits.rst +390 -0
- pygeai/_docs/source/content/api_reference.rst +58 -0
- pygeai/_docs/source/content/authentication.rst +295 -0
- pygeai/_docs/source/content/chat_gui.rst +121 -0
- pygeai/_docs/source/content/cli.rst +203 -0
- pygeai/_docs/source/content/debugger.rst +651 -0
- pygeai/_docs/source/content/intro.rst +67 -0
- pygeai/_docs/source/content/migration.rst +929 -0
- pygeai/_docs/source/content/modules.rst +7 -0
- pygeai/_docs/source/content/quickstart.rst +143 -0
- pygeai/_docs/source/content/samples.rst +394 -0
- pygeai/_docs/source/index.rst +75 -0
- pygeai/_docs/source/modules.rst +7 -0
- pygeai/_docs/source/pygeai.admin.rst +29 -0
- pygeai/_docs/source/pygeai.analytics.rst +53 -0
- pygeai/_docs/source/pygeai.assistant.data.rst +21 -0
- pygeai/_docs/source/pygeai.assistant.data_analyst.rst +29 -0
- pygeai/_docs/source/pygeai.assistant.rag.rst +53 -0
- pygeai/_docs/source/pygeai.assistant.rst +55 -0
- pygeai/_docs/source/pygeai.auth.rst +29 -0
- pygeai/_docs/source/pygeai.chat.rst +69 -0
- pygeai/_docs/source/pygeai.cli.commands.flows.rst +10 -0
- pygeai/_docs/source/pygeai.cli.commands.lab.rst +53 -0
- pygeai/_docs/source/pygeai.cli.commands.rst +222 -0
- pygeai/_docs/source/pygeai.cli.rst +62 -0
- pygeai/_docs/source/pygeai.cli.texts.rst +21 -0
- pygeai/_docs/source/pygeai.core.base.rst +53 -0
- pygeai/_docs/source/pygeai.core.common.rst +37 -0
- pygeai/_docs/source/pygeai.core.embeddings.rst +61 -0
- pygeai/_docs/source/pygeai.core.feedback.rst +37 -0
- pygeai/_docs/source/pygeai.core.files.rst +61 -0
- pygeai/_docs/source/pygeai.core.llm.rst +29 -0
- pygeai/_docs/source/pygeai.core.plugins.rst +37 -0
- pygeai/_docs/source/pygeai.core.rerank.rst +53 -0
- pygeai/_docs/source/pygeai.core.rst +63 -0
- pygeai/_docs/source/pygeai.core.secrets.rst +29 -0
- pygeai/_docs/source/pygeai.core.services.llm.rst +29 -0
- pygeai/_docs/source/pygeai.core.services.rst +37 -0
- pygeai/_docs/source/pygeai.core.utils.rst +37 -0
- pygeai/_docs/source/pygeai.dbg.rst +21 -0
- pygeai/_docs/source/pygeai.evaluation.dataset.rst +29 -0
- pygeai/_docs/source/pygeai.evaluation.plan.rst +29 -0
- pygeai/_docs/source/pygeai.evaluation.result.rst +29 -0
- pygeai/_docs/source/pygeai.evaluation.rst +31 -0
- pygeai/_docs/source/pygeai.flows.rst +29 -0
- pygeai/_docs/source/pygeai.gam.rst +29 -0
- pygeai/_docs/source/pygeai.health.rst +29 -0
- pygeai/_docs/source/pygeai.lab.agents.rst +37 -0
- pygeai/_docs/source/pygeai.lab.processes.rst +37 -0
- pygeai/_docs/source/pygeai.lab.rst +65 -0
- pygeai/_docs/source/pygeai.lab.spec.rst +29 -0
- pygeai/_docs/source/pygeai.lab.strategies.rst +37 -0
- pygeai/_docs/source/pygeai.lab.tools.rst +37 -0
- pygeai/_docs/source/pygeai.man.man1.rst +10 -0
- pygeai/_docs/source/pygeai.man.rst +18 -0
- pygeai/_docs/source/pygeai.migration.rst +29 -0
- pygeai/_docs/source/pygeai.organization.limits.rst +45 -0
- pygeai/_docs/source/pygeai.organization.rst +61 -0
- pygeai/_docs/source/pygeai.proxy.rst +53 -0
- pygeai/_docs/source/pygeai.rst +35 -0
- pygeai/_docs/source/pygeai.tests.admin.rst +21 -0
- pygeai/_docs/source/pygeai.tests.analytics.rst +45 -0
- pygeai/_docs/source/pygeai.tests.assistants.rag.rst +37 -0
- pygeai/_docs/source/pygeai.tests.assistants.rst +45 -0
- pygeai/_docs/source/pygeai.tests.auth.rst +29 -0
- pygeai/_docs/source/pygeai.tests.chat.rst +45 -0
- pygeai/_docs/source/pygeai.tests.cli.commands.lab.rst +37 -0
- pygeai/_docs/source/pygeai.tests.cli.commands.rst +165 -0
- pygeai/_docs/source/pygeai.tests.cli.docker.rst +10 -0
- pygeai/_docs/source/pygeai.tests.cli.rst +46 -0
- pygeai/_docs/source/pygeai.tests.core.base.data.rst +29 -0
- pygeai/_docs/source/pygeai.tests.core.base.rst +45 -0
- pygeai/_docs/source/pygeai.tests.core.common.data.rst +10 -0
- pygeai/_docs/source/pygeai.tests.core.common.rst +37 -0
- pygeai/_docs/source/pygeai.tests.core.embeddings.rst +37 -0
- pygeai/_docs/source/pygeai.tests.core.feedback.rst +21 -0
- pygeai/_docs/source/pygeai.tests.core.files.rst +53 -0
- pygeai/_docs/source/pygeai.tests.core.llm.rst +21 -0
- pygeai/_docs/source/pygeai.tests.core.plugins.rst +21 -0
- pygeai/_docs/source/pygeai.tests.core.rerank.rst +37 -0
- pygeai/_docs/source/pygeai.tests.core.rst +39 -0
- pygeai/_docs/source/pygeai.tests.core.secrets.rst +21 -0
- pygeai/_docs/source/pygeai.tests.core.services.rst +21 -0
- pygeai/_docs/source/pygeai.tests.core.utils.rst +21 -0
- pygeai/_docs/source/pygeai.tests.dbg.rst +21 -0
- pygeai/_docs/source/pygeai.tests.evaluation.dataset.rst +21 -0
- pygeai/_docs/source/pygeai.tests.evaluation.plan.rst +21 -0
- pygeai/_docs/source/pygeai.tests.evaluation.result.rst +21 -0
- pygeai/_docs/source/pygeai.tests.evaluation.rst +20 -0
- pygeai/_docs/source/pygeai.tests.gam.rst +21 -0
- pygeai/_docs/source/pygeai.tests.health.rst +21 -0
- pygeai/_docs/source/pygeai.tests.integration.assistants.rag.rst +21 -0
- pygeai/_docs/source/pygeai.tests.integration.assistants.rst +18 -0
- pygeai/_docs/source/pygeai.tests.integration.chat.rst +21 -0
- pygeai/_docs/source/pygeai.tests.integration.lab.agents.rst +69 -0
- pygeai/_docs/source/pygeai.tests.integration.lab.processes.rst +77 -0
- pygeai/_docs/source/pygeai.tests.integration.lab.reasoning_strategies.rst +37 -0
- pygeai/_docs/source/pygeai.tests.integration.lab.rst +21 -0
- pygeai/_docs/source/pygeai.tests.integration.lab.tools.rst +77 -0
- pygeai/_docs/source/pygeai.tests.integration.rst +20 -0
- pygeai/_docs/source/pygeai.tests.lab.agents.rst +29 -0
- pygeai/_docs/source/pygeai.tests.lab.processes.rst +29 -0
- pygeai/_docs/source/pygeai.tests.lab.rst +49 -0
- pygeai/_docs/source/pygeai.tests.lab.spec.rst +29 -0
- pygeai/_docs/source/pygeai.tests.lab.strategies.rst +29 -0
- pygeai/_docs/source/pygeai.tests.lab.tools.rst +29 -0
- pygeai/_docs/source/pygeai.tests.migration.rst +29 -0
- pygeai/_docs/source/pygeai.tests.organization.limits.rst +29 -0
- pygeai/_docs/source/pygeai.tests.organization.rst +53 -0
- pygeai/_docs/source/pygeai.tests.proxy.rst +61 -0
- pygeai/_docs/source/pygeai.tests.rst +33 -0
- pygeai/admin/clients.py +14 -11
- pygeai/admin/endpoints.py +2 -2
- pygeai/analytics/clients.py +505 -0
- pygeai/analytics/endpoints.py +35 -0
- pygeai/analytics/managers.py +606 -0
- pygeai/analytics/mappers.py +207 -0
- pygeai/analytics/responses.py +240 -0
- pygeai/assistant/clients.py +48 -57
- pygeai/assistant/data/__init__.py +0 -0
- pygeai/assistant/data/clients.py +15 -0
- pygeai/assistant/data_analyst/__init__.py +0 -0
- pygeai/assistant/data_analyst/clients.py +75 -0
- pygeai/assistant/data_analyst/endpoints.py +2 -0
- pygeai/assistant/endpoints.py +0 -2
- pygeai/assistant/managers.py +738 -0
- pygeai/assistant/mappers.py +153 -0
- pygeai/assistant/rag/clients.py +132 -21
- pygeai/assistant/rag/mappers.py +228 -0
- pygeai/assistant/rag/models.py +396 -0
- pygeai/assistant/rag/responses.py +10 -0
- pygeai/auth/__init__.py +0 -0
- pygeai/auth/clients.py +129 -0
- pygeai/auth/endpoints.py +6 -0
- pygeai/chat/clients.py +406 -31
- pygeai/chat/endpoints.py +3 -0
- pygeai/chat/iris.py +17 -0
- pygeai/chat/managers.py +64 -0
- pygeai/chat/session.py +38 -0
- pygeai/chat/settings.py +6 -0
- pygeai/chat/ui.py +678 -0
- pygeai/cli/__init__.py +0 -1
- pygeai/cli/commands/admin.py +9 -12
- pygeai/cli/commands/analytics.py +533 -0
- pygeai/cli/commands/assistant.py +11 -11
- pygeai/cli/commands/auth.py +299 -0
- pygeai/cli/commands/base.py +201 -7
- pygeai/cli/commands/chat.py +875 -14
- pygeai/cli/commands/common.py +30 -26
- pygeai/cli/commands/configuration.py +84 -9
- pygeai/cli/commands/docs.py +105 -0
- pygeai/cli/commands/embeddings.py +187 -0
- pygeai/cli/commands/evaluation.py +2069 -0
- pygeai/cli/commands/feedback.py +93 -0
- pygeai/cli/commands/files.py +312 -0
- pygeai/cli/commands/flows/__init__.py +0 -0
- pygeai/cli/commands/gam.py +349 -0
- pygeai/cli/commands/lab/__init__.py +0 -0
- pygeai/cli/commands/lab/ai_lab.py +4110 -0
- pygeai/cli/commands/lab/common.py +135 -0
- pygeai/cli/commands/lab/options.py +8 -0
- pygeai/cli/commands/lab/spec.py +273 -0
- pygeai/cli/commands/lab/utils.py +13 -0
- pygeai/cli/commands/llm.py +164 -0
- pygeai/cli/commands/migrate.py +1198 -0
- pygeai/cli/commands/options.py +86 -0
- pygeai/cli/commands/organization.py +560 -98
- pygeai/cli/commands/rag.py +306 -10
- pygeai/cli/commands/rerank.py +108 -0
- pygeai/cli/commands/secrets.py +357 -0
- pygeai/cli/commands/usage_limits.py +583 -0
- pygeai/cli/commands/validators.py +209 -0
- pygeai/cli/commands/version.py +44 -0
- pygeai/cli/error_handler.py +151 -0
- pygeai/cli/geai.py +171 -30
- pygeai/cli/geai_proxy.py +318 -0
- pygeai/cli/install_man.py +107 -0
- pygeai/cli/parsers.py +78 -25
- pygeai/cli/texts/help.py +712 -55
- pygeai/core/__init__.py +9 -1
- pygeai/core/base/clients.py +61 -10
- pygeai/core/base/mappers.py +208 -30
- pygeai/core/base/models.py +8 -308
- pygeai/core/base/responses.py +18 -1
- pygeai/core/base/session.py +110 -17
- pygeai/core/common/config.py +98 -16
- pygeai/core/common/decorators.py +44 -0
- pygeai/core/common/exceptions.py +104 -4
- pygeai/core/embeddings/__init__.py +19 -0
- pygeai/core/embeddings/clients.py +93 -0
- pygeai/core/embeddings/endpoints.py +1 -0
- pygeai/core/embeddings/managers.py +62 -0
- pygeai/core/embeddings/mappers.py +52 -0
- pygeai/core/embeddings/models.py +14 -0
- pygeai/core/embeddings/responses.py +31 -0
- pygeai/core/feedback/__init__.py +0 -0
- pygeai/core/feedback/clients.py +50 -0
- pygeai/core/feedback/endpoints.py +1 -0
- pygeai/core/feedback/models.py +10 -0
- pygeai/core/files/__init__.py +0 -0
- pygeai/core/files/clients.py +156 -0
- pygeai/core/files/endpoints.py +5 -0
- pygeai/core/files/managers.py +224 -0
- pygeai/core/files/mappers.py +44 -0
- pygeai/core/files/models.py +24 -0
- pygeai/core/files/responses.py +19 -0
- pygeai/core/handlers.py +32 -0
- pygeai/core/llm/__init__.py +0 -0
- pygeai/core/llm/clients.py +53 -0
- pygeai/core/llm/endpoints.py +4 -0
- pygeai/core/models.py +799 -0
- pygeai/core/plugins/__init__.py +0 -0
- pygeai/core/plugins/clients.py +32 -0
- pygeai/core/plugins/endpoints.py +1 -0
- pygeai/core/plugins/models.py +86 -0
- pygeai/core/rerank/__init__.py +0 -0
- pygeai/core/rerank/clients.py +35 -0
- pygeai/core/rerank/endpoints.py +1 -0
- pygeai/core/rerank/managers.py +47 -0
- pygeai/core/rerank/mappers.py +23 -0
- pygeai/core/rerank/models.py +27 -0
- pygeai/core/responses.py +104 -0
- pygeai/core/secrets/__init__.py +0 -0
- pygeai/core/secrets/clients.py +212 -0
- pygeai/core/secrets/endpoints.py +7 -0
- pygeai/core/services/llm/__init__.py +0 -0
- pygeai/core/services/llm/model.py +186 -0
- pygeai/core/services/llm/providers.py +15 -0
- pygeai/core/services/response.py +18 -0
- pygeai/core/services/rest.py +311 -89
- pygeai/core/utils/__init__.py +0 -0
- pygeai/core/utils/console.py +83 -0
- pygeai/core/utils/parsers.py +32 -0
- pygeai/core/utils/validators.py +10 -0
- pygeai/dbg/__init__.py +3 -0
- pygeai/dbg/debugger.py +870 -0
- pygeai/evaluation/__init__.py +0 -0
- pygeai/evaluation/clients.py +19 -0
- pygeai/evaluation/dataset/__init__.py +0 -0
- pygeai/evaluation/dataset/clients.py +514 -0
- pygeai/evaluation/dataset/endpoints.py +26 -0
- pygeai/evaluation/plan/__init__.py +0 -0
- pygeai/evaluation/plan/clients.py +302 -0
- pygeai/evaluation/plan/endpoints.py +16 -0
- pygeai/evaluation/result/__init__.py +0 -0
- pygeai/evaluation/result/clients.py +70 -0
- pygeai/evaluation/result/endpoints.py +2 -0
- pygeai/flows/__init__.py +0 -0
- pygeai/flows/endpoints.py +362 -0
- pygeai/flows/models.py +1304 -0
- pygeai/gam/__init__.py +0 -0
- pygeai/gam/clients.py +178 -0
- pygeai/gam/endpoints.py +4 -0
- pygeai/health/__init__.py +0 -0
- pygeai/health/clients.py +24 -0
- pygeai/health/endpoints.py +1 -0
- pygeai/lab/__init__.py +0 -0
- pygeai/lab/agents/__init__.py +0 -0
- pygeai/lab/agents/clients.py +426 -0
- pygeai/lab/agents/endpoints.py +12 -0
- pygeai/lab/agents/mappers.py +319 -0
- pygeai/lab/clients.py +24 -0
- pygeai/lab/constants.py +3 -0
- pygeai/lab/managers.py +1558 -0
- pygeai/lab/models.py +1719 -0
- pygeai/lab/processes/__init__.py +0 -0
- pygeai/lab/processes/clients.py +1051 -0
- pygeai/lab/processes/endpoints.py +26 -0
- pygeai/lab/processes/mappers.py +395 -0
- pygeai/lab/runners.py +90 -0
- pygeai/lab/spec/__init__.py +0 -0
- pygeai/lab/spec/loader.py +24 -0
- pygeai/lab/spec/parsers.py +39 -0
- pygeai/lab/strategies/__init__.py +0 -0
- pygeai/lab/strategies/clients.py +212 -0
- pygeai/lab/strategies/endpoints.py +5 -0
- pygeai/lab/strategies/mappers.py +58 -0
- pygeai/lab/tools/__init__.py +0 -0
- pygeai/lab/tools/clients.py +465 -0
- pygeai/lab/tools/endpoints.py +13 -0
- pygeai/lab/tools/mappers.py +131 -0
- pygeai/man/__init__.py +1 -0
- pygeai/man/man1/__init__.py +1 -0
- pygeai/man/man1/geai-proxy.1 +246 -0
- pygeai/man/man1/geai.1 +2615 -0
- pygeai/migration/__init__.py +33 -0
- pygeai/migration/strategies.py +603 -0
- pygeai/migration/tools.py +180 -0
- pygeai/organization/clients.py +246 -18
- pygeai/organization/endpoints.py +17 -8
- pygeai/organization/limits/__init__.py +0 -0
- pygeai/organization/limits/clients.py +281 -0
- pygeai/organization/limits/endpoints.py +15 -0
- pygeai/organization/limits/managers.py +331 -0
- pygeai/organization/limits/mappers.py +21 -0
- pygeai/organization/managers.py +537 -0
- pygeai/organization/mappers.py +111 -46
- pygeai/organization/responses.py +61 -11
- pygeai/proxy/__init__.py +0 -0
- pygeai/proxy/clients.py +216 -0
- pygeai/proxy/config.py +128 -0
- pygeai/proxy/managers.py +232 -0
- pygeai/proxy/servers.py +304 -0
- pygeai/proxy/tool.py +69 -0
- pygeai/tests/admin/__init__.py +0 -0
- pygeai/tests/admin/test_clients.py +148 -0
- pygeai/tests/analytics/__init__.py +0 -0
- pygeai/tests/analytics/test_clients.py +86 -0
- pygeai/tests/analytics/test_managers.py +94 -0
- pygeai/tests/analytics/test_mappers.py +84 -0
- pygeai/tests/analytics/test_responses.py +73 -0
- pygeai/tests/assistants/rag/__init__.py +0 -0
- pygeai/tests/assistants/rag/test_clients.py +346 -0
- pygeai/tests/assistants/rag/test_mappers.py +189 -0
- pygeai/tests/assistants/rag/test_models.py +292 -0
- pygeai/tests/assistants/test_clients.py +176 -80
- pygeai/tests/assistants/test_managers.py +198 -0
- pygeai/tests/assistants/test_mappers.py +111 -0
- pygeai/tests/auth/__init__.py +0 -0
- pygeai/tests/auth/test_clients.py +289 -0
- pygeai/tests/auth/test_oauth.py +172 -0
- pygeai/tests/auth/test_session_logging.py +150 -0
- pygeai/tests/chat/__init__.py +0 -0
- pygeai/tests/chat/test_clients.py +393 -0
- pygeai/tests/chat/test_iris.py +38 -0
- pygeai/tests/chat/test_session.py +62 -0
- pygeai/tests/chat/test_ui.py +224 -0
- pygeai/tests/cli/__init__.py +0 -0
- pygeai/tests/cli/commands/__init__.py +0 -0
- pygeai/tests/cli/commands/lab/__init__.py +0 -0
- pygeai/tests/cli/commands/lab/test_ai_lab.py +786 -0
- pygeai/tests/cli/commands/lab/test_common.py +208 -0
- pygeai/tests/cli/commands/lab/test_spec.py +246 -0
- pygeai/tests/cli/commands/test_assistant.py +202 -0
- pygeai/tests/cli/commands/test_chat.py +130 -0
- pygeai/tests/cli/commands/test_common.py +350 -0
- pygeai/tests/cli/commands/test_embeddings.py +132 -0
- pygeai/tests/cli/commands/test_evaluation.py +656 -0
- pygeai/tests/cli/commands/test_feedback.py +65 -0
- pygeai/tests/cli/commands/test_files.py +161 -0
- pygeai/tests/cli/commands/test_gam.py +201 -0
- pygeai/tests/cli/commands/test_llm.py +114 -0
- pygeai/tests/cli/commands/test_migrate.py +176 -0
- pygeai/tests/cli/commands/test_organization.py +276 -0
- pygeai/tests/cli/commands/test_rag.py +266 -0
- pygeai/tests/cli/commands/test_rerank.py +110 -0
- pygeai/tests/cli/commands/test_secrets.py +171 -0
- pygeai/tests/cli/commands/test_show_help.py +41 -0
- pygeai/tests/cli/commands/test_usage_limits.py +412 -0
- pygeai/tests/cli/commands/test_validators.py +160 -0
- pygeai/tests/cli/commands/test_version.py +81 -0
- pygeai/tests/cli/docker/__init__.py +0 -0
- pygeai/tests/cli/test_credentials_flag.py +316 -0
- pygeai/tests/cli/test_error_handler.py +225 -0
- pygeai/tests/cli/test_geai_driver.py +154 -0
- pygeai/tests/cli/test_parsers.py +154 -0
- pygeai/tests/core/base/__init__.py +0 -0
- pygeai/tests/core/base/data/__init__.py +0 -0
- pygeai/tests/core/base/data/mappers.py +117 -0
- pygeai/tests/core/base/data/models.py +312 -0
- pygeai/tests/core/base/test_mappers.py +569 -0
- pygeai/tests/core/base/test_models.py +261 -0
- pygeai/tests/core/base/test_responses.py +53 -0
- pygeai/tests/core/common/__init__.py +0 -0
- pygeai/tests/core/common/data/__init__.py +0 -0
- pygeai/tests/core/common/test_config.py +186 -0
- pygeai/tests/core/common/test_decorators.py +69 -0
- pygeai/tests/core/embeddings/__init__.py +0 -0
- pygeai/tests/core/embeddings/test_clients.py +225 -0
- pygeai/tests/core/embeddings/test_managers.py +171 -0
- pygeai/tests/core/embeddings/test_mappers.py +142 -0
- pygeai/tests/core/feedback/__init__.py +0 -0
- pygeai/tests/core/feedback/test_clients.py +64 -0
- pygeai/tests/core/files/__init__.py +0 -0
- pygeai/tests/core/files/test_clients.py +128 -0
- pygeai/tests/core/files/test_managers.py +219 -0
- pygeai/tests/core/files/test_mappers.py +137 -0
- pygeai/tests/core/files/test_models.py +103 -0
- pygeai/tests/core/files/test_responses.py +122 -0
- pygeai/tests/core/llm/__init__.py +0 -0
- pygeai/tests/core/llm/test_clients.py +142 -0
- pygeai/tests/core/plugins/__init__.py +0 -0
- pygeai/tests/core/plugins/test_clients.py +66 -0
- pygeai/tests/core/rerank/__init__.py +0 -0
- pygeai/tests/core/rerank/test_clients.py +76 -0
- pygeai/tests/core/rerank/test_managers.py +99 -0
- pygeai/tests/core/rerank/test_mappers.py +54 -0
- pygeai/tests/core/secrets/__init__.py +0 -0
- pygeai/tests/core/secrets/test_clients.py +264 -0
- pygeai/tests/core/services/__init__.py +0 -0
- pygeai/tests/core/services/test_rest.py +273 -0
- pygeai/tests/core/test_handlers.py +66 -0
- pygeai/tests/core/utils/__init__.py +0 -0
- pygeai/tests/core/utils/test_console.py +80 -0
- pygeai/tests/dbg/__init__.py +0 -0
- pygeai/tests/dbg/test_debugger.py +591 -0
- pygeai/tests/evaluation/__init__.py +0 -0
- pygeai/tests/evaluation/dataset/__init__.py +0 -0
- pygeai/tests/evaluation/dataset/test_clients.py +265 -0
- pygeai/tests/evaluation/plan/__init__.py +0 -0
- pygeai/tests/evaluation/plan/test_clients.py +195 -0
- pygeai/tests/evaluation/result/__init__.py +0 -0
- pygeai/tests/evaluation/result/test_clients.py +66 -0
- pygeai/tests/gam/__init__.py +0 -0
- pygeai/tests/gam/test_clients.py +195 -0
- pygeai/tests/health/__init__.py +0 -0
- pygeai/tests/health/test_clients.py +41 -0
- pygeai/tests/integration/__init__.py +0 -0
- pygeai/tests/integration/assistants/__init__.py +0 -0
- pygeai/tests/integration/assistants/rag/__init__.py +0 -0
- pygeai/tests/integration/assistants/rag/test_create_rag.py +91 -0
- pygeai/tests/integration/chat/__init__.py +0 -0
- pygeai/tests/integration/chat/test_generate_image.py +158 -0
- pygeai/tests/integration/lab/__init__.py +0 -0
- pygeai/tests/integration/lab/agents/__init__.py +0 -0
- pygeai/tests/integration/lab/agents/test_agents_list.py +106 -0
- pygeai/tests/integration/lab/agents/test_create_agent.py +319 -0
- pygeai/tests/integration/lab/agents/test_create_sharing_link.py +70 -0
- pygeai/tests/integration/lab/agents/test_delete_agent.py +75 -0
- pygeai/tests/integration/lab/agents/test_get_agent.py +94 -0
- pygeai/tests/integration/lab/agents/test_publish_agent_revision.py +127 -0
- pygeai/tests/integration/lab/agents/test_update_agent.py +250 -0
- pygeai/tests/integration/lab/processes/__init__.py +0 -0
- pygeai/tests/integration/lab/processes/test_create_process.py +345 -0
- pygeai/tests/integration/lab/processes/test_create_task.py +211 -0
- pygeai/tests/integration/lab/processes/test_delete_process.py +111 -0
- pygeai/tests/integration/lab/processes/test_get_process.py +201 -0
- pygeai/tests/integration/lab/processes/test_list_process_instances.py +91 -0
- pygeai/tests/integration/lab/processes/test_list_processes.py +138 -0
- pygeai/tests/integration/lab/processes/test_publish_process_revision.py +232 -0
- pygeai/tests/integration/lab/processes/test_update_process.py +289 -0
- pygeai/tests/integration/lab/reasoning_strategies/__init__.py +0 -0
- pygeai/tests/integration/lab/reasoning_strategies/test_get_reasoning_strategy.py +70 -0
- pygeai/tests/integration/lab/reasoning_strategies/test_list_reasoning_strategies.py +93 -0
- pygeai/tests/integration/lab/reasoning_strategies/test_update_reasoning_strategy.py +149 -0
- pygeai/tests/integration/lab/tools/__init__.py +0 -0
- pygeai/tests/integration/lab/tools/test_create_tool.py +288 -0
- pygeai/tests/integration/lab/tools/test_delete_tool.py +87 -0
- pygeai/tests/integration/lab/tools/test_get_parameter.py +98 -0
- pygeai/tests/integration/lab/tools/test_get_tool.py +91 -0
- pygeai/tests/integration/lab/tools/test_list_tools.py +106 -0
- pygeai/tests/integration/lab/tools/test_publish_tool_revision.py +119 -0
- pygeai/tests/integration/lab/tools/test_set_parameter.py +114 -0
- pygeai/tests/integration/lab/tools/test_update_tool.py +267 -0
- pygeai/tests/lab/__init__.py +0 -0
- pygeai/tests/lab/agents/__init__.py +0 -0
- pygeai/tests/lab/agents/test_clients.py +481 -0
- pygeai/tests/lab/agents/test_mappers.py +440 -0
- pygeai/tests/lab/processes/__init__.py +0 -0
- pygeai/tests/lab/processes/test_clients.py +1416 -0
- pygeai/tests/lab/processes/test_mappers.py +1092 -0
- pygeai/tests/lab/spec/__init__.py +0 -0
- pygeai/tests/lab/spec/test_loader.py +59 -0
- pygeai/tests/lab/spec/test_parsers.py +182 -0
- pygeai/tests/lab/strategies/__init__.py +0 -0
- pygeai/tests/lab/strategies/test_clients.py +241 -0
- pygeai/tests/lab/strategies/test_mappers.py +132 -0
- pygeai/tests/lab/test_managers.py +553 -0
- pygeai/tests/lab/test_mappers.py +245 -0
- pygeai/tests/lab/test_models.py +1154 -0
- pygeai/tests/lab/tools/__init__.py +0 -0
- pygeai/tests/lab/tools/test_clients.py +521 -0
- pygeai/tests/lab/tools/test_mappers.py +198 -0
- pygeai/tests/migration/__init__.py +0 -0
- pygeai/tests/migration/test_strategies.py +405 -0
- pygeai/tests/migration/test_tools.py +159 -0
- pygeai/tests/organization/limits/__init__.py +0 -0
- pygeai/tests/organization/limits/test_clients.py +567 -0
- pygeai/tests/organization/limits/test_managers.py +402 -0
- pygeai/tests/organization/test_clients.py +615 -64
- pygeai/tests/organization/test_managers.py +424 -0
- pygeai/tests/organization/test_mappers.py +153 -0
- pygeai/tests/organization/test_responses.py +137 -0
- pygeai/tests/proxy/__init__.py +1 -0
- pygeai/tests/proxy/test_clients.py +397 -0
- pygeai/tests/proxy/test_config.py +171 -0
- pygeai/tests/proxy/test_integration.py +305 -0
- pygeai/tests/proxy/test_managers.py +312 -0
- pygeai/tests/proxy/test_servers.py +387 -0
- pygeai/tests/proxy/test_tool.py +176 -0
- pygeai/tests/snippets/__init__.py +0 -0
- pygeai/tests/snippets/analytics/__init__.py +0 -0
- pygeai/tests/snippets/analytics/get_agent_usage_per_user.py +16 -0
- pygeai/tests/snippets/analytics/get_agents_created_and_modified.py +11 -0
- pygeai/tests/snippets/analytics/get_average_cost_per_request.py +10 -0
- pygeai/tests/snippets/analytics/get_overall_error_rate.py +10 -0
- pygeai/tests/snippets/analytics/get_top_10_agents_by_requests.py +12 -0
- pygeai/tests/snippets/analytics/get_total_active_users.py +10 -0
- pygeai/tests/snippets/analytics/get_total_cost.py +10 -0
- pygeai/tests/snippets/analytics/get_total_requests_per_day.py +12 -0
- pygeai/tests/snippets/analytics/get_total_tokens.py +12 -0
- pygeai/tests/snippets/assistants/__init__.py +0 -0
- pygeai/tests/snippets/assistants/create_chat_assistant.py +54 -0
- pygeai/tests/snippets/assistants/create_text_assistant.py +51 -0
- pygeai/tests/snippets/assistants/data_analyst/__init__.py +0 -0
- pygeai/tests/snippets/assistants/data_analyst/extend_and_check.py +100 -0
- pygeai/tests/snippets/assistants/data_analyst/extend_dataset.py +9 -0
- pygeai/tests/snippets/assistants/data_analyst/get_status.py +9 -0
- pygeai/tests/snippets/assistants/file_summarizer_assistant.py +149 -0
- pygeai/tests/snippets/assistants/get_assistant_data.py +8 -0
- pygeai/tests/snippets/assistants/get_assistant_list.py +7 -0
- pygeai/tests/snippets/assistants/rag/__init__.py +0 -0
- pygeai/tests/snippets/assistants/rag/create_rag_assistant.py +65 -0
- pygeai/tests/snippets/assistants/rag/delete_al_documents.py +7 -0
- pygeai/tests/snippets/assistants/rag/delete_document.py +10 -0
- pygeai/tests/snippets/assistants/rag/delete_rag_assistant.py +8 -0
- pygeai/tests/snippets/assistants/rag/get_document.py +10 -0
- pygeai/tests/snippets/assistants/rag/get_documents.py +7 -0
- pygeai/tests/snippets/assistants/rag/get_rag_assistant_data.py +8 -0
- pygeai/tests/snippets/assistants/rag/update_rag_assistant.py +48 -0
- pygeai/tests/snippets/assistants/rag/upload_document.py +19 -0
- pygeai/tests/snippets/assistants/send_feedback.py +14 -0
- pygeai/tests/snippets/assistants/update_chat_assistant.py +63 -0
- pygeai/tests/snippets/auth/__init__.py +0 -0
- pygeai/tests/snippets/chat/__init__.py +0 -0
- pygeai/tests/snippets/chat/cancel_request.py +7 -0
- pygeai/tests/snippets/chat/chat_completion.py +28 -0
- pygeai/tests/snippets/chat/chat_completion_1.py +40 -0
- pygeai/tests/snippets/chat/chat_completion_2.py +60 -0
- pygeai/tests/snippets/chat/chat_completion_3.py +27 -0
- pygeai/tests/snippets/chat/chat_completion_4.py +67 -0
- pygeai/tests/snippets/chat/chat_completion_streaming.py +63 -0
- pygeai/tests/snippets/chat/chat_completion_with_reasoning_effort.py +18 -0
- pygeai/tests/snippets/chat/get_request_status.py +7 -0
- pygeai/tests/snippets/chat/get_response.py +15 -0
- pygeai/tests/snippets/chat/get_response_complete_example.py +67 -0
- pygeai/tests/snippets/chat/get_response_streaming.py +20 -0
- pygeai/tests/snippets/chat/get_response_with_files.py +16 -0
- pygeai/tests/snippets/chat/get_response_with_instructions.py +19 -0
- pygeai/tests/snippets/chat/get_response_with_metadata.py +24 -0
- pygeai/tests/snippets/chat/get_response_with_parallel_tools.py +58 -0
- pygeai/tests/snippets/chat/get_response_with_reasoning.py +21 -0
- pygeai/tests/snippets/chat/get_response_with_store.py +38 -0
- pygeai/tests/snippets/chat/get_response_with_tools.py +36 -0
- pygeai/tests/snippets/chat/get_response_with_truncation.py +24 -0
- pygeai/tests/snippets/chat/send_chat_request.py +33 -0
- pygeai/tests/snippets/dbg/__init__.py +0 -0
- pygeai/tests/snippets/dbg/basic_debugging.py +32 -0
- pygeai/tests/snippets/dbg/breakpoint_management.py +48 -0
- pygeai/tests/snippets/dbg/file_debugging.py +72 -0
- pygeai/tests/snippets/dbg/module_debugging.py +61 -0
- pygeai/tests/snippets/dbg/stack_navigation.py +45 -0
- pygeai/tests/snippets/dbg/stepping_example.py +40 -0
- pygeai/tests/snippets/embeddings/__init__.py +0 -0
- pygeai/tests/snippets/embeddings/cache_example.py +31 -0
- pygeai/tests/snippets/embeddings/cohere_example.py +41 -0
- pygeai/tests/snippets/embeddings/generate_embeddings.py +26 -0
- pygeai/tests/snippets/embeddings/openai_base64_example.py +27 -0
- pygeai/tests/snippets/embeddings/openai_example.py +30 -0
- pygeai/tests/snippets/embeddings/similarity_example.py +42 -0
- pygeai/tests/snippets/evaluation/__init__.py +0 -0
- pygeai/tests/snippets/evaluation/dataset/__init__.py +0 -0
- pygeai/tests/snippets/evaluation/dataset/complete_workflow_example.py +195 -0
- pygeai/tests/snippets/evaluation/dataset/create_dataset.py +26 -0
- pygeai/tests/snippets/evaluation/dataset/create_dataset_from_file.py +11 -0
- pygeai/tests/snippets/evaluation/dataset/create_dataset_row.py +17 -0
- pygeai/tests/snippets/evaluation/dataset/create_expected_source.py +18 -0
- pygeai/tests/snippets/evaluation/dataset/create_filter_variable.py +19 -0
- pygeai/tests/snippets/evaluation/dataset/delete_dataset.py +9 -0
- pygeai/tests/snippets/evaluation/dataset/delete_dataset_row.py +10 -0
- pygeai/tests/snippets/evaluation/dataset/delete_expected_source.py +15 -0
- pygeai/tests/snippets/evaluation/dataset/delete_filter_variable.py +15 -0
- pygeai/tests/snippets/evaluation/dataset/get_dataset.py +9 -0
- pygeai/tests/snippets/evaluation/dataset/get_dataset_row.py +10 -0
- pygeai/tests/snippets/evaluation/dataset/get_expected_source.py +15 -0
- pygeai/tests/snippets/evaluation/dataset/get_filter_variable.py +15 -0
- pygeai/tests/snippets/evaluation/dataset/list_dataset_rows.py +9 -0
- pygeai/tests/snippets/evaluation/dataset/list_datasets.py +6 -0
- pygeai/tests/snippets/evaluation/dataset/list_expected_sources.py +10 -0
- pygeai/tests/snippets/evaluation/dataset/list_filter_variables.py +10 -0
- pygeai/tests/snippets/evaluation/dataset/update_dataset.py +15 -0
- pygeai/tests/snippets/evaluation/dataset/update_dataset_row.py +20 -0
- pygeai/tests/snippets/evaluation/dataset/update_expected_source.py +18 -0
- pygeai/tests/snippets/evaluation/dataset/update_filter_variable.py +19 -0
- pygeai/tests/snippets/evaluation/dataset/upload_dataset_rows_file.py +10 -0
- pygeai/tests/snippets/evaluation/plan/__init__.py +0 -0
- pygeai/tests/snippets/evaluation/plan/add_plan_system_metric.py +13 -0
- pygeai/tests/snippets/evaluation/plan/complete_workflow_example.py +136 -0
- pygeai/tests/snippets/evaluation/plan/create_evaluation_plan.py +24 -0
- pygeai/tests/snippets/evaluation/plan/create_rag_evaluation_plan.py +22 -0
- pygeai/tests/snippets/evaluation/plan/delete_evaluation_plan.py +9 -0
- pygeai/tests/snippets/evaluation/plan/delete_plan_system_metric.py +13 -0
- pygeai/tests/snippets/evaluation/plan/execute_evaluation_plan.py +11 -0
- pygeai/tests/snippets/evaluation/plan/get_evaluation_plan.py +9 -0
- pygeai/tests/snippets/evaluation/plan/get_plan_system_metric.py +13 -0
- pygeai/tests/snippets/evaluation/plan/get_system_metric.py +9 -0
- pygeai/tests/snippets/evaluation/plan/list_evaluation_plans.py +7 -0
- pygeai/tests/snippets/evaluation/plan/list_plan_system_metrics.py +9 -0
- pygeai/tests/snippets/evaluation/plan/list_system_metrics.py +7 -0
- pygeai/tests/snippets/evaluation/plan/update_evaluation_plan.py +22 -0
- pygeai/tests/snippets/evaluation/plan/update_plan_system_metric.py +14 -0
- pygeai/tests/snippets/evaluation/result/__init__.py +0 -0
- pygeai/tests/snippets/evaluation/result/complete_workflow_example.py +150 -0
- pygeai/tests/snippets/evaluation/result/get_evaluation_result.py +26 -0
- pygeai/tests/snippets/evaluation/result/list_evaluation_results.py +17 -0
- pygeai/tests/snippets/files/__init__.py +0 -0
- pygeai/tests/snippets/files/delete_file.py +9 -0
- pygeai/tests/snippets/files/get_file_content.py +10 -0
- pygeai/tests/snippets/files/get_file_data.py +9 -0
- pygeai/tests/snippets/files/get_file_list.py +6 -0
- pygeai/tests/snippets/files/upload_file.py +13 -0
- pygeai/tests/snippets/gam/__init__.py +0 -0
- pygeai/tests/snippets/gam/gam_access_token.py +87 -0
- pygeai/tests/snippets/lab/__init__.py +0 -0
- pygeai/tests/snippets/lab/agentic_flow_example_1.py +326 -0
- pygeai/tests/snippets/lab/agentic_flow_example_2.py +206 -0
- pygeai/tests/snippets/lab/agentic_flow_example_3.py +486 -0
- pygeai/tests/snippets/lab/agentic_flow_example_4.py +446 -0
- pygeai/tests/snippets/lab/agents/__init__.py +0 -0
- pygeai/tests/snippets/lab/agents/create_agent.py +48 -0
- pygeai/tests/snippets/lab/agents/create_agent_2.py +48 -0
- pygeai/tests/snippets/lab/agents/create_agent_edge_case.py +48 -0
- pygeai/tests/snippets/lab/agents/create_agent_with_permissions.py +39 -0
- pygeai/tests/snippets/lab/agents/create_agent_with_properties.py +46 -0
- pygeai/tests/snippets/lab/agents/create_agent_without_instructions.py +48 -0
- pygeai/tests/snippets/lab/agents/delete_agent.py +12 -0
- pygeai/tests/snippets/lab/agents/get_agent.py +24 -0
- pygeai/tests/snippets/lab/agents/get_agent_with_new_fields.py +62 -0
- pygeai/tests/snippets/lab/agents/get_sharing_link.py +13 -0
- pygeai/tests/snippets/lab/agents/list_agents.py +18 -0
- pygeai/tests/snippets/lab/agents/publish_agent_revision.py +12 -0
- pygeai/tests/snippets/lab/agents/update_agent.py +50 -0
- pygeai/tests/snippets/lab/agents/update_agent_properties.py +50 -0
- pygeai/tests/snippets/lab/assistant_to_agent.py +191 -0
- pygeai/tests/snippets/lab/crud_ui.py +462 -0
- pygeai/tests/snippets/lab/processes/__init__.py +0 -0
- pygeai/tests/snippets/lab/processes/create_process.py +24 -0
- pygeai/tests/snippets/lab/processes/create_task.py +8 -0
- pygeai/tests/snippets/lab/processes/jobs/__init__.py +0 -0
- pygeai/tests/snippets/lab/processes/jobs/list_jobs.py +21 -0
- pygeai/tests/snippets/lab/processes/kbs/__init__.py +0 -0
- pygeai/tests/snippets/lab/processes/kbs/create_kb.py +18 -0
- pygeai/tests/snippets/lab/processes/kbs/get_kb.py +26 -0
- pygeai/tests/snippets/lab/processes/kbs/list_kbs.py +30 -0
- pygeai/tests/snippets/lab/processes/kbs/try_all.py +73 -0
- pygeai/tests/snippets/lab/processes/list_processes.py +10 -0
- pygeai/tests/snippets/lab/runner_1.py +212 -0
- pygeai/tests/snippets/lab/samples/__init__.py +0 -0
- pygeai/tests/snippets/lab/samples/summarize_files.py +162 -0
- pygeai/tests/snippets/lab/strategies/__init__.py +0 -0
- pygeai/tests/snippets/lab/strategies/create_reasoning_strategy.py +22 -0
- pygeai/tests/snippets/lab/strategies/get_reasoning_strategy.py +10 -0
- pygeai/tests/snippets/lab/strategies/list_reasoning_strategies.py +16 -0
- pygeai/tests/snippets/lab/strategies/update_reasoning_strategy.py +26 -0
- pygeai/tests/snippets/lab/tools/__init__.py +0 -0
- pygeai/tests/snippets/lab/tools/create_tool.py +48 -0
- pygeai/tests/snippets/lab/tools/create_tool_edge_case.py +50 -0
- pygeai/tests/snippets/lab/tools/delete_tool.py +21 -0
- pygeai/tests/snippets/lab/tools/get_parameter.py +21 -0
- pygeai/tests/snippets/lab/tools/get_tool.py +22 -0
- pygeai/tests/snippets/lab/tools/list_tools.py +23 -0
- pygeai/tests/snippets/lab/tools/publish_tool_revision.py +13 -0
- pygeai/tests/snippets/lab/tools/set_parameters.py +33 -0
- pygeai/tests/snippets/lab/tools/update_tool.py +52 -0
- pygeai/tests/snippets/lab/use_cases/__init__.py +0 -0
- pygeai/tests/snippets/lab/use_cases/c_code_fixer_agent_flow.py +238 -0
- pygeai/tests/snippets/lab/use_cases/create_cli_expert.py +1640 -0
- pygeai/tests/snippets/lab/use_cases/create_lab_expert.py +4541 -0
- pygeai/tests/snippets/lab/use_cases/create_tool_headless_web_browser.py +133 -0
- pygeai/tests/snippets/lab/use_cases/create_web_designer.py +189 -0
- pygeai/tests/snippets/lab/use_cases/create_web_reader.py +185 -0
- pygeai/tests/snippets/lab/use_cases/file_summarizer_example.py +157 -0
- pygeai/tests/snippets/lab/use_cases/file_summarizer_example_2.py +157 -0
- pygeai/tests/snippets/lab/use_cases/update_cli_expert.py +1773 -0
- pygeai/tests/snippets/lab/use_cases/update_lab_expert.py +4541 -0
- pygeai/tests/snippets/lab/use_cases/update_web_designer.py +188 -0
- pygeai/tests/snippets/lab/use_cases/update_web_reader.py +195 -0
- pygeai/tests/snippets/lab/use_cases/update_web_reader_with_tool.py +210 -0
- pygeai/tests/snippets/migrate/__init__.py +45 -0
- pygeai/tests/snippets/migrate/agent_migration.py +110 -0
- pygeai/tests/snippets/migrate/assistant_migration.py +64 -0
- pygeai/tests/snippets/migrate/orchestrator_examples.py +179 -0
- pygeai/tests/snippets/migrate/process_migration.py +64 -0
- pygeai/tests/snippets/migrate/project_migration.py +42 -0
- pygeai/tests/snippets/migrate/tool_migration.py +64 -0
- pygeai/tests/snippets/organization/__init__.py +0 -0
- pygeai/tests/snippets/organization/add_project_member.py +10 -0
- pygeai/tests/snippets/organization/add_project_member_batch.py +44 -0
- pygeai/tests/snippets/organization/create_project.py +23 -0
- pygeai/tests/snippets/organization/delete_project.py +7 -0
- pygeai/tests/snippets/organization/export_request_data.py +7 -0
- pygeai/tests/snippets/organization/get_memberships.py +12 -0
- pygeai/tests/snippets/organization/get_organization_members.py +6 -0
- pygeai/tests/snippets/organization/get_project_data.py +7 -0
- pygeai/tests/snippets/organization/get_project_list.py +8 -0
- pygeai/tests/snippets/organization/get_project_members.py +6 -0
- pygeai/tests/snippets/organization/get_project_memberships.py +12 -0
- pygeai/tests/snippets/organization/get_project_roles.py +6 -0
- pygeai/tests/snippets/organization/get_project_tokens.py +7 -0
- pygeai/tests/snippets/organization/update_project.py +14 -0
- pygeai/tests/snippets/rerank/__init__.py +0 -0
- pygeai/tests/snippets/rerank/rerank_chunks.py +19 -0
- pygeai/tests/snippets/secrets/__init__.py +0 -0
- pygeai/tests/snippets/usage_limit/__init__.py +0 -0
- pygeai/tests/snippets/usage_limit/delete_usage_limit.py +16 -0
- pygeai/tests/snippets/usage_limit/get_all_usage_limit_from_organization.py +12 -0
- pygeai/tests/snippets/usage_limit/get_usage_limit_from_organization.py +11 -0
- pygeai/tests/snippets/usage_limit/get_usage_limit_from_project.py +13 -0
- pygeai/tests/snippets/usage_limit/set_usage_limit_organization.py +22 -0
- pygeai/tests/snippets/usage_limit/set_usage_limit_project.py +23 -0
- pygeai/tests/snippets/usage_limit/update_usage_limit_organization.py +23 -0
- pygeai/tests/snippets/usage_limit/update_usage_limit_project.py +24 -0
- pygeai/vendor/a2a/__init__.py +1 -0
- pygeai/vendor/a2a/auth/__init__.py +0 -0
- pygeai/vendor/a2a/auth/user.py +31 -0
- pygeai/vendor/a2a/client/__init__.py +19 -0
- pygeai/vendor/a2a/client/client.py +425 -0
- pygeai/vendor/a2a/client/errors.py +33 -0
- pygeai/vendor/a2a/client/helpers.py +22 -0
- pygeai/vendor/a2a/py.typed +0 -0
- pygeai/vendor/a2a/server/__init__.py +1 -0
- pygeai/vendor/a2a/server/agent_execution/__init__.py +18 -0
- pygeai/vendor/a2a/server/agent_execution/agent_executor.py +44 -0
- pygeai/vendor/a2a/server/agent_execution/context.py +155 -0
- pygeai/vendor/a2a/server/agent_execution/request_context_builder.py +20 -0
- pygeai/vendor/a2a/server/agent_execution/simple_request_context_builder.py +77 -0
- pygeai/vendor/a2a/server/apps/__init__.py +16 -0
- pygeai/vendor/a2a/server/apps/jsonrpc/__init__.py +16 -0
- pygeai/vendor/a2a/server/apps/jsonrpc/fastapi_app.py +88 -0
- pygeai/vendor/a2a/server/apps/jsonrpc/jsonrpc_app.py +426 -0
- pygeai/vendor/a2a/server/apps/jsonrpc/starlette_app.py +123 -0
- pygeai/vendor/a2a/server/context.py +23 -0
- pygeai/vendor/a2a/server/events/__init__.py +21 -0
- pygeai/vendor/a2a/server/events/event_consumer.py +149 -0
- pygeai/vendor/a2a/server/events/event_queue.py +156 -0
- pygeai/vendor/a2a/server/events/in_memory_queue_manager.py +85 -0
- pygeai/vendor/a2a/server/events/queue_manager.py +35 -0
- pygeai/vendor/a2a/server/request_handlers/__init__.py +20 -0
- pygeai/vendor/a2a/server/request_handlers/default_request_handler.py +435 -0
- pygeai/vendor/a2a/server/request_handlers/jsonrpc_handler.py +327 -0
- pygeai/vendor/a2a/server/request_handlers/request_handler.py +161 -0
- pygeai/vendor/a2a/server/request_handlers/response_helpers.py +133 -0
- pygeai/vendor/a2a/server/tasks/__init__.py +20 -0
- pygeai/vendor/a2a/server/tasks/inmemory_push_notifier.py +62 -0
- pygeai/vendor/a2a/server/tasks/inmemory_task_store.py +51 -0
- pygeai/vendor/a2a/server/tasks/push_notifier.py +25 -0
- pygeai/vendor/a2a/server/tasks/result_aggregator.py +151 -0
- pygeai/vendor/a2a/server/tasks/task_manager.py +253 -0
- pygeai/vendor/a2a/server/tasks/task_store.py +22 -0
- pygeai/vendor/a2a/server/tasks/task_updater.py +155 -0
- pygeai/vendor/a2a/types.py +1624 -0
- pygeai/vendor/a2a/utils/__init__.py +40 -0
- pygeai/vendor/a2a/utils/artifact.py +72 -0
- pygeai/vendor/a2a/utils/errors.py +69 -0
- pygeai/vendor/a2a/utils/helpers.py +176 -0
- pygeai/vendor/a2a/utils/message.py +83 -0
- pygeai/vendor/a2a/utils/task.py +57 -0
- pygeai/vendor/a2a/utils/telemetry.py +299 -0
- pygeai-0.6.0b15.dist-info/METADATA +205 -0
- pygeai-0.6.0b15.dist-info/RECORD +799 -0
- {pygeai-0.1.6.dist-info → pygeai-0.6.0b15.dist-info}/WHEEL +1 -1
- pygeai-0.6.0b15.dist-info/entry_points.txt +5 -0
- {pygeai-0.1.6.dist-info → pygeai-0.6.0b15.dist-info/licenses}/LICENSE +13 -1
- {pygeai-0.1.6.dist-info → pygeai-0.6.0b15.dist-info}/top_level.txt +0 -1
- docs/source/conf.py +0 -45
- pygeai/core/clients.py +0 -240
- pygeai/tests/core/test_clients.py +0 -49
- pygeai-0.1.6.dist-info/METADATA +0 -92
- pygeai-0.1.6.dist-info/RECORD +0 -65
- pygeai-0.1.6.dist-info/SOURCES.sync-conflict-20241223-145950-3QD4F42.txt +0 -41
- pygeai-0.1.6.dist-info/entry_points.txt +0 -2
- /pygeai/{agent → analytics}/__init__.py +0 -0
pygeai/chat/ui.py
ADDED
|
@@ -0,0 +1,678 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
import streamlit as st
|
|
4
|
+
import argparse
|
|
5
|
+
import json
|
|
6
|
+
import os
|
|
7
|
+
from datetime import datetime
|
|
8
|
+
from pygeai.chat.session import AgentChatSession
|
|
9
|
+
from pygeai.core.utils.console import Console
|
|
10
|
+
from pygeai.core.common.config import get_settings
|
|
11
|
+
from pygeai.lab.managers import AILabManager
|
|
12
|
+
from pygeai.lab.models import FilterSettings, AgentList
|
|
13
|
+
import sys
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
global SESSION_FILE_PATH
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def parse_args():
|
|
22
|
+
"""Parse command-line arguments."""
|
|
23
|
+
parser = argparse.ArgumentParser(description="Streamlit chat interface for pygeai agent")
|
|
24
|
+
parser.add_argument("--agent-name", "-n", required=True, help="Name of the agent to interact with")
|
|
25
|
+
args, unknown = parser.parse_known_args() # Ignore Streamlit's args
|
|
26
|
+
return args
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def save_session_to_file(messages, file_path):
|
|
30
|
+
"""Helper function to save session to a server-side file."""
|
|
31
|
+
try:
|
|
32
|
+
os.makedirs(os.path.dirname(file_path), exist_ok=True)
|
|
33
|
+
with open(file_path, 'w') as f:
|
|
34
|
+
json.dump(messages, f, indent=2)
|
|
35
|
+
logger.info(f"Session automatically saved to {file_path}")
|
|
36
|
+
return True
|
|
37
|
+
except Exception as e:
|
|
38
|
+
logger.error(f"Error saving session to {file_path}: {e}")
|
|
39
|
+
st.error(f"Failed to auto-save session: {e}")
|
|
40
|
+
return False
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def get_unique_file_path(base_path):
|
|
44
|
+
"""Generate a unique file path by appending a numeric suffix if the file exists."""
|
|
45
|
+
if not os.path.exists(base_path):
|
|
46
|
+
return base_path
|
|
47
|
+
|
|
48
|
+
directory, filename = os.path.split(base_path)
|
|
49
|
+
name, ext = os.path.splitext(filename)
|
|
50
|
+
counter = 1
|
|
51
|
+
|
|
52
|
+
new_path = base_path
|
|
53
|
+
while os.path.exists(new_path):
|
|
54
|
+
new_filename = f"{name}_{counter}{ext}"
|
|
55
|
+
new_path = os.path.join(directory, new_filename)
|
|
56
|
+
counter += 1
|
|
57
|
+
|
|
58
|
+
return new_path
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def get_session_file_path(agent_name, custom_filename=None):
|
|
62
|
+
"""Generate the session file path with date and agent name, or use a custom filename."""
|
|
63
|
+
if custom_filename:
|
|
64
|
+
if not custom_filename.endswith('.json'):
|
|
65
|
+
custom_filename += '.json'
|
|
66
|
+
return os.path.join("chats", custom_filename)
|
|
67
|
+
current_date = datetime.now().strftime("%Y-%m-%d")
|
|
68
|
+
return os.path.join("chats", f"chat_session_{agent_name}_{current_date}.json")
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def list_session_files():
|
|
72
|
+
"""List all JSON files in the 'chats' directory."""
|
|
73
|
+
chats_dir = "chats"
|
|
74
|
+
if not os.path.exists(chats_dir):
|
|
75
|
+
return []
|
|
76
|
+
try:
|
|
77
|
+
return [f for f in os.listdir(chats_dir) if f.endswith('.json')]
|
|
78
|
+
except Exception as e:
|
|
79
|
+
logger.error(f"Error listing session files in {chats_dir}: {e}")
|
|
80
|
+
return []
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def load_session_from_file(file_path):
|
|
84
|
+
"""Load session data from a specified file."""
|
|
85
|
+
try:
|
|
86
|
+
with open(file_path, 'r') as f:
|
|
87
|
+
data = json.load(f)
|
|
88
|
+
if isinstance(data, list):
|
|
89
|
+
return data, True
|
|
90
|
+
else:
|
|
91
|
+
return None, False
|
|
92
|
+
except Exception as e:
|
|
93
|
+
logger.error(f"Error loading session from {file_path}: {e}")
|
|
94
|
+
return None, False
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def delete_session_file(file_path):
|
|
98
|
+
"""Helper function to delete a session file from the file system."""
|
|
99
|
+
try:
|
|
100
|
+
if os.path.exists(file_path):
|
|
101
|
+
os.remove(file_path)
|
|
102
|
+
logger.info(f"Session file deleted: {file_path}")
|
|
103
|
+
return True, f"Session file {os.path.basename(file_path)} deleted successfully."
|
|
104
|
+
else:
|
|
105
|
+
logger.warning(f"Session file not found: {file_path}")
|
|
106
|
+
return False, f"Session file {os.path.basename(file_path)} not found."
|
|
107
|
+
except Exception as e:
|
|
108
|
+
logger.error(f"Error deleting session file {file_path}: {e}")
|
|
109
|
+
return False, f"Error deleting session file {os.path.basename(file_path)}: {str(e)}"
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def get_alias_list():
|
|
113
|
+
"""Get list of available aliases from settings."""
|
|
114
|
+
try:
|
|
115
|
+
settings = get_settings()
|
|
116
|
+
aliases = list(settings.list_aliases().keys())
|
|
117
|
+
return ["-"] + aliases # Add "-" as default no-selection option
|
|
118
|
+
except Exception as e:
|
|
119
|
+
logger.error(f"Error fetching alias list: {e}")
|
|
120
|
+
st.error(f"Failed to fetch alias list: {e}")
|
|
121
|
+
return ["-"]
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def get_agent_list(alias, project_id):
|
|
125
|
+
"""Get list of agents for a given alias and project ID."""
|
|
126
|
+
try:
|
|
127
|
+
if alias == "-" or not project_id:
|
|
128
|
+
return ["-"]
|
|
129
|
+
ai_lab_manager = AILabManager(alias=alias)
|
|
130
|
+
filter_settings = FilterSettings(
|
|
131
|
+
allow_external=False,
|
|
132
|
+
allow_drafts=True,
|
|
133
|
+
access_scope="private"
|
|
134
|
+
)
|
|
135
|
+
result = ai_lab_manager.get_agent_list(
|
|
136
|
+
project_id=project_id,
|
|
137
|
+
filter_settings=filter_settings
|
|
138
|
+
)
|
|
139
|
+
if isinstance(result, AgentList) and result.agents:
|
|
140
|
+
# Store full agent data for preview
|
|
141
|
+
st.session_state.agent_data = {f"{agent.name} (ID: {agent.id})": agent for agent in result.agents}
|
|
142
|
+
return ["-"] + [f"{agent.name} (ID: {agent.id})" for agent in result.agents]
|
|
143
|
+
else:
|
|
144
|
+
st.error(f"No agents found for project ID {project_id} or errors occurred: {result.errors if hasattr(result, 'errors') else 'Unknown error'}")
|
|
145
|
+
return ["-"]
|
|
146
|
+
except Exception as e:
|
|
147
|
+
logger.error(f"Error fetching agents for project ID {project_id} with alias {alias}: {e}")
|
|
148
|
+
st.error(f"Failed to fetch agents for project: {e}")
|
|
149
|
+
return ["-"]
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def save_recent_agents(agent_name):
|
|
153
|
+
"""Save a recently used agent to session state or file."""
|
|
154
|
+
if "recent_agents" not in st.session_state:
|
|
155
|
+
st.session_state.recent_agents = []
|
|
156
|
+
if agent_name and agent_name not in st.session_state.recent_agents:
|
|
157
|
+
st.session_state.recent_agents = [agent_name] + st.session_state.recent_agents[:4] # Keep top 5 recent
|
|
158
|
+
# Optionally save to a file for persistence
|
|
159
|
+
try:
|
|
160
|
+
with open("recent_agents.json", "w") as f:
|
|
161
|
+
json.dump(st.session_state.recent_agents, f)
|
|
162
|
+
except Exception as e:
|
|
163
|
+
logger.error(f"Error saving recent agents: {e}")
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def load_recent_agents():
|
|
167
|
+
"""Load recent agents from session state or file."""
|
|
168
|
+
if "recent_agents" not in st.session_state:
|
|
169
|
+
try:
|
|
170
|
+
with open("recent_agents.json", "r") as f:
|
|
171
|
+
st.session_state.recent_agents = json.load(f)
|
|
172
|
+
except Exception:
|
|
173
|
+
st.session_state.recent_agents = []
|
|
174
|
+
return st.session_state.recent_agents
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def run_streamlit_chat():
|
|
178
|
+
"""Run a Streamlit chat interface for the specified agent."""
|
|
179
|
+
args = parse_args()
|
|
180
|
+
initial_agent_name = args.agent_name
|
|
181
|
+
try:
|
|
182
|
+
# Initialize session state for multiple tabs and current agent
|
|
183
|
+
if "sessions" not in st.session_state:
|
|
184
|
+
st.session_state.sessions = {
|
|
185
|
+
initial_agent_name: {
|
|
186
|
+
"messages": [],
|
|
187
|
+
"chat_session": AgentChatSession(initial_agent_name),
|
|
188
|
+
"custom_filename": "",
|
|
189
|
+
"active": True
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
if "active_tab" not in st.session_state:
|
|
193
|
+
st.session_state.active_tab = initial_agent_name
|
|
194
|
+
if "agent_data" not in st.session_state:
|
|
195
|
+
st.session_state.agent_data = {}
|
|
196
|
+
if "search_term" not in st.session_state:
|
|
197
|
+
st.session_state.search_term = ""
|
|
198
|
+
# if "editing_message" not in st.session_state:
|
|
199
|
+
# st.session_state.editing_message = None
|
|
200
|
+
# if "edit_content" not in st.session_state:
|
|
201
|
+
# st.session_state.edit_content = ""
|
|
202
|
+
# if "regenerate_response" not in st.session_state:
|
|
203
|
+
# st.session_state.regenerate_response = False
|
|
204
|
+
|
|
205
|
+
# Load recent agents
|
|
206
|
+
load_recent_agents()
|
|
207
|
+
|
|
208
|
+
# Load global vars
|
|
209
|
+
global current_session
|
|
210
|
+
global SESSION_FILE_PATH
|
|
211
|
+
|
|
212
|
+
# Get current session for active tab
|
|
213
|
+
current_session = st.session_state.sessions[st.session_state.active_tab]
|
|
214
|
+
if "editing_message" not in current_session:
|
|
215
|
+
current_session["editing_message"] = None
|
|
216
|
+
if "edit_content" not in current_session:
|
|
217
|
+
current_session["edit_content"] = ""
|
|
218
|
+
if "regenerate_response" not in current_session:
|
|
219
|
+
current_session["regenerate_response"] = False
|
|
220
|
+
SESSION_FILE_PATH = get_session_file_path(st.session_state.active_tab, current_session.get("custom_filename", ""))
|
|
221
|
+
|
|
222
|
+
# Initialize messages for new session if not already set
|
|
223
|
+
if not current_session["messages"]:
|
|
224
|
+
if os.path.exists(SESSION_FILE_PATH):
|
|
225
|
+
try:
|
|
226
|
+
with open(SESSION_FILE_PATH, 'r') as f:
|
|
227
|
+
restored_data = json.load(f)
|
|
228
|
+
if isinstance(restored_data, list):
|
|
229
|
+
current_session["messages"] = restored_data
|
|
230
|
+
st.success(f"Session automatically restored from {SESSION_FILE_PATH}")
|
|
231
|
+
else:
|
|
232
|
+
logger.warning(f"Invalid session data in {SESSION_FILE_PATH}. Starting fresh.")
|
|
233
|
+
intro = current_session["chat_session"].get_answer(
|
|
234
|
+
["You're about to speak to a user. Introduce yourself in a clear and concise manner, "
|
|
235
|
+
"stating who you are and what you do. Nothing else."]
|
|
236
|
+
)
|
|
237
|
+
if "Agent not found" in str(intro):
|
|
238
|
+
st.error("The specified agent doesn't seem to exist. Please review the name and try again.")
|
|
239
|
+
logger.error("The specified agent doesn't seem to exist. Please review the name and try again.")
|
|
240
|
+
return
|
|
241
|
+
current_session["messages"] = [{"role": "assistant", "content": intro}]
|
|
242
|
+
except Exception as e:
|
|
243
|
+
logger.error(f"Error auto-restoring session from {SESSION_FILE_PATH}: {e}")
|
|
244
|
+
intro = current_session["chat_session"].get_answer(
|
|
245
|
+
["You're about to speak to a user. Introduce yourself in a clear and concise manner, "
|
|
246
|
+
"stating who you are and what you do. Nothing else."]
|
|
247
|
+
)
|
|
248
|
+
if "Agent not found" in str(intro):
|
|
249
|
+
st.error("The specified agent doesn't seem to exist. Please review the name and try again.")
|
|
250
|
+
logger.error("The specified agent doesn't seem to exist. Please review the name and try again.")
|
|
251
|
+
return
|
|
252
|
+
current_session["messages"] = [{"role": "assistant", "content": intro}]
|
|
253
|
+
else:
|
|
254
|
+
intro = current_session["chat_session"].get_answer(
|
|
255
|
+
["You're about to speak to a user. Introduce yourself in a clear and concise manner, "
|
|
256
|
+
"stating who you are and what you do. Nothing else."]
|
|
257
|
+
)
|
|
258
|
+
if "Agent not found" in str(intro):
|
|
259
|
+
st.error("The specified agent doesn't seem to exist. Please review the name and try again.")
|
|
260
|
+
logger.error("The specified agent doesn't seem to exist. Please review the name and try again.")
|
|
261
|
+
return
|
|
262
|
+
current_session["messages"] = [{"role": "assistant", "content": intro}]
|
|
263
|
+
save_session_to_file(current_session["messages"], SESSION_FILE_PATH)
|
|
264
|
+
st.rerun()
|
|
265
|
+
|
|
266
|
+
# Set page title
|
|
267
|
+
st.title(f"Chat with {st.session_state.active_tab}")
|
|
268
|
+
|
|
269
|
+
# Display the session save path in the main area for better readability
|
|
270
|
+
st.info(f"Session will be saved as: {SESSION_FILE_PATH}", icon="ℹ️")
|
|
271
|
+
|
|
272
|
+
# Chat History Search
|
|
273
|
+
search_term = st.text_input("Search Chat History", value=st.session_state.search_term, placeholder="Enter keyword to filter messages")
|
|
274
|
+
if search_term != st.session_state.search_term:
|
|
275
|
+
st.session_state.search_term = search_term
|
|
276
|
+
st.rerun()
|
|
277
|
+
|
|
278
|
+
# Single Session Chat
|
|
279
|
+
current_session = st.session_state.sessions[st.session_state.active_tab]
|
|
280
|
+
if "editing_message" not in current_session:
|
|
281
|
+
current_session["editing_message"] = None
|
|
282
|
+
if "edit_content" not in current_session:
|
|
283
|
+
current_session["edit_content"] = ""
|
|
284
|
+
render_chat_history(
|
|
285
|
+
current_session["messages"],
|
|
286
|
+
search_term,
|
|
287
|
+
tab_key_prefix=st.session_state.active_tab,
|
|
288
|
+
session=current_session
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
# Sidebar for session management and agent selection
|
|
292
|
+
with st.sidebar:
|
|
293
|
+
st.header("Session Management")
|
|
294
|
+
|
|
295
|
+
with st.expander("Help: Session Saving & Restoring", expanded=False):
|
|
296
|
+
st.markdown("""
|
|
297
|
+
**Session Saving & Restoring Explained:**
|
|
298
|
+
- **Auto-Save Session**: When toggled on, your chat history is automatically saved to a server-side file in the 'chats' directory after each message or action.
|
|
299
|
+
- **Custom Session Filename**: Enter a custom name for the session file to save it with a specific identifier.
|
|
300
|
+
- **Save Session (JSON)**: Download a local copy of your chat history.
|
|
301
|
+
- **Restore Session (JSON)**: Upload a previously saved JSON file to load a specific chat history.
|
|
302
|
+
- **Available Sessions**: List of saved session files with previews. Click to load into the current tab.
|
|
303
|
+
- **Reset Chat**: Clears the current session and starts fresh with the agent's introduction.
|
|
304
|
+
""")
|
|
305
|
+
|
|
306
|
+
# Custom filename input for the current session
|
|
307
|
+
custom_filename = st.text_input("Custom Session Filename (optional)", value=current_session.get("custom_filename", ""), placeholder="e.g., my_custom_session")
|
|
308
|
+
if custom_filename != current_session.get("custom_filename", ""):
|
|
309
|
+
current_session["custom_filename"] = custom_filename
|
|
310
|
+
SESSION_FILE_PATH = get_session_file_path(st.session_state.active_tab, custom_filename)
|
|
311
|
+
if current_session["messages"]:
|
|
312
|
+
save_session_to_file(current_session["messages"], SESSION_FILE_PATH)
|
|
313
|
+
st.rerun()
|
|
314
|
+
|
|
315
|
+
uploaded_file = st.file_uploader("Restore Session (JSON)", type=["json"])
|
|
316
|
+
if uploaded_file is not None and "session_restored" not in st.session_state:
|
|
317
|
+
try:
|
|
318
|
+
restored_data = json.load(uploaded_file)
|
|
319
|
+
if isinstance(restored_data, list):
|
|
320
|
+
current_session["messages"] = restored_data
|
|
321
|
+
st.session_state.session_restored = True
|
|
322
|
+
save_session_to_file(current_session["messages"], SESSION_FILE_PATH)
|
|
323
|
+
st.success(f"Session restored from {uploaded_file.name}")
|
|
324
|
+
st.rerun()
|
|
325
|
+
else:
|
|
326
|
+
st.error("Invalid session file: Must contain a list of messages in JSON format.")
|
|
327
|
+
except json.JSONDecodeError:
|
|
328
|
+
st.error("Invalid JSON format in uploaded file.")
|
|
329
|
+
except Exception as e:
|
|
330
|
+
st.error(f"Error restoring session: {e}")
|
|
331
|
+
logger.error(f"Error restoring session: {e}")
|
|
332
|
+
|
|
333
|
+
if current_session["messages"]:
|
|
334
|
+
session_json = json.dumps(current_session["messages"], indent=2)
|
|
335
|
+
current_date = datetime.now().strftime("%Y-%m-%d")
|
|
336
|
+
st.download_button(
|
|
337
|
+
label="Save Session (JSON)",
|
|
338
|
+
data=session_json,
|
|
339
|
+
file_name=f"chat_session_{st.session_state.active_tab}_{current_date}.json",
|
|
340
|
+
mime="application/json"
|
|
341
|
+
)
|
|
342
|
+
|
|
343
|
+
auto_save = st.toggle("Auto-Save Session", value=st.session_state.get("auto_save", True))
|
|
344
|
+
st.session_state.auto_save = auto_save
|
|
345
|
+
|
|
346
|
+
# Available Sessions with Preview
|
|
347
|
+
st.subheader("Available Sessions")
|
|
348
|
+
session_files = list_session_files()
|
|
349
|
+
session_feedback_placeholder = st.empty()
|
|
350
|
+
if session_files:
|
|
351
|
+
st.markdown("Click a file to load the session, or use the trash icon to delete:")
|
|
352
|
+
for file in session_files:
|
|
353
|
+
col1, col2 = st.columns([3, 1])
|
|
354
|
+
with col1:
|
|
355
|
+
if st.button(file, key=f"load_{file}", use_container_width=True):
|
|
356
|
+
file_path = os.path.join("chats", file)
|
|
357
|
+
loaded_data, success = load_session_from_file(file_path)
|
|
358
|
+
if success:
|
|
359
|
+
current_session["messages"] = loaded_data
|
|
360
|
+
st.success(f"Session loaded from {file}")
|
|
361
|
+
if st.session_state.auto_save:
|
|
362
|
+
save_session_to_file(current_session["messages"], SESSION_FILE_PATH)
|
|
363
|
+
st.rerun()
|
|
364
|
+
else:
|
|
365
|
+
st.error(f"Failed to load session from {file}")
|
|
366
|
+
with col2:
|
|
367
|
+
if st.button("🗑️", key=f"delete_{file}", help=f"Delete {file}"):
|
|
368
|
+
file_path = os.path.join("chats", file)
|
|
369
|
+
if os.path.abspath(file_path) == os.path.abspath(SESSION_FILE_PATH):
|
|
370
|
+
with session_feedback_placeholder.container():
|
|
371
|
+
st.markdown("---")
|
|
372
|
+
st.error(
|
|
373
|
+
"Cannot delete the currently active session file. Please switch to another session or reset the chat first.",
|
|
374
|
+
icon="🚫")
|
|
375
|
+
st.markdown("---")
|
|
376
|
+
else:
|
|
377
|
+
try:
|
|
378
|
+
os.remove(file_path)
|
|
379
|
+
logger.info(f"Deleted session file: {file_path}")
|
|
380
|
+
with session_feedback_placeholder.container():
|
|
381
|
+
st.markdown("---")
|
|
382
|
+
st.success(f"Deleted {file}", icon="✅")
|
|
383
|
+
st.markdown("---")
|
|
384
|
+
st.rerun()
|
|
385
|
+
except Exception as e:
|
|
386
|
+
logger.error(f"Error deleting session file {file_path}: {e}")
|
|
387
|
+
with session_feedback_placeholder.container():
|
|
388
|
+
st.markdown("---")
|
|
389
|
+
st.error(f"Failed to delete {file}: {e}", icon="❌")
|
|
390
|
+
st.markdown("---")
|
|
391
|
+
else:
|
|
392
|
+
st.markdown("No saved sessions found in 'chats' directory.")
|
|
393
|
+
|
|
394
|
+
# New Feature: Agent Selection
|
|
395
|
+
st.header("Switch Agent")
|
|
396
|
+
with st.expander("Help: Switching Agents", expanded=False):
|
|
397
|
+
st.markdown("""
|
|
398
|
+
**Switching Agents Explained:**
|
|
399
|
+
- **Select Alias**: Choose a profile (alias) to access specific API configurations.
|
|
400
|
+
- **Enter Project ID**: Provide the ID of the project to list available agents.
|
|
401
|
+
- **Select Agent**: Pick an agent to chat with. You'll be prompted to confirm before switching.
|
|
402
|
+
- Switching to a new agent starts a fresh session in a new tab.
|
|
403
|
+
""")
|
|
404
|
+
|
|
405
|
+
# Initialize session state for alias, project ID, and agent selection
|
|
406
|
+
if "selected_alias" not in st.session_state:
|
|
407
|
+
st.session_state.selected_alias = "-"
|
|
408
|
+
if "project_id_input" not in st.session_state:
|
|
409
|
+
st.session_state.project_id_input = ""
|
|
410
|
+
if "selected_agent" not in st.session_state:
|
|
411
|
+
st.session_state.selected_agent = "-"
|
|
412
|
+
if "confirm_switch" not in st.session_state:
|
|
413
|
+
st.session_state.confirm_switch = False
|
|
414
|
+
|
|
415
|
+
# Alias Selection
|
|
416
|
+
alias_list = get_alias_list()
|
|
417
|
+
selected_alias = st.selectbox("Select Alias (Profile)", alias_list, index=alias_list.index(st.session_state.selected_alias))
|
|
418
|
+
if selected_alias != st.session_state.selected_alias:
|
|
419
|
+
st.session_state.selected_alias = selected_alias
|
|
420
|
+
st.session_state.selected_agent = "-"
|
|
421
|
+
st.rerun()
|
|
422
|
+
|
|
423
|
+
# Project ID Input
|
|
424
|
+
project_id_input = st.text_input("Enter Project ID", value=st.session_state.project_id_input, placeholder="e.g., 2ca6883f-6778-40bb-bcc1-85451fb11107")
|
|
425
|
+
if project_id_input != st.session_state.project_id_input:
|
|
426
|
+
st.session_state.project_id_input = project_id_input
|
|
427
|
+
st.session_state.selected_agent = "-"
|
|
428
|
+
st.rerun()
|
|
429
|
+
|
|
430
|
+
# Agent Selection
|
|
431
|
+
agent_list = get_agent_list(st.session_state.selected_alias, st.session_state.project_id_input) if st.session_state.selected_alias != "-" and st.session_state.project_id_input else ["-"]
|
|
432
|
+
selected_agent = st.selectbox("Select Agent", agent_list, index=agent_list.index(st.session_state.selected_agent) if st.session_state.selected_agent in agent_list else 0)
|
|
433
|
+
if selected_agent != st.session_state.selected_agent:
|
|
434
|
+
st.session_state.selected_agent = selected_agent
|
|
435
|
+
st.session_state.confirm_switch = False
|
|
436
|
+
|
|
437
|
+
# Agent Info Preview
|
|
438
|
+
if st.session_state.selected_agent != "-" and st.session_state.selected_agent in st.session_state.agent_data:
|
|
439
|
+
agent_obj = st.session_state.agent_data.get(st.session_state.selected_agent)
|
|
440
|
+
if agent_obj and getattr(agent_obj, 'description', None):
|
|
441
|
+
st.markdown("**Agent Description:**")
|
|
442
|
+
st.markdown(f"{agent_obj.description[:200]}{'...' if len(agent_obj.description) > 200 else ''}")
|
|
443
|
+
|
|
444
|
+
# Favorite/Recent Agents List
|
|
445
|
+
st.subheader("Recent Agents")
|
|
446
|
+
recent_agents = load_recent_agents()
|
|
447
|
+
if recent_agents:
|
|
448
|
+
for agent in recent_agents:
|
|
449
|
+
if st.button(f"Switch to {agent}", key=f"recent_{agent}"):
|
|
450
|
+
if agent != st.session_state.active_tab:
|
|
451
|
+
if agent not in st.session_state.sessions:
|
|
452
|
+
st.session_state.sessions[agent] = {
|
|
453
|
+
"messages": [],
|
|
454
|
+
"chat_session": AgentChatSession(agent),
|
|
455
|
+
"custom_filename": "",
|
|
456
|
+
"active": True
|
|
457
|
+
}
|
|
458
|
+
st.session_state.active_tab = agent
|
|
459
|
+
save_recent_agents(agent)
|
|
460
|
+
st.rerun()
|
|
461
|
+
else:
|
|
462
|
+
st.markdown("No recent agents found.")
|
|
463
|
+
|
|
464
|
+
# Confirmation for switching agent
|
|
465
|
+
if st.session_state.selected_agent != "-" and st.session_state.selected_agent.split(" (ID: ")[0] != st.session_state.active_tab:
|
|
466
|
+
if not st.session_state.confirm_switch:
|
|
467
|
+
st.warning(f"Do you wish to chat with {st.session_state.selected_agent.split(' (ID: ')[0]}? This will start a new session in a new tab.", icon="⚠️")
|
|
468
|
+
col1, col2 = st.columns(2)
|
|
469
|
+
with col1:
|
|
470
|
+
if st.button("Confirm Switch"):
|
|
471
|
+
st.session_state.confirm_switch = True
|
|
472
|
+
new_agent_name = st.session_state.selected_agent.split(" (ID: ")[0]
|
|
473
|
+
if new_agent_name not in st.session_state.sessions:
|
|
474
|
+
st.session_state.sessions[new_agent_name] = {
|
|
475
|
+
"messages": [],
|
|
476
|
+
"chat_session": AgentChatSession(new_agent_name),
|
|
477
|
+
"custom_filename": "",
|
|
478
|
+
"active": True
|
|
479
|
+
}
|
|
480
|
+
st.session_state.active_tab = new_agent_name
|
|
481
|
+
save_recent_agents(new_agent_name)
|
|
482
|
+
current_session = st.session_state.sessions[new_agent_name]
|
|
483
|
+
if not current_session["messages"]:
|
|
484
|
+
intro = current_session["chat_session"].get_answer(
|
|
485
|
+
["You're about to speak to a user. Introduce yourself in a clear and concise manner, "
|
|
486
|
+
"stating who you are and what you do. Nothing else."]
|
|
487
|
+
)
|
|
488
|
+
if "Agent not found" in str(intro):
|
|
489
|
+
st.error("The specified agent doesn't seem to exist. Please review the name and try again.")
|
|
490
|
+
logger.error("The specified agent doesn't seem to exist. Please review the name and try again.")
|
|
491
|
+
return
|
|
492
|
+
current_session["messages"] = [{"role": "assistant", "content": intro}]
|
|
493
|
+
SESSION_FILE_PATH = get_session_file_path(new_agent_name, current_session.get("custom_filename", ""))
|
|
494
|
+
if st.session_state.auto_save:
|
|
495
|
+
save_session_to_file(current_session["messages"], SESSION_FILE_PATH)
|
|
496
|
+
st.rerun()
|
|
497
|
+
with col2:
|
|
498
|
+
if st.button("Cancel"):
|
|
499
|
+
st.session_state.selected_agent = "-"
|
|
500
|
+
st.session_state.confirm_switch = False
|
|
501
|
+
st.rerun()
|
|
502
|
+
else:
|
|
503
|
+
st.success(f"Switched to agent {st.session_state.selected_agent.split(' (ID: ')[0]}!", icon="✅")
|
|
504
|
+
|
|
505
|
+
# Reset chat button for current tab
|
|
506
|
+
if st.button("Reset Chat"):
|
|
507
|
+
current_session["messages"] = []
|
|
508
|
+
intro = current_session["chat_session"].get_answer(
|
|
509
|
+
["You're about to speak to a user. Introduce yourself in a clear and concise manner, "
|
|
510
|
+
"stating who you are and what you do. Nothing else."]
|
|
511
|
+
)
|
|
512
|
+
if "Agent not found" in str(intro):
|
|
513
|
+
st.error("The specified agent doesn't seem to exist. Please review the name and try again.")
|
|
514
|
+
logger.error("The specified agent doesn't seem to exist. Please review the name and try again.")
|
|
515
|
+
return
|
|
516
|
+
current_session["messages"] = [{"role": "assistant", "content": intro}]
|
|
517
|
+
if st.session_state.auto_save:
|
|
518
|
+
save_session_to_file(current_session["messages"], SESSION_FILE_PATH)
|
|
519
|
+
st.rerun()
|
|
520
|
+
|
|
521
|
+
error_container = st.empty()
|
|
522
|
+
|
|
523
|
+
# "Complete Answer" button logic
|
|
524
|
+
if (current_session["messages"] and
|
|
525
|
+
current_session["messages"][-1]["role"] == "assistant" and
|
|
526
|
+
"complete_answer_triggered" not in st.session_state):
|
|
527
|
+
if st.button("Complete Answer"):
|
|
528
|
+
st.session_state.complete_answer_triggered = True
|
|
529
|
+
last_assistant_message = current_session["messages"][-1]["content"]
|
|
530
|
+
continuation_prompt = (
|
|
531
|
+
f"The previous answer was: '{last_assistant_message}'. "
|
|
532
|
+
"It seems incomplete. Please continue and complete the answer."
|
|
533
|
+
)
|
|
534
|
+
current_session["messages"].append({"role": "user", "content": continuation_prompt})
|
|
535
|
+
with st.chat_message("user"):
|
|
536
|
+
st.markdown(continuation_prompt)
|
|
537
|
+
with st.chat_message("assistant"):
|
|
538
|
+
with st.spinner("Continuing answer..."):
|
|
539
|
+
response_placeholder = st.empty()
|
|
540
|
+
continued_answer = ""
|
|
541
|
+
result = current_session["chat_session"].stream_answer(current_session["messages"])
|
|
542
|
+
for chunk in result:
|
|
543
|
+
continued_answer += chunk
|
|
544
|
+
sanitized_answer = continued_answer
|
|
545
|
+
response_placeholder.markdown(f'{sanitized_answer}')
|
|
546
|
+
current_session["messages"].append({"role": "assistant", "content": continued_answer})
|
|
547
|
+
if st.session_state.auto_save:
|
|
548
|
+
save_session_to_file(current_session["messages"], SESSION_FILE_PATH)
|
|
549
|
+
del st.session_state.complete_answer_triggered
|
|
550
|
+
st.rerun()
|
|
551
|
+
|
|
552
|
+
# Chat input for current tab
|
|
553
|
+
if user_input := st.chat_input(f"Ask {st.session_state.active_tab}"):
|
|
554
|
+
if not user_input.strip():
|
|
555
|
+
logger.warning(f"Empty input submitted for agent {st.session_state.active_tab}")
|
|
556
|
+
with error_container.container():
|
|
557
|
+
st.error(f"Unable to communicate with the agent {st.session_state.active_tab}")
|
|
558
|
+
return
|
|
559
|
+
error_container.empty()
|
|
560
|
+
|
|
561
|
+
# Append user message to session
|
|
562
|
+
with st.chat_message("user"):
|
|
563
|
+
st.markdown(f"{user_input}")
|
|
564
|
+
current_session["messages"].append({"role": "user", "content": user_input})
|
|
565
|
+
|
|
566
|
+
# Save session if auto_save is enabled
|
|
567
|
+
if st.session_state.auto_save:
|
|
568
|
+
save_session_to_file(current_session["messages"], SESSION_FILE_PATH)
|
|
569
|
+
|
|
570
|
+
# Stream assistant response
|
|
571
|
+
with st.chat_message("assistant"):
|
|
572
|
+
with st.spinner("Processing..."):
|
|
573
|
+
response_placeholder = st.empty()
|
|
574
|
+
answer = ""
|
|
575
|
+
result = current_session["chat_session"].stream_answer(current_session["messages"])
|
|
576
|
+
for chunk in result:
|
|
577
|
+
answer += chunk
|
|
578
|
+
sanitized_answer = answer
|
|
579
|
+
response_placeholder.markdown(f'{sanitized_answer}')
|
|
580
|
+
|
|
581
|
+
# Append the complete response to session
|
|
582
|
+
current_session["messages"].append({"role": "assistant", "content": answer})
|
|
583
|
+
|
|
584
|
+
# Save session again after assistant response
|
|
585
|
+
if st.session_state.auto_save:
|
|
586
|
+
save_session_to_file(current_session["messages"], SESSION_FILE_PATH)
|
|
587
|
+
st.rerun()
|
|
588
|
+
except Exception as e:
|
|
589
|
+
st.error(f"An unexpected error occurred: {e}")
|
|
590
|
+
logger.error(f"An unexpected error occurred: {e}")
|
|
591
|
+
Console.write_stderr("An unexpected error has occurred. Please contact the developers.")
|
|
592
|
+
sys.exit(1)
|
|
593
|
+
|
|
594
|
+
|
|
595
|
+
def render_chat_history(messages, search_term="", tab_key_prefix="", session=None):
|
|
596
|
+
"""Render chat history with search filter, copy, and edit buttons."""
|
|
597
|
+
|
|
598
|
+
global auto_save
|
|
599
|
+
|
|
600
|
+
filtered_messages = []
|
|
601
|
+
if search_term:
|
|
602
|
+
search_term = search_term.lower()
|
|
603
|
+
filtered_messages = [msg for msg in messages if search_term in msg["content"].lower()]
|
|
604
|
+
else:
|
|
605
|
+
filtered_messages = messages
|
|
606
|
+
|
|
607
|
+
if search_term and not filtered_messages:
|
|
608
|
+
st.info("No messages match your search term.", icon="ℹ️")
|
|
609
|
+
elif search_term:
|
|
610
|
+
st.info(f"Showing {len(filtered_messages)} messages matching '{search_term}'", icon="🔍")
|
|
611
|
+
|
|
612
|
+
# Find the index of the last user message in the filtered list for edit button display
|
|
613
|
+
last_user_msg_index = None
|
|
614
|
+
for i, msg in enumerate(filtered_messages):
|
|
615
|
+
if msg["role"] == "user":
|
|
616
|
+
last_user_msg_index = i
|
|
617
|
+
|
|
618
|
+
for i, message in enumerate(filtered_messages):
|
|
619
|
+
with st.chat_message(message["role"]):
|
|
620
|
+
col1, col2 = st.columns([5, 1])
|
|
621
|
+
with col1:
|
|
622
|
+
st.markdown(message["content"])
|
|
623
|
+
with col2:
|
|
624
|
+
# Edit Button - Only for the last user message
|
|
625
|
+
if message["role"] == "user" and i == last_user_msg_index:
|
|
626
|
+
if st.button("✏️", key=f"{tab_key_prefix}_edit_{i}", help="Edit this message"):
|
|
627
|
+
session["editing_message"] = i
|
|
628
|
+
session["edit_content"] = message["content"]
|
|
629
|
+
st.rerun()
|
|
630
|
+
|
|
631
|
+
# Handle Message Editing
|
|
632
|
+
if session and session.get("editing_message") is not None:
|
|
633
|
+
with st.container():
|
|
634
|
+
st.markdown("**Editing Message:**")
|
|
635
|
+
new_content = st.text_area(
|
|
636
|
+
"Edit your message:",
|
|
637
|
+
value=session.get("edit_content", ""),
|
|
638
|
+
key=f"{tab_key_prefix}_edit_area"
|
|
639
|
+
)
|
|
640
|
+
col1, col2 = st.columns(2)
|
|
641
|
+
with col1:
|
|
642
|
+
if st.button("Save Edit", key=f"{tab_key_prefix}_save_edit"):
|
|
643
|
+
# Update the message content
|
|
644
|
+
messages[session["editing_message"]]["content"] = new_content
|
|
645
|
+
# Check if there's a subsequent agent response to remove
|
|
646
|
+
if session["editing_message"] + 1 < len(messages) and messages[session["editing_message"] + 1]["role"] == "assistant":
|
|
647
|
+
messages.pop(session["editing_message"] + 1) # Remove the old response
|
|
648
|
+
session["regenerate_response"] = True # Flag to regenerate response
|
|
649
|
+
session["editing_message"] = None
|
|
650
|
+
session["edit_content"] = ""
|
|
651
|
+
st.rerun()
|
|
652
|
+
with col2:
|
|
653
|
+
if st.button("Cancel Edit", key=f"{tab_key_prefix}_cancel_edit"):
|
|
654
|
+
session["editing_message"] = None
|
|
655
|
+
session["edit_content"] = ""
|
|
656
|
+
session["regenerate_response"] = False
|
|
657
|
+
st.rerun()
|
|
658
|
+
|
|
659
|
+
# Regenerate agent response if needed after edit
|
|
660
|
+
if session and session.get("regenerate_response"):
|
|
661
|
+
with st.chat_message("assistant"):
|
|
662
|
+
with st.spinner("Regenerating response..."):
|
|
663
|
+
response_placeholder = st.empty()
|
|
664
|
+
answer = ""
|
|
665
|
+
result = current_session["chat_session"].stream_answer(messages)
|
|
666
|
+
for chunk in result:
|
|
667
|
+
answer += chunk
|
|
668
|
+
sanitized_answer = answer
|
|
669
|
+
response_placeholder.markdown(f'{sanitized_answer}')
|
|
670
|
+
messages.append({"role": "assistant", "content": answer})
|
|
671
|
+
if st.session_state.auto_save:
|
|
672
|
+
save_session_to_file(messages, SESSION_FILE_PATH)
|
|
673
|
+
session["regenerate_response"] = False
|
|
674
|
+
st.rerun()
|
|
675
|
+
|
|
676
|
+
|
|
677
|
+
if __name__ == "__main__":
|
|
678
|
+
run_streamlit_chat()
|