# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
[project]
authors = [{ name = "Google" }]
dependencies = [
"dotpromptz==0.1.5",
"genkit",
"genkit-plugin-anthropic",
"genkit-plugin-cf-ai",
"genkit-plugin-compat-oai",
"genkit-plugin-deepseek",
"genkit-plugin-dev-local-vectorstore",
"genkit-plugin-evaluators",
"genkit-plugin-firebase",
"genkit-plugin-flask",
"genkit-plugin-google-cloud",
"genkit-plugin-google-genai",
"genkit-plugin-ollama",
"genkit-plugin-vertex-ai",
"genkit-plugin-xai",
"genkit-plugin-mcp",
"genkit-plugin-msfoundry",
"genkit-plugin-aws-bedrock",
"genkit-plugin-aws",
"genkit-plugin-azure",
"genkit-plugin-cf",
"genkit-plugin-mistral",
"genkit-plugin-huggingface",
"genkit-plugin-observability",
"liccheck>=0.9.2",
"mcp>=1.25.0",
"python-multipart>=0.0.22",
"strenum>=0.4.15; python_version < '3.11'",
]
description = "Workspace for Genkit packages"
license = "Apache-2.0"
name = "genkit-workspace"
readme = "README.md"
requires-python = ">=3.10"
version = "0.1.0"
[dependency-groups]
dev = [
"bpython>=0.25",
"ipython~=8.22; python_version <= '3.10'",
"ipython~=9.0.2; python_version >= '3.11'",
"jupyter>=1.1.1",
"pytest-asyncio>=0.25.3",
"pytest>=8.3.4",
"pytest-cov>=6.0.0",
"datamodel-code-generator>=0.27.3",
"pytest-watcher>=0.4.3",
"pytest-mock>=3.14.0",
"twine>=6.1.0",
"poethepoet>=0.33.1",
"pip>=25.0.1",
"tox>=4.25.0",
"tox-uv>=1.25.0",
"nox>=2025.2.9",
"nox-uv>=0.2.2",
]
lint = [
"bandit>=1.7.0",
"deptry>=0.22.0",
"mypy>=1.14.0",
"pip-audit>=2.7.0",
"pypdf>=6.6.2",
"pyrefly>=0.15.0",
"pyright>=1.1.392",
"pysentry-rs>=0.3.14",
"ruff>=0.9",
"strenum>=0.4.15",
"streamlit>=1.41.0",
"ty>=0.0.1",
"typos>=1.42.0",
]
[tool.hatch.build.targets.wheel]
[tool.setuptools]
py-modules = []
# Pytest for unit testing and coverage.
[tool.pytest]
[tool.pytest.ini_options]
addopts = [
"--cov",
#"--cov-report=", # Disable terminal report generation by pytest-cov
"-ra",
"-vv",
]
asyncio_default_fixture_loop_scope = "session"
python_files = ["*_test.py"]
testpaths = ["packages", "plugins", "samples", "tests"]
#asyncio_mode = "auto"
asyncio_mode = "strict"
[tool.coverage.report]
fail_under = 78
[tool.coverage.run]
omit = [
"**/__init__.py", # Often contains just imports
"**/testing.py", # Test utilities
"**/constants.py", # Typically just constants
"**/typing.py", # Often auto-generated or complex types
"**/types.py", # Often auto-generated or complex types
]
source = ["packages", "plugins"]
# uv based package management.
[tool.uv]
default-groups = ["dev", "lint"]
[tool.uv.sources]
# Samples (alphabetical by package name from pyproject.toml)
anthropic-hello = { workspace = true }
aws-bedrock-hello = { workspace = true }
aws-hello = { workspace = true }
azure-hello = { workspace = true }
cf-ai-hello = { workspace = true }
cf-hello = { workspace = true }
compat-oai-hello = { workspace = true }
deepseek-hello = { workspace = true }
dev-local-vectorstore-hello = { workspace = true }
evaluator-demo = { workspace = true }
firestore-retreiver = { workspace = true }
flask-hello = { workspace = true }
format-demo = { workspace = true }
google-genai-code-execution = { workspace = true }
google-genai-context-caching = { workspace = true }
google-genai-hello = { workspace = true }
google-genai-image = { workspace = true }
google-genai-vertexai-hello = { workspace = true }
google-genai-vertexai-image = { workspace = true }
huggingface-hello = { workspace = true }
media-models-demo = { workspace = true }
menu = { workspace = true }
mistral-hello = { workspace = true }
model-garden = { workspace = true }
msfoundry-hello = { workspace = true }
multi-server = { workspace = true }
observability-hello = { workspace = true }
ollama-hello = { workspace = true }
ollama-simple-embed = { workspace = true }
prompt-demo = { workspace = true }
realtime-tracing-demo = { workspace = true }
short-n-long = { workspace = true }
tool-interrupts = { workspace = true }
vertex-ai-vector-search-bigquery = { workspace = true }
vertex-ai-vector-search-firestore = { workspace = true }
xai-hello = { workspace = true }
# Core packages
genkit = { workspace = true }
# Plugins (alphabetical)
genkit-plugin-anthropic = { workspace = true }
genkit-plugin-aws = { workspace = true }
genkit-plugin-aws-bedrock = { workspace = true }
genkit-plugin-azure = { workspace = true }
genkit-plugin-cf = { workspace = true }
genkit-plugin-cf-ai = { workspace = true }
genkit-plugin-compat-oai = { workspace = true }
genkit-plugin-deepseek = { workspace = true }
genkit-plugin-dev-local-vectorstore = { workspace = true }
genkit-plugin-evaluators = { workspace = true }
genkit-plugin-firebase = { workspace = true }
genkit-plugin-flask = { workspace = true }
genkit-plugin-google-cloud = { workspace = true }
genkit-plugin-google-genai = { workspace = true }
genkit-plugin-huggingface = { workspace = true }
genkit-plugin-mcp = { workspace = true }
genkit-plugin-mistral = { workspace = true }
genkit-plugin-msfoundry = { workspace = true }
genkit-plugin-observability = { workspace = true }
genkit-plugin-ollama = { workspace = true }
genkit-plugin-vertex-ai = { workspace = true }
genkit-plugin-xai = { workspace = true }
[tool.uv.workspace]
exclude = ["*/shared"]
members = ["packages/*", "plugins/*", "samples/*"]
# Ruff checks and formatting.
[tool.ruff]
exclude = [
".bzr",
".direnv",
".eggs",
".git",
".git-rewrite",
".hg",
".ipynb_checkpoints",
".mypy_cache",
".nox",
".pants.d",
".pyenv",
".pytest_cache",
".pytype",
".ruff_cache",
".svn",
".tox",
".venv",
".vscode",
"__pypackages__",
"_build",
"bazel-*",
"buck-out",
"build",
"dist",
"node_modules",
"site-packages",
"venv",
]
indent-width = 4
line-length = 120
preview = true
target-version = "py310"
unsafe-fixes = true
[tool.ruff.lint]
fixable = ["ALL"]
select = [
"E", # pycodestyle (errors)
"W", # pycodestyle (warnings)
"F", # pyflakes
"I", # isort (import sorting)
"UP", # pyupgrade (Python version upgrades)
"B", # flake8-bugbear (common bugs)
"N", # pep8-naming (naming conventions)
"D", # pydocstyle
"ANN", # flake8-annotations (type hints)
"F401", # unused imports
"F403", # wildcard imports
"F841", # unused variables
"S", # flake8-bandit (security)
"ASYNC",# flake8-async (async best practices)
"T20", # flake8-print (no print statements)
# TODO(https://github.com/firebase/genkit/issues/4398): Enable PLC0415 after
# completing cleanup of remaining in-function imports in core framework.
# "PLC0415",
]
ignore = [
"S101", # assert used - we use assert for type narrowing and tests
"S105", # hardcoded password string - false positives in tests
"S106", # hardcoded password func arg - false positives in tests
"S311", # random not for security - we don't use random for crypto
]
[tool.ruff.lint.per-file-ignores]
# Typing tests use reveal_type(), intentional unused vars, and don't need docstrings
"packages/genkit/tests/typing/*.py" = ["D", "F821", "F841", "B018", "ANN"]
# Samples have install_rich_traceback() call after imports, before other code
# Samples are demo code and can use blocking I/O for simplicity
"samples/*/*.py" = ["E402", "ASYNC"]
"samples/*/**/*.py" = ["E402", "ASYNC"]
"samples/*/src/*.py" = ["E402", "ASYNC"]
# Core framework: temporarily ignore security/async rules until core team approves fixes
# These will be addressed in a separate PR with core framework changes
"packages/genkit/**/*.py" = ["S110", "S112", "S310", "T201"]
[tool.ruff.lint.isort]
combine-as-imports = true
force-single-line = false
known-first-party = ["genkit"]
section-order = [
"future",
"standard-library",
"third-party",
"first-party",
"local-folder",
]
[tool.ruff.lint.pydocstyle]
convention = "google"
[tool.ruff.format]
docstring-code-format = true
docstring-code-line-length = 120
indent-style = "space"
line-ending = "lf"
quote-style = "single"
skip-magic-trailing-comma = false
[tool.datamodel-codegen]
#collapse-root-models = true # Don't use; produces Any as types.
#strict-types = ["str", "int", "float", "bool", "bytes"] # Don't use; produces StrictStr, StrictInt, etc.
#use-subclass-enum = true
capitalize-enum-members = true
disable-timestamp = true
enable-version-header = true
field-constraints = true
input = "../genkit-tools/genkit-schema.json"
input-file-type = "jsonschema"
output = "packages/genkit/src/genkit/core/typing.py"
output-model-type = "pydantic_v2.BaseModel"
snake-case-field = true
strict-nullable = true
target-python-version = "3.11"
use-default = false
use-schema-description = true
use-standard-collections = true
use-subclass-enum = true
use-union-operator = true
use-unique-items-as-set = true
[tool.liccheck]
authorized_licenses = [
"3-clause bsd",
"apache 2.0",
"apache software license",
"apache software",
"apache",
"apache-2.0",
"bsd license",
"bsd-3-clause",
"bsd",
"cmu license (mit-cmu)",
"isc license (iscl)",
"isc license",
"mit license",
"mit",
"mit-cmu",
"new bsd license",
"new bsd",
"psf-2.0",
"python software foundation license",
"simplified bsd",
"the unlicense (unlicense)", # TODO: verify.
"bsd-2-clause",
"apache license 2.0",
"apache-2.0 and mit",
"mpl-2.0 and mit", # tqdm uses this dual license
]
dependencies = true
unauthorized_licenses = [
"gnu lgpl",
"gpl v3",
"lgpl with exceptions or zpl",
"zpl 2.1",
"mpl",
]
[tool.liccheck.authorized_packages]
aiohappyeyeballs = "2.6.1" # Python Software Foundation (transitive dep of xai-sdk)
aiohttp = "3.13.3" # Apache-2.0 AND MIT (transitive dep of xai-sdk)
certifi = "2026.1.4" # TODO: Verify.
dependencies = true
dotpromptz-handlebars = "0.1.8" # Apache-2.0 "https://github.com/google/dotprompt/blob/main/LICENSE"
google-crc32c = "1.8.0" # Apache-2.0
mistralai = ">=1.9.11" # Apache-2.0 "https://github.com/mistralai/client-python/blob/main/LICENSE"
multidict = "6.7.0" # Apache-2.0
ollama = "0.5.1" # MIT "https://github.com/ollama/ollama-python/blob/main/LICENSE"
pyasn1 = "0.6.2" # BSD-2-Clause
# Ty (Astral/Ruff) type checking configuration.
# See: https://docs.astral.sh/ty/modules/#first-party-modules
[tool.ty.environment]
root = [
# Core package
"packages/genkit/src",
# Plugins
"plugins/anthropic/src",
"plugins/aws/src",
"plugins/aws-bedrock/src",
"plugins/azure/src",
"plugins/cf/src",
"plugins/cf-ai/src",
"plugins/compat-oai/src",
"plugins/deepseek/src",
"plugins/dev-local-vectorstore/src",
"plugins/evaluators/src",
"plugins/firebase/src",
"plugins/flask/src",
"plugins/google-cloud/src",
"plugins/google-genai/src",
"plugins/huggingface/src",
"plugins/mcp/src",
"plugins/mistral/src",
"plugins/msfoundry/src",
"plugins/observability/src",
"plugins/ollama/src",
"plugins/vertex-ai/src",
"plugins/xai/src",
# Samples
".", # For samples.shared imports
"samples/evaluator-demo", # For evaluator_demo package imports
"samples/menu/src", # For menu sample imports
"plugins/mcp/tests", # For fakes module imports in tests
]
# Pyright type checking configuration.
[tool.pyright]
exclude = [
"**/__pycache__",
".git",
".mypy_cache",
".nox",
".pytest_cache",
".ruff_cache",
".tox",
"build",
"dist",
]
# Use the venv where packages are installed as editable installs
pythonVersion = "3.10"
reportMissingImports = true
reportMissingTypeStubs = false
typeCheckingMode = "basic"
venv = ".venv"
venvPath = "."
# Pyrefly type checking configuration (Meta's new type checker).
#
# Import Resolution Note:
# Pyrefly doesn't fully support PEP 420 namespace packages. The genkit plugins use
# namespace packages (genkit.plugins.*) where intermediate directories (genkit/ and
# genkit/plugins/) don't have __init__.py files. This is intentional for allowing
# multiple packages to contribute to the same namespace, but pyrefly can't resolve
# these imports statically. We use ignore-missing-imports for "genkit.plugins.*" to
# suppress false positive import errors while still catching real type errors.
# At runtime, these imports work correctly because Python's import system handles
# PEP 420 namespace packages natively.
[tool.pyrefly]
project_excludes = [
"**/__pycache__",
".git",
".mypy_cache",
".nox",
".pytest_cache",
".ruff_cache",
".tox",
".venv",
"build",
"dist",
]
project_includes = [
# Core package (source and tests)
"packages/genkit/src/**/*.py",
"packages/genkit/tests/**/*.py",
# Plugins (source and tests)
"plugins/*/src/**/*.py",
"plugins/*/tests/**/*.py",
# Samples
"samples/*/src/**/*.py",
"samples/evaluator-demo/evaluator_demo/**/*.py",
]
# Search path for first-party code import resolution.
# The project root "." covers all packages. Additional paths are needed for:
# - plugins/mcp/tests: has a local `fakes` module for test mocks
# - samples/evaluator-demo: has `evaluator_demo` package with internal imports
# - samples/menu/src: has internal imports (menu_ai, menu_schemas)
search-path = [
".",
"plugins/mcp/tests",
"samples/evaluator-demo",
"samples/menu/src",
]
# Ignore missing imports for namespace packages - pyrefly can't resolve PEP 420
# namespace packages but these imports work at runtime
ignore-missing-imports = ["genkit.plugins.*"]
python_version = "3.10"
# Treat warnings as errors.
[tool.pyrefly.errors]
deprecated = "error"
redundant-cast = "error"