diff --git a/poetry.lock b/poetry.lock index 7e2f05e9..fc24a31f 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.1.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand. [[package]] name = "about-time" @@ -452,6 +452,18 @@ cffi = ">=1.0.1" dev = ["cogapp", "pre-commit", "pytest", "wheel"] tests = ["pytest"] +[[package]] +name = "argparse" +version = "1.4.0" +description = "Python command-line parsing library" +optional = false +python-versions = "*" +groups = ["main"] +files = [ + {file = "argparse-1.4.0-py2.py3-none-any.whl", hash = "sha256:c31647edb69fd3d465a847ea3157d37bed1f95f19760b11a47aa91c04b666314"}, + {file = "argparse-1.4.0.tar.gz", hash = "sha256:62b089a55be1d8949cd2bc7e0df0bddb9e028faefc8c32038cc84862aefdd6e4"}, +] + [[package]] name = "arrow" version = "1.3.0" @@ -1405,24 +1417,6 @@ files = [ {file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"}, ] -[[package]] -name = "deprecated" -version = "1.2.18" -description = "Python @deprecated decorator to deprecate old python classes, functions or methods." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" -groups = ["main"] -files = [ - {file = "Deprecated-1.2.18-py2.py3-none-any.whl", hash = "sha256:bd5011788200372a32418f888e326a09ff80d0214bd961147cfed01b5c018eec"}, - {file = "deprecated-1.2.18.tar.gz", hash = "sha256:422b6f6d859da6f2ef57857761bfb392480502a64c3028ca9bbe86085d72115d"}, -] - -[package.dependencies] -wrapt = ">=1.10,<2" - -[package.extras] -dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "setuptools ; python_version >= \"3.12\"", "tox"] - [[package]] name = "distlib" version = "0.3.9" @@ -2330,7 +2324,7 @@ description = "Lightweight in-process concurrent programming" optional = false python-versions = ">=3.9" groups = ["main"] -markers = "python_version >= \"3.12\"" +markers = "python_version == \"3.12\" or python_version == \"3.13\"" files = [ {file = "greenlet-3.2.2-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:c49e9f7c6f625507ed83a7485366b46cbe325717c60837f7244fc99ba16ba9d6"}, {file = "greenlet-3.2.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c3cc1a3ed00ecfea8932477f729a9f616ad7347a5e55d50929efa50a86cb7be7"}, @@ -2864,6 +2858,18 @@ perf = ["ipython"] test = ["flufl.flake8", "importlib_resources (>=1.3) ; python_version < \"3.9\"", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"] type = ["pytest-mypy"] +[[package]] +name = "inflection" +version = "0.5.1" +description = "A port of Ruby on Rails inflector to Python" +optional = false +python-versions = ">=3.5" +groups = ["main"] +files = [ + {file = "inflection-0.5.1-py2.py3-none-any.whl", hash = "sha256:f38b2b640938a4f35ade69ac3d053042959b62a0f1076a5bbaa1b9526605a8a2"}, + {file = "inflection-0.5.1.tar.gz", hash = "sha256:1a29730d366e996aaacffb2f1f1cb9593dc38e2ddd30c91250c6dde09ea9b417"}, +] + [[package]] name = "iniconfig" version = "2.1.0" @@ -3103,7 +3109,7 @@ description = "Low-level, pure Python DBus protocol wrapper." optional = false python-versions = ">=3.7" groups = ["dev"] -markers = "sys_platform == \"linux\" and platform_machine != \"ppc64le\" and platform_machine != \"s390x\"" +markers = "platform_machine != \"ppc64le\" and platform_machine != \"s390x\" and sys_platform == \"linux\"" files = [ {file = "jeepney-0.9.0-py3-none-any.whl", hash = "sha256:97e5714520c16fc0a45695e5365a2e11b81ea79bba796e26f9f1d178cb182683"}, {file = "jeepney-0.9.0.tar.gz", hash = "sha256:cf0e9e845622b81e4a28df94c40345400256ec608d0e55bb8a3feaa9163f5732"}, @@ -3799,6 +3805,91 @@ extra-proxy = ["azure-identity (>=1.15.0,<2.0.0)", "azure-keyvault-secrets (>=4. proxy = ["PyJWT (>=2.8.0,<3.0.0)", "apscheduler (>=3.10.4,<4.0.0)", "backoff", "boto3 (==1.34.34)", "cryptography (>=43.0.1,<44.0.0)", "fastapi (>=0.115.5,<0.116.0)", "fastapi-sso (>=0.16.0,<0.17.0)", "gunicorn (>=23.0.0,<24.0.0)", "litellm-enterprise (==0.1.9)", "litellm-proxy-extras (==0.2.6)", "mcp (==1.9.3) ; python_version >= \"3.10\"", "orjson (>=3.9.7,<4.0.0)", "pynacl (>=1.5.0,<2.0.0)", "python-multipart (>=0.0.18,<0.0.19)", "pyyaml (>=6.0.1,<7.0.0)", "rich (==13.7.1)", "rq", "uvicorn (>=0.29.0,<0.30.0)", "uvloop (>=0.21.0,<0.22.0) ; sys_platform != \"win32\"", "websockets (>=13.1.0,<14.0.0)"] utils = ["numpydoc"] +[[package]] +name = "lmnr" +version = "0.6.16" +description = "Python SDK for Laminar" +optional = false +python-versions = "<4,>=3.10" +groups = ["main"] +files = [ + {file = "lmnr-0.6.16-py3-none-any.whl", hash = "sha256:9bd964147befd775fa667731ed0022f23d829d67bb7f0e28ccda57f062795e9c"}, + {file = "lmnr-0.6.16.tar.gz", hash = "sha256:5001cdf487af169dffc78658b46427b579f28b9ec541c2f220a3c7aabe3e1f0a"}, +] + +[package.dependencies] +argparse = ">=1.0" +grpcio = ">=1" +httpx = ">=0.25.0" +opentelemetry-api = ">=1.33.0" +opentelemetry-exporter-otlp-proto-grpc = ">=1.33.0" +opentelemetry-exporter-otlp-proto-http = ">=1.33.0" +opentelemetry-instrumentation-alephalpha = {version = ">=0.40.12", optional = true, markers = "extra == \"all\""} +opentelemetry-instrumentation-anthropic = {version = ">=0.40.12", optional = true, markers = "extra == \"all\""} +opentelemetry-instrumentation-bedrock = {version = ">=0.40.12", optional = true, markers = "extra == \"all\""} +opentelemetry-instrumentation-chromadb = {version = ">=0.40.12", optional = true, markers = "extra == \"all\""} +opentelemetry-instrumentation-cohere = {version = ">=0.40.12", optional = true, markers = "extra == \"all\""} +opentelemetry-instrumentation-crewai = {version = ">=0.40.12", optional = true, markers = "extra == \"all\""} +opentelemetry-instrumentation-google-generativeai = {version = "<0.40.10", optional = true, markers = "extra == \"all\""} +opentelemetry-instrumentation-groq = {version = ">=0.40.12", optional = true, markers = "extra == \"all\""} +opentelemetry-instrumentation-haystack = {version = ">=0.40.12", optional = true, markers = "extra == \"all\""} +opentelemetry-instrumentation-lancedb = {version = ">=0.40.12", optional = true, markers = "extra == \"all\""} +opentelemetry-instrumentation-langchain = {version = ">=0.40.12", optional = true, markers = "extra == \"all\""} +opentelemetry-instrumentation-llamaindex = {version = ">=0.40.12", optional = true, markers = "extra == \"all\""} +opentelemetry-instrumentation-marqo = {version = ">=0.40.12", optional = true, markers = "extra == \"all\""} +opentelemetry-instrumentation-mcp = {version = ">=0.40.12", optional = true, markers = "extra == \"all\""} +opentelemetry-instrumentation-milvus = {version = ">=0.40.12", optional = true, markers = "extra == \"all\""} +opentelemetry-instrumentation-mistralai = {version = ">=0.40.12", optional = true, markers = "extra == \"all\""} +opentelemetry-instrumentation-ollama = {version = ">=0.40.12", optional = true, markers = "extra == \"all\""} +opentelemetry-instrumentation-openai = {version = ">=0.40.12", optional = true, markers = "extra == \"all\""} +opentelemetry-instrumentation-pinecone = {version = ">=0.40.12", optional = true, markers = "extra == \"all\""} +opentelemetry-instrumentation-qdrant = {version = ">=0.40.12", optional = true, markers = "extra == \"all\""} +opentelemetry-instrumentation-replicate = {version = ">=0.40.12", optional = true, markers = "extra == \"all\""} +opentelemetry-instrumentation-sagemaker = {version = ">=0.40.12", optional = true, markers = "extra == \"all\""} +opentelemetry-instrumentation-threading = ">=0.54b0" +opentelemetry-instrumentation-together = {version = ">=0.40.12", optional = true, markers = "extra == \"all\""} +opentelemetry-instrumentation-transformers = {version = ">=0.40.12", optional = true, markers = "extra == \"all\""} +opentelemetry-instrumentation-vertexai = {version = ">=0.40.12", optional = true, markers = "extra == \"all\""} +opentelemetry-instrumentation-watsonx = {version = ">=0.40.12", optional = true, markers = "extra == \"all\""} +opentelemetry-instrumentation-weaviate = {version = ">=0.40.12", optional = true, markers = "extra == \"all\""} +opentelemetry-sdk = ">=1.33.0" +opentelemetry-semantic-conventions = ">=0.54b0" +opentelemetry-semantic-conventions-ai = ">=0.4.8" +pydantic = ">=2.0.3,<3.0.0" +python-dotenv = ">=1.0" +tenacity = ">=8.0" +tqdm = ">=4.0" + +[package.extras] +alephalpha = ["opentelemetry-instrumentation-alephalpha (>=0.40.12)"] +all = ["opentelemetry-instrumentation-alephalpha (>=0.40.12)", "opentelemetry-instrumentation-anthropic (>=0.40.12)", "opentelemetry-instrumentation-bedrock (>=0.40.12)", "opentelemetry-instrumentation-chromadb (>=0.40.12)", "opentelemetry-instrumentation-cohere (>=0.40.12)", "opentelemetry-instrumentation-crewai (>=0.40.12)", "opentelemetry-instrumentation-google-generativeai (<0.40.10)", "opentelemetry-instrumentation-groq (>=0.40.12)", "opentelemetry-instrumentation-haystack (>=0.40.12)", "opentelemetry-instrumentation-lancedb (>=0.40.12)", "opentelemetry-instrumentation-langchain (>=0.40.12)", "opentelemetry-instrumentation-llamaindex (>=0.40.12)", "opentelemetry-instrumentation-marqo (>=0.40.12)", "opentelemetry-instrumentation-mcp (>=0.40.12)", "opentelemetry-instrumentation-milvus (>=0.40.12)", "opentelemetry-instrumentation-mistralai (>=0.40.12)", "opentelemetry-instrumentation-ollama (>=0.40.12)", "opentelemetry-instrumentation-openai (>=0.40.12)", "opentelemetry-instrumentation-pinecone (>=0.40.12)", "opentelemetry-instrumentation-qdrant (>=0.40.12)", "opentelemetry-instrumentation-replicate (>=0.40.12)", "opentelemetry-instrumentation-sagemaker (>=0.40.12)", "opentelemetry-instrumentation-together (>=0.40.12)", "opentelemetry-instrumentation-transformers (>=0.40.12)", "opentelemetry-instrumentation-vertexai (>=0.40.12)", "opentelemetry-instrumentation-watsonx (>=0.40.12)", "opentelemetry-instrumentation-weaviate (>=0.40.12)"] +anthropic = ["opentelemetry-instrumentation-anthropic (>=0.40.12)"] +bedrock = ["opentelemetry-instrumentation-bedrock (>=0.40.12)"] +chromadb = ["opentelemetry-instrumentation-chromadb (>=0.40.12)"] +cohere = ["opentelemetry-instrumentation-cohere (>=0.40.12)"] +crewai = ["opentelemetry-instrumentation-crewai (>=0.40.12)"] +google-generativeai = ["opentelemetry-instrumentation-google-generativeai (<0.40.10)"] +groq = ["opentelemetry-instrumentation-groq (>=0.40.12)"] +haystack = ["opentelemetry-instrumentation-haystack (>=0.40.12)"] +lancedb = ["opentelemetry-instrumentation-lancedb (>=0.40.12)"] +langchain = ["opentelemetry-instrumentation-langchain (>=0.40.12)"] +llamaindex = ["opentelemetry-instrumentation-llamaindex (>=0.40.12)"] +marqo = ["opentelemetry-instrumentation-marqo (>=0.40.12)"] +mcp = ["opentelemetry-instrumentation-mcp (>=0.40.12)"] +milvus = ["opentelemetry-instrumentation-milvus (>=0.40.12)"] +mistralai = ["opentelemetry-instrumentation-mistralai (>=0.40.12)"] +ollama = ["opentelemetry-instrumentation-ollama (>=0.40.12)"] +openai = ["opentelemetry-instrumentation-openai (>=0.40.12)"] +pinecone = ["opentelemetry-instrumentation-pinecone (>=0.40.12)"] +qdrant = ["opentelemetry-instrumentation-qdrant (>=0.40.12)"] +replicate = ["opentelemetry-instrumentation-replicate (>=0.40.12)"] +sagemaker = ["opentelemetry-instrumentation-sagemaker (>=0.40.12)"] +together = ["opentelemetry-instrumentation-together (>=0.40.12)"] +transformers = ["opentelemetry-instrumentation-transformers (>=0.40.12)"] +vertexai = ["opentelemetry-instrumentation-vertexai (>=0.40.12)"] +watsonx = ["opentelemetry-instrumentation-watsonx (>=0.40.12)"] +weaviate = ["opentelemetry-instrumentation-weaviate (>=0.40.12)"] + [[package]] name = "mako" version = "1.3.10" @@ -4649,7 +4740,7 @@ description = "ONNX Runtime is a runtime accelerator for Machine Learning models optional = false python-versions = ">=3.10" groups = ["main"] -markers = "python_version >= \"3.12\"" +markers = "python_version == \"3.12\" or python_version == \"3.13\"" files = [ {file = "onnxruntime-1.22.0-cp310-cp310-macosx_13_0_universal2.whl", hash = "sha256:85d8826cc8054e4d6bf07f779dc742a363c39094015bdad6a08b3c18cfe0ba8c"}, {file = "onnxruntime-1.22.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:468c9502a12f6f49ec335c2febd22fdceecc1e4cc96dfc27e419ba237dff5aff"}, @@ -4743,19 +4834,664 @@ openapi-schema-validator = ">=0.6.0,<0.7.0" [[package]] name = "opentelemetry-api" -version = "1.32.1" +version = "1.34.1" description = "OpenTelemetry Python API" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" groups = ["main"] files = [ - {file = "opentelemetry_api-1.32.1-py3-none-any.whl", hash = "sha256:bbd19f14ab9f15f0e85e43e6a958aa4cb1f36870ee62b7fd205783a112012724"}, - {file = "opentelemetry_api-1.32.1.tar.gz", hash = "sha256:a5be71591694a4d9195caf6776b055aa702e964d961051a0715d05f8632c32fb"}, + {file = "opentelemetry_api-1.34.1-py3-none-any.whl", hash = "sha256:b7df4cb0830d5a6c29ad0c0691dbae874d8daefa934b8b1d642de48323d32a8c"}, + {file = "opentelemetry_api-1.34.1.tar.gz", hash = "sha256:64f0bd06d42824843731d05beea88d4d4b6ae59f9fe347ff7dfa2cc14233bbb3"}, ] [package.dependencies] -deprecated = ">=1.2.6" -importlib-metadata = ">=6.0,<8.7.0" +importlib-metadata = ">=6.0,<8.8.0" +typing-extensions = ">=4.5.0" + +[[package]] +name = "opentelemetry-exporter-otlp-proto-common" +version = "1.34.1" +description = "OpenTelemetry Protobuf encoding" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "opentelemetry_exporter_otlp_proto_common-1.34.1-py3-none-any.whl", hash = "sha256:8e2019284bf24d3deebbb6c59c71e6eef3307cd88eff8c633e061abba33f7e87"}, + {file = "opentelemetry_exporter_otlp_proto_common-1.34.1.tar.gz", hash = "sha256:b59a20a927facd5eac06edaf87a07e49f9e4a13db487b7d8a52b37cb87710f8b"}, +] + +[package.dependencies] +opentelemetry-proto = "1.34.1" + +[[package]] +name = "opentelemetry-exporter-otlp-proto-grpc" +version = "1.34.1" +description = "OpenTelemetry Collector Protobuf over gRPC Exporter" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "opentelemetry_exporter_otlp_proto_grpc-1.34.1-py3-none-any.whl", hash = "sha256:04bb8b732b02295be79f8a86a4ad28fae3d4ddb07307a98c7aa6f331de18cca6"}, + {file = "opentelemetry_exporter_otlp_proto_grpc-1.34.1.tar.gz", hash = "sha256:7c841b90caa3aafcfc4fee58487a6c71743c34c6dc1787089d8b0578bbd794dd"}, +] + +[package.dependencies] +googleapis-common-protos = ">=1.52,<2.0" +grpcio = [ + {version = ">=1.63.2,<2.0.0", markers = "python_version < \"3.13\""}, + {version = ">=1.66.2,<2.0.0", markers = "python_version >= \"3.13\""}, +] +opentelemetry-api = ">=1.15,<2.0" +opentelemetry-exporter-otlp-proto-common = "1.34.1" +opentelemetry-proto = "1.34.1" +opentelemetry-sdk = ">=1.34.1,<1.35.0" +typing-extensions = ">=4.5.0" + +[[package]] +name = "opentelemetry-exporter-otlp-proto-http" +version = "1.34.1" +description = "OpenTelemetry Collector Protobuf over HTTP Exporter" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "opentelemetry_exporter_otlp_proto_http-1.34.1-py3-none-any.whl", hash = "sha256:5251f00ca85872ce50d871f6d3cc89fe203b94c3c14c964bbdc3883366c705d8"}, + {file = "opentelemetry_exporter_otlp_proto_http-1.34.1.tar.gz", hash = "sha256:aaac36fdce46a8191e604dcf632e1f9380c7d5b356b27b3e0edb5610d9be28ad"}, +] + +[package.dependencies] +googleapis-common-protos = ">=1.52,<2.0" +opentelemetry-api = ">=1.15,<2.0" +opentelemetry-exporter-otlp-proto-common = "1.34.1" +opentelemetry-proto = "1.34.1" +opentelemetry-sdk = ">=1.34.1,<1.35.0" +requests = ">=2.7,<3.0" +typing-extensions = ">=4.5.0" + +[[package]] +name = "opentelemetry-instrumentation" +version = "0.55b1" +description = "Instrumentation Tools & Auto Instrumentation for OpenTelemetry Python" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "opentelemetry_instrumentation-0.55b1-py3-none-any.whl", hash = "sha256:cbb1496b42bc394e01bc63701b10e69094e8564e281de063e4328d122cc7a97e"}, + {file = "opentelemetry_instrumentation-0.55b1.tar.gz", hash = "sha256:2dc50aa207b9bfa16f70a1a0571e011e737a9917408934675b89ef4d5718c87b"}, +] + +[package.dependencies] +opentelemetry-api = ">=1.4,<2.0" +opentelemetry-semantic-conventions = "0.55b1" +packaging = ">=18.0" +wrapt = ">=1.0.0,<2.0.0" + +[[package]] +name = "opentelemetry-instrumentation-alephalpha" +version = "0.40.14" +description = "OpenTelemetry Aleph Alpha instrumentation" +optional = false +python-versions = "<4,>=3.9" +groups = ["main"] +files = [ + {file = "opentelemetry_instrumentation_alephalpha-0.40.14-py3-none-any.whl", hash = "sha256:2dfc50a7ab40edca2fecc18c38f3b7ef3942294bda2e8283298bbd51ec1f3f82"}, + {file = "opentelemetry_instrumentation_alephalpha-0.40.14.tar.gz", hash = "sha256:a015d7697645e9275637152d1d94f2df8e3f7c9d1ee3f983f4987ffc927f186c"}, +] + +[package.dependencies] +opentelemetry-api = ">=1.28.0,<2.0.0" +opentelemetry-instrumentation = ">=0.50b0" +opentelemetry-semantic-conventions = ">=0.50b0" +opentelemetry-semantic-conventions-ai = "0.4.9" + +[[package]] +name = "opentelemetry-instrumentation-anthropic" +version = "0.40.14" +description = "OpenTelemetry Anthropic instrumentation" +optional = false +python-versions = "<4,>=3.9" +groups = ["main"] +files = [ + {file = "opentelemetry_instrumentation_anthropic-0.40.14-py3-none-any.whl", hash = "sha256:d516a7aaa4b81b6fa6585f3db7a84feacb288fc56721484c63422ea6a9119c00"}, + {file = "opentelemetry_instrumentation_anthropic-0.40.14.tar.gz", hash = "sha256:5450cc52fbbd916c21fc74df511e93ce794e889fbd916f90decaa1240893419e"}, +] + +[package.dependencies] +opentelemetry-api = ">=1.28.0,<2.0.0" +opentelemetry-instrumentation = ">=0.50b0" +opentelemetry-semantic-conventions = ">=0.50b0" +opentelemetry-semantic-conventions-ai = "0.4.9" + +[[package]] +name = "opentelemetry-instrumentation-bedrock" +version = "0.40.14" +description = "OpenTelemetry Bedrock instrumentation" +optional = false +python-versions = "<4,>=3.9" +groups = ["main"] +files = [ + {file = "opentelemetry_instrumentation_bedrock-0.40.14-py3-none-any.whl", hash = "sha256:ba2a78bbc83f246f52bd1eaf2ed6d4a53ab37fad09ff0ca550b7f7bc3f0f9466"}, + {file = "opentelemetry_instrumentation_bedrock-0.40.14.tar.gz", hash = "sha256:6e3be927922825992baf07e45521ed4f9cfd5d015e7d14714d478920241d6656"}, +] + +[package.dependencies] +anthropic = ">=0.17.0" +opentelemetry-api = ">=1.28.0,<2.0.0" +opentelemetry-instrumentation = ">=0.50b0" +opentelemetry-semantic-conventions = ">=0.50b0" +opentelemetry-semantic-conventions-ai = "0.4.9" +tokenizers = ">=0.13.0" + +[[package]] +name = "opentelemetry-instrumentation-chromadb" +version = "0.40.14" +description = "OpenTelemetry Chroma DB instrumentation" +optional = false +python-versions = "<4,>=3.9" +groups = ["main"] +files = [ + {file = "opentelemetry_instrumentation_chromadb-0.40.14-py3-none-any.whl", hash = "sha256:ac721939d63c988f787e11f22e2df8003da4f8346c7485d7c25fb82a4edf5f9f"}, + {file = "opentelemetry_instrumentation_chromadb-0.40.14.tar.gz", hash = "sha256:db2f01b324f95b5b69a6ad2152d855c1707290d3cd270702f3216cbae736c6d5"}, +] + +[package.dependencies] +opentelemetry-api = ">=1.28.0,<2.0.0" +opentelemetry-instrumentation = ">=0.50b0" +opentelemetry-semantic-conventions = ">=0.50b0" +opentelemetry-semantic-conventions-ai = "0.4.9" + +[[package]] +name = "opentelemetry-instrumentation-cohere" +version = "0.40.14" +description = "OpenTelemetry Cohere instrumentation" +optional = false +python-versions = "<4,>=3.9" +groups = ["main"] +files = [ + {file = "opentelemetry_instrumentation_cohere-0.40.14-py3-none-any.whl", hash = "sha256:23457fb8d0bffc405f1d22b940c49ac00358b2f5f5190466a2d687e62b819bf6"}, + {file = "opentelemetry_instrumentation_cohere-0.40.14.tar.gz", hash = "sha256:4515396ca8b381fde45b7905db33a4da45a01c5346e4b4a567dff160bd85fb5e"}, +] + +[package.dependencies] +opentelemetry-api = ">=1.28.0,<2.0.0" +opentelemetry-instrumentation = ">=0.50b0" +opentelemetry-semantic-conventions = ">=0.50b0" +opentelemetry-semantic-conventions-ai = "0.4.9" + +[[package]] +name = "opentelemetry-instrumentation-crewai" +version = "0.40.14" +description = "OpenTelemetry crewAI instrumentation" +optional = false +python-versions = "<4,>=3.10" +groups = ["main"] +files = [ + {file = "opentelemetry_instrumentation_crewai-0.40.14-py3-none-any.whl", hash = "sha256:021ef20c0761a77be803623ce90e0697d17c27615d4aba8012d8b72982528641"}, + {file = "opentelemetry_instrumentation_crewai-0.40.14.tar.gz", hash = "sha256:ce8b0140210c3a695a205bda1a6a0579c50aaf862598d20a5c3eebb7fb74401d"}, +] + +[package.dependencies] +opentelemetry-api = ">=1.28.0,<2.0.0" +opentelemetry-instrumentation = ">=0.50b0" +opentelemetry-semantic-conventions = ">=0.50b0" +opentelemetry-semantic-conventions-ai = "0.4.9" + +[[package]] +name = "opentelemetry-instrumentation-google-generativeai" +version = "0.40.9" +description = "OpenTelemetry Google Generative AI instrumentation" +optional = false +python-versions = "<4,>=3.9" +groups = ["main"] +files = [ + {file = "opentelemetry_instrumentation_google_generativeai-0.40.9-py3-none-any.whl", hash = "sha256:473ffe01f617b173072f71b1b092ac1932055817aa700e3a8fdfb1ca1085040b"}, + {file = "opentelemetry_instrumentation_google_generativeai-0.40.9.tar.gz", hash = "sha256:4b901794a9690229fd5ebc3ce82addbdaa4b76123d8299652306ac8dcee892fa"}, +] + +[package.dependencies] +opentelemetry-api = ">=1.28.0,<2.0.0" +opentelemetry-instrumentation = ">=0.50b0" +opentelemetry-semantic-conventions = ">=0.50b0" +opentelemetry-semantic-conventions-ai = "0.4.9" + +[[package]] +name = "opentelemetry-instrumentation-groq" +version = "0.40.14" +description = "OpenTelemetry Groq instrumentation" +optional = false +python-versions = "<4,>=3.9" +groups = ["main"] +files = [ + {file = "opentelemetry_instrumentation_groq-0.40.14-py3-none-any.whl", hash = "sha256:f53342c8980d7546264e41cf4afecb604f4b590430dfe2d9d863b97225e2ee0a"}, + {file = "opentelemetry_instrumentation_groq-0.40.14.tar.gz", hash = "sha256:f2f6b787382dac7309f28eed7f27a8ff6e36caf7e8fe85c02f09fc75b9967838"}, +] + +[package.dependencies] +opentelemetry-api = ">=1.28.0,<2.0.0" +opentelemetry-instrumentation = ">=0.50b0" +opentelemetry-semantic-conventions = ">=0.50b0" +opentelemetry-semantic-conventions-ai = "0.4.9" + +[[package]] +name = "opentelemetry-instrumentation-haystack" +version = "0.40.14" +description = "OpenTelemetry Haystack instrumentation" +optional = false +python-versions = "<4,>=3.9" +groups = ["main"] +files = [ + {file = "opentelemetry_instrumentation_haystack-0.40.14-py3-none-any.whl", hash = "sha256:b11c6e57c0c66dc9154f7c8328c5018501f268224c53307c0518a6e407d91cae"}, + {file = "opentelemetry_instrumentation_haystack-0.40.14.tar.gz", hash = "sha256:e49be73ccb2302ebace9a28014ab20dbcaec6d00893358de54b9054202596f9b"}, +] + +[package.dependencies] +opentelemetry-api = ">=1.28.0,<2.0.0" +opentelemetry-instrumentation = ">=0.50b0" +opentelemetry-semantic-conventions = ">=0.50b0" +opentelemetry-semantic-conventions-ai = "0.4.9" + +[[package]] +name = "opentelemetry-instrumentation-lancedb" +version = "0.40.14" +description = "OpenTelemetry Lancedb instrumentation" +optional = false +python-versions = "<4,>=3.9" +groups = ["main"] +files = [ + {file = "opentelemetry_instrumentation_lancedb-0.40.14-py3-none-any.whl", hash = "sha256:3dc37d8b2791fe4769c1b8ffe90c9ccd53af57ccd0ec100ed3da387b60b88021"}, + {file = "opentelemetry_instrumentation_lancedb-0.40.14.tar.gz", hash = "sha256:0907ddd3f8639880c2c65cb94789dc4ca0b0ef19a79173dd1278ab7fd80178a6"}, +] + +[package.dependencies] +opentelemetry-api = ">=1.28.0,<2.0.0" +opentelemetry-instrumentation = ">=0.50b0" +opentelemetry-semantic-conventions = ">=0.50b0" +opentelemetry-semantic-conventions-ai = "0.4.9" + +[[package]] +name = "opentelemetry-instrumentation-langchain" +version = "0.40.14" +description = "OpenTelemetry Langchain instrumentation" +optional = false +python-versions = "<4,>=3.9" +groups = ["main"] +files = [ + {file = "opentelemetry_instrumentation_langchain-0.40.14-py3-none-any.whl", hash = "sha256:f400d25b1c5fb03fcaabae40970a7980d9c45d2b22e0ceeb99ce62b7b3d3c6e2"}, + {file = "opentelemetry_instrumentation_langchain-0.40.14.tar.gz", hash = "sha256:a196eef6990b98fc67acca945883e39fbdaf075f8a36636e7a9e580092f7c3ea"}, +] + +[package.dependencies] +opentelemetry-api = ">=1.28.0,<2.0.0" +opentelemetry-instrumentation = ">=0.50b0" +opentelemetry-semantic-conventions = ">=0.50b0" +opentelemetry-semantic-conventions-ai = "0.4.9" + +[[package]] +name = "opentelemetry-instrumentation-llamaindex" +version = "0.40.14" +description = "OpenTelemetry LlamaIndex instrumentation" +optional = false +python-versions = "<4,>=3.9" +groups = ["main"] +files = [ + {file = "opentelemetry_instrumentation_llamaindex-0.40.14-py3-none-any.whl", hash = "sha256:20362a9e94cf3a5632e62baaedd1f1a003674230d6a4352f2a83716751351267"}, + {file = "opentelemetry_instrumentation_llamaindex-0.40.14.tar.gz", hash = "sha256:9916136126cd59c8360b189b022af6337f3ed091dccbf11317b045c452e5185b"}, +] + +[package.dependencies] +inflection = ">=0.5.1,<0.6.0" +opentelemetry-api = ">=1.28.0,<2.0.0" +opentelemetry-instrumentation = ">=0.50b0" +opentelemetry-semantic-conventions = ">=0.50b0" +opentelemetry-semantic-conventions-ai = "0.4.9" + +[[package]] +name = "opentelemetry-instrumentation-marqo" +version = "0.40.14" +description = "OpenTelemetry Marqo instrumentation" +optional = false +python-versions = "<4,>=3.9" +groups = ["main"] +files = [ + {file = "opentelemetry_instrumentation_marqo-0.40.14-py3-none-any.whl", hash = "sha256:db93511f2a6990cf6cc3dcbb1279847f72723671503ca4a5a896c3595711e932"}, + {file = "opentelemetry_instrumentation_marqo-0.40.14.tar.gz", hash = "sha256:1710e2d079ccb7e5aef9d204acde5bae002028a95865fec3e711ae1f07ffbc25"}, +] + +[package.dependencies] +opentelemetry-api = ">=1.28.0,<2.0.0" +opentelemetry-instrumentation = ">=0.50b0" +opentelemetry-semantic-conventions = ">=0.50b0" +opentelemetry-semantic-conventions-ai = "0.4.9" + +[[package]] +name = "opentelemetry-instrumentation-mcp" +version = "0.40.14" +description = "OpenTelemetry mcp instrumentation" +optional = false +python-versions = "<4,>=3.10" +groups = ["main"] +files = [ + {file = "opentelemetry_instrumentation_mcp-0.40.14-py3-none-any.whl", hash = "sha256:8ac37b7e138c48ea85cb67c8e737fb3b18b618650a7c2239731e6a7190586e65"}, + {file = "opentelemetry_instrumentation_mcp-0.40.14.tar.gz", hash = "sha256:32ed438acc1e21d26e991ea5c5c9b03f381faf8d963878f2822e45e666a41a1c"}, +] + +[package.dependencies] +opentelemetry-api = ">=1.28.0,<2.0.0" +opentelemetry-instrumentation = ">=0.50b0" +opentelemetry-semantic-conventions = ">=0.50b0" +opentelemetry-semantic-conventions-ai = "0.4.9" + +[[package]] +name = "opentelemetry-instrumentation-milvus" +version = "0.40.14" +description = "OpenTelemetry Milvus instrumentation" +optional = false +python-versions = "<4,>=3.9" +groups = ["main"] +files = [ + {file = "opentelemetry_instrumentation_milvus-0.40.14-py3-none-any.whl", hash = "sha256:02c3c8e50558aed577d3527ca81904106a3ea86304b69fef9a2e8d7b2f9581a5"}, + {file = "opentelemetry_instrumentation_milvus-0.40.14.tar.gz", hash = "sha256:7c7e3fb830acfac2a0b102c408f4c40f2c5b86e22cf12bebe35cc7555c612e5b"}, +] + +[package.dependencies] +opentelemetry-api = ">=1.28.0,<2.0.0" +opentelemetry-instrumentation = ">=0.50b0" +opentelemetry-semantic-conventions = ">=0.50b0" +opentelemetry-semantic-conventions-ai = "0.4.9" + +[[package]] +name = "opentelemetry-instrumentation-mistralai" +version = "0.40.14" +description = "OpenTelemetry Mistral AI instrumentation" +optional = false +python-versions = "<4,>=3.9" +groups = ["main"] +files = [ + {file = "opentelemetry_instrumentation_mistralai-0.40.14-py3-none-any.whl", hash = "sha256:be0360b8184d287aaf94e970ada56812ff6c313c23f78984f886948279ad2df7"}, + {file = "opentelemetry_instrumentation_mistralai-0.40.14.tar.gz", hash = "sha256:17f77f82d3f3843a4c5d25c42899e729d572e1b1d5ae1947a0b8e8a9ef4f5665"}, +] + +[package.dependencies] +opentelemetry-api = ">=1.28.0,<2.0.0" +opentelemetry-instrumentation = ">=0.50b0" +opentelemetry-semantic-conventions = ">=0.50b0" +opentelemetry-semantic-conventions-ai = "0.4.9" + +[[package]] +name = "opentelemetry-instrumentation-ollama" +version = "0.40.14" +description = "OpenTelemetry Ollama instrumentation" +optional = false +python-versions = "<4,>=3.9" +groups = ["main"] +files = [ + {file = "opentelemetry_instrumentation_ollama-0.40.14-py3-none-any.whl", hash = "sha256:d38f31f8d06ef25acce34c490c8d113476781e2b2b2b50964c97c79d4fef3ad7"}, + {file = "opentelemetry_instrumentation_ollama-0.40.14.tar.gz", hash = "sha256:6589aef14575e87f68e129e0f989742a8d751f029e56bccf158791202380e2cb"}, +] + +[package.dependencies] +opentelemetry-api = ">=1.28.0,<2.0.0" +opentelemetry-instrumentation = ">=0.50b0" +opentelemetry-semantic-conventions = ">=0.50b0" +opentelemetry-semantic-conventions-ai = "0.4.9" + +[[package]] +name = "opentelemetry-instrumentation-openai" +version = "0.40.14" +description = "OpenTelemetry OpenAI instrumentation" +optional = false +python-versions = "<4,>=3.9" +groups = ["main"] +files = [ + {file = "opentelemetry_instrumentation_openai-0.40.14-py3-none-any.whl", hash = "sha256:72319113370a018390e9c987dc3dac569380591fbaa5639c5e5cacd3f3165f4a"}, + {file = "opentelemetry_instrumentation_openai-0.40.14.tar.gz", hash = "sha256:3ba8e36a3853833f5c0c6b3b8ffa0f1289e6423e0d428bd1c7b3f27abdc545f0"}, +] + +[package.dependencies] +opentelemetry-api = ">=1.28.0,<2.0.0" +opentelemetry-instrumentation = ">=0.50b0" +opentelemetry-semantic-conventions = ">=0.50b0" +opentelemetry-semantic-conventions-ai = "0.4.9" +tiktoken = ">=0.6.0,<1" + +[[package]] +name = "opentelemetry-instrumentation-pinecone" +version = "0.40.14" +description = "OpenTelemetry Pinecone instrumentation" +optional = false +python-versions = "<4,>=3.9" +groups = ["main"] +files = [ + {file = "opentelemetry_instrumentation_pinecone-0.40.14-py3-none-any.whl", hash = "sha256:a3cd747468ddb4a6f4caf249f3d7a21b61dc8c3fb9c44cb586943a7eec56ab3a"}, + {file = "opentelemetry_instrumentation_pinecone-0.40.14.tar.gz", hash = "sha256:314be6cdc847dacde4a96d352c3739d809ed8753992e6e25f1e7d9586eb781d3"}, +] + +[package.dependencies] +opentelemetry-api = ">=1.28.0,<2.0.0" +opentelemetry-instrumentation = ">=0.50b0" +opentelemetry-semantic-conventions = ">=0.50b0" +opentelemetry-semantic-conventions-ai = "0.4.9" + +[[package]] +name = "opentelemetry-instrumentation-qdrant" +version = "0.40.14" +description = "OpenTelemetry Qdrant instrumentation" +optional = false +python-versions = "<4,>=3.9" +groups = ["main"] +files = [ + {file = "opentelemetry_instrumentation_qdrant-0.40.14-py3-none-any.whl", hash = "sha256:12666e657529977c4b08f78c869eba4868ff214c77cf6f40947b36934254a0c2"}, + {file = "opentelemetry_instrumentation_qdrant-0.40.14.tar.gz", hash = "sha256:eef5b9a8a4a8069eca1d06652c2d5ba0fa9a012c5b2f48c7577507b5219528d0"}, +] + +[package.dependencies] +opentelemetry-api = ">=1.28.0,<2.0.0" +opentelemetry-instrumentation = ">=0.50b0" +opentelemetry-semantic-conventions = ">=0.50b0" +opentelemetry-semantic-conventions-ai = "0.4.9" + +[[package]] +name = "opentelemetry-instrumentation-replicate" +version = "0.40.14" +description = "OpenTelemetry Replicate instrumentation" +optional = false +python-versions = "<4,>=3.9" +groups = ["main"] +files = [ + {file = "opentelemetry_instrumentation_replicate-0.40.14-py3-none-any.whl", hash = "sha256:7f204bb5b36ee69c2068c3cdaac6ec9b49b449c07b2d39cb47157b672e59751d"}, + {file = "opentelemetry_instrumentation_replicate-0.40.14.tar.gz", hash = "sha256:d010113254a1cdc142bc74e7feaff555344692eb808b46eebb25c56a26db5281"}, +] + +[package.dependencies] +opentelemetry-api = ">=1.28.0,<2.0.0" +opentelemetry-instrumentation = ">=0.50b0" +opentelemetry-semantic-conventions = ">=0.50b0" +opentelemetry-semantic-conventions-ai = "0.4.9" + +[[package]] +name = "opentelemetry-instrumentation-sagemaker" +version = "0.40.14" +description = "OpenTelemetry SageMaker instrumentation" +optional = false +python-versions = "<4,>=3.9" +groups = ["main"] +files = [ + {file = "opentelemetry_instrumentation_sagemaker-0.40.14-py3-none-any.whl", hash = "sha256:28d7cc2c43b77bb69f20d8902c0bede9b828f9bfb7aa8ebe75fd542dcb8a6545"}, + {file = "opentelemetry_instrumentation_sagemaker-0.40.14.tar.gz", hash = "sha256:d1d31423a4d57239428d2b925e4801d61782b52adb9b80baf4e86c6f03b1ad06"}, +] + +[package.dependencies] +opentelemetry-api = ">=1.26.0,<2.0.0" +opentelemetry-instrumentation = ">=0.50b0" +opentelemetry-semantic-conventions = ">=0.50b0" +opentelemetry-semantic-conventions-ai = "0.4.9" + +[[package]] +name = "opentelemetry-instrumentation-threading" +version = "0.55b1" +description = "Thread context propagation support for OpenTelemetry" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "opentelemetry_instrumentation_threading-0.55b1-py3-none-any.whl", hash = "sha256:f865542b32b219c8fd01deb03b8c3c9ba2eb3f0501ae303338403fd2242962c7"}, + {file = "opentelemetry_instrumentation_threading-0.55b1.tar.gz", hash = "sha256:4ed68502e7ed017bfc10b1f9e508cc5ccaea0e46ac1010f7f2541ab9c6eacd92"}, +] + +[package.dependencies] +opentelemetry-api = ">=1.12,<2.0" +opentelemetry-instrumentation = "0.55b1" +wrapt = ">=1.0.0,<2.0.0" + +[[package]] +name = "opentelemetry-instrumentation-together" +version = "0.40.14" +description = "OpenTelemetry Together AI instrumentation" +optional = false +python-versions = "<4,>=3.9" +groups = ["main"] +files = [ + {file = "opentelemetry_instrumentation_together-0.40.14-py3-none-any.whl", hash = "sha256:7e5fe1793ab624fc8c104a46f707beabaaaec92666b0551c0ac80355ba324c17"}, + {file = "opentelemetry_instrumentation_together-0.40.14.tar.gz", hash = "sha256:bdee203caa0e3a4dff5f20e0a7802860ea51d021a714e89de919091226fadb99"}, +] + +[package.dependencies] +opentelemetry-api = ">=1.28.0,<2.0.0" +opentelemetry-instrumentation = ">=0.50b0" +opentelemetry-semantic-conventions = ">=0.50b0" +opentelemetry-semantic-conventions-ai = "0.4.9" + +[[package]] +name = "opentelemetry-instrumentation-transformers" +version = "0.40.14" +description = "OpenTelemetry transformers instrumentation" +optional = false +python-versions = "<4,>=3.9" +groups = ["main"] +files = [ + {file = "opentelemetry_instrumentation_transformers-0.40.14-py3-none-any.whl", hash = "sha256:b7de54a27b4de8724981bb69c2cb4ec740e084dbea2ec834349b71b6d503c85d"}, + {file = "opentelemetry_instrumentation_transformers-0.40.14.tar.gz", hash = "sha256:7dc3e11055a16c29e5bb9b0892deb9edb4927e4390d83c6678ca360af818fbff"}, +] + +[package.dependencies] +opentelemetry-api = ">=1.28.0,<2.0.0" +opentelemetry-instrumentation = ">=0.50b0" +opentelemetry-semantic-conventions = ">=0.50b0" +opentelemetry-semantic-conventions-ai = "0.4.9" + +[[package]] +name = "opentelemetry-instrumentation-vertexai" +version = "0.40.14" +description = "OpenTelemetry Vertex AI instrumentation" +optional = false +python-versions = "<4,>=3.9" +groups = ["main"] +files = [ + {file = "opentelemetry_instrumentation_vertexai-0.40.14-py3-none-any.whl", hash = "sha256:5146387a0060fbdec87a8cbbf5bee2aae7afb791cfd673fded2fa7394021cfb6"}, + {file = "opentelemetry_instrumentation_vertexai-0.40.14.tar.gz", hash = "sha256:f6f8ecd47576575ff62d645d1b343cfbdc4143d7b3c4b1424605ab6278d5122b"}, +] + +[package.dependencies] +opentelemetry-api = ">=1.28.0,<2.0.0" +opentelemetry-instrumentation = ">=0.50b0" +opentelemetry-semantic-conventions = ">=0.50b0" +opentelemetry-semantic-conventions-ai = "0.4.9" + +[[package]] +name = "opentelemetry-instrumentation-watsonx" +version = "0.40.14" +description = "OpenTelemetry IBM Watsonx Instrumentation" +optional = false +python-versions = "<4,>=3.9" +groups = ["main"] +files = [ + {file = "opentelemetry_instrumentation_watsonx-0.40.14-py3-none-any.whl", hash = "sha256:119f0fc0e5a4dddac31a0ea9cfd7ea41398814923b3018836780fc4e46f930d1"}, + {file = "opentelemetry_instrumentation_watsonx-0.40.14.tar.gz", hash = "sha256:e131f498b764fc76c1f433377b9ef554b12de604f2f6b8dd72e0440226034da7"}, +] + +[package.dependencies] +opentelemetry-api = ">=1.28.0,<2.0.0" +opentelemetry-instrumentation = ">=0.50b0" +opentelemetry-semantic-conventions = ">=0.50b0" +opentelemetry-semantic-conventions-ai = "0.4.9" + +[[package]] +name = "opentelemetry-instrumentation-weaviate" +version = "0.40.14" +description = "OpenTelemetry Weaviate instrumentation" +optional = false +python-versions = "<4,>=3.9" +groups = ["main"] +files = [ + {file = "opentelemetry_instrumentation_weaviate-0.40.14-py3-none-any.whl", hash = "sha256:4ab8f786eb78394be37aed0df96ceefa46072d48f0aee7e9f8ad3526e04e23fd"}, + {file = "opentelemetry_instrumentation_weaviate-0.40.14.tar.gz", hash = "sha256:539c62d542bcb2bf5e39a2939403397b1e898c852d5e343a3f348a9c33bfa7f5"}, +] + +[package.dependencies] +opentelemetry-api = ">=1.28.0,<2.0.0" +opentelemetry-instrumentation = ">=0.50b0" +opentelemetry-semantic-conventions = ">=0.50b0" +opentelemetry-semantic-conventions-ai = "0.4.9" + +[[package]] +name = "opentelemetry-proto" +version = "1.34.1" +description = "OpenTelemetry Python Proto" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "opentelemetry_proto-1.34.1-py3-none-any.whl", hash = "sha256:eb4bb5ac27f2562df2d6857fc557b3a481b5e298bc04f94cc68041f00cebcbd2"}, + {file = "opentelemetry_proto-1.34.1.tar.gz", hash = "sha256:16286214e405c211fc774187f3e4bbb1351290b8dfb88e8948af209ce85b719e"}, +] + +[package.dependencies] +protobuf = ">=5.0,<6.0" + +[[package]] +name = "opentelemetry-sdk" +version = "1.34.1" +description = "OpenTelemetry Python SDK" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "opentelemetry_sdk-1.34.1-py3-none-any.whl", hash = "sha256:308effad4059562f1d92163c61c8141df649da24ce361827812c40abb2a1e96e"}, + {file = "opentelemetry_sdk-1.34.1.tar.gz", hash = "sha256:8091db0d763fcd6098d4781bbc80ff0971f94e260739aa6afe6fd379cdf3aa4d"}, +] + +[package.dependencies] +opentelemetry-api = "1.34.1" +opentelemetry-semantic-conventions = "0.55b1" +typing-extensions = ">=4.5.0" + +[[package]] +name = "opentelemetry-semantic-conventions" +version = "0.55b1" +description = "OpenTelemetry Semantic Conventions" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "opentelemetry_semantic_conventions-0.55b1-py3-none-any.whl", hash = "sha256:5da81dfdf7d52e3d37f8fe88d5e771e191de924cfff5f550ab0b8f7b2409baed"}, + {file = "opentelemetry_semantic_conventions-0.55b1.tar.gz", hash = "sha256:ef95b1f009159c28d7a7849f5cbc71c4c34c845bb514d66adfdf1b3fff3598b3"}, +] + +[package.dependencies] +opentelemetry-api = "1.34.1" +typing-extensions = ">=4.5.0" + +[[package]] +name = "opentelemetry-semantic-conventions-ai" +version = "0.4.9" +description = "OpenTelemetry Semantic Conventions Extension for Large Language Models" +optional = false +python-versions = "<4,>=3.9" +groups = ["main"] +files = [ + {file = "opentelemetry_semantic_conventions_ai-0.4.9-py3-none-any.whl", hash = "sha256:71149e46a72554ae17de46bca6c11ba540c19c89904bd4cc3111aac6edf10315"}, + {file = "opentelemetry_semantic_conventions_ai-0.4.9.tar.gz", hash = "sha256:54a0b901959e2de5124384925846bac2ea0a6dab3de7e501ba6aecf5e293fe04"}, +] [[package]] name = "orjson" @@ -5149,7 +5885,7 @@ description = "A high-level API to automate web browsers" optional = false python-versions = ">=3.9" groups = ["main"] -markers = "python_version >= \"3.12\"" +markers = "python_version == \"3.12\" or python_version == \"3.13\"" files = [ {file = "playwright-1.52.0-py3-none-macosx_10_13_x86_64.whl", hash = "sha256:19b2cb9d4794062008a635a99bd135b03ebb782d460f96534a91cb583f549512"}, {file = "playwright-1.52.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:0797c0479cbdc99607412a3c486a3a2ec9ddc77ac461259fd2878c975bcbb94a"}, @@ -5396,21 +6132,23 @@ testing = ["google-api-core (>=1.31.5)"] [[package]] name = "protobuf" -version = "6.31.1" +version = "5.29.5" description = "" optional = false -python-versions = ">=3.9" +python-versions = ">=3.8" groups = ["main"] files = [ - {file = "protobuf-6.31.1-cp310-abi3-win32.whl", hash = "sha256:7fa17d5a29c2e04b7d90e5e32388b8bfd0e7107cd8e616feef7ed3fa6bdab5c9"}, - {file = "protobuf-6.31.1-cp310-abi3-win_amd64.whl", hash = "sha256:426f59d2964864a1a366254fa703b8632dcec0790d8862d30034d8245e1cd447"}, - {file = "protobuf-6.31.1-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:6f1227473dc43d44ed644425268eb7c2e488ae245d51c6866d19fe158e207402"}, - {file = "protobuf-6.31.1-cp39-abi3-manylinux2014_aarch64.whl", hash = "sha256:a40fc12b84c154884d7d4c4ebd675d5b3b5283e155f324049ae396b95ddebc39"}, - {file = "protobuf-6.31.1-cp39-abi3-manylinux2014_x86_64.whl", hash = "sha256:4ee898bf66f7a8b0bd21bce523814e6fbd8c6add948045ce958b73af7e8878c6"}, - {file = "protobuf-6.31.1-cp39-cp39-win32.whl", hash = "sha256:0414e3aa5a5f3ff423828e1e6a6e907d6c65c1d5b7e6e975793d5590bdeecc16"}, - {file = "protobuf-6.31.1-cp39-cp39-win_amd64.whl", hash = "sha256:8764cf4587791e7564051b35524b72844f845ad0bb011704c3736cce762d8fe9"}, - {file = "protobuf-6.31.1-py3-none-any.whl", hash = "sha256:720a6c7e6b77288b85063569baae8536671b39f15cc22037ec7045658d80489e"}, - {file = "protobuf-6.31.1.tar.gz", hash = "sha256:d8cac4c982f0b957a4dc73a80e2ea24fab08e679c0de9deb835f4a12d69aca9a"}, + {file = "protobuf-5.29.5-cp310-abi3-win32.whl", hash = "sha256:3f1c6468a2cfd102ff4703976138844f78ebd1fb45f49011afc5139e9e283079"}, + {file = "protobuf-5.29.5-cp310-abi3-win_amd64.whl", hash = "sha256:3f76e3a3675b4a4d867b52e4a5f5b78a2ef9565549d4037e06cf7b0942b1d3fc"}, + {file = "protobuf-5.29.5-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:e38c5add5a311f2a6eb0340716ef9b039c1dfa428b28f25a7838ac329204a671"}, + {file = "protobuf-5.29.5-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:fa18533a299d7ab6c55a238bf8629311439995f2e7eca5caaff08663606e9015"}, + {file = "protobuf-5.29.5-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:63848923da3325e1bf7e9003d680ce6e14b07e55d0473253a690c3a8b8fd6e61"}, + {file = "protobuf-5.29.5-cp38-cp38-win32.whl", hash = "sha256:ef91363ad4faba7b25d844ef1ada59ff1604184c0bcd8b39b8a6bef15e1af238"}, + {file = "protobuf-5.29.5-cp38-cp38-win_amd64.whl", hash = "sha256:7318608d56b6402d2ea7704ff1e1e4597bee46d760e7e4dd42a3d45e24b87f2e"}, + {file = "protobuf-5.29.5-cp39-cp39-win32.whl", hash = "sha256:6f642dc9a61782fa72b90878af134c5afe1917c89a568cd3476d758d3c3a0736"}, + {file = "protobuf-5.29.5-cp39-cp39-win_amd64.whl", hash = "sha256:470f3af547ef17847a28e1f47200a1cbf0ba3ff57b7de50d22776607cd2ea353"}, + {file = "protobuf-5.29.5-py3-none-any.whl", hash = "sha256:6cf42630262c59b2d8de33954443d94b746c952b01434fc58a417fdbd2e84bd5"}, + {file = "protobuf-5.29.5.tar.gz", hash = "sha256:bc1463bafd4b0929216c35f437a8e28731a2b7fe3d98bb77a600efced5a15c84"}, ] [[package]] @@ -5444,7 +6182,7 @@ description = "PostgreSQL database adapter for Python" optional = false python-versions = ">=3.7" groups = ["main"] -markers = "python_version < \"3.13\"" +markers = "python_version == \"3.12\" or python_version == \"3.11\"" files = [ {file = "psycopg-3.1.18-py3-none-any.whl", hash = "sha256:4d5a0a5a8590906daa58ebd5f3cfc34091377354a1acced269dd10faf55da60e"}, {file = "psycopg-3.1.18.tar.gz", hash = "sha256:31144d3fb4c17d78094d9e579826f047d4af1da6a10427d91dfcfb6ecdf6f12b"}, @@ -5497,7 +6235,7 @@ description = "PostgreSQL database adapter for Python -- C optimisation distribu optional = false python-versions = ">=3.7" groups = ["main"] -markers = "python_version < \"3.13\" and implementation_name != \"pypy\"" +markers = "(python_version == \"3.12\" or python_version == \"3.11\") and implementation_name != \"pypy\"" files = [ {file = "psycopg_binary-3.1.18-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5c323103dfa663b88204cf5f028e83c77d7a715f9b6f51d2bbc8184b99ddd90a"}, {file = "psycopg_binary-3.1.18-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:887f8d856c91510148be942c7acd702ccf761a05f59f8abc123c22ab77b5a16c"}, @@ -5947,7 +6685,7 @@ description = "A rough port of Node.js's EventEmitter to Python with a few trick optional = false python-versions = ">=3.8" groups = ["main"] -markers = "python_version >= \"3.12\"" +markers = "python_version == \"3.12\" or python_version == \"3.13\"" files = [ {file = "pyee-13.0.0-py3-none-any.whl", hash = "sha256:48195a3cddb3b1515ce0695ed76036b5ccc2ef3a9f963ff9f77aec0139845498"}, {file = "pyee-13.0.0.tar.gz", hash = "sha256:b391e3c5a434d1f5118a25615001dbc8f669cf410ab67d04c4d4e07c55481c37"}, @@ -6231,7 +6969,7 @@ description = "A (partial) reimplementation of pywin32 using ctypes/cffi" optional = false python-versions = ">=3.6" groups = ["dev"] -markers = "sys_platform == \"win32\" and platform_machine != \"ppc64le\" and platform_machine != \"s390x\"" +markers = "platform_machine != \"ppc64le\" and platform_machine != \"s390x\" and sys_platform == \"win32\"" files = [ {file = "pywin32-ctypes-0.2.3.tar.gz", hash = "sha256:d162dc04946d704503b2edc4d55f3dba5c1d539ead017afa00142c38b9885755"}, {file = "pywin32_ctypes-0.2.3-py3-none-any.whl", hash = "sha256:8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8"}, @@ -6938,7 +7676,7 @@ description = "Python bindings to FreeDesktop.org Secret Service API" optional = false python-versions = ">=3.6" groups = ["dev"] -markers = "sys_platform == \"linux\" and platform_machine != \"ppc64le\" and platform_machine != \"s390x\"" +markers = "platform_machine != \"ppc64le\" and platform_machine != \"s390x\" and sys_platform == \"linux\"" files = [ {file = "SecretStorage-3.3.3-py3-none-any.whl", hash = "sha256:f356e6628222568e3af06f2eba8df495efa13b3b63081dafd4f7d9a7b7bc9f99"}, {file = "SecretStorage-3.3.3.tar.gz", hash = "sha256:2403533ef369eca6d2ba81718576c5e0f564d5cca1b58f73a8b23e7d4eeebd77"}, @@ -7374,6 +8112,22 @@ grpc = ["grpcio (>=1.48.2,<2)"] opentelemetry = ["opentelemetry-api (>=1.11.1,<2)", "opentelemetry-sdk (>=1.11.1,<2)"] pydantic = ["pydantic (>=2.0.0,<3)"] +[[package]] +name = "tenacity" +version = "9.1.2" +description = "Retry code until it succeeds" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "tenacity-9.1.2-py3-none-any.whl", hash = "sha256:f77bf36710d8b73a50b2dd155c97b870017ad21afe6ab300326b0371b3b05138"}, + {file = "tenacity-9.1.2.tar.gz", hash = "sha256:1169d376c297e7de388d18b4481760d478b0e99a777cad3a9c86e556f4b697cb"}, +] + +[package.extras] +doc = ["reno", "sphinx"] +test = ["pytest", "tornado (>=4.5)", "typeguard"] + [[package]] name = "terminado" version = "0.18.1" @@ -8258,7 +9012,7 @@ description = "Fast implementation of asyncio event loop on top of libuv" optional = false python-versions = ">=3.8.0" groups = ["main"] -markers = "platform_python_implementation != \"PyPy\" and sys_platform != \"win32\" and sys_platform != \"cygwin\"" +markers = "sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"PyPy\"" files = [ {file = "uvloop-0.21.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ec7e6b09a6fdded42403182ab6b832b71f4edaf7f37a9a0e371a01db5f0cb45f"}, {file = "uvloop-0.21.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:196274f2adb9689a289ad7d65700d37df0c0930fd8e4e743fa4834e850d7719d"}, @@ -8858,4 +9612,4 @@ type = ["pytest-mypy"] [metadata] lock-version = "2.1" python-versions = ">=3.11,<3.14" -content-hash = "cf74ed450038ba2efd72f86b361f135b6cab2e2a4f275061d69d7cbb0ed7dfb5" +content-hash = "3bd6f84bd33a4a4f94a2fb7047fa1b089162a4743a1448355807003b83fb575f" diff --git a/pyproject.toml b/pyproject.toml index 087af552..bebb0be5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -77,6 +77,7 @@ types-boto3 = {extras = ["full"], version = "^1.38.31"} lark = "^1.2.2" libcst = "^1.8.2" curlparser = "^0.1.0" +lmnr = {extras = ["all"], version = "^0.6.16"} [tool.poetry.group.dev.dependencies] isort = "^5.13.2" diff --git a/skyvern/config.py b/skyvern/config.py index e3fbaa99..4db56f2e 100644 --- a/skyvern/config.py +++ b/skyvern/config.py @@ -284,6 +284,12 @@ class Settings(BaseSettings): The secret used to sign the email/identity of the user. """ + # Trace settings + TRACE_ENABLED: bool = False + TRACE_PROVIDER: str = "lmnr" + TRACE_PROVIDER_HOST: str | None = None + TRACE_PROVIDER_API_KEY: str = "fillmein" + def get_model_name_to_llm_key(self) -> dict[str, dict[str, str]]: """ Keys are model names available to blocks in the frontend. These map to key names diff --git a/skyvern/forge/agent.py b/skyvern/forge/agent.py index 103d5ed7..125ecede 100644 --- a/skyvern/forge/agent.py +++ b/skyvern/forge/agent.py @@ -71,6 +71,7 @@ from skyvern.forge.sdk.models import Step, StepStatus from skyvern.forge.sdk.schemas.files import FileInfo from skyvern.forge.sdk.schemas.organizations import Organization from skyvern.forge.sdk.schemas.tasks import Task, TaskRequest, TaskResponse, TaskStatus +from skyvern.forge.sdk.trace import TraceManager from skyvern.forge.sdk.workflow.context_manager import WorkflowRunContext from skyvern.forge.sdk.workflow.models.block import ActionBlock, BaseTaskBlock, ValidationBlock from skyvern.forge.sdk.workflow.models.workflow import Workflow, WorkflowRun, WorkflowRunStatus @@ -268,6 +269,9 @@ class ForgeAgent: operations = await app.AGENT_FUNCTION.generate_async_operations(organization, task, page) self.async_operation_pool.add_operations(task.task_id, operations) + @TraceManager.traced_async( + ignore_inputs=["api_key", "close_browser_on_completion", "task_block", "cua_response", "llm_caller"] + ) async def execute_step( self, organization: Organization, @@ -428,8 +432,9 @@ class ForgeAgent: if not llm_caller: # create a new UI-TARS llm_caller llm_key = task.llm_key or settings.VOLCENGINE_CUA_LLM_KEY - llm_caller = UITarsLLMCaller(llm_key=llm_key, screenshot_scaling_enabled=True) - llm_caller.initialize_conversation(task) + ui_tars_llm_caller = UITarsLLMCaller(llm_key=llm_key, screenshot_scaling_enabled=True) + ui_tars_llm_caller.initialize_conversation(task) + llm_caller = ui_tars_llm_caller # TODO: remove the code after migrating everything to llm callers # currently, only anthropic cua and ui_tars tasks use llm_caller @@ -829,6 +834,9 @@ class ForgeAgent: ) return True + @TraceManager.traced_async( + ignore_inputs=["browser_state", "organization", "task_block", "cua_response", "llm_caller"] + ) async def agent_step( self, task: Task, diff --git a/skyvern/forge/agent_functions.py b/skyvern/forge/agent_functions.py index bc71c924..25aba383 100644 --- a/skyvern/forge/agent_functions.py +++ b/skyvern/forge/agent_functions.py @@ -18,6 +18,7 @@ from skyvern.forge.sdk.core import skyvern_context from skyvern.forge.sdk.models import Step, StepStatus from skyvern.forge.sdk.schemas.organizations import Organization from skyvern.forge.sdk.schemas.tasks import Task, TaskStatus +from skyvern.forge.sdk.trace import TraceManager from skyvern.forge.sdk.workflow.models.block import BlockTypeVar from skyvern.webeye.browser_factory import BrowserState from skyvern.webeye.scraper.scraper import ELEMENT_NODE_ATTRIBUTES, CleanupElementTreeFunc, json_to_html @@ -538,6 +539,7 @@ class AgentFunction: ) -> CleanupElementTreeFunc: MAX_ELEMENT_CNT = 3000 + @TraceManager.traced_async(ignore_input=True) async def cleanup_element_tree_func(frame: Page | Frame, url: str, element_tree: list[dict]) -> list[dict]: """ Remove rect and attribute.unique_id from the elements. diff --git a/skyvern/forge/app.py b/skyvern/forge/app.py index 108d3f7f..1767ec16 100644 --- a/skyvern/forge/app.py +++ b/skyvern/forge/app.py @@ -15,6 +15,8 @@ from skyvern.forge.sdk.db.client import AgentDB from skyvern.forge.sdk.experimentation.providers import BaseExperimentationProvider, NoOpExperimentationProvider from skyvern.forge.sdk.schemas.organizations import Organization from skyvern.forge.sdk.settings_manager import SettingsManager +from skyvern.forge.sdk.trace import TraceManager +from skyvern.forge.sdk.trace.lmnr import LaminarTrace from skyvern.forge.sdk.workflow.context_manager import WorkflowContextManager from skyvern.forge.sdk.workflow.service import WorkflowService from skyvern.webeye.browser_manager import BrowserManager @@ -76,3 +78,7 @@ authentication_function: Callable[[str], Awaitable[Organization]] | None = None setup_api_app: Callable[[FastAPI], None] | None = None agent = ForgeAgent() + +if SettingsManager.get_settings().TRACE_ENABLED: + if SettingsManager.get_settings().TRACE_PROVIDER == "lmnr": + TraceManager.set_trace_provider(LaminarTrace(api_key=SettingsManager.get_settings().TRACE_PROVIDER_API_KEY)) diff --git a/skyvern/forge/sdk/api/llm/api_handler_factory.py b/skyvern/forge/sdk/api/llm/api_handler_factory.py index b19971b9..e4131d3a 100644 --- a/skyvern/forge/sdk/api/llm/api_handler_factory.py +++ b/skyvern/forge/sdk/api/llm/api_handler_factory.py @@ -31,6 +31,7 @@ from skyvern.forge.sdk.core import skyvern_context from skyvern.forge.sdk.models import Step from skyvern.forge.sdk.schemas.ai_suggestions import AISuggestion from skyvern.forge.sdk.schemas.task_v2 import TaskV2, Thought +from skyvern.forge.sdk.trace import TraceManager from skyvern.utils.image_resizer import Resolution, get_resize_target_dimension, resize_screenshots LOG = structlog.get_logger() @@ -89,6 +90,7 @@ class LLMAPIHandlerFactory: ) main_model_group = llm_config.main_model_group + @TraceManager.traced_async(tags=[llm_key], ignore_inputs=["prompt", "screenshots", "parameters"]) async def llm_api_handler_with_router_and_fallback( prompt: str, prompt_name: str, @@ -286,6 +288,7 @@ class LLMAPIHandlerFactory: assert isinstance(llm_config, LLMConfig) + @TraceManager.traced_async(tags=[llm_key], ignore_inputs=["prompt", "screenshots", "parameters"]) async def llm_api_handler( prompt: str, prompt_name: str, @@ -743,6 +746,7 @@ class LLMCaller: return get_resize_target_dimension(window_dimension) return self.screenshot_resize_target_dimension + @TraceManager.traced_async(ignore_input=True) async def _dispatch_llm_call( self, messages: list[dict[str, Any]], diff --git a/skyvern/forge/sdk/trace/__init__.py b/skyvern/forge/sdk/trace/__init__.py new file mode 100644 index 00000000..a618ba33 --- /dev/null +++ b/skyvern/forge/sdk/trace/__init__.py @@ -0,0 +1,92 @@ +from functools import wraps +from typing import Any, Awaitable, Callable, ParamSpec, TypeVar + +from skyvern.forge.sdk.core import skyvern_context +from skyvern.forge.sdk.settings_manager import SettingsManager +from skyvern.forge.sdk.trace.base import BaseTrace, NoOpTrace + +P = ParamSpec("P") +R = TypeVar("R") + + +class TraceManager: + __instance: BaseTrace = NoOpTrace() + + @staticmethod + def traced_async( + *, + name: str | None = None, + metadata: dict[str, Any] | None = None, + tags: list[str] | None = None, + **trace_parameters: Any, + ) -> Callable[[Callable[P, Awaitable[R]]], Callable[P, Awaitable[R]]]: + def decorator(func: Callable[P, Awaitable[R]]) -> Callable[P, Awaitable[R]]: + @wraps(func) + async def wrapper(*args: P.args, **kwargs: P.kwargs) -> R: + new_metadata: dict[str, Any] = metadata or {} + user_id: str | None = None + context = skyvern_context.current() + if context is not None: + new_metadata["request_id"] = context.request_id + new_metadata["organization_id"] = context.organization_id + new_metadata["task_id"] = context.task_id + new_metadata["workflow_id"] = context.workflow_id + new_metadata["workflow_run_id"] = context.workflow_run_id + new_metadata["task_v2_id"] = context.task_v2_id + new_metadata["run_id"] = context.run_id + new_metadata["organization_name"] = context.organization_name + user_id = context.run_id + + new_tags: list[str] = tags or [] + new_tags.append(SettingsManager.get_settings().ENV) + + return await TraceManager.__instance.traced_async( + name=name, metadata=new_metadata, tags=new_tags, user_id=user_id, **trace_parameters + )(func)(*args, **kwargs) + + return wrapper + + return decorator + + @staticmethod + def traced( + *, + name: str | None = None, + metadata: dict[str, Any] | None = None, + tags: list[str] | None = None, + **trace_parameters: Any, + ) -> Callable[[Callable[P, R]], Callable[P, R]]: + def decorator(func: Callable[P, R]) -> Callable[P, R]: + def wrapper(*args: P.args, **kwargs: P.kwargs) -> R: + new_metadata: dict[str, Any] = metadata or {} + user_id: str | None = None + context = skyvern_context.current() + if context is not None: + new_metadata["request_id"] = context.request_id + new_metadata["organization_id"] = context.organization_id + new_metadata["task_id"] = context.task_id + new_metadata["workflow_id"] = context.workflow_id + new_metadata["workflow_run_id"] = context.workflow_run_id + new_metadata["task_v2_id"] = context.task_v2_id + new_metadata["run_id"] = context.run_id + new_metadata["organization_name"] = context.organization_name + user_id = context.run_id + + new_tags: list[str] = tags or [] + new_tags.append(SettingsManager.get_settings().ENV) + + return TraceManager.__instance.traced( + name=name, metadata=new_metadata, tags=new_tags, user_id=user_id, **trace_parameters + )(func)(*args, **kwargs) + + return wrapper + + return decorator + + @staticmethod + def get_trace_provider() -> BaseTrace: + return TraceManager.__instance + + @staticmethod + def set_trace_provider(trace_provider: BaseTrace) -> None: + TraceManager.__instance = trace_provider diff --git a/skyvern/forge/sdk/trace/base.py b/skyvern/forge/sdk/trace/base.py new file mode 100644 index 00000000..e7108530 --- /dev/null +++ b/skyvern/forge/sdk/trace/base.py @@ -0,0 +1,47 @@ +from abc import ABC, abstractmethod +from typing import Any, Awaitable, Callable, ParamSpec, TypeVar + +P = ParamSpec("P") +R = TypeVar("R") + + +class BaseTrace(ABC): + @abstractmethod + def traced( + self, + name: str | None = None, + metadata: dict[str, Any] | None = None, + tags: list[str] | None = None, + **kwargs: Any, + ) -> Callable[[Callable[P, R]], Callable[P, R]]: + pass + + @abstractmethod + def traced_async( + self, + name: str | None = None, + metadata: dict[str, Any] | None = None, + tags: list[str] | None = None, + **kwargs: Any, + ) -> Callable[[Callable[P, Awaitable[R]]], Callable[P, Awaitable[R]]]: + pass + + +class NoOpTrace(BaseTrace): + def traced( + self, + name: str | None = None, + metadata: dict[str, Any] | None = None, + tags: list[str] | None = None, + **kwargs: Any, + ) -> Callable[[Callable[P, R]], Callable[P, R]]: + return lambda func: func + + def traced_async( + self, + name: str | None = None, + metadata: dict[str, Any] | None = None, + tags: list[str] | None = None, + **kwargs: Any, + ) -> Callable[[Callable[P, Awaitable[R]]], Callable[P, Awaitable[R]]]: + return lambda func: func diff --git a/skyvern/forge/sdk/trace/lmnr.py b/skyvern/forge/sdk/trace/lmnr.py new file mode 100644 index 00000000..17849c21 --- /dev/null +++ b/skyvern/forge/sdk/trace/lmnr.py @@ -0,0 +1,33 @@ +from typing import Any, Awaitable, Callable, ParamSpec, TypeVar + +import litellm +from lmnr import Instruments, Laminar, LaminarLiteLLMCallback, observe + +from skyvern.forge.sdk.trace.base import BaseTrace + +P = ParamSpec("P") +R = TypeVar("R") + + +class LaminarTrace(BaseTrace): + def __init__(self, api_key: str) -> None: + Laminar.initialize(project_api_key=api_key, disabled_instruments={Instruments.SKYVERN}) + litellm.callbacks.append(LaminarLiteLLMCallback()) + + def traced( + self, + name: str | None = None, + metadata: dict[str, Any] | None = None, + tags: list[str] | None = None, + **kwargs: Any, + ) -> Callable[[Callable[P, R]], Callable[P, R]]: + return observe(name=name, ignore_output=True, metadata=metadata, tags=tags, **kwargs) + + def traced_async( + self, + name: str | None = None, + metadata: dict[str, Any] | None = None, + tags: list[str] | None = None, + **kwargs: Any, + ) -> Callable[[Callable[P, Awaitable[R]]], Callable[P, Awaitable[R]]]: + return observe(name=name, ignore_output=True, metadata=metadata, tags=tags, **kwargs) diff --git a/skyvern/forge/sdk/workflow/models/block.py b/skyvern/forge/sdk/workflow/models/block.py index 76354d9a..f575686e 100644 --- a/skyvern/forge/sdk/workflow/models/block.py +++ b/skyvern/forge/sdk/workflow/models/block.py @@ -54,6 +54,7 @@ from skyvern.forge.sdk.db.enums import TaskType from skyvern.forge.sdk.schemas.files import FileInfo from skyvern.forge.sdk.schemas.task_v2 import TaskV2Status from skyvern.forge.sdk.schemas.tasks import Task, TaskOutput, TaskStatus +from skyvern.forge.sdk.trace import TraceManager from skyvern.forge.sdk.workflow.context_manager import BlockMetadata, WorkflowRunContext from skyvern.forge.sdk.workflow.exceptions import ( CustomizedCodeException, @@ -292,6 +293,7 @@ class Block(BaseModel, abc.ABC): organization_id=organization_id, ) + @TraceManager.traced_async(ignore_inputs=["kwargs"]) async def execute_safe( self, workflow_run_id: str, diff --git a/skyvern/forge/sdk/workflow/service.py b/skyvern/forge/sdk/workflow/service.py index 1ef5b50b..1cdbfa67 100644 --- a/skyvern/forge/sdk/workflow/service.py +++ b/skyvern/forge/sdk/workflow/service.py @@ -30,6 +30,7 @@ from skyvern.forge.sdk.schemas.files import FileInfo from skyvern.forge.sdk.schemas.organizations import Organization from skyvern.forge.sdk.schemas.tasks import Task from skyvern.forge.sdk.schemas.workflow_runs import WorkflowRunBlock, WorkflowRunTimeline, WorkflowRunTimelineType +from skyvern.forge.sdk.trace import TraceManager from skyvern.forge.sdk.workflow.exceptions import ( ContextParameterSourceNotDefined, InvalidWaitBlockTime, @@ -248,6 +249,7 @@ class WorkflowService: return workflow_run + @TraceManager.traced_async(ignore_inputs=["organization", "api_key"]) async def execute_workflow( self, workflow_run_id: str, diff --git a/skyvern/services/task_v2_service.py b/skyvern/services/task_v2_service.py index 7326ad5a..6e345316 100644 --- a/skyvern/services/task_v2_service.py +++ b/skyvern/services/task_v2_service.py @@ -30,6 +30,7 @@ from skyvern.forge.sdk.db.enums import OrganizationAuthTokenType from skyvern.forge.sdk.schemas.organizations import Organization from skyvern.forge.sdk.schemas.task_v2 import TaskV2, TaskV2Metadata, TaskV2Status, ThoughtScenario, ThoughtType from skyvern.forge.sdk.schemas.workflow_runs import WorkflowRunTimeline, WorkflowRunTimelineType +from skyvern.forge.sdk.trace import TraceManager from skyvern.forge.sdk.workflow.models.block import ( BlockResult, BlockStatus, @@ -298,6 +299,7 @@ async def initialize_task_v2( return task_v2 +@TraceManager.traced_async(ignore_inputs=["organization"]) async def run_task_v2( organization: Organization, task_v2_id: str, diff --git a/skyvern/webeye/actions/handler.py b/skyvern/webeye/actions/handler.py index 9e51f46d..81b1982f 100644 --- a/skyvern/webeye/actions/handler.py +++ b/skyvern/webeye/actions/handler.py @@ -71,6 +71,7 @@ from skyvern.forge.sdk.models import Step from skyvern.forge.sdk.schemas.tasks import Task from skyvern.forge.sdk.services.bitwarden import BitwardenConstants from skyvern.forge.sdk.services.credentials import OnePasswordConstants +from skyvern.forge.sdk.trace import TraceManager from skyvern.services.task_v1_service import is_cua_task from skyvern.utils.prompt_engine import CheckPhoneNumberFormatResponse, load_prompt_with_elements from skyvern.webeye.actions import actions, handler_utils @@ -340,6 +341,7 @@ class ActionHandler: cls._teardown_action_types[action_type] = handler @staticmethod + @TraceManager.traced_async(ignore_inputs=["scraped_page", "page"]) async def handle_action( scraped_page: ScrapedPage, task: Task, @@ -459,6 +461,7 @@ def check_for_invalid_web_action( return [] +@TraceManager.traced_async(ignore_inputs=["scraped_page", "page"]) async def handle_solve_captcha_action( action: actions.SolveCaptchaAction, page: Page, @@ -474,6 +477,7 @@ async def handle_solve_captcha_action( return [ActionSuccess()] +@TraceManager.traced_async(ignore_inputs=["scraped_page", "page"]) async def handle_click_action( action: actions.ClickAction, page: Page, @@ -650,6 +654,7 @@ async def handle_click_action( return results +@TraceManager.traced_async(ignore_inputs=["anchor_element", "scraped_page", "page", "incremental_scraped", "dom"]) async def handle_sequential_click_for_dropdown( action: actions.ClickAction, anchor_element: SkyvernElement, @@ -722,6 +727,7 @@ async def handle_sequential_click_for_dropdown( ) +@TraceManager.traced_async(ignore_inputs=["scraped_page", "page"]) async def handle_click_to_download_file_action( action: actions.ClickAction, page: Page, @@ -814,6 +820,7 @@ async def handle_click_to_download_file_action( return [ActionSuccess(download_triggered=True)] +@TraceManager.traced_async(ignore_inputs=["scraped_page", "page"]) async def handle_input_text_action( action: actions.InputTextAction, page: Page, @@ -1135,6 +1142,7 @@ async def handle_input_text_action( await skyvern_element.press_key("Tab") +@TraceManager.traced_async(ignore_inputs=["scraped_page", "page"]) async def handle_upload_file_action( action: actions.UploadFileAction, page: Page, @@ -1212,6 +1220,7 @@ async def handle_upload_file_action( # This function is deprecated. Downloads are handled by the click action handler now. +@TraceManager.traced_async(ignore_inputs=["scraped_page", "page"]) async def handle_download_file_action( action: actions.DownloadFileAction, page: Page, @@ -1253,6 +1262,7 @@ async def handle_download_file_action( return [ActionSuccess(data={"file_path": full_file_path})] +@TraceManager.traced_async(ignore_inputs=["scraped_page", "page"]) async def handle_null_action( action: actions.NullAction, page: Page, @@ -1263,6 +1273,7 @@ async def handle_null_action( return [ActionSuccess()] +@TraceManager.traced_async(ignore_inputs=["scraped_page", "page"]) async def handle_select_option_action( action: actions.SelectOptionAction, page: Page, @@ -1600,6 +1611,7 @@ async def handle_select_option_action( await incremental_scraped.stop_listen_dom_increment() +@TraceManager.traced_async(ignore_inputs=["scraped_page", "page"]) async def handle_checkbox_action( action: actions.CheckboxAction, page: Page, @@ -1628,6 +1640,7 @@ async def handle_checkbox_action( return [ActionSuccess()] +@TraceManager.traced_async(ignore_inputs=["scraped_page", "page"]) async def handle_wait_action( action: actions.WaitAction, page: Page, @@ -1639,6 +1652,7 @@ async def handle_wait_action( return [ActionFailure(exception=Exception("Wait action is treated as a failure"))] +@TraceManager.traced_async(ignore_inputs=["scraped_page", "page"]) async def handle_terminate_action( action: actions.TerminateAction, page: Page, @@ -1649,6 +1663,7 @@ async def handle_terminate_action( return [ActionSuccess()] +@TraceManager.traced_async(ignore_inputs=["scraped_page", "page"]) async def handle_complete_action( action: actions.CompleteAction, page: Page, @@ -1694,6 +1709,7 @@ async def handle_complete_action( return [ActionSuccess()] +@TraceManager.traced_async(ignore_inputs=["scraped_page", "page"]) async def handle_extract_action( action: actions.ExtractAction, page: Page, @@ -1715,6 +1731,7 @@ async def handle_extract_action( return [ActionFailure(exception=Exception("No data extraction goal"))] +@TraceManager.traced_async(ignore_inputs=["scraped_page", "page"]) async def handle_scroll_action( action: actions.ScrollAction, page: Page, @@ -1728,6 +1745,7 @@ async def handle_scroll_action( return [ActionSuccess()] +@TraceManager.traced_async(ignore_inputs=["scraped_page", "page"]) async def handle_keypress_action( action: actions.KeypressAction, page: Page, @@ -1787,6 +1805,7 @@ async def handle_keypress_action( return [ActionSuccess()] +@TraceManager.traced_async(ignore_inputs=["scraped_page", "page"]) async def handle_move_action( action: actions.MoveAction, page: Page, @@ -1798,6 +1817,7 @@ async def handle_move_action( return [ActionSuccess()] +@TraceManager.traced_async(ignore_inputs=["scraped_page", "page"]) async def handle_drag_action( action: actions.DragAction, page: Page, @@ -1815,6 +1835,7 @@ async def handle_drag_action( return [ActionSuccess()] +@TraceManager.traced_async(ignore_inputs=["scraped_page", "page"]) async def handle_verification_code_action( action: actions.VerificationCodeAction, page: Page, @@ -1833,6 +1854,7 @@ async def handle_verification_code_action( return [ActionSuccess()] +@TraceManager.traced_async(ignore_inputs=["scraped_page", "page"]) async def handle_left_mouse_action( action: actions.LeftMouseAction, page: Page, @@ -2092,6 +2114,7 @@ async def chain_click( return [ActionFailure(WrongElementToUploadFile(action.element_id))] +@TraceManager.traced_async(ignore_inputs=["context", "page", "dom", "text", "skyvern_element", "preserved_elements"]) async def choose_auto_completion_dropdown( context: InputOrSelectContext, page: Page, @@ -2418,6 +2441,19 @@ async def input_or_auto_complete_input( return None +@TraceManager.traced_async( + ignore_inputs=[ + "input_or_select_context", + "page", + "dom", + "skyvern_element", + "skyvern_frame", + "incremental_scraped", + "dropdown_menu_element", + "target_value", + "continue_until_close", + ] +) async def sequentially_select_from_dropdown( action: SelectOptionAction, input_or_select_context: InputOrSelectContext, @@ -2470,6 +2506,7 @@ async def sequentially_select_from_dropdown( force_select=force_select, target_value=target_value, ) + assert single_select_result is not None select_history.append(single_select_result) values.append(single_select_result.value) # wait 1s until DOM finished updating @@ -2614,6 +2651,7 @@ class CustomSelectPromptOptions(BaseModel): target_value: str | None = None +@TraceManager.traced_async(ignore_inputs=["scraped_page", "page"]) async def select_from_emerging_elements( current_element_id: str, options: CustomSelectPromptOptions, @@ -2702,6 +2740,19 @@ async def select_from_emerging_elements( return ActionSuccess() +@TraceManager.traced_async( + ignore_inputs=[ + "context", + "page", + "skyvern_element", + "skyvern_frame", + "incremental_scraped", + "check_filter_funcs", + "dropdown_menu_element", + "select_history", + "target_value", + ] +) async def select_from_dropdown( context: InputOrSelectContext, page: Page, @@ -2893,6 +2944,17 @@ async def select_from_dropdown( return single_select_result +@TraceManager.traced_async( + ignore_inputs=[ + "value", + "page", + "skyvern_element", + "skyvern_frame", + "dom", + "incremental_scraped", + "dropdown_menu_element", + ] +) async def select_from_dropdown_by_value( value: str, page: Page, @@ -3133,6 +3195,9 @@ async def try_to_find_potential_scrollable_element( return skyvern_element +@TraceManager.traced_async( + ignore_inputs=["scrollable_element", "page", "skyvern_frame", "incremental_scraped", "is_continue"] +) async def scroll_down_to_load_all_options( scrollable_element: SkyvernElement, page: Page, diff --git a/skyvern/webeye/scraper/scraper.py b/skyvern/webeye/scraper/scraper.py index fcd3fb16..98d33832 100644 --- a/skyvern/webeye/scraper/scraper.py +++ b/skyvern/webeye/scraper/scraper.py @@ -16,6 +16,7 @@ from skyvern.constants import BUILDING_ELEMENT_TREE_TIMEOUT_MS, DEFAULT_MAX_TOKE from skyvern.exceptions import FailedToTakeScreenshot, ScrapingFailed, UnknownElementTreeFormat from skyvern.forge.sdk.api.crypto import calculate_sha256 from skyvern.forge.sdk.core import skyvern_context +from skyvern.forge.sdk.trace import TraceManager from skyvern.utils.image_resizer import Resolution from skyvern.utils.token_counter import count_tokens from skyvern.webeye.browser_factory import BrowserState @@ -392,6 +393,7 @@ class ScrapedPage(BaseModel, ElementTreeBuilder): return await self.generate_scraped_page(take_screenshots=False) +@TraceManager.traced_async(ignore_input=True) async def scrape_website( browser_state: BrowserState, url: str, @@ -646,11 +648,9 @@ async def add_frame_interactable_elements( ) return elements, element_tree - frame_js_script = f"async () => await buildTreeFromBody('{unique_id}', {frame_index})" - - await SkyvernFrame.evaluate(frame=frame, expression=JS_FUNCTION_DEFS) - frame_elements, frame_element_tree = await SkyvernFrame.evaluate( - frame=frame, expression=frame_js_script, timeout_ms=BUILDING_ELEMENT_TREE_TIMEOUT_MS + skyvern_frame = await SkyvernFrame.create_instance(frame) + frame_elements, frame_element_tree = await skyvern_frame.build_tree_from_body( + frame_name=unique_id, frame_index=frame_index ) for element in elements: @@ -662,6 +662,7 @@ async def add_frame_interactable_elements( return elements, element_tree +@TraceManager.traced_async(ignore_input=True) async def get_interactable_element_tree( page: Page, scrape_exclude: ScrapeExcludeFunc | None = None, @@ -671,12 +672,9 @@ async def get_interactable_element_tree( :param page: Page instance to get the element tree from. :return: Tuple containing the element tree and a map of element IDs to elements. """ - await SkyvernFrame.evaluate(frame=page, expression=JS_FUNCTION_DEFS) # main page index is 0 - main_frame_js_script = "async () => await buildTreeFromBody('main.frame', 0)" - elements, element_tree = await SkyvernFrame.evaluate( - frame=page, expression=main_frame_js_script, timeout_ms=BUILDING_ELEMENT_TREE_TIMEOUT_MS - ) + skyvern_page = await SkyvernFrame.create_instance(page) + elements, element_tree = await skyvern_page.build_tree_from_body(frame_name="main.frame", frame_index=0) context = skyvern_context.ensure_context() frames = await get_all_children_frames(page) @@ -718,25 +716,23 @@ class IncrementalScrapePage(ElementTreeBuilder): return True return False + @TraceManager.traced_async(ignore_input=True) async def get_incremental_element_tree( self, cleanup_element_tree: CleanupElementTreeFunc, ) -> list[dict]: frame = self.skyvern_frame.get_frame() - js_script = "async () => await getIncrementElements()" try: - incremental_elements, incremental_tree = await SkyvernFrame.evaluate( - frame=frame, expression=js_script, timeout_ms=BUILDING_ELEMENT_TREE_TIMEOUT_MS + incremental_elements, incremental_tree = await self.skyvern_frame.get_incremental_element_tree( + wait_until_finished=True ) except TimeoutError: LOG.warning( "Timeout to get incremental elements with wait_until_finished, going to get incremental elements without waiting", ) - - js_script = "async () => await getIncrementElements(false)" - incremental_elements, incremental_tree = await SkyvernFrame.evaluate( - frame=frame, expression=js_script, timeout_ms=BUILDING_ELEMENT_TREE_TIMEOUT_MS + incremental_elements, incremental_tree = await self.skyvern_frame.get_incremental_element_tree( + wait_until_finished=False ) # we listen the incremental elements seperated by frames, so all elements will be in the same SkyvernFrame diff --git a/skyvern/webeye/utils/page.py b/skyvern/webeye/utils/page.py index f12c94f9..e65a6517 100644 --- a/skyvern/webeye/utils/page.py +++ b/skyvern/webeye/utils/page.py @@ -14,6 +14,7 @@ from playwright.async_api import ElementHandle, Frame, Page from skyvern.config import settings from skyvern.constants import BUILDING_ELEMENT_TREE_TIMEOUT_MS, PAGE_CONTENT_TIMEOUT, SKYVERN_DIR from skyvern.exceptions import FailedToTakeScreenshot +from skyvern.forge.sdk.trace import TraceManager LOG = structlog.get_logger() @@ -221,6 +222,7 @@ class SkyvernFrame: return await SkyvernFrame.evaluate(frame=frame, expression="() => document.location.href") @staticmethod + @TraceManager.traced_async(ignore_inputs=["file_path", "timeout"]) async def take_scrolling_screenshot( page: Page, file_path: str | None = None, @@ -286,6 +288,7 @@ class SkyvernFrame: await skyvern_frame.scroll_to_x_y(x, y) @staticmethod + @TraceManager.traced_async(ignore_inputs=["page"]) async def take_split_screenshots( page: Page, url: str | None = None, @@ -436,3 +439,21 @@ class SkyvernFrame: async def get_select_options(self, element: ElementHandle) -> tuple[list, str]: js_script = "([element]) => getSelectOptions(element)" return await self.evaluate(frame=self.frame, expression=js_script, arg=[element]) + + @TraceManager.traced_async() + async def build_tree_from_body( + self, frame_name: str | None, frame_index: int, timeout_ms: float = BUILDING_ELEMENT_TREE_TIMEOUT_MS + ) -> tuple[list[dict], list[dict]]: + js_script = "async ([frame_name, frame_index]) => await buildTreeFromBody(frame_name, frame_index)" + return await self.evaluate( + frame=self.frame, expression=js_script, timeout_ms=timeout_ms, arg=[frame_name, frame_index] + ) + + @TraceManager.traced_async() + async def get_incremental_element_tree( + self, wait_until_finished: bool = True, timeout_ms: float = BUILDING_ELEMENT_TREE_TIMEOUT_MS + ) -> tuple[list[dict], list[dict]]: + js_script = "async ([wait_until_finished]) => await getIncrementElements(wait_until_finished)" + return await self.evaluate( + frame=self.frame, expression=js_script, timeout_ms=timeout_ms, arg=[wait_until_finished] + )