55459d5df9
## Related issue https://linear.app/omnigent/issue/OMNI-4270/remove-memory-extra ## Summary - Remove the deprecated `memory` compatibility alias now that `hindsight` is the canonical extra. - Regenerate the normalized lockfile so published package metadata no longer advertises `memory`. ## Test Plan - `uv run --no-sync pytest -q tests/onboarding/test_extra_install.py` - Build the wheel and inspect its `METADATA` to confirm `hindsight` remains in `Provides-Extra` and `memory` does not. - `git diff --check` ## Demo N/A — packaging-only change. ## Type of change - [ ] Bug fix - [ ] Feature - [ ] UI / frontend change - [ ] Refactor / chore - [ ] Docs - [ ] Test / CI - [x] Breaking change ## Test coverage - [ ] Unit tests added / updated - [ ] Integration tests added / updated - [ ] E2E tests added / updated - [x] Manual verification completed - [x] Existing tests cover this change - [ ] Not applicable ## Coverage notes Verified the built wheel's optional dependency metadata directly; the existing onboarding extra tests continue to pass. ## Changelog The deprecated `omnigent[memory]` extra has been removed; use `omnigent[hindsight]` instead. Signed-off-by: Zeyi (Rice) Fan <zeyi.f@databricks.com>
655 lines
35 KiB
TOML
655 lines
35 KiB
TOML
[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.11.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.11.0.dev0",
|
||
"omnigent-ui-sdk==0.11.0.dev0",
|
||
# Merged from omnigent + omnigent.
|
||
"pyyaml>=6.0,<7",
|
||
# OpenClaw stores its wrapped acpx registry as JSON5.
|
||
"json5>=0.10,<1",
|
||
# openai-agents<0.18.2 omits a field required by openai>=2.45.
|
||
# Keep this cap until the websockets<15 compatibility pin can be lifted.
|
||
"openai>=1.0,<2.45",
|
||
# >=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.
|
||
# NOT pure-Python: cel-python hard-depends on google-re2 (a C++ extension,
|
||
# imported at celpy module scope with no fallback), whose sdist needs bazel.
|
||
# Packagers must pin its prebuilt wheel — see WHEEL_PACKAGES in
|
||
# .github/scripts/homebrew/generate_formula.py.
|
||
"cel-python>=0.5",
|
||
# 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",
|
||
# Decode and validate public branding assets before serving them.
|
||
"pillow>=12.2,<13",
|
||
# 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",
|
||
# Server performance metrics use the no-op API even when tracing is off.
|
||
"opentelemetry-api>=1.20,<2",
|
||
# 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",
|
||
# CA root bundle for client TLS verification (omnigent/tls.py,
|
||
# omnigent/inner/egress/ca.py). Required as a real fallback on uv /
|
||
# python-build-standalone interpreters whose OpenSSL has no default cert
|
||
# path; previously only transitive, pinned here now that we import it.
|
||
"certifi>=2023.7",
|
||
# Protobuf schema for the AI-gateway routing API
|
||
# (omnigent/api/routing/v1/routing.proto).
|
||
# Previously only a transitive dep; declared directly now that we ship a proto.
|
||
# Upper bound widened to <8 so the google-antigravity extra can pull in
|
||
# protobuf 7.x without conflicting with this core floor. Our own
|
||
# routing_pb2 gencode was compiled against protobuf 6.x; the protobuf
|
||
# runtime guarantee allows a newer runtime (7.x) to load older gencode, so
|
||
# a plain install stays on 6.x and an antigravity install upgrades to 7.x.
|
||
"protobuf>=6,<8",
|
||
# RFC 5545 recurrence rules for the scheduled-task scheduler
|
||
# (omnigent/server/scheduled/rrule.py). Imported at module top and pulled
|
||
# onto the core server boot path via app.py; previously only a transitive
|
||
# dep, declared directly now that we import it.
|
||
"python-dateutil>=2.8,<3",
|
||
# IANA time-zone database for `zoneinfo`. Windows ships no system tz
|
||
# database, so `ZoneInfo("UTC")` raises ZoneInfoNotFoundError there
|
||
# unless this package is installed. Evaluated at module top in
|
||
# omnigent/server/scheduled/rrule.py and scheduler.py, both pulled onto
|
||
# the core server boot path via app.py, so a Windows install crashes on
|
||
# `omnigent server start` without it. POSIX platforms use the system
|
||
# database and don't need the wheel.
|
||
"tzdata>=2024.1; platform_system == 'Windows'",
|
||
]
|
||
|
||
[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` carries dependencies moved out of the default install that internal
|
||
# CI / dev workflows still exercise.
|
||
all = [
|
||
"databricks-sdk>=0.56.0,<1",
|
||
"opentelemetry-sdk>=1.20,<2",
|
||
"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",
|
||
]
|
||
# 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"]
|
||
# Blaxel sandbox launcher (`omnigent sandbox --provider blaxel` and
|
||
# server-managed `sandbox.provider: blaxel`).
|
||
blaxel = ["blaxel>=0.4.1,<0.5"]
|
||
# 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"]
|
||
# Islo sandbox launcher (`omnigent sandbox --provider islo` and
|
||
# server-managed `sandbox.provider: islo`). The launcher module ships in
|
||
# the base package and imports the SDK lazily, so only users of the
|
||
# provider need this extra.
|
||
islo = ["islo>=0.3.5,<0.4"]
|
||
# 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.88,<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"]
|
||
# OpenTelemetry tracing is opt-in so the exporters and automatic
|
||
# instrumentors do not inflate the default install.
|
||
tracing = [
|
||
"opentelemetry-sdk>=1.20,<2",
|
||
"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",
|
||
]
|
||
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.
|
||
# google-antigravity ships proto gencode compiled against protobuf 7.x, so
|
||
# the runtime must satisfy >=7 when this extra is installed; the core allows
|
||
# >=6,<8, so this constraint selects the 7.x slot and prevents the
|
||
# "gencode/runtime version mismatch" error at import time.
|
||
antigravity = ["google-antigravity>=0.1,<1", "protobuf>=7,<8"]
|
||
# 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"]
|
||
# Server-side streaming dictation (`WS /v1/dictation/stream`,
|
||
# designs/server-dictation.md). Local CPU speech-to-text via sherpa-onnx;
|
||
# the engine module imports it lazily, so only servers offering dictation
|
||
# need the extra. Models are fetched separately
|
||
# (scripts/fetch-dictation-models.sh). sherpa-onnx-core (the native
|
||
# onnxruntime payload) is pinned explicitly because sherpa-onnx's wheel
|
||
# metadata declares it inconsistently across platforms — without the
|
||
# explicit pin it is missing from uv.lock, which breaks both the hashed
|
||
# OSV audit and aarch64 installs.
|
||
dictation = [
|
||
"sherpa-onnx>=1.13,<2",
|
||
"sherpa-onnx-core>=1.13,<2",
|
||
# The engine converts PCM frames with numpy directly; declare it
|
||
# rather than riding whichever extra happens to pull it in.
|
||
"numpy>=1.24,<3",
|
||
]
|
||
# 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.
|
||
hindsight = ["hindsight-client>=0.4.0"]
|
||
# Nimble research runs (the `nimble_research` builtin). The tool imports the
|
||
# nimble-python client lazily, so only users who enable nimble_research need
|
||
# this extra. nimble_extract talks raw httpx and needs no extra.
|
||
nimble = ["nimble-python>=1.2.0,<2"]
|
||
# Slack integration (`omni integration slack`). The @omnigent socket-mode bot
|
||
# lives in the separate `omnigent-slack` package (heavy deps — slack_bolt /
|
||
# aiohttp — kept out of the baseline install). The CLI launches it as a
|
||
# subprocess (`python -m omnigent_slack`), so it must be importable in the same
|
||
# environment; installing `omnigent[slack]` puts it there. Local/editable
|
||
# installs resolve it from `integrations/slack` via [tool.uv.sources] below;
|
||
# publishing `omnigent[slack]` to an index additionally requires publishing
|
||
# `omnigent-slack` there (not yet wired into the release pipeline).
|
||
# Version-locked (==) with the lockstep cycle — `scripts/update_versions.py`
|
||
# keeps this pin in sync with the other sibling `==` pins
|
||
# (`omnigent-client`, `omnigent-ui-sdk`) and the sub-package's own
|
||
# `[project].version` in `integrations/slack/pyproject.toml`.
|
||
slack = [
|
||
"omnigent-slack==0.11.0.dev0",
|
||
]
|
||
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. Floored
|
||
# at 0.9.0 (the release the lock already resolves): with the old >=0.1.0
|
||
# floor, a fresh install could satisfy the ai-bridge floor below by
|
||
# dropping mcp to 0.1.0, which pulls no mlflow/pyarrow at all.
|
||
"databricks-mcp>=0.9.0",
|
||
# Floor the transitive databricks-ai-bridge: older releases pull a
|
||
# databricks-vectorsearch that pins protobuf 5.x (conflicts with our
|
||
# protobuf>=6), so the resolver backtracks to an ai-bridge that caps
|
||
# mlflow at 3.2 and pyarrow<22 — and pyarrow 21 has no cp314 wheel, so a
|
||
# fresh install on Python 3.14 tries (and fails) to build it from source.
|
||
"databricks-ai-bridge>=0.19",
|
||
]
|
||
# Load testing (dev/loadtest/). Locust drives the concurrency and the
|
||
# openai-agents harness runs the mocked turns. Opt-in — only load-test users
|
||
# need it.
|
||
loadtest = [
|
||
"locust>=2.30,<3",
|
||
]
|
||
|
||
# Repository-only workflows use PEP 735 dependency groups so development
|
||
# tooling is not published as an installable Omnigent capability.
|
||
[dependency-groups]
|
||
lint = [
|
||
"ruff>=0.6",
|
||
"pyrefly==1.1.1",
|
||
"pre-commit>=3.5",
|
||
# protoc + the well-known-type protos, for regenerating the routing API
|
||
# bindings (omnigent/api/routing/v1/routing_pb2.*). Bundles its own compiler so no
|
||
# system protoc is needed. Capped below 1.83 so the bundled libprotoc emits
|
||
# protobuf 6.x gencode; routing_pb2 must stay at gencode 6.x because
|
||
# cwsandbox/modal installs are pinned to a protobuf 6.x runtime and the
|
||
# protobuf runtime cannot be older than the gencode version. A 7.x runtime
|
||
# (antigravity) also loads 6.x gencode under the forward-compat guarantee,
|
||
# so 6.x gencode satisfies all install forks.
|
||
"grpcio-tools>=1.68,<=1.81.1",
|
||
]
|
||
test = [
|
||
"pytest>=7.0",
|
||
# These clients are optional product capabilities, but their tests import
|
||
# and execute the real packages against mocks.
|
||
"hindsight-client>=0.4.0",
|
||
"nimble-python>=1.2.0,<2",
|
||
"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",
|
||
# 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",
|
||
]
|
||
dev = [
|
||
{ include-group = "lint" },
|
||
{ include-group = "test" },
|
||
]
|
||
|
||
[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"
|
||
|
||
[tool.uv]
|
||
# Keep plain `uv sync` aligned with the published base package. Repository
|
||
# workflows opt into the smallest dependency group they need.
|
||
default-groups = []
|
||
|
||
# `antigravity` requires protobuf>=7 (google-antigravity ships gencode
|
||
# compiled against protobuf 7.x). The following extras/groups all cap their
|
||
# own transitive deps at protobuf<7, making them mutually exclusive with
|
||
# `antigravity`. Declaring conflicts lets uv resolve each set in an isolated
|
||
# fork rather than failing the whole lockfile or silently downgrading
|
||
# shared dependencies like databricks-sdk.
|
||
# cwsandbox: protobuf<7 (cwsandbox itself)
|
||
# modal: protobuf<7 (modal itself)
|
||
# databricks: protobuf<7 (databricks-sdk>=0.56 caps at <7.0)
|
||
# lint group: protobuf<7 (grpcio-tools<=1.81.1 requires protobuf<7) — only
|
||
# conflicts with antigravity, not with cwsandbox/modal/databricks
|
||
conflicts = [
|
||
[{ extra = "antigravity" }, { extra = "cwsandbox" }],
|
||
[{ extra = "antigravity" }, { extra = "modal" }],
|
||
[{ extra = "antigravity" }, { extra = "databricks" }],
|
||
[{ group = "lint" }, { extra = "antigravity" }],
|
||
]
|
||
|
||
# Share the repository lockfile with standalone automation packages.
|
||
[tool.uv.workspace]
|
||
members = [".github/triage_v2"]
|
||
|
||
# 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 }
|
||
# Local resolution for the `slack` extra. Only pulled in when `omnigent[slack]`
|
||
# is requested (the extra is opt-in), so a default install never builds it.
|
||
omnigent-slack = { path = "integrations/slack", 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"]
|
||
"omnigent.resources.scripts" = ["*.sh"]
|
||
# 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.",
|
||
"compat_smoke: core server↔runner and UI↔server protocol boundary test. Must use mock LLM and exercise a cross-component interaction. Selected by the backwards-compat PR gate (-m compat_smoke) for a fast multi-test signal before the full overnight matrix.",
|
||
"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.",
|
||
"smart_routing: end-to-end Smart Routing CUJ (tests/e2e/routing). Opt-in via OMNIGENT_E2E_SMART_ROUTING=1: launches a real omnigent host plus real claude/codex TUIs against a gateway. The routing service itself is an in-test mock, so no AI-Gateway task_v1 deployment is needed.",
|
||
"live_model_flows: end-to-end model-flow CUJs (tests/e2e/omnigent/test_model_flows_live.py). Opt-in via OMNIGENT_E2E_MODEL_FLOWS=1: boots a real omnigent server + host from a checkout (OMNIGENT_E2E_MODEL_FLOWS_REPO overrides which one, enabling the red-on-main matrix) with real claude/codex logins, drives the real SPA in a browser, and asserts pane truth via tmux. Never runs in CI by accident; each landing PR runs it locally per docs/model-flows test plan.",
|
||
"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.<group> 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",
|
||
# Protobuf-generated code (DO NOT EDIT); not ours to restyle.
|
||
"omnigent/api/**/*_pb2.py",
|
||
"omnigent/api/**/*_pb2.pyi",
|
||
]
|
||
|
||
[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)
|
||
# ``DTZ`` — flake8-datetimez (explicit timezone-aware datetimes)
|
||
# ``LOG`` — flake8-logging (correct exception and logger usage)
|
||
# ``RUF`` — ruff-specific (sorted ``__all__``, dangling asyncio
|
||
# tasks, unused noqa, ...)
|
||
select = ["E", "F", "I", "UP", "ARG", "BLE", "B", "SIM", "RET", "C4", "PIE", "DTZ", "LOG", "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"]
|
||
# Telemetry modules intentionally catch all exceptions at every boundary —
|
||
# telemetry must never disrupt the application under any circumstances.
|
||
"omnigent/telemetry/*.py" = ["BLE001", "SIM105"]
|
||
"sdks/**/*.py" = [
|
||
"ARG001", "ARG002", "BLE001", "B008", "RUF012",
|
||
]
|
||
# slack_bolt dispatches to handlers by parameter NAME (``body``, ``event``,
|
||
# ``client``, ``ack``, ``view``), so unused handler args can't be renamed to
|
||
# ``_`` without breaking injection. The bot also has deliberate boundary
|
||
# catches (best-effort acks, background login tasks) that must never abort a
|
||
# turn, hence BLE001.
|
||
"integrations/slack/**/*.py" = [
|
||
"ARG001", "ARG002", "BLE001", "B008", "RUF012",
|
||
]
|
||
# The sessions route is a facade over an implementation package. Its explicit
|
||
# imports intentionally re-export implementation names and load route modules
|
||
# for registration, so F401 remains expected in this package.
|
||
"omnigent/server/routes/sessions/__init__.py" = ["ARG001", "ARG002", "BLE001", "E501", "F401"]
|
||
"omnigent/server/routes/sessions/*.py" = ["ARG001", "ARG002", "BLE001", "E501", "F401"]
|