Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions NEXT_CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# NEXT CHANGELOG

## Release v0.118.0

### New Features and Improvements

* Added a `meta-harness` user-agent dimension that reports the omnigent meta-harness (detected via the `OMNIGENT` environment variable) independently of agent detection.

### Security

### Bug Fixes

### Documentation

### Breaking Changes

### Internal Changes

### API Changes
38 changes: 38 additions & 0 deletions databricks/sdk/useragent.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
RUNTIME_KEY = "runtime"
CICD_KEY = "cicd"
AUTH_KEY = "auth"
META_HARNESS_KEY = "meta-harness"

_product_name = "unknown"
_product_version = "0.0.0"
Expand Down Expand Up @@ -175,6 +176,9 @@ def to_string(
agent = agent_provider()
if agent:
base.append(("agent", agent))
meta_harness = meta_harness_provider()
if meta_harness:
base.append((META_HARNESS_KEY, meta_harness))
return " ".join(f"{k}/{v}" for k, v in base)


Expand Down Expand Up @@ -329,3 +333,37 @@ def _agent_env_fallback() -> str:
if not v:
return ""
return _sanitize_agent_value(v)[:_MAX_AGENT_FALLBACK_LEN]


@dataclass(frozen=True)
class _MetaHarnessRecord:
env_var: str
product: str


# Known agent meta-harnesses, detected independently of agents (a meta-harness
# is not an agent). Keep in sync with databricks-sdk-go and databricks-sdk-java.
_KNOWN_META_HARNESSES: List[_MetaHarnessRecord] = [
_MetaHarnessRecord("OMNIGENT", "omnigent"), # https://github.com/omnigent-ai/omnigent
]

# None = not computed, "" = computed but no meta-harness found.
_meta_harness_provider = None


def meta_harness_provider() -> str:
"""Detect a known agent meta-harness by presence-only env var, else "".

Returns "multiple" if more than one matched. Cached after the first call.
"""
global _meta_harness_provider
if _meta_harness_provider is not None:
return _meta_harness_provider
matches = [h.product for h in _KNOWN_META_HARNESSES if h.env_var in os.environ]
if len(matches) == 1:
_meta_harness_provider = matches[0]
elif len(matches) > 1:
_meta_harness_provider = "multiple"
else:
_meta_harness_provider = ""
return _meta_harness_provider
1 change: 1 addition & 0 deletions tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ def system(self):
monkeypatch.setattr(useragent, "_extra", [])
monkeypatch.setattr(useragent, "_cicd_provider", None)
monkeypatch.setattr(useragent, "_agent_provider", None)
monkeypatch.setattr(useragent, "_meta_harness_provider", None)

monkeypatch.setattr(platform, "python_version", lambda: "3.0.0")
monkeypatch.setattr(platform, "uname", MockUname)
Expand Down
1 change: 1 addition & 0 deletions tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ def system(self):
monkeypatch.setattr(useragent, "_extra", [])
monkeypatch.setattr(useragent, "_cicd_provider", None)
monkeypatch.setattr(useragent, "_agent_provider", None)
monkeypatch.setattr(useragent, "_meta_harness_provider", None)

monkeypatch.setattr(platform, "python_version", lambda: "3.0.0")
monkeypatch.setattr(platform, "uname", MockUname)
Expand Down
65 changes: 64 additions & 1 deletion tests/test_user_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,12 @@ def clean_useragent_env():
original_env = os.environ.copy()
os.environ.clear()

# Clear cached CICD and agent providers.
# Clear cached CICD, agent, and meta-harness providers.
from databricks.sdk import useragent

useragent._cicd_provider = None
useragent._agent_provider = None
useragent._meta_harness_provider = None

yield

Expand All @@ -81,6 +82,7 @@ def clean_useragent_env():
os.environ.update(original_env)
useragent._cicd_provider = None
useragent._agent_provider = None
useragent._meta_harness_provider = None


def test_user_agent_cicd_no_provider(clean_useragent_env):
Expand Down Expand Up @@ -493,3 +495,64 @@ def test_agent_provider_cached(clean_useragent_env):
os.environ["CLAUDECODE"] = "1"

assert useragent.agent_provider() == "cursor"


def test_meta_harness_provider_no_meta_harness(clean_useragent_env):
from databricks.sdk import useragent

assert useragent.meta_harness_provider() == ""


def test_meta_harness_provider_omnigent(clean_useragent_env):
os.environ["OMNIGENT"] = "1"
from databricks.sdk import useragent

assert useragent.meta_harness_provider() == "omnigent"


def test_meta_harness_provider_omnigent_empty_value_still_counts_as_set(clean_useragent_env):
# Presence-only matcher: an empty value still fires.
os.environ["OMNIGENT"] = ""
from databricks.sdk import useragent

assert useragent.meta_harness_provider() == "omnigent"


def test_meta_harness_provider_cached(clean_useragent_env):
os.environ["OMNIGENT"] = "1"
from databricks.sdk import useragent

assert useragent.meta_harness_provider() == "omnigent"

# Change the environment: the cached result should persist.
del os.environ["OMNIGENT"]

assert useragent.meta_harness_provider() == "omnigent"


def test_user_agent_string_includes_meta_harness(clean_useragent_env):
os.environ["OMNIGENT"] = "1"
from databricks.sdk import useragent

ua = useragent.to_string()
assert "meta-harness/omnigent" in ua


def test_user_agent_string_no_meta_harness(clean_useragent_env):
from databricks.sdk import useragent

ua = useragent.to_string()
assert "meta-harness/" not in ua


def test_meta_harness_independent_of_agent(clean_useragent_env):
# omnigent spawns the real agent CLI, so both env vars are set: the UA must
# carry both dimensions and omnigent must not trip the agent "multiple" signal.
os.environ["CLAUDECODE"] = "1"
os.environ["OMNIGENT"] = "1"
from databricks.sdk import useragent

ua = useragent.to_string()
assert "agent/claude-code" in ua
assert "meta-harness/omnigent" in ua
assert useragent.agent_provider() == "claude-code"
Loading