[build-system] requires = ["setuptools>=68.0"] build-backend = "setuptools.build_meta" [project] name = "omnigent" # Keep in sync with omnigent/version.py's VERSION constant. version = "0.6.0.dev0" description = "Omnigent: declarative agent authoring and runtime framework" readme = "README.md" requires-python = ">=3.12" authors = [ { name = "Databricks, Inc." }, ] keywords = ["agents", "llm", "ai", "databricks", "cli"] classifiers = [ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", ] dependencies = [ # SDK path-deps, version-locked: the three packages release together at # one version, so a published `omnigent==X` must resolve the SDK wheels # built alongside it (release-omnigent.yml verifies these pins match the # release tag). Local/editable installs still resolve via tool.uv.sources. "omnigent-client==0.6.0.dev0", "omnigent-ui-sdk==0.6.0.dev0", # Merged from omnigent + omnigent. "pyyaml>=6.0,<7", "openai>=1.0,<3", # >=14: the `e2b` extra's SDK (>=2.26) needs rich>=14 (was >=13,<14). "rich>=14,<15", "prompt_toolkit>=3.0,<4", "mcp>=1.0,<2", "starlette>=1.0.1,<2", "uvicorn[standard]>=0.30,<1", # websockets >=15 asyncio client hangs on macOS before emitting any handshake # bytes; pin below 15 until upstream fixes the regression (see issue #1514). "websockets>=10.4,<15", "httpx>=0.27,<1", "ftfy>=6.0", # Portable zombie-aware PID liveness checks for the host daemon # lifecycle (omnigent/host/local_server.py). "psutil>=5.9,<8", # CEL (Common Expression Language) for inline policy evaluation. # Non-Turing-complete, side-effect-free, guaranteed to terminate. # No wheels for Linux aarch64 or macOS x86_64 (Intel); excluded so # installation succeeds. The CEL policy module degrades gracefully # when the library is absent. 'cel-expr-python>=0.1; platform_machine != "aarch64" and (sys_platform != "darwin" or platform_machine != "x86_64")', # OS keychain for storing model-provider API keys (OSS model # selection). Used by omnigent/onboarding/secrets.py; falls back to # a 0600 file when no keyring backend is available (e.g. headless). "keyring>=24,<26", # Round-trip (comment/format-preserving) TOML editing of the user's # ~/.codex/config.toml when removing a Databricks provider # (omnigent/onboarding/ucode_cleanup.py). stdlib tomllib is read-only. "tomlkit>=0.12,<1", # omnigent deps (runtime, spec, server, persistent terminal, etc.). "alembic>=1.0,<2", "anyio>=4.0,<5", "cachetools>=5.0,<7", # _HostGroup (omnigent/cli.py) rewrites a leading positional server URL # into `--server` before Click parses it, so it no longer depends on # Click's internal `protected_args` (made read-only in click 8.2, slated # for removal in click 9). Upper bound `<10` only guards against an # as-yet-unreleased click 10 with unknown breaking changes. "click>=8.0,<10", "fastapi>=0.100,<1", # pexpect/pyte back the POSIX tmux/PTY terminal stack, which is disabled # on Windows (no usable PTY); omnigent never imports them on the core # path, so skip them there to avoid shipping an unusable dependency. "pexpect>=4.9,<5; platform_system != 'Windows'", "pyte>=0.8,<1; platform_system != 'Windows'", "pydantic>=2.0,<3", "sqlalchemy>=2.0,<3", # Client-side compression for opaque text columns (omnigent/db/compression.py), # so per-conversation JSON/text is stored uniformly compressed across SQLite, # PostgreSQL, and MySQL rather than depending on each backend's storage engine. "zstandard>=0.22,<1", "tiktoken>=0.7,<1", "opentelemetry-exporter-otlp-proto-grpc>=1.20,<2", "opentelemetry-exporter-otlp-proto-http>=1.20,<2", "opentelemetry-instrumentation-fastapi>=0,<1", "opentelemetry-instrumentation-httpx>=0,<1", "opentelemetry-instrumentation-sqlalchemy>=0,<1", # The Claude Code and OpenAI Agents harnesses are part of the # baseline install — every CUJ command in the README depends on at # least one of them, so making them optional just forces every user # to remember `--extra all`. Issue #406. "claude-agent-sdk>=0.1.62", "openai-agents>=0.0.17", "PyJWT[crypto]>=2.8,<3", "argon2-cffi>=23.1,<24", # PEP 440 version comparison for the update check / `omni upgrade` # (omnigent/update_check.py, omnigent/cli.py): compares the installed # version against the latest PyPI release. Previously only a # transitive dep; pinned here now that we import it directly. "packaging>=23,<26", ] [project.optional-dependencies] # Retained as no-op aliases so existing `--extra` invocations keep # working; the underlying packages are now default deps above. claude-sdk = [] openai-agents = [] # `all` additionally carries databricks-sdk: the SDK moved out of the # default install (it now lives in the `databricks` extra), but internal # CI / dev installs use `--extra all` and the test suite, deploy tooling, # and databricks_mcps servers import it. all = ["databricks-sdk>=0.56.0,<1"] # From omnigent. bedrock = ["boto3>=1.30,<2", "botocore>=1.30,<2"] # S3-compatible artifact store (AWS S3, Cloudflare R2, MinIO, …). Selected # with ``OMNIGENT_ARTIFACT_URI=s3://bucket/prefix``; the store imports boto3 # lazily, so only users of this backend need the extra. s3 = ["boto3>=1.30,<2", "botocore>=1.30,<2"] vertex = ["google-auth>=2.0,<3"] # Modal sandbox launcher (`omnigent sandbox --provider modal`). The # launcher module ships in the base package and imports the SDK lazily, # so only users of the provider need this extra. modal = ["modal>=1.0,<2"] # Daytona sandbox launcher (`omnigent sandbox --provider daytona` and # server-managed `sandbox.provider: daytona`). # Same lazy-import posture as the modal extra. Pre-1.0 SDK: pin minor. daytona = ["daytona>=0.180,<1"] # Boxlite sandbox launcher: server-managed `sandbox.provider: boxlite`, either # local embedded micro-VMs (KVM/HVF, no daemon) or a remote `boxlite serve` # pool. Same lazy-import posture as the modal/daytona extras. Pre-1.0 SDK: pin # minor. boxlite = ["boxlite>=0.9.5,<1"] # CoreWeave Sandbox launcher (`omnigent sandbox --provider cwsandbox` and # server-managed `sandbox.provider: cwsandbox`). # Same lazy-import posture as above. Pre-1.0 SDK: pin minor. cwsandbox = ["cwsandbox>=0.24,<1"] # E2B sandbox launcher (`omnigent sandbox --provider e2b` and # server-managed `sandbox.provider: e2b`). # Same lazy-import posture as above. e2b = ["e2b>=2.26,<3"] # NVIDIA OpenShell launcher (`omnigent sandbox --provider openshell`). # Self-hosted gRPC gateway; the SDK pulls grpcio + protobuf. Same # lazy-import posture as above. Pre-1.0 SDK: pin minor. openshell = ["openshell>=0.0.7,<1"] # On-demand Kubernetes runner Pod launcher (server-managed # `sandbox.provider: kubernetes`). The launcher module ships in the base # package and imports the official client lazily, so only users of the # provider need this extra. kubernetes = ["kubernetes>=36,<37"] # The tracing extra is now a no-op shim kept for backwards compatibility. # Tracing is built on OpenTelemetry directly (opentelemetry-exporter-otlp-* # are in the default install). `omnigent[tracing]` still works — it just # no longer pulls in the heavy mlflow dependency. tracing = [] agents-sdk = [ "openai-agents>=0.1,<1", "opentelemetry-instrumentation-openai-agents-v2>=0.1", ] # Google Antigravity SDK harness (`harness: antigravity`). Optional: the # harness module imports the SDK lazily on first turn, so only users of the # harness need this extra. Early SDK (v0.1.x) — pin minor. antigravity = ["google-antigravity>=0.1,<1"] # GitHub Copilot SDK harness (`harness: copilot`). Optional: the harness module # imports the SDK lazily on first turn, so only users of the harness need this # extra. The wheel bundles the Copilot CLI binary it drives (~90MB), which is # why it is not part of the baseline install. Pin major. copilot = ["github-copilot-sdk>=1,<2"] # Cursor SDK harness (`harness: cursor`). Optional like antigravity: the # harness imports the cursor-sdk lazily on first turn, so only `--harness # cursor` users need this extra (`omnigent[cursor]`). Was a baseline dependency; # now opt-in to keep the default install lean. cursor = ["cursor-sdk>=0.1.7"] # Hindsight long-term memory built-in tools (hindsight_retain / _recall / # _reflect). The tools import the client lazily, so only users who enable a # Hindsight memory tool need this extra. memory = ["hindsight-client>=0.4.0"] databricks = [ # Floor matches what core code was tested against when the SDK was a # default dependency (it moved here from `dependencies` above). "databricks-sdk>=0.56.0,<1", "opentelemetry-distro>=0,<1", "psycopg[binary]>=3.1,<4", "pymysql>=1.1,<2", # Databricks-specific MCP servers. Not imported by core Omnigent # code, so it is opt-in here rather than a default dependency. "databricks-mcp>=0.1.0", ] dev = [ "pytest>=7.0", # hindsight-client is opt-in (the `memory` extra), but the Hindsight # memory tool tests import + mock it, so keep it in the dev set. "hindsight-client>=0.4.0", "pytest-asyncio>=0.21", "pytest-xdist>=3.6", # Line coverage during the unit-test matrix. Each CI shard writes its # own data file; the code-coverage workflow combines them. See # `[tool.coverage.run]` below for the relative-files setting that makes # cross-runner combine work. "pytest-cov>=5", "pytest-playwright>=0.7", # Visual-regression snapshot plugin for the e2e_ui suite. Provides the # `assert_snapshot` fixture + `--update-snapshots` flag the UI diff gate # uses (see tests/e2e_ui/visual/ and .github/workflows/ui-snapshot.yml). # Requires pytest-playwright>=0.7 (hence the floor bump above). "pytest-playwright-visual-snapshot>=0.5.1", # Hash-partition the test suite across N shards for the nightly # matrix. Pinned to a known-stable older release. Used by e2e.yml; # the e2e-ui suite uses its own round-robin `--splits`/`--group` # split (see tests/e2e_ui/conftest.py), so no extra dep there. "pytest-shard==0.1.2", # Per-test wallclock cap. Without this, a single hung test (e.g. # a pexpect REPL test waiting for a terminal pattern that never # arrives) blocks the whole pytest session until the workflow's # step-level timeout-minutes fires, killing the worker without # producing a junit XML or per-test traceback. With --timeout=N, # pytest-timeout fails the offending test with a clear traceback # and lets the rest of the suite continue. Pinned exactly to a # known-good release for consistency with pytest-shard above. "pytest-timeout==2.4.0", # Retry LLM-driven inner tests up to 2 extra times on codex; see # ``pytest_collection_modifyitems`` in ``tests/inner/conftest.py``. # Pinned exactly to a known-stable release for consistency with # pytest-shard / pytest-timeout above. 16.2+ is required under # pytest 9: 14.0 predates pytest 9 and corrupts fixture-finalizer # state around reruns (stale FixtureDef._finalizers / SetupState # surgery, fixed upstream in 16.2), which leaked one test's # monkeypatch of ``sessions._get_runner_client`` into later tests # on the same xdist worker and flaked the WS-tunnel suite (the # "Runner stream relay exited before becoming ready" 503s). "pytest-rerunfailures==16.3", "filelock>=3.0", "ruff>=0.6", "mypy>=1.10", "pre-commit>=3.5", "types-PyYAML>=6.0", "filelock>=3.0", # gitwildmatch glob matching for repo tooling manifests. Declared # explicitly rather than relied on transitively (via mypy). "pathspec>=0.12", # Cloud-service mocks for the artifact-store / Cloudflare integration # tests: moto is the standard S3-compatible mock (used for R2), respx is # the standard HTTPX mock (used to back the Cloudflare D1 REST API with an # in-memory SQLite), and boto3 backs the S3 artifact store under test. "moto[s3]>=5,<6", "respx>=0.21,<1", "boto3>=1.30,<2", # The Cloudflare D1 SQLAlchemy dialect, exercised by the D1 FTS integration # test (tests/db/test_d1_fts_dialect.py) via respx + sqlite3. "sqlalchemy-cloudflare-d1==0.3.10", ] [project.scripts] # Unified entry point. `omnigent` is the click-based CLI that absorbs # the legacy argparse commands from `omnigent/inner/cli.py` plus the # omnigent `ap` subcommands. See designs/UNIFICATION.md § CLI # absorption. `omni` is installed as a short alias — both resolve to # the same entry point. (No former-name aliases: only `omnigent` and # `omni` ship, internal and OSS alike.) omnigent = "omnigent.cli:main" omni = "omnigent.cli:main" # uv path-deps for the sibling SDK packages (renamed in Stage 3). [tool.uv.sources] omnigent-client = { path = "sdks/python-client", editable = true } omnigent-ui-sdk = { path = "sdks/ui", editable = true } [tool.setuptools] include-package-data = true [tool.setuptools.packages.find] where = ["."] # Discovers the `omnigent` package (including `omnigent.inner.*` and # all omnigent subpackages absorbed during unification). include = ["omnigent*"] [tool.setuptools.package-data] "omnigent.db" = ["alembic.ini"] "omnigent.db.migrations" = ["script.py.mako"] "omnigent.resources.examples" = ["*.yaml", "*.sh", "debby/**/*", "polly/**/*"] "omnigent.resources.pi_native" = ["*.js"] # include UI assets in build, plus the static API-only landing page served # at "/" when no web UI bundle is present "omnigent.server" = ["static/web-ui/**/*", "static/api_only_landing.html"] [tool.pytest.ini_options] # auto mode: async tests without @pytest.mark.asyncio() are auto- # collected as asyncio. Inner (omnigent-legacy) tests rely on # this. SDK tests (tests/frontends/sdk/) use explicit markers; # both work under auto. asyncio_mode = "auto" testpaths = ["tests"] # tests/e2e, tests/e2e_ui, and tests/e2e_live all require real LLM # credentials and/or extra setup (Databricks profile; npm build + # Playwright browsers for the UI suite; a deployed Databricks App URL # for the live suite). Opt-in via explicit pytest invocation. addopts = "--ignore=tests/e2e --ignore=tests/e2e_ui --ignore=tests/e2e_live --ignore=tests/integration" # Default per-test wallclock cap. Catches infinite hangs in any # suite (unit, inner, integration, e2e) without bothering tests # that actually finish. The longest legitimate integration tests # are well under 5 min; anything longer than that is almost # certainly a hang and should surface a traceback rather than # stall the worker. CLI overrides still work: e2e workflows pass # a stricter --timeout=180; individual tests can opt out via # ``@pytest.mark.timeout(N)``. ``thread`` method is more reliable # than the default ``signal`` method when tests fork subprocesses # (SIGALRM doesn't reach blocked-on-pty children) — see # pytest-timeout README. timeout = 300 timeout_method = "thread" # SDK tests under ``tests/frontends/sdk/`` import the # ``omnigent_client`` and ``omnigent_ui_sdk`` packages that # live in ``sdks/python-client/`` and ``sdks/ui/`` respectively. # Without this pythonpath the imports fail at collection time # with ``ModuleNotFoundError: No module named 'omnigent_client'`` # unless the SDKs are installed editable into the venv. Listing # both relative paths here keeps the test suite self-contained. pythonpath = [".", "sdks/python-client", "sdks/ui"] markers = [ "live: end-to-end tests requiring real LLM API key (run with --llm-api-key)", "live_app: end-to-end tests requiring a deployed Databricks App server", "databricks: requires the `databricks` extra (psycopg / databricks-sdk). Deselected on the standard lanes via -m 'not databricks'; runs only in the Pytest (databricks) lane, which installs the extra. Use for tests that build a postgresql+psycopg engine or call the Databricks SDK.", "model(name, ...): one arg pins this test to that model overriding the suite-wide --model CLI default; multiple args fan the test out across all listed models via indirect parametrize.", "model_pinned: opt out of tests/_model_pools.py spreading and retry rotation; literal model strings are used as written.", "flaky(reruns=2, reruns_delay=0): rerun a nondeterministic test on failure (pytest-rerunfailures). Use for tests flaky due to timing/scheduling races (e.g. PTY drain timing), NOT real-LLM nondeterminism — those use llm_flaky, which rotates models per attempt.", "llm_flaky(reruns=2, reruns_delay=1): rerun a nondeterministic real-LLM test on failure, rotating to a different model each attempt (tests/_model_pools.py). Never apply to heavy e2e tests that can hit the CI --timeout=180 cap (rerun + loadscope can crash the shard).", "in_process_sessions: run a server integration test with the legacy in-process sessions path instead of sessions-native runner dispatch.", "nightly: runs only in the scheduled/dispatch pass of its suite; PR and push runs exclude it via -m 'not nightly'. Remove the marker to promote a burned-in test to the PR gate.", "min_server_version(version): skip this test when the live server under test is older than `version` (PEP 440 release-tuple comparison, so a `.devN` of X satisfies X). Used by the server-version backwards-compat CI (docs/SERVER_VERSION_COMPAT_CI.md); inert in normal runs where the server is current.", "min_runner_version(version): skip this test when the pinned runner/host under test is older than `version` (PEP 440 release-tuple comparison, so a `.devN` of X satisfies X). Used by the runner/host backwards-compat CI (Config 2); inert in normal runs (no OMNIGENT_COMPAT_RUNNER_VERSION set).", "mock_only: tests/integration test that only works in mock-LLM mode (no --llm-api-key). Skipped by tests/integration/conftest.py when a real --llm-api-key is supplied (the real-LLM Integration jobs). Use for tests whose mock LLM is scripted with a fixed tool-call sequence — a real LLM cannot reproduce the scripted markers.", "visual: UI diff visual-regression snapshot (pytest-playwright-visual-snapshot). Runs only in the pinned-runner gate (.github/workflows/ui-snapshot.yml); the main e2e_ui suite excludes it via -m 'not visual' since it runs on the unpinned ubuntu-latest.", "posix_only: test relies on POSIX-only behaviour (fork, PTY, tmux, Unix sockets, signals); auto-skipped on Windows by tests/conftest.py.", "windows_only: test relies on Windows-only behaviour (Job Objects, cmd.exe); auto-skipped on POSIX by tests/conftest.py.", ] # Visual snapshot baselines are committed here, keyed per-OS by the plugin # (e.g. test_empty_landing_matches_baseline[linux].png). Failure artifacts # (actual/expected/diff PNGs) land in the gitignored sibling dir. Both are # relative to the repo root, which is where pytest is always invoked. playwright_visual_snapshots_path = "tests/e2e_ui/visual/snapshots" playwright_visual_snapshot_failures_path = "tests/e2e_ui/visual/snapshot_failures" [tool.coverage.run] # Measure the shipped package only; tests live under tests/. source = ["omnigent"] # Each CI shard sets COVERAGE_FILE=artifacts/.coverage. and writes # one data file (pytest-cov already combines the xdist workers within a # shard). `relative_files` stores paths relative to the repo root so the # code-coverage workflow can `coverage combine` data files produced on # separate sharded runners with differing absolute checkout paths. relative_files = true [tool.coverage.report] show_missing = true # Report-only for now: no `fail_under`, so coverage never fails a build. # The code-coverage workflow reports against a plain `git checkout` that # has no generated files (e.g. omnigent/_build_info.py, written during # `uv sync` in the CI shards). Without this, `coverage report`/`xml` exit # 1 on "No source for code" and fail the step under `set -e`; ignore those # unreadable-source files instead. ignore_errors = true [tool.ruff] line-length = 99 # NOTE: kept at py310 even though requires-python is >=3.12. Bumping this to # py312 makes ruff's UP041 rewrite `asyncio.TimeoutError` -> `TimeoutError` # (aliased since 3.11) across the whole codebase — a separate, out-of-scope # migration that belongs in its own cleanup PR. target-version = "py310" # Vendored upstream code — not ours to restyle. # - ``omnigent/inner/databricks_mcps/google``: Google MCP server source. # - ``assistant-ui/``: assistant-ui.com React/Python suite imported as a # vendored snapshot; tracked upstream, no in-tree edits. extend-exclude = [ "omnigent/inner/databricks_mcps/google", "assistant-ui", ] [tool.ruff.lint] # ``E``/``F`` — pycodestyle + pyflakes baseline # ``I`` — import sorting # ``UP`` — pyupgrade (modernize syntax) # ``ARG`` — unused function arguments # ``BLE`` — blind ``except Exception`` # ``B`` — flake8-bugbear (latent bugs, e.g. mutable defaults, # unbound loop variables in closures, raise-from) # ``SIM`` — flake8-simplify (reduce unnecessary complexity) # ``RET`` — flake8-return (consistent return statements) # ``C4`` — flake8-comprehensions (cleaner list/dict/set comprehensions) # ``PIE`` — flake8-pie (misc correctness + style) # ``RUF`` — ruff-specific (sorted ``__all__``, dangling asyncio # tasks, unused noqa, ...) select = ["E", "F", "I", "UP", "ARG", "BLE", "B", "SIM", "RET", "C4", "PIE", "RUF"] ignore = [ # ARG003 (unused class-method args): too noisy on ABC-subclass signatures # where the arg is required by the interface contract. "ARG003", # RUF001/002/003 ambiguous-unicode: the repo uses ``—`` / ``–`` / ``×`` / # ``╱`` in docstrings and CLI UI strings intentionally. The rule was # designed for source strings that could be confused with ASCII and # throws off on legitimate typographic characters in prose. "RUF001", "RUF002", "RUF003", # SIM102/103/108: style-only transforms (collapse nested if / return # condition directly / rewrite if-else as ternary). Often make code # harder to read when the conditions are non-trivial. Kept available # as manual refactoring hints but not enforced. "SIM102", "SIM103", "SIM108", ] [tool.ruff.lint.isort] # Classify first-party imports by NAME, not by file existence. Ruff's # default detection resolves each module against the filesystem, so an # import of an optional submodule absent from a given checkout (e.g. # omnigent.onboarding.internal_beta) would be reclassified as third-party # there, demanding a different import order per checkout. Pinning the # package name keeps one canonical order everywhere. known-first-party = ["omnigent"] [tool.ruff.lint.per-file-ignores] # Tests legitimately accept parameters they don't use (pytest fixtures, # mock callback signatures) and intercept broad exceptions to assert on # error paths. Cleaning these up is a separate cleanup pass. # # RUF012 (mutable default class attribute): test fake classes and # Textual/pytest harnesses routinely declare class-level # ``BINDINGS = [...]`` / ``inputSchema: dict = {...}`` that are never # mutated — the rule's production-shared-state concern doesn't apply. # # B007 (loop var unused): occasional ``for i, x in enumerate(...)`` in # tests where only ``x`` matters; style not worth policing. # # B008 (function call in default): pytest / factory_boy idioms. # # SIM117 (combined with): already-legible nested ``with`` in test # fixtures that would be harder to read if merged. "tests/**/*.py" = [ "ARG001", "ARG002", "ARG004", "ARG005", "BLE001", "RUF012", "B007", "B008", "SIM117", ] # Example scripts predate the rule and are exempted until they graduate. "tests/resources/examples/**/*.py" = [ "ARG001", "ARG002", "ARG004", "ARG005", "BLE001", "RUF012", "B007", "B008", "SIM117", ] # Graduation backlog for code migrated from omnigent during the # unification. Pre-unification Omnigent' ruff config only selected # ``E, F, I, UP`` — none of the ARG/BLE/B/SIM/... rules — so these # files have a backlog of unused-arg, blind-except, and bugbear issues # that were invisible before. Graduate each subpath out of this list # as it's cleaned up. "omnigent/llms/**/*.py" = [ "ARG001", "ARG002", "BLE001", "B008", "RUF012", ] "omnigent/onboarding/**/*.py" = [ "ARG001", "ARG002", "BLE001", "B008", "RUF012", ] "omnigent/runtime/**/*.py" = [ "ARG001", "ARG002", "BLE001", "B008", "RUF012", ] "omnigent/terminals/**/*.py" = [ "ARG001", "ARG002", "BLE001", "B008", "RUF012", ] "omnigent/tools/**/*.py" = [ "ARG001", "ARG002", "BLE001", "B008", "RUF012", ] # The native Antigravity (agy) transcript forwarder / supervisor is a # long-lived boundary loop that must restart on ANY non-cancellation # Exception (a crash there silently stops the web transcript mirror), so its # top-level catch is a deliberate, documented boundary catch — BLE001 is # waived for these top-level antigravity_native modules (see the inline # comments at each catch site). "omnigent/antigravity_native*.py" = ["BLE001"] "sdks/**/*.py" = [ "ARG001", "ARG002", "BLE001", "B008", "RUF012", ] [tool.mypy] python_version = "3.12" strict = true # Ban explicit `Any` in annotations. `Any` defeats static typing; prefer # real types, Protocols, TypedDicts, or `object` with runtime checks. When # a genuine boundary needs it (opaque JSON shapes, foreign SDKs) annotate # with `# type: ignore[explicit-any]` *and a comment explaining why*. disallow_any_explicit = true # Vendored Google MCP server code — upstream code, not ours to type. # setup.py — build-time scaffolding that imports the (untyped) setuptools # build_py and subclasses it; not application code, so excluded from mypy # rather than pulling in types-setuptools just for one shim file. exclude = ["^omnigent/inner/databricks_mcps/google/", "^setup\\.py$"] # Incremental rollout: load imported modules for type info but don't # report their errors. Remove once every omnigent/ module is clean. follow_imports = "silent" [[tool.mypy.overrides]] module = "mcp.*" ignore_missing_imports = true [[tool.mypy.overrides]] module = "databricks.*" ignore_missing_imports = true [[tool.mypy.overrides]] module = "databricks_mcp.*" ignore_missing_imports = true # psycopg is an optional dep (only declared in the ``databricks`` # extra, used by ``deploy/databricks/grant_sp_perms.py``). Previously installed # transitively via ``dbos``; after the DBOS removal, ``uv sync # --extra dev`` no longer pulls it, so the lint workflow can't # import it. Treat the missing module as silent — runtime use still # requires installing the ``databricks`` extra. [[tool.mypy.overrides]] module = "psycopg.*" ignore_missing_imports = true [[tool.mypy.overrides]] module = "openai.*" ignore_missing_imports = true [[tool.mypy.overrides]] module = "claude_agent_sdk.*" ignore_missing_imports = true [[tool.mypy.overrides]] module = "agents.*" ignore_missing_imports = true [[tool.mypy.overrides]] module = "ftfy" ignore_missing_imports = true # modal is an optional dep (the `modal` extra); the sandbox launcher # imports it lazily so the base install never needs it. [[tool.mypy.overrides]] module = "modal.*" ignore_missing_imports = true # daytona is an optional dep (the `daytona` extra); same lazy-import # posture as modal above. [[tool.mypy.overrides]] module = "daytona.*" ignore_missing_imports = true # hindsight-client is an optional dep (the `memory` extra); the memory # built-in tools import it lazily so the base install never needs it. [[tool.mypy.overrides]] module = "hindsight_client.*" ignore_missing_imports = true # cwsandbox is an optional dep (the `cwsandbox` extra); same lazy-import # posture as modal above. [[tool.mypy.overrides]] module = "cwsandbox.*" ignore_missing_imports = true # e2b is an optional dep (the `e2b` extra); same lazy-import posture as # modal above. [[tool.mypy.overrides]] module = "e2b.*" ignore_missing_imports = true # openshell is an optional dep (the `openshell` extra); same lazy-import # posture as modal above. grpc rides in via the openshell SDK and is not # a base dependency, so its imports are unresolved in the default env too. [[tool.mypy.overrides]] module = "openshell.*" ignore_missing_imports = true # boxlite is an optional dep (the `boxlite` extra); same lazy-import posture # as modal above. [[tool.mypy.overrides]] module = "boxlite.*" ignore_missing_imports = true # kubernetes is an optional dep (the `kubernetes` extra); same lazy-import # posture as modal above. urllib3 rides in via the kubernetes client. [[tool.mypy.overrides]] module = "kubernetes.*" ignore_missing_imports = true [[tool.mypy.overrides]] module = "grpc.*" ignore_missing_imports = true [[tool.mypy.overrides]] module = "prompt_toolkit.*" ignore_missing_imports = true [[tool.mypy.overrides]] module = "yaml" ignore_missing_imports = true [[tool.mypy.overrides]] module = "pexpect" ignore_missing_imports = true [[tool.mypy.overrides]] module = "cachetools" ignore_missing_imports = true [[tool.mypy.overrides]] module = "httpx" ignore_missing_imports = true [[tool.mypy.overrides]] module = "boto3" ignore_missing_imports = true [[tool.mypy.overrides]] module = "botocore.*" ignore_missing_imports = true [[tool.mypy.overrides]] module = "google.*" ignore_missing_imports = true [[tool.mypy.overrides]] module = "opentelemetry.instrumentation.*" ignore_missing_imports = true # The Modal deploy glue (deploy/modal/modal_app.py) decorates with the # optional `modal` extra, which the lint env doesn't install — under the # modal.* ignore-missing-imports override above its decorators type as # Any and trip disallow_untyped_decorators. Relax just that flag. [[tool.mypy.overrides]] module = "modal_app" disallow_untyped_decorators = false # omnigent-derived repl code has its own relaxed typing config. [[tool.mypy.overrides]] module = "omnigent.repl.*" disallow_untyped_defs = false disallow_untyped_decorators = false warn_return_any = false check_untyped_defs = false # omnigent-derived code that pre-unification omnigent never # subjected to ``disallow_any_explicit`` (its pyproject.toml didn't # set that flag). Keep the rest of strict mypy on — just relax the # explicit-Any ban until these modules can be graduated. [[tool.mypy.overrides]] module = [ "omnigent.runtime.*", "omnigent.server.*", "omnigent.tools.*", "omnigent.entities.*", "omnigent.stores.*", "omnigent.db.*", "omnigent.llms.*", "omnigent.onboarding.*", "omnigent.terminals.*", "omnigent.client_tools.*", "omnigent.spec.omnigent", "omnigent.spec._omnigent_compat", "dump_openapi", ] disallow_any_explicit = false [[tool.mypy.overrides]] module = "omnigent_ui_sdk.*" ignore_missing_imports = true follow_imports = "skip" # SDK shim aliases — ignore their own import resolution issues. These # are re-exports of omnigent_client/omnigent_ui_sdk (post-Stage-3) # via sys.modules aliasing. [[tool.mypy.overrides]] module = "omnigent_client.*" ignore_missing_imports = true disallow_any_explicit = false # Tests in the mypy allowlist predate the stricter omnigent # Any rule. [[tool.mypy.overrides]] module = "tests.*" disallow_any_explicit = false